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
test_mod_ssi_reset(request_st * const r,handler_ctx * const hctx)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
test_mod_ssi_write_testfile(int fd,const char * buf,size_t len)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
test_mod_ssi_read_fd(request_st * const r,handler_ctx * const hctx)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);
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