* BIG rewrite of header handling and slimming of context_loop and session_loop; shuff...
authorWilfried Göesgens <willi@citadel.org>
Sun, 17 May 2009 08:34:33 +0000 (08:34 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 17 May 2009 08:34:33 +0000 (08:34 +0000)
23 files changed:
webcit/auth.c
webcit/calendar.c
webcit/context_loop.c
webcit/downloads.c
webcit/gettext.c
webcit/groupdav_main.c
webcit/listsub.c
webcit/mainmenu.c
webcit/messages.c
webcit/msg_renderers.c
webcit/openid.c
webcit/paramhandling.c
webcit/preferences.c
webcit/roomops.c
webcit/rss.c
webcit/serv_func.c
webcit/subst.c
webcit/tcp_sockets.c
webcit/vcard_edit.c
webcit/webcit.c
webcit/webcit.h
webcit/webserver.c
webcit/who.c

index b9e28faf3513db6e7cb03830012e193a89396044..be1246527d90b1a9d0087784ac6c1ced622bdf26 100644 (file)
@@ -27,7 +27,42 @@ void initialize_axdefs(void) {
        axdefs[6] = _("Aide");          /* chief */
 }
 
+int ReEstablish_Session(void)
+{
+       StrBuf *Buf = NewStrBuf();
+       wcsession *WCC = WC;
 
+       serv_printf("USER %s", ChrPtr(WCC->Hdr->c_username));
+       StrBuf_ServGetln(Buf);
+       if (GetServerStatus(Buf, NULL) == 3) {
+               serv_printf("PASS %s", ChrPtr(WCC->Hdr->c_password));
+               StrBuf_ServGetln(Buf);
+               if (GetServerStatus(Buf, NULL) == 2) {
+                       become_logged_in(WCC->Hdr->c_username, 
+                                        WCC->Hdr->c_password, Buf);
+                       get_preference("default_header_charset", &WCC->DefaultCharset);
+               }
+       }
+       /*
+        * If we don't have a current room, but a cookie specifying the
+        * current room is supplied, make an effort to go there.
+        */
+       if ((StrLength(WCC->wc_roomname) == 0) && (StrLength(WCC->Hdr->c_roomname) > 0)) {
+               serv_printf("GOTO %s", 
+                           ChrPtr(WCC->Hdr->c_roomname));
+               StrBuf_ServGetln(Buf);
+               if (GetServerStatus(Buf, NULL) == 2) {
+                       if (WCC->wc_roomname == NULL) {
+                               WCC->wc_roomname = NewStrBufDup(WCC->Hdr->c_roomname);
+                       }
+                       else {
+                               FlushStrBuf(WCC->wc_roomname);
+                               StrBufAppendBuf(WCC->wc_roomname, WCC->Hdr->c_roomname, 0);
+                       }
+               }
+       }
+       FreeStrBuf(&Buf);
+}
 
 
 /* 
@@ -330,8 +365,8 @@ void do_openid_login(void)
                snprintf(buf, sizeof buf,
                        "OIDS %s|%s://%s/finalize_openid_login|%s://%s",
                        bstr("openid_url"),
-                        (is_https ? "https" : "http"), ChrPtr(WCC->http_host),
-                        (is_https ? "https" : "http"), ChrPtr(WCC->http_host)
+                        (is_https ? "https" : "http"), ChrPtr(WCC->Hdr->http_host),
+                        (is_https ? "https" : "http"), ChrPtr(WCC->Hdr->http_host)
                );
 
                serv_puts(buf);
@@ -379,8 +414,8 @@ void finalize_openid_login(void)
                                const char *HKey;
                                HashPos *Cursor;
                                
-                               Cursor = GetNewHashPos (WCC->urlstrings, 0);
-                               while (GetNextHashPos(WCC->urlstrings, Cursor, &HKLen, &HKey, &U)) {
+                               Cursor = GetNewHashPos (WCC->Hdr->urlstrings, 0);
+                               while (GetNextHashPos(WCC->Hdr->urlstrings, Cursor, &HKLen, &HKey, &U)) {
                                        u = (urlcontent*) U;
                                        if (!strncasecmp(u->url_key, "openid.", 7)) {
                                                serv_printf("%s|%s", &u->url_key[7], ChrPtr(u->url_data));
@@ -917,13 +952,14 @@ void
 InitModule_AUTH
 (void)
 {
-       WebcitAddUrlHandler(HKEY("do_welcome"), do_welcome, ANONYMOUS);
-       WebcitAddUrlHandler(HKEY("login"), do_login, ANONYMOUS);
+       WebcitAddUrlHandler(HKEY(""), do_welcome, ANONYMOUS|COOKIEUNNEEDED); /* no url pattern at all? Show login. */
+       WebcitAddUrlHandler(HKEY("do_welcome"), do_welcome, ANONYMOUS|COOKIEUNNEEDED);
+       WebcitAddUrlHandler(HKEY("login"), do_login, ANONYMOUS|COOKIEUNNEEDED);
        WebcitAddUrlHandler(HKEY("display_openid_login"), _display_openid_login, ANONYMOUS);
        WebcitAddUrlHandler(HKEY("openid_login"), do_openid_login, ANONYMOUS);
        WebcitAddUrlHandler(HKEY("finalize_openid_login"), finalize_openid_login, ANONYMOUS);
        WebcitAddUrlHandler(HKEY("openid_manual_create"), openid_manual_create, ANONYMOUS);
-       WebcitAddUrlHandler(HKEY("do_logout"), do_logout, 0);
+       WebcitAddUrlHandler(HKEY("do_logout"), do_logout, ANONYMOUS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
        WebcitAddUrlHandler(HKEY("validate"), validate, 0);
        WebcitAddUrlHandler(HKEY("display_reg"), _display_reg, 0);
        WebcitAddUrlHandler(HKEY("display_changepw"), display_changepw, 0);
index 48a0f1fc793461630d2a70e8d70a03643e94f9c4..b1e9b9a585af94f2263e32a080f42b0e95f83a57 100644 (file)
@@ -1257,7 +1257,9 @@ void save_event(void) {
 /*
  * Anonymous request of freebusy data for a user
  */
-void do_freebusy(const char *req) {
+void do_freebusy(void)
+{ /// TODO: request line const char *req) {
+       const char req[] = "";
        char who[SIZ];
        char buf[SIZ];
        int len;
@@ -1296,7 +1298,6 @@ void do_freebusy(const char *req) {
 
 
 
-
 void 
 InitModule_CALENDAR
 (void)
@@ -1305,6 +1306,7 @@ InitModule_CALENDAR
        RegisterPreference("dayend", _("Calendar day view ends at:"), PRF_INT, NULL);
        RegisterPreference("weekstart", _("Week starts on:"), PRF_INT, NULL);
 
+       WebcitAddUrlHandler(HKEY("freebusy"), do_freebusy, COOKIEUNNEEDED|ANONYMOUS|FORCE_SESSIONCLOSE);
        WebcitAddUrlHandler(HKEY("display_edit_task"), display_edit_task, 0);
        WebcitAddUrlHandler(HKEY("save_task"), save_task, 0);
        WebcitAddUrlHandler(HKEY("display_edit_event"), display_edit_event, 0);
index 90038a7c8501caa0e0d73bd092f6153835cc1c3a..db6fd289a5afce695f9413237901a664de60e45b 100644 (file)
@@ -19,6 +19,16 @@ wcsession *SessionList = NULL; /**< our sessions ????*/
 
 pthread_key_t MyConKey;         /**< TSD key for MySession() */
 HashList *HttpReqTypes = NULL;
+HashList *HttpHeaderHandler = NULL;
+extern HashList *HandlerHash;
+
+void DestroyHttpHeaderHandler(void *V)
+{
+       OneHttpHeader *pHdr;
+       pHdr = (OneHttpHeader*) V;
+       FreeStrBuf(&pHdr->Val);
+       free(pHdr);
+}
 
 void shutdown_sessions(void)
 {
@@ -165,11 +175,33 @@ int lingering_close(int fd)
 
 
 
+
+/**
+ * \brief Detects a 'mobile' user agent 
+ */
+int is_mobile_ua(char *user_agent) {
+      if (strstr(user_agent,"iPhone OS") != NULL) {
+       return 1;
+      } else if (strstr(user_agent,"Windows CE") != NULL) {
+       return 1;
+      } else if (strstr(user_agent,"SymbianOS") != NULL) {
+       return 1;
+      } else if (strstr(user_agent, "Opera Mobi") != NULL) {
+       return 1;
+      } else if (strstr(user_agent, "Firefox/2.0.0 Opera 9.51 Beta") != NULL) {
+             /*  For some reason a new install of Opera 9.51beta decided to spoof. */
+         return 1;
+         }
+      return 0;
+}
+
+
+
 /*
  * Look for commonly-found probes of malware such as worms, viruses, trojans, and Microsoft Office.
  * Short-circuit these requests so we don't have to send them through the full processing loop.
  */
-int is_bogus(StrBuf *http_cmd) {
+int is_bogus(StrBuf *http_cmd) {////TODO!
        const char *url;
        int i, max;
        const char *bogus_prefixes[] = {
@@ -197,93 +229,126 @@ int is_bogus(StrBuf *http_cmd) {
 }
 
 
+int ReadHttpSubject(ParsedHttpHdrs *Hdr, StrBuf *Line, StrBuf *Buf)
+{
+       const char *Args;
+       void *vLine, *vHandler;
+       const char *Pos = NULL;
+
+
+       Hdr->ReqLine = Line;
+       /* The requesttype... GET, POST... */
+       StrBufExtract_token(Buf, Hdr->ReqLine, 0, ' ');
+       if (GetHash(HttpReqTypes, SKEY(Buf), &vLine) &&
+           (vLine != NULL))
+       {
+               Hdr->eReqType = *(long*)vLine;
+       }
+       else {
+               Hdr->eReqType = eGET;
+               return 1;
+       }
+       StrBufCutLeft(Hdr->ReqLine, StrLength(Buf) + 1);
+
+       /* the HTTP Version... */
+       StrBufExtract_token(Buf, Hdr->ReqLine, 1, ' ');
+       StrBufCutRight(Hdr->ReqLine, StrLength(Buf) + 1);
+       if ((StrLength(Buf) == 0) ||
+           is_bogus(Hdr->ReqLine)) {
+               Hdr->eReqType = eGET;
+               return 1;
+       }
+
+       Hdr->this_page = NewStrBufDup(Hdr->ReqLine);
+       /* chop Filename / query arguments */
+       Args = strchr(ChrPtr(Hdr->ReqLine), '?');
+       if (Args == NULL) /* whe're not that picky about params... TODO: this will spoil '&' in filenames.*/
+               Args = strchr(ChrPtr(Hdr->ReqLine), '&');
+       if (Args != NULL) {
+               Hdr->PlainArgs = NewStrBufPlain(
+                       Args, 
+                       StrLength(Hdr->ReqLine) -
+                       (Args - ChrPtr(Hdr->ReqLine)));
+               StrBufCutAt(Hdr->ReqLine, 0, Args);
+       } /* don't parse them yet, maybe we don't even care... */
+       
+       /* now lookup what we are going to do with this... */
+       /* skip first slash */
+       StrBufExtract_NextToken(Buf, Hdr->ReqLine, &Pos, '/');
+       do {
+               StrBufExtract_NextToken(Buf, Hdr->ReqLine, &Pos, '/');
+
+               GetHash(HandlerHash, SKEY(Buf), &vHandler),
+               Hdr->Handler = (WebcitHandler*) vHandler;
+               if (Hdr->Handler == NULL)
+                       break;
+               /* are we about to ignore some prefix like webcit/ ? */
+               if ((Hdr->Handler->Flags & URLNAMESPACE) == 0)
+                       break;
+       } while (1);
+       /* remove the handlername from the URL */
+       if (Pos != NULL) {
+               StrBufCutLeft(Hdr->ReqLine, 
+                             Pos - ChrPtr(Hdr->ReqLine));
+       }
+/*
+       if (Hdr->Handler == NULL)
+               return 1;
+*/
+       Hdr->HTTPHeaders = NewHash(1, NULL);
+
+       return 0;
+}
+
+int AnalyseHeaders(ParsedHttpHdrs *Hdr)
+{
+       OneHttpHeader *pHdr;
+       void *vHdr;
+       long HKLen;
+       const char *HashKey;
+       HashPos *at = GetNewHashPos(Hdr->HTTPHeaders, 0);
+       
+       while (GetNextHashPos(Hdr->HTTPHeaders, at, &HKLen, &HashKey, &vHdr) && 
+              (vHdr != NULL)) {
+               pHdr = (OneHttpHeader *)vHdr;
+               if (pHdr->HaveEvaluator)
+                       pHdr->H(pHdr->Val, Hdr);
+
+       }
+       DeleteHashPos(&at);
+       return 0;
+}
+
 /*const char *nix(void *vptr) {return ChrPtr( (StrBuf*)vptr);}*/
 
 /*
- * handle one request
- *
- * This loop gets called once for every HTTP connection made to WebCit.  At
- * this entry point we have an HTTP socket with a browser allegedly on the
- * other end, but we have not yet bound to a WebCit session.
- *
- * The job of this function is to locate the correct session and bind to it,
- * or create a session if necessary and bind to it, then run the WebCit
- * transaction loop.  Afterwards, we unbind from the session.  When this
- * function returns, the worker thread is then free to handle another
- * transaction.
+ * Read in the request
  */
-void context_loop(int *sock)
+int ReadHTTPRequset (ParsedHttpHdrs *Hdr)
 {
-       long eReqType = eGET;
-       int isbogus = 0;
-       const char *Pos = NULL;
-       const char *buf;
-       int desired_session = 0;
-       int got_cookie = 0;
-       int gzip_ok = 0;
-       wcsession *TheSession, *sptr;
-       char httpauth_string[1024];
-       char httpauth_user[1024];
-       char httpauth_pass[1024];
-       int nLine = 0;
-       int LineLen;
-       void *vLine;
-       StrBuf *Buf, *Line, *LastLine, *HeaderName, *ReqLine;
        const char *pch, *pchs, *pche;
-       HashList *HTTPHeaders;
-
-       strcpy(httpauth_string, "");
-       strcpy(httpauth_user, DEFAULT_HTTPAUTH_USER);
-       strcpy(httpauth_pass, DEFAULT_HTTPAUTH_PASS);
+       OneHttpHeader *pHdr;
+       StrBuf *Line, *LastLine, *HeaderName;
+       int nLine = 0;
+       void *vF;
+       int isbogus = 0;
 
-       /*
-        * Find out what it is that the web browser is asking for
-        */
        HeaderName = NewStrBuf();
-       Buf = NewStrBuf();
+       Hdr->ReadBuf = NewStrBuf();
        LastLine = NULL;
-       HTTPHeaders = NewHash(1, NULL);
-
-       /*
-        * Read in the request
-        */
        do {
                nLine ++;
                Line = NewStrBuf();
 
+               if (ClientGetLine(&Hdr->http_sock, Line, Hdr->ReadBuf, &Hdr->Pos) < 0) return 1;
 
-               if (ClientGetLine(sock, Line, Buf, &Pos) < 0) return;
-
-               LineLen = StrLength(Line);
-
-               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;
-                       }
+               if (StrLength(Line) == 0) {
+                       FreeStrBuf(&Line);
                        continue;
                }
-               if (LineLen == 0) {
-                       FreeStrBuf(&Line);
+               if (nLine == 1) {
+                       isbogus = ReadHttpSubject(Hdr, Line, HeaderName);
+                       if (isbogus) break;
                        continue;
                }
 
@@ -311,64 +376,72 @@ void context_loop(int *sock)
                StrBufCutLeft(Line, pch - pchs);
 
                StrBufUpCase(HeaderName);
-               Put(HTTPHeaders, SKEY(HeaderName), Line, HFreeStrBuf);
+
+               pHdr = (OneHttpHeader*) malloc(sizeof(OneHttpHeader));
+               memset(pHdr, 0, sizeof(OneHttpHeader));
+               pHdr->Val = Line;
+
+               if (GetHash(HttpHeaderHandler, SKEY(HeaderName), &vF) &&
+                   (vF != NULL))
+               {
+                       OneHttpHeader *FHdr = (OneHttpHeader*) vF;
+                       pHdr->H = FHdr->H;
+                       pHdr->HaveEvaluator = 1;
+               }
+               Put(Hdr->HTTPHeaders, SKEY(HeaderName), pHdr, DestroyHttpHeaderHandler);
                LastLine = Line;
-       } while (LineLen > 0);
+       } while (Line != NULL);
 
        FreeStrBuf(&HeaderName);
 
-       if (isbogus)
-               StrBufPlain(ReqLine, HKEY("/404"));
+       return isbogus;
+}
 
 
-/*     dbg_PrintHash(HTTPHeaders, nix, NULL);  */
 
+/*
+ * handle one request
+ *
+ * This loop gets called once for every HTTP connection made to WebCit.  At
+ * this entry point we have an HTTP socket with a browser allegedly on the
+ * other end, but we have not yet bound to a WebCit session.
+ *
+ * The job of this function is to locate the correct session and bind to it,
+ * or create a session if necessary and bind to it, then run the WebCit
+ * transaction loop.  Afterwards, we unbind from the session.  When this
+ * function returns, the worker thread is then free to handle another
+ * transaction.
+ */
+void context_loop(int *sock)
+{
+       ParsedHttpHdrs Hdr;
+       int isbogus = 0;
+       wcsession *TheSession, *sptr;
+       struct timeval tx_start;
+       struct timeval tx_finish;
+       
+       gettimeofday(&tx_start, NULL);          /* start a stopwatch for performance timing */
 
+       memset(&Hdr, 0, sizeof(ParsedHttpHdrs));
+       Hdr.eReqType = eGET;
+       Hdr.http_sock = *sock;
        /*
-        * Can we compress?
+        * Find out what it is that the web browser is asking for
         */
-       if (!isbogus &&
-           GetHash(HTTPHeaders, HKEY("ACCEPT-ENCODING"), &vLine) && 
-           (vLine != NULL)) {
-               buf = ChrPtr((StrBuf*)vLine);
-               if (strstr(&buf[16], "gzip")) {
-                       gzip_ok = 1;
-               }
-       }
+       isbogus = ReadHTTPRequset(&Hdr);
 
-       /*
-        * Browser-based sessions use cookies for session authentication
-        */
-       if (!isbogus &&
-           GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && 
-           (vLine != NULL)) {
-               cookie_to_stuff(vLine, &desired_session,
-                               NULL, NULL, NULL);
-               got_cookie = 1;
-       }
+       if (!isbogus)
+               isbogus = AnalyseHeaders(&Hdr);
+/*
+       if (isbogus)
+               StrBufPlain(ReqLine, HKEY("/404"));
+*/
 
-       /*
-        * GroupDAV-based sessions use HTTP authentication
-        */
-       if (!isbogus &&
-           GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && 
-           (vLine != NULL)) {
-               Line = (StrBuf*)vLine;
-               if (strncasecmp(ChrPtr(Line), "Basic", 5) == 0) {
-                       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 scheme not supported! [%s]\n", ChrPtr(Line));
-       }
+/*     dbg_PrintHash(HTTPHeaders, nix, NULL);  */
+
+
+///HttpHeaderHandler
 
-       if (!isbogus &&
-           GetHash(HTTPHeaders, HKEY("IF-MODIFIED-SINCE"), &vLine) && 
-           (vLine != NULL)) {
-               if_modified_since = httpdate_to_timestamp((StrBuf*)vLine);
-       }
 
 
 
@@ -377,14 +450,14 @@ void context_loop(int *sock)
         * 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 (!isbogus &&
            (StrLength(ReqLine) >= 8) && 
            (strstr(ChrPtr(ReqLine), "/webcit/")) ) {
                StrBufCutLeft(ReqLine, 7);
        }
 
-       /* Begin parsing the request. */
+       /* Begin parsing the request. * /
 #ifdef TECH_PREVIEW
        if ((strncmp(ChrPtr(ReqLine), "/sslg", 5) != 0) &&
            (strncmp(ChrPtr(ReqLine), "/static/", 8) != 0) &&
@@ -392,48 +465,12 @@ void context_loop(int *sock)
            (strncmp(ChrPtr(ReqLine), "/wholist_section", 16) != 0) &&
            (strstr(ChrPtr(ReqLine), "wholist_section") == NULL)) {
 #endif
-               lprintf(5, "HTTP: %s %s\n", ReqStrs[eReqType], ChrPtr(ReqLine));
+               lprintf(5, "HTTP: %s %s\n", ReqStrs[Hdr.eReqType], ChrPtr(ReqLine));
 #ifdef TECH_PREVIEW
        }
 #endif
 
-
-       /**
-        * While we're at it, gracefully handle requests for the
-        * robots.txt and favicon.ico files.
-        */
-       if ((StrLength(ReqLine) >= 11) &&
-           !strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) {
-               StrBufPlain(ReqLine, 
-                           HKEY("/static/robots.txt"
-                                "?force_close_session=yes HTTP/1.1"));
-               eReqType = eGET;
-       }
-       else if ((StrLength(ReqLine) >= 11) &&
-                !strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) {
-               StrBufPlain(ReqLine, HKEY("/static/favicon.ico"));
-               eReqType = eGET;
-       }
-
-       /**
-        * These are the URL's which may be executed without a
-        * session cookie already set.  If it's not one of these,
-        * force the session to close because cookies are
-        * probably disabled on the client browser.
-        */
-       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)) {
-               StrBufPlain(ReqLine, 
-                           HKEY("/static/nocookies.html"
-                                "?force_close_session=yes"));
-       }
+*/
 
        /**
         * See if there's an existing session open with the desired ID or user/pass
@@ -446,15 +483,15 @@ void context_loop(int *sock)
                     ((sptr != NULL) && (TheSession == NULL)); 
                      sptr = sptr->next) {
 
-                       /** If HTTP-AUTH, look for a session with matching credentials */
-                       if ( (!IsEmptyStr(httpauth_user))
+                       /** If HTTP-AUTH, look for a session with matching credentials * /
+                       if ( (////TODO check auth type here...
                             &&(!strcasecmp(ChrPtr(sptr->httpauth_user), httpauth_user))
                             &&(!strcasecmp(ChrPtr(sptr->httpauth_pass), httpauth_pass)) ) {
                                TheSession = sptr;
                        }
 
                        /** If cookie-session, look for a session with matching session ID */
-                       if ( (desired_session != 0) && (sptr->wc_session == desired_session)) {
+                       if ( (Hdr.desired_session != 0) && (sptr->wc_session == Hdr.desired_session)) {
                                TheSession = sptr;
                        }
 
@@ -470,7 +507,7 @@ void context_loop(int *sock)
                TheSession = (wcsession *)
                        malloc(sizeof(wcsession));
                memset(TheSession, 0, sizeof(wcsession));
-               TheSession->headers = HTTPHeaders;
+               TheSession->Hdr = &Hdr;
                TheSession->serv_sock = (-1);
                TheSession->chat_sock = (-1);
        
@@ -480,16 +517,16 @@ void context_loop(int *sock)
                 * doesn't, and that's a Bad Thing because it causes lots of spurious sessions
                 * to get created.
                 */     
-               if (desired_session == 0) {
+               if (Hdr.desired_session == 0) {
                        TheSession->wc_session = GenerateSessionID();
                }
                else {
-                       TheSession->wc_session = desired_session;
+                       TheSession->wc_session = Hdr.desired_session;
                }
-
+/*
                TheSession->httpauth_user = NewStrBufPlain(httpauth_user, -1);
-               TheSession->httpauth_pass = NewStrBufPlain(httpauth_user, -1);
-
+                       TheSession->httpauth_pass = NewStrBufPlain(httpauth_user, -1);
+*/
                pthread_setspecific(MyConKey, (void *)TheSession);
                session_new_modules(TheSession);
 
@@ -513,23 +550,34 @@ 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;
+       TheSession->Hdr = &Hdr;
 
        session_attach_modules(TheSession);
-       session_loop(ReqLine, Buf, &Pos);                               /* do transaction */
+       session_loop();                         /* do transaction */
        session_detach_modules(TheSession);
 
-       TheSession->headers = NULL;
+       TheSession->Hdr = NULL;
        pthread_mutex_unlock(&TheSession->SessionMutex);        /* unbind */
-
+/* TODO
+
+       FreeStrBuf(&c_username);
+       FreeStrBuf(&c_password);
+       FreeStrBuf(&c_roomname);
+       FreeStrBuf(&c_httpauth_user);
+       FreeStrBuf(&c_httpauth_pass);
+*/
        /* Free the request buffer */
-       DeleteHash(&HTTPHeaders);
-       FreeStrBuf(&ReqLine);
-       FreeStrBuf(&Buf);
+       ///DeleteHash(&HTTPHeaders);
+       ///FreeStrBuf(&ReqLine);
+       
+       /* How long did this transaction take? */
+       gettimeofday(&tx_finish, NULL);
+       
+       lprintf(9, "Transaction completed in %ld.%06ld seconds.\n",
+               ((tx_finish.tv_sec*1000000 + tx_finish.tv_usec) - (tx_start.tv_sec*1000000 + tx_start.tv_usec)) / 1000000,
+               ((tx_finish.tv_sec*1000000 + tx_finish.tv_usec) - (tx_start.tv_sec*1000000 + tx_start.tv_usec)) % 1000000
+       );
 }
 
 void tmplput_nonce(StrBuf *Target, WCTemplputParams *TP)
@@ -549,6 +597,156 @@ void tmplput_current_room(StrBuf *Target, WCTemplputParams *TP)
        StrBufAppendTemplate(Target, TP, WC->wc_roomname, 0); 
 }
 
+
+void Header_HandleCookie(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       hdr->RawCookie = Line;
+       if (hdr->DontNeedAuth)
+               return;
+/*
+       c_username = NewStrBuf();
+       c_password = NewStrBuf();
+       c_roomname = NewStrBuf();
+       safestrncpy(c_httpauth_string, "", sizeof c_httpauth_string);
+       c_httpauth_user = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_USER));
+       c_httpauth_pass = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_PASS));
+*/
+       cookie_to_stuff(Line, &hdr->desired_session,
+                       hdr->c_username,
+                       hdr->c_password,
+                       hdr->c_roomname);
+       hdr->got_cookie = 1;
+}
+
+
+       /*
+        * Browser-based sessions use cookies for session authentication
+        * /
+       if (!isbogus &&
+           GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && 
+           (vLine != NULL)) {
+               cookie_to_stuff(vLine, &desired_session,
+                               NULL, NULL, NULL);
+               got_cookie = 1;
+       }
+       */
+       /*
+        * GroupDAV-based sessions use HTTP authentication
+        */
+/*
+       if (!isbogus &&
+           GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && 
+           (vLine != NULL)) {
+               Line = (StrBuf*)vLine;
+               if (strncasecmp(ChrPtr(Line), "Basic", 5) == 0) {
+                       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 scheme not supported! [%s]\n", ChrPtr(Line));
+       }
+
+*/
+void Header_HandleAuth(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       const char *Pos = NULL;
+       StrBufDecodeBase64(Line);
+       StrBufExtract_NextToken(hdr->c_username, Line, &Pos, ':');
+       StrBufExtract_NextToken(hdr->c_password, Line, &Pos, ':');
+}
+
+void Header_HandleContentLength(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       hdr->ContentLength = StrToi(Line);
+}
+
+void Header_HandleContentType(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       hdr->ContentType = Line;
+}
+
+void Header_HandleUserAgent(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       hdr->user_agent = Line;
+#ifdef TECH_PREVIEW
+/* TODO: do this later on session creating
+       if ((WCC->is_mobile < 0) && is_mobile_ua(&buf[12])) {                   
+               WCC->is_mobile = 1;
+       }
+       else {
+               WCC->is_mobile = 0;
+       }
+*/
+#endif
+}
+
+
+void Header_HandleHost(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       if ((follow_xff) && (hdr->http_host != NULL))
+               return;
+       else
+               hdr->http_host = Line;
+}
+
+void Header_HandleXFFHost(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       if (follow_xff)
+               hdr->http_host = Line;
+}
+
+
+void Header_HandleXFF(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       hdr->browser_host = Line;
+
+       while (StrBufNum_tokens(hdr->browser_host, ',') > 1) {
+               StrBufRemove_token(hdr->browser_host, 0, ',');
+       }
+       StrBufTrim(hdr->browser_host);
+}
+
+void Header_HandleIfModSince(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       hdr->if_modified_since = httpdate_to_timestamp(Line);
+}
+
+void Header_HandleAcceptEncoding(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+       /*
+        * Can we compress?
+        */
+       if (strstr(&ChrPtr(Line)[16], "gzip")) {
+               hdr->gzip_ok = 1;
+       }
+}
+
+/*
+{
+       c_username = NewStrBuf();
+       c_password = NewStrBuf();
+       c_roomname = NewStrBuf();
+       safestrncpy(c_httpauth_string, "", sizeof c_httpauth_string);
+       c_httpauth_user = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_USER));
+       c_httpauth_pass = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_PASS));
+}
+*/
+       /* *
+        * These are the URL's which may be executed without a
+        * session cookie already set.  If it's not one of these,
+        * force the session to close because cookies are
+        * probably disabled on the client browser.
+        * /
+       else if ( (StrLength(ReqLine) > 1 )
+               && (strncasecmp(ChrPtr(ReqLine), "/404", 4))
+               && (Hdr.got_cookie == 0)) {
+               StrBufPlain(ReqLine, 
+                           HKEY("/static/nocookies.html"
+                                "?force_close_session=yes"));
+       }
+*/
 const char *ReqStrs[eNONE] = {
        "GET",
        "POST",
@@ -567,7 +765,7 @@ ServerStartModule_CONTEXT
 {
        long *v;
        HttpReqTypes = NewHash(1, NULL);
-
+       HttpHeaderHandler = NewHash(1, NULL);
 
        v = malloc(sizeof(long));
        *v = eGET;
@@ -611,14 +809,42 @@ ServerShutdownModule_CONTEXT
 (void)
 {
        DeleteHash(&HttpReqTypes);
+       DeleteHash(&HttpHeaderHandler);
 }
 
-
+void RegisterHeaderHandler(const char *Name, long Len, Header_Evaluator F)
+{
+       OneHttpHeader *pHdr;
+       pHdr = (OneHttpHeader*) malloc(sizeof(OneHttpHeader));
+       memset(pHdr, 0, sizeof(OneHttpHeader));
+       pHdr->H = F;
+       Put(HttpHeaderHandler, Name, Len, pHdr, DestroyHttpHeaderHandler);
+}
+extern void blank_page(void); ///TODO: remove me
 void 
 InitModule_CONTEXT
 (void)
 {
+       RegisterHeaderHandler(HKEY("COOKIE"), Header_HandleCookie);
+       RegisterHeaderHandler(HKEY("AUTHORIZATION"), Header_HandleAuth);
+       RegisterHeaderHandler(HKEY("CONTENT-LENGTH"), Header_HandleContentLength);
+       RegisterHeaderHandler(HKEY("CONTENT-TYPE"), Header_HandleContentType);
+       RegisterHeaderHandler(HKEY("USER-AGENT"), Header_HandleUserAgent);
+       RegisterHeaderHandler(HKEY("X-FORWARDED-HOST"), Header_HandleXFFHost);
+       RegisterHeaderHandler(HKEY("HOST"), Header_HandleHost);
+       RegisterHeaderHandler(HKEY("X-FORWARDED-FOR"), Header_HandleXFF);
+       RegisterHeaderHandler(HKEY("ACCEPT-ENCODING"), Header_HandleAcceptEncoding);
+       RegisterHeaderHandler(HKEY("IF-MODIFIED-SINCE"), Header_HandleIfModSince);
+
        RegisterNamespace("CURRENT_USER", 0, 1, tmplput_current_user, CTX_NONE);
        RegisterNamespace("CURRENT_ROOM", 0, 1, tmplput_current_room, CTX_NONE);
        RegisterNamespace("NONCE", 0, 0, tmplput_nonce, 0);
+
+
+
+       WebcitAddUrlHandler(HKEY("blank"), blank_page, ANONYMOUS|BOGUS);
+
+       WebcitAddUrlHandler(HKEY("blank"), blank_page, URLNAMESPACE);
 }
+//FreeStrBuf(&WCC->this_page);
+       
index 5f4ee0647535982ed9ed78e5bcd3f5fbb5fe5daa..e00161e15afcfaeb7af4bbba716e08e0330ee9d9 100644 (file)
@@ -235,7 +235,7 @@ void display_mime_icon(void)
                snprintf (FileBuf, SIZ, "%s%s", static_dirs[0], "/diskette_24x.gif");
        else
                snprintf (FileBuf, SIZ, "%s%s", static_dirs[3], FileName);
-       output_static(FileBuf);
+       //// TODO! output_static(FileBuf);
 }
 
 void download_file(void)
@@ -249,8 +249,9 @@ void download_file(void)
        int force_download = 1;
        
        Buf = NewStrBuf();
-       StrBufUnescape(WCC->UrlFragment2, 1);
-       serv_printf("OPEN %s", ChrPtr(WCC->UrlFragment2));
+       StrBufExtract_token(Buf, WCC->Hdr->ReqLine, 2, '/');
+       StrBufUnescape(Buf, 1);
+       serv_printf("OPEN %s", ChrPtr(Buf));
        StrBuf_ServGetln(Buf);
        if (GetServerStatus(Buf, NULL) == 2) {
                StrBufCutLeft(Buf, 4);
@@ -386,7 +387,7 @@ void output_image(void)
         * when there's no such image on the server.
         */
        StrBufPrintf (Buf, "%s%s", static_dirs[0], "/blank.gif");
-       output_static(ChrPtr(Buf));
+       //// TDODO output_static(ChrPtr(Buf));
        FreeStrBuf(&Buf);
 }
 
index f3472b3617779f02e2826fb35dd62b38985b05a0..209162e8001aaf493cc2d752a54995e67b93bc1a 100644 (file)
@@ -396,8 +396,8 @@ SessionNewModule_GETTEXT
 {
 #ifdef ENABLE_NLS
        void *vLine;
-       
-       if (GetHash(WC->headers, HKEY("ACCEPT-LANGUAGE"), &vLine) && 
+       ////TODO: make me a header getter
+       if (GetHash(WC->Hdr->HTTPHeaders, HKEY("ACCEPT-LANGUAGE"), &vLine) && 
            (vLine != NULL)) {
                StrBuf *accept_language = (StrBuf*) vLine;
                httplang_to_locale(accept_language);
index 7d774feac65495b15cf040c884eae70d3a2de9f1..2e33e26a539fb63ce9995af0fbee0112ebdb0693 100644 (file)
@@ -101,10 +101,10 @@ void groupdav_main(HashList *HTTPHeaders,
        strcpy(dav_ifmatch, "");
        dav_depth = 0;
 
-       if ((StrLength(WCC->http_host) == 0) &&
+       if ((StrLength(WCC->Hdr->http_host) == 0) &&
            GetHash(HTTPHeaders, HKEY("HOST"), &vLine) && 
            (vLine != NULL)) {
-               WCC->http_host = (StrBuf*)vLine;
+               WCC->Hdr->http_host = (StrBuf*)vLine;
        }
        if (GetHash(HTTPHeaders, HKEY("IF-MATCH"), &vLine) && 
            (vLine != NULL)) {
@@ -163,7 +163,7 @@ void groupdav_main(HashList *HTTPHeaders,
                }
        }
 
-       switch (WCC->eReqType)
+       switch (WCC->Hdr->eReqType)
        {
        /*
         * The OPTIONS method is not required by GroupDAV.  This is an
@@ -216,7 +216,7 @@ void groupdav_main(HashList *HTTPHeaders,
                groupdav_common_headers();
                hprintf("Content-Type: text/plain\r\n");
                wprintf("GroupDAV method \"%s\" is not implemented.\r\n",
-                       ReqStrs[WCC->eReqType]);
+                       ReqStrs[WCC->Hdr->eReqType]);
                end_burst();
        }
 }
@@ -228,9 +228,19 @@ void groupdav_main(HashList *HTTPHeaders,
 void groupdav_identify_host(void) {
        wcsession *WCC = WC;
 
-       if (StrLength(WCC->http_host)!=0) {
+       if (StrLength(WCC->Hdr->http_host)!=0) {
                wprintf("%s://%s",
                        (is_https ? "https" : "http"),
-                       ChrPtr(WCC->http_host));
+                       ChrPtr(WCC->Hdr->http_host));
        }
 }
+
+
+void 
+InitModule_GROUPDAV
+(void)
+{
+
+       WebcitAddUrlHandler(HKEY("groupdav"), do_logout, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
+
+}
index 8a2f2f5acee7c29cd9284126f8c470fef7d3854c..0f4af8ce9042dd81d4dd012534001ad32ca5f6ab 100644 (file)
@@ -61,7 +61,7 @@ void do_listsub(void)
                        email,
                        subtype,
                        (is_https ? "https" : "http"),
-                           ChrPtr(WC->http_host)
+                           ChrPtr(WC->Hdr->http_host)
                );
                serv_getln(buf, sizeof buf);
                if (buf[0] == '2') {
@@ -102,7 +102,7 @@ void do_listsub(void)
                            room,
                            email,
                            (is_https ? "https" : "http"),
-                           ChrPtr(WC->http_host)
+                           ChrPtr(WC->Hdr->http_host)
                );
                serv_getln(buf, sizeof buf);
                if (buf[0] == '2') {
@@ -224,3 +224,14 @@ FORM:              wprintf("<form method=\"POST\" action=\"listsub\">\n");
        wDumpContent(0);
        end_webcit_session();
 }
+
+
+
+void 
+InitModule_LISTSUB
+(void)
+{
+       WebcitAddUrlHandler(HKEY("listsub"), do_listsub, ANONYMOUS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
+
+
+}
index 1ce5e5ee60c7ee9985549667b20560634739d9cf..ab3d2f38ab51ca6ebd484a74b41b52ffa924e335 100644 (file)
@@ -62,7 +62,7 @@ void display_generic(void)
        wprintf("<br /><textarea name=\"g_input\" rows=10 cols=80 width=80></textarea><br />\n");
 
        wprintf("<font size=-2>");
-       wprintf(_("Detected host header is %s://%s"), (is_https ? "https" : "http"), ChrPtr(WC->http_host));
+       wprintf(_("Detected host header is %s://%s"), (is_https ? "https" : "http"), ChrPtr(WC->Hdr->http_host));
        wprintf("</font>\n");
        wprintf("<input type=\"submit\" name=\"sc_button\" value=\"%s\">", _("Send command"));
        wprintf("&nbsp;");
@@ -200,7 +200,7 @@ void display_shutdown(void)
                output_headers(1, 0, 0, 0, 1, 0);
                DoTemplate(HKEY("display_serverrestart"), NULL, &NoCtx);
                end_burst();
-               lingering_close(WC->http_sock);
+               lingering_close(WC->Hdr->http_sock);
                sleeeeeeeeeep(10);
                serv_printf("NOOP");
                serv_printf("NOOP");
index f6db797048046f6f6ecce07749e4c3ede0f8dd2f..0a9f2c746b332965191e670047f4f336ddb74e81 100644 (file)
@@ -365,9 +365,9 @@ void handle_one_message(void)
        const StrBuf *Tmpl;
        StrBuf *CmdBuf = NULL;
 
-       msgnum = StrTol(WCC->UrlFragment3);
-       gotoroom(WCC->UrlFragment2);
-       switch (WCC->eReqType)
+       //msgnum = StrTol(WCC->UrlFragment3);
+       //gotoroom(WCC->UrlFragment2);
+       switch (WCC->Hdr->eReqType)
        {
        case eGET:
        case ePOST:
@@ -395,7 +395,7 @@ void handle_one_message(void)
        case eCOPY:
                CopyMessage = 1;
        case eMOVE:
-               if (GetHash(WCC->headers, HKEY("DESTINATION"), &vLine) &&
+               if (GetHash(WCC->Hdr->HTTPHeaders, HKEY("DESTINATION"), &vLine) &&
                    (vLine!=NULL)) {
                        Destination = (StrBuf*) vLine;
                        serv_printf("MOVE %ld|%s|%d", msgnum, ChrPtr(Destination), CopyMessage);
@@ -426,8 +426,8 @@ void embed_message(void) {
        const StrBuf *Tmpl;
        StrBuf *CmdBuf = NULL;
 
-       msgnum = StrTol(WCC->UrlFragment2);
-       switch (WCC->eReqType)
+       msgnum = StrBufExtract_long(WCC->Hdr->ReqLine, 2, '/');
+       switch (WCC->Hdr->eReqType)
        {
        case eGET:
        case ePOST:
@@ -466,7 +466,7 @@ void print_message(void) {
        long msgnum = 0L;
        const StrBuf *Mime;
 
-       msgnum = StrTol(WC->UrlFragment2);
+       msgnum = StrBufExtract_long(WC->Hdr->ReqLine, 2, '/');
        output_headers(0, 0, 0, 0, 0, 0);
 
        hprintf("Content-type: text/html\r\n"
@@ -490,7 +490,7 @@ void mobile_message_view(void)
        long msgnum = 0L;
        const StrBuf *Mime;
   
-       msgnum = StrTol(WC->UrlFragment2);
+       msgnum = StrBufExtract_long(WC->Hdr->ReqLine, 2, '/');
        output_headers(1, 0, 0, 0, 0, 1);
        begin_burst();
        do_template("msgcontrols", NULL);
@@ -507,7 +507,7 @@ void display_headers(void) {
        long msgnum = 0L;
        char buf[1024];
 
-       msgnum = StrTol(WC->UrlFragment2);
+       msgnum = StrBufExtract_long(WC->Hdr->ReqLine, 2, '/');
        output_headers(0, 0, 0, 0, 0, 0);
 
        hprintf("Content-type: text/plain\r\n"
@@ -1731,14 +1731,18 @@ void postpart(StrBuf *partnum, StrBuf *filename, int force_download)
  */
 void mimepart(int force_download)
 {
+       long msgnum, att;
        wcsession *WCC = WC;
        StrBuf *Buf;
        off_t bytes;
        StrBuf *ContentType = NewStrBufPlain(HKEY("application/octet-stream"));
        const char *CT;
 
+       msgnum = StrBufExtract_long(WCC->Hdr->ReqLine, 2, '/');
+       att = StrBufExtract_long(WCC->Hdr->ReqLine, 3, '/');
+
        Buf = NewStrBuf();
-       serv_printf("OPNA %s|%s", ChrPtr(WCC->UrlFragment2), ChrPtr(WCC->UrlFragment3));
+       serv_printf("OPNA %ld|%ld", msgnum, att);
        StrBuf_ServGetln(Buf);
        if (GetServerStatus(Buf, NULL) == 2) {
                StrBufCutLeft(Buf, 4);
@@ -1754,7 +1758,8 @@ void mimepart(int force_download)
 
                if (!force_download) {
                        if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream")) {
-                               CT = GuessMimeByFilename(SKEY(WCC->UrlFragment4));
+                               StrBufExtract_token(Buf, WCC->Hdr->ReqLine, 4, '/');
+                               CT = GuessMimeByFilename(SKEY(Buf));
                        }
                        if (!strcasecmp(ChrPtr(ContentType), "application/octet-stream")) {
                                CT = GuessMimeType(SKEY(WCC->WBuf));
@@ -1837,15 +1842,29 @@ void download_mimepart(void) {
 }
 
 void view_postpart(void) {
-       postpart(WC->UrlFragment2,
-                WC->UrlFragment3,
-                0);
+       StrBuf *filename = NewStrBuf();
+       StrBuf *partnum = NewStrBuf();
+
+       StrBufExtract_token(partnum, WC->Hdr->ReqLine, 2, '/');
+       StrBufExtract_token(filename, WC->Hdr->ReqLine, 3, '/');
+
+       postpart(partnum, filename, 0);
+
+       FreeStrBuf(&filename);
+       FreeStrBuf(&partnum);
 }
 
 void download_postpart(void) {
-       postpart(WC->UrlFragment2,
-                WC->UrlFragment3,
-                1);
+       StrBuf *filename = NewStrBuf();
+       StrBuf *partnum = NewStrBuf();
+
+       StrBufExtract_token(partnum, WC->Hdr->ReqLine, 2, '/');
+       StrBufExtract_token(filename, WC->Hdr->ReqLine, 3, '/');
+
+       postpart(partnum, filename, 1);
+
+       FreeStrBuf(&filename);
+       FreeStrBuf(&partnum);
 }
 
 void h_readnew(void) { readloop(readnew);}
@@ -1916,7 +1935,7 @@ InitModule_MSG
        WebcitAddUrlHandler(HKEY("delete_msg"), delete_msg, 0);
        WebcitAddUrlHandler(HKEY("confirm_move_msg"), confirm_move_msg, 0);
        WebcitAddUrlHandler(HKEY("msg"), embed_message, NEED_URL);
-       WebcitAddUrlHandler(HKEY("message"), handle_one_message, NEED_URL|XHTTP_COMMANDS);
+       WebcitAddUrlHandler(HKEY("message"), handle_one_message, NEED_URL|XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
        WebcitAddUrlHandler(HKEY("printmsg"), print_message, NEED_URL);
        WebcitAddUrlHandler(HKEY("mobilemsg"), mobile_message_view, NEED_URL);
        WebcitAddUrlHandler(HKEY("msgheaders"), display_headers, NEED_URL);
index 3f774992cbc7e460b9c1136e71bd03d1d411b01d..dbb69d20bf0510a0e0c177389c94ba6d6ac64449 100644 (file)
@@ -1107,6 +1107,7 @@ readloop_struct rlid[] = {
 
 void SetAccessCommand(long Oper)
 {
+/* TODO: whats achieved by this?
        wcsession *WCC = WC;    
 
        if (WCC->UrlFragment1 != NULL ) {
@@ -1116,6 +1117,7 @@ void SetAccessCommand(long Oper)
        }
        else 
                WCC->UrlFragment1 = NewStrBufPlain(rlid[Oper].name.Key, rlid[Oper].name.len);
+*/
 }
                
 
index 4c234b178ea3c5aaddd06b9ff23e3400192195bc..4385f703be4ac49349ed35cfc9e97af20634dea0 100644 (file)
@@ -75,8 +75,8 @@ void openid_attach(void) {
                snprintf(buf, sizeof buf,
                         "OIDS %s|%s://%s/finalize_openid_login|%s://%s",
                         bstr("openid_url"),
-                        (is_https ? "https" : "http"), ChrPtr(WCC->http_host),
-                        (is_https ? "https" : "http"), ChrPtr(WCC->http_host)
+                        (is_https ? "https" : "http"), ChrPtr(WCC->Hdr->http_host),
+                        (is_https ? "https" : "http"), ChrPtr(WCC->Hdr->http_host)
                );
 
                serv_puts(buf);
index 8ab501bea0586984bbfe2d4a8c137df8a0b088dd..1f4fc85058711db5e1385e204333dee6af6e903f 100644 (file)
@@ -24,8 +24,8 @@ void ParseURLParams(StrBuf *url)
        urlcontent *u;
        wcsession *WCC = WC;
 
-       if (WCC->urlstrings == NULL)
-               WCC->urlstrings = NewHash(1, NULL);
+       if (WCC->Hdr->urlstrings == NULL)
+               WCC->Hdr->urlstrings = NewHash(1, NULL);
        eptr = ChrPtr(url) + StrLength(url);
        up = ChrPtr(url);
        while ((up < eptr) && (!IsEmptyStr(up))) {
@@ -56,7 +56,7 @@ void ParseURLParams(StrBuf *url)
                        continue;
                }
 
-               Put(WCC->urlstrings, u->url_key, keylen, u, free_url);
+               Put(WCC->Hdr->urlstrings, u->url_key, keylen, u, free_url);
                len = bptr - aptr;
                u->url_data = NewStrBufPlain(aptr, len);
                StrBufUnescape(u->url_data, 1);
@@ -77,7 +77,7 @@ void ParseURLParams(StrBuf *url)
  */
 void free_urls(void)
 {
-       DeleteHash(&WC->urlstrings);
+       DeleteHash(&WC->Hdr->urlstrings);
 }
 
 /*
@@ -93,8 +93,8 @@ void dump_vars(void)
        const char *HKey;
        HashPos *Cursor;
        
-       Cursor = GetNewHashPos (WCC->urlstrings, 0);
-       while (GetNextHashPos(WCC->urlstrings, Cursor, &HKLen, &HKey, &U)) {
+       Cursor = GetNewHashPos (WCC->Hdr->urlstrings, 0);
+       while (GetNextHashPos(WCC->Hdr->urlstrings, Cursor, &HKLen, &HKey, &U)) {
                u = (urlcontent*) U;
                wprintf("%38s = %s\n", u->url_key, ChrPtr(u->url_data));
        }
@@ -108,8 +108,8 @@ const char *XBstr(const char *key, size_t keylen, size_t *len)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, keylen, &U)) {
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, keylen, &U)) {
                *len = StrLength(((urlcontent *)U)->url_data);
                return ChrPtr(((urlcontent *)U)->url_data);
        }
@@ -123,8 +123,8 @@ const char *XBSTR(const char *key, size_t *len)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) &&
-           GetHash(WC->urlstrings, key, strlen (key), &U)){
+       if ((WC->Hdr->urlstrings != NULL) &&
+           GetHash(WC->Hdr->urlstrings, key, strlen (key), &U)){
                *len = StrLength(((urlcontent *)U)->url_data);
                return ChrPtr(((urlcontent *)U)->url_data);
        }
@@ -139,8 +139,8 @@ const char *BSTR(const char *key)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) &&
-           GetHash(WC->urlstrings, key, strlen (key), &U))
+       if ((WC->Hdr->urlstrings != NULL) &&
+           GetHash(WC->Hdr->urlstrings, key, strlen (key), &U))
                return ChrPtr(((urlcontent *)U)->url_data);
        else    
                return ("");
@@ -150,8 +150,8 @@ const char *Bstr(const char *key, size_t keylen)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, keylen, &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, keylen, &U))
                return ChrPtr(((urlcontent *)U)->url_data);
        else    
                return ("");
@@ -161,8 +161,8 @@ const StrBuf *SBSTR(const char *key)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) &&
-           GetHash(WC->urlstrings, key, strlen (key), &U))
+       if ((WC->Hdr->urlstrings != NULL) &&
+           GetHash(WC->Hdr->urlstrings, key, strlen (key), &U))
                return ((urlcontent *)U)->url_data;
        else    
                return NULL;
@@ -172,8 +172,8 @@ const StrBuf *SBstr(const char *key, size_t keylen)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, keylen, &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, keylen, &U))
                return ((urlcontent *)U)->url_data;
        else    
                return NULL;
@@ -183,8 +183,8 @@ long LBstr(const char *key, size_t keylen)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, keylen, &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, keylen, &U))
                return StrTol(((urlcontent *)U)->url_data);
        else    
                return (0);
@@ -194,8 +194,8 @@ long LBSTR(const char *key)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, strlen(key), &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
                return StrTol(((urlcontent *)U)->url_data);
        else    
                return (0);
@@ -205,8 +205,8 @@ int IBstr(const char *key, size_t keylen)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, keylen, &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, keylen, &U))
                return StrTol(((urlcontent *)U)->url_data);
        else    
                return (0);
@@ -216,8 +216,8 @@ int IBSTR(const char *key)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, strlen(key), &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
                return StrToi(((urlcontent *)U)->url_data);
        else    
                return (0);
@@ -227,8 +227,8 @@ int HaveBstr(const char *key, size_t keylen)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, keylen, &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, keylen, &U))
                return (StrLength(((urlcontent *)U)->url_data) != 0);
        else    
                return (0);
@@ -238,8 +238,8 @@ int HAVEBSTR(const char *key)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, strlen(key), &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
                return (StrLength(((urlcontent *)U)->url_data) != 0);
        else    
                return (0);
@@ -250,8 +250,8 @@ int YesBstr(const char *key, size_t keylen)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, keylen, &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, keylen, &U))
                return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
        else    
                return (0);
@@ -261,8 +261,8 @@ int YESBSTR(const char *key)
 {
        void *U;
 
-       if ((WC->urlstrings != NULL) && 
-           GetHash(WC->urlstrings, key, strlen(key), &U))
+       if ((WC->Hdr->urlstrings != NULL) && 
+           GetHash(WC->Hdr->urlstrings, key, strlen(key), &U))
                return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0;
        else    
                return (0);
@@ -296,8 +296,8 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp,
 #ifdef DEBUG_URLSTRINGS
        lprintf(9, "upload_handler() name=%s, type=%s, len=%d\n", name, cbtype, length);
 #endif
-       if (WC->urlstrings == NULL)
-               WC->urlstrings = NewHash(1, NULL);
+       if (WC->Hdr->urlstrings == NULL)
+               WC->Hdr->urlstrings = NewHash(1, NULL);
 
        /* Form fields */
        if ( (length > 0) && (IsEmptyStr(cbtype)) ) {
@@ -306,7 +306,7 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp,
                safestrncpy(u->url_key, name, sizeof(u->url_key));
                u->url_data = NewStrBufPlain(content, length);
                
-               Put(WC->urlstrings, u->url_key, strlen(u->url_key), u, free_url);
+               Put(WC->Hdr->urlstrings, u->url_key, strlen(u->url_key), u, free_url);
 #ifdef DEBUG_URLSTRINGS
                lprintf(9, "Key: <%s> len: [%ld] Data: <%s>\n", 
                        u->url_key, 
@@ -347,7 +347,7 @@ void PutBstr(const char *key, long keylen, StrBuf *Value)
        u = (urlcontent*)malloc(sizeof(urlcontent));
        memcpy(u->url_key, key, keylen + 1);
        u->url_data = Value;
-       Put(WC->urlstrings, u->url_key, keylen, u, free_url);
+       Put(WC->Hdr->urlstrings, u->url_key, keylen, u, free_url);
 }
 
 
@@ -377,11 +377,13 @@ void diagnostics(void)
        output_headers(1, 1, 1, 0, 0, 0);
        wprintf("Session: %d<hr />\n", WC->wc_session);
        wprintf("Command: <br /><PRE>\n");
-       StrEscPuts(WC->UrlFragment1);
+/*     
+StrEscPuts(WC->UrlFragment1);
        wprintf("<br />\n");
        StrEscPuts(WC->UrlFragment2);
        wprintf("<br />\n");
        StrEscPuts(WC->UrlFragment3);
+*/
        wprintf("</PRE><hr />\n");
        wprintf("Variables: <br /><PRE>\n");
        dump_vars();
@@ -396,16 +398,24 @@ void tmplput_url_part(StrBuf *Target, WCTemplputParams *TP)
        wcsession *WCC = WC;
        
        if (WCC != NULL) {
-               if (TP->Tokens->Params[0]->lvalue == 0)
-                       UrlBuf = WCC->UrlFragment1;
-               else if (TP->Tokens->Params[0]->lvalue == 1)
-                       UrlBuf = WCC->UrlFragment2;
-               else
-                       UrlBuf = WCC->UrlFragment3;
+               if (TP->Tokens->Params[0]->lvalue == 0) {
+                       UrlBuf = NewStrBuf();
+                       StrBufExtract_token(UrlBuf, WCC->Hdr->ReqLine, 1, '/');
+               }
+               else if (TP->Tokens->Params[0]->lvalue == 1) {
+                       UrlBuf = NewStrBuf();
+                       StrBufExtract_token(UrlBuf, WCC->Hdr->ReqLine, 2, '/');
+               }
+               else {
+                       UrlBuf = NewStrBuf();
+                       StrBufExtract_token(UrlBuf, WCC->Hdr->ReqLine, 3, '/');
+               }
+
                if (UrlBuf == NULL)  {
                        LogTemplateError(Target, "urlbuf", ERR_PARM1, TP, "not set.");
                }
                StrBufAppendTemplate(Target, TP, UrlBuf, 2);
+               FreeStrBuf(&UrlBuf);
        }
 }
 
@@ -426,12 +436,12 @@ void
 SessionAttachModule_PARAMHANDLING
 (wcsession *sess)
 {
-       sess->urlstrings = NewHash(1,NULL);
+       sess->Hdr->urlstrings = NewHash(1,NULL);
 }
 
 void
 SessionDetachModule_PARAMHANDLING
 (wcsession *sess)
 {
-       DeleteHash(&sess->urlstrings);
+       DeleteHash(&sess->Hdr->urlstrings);
 }
index 4161ad18954659e4731dba3b4bb2001a868b6e29..174e0e33e0c107411d551699491408c0186db68b 100644 (file)
@@ -911,7 +911,7 @@ void DeleteGVSNHash(HashList **KillMe)
 void offer_start_page(StrBuf *Target, WCTemplputParams *TP)
 {
        wprintf("<a href=\"change_start_page?startpage=");
-       urlescputs(ChrPtr(WC->this_page));
+       urlescputs(ChrPtr(WC->Hdr->this_page));
        wprintf("\">");
        wprintf(_("Make this my start page"));
        wprintf("</a>");
index 442d167ac5b7e086d4a35f6e301110a2bb293330..41da33ceb40cdc1ef72e79bf4e350df61067fb30 100644 (file)
@@ -472,6 +472,7 @@ void embed_search_o_matic(StrBuf *Target, WCTemplputParams *TP)
  */
 
 void embed_room_banner(char *got, int navbar_style) {
+       wcsession *WCC = WC;
        char buf[256];
        char buf2[1024];
        char with_files[256];
@@ -501,9 +502,9 @@ void embed_room_banner(char *got, int navbar_style) {
         * we want it to remember the URL as a "/dotskip" one instead of
         * a "skip" or "gotonext" or something like that.
         */
-       if (WC->this_page == NULL)
-               WC->this_page = NewStrBuf();
-       StrBufPrintf(WC->this_page, 
+       if (WCC->Hdr->this_page == NULL)
+               WCC->Hdr->this_page = NewStrBuf();
+       StrBufPrintf(WCC->Hdr->this_page, 
                     "dotskip&room=%s",
                     ChrPtr(WC->wc_roomname));
 
@@ -1818,7 +1819,7 @@ void display_editroom(void)
                wprintf(_("The URL for subscribe/unsubscribe is: "));
                wprintf("<TT>%s://%s/listsub</TT></td></tr>\n",
                        (is_https ? "https" : "http"),
-                       ChrPtr(WC->http_host));
+                       ChrPtr(WC->Hdr->http_host));
                /* Public posting? */
                wprintf("<tr><td>");
                wprintf(_("Allow non-subscribers to mail to this room."));
@@ -3312,7 +3313,7 @@ void set_floordiv_expanded(void) {
        StrBuf *FloorDiv;
        
        FloorDiv = NewStrBuf();
-       StrBufAppendBuf(FloorDiv, WCC->UrlFragment2, 0);
+       StrBufExtract_token(FloorDiv, WCC->Hdr->ReqLine, 2, '/');
        set_preference("floordiv_expanded", FloorDiv, 1);
        WCC->floordiv_expanded = FloorDiv;
 }
index 09e17d0e4450df62b716408251eb335cc173642e..7f61889164789828b53b3ca7a6a921cc00a0ea87 100644 (file)
@@ -12,7 +12,6 @@
 #define ALLOW_ANON_RSS 0
 #define ANON_RSS_USER ""
 #define ANON_RSS_PASS ""
-time_t if_modified_since;    /**< the last modified stamp */
 
 /*
  * view rss Config menu
@@ -135,7 +134,7 @@ void display_rss(const StrBuf *roomname)
                }
        }
        /*/ Commented out. Play dumb for now, also doesn't work with anonrss hack */
-       /* if (if_modified_since > 0 && if_modified_since > now) {
+       /* if (WCC->Hdr->if_modified_since > 0 && WCC->Hdr->if_modified_since > now) {
                lprintf(3, "RSS: Feed not updated since the last time you looked\n");
                hprintf("HTTP/1.1 304 Not Modified\r\n");
                hprintf("Last-Modified: %s\r\n", date);
@@ -156,7 +155,7 @@ void display_rss(const StrBuf *roomname)
        hprintf("Content-Type: application/rss+xml\r\n");
        hprintf("Server: %s\r\n", PACKAGE_STRING);
        hprintf("Connection: close\r\n");
-       if (WCC->eReqType == eHEAD)
+       if (WCC->Hdr->eReqType == eHEAD)
                return;
 
        /* <?xml.. etc confuses our subst parser, so do it here */
@@ -165,7 +164,7 @@ void display_rss(const StrBuf *roomname)
        SVPutBuf("ROOM", WCC->wc_roomname, 1);
        SVPutBuf("NODE", WCC->serv_info->serv_humannode, 1);
        /* TODO:  Fix me */
-       svprintf(HKEY("ROOM_LINK"), WCS_STRING, "%s://%s/", (is_https ? "https" : "http"), ChrPtr(WCC->http_host));
+       svprintf(HKEY("ROOM_LINK"), WCS_STRING, "%s://%s/", (is_https ? "https" : "http"), ChrPtr(WCC->Hdr->http_host));
        
        /** Get room info for description */
        serv_puts("RINF");
@@ -370,3 +369,10 @@ ENDITEM:
 }
 
 
+void 
+InitModule_RSS
+(void)
+{
+       WebcitAddUrlHandler(HKEY("do_welcome"), display_rss, COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
+
+}
index 23e646baca9fddabbb0eac5c2cb09960e6147bf5..88289bde65adabc9c242d14b94dac00a303fef1a 100644 (file)
@@ -5,6 +5,8 @@
 #include "webcit.h"
 #include "webserver.h"
 
+int is_uds = 0;
+char serv_sock_name[PATH_MAX] = "";
 
 void DeleteServInfo(ServInfo **FreeMe)
 {
@@ -29,7 +31,7 @@ void DeleteServInfo(ServInfo **FreeMe)
  * browser_host                the citadell we want to connect to
  * user_agent          which browser uses our client?
  */
-ServInfo *get_serv_info(StrBuf *browser_host, char *user_agent)
+ServInfo *get_serv_info(StrBuf *browser_host, StrBuf *user_agent)
 {
        ServInfo *info;
        StrBuf *Buf;
@@ -41,7 +43,7 @@ ServInfo *get_serv_info(StrBuf *browser_host, char *user_agent)
                    DEVELOPER_ID,
                    CLIENT_ID,
                    CLIENT_VERSION,
-                   user_agent,
+                   ChrPtr(user_agent),
                    ChrPtr(browser_host)
        );
        StrBuf_ServGetln(Buf);
@@ -128,7 +130,160 @@ ServInfo *get_serv_info(StrBuf *browser_host, char *user_agent)
        return info;
 }
 
+int GetConnected (void)
+{
+       StrBuf *Buf;
+       wcsession *WCC = WC;
+
+       if (WCC->ReadBuf == NULL)
+               WCC->ReadBuf = NewStrBuf();
+       if (is_uds) /* unix domain socket */
+               WCC->serv_sock = uds_connectsock(serv_sock_name);
+       else        /* tcp socket */
+               WCC->serv_sock = tcp_connectsock(ctdlhost, ctdlport);
+       
+       if (WCC->serv_sock < 0) {
+               do_logout();
+               FreeStrBuf(&WCC->ReadBuf);
+               return 1;
+       }
+       else {
+               long Status;
+               Buf = NewStrBuf();
+               WCC->connected = 1;
+               StrBuf_ServGetln(Buf);  /* get the server greeting */
+               GetServerStatus(Buf, &Status);
+               FreeStrBuf(&Buf);
+               /* Are there too many users already logged in? */
+               if (Status == 571) {
+                       wprintf(_("This server is already serving its maximum number of users and cannot accept any additional logins at this time.  Please try again later or contact your system administrator."));
+                       end_burst();
+                       end_webcit_session();
+                       return 1;
+               }
+
+               /*
+                * From what host is our user connecting?  Go with
+                * the host at the other end of the HTTP socket,
+                * unless we are following X-Forwarded-For: headers
+                * and such a header has already turned up something.
+                */
+               if ( (!follow_xff) || (StrLength(WCC->Hdr->browser_host) == 0) ) {
+                       if (WCC->Hdr->browser_host == NULL) {
+                               WCC->Hdr->browser_host = NewStrBuf();
+                               Put(WCC->Hdr->HTTPHeaders, HKEY("FreeMeWithTheOtherHeaders"), 
+                                   WCC->Hdr->browser_host, HFreeStrBuf);
+                       }
+                       locate_host(WCC->Hdr->browser_host, WCC->Hdr->http_sock);
+               }
+               if (WCC->serv_info == NULL)
+                       WCC->serv_info = get_serv_info(WCC->Hdr->browser_host, WCC->Hdr->user_agent);
+               if (WCC->serv_info == NULL){
+                       begin_burst();
+                       wprintf(_("Received unexpected answer from Citadel "
+                                 "server; bailing out."));
+                       hprintf("HTTP/1.1 200 OK\r\n");
+                       hprintf("Content-type: text/plain; charset=utf-8\r\n");
+                       end_burst();
+                       end_webcit_session();
+                       return 1;
+               }
+               if (WCC->serv_info->serv_rev_level < MINIMUM_CIT_VERSION) {
+                       begin_burst();
+                       wprintf(_("You are connected to a Citadel "
+                                 "server running Citadel %d.%02d. \n"
+                                 "In order to run this version of WebCit "
+                                 "you must also have Citadel %d.%02d or"
+                                 " newer.\n\n\n"),
+                               WCC->serv_info->serv_rev_level / 100,
+                               WCC->serv_info->serv_rev_level % 100,
+                               MINIMUM_CIT_VERSION / 100,
+                               MINIMUM_CIT_VERSION % 100
+                               );
+                       hprintf("HTTP/1.1 200 OK\r\n");
+                       hprintf("Content-type: text/plain; charset=utf-8\r\n");
+                       end_burst();
+                       end_webcit_session();
+                       return 1;
+               }
+       }
+       if (WCC->ReadBuf == NULL)
+               WCC->ReadBuf = NewStrBuf();
+       if (is_uds)/* unix domain socket */
+               WCC->serv_sock = uds_connectsock(serv_sock_name);
+       else /* tcp socket */
+               WCC->serv_sock = tcp_connectsock(ctdlhost, ctdlport);
+       
+       if (WCC->serv_sock < 0) {
+               do_logout();
+               FreeStrBuf(&WCC->ReadBuf);
+               return 1;
+       }
+       else {
+               long Status;
+               StrBuf *Buf;
+
+               Buf = NewStrBuf();
+               WCC->connected = 1;
+               StrBuf_ServGetln(Buf);
+               GetServerStatus(Buf,&Status);
+               /* get the server greeting */
+               
+               /* Are there too many users already logged in? */
+               if (Status == 571) {
+                       wprintf(_("This server is already serving its maximum number of users and cannot accept any additional logins at this time.  Please try again later or contact your system administrator."));
+                       end_burst();
+                       end_webcit_session();
+                       return 1;
+               }
 
+               /*
+                * From what host is our user connecting?  Go with
+                * the host at the other end of the HTTP socket,
+                * unless we are following X-Forwarded-For: headers
+                * and such a header has already turned up something.
+                */
+               if ( (!follow_xff) || (StrLength(WCC->Hdr->browser_host) == 0) ) {
+                       if (WCC->Hdr->browser_host == NULL) {
+                               WCC->Hdr->browser_host = NewStrBuf();
+                               Put(WCC->Hdr->HTTPHeaders, HKEY("FreeMeWithTheOtherHeaders"), 
+                                   WCC->Hdr->browser_host, HFreeStrBuf);
+                       }
+                       locate_host(WCC->Hdr->browser_host, WCC->Hdr->http_sock);
+               }
+               if (WCC->serv_info == NULL)
+                       WCC->serv_info = get_serv_info(WCC->Hdr->browser_host, WCC->Hdr->user_agent);
+               if (WCC->serv_info == NULL){
+                       begin_burst();
+                       wprintf(_("Received unexpected answer from Citadel "
+                                 "server; bailing out."));
+                       hprintf("HTTP/1.1 200 OK\r\n");
+                       hprintf("Content-type: text/plain; charset=utf-8\r\n");
+                       end_burst();
+                       end_webcit_session();
+                       return 1;
+               }
+               if (WCC->serv_info->serv_rev_level < MINIMUM_CIT_VERSION) {
+                       begin_burst();
+                       wprintf(_("You are connected to a Citadel "
+                                 "server running Citadel %d.%02d. \n"
+                                 "In order to run this version of WebCit "
+                                 "you must also have Citadel %d.%02d or"
+                                 " newer.\n\n\n"),
+                               WCC->serv_info->serv_rev_level / 100,
+                               WCC->serv_info->serv_rev_level % 100,
+                               MINIMUM_CIT_VERSION / 100,
+                               MINIMUM_CIT_VERSION % 100
+                               );
+                       hprintf("HTTP/1.1 200 OK\r\n");
+                       hprintf("Content-type: text/plain; charset=utf-8\r\n");
+                       end_burst();
+                       end_webcit_session();
+                       return 1;
+               }
+       }
+       return 0;
+}
 
 /**
  *  Read Citadel variformat text and spit it out as HTML.
@@ -633,6 +788,9 @@ void
 InitModule_SERVFUNC
 (void)
 {
+       is_uds = strcasecmp(ctdlhost, "uds") == 0;
+       if (is_uds)
+               snprintf(serv_sock_name, PATH_MAX, "%s/citadel.socket", ctdlport);
 
        RegisterConditional(HKEY("COND:SERV:OPENID"), 2, conditional_serv_supports_openid, CTX_NONE);
        RegisterConditional(HKEY("COND:SERV:NEWU"), 2, conditional_serv_newuser_disabled, CTX_NONE);
index 46569a11b64fd71aeb8b5b2e3a48cf605a17217c..6842a99b9b943bdabec2fdd87ac88661bafd5838 100644 (file)
@@ -211,7 +211,7 @@ void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplpu
                                                      Error,
                                                      eERROR), 1);
 */
-               WildFireSerializePayload(Header, WCC->HBuf, &WCC->nWildfireHeaders, NULL);
+               WildFireSerializePayload(Header, WCC->HBuf, &WCC->Hdr->nWildfireHeaders, NULL);
        }
        else
        {
@@ -228,7 +228,7 @@ void LogTemplateError (StrBuf *Target, const char *Type, int ErrorPos, WCTemplpu
                             ChrPtr(Error), 
                             ChrPtr(TP->Tokens->FlatToken));
                SerializeJson(Header, WildFireException(HKEY(__FILE__), __LINE__, Info, 1), 1);
-               WildFireSerializePayload(Header, WCC->HBuf, &WCC->nWildfireHeaders, NULL);
+               WildFireSerializePayload(Header, WCC->HBuf, &WCC->Hdr->nWildfireHeaders, NULL);
        }
        FreeStrBuf(&Header);
        FreeStrBuf(&Info);
@@ -267,7 +267,7 @@ void LogError (StrBuf *Target, const char *Type, const char *Format, ...)
                                                0,
                                                Info,
                                                1), 1);
-       WildFireSerializePayload(Header, WCC->HBuf, &WCC->nWildfireHeaders, NULL);
+       WildFireSerializePayload(Header, WCC->HBuf, &WCC->Hdr->nWildfireHeaders, NULL);
        
        FreeStrBuf(&Header);
        FreeStrBuf(&Info);
index 9c74b5782b8a4c1a094c7ecde2832426f81135f8..27fba51d19145153a0d510424667bfb5a1f3fb84 100644 (file)
@@ -585,7 +585,7 @@ long end_burst(void)
         fd_set wset;
         int fdflags;
 
-       if (!DisableGzip && (WCC->gzip_ok) && CompressBuffer(WCC->WBuf))
+       if (!DisableGzip && (WCC->Hdr->gzip_ok) && CompressBuffer(WCC->WBuf))
        {
                hprintf("Content-encoding: gzip\r\n");
        }
@@ -611,19 +611,19 @@ long end_burst(void)
        write(2, ptr, StrLength(WCC->WBuf));
        write(2, "\033[30m", 5);
 #endif
-       fdflags = fcntl(WC->http_sock, F_GETFL);
+       fdflags = fcntl(WC->Hdr->http_sock, F_GETFL);
 
        while (ptr < eptr) {
                 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
                         FD_ZERO(&wset);
-                        FD_SET(WCC->http_sock, &wset);
-                        if (select(WCC->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
+                        FD_SET(WCC->Hdr->http_sock, &wset);
+                        if (select(WCC->Hdr->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
                                 lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno));
                                 return -1;
                         }
                 }
 
-                if ((res = write(WCC->http_sock, 
+                if ((res = write(WCC->Hdr->http_sock, 
                                 ptr,
                                 count)) == -1) {
                         lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno));
@@ -648,14 +648,14 @@ long end_burst(void)
         while (ptr < eptr) {
                 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
                         FD_ZERO(&wset);
-                        FD_SET(WCC->http_sock, &wset);
-                        if (select(WCC->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
+                        FD_SET(WCC->Hdr->http_sock, &wset);
+                        if (select(WCC->Hdr->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
                                 lprintf(2, "client_write: Socket select failed (%s)\n", strerror(errno));
                                 return -1;
                         }
                 }
 
-                if ((res = write(WCC->http_sock, 
+                if ((res = write(WCC->Hdr->http_sock, 
                                 ptr,
                                 count)) == -1) {
                         lprintf(2, "client_write: Socket write failed (%s)\n", strerror(errno));
index 826a351423ff0e70fb238de2b412d4583a9e74bb..31780a6a136a2507be84e71501d558bb38df2482 100644 (file)
@@ -1218,7 +1218,7 @@ void display_vcard_photo_img(void)
        const char *contentType;
        wcsession *WCC = WC;
 
-       msgnum = StrTol(WCC->UrlFragment2);
+       msgnum = StrBufExtract_long(WCC->Hdr->ReqLine, 2, '/');
        
        vcard = load_mimepart(msgnum,"1");
        v = VCardLoad(vcard);
index 5057192c30f7aa28967b9d0fc6808cc6fd1428a1..e14fb312b69db16675a33dd16df1973c0b455197 100644 (file)
@@ -27,11 +27,7 @@ void WebcitAddUrlHandler(const char * UrlString,
                         WebcitHandlerFunc F, 
                         long Flags)
 {
-       WebcitHandler *NewHandler;
-
-       if (HandlerHash == NULL)
-               HandlerHash = NewHash(1, NULL);
-       
+       WebcitHandler *NewHandler;      
        NewHandler = (WebcitHandler*) malloc(sizeof(WebcitHandler));
        NewHandler->F = F;
        NewHandler->Flags = Flags;
@@ -296,7 +292,7 @@ void print_menu_box(char* Title, char *Class, int nLines, ...)
 /*
  * dump out static pages from disk
  */
-void output_static(const char *what)
+void output_static(void)
 {
        int fd;
        struct stat statbuf;
@@ -305,7 +301,7 @@ void output_static(const char *what)
        const char *content_type;
        int len;
        const char *Err;
-
+       char what[] = "TODO";
        fd = open(what, O_RDONLY);
        if (fd <= 0) {
                lprintf(9, "output_static('%s')  -- NOT FOUND --\n", what);
@@ -448,6 +444,55 @@ void end_ajax_response(void) {
         wDumpContent(0);
 }
 
+       /* If it's a "force 404" situation then display the error and bail. */
+void do_404(void)
+{
+       hprintf("HTTP/1.1 404 Not found\r\n");
+       hprintf("Content-Type: text/plain\r\n");
+       wprintf("Not found\r\n");
+       end_burst();
+}
+/* TODO: staticdata
+{
+       /* Static content can be sent without connecting to Citadel. * /
+       is_static = 0;
+       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;
+               }
+       }
+       if (is_static) {
+               if (nBackDots < 2)
+               {
+                       snprintf(buf, sizeof buf, "%s/%s/%s/%s/%s/%s/%s/%s",
+                                static_dirs[n_static], 
+                                index[1], index[2], index[3], index[4], index[5], index[6], index[7]);
+                       for (a=0; a<8; ++a) {
+                               if (buf[strlen(buf)-1] == '/') {
+                                       buf[strlen(buf)-1] = 0;
+                               }
+                       }
+                       for (a = 0; a < strlen(buf); ++a) {
+                               if (isspace(buf[a])) {
+                                       buf[a] = 0;
+                               }
+                       }
+                       output_static(buf);
+               }
+               else 
+               {
+                       lprintf(9, "Suspicious request. Ignoring.");
+                       hprintf("HTTP/1.1 404 Security check failed\r\n");
+                       hprintf("Content-Type: text/plain\r\n\r\n");
+                       wprintf("You have sent a malformed or invalid request.\r\n");
+                       end_burst();
+               }
+               goto SKIP_ALL_THIS_CRAP;        /* Don't try to connect * /
+       }
+       }*/
+
+
 /*
  * Wraps a Citadel server command in an AJAX transaction.
  */
@@ -540,79 +585,68 @@ void seconds_since_last_gexp(void)
        }
 }
 
-/**
- * \brief Detects a 'mobile' user agent 
- */
-int is_mobile_ua(char *user_agent) {
-      if (strstr(user_agent,"iPhone OS") != NULL) {
-       return 1;
-      } else if (strstr(user_agent,"Windows CE") != NULL) {
-       return 1;
-      } else if (strstr(user_agent,"SymbianOS") != NULL) {
-       return 1;
-      } else if (strstr(user_agent, "Opera Mobi") != NULL) {
-       return 1;
-      } else if (strstr(user_agent, "Firefox/2.0.0 Opera 9.51 Beta") != NULL) {
-             /*  For some reason a new install of Opera 9.51beta decided to spoof. */
-         return 1;
-         }
-      return 0;
+
+
+void ReadPostData(void)
+{
+       const char *content_end = NULL;
+       int body_start = 0;
+       wcsession *WCC = WC;
+       StrBuf *content = NULL;
+       
+       content = NewStrBuf();
+
+       StrBufPrintf(content, 
+                    "Content-type: %s\n"
+                    "Content-length: %ld\n\n",
+                    ChrPtr(WCC->Hdr->ContentType), 
+                            WCC->Hdr->ContentLength);
+/*
+  hprintf("Content-type: %s\n"
+  "Content-length: %d\n\n",
+  ContentType, ContentLength);
+*/
+       body_start = StrLength(content);
+
+       /** Read the entire input data at once. */
+       client_read_to(&WCC->Hdr->http_sock, 
+                      content, 
+                      WCC->Hdr->ReadBuf, &WCC->Hdr->Pos,
+                      WCC->Hdr->ContentLength,
+                      SLEEPING);
+       
+       if (!strncasecmp(ChrPtr(WCC->Hdr->ContentType), "application/x-www-form-urlencoded", 33)) {
+               StrBufCutLeft(content, body_start);
+               ParseURLParams(content);
+       } else if (!strncasecmp(ChrPtr(WCC->Hdr->ContentType), "multipart", 9)) {
+               content_end = ChrPtr(content) + 
+                       WCC->Hdr->ContentLength + 
+                       body_start;
+               mime_parser(ChrPtr(content), content_end, *upload_handler, NULL, NULL, NULL, 0);
+       }
+       FreeStrBuf(&content);
 }
 
 
 /*
  * Entry point for WebCit transaction
  */
-void session_loop(StrBuf *ReqLine, 
-                 StrBuf *ReadBuf,
-                 const char **Pos)
+void session_loop(void)
 {
+       int Flags = 0;
+       int xhttp;
        StrBuf *Buf;
-       const char *pch, *pchs, *pche;
-       void *vLine;
-       char action[1024];
-       char arg[8][128];
-       size_t sizes[10];
-       char *index[10];
+       
        char buf[SIZ];
-       int a, nBackDots, nEmpty;
-       int ContentLength = 0;
-       StrBuf *ContentType = NULL;
-       StrBuf *UrlLine = NULL;
-       StrBuf *content = NULL;
-       const char *content_end = NULL;
-       StrBuf *browser_host = NULL;
-       char user_agent[256];
-       int body_start = 0;
-       int is_static = 0;
-       int n_static = 0;
-       int len = 0;
-       void *vHandler;
-       WebcitHandler *Handler;
-       struct timeval tx_start;
-       struct timeval tx_finish;
 
        /*
         * We stuff these with the values coming from the client cookies,
         * so we can use them to reconnect a timed out session if we have to.
         */
-       StrBuf *c_username;
-       StrBuf *c_password;
-       StrBuf *c_roomname;
-       char c_httpauth_string[SIZ];
-       StrBuf *c_httpauth_user;
-       StrBuf *c_httpauth_pass;
        wcsession *WCC;
 
-       gettimeofday(&tx_start, NULL);          /* start a stopwatch for performance timing */
        
        Buf = NewStrBuf();
-       c_username = NewStrBuf();
-       c_password = NewStrBuf();
-       c_roomname = NewStrBuf();
-       safestrncpy(c_httpauth_string, "", sizeof c_httpauth_string);
-       c_httpauth_user = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_USER));
-       c_httpauth_pass = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_PASS));
 
        WCC= WC;
 
@@ -620,9 +654,10 @@ void session_loop(StrBuf *ReqLine,
        WCC->upload = NULL;
        WCC->is_mobile = 0;
        WCC->trailing_javascript = NewStrBuf();
-       WCC->nWildfireHeaders = 0;
-
-       /** Figure out the action */
+       WCC->Hdr->nWildfireHeaders = 0;
+       if (WCC->Hdr->Handler != NULL)
+               Flags = WCC->Hdr->Handler->Flags; /* so we can temporarily add our own... */
+       /** Figure out the action * /
        index[0] = action;
        sizes[0] = sizeof action;
        for (a=1; a<9; a++)
@@ -632,168 +667,26 @@ void session_loop(StrBuf *ReqLine,
        }
        nBackDots = 0;
        nEmpty = 0;
-       for ( a = 0; a < 9; ++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;
-               if ((index[a][0] == '.') && (index[a][1] == '.'))
-                       nBackDots++;
-               if (index[a][0] == '\0')
-                       nEmpty++;
-       }
-
-
-       if (GetHash(WCC->headers, HKEY("COOKIE"), &vLine) && 
-           (vLine != NULL)){
-               cookie_to_stuff((StrBuf *)vLine, NULL,
-                               c_username,
-                               c_password,
-                               c_roomname);
-       }
-       if (GetHash(WCC->headers, HKEY("AUTHORIZATION"), &vLine) &&
-           (vLine!=NULL)) {
-               StrBufDecodeBase64((StrBuf*)vLine);
-               StrBufExtract_token(c_httpauth_user, (StrBuf*)vLine, 0, ':');
-               StrBufExtract_token(c_httpauth_pass, (StrBuf*)vLine, 1, ':');
-       }
-       if (GetHash(WCC->headers, HKEY("CONTENT-LENGTH"), &vLine) &&
-           (vLine!=NULL)) {
-               ContentLength = StrToi((StrBuf*)vLine);
-       }
-       if (GetHash(WCC->headers, HKEY("CONTENT-TYPE"), &vLine) &&
-           (vLine!=NULL)) {
-               ContentType = (StrBuf*)vLine;
-       }
-       if (GetHash(WCC->headers, 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 {
-                       WCC->is_mobile = 0;
-               }
-#endif
-       }
-       if ((follow_xff) &&
-           GetHash(WCC->headers, HKEY("X-FORWARDED-HOST"), &vLine) &&
-           (vLine != NULL)) {
-               WCC->http_host = (StrBuf*)vLine;
-       }
-       if ((StrLength(WCC->http_host) == 0) && 
-           GetHash(WCC->headers, HKEY("HOST"), &vLine) &&
-           (vLine!=NULL)) {
-               WCC->http_host = (StrBuf*)vLine;
-       }
-
-       if (GetHash(WCC->headers, HKEY("X-FORWARDED-FOR"), &vLine) &&
-           (vLine!=NULL)) {
-               browser_host = (StrBuf*) vLine;
-
-               while (StrBufNum_tokens(browser_host, ',') > 1) {
-                       StrBufRemove_token(browser_host, 0, ',');
-               }
-               StrBufTrim(browser_host);
-       }
-
-       if (ContentLength > 0) {
-               content = NewStrBuf();
-               StrBufPrintf(content, "Content-type: %s\n"
-                        "Content-length: %d\n\n",
-                        ChrPtr(ContentType), ContentLength);
 /*
-               hprintf("Content-type: %s\n"
-                       "Content-length: %d\n\n",
-                       ContentType, ContentLength);
+  for ( a = 0; a < 9; ++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;
+  if ((index[a][0] == '.') && (index[a][1] == '.'))
+  nBackDots++;
+  if (index[a][0] == '\0')
+  nEmpty++;
+  }
 */
-               body_start = StrLength(content);
-
-               /** Read the entire input data at once. */
-               client_read_to(&WCC->http_sock, 
-                              content, 
-                              ReadBuf, Pos,
-                              ContentLength,
-                              SLEEPING);
-
-               if (!strncasecmp(ChrPtr(ContentType), "application/x-www-form-urlencoded", 33)) {
-                       StrBufCutLeft(content, body_start);
-                       ParseURLParams(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;
+       if (WCC->Hdr->ContentLength > 0) {
+               ReadPostData();
        }
 
-       /* make a note of where we are in case the user wants to save it */
-       WCC->this_page = NewStrBufDup(ReqLine);
-       StrBufRemove_token(WCC->this_page, 2, ' ');
-       StrBufRemove_token(WCC->this_page, 0, ' ');
-
        /* If there are variables in the URL, we must grab them now */
-       UrlLine = NewStrBufDup(ReqLine);
-       len = StrLength(UrlLine);
-       pch = pchs = ChrPtr(UrlLine);
-       pche = pchs + len;
-       while (pch < pche) {
-               if ((*pch == '?') || (*pch == '&')) {
-                       StrBufCutLeft(UrlLine, pch - pchs + 1);
-                       ParseURLParams(UrlLine);
-                       break;
-               }
-               pch ++;
-       }
-       FreeStrBuf(&UrlLine);
-
-       /* If it's a "force 404" situation then display the error and bail. */
-       if (!strcmp(action, "404")) {
-               hprintf("HTTP/1.1 404 Not found\r\n");
-               hprintf("Content-Type: text/plain\r\n");
-               wprintf("Not found\r\n");
-               end_burst();
-               goto SKIP_ALL_THIS_CRAP;
-       }
-
-       /* Static content can be sent without connecting to Citadel. */
-       is_static = 0;
-       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;
-               }
-       }
-       if (is_static) {
-               if (nBackDots < 2)
-               {
-                       snprintf(buf, sizeof buf, "%s/%s/%s/%s/%s/%s/%s/%s",
-                                static_dirs[n_static], 
-                                index[1], index[2], index[3], index[4], index[5], index[6], index[7]);
-                       for (a=0; a<8; ++a) {
-                               if (buf[strlen(buf)-1] == '/') {
-                                       buf[strlen(buf)-1] = 0;
-                               }
-                       }
-                       for (a = 0; a < strlen(buf); ++a) {
-                               if (isspace(buf[a])) {
-                                       buf[a] = 0;
-                               }
-                       }
-                       output_static(buf);
-               }
-               else 
-               {
-                       lprintf(9, "Suspicious request. Ignoring.");
-                       hprintf("HTTP/1.1 404 Security check failed\r\n");
-                       hprintf("Content-Type: text/plain\r\n\r\n");
-                       wprintf("You have sent a malformed or invalid request.\r\n");
-                       end_burst();
-               }
-               goto SKIP_ALL_THIS_CRAP;        /* Don't try to connect */
-       }
+       if (WCC->Hdr->PlainArgs != NULL)
+               ParseURLParams(WCC->Hdr->PlainArgs);
 
        /* If the client sent a nonce that is incorrect, kill the request. */
        if (havebstr("nonce")) {
@@ -814,123 +707,28 @@ void session_loop(StrBuf *ReqLine,
         * connection now.
         */
        if (!WCC->connected) {
-               if (WCC->ReadBuf == NULL)
-                       WCC->ReadBuf = NewStrBuf();
-               if (!strcasecmp(ctdlhost, "uds")) {
-                       /* unix domain socket */
-                       snprintf(buf, SIZ, "%s/citadel.socket", ctdlport);
-                       WCC->serv_sock = uds_connectsock(buf);
-               }
-               else {
-                       /* tcp socket */
-                       WCC->serv_sock = tcp_connectsock(ctdlhost, ctdlport);
-               }
-
-               if (WCC->serv_sock < 0) {
-                       do_logout();
-                       FreeStrBuf(&WCC->ReadBuf);
+               if (GetConnected ())
                        goto SKIP_ALL_THIS_CRAP;
-               }
-               else {
-                       WCC->connected = 1;
-                       serv_getln(buf, sizeof buf);    /* get the server greeting */
-
-                       /* Are there too many users already logged in? */
-                       if (!strncmp(buf, "571", 3)) {
-                               wprintf(_("This server is already serving its maximum number of users and cannot accept any additional logins at this time.  Please try again later or contact your system administrator."));
-                               end_burst();
-                               end_webcit_session();
-                               goto SKIP_ALL_THIS_CRAP;
-                       }
-
-                       /*
-                        * From what host is our user connecting?  Go with
-                        * the host at the other end of the HTTP socket,
-                        * unless we are following X-Forwarded-For: headers
-                        * and such a header has already turned up something.
-                        */
-                       if ( (!follow_xff) || (StrLength(browser_host) == 0) ) {
-                               if (browser_host == NULL) {
-                                       browser_host = NewStrBuf();
-                                       Put(WCC->headers, HKEY("FreeMeWithTheOtherHeaders"), 
-                                           browser_host, HFreeStrBuf);
-                               }
-                               locate_host(browser_host, WCC->http_sock);
-                       }
-                       if (WCC->serv_info == NULL)
-                               WCC->serv_info = get_serv_info(browser_host, user_agent);
-                       if (WCC->serv_info == NULL){
-                               begin_burst();
-                               wprintf(_("Received unexpected answer from Citadel "
-                                         "server; bailing out."));
-                               hprintf("HTTP/1.1 200 OK\r\n");
-                               hprintf("Content-type: text/plain; charset=utf-8\r\n");
-                               end_burst();
-                               end_webcit_session();
-                               goto SKIP_ALL_THIS_CRAP;
-                       }
-                       if (WCC->serv_info->serv_rev_level < MINIMUM_CIT_VERSION) {
-                               begin_burst();
-                               wprintf(_("You are connected to a Citadel "
-                                       "server running Citadel %d.%02d. \n"
-                                       "In order to run this version of WebCit "
-                                       "you must also have Citadel %d.%02d or"
-                                       " newer.\n\n\n"),
-                                               WCC->serv_info->serv_rev_level / 100,
-                                               WCC->serv_info->serv_rev_level % 100,
-                                               MINIMUM_CIT_VERSION / 100,
-                                               MINIMUM_CIT_VERSION % 100
-                                       );
-                               hprintf("HTTP/1.1 200 OK\r\n");
-                               hprintf("Content-type: text/plain; charset=utf-8\r\n");
-                               end_burst();
-                               end_webcit_session();
-                               goto SKIP_ALL_THIS_CRAP;
-                       }
-               }
        }
 
-       /*
-        * Functions which can be performed without logging in
-        */
-       if (!strcasecmp(action, "listsub")) {
-               do_listsub();
-               goto SKIP_ALL_THIS_CRAP;
-       }
-       if (!strcasecmp(action, "freebusy")) {
-               do_freebusy(ChrPtr(ReqLine));
-               goto SKIP_ALL_THIS_CRAP;
-       }
 
        /*
         * If we're not logged in, but we have HTTP Authentication data,
         * try logging in to Citadel using that.
         */
        if ((!WCC->logged_in)
-           && (StrLength(c_httpauth_user) > 0)
-           && (StrLength(c_httpauth_pass) > 0))
+           && (StrLength(WCC->Hdr->c_username) > 0)
+           && (StrLength(WCC->Hdr->c_password) > 0))
        {
                FlushStrBuf(Buf);
-               serv_printf("USER %s", ChrPtr(c_httpauth_user));
+               serv_printf("USER %s", ChrPtr(WCC->Hdr->c_username));
                StrBuf_ServGetln(Buf);
                if (GetServerStatus(Buf, NULL) == 3) {
-                       serv_printf("PASS %s", ChrPtr(c_httpauth_pass));
+                       serv_printf("PASS %s", ChrPtr(WCC->Hdr->c_password));
                        StrBuf_ServGetln(Buf);
                        if (GetServerStatus(Buf, NULL) == 2) {
-                               become_logged_in(c_httpauth_user,
-                                               c_httpauth_pass, Buf);
-                               if (WCC->httpauth_user == NULL)
-                                       WCC->httpauth_user = NewStrBufDup(c_httpauth_user);
-                               else {
-                                       FlushStrBuf(WCC->httpauth_user);
-                                       StrBufAppendBuf(WCC->httpauth_user, c_httpauth_user, 0);
-                               }
-                               if (WCC->httpauth_pass == NULL)
-                                       WCC->httpauth_pass = NewStrBufDup(c_httpauth_pass);
-                               else {
-                                       FlushStrBuf(WCC->httpauth_pass);
-                                       StrBufAppendBuf(WCC->httpauth_pass, c_httpauth_pass, 0);
-                               }
+                               become_logged_in(WCC->Hdr->c_username,
+                                                WCC->Hdr->c_password, Buf);
                        } else {
                                /* Should only display when password is wrong */
                                authorization_required(&buf[4]);
@@ -940,63 +738,18 @@ void session_loop(StrBuf *ReqLine,
                }
        }
 
-       /* This needs to run early */
-#ifdef TECH_PREVIEW
-       if (!strcasecmp(action, "rss")) {
-               display_rss(sbstr("room"));
-               goto SKIP_ALL_THIS_CRAP;
-       }
-#endif
-
-       /* 
-        * The GroupDAV stuff relies on HTTP authentication instead of
-        * our session's authentication.
-        */
-       if (!strncasecmp(action, "groupdav", 8)) {
-               groupdav_main(WCC->headers, 
-                             ReqLine, 
-                             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 */
-               goto SKIP_ALL_THIS_CRAP;
-       }
-
-
-       /*
-        * Automatically send requests with any method other than GET or
-        * POST to the GroupDAV code as well.
-        */
-       if ((WCC->eReqType != eGET) &&
-           (WCC->eReqType != ePOST) &&
-           (WCC->eReqType != eHEAD)) {
-               groupdav_main(WCC->headers, ReqLine, 
-                             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 */
-               goto SKIP_ALL_THIS_CRAP;
-       }
+       xhttp = (WCC->Hdr->eReqType != eGET) &&
+               (WCC->Hdr->eReqType != ePOST) &&
+               (WCC->Hdr->eReqType != eHEAD);
 
        /*
         * If we're not logged in, but we have username and password cookies
         * supplied by the browser, try using them to log in.
         */
        if ((!WCC->logged_in)
-          && (StrLength(c_username)>0)
-          && (StrLength(c_password)>0)) {
-               serv_printf("USER %s", ChrPtr(c_username));
-               StrBuf_ServGetln(Buf);
-               if (GetServerStatus(Buf, NULL) == 3) {
-                       serv_printf("PASS %s", ChrPtr(c_password));
-                       StrBuf_ServGetln(Buf);
-                       if (GetServerStatus(Buf, NULL) == 2) {
-                               become_logged_in(c_username, c_password, Buf);
-                               get_preference("default_header_charset", &WCC->DefaultCharset);
-                       }
-               }
+          && (StrLength(WCC->Hdr->c_username)>0)
+          && (StrLength(WCC->Hdr->c_password)>0)) {
+               ReEstablish_Session();
        }
 
        /*
@@ -1004,35 +757,19 @@ void session_loop(StrBuf *ReqLine,
         * prior to doing anything else.
         */
        if (havebstr("gotofirst")) {
-               gotoroom(sbstr("gotofirst"));   /* do this quietly to avoid session output! */
+               int ret;
+               ret = gotoroom(sbstr("gotofirst"));     /* do this quietly to avoid session output! */
+               if (ret != 0)
+                       lprintf(1, "GOTOFIRST: Unable to change to [%s]; Reason: %d\n", bstr("gotofirst"), ret);
        }
 
-       /*
-        * If we don't have a current room, but a cookie specifying the
-        * current room is supplied, make an effort to go there.
-        */
-       if ((StrLength(WCC->wc_roomname) == 0) && (StrLength(c_roomname) > 0)) {
-               serv_printf("GOTO %s", ChrPtr(c_roomname));
-               StrBuf_ServGetln(Buf);
-               if (GetServerStatus(Buf, NULL) == 2) {
-                       if (WCC->wc_roomname == NULL) {
-                               WCC->wc_roomname = NewStrBufDup(c_roomname);
-                       }
-                       else {
-                               FlushStrBuf(WCC->wc_roomname);
-                               StrBufAppendBuf(WCC->wc_roomname, c_roomname, 0);
-                       }
-               }
-       }
-       
-       GetHash(HandlerHash, action, strlen(action) /* TODO*/, &vHandler),
-               Handler = (WebcitHandler*) vHandler;
-       if (Handler != NULL) {
-               if (!WCC->logged_in && ((Handler->Flags & ANONYMOUS) == 0)) {
+       if (WCC->Hdr->Handler != NULL) {
+               if (!WCC->logged_in && ((WCC->Hdr->Handler->Flags & ANONYMOUS) == 0)) {
                        display_login(NULL);
                }
                else {
-                       if((Handler->Flags & NEED_URL)) {
+/*
+                       if((WCC->Hdr->Handler->Flags & NEED_URL)) {
                                if (WCC->UrlFragment1 == NULL)
                                        WCC->UrlFragment1 = NewStrBuf();
                                if (WCC->UrlFragment2 == NULL)
@@ -1046,10 +783,11 @@ void session_loop(StrBuf *ReqLine,
                                StrBufPlain(WCC->UrlFragment3, index[2], -1);
                                StrBufPlain(WCC->UrlFragment4, index[3], -1);
                        }
-                       if ((Handler->Flags & AJAX) != 0)
+*/
+                       if ((WCC->Hdr->Handler->Flags & AJAX) != 0)
                                begin_ajax_response();
-                       Handler->F();
-                       if ((Handler->Flags & AJAX) != 0)
+                       WCC->Hdr->Handler->F();
+                       if ((WCC->Hdr->Handler->Flags & AJAX) != 0)
                                end_ajax_response();
                }
        }
@@ -1067,26 +805,8 @@ SKIP_ALL_THIS_CRAP:
                WCC->SavePrefsToServer = 0;
        }
        FreeStrBuf(&Buf);
-       FreeStrBuf(&c_username);
-       FreeStrBuf(&c_password);
-       FreeStrBuf(&c_roomname);
-       FreeStrBuf(&c_httpauth_user);
-       FreeStrBuf(&c_httpauth_pass);
-       FreeStrBuf(&WCC->this_page);
        fflush(stdout);
-       if (content != NULL) {
-               FreeStrBuf(&content);
-               content = NULL;
-       }
-       WCC->http_host = NULL;
-
-       /* How long did this transaction take? */
-       gettimeofday(&tx_finish, NULL);
-       
-       lprintf(9, "Transaction completed in %ld.%06ld seconds.\n",
-               ((tx_finish.tv_sec*1000000 + tx_finish.tv_usec) - (tx_start.tv_sec*1000000 + tx_start.tv_usec)) / 1000000,
-               ((tx_finish.tv_sec*1000000 + tx_finish.tv_usec) - (tx_start.tv_sec*1000000 + tx_start.tv_usec)) % 1000000
-       );
+       WCC->Hdr->http_host = NULL;
 }
 
 
@@ -1145,14 +865,43 @@ void tmplput_csslocal(StrBuf *Target, WCTemplputParams *TP)
 
 extern char static_local_dir[PATH_MAX];
 
+
+       /* TODO: integrate this into the static startup logic
+
+        * While we're at it, gracefully handle requests for the
+        * robots.txt and favicon.ico files.
+        * /
+       if ((StrLength(ReqLine) >= 11) &&
+           !strncasecmp(ChrPtr(ReqLine), "/robots.txt", 11)) {
+               StrBufPlain(ReqLine, 
+                           HKEY("/static/robots.txt"
+                                "?force_close_session=yes HTTP/1.1"));
+               Hdr.eReqType = eGET;
+       }
+       else if ((StrLength(ReqLine) >= 11) &&
+                !strncasecmp(ChrPtr(ReqLine), "/favicon.ico", 12)) {
+               StrBufPlain(ReqLine, HKEY("/static/favicon.ico"));
+               Hdr.eReqType = eGET;
+       }
+
+*/
 void 
 InitModule_WEBCIT
 (void)
 {
        char dir[SIZ];
+       WebcitAddUrlHandler(HKEY("404"), do_404, ANONYMOUS|COOKIEUNNEEDED);
+       WebcitAddUrlHandler(HKEY("blank"), blank_page, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
+
+       WebcitAddUrlHandler(HKEY("robots.txt"), output_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
+       WebcitAddUrlHandler(HKEY("favicon.ico"), output_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
+       WebcitAddUrlHandler(HKEY("static"), output_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
+       WebcitAddUrlHandler(HKEY("static.local"), output_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
+       WebcitAddUrlHandler(HKEY("tinymce"), output_static, ANONYMOUS|COOKIEUNNEEDED|ISSTATIC);
+
        WebcitAddUrlHandler(HKEY("blank"), blank_page, ANONYMOUS);
        WebcitAddUrlHandler(HKEY("do_template"), url_do_template, ANONYMOUS);
-       WebcitAddUrlHandler(HKEY("sslg"), seconds_since_last_gexp, AJAX);
+       WebcitAddUrlHandler(HKEY("sslg"), seconds_since_last_gexp, AJAX|LOGCHATTY);
        WebcitAddUrlHandler(HKEY("ajax_servcmd"), ajax_servcmd, 0);
 
        RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE);
@@ -1201,7 +950,7 @@ void
 SessionDetachModule_WEBCIT
 (wcsession *sess)
 {
-       DeleteHash(&sess->urlstrings);
+       DeleteHash(&sess->Hdr->urlstrings);// TODO?
        if (sess->upload_length > 0) {
                free(sess->upload);
                sess->upload_length = 0;
@@ -1224,10 +973,12 @@ SessionDestroyModule_WEBCIT
 {
        FreeStrBuf(&sess->WBuf);
        FreeStrBuf(&sess->HBuf);
+       /*
        FreeStrBuf(&sess->UrlFragment1);
        FreeStrBuf(&sess->UrlFragment2);
        FreeStrBuf(&sess->UrlFragment3);
        FreeStrBuf(&sess->UrlFragment4);
+       */
        FreeStrBuf(&sess->ImportantMsg);
 }
 
index 2d204cd6bdbe1ae085dc68a73874c668bea5fc36..6a2b13589e2e54cd933a6eb75fc440526fde66c8 100644 (file)
@@ -346,6 +346,33 @@ typedef struct _addrbookent {
 } addrbookent;
 
 
+
+
+#define AJAX (1<<0)
+#define ANONYMOUS (1<<1)
+#define NEED_URL (1<<2)
+#define XHTTP_COMMANDS (1<<3)
+#define BOGUS (1<<4)
+#define URLNAMESPACE (1<<4)
+#define LOGCHATTY (1<<5)
+#define COOKIEUNNEEDED (1<<6)
+#define ISSTATIC (1<<7)
+#define FORCE_SESSIONCLOSE (1<<8)
+
+
+typedef void (*WebcitHandlerFunc)(void);
+typedef struct  _WebcitHandler{
+       WebcitHandlerFunc F;
+       long Flags;
+} WebcitHandler;
+void WebcitAddUrlHandler(const char * UrlString, long UrlSLen, WebcitHandlerFunc F, long Flags);
+
+
+
+
+
+
+
 typedef struct _headereval {
        ExamineMsgHeaderFunc evaluator;
        int Type;
@@ -377,6 +404,49 @@ enum {
        eNONE
 };
 const char *ReqStrs[eNONE];
+
+
+
+typedef struct _ParsedHttpHdrs {
+       int http_sock;                          /**< HTTP server socket */
+       const char *Pos;
+       StrBuf *ReadBuf;
+
+       long eReqType;                          /**< eGET, ePOST.... */
+       const WebcitHandler *Handler;
+       
+       int DontNeedAuth;
+       int got_cookie;
+       long ContentLength;
+       time_t if_modified_since;
+       int gzip_ok;                            /**< Nonzero if Accept-encoding: gzip */
+
+       StrBuf *c_username;
+       StrBuf *c_password;
+       StrBuf *c_roomname;
+       StrBuf *RawCookie;
+       int desired_session;
+
+       StrBuf *ContentType;
+
+       StrBuf *RawLine;/* TODO: freeme */
+       StrBuf *ReqLine;
+       StrBuf *http_host;                      /**< HTTP Host: header */
+       StrBuf *browser_host;
+       StrBuf *user_agent;
+
+       StrBuf *UrlFragment1;                   /**< first urlfragment, if NEED_URL is specified by the handler*/
+       StrBuf *UrlFragment2;                   /**< second urlfragment, if NEED_URL is specified by the handler*/
+       StrBuf *UrlFragment3;                   /**< third urlfragment, if NEED_URL is specified by the handler*/
+       StrBuf *UrlFragment4;                   /**< fourth urlfragment, if NEED_URL is specified by the handler*/
+       StrBuf *this_page;                      /**< URL of current page */
+       StrBuf *PlainArgs; /*TODO: freeme*/
+       HashList *urlstrings;                   /**< variables passed to webcit in a URL */
+       HashList *HTTPHeaders;                  /**< the headers the client sent us */
+       int nWildfireHeaders;                   /**< how many wildfire headers did we already send? */
+} ParsedHttpHdrs;
+
+
 /*
  * One of these is kept for each active Citadel session.
  * HTTP transactions are bound to one at a time.
@@ -393,7 +463,6 @@ struct wcsession {
        int nonce;                              /**< session nonce (to prevent session riding) */
 
 /* Session local Members */
-       int http_sock;                          /**< HTTP server socket */
        int serv_sock;                          /**< Client socket to Citadel server */
        StrBuf *ReadBuf;                        /**< here we keep our stuff while reading linebuffered from the server. */
        StrBuf *MigrateReadLineBuf;             /**< here we buffer legacy server read stuff */
@@ -402,25 +471,15 @@ 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 */
+       int is_ajax;                            /** < are we doing an ajax request? */
 
 /* 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*/
-       StrBuf *UrlFragment3;                   /**< third urlfragment, if NEED_URL is specified by the handler*/
-       StrBuf *UrlFragment4;                   /**< fourth urlfragment, if NEED_URL is specified by the handler*/
+       ParsedHttpHdrs *Hdr;
        StrBuf *WBuf;                           /**< Our output buffer */
        StrBuf *HBuf;                           /**< Our HeaderBuffer */
-       StrBuf *this_page;                      /**< URL of current page */
-       HashList *urlstrings;                   /**< variables passed to webcit in a URL */
-       HashList *vars;                         /**< HTTP variable substitutions for this page */
-       HashList *headers;                      /**< the headers the client sent us */
-       StrBuf *http_host;                      /**< HTTP Host: header */
-       int is_ajax;                            /** < are we doing an ajax request? */
-       int gzip_ok;                            /**< Nonzero if Accept-encoding: gzip */
-       int nWildfireHeaders;                   /**< how many wildfire headers did we already send? */
 
+       HashList *vars;                         /**< HTTP variable substitutions for this page */
        StrBuf *trailing_javascript;            /**< extra javascript to be appended to page */
        char ImportantMessage[SIZ];             /**< ??? todo */
        StrBuf *ImportantMsg;
@@ -501,6 +560,17 @@ struct wcsession {
 
 };
 
+
+typedef void (*Header_Evaluator)(StrBuf *Line, ParsedHttpHdrs *hdr);
+
+typedef struct _HttpHeader {
+       Header_Evaluator H;
+       StrBuf *Val;
+       int HaveEvaluator;
+} OneHttpHeader;
+
+
+
 /* values for WC->current_iconbar */
 enum {
        current_iconbar_menu,     /* view the icon menue */
@@ -560,7 +630,6 @@ extern char *server_cookie;
 extern int is_https;
 extern int setup_wizard;
 extern char wizard_filename[];
-extern time_t if_modified_since;
 extern int follow_xff;
 
 void InitialiseSemaphores(void);
@@ -585,7 +654,8 @@ void display_main_menu(void);
 void display_aide_menu(void);
 void display_advanced_menu(void);
 void slrp_highest(void);
-ServInfo *get_serv_info(StrBuf *, char *);
+ServInfo *get_serv_info(StrBuf *, StrBuf *);
+int GetConnected(void);
 void DeleteServInfo(ServInfo **FreeMe);
 int uds_connectsock(char *);
 int tcp_connectsock(char *, char *);
@@ -625,7 +695,7 @@ void output_headers(    int do_httpheaders,
 void output_custom_content_header(const char *ctype);
 void wprintf(const char *format,...)__attribute__((__format__(__printf__,1,2)));
 void hprintf(const char *format,...)__attribute__((__format__(__printf__,1,2)));
-void output_static(const char *what);
+void output_static(void);
 
 void print_menu_box(char* Title, char *Class, int nLines, ...);
 long stresc(char *target, long tSize, char *strbuf, int nbsp, int nolinebreaks);
@@ -651,6 +721,8 @@ void text_to_server_qp(char *ptr);
 void confirm_delete_msg(void);
 void display_success(char *);
 void authorization_required(const char *message);
+int ReEstablish_Session(void);
+
 void server_to_text(void);
 void save_edit(char *description, char *enter_cmd, int regoto);
 void display_edit(char *description, char *check_cmd,
@@ -669,9 +741,7 @@ void shutdown_sessions(void);
 void do_housekeeping(void);
 void smart_goto(const StrBuf *);
 void worker_entry(void);
-void session_loop(StrBuf *ReqLine, 
-                 StrBuf *ReadBuf, 
-                 const char **Pos);
+void session_loop(void);
 size_t wc_strftime(char *s, size_t max, const char *format, const struct tm *tm);
 void fmt_time(char *buf, size_t siz, time_t thetime);
 void httpdate(char *buf, time_t thetime);
@@ -748,7 +818,6 @@ 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(const char *req);
 int ical_ctdl_is_overlap(
                         struct icaltimetype t1start,
                         struct icaltimetype t1end,
@@ -835,19 +904,6 @@ void http_datestring(char *buf, size_t n, time_t xtime);
 
 typedef void (*IcalCallbackFunc)(icalcomponent *, long, char*, int, struct calview *);
 
-typedef void (*WebcitHandlerFunc)(void);
-typedef struct  _WebcitHandler{
-       WebcitHandlerFunc F;
-       long Flags;
-} WebcitHandler;
-void WebcitAddUrlHandler(const char * UrlString, long UrlSLen, WebcitHandlerFunc F, long Flags);
-
-#define AJAX (1<<0)
-#define ANONYMOUS (1<<1)
-#define NEED_URL (1<<2)
-#define XHTTP_COMMANDS (1<<3)
-
-
 /* These should be empty, but we have them for testing */
 #define DEFAULT_HTTPAUTH_USER  ""
 #define DEFAULT_HTTPAUTH_PASS  ""
index 8488020effca4a1cae9f12ea8aed938d4de86b5a..8c6cd198f0ac3eada767d23623715b6515503d63 100644 (file)
@@ -480,15 +480,6 @@ int main(int argc, char **argv)
        lprintf(9, "Text domain Charset: %s\n", bind_textdomain_codeset("webcit","UTF8"));
 #endif
 
-
-
-
-
-
-
-
-
-
        initialise_modules();
        initialize_viewdefs();
        initialize_axdefs();
index 1c19f775796badd2400a7fe9ed6315ced801cff6..408cf590dc4948002a21971a216c1608231cf9b1 100644 (file)
@@ -321,6 +321,8 @@ void
 InitModule_WHO
 (void)
 {
+       
+
        WebcitAddUrlHandler(HKEY("terminate_session"), _terminate_session, 0);
        WebcitAddUrlHandler(HKEY("edit_me"), edit_me, 0);