* serv_getln now is a wrapper around existing functionality. a new temporary var...
[citadel.git] / webcit / webcit.c
index 1aa8ae12b9da426eb1151bccd5dae14898e7cbcb..9b3a926fbb67b05249ae56812e71e7ad5cd34468 100644 (file)
@@ -168,21 +168,34 @@ void output_headers(      int do_httpheaders,     /* 1 = output HTTP headers
                do_template("head", NULL);
 
                /* check for ImportantMessages (these display in a div overlaying the main screen) */
-               if (!IsEmptyStr(WC->ImportantMessage)) {
+               if (!IsEmptyStr(WCC->ImportantMessage)) {
                        wprintf("<div id=\"important_message\">\n"
                                "<span class=\"imsg\">");
-                       escputs(WC->ImportantMessage);
+                       StrEscAppend(WCC->WBuf, NULL, WCC->ImportantMessage, 0, 0);
                        wprintf("</span><br />\n"
                                "</div>\n"
                        );
-                       StrBufAppendPrintf(WCC->trailing_javascript,
-                               "setTimeout('hide_imsg_popup()', 5000); \n"
+                       StrBufAppendBufPlain(WCC->trailing_javascript,
+                                            HKEY("setTimeout('hide_imsg_popup()', 5000);       \n"), 
+                                            0
                        );
                        WCC->ImportantMessage[0] = 0;
                }
-
+               else if (StrLength(WCC->ImportantMsg) > 0) {
+                       wprintf("<div id=\"important_message\">\n"
+                               "<span class=\"imsg\">");
+                       StrEscAppend(WCC->WBuf, WCC->ImportantMsg, NULL, 0, 0);
+                       wprintf("</span><br />\n"
+                               "</div>\n"
+                       );
+                       StrBufAppendBufPlain(WCC->trailing_javascript,
+                                            HKEY("setTimeout('hide_imsg_popup()', 5000);       \n"),
+                                            0
+                       );
+                       FlushStrBuf(WCC->ImportantMsg);
+               }
                if ( (WCC->logged_in) && (!unset_cookies) ) {
-                 //DoTemplate(HKEY("iconbar"), NULL, &NoCtx);
+                       /*DoTemplate(HKEY("iconbar"), NULL, &NoCtx);*/
                        page_popup();
                }
 
@@ -283,7 +296,7 @@ void print_menu_box(char* Title, char *Class, int nLines, ...)
 /*
  * dump out static pages from disk
  */
-void output_static(char *what)
+void output_static(const char *what)
 {
        int fd;
        struct stat statbuf;
@@ -346,7 +359,7 @@ void output_static(char *what)
  * titlebarmsg         text to display in the title bar
  * messagetext         body of the box
  */
-void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext)
+void convenience_page(const char *titlebarcolor, const char *titlebarmsg, const char *messagetext)
 {
        hprintf("HTTP/1.1 200 OK\n");
        output_headers(1, 1, 2, 0, 0, 0);
@@ -378,7 +391,6 @@ void url_do_template(void) {
        const StrBuf *MimeType;
        const StrBuf *Tmpl = sbstr("template");
        begin_burst();
-       output_headers(0, 0, 0, 0, 1, 0);
        MimeType = DoTemplate(SKEY(Tmpl), NULL, &NoCtx);
        http_transmit_thing(ChrPtr(MimeType), 0);
 }
@@ -441,44 +453,54 @@ void end_ajax_response(void) {
  */
 void ajax_servcmd(void)
 {
-       char buf[1024];
-       char gcontent[1024];
+       wcsession *WCC = WC;
+       int Done = 0;
+       StrBuf *Buf;
        char *junk;
        size_t len;
 
        begin_ajax_response();
-
-       serv_printf("%s", bstr("g_cmd"));
-       serv_getln(buf, sizeof buf);
-       wprintf("%s\n", buf);
-
-       if (buf[0] == '8') {
-               serv_printf("\n\n000");
-       }
-       if ((buf[0] == '1') || (buf[0] == '8')) {
-               while (serv_getln(gcontent, sizeof gcontent), strcmp(gcontent, "000")) {
-                       wprintf("%s\n", gcontent);
+       Buf = NewStrBuf();
+       serv_puts(bstr("g_cmd"));
+       StrBuf_ServGetln(Buf);
+       StrBufAppendBuf(WCC->WBuf, Buf, 0);
+       StrBufAppendBufPlain(WCC->WBuf, HKEY("\n"), 0);
+       
+       switch (GetServerStatus(Buf, NULL)) {
+       case 8:
+               serv_puts("\n\n000");
+               if ( (StrLength(Buf)==3) && 
+                    !strcmp(ChrPtr(Buf), "000")) {
+                       StrBufAppendBufPlain(WCC->WBuf, HKEY("\000"), 0);
+                       break;
                }
-               wprintf("000");
-       }
-       if (buf[0] == '4') {
+       case 1:
+               while (!Done) {
+                       StrBuf_ServGetln(Buf);
+                       if ( (StrLength(Buf)==3) && 
+                            !strcmp(ChrPtr(Buf), "000")) {
+                               Done = 1;
+                       }
+                       StrBufAppendBuf(WCC->WBuf, Buf, 0);
+                       StrBufAppendBufPlain(WCC->WBuf, HKEY("\n"), 0);
+               }
+               break;
+       case 4:
                text_to_server(bstr("g_input"));
                serv_puts("000");
-       }
-       if (buf[0] == '6') {
-               len = atol(&buf[4]);
-               junk = malloc(len);
-               serv_read(junk, len);
-               free(junk);
-       }
-       if (buf[0] == '7') {
-               len = atol(&buf[4]);
+               break;
+       case 6:
+               len = atol(&ChrPtr(Buf)[4]);
+               StrBuf_ServGetBLOBBuffered(Buf, len);
+               break;
+       case 7:
+               len = atol(&ChrPtr(Buf)[4]);
                junk = malloc(len);
                memset(junk, 0, len);
                serv_write(junk, len);
                free(junk);
        }
-
+       
        end_ajax_response();
        
        /*
@@ -488,8 +510,9 @@ void ajax_servcmd(void)
         * that page_popup() doesn't try to open it a second time.
         */
        if (!strncasecmp(bstr("g_cmd"), "GEXP", 4)) {
-               WC->last_pager_check = time(NULL);
+               WCC->last_pager_check = time(NULL);
        }
+       FreeStrBuf(&Buf);
 }
 
 
@@ -540,7 +563,11 @@ int is_mobile_ua(char *user_agent) {
 /*
  * Entry point for WebCit transaction
  */
-void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method, StrBuf *ReadBuf)
+void session_loop(HashList *HTTPHeaders, 
+                 StrBuf *ReqLine, 
+                 StrBuf *request_method, 
+                 StrBuf *ReadBuf,
+                 const char **Pos)
 {
        StrBuf *Buf;
        const char *pch, *pchs, *pche;
@@ -564,6 +591,8 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
        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,
@@ -576,6 +605,8 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
        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();
@@ -690,7 +721,11 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
                body_start = StrLength(content);
 
                /** Read the entire input data at once. */
-               client_read(&WCC->http_sock, content, ReadBuf, ContentLength + body_start);
+               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);
@@ -770,7 +805,7 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
        }
 
        /* If the client sent a nonce that is incorrect, kill the request. */
-       if (strlen(bstr("nonce")) > 0) {
+       if (havebstr("nonce")) {
                lprintf(9, "Comparing supplied nonce %s to session nonce %ld\n", 
                        bstr("nonce"), WCC->nonce);
                if (ibstr("nonce") != WCC->nonce) {
@@ -788,6 +823,8 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
         * 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);
@@ -800,6 +837,7 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
 
                if (WCC->serv_sock < 0) {
                        do_logout();
+                       FreeStrBuf(&WCC->ReadBuf);
                        goto SKIP_ALL_THIS_CRAP;
                }
                else {
@@ -828,8 +866,18 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
                                }
                                locate_host(browser_host, WCC->http_sock);
                        }
-
-                       WCC->serv_info = get_serv_info(browser_host, user_agent);
+                       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 "
@@ -842,6 +890,8 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
                                                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;
@@ -996,9 +1046,12 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method
                                        WCC->UrlFragment2 = NewStrBuf();
                                if (WCC->UrlFragment3 == NULL)
                                        WCC->UrlFragment3 = NewStrBuf();
-                               StrBufPrintf(WCC->UrlFragment1, "%s", index[0]);
-                               StrBufPrintf(WCC->UrlFragment2, "%s", index[1]);
-                               StrBufPrintf(WCC->UrlFragment3, "%s", index[2]);
+                               if (WCC->UrlFragment4 == NULL)
+                                       WCC->UrlFragment4 = NewStrBuf();
+                               StrBufPlain(WCC->UrlFragment1, index[0], -1);
+                               StrBufPlain(WCC->UrlFragment2, index[1], -1);
+                               StrBufPlain(WCC->UrlFragment3, index[2], -1);
+                               StrBufPlain(WCC->UrlFragment4, index[3], -1);
                        }
                        if ((Handler->Flags & AJAX) != 0)
                                begin_ajax_response();
@@ -1039,6 +1092,14 @@ SKIP_ALL_THIS_CRAP:
        }
        FreeStrBuf(&WCC->trailing_javascript);
        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
+       );
 }
 
 
@@ -1059,7 +1120,8 @@ int ConditionalImportantMesage(StrBuf *Target, WCTemplputParams *TP)
 {
        wcsession *WCC = WC;
        if (WCC != NULL)
-               return (!IsEmptyStr(WCC->ImportantMessage));
+               return ((!IsEmptyStr(WCC->ImportantMessage)) || 
+                       (StrLength(WCC->ImportantMsg) > 0));
        else
                return 0;
 }
@@ -1069,12 +1131,14 @@ void tmplput_importantmessage(StrBuf *Target, WCTemplputParams *TP)
        wcsession *WCC = WC;
        
        if (WCC != NULL) {
-/*
-               StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType,
-                                    WCC->ImportantMessage, 0);
-*/
-               StrEscAppend(Target, NULL, WCC->ImportantMessage, 0, 0);
-               WCC->ImportantMessage[0] = '\0';
+               if (!IsEmptyStr(WCC->ImportantMessage)) {
+                       StrEscAppend(Target, NULL, WCC->ImportantMessage, 0, 0);
+                       WCC->ImportantMessage[0] = '\0';
+               }
+               else if (StrLength(WCC->ImportantMsg) > 0) {
+                       StrEscAppend(Target, WCC->ImportantMsg, NULL, 0, 0);
+                       FlushStrBuf(WCC->ImportantMsg);
+               }
        }
 }