* do linebuffered/non-blocking reads from http requests
authorWilfried Göesgens <willi@citadel.org>
Sun, 14 Sep 2008 16:50:08 +0000 (16:50 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 14 Sep 2008 16:50:08 +0000 (16:50 +0000)
* migrate HTTP-Headers to a Hashtable
* adjust the rest of the party to work with this.

18 files changed:
webcit/calendar.c
webcit/context_loop.c
webcit/cookie_conversion.c
webcit/crypto.c
webcit/fmt_date.c
webcit/gettext.c
webcit/groupdav.h
webcit/groupdav_delete.c
webcit/groupdav_get.c
webcit/groupdav_main.c
webcit/groupdav_options.c
webcit/groupdav_propfind.c
webcit/groupdav_put.c
webcit/rss.c
webcit/webcit.c
webcit/webcit.h
webcit/webserver.c
webcit/webserver.h

index c9d40bc8e0d8a8055a3305588e4023cb070e9884..b966c264bf02c049d32c65d8abdcef751dc1a837 100644 (file)
@@ -1072,7 +1072,7 @@ void save_event(void) {
 /*
  * Anonymous request of freebusy data for a user
  */
-void do_freebusy(char *req) {
+void do_freebusy(const char *req) {
        char who[SIZ];
        char buf[SIZ];
        int len;
index 4cf0b5bfee7ee265d8444d283bec75d3e1ec5b79..bdf17054d431ac211c56efd982221c36923a1d3f 100644 (file)
@@ -53,7 +53,7 @@ void DestroySession(struct wcsession **sessions_to_kill)
        FreeStrBuf(&((*sessions_to_kill)->UrlFragment2));
        FreeStrBuf(&((*sessions_to_kill)->WBuf));
        FreeStrBuf(&((*sessions_to_kill)->HBuf));
-
+       FreeStrBuf(&((*sessions_to_kill)->CLineBuf));
        free((*sessions_to_kill));
        (*sessions_to_kill) = NULL;
 }
@@ -171,40 +171,52 @@ int GenerateSessionID(void)
 /*
  * Collapse multiple cookies on one line
  */
-int req_gets(int *sock, char *buf, char *hold, size_t hlen)
-{
-       int a, b;
-
-       if (IsEmptyStr(hold)) {
-               strcpy(buf, "");
-               a = client_getln(sock, buf, SIZ);
-               if (a<1) return(-1);
-       } else {
-               safestrncpy(buf, hold, SIZ);
-       }
-       strcpy(hold, "");
-
-       if (!strncasecmp(buf, "Cookie: ", 8)) {
-               int len;
-               len = strlen(buf);
-               for (a = 0; a < len; ++a)
-                       if (buf[a] == ';') {
-                               // we don't refresh len, because of we 
-                               // only exit from here.
-                               snprintf(hold, hlen, "Cookie: %s", &buf[a + 1]);
-                               buf[a] = 0;
-                               b = 8;
-                               while (isspace(hold[b]))
-                                       b++;
-                               
-                               memmove(&hold[8], &hold[b], len - b + 1);
-                               return(0);
-                       }
-       }
+////int req_gets(int *sock, char *buf, char *hold, size_t hlen)
+////{
+////   int a, b;
+////
+////   if (IsEmptyStr(hold)) {
+////           strcpy(buf, "");
+////           a = client_getln(sock, buf, SIZ);
+////           if (a<1) return(-1);
+////   } else {
+////           safestrncpy(buf, hold, SIZ);
+////   }
+////   strcpy(hold, "");
+////
+////   if (!strncasecmp(buf, "Cookie: ", 8)) {
+////           int len;
+////           len = strlen(buf);
+////           for (a = 0; a < len; ++a)
+////                   if (buf[a] == ';') {
+////                           // we don't refresh len, because of we 
+////                           // only exit from here.
+////                           snprintf(hold, hlen, "Cookie: %s", &buf[a + 1]);
+////                           buf[a] = 0;
+////                           b = 8;
+////                           while (isspace(hold[b]))
+////                                   b++;
+////                           
+////                           memmove(&hold[8], &hold[b], len - b + 1);
+////                           return(0);
+////                   }
+////   }
+////
+////   return(0);
+////}
+
 
-       return(0);
+/*
+ * Collapse multiple cookies on one line
+ */
+int ReqGetStrBuf(int *sock, StrBuf *Target, StrBuf *buf)
+{
+       
+       return ClientGetLine(sock, Target, buf);
 }
 
+
+
 /*
  * lingering_close() a`la Apache. see
  * http://www.apache.org/docs/misc/fin_wait_2.html for rationale
@@ -249,12 +261,12 @@ int lingering_close(int fd)
  *
  * \param      http_cmd        The HTTP request to check
  */
-int is_bogus(char *http_cmd) {
-       char *url;
+int is_bogus(StrBuf *http_cmd) {
+       const char *url;
        int i, max;
 
-       url = strstr(http_cmd, " ");
-       if (url == NULL) return(1);
+       url = ChrPtr(http_cmd);
+       if (IsEmptyStr(url)) return(1);
        ++url;
 
        char *bogus_prefixes[] = {
@@ -277,6 +289,7 @@ int is_bogus(char *http_cmd) {
 }
 
 
+const char *nix(void *vptr) {return ChrPtr( (StrBuf*)vptr);}
 
 /**
  * \brief handle one request
@@ -293,10 +306,7 @@ int is_bogus(char *http_cmd) {
  */
 void context_loop(int *sock)
 {
-       struct httprequest *req = NULL;
-       struct httprequest *last = NULL;
-       struct httprequest *hptr;
-       char buf[SIZ], hold[SIZ];
+       const char *buf;
        int desired_session = 0;
        int got_cookie = 0;
        int gzip_ok = 0;
@@ -304,9 +314,14 @@ void context_loop(int *sock)
        char httpauth_string[1024];
        char httpauth_user[1024];
        char httpauth_pass[1024];
-       char accept_language[256];
        char *ptr = NULL;
        int session_is_new = 0;
+       int nLine = 0;
+       int LineLen;
+       void *vLine;
+       StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine, *accept_language, *ReqType, *HTTPVersion;
+       const char *pch, *pchs, *pche;
+       HashList *HTTPHeaders;
 
        strcpy(httpauth_string, "");
        strcpy(httpauth_user, DEFAULT_HTTPAUTH_USER);
@@ -315,111 +330,161 @@ void context_loop(int *sock)
        /**
         * Find out what it is that the web browser is asking for
         */
-       memset(hold, 0, sizeof(hold));
+       HeaderName = NewStrBuf();
+       Buf = NewStrBuf();
+       LastLine = NULL;
+       HTTPHeaders = NewHash(1, NULL);
+       /**
+        * Read in the request
+        */
        do {
-               if (req_gets(sock, buf, hold, SIZ) < 0) return;
-
-               /**
-                * Can we compress?
-                */
-               if (!strncasecmp(buf, "Accept-encoding:", 16)) {
-                       if (strstr(&buf[16], "gzip")) {
-                               gzip_ok = 1;
-                       }
-               }
+               nLine ++;
+               Line = NewStrBuf();
+               if (ReqGetStrBuf(sock, Line, Buf) < 0) return;
 
-               /**
-                * Browser-based sessions use cookies for session authentication
-                */
-               if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
-                       cookie_to_stuff(&buf[15], &desired_session,
-                               NULL, 0, NULL, 0, NULL, 0);
-                       got_cookie = 1;
+               LineLen = StrLength(Line);
+
+               if (nLine == 1) {
+                       ReqLine = Line;
+                       continue;
+               }
+               if (LineLen == 0) {
+                       FreeStrBuf(&Line);
+                       continue;
                }
 
-               /**
-                * GroupDAV-based sessions use HTTP authentication
-                */
-               if (!strncasecmp(buf, "Authorization: Basic ", 21)) {
-                       CtdlDecodeBase64(httpauth_string, &buf[21], strlen(&buf[21]));
-                       extract_token(httpauth_user, httpauth_string, 0, ':', sizeof httpauth_user);
-                       extract_token(httpauth_pass, httpauth_string, 1, ':', sizeof httpauth_pass);
+               /** Do we need to Unfold? */
+               if ((LastLine != NULL) && 
+                   (isspace(*ChrPtr(Line)))) {
+                       pch = pchs = ChrPtr(Line);
+                       pche = pchs + StrLength(Line);
+                       while (isspace(pch) && (pch < pche))
+                               pch ++;
+                       StrBufCutLeft(Line, pch - pchs);
+                       StrBufAppendBuf(LastLine, Line, 0);
+                       FreeStrBuf(&Line);
+                       continue;
                }
 
-               if (!strncasecmp(buf, "If-Modified-Since: ", 19)) {
-                       if_modified_since = httpdate_to_timestamp(&buf[19]);
+               StrBufExtract_token(HeaderName, Line, 0, ':');
+       //// TODO: filter bad chars!
+
+               pchs = ChrPtr(Line);
+               pch = pchs + StrLength(HeaderName) + 1;
+               pche = pchs + StrLength(Line);
+               while (isspace(*pch) && (pch < pche))
+                       pch ++;
+               StrBufCutLeft(Line, pch - pchs);
+
+               StrBufUpCase(HeaderName);
+               Put(HTTPHeaders, SKEY(HeaderName), Line, HFreeStrBuf);
+               LastLine = Line;
+       } while (LineLen > 0);
+       FreeStrBuf(&HeaderName);
+
+////   dbg_PrintHash(HTTPHeaders, nix, NULL);
+
+
+       /**
+        * Can we compress?
+        */
+       if (GetHash(HTTPHeaders, HKEY("ACCEPT-ENCODING"), &vLine) && 
+           (vLine != NULL)) {
+               buf = ChrPtr((StrBuf*)vLine);
+               if (strstr(&buf[16], "gzip")) {
+                       gzip_ok = 1;
                }
+       }
+
+       /**
+        * Browser-based sessions use cookies for session authentication
+        */
+       if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && 
+           (vLine != NULL)) {
+               cookie_to_stuff(vLine, &desired_session,
+                               NULL, 0, NULL, 0, NULL, 0);
+               got_cookie = 1;
+       }
 
-               if (!strncasecmp(buf, "Accept-Language: ", 17)) {
-                       safestrncpy(accept_language, &buf[17], sizeof accept_language);
+       /**
+        * GroupDAV-based sessions use HTTP authentication
+        */
+       if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && 
+           (vLine != NULL)) {
+               Line = (StrBuf*)vLine;
+               if (strncasecmp(ChrPtr(Line), "Basic ", 6)) {
+                       StrBufCutLeft(Line, 6);
+                       CtdlDecodeBase64(httpauth_string, ChrPtr(Line), StrLength(Line));
+                       extract_token(httpauth_user, httpauth_string, 0, ':', sizeof httpauth_user);
+                       extract_token(httpauth_pass, httpauth_string, 1, ':', sizeof httpauth_pass);
                }
+               else 
+                       lprintf(1, "Authentication sheme not supported! [%s]\n", ChrPtr(Line));
+       }
 
-               /**
-                * Read in the request
-                */
-               hptr = (struct httprequest *)
-                       malloc(sizeof(struct httprequest));
-               if (req == NULL)
-                       req = hptr;
-               else
-                       last->next = hptr;
-               hptr->next = NULL;
-               last = hptr;
+       if (GetHash(HTTPHeaders, HKEY("IF-MODIFIED-SINCE"), &vLine) && 
+           (vLine != NULL)) {
+               if_modified_since = httpdate_to_timestamp((StrBuf*)vLine);
+       }
 
-               safestrncpy(hptr->line, buf, sizeof hptr->line);
+       if (GetHash(HTTPHeaders, HKEY("ACCEPT-LANGUAGE"), &vLine) && 
+           (vLine != NULL)) {
+               accept_language = (StrBuf*) vLine;
+       }
 
-       } while (!IsEmptyStr(buf));
 
        /**
         * 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.
         */
-       
-       ptr = strstr(req->line, " /webcit ");   /*< Handle "/webcit" */
-       if (ptr != NULL) {
-               strcpy(ptr+2, ptr+8);
-       }
 
-       ptr = strstr(req->line, " /webcit");    /*< Handle "/webcit/" */
-       if (ptr != NULL) {
-               strcpy(ptr+1, ptr+8);
+       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 ((StrLength(ReqLine) > 10) &&
+           (ptr = strstr(ChrPtr(ReqLine), "/webcit "), /*< Handle "/webcit" */
+            (ptr != NULL))) {
+               StrBufCutLeft(ReqLine, 6);
        }
 
-       safestrncpy(buf, req->line, sizeof buf);
        /** Begin parsing the request. */
 #ifdef TECH_PREVIEW
-       if ((strncmp(req->line+4, "/sslg", 5) != 0) &&
-           (strncmp(req->line+4, "/static/", 8) != 0) &&
-           (strncmp(req->line+4, "/wholist_section", 16) != 0)) {
+       if ((strncmp(ChrPtr(ReqLine), "/sslg", 5) != 0) &&
+           (strncmp(ChrPtr(ReqLine), "/static/", 8) != 0) &&
+           (strncmp(ChrPtr(ReqLine), "/wholist_section", 16) != 0)) {
 #endif
-               lprintf(5, "HTTP: %s\n", buf);
+               lprintf(5, "HTTP: %s %s %s\n", ChrPtr(ReqType), ChrPtr(ReqLine), ChrPtr(HTTPVersion));
 #ifdef TECH_PREVIEW
        }
 #endif
 
        /** Check for bogus requests */
-       if (is_bogus(buf)) {
-               strcpy(req->line, "GET /404 HTTP/1.1");
-               strcpy(buf, "GET /404 HTTP/1.1");
+       if ((StrLength(HTTPVersion) == 0) ||
+           (StrLength(ReqType) == 0) || 
+           is_bogus(ReqLine)) {
+               StrBufPlain(ReqLine, HKEY("/404 HTTP/1.1"));
+               StrBufPlain(ReqType, HKEY("GET"));
        }
-
-       /**
-        * Strip out the method, leaving the URL up front...
-        */
-       remove_token(buf, 0, ' ');
-       if (buf[1]==' ') buf[1]=0;
+       FreeStrBuf(&HTTPVersion);
 
        /**
         * While we're at it, gracefully handle requests for the
         * robots.txt and favicon.ico files.
         */
-       if (!strncasecmp(buf, "/robots.txt", 11)) {
-               strcpy(req->line, "GET /static/robots.txt"
-                               "?force_close_session=yes HTTP/1.1");
+       if (!strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) {
+               StrBufPlain(ReqLine, 
+                           HKEY("/static/robots.txt"
+                                "?force_close_session=yes HTTP/1.1"));
+               StrBufPlain(ReqType, HKEY("GET"));
        }
-       else if (!strncasecmp(buf, "/favicon.ico", 12)) {
-               strcpy(req->line, "GET /static/favicon.ico");
+       else if (!strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) {
+               StrBufPlain(ReqLine, HKEY("/static/favicon.ico"));
+               StrBufPlain(ReqType, HKEY("GET"));
        }
 
        /**
@@ -428,17 +493,18 @@ void context_loop(int *sock)
         * force the session to close because cookies are
         * probably disabled on the client browser.
         */
-       else if ( (strcmp(buf, "/"))
-               && (strncasecmp(buf, "/listsub", 8))
-               && (strncasecmp(buf, "/freebusy", 9))
-               && (strncasecmp(buf, "/do_logout", 10))
-               && (strncasecmp(buf, "/groupdav", 9))
-               && (strncasecmp(buf, "/static", 7))
-               && (strncasecmp(buf, "/rss", 4))
-               && (strncasecmp(buf, "/404", 4))
+       else if ( (StrLength(ReqLine) > 1 )
+               && (strncasecmp(ChrPtr(ReqLine), "/listsub", 8))
+               && (strncasecmp(ChrPtr(ReqLine), "/freebusy", 9))
+               && (strncasecmp(ChrPtr(ReqLine), "/do_logout", 10))
+               && (strncasecmp(ChrPtr(ReqLine), "/groupdav", 9))
+               && (strncasecmp(ChrPtr(ReqLine), "/static", 7))
+               && (strncasecmp(ChrPtr(ReqLine), "/rss", 4))
+               && (strncasecmp(ChrPtr(ReqLine), "/404", 4))
                && (got_cookie == 0)) {
-               strcpy(req->line, "GET /static/nocookies.html"
-                               "?force_close_session=yes HTTP/1.1");
+               StrBufPlain(ReqLine, 
+                           HKEY("/static/nocookies.html"
+                                "?force_close_session=yes"));
        }
 
        /**
@@ -499,7 +565,9 @@ void context_loop(int *sock)
                TheSession->vars = NULL;
                TheSession->nonce = rand();
                TheSession->WBuf = NULL;
+               TheSession->CLineBuf = NewStrBuf();
                TheSession->next = SessionList;
+               TheSession->is_mobile = -1;
                SessionList = TheSession;
                pthread_mutex_unlock(&SessionListMutex);
                session_is_new = 1;
@@ -527,7 +595,7 @@ void context_loop(int *sock)
        }
        go_selected_language();                                 /* set locale */
 #endif
-       session_loop(req);                                      /* do transaction */
+       session_loop(HTTPHeaders, ReqLine, ReqType, Buf);                               /* do transaction */
 #ifdef ENABLE_NLS
        stop_selected_language();                               /* unset locale */
 #endif
@@ -540,12 +608,10 @@ void context_loop(int *sock)
        pthread_mutex_unlock(&TheSession->SessionMutex);        /* unbind */
 
        /* Free the request buffer */
-       while (req != NULL) {
-               hptr = req->next;
-               free(req);
-               req = hptr;
-       }
-
+       DeleteHash(&HTTPHeaders);
+       FreeStrBuf(&ReqLine);
+       FreeStrBuf(&ReqType);
+       FreeStrBuf(&Buf);
        /*
         * Free up any session-local substitution variables which
         * were set during this transaction
index fd3082b7902ce587403b2f0c2f276df2da15b64c..e891bccc625f537fb0b21c550318bf4df13d5cbb 100644 (file)
@@ -46,7 +46,7 @@ void stuff_to_cookie(char *cookie, size_t clen, int session,
  * \param      len     the length of the string
  * \return     the corrosponding integer value
  */
-int xtoi(char *in, size_t len)
+int xtoi(const char *in, size_t len)
 {
        int val = 0;
        char c = 0;
@@ -77,18 +77,23 @@ int xtoi(char *in, size_t len)
  * \param room the room he is in
  * \param room_len the length of the room string
  */
-void cookie_to_stuff(char *cookie, int *session,
+void cookie_to_stuff(StrBuf *cookie, int *session,
                char *user, size_t user_len,
                char *pass, size_t pass_len,
                char *room, size_t room_len)
 {
+       const char *pch;
        char buf[SIZ];
        int i, len;
 
+       if (strncmp(ChrPtr(cookie), HKEY("webcit=")) == 0)
+               StrBufCutLeft(cookie, 7);
+
        strcpy(buf, "");
-       len = strlen(cookie) / 2;
+       len = StrLength(cookie) / 2;
+       pch = ChrPtr(cookie);
        for (i=0; i<len; ++i) {
-               buf[i] = xtoi(&cookie[i*2], 2);
+               buf[i] = xtoi(&pch[i*2], 2);
                buf[i+1] = 0;
        }
 
index 6d78acfa8c3ab9aadba61f6d1f8d0d45c7ffac9a..ffa628aeafb645f48db3502f936996be3f287720 100644 (file)
@@ -227,7 +227,7 @@ void init_ssl(void)
                                        X509_NAME_add_entry_by_txt(
                                                name, "OU",
                                                MBSTRING_ASC, 
-                                               (unsigned char*)"Citadel server",
+                                               (unsigned char*)"Citadel server1",
                                                -1, -1, 0);
 
                                        X509_NAME_add_entry_by_txt(
@@ -387,7 +387,7 @@ int starttls(int sock) {
                 * revert to unencrypted communications.
                 */
                long errval;
-               char *ssl_error_reason = NULL;
+               const char *ssl_error_reason = NULL;
 
                errval = SSL_get_error(newssl, retval);
                ssl_error_reason = ERR_reason_error_string(ERR_get_error());
@@ -400,7 +400,7 @@ int starttls(int sock) {
        }
        if (retval < 1) {
                long errval;
-               char *ssl_error_reason = NULL;
+               const char *ssl_error_reason = NULL;
 
                errval = SSL_get_error(newssl, retval);
                ssl_error_reason = ERR_reason_error_string(ERR_get_error());
@@ -411,16 +411,16 @@ int starttls(int sock) {
                SSL_free(newssl);
                newssl = NULL;
                return(4);
-       } else lprintf(3, "SSL_accept success\n");
+       } else lprintf(15, "SSL_accept success\n");
        BIO_set_close(newssl->rbio, BIO_NOCLOSE);
        bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(newssl), &alg_bits);
-       lprintf(5, "SSL/TLS using %s on %s (%d of %d bits)\n",
+       lprintf(15, "SSL/TLS using %s on %s (%d of %d bits)\n",
                SSL_CIPHER_get_name(SSL_get_current_cipher(newssl)),
                SSL_CIPHER_get_version(SSL_get_current_cipher(newssl)),
                bits, alg_bits);
 
        pthread_setspecific(ThreadSSL, newssl);
-       lprintf(3, "SSL started\n");
+       lprintf(15, "SSL started\n");
        return(0);
 }
 
@@ -438,7 +438,7 @@ void endtls(void)
 
        if (THREADSSL == NULL) return;
 
-       lprintf(5, "Ending SSL/TLS\n");
+       lprintf(15, "Ending SSL/TLS\n");
        SSL_shutdown(THREADSSL);
        ctx = SSL_get_SSL_CTX(THREADSSL);
 
@@ -524,7 +524,7 @@ void client_write_ssl(const StrBuf *Buf)
  * \param timeout how long should we wait?
  * \returns what???
  */
-int client_read_ssl(char *buf, int bytes, int timeout)
+int client_read_sslbuffer(StrBuf *buf, int timeout)
 {
 #if 0
        fd_set rfds;
@@ -532,13 +532,13 @@ int client_read_ssl(char *buf, int bytes, int timeout)
        int retval;
        int s;
 #endif
-       int len, rlen;
+       char sbuf[16384]; /**< Openssl communicates in 16k blocks, so lets speak its native tongue. */
+       int rlen;
        char junk[1];
 
        if (THREADSSL == NULL) return(0);
 
-       len = 0;
-       while (len < bytes) {
+       while (1) {
 #if 0
                /**
                 * This code is disabled because we don't need it when
@@ -562,7 +562,7 @@ int client_read_ssl(char *buf, int bytes, int timeout)
                                lprintf(9, "SSL_write in client_read\n");
                        }
                }
-               rlen = SSL_read(THREADSSL, &buf[len], bytes - len);
+               rlen = SSL_read(THREADSSL, sbuf, sizeof(sbuf));
                if (rlen < 1) {
                        long errval;
 
@@ -576,7 +576,8 @@ int client_read_ssl(char *buf, int bytes, int timeout)
                        endtls();
                        return (0);
                }
-               len += rlen;
+               StrBufAppendBufPlain(buf, sbuf, rlen, 0);
+               return(1);
        }
        return (1);
 }
index ac4af4337bc64904a9882d54358f982959868464..7ae90fbb301b688fa1db3119a4387e066764a2f1 100644 (file)
@@ -147,14 +147,14 @@ void fmt_time(char *buf, time_t thetime)
  * FIXME won't read asctime
  * Doesn't understand timezone, but we only should be using GMT/UTC anyway
  */
-time_t httpdate_to_timestamp(char *buf)
+time_t httpdate_to_timestamp(StrBuf *buf)
 {
        time_t t = 0;
        struct tm tt;
-       char *c;
+       const char *c;
 
        /** Skip day of week, to number */
-       for (c = buf; *c != ' '; c++)
+       for (c = ChrPtr(buf); *c != ' '; c++)
                ;
        c++;
        
index ea810deb32e925e44f0666b1c1489e62052110ff..2c12eff805a234ab306a70798d5d98329240d807 100644 (file)
@@ -51,7 +51,7 @@ typedef struct _lang_pref{
  * \param LocaleString the string from the browser http headers
  */
 
-void httplang_to_locale(char *LocaleString)
+void httplang_to_locale(StrBuf *LocaleString)
 {
        LangStruct wanted_locales[SEARCH_LANG];
        LangStruct *ls;
@@ -63,24 +63,32 @@ void httplang_to_locale(char *LocaleString)
        int av;
        int nBest;
        int nParts;
-       char search[1024];
+       StrBuf *Buf = NULL;
+       StrBuf *SBuf;
        
-       safestrncpy(search, LocaleString, sizeof search);
-       nParts=num_tokens(search,',');
+       nParts=StrBufNum_tokens(LocaleString,',');
        for (i=0; ((i<nParts)&&(i<SEARCH_LANG)); i++)
         {
-                       char buf[16];
                        char sbuf[16];
                        char lbuf[16];
                        int blen;
                        
+                       if (Buf == NULL) {
+                               Buf = NewStrBuf();
+                               SBuf = NewStrBuf();
+                       }
+                       else {
+                               FlushStrBuf(Buf);
+                               FlushStrBuf(SBuf);
+                       }
+
                        ls=&wanted_locales[i];
 
-                       extract_token(&buf[0],search, i,',',16);
+                       StrBufExtract_token(Buf,LocaleString, i,',');
                        /** we are searching, if this list item has something like ;q=n*/
-                       if (num_tokens(&buf[0],'=')>1) {
+                       if (StrBufNum_tokens(Buf,'=')>1) {
                                int sbuflen, k;
-                               extract_token(&sbuf[0],&buf[0], 1,'=',16);
+                               StrBufExtract_token(SBuf,Buf, 1,'=');
                                sbuflen=strlen(&sbuf[0]);
                                for (k=0; k<sbuflen; k++) if (sbuf[k]=='.') sbuf[k]='0';
                                ls->priority=atol(&sbuf[0]);
@@ -89,12 +97,12 @@ void httplang_to_locale(char *LocaleString)
                                ls->priority=1000;
                        }
                        /** get the locale part */
-                       extract_token(&sbuf[0],&buf[0],0,';',16);
+                       StrBufExtract_token(SBuf ,Buf, 0, ';');
                        /** get the lang part, which should be allways there */
-                       extract_token(&ls->lang[0],&sbuf[0],0,'-',16);
+                       extract_token(&ls->lang[0], ChrPtr(SBuf), 0, '-', 16);
                        /** get the area code if any. */
-                       if (num_tokens(&sbuf[0],'-')>1) {
-                               extract_token(&ls->region[0],&sbuf[0],1,'-',16);
+                       if (StrBufNum_tokens(SBuf,'-') > 1) {
+                               extract_token(&ls->region[0],ChrPtr(SBuf),1,'-',16);
                        }
                        else { /** no ara code? use lang code */
                                blen=strlen(&ls->lang[0]);
@@ -149,6 +157,8 @@ void httplang_to_locale(char *LocaleString)
        }
        WC->selected_language=nBest;
        lprintf(9, "language found: %s\n", AvailLangLoaded[WC->selected_language]);
+       FreeStrBuf(&Buf);
+       FreeStrBuf(&SBuf);
 }
 
 /* TODO: we skip the language weighting so far. */
index be896646c9d0376e45800f0f2212b9c65e908b24..42709a5b795a9d4ade63cd4fa208638ecf8c0930 100644 (file)
@@ -14,12 +14,20 @@ struct epdata {
 
 
 void groupdav_common_headers(void);
-void groupdav_main(struct httprequest *, char *, int, char *);
-void groupdav_get(char *);
-void groupdav_put(char *, char *, char *, char *, int);
-void groupdav_delete(char *, char *);
-void groupdav_propfind(char *, int, char *, char *);
-void groupdav_options(char *);
+void groupdav_main(HashList *HTTPHeaders,
+                  StrBuf *DavPathname,
+                  StrBuf *DavMethod,
+                  StrBuf *dav_content_type,
+                  int dav_content_length,
+                  StrBuf *dav_content,
+                  int Offset);
+void groupdav_get(const char *dav_pathname);
+void groupdav_put(const char *dav_pathname, char *dav_ifmatch,
+                 const char *dav_content_type, StrBuf *dav_content,
+                 int offset);
+void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch);
+void groupdav_propfind(const char *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset);
+void groupdav_options(const char *dav_pathname);
 long locate_message_by_uid(char *);
 void groupdav_folder_list(void);
 void euid_escapize(char *, char *);
index 8aa9f3b57cd0a85f2162299ba7782cf34cc788b7..2a76687b1e811fde160cf17ef9309a9d81a570f0 100644 (file)
@@ -13,7 +13,7 @@
 /*
  * The pathname is always going to be /groupdav/room_name/euid
  */
-void groupdav_delete(char *dav_pathname, char *dav_ifmatch) {
+void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch) {
        char dav_roomname[SIZ];
        char dav_uid[SIZ];
        long dav_msgnum = (-1);
@@ -22,20 +22,20 @@ void groupdav_delete(char *dav_pathname, char *dav_ifmatch) {
        int len;
 
        /* First, break off the "/groupdav/" prefix */
-       remove_token(dav_pathname, 0, '/');
-       remove_token(dav_pathname, 0, '/');
+       StrBufRemove_token(dav_pathname, 0, '/');
+       StrBufRemove_token(dav_pathname, 0, '/');
 
        /* Now extract the message euid */
-       n = num_tokens(dav_pathname, '/');
-       extract_token(dav_uid, dav_pathname, n-1, '/', sizeof dav_uid);
-       remove_token(dav_pathname, n-1, '/');
+       n = StrBufNum_tokens(dav_pathname, '/');
+       extract_token(dav_uid, ChrPtr(dav_pathname), n-1, '/', sizeof dav_uid);
+       StrBufRemove_token(dav_pathname, n-1, '/');
 
        /* What's left is the room name.  Remove trailing slashes. */
-       len = strlen(dav_pathname);
-       if (dav_pathname[len-1] == '/') {
-               dav_pathname[len-1] = 0;
+       len = StrLength(dav_pathname);
+       if ((len > 0) && (ChrPtr(dav_pathname)[len-1] == '/')) {
+               StrBufCutRight(dav_pathname, 1);
        }
-       strcpy(dav_roomname, dav_pathname);
+       strcpy(dav_roomname, ChrPtr(dav_pathname));
 
        /* Go to the correct room. */
        if (strcasecmp(WC->wc_roomname, dav_roomname)) {
index 02d4ea26b2d91f19bcdad55d4e623413ea01c8d0..928a5669b947695fa15f561e374cd7f2ac6720a3 100644 (file)
@@ -86,7 +86,7 @@ void extract_preferred(char *name, char *filename, char *partnum, char *disp,
  * /groupdav/room_name/euid    (GroupDAV)
  * /groupdav/room_name         (webcal)
  */
-void groupdav_get(char *dav_pathname) {
+void groupdav_get(const char *dav_pathname) {
        char dav_roomname[1024];
        char dav_uid[1024];
        long dav_msgnum = (-1);
index b03650b77ed07e7092526ff4612dee6e390fb357..9d43f7ff38308ad4d9896c9dac202f898138b0b5 100644 (file)
@@ -84,46 +84,45 @@ void euid_unescapize(char *target, char *source) {
 /*
  * Main entry point for GroupDAV requests
  */
-void groupdav_main(struct httprequest *req,
-                       char *dav_content_type,
-                       int dav_content_length,
-                       char *dav_content
+void groupdav_main(HashList *HTTPHeaders,
+                  StrBuf *DavPathname,
+                  StrBuf *DavMethod,
+                  StrBuf *dav_content_type,
+                  int dav_content_length,
+                  StrBuf *dav_content,
+                  int Offset
 ) {
-       struct httprequest *rptr;
-       char dav_method[256];
-       char dav_pathname[256];
+       void *vLine;
        char dav_ifmatch[256];
        int dav_depth;
        char *ds;
        int i, len;
 
-       strcpy(dav_method, "");
-       strcpy(dav_pathname, "");
        strcpy(dav_ifmatch, "");
        dav_depth = 0;
 
-       for (rptr=req; rptr!=NULL; rptr=rptr->next) {
-               if (!strncasecmp(rptr->line, "Host: ", 6)) {
-                       if (IsEmptyStr(WC->http_host)) {
-                               safestrncpy(WC->http_host, &rptr->line[6],
-                                       sizeof WC->http_host);
-                       }
-                }
-               if (!strncasecmp(rptr->line, "If-Match: ", 10)) {
-                        safestrncpy(dav_ifmatch, &rptr->line[10],
-                               sizeof dav_ifmatch);
-                }
-               if (!strncasecmp(rptr->line, "Depth: ", 7)) {
-                       if (!strcasecmp(&rptr->line[7], "infinity")) {
-                               dav_depth = 32767;
-                       }
-                       else if (!strcmp(&rptr->line[7], "0")) {
-                               dav_depth = 0;
-                       }
-                       else if (!strcmp(&rptr->line[7], "1")) {
-                               dav_depth = 1;
-                       }
-                }
+       if (IsEmptyStr(WC->http_host) &&
+           GetHash(HTTPHeaders, HKEY("HOST"), &vLine) && 
+           (vLine != NULL)) {
+               safestrncpy(WC->http_host, ChrPtr((StrBuf*)vLine),
+                           sizeof WC->http_host);
+       }
+       if (GetHash(HTTPHeaders, HKEY("IF-MATCH"), &vLine) && 
+           (vLine != NULL)) {
+               safestrncpy(dav_ifmatch, ChrPtr((StrBuf*)vLine),
+                           sizeof dav_ifmatch);
+       }
+       if (GetHash(HTTPHeaders, HKEY("DEPTH"), &vLine) && 
+           (vLine != NULL)) {
+               if (!strcasecmp(ChrPtr((StrBuf*)vLine), "infinity")) {
+                       dav_depth = 32767;
+               }
+               else if (strcmp(ChrPtr((StrBuf*)vLine), "0") == 0) {
+                       dav_depth = 0;
+               }
+               else if (strcmp(ChrPtr((StrBuf*)vLine), "1") == 0) {
+                       dav_depth = 1;
+               }
        }
 
        if (!WC->logged_in) {
@@ -136,9 +135,9 @@ void groupdav_main(struct httprequest *req,
                return;
        }
 
-       extract_token(dav_method, req->line, 0, ' ', sizeof dav_method);
-       extract_token(dav_pathname, req->line, 1, ' ', sizeof dav_pathname);
-       unescape_input(dav_pathname);
+//     extract_token(dav_method, req->line, 0, ' ', sizeof dav_method);
+//     extract_token(dav_pathname, req->line, 1, ' ', sizeof dav_pathname);
+       //// TODO unescape_input(dav_pathname);
 
        /* If the request does not begin with "/groupdav", prepend it.  If
         * we happen to introduce a double-slash, that's ok; we'll strip it
@@ -155,7 +154,7 @@ void groupdav_main(struct httprequest *req,
         */
        
        /* Remove any stray double-slashes in pathname */
-       while (ds=strstr(dav_pathname, "//"), ds != NULL) {
+       while (ds=strstr(ChrPtr(DavPathname), "//"), ds != NULL) {
                strcpy(ds, ds+1);
        }
 
@@ -186,8 +185,8 @@ void groupdav_main(struct httprequest *req,
         * experiment to determine what might be involved in supporting
         * other variants of DAV in the future.
         */
-       if (!strcasecmp(dav_method, "OPTIONS")) {
-               groupdav_options(dav_pathname);
+       if (!strcasecmp(ChrPtr(DavMethod), "OPTIONS")) {
+               groupdav_options(ChrPtr(DavPathname));
                return;
        }
 
@@ -195,35 +194,36 @@ void groupdav_main(struct httprequest *req,
         * The PROPFIND method is basically used to list all objects in a
         * room, or to list all relevant rooms on the server.
         */
-       if (!strcasecmp(dav_method, "PROPFIND")) {
-               groupdav_propfind(dav_pathname, dav_depth,
-                               dav_content_type, dav_content);
+       if (!strcasecmp(ChrPtr(DavMethod), "PROPFIND")) {
+               groupdav_propfind(ChrPtr(DavPathname), dav_depth,
+                                 dav_content_type, dav_content, 
+                                 Offset);
                return;
        }
 
        /*
         * The GET method is used for fetching individual items.
         */
-       if (!strcasecmp(dav_method, "GET")) {
-               groupdav_get(dav_pathname);
+       if (!strcasecmp(ChrPtr(DavMethod), "GET")) {
+               groupdav_get(ChrPtr(DavPathname));
                return;
        }
 
        /*
         * The PUT method is used to add or modify items.
         */
-       if (!strcasecmp(dav_method, "PUT")) {
-               groupdav_put(dav_pathname, dav_ifmatch,
-                               dav_content_type, dav_content,
-                               dav_content_length);
+       if (!strcasecmp(ChrPtr(DavMethod), "PUT")) {
+               groupdav_put(ChrPtr(DavPathname), dav_ifmatch,
+                            ChrPtr(dav_content_type), dav_content, 
+                            Offset);
                return;
        }
 
        /*
         * The DELETE method kills, maims, and destroys.
         */
-       if (!strcasecmp(dav_method, "DELETE")) {
-               groupdav_delete(dav_pathname, dav_ifmatch);
+       if (!strcasecmp(ChrPtr(DavMethod), "DELETE")) {
+               groupdav_delete(DavPathname, dav_ifmatch);
                return;
        }
 
@@ -234,7 +234,7 @@ void groupdav_main(struct httprequest *req,
        groupdav_common_headers();
        hprintf("Content-Type: text/plain\r\n");
        wprintf("GroupDAV method \"%s\" is not implemented.\r\n",
-               dav_method);
+               ChrPtr(DavMethod));
        end_burst();
 }
 
index ac902331c167b4af101b0e69ea3c2778deba1093..366f5ffe3ce580a6e3fe76766f252838f05c586e 100644 (file)
@@ -12,7 +12,7 @@
 /*
  * The pathname is always going to be /groupdav/room_name/msg_num
  */
-void groupdav_options(char *dav_pathname) {
+void groupdav_options(const char *dav_pathname) {
        char dav_roomname[256];
        char dav_uid[256];
        long dav_msgnum = (-1);
index f9b2ce0d71d7c22b8b4ba3d99400f5f454b45078..6da1f0e851585a1ddd0905b95098ccc1223ac4af 100644 (file)
@@ -62,7 +62,7 @@ long locate_message_by_uid(char *uid) {
  * List rooms (or "collections" in DAV terminology) which contain
  * interesting groupware objects.
  */
-void groupdav_collection_list(char *dav_pathname, int dav_depth)
+void groupdav_collection_list(const char *dav_pathname, int dav_depth)
 {
        char buf[256];
        char roomname[256];
@@ -227,7 +227,7 @@ void groupdav_collection_list(char *dav_pathname, int dav_depth)
 /*
  * The pathname is always going to be /groupdav/room_name/msg_num
  */
-void groupdav_propfind(char *dav_pathname, int dav_depth, char *dav_content_type, char *dav_content) {
+void groupdav_propfind(const char *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset) {
        char dav_roomname[256];
        char dav_uid[256];
        char msgnum[256];
index b69114c2fb71a253ade4678b905485a6e43cce07..cbb37f3853bba02ad57fbd738f7313a252842648 100644 (file)
@@ -15,7 +15,7 @@
  * component.  This would be for webcal:// 'publish' operations, not
  * for GroupDAV.
  */
-void groupdav_put_bigics(char *dav_content, int dav_content_length)
+void groupdav_put_bigics(StrBuf *dav_content, int offset)
 {
        char buf[1024];
 
@@ -37,7 +37,7 @@ void groupdav_put_bigics(char *dav_content, int dav_content_length)
                return;
        }
 
-       serv_write(dav_content, dav_content_length);
+       serv_write(ChrPtr(dav_content) + offset, StrLength(dav_content) - offset);
        serv_printf("\n000");
 
        /* Report success and not much else. */
@@ -54,10 +54,10 @@ void groupdav_put_bigics(char *dav_content, int dav_content_length)
  * /groupdav/room_name/euid    (GroupDAV)
  * /groupdav/room_name         (webcal)
  */
-void groupdav_put(char *dav_pathname, char *dav_ifmatch,
-               char *dav_content_type, char *dav_content,
-               int dav_content_length
-{
+void groupdav_put(const char *dav_pathname, char *dav_ifmatch,
+                 const char *dav_content_type, StrBuf *dav_content,
+                 int offset) 
+{
        char dav_roomname[1024];
        char dav_uid[1024];
        long new_msgnum = (-2L);
@@ -119,7 +119,7 @@ void groupdav_put(char *dav_pathname, char *dav_ifmatch,
        /** PUT on the collection itself uploads an ICS of the entire collection.
         */
        if (!strcasecmp(dav_uid, "")) {
-               groupdav_put_bigics(dav_content, dav_content_length);
+               groupdav_put_bigics(dav_content, offset);
                return;
        }
 
@@ -142,7 +142,7 @@ void groupdav_put(char *dav_pathname, char *dav_ifmatch,
 
        /* Send the content to the Citadel server */
        serv_printf("Content-type: %s\n\n", dav_content_type);
-       serv_puts(dav_content);
+       serv_puts(ChrPtr(dav_content) + offset);
        serv_puts("\n000");
 
        /* Fetch the reply from the Citadel server */
index fb6cb59267567c397f7a14221c8f6261df62994a..696ed019cc19773c02730dc62c4d2514c4db8abe 100644 (file)
@@ -47,7 +47,7 @@ void display_rss_control(char *reply_to, char *subject)
  * \param roomname the room we sould print out as rss 
  * \param request_method the way the rss is requested????
  */
-void display_rss(char *roomname, char *request_method)
+void display_rss(char *roomname, StrBuf *request_method)
 {
        int nummsgs;
        int a, b;
@@ -146,7 +146,7 @@ void display_rss(char *roomname, char *request_method)
        hprintf("Content-Type: application/rss+xml\r\n");
        hprintf("Server: %s\r\n", PACKAGE_STRING);
        hprintf("Connection: close\r\n");
-       if (!strcasecmp(request_method, "HEAD"))
+       if (!strcasecmp(ChrPtr(request_method), "HEAD"))
                return;
 
        /* <?xml.. etc confuses our subst parser, so do it here */
index bcdb8e9477c0c4f3582b4caf07c3ef01f57b14ed..20b9342e2943e055232eb63b0f3378ff15e7c6a0 100644 (file)
@@ -1213,7 +1213,6 @@ void begin_ajax_response(void) {
  * print ajax response footer 
  */
 void end_ajax_response(void) {
-        ///hprintf("\r\n");///// todo: is this right?
         wDumpContent(0);
 }
 
@@ -1320,22 +1319,20 @@ int is_mobile_ua(char *user_agent) {
 /*
  * Entry point for WebCit transaction
  */
-void session_loop(struct httprequest *req)
+void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method, StrBuf *ReadBuf)
 {
-       char cmd[1024];
+       const char *pch, *pchs, *pche;
+       void *vLine;
        char action[1024];
        char arg[8][128];
        size_t sizes[10];
        char *index[10];
        char buf[SIZ];
-       char request_method[128];
-       char pathname[1024];
-       int a, b, nBackDots, nEmpty;
+       int a, nBackDots, nEmpty;
        int ContentLength = 0;
-       char ContentType[512];
-       char *content = NULL;
-       char *content_end = NULL;
-       struct httprequest *hptr;
+       StrBuf *ContentType, *UrlLine;
+       StrBuf *content = NULL;
+       const char *content_end = NULL;
        char browser_host[256];
        char user_agent[256];
        int body_start = 0;
@@ -1352,7 +1349,6 @@ void session_loop(struct httprequest *req)
        char c_httpauth_string[SIZ];
        char c_httpauth_user[SIZ];
        char c_httpauth_pass[SIZ];
-       char cookie[SIZ];
        struct wcsession *WCC;
        
        safestrncpy(c_username, "", sizeof c_username);
@@ -1376,14 +1372,6 @@ void session_loop(struct httprequest *req)
        WCC->upload = NULL;
        WCC->is_mobile = 0;
 
-       hptr = req;
-       if (hptr == NULL) return;
-
-       safestrncpy(cmd, hptr->line, sizeof cmd);
-       hptr = hptr->next;
-       extract_token(request_method, cmd, 0, ' ', sizeof request_method);
-       extract_token(pathname, cmd, 1, ' ', sizeof pathname);
-
        /** Figure out the action */
        index[0] = action;
        sizes[0] = sizeof action;
@@ -1397,7 +1385,7 @@ void session_loop(struct httprequest *req)
        nEmpty = 0;
        for ( a = 0; a < 9; ++a)
        {
-               extract_token(index[a], pathname, a + 1, '/', sizes[a]);
+               extract_token(index[a], ChrPtr(ReqLine), a + 1, '/', sizes[a]);
                if (strstr(index[a], "?")) *strstr(index[a], "?") = 0;
                if (strstr(index[a], "&")) *strstr(index[a], "&") = 0;
                if (strstr(index[a], " ")) *strstr(index[a], " ") = 0;
@@ -1407,113 +1395,109 @@ void session_loop(struct httprequest *req)
                        nEmpty++;
        }
 
-       while (hptr != NULL) {
-               safestrncpy(buf, hptr->line, sizeof buf);
-               /* lprintf(9, "HTTP HEADER: %s\n", buf); */
-               hptr = hptr->next;
 
-               if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
-                       safestrncpy(cookie, &buf[15], sizeof cookie);
-                       cookie_to_stuff(cookie, NULL,
-                                       c_username, sizeof c_username,
-                                       c_password, sizeof c_password,
-                                       c_roomname, sizeof c_roomname);
-               }
-               else if (!strncasecmp(buf, "Authorization: Basic ", 21)) {
-                       CtdlDecodeBase64(c_httpauth_string, &buf[21], strlen(&buf[21]));
-                       extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user);
-                       extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass);
-               }
-               else if (!strncasecmp(buf, "Content-length: ", 16)) {
-                       ContentLength = atoi(&buf[16]);
-               }
-               else if (!strncasecmp(buf, "Content-type: ", 14)) {
-                       safestrncpy(ContentType, &buf[14], sizeof ContentType);
-               }
-               else if (!strncasecmp(buf, "User-agent: ", 12)) {
-                       safestrncpy(user_agent, &buf[12], sizeof user_agent);
-                       #ifdef TECH_PREVIEW
-                       if (is_mobile_ua(&buf[12])) {
-                               WCC->is_mobile = 1;
-                       }
-                       #endif
-               }
-               else if (!strncasecmp(buf, "X-Forwarded-Host: ", 18)) {
-                       if (follow_xff) {
-                               safestrncpy(WCC->http_host, &buf[18], sizeof WCC->http_host);
-                       }
+       if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && 
+           (vLine != NULL)){
+               cookie_to_stuff((StrBuf *)vLine, NULL,
+                               c_username, sizeof c_username,
+                               c_password, sizeof c_password,
+                               c_roomname, sizeof c_roomname);
+       }
+       if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) &&
+           (vLine!=NULL)) {
+               CtdlDecodeBase64(c_httpauth_string, ChrPtr((StrBuf*)vLine), StrLength((StrBuf*)vLine));
+               extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user);
+               extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass);
+       }
+       if (GetHash(HTTPHeaders, HKEY("CONTENT-LENGTH"), &vLine) &&
+           (vLine!=NULL)) {
+               ContentLength = StrToi((StrBuf*)vLine);
+       }
+       if (GetHash(HTTPHeaders, HKEY("CONTENT-TYPE"), &vLine) &&
+           (vLine!=NULL)) {
+               ContentType = (StrBuf*)vLine;
+       }
+       if (GetHash(HTTPHeaders, HKEY("USER-AGENT"), &vLine) &&
+           (vLine!=NULL)) {
+               safestrncpy(user_agent, ChrPtr((StrBuf*)vLine), sizeof user_agent);
+#ifdef TECH_PREVIEW
+               if ((WCC->is_mobile < 0) && is_mobile_ua(&buf[12])) {                   
+                       WCC->is_mobile = 1;
                }
-               else if (!strncasecmp(buf, "Host: ", 6)) {
-                       if (IsEmptyStr(WCC->http_host)) {
-                               safestrncpy(WCC->http_host, &buf[6], sizeof WCC->http_host);
-                       }
+               else {
+                       WCC->is_mobile = 0;
                }
-               else if (!strncasecmp(buf, "X-Forwarded-For: ", 17)) {
-                       safestrncpy(browser_host, &buf[17], sizeof browser_host);
-                       while (num_tokens(browser_host, ',') > 1) {
-                               remove_token(browser_host, 0, ',');
-                       }
-                       striplt(browser_host);
+#endif
+       }
+       if ((follow_xff) &&
+           GetHash(HTTPHeaders, HKEY("X-FORWARDED-HOST"), &vLine) &&
+           (vLine != NULL)) {
+               safestrncpy(WCC->http_host, &buf[18], sizeof WCC->http_host);
+       }
+       if (IsEmptyStr(WCC->http_host) && 
+           GetHash(HTTPHeaders, HKEY("HOST"), &vLine) &&
+           (vLine!=NULL)) {
+               safestrncpy(WCC->http_host, 
+                           ChrPtr((StrBuf*)vLine), 
+                           sizeof WCC->http_host);
+               
+       }
+       if (GetHash(HTTPHeaders, HKEY("X-FORWARDED-FOR"), &vLine) &&
+           (vLine!=NULL)) {
+               safestrncpy(browser_host, 
+                           ChrPtr((StrBuf*) vLine), 
+                           sizeof browser_host);
+               while (num_tokens(browser_host, ',') > 1) {
+                       remove_token(browser_host, 0, ',');
                }
+               striplt(browser_host);
        }
 
        if (ContentLength > 0) {
-               int BuffSize;
-
-               BuffSize = ContentLength + SIZ;
-               content = malloc(BuffSize);
-               memset(content, 0, BuffSize);
-               snprintf(content,  BuffSize, "Content-type: %s\n"
+               content = NewStrBuf();
+               StrBufPrintf(content, "Content-type: %s\n"
                         "Content-length: %d\n\n",
-                        ContentType, ContentLength);
+                        ChrPtr(ContentType), ContentLength);
 /*
                hprintf("Content-type: %s\n"
                        "Content-length: %d\n\n",
                        ContentType, ContentLength);
 */
-               body_start = strlen(content);
+               body_start = StrLength(content);
 
                /** Read the entire input data at once. */
-               client_read(&WCC->http_sock, &content[body_start], ContentLength);
-
-               if (!strncasecmp(ContentType, "application/x-www-form-urlencoded", 33)) {
-                       StrBuf *Content;
-
-                       Content = _NewConstStrBuf(&content[body_start],ContentLength);
-                       addurls(Content);
-                       FreeStrBuf(&Content);
-               } else if (!strncasecmp(ContentType, "multipart", 9)) {
-                       content_end = content + ContentLength + body_start;
-                       mime_parser(content, content_end, *upload_handler, NULL, NULL, NULL, 0);
+               client_read(&WCC->http_sock, content, ReadBuf, ContentLength);
+
+               if (!strncasecmp(ChrPtr(ContentType), "application/x-www-form-urlencoded", 33)) {
+                       StrBufCutLeft(content, body_start);
+                       addurls(content);
+               } else if (!strncasecmp(ChrPtr(ContentType), "multipart", 9)) {
+                       content_end = ChrPtr(content) + ContentLength + body_start;
+                       mime_parser(ChrPtr(content), content_end, *upload_handler, NULL, NULL, NULL, 0);
                }
        } else {
                content = NULL;
        }
 
        /* make a note of where we are in case the user wants to save it */
-       safestrncpy(WCC->this_page, cmd, sizeof(WCC->this_page));
+       safestrncpy(WCC->this_page, ChrPtr(ReqLine), sizeof(WCC->this_page));
        remove_token(WCC->this_page, 2, ' ');
        remove_token(WCC->this_page, 0, ' ');
 
        /* If there are variables in the URL, we must grab them now */
-       len = strlen(cmd);
-       for (a = 0; a < len; ++a) {
-               if ((cmd[a] == '?') || (cmd[a] == '&')) {
-                       StrBuf *Params;
-                       for (b = a; b < len; ++b) {
-                               if (isspace(cmd[b])){
-                                       cmd[b] = 0;
-                                       len = b - 1;
-                               }
-                       }
-                       //cmd[len - a] = '\0';
-                       Params = _NewConstStrBuf(&cmd[a + 1], len - a);
-                       addurls(Params);
-                       FreeStrBuf(&Params);
-                       cmd[a] = 0;
-                       len = a - 1;
+       UrlLine = NewStrBufDup(ReqLine);
+       len = StrLength(UrlLine);
+       pch = pchs = ChrPtr(UrlLine);
+       pche = pchs + len;
+       while (pch < pche) {
+               if ((*pch == '?') || (*pch == '&')) {
+                       StrBufCutLeft(UrlLine, pch - pchs + 1);
+                       addurls(UrlLine);
+                       break;
                }
+               pch ++;
        }
+       FreeStrBuf(&UrlLine);
 
        /* If it's a "force 404" situation then display the error and bail. */
        if (!strcmp(action, "404")) {
@@ -1526,7 +1510,7 @@ void session_loop(struct httprequest *req)
 
        /* Static content can be sent without connecting to Citadel. */
        is_static = 0;
-       for (a=0; a<ndirs; ++a) {
+       for (a=0; a<ndirs && ! is_static; ++a) {
                if (!strcasecmp(action, (char*)static_content_dirs[a])) { /* map web to disk location */
                        is_static = 1;
                        n_static = a;
@@ -1625,7 +1609,7 @@ void session_loop(struct httprequest *req)
                        }
                }
        }
-////////todo: restorte language in this case
+////////todo: restore language in this case
        /*
         * Functions which can be performed without logging in
         */
@@ -1634,7 +1618,7 @@ void session_loop(struct httprequest *req)
                goto SKIP_ALL_THIS_CRAP;
        }
        if (!strcasecmp(action, "freebusy")) {
-               do_freebusy(cmd);
+               do_freebusy(ChrPtr(ReqLine));
                goto SKIP_ALL_THIS_CRAP;
        }
 
@@ -1676,8 +1660,10 @@ void session_loop(struct httprequest *req)
         * our session's authentication.
         */
        if (!strncasecmp(action, "groupdav", 8)) {
-               groupdav_main(req, ContentType, /* do GroupDAV methods */
-                       ContentLength, content+body_start);
+               groupdav_main(HTTPHeaders, 
+                             ReqLine, request_method,
+                             ContentType, /* do GroupDAV methods */
+                             ContentLength, content, body_start);
                if (!WCC->logged_in) {
                        WCC->killthis = 1;      /* If not logged in, don't */
                }                               /* keep the session active */
@@ -1689,9 +1675,10 @@ void session_loop(struct httprequest *req)
         * Automatically send requests with any method other than GET or
         * POST to the GroupDAV code as well.
         */
-       if ((strcasecmp(request_method, "GET")) && (strcasecmp(request_method, "POST"))) {
-               groupdav_main(req, ContentType, /** do GroupDAV methods */
-                       ContentLength, content+body_start);
+       if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) {
+               groupdav_main(HTTPHeaders, ReqLine, 
+                             request_method, ContentType, /** do GroupDAV methods */
+                             ContentLength, content, body_start);
                if (!WCC->logged_in) {
                        WCC->killthis = 1;      /** If not logged in, don't */
                }                               /** keep the session active */
@@ -1774,7 +1761,7 @@ void session_loop(struct httprequest *req)
 SKIP_ALL_THIS_CRAP:
        fflush(stdout);
        if (content != NULL) {
-               free(content);
+               FreeStrBuf(&content);
                content = NULL;
        }
        free_urls();
index 5d678c3f6b098835c2932ccbeae8563b5502e579..8805d0aa88a4e5c55c8338215928cf69d23a28e4 100644 (file)
@@ -196,12 +196,6 @@ extern locale_t wc_locales[];
 #define NLI    "(not logged in)"
 
 
-/** \brief     Linked list of lines appearing in an HTTP client request */
-struct httprequest {
-       struct httprequest *next;  /**< the next request in the list */
-       char line[SIZ];            /**< the request line */
-};
-
 /**
  * \brief      Linked list of session variables encoded in an x-www-urlencoded content type
  */
@@ -470,6 +464,7 @@ struct wcsession {
        StrBuf *UrlFragment2;                   /**< second urlfragment, if NEED_URL is specified by the handler*/
        StrBuf *WBuf;                           /**< Our output buffer */
        StrBuf *HBuf;                           /**< Our HeaderBuffer */
+       StrBuf *CLineBuf;                       /**< linebuffering client stuff */
 
        HashList *ServCfg;                      /**< cache our server config for editing */
        HashList *InetCfg;                      /**< Our inet server config for editing */
@@ -534,7 +529,7 @@ void end_critical_section(int which_one);
 
 void stuff_to_cookie(char *cookie, size_t clen, int session,
                        char *user, char *pass, char *room);
-void cookie_to_stuff(char *cookie, int *session,
+void cookie_to_stuff(StrBuf *cookie, int *session,
                 char *user, size_t user_len,
                 char *pass, size_t pass_len,
                 char *room, size_t room_len);
@@ -652,11 +647,11 @@ void shutdown_sessions(void);
 void do_housekeeping(void);
 void smart_goto(char *);
 void worker_entry(void);
-void session_loop(struct httprequest *);
+void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *ReqType, StrBuf *ReadBuf);
 size_t wc_strftime(char *s, size_t max, const char *format, const struct tm *tm);
 void fmt_time(char *buf, time_t thetime);
 void httpdate(char *buf, time_t thetime);
-time_t httpdate_to_timestamp(char *buf);
+time_t httpdate_to_timestamp(StrBuf *buf);
 void end_webcit_session(void);
 void page_popup(void);
 void http_redirect(const char *);
@@ -771,7 +766,7 @@ void ical_dezonify(icalcomponent *cal);
 void partstat_as_string(char *buf, icalproperty *attendee);
 icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp);
 void check_attendee_availability(icalcomponent *supplied_vevent);
-void do_freebusy(char *req);
+void do_freebusy(const char *req);
 int ical_ctdl_is_overlap(
                         struct icaltimetype t1start,
                         struct icaltimetype t1end,
@@ -798,13 +793,13 @@ long unescape_input(char *buf);
 void do_selected_iconbar(void);
 int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen);
 void spawn_another_worker_thread(void);
-void display_rss(char *roomname, char *request_method);
+void display_rss(char *roomname, StrBuf *request_method);
 void offer_languages(void);
 void set_selected_language(const char *);
 void go_selected_language(void);
 void stop_selected_language(void);
 void preset_locale(void);
-void httplang_to_locale(char *LocaleString);
+void httplang_to_locale(StrBuf *LocaleString);
 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[]);
@@ -813,7 +808,7 @@ void begin_tab(int tabnum, int num_tabs);
 void end_tab(int tabnum, int num_tabs);
 void str_wiki_index(char *s);
 int get_time_format_cached (void);
-int xtoi(char *in, size_t len);
+int xtoi(const char *in, size_t len);
 void webcit_fmt_date(char *buf, time_t thetime, int brief);
 int fetch_http(char *url, char *target_buf, int maxbytes);
 
@@ -838,7 +833,7 @@ void endtls(void);
 void ssl_lock(int mode, int n, const char *file, int line);
 int starttls(int sock);
 extern SSL_CTX *ssl_ctx;  
-int client_read_ssl(char *buf, int bytes, int timeout);
+int client_read_sslbuffer(StrBuf *buf, int timeout);
 void client_write_ssl(const StrBuf *Buf);
 #endif
 
index 8f04c224f67245f5596242d222203af7308a2141..d8bd340055ace45cb0d077c96e35b3561254b2a3 100644 (file)
@@ -196,43 +196,38 @@ int ig_uds_server(char *sockpath, int queue_len)
  *      0       Request timed out.
  *     -1      Connection is broken, or other error.
  */
-int client_read_to(int *sock, char *buf, int bytes, int timeout)
+int client_read_to(int *sock, StrBuf *Target, StrBuf *Buf, int bytes, int timeout)
 {
-       int len, rlen;
-       fd_set rfds;
-       struct timeval tv;
-       int retval;
-
+       const char *Error;
+       int retval = 0;
 
 #ifdef HAVE_OPENSSL
        if (is_https) {
-               return (client_read_ssl(buf, bytes, timeout));
-       }
-#endif
+               while ((retval >= 0) && (StrLength(Buf) < bytes))
+                       retval = client_read_sslbuffer(Buf, timeout);
+               if (retval >= 0) {
+                       StrBufAppendBuf(Target, Buf, 0); /// todo: Buf > bytes?
 
-       len = 0;
-       while ((len < bytes) && (*sock > 0)) {
-               FD_ZERO(&rfds);
-               FD_SET(*sock, &rfds);
-               tv.tv_sec = timeout;
-               tv.tv_usec = 0;
-
-               retval = select((*sock) + 1, &rfds, NULL, NULL, &tv);
-               if (FD_ISSET(*sock, &rfds) == 0) {
-                       return (0);
                }
-
-               rlen = read(*sock, &buf[len], bytes - len);
-
-               if (rlen < 1) {
-                       lprintf(2, "client_read() failed: %s\n",
-                               strerror(errno));
-                       if (*sock > 0)
-                               close(*sock);
-                       *sock = -1;     
-                       return (-1);
+               else {
+                       lprintf(2, "client_read_ssl() failed\n");
+                       return -1;
                }
-               len = len + rlen;
+       }
+#endif
+
+       if (StrLength(Buf) > 0) {//// todo: what if Buf > bytes?
+               StrBufAppendBuf(Target, Buf, 0);
+       }
+       retval = StrBufReadBLOB(Target, 
+                          sock, 
+                          (StrLength(Target) > 0), 
+                          bytes - StrLength(Target), 
+                               &Error);
+       if (retval < 0) {
+               lprintf(2, "client_read() failed: %s\n",
+                       Error);
+               return retval;
        }
 
 #ifdef HTTP_TRACING
@@ -364,9 +359,9 @@ long end_burst(void)
  * buf         the buffer to write to
  * bytes       Number of bytes to read
  */
-int client_read(int *sock, char *buf, int bytes)
+int client_read(int *sock, StrBuf *Target, StrBuf *buf, int bytes)
 {
-       return (client_read_to(sock, buf, bytes, SLEEPING));
+       return (client_read_to(sock, Target, buf, bytes, SLEEPING));
 }
 
 
@@ -381,38 +376,37 @@ int client_read(int *sock, char *buf, int bytes)
  *
  * returns the number of bytes read
  */
-int client_getln(int *sock, char *buf, int bufsiz)
-{
-       int i = 0;
-       int retval = 0;
-
-       /* Read one character at a time.*/
-       for (i = 0; *sock > 0; i++) {
-               retval = client_read(sock, &buf[i], 1);
-               if (retval < 0)
-                       return retval;
-               if (retval != 1 || buf[i] == '\n' || i == (bufsiz-1))
-                       break;
-               if ( (!isspace(buf[i])) && (!isprint(buf[i])) ) {
-                       /* Non printable character recieved from client */
-                       return(-1);
-               }
-       }
-
-       /* If we got a long line, discard characters until the newline. */
-       if (i == (bufsiz-1))
-               while (buf[i] != '\n' && retval == 1)
-                       retval = client_read(sock, &buf[i], 1);
-
-       /*
-        * Strip any trailing non-printable characters.
-        */
-       buf[i] = 0;
-       while ((i > 0) && (!isprint(buf[i - 1]))) {
-               buf[--i] = 0;
-       }
-       return (retval);
-}
+/////int client_getln(int *sock, char *buf, int bufsiz)
+/////{
+/////  int i, retval;
+/////
+/////  /* Read one character at a time.*/
+/////  for (i = 0; *sock > 0; i++) {
+/////          retval = client_read(sock, &buf[i], 1);
+/////          if (retval < 0)
+/////                  return retval;
+/////          if (retval != 1 || buf[i] == '\n' || i == (bufsiz-1))
+/////                  break;
+/////          if ( (!isspace(buf[i])) && (!isprint(buf[i])) ) {
+/////                  /* Non printable character recieved from client */
+/////                  return(-1);
+/////          }
+/////  }
+/////
+/////  /* If we got a long line, discard characters until the newline. */
+/////  if (i == (bufsiz-1))
+/////          while (buf[i] != '\n' && retval == 1)
+/////                  retval = client_read(sock, &buf[i], 1);
+/////
+/////  /*
+/////   * Strip any trailing non-printable characters.
+/////   */
+/////  buf[i] = 0;
+/////  while ((i > 0) && (!isprint(buf[i - 1]))) {
+/////          buf[--i] = 0;
+/////  }
+/////  return (retval);
+/////}
 
 /*
  * Shut us down the regular way.
@@ -426,6 +420,56 @@ void graceful_shutdown_watcher(int signum) {
                exit(0);
 }
 
+
+int ClientGetLine(int *sock, StrBuf *Target, StrBuf *CLineBuf)
+{
+       const char *Error, *pch, *pchs;
+       int rlen, len, retval = 0;
+
+       if (is_https) {
+               if (StrLength(CLineBuf) > 0) {
+                       pchs = ChrPtr(CLineBuf);
+                       pch = strchr(pchs, '\n');
+                       if (pch != NULL) {
+                               rlen = 0;
+                               len = pch - pchs;
+                               if (len > 0 && (*(pch - 1) == '\r') )
+                                       rlen ++;
+                               StrBufSub(Target, CLineBuf, 0, len - rlen);
+                               StrBufCutLeft(CLineBuf, len + 1);
+                               return len - rlen;
+                       }
+               }
+
+               while ((retval >= 0) && 
+                      (pchs = ChrPtr(CLineBuf),
+                       pch = strchr(pchs, '\n'), 
+                       pch == NULL))
+                       retval = client_read_sslbuffer(CLineBuf, SLEEPING);
+               if ((retval > 0) && (pch != NULL)) {
+                       rlen = 0;
+                       len = pch - pchs;
+                       if (len > 0 && (*(pch - 1) == '\r') )
+                               rlen ++;
+                       StrBufSub(Target, CLineBuf, 0, len - rlen);
+                       StrBufCutLeft(CLineBuf, len + 1);
+                       return len - rlen;
+
+               }
+               else 
+                       return -1;
+       }
+       else 
+               return StrBufTCP_read_buffered_line(Target, 
+                                                   CLineBuf,
+                                                   sock,
+                                                   5,
+                                                   1,
+                                                   &Error);
+}
+
+
+
 /*
  * Shut us down the regular way.
  * signum is the signal we want to forward
index bf3ba3ad78a6b0fc57156dc847fd91fca539f8bf..82b4a51dfd690a6e574c508e0c5056e9b9bc1813 100644 (file)
@@ -5,9 +5,10 @@ extern char *static_content_dirs[PATH_MAX];  /**< Disk representation */
 extern int ndirs;
 extern char socket_dir[PATH_MAX];
 
+int ClientGetLine(int *sock, StrBuf *Target, StrBuf *CLineBuf);
 int client_getln(int *sock, char *buf, int bufsiz);
-int client_read(int *sock, char *buf, int bytes);
-int client_read_to(int *sock, char *buf, int bytes, int timeout);
+int client_read(int *sock, StrBuf *Target, StrBuf *buf, int bytes);
+int client_read_to(int *sock, StrBuf *Target, StrBuf *Buf, int bytes, int timeout);
 int lprintf(int loglevel, const char *format, ...);
 void wc_backtrace(void);
 void ShutDownWebcit(void);