From: Wilfried Göesgens Date: Sun, 10 May 2009 22:01:12 +0000 (+0000) Subject: * use enum to handle http request types X-Git-Tag: v7.86~1181 X-Git-Url: https://code.citadel.org/?a=commitdiff_plain;h=9b0044ebde16159fdc39adb22700b07dbdeed7d0;p=citadel.git * use enum to handle http request types * some more cleanup --- diff --git a/webcit/context_loop.c b/webcit/context_loop.c index 314313c37..30b33cd72 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -18,7 +18,7 @@ pthread_mutex_t SessionListMutex; wcsession *SessionList = NULL; /**< our sessions ????*/ pthread_key_t MyConKey; /**< TSD key for MySession() */ - +HashList *HttpReqTypes = NULL; void shutdown_sessions(void) { @@ -214,6 +214,8 @@ int is_bogus(StrBuf *http_cmd) { */ void context_loop(int *sock) { + long eReqType = eGET; + int isbogus = 0; const char *Pos = NULL; const char *buf; int desired_session = 0; @@ -223,11 +225,10 @@ void context_loop(int *sock) char httpauth_string[1024]; char httpauth_user[1024]; char httpauth_pass[1024]; - int session_is_new = 0; int nLine = 0; int LineLen; void *vLine; - StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine, *ReqType, *HTTPVersion; + StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine; const char *pch, *pchs, *pche; HashList *HTTPHeaders; @@ -257,6 +258,28 @@ void context_loop(int *sock) if (nLine == 1) { ReqLine = Line; + /* The requesttype... GET, POST... */ + StrBufExtract_token(HeaderName, ReqLine, 0, ' '); + if (GetHash(HttpReqTypes, SKEY(HeaderName), &vLine) && + (vLine != NULL)) + { + eReqType = *(long*)vLine; + } + else { + eReqType = eGET; + isbogus = 1; + break; + } + StrBufCutLeft(ReqLine, StrLength(HeaderName) + 1); + /* the HTTP Version... */ + StrBufExtract_token(HeaderName, ReqLine, 1, ' '); + StrBufCutRight(ReqLine, StrLength(HeaderName) + 1); + if ((StrLength(HeaderName) == 0) || + is_bogus(ReqLine)) { + eReqType = eGET; + isbogus = 1; + break; + } continue; } if (LineLen == 0) { @@ -291,15 +314,21 @@ void context_loop(int *sock) Put(HTTPHeaders, SKEY(HeaderName), Line, HFreeStrBuf); LastLine = Line; } while (LineLen > 0); + FreeStrBuf(&HeaderName); + if (isbogus) + StrBufPlain(ReqLine, HKEY("/404")); + + /* dbg_PrintHash(HTTPHeaders, nix, NULL); */ /* * Can we compress? */ - if (GetHash(HTTPHeaders, HKEY("ACCEPT-ENCODING"), &vLine) && + if (!isbogus && + GetHash(HTTPHeaders, HKEY("ACCEPT-ENCODING"), &vLine) && (vLine != NULL)) { buf = ChrPtr((StrBuf*)vLine); if (strstr(&buf[16], "gzip")) { @@ -310,7 +339,8 @@ void context_loop(int *sock) /* * Browser-based sessions use cookies for session authentication */ - if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && + if (!isbogus && + GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && (vLine != NULL)) { cookie_to_stuff(vLine, &desired_session, NULL, NULL, NULL); @@ -320,7 +350,8 @@ void context_loop(int *sock) /* * GroupDAV-based sessions use HTTP authentication */ - if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && + if (!isbogus && + GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && (vLine != NULL)) { Line = (StrBuf*)vLine; if (strncasecmp(ChrPtr(Line), "Basic", 5) == 0) { @@ -333,26 +364,23 @@ void context_loop(int *sock) lprintf(1, "Authentication scheme not supported! [%s]\n", ChrPtr(Line)); } - if (GetHash(HTTPHeaders, HKEY("IF-MODIFIED-SINCE"), &vLine) && + if (!isbogus && + GetHash(HTTPHeaders, HKEY("IF-MODIFIED-SINCE"), &vLine) && (vLine != NULL)) { if_modified_since = httpdate_to_timestamp((StrBuf*)vLine); } - ReqType = NewStrBuf(); - HTTPVersion = NewStrBuf(); - StrBufExtract_token(HTTPVersion, ReqLine, 2, ' '); - StrBufExtract_token(ReqType, ReqLine, 0, ' '); - StrBufCutLeft(ReqLine, StrLength(ReqType) + 1); - StrBufCutRight(ReqLine, StrLength(HTTPVersion) + 1); /* * If the request is prefixed by "/webcit" then chop that off. This * allows a front end web server to forward all /webcit requests to us * while still using the same web server port for other things. */ - if ( (StrLength(ReqLine) >= 8) && (strstr(ChrPtr(ReqLine), "/webcit/")) ) { + if (!isbogus && + (StrLength(ReqLine) >= 8) && + (strstr(ChrPtr(ReqLine), "/webcit/")) ) { StrBufCutLeft(ReqLine, 7); } @@ -364,33 +392,27 @@ void context_loop(int *sock) (strncmp(ChrPtr(ReqLine), "/wholist_section", 16) != 0) && (strstr(ChrPtr(ReqLine), "wholist_section") == NULL)) { #endif - lprintf(5, "HTTP: %s %s %s\n", ChrPtr(ReqType), ChrPtr(ReqLine), ChrPtr(HTTPVersion)); + lprintf(5, "HTTP: %s %s\n", ReqStrs[eReqType], ChrPtr(ReqLine)); #ifdef TECH_PREVIEW } #endif - /** Check for bogus requests */ - if ((StrLength(HTTPVersion) == 0) || - (StrLength(ReqType) == 0) || - is_bogus(ReqLine)) { - StrBufPlain(ReqLine, HKEY("/404 HTTP/1.1")); - StrBufPlain(ReqType, HKEY("GET")); - } - FreeStrBuf(&HTTPVersion); /** * While we're at it, gracefully handle requests for the * robots.txt and favicon.ico files. */ - if (!strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) { + if ((StrLength(ReqLine) >= 11) && + !strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) { StrBufPlain(ReqLine, HKEY("/static/robots.txt" "?force_close_session=yes HTTP/1.1")); - StrBufPlain(ReqType, HKEY("GET")); + eReqType = eGET; } - else if (!strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) { + else if ((StrLength(ReqLine) >= 11) && + !strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) { StrBufPlain(ReqLine, HKEY("/static/favicon.ico")); - StrBufPlain(ReqType, HKEY("GET")); + eReqType = eGET; } /** @@ -478,9 +500,7 @@ void context_loop(int *sock) TheSession->is_mobile = -1; SessionList = TheSession; pthread_mutex_unlock(&SessionListMutex); - session_is_new = 1; } - TheSession->headers = HTTPHeaders; /* * A future improvement might be to check the session integrity @@ -493,13 +513,14 @@ void context_loop(int *sock) pthread_mutex_lock(&TheSession->SessionMutex); /* bind */ pthread_setspecific(MyConKey, (void *)TheSession); + TheSession->eReqType = eReqType; + TheSession->headers = HTTPHeaders; TheSession->lastreq = time(NULL); /* log */ TheSession->http_sock = *sock; TheSession->gzip_ok = gzip_ok; session_attach_modules(TheSession); - - session_loop(ReqLine, ReqType, Buf, &Pos); /* do transaction */ + session_loop(ReqLine, Buf, &Pos); /* do transaction */ session_detach_modules(TheSession); TheSession->headers = NULL; @@ -508,7 +529,6 @@ void context_loop(int *sock) /* Free the request buffer */ DeleteHash(&HTTPHeaders); FreeStrBuf(&ReqLine); - FreeStrBuf(&ReqType); FreeStrBuf(&Buf); } @@ -529,6 +549,59 @@ void tmplput_current_room(StrBuf *Target, WCTemplputParams *TP) StrBufAppendTemplate(Target, TP, WC->wc_roomname, 0); } +const char *ReqStrs[eNONE] = { + "GET", + "POST", + "OPTIONS", + "PROPFIND", + "PUT", + "DELETE", + "HEAD" +}; + +void +ServerStartModule_CONTEXT +(void) +{ + long *v; + HttpReqTypes = NewHash(1, NULL); + + + v = malloc(sizeof(long)); + *v = eGET; + Put(HttpReqTypes, HKEY("GET"), v, NULL); + + v = malloc(sizeof(long)); + *v = ePOST; + Put(HttpReqTypes, HKEY("POST"), v, NULL); + + v = malloc(sizeof(long)); + *v = eOPTIONS; + Put(HttpReqTypes, HKEY("OPTIONS"), v, NULL); + + v = malloc(sizeof(long)); + *v = ePROPFIND; + Put(HttpReqTypes, HKEY("PROPFIND"), v, NULL); + + v = malloc(sizeof(long)); + *v = ePUT; + Put(HttpReqTypes, HKEY("PUT"), v, NULL); + + v = malloc(sizeof(long)); + *v = eDELETE; + Put(HttpReqTypes, HKEY("DELETE"), v, NULL); + + v = malloc(sizeof(long)); + *v = eHEAD; + Put(HttpReqTypes, HKEY("HEAD"), v, NULL); +} + +void +ServerShutdownModule_CONTEXT +(void) +{ + DeleteHash(&HttpReqTypes); +} void diff --git a/webcit/groupdav.h b/webcit/groupdav.h index ee7ffff80..82b532192 100644 --- a/webcit/groupdav.h +++ b/webcit/groupdav.h @@ -16,7 +16,6 @@ struct epdata { void groupdav_common_headers(void); void groupdav_main(HashList *HTTPHeaders, StrBuf *DavPathname, - StrBuf *DavMethod, StrBuf *dav_content_type, int dav_content_length, StrBuf *dav_content, diff --git a/webcit/groupdav_main.c b/webcit/groupdav_main.c index ce04ea675..7d774feac 100644 --- a/webcit/groupdav_main.c +++ b/webcit/groupdav_main.c @@ -86,7 +86,6 @@ void euid_unescapize(char *target, const char *source) { */ void groupdav_main(HashList *HTTPHeaders, StrBuf *DavPathname, - StrBuf *DavMethod, StrBuf *dav_content_type, int dav_content_length, StrBuf *dav_content, @@ -164,62 +163,62 @@ void groupdav_main(HashList *HTTPHeaders, } } + switch (WCC->eReqType) + { /* * The OPTIONS method is not required by GroupDAV. This is an * experiment to determine what might be involved in supporting * other variants of DAV in the future. */ - if (!strcasecmp(ChrPtr(DavMethod), "OPTIONS")) { + case eOPTIONS: groupdav_options(DavPathname); - return; - } + break; + /* * The PROPFIND method is basically used to list all objects in a * room, or to list all relevant rooms on the server. */ - if (!strcasecmp(ChrPtr(DavMethod), "PROPFIND")) { + case ePROPFIND: groupdav_propfind(DavPathname, dav_depth, dav_content_type, dav_content, Offset); - return; - } + break; /* * The GET method is used for fetching individual items. */ - if (!strcasecmp(ChrPtr(DavMethod), "GET")) { + case eGET: groupdav_get(DavPathname); - return; - } - + break; + /* * The PUT method is used to add or modify items. */ - if (!strcasecmp(ChrPtr(DavMethod), "PUT")) { + case ePUT: groupdav_put(DavPathname, dav_ifmatch, ChrPtr(dav_content_type), dav_content, Offset); - return; - } - + break; + /* * The DELETE method kills, maims, and destroys. */ - if (!strcasecmp(ChrPtr(DavMethod), "DELETE")) { + case eDELETE: groupdav_delete(DavPathname, dav_ifmatch); - return; - } + break; + default: /* * Couldn't find what we were looking for. Die in a car fire. */ - hprintf("HTTP/1.1 501 Method not implemented\r\n"); - groupdav_common_headers(); - hprintf("Content-Type: text/plain\r\n"); - wprintf("GroupDAV method \"%s\" is not implemented.\r\n", - ChrPtr(DavMethod)); - end_burst(); + hprintf("HTTP/1.1 501 Method not implemented\r\n"); + groupdav_common_headers(); + hprintf("Content-Type: text/plain\r\n"); + wprintf("GroupDAV method \"%s\" is not implemented.\r\n", + ReqStrs[WCC->eReqType]); + end_burst(); + } } diff --git a/webcit/rss.c b/webcit/rss.c index ab01a2aef..09e17d0e4 100644 --- a/webcit/rss.c +++ b/webcit/rss.c @@ -43,7 +43,7 @@ void display_rss_control(char *reply_to, char *subject) * roomname the room we sould print out as rss * request_method the way the rss is requested???? */ -void display_rss(const StrBuf *roomname, StrBuf *request_method) +void display_rss(const StrBuf *roomname) { message_summary *Msg; wcsession *WCC = WC; @@ -156,7 +156,7 @@ void display_rss(const StrBuf *roomname, StrBuf *request_method) hprintf("Content-Type: application/rss+xml\r\n"); hprintf("Server: %s\r\n", PACKAGE_STRING); hprintf("Connection: close\r\n"); - if (!strcasecmp(ChrPtr(request_method), "HEAD")) + if (WCC->eReqType == eHEAD) return; /* headers, - ReqLine, request_method, + ReqLine, ContentType, /* do GroupDAV methods */ ContentLength, content, body_start); if (!WCC->logged_in) { @@ -969,9 +968,11 @@ void session_loop(StrBuf *ReqLine, * Automatically send requests with any method other than GET or * POST to the GroupDAV code as well. */ - if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) { + if ((WCC->eReqType != eGET) && + (WCC->eReqType != ePOST) && + (WCC->eReqType != eHEAD)) { groupdav_main(WCC->headers, ReqLine, - request_method, ContentType, /** do GroupDAV methods */ + ContentType, /** do GroupDAV methods */ ContentLength, content, body_start); if (!WCC->logged_in) { WCC->killthis = 1; /** If not logged in, don't */ @@ -1077,12 +1078,6 @@ SKIP_ALL_THIS_CRAP: FreeStrBuf(&content); content = NULL; } - DeleteHash(&WCC->urlstrings); - if (WCC->upload_length > 0) { - free(WCC->upload); - WCC->upload_length = 0; - } - FreeStrBuf(&WCC->trailing_javascript); WCC->http_host = NULL; /* How long did this transaction take? */ @@ -1206,6 +1201,13 @@ void SessionDetachModule_WEBCIT (wcsession *sess) { + DeleteHash(&sess->urlstrings); + if (sess->upload_length > 0) { + free(sess->upload); + sess->upload_length = 0; + } + FreeStrBuf(&sess->trailing_javascript); + if (StrLength(sess->WBuf) > SIZ * 30) /* Bigger than 120K? release. */ { FreeStrBuf(&sess->WBuf); diff --git a/webcit/webcit.h b/webcit/webcit.h index 1efdeec09..77e858ce4 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -328,6 +328,17 @@ enum { eNone }; +enum { + eGET, + ePOST, + eOPTIONS, + ePROPFIND, + ePUT, + eDELETE, + eHEAD, + eNONE +}; +const char *ReqStrs[eNONE]; /* * One of these is kept for each active Citadel session. * HTTP transactions are bound to one at a time. @@ -353,7 +364,9 @@ struct wcsession { time_t lastreq; /**< Timestamp of most recent HTTP */ time_t last_pager_check; /**< last time we polled for instant msgs */ ServInfo *serv_info; /**< Iformation about the citserver we're connected to */ + /* Request local Members */ + long eReqType; /**< eGET, ePOST.... */ StrBuf *CLineBuf; /**< linebuffering client stuff */ StrBuf *UrlFragment1; /**< first urlfragment, if NEED_URL is specified by the handler*/ StrBuf *UrlFragment2; /**< second urlfragment, if NEED_URL is specified by the handler*/ @@ -619,7 +632,6 @@ void do_housekeeping(void); void smart_goto(const StrBuf *); void worker_entry(void); void session_loop(StrBuf *ReqLine, - StrBuf *ReqType, StrBuf *ReadBuf, const char **Pos); size_t wc_strftime(char *s, size_t max, const char *format, const struct tm *tm); @@ -721,7 +733,7 @@ void http_transmit_thing(const char *content_type, int is_static); long unescape_input(char *buf); void do_selected_iconbar(void); void spawn_another_worker_thread(void); -void display_rss(const StrBuf *roomname, StrBuf *request_method); +void display_rss(const StrBuf *roomname); void StrEndTab(StrBuf *Target, int tabnum, int num_tabs); void StrBeginTab(StrBuf *Target, int tabnum, int num_tabs); void StrTabbedDialog(StrBuf *Target, int num_tabs, StrBuf *tabnames[]);