aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-09-13 17:38:15 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-09-13 17:38:15 +0200
commit772c2db9716f2aa255a5316b3435899b00483dde (patch)
tree0ceec717d30d09198119d0c72612b8531412f3db
parentaa7da73880539713b14d19d6b34c2940c3579fcd (diff)
downloadbusybox-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.c104
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
53static char* skip_whitespace(char *s)
54{
55 while (*s == ' ' || *s == '\t') ++s;
56
57 return s;
58}
59
49static char line[64 * 1024]; 60static char line[64 * 1024];
50 61
51/*
52 * Currently only handles directives which are alone on the line
53 */
54static void process_includes(const char *filename) 62static 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
85int main(int argc, char *argv[]) 146int 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;