From f0bdfb5861cdd973591b47ba7bdc2661d92dcd2e Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Fri, 3 Dec 1999 05:09:55 +0000 Subject: [PATCH] * Rewrote the HTTP engine and application coupling to run in a worker thread model and to run as a single multithreaded program (eliminated helper processes and pipes). It currently runs but has many large bugs. --- webcit/ChangeLog | 6 +- webcit/Makefile.in | 23 ++- webcit/auth.c | 30 +++- webcit/braindamage.c | 58 ------- webcit/child.h | 107 ------------ webcit/context_loop.c | 340 +++++++++++-------------------------- webcit/cookie_conversion.c | 16 +- webcit/graphics.c | 23 ++- webcit/locate_host.c | 16 +- webcit/mainmenu.c | 34 +++- webcit/messages.c | 39 +++-- webcit/mime_parser.c | 20 ++- webcit/netconf.c | 43 +++-- webcit/paging.c | 24 ++- webcit/roomops.c | 44 +++-- webcit/serv_func.c | 27 ++- webcit/siteconfig.c | 21 ++- webcit/sysmsgs.c | 30 +++- webcit/tcp_sockets.c | 17 +- webcit/tools.c | 25 ++- webcit/userlist.c | 23 ++- webcit/webcit.c | 249 +++++++++------------------ webcit/webcit.h | 154 +++++++++++++++-- webcit/webserver.c | 96 +++++++---- webcit/who.c | 32 +++- webcit/wildmat.c | 201 ---------------------- 26 files changed, 755 insertions(+), 943 deletions(-) delete mode 100644 webcit/braindamage.c delete mode 100644 webcit/child.h delete mode 100644 webcit/wildmat.c diff --git a/webcit/ChangeLog b/webcit/ChangeLog index 16dd4d70c..e4df58853 100644 --- a/webcit/ChangeLog +++ b/webcit/ChangeLog @@ -1,4 +1,9 @@ $Log$ +Revision 1.109 1999/12/03 05:09:54 ajc +* Rewrote the HTTP engine and application coupling to run in a worker thread + model and to run as a single multithreaded program (eliminated helper + processes and pipes). It currently runs but has many large bugs. + Revision 1.108 1999/12/03 00:18:20 ajc * Added ".c.o" rule to Makefile @@ -319,4 +324,3 @@ Sun Dec 6 19:50:55 EST 1998 Art Cancro 1998-12-03 Nathan Bryant * webserver.c: warning fix - diff --git a/webcit/Makefile.in b/webcit/Makefile.in index a88fd4080..2cd30c9a6 100644 --- a/webcit/Makefile.in +++ b/webcit/Makefile.in @@ -10,7 +10,7 @@ srcdir=@srcdir@ # End of configuration section -all: webserver webcit +all: webserver .SUFFIXES: .c .o @@ -22,23 +22,20 @@ distclean: clean webserver: webserver.o context_loop.o tools.o \ - cookie_conversion.o locate_host.o $(LIBOBJS) + cookie_conversion.o locate_host.o \ + webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \ + roomops.o messages.o userlist.o paging.o sysmsgs.o \ + mime_parser.o graphics.o netconf.o siteconfig.o $(LIBOBJS) $(CC) webserver.o context_loop.o tools.o cookie_conversion.o \ - locate_host.o $(LIBOBJS) $(LIBS) -o webserver + webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \ + roomops.o messages.o userlist.o paging.o sysmsgs.o \ + locate_host.o siteconfig.o \ + mime_parser.o graphics.o netconf.o \ + $(LIBOBJS) $(LIBS) -o webserver .c.o: $(CC) $(CFLAGS) $(DEFS) -c -D_REENTRANT -DWEBCITDIR=\"`pwd`\" $< - -webcit: webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \ - roomops.o tools.o messages.o userlist.o paging.o sysmsgs.o \ - mime_parser.o graphics.o netconf.o cookie_conversion.o siteconfig.o \ - wildmat.o braindamage.o - $(CC) webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \ - tools.o roomops.o messages.o userlist.o paging.o sysmsgs.o siteconfig.o \ - mime_parser.o graphics.o netconf.o cookie_conversion.o \ - wildmat.o braindamage.o -o webcit - Makefile: $(srcdir)/Makefile.in config.status CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status diff --git a/webcit/auth.c b/webcit/auth.c index 28d89efba..64147f1a1 100644 --- a/webcit/auth.c +++ b/webcit/auth.c @@ -6,16 +6,28 @@ * $Id$ */ + +#include #include -#ifdef HAVE_UNISTD_H #include -#endif #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include +#include +#include +#include #include "webcit.h" -#include "child.h" + char *axdefs[] = { @@ -35,7 +47,7 @@ void display_login(char *mesg) { char buf[256]; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(3); /* Da banner */ @@ -172,7 +184,7 @@ void do_logout(void) strcpy(WC->wc_password, ""); strcpy(WC->wc_roomname, ""); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(2); /* note "2" causes cookies to be unset */ wprintf("
"); @@ -204,7 +216,7 @@ void validate(void) char buf[256]; int a; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); strcpy(buf, bstr("user")); @@ -283,7 +295,7 @@ void display_reg(int during_login) char buf[256]; int a; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -387,7 +399,7 @@ void display_changepw(void) { char buf[256]; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); diff --git a/webcit/braindamage.c b/webcit/braindamage.c deleted file mode 100644 index 564cda569..000000000 --- a/webcit/braindamage.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "webcit.h" -#include "child.h" - -/* - * browser_braindamage_check() - * - * Given the value of the HTTP "User-agent:" directive supplied by - * a web browser, determine using a local configuration file whether - * the browser is capable of handling JavaScript. - * - * This function returns one of the following values: - * B_YES (Yes, it's ok to use JavaScript) - * B_NO (No, fall back to HTML) - * B_ASK (We don't know; ask the user) - */ - -int browser_braindamage_check(char *browser) -{ - FILE *fp; - char buf[256]; - int thisval; - - fp = fopen("static/braindamage", "r"); - if (fp == NULL) - return (B_ASK); - - while (fgets(buf, 256, fp) != NULL) { - buf[strlen(buf)-1] = 0; - thisval = (-1); - if (!strncasecmp(buf, "YES", 3)) { - thisval = B_YES; - strcpy(buf, &buf[3]); - } else if (!strncasecmp(buf, "NO", 2)) { - thisval = B_NO; - strcpy(buf, &buf[2]); - } else if (!strncasecmp(buf, "ASK", 3)) { - thisval = B_ASK; - strcpy(buf, &buf[3]); - } - if (thisval >= 0) { - while (isspace(buf[0])) strcpy(buf, &buf[1]); - if (wildmat(buf, browser)) { - return(thisval); - } - } - } - - fclose(fp); - return (B_ASK); -} diff --git a/webcit/child.h b/webcit/child.h deleted file mode 100644 index d698e36f3..000000000 --- a/webcit/child.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * child.h: prototypes for the `webcit' child process - * - * $Id$ - */ - -void become_logged_in(char *, char *, char *); -void do_login(void); -void display_login(char *mesg); -void do_welcome(void); -void do_logout(void); -void display_main_menu(void); -void display_advanced_menu(void); -void list_all_rooms_by_floor(void); -void slrp_highest(void); -void gotonext(void); -void ungoto(void); -void get_serv_info(char *, char *); -int connectsock(char *host, char *service, char *protocol); -void serv_gets(char *strbuf); -void serv_puts(char *string); -void whobbs(void); -void fmout(FILE * fp); -void wDumpContent(int); -void serv_printf(const char *format,...); -char *bstr(char *key); -char *urlesc(char *); -void urlescputs(char *); -void output_headers(int); -void wprintf(const char *format,...); -void extract(char *dest, char *source, int parmnum); -int extract_int(char *source, int parmnum); -void output_static(char *what); -void escputs(char *strbuf); -void url(char *buf); -void escputs1(char *strbuf, int nbsp); -long extract_long(char *source, long int parmnum); -void dump_vars(void); -void embed_main_menu(void); -void serv_read(char *buf, int bytes); -int haschar(char *st, char ch); -void readloop(char *oper); -void text_to_server(char *ptr); -void display_enter(void); -void post_message(void); -void confirm_delete_msg(void); -void delete_msg(void); -void confirm_move_msg(void); -void move_msg(void); -void userlist(void); -void showuser(void); -void display_page(void); -void page_user(void); -void do_chat(void); -void display_private(char *rname, int req_pass); -void goto_private(void); -void zapped_list(void); -void display_zap(void); -void zap(void); -void display_error(char *); -void display_success(char *); -void display_entroom(void); -void entroom(void); -void display_editroom(void); -void editroom(void); -void server_to_text(void); -void save_edit(char *description, char *enter_cmd, int regoto); -void display_edit(char *description, char *check_cmd, - char *read_cmd, char *save_cmd); -void gotoroom(char *gname, int display_name); -void confirm_delete_room(void); -void delete_room(void); -void validate(void); -void display_graphics_upload(char *, char *, char *); -void do_graphics_upload(char *upl_cmd); -void serv_read(char *buf, int bytes); -void serv_gets(char *strbuf); -void serv_write(char *buf, int nbytes); -void serv_puts(char *string); -void serv_printf(const char *format,...); -void load_floorlist(void); -void select_floor_to_edit_pic(void); -void display_reg(int); -void register_user(void); -void display_changepw(void); -void changepw(void); -void display_edit_node(void); -void display_netconf(void); -void display_confirm_unshare(void); -void display_confirm_delete_node(void); -void delete_node(void); -void unshare(void); -void display_add_node(void); -void add_node(void); -void display_share(void); -void share(void); -void terminate_session(void); -void edit_me(void); -void display_siteconfig(void); -void siteconfig(void); -void display_generic(void); -void do_generic(void); -int browser_braindamage_check(char *); -void display_menubar(int); -void embed_room_banner(char *); -void smart_goto(char *); -void ExpressMessageCat(char *); diff --git a/webcit/context_loop.c b/webcit/context_loop.c index 2f0c5a382..9a66b0228 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -38,109 +38,27 @@ #include "webcit.h" #include "webserver.h" -/* - * We keep one of these around for each active session - */ -struct wc_session { - struct wc_session *next; /* Next session in list */ - int session_id; /* Session ID */ - pid_t webcit_pid; /* PID of the webcit process */ - int inpipe[2]; /* Data from webserver to session */ - int outpipe[2]; /* Data from session to webserver */ - pthread_mutex_t critter; /* Critical section uses pipes */ - time_t lastreq; /* Timestamp of most recent http */ -}; - -struct wc_session *SessionList = NULL; -extern const char *defaulthost; -extern const char *defaultport; - /* Only one thread may manipulate SessionList at a time... */ -pthread_mutex_t MasterCritter; - - -/* - * Grab a lock on the session, so other threads don't try to access - * the pipes at the same time. - */ -static void lock_session(struct wc_session *session) -{ - printf("Locking session %d...\n", session->session_id); - pthread_mutex_lock(&session->critter); - printf(" ...got lock\n"); -} - -/* - * Let go of the lock. - */ -static void unlock_session(struct wc_session *session) -{ - printf("Unlocking.\n"); - pthread_mutex_unlock(&session->critter); -} - -/* - * Remove a session context from the list. - * Set do_lock to 1, to lock the list while manipulating it. The ONLY - * situation in which this should _not_ be done is when it's already locked - * by the caller. - */ -void remove_session(struct wc_session *TheSession, int do_lock) -{ - struct wc_session *sptr; - - printf("Removing session.\n"); - - /* Lock the list while manipulating it */ - if (do_lock) - pthread_mutex_lock(&MasterCritter); - - if (SessionList == TheSession) { - SessionList = SessionList->next; - } else { - for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { - if (sptr->next == TheSession) { - sptr->next = TheSession->next; - } - } - } - - if (do_lock) - pthread_mutex_unlock(&MasterCritter); - - /* Now finish destroying the session */ - close(TheSession->inpipe[1]); - close(TheSession->outpipe[0]); - if (do_lock) - unlock_session(TheSession); - free(TheSession); - -} - +pthread_mutex_t SessionListMutex; +struct wcsession *SessionList = NULL; +pthread_key_t MyConKey; /* TSD key for MySession() */ void do_housekeeping(void) { - struct wc_session *sptr; + struct wcsession *sptr; - pthread_mutex_lock(&MasterCritter); + pthread_mutex_lock(&SessionListMutex); /* Kill idle sessions */ for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { if ((time(NULL) - (sptr->lastreq)) > (time_t) WEBCIT_TIMEOUT) { - kill(sptr->webcit_pid, 15); + /* FIX do something here */ } } - /* Remove dead sessions */ - for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { - if (kill(sptr->webcit_pid, 0)) { - remove_session(sptr, 0); - } - } - - pthread_mutex_unlock(&MasterCritter); + pthread_mutex_unlock(&SessionListMutex); } @@ -156,12 +74,23 @@ void housekeeping_loop(void) } - - - +/* + * Generate a unique WebCit session ID (which is not the same thing as the + * Citadel session ID). + * + * FIX ... we really should check to make sure we're generating a truly + * unique session ID by traversing the SessionList. + * + */ int GenerateSessionID(void) { - return getpid(); + static int seq = (-1); + + if (seq < 0) { + seq = (int) time(NULL); + } + + return ++seq; } @@ -239,42 +168,37 @@ static int lingering_close(int fd) return close(fd); } + + + /* - * This loop gets called once for every HTTP connection made to WebCit. + * This loop gets called once for every HTTP connection made to WebCit. At + * this entry point we have an HTTP socket with a browser allegedly on the + * other end, but we have not yet bound to a WebCit session. + * + * The job of this function is to locate the correct session and bind to it, + * or create a session if necessary and bind to it, then run the WebCit + * transaction loop. Afterwards, we unbind from the session. When this + * function returns, the worker thread is then free to handle another + * transaction. */ -void *context_loop(int sock) +void context_loop(int sock) { - char (*req)[256]; + struct httprequest *req = NULL; + struct httprequest *last = NULL; + struct httprequest *hptr; char buf[256], hold[256]; - char browser_host[256]; - char browser[256]; - int num_lines = 0; - int a; - int f; int desired_session = 0; int got_cookie = 0; - char str_session[256]; - struct wc_session *sptr; - struct wc_session *TheSession; - int ContentLength; + struct wcsession *TheSession, *sptr; int CloseSession = 0; - if ((req = malloc((long) sizeof(char[256][256]))) == NULL) { - sprintf(buf, "Can't malloc buffers; dropping connection.\n"); - fprintf(stderr, "%s", buf); - write(sock, buf, strlen(buf)); - close(sock); - pthread_exit(NULL); - } - bzero(req, sizeof(char[256][256])); /* clear it out */ - strcpy(browser, "unknown"); - printf("Reading request from socket %d\n", sock); + fprintf(stderr, "Reading request from socket %d\n", sock); /* * Find out what it is that the web browser is asking for */ - ContentLength = 0; do { req_gets(sock, buf, hold); if (!strncasecmp(buf, "Cookie: webcit=", 15)) { @@ -282,13 +206,18 @@ void *context_loop(int sock) NULL, NULL, NULL); got_cookie = 1; } - else if (!strncasecmp(buf, "Content-length: ", 16)) { - ContentLength = atoi(&buf[16]); - } - else if (!strncasecmp(buf, "User-agent: ", 12)) { - strcpy(browser, &buf[12]); - } - strcpy(&req[num_lines++][0], buf); + + hptr = (struct httprequest *) + malloc(sizeof(struct httprequest)); + if (req == NULL) + req = hptr; + else + last->next = hptr; + hptr->next = NULL; + last = hptr; + + strcpy(hptr->line, buf); + } while (strlen(buf) > 0); @@ -297,7 +226,7 @@ void *context_loop(int sock) * set. If there isn't, the client browser has cookies turned off * (or doesn't support them) and we have to barf & bail. */ - strcpy(buf, &req[0][0]); + strcpy(buf, req->line); if (!strncasecmp(buf, "GET ", 4)) strcpy(buf, &buf[4]); else if (!strncasecmp(buf, "HEAD ", 5)) strcpy(buf, &buf[5]); if (buf[1]==' ') buf[1]=0; @@ -307,12 +236,12 @@ void *context_loop(int sock) * robots.txt file... */ if (!strncasecmp(buf, "/robots.txt", 11)) { - strcpy(&req[0][0], "GET /static/robots.txt HTTP/1.0"); + strcpy(req->line, "GET /static/robots.txt HTTP/1.0"); } /* Do the non-root-cookie check now. */ else if ( (strcmp(buf, "/")) && (got_cookie == 0)) { - strcpy(&req[0][0], "GET /static/nocookies.html HTTP/1.0"); + strcpy(req->line, "GET /static/nocookies.html HTTP/1.0"); } @@ -322,25 +251,13 @@ void *context_loop(int sock) */ TheSession = NULL; if (desired_session != 0) { - pthread_mutex_lock(&MasterCritter); + pthread_mutex_lock(&SessionListMutex); for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { - if (sptr->session_id == desired_session) { + if (sptr->wc_session == desired_session) { TheSession = sptr; } } - pthread_mutex_unlock(&MasterCritter); - } - - /* - * Before we trumpet to the universe that the session we're looking - * for actually exists, check first to make sure it's still there. - */ - if (TheSession != NULL) { - if (kill(TheSession->webcit_pid, 0)) { - printf(" Session is *DEAD* !!\n"); - remove_session(TheSession, 1); - TheSession = NULL; - } + pthread_mutex_unlock(&SessionListMutex); } /* @@ -348,130 +265,65 @@ void *context_loop(int sock) */ if (TheSession == NULL) { printf("Creating a new session\n"); - locate_host(browser_host, sock); - TheSession = (struct wc_session *) - malloc(sizeof(struct wc_session)); - TheSession->session_id = GenerateSessionID(); - pipe(TheSession->inpipe); - pipe(TheSession->outpipe); - pthread_mutex_init(&TheSession->critter, NULL); - - pthread_mutex_lock(&MasterCritter); + TheSession = (struct wcsession *) + malloc(sizeof(struct wcsession)); + memset(TheSession, 0, sizeof(struct wcsession)); + TheSession->wc_session = GenerateSessionID(); + pthread_mutex_init(&TheSession->SessionMutex, NULL); + + pthread_mutex_lock(&SessionListMutex); TheSession->next = SessionList; SessionList = TheSession; - pthread_mutex_unlock(&MasterCritter); - - sprintf(str_session, "%d", TheSession->session_id); - f = fork(); - if (f > 0) - TheSession->webcit_pid = f; - - fflush(stdout); - fflush(stdin); - if (f == 0) { - - /* Hook stdio to the ends of the pipe we're using */ - dup2(TheSession->inpipe[0], 0); - dup2(TheSession->outpipe[1], 1); - - /* Close the ends of the pipes that we're not using */ - close(TheSession->inpipe[1]); - close(TheSession->outpipe[0]); - - /* Close the HTTP socket in this pid; don't need it */ - close(sock); - - /* Run the actual WebCit session */ - execlp("./webcit", "webcit", str_session, defaulthost, - defaultport, browser_host, browser, NULL); - - /* Simple page to display if exec fails */ - printf("HTTP/1.0 404 WebCit Failure\n\n"); - printf("Server: %s\n", SERVER); - printf("X-WebCit-Session: close\n"); - printf("Content-type: text/html\n"); - printf("Content-length: 76\n"); - printf("\n"); - printf("Error\n"); - printf("execlp() failed: %s\n", strerror(errno)); - exit(0); - } else { - /* Close the ends of the pipes that we're not using */ - close(TheSession->inpipe[0]); - close(TheSession->outpipe[1]); - } + pthread_mutex_unlock(&SessionListMutex); } - /* - * Send the request to the appropriate session... - */ - lock_session(TheSession); - TheSession->lastreq = time(NULL); - printf(" Writing %d lines of command\n", num_lines); - printf("%s\n", &req[0][0]); - for (a = 0; a < num_lines; ++a) { - write(TheSession->inpipe[1], &req[a][0], strlen(&req[a][0])); - write(TheSession->inpipe[1], "\n", 1); - } - printf(" Writing %d bytes of content\n", ContentLength); - while (ContentLength > 0) { - a = ContentLength; - if (a > sizeof buf) - a = sizeof buf; - if (!client_read(sock, buf, a)) - goto end; - if (write(TheSession->inpipe[1], buf, a) != a) - goto end; - ContentLength -= a; - } /* - * ...and get the response. + * + * FIX ... check session integrity here before continuing + * */ - printf(" Reading response\n"); - ContentLength = 0; - do { - gets0(TheSession->outpipe[0], buf); - write(sock, buf, strlen(buf)); - write(sock, "\n", 1); - if (!strncasecmp(buf, "Content-length: ", 16)) - ContentLength = atoi(&buf[16]); - if (!strcasecmp(buf, "X-WebCit-Session: close")) { - CloseSession = 1; - } - } while (strlen(buf) > 0); - printf(" Reading %d bytes of content\n", ContentLength); - while (ContentLength--) { - read(TheSession->outpipe[0], buf, 1); - write(sock, buf, 1); - } + + /* + * Bind to the session + */ + pthread_mutex_lock(&TheSession->SessionMutex); + pthread_setspecific(MyConKey, (void *)TheSession); + TheSession->lastreq = time(NULL); + TheSession->http_sock = sock; + + /* + * Perform the WebCit transaction + */ + fprintf(stderr, "Transaction: %s\n", req->line); + session_loop(req); + fprintf(stderr, "Returned from transaction loop\n"); /* * If the last response included a "close session" directive, * remove the context now. */ if (CloseSession) { - remove_session(TheSession, 1); + /* FIX remove_session(TheSession, 1); */ } else { -end: unlock_session(TheSession); + + pthread_mutex_unlock(&TheSession->SessionMutex); } - free(req); + /* Free the request buffer */ + while (req != NULL) { + hptr = req->next; + free(req); + req = hptr; + } /* - * Now our HTTP connection is done. It would be relatively easy - * to support HTTP/1.1 "persistent" connections by looping back to - * the top of this function. For now, we'll just close. + * Now our HTTP connection is done. Close the socket and exit this + * function, so the worker thread can handle a new HTTP connection. */ printf(" Closing socket %d ... ret=%d\n", sock, lingering_close(sock)); - - /* - * The thread handling this HTTP connection is now finished. - * Instead of calling pthread_exit(), just return. It does the same - * thing, and supresses a compiler warning. - */ - return NULL; + return; } diff --git a/webcit/cookie_conversion.c b/webcit/cookie_conversion.c index 3bb3554b9..5f139fdf5 100644 --- a/webcit/cookie_conversion.c +++ b/webcit/cookie_conversion.c @@ -1,12 +1,24 @@ + +#include #include #include #include +#include #include #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" /* * Pack all session info into one easy-to-digest cookie. Healthy and delicious! diff --git a/webcit/graphics.c b/webcit/graphics.c index 56c4ceebe..3e8ebc617 100644 --- a/webcit/graphics.c +++ b/webcit/graphics.c @@ -1,13 +1,24 @@ + +#include #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include -#include +#include +#include +#include #include "webcit.h" -#include "child.h" - void display_graphics_upload(char *description, char *check_cmd, char *uplurl) { @@ -19,7 +30,7 @@ void display_graphics_upload(char *description, char *check_cmd, char *uplurl) display_error(&buf[4]); return; } - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); wprintf("
"); diff --git a/webcit/locate_host.c b/webcit/locate_host.c index fba5d8847..87d1385aa 100644 --- a/webcit/locate_host.c +++ b/webcit/locate_host.c @@ -2,16 +2,30 @@ * locate the originating host */ + +#include #include #include #include +#include #include #include +#include #include -#include +#include #include +#include #include #include +#include +#include +#include +#include +#include +#include "webcit.h" + + + void locate_host(char *tbuf, int client_socket) { diff --git a/webcit/mainmenu.c b/webcit/mainmenu.c index 8713620f4..0cdc6ebc5 100644 --- a/webcit/mainmenu.c +++ b/webcit/mainmenu.c @@ -1,15 +1,31 @@ /* $Id$ */ + + + +#include #include -#ifdef HAVE_UNISTD_H #include -#endif #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + /* @@ -191,7 +207,7 @@ void embed_advanced_menu(void) */ void display_main_menu(void) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); embed_main_menu(); wDumpContent(2); @@ -200,7 +216,7 @@ void display_main_menu(void) void display_advanced_menu(void) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); embed_advanced_menu(); embed_main_menu(); @@ -213,7 +229,7 @@ void display_advanced_menu(void) */ void display_generic(void) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -253,7 +269,7 @@ void do_generic(void) return; } - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); serv_printf("%s", bstr("g_cmd")); @@ -316,7 +332,7 @@ void display_menubar(int as_single_page) { char buf[256]; if (as_single_page) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(0); wprintf("\n" "\n" diff --git a/webcit/messages.c b/webcit/messages.c index 0af37486a..7966e9c41 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -1,12 +1,31 @@ + + + + +#include #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include -#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + + char reply_to[512]; long msgarr[1024]; @@ -221,7 +240,7 @@ void readloop(char *oper) int a; int nummsgs; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
%s - ", WC->wc_roomname); @@ -274,7 +293,7 @@ void post_message(void) char buf[256]; static long dont_post = (-1L); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf(""); @@ -339,7 +358,7 @@ void display_enter(void) long now; struct tm *tm; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf(""); @@ -408,7 +427,7 @@ void confirm_delete_msg(void) msgid = atol(bstr("msgid")); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -440,7 +459,7 @@ void delete_msg(void) msgid = atol(bstr("msgid")); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); if (!strcasecmp(bstr("yesno"), "Yes")) { @@ -469,7 +488,7 @@ void confirm_move_msg(void) msgid = atol(bstr("msgid")); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -517,7 +536,7 @@ void move_msg(void) msgid = atol(bstr("msgid")); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); if (!strcasecmp(bstr("yesno"), "Move")) { diff --git a/webcit/mime_parser.c b/webcit/mime_parser.c index 91c15b9dc..5782c5a72 100644 --- a/webcit/mime_parser.c +++ b/webcit/mime_parser.c @@ -5,16 +5,30 @@ * messages -- in the case of WebCit, a form containing uploaded files. */ + + +#include #include #include #include +#include #include #include -#include +#include +#include +#include +#include +#include +#include #include -#include "mime_parser.h" +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + diff --git a/webcit/netconf.c b/webcit/netconf.c index 010fec575..6b2d763cd 100644 --- a/webcit/netconf.c +++ b/webcit/netconf.c @@ -1,12 +1,31 @@ + + + +#include #include #include #include +#include #include #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + + + struct sharelist { struct sharelist *next; @@ -22,7 +41,7 @@ void display_edit_node(void) strcpy(node, bstr("node")); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); wprintf("
"); wprintf("
"); wprintf("
"); wprintf("Back to menu\n"); @@ -191,7 +210,7 @@ void unshare(void) serv_puts(buf); serv_gets(buf); if (buf[0] == '1') { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); server_to_text(); wprintf("Back to menu\n"); @@ -206,7 +225,7 @@ void unshare(void) void display_add_node(void) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); wprintf("Back to menu\n"); @@ -266,7 +285,7 @@ void display_share(void) strcpy(node, bstr("node")); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); wprintf("Back to menu\n"); diff --git a/webcit/paging.c b/webcit/paging.c index 828b93452..51611c2ea 100644 --- a/webcit/paging.c +++ b/webcit/paging.c @@ -1,16 +1,26 @@ /* $Id$ */ +#include #include -#ifdef HAVE_UNISTD_H #include -#endif #include +#include #include #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + /* * display the form for paging (x-messaging) another user @@ -20,7 +30,7 @@ void display_page(void) char buf[256]; char user[256]; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -70,7 +80,7 @@ void page_user(void) char sc[256]; char buf[256]; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); strcpy(recp, bstr("recp")); @@ -102,7 +112,7 @@ void page_user(void) void do_chat(void) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); diff --git a/webcit/roomops.c b/webcit/roomops.c index bf47eaa50..e4ec0bc72 100644 --- a/webcit/roomops.c +++ b/webcit/roomops.c @@ -1,15 +1,33 @@ /* $Id$ */ + +#include #include -#include -#ifdef HAVE_UNISTD_H #include -#endif #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + + + + + /* * This struct holds a list of rooms for oto operations. @@ -232,7 +250,7 @@ void list_all_rooms_by_floor(void) load_floorlist(); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf(""); @@ -279,7 +297,7 @@ void list_all_rooms_by_floor(void) */ void zapped_list(void) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
Floor
"); wprintf("
"); @@ -946,7 +964,7 @@ void display_entroom(void) display_error(&buf[4]); return; } - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -1028,7 +1046,7 @@ void entroom(void) void display_private(char *rname, int req_pass) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -1091,7 +1109,7 @@ void goto_private(void) display_private(bstr("gr_name"), 1); return; } - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("%s\n", &buf[4]); wDumpContent(1); @@ -1104,7 +1122,7 @@ void goto_private(void) */ void display_zap(void) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -1171,7 +1189,7 @@ void confirm_delete_room(void) display_error(&buf[4]); return; } - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); wprintf(" #include -#include -#ifdef HAVE_UNISTD_H #include -#endif #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + + + + struct serv_info serv_info; diff --git a/webcit/siteconfig.c b/webcit/siteconfig.c index e178a1733..568b0e4e4 100644 --- a/webcit/siteconfig.c +++ b/webcit/siteconfig.c @@ -3,15 +3,30 @@ * */ + +#include #include #include #include +#include #include #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + void display_siteconfig(void) @@ -19,7 +34,7 @@ void display_siteconfig(void) char buf[256]; int i; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); serv_printf("CONF get"); diff --git a/webcit/sysmsgs.c b/webcit/sysmsgs.c index 526068129..fed1603cd 100644 --- a/webcit/sysmsgs.c +++ b/webcit/sysmsgs.c @@ -1,12 +1,32 @@ + + +#include #include #include #include +#include #include #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + + + + + /* * display the form for editing something (room info, bio, etc) @@ -23,7 +43,7 @@ void display_edit(char *description, char *check_cmd, display_error(&buf[4]); return; } - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("
"); @@ -60,7 +80,7 @@ void save_edit(char *description, char *enter_cmd, int regoto) char buf[256]; if (strcmp(bstr("sc"), "Save")) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("Cancelled. %s was not saved.
\n", description); wDumpContent(1); @@ -78,7 +98,7 @@ void save_edit(char *description, char *enter_cmd, int regoto) if (regoto) { smart_goto(WC->wc_roomname); } else { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("%s has been saved.\n", description); wDumpContent(1); diff --git a/webcit/tcp_sockets.c b/webcit/tcp_sockets.c index d7ec10712..50a9b299e 100644 --- a/webcit/tcp_sockets.c +++ b/webcit/tcp_sockets.c @@ -6,21 +6,32 @@ * $Id$ */ + +#include #include -#ifdef HAVE_UNISTD_H #include -#endif #include +#include #include #include +#include #include +#include +#include #include -#include #include #include +#include +#include #include +#include +#include #include "webcit.h" + + + + char server_is_local = 0; #ifndef INADDR_NONE diff --git a/webcit/tools.c b/webcit/tools.c index 13fb03342..3754ac4df 100644 --- a/webcit/tools.c +++ b/webcit/tools.c @@ -2,11 +2,32 @@ * tools.c -- Miscellaneous routines */ -#include + + +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include "webcit.h" + + + char *safestrncpy(char *dest, const char *src, size_t n) { if (dest == NULL || src == NULL) { @@ -100,7 +121,7 @@ long extract_long(char *source, long int parmnum) */ int haschar(st, ch) char st[]; -int ch; +char ch; { int a, b; b = 0; diff --git a/webcit/userlist.c b/webcit/userlist.c index d710ca5e9..44e60a056 100644 --- a/webcit/userlist.c +++ b/webcit/userlist.c @@ -1,13 +1,26 @@ +#include #include #include #include +#include #include #include -#include +#include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include #include "webcit.h" -#include "child.h" + + + struct namelist { struct namelist *next; @@ -36,7 +49,7 @@ void userlist(void) strcpy(bptr->name, buf); bio = bptr; } - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); serv_puts("LIST"); @@ -101,7 +114,7 @@ void showuser(void) char buf[256]; int have_pic; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); diff --git a/webcit/webcit.c b/webcit/webcit.c index 10819551a..78646ffe0 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -8,19 +8,29 @@ * $Id$ */ +#include #include -#ifdef HAVE_UNISTD_H #include -#endif #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include -#include #include +#include +#include #include "webcit.h" -#include "child.h" -#include "mime_parser.h" + + int TransactionCount = 0; char *ExpressMessages = NULL; @@ -30,9 +40,6 @@ char *ExpressMessages = NULL; */ int fake_frames = 0; -struct webcontent *wlist = NULL; -struct webcontent *wlast = NULL; - struct urlcontent *urlstrings = NULL; static const char *defaulthost = DEFAULT_HOST; @@ -40,8 +47,6 @@ static const char *defaultport = DEFAULT_PORT; -struct wcsession *WC = NULL; /* FIX take this out when multithreaded */ - void unescape_input(char *buf) { int a, b; @@ -158,40 +163,18 @@ char *bstr(char *key) void wprintf(const char *format,...) { va_list arg_ptr; - struct webcontent *wptr; - - wptr = (struct webcontent *) malloc(sizeof(struct webcontent)); - wptr->next = NULL; - if (wlist == NULL) { - wlist = wptr; - wlast = wptr; - } else { - wlast->next = wptr; - wlast = wptr; - } + char wbuf[1024]; va_start(arg_ptr, format); - vsprintf(wptr->w_data, format, arg_ptr); + vsprintf(wbuf, format, arg_ptr); va_end(arg_ptr); -} - -int wContentLength(void) -{ - struct webcontent *wptr; - int len = 0; - - for (wptr = wlist; wptr != NULL; wptr = wptr->next) { - len = len + strlen(wptr->w_data); - } - return (len); + write(WC->http_sock, wbuf, strlen(wbuf)); } + /* - * wDumpContent() takes all the stuff that's been queued up using - * the wprintf() and escputs() functions, and sends it out to the browser. - * By queuing instead of transmitting as it's generated, we're able to - * calculate a Content-length: header. + * wDumpContent() wraps up an HTTP session, closes tags, etc. * * print_standard_html_footer should be set to 0 to transmit only, 1 to * append the main menu and closing tags, or 2 to @@ -199,8 +182,6 @@ int wContentLength(void) */ void wDumpContent(int print_standard_html_footer) { - struct webcontent *wptr; - if (fake_frames) { wprintf("
" "" @@ -228,17 +209,8 @@ void wDumpContent(int print_standard_html_footer) } wprintf("\n"); } - printf("Content-type: text/html\n"); - printf("Content-length: %d\n", wContentLength()); - printf("\n"); - - while (wlist != NULL) { - fwrite(wlist->w_data, strlen(wlist->w_data), 1, stdout); - wptr = wlist->next; - free(wlist); - wlist = wptr; - } - wlast = NULL; + + } @@ -309,37 +281,6 @@ void urlescputs(char *strbuf) -/* - * Get a line of text from the webserver (which originally came from the - * user's browser), checking for sanity etc. - */ -char *getz(char *buf) -{ - int e = 0; - - bzero(buf, 256); - - /* If fgets() fails, it's because the webserver crashed, so kill off - * the session too. - */ - if (fgets(buf, 256, stdin) == NULL) { - e = errno; - fprintf(stderr, "webcit: exit code %d (%s)\n", - e, strerror(e)); - fflush(stderr); - exit(e); - - /* Otherwise, strip out nonprintables and resume our happy day. - */ - } else { - while ((strlen(buf) > 0) && (!isprint(buf[strlen(buf) - 1]))) - buf[strlen(buf) - 1] = 0; - return buf; - } -} - - - /* * Output all that important stuff that the browser will want to see * @@ -355,22 +296,25 @@ void output_headers(int print_standard_html_head) static char *unset = "; expires=28-May-1971 18:10:00 GMT"; char cookie[256]; - printf("Server: %s\n", SERVER); - printf("Connection: close\n"); + wprintf("Content-type: text/html\n"); + wprintf("Server: %s\n", SERVER); + wprintf("Connection: close\n"); if (print_standard_html_head > 0) { - printf("Pragma: no-cache\n"); - printf("Cache-Control: no-store\n"); + wprintf("Pragma: no-cache\n"); + wprintf("Cache-Control: no-store\n"); } stuff_to_cookie(cookie, WC->wc_session, WC->wc_username, WC->wc_password, WC->wc_roomname); if (print_standard_html_head == 2) { - printf("X-WebCit-Session: close\n"); - printf("Set-cookie: webcit=%s\n", unset); + wprintf("X-WebCit-Session: close\n"); + wprintf("Set-cookie: webcit=%s\n", unset); } else { - printf("Set-cookie: webcit=%s\n", cookie); + wprintf("Set-cookie: webcit=%s\n", cookie); } + wprintf("\n"); + if (print_standard_html_head > 0) { wprintf(""); escputs(serv_info.serv_humannode); @@ -462,36 +406,32 @@ void output_static(char *what) sprintf(buf, "static/%s", what); fp = fopen(buf, "rb"); if (fp == NULL) { - printf("HTTP/1.0 404 %s\n", strerror(errno)); - output_headers(0); - printf("Content-Type: text/plain\n"); - sprintf(buf, "%s: %s\n", what, strerror(errno)); - printf("Content-length: %d\n", strlen(buf)); - printf("\n"); - fwrite(buf, strlen(buf), 1, stdout); + wprintf("HTTP/1.0 404 %s\n", strerror(errno)); + wprintf("Content-Type: text/plain\n"); + wprintf("\n"); + wprintf("Cannot open %s: %s\n", what, strerror(errno)); } else { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(0); if (!strncasecmp(&what[strlen(what) - 4], ".gif", 4)) - printf("Content-type: image/gif\n"); + wprintf("Content-type: image/gif\n"); else if (!strncasecmp(&what[strlen(what) - 4], ".txt", 4)) - printf("Content-type: text/plain\n"); + wprintf("Content-type: text/plain\n"); else if (!strncasecmp(&what[strlen(what) - 4], ".jpg", 4)) - printf("Content-type: image/jpeg\n"); + wprintf("Content-type: image/jpeg\n"); else if (!strncasecmp(&what[strlen(what) - 5], ".html", 5)) - printf("Content-type: text/html\n"); + wprintf("Content-type: text/html\n"); else - printf("Content-type: application/octet-stream\n"); + wprintf("Content-type: application/octet-stream\n"); fstat(fileno(fp), &statbuf); bytes = statbuf.st_size; - printf("Content-length: %ld\n", (long) bytes); + wprintf("Content-length: %ld\n", (long) bytes); printf("\n"); while (bytes--) { - putc(getc(fp), stdout); + wprintf("%c", getc(fp) ); } - fflush(stdout); fclose(fp); } } @@ -509,11 +449,11 @@ void output_image() serv_gets(buf); if (buf[0] == '2') { bytes = extract_long(&buf[4], 0); - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(0); - printf("Content-type: image/gif\n"); - printf("Content-length: %ld\n", (long) bytes); - printf("\n"); + wprintf("Content-type: image/gif\n"); + wprintf("Content-length: %ld\n", (long) bytes); + wprintf("\n"); while (bytes > (off_t) 0) { thisblock = (off_t) sizeof(xferbuf); @@ -524,7 +464,7 @@ void output_image() if (buf[0] == '6') thisblock = extract_long(&buf[4], 0); serv_read(xferbuf, (int) thisblock); - fwrite(xferbuf, thisblock, 1, stdout); + write(WC->http_sock, xferbuf, thisblock); bytes = bytes - thisblock; accomplished = accomplished + thisblock; } @@ -532,13 +472,11 @@ void output_image() serv_puts("CLOS"); serv_gets(buf); } else { - printf("HTTP/1.0 404 %s\n", strerror(errno)); + wprintf("HTTP/1.0 404 %s\n", strerror(errno)); output_headers(0); - printf("Content-Type: text/plain\n"); - sprintf(buf, "Error retrieving image\n"); - printf("Content-length: %d\n", strlen(buf)); - printf("\n"); - fwrite(buf, strlen(buf), 1, stdout); + wprintf("Content-Type: text/plain\n"); + wprintf("\n"); + wprintf("Error retrieving image\n"); } } @@ -549,7 +487,7 @@ void output_image() */ void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=%s><TR><TD>", titlebarcolor); wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\""); @@ -628,7 +566,10 @@ void upload_handler(char *name, char *filename, char *encoding, } -void session_loop(char *browser_host, char *user_agent) +/* + * Entry point for WebCit transaction + */ +void session_loop(struct httprequest *req) { char cmd[256]; char action[256]; @@ -637,6 +578,9 @@ void session_loop(char *browser_host, char *user_agent) int ContentLength = 0; char ContentType[512]; char *content; + struct httprequest *hptr; + char browser_host[256]; + char user_agent[256]; /* We stuff these with the values coming from the client cookies, * so we can use them to reconnect a timed out session if we have to. @@ -657,32 +601,38 @@ void session_loop(char *browser_host, char *user_agent) WC->upload_length = 0; WC->upload = NULL; - if (getz(cmd) == NULL) - return; + hptr = req; + if (hptr == NULL) return; + + strcpy(cmd, hptr->line); + hptr = hptr->next; extract_action(action, cmd); - do { - if (getz(buf) == NULL) - return; + while (hptr != NULL) { + strcpy(buf, hptr->line); + hptr = hptr->next; if (!strncasecmp(buf, "Cookie: webcit=", 15)) { strcpy(cookie, &buf[15]); cookie_to_stuff(cookie, NULL, c_username, c_password, c_roomname); } - if (!strncasecmp(buf, "Content-length: ", 16)) { + else if (!strncasecmp(buf, "Content-length: ", 16)) { ContentLength = atoi(&buf[16]); } - if (!strncasecmp(buf, "Content-type: ", 14)) { + else if (!strncasecmp(buf, "Content-type: ", 14)) { strcpy(ContentType, &buf[14]); } - } while (strlen(buf) > 0); + else if (!strncasecmp(buf, "User-agent: ", 12)) { + strcpy(user_agent, &buf[12]); + } + } ++TransactionCount; if (ContentLength > 0) { content = malloc(ContentLength + 1); - fread(content, ContentLength, 1, stdin); + read(WC->http_sock, content, ContentLength); content[ContentLength] = 0; @@ -707,7 +657,7 @@ void session_loop(char *browser_host, char *user_agent) cmd[a] = 0; } /* - * If we're not WC->connected to a Citadel server, try to hook up the + * If we're not connected to a Citadel server, try to hook up the * connection now. Preference is given to the host and port specified * by browser cookies, if cookies have been supplied. */ @@ -723,6 +673,7 @@ void session_loop(char *browser_host, char *user_agent) WC->connected = 1; serv_gets(buf); /* get the server welcome message */ + locate_host(browser_host, WC->http_sock); get_serv_info(browser_host, user_agent); } check_for_express_messages(); @@ -919,7 +870,7 @@ void session_loop(char *browser_host, char *user_agent) } else if (!strcasecmp(action, "display_menubar")) { display_menubar(1); } else if (!strcasecmp(action, "diagnostics")) { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("TransactionCount is %d<BR>\n", TransactionCount); @@ -948,43 +899,3 @@ void session_loop(char *browser_host, char *user_agent) WC->upload_length = 0; } } - -int main(int argc, char *argv[]) -{ - - char browser[256]; - int bd; - - if (argc != 6) { - fprintf(stderr, - "webcit: usage error (argc must be 6, not %d)\n", - argc); - return 1; - } - - WC = (struct wcsession *) malloc(sizeof(struct wcsession)); - memset(WC, 0, sizeof(struct wcsession)); - - - - WC->wc_session = atoi(argv[1]); - defaulthost = argv[2]; - defaultport = argv[3]; - - strcpy(WC->wc_username, ""); - strcpy(WC->wc_password, ""); - strcpy(WC->wc_roomname, ""); - - /* Clear out serv_info and temporarily set the value of serv_humannode - * to a default value, because it'll be used in HTML page titles - */ - memset(&serv_info, 0, sizeof(serv_info)); - strcpy(serv_info.serv_humannode, "WebCit"); - - strcpy(browser, argv[5]); - bd = browser_braindamage_check(browser); - - while (1) { - session_loop(argv[4], browser); - } -} diff --git a/webcit/webcit.h b/webcit/webcit.h index a831ec92f..0c5ae0732 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -3,10 +3,10 @@ #define SLEEPING 180 /* TCP connection timeout */ #define WEBCIT_TIMEOUT 900 /* WebCit session timeout */ #define PORT_NUM 2000 /* port number to listen on */ -#define SERVER "WebCit v2.01" /* who's in da house */ +#define SERVER "WebCit v2.50" /* who's in da house */ #define DEVELOPER_ID 0 #define CLIENT_ID 4 -#define CLIENT_VERSION 201 +#define CLIENT_VERSION 250 #define DEFAULT_HOST "localhost" #define DEFAULT_PORT "504" #define LB (1) @@ -34,17 +34,9 @@ #define QR_MAILBOX 16384 /* Set if this is a private mailbox */ -/* Browser braindamage check values */ -enum { - B_NO, - B_YES, - B_ASK -}; - - -struct webcontent { - struct webcontent *next; - char w_data[256]; +struct httprequest { + struct httprequest *next; + char line[256]; }; struct urlcontent { @@ -66,8 +58,15 @@ struct serv_info { int serv_ok_floors; }; + + +/* + * One of these is kept for each active Citadel session. + * HTTP transactions are bound to one at a time. + */ struct wcsession { - int wc_session; + struct wcsession *next; /* Linked list */ + int wc_session; /* WebCit session ID */ char wc_username[256]; char wc_password[256]; char wc_roomname[256]; @@ -76,8 +75,8 @@ struct wcsession { int axlevel; int is_aide; int is_room_aide; + int http_sock; int serv_sock; - struct serv_info serv_info; unsigned room_flags; char ugname[128]; long uglsn; @@ -85,14 +84,133 @@ struct wcsession { char *upload; int new_mail; int need_vali; + pthread_mutex_t SessionMutex; /* mutex for exclusive access */ + time_t lastreq; /* Timestamp of most recent HTTP */ }; -extern struct wcsession *WC; + + +#define WC ((struct wcsession *)pthread_getspecific(MyConKey)) +extern pthread_key_t MyConKey; struct serv_info serv_info; extern char floorlist[128][256]; extern char *axdefs[]; -void stuff_to_cookie(char *, int, char *, char *, char *); -void cookie_to_stuff(char *, int *, char *, char *, char *); + +void stuff_to_cookie(char *cookie, int session, + char *user, char *pass, char *room); +void cookie_to_stuff(char *cookie, int *session, + char *user, char *pass, char *room); void locate_host(char *, int); +void become_logged_in(char *, char *, char *); +void do_login(void); +void display_login(char *mesg); +void do_welcome(void); +void do_logout(void); +void display_main_menu(void); +void display_advanced_menu(void); +void list_all_rooms_by_floor(void); +void slrp_highest(void); +void gotonext(void); +void ungoto(void); +void get_serv_info(char *, char *); +int connectsock(char *host, char *service, char *protocol); +void serv_gets(char *strbuf); +void serv_puts(char *string); +void whobbs(void); +void fmout(FILE * fp); +void wDumpContent(int); +void serv_printf(const char *format,...); +char *bstr(char *key); +char *urlesc(char *); +void urlescputs(char *); +void output_headers(int); +void wprintf(const char *format,...); +void extract(char *dest, char *source, int parmnum); +int extract_int(char *source, int parmnum); +void output_static(char *what); +void escputs(char *strbuf); +void url(char *buf); +void escputs1(char *strbuf, int nbsp); +long extract_long(char *source, long int parmnum); +void dump_vars(void); +void embed_main_menu(void); +void serv_read(char *buf, int bytes); +int haschar(char *, char); +void readloop(char *oper); +void text_to_server(char *ptr); +void display_enter(void); +void post_message(void); +void confirm_delete_msg(void); +void delete_msg(void); +void confirm_move_msg(void); +void move_msg(void); +void userlist(void); +void showuser(void); +void display_page(void); +void page_user(void); +void do_chat(void); +void display_private(char *rname, int req_pass); +void goto_private(void); +void zapped_list(void); +void display_zap(void); +void zap(void); +void display_error(char *); +void display_success(char *); +void display_entroom(void); +void entroom(void); +void display_editroom(void); +void editroom(void); +void server_to_text(void); +void save_edit(char *description, char *enter_cmd, int regoto); +void display_edit(char *description, char *check_cmd, + char *read_cmd, char *save_cmd); +void gotoroom(char *gname, int display_name); +void confirm_delete_room(void); +void delete_room(void); +void validate(void); +void display_graphics_upload(char *, char *, char *); +void do_graphics_upload(char *upl_cmd); +void serv_read(char *buf, int bytes); +void serv_gets(char *strbuf); +void serv_write(char *buf, int nbytes); +void serv_puts(char *string); +void serv_printf(const char *format,...); +void load_floorlist(void); +void select_floor_to_edit_pic(void); +void display_reg(int); +void register_user(void); +void display_changepw(void); +void changepw(void); +void display_edit_node(void); +void display_netconf(void); +void display_confirm_unshare(void); +void display_confirm_delete_node(void); +void delete_node(void); +void unshare(void); +void display_add_node(void); +void add_node(void); +void display_share(void); +void share(void); +void terminate_session(void); +void edit_me(void); +void display_siteconfig(void); +void siteconfig(void); +void display_generic(void); +void do_generic(void); +void display_menubar(int); +void embed_room_banner(char *); +void smart_goto(char *); +void ExpressMessageCat(char *); +void worker_entry(void); +void session_loop(struct httprequest *); +void mime_parser(char *content, + int ContentLength, + char *ContentType, + void (*CallBack) + (char *cbname, + char *cbfilename, + char *cbencoding, + void *cbcontent, char *cbtype, size_t cblength) +); diff --git a/webcit/webserver.c b/webcit/webserver.c index 3a00ac373..ce0c9159d 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -44,11 +44,18 @@ int vsnprintf(char *buf, size_t max, const char *fmt, va_list argp); int msock; /* master listening socket */ extern void *context_loop(int); extern void *housekeeping_loop(void); -extern pthread_mutex_t MasterCritter; +extern pthread_mutex_t SessionListMutex; +extern pthread_key_t MyConKey; + + + + const char *defaulthost = DEFAULT_HOST; const char *defaultport = DEFAULT_PORT; +pthread_mutex_t AcceptQueue; + /* * This is a generic function to set up a master socket for listening on * a TCP port. The server shuts down if the bind fails. @@ -230,9 +237,6 @@ void start_daemon(int do_close_stdio) */ int main(int argc, char **argv) { - struct sockaddr_in fsin; /* Data for master socket */ - int alen; /* Data for master socket */ - int ssock; /* Descriptor for master socket */ pthread_t SessThread; /* Thread descriptor */ pthread_attr_t attr; /* Thread attributes */ int a, i; /* General-purpose variables */ @@ -264,12 +268,21 @@ int main(int argc, char **argv) defaultport = argv[optind]; } /* Tell 'em who's in da house */ - printf("WebCit version 2.01\n"); - printf("Copyright (C) 1996-1999. All rights reserved.\n\n"); + fprintf(stderr, SERVER "\n" + "Copyright (C) 1996-1999. All rights reserved.\n\n"); if (chdir(WEBCITDIR) != 0) perror("chdir"); + /* + * Set up a place to put thread-specific data. + * We only need a single pointer per thread - it points to the + * wcsession struct to which the thread is currently bound. + */ + if (pthread_key_create(&MyConKey, NULL) != 0) { + fprintf(stderr, "Can't create TSD key: %s\n", strerror(errno)); + } + /* * Bind the server to our favorite port. * There is no need to check for errors, because ig_tcp_server() @@ -280,9 +293,8 @@ int main(int argc, char **argv) printf("Listening on socket %d\n", msock); signal(SIGPIPE, SIG_IGN); - pthread_mutex_init(&MasterCritter, NULL); - - + pthread_mutex_init(&SessionListMutex, NULL); + pthread_mutex_init(&AcceptQueue, NULL); /* * Start up the housekeeping thread @@ -294,35 +306,57 @@ int main(int argc, char **argv) - /* - * Endless loop. Listen on the master socket. When a connection - * comes in, create a socket, a context, and a thread. - */ - while (1) { + /* FIX make this variable */ + for (i=0; i<10; ++i) { + + /* set attributes for the new thread */ + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + /* now create the thread */ + if (pthread_create(&SessThread, &attr, + (void *(*)(void *)) worker_entry, NULL) + != 0) { + printf("webcit: can't create thread: %s\n", + strerror(errno)); + } + } + + /* now become a worker thread too */ + worker_entry(); + pthread_exit(NULL); +} + + +/* + * Entry point for worker threads + */ +void worker_entry(void) { + int ssock; + struct sockaddr_in fsin; + int alen; + int i = 0; + int time_to_die = 0; + + do { + /* Only one thread can accept at a time */ + pthread_mutex_lock(&AcceptQueue); ssock = accept(msock, (struct sockaddr *) &fsin, &alen); + pthread_mutex_unlock(&AcceptQueue); + printf("New connection on socket %d\n", ssock); if (ssock < 0) { printf("webcit: accept() failed: %s\n", - strerror(errno)); + strerror(errno)); } else { /* Set the SO_REUSEADDR socket option */ i = 1; setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, - &i, sizeof(i)); - - /* set attributes for the new thread */ - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, - PTHREAD_CREATE_DETACHED); - - /* now create the thread */ - if (pthread_create(&SessThread, &attr, - (void *(*)(void *)) context_loop, - (void *) ssock) - != 0) { - printf("webcit: can't create thread: %s\n", - strerror(errno)); - } + &i, sizeof(i)); + context_loop(ssock); } - } + + } while (!time_to_die); + + pthread_exit(NULL); } diff --git a/webcit/who.c b/webcit/who.c index c71ce66a4..8afc9d081 100644 --- a/webcit/who.c +++ b/webcit/who.c @@ -1,16 +1,34 @@ /* $Id$ */ + + + +#include <ctype.h> #include <stdlib.h> -#ifdef HAVE_UNISTD_H #include <unistd.h> -#endif #include <stdio.h> +#include <fcntl.h> #include <signal.h> #include <sys/types.h> -#include <ctype.h> +#include <sys/wait.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <limits.h> +#include <netinet/in.h> +#include <netdb.h> #include <string.h> +#include <pwd.h> +#include <errno.h> +#include <stdarg.h> +#include <pthread.h> +#include <signal.h> #include "webcit.h" -#include "child.h" + + + + + + struct whouser { struct whouser *next; @@ -31,7 +49,7 @@ void whobbs(void) char buf[256], sess, user[256], room[256], host[256]; int foundit; - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>"); @@ -150,7 +168,7 @@ void terminate_session(void) display_error(&buf[4]); } } else { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>"); wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\" SIZE=+1 COLOR=\"FFFFFF\"<B>Confirm session termination"); @@ -199,7 +217,7 @@ void edit_me(void) whobbs(); } else { - printf("HTTP/1.0 200 OK\n"); + wprintf("HTTP/1.0 200 OK\n"); output_headers(1); wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>"); diff --git a/webcit/wildmat.c b/webcit/wildmat.c deleted file mode 100644 index f060ac818..000000000 --- a/webcit/wildmat.c +++ /dev/null @@ -1,201 +0,0 @@ -/* $Source$ - - * $Revision$ - * - * wildmat.c - simple regular expression pattern matching routines - * - * DESCRIPTION - * - * These routines provide simple UNIX style regular expression matching. - * They were originally written by Rich Salz, the comp.sources.unix - * moderator for inclusion in some of his software. These routines - * were released into the public domain and used by John Gilmore in - * USTAR. - * - * AUTHORS - * - * Mark H. Colburn, NAPS International (mark@jhereg.mn.org) - * John Gilmore (gnu@hoptoad) - * Rich Salz (rs@uunet.uu.net) - * - * - * Sponsored by The USENIX Association for public distribution. - * - * Copyright (c) 1989 Mark H. Colburn. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice is duplicated in all such - * forms and that any documentation, advertising materials, and other - * materials related to such distribution and use acknowledge that the - * software was developed * by Mark H. Colburn and sponsored by The - * USENIX Association. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $Log$ - * Revision 1.3 1999/06/08 02:01:29 ajc - * * Session no longer locks up when an express message is cancelled - * * The default Citadel server is now "localhost" instead of uncnsrd - * * Added some documentation - * - * Revision 1.2 1999/06/03 03:48:52 ajc - * * Ditched the frames mode completely. It wasn't working properly in, - * among other places, IE 5. Die, Bill, Die. - * - * Revision 1.1 1999/03/07 03:09:55 ajc - * * wildmat.c, braindamage.c: added - * - * Revision 1.1 88/12/23 18:02:41 mark - * Initial revision - * - */ - -/* Includes */ - -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> - - - -/* Function Prototypes */ - -#ifdef __STDC__ -static int star(char *, char *); -#else /* !__STDC__ */ -static int star(); -#endif /* __STDC__ */ - - -/* - * star - handle trailing * in a regular expression - * - * DESCRIPTION - * - * Star is used to match filename expansions containing a trailing - * asterisk ('*'). Star call wildmat() to determine if the substring - * passed to it is matches the regular expression. - * - * PARAMETERS - * - * char *source - The source string which is to be compared to the - * regular expression pattern. - * char *pattern - The regular expression which we are supposed to - * match to. - * - * RETURNS - * - * Returns non-zero if the entire source string is completely matched by - * the regular expression pattern, returns 0 otherwise. This is used to - * see if *'s in a pattern matched the entire source string. - * - */ - -#ifdef __STDC__ - -static int star(char *source, char *pattern) -#else - -static int star(source, pattern) -char *source; /* source operand */ -char *pattern; /* regular expression to match */ - -#endif -{ - while (!wildmat(source, pattern)) { - if (*++source == '\0') { - return (0); - } - } - return (1); -} - - -/* - * wildmat - match a regular expression - * - * DESCRIPTION - * - * Wildmat attempts to match the string pointed to by source to the - * regular expression pointed to by pattern. The subset of regular - * expression syntax which is supported is defined by POSIX P1003.2 - * FILENAME EXPANSION rules. - * - * PARAMETERS - * - * char *source - The source string which is to be compared to the - * regular expression pattern. - * char *pattern - The regular expression which we are supposed to - * match to. - * - * RETURNS - * - * Returns non-zero if the source string matches the regular expression - * pattern specified, returns 0 otherwise. - * - */ - -#ifdef __STDC__ - -int wildmat(char *pattern, char *source) -#else - -int wildmat(pattern, source) -char *pattern; /* regular expression to match */ -char *source; /* source operand */ - -#endif -{ - int last; /* last character matched */ - int matched; /* !0 if a match occurred */ - int reverse; /* !0 if sense of match is reversed */ - - for (; *pattern; source++, pattern++) { - switch (*pattern) { - case '\\': - /* Literal match with following character */ - pattern++; - /* FALLTHRU */ - default: - if (*source != *pattern) { - return (0); - } - continue; - case '?': - /* Match anything. */ - if (*source == '\0') { - return (0); - } - continue; - case '*': - /* Trailing star matches everything. */ - return (*++pattern ? star(source, pattern) : 1); - case '[': - /* [^....] means inverse character class. */ - if ((reverse = pattern[1]) == '^') { - pattern++; - } - for (last = 0400, matched = 0; - *++pattern && *pattern != ']'; last = *pattern) { - /* This next line requires a good C compiler. */ - if (*pattern == '-' - ? *source <= *++pattern && *source >= last - : *source == *pattern) { - matched = 1; - } - } - if (matched == reverse) { - return (0); - } - continue; - } - } - - /* - * For "tar" use, matches that end at a slash also work. --hoptoad!gnu - */ - return (*source == '\0' || *source == '/'); -} -- 2.30.2