time_t timer = time(0);
char timeStr[80];
int len;
+ enum {
+ numNames = sizeof(httpResponseNames) / sizeof(httpResponseNames[0])
+ };
- for (i = 0;
- i < (sizeof(httpResponseNames)/sizeof(httpResponseNames[0])); i++) {
+ for (i = 0; i < numNames; i++) {
if (httpResponseNames[i].type == responseNum) {
responseString = httpResponseNames[i].name;
infoString = httpResponseNames[i].info;
responseNum, responseString,
responseNum, responseString, infoString);
}
-#if DEBUG
- fprintf(stderr, "headers: '%s'\n", buf);
-#endif
+ if (DEBUG)
+ fprintf(stderr, "headers: '%s'\n", buf);
return full_write(config->accepted_socket, buf, len);
}
if (purl == NULL)
_exit(242);
- inFd = toCgi[0];
+ inFd = toCgi[0];
outFd = fromCgi[1];
dup2(inFd, 0); // replace stdin with the pipe
setenv1("REQUEST_URI", purl);
}
if (script != NULL)
- *script = '\0'; /* reduce /PATH_INFO */
+ *script = '\0'; /* cut off /PATH_INFO */
/* SCRIPT_FILENAME required by PHP in CGI mode */
if (!realpath(purl + 1, realpath_buff))
goto error_execing_cgi;
setenv1("SCRIPT_FILENAME", realpath_buff);
/* set SCRIPT_NAME as full path: /cgi-bin/dirs/script.cgi */
setenv1("SCRIPT_NAME", purl);
+ /* TODO: bug 996 says we need to decodeString(config->query)
+ * before placing it into env. Is this true? Add example
+ * in the comment please... */
setenv1("QUERY_STRING", config->query);
setenv1("SERVER_SOFTWARE", httpdVersion);
putenv("SERVER_PROTOCOL=HTTP/1.0");
post_readed_size = 0;
post_readed_idx = 0;
- inFd = fromCgi[0];
+ inFd = fromCgi[0];
outFd = toCgi[1];
close(fromCgi[1]);
close(toCgi[0]);
# error "PIPESIZE >= MAX_MEMORY_BUFF"
#endif
- // There is something to read
+ /* There is something to read */
count = safe_read(inFd, rbuf, PIPESIZE);
if (count == 0)
break; /* closed */
if (strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) {
full_write(s, "HTTP/1.0 200 OK\r\n", 17);
}
+ /* Sometimes CGI is writing to pipe in small chunks
+ * and we don't see Content-type (because the read
+ * is too short) and we emit bogus "text/plain"!
+ * Is it a bug or CGI *has to* write it in one piece? */
if (strstr(rbuf, "ontent-") == 0) {
full_write(s, "Content-type: text/plain\r\n\r\n", 28);
}
break;
if (DEBUG)
- fprintf(stderr, "cgi read %d bytes\n", count);
+ fprintf(stderr, "cgi read %d bytes: '%.*s'\n", count, count, rbuf);
}
}
}
strcpy(url, buf);
/* extract url args if present */
test = strchr(url, '?');
+ config->query = NULL;
if (test) {
*test++ = '\0';
config->query = test;
*test = '/';
}
if (blank >= 0) {
- // read until blank line for HTTP version specified, else parse immediate
+ /* read until blank line for HTTP version specified, else parse immediate */
while (1) {
alarm(TIMEOUT);
count = getLine();
length = strtol(test, &test, 10);
/* length is "ulong", but we need to pass it to int later */
/* so we check for negative or too large values in one go: */
- /* (long -> ulong conv will cause negatives to be seen as > INT_MAX) */
+ /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */
if (test[0] || errno || length > INT_MAX)
goto bail_out;
}
} /* while extra header reading */
}
- (void) alarm(0);
+ alarm(0);
if (config->alarm_signaled)
break;
if (strcmp(strrchr(url, '/') + 1, httpd_conf) == 0 || ip_allowed == 0) {
/* protect listing [/path]/httpd_conf or IP deny */
#if ENABLE_FEATURE_HTTPD_CGI
-FORBIDDEN: /* protect listing /cgi-bin */
+ FORBIDDEN: /* protect listing /cgi-bin */
#endif
sendHeaders(HTTP_FORBIDDEN);
break;
#if ENABLE_FEATURE_HTTPD_CGI
if (strncmp(test, "cgi-bin", 7) == 0) {
if (test[7] == '/' && test[8] == 0)
- goto FORBIDDEN; // protect listing cgi-bin/
+ goto FORBIDDEN; /* protect listing cgi-bin/ */
sendCgi(url, prequest, length, cookie, content_type);
- } else {
- if (prequest != request_GET)
- sendHeaders(HTTP_NOT_IMPLEMENTED);
- else {
+ break;
+ }
+ if (prequest != request_GET) {
+ sendHeaders(HTTP_NOT_IMPLEMENTED);
+ break;
+ }
#endif /* FEATURE_HTTPD_CGI */
- if (purl[-1] == '/')
- strcpy(purl, "index.html");
- if (stat(test, &sb) == 0) {
- config->ContentLength = sb.st_size;
- config->last_mod = sb.st_mtime;
- }
- sendFile(test);
- config->ContentLength = -1;
+ if (purl[-1] == '/')
+ strcpy(purl, "index.html");
+ if (stat(test, &sb) == 0) {
+ /* It's a dir URL and there is index.html */
+ config->ContentLength = sb.st_size;
+ config->last_mod = sb.st_mtime;
+ }
#if ENABLE_FEATURE_HTTPD_CGI
+ else if (purl[-1] == '/') {
+ /* It's a dir URL and there is no index.html
+ * Try cgi-bin/index.cgi */
+ if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
+ purl[0] = '\0';
+ config->query = url;
+ sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
+ break;
}
}
-#endif
+#endif /* FEATURE_HTTPD_CGI */
+ sendFile(test);
+ config->ContentLength = -1;
} while (0);
bail_out:
/* set the KEEPALIVE option to cull dead connections */
on = 1;
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
-#if !DEBUG
- if (fork() == 0)
-#endif
- {
- /* This is the spawned thread */
+
+ if (DEBUG || fork() == 0) {
+ /* child */
#if ENABLE_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
/* protect reload config, may be confuse checking */
signal(SIGHUP, SIG_IGN);
#endif
handleIncoming();
-#if !DEBUG
- exit(0);
-#endif
+ if (!DEBUG)
+ exit(0);
}
close(s);
- } // while (1)
+ } /* while (1) */
return 0;
}
USE_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;)
USE_FEATURE_HTTPD_AUTH_MD5(const char *pass;)
+#if ENABLE_LOCALE_SUPPORT
+ /* Undo busybox.c: we want to speak English in http (dates etc) */
+ setlocale(LC_TIME, "C");
+#endif
+
config = xzalloc(sizeof(*config));
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
config->realm = "Web Server Authentication";