diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-13 17:38:15 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-13 17:38:15 +0200 |
commit | 772c2db9716f2aa255a5316b3435899b00483dde (patch) | |
tree | 0ceec717d30d09198119d0c72612b8531412f3db | |
parent | aa7da73880539713b14d19d6b34c2940c3579fcd (diff) | |
download | busybox-w32-772c2db9716f2aa255a5316b3435899b00483dde.tar.gz busybox-w32-772c2db9716f2aa255a5316b3435899b00483dde.tar.bz2 busybox-w32-772c2db9716f2aa255a5316b3435899b00483dde.zip |
httpd_ssi.c: make it a bit less broken
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/httpd_ssi.c | 104 |
1 files changed, 83 insertions, 21 deletions
diff --git a/networking/httpd_ssi.c b/networking/httpd_ssi.c index 86f341fbd..03f263397 100644 --- a/networking/httpd_ssi.c +++ b/networking/httpd_ssi.c | |||
@@ -31,13 +31,17 @@ httpd_ssi.c -o httpd_ssi | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | /* Size (i386, static uclibc, approximate): | 33 | /* Size (i386, static uclibc, approximate): |
34 | text data bss dec hex filename | 34 | * text data bss dec hex filename |
35 | 8931 164 68552 77647 12f4f httpd_ssi | 35 | * 9487 160 68552 78199 13177 httpd_ssi |
36 | */ | 36 | * |
37 | * Note: it wouldn't be too hard to get rid of stdio and strdup, | ||
38 | * (especially that fgets() mangles NULs...) | ||
39 | */ | ||
37 | 40 | ||
38 | #include <sys/types.h> | 41 | #include <sys/types.h> |
39 | #include <sys/stat.h> | 42 | #include <sys/stat.h> |
40 | #include <errno.h> | 43 | #include <errno.h> |
44 | #include <fcntl.h> | ||
41 | #include <stdint.h> | 45 | #include <stdint.h> |
42 | #include <stdlib.h> | 46 | #include <stdlib.h> |
43 | #include <string.h> | 47 | #include <string.h> |
@@ -46,40 +50,97 @@ httpd_ssi.c -o httpd_ssi | |||
46 | #include <dirent.h> | 50 | #include <dirent.h> |
47 | #include <time.h> | 51 | #include <time.h> |
48 | 52 | ||
53 | static char* skip_whitespace(char *s) | ||
54 | { | ||
55 | while (*s == ' ' || *s == '\t') ++s; | ||
56 | |||
57 | return s; | ||
58 | } | ||
59 | |||
49 | static char line[64 * 1024]; | 60 | static char line[64 * 1024]; |
50 | 61 | ||
51 | /* | ||
52 | * Currently only handles directives which are alone on the line | ||
53 | */ | ||
54 | static void process_includes(const char *filename) | 62 | static void process_includes(const char *filename) |
55 | { | 63 | { |
64 | int curdir_fd; | ||
65 | char *end; | ||
56 | FILE *fp = fopen(filename, "r"); | 66 | FILE *fp = fopen(filename, "r"); |
57 | if (!fp) | 67 | if (!fp) |
58 | exit(1); | 68 | exit(1); |
59 | 69 | ||
60 | #define INCLUDE "<!--#include file=\"" | 70 | /* Ensure that nested includes are relative: |
71 | * if we include a/1.htm and it includes b/2.htm, | ||
72 | * we need to include a/b/2.htm, not b/2.htm | ||
73 | */ | ||
74 | curdir_fd = -1; | ||
75 | end = strrchr(filename, '/'); | ||
76 | if (end) { | ||
77 | curdir_fd = open(".", O_RDONLY); | ||
78 | /* *end = '\0' would mishandle "/file.htm" */ | ||
79 | end[1] = '\0'; | ||
80 | chdir(filename); | ||
81 | } | ||
82 | |||
83 | #define INCLUDE "<!--#include" | ||
61 | while (fgets(line, sizeof(line), fp)) { | 84 | while (fgets(line, sizeof(line), fp)) { |
62 | char *closing_dq; | 85 | unsigned preceding_len; |
86 | char *include_directive; | ||
63 | 87 | ||
64 | /* FIXME: output text leading to INCLUDE first */ | 88 | include_directive = strstr(line, INCLUDE); |
65 | if (strncmp(line, INCLUDE, sizeof(INCLUDE)-1) != 0 | 89 | if (!include_directive) { |
66 | || (closing_dq = strchr(line + sizeof(INCLUDE)-1, '"')) == NULL | 90 | fputs(line, stdout); |
67 | /* or strstr(line + sizeof(INCLUDE)-1, "\" -->")? */ | 91 | continue; |
92 | } | ||
93 | preceding_len = include_directive - line; | ||
94 | if (memchr(line, '\"', preceding_len) | ||
95 | || memchr(line, '\'', preceding_len) | ||
68 | ) { | 96 | ) { |
97 | /* INCLUDE string may be inside "str" or 'str', | ||
98 | * ignore it */ | ||
99 | fputs(line, stdout); | ||
100 | continue; | ||
101 | } | ||
102 | /* Small bug: we accept #includefile="file" too */ | ||
103 | include_directive = skip_whitespace(include_directive + sizeof(INCLUDE)-1); | ||
104 | if (strncmp(include_directive, "file=\"", 6) != 0) { | ||
105 | /* "<!--#include virtual=..."? - not supported */ | ||
106 | fputs(line, stdout); | ||
107 | continue; | ||
108 | } | ||
109 | include_directive += 6; /* now it points to file name */ | ||
110 | end = strchr(include_directive, '\"'); | ||
111 | if (!end) { | ||
69 | fputs(line, stdout); | 112 | fputs(line, stdout); |
70 | continue; | 113 | continue; |
71 | } | 114 | } |
72 | *closing_dq = '\0'; | 115 | /* We checked that this is a valid include directive */ |
116 | |||
117 | /* Print everything before directive */ | ||
118 | if (preceding_len) { | ||
119 | line[preceding_len] = '\0'; | ||
120 | fputs(line, stdout); | ||
121 | } | ||
122 | /* Save everything after directive */ | ||
123 | *end++ = '\0'; | ||
124 | end = strchr(end, '>'); | ||
125 | if (end) | ||
126 | end = strdup(end + 1); | ||
127 | |||
73 | /* FIXME: | 128 | /* FIXME: |
74 | * (1) are relative paths with /../ etc ok? | 129 | * (1) are relative paths with /../ etc ok? |
75 | * (2) if we include a/1.htm and it includes b/2.htm, | 130 | * (2) what to do with absolute paths? |
76 | * do we need to include a/b/2.htm or b/2.htm? | 131 | * are they relative to doc root or to real root? |
77 | * IOW, do we need to "cd $dirname"? | ||
78 | */ | 132 | */ |
79 | process_includes(line + sizeof(INCLUDE)-1); | 133 | process_includes(include_directive); |
80 | /* FIXME: this should be the tail of line after --> */ | 134 | |
81 | putchar('\n'); | 135 | /* Print everything after directive */ |
136 | if (end) { | ||
137 | fputs(end, stdout); | ||
138 | free(end); | ||
139 | } | ||
82 | } | 140 | } |
141 | if (curdir_fd >= 0) | ||
142 | fchdir(curdir_fd); | ||
143 | fclose(fp); | ||
83 | } | 144 | } |
84 | 145 | ||
85 | int main(int argc, char *argv[]) | 146 | int main(int argc, char *argv[]) |
@@ -95,13 +156,14 @@ int main(int argc, char *argv[]) | |||
95 | * Connection: close | 156 | * Connection: close |
96 | * Content-Type: text/html | 157 | * Content-Type: text/html |
97 | */ | 158 | */ |
98 | printf( | 159 | fputs( |
99 | /* "Date: Thu, 10 Sep 2009 18:23:28 GMT\r\n" */ | 160 | /* "Date: Thu, 10 Sep 2009 18:23:28 GMT\r\n" */ |
100 | /* "Server: Apache\r\n" */ | 161 | /* "Server: Apache\r\n" */ |
101 | /* "Accept-Ranges: bytes\r\n" - do we really accept bytes?! */ | 162 | /* "Accept-Ranges: bytes\r\n" - do we really accept bytes?! */ |
102 | "Connection: close\r\n" | 163 | "Connection: close\r\n" |
103 | "Content-Type: text/html\r\n" | 164 | "Content-Type: text/html\r\n" |
104 | "\r\n" | 165 | "\r\n", |
166 | stdout | ||
105 | ); | 167 | ); |
106 | process_includes(argv[1]); | 168 | process_includes(argv[1]); |
107 | return 0; | 169 | return 0; |