1 #include "first.h" 2 3 #undef NDEBUG 4 #include <sys/types.h> 5 #include <assert.h> 6 #include <stdlib.h> 7 #include <stdio.h> 8 #include <unistd.h> 9 10 #include "mod_ssi.c" 11 #include "fdlog.h" 12 13 static void test_mod_ssi_reset (request_st * const r, handler_ctx * const hctx) 14 { 15 r->http_status = 0; 16 r->resp_htags = 0; 17 array_reset_data_strings(&r->resp_headers); 18 http_response_body_clear(r, 0); 19 20 buffer_clear(hctx->timefmt); 21 array_reset_data_strings(hctx->ssi_vars); 22 array_reset_data_strings(hctx->ssi_cgi_env); 23 } 24 25 static void test_mod_ssi_write_testfile (int fd, const char *buf, size_t len) 26 { 27 if (0 != lseek(fd, 0, SEEK_SET) 28 || (ssize_t)len != write(fd, buf, len) 29 || 0 != ftruncate(fd, (off_t)len) 30 || 0 != lseek(fd, 0, SEEK_SET)) { 31 perror("lseek(),ftruncate(),write()"); /*(unlikely: partial write)*/ 32 exit(1); 33 } 34 } 35 36 37 static void 38 test_mod_ssi_read_fd (request_st * const r, handler_ctx * const hctx) 39 { 40 /* TODO: add adjustments for _WIN32 */ 41 char fn[] = "/tmp/lighttpd_mod_ssi_XXXXXX"; 42 struct stat st; 43 chunkqueue * const cq = &r->write_queue; 44 45 int fd = fdevent_mkostemp(fn, 0); 46 if (fd < 0) { 47 perror("mkstemp()"); 48 exit(1); 49 } 50 if (0 != fstat(fd, &st)) { 51 perror("fstat()"); 52 exit(1); 53 } 54 unlink(fn); 55 56 const char ssi_simple[] = 57 "<!--#echo var=\"SCRIPT_NAME\" -->"; 58 test_mod_ssi_write_testfile(fd, ssi_simple, sizeof(ssi_simple)-1); 59 test_mod_ssi_reset(r, hctx); 60 array_set_key_value(hctx->ssi_cgi_env, 61 CONST_STR_LEN("SCRIPT_NAME"), 62 CONST_STR_LEN("/ssi.shtml")); 63 mod_ssi_read_fd(r, hctx, &st, fd); 64 assert(cq->first); 65 assert(buffer_eq_slen(cq->first->mem, 66 CONST_STR_LEN("/ssi.shtml"))); 67 68 hctx->conf.ssi_exec = 0; /* default */ 69 const char ssi_exec[] = 70 "<!--#exec cmd=\"expr 1 + 1\"-->"; 71 test_mod_ssi_write_testfile(fd, ssi_exec, sizeof(ssi_exec)-1); 72 test_mod_ssi_reset(r, hctx); 73 mod_ssi_read_fd(r, hctx, &st, fd); 74 assert(NULL == cq->first); 75 76 hctx->conf.ssi_exec = 1; 77 test_mod_ssi_write_testfile(fd, ssi_exec, sizeof(ssi_exec)-1); 78 test_mod_ssi_reset(r, hctx); 79 mod_ssi_read_fd(r, hctx, &st, fd); 80 assert(cq->first); 81 assert(cq->first->type == FILE_CHUNK); 82 assert(2 == chunkqueue_length(cq)); 83 char buf[80]; 84 if (0 != lseek(cq->first->file.fd, 0, SEEK_SET) 85 || 2 != read(cq->first->file.fd, buf, sizeof(buf))) { 86 perror("lseek(),read()"); 87 exit(1); 88 } 89 assert(0 == memcmp(buf, "2\n", 2)); 90 hctx->conf.ssi_exec = 0; 91 92 char fni[] = "/tmp/lighttpd_mod_ssi_inc_XXXXXX"; 93 int fdi = fdevent_mkostemp(fni, 0); 94 if (fdi < 0) { 95 perror("mkstemp()"); 96 exit(1); 97 } 98 const char ssi_include[] = 99 "ssi-include"; 100 test_mod_ssi_write_testfile(fdi, ssi_include, sizeof(ssi_include)-1); 101 close(fdi); 102 103 const char ssi_include_shtml[] = 104 "<!--#echo var=SCRIPT_NAME-->\n" 105 "<!--#echo var='SCRIPT_NAME'-->\n" 106 "<!--#echo var=\"SCRIPT_NAME\"-->\n"; 107 buffer * const b = buffer_init(); 108 buffer_copy_string_len(b, CONST_STR_LEN(ssi_include_shtml)); 109 buffer_append_str3(b, CONST_STR_LEN("<!--#include virtual=\""), 110 fni+5, strlen(fni)-5, /*(step over "/tmp/")*/ 111 CONST_STR_LEN("\" -->\n")); 112 buffer_append_str3(b, CONST_STR_LEN("<!--#include file=\""), 113 fni+5, strlen(fni)-5, /*(step over "/tmp/")*/ 114 CONST_STR_LEN("\" -->\n")); 115 test_mod_ssi_write_testfile(fd, BUF_PTR_LEN(b)); 116 buffer_free(b); 117 test_mod_ssi_reset(r, hctx); 118 array_set_key_value(hctx->ssi_cgi_env, 119 CONST_STR_LEN("SCRIPT_NAME"), 120 CONST_STR_LEN("/ssi-include.shtml")); 121 buffer_copy_string_len(&r->physical.doc_root, CONST_STR_LEN("/tmp")); 122 buffer_copy_string_len(&r->uri.path, CONST_STR_LEN("/ssi-include.shtml")); 123 buffer_copy_string_len(&r->physical.rel_path, CONST_STR_LEN("/ssi-include.shtml")); 124 buffer_copy_string_len(&r->physical.path, CONST_STR_LEN("/tmp/ssi-include.shtml")); 125 mod_ssi_read_fd(r, hctx, &st, fd); 126 chunkqueue_read_squash(cq, r->conf.errh); 127 assert(buffer_eq_slen(cq->first->mem, 128 CONST_STR_LEN("/ssi-include.shtml\n" 129 "/ssi-include.shtml\n" 130 "/ssi-include.shtml\n" 131 "ssi-include\n" 132 "ssi-include\n"))); 133 134 unlink(fni); 135 136 test_mod_ssi_reset(r, hctx); 137 close(fd); 138 } 139 140 void test_mod_ssi (void); 141 void test_mod_ssi (void) 142 { 143 plugin_data * const p = mod_ssi_init(); 144 assert(NULL != p); 145 146 request_st r; 147 148 memset(&r, 0, sizeof(request_st)); 149 r.tmp_buf = buffer_init(); 150 r.conf.errh = fdlog_init(NULL, -1, FDLOG_FD); 151 r.conf.errh->fd = -1; /* (disable) */ 152 r.conf.follow_symlink = 1; 153 154 handler_ctx * const hctx = handler_ctx_init(p, r.conf.errh); 155 assert(NULL != hctx); 156 157 test_mod_ssi_read_fd(&r, hctx); 158 159 handler_ctx_free(hctx); 160 161 fdlog_free(r.conf.errh); 162 buffer_free(r.tmp_buf); 163 chunkqueue_reset(&r.write_queue); 164 165 free(r.uri.path.ptr); 166 free(r.physical.path.ptr); 167 free(r.physical.rel_path.ptr); 168 free(r.physical.doc_root.ptr); 169 170 mod_ssi_free(p); 171 free(p); 172 stat_cache_free(); 173 } 174