* use enum to handle http request types
authorWilfried Göesgens <willi@citadel.org>
Sun, 10 May 2009 22:01:12 +0000 (22:01 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 10 May 2009 22:01:12 +0000 (22:01 +0000)
* some more cleanup

webcit/context_loop.c
webcit/groupdav.h
webcit/groupdav_main.c
webcit/rss.c
webcit/webcit.c
webcit/webcit.h

index 314313c37b6dd31f6cc7e280e11386cf18f2986a..30b33cd725b50fafc8d585b8556a7a3ecd3cb466 100644 (file)
@@ -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 
index ee7ffff8012ffd1f437f1a7b7a8d958a9a784c4d..82b532192f15f2fd6a7220cf8e30b3ed6490f65e 100644 (file)
@@ -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,
index ce04ea675b8fbd3f5dcbc1317308b69ecf9e81c3..7d774feac65495b15cf040c884eae70d3a2de9f1 100644 (file)
@@ -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();
+       }
 }
 
 
index ab01a2aef1d598d1062a8966a3047c0bf2848969..09e17d0e4450df62b716408251eb335cc173642e 100644 (file)
@@ -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;
 
        /* <?xml.. etc confuses our subst parser, so do it here */
index e1e9c5ded3184482631f9182f979f41e40acd405..5057192c30f7aa28967b9d0fc6808cc6fd1428a1 100644 (file)
@@ -564,7 +564,6 @@ int is_mobile_ua(char *user_agent) {
  * Entry point for WebCit transaction
  */
 void session_loop(StrBuf *ReqLine, 
-                 StrBuf *request_method, 
                  StrBuf *ReadBuf,
                  const char **Pos)
 {
@@ -944,7 +943,7 @@ void session_loop(StrBuf *ReqLine,
        /* This needs to run early */
 #ifdef TECH_PREVIEW
        if (!strcasecmp(action, "rss")) {
-               display_rss(sbstr("room"), request_method);
+               display_rss(sbstr("room"));
                goto SKIP_ALL_THIS_CRAP;
        }
 #endif
@@ -955,7 +954,7 @@ void session_loop(StrBuf *ReqLine,
         */
        if (!strncasecmp(action, "groupdav", 8)) {
                groupdav_main(WCC->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);
index 1efdeec091589fb36e8cb1f3a598f78508486306..77e858ce4291c2b04a148252559b6587c5ac4f17 100644 (file)
@@ -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[]);