1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-25 20:02:37 +03:00
esp8266/httpd/awhttpd.patch
cameronrich cd9b3c8865 improved performance
git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@30 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
2006-08-10 21:02:56 +00:00

2371 lines
54 KiB
Diff

diff -Naur awhttpd/aw3.h axTLS/httpd/awhttpd/aw3.h
--- awhttpd/aw3.h 2005-01-23 13:17:14.000000000 +1000
+++ axTLS/httpd/awhttpd/aw3.h 2006-08-10 18:33:47.609375000 +1000
@@ -7,17 +7,16 @@
*/
-#include <stdio.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+#include "os_port.h"
+#include "ssl.h"
#define BACKLOG 15
#define VERSION "3.0.7"
+#ifdef CONFIG_HTTP_HAS_IPV6
#define HAVE_IPV6
+#endif
#define MAXFILEPATH 1024
#define MAXIPLEN 45
@@ -26,6 +25,7 @@
#define BLOCKSIZE 4096
#define INITIAL_CONNECTION_SLOTS 10
+#define CONFIG_HTTP_DEFAULT_SSL_OPTIONS 0
#define STATE_WANT_TO_READ_HEAD 1
#define STATE_WANT_TO_SEND_HEAD 2
@@ -37,7 +37,6 @@
#define TYPE_HEAD 1
#define TYPE_POST 2
-
struct connstruct {
struct connstruct *next;
@@ -46,29 +45,43 @@
int networkdesc;
int filedesc;
- DIR *dirp;
- int timeout;
+#if defined(CONFIG_HTTP_DIRECTORIES)
+#ifdef WIN32
+ HANDLE dirp;
+ WIN32_FIND_DATA file_data;
+#else
+ DIR *dirp;
+#endif
+#endif
+ time_t timeout;
char ip[MAXIPLEN];
-
char actualfile[MAXREQUESTLENGTH];
char filereq[MAXREQUESTLENGTH];
+#if defined(CONFIG_HTTP_HAS_CGI)
char cgiargs[MAXREQUESTLENGTH];
char cgiscriptinfo[MAXREQUESTLENGTH];
char cgipathinfo[MAXREQUESTLENGTH];
+#endif
char virtualhostreq[MAXREQUESTLENGTH];
int numbytes;
- long offset;
char databuf[BLOCKSIZE];
+ unsigned char is_ssl;
+ unsigned char close_when_done;
+ unsigned char modified_since;
};
struct serverstruct {
struct serverstruct *next;
int sd;
+ int is_ssl;
+#ifdef CONFIG_HTTP_HAS_SSL
+ SSLCTX *ssl_ctx;
+#endif
};
@@ -96,28 +109,13 @@
// Conf global prototypes
-extern int usevirtualhosts;
extern char *webroot;
extern int allowdirectorylisting;
extern int allowcgi;
extern int permcheck;
-extern int maxusers;
-extern int usertimeout;
-extern int initialslots;
-extern char *quote;
-extern int initialslots;
-
-extern int numusers;
-
-
-// Useful macros
-#define istimedout(tp,ct) ((ct) > (tp)->timeout)
-#define updatetimeout(tp,ct) ((tp)->timeout = (ct)+usertimeout)
-
-
// conn.c prototypes
-void addconnection(int sd, char *ip);
+void addconnection(int sd, char *ip, int is_ssl);
void removeconnection(struct connstruct *cn);
@@ -129,49 +127,47 @@
void procsendhead(struct connstruct *cn);
void procreadfile(struct connstruct *cn);
void procsendfile(struct connstruct *cn);
+int special_write(struct connstruct *cn, const uint8_t *buf, size_t count);
// net.c prototypes
void addtoservers(int sd);
-void selectloop();
+void selectloop(void);
// socket.c prototypes
-int pollsocket(int sd, long ustimeout);
-void handlenewconnection(int listenfd);
+void handlenewconnection(int listenfd, int is_ssl);
int openlistener(int port);
int openlistener6(int port);
// errors.c prototypes
-void send505(int sd, char *reason);
void send404(struct connstruct *cn);
void send301(struct connstruct *cn);
// misc.c prototypes
-void nada();
-void die();
-void reaper();
+void nada(int sigtype);
+void die(int sigtype);
+void reaper(int sigtype);
void stripcrlf(char *p);
char *my_strncpy(char *dest, const char *src, size_t n);
#ifndef __HAVE_ARCH_STRNLEN
size_t strnlen ( const char * str, size_t maxlen );
#endif
int iscgi(char *fn);
-int split(char *tp, char *sp[], int maxwords, char sc);
-int confsplit(char *tp, char *sp[], int maxwords);
+void split(char *tp, char *sp[], int maxwords, char sc);
int sanitizefile(char *buf);
int sanitizehost(char *buf);
void buildactualfile(struct connstruct *cn);
int issockwriteable(int sd);
int isdir(char *name);
-void status();
int trycgi_withpathinfo(struct connstruct *cn);
// mime_types.c prototypes
-char *getmimetype(char *fn);
+void mime_init(void);
+const char *getmimetype(const char *fn);
// urldecode.c prototypes
@@ -188,7 +184,6 @@
// conf.c prototypes
-void defaultconfvals();
void procconf(char *filename);
@@ -202,4 +197,4 @@
// main.c prototypes
-void initlists();
+void initlists(void);
diff -Naur awhttpd/cgi.c axTLS/httpd/awhttpd/cgi.c
--- awhttpd/cgi.c 2005-06-04 14:09:52.000000000 +1000
+++ axTLS/httpd/awhttpd/cgi.c 2006-08-10 18:33:47.625000000 +1000
@@ -7,93 +7,46 @@
*/
-#include <unistd.h>
#include <string.h>
#include <stdlib.h>
-#include <sys/socket.h>
+#include <stdio.h>
#include "aw3.h"
+#if defined(CONFIG_HTTP_HAS_CGI)
void addcgiext(char *tp) {
struct cgiextstruct *ex;
ex = (struct cgiextstruct *) malloc(sizeof(struct cgiextstruct));
- if (ex == NULL) {
- fprintf(stderr, "Serious memory error...\n");
- exit(0);
- }
-
ex->ext = strdup(tp);
- if (ex->ext == NULL) {
- fprintf(stderr, "Serious memory error...\n");
- exit(0);
- }
-
ex->next = cgiexts;
cgiexts = ex;
-
- return;
-
-}
-
-
-
-void gensysenv(struct connstruct *cn) {
-
- #ifndef LIMITEDCGI
-
- char buf[1024];
-
- setenv("REMOTE_ADDR", cn->ip, 1);
-
- snprintf(buf, sizeof(buf), "%d", numusers);
- setenv("AW_NUMUSERS", buf, 1);
-
- setenv("AW_VERSION", VERSION, 1);
-
- setenv("AW_QUOTE", quote, 1);
-
-/* Commented this out because (and this is ridiculous) PHP
- doesn't seem to work with this variable specified
- */
-/*
- snprintf ( buf, sizeof(buf), "Anti-Web V%s (%s)", VERSION, quote );
- setenv("SERVER_SOFTWARE", buf, 1);
-*/
-
- setenv("SCRIPT_NAME", cn->cgiscriptinfo, 1);
-
- setenv("PATH_INFO", cn->cgipathinfo, 1);
-
- setenv("QUERY_STRING", cn->cgiargs, 1);
-
- return;
-
- #endif
-
}
-
-
void proccgi(struct connstruct *cn, int has_pathinfo) {
- int tpipe[2], fv;
- char *myargs[3];
+ int tpipe[2];
+ char *myargs[5];
char buf[MAXREQUESTLENGTH];
-
- snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: Anti-Web V%s (%s)\n%s",
- VERSION,
- quote, (cn->reqtype == TYPE_HEAD) ? "\n" : "");
- write(cn->networkdesc, buf, strlen(buf));
+#ifdef WIN32
+ int tmp_stdout;
+#else
+ int fv;
+#endif
+
+ snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: Anti-Web V%s\n%s",
+ VERSION, (cn->reqtype == TYPE_HEAD) ? "\n" : "");
+ special_write(cn, buf, strlen(buf));
if (cn->reqtype == TYPE_HEAD) {
removeconnection(cn);
return;
}
+#ifndef WIN32
if (pipe(tpipe) == -1) {
removeconnection(cn);
return;
@@ -108,7 +61,8 @@
return;
}
- if (fv != 0) {
+ if (fv != 0)
+ {
// Close the write descriptor
close(tpipe[1]);
cn->filedesc = tpipe[0];
@@ -132,19 +86,62 @@
close(tpipe[1]);
myargs[0] = cn->actualfile;
- myargs[1] = strdup(cn->cgiargs);
+ myargs[1] = cn->cgiargs;
myargs[2] = NULL;
- if (!has_pathinfo)
- {
- my_strncpy(cn->cgipathinfo, "/", MAXREQUESTLENGTH);
- my_strncpy(cn->cgiscriptinfo, cn->filereq, MAXREQUESTLENGTH);
- }
-
- gensysenv(cn);
+ if (!has_pathinfo) {
+ my_strncpy(cn->cgipathinfo, "/", MAXREQUESTLENGTH);
+ my_strncpy(cn->cgiscriptinfo, cn->filereq, MAXREQUESTLENGTH);
+ }
execv(cn->actualfile, myargs);
+#else /* WIN32 */
+ if (_pipe(tpipe, 4096, O_BINARY| O_NOINHERIT) == -1) {
+ removeconnection(cn);
+ return;
+ }
- exit(0);
+ myargs[0] = "sh";
+ myargs[1] = "-c";
+ myargs[2] = cn->actualfile;
+ myargs[3] = cn->cgiargs;
+ myargs[4] = NULL;
+
+ /* convert all the forward slashes to back slashes */
+ {
+ char *t = myargs[2];
+ while ((t = strchr(t, '\\')))
+ {
+ *t++ = '/';
+ }
+ }
+
+ tmp_stdout = _dup(_fileno(stdout));
+ _dup2(tpipe[1], _fileno(stdout));
+ close(tpipe[1]);
+
+ /* change to suit execution method */
+ if (spawnl(P_NOWAIT, "c:\\Program Files\\cygwin\\bin\\sh.exe",
+ myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]) == -1) {
+ removeconnection(cn);
+ return;
+ }
+
+ _dup2(tmp_stdout, _fileno(stdout));
+ close(tmp_stdout);
+ cn->filedesc = tpipe[0];
+ cn->state = STATE_WANT_TO_READ_FILE;
+
+ for (;;)
+ {
+ procreadfile(cn);
+ if (cn->filedesc == -1)
+ break;
+
+ procsendfile(cn);
+ usleep(200000); /* don't know why this delay makes it work (yet) */
+ }
+#endif
}
+#endif /* CONFIG_HTTP_HAS_CGI */
diff -Naur awhttpd/conf.c axTLS/httpd/awhttpd/conf.c
--- awhttpd/conf.c 2005-06-04 14:09:52.000000000 +1000
+++ axTLS/httpd/awhttpd/conf.c 1970-01-01 10:00:00.000000000 +1000
@@ -1,265 +0,0 @@
-/* Anti-Web HTTPD */
-/* Hardcore Software */
-/*
-This software is Copyright (C) 2001-2004 By Hardcore Software and
-others. The software is distributed under the terms of the GNU General
-Public License. See the file 'COPYING' for more details.
-*/
-
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "aw3.h"
-
-
-
-// CONF GLOBALS:
-
-int usevirtualhosts;
-char *webroot;
-int allowdirectorylisting;
-int allowcgi;
-int permcheck;
-int maxusers;
-int usertimeout;
-int initialslots;
-char *quote;
-
-int numusers;
-
-
-
-void defaultconfvals() {
-
- usevirtualhosts = 0;
- allowdirectorylisting = 0;
- allowcgi = 0;
- permcheck = 0;
- maxusers = 500;
- usertimeout = 5;
- initialslots = 10;
- quote = "Fear and loathing on the WWW";
-
- // Not really conf stuff:
- numusers = 0;
-
- return;
-
-}
-
-
-void procconf(char *filename) {
-
- FILE *fp;
- char buf[MAXREQUESTLENGTH];
- char *segs[10];
- int tp, err=0, warn=0;
-
- usevirtualhosts = 1;
-
- fp = fopen(filename, "r");
-
- if (fp == NULL) {
- fprintf(stderr, "ERROR: Unable to open conf file '%s'\n", filename);
- exit(1);
- }
-
-
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- stripcrlf(buf);
-
- confsplit(buf, segs, 10);
-
- if (segs[0] == NULL) continue;
-
- if (segs[1] == NULL) {
- fprintf(stderr, "ERR: Unknown command in '%s': '%s'\n", filename, segs[0]);
- err++;
- continue;
- }
-
-
- if (strcasecmp(segs[0], "listen") == 0) {
- if (isdigit(*segs[1])) {
- if ((tp=openlistener(atoi(segs[1]))) == -1) {
- fprintf(stderr, "ERR: Couldn't bind to port %d (IPv4)\n", atoi(segs[1]));
- err++;
- continue;
- }
-
- addtoservers(tp);
- continue;
- }
- }
-
- if (strcasecmp(segs[0], "listen6") == 0) {
- #ifdef HAVE_IPV6
- if (isdigit(*segs[1])) {
- if ((tp=openlistener6(atoi(segs[1]))) == -1) {
- fprintf(stderr, "ERR: Couldn't bind to port %d (IPv6)\n", atoi(segs[1]));
- err++;
- continue;
- }
-
- addtoservers(tp);
- continue;
- }
- #else
- fprintf(stderr, "ERR: AW was compiled without IPv6 support!\n");
- err++;
- continue;
- #endif
- }
-
- if (strcasecmp(segs[0], "maxusers") == 0) {
- maxusers = tp = atoi(segs[1]);
- if (tp < 1) {
- fprintf(stderr, "ERR: Bad value for maxusers\n");
- err++;
- }
- if (tp < 10 || tp > 10000) {
- fprintf(stderr, "WARN: Value for maxusers (%d) is not withing the recommended range\n", tp);
- warn++;
- }
- continue;
- }
-
- if (strcasecmp(segs[0], "usertimeout") == 0) {
- usertimeout = tp = atoi(segs[1]);
- if (tp < 1) {
- fprintf(stderr, "ERR: Bad value for usertimeout\n");
- err++;
- }
- if (tp > 100) {
- fprintf(stderr, "WARN: Value for usertimeout (%d) is not withing the recommended range\n", tp);
- warn++;
- }
- continue;
- }
-
- if (strcasecmp(segs[0], "initialslots") == 0) {
- initialslots = tp = atoi(segs[1]);
- if (tp < 1) {
- fprintf(stderr, "ERR: Bad value for initialslots\n");
- err++;
- }
- continue;
- }
-
- if (strcasecmp(segs[0], "directorylisting") == 0) {
- if (strcasecmp(segs[1], "on") == 0) allowdirectorylisting = 1;
- else if (strcasecmp(segs[1], "off") == 0) allowdirectorylisting = 0;
- else {
- fprintf(stderr, "ERR: Need on or off for directorylisting\n");
- err++;
- }
- continue;
- }
-
- if (strcasecmp(segs[0], "cgi") == 0) {
- if (strcasecmp(segs[1], "on") == 0) allowcgi = 1;
- else if (strcasecmp(segs[1], "off") == 0) allowcgi = 0;
- else {
- fprintf(stderr, "ERR: Need on or off for cgi\n");
- err++;
- }
- continue;
- }
-
- if (strcasecmp(segs[0], "cgiext") == 0) {
- if (*(segs[1]) != '.' && *(segs[1]+1) != '\0') {
- fprintf(stderr, "ERR: CGI extensions must start with a period and be at least 2 chars long\n");
- err++;
- continue;
- }
- addcgiext(segs[1]);
- continue;
- }
-
- if (strcasecmp(segs[0], "addindex") == 0) {
- if (*(segs[1]) == '.') {
- fprintf(stderr, "ERR: Index files can't start with a dot\n");
- err++;
- continue;
- }
- addindex(segs[1]);
- continue;
- }
-
- if (strcasecmp(segs[0], "permcheck") == 0) {
- if (strcasecmp(segs[1], "on") == 0) permcheck = 1;
- else if (strcasecmp(segs[1], "off") == 0) permcheck = 0;
- else {
- fprintf(stderr, "ERR: Need on or off for permcheck\n");
- err++;
- }
- continue;
- }
-
- if (strcasecmp(segs[0], "dropto") == 0) {
- struct passwd *bl;
-
- if ((bl = getpwnam(segs[1])) == NULL) {
- fprintf(stderr, "ERR: Unable to look up user '%s' to drop privileges\n", segs[1]);
- err++;
- } else {
- if (setgid(bl->pw_gid) != 0) {
- fprintf(stderr, "WARN: Unable to drop GID to %d\n", bl->pw_gid);
- warn++;
- }
- if (setuid(bl->pw_uid) != 0) {
- fprintf(stderr, "WARN: Unable to drop UID to %d\n", bl->pw_uid);
- warn++;
- }
- }
- continue;
- }
-
- if (strcasecmp(segs[0], "quote") == 0) {
- quote = strdup(segs[1]);
- continue;
- }
-
-
- if (segs[2] == NULL) {
- fprintf(stderr, "ERR: Unknown command in '%s': '%s'\n", filename, segs[0]);
- err++;
- continue;
- }
-
-
- // Otherwise:
-
- fprintf(stderr, "ERR: Unknown command in '%s': '%s'\n", filename, segs[0]);
- err++;
- continue;
-
- }
-
-
- if (initialslots > maxusers) {
- fprintf(stderr, "ERR: initialslots is greater than maxusers!\n");
- err++;
- }
-
-
- if (warn) {
- fprintf(stderr, "Alert! %d warnings!\n", warn);
- }
-
- if (err) {
- fprintf(stderr, "Unable to start: %d errors!\n", err);
- exit(1);
- }
-
- fclose(fp);
-
- return;
-
-}
diff -Naur awhttpd/conn.c axTLS/httpd/awhttpd/conn.c
--- awhttpd/conn.c 2004-12-07 16:11:02.000000000 +1000
+++ axTLS/httpd/awhttpd/conn.c 2006-08-10 18:33:47.625000000 +1000
@@ -9,26 +9,16 @@
#include <stdio.h>
#include <string.h>
-#include <unistd.h>
-#include <time.h>
#include <stdlib.h>
-
#include "aw3.h"
-
-void addconnection(int sd, char *ip) {
+void addconnection(int sd, char *ip, int is_ssl) {
struct connstruct *tp;
// Get ourselves a connstruct
if (freeconns == NULL) {
tp = (struct connstruct *) malloc(sizeof(struct connstruct));
- if (tp == NULL) {
- send505(sd, "Out of memory");
- // removeconnection() should be used normally
- close(sd);
- return;
- }
} else {
tp = freeconns;
freeconns = tp->next;
@@ -39,12 +29,21 @@
usedconns = tp;
tp->networkdesc = sd;
+#ifdef CONFIG_HTTP_HAS_SSL
+ if (is_ssl)
+ ssl_server_new(servers->ssl_ctx, sd);
+#endif
tp->filedesc = -1;
+#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
tp->dirp = NULL;
+#endif
+ tp->is_ssl = is_ssl;
*(tp->actualfile) = '\0';
*(tp->filereq) = '\0';
+#if defined(CONFIG_HTTP_HAS_CGI)
*(tp->cgiargs) = '\0';
+#endif
*(tp->virtualhostreq) = '\0';
tp->state = STATE_WANT_TO_READ_HEAD;
@@ -52,21 +51,16 @@
my_strncpy(tp->ip, ip, MAXIPLEN);
- tp->offset = -1;
-
- numusers++;
-
- updatetimeout(tp, time(NULL));
+ tp->close_when_done = 0;
+ tp->modified_since = 0;
+ tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;
return;
}
-// Remove cn from the used list
-// FIXME: This O(N) operation could be avoided if we used
-// doubly linked lists...
void removeconnection(struct connstruct *cn) {
struct connstruct *tp;
@@ -95,12 +89,21 @@
freeconns = cn;
// Close it all down
- if (cn->networkdesc != -1) close(cn->networkdesc);
+ if (cn->networkdesc != -1) {
+#ifdef CONFIG_HTTP_HAS_SSL
+ if (cn->is_ssl) {
+ ssl_free(ssl_find(servers->ssl_ctx, cn->networkdesc));
+ }
+#endif
+ SOCKET_CLOSE(cn->networkdesc);
+ }
if (cn->filedesc != -1) close(cn->filedesc);
- if (cn->dirp != NULL) closedir(cn->dirp);
-
- numusers--;
-
- return;
-
+#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
+ if (cn->dirp != NULL)
+#ifdef WIN32
+ FindClose(cn->dirp);
+#else
+ closedir(cn->dirp);
+#endif
+#endif
}
diff -Naur awhttpd/errors.c axTLS/httpd/awhttpd/errors.c
--- awhttpd/errors.c 2005-01-23 06:49:29.000000000 +1000
+++ axTLS/httpd/awhttpd/errors.c 2006-08-10 18:33:47.625000000 +1000
@@ -8,7 +8,6 @@
#include <stdio.h>
-#include <unistd.h>
#include <string.h>
#include "aw3.h"
@@ -20,7 +19,7 @@
snprintf(buf, sizeof(buf), "HTTP/1.1 301 Moved Permanently\nLocation: %s/\n\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>301 Moved Permanently</TITLE>\n</HEAD><BODY>\n<H1>Moved Permanently</H1>\nThe document has moved <A HREF=\"%s/\">here</A>.<P>\n<HR>\n</BODY></HTML>\n", cn->filereq, cn->filereq);
- write(cn->networkdesc, buf, strlen(buf));
+ special_write(cn, buf, strlen(buf));
return;
@@ -34,21 +33,7 @@
snprintf(buf, sizeof(buf), "HTTP/1.0 404 Not Found\nContent-Type: text/html\n\n<HTML><BODY>\n<TITLE>404 Not Found</TITLE><H1>It ain't there my friend. (404 Not Found)</H1>\n<BR><BR>Anti-Web HTTPD - Take back some simplicity.\n</BODY></HTML>\n");
- write(cn->networkdesc, buf, strlen(buf));
-
- return;
-
-}
-
-
-
-void send505(int sd, char *reason) {
-
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "HTTP/1.0 505 Server Error\nContent-Type: text/html\n\n<HTML><BODY>\n<TITLE>505 Internal Server Error</TITLE><H1>Internal Server Error: %s</H1>\n<BR><BR>Anti-Web HTTPD - Take back some simplicity.\n</BODY></HTML>\n", reason);
-
- write(sd, buf, strlen(buf));
+ special_write(cn, buf, strlen(buf));
return;
diff -Naur awhttpd/index.c axTLS/httpd/awhttpd/index.c
--- awhttpd/index.c 2005-06-04 14:09:52.000000000 +1000
+++ axTLS/httpd/awhttpd/index.c 2006-08-10 18:33:47.625000000 +1000
@@ -11,7 +11,6 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <unistd.h>
#include <stdlib.h>
#include "aw3.h"
@@ -22,20 +21,9 @@
struct indexstruct *ex;
ex = (struct indexstruct *) malloc(sizeof(struct indexstruct));
- if (ex == NULL) {
- fprintf(stderr, "Serious memory error...\n");
- exit(1);
- }
-
ex->name = strdup(tp);
- if (ex->name == NULL) {
- fprintf(stderr, "Serious memory error...\n");
- exit(1);
- }
-
ex->next = indexlist;
indexlist = ex;
-
return;
}
@@ -52,7 +40,13 @@
tp = indexlist;
while(tp != NULL) {
- snprintf(tbuf, sizeof(tbuf), "%s%s", cn->actualfile, tp->name);
+ sprintf(tbuf, "%s%s%s", cn->actualfile,
+#ifdef WIN32
+ "\\",
+#else
+ "/",
+#endif
+ tp->name);
if (stat(tbuf, stp) != -1) {
my_strncpy(cn->actualfile, tbuf, MAXREQUESTLENGTH);
diff -Naur awhttpd/main.c axTLS/httpd/awhttpd/main.c
--- awhttpd/main.c 2005-06-04 14:09:52.000000000 +1000
+++ axTLS/httpd/awhttpd/main.c 2006-08-11 06:46:48.437500000 +1000
@@ -11,7 +11,6 @@
#include <string.h>
#include <sys/types.h>
#include <signal.h>
-#include <unistd.h>
#include <stdlib.h>
#include "aw3.h"
@@ -21,10 +20,42 @@
struct serverstruct *servers;
struct connstruct *usedconns;
struct connstruct *freeconns;
+#if defined(CONFIG_HTTP_HAS_CGI)
struct cgiextstruct *cgiexts;
+#endif
struct indexstruct *indexlist;
+char *webroot = CONFIG_HTTP_WEBROOT;
+/* clean up memory for valgrind */
+static void sigint_cleanup(int sig)
+{
+ struct serverstruct *sp;
+ struct connstruct *tp;
+ int i;
+
+ while(servers != NULL) {
+#ifdef CONFIG_HTTP_HAS_SSL
+ if (servers->is_ssl)
+ ssl_ctx_free(servers->ssl_ctx);
+#endif
+ sp = servers->next;
+ free(servers);
+ servers = sp;
+ }
+ free(indexlist->name);
+ free(indexlist);
+ for(i=0; i< INITIAL_CONNECTION_SLOTS; i++) {
+ if (freeconns == NULL)
+ break;
+
+ tp = freeconns->next;
+ free(freeconns);
+ freeconns = tp;
+ }
+
+ exit(0);
+}
void initlists() {
int i;
@@ -33,108 +64,119 @@
servers = NULL;
usedconns = NULL;
freeconns = NULL;
+#if defined(CONFIG_HTTP_HAS_CGI)
cgiexts = NULL;
+#endif
indexlist = NULL;
for(i=0; i<INITIAL_CONNECTION_SLOTS; i++) {
tp = freeconns;
- freeconns = (struct connstruct *) malloc(sizeof(struct connstruct));
- if (freeconns == NULL) {
- fprintf(stderr, "Not enough memory to allocate %d connection slots!\n",
- INITIAL_CONNECTION_SLOTS);
- exit(1);
- }
+ freeconns = (struct connstruct *) calloc(1, sizeof(struct connstruct));
freeconns->next = tp;
}
}
-void usage(char *cmline) {
- fprintf(stderr, "Anti-Web V%s (C) 2001-2004 by Hardcore Software and others\n\n", VERSION);
-
- fprintf(stderr, " AW has 2 valid command lines (see README for details)\n\n");
-
- fprintf(stderr, " %s <dir> <port>\n", cmline);
- fprintf(stderr, " <dir> The root of your HTML tree\n");
- fprintf(stderr, " <port> The port to use\n\n");
-
- fprintf(stderr, " %s <dir>\n", cmline);
- fprintf(stderr, " <dir>/awhttpd.conf Conf file\n");
- fprintf(stderr, " <dir>/default/ Default HTML root\n");
- fprintf(stderr, " <dir>/example.com/ Zero or more virtual host directories\n");
-
- exit(1);
-}
-
-
int main(int argc, char *argv[]) {
- char buf[MAXREQUESTLENGTH];
- int pid, tp;
-
+ int tp;
+#if defined(CONFIG_HTTP_IS_DAEMON)
+ int pid;
+#endif
+
+#ifdef WIN32
+ WORD wVersionRequested = MAKEWORD(2,2);
+ WSADATA wsaData;
+ WSAStartup(wVersionRequested,&wsaData);
+#endif
+
+ mime_init();
initlists();
-
- if (argc != 2 && argc != 3) usage(argv[0]);
-
- webroot = strdup(argv[1]);
-
tp = strlen(webroot);
if (webroot[tp-1] == '/') webroot[tp-1] = '\0';
if (isdir(webroot) == 0) {
+#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "'%s' is not a directory\n", webroot);
+#endif
exit(1);
}
- defaultconfvals();
-
- if (argc == 2) {
- snprintf(buf, sizeof(buf), "%s/awhttpd.conf", webroot);
- procconf(buf);
- } else {
- if ((tp=openlistener(atoi(argv[2]))) == -1) {
- fprintf(stderr, "ERR: Couldn't bind to port %d (IPv4)\n", atoi(argv[2]));
+ if ((tp=openlistener(CONFIG_HTTP_PORT)) == -1) {
+#ifdef CONFIG_HTTP_VERBOSE
+ fprintf(stderr, "ERR: Couldn't bind to port %d (IPv4)\n",
+ CONFIG_HTTP_PORT);
+#endif
exit(1);
- }
+ }
addindex("index.html");
addtoservers(tp);
- setgid(32767);
- setuid(32767);
- }
- if (permcheck == 1) procpermcheck(webroot);
+#ifndef WIN32
+ if (getuid() == 0)
+ {
+ setgid(32767);
+ setuid(32767);
+ }
+#endif
+
+#ifdef CONFIG_HTTP_HAS_SSL
+ if ((tp=openlistener(CONFIG_HTTP_HTTPS_PORT)) == -1) {
+#ifdef CONFIG_HTTP_VERBOSE
+ fprintf(stderr, "ERR: Couldn't bind to port %d (IPv4)\n",
+ CONFIG_HTTP_HTTPS_PORT);
+#endif
+ exit(1);
+ }
+
+ addtoservers(tp);
+ servers->ssl_ctx = ssl_ctx_new(CONFIG_HTTP_DEFAULT_SSL_OPTIONS,
+ CONFIG_HTTP_SESSION_CACHE_SIZE);
+ servers->is_ssl = 1;
+#endif /* CONFIG_HTTP_HAS_SSL */
+
+#if defined(CONFIG_HTTP_PERM_CHECK)
+ procpermcheck(webroot);
+#endif
+#if defined(CONFIG_HTTP_HAS_CGI)
+ addcgiext(CONFIG_HTTP_CGI_EXTENSION);
+#endif
+#if defined(CONFIG_HTTP_VERBOSE)
+ printf("awhttpd: listening on ports http:%d and https:%d\n",
+ CONFIG_HTTP_PORT, CONFIG_HTTP_HTTPS_PORT);
+ TTY_FLUSH();
+#endif
+#if defined(CONFIG_HTTP_IS_DAEMON)
pid = fork();
if(pid > 0) {
status();
exit(0);
} else if(pid == -1) {
+#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr,"Anti-Web: Sorry, fork failed... Tough dice.\n");
+#endif
exit(1);
}
setsid();
+#endif
/* SIGNALS */
- signal(SIGINT, die);
- signal(SIGQUIT, die);
+ signal(SIGINT, sigint_cleanup);
signal(SIGTERM, die);
+#if defined(CONFIG_HTTP_HAS_CGI)
+#ifndef WIN32
signal(SIGCHLD, reaper);
-
- #ifndef SOLARIS
- signal(SIGPIPE, nada);
- #endif
-
- #ifdef SOLARIS
- act.sa_handler = nada;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_RESTART;
-
- sigaction(SIGPIPE,&act,NULL);
- #endif
-
+#endif
+#endif
+#ifndef WIN32
+ signal(SIGQUIT, die);
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
selectloop();
return 0;
diff -Naur awhttpd/mime_types.c axTLS/httpd/awhttpd/mime_types.c
--- awhttpd/mime_types.c 2004-01-26 01:08:47.000000000 +1000
+++ axTLS/httpd/awhttpd/mime_types.c 2006-08-10 18:33:47.625000000 +1000
@@ -7,28 +7,21 @@
*/
-/*Code from mini_httpd - small HTTP server
-**
-** Copyright C 1999,2000 by Jef Poskanzer <jef@acme.com>.
-*/
-
-/* mini_httpd code adapted for Anti-Web by zas@norz.org */
-/* A couple TINY changes by Fractal */
-
-// Reformatted for aw3 -fractal
-
-// FIXME: Ideally this code would use a binary search or a hash table...
-
-
#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "os_port.h"
-char mime_default[] = "text/plain";
+static const char mime_default[] = "text/plain";
-struct {
- char *ext;
- char *type;
-} mime_table[] = {
+typedef struct {
+ const char * const ext;
+ const char * const type;
+} mime_table_t;
+
+static mime_table_t mime_table[] = {
// Fundamentals
{ ".html", "text/html" },
@@ -160,21 +153,29 @@
};
+static int mime_cmp(const mime_table_t *t1, const mime_table_t *t2)
+{
+ return strcasecmp(t1->ext, t2->ext);
+}
-char *getmimetype(char *name) {
- int namelen, extlen, i;
-
- namelen = strlen(name);
-
- for (i=0; i<sizeof(mime_table)/sizeof(*mime_table); i++) {
- extlen = strlen(mime_table[i].ext);
+void mime_init(void)
+{
+ qsort(mime_table, sizeof(mime_table)/sizeof(mime_table_t),
+ sizeof(mime_table_t),
+ (int (*)(const void *, const void *))mime_cmp);
+}
- if (extlen >= namelen) continue;
+const char *getmimetype(const char *name) {
+ mime_table_t *mime_type;
- if (strcasecmp(name+(namelen-extlen), mime_table[i].ext) == 0)
- return mime_table[i].type;
- }
+ if ((name = strrchr(name, '.')) == NULL)
+ return mime_default;
- return mime_default;
+ mime_type = bsearch(&name, mime_table,
+ sizeof(mime_table)/sizeof(mime_table_t),
+ sizeof(mime_table_t),
+ (int (*)(const void *, const void *))mime_cmp);
+ return mime_type == NULL ? mime_default : mime_type->type;
}
+
diff -Naur awhttpd/misc.c axTLS/httpd/awhttpd/misc.c
--- awhttpd/misc.c 2005-01-23 12:59:09.000000000 +1000
+++ axTLS/httpd/awhttpd/misc.c 2006-08-10 18:33:47.625000000 +1000
@@ -7,33 +7,33 @@
*/
-#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
-#include <sys/time.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <unistd.h>
#include "aw3.h"
-void nada() { }
+void nada(int sigtype) { }
-void die() {
+void die(int sigtype) {
exit(0);
}
-void reaper() {
+#if defined(CONFIG_HTTP_HAS_CGI)
+#ifndef WIN32
+void reaper(int sigtype) {
wait3(NULL,WNOHANG,NULL);
}
+#endif
+#endif
void stripcrlf(char *p) {
@@ -76,116 +76,6 @@
}
#endif
-
-int iscgi(char *fn) {
-
- struct cgiextstruct *tp;
- int fnlen, extlen;
-
- fnlen = strlen(fn);
- tp = cgiexts;
-
- while (tp != NULL) {
- extlen = strlen(tp->ext);
-
- if (strcasecmp(fn+(fnlen-extlen), tp->ext) == 0)
- return 1;
-
- tp = tp->next;
- }
-
- return 0;
-
-}
-
-
-
-int split(char *tp, char *sp[], int maxwords, char sc) {
-
- int i=0;
-
- while(1) {
- /* Skip leading whitespace */
- while(*tp == sc) tp++;
-
- if (*tp == '\0') {
- sp[i] = NULL;
- break;
- }
- if (i==maxwords-2) {
- sp[maxwords-2] = NULL;
- break;
- }
-
- sp[i] = tp;
-
- while(*tp != sc && *tp != '\0') tp++;
- if (*tp == sc) *tp++ = '\0';
- i++;
-
- }
-
- return i;
-
-}
-
-
-
-int confsplit(char *tp, char *sp[], int maxwords) {
-
- int i;
-
- // Skip comments
- i=0;
- while (tp[i] != '\0' && tp[i] != '#') i++;
- tp[i] = '\0';
-
- i=0;
- while(1) {
- /* Skip leading whitespace */
- while(*tp == ' ') tp++;
-
- if (*tp == '\0') {
- sp[i] = NULL;
- break;
- }
- if (i==maxwords-2) {
- sp[maxwords-2] = NULL;
- break;
- }
-
- if (*tp == '"') {
- tp++;
-
- if (*tp == '"') {
- tp++;
- continue;
- }
-
- sp[i] = tp;
-
- while(*tp != '"' && *tp != '\0') tp++;
- if (*tp == '"') *tp++ = '\0';
- i++;
-
- } else {
- sp[i] = tp;
-
- while(*tp != ' ' && *tp != '\0') tp++;
- if (*tp == ' ') *tp++ = '\0';
- i++;
- }
-
- }
-
- return i;
-
-}
-
-
-
-
-
int sanitizefile(char *buf) {
int len,i;
@@ -198,9 +88,6 @@
// Check for "/." : In other words, don't send files starting with a .
// Notice, GOBBLES, that this includes ".."
if (buf[i] == '/' && buf[i+1] == '.') return 0;
-
- // Give people a "hidden prefix" for hiding private files in the HTML tree
- if (strncmp(buf+i, "/aw_", 4) == 0) return 0;
}
return 1;
@@ -231,34 +118,33 @@
}
-
-
void buildactualfile(struct connstruct *cn) {
- char tpbuf[MAXREQUESTLENGTH];
-
- if (usevirtualhosts) {
- if (*(cn->virtualhostreq) == '\0')
- my_strncpy(cn->virtualhostreq, "default", MAXREQUESTLENGTH);
-
- snprintf(tpbuf, sizeof(tpbuf), "%s/%s", webroot, cn->virtualhostreq);
- if (isdir(tpbuf) == 0) {
- my_strncpy(cn->virtualhostreq, "default", MAXREQUESTLENGTH);
- }
- } else {
- *(cn->virtualhostreq) = '\0';
- }
-
- snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s/%s%s",
+ snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s%s",
webroot,
- cn->virtualhostreq,
cn->filereq);
+ /* Add directory slash if not there */
+ if (isdir(cn->actualfile) &&
+ cn->actualfile[strlen(cn->actualfile)-1] != '/')
+ strcat(cn->actualfile, "/");
+
+#ifdef WIN32
+ /* convert all the forward slashes to back slashes */
+ {
+ char *t = cn->actualfile;
+ while ((t = strchr(t, '/')))
+ {
+ *t++ = '\\';
+ }
+ }
+#endif
+
return;
}
-
+#if defined(CONFIG_HTTP_DIRECTORIES)
int issockwriteable(int sd) {
fd_set wfds;
@@ -275,11 +161,11 @@
return FD_ISSET(sd, &wfds);
}
-
+#endif
int isdir(char *tpbuf) {
- static struct stat st;
+ struct stat st;
if (stat(tpbuf, &st) == -1) return 0;
@@ -288,25 +174,52 @@
}
+#if defined(CONFIG_HTTP_HAS_CGI)
+int iscgi(char *fn) {
+ struct cgiextstruct *tp;
+ int fnlen, extlen;
-// FIXME: Arg! This function is horrible! Rewrite it
-void status() {
+ fnlen = strlen(fn);
+ tp = cgiexts;
- int i;
+ while (tp != NULL) {
+ extlen = strlen(tp->ext);
- fprintf(stdout," [*************************************************]\n");
- fprintf(stdout," [ Anti-Web V%-6s by Hardcore Software ]\n",VERSION);
- fprintf(stdout," [*************************************************]\n");
- fprintf(stdout," [ DIRECTORY {%s}",webroot);
- if(strlen(webroot)<35)
- for(i=1;i<=35-strlen(webroot);i++) fprintf(stdout," ");
- fprintf(stdout,"]\n");
- fprintf(stdout," [*************************************************]\n");
+ if (strcasecmp(fn+(fnlen-extlen), tp->ext) == 0)
+ return 1;
+
+ tp = tp->next;
+ }
+
+ return 0;
}
+void split(char *tp, char *sp[], int maxwords, char sc) {
+
+ int i=0;
+ while(1) {
+ /* Skip leading whitespace */
+ while(*tp == sc) tp++;
+
+ if (*tp == '\0') {
+ sp[i] = NULL;
+ break;
+ }
+ if (i==maxwords-2) {
+ sp[maxwords-2] = NULL;
+ break;
+ }
+
+ sp[i] = tp;
+
+ while(*tp != sc && *tp != '\0') tp++;
+ if (*tp == sc) *tp++ = '\0';
+ i++;
+ }
+}
/* This function was originally written by Nicolas Benoit
but I've rewritten some parts of it to work under
@@ -329,7 +242,7 @@
while (fr_rs[i] != NULL) {
snprintf(tpfile, sizeof(tpfile), "%s/%s%s", webroot, cn->virtualhostreq, fr_str);
- if (iscgi(tpfile) && access(tpfile, X_OK) == 0 && isdir(tpfile) == 0) {
+ if (iscgi(tpfile) && isdir(tpfile) == 0) {
/* We've found our CGI file! */
my_strncpy(cn->actualfile, tpfile, MAXREQUESTLENGTH);
my_strncpy(cn->cgiscriptinfo, fr_str, MAXREQUESTLENGTH);
@@ -349,3 +262,4 @@
*(cn->cgipathinfo) = '\0';
return -1;
}
+#endif
diff -Naur awhttpd/net.c axTLS/httpd/awhttpd/net.c
--- awhttpd/net.c 2005-06-04 14:09:52.000000000 +1000
+++ axTLS/httpd/awhttpd/net.c 2006-08-10 18:33:47.640625000 +1000
@@ -8,9 +8,7 @@
#include <stdio.h>
-#include <sys/time.h>
#include <sys/types.h>
-#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
@@ -23,17 +21,10 @@
void addtoservers(int sd) {
struct serverstruct *tp;
- tp = (struct serverstruct *) malloc(sizeof(struct serverstruct));
- if (tp == NULL) {
- fprintf(stderr, "Serious memory error...\n");
- exit(1);
- }
-
+ tp = (struct serverstruct *) calloc(1, sizeof(struct serverstruct));
tp->next = servers;
tp->sd = sd;
-
servers = tp;
-
return;
}
@@ -64,7 +55,7 @@
currtime = time(NULL);
while(tp != NULL) {
- if (istimedout(tp, currtime)) {
+ if (currtime > tp->timeout) {
to = tp;
tp = tp->next;
removeconnection(to);
@@ -87,14 +78,15 @@
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum) wnum = tp->networkdesc;
}
+#if defined(CONFIG_HTTP_DIRECTORIES)
if (tp->state == STATE_DOING_DIR) {
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum) wnum = tp->networkdesc;
}
+#endif
tp = tp->next;
}
- //active = select(4, &rfds, &wfds, NULL, NULL);
active = select(wnum > rnum ? wnum+1 : rnum+1,
rnum != -1 ? &rfds : NULL,
wnum != -1 ? &wfds : NULL,
@@ -104,7 +96,7 @@
sp = servers;
while(active > 0 && sp != NULL) {
if (FD_ISSET(sp->sd, &rfds)) {
- handlenewconnection(sp->sd);
+ handlenewconnection(sp->sd, sp->is_ssl);
active--;
}
sp = sp->next;
@@ -112,41 +104,37 @@
// Handle the established sockets
tp = usedconns;
- currtime = time(NULL);
while(active > 0 && tp != NULL) {
to = tp;
tp = tp->next;
if (to->state == STATE_WANT_TO_READ_HEAD)
if (FD_ISSET(to->networkdesc, &rfds)) {
- updatetimeout(to, currtime);
active--;
procreadhead(to);
}
if (to->state == STATE_WANT_TO_SEND_HEAD)
if (FD_ISSET(to->networkdesc, &wfds)) {
- updatetimeout(to, currtime);
active--;
procsendhead(to);
}
if (to->state == STATE_WANT_TO_READ_FILE)
if (FD_ISSET(to->filedesc, &rfds)) {
- updatetimeout(to, currtime);
active--;
procreadfile(to);
}
if (to->state == STATE_WANT_TO_SEND_FILE)
if (FD_ISSET(to->networkdesc, &wfds)) {
- updatetimeout(to, currtime);
active--;
procsendfile(to);
}
+#if defined(CONFIG_HTTP_DIRECTORIES)
if (to->state == STATE_DOING_DIR)
if (FD_ISSET(to->networkdesc, &wfds)) {
- updatetimeout(to, currtime);
active--;
procdodir(to);
}
+#endif
}
diff -Naur awhttpd/permcheck.c axTLS/httpd/awhttpd/permcheck.c
--- awhttpd/permcheck.c 2005-01-23 06:49:29.000000000 +1000
+++ axTLS/httpd/awhttpd/permcheck.c 2006-08-10 18:33:47.640625000 +1000
@@ -7,21 +7,23 @@
*/
-#include <unistd.h>
#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
#include "aw3.h"
+#if defined(CONFIG_HTTP_PERM_CHECK)
void procpermcheck(char *pathtocheck) {
-
+ char thepath[MAXREQUESTLENGTH];
+#ifndef WIN32
DIR *tpdir;
struct dirent *dp;
- char thepath[MAXREQUESTLENGTH];
tpdir=opendir(pathtocheck);
if (tpdir==NULL) {
- printf("WARNING: UID (%d) is unable to read %s\n", getuid(), pathtocheck);
+ printf("WARNING: UID (%d) is unable to read %s\n", (int)getuid(), pathtocheck);
return;
}
@@ -38,14 +40,56 @@
}
if (access(thepath, R_OK) != 0)
- printf("WARNING: UID (%d) is unable to read %s\n", getuid(), thepath);
+ printf("WARNING: UID (%d) is unable to read %s\n", (int)getuid(), thepath);
if (access(thepath, W_OK) == 0)
- printf("SECURITY: UID (%d) is ABLE TO WRITE TO %s\n", getuid(), thepath);
+ printf("SECURITY: UID (%d) is ABLE TO WRITE TO %s\n", (int)getuid(), thepath);
}
closedir(tpdir);
+#else /* Win32 */
+ HANDLE tpdir;
+ WIN32_FIND_DATA file_data;
+ struct stat st;
+ char buf2[1024];
+
+ strcpy(buf2, pathtocheck);
+ strcat(buf2, "\\*");
+ tpdir = FindFirstFile(buf2, &file_data);
+
+ if (tpdir == INVALID_HANDLE_VALUE) {
+ printf("WARNING: unable to read %s\n", buf2);
+ TTY_FLUSH();
+ return;
+ }
+
+ while (FindNextFile(tpdir, &file_data)) {
+
+ if (strcmp(file_data.cFileName, "..")==0) continue;
+ if (strcmp(file_data.cFileName, ".")==0) continue;
+
+ snprintf(thepath, sizeof(thepath), "%s\\%s",
+ pathtocheck, file_data.cFileName);
- return;
+ if (isdir(thepath)) {
+ procpermcheck(thepath);
+ continue;
+ }
+
+ if (stat(thepath, &st) >= 0) {
+ if ((st.st_mode & _S_IREAD) == 0) {
+ printf("WARNING: unable to read %s\n", thepath);
+ TTY_FLUSH();
+ }
+
+ if (st.st_mode & _S_IWRITE) {
+ printf("SECURITY: ABLE TO WRITE TO %s\n", thepath);
+ TTY_FLUSH();
+ }
+ }
+ }
+ FindClose(tpdir);
+#endif
}
+#endif /* CONFIG_HTTP_PERM_CHECK */
diff -Naur awhttpd/proc.c axTLS/httpd/awhttpd/proc.c
--- awhttpd/proc.c 2005-01-23 10:59:41.000000000 +1000
+++ axTLS/httpd/awhttpd/proc.c 2006-08-10 18:33:47.640625000 +1000
@@ -13,91 +13,92 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include <unistd.h>
#include <time.h>
#include <string.h>
#include "aw3.h"
-
-
+static int special_read(struct connstruct *cn, void *buf, size_t count);
// Returns 1 if elems should continue being read, 0 otherwise
int procheadelem(struct connstruct *cn, char *buf) {
- char *words[10];
-
- split(buf, words, 10, ' ');
+ char *delim, *value;
+#if defined(CONFIG_HTTP_HAS_CGI)
+ char *cgi_delim;
+#endif
- if (words[0] == NULL) return 0;
-
- if (strcmp(words[0], "GET")==0 ||
- strcmp(words[0], "HEAD")==0 ||
- strcmp(words[0], "POST")==0) {
- char *segs[4];
-
- if (*words[0] == 'H') cn->reqtype = TYPE_HEAD;
- else if (*words[0] == 'P') cn->reqtype = TYPE_POST;
+ if ((delim = strchr(buf, ' ')) == NULL)
+ return 0;
- split(words[1], segs, 4, '?');
+ *delim = 0;
+ value = delim+1;
- if (segs[0] == NULL) return 0;
+ if (strcmp(buf, "GET")==0 ||
+ strcmp(buf, "HEAD")==0 ||
+ strcmp(buf, "POST")==0)
+ {
+ if (buf[0] == 'H')
+ cn->reqtype = TYPE_HEAD;
+ else if (buf[0] == 'P')
+ cn->reqtype = TYPE_POST;
+
+ if ((delim = strchr(value, ' ')) == NULL) /* expect HTTP type */
+ return 0;
+ *delim = 0;
- urldecode(segs[0]);
+ urldecode(value);
- if (sanitizefile(segs[0]) == 0) {
+ if (sanitizefile(value) == 0) {
send404(cn);
removeconnection(cn);
return 0;
}
- my_strncpy(cn->filereq, segs[0], MAXREQUESTLENGTH);
-
- if (segs[1] != NULL) my_strncpy(cn->cgiargs, segs[1], MAXREQUESTLENGTH);
-
- } else if (strcmp(words[0], "Host:")==0) {
+ my_strncpy(cn->filereq, value, MAXREQUESTLENGTH);
+#if defined(CONFIG_HTTP_HAS_CGI)
+ if ((cgi_delim = strchr(value, '?')))
+ {
+ *cgi_delim = NULL;
+ my_strncpy(cn->cgiargs, value+1, MAXREQUESTLENGTH);
+ }
+#endif
- if (words[1] == NULL) return 0;
+ } else if (strcmp(buf, "Host:")==0) {
- if (sanitizehost(words[1]) == 0) {
+ if (sanitizehost(value) == 0) {
send404(cn);
removeconnection(cn);
return 0;
}
- my_strncpy(cn->virtualhostreq, words[1], MAXREQUESTLENGTH);
- } else if (strcmp(words[0], "Range:")==0) {
-
- cn->offset = -1;
-
- if (strchr(words[1], '-') == NULL) return 1;
-
- if (strchr(words[1], '=') != NULL) {
- while(*words[1] != '=') words[1]++;
- words[1]++;
- }
-
- if (isdigit(*words[1]) == 0) return 1;
-
- cn->offset = atoi(words[1]);
-
+ my_strncpy(cn->virtualhostreq, value, MAXREQUESTLENGTH);
+ } else if (strcmp(buf, "Connection:")==0 &&
+ strcmp(value, "close")==0) {
+ cn->close_when_done = 1;
+ } else if (strcmp(buf, "If-Modified-Since:") ==0 ) {
+ /* TODO: parse this date properly with getdate() or similar */
+ cn->modified_since = 1;
}
return 1;
-}
-
+}
+#if defined(CONFIG_HTTP_DIRECTORIES)
void procdirlisting(struct connstruct *cn) {
char buf[MAXREQUESTLENGTH];
+ char actualfile[1024];
+#ifndef CONFIG_HTTP_DIRECTORIES
if (allowdirectorylisting == 0) {
send404(cn);
removeconnection(cn);
return;
}
+#endif
if (cn->reqtype == TYPE_HEAD) {
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n");
@@ -107,7 +108,17 @@
return;
}
- cn->dirp = opendir(cn->actualfile);
+ strcpy(actualfile, cn->actualfile);
+#ifdef WIN32
+ strcat(actualfile, "*");
+ cn->dirp = FindFirstFile(actualfile, &cn->file_data);
+ if (cn->dirp == INVALID_HANDLE_VALUE) {
+ send404(cn);
+ removeconnection(cn);
+ return;
+ }
+#else
+ cn->dirp = opendir(actualfile);
if (cn->dirp == NULL) {
send404(cn);
removeconnection(cn);
@@ -116,12 +127,13 @@
// Get rid of the "."
readdir(cn->dirp);
+#endif
// If the browser doesn't specify a virtual host, the client will
// see "http://default/thedir/" instead of "http://thehost.com/thedir/"
// Consider this punishment for using such an old browser.
- snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<HTML><BODY>\n<TITLE>Directory Listing</TITLE>\n<H2>Directory listing of http://%s%s</H2><BR>\n", cn->virtualhostreq, cn->filereq);
- write(cn->networkdesc, buf, strlen(buf));
+ snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<HTML><BODY>\n<TITLE>Directory Listing</TITLE>\n<H2>Directory listing of %s://%s%s</H2><BR>\n", cn->is_ssl ? "https" : "http", cn->virtualhostreq, cn->filereq);
+ special_write(cn, buf, strlen(buf));
cn->state = STATE_DOING_DIR;
@@ -134,36 +146,48 @@
void procdodir(struct connstruct *cn) {
+#ifndef WIN32
struct dirent *dp;
+#endif
char buf[MAXREQUESTLENGTH];
- char encbuf[sizeof(dp->d_name)*3+1];
+ char encbuf[1024];
int putslash;
+ char *file;
do {
- if ((dp = readdir(cn->dirp)) == NULL) {
+#ifdef WIN32
+ if (!FindNextFile(cn->dirp, &cn->file_data)) {
+#else
+ if ((dp = readdir(cn->dirp)) == NULL) {
+#endif
snprintf(buf, sizeof(buf), "<BR><BR>End of Anti-Web directory listing.</BODY></HTML>\n");
- write(cn->networkdesc, buf, strlen(buf));
+ special_write(cn, buf, strlen(buf));
removeconnection(cn);
return;
}
+#ifdef WIN32
+ file = cn->file_data.cFileName;
+#else
+ file = dp->d_name;
+#endif
if (cn->filereq[0] == '/' && cn->filereq[1] == '\0' &&
- strcmp(dp->d_name, "..") == 0) continue;
+ strcmp(file, "..") == 0) continue;
- snprintf(buf, sizeof(buf), "%s%s", cn->actualfile, dp->d_name);
+ snprintf(buf, sizeof(buf), "%s%s", cn->actualfile, file);
putslash = isdir(buf);
- urlencode(dp->d_name, encbuf);
+ urlencode(file, encbuf);
snprintf(buf, sizeof(buf), "<A HREF=\"%s%s\">%s%s</A><BR>\n",
- encbuf, putslash ? "/" : "", dp->d_name, putslash ? "/" : "");
- write(cn->networkdesc, buf, strlen(buf));
+ encbuf, putslash ? "/" : "", file, putslash ? "/" : "");
+ special_write(cn, buf, strlen(buf));
} while (issockwriteable(cn->networkdesc));
return;
}
-
+#endif
@@ -172,9 +196,10 @@
char buf[MAXREQUESTLENGTH*4], *tp, *next;
int rv;
- rv = read(cn->networkdesc, buf, sizeof(buf)-1);
- if (rv == 0 || rv == -1) {
- removeconnection(cn);
+ rv = special_read(cn, buf, sizeof(buf)-1);
+ if (rv <= 0) {
+ if (rv < 0)
+ removeconnection(cn);
return;
}
@@ -217,36 +242,85 @@
void procsendhead(struct connstruct *cn) {
char buf[1024];
+ char actualfile[1024];
struct stat stbuf;
+ time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT;
+ char date[32];
+ strcpy(date, ctime(&now));
+
+ strcpy(actualfile, cn->actualfile);
+
+#ifdef WIN32
+ /* stat() under win32 can't deal with trail slash */
+ if (actualfile[strlen(actualfile)-1] == '\\')
+ actualfile[strlen(actualfile)-1] = 0;
+#endif
- if (stat(cn->actualfile, &stbuf) == -1) {
- if (allowcgi != 0) {
+ if (stat(actualfile, &stbuf) == -1) {
+#if defined(CONFIG_HTTP_HAS_CGI)
if (trycgi_withpathinfo(cn) == 0) { // We Try To Find A CGI
proccgi(cn,1);
return;
}
- }
+#endif
send404(cn);
removeconnection(cn);
return;
}
+#if defined(CONFIG_HTTP_HAS_CGI)
if (iscgi(cn->actualfile)) {
+#ifndef WIN32
// Set up CGI script
- if (allowcgi == 0 ||
- access(cn->actualfile, X_OK) != 0 ||
- isdir(cn->actualfile)) {
+ if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) {
+ send404(cn);
+ removeconnection(cn);
+ return;
+ }
+#endif
+
+ proccgi(cn,0);
+ return;
+ }
+#endif
+
+ if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
+ if (cn->filereq[strlen(cn->filereq)-1] != '/') {
+ send301(cn);
+ removeconnection(cn);
+ return;
+ }
+
+ // Check to see if this dir has an index file
+ if (procindex(cn, &stbuf) == 0) {
+#if defined(CONFIG_HTTP_DIRECTORIES)
+ // If not, we do a directory listing of it
+ procdirlisting(cn);
+#else
send404(cn);
removeconnection(cn);
+#endif
return;
}
- proccgi(cn,0);
- return;
- }
+#if defined(CONFIG_HTTP_HAS_CGI)
+ // If the index is a CGI file, handle it like any other CGI
+ if (iscgi(cn->actualfile)) {
+ // Set up CGI script
+ if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) {
+ send404(cn);
+ removeconnection(cn);
+ return;
+ }
+ proccgi(cn,0);
+ return;
+ }
+#endif
+ // If the index isn't a CGI, we continue on with the index file
+ }
if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
if (cn->filereq[strlen(cn->filereq)-1] != '/') {
send301(cn);
@@ -256,17 +330,18 @@
// Check to see if this dir has an index file
if (procindex(cn, &stbuf) == 0) {
+#if defined(CONFIG_HTTP_DIRECTORIES)
// If not, we do a directory listing of it
procdirlisting(cn);
+#endif
return;
}
+#if defined(CONFIG_HTTP_HAS_CGI)
// If the index is a CGI file, handle it like any other CGI
if (iscgi(cn->actualfile)) {
// Set up CGI script
- if (allowcgi == 0 ||
- access(cn->actualfile, X_OK) != 0 ||
- isdir(cn->actualfile)) {
+ if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) {
send404(cn);
removeconnection(cn);
return;
@@ -275,50 +350,68 @@
proccgi(cn,0);
return;
}
+#endif
// If the index isn't a CGI, we continue on with the index file
}
- if (cn->offset == -1 || cn->offset >= stbuf.st_size) {
- cn->offset = -1;
+ if (cn->modified_since) {
+ snprintf(buf, sizeof(buf), "HTTP/1.1 304 Not Modified\nServer: Anti-Web V%s\nDate: %s\n", VERSION, date);
+ special_write(cn, buf, strlen(buf));
+ cn->modified_since = 0;
+ cn->state = STATE_WANT_TO_READ_HEAD;
+ return;
+ }
+ else {
+#ifdef CONFIG_HTTP_VERBOSE
+ printf("awhttpd: %s send %s\n",
+ cn->is_ssl ? "https" : "http", cn->actualfile);
+ TTY_FLUSH();
+#endif
- snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: Anti-Web V%s (%s)\nContent-Type: %s\nContent-Length: %ld\nLast-Modified: %s\n",
- VERSION,
- quote,
- getmimetype(cn->actualfile),
- (long) stbuf.st_size,
- ctime(&(stbuf.st_mtime))); // ctime() has a \n on the end
- } else {
- snprintf(buf, sizeof(buf), "HTTP/1.1 206 OK\nServer: Anti-Web V%s (%s)\nContent-Type: %s\nContent-Range: %ld-%ld/%ld\nContent-Length: %ld\nLast-Modified: %s\n",
+ snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: Anti-Web V%s\nContent-Type: %s\nContent-Length: %ld\nDate: %sLast-Modified: %s\n",
VERSION,
- quote,
getmimetype(cn->actualfile),
- cn->offset,
- (long) stbuf.st_size-1,
(long) stbuf.st_size,
- (long) stbuf.st_size - cn->offset,
+ date,
ctime(&(stbuf.st_mtime))); // ctime() has a \n on the end
}
- write(cn->networkdesc, buf, strlen(buf));
+ special_write(cn, buf, strlen(buf));
if (cn->reqtype == TYPE_HEAD) {
removeconnection(cn);
return;
} else {
+ int flags = O_RDONLY;
+#if defined(WIN32) || defined(CYGWIN)
+ flags |= O_BINARY;
+#endif
- cn->filedesc = open(cn->actualfile, O_RDONLY);
+ cn->filedesc = open(cn->actualfile, flags);
if (cn->filedesc == -1) {
send404(cn);
removeconnection(cn);
return;
}
- if (cn->offset != -1) {
- lseek(cn->filedesc, cn->offset, SEEK_SET);
+#ifdef WIN32
+ for (;;)
+ {
+ procreadfile(cn);
+ if (cn->filedesc == -1)
+ {
+ break;
+ }
+
+ do
+ {
+ procsendfile(cn);
+ } while (cn->state != STATE_WANT_TO_READ_FILE);
}
-
+#else
cn->state = STATE_WANT_TO_READ_FILE;
+#endif
return;
}
@@ -328,13 +421,18 @@
void procreadfile(struct connstruct *cn) {
- int rv;
-
- rv = read(cn->filedesc, cn->databuf, BLOCKSIZE);
+ int rv = read(cn->filedesc, cn->databuf, BLOCKSIZE);
if (rv == 0 || rv == -1) {
- removeconnection(cn);
- return;
+ close(cn->filedesc);
+ cn->filedesc = -1;
+ if (cn->close_when_done) /* close immediately */
+ removeconnection(cn);
+ else { /* keep socket open - HTTP 1.1 */
+ cn->state = STATE_WANT_TO_READ_HEAD;
+ cn->numbytes = 0;
+ }
+ return;
}
cn->numbytes = rv;
@@ -347,11 +445,9 @@
void procsendfile(struct connstruct *cn) {
- int rv;
-
- rv = write(cn->networkdesc, cn->databuf, cn->numbytes);
+ int rv = special_write(cn, cn->databuf, cn->numbytes);
- if (rv == -1)
+ if (rv < 0)
removeconnection(cn);
else if (rv == cn->numbytes)
cn->state = STATE_WANT_TO_READ_FILE;
@@ -361,7 +457,47 @@
memmove(cn->databuf, cn->databuf + rv, cn->numbytes - rv);
cn->numbytes -= rv;
}
+}
- return;
+int special_write(struct connstruct *cn,
+ const uint8_t *buf, size_t count)
+{
+ int res;
+
+#ifdef CONFIG_HTTP_HAS_SSL
+ if (cn->is_ssl)
+ {
+ SSL *ssl = ssl_find(servers->ssl_ctx, cn->networkdesc);
+ if (ssl)
+ {
+ res = ssl_write(ssl, (unsigned char *)buf, count);
+ }
+ else
+ return -1;
+ }
+ else
+#endif
+ res = SOCKET_WRITE(cn->networkdesc, buf, count);
+
+ return res;
+}
+
+static int special_read(struct connstruct *cn, void *buf, size_t count)
+{
+ int res;
+
+#ifdef CONFIG_HTTP_HAS_SSL
+ if (cn->is_ssl)
+ {
+ SSL *ssl = ssl_find(servers->ssl_ctx, cn->networkdesc);
+ unsigned char *read_buf;
+
+ if ((res = ssl_read(ssl, &read_buf)) > SSL_OK)
+ memcpy(buf, read_buf, res > (int)count ? count : res);
+ }
+ else
+#endif
+ res = SOCKET_READ(cn->networkdesc, buf, count);
+ return res;
}
diff -Naur awhttpd/socket.c axTLS/httpd/awhttpd/socket.c
--- awhttpd/socket.c 2004-04-25 13:03:05.000000000 +1000
+++ axTLS/httpd/awhttpd/socket.c 2006-08-10 18:33:47.640625000 +1000
@@ -8,61 +8,17 @@
#include <stdio.h>
-#include <netdb.h>
-#include <sys/time.h>
#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <time.h>
-#include <unistd.h>
#include <string.h>
-
#include "aw3.h"
-int checkmaxusers(int sd) {
-
- if (maxusers <= 0) return 1;
-
- if (numusers >= maxusers) {
- send505(sd, "Maximum user limit reached");
- // removeconnection() should be used normally
- close(sd);
-
- return 0;
- }
-
- return 1;
-}
-
-
-int pollsocket(int sd, long ustimeout) {
-
- fd_set rfds;
- struct timeval tv;
-
- tv.tv_sec = 0;
- tv.tv_usec = ustimeout;
-
- FD_ZERO(&rfds);
- FD_SET(sd, &rfds);
-
- select(FD_SETSIZE, &rfds, NULL, NULL, (ustimeout >= 0) ? &tv : NULL);
-
- return FD_ISSET(sd, &rfds);
-
-}
-
-
-
#ifdef HAVE_IPV6
-void handlenewconnection(int listenfd) {
+void handlenewconnection(int listenfd, int is_ssl) {
struct sockaddr_in6 their_addr;
int tp = sizeof(their_addr);
@@ -82,7 +38,7 @@
*ipbuf = '\0';
}
- if (checkmaxusers(connfd)) addconnection(connfd, ipbuf);
+ addconnection(connfd, ipbuf, is_ssl);
return;
@@ -90,19 +46,17 @@
#else
-void handlenewconnection(int listenfd) {
+void handlenewconnection(int listenfd, int is_ssl) {
struct sockaddr_in their_addr;
int tp = sizeof(struct sockaddr_in);
int connfd;
- char ipbuf[100];
connfd = accept(listenfd, (struct sockaddr *)&their_addr, &tp);
if (connfd == -1) return;
- if (checkmaxusers(connfd))
- addconnection(connfd, inet_ntoa(their_addr.sin_addr));
+ addconnection(connfd, inet_ntoa(their_addr.sin_addr), is_ssl);
return;
}
@@ -113,8 +67,12 @@
int openlistener(int port) {
-
- int tp=0,sd;
+ int sd;
+#ifdef WIN32
+ char tp=1;
+#else
+ int tp=1;
+#endif
struct sockaddr_in my_addr;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) return -1;
@@ -125,7 +83,7 @@
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &tp, sizeof(tp));
my_addr.sin_family = AF_INET; // host byte order
- my_addr.sin_port = htons(port); // short, network byte order
+ my_addr.sin_port = htons((short)port); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), 0, 8); // zero the rest of the struct
diff -Naur awhttpd/urlencode.c axTLS/httpd/awhttpd/urlencode.c
--- awhttpd/urlencode.c 2004-05-14 10:53:47.000000000 +1000
+++ axTLS/httpd/awhttpd/urlencode.c 2006-08-10 18:33:47.640625000 +1000
@@ -13,7 +13,7 @@
#include <ctype.h>
#include <stdlib.h>
-
+#include <stdio.h>
#include "aw3.h"
@@ -37,7 +37,7 @@
(*p > 'Z' && *p < '_') ||
(*p > '_' && *p < 'a') ||
(*p > 'z' && *p < 0xA1)) {
- sprintf(tp, "%%%02X", *p);
+ sprintf((char *)tp, "%%%02X", *p);
tp += 3;
} else {
*tp = *p;