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
00045
00046
00047
00048
00049
00050
00055
00056 #include <cfg/arch.h>
00057
00058 #include <io.h>
00059 #include <ctype.h>
00060 #include <stdio.h>
00061 #include <string.h>
00062 #include <stdlib.h>
00063 #include <sys/types.h>
00064 #include <unistd.h>
00065 #include <fcntl.h>
00066
00067
00068 #include <sys/heap.h>
00069 #include <sys/version.h>
00070
00071 #include <pro/httpd.h>
00072 #include <pro/ssi.h>
00073 #include "dencode.h"
00074
00075 #define BUFSIZE 512
00076
00077 #define MIN(a,b) (a<b?a:b)
00078
00079 #define SSI_TYPE_FILE 0x01
00080 #define SSI_TYPE_VIRTUAL 0x02
00081 #define SSI_TYPE_EXEC 0x03
00082
00083
00094 static void NutSsiProcessFile(FILE * stream, char *filename)
00095 {
00096 int fd;
00097 int n;
00098 char *data;
00099 int size;
00100 long file_len;
00101
00102 fd = _open(filename, _O_BINARY | _O_RDONLY);
00103
00104 if (fd == -1) {
00105 fprintf_P(stream, PSTR("404 Not found: %s\n"), filename);
00106 return;
00107 }
00108
00109 file_len = _filelength(fd);
00110
00111 size = 512;
00112 if ((data = NutHeapAlloc(size)) != 0) {
00113 while (file_len) {
00114 if (file_len < 512L)
00115 size = (int) file_len;
00116
00117 n = _read(fd, data, size);
00118 if (fwrite(data, 1, n, stream) == 0)
00119 break;
00120 file_len -= (long) n;
00121 }
00122 NutHeapFree(data);
00123 }
00124
00125 _close(fd);
00126 }
00127
00128 static void DestroyRequestInfo(REQUEST * req)
00129 {
00130 if (req->req_url)
00131 NutHeapFree(req->req_url);
00132 if (req->req_query)
00133 NutHeapFree(req->req_query);
00134 if (req->req_type)
00135 NutHeapFree(req->req_type);
00136 if (req->req_cookie)
00137 NutHeapFree(req->req_cookie);
00138 if (req->req_auth)
00139 NutHeapFree(req->req_auth);
00140 if (req->req_agent)
00141 NutHeapFree(req->req_agent);
00142 if (req->req_qptrs)
00143 NutHeapFree(req->req_qptrs);
00144 NutHeapFree(req);
00145 }
00146
00160 static void NutSsiProcessVirtual(FILE * stream, char *url, char* http_root, REQUEST *orig_req)
00161 {
00162 int fd;
00163 int i;
00164 int n;
00165 char *data;
00166 int size;
00167 long file_len;
00168 char *filename = NULL;
00169 void (*handler)(FILE *stream, int fd, int file_len, char *http_root, REQUEST *req);
00170
00171
00172 char *cp;
00173 REQUEST * req;
00174
00175 if (NutDecodePath(url) == 0) {
00176 fprintf_P(stream, PSTR("400 Bead request\n"));
00177 return;
00178 }
00179
00180
00181
00182
00183 if (strncasecmp(url, "cgi-bin/", 8) == 0) {
00184 if ((req = NutHeapAllocClear(sizeof(REQUEST))) == 0) {
00185 fprintf_P(stream, PSTR("500 Internal error\n"));
00186 return;
00187 }
00188 req->req_method = METHOD_GET;
00189 req->req_version = orig_req->req_version;
00190 req->req_length = 0;
00191
00192 if (orig_req->req_agent != NULL) {
00193 if ((req->req_agent = NutHeapAlloc((strlen(orig_req->req_agent) + 1))) == 0) {
00194 fprintf_P(stream, PSTR("500 Internal error\n"));
00195 DestroyRequestInfo(req);
00196 return;
00197 }
00198 strcpy(req->req_agent, orig_req->req_agent);
00199 }
00200 if (orig_req->req_cookie!= NULL) {
00201 if ((req->req_cookie = NutHeapAlloc((strlen(orig_req->req_cookie) + 1))) == 0) {
00202 fprintf_P(stream, PSTR("500 Internal error\n"));
00203 DestroyRequestInfo(req);
00204 return;
00205 }
00206 strcpy(req->req_cookie, orig_req->req_cookie);
00207 }
00208 if ((cp = strchr(url, '?')) != 0) {
00209 *cp++ = 0;
00210 if ((req->req_query = NutHeapAlloc(512)) == 0) {
00211 fprintf_P(stream, PSTR("500 Internal error\n"));
00212 DestroyRequestInfo(req);
00213 return;
00214 }
00215 strcpy(req->req_query, cp);
00216 if (strcmp(req->req_query, "$QUERY_STRING") == 0){
00217 req->req_query[0] = 0;
00218 for (i = 0; i < (orig_req->req_numqptrs*2); i++) {
00219 if(i)
00220 strcat (req->req_query, "&");
00221 strcat (req->req_query, orig_req->req_qptrs[i]);
00222 strcat (req->req_query, "=");
00223 i++;
00224 strcat (req->req_query, orig_req->req_qptrs[i]);
00225 }
00226 }
00227 NutHttpProcessQueryString(req);
00228 }
00229 if ((req->req_url = NutHeapAlloc(strlen(url) + 1)) == 0) {
00230 fprintf_P(stream, PSTR("500 Internal error\n"));
00231 DestroyRequestInfo(req);
00232 return;
00233 }
00234 strcpy(req->req_url, url);
00235
00236
00237 NutCgiProcessRequest(stream, req);
00238 DestroyRequestInfo(req);
00239 return;
00240 }
00241
00242
00243
00244
00245 if (http_root) {
00246 filename = NutHeapAlloc(strlen(http_root) + strlen(url) + 1);
00247 strcpy(filename, http_root);
00248 } else {
00249 filename = NutHeapAlloc(strlen(url) + 6);
00250 strcpy(filename, "UROM:");
00251 }
00252
00253 strcat(filename, url);
00254
00255 handler = NutGetMimeHandler(filename);
00256
00257 fd = _open(filename, _O_BINARY | _O_RDONLY);
00258 NutHeapFree(filename);
00259 if (fd == -1) {
00260 char *index;
00261 u_short urll;
00262
00263
00264 urll = strlen(url);
00265 if ((index = NutHeapAllocClear(urll + 12)) == 0) {
00266 fprintf_P(stream, PSTR("500 Internal error\n"));
00267 return;
00268 }
00269 if (urll)
00270 strcpy(index, url);
00271 if (urll && index[urll - 1] != '/')
00272 strcat(index, "/");
00273 strcat(index, "index.html");
00274
00275 if (http_root) {
00276 filename = NutHeapAlloc(strlen(http_root) + strlen(index) + 1);
00277 strcpy(filename, http_root);
00278 } else {
00279 filename = NutHeapAlloc(strlen(index) + 6);
00280 strcpy(filename, "UROM:");
00281 }
00282 strcat(filename, index);
00283
00284 NutHeapFree(index);
00285
00286 handler = NutGetMimeHandler(filename);
00287
00288 fd = _open(filename, _O_BINARY | _O_RDONLY);
00289 NutHeapFree(filename);
00290 if (fd == -1) {
00291 urll = strlen(url);
00292 if ((index = NutHeapAllocClear(urll + 13)) == 0) {
00293 fprintf_P(stream, PSTR("500 Internal error\n"));
00294 return;
00295 }
00296 if (urll)
00297 strcpy(index, url);
00298 if (urll && index[urll - 1] != '/')
00299 strcat(index, "/");
00300 strcat(index, "index.shtml");
00301
00302 if (http_root) {
00303 filename = NutHeapAlloc(strlen(http_root) + strlen(index) + 1);
00304 strcpy(filename, http_root);
00305 } else {
00306 filename = NutHeapAlloc(strlen(index) + 6);
00307 strcpy(filename, "UROM:");
00308 }
00309 strcat(filename, index);
00310
00311 NutHeapFree(index);
00312
00313 handler = NutGetMimeHandler(filename);
00314
00315 fd = _open(filename, _O_BINARY | _O_RDONLY);
00316 NutHeapFree(filename);
00317 if (fd == -1) {
00318 fprintf_P(stream, PSTR("404 Not found: %s\n"), filename);
00319 return;
00320 }
00321 }
00322 }
00323
00324 file_len = _filelength(fd);
00325
00326 if (handler == NULL) {
00327 size = 512;
00328 if ((data = NutHeapAlloc(size)) != 0) {
00329 while (file_len) {
00330 if (file_len < 512L)
00331 size = (int) file_len;
00332
00333 n = _read(fd, data, size);
00334 if (fwrite(data, 1, n, stream) == 0)
00335 break;
00336 file_len -= (long) n;
00337 }
00338 NutHeapFree(data);
00339 }
00340 } else handler(stream, fd, file_len, http_root, orig_req);
00341 _close(fd);
00342 }
00343
00356 static void NutSsiSkipWhitespace(char *buffer, u_short *pos, u_short end)
00357 {
00358 while ((*pos < end) && (
00359 (buffer[*pos] == '\n') || (buffer[*pos] == '\r') ||
00360 (buffer[*pos] == '\t') || (buffer[*pos] == ' ')))
00361 (*pos) ++;
00362 }
00363
00382 static u_char NutSsiCheckForSsi(FILE *stream, char *buffer, u_short end, char* http_root, REQUEST *req)
00383 {
00384 u_short pos = 4;
00385 char * filename;
00386 u_char type;
00387
00388 pos = 4;
00389 NutSsiSkipWhitespace(buffer, &pos, end);
00390 if (pos == end) return 0;
00391
00392 if (strncasecmp(&buffer[pos], "#include", 8) == 0) {
00393 pos += 8;
00394 type = SSI_TYPE_VIRTUAL;
00395 } else
00396 if (strncasecmp(&buffer[pos], "#exec", 5) == 0) {
00397 pos += 5;
00398 type = SSI_TYPE_EXEC;
00399 } else return 0;
00400 if (pos >= end) return 0;
00401
00402 NutSsiSkipWhitespace(buffer, &pos, end);
00403 if (pos == end) return 0;
00404
00405 if (type == SSI_TYPE_VIRTUAL) {
00406 if (strncasecmp(&buffer[pos], "virtual", 7) == 0) {
00407 pos += 7;
00408 } else
00409 if (strncasecmp(&buffer[pos], "file", 4) == 0) {
00410 pos += 4;
00411 type = SSI_TYPE_FILE;
00412 } else return 0;
00413 } else {
00414 if (strncasecmp(&buffer[pos], "cgi", 3) == 0) {
00415 pos += 3;
00416 } else return 0;
00417 }
00418 if (pos >= end) return 0;
00419
00420 NutSsiSkipWhitespace(buffer, &pos, end);
00421 if (pos == end) return 0;
00422
00423 if (buffer[pos] != '=') return 0;
00424 pos ++;
00425
00426 NutSsiSkipWhitespace(buffer, &pos, end);
00427 if (pos == end) return 0;
00428
00429 if (buffer[pos] == '"') {
00430 pos ++;
00431 if (pos == end) return 0;
00432 filename = &buffer[pos];
00433 while (buffer[pos] != '"') {
00434 pos ++;
00435 if (pos == end) return 0;
00436 }
00437 buffer[pos] = '\0';
00438 switch (type) {
00439 case SSI_TYPE_FILE:
00440 NutSsiProcessFile(stream, filename);
00441 break;
00442 case SSI_TYPE_VIRTUAL:
00443 NutSsiProcessVirtual(stream, filename, http_root, req);
00444 break;
00445 case SSI_TYPE_EXEC:
00446 NutSsiProcessVirtual(stream, filename, http_root, req);
00447 break;
00448 }
00449 }
00450 return 1;
00451 }
00452
00472 static void NutHttpProcessSHTML(FILE * stream, int fd, int file_len, char* http_root, REQUEST *req)
00473 {
00474 char * buffer;
00475 u_char in_comment;
00476 int buffsize;
00477 int fpos;
00478 int n;
00479 char *index;
00480 u_char found;
00481 buffsize = MIN(BUFSIZE, file_len);
00482 buffer = NutHeapAlloc(buffsize+1);
00483 in_comment = 0;
00484 fpos = 0;
00485 while (file_len != fpos) {
00486 memset(buffer, 0, buffsize+1);
00487 n = _read(fd, buffer, MIN(buffsize, file_len-fpos));
00488
00489 if (!in_comment) {
00490
00491 index = strstr(buffer, "<!--");
00492 if (index == NULL) {
00493 if (file_len > buffsize) {
00494 fwrite(buffer, 1, MIN(buffsize-100, n), stream);
00495 fpos += MIN(buffsize-100, n);
00496 _seek(fd, fpos, SEEK_SET);
00497 } else {
00498 fwrite(buffer, 1, n, stream);
00499 fpos += n;
00500 }
00501
00502 } else {
00503 found = (int)index - (int)buffer;
00504 fwrite (buffer, 1, found, stream);
00505 fpos += found;
00506 _seek(fd, fpos, SEEK_SET);
00507 in_comment = 1;
00508 }
00509 } else {
00510 index = strstr(buffer, "-->");
00511 if (index == NULL) {
00512 fwrite(buffer, 1, MIN(buffsize, n), stream);
00513 fpos += MIN(buffsize, n);
00514 in_comment = 0;
00515 } else {
00516 found = (int)index - (int)buffer;
00517 if (!NutSsiCheckForSsi(stream, buffer, found, http_root, req)) {
00518 fwrite(buffer, 1, found+3, stream);
00519 }
00520 fpos += found+3;
00521 _seek(fd, fpos, SEEK_SET);
00522 in_comment = 0;
00523 }
00524 }
00525 }
00526
00527 NutHeapFree(buffer);
00528 }
00529
00540 void NutRegisterSsi(void)
00541 {
00542 NutSetMimeHandler(".shtml", NutHttpProcessSHTML);
00543 }
00544