00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00049
00050 #include <cfg/arch.h>
00051
00052 #include <io.h>
00053 #include <ctype.h>
00054 #include <stdio.h>
00055 #include <string.h>
00056 #include <stdlib.h>
00057 #include <sys/types.h>
00058 #include <unistd.h>
00059 #include <fcntl.h>
00060
00061
00062 #include <sys/heap.h>
00063 #include <sys/version.h>
00064
00065 #include <pro/httpd.h>
00066 #include <pro/ssi.h>
00067 #include "dencode.h"
00068
00069 #define BUFSIZE 512
00070
00071 #define MIN(a,b) (a<b?a:b)
00072
00073 #define SSI_TYPE_FILE 0x01
00074 #define SSI_TYPE_VIRTUAL 0x02
00075 #define SSI_TYPE_EXEC 0x03
00076
00077
00088 static void NutSsiProcessFile(FILE * stream, char *filename)
00089 {
00090 int fd;
00091 int n;
00092 char *data;
00093 int size;
00094 long file_len;
00095
00096 fd = _open(filename, _O_BINARY | _O_RDONLY);
00097
00098 if (fd == -1) {
00099 fprintf_P(stream, PSTR("404 Not found: %s\n"), filename);
00100 return;
00101 }
00102
00103 file_len = _filelength(fd);
00104
00105 size = 512;
00106 if ((data = NutHeapAlloc(size)) != 0) {
00107 while (file_len) {
00108 if (file_len < 512L)
00109 size = (int) file_len;
00110
00111 n = _read(fd, data, size);
00112 if (fwrite(data, 1, n, stream) == 0)
00113 break;
00114 file_len -= (long) n;
00115 }
00116 NutHeapFree(data);
00117 }
00118
00119 _close(fd);
00120 }
00121
00122 static void DestroyRequestInfo(REQUEST * req)
00123 {
00124 if (req->req_url)
00125 NutHeapFree(req->req_url);
00126 if (req->req_query)
00127 NutHeapFree(req->req_query);
00128 if (req->req_type)
00129 NutHeapFree(req->req_type);
00130 if (req->req_cookie)
00131 NutHeapFree(req->req_cookie);
00132 if (req->req_auth)
00133 NutHeapFree(req->req_auth);
00134 if (req->req_agent)
00135 NutHeapFree(req->req_agent);
00136 if (req->req_qptrs)
00137 NutHeapFree(req->req_qptrs);
00138 NutHeapFree(req);
00139 }
00140
00154 static void NutSsiProcessVirtual(FILE * stream, char *url, char* http_root, REQUEST *orig_req)
00155 {
00156 int fd;
00157 int n;
00158 char *data;
00159 int size;
00160 long file_len;
00161 char *filename = NULL;
00162 void (*handler)(FILE *stream, int fd, int file_len, char *http_root, REQUEST *req);
00163
00164
00165 char *cp;
00166 REQUEST * req;
00167
00168 if (NutDecodePath(url) == 0) {
00169 fprintf_P(stream, PSTR("400 Bead request\n"));
00170 return;
00171 }
00172
00173
00174
00175
00176 if (strncasecmp(url, "cgi-bin/", 8) == 0) {
00177 if ((req = NutHeapAllocClear(sizeof(REQUEST))) == 0) {
00178 fprintf_P(stream, PSTR("500 Internal error\n"));
00179 return;
00180 }
00181 req->req_method = METHOD_GET;
00182 req->req_version = orig_req->req_version;
00183 req->req_length = 0;
00184
00185 if (orig_req->req_agent != NULL) {
00186 if ((req->req_agent = NutHeapAlloc((strlen(orig_req->req_agent) + 1))) == 0) {
00187 fprintf_P(stream, PSTR("500 Internal error\n"));
00188 DestroyRequestInfo(req);
00189 return;
00190 }
00191 strcpy(req->req_agent, orig_req->req_agent);
00192 }
00193 if (orig_req->req_cookie!= NULL) {
00194 if ((req->req_cookie = NutHeapAlloc((strlen(orig_req->req_cookie) + 1))) == 0) {
00195 fprintf_P(stream, PSTR("500 Internal error\n"));
00196 DestroyRequestInfo(req);
00197 return;
00198 }
00199 strcpy(req->req_cookie, orig_req->req_cookie);
00200 }
00201 if ((cp = strchr(url, '?')) != 0) {
00202 *cp++ = 0;
00203 if ((req->req_query = NutHeapAlloc(strlen(cp) + 1)) == 0) {
00204 fprintf_P(stream, PSTR("500 Internal error\n"));
00205 DestroyRequestInfo(req);
00206 return;
00207 }
00208 strcpy(req->req_query, cp);
00209
00210 NutHttpProcessQueryString(req);
00211 }
00212 if ((req->req_url = NutHeapAlloc(strlen(url) + 1)) == 0) {
00213 fprintf_P(stream, PSTR("500 Internal error\n"));
00214 DestroyRequestInfo(req);
00215 return;
00216 }
00217 strcpy(req->req_url, url);
00218
00219 NutCgiProcessRequest(stream, req);
00220 DestroyRequestInfo(req);
00221 return;
00222 }
00223
00224
00225
00226
00227 if (http_root) {
00228 filename = NutHeapAlloc(strlen(http_root) + strlen(url) + 1);
00229 strcpy(filename, http_root);
00230 } else {
00231 filename = NutHeapAlloc(strlen(url) + 6);
00232 strcpy(filename, "UROM:");
00233 }
00234
00235 strcat(filename, url);
00236
00237 handler = NutGetMimeHandler(filename);
00238
00239 fd = _open(filename, _O_BINARY | _O_RDONLY);
00240 NutHeapFree(filename);
00241 if (fd == -1) {
00242 char *index;
00243 u_short urll;
00244
00245
00246 urll = strlen(url);
00247 if ((index = NutHeapAllocClear(urll + 12)) == 0) {
00248 fprintf_P(stream, PSTR("500 Internal error\n"));
00249 return;
00250 }
00251 if (urll)
00252 strcpy(index, url);
00253 if (urll && index[urll - 1] != '/')
00254 strcat(index, "/");
00255 strcat(index, "index.html");
00256
00257 if (http_root) {
00258 filename = NutHeapAlloc(strlen(http_root) + strlen(index) + 1);
00259 strcpy(filename, http_root);
00260 } else {
00261 filename = NutHeapAlloc(strlen(index) + 6);
00262 strcpy(filename, "UROM:");
00263 }
00264 strcat(filename, index);
00265
00266 NutHeapFree(index);
00267
00268 handler = NutGetMimeHandler(filename);
00269
00270 fd = _open(filename, _O_BINARY | _O_RDONLY);
00271 NutHeapFree(filename);
00272 if (fd == -1) {
00273 urll = strlen(url);
00274 if ((index = NutHeapAllocClear(urll + 13)) == 0) {
00275 fprintf_P(stream, PSTR("500 Internal error\n"));
00276 return;
00277 }
00278 if (urll)
00279 strcpy(index, url);
00280 if (urll && index[urll - 1] != '/')
00281 strcat(index, "/");
00282 strcat(index, "index.shtml");
00283
00284 if (http_root) {
00285 filename = NutHeapAlloc(strlen(http_root) + strlen(index) + 1);
00286 strcpy(filename, http_root);
00287 } else {
00288 filename = NutHeapAlloc(strlen(index) + 6);
00289 strcpy(filename, "UROM:");
00290 }
00291 strcat(filename, index);
00292
00293 NutHeapFree(index);
00294
00295 handler = NutGetMimeHandler(filename);
00296
00297 fd = _open(filename, _O_BINARY | _O_RDONLY);
00298 NutHeapFree(filename);
00299 if (fd == -1) {
00300 fprintf_P(stream, PSTR("404 Not found: %s\n"), filename);
00301 return;
00302 }
00303 }
00304 }
00305
00306 file_len = _filelength(fd);
00307
00308 if (handler == NULL) {
00309 size = 512;
00310 if ((data = NutHeapAlloc(size)) != 0) {
00311 while (file_len) {
00312 if (file_len < 512L)
00313 size = (int) file_len;
00314
00315 n = _read(fd, data, size);
00316 if (fwrite(data, 1, n, stream) == 0)
00317 break;
00318 file_len -= (long) n;
00319 }
00320 NutHeapFree(data);
00321 }
00322 } else handler(stream, fd, file_len, http_root, orig_req);
00323 _close(fd);
00324 }
00325
00338 static void NutSsiSkipWhitespace(char *buffer, u_short *pos, u_short end)
00339 {
00340 while ((*pos < end) && (
00341 (buffer[*pos] == '\n') || (buffer[*pos] == '\r') ||
00342 (buffer[*pos] == '\t') || (buffer[*pos] == ' ')))
00343 (*pos) ++;
00344 }
00345
00364 static u_char NutSsiCheckForSsi(FILE *stream, char *buffer, u_short end, char* http_root, REQUEST *req)
00365 {
00366 u_short pos = 4;
00367 char * filename;
00368 u_char type;
00369
00370 pos = 4;
00371 NutSsiSkipWhitespace(buffer, &pos, end);
00372 if (pos == end) return 0;
00373
00374 if (strncasecmp(&buffer[pos], "#include", 8) == 0) {
00375 pos += 8;
00376 type = SSI_TYPE_VIRTUAL;
00377 } else
00378 if (strncasecmp(&buffer[pos], "#exec", 5) == 0) {
00379 pos += 5;
00380 type = SSI_TYPE_EXEC;
00381 } else return 0;
00382 if (pos >= end) return 0;
00383
00384 NutSsiSkipWhitespace(buffer, &pos, end);
00385 if (pos == end) return 0;
00386
00387 if (type == SSI_TYPE_VIRTUAL) {
00388 if (strncasecmp(&buffer[pos], "virtual", 7) == 0) {
00389 pos += 7;
00390 } else
00391 if (strncasecmp(&buffer[pos], "file", 4) == 0) {
00392 pos += 4;
00393 type = SSI_TYPE_FILE;
00394 } else return 0;
00395 } else {
00396 if (strncasecmp(&buffer[pos], "cgi", 3) == 0) {
00397 pos += 3;
00398 } else return 0;
00399 }
00400 if (pos >= end) return 0;
00401
00402 NutSsiSkipWhitespace(buffer, &pos, end);
00403 if (pos == end) return 0;
00404
00405 if (buffer[pos] != '=') return 0;
00406 pos ++;
00407
00408 NutSsiSkipWhitespace(buffer, &pos, end);
00409 if (pos == end) return 0;
00410
00411 if (buffer[pos] == '"') {
00412 pos ++;
00413 if (pos == end) return 0;
00414 filename = &buffer[pos];
00415 while (buffer[pos] != '"') {
00416 pos ++;
00417 if (pos == end) return 0;
00418 }
00419 buffer[pos] = '\0';
00420 switch (type) {
00421 case SSI_TYPE_FILE:
00422 NutSsiProcessFile(stream, filename);
00423 break;
00424 case SSI_TYPE_VIRTUAL:
00425 NutSsiProcessVirtual(stream, filename, http_root, req);
00426 break;
00427 case SSI_TYPE_EXEC:
00428 NutSsiProcessVirtual(stream, filename, http_root, req);
00429 break;
00430 }
00431 }
00432 return 1;
00433 }
00434
00454 static void NutHttpProcessSHTML(FILE * stream, int fd, int file_len, char* http_root, REQUEST *req)
00455 {
00456 char * buffer;
00457 u_char in_comment;
00458 int buffsize;
00459 int fpos;
00460 int n;
00461 char *index;
00462 u_char found;
00463 buffsize = MIN(BUFSIZE, file_len);
00464 buffer = NutHeapAlloc(buffsize+1);
00465 in_comment = 0;
00466 fpos = 0;
00467 while (file_len != fpos) {
00468 memset(buffer, 0, buffsize+1);
00469 n = _read(fd, buffer, MIN(buffsize, file_len-fpos));
00470
00471 if (!in_comment) {
00472
00473 index = strstr(buffer, "<!--");
00474 if (index == NULL) {
00475 if (file_len > buffsize) {
00476 fwrite(buffer, 1, MIN(buffsize-100, n), stream);
00477 fpos += MIN(buffsize-100, n);
00478 _seek(fd, fpos, SEEK_SET);
00479 } else {
00480 fwrite(buffer, 1, n, stream);
00481 fpos += n;
00482 }
00483
00484 } else {
00485 found = (int)index - (int)buffer;
00486 fwrite (buffer, 1, found, stream);
00487 fpos += found;
00488 _seek(fd, fpos, SEEK_SET);
00489 in_comment = 1;
00490 }
00491 } else {
00492 index = strstr(buffer, "-->");
00493 if (index == NULL) {
00494 fwrite(buffer, 1, MIN(buffsize, n), stream);
00495 fpos += MIN(buffsize, n);
00496 in_comment = 0;
00497 } else {
00498 found = (int)index - (int)buffer;
00499 if (!NutSsiCheckForSsi(stream, buffer, found, http_root, req)) {
00500 fwrite(buffer, 1, found+3, stream);
00501 }
00502 fpos += found+3;
00503 _seek(fd, fpos, SEEK_SET);
00504 in_comment = 0;
00505 }
00506 }
00507 }
00508
00509 NutHeapFree(buffer);
00510 }
00511
00522 void NutRegisterSsi(void)
00523 {
00524 NutSetMimeHandler(".shtml", NutHttpProcessSHTML);
00525 }
00526