X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fwebcit.c;h=e1e9c5ded3184482631f9182f979f41e40acd405;hb=27e6a22f021cffe2cee1a41accbf9d2f78b20dab;hp=51105a76bb72052be0eacf27ea2d6bf4bf456cb9;hpb=1083c2a818cda51f81c908a801bd5f922f99149e;p=citadel.git diff --git a/webcit/webcit.c b/webcit/webcit.c index 51105a76b..e1e9c5ded 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -5,14 +5,13 @@ * persistent session to the Citadel server, handling HTTP WebCit requests as * they arrive and presenting a user interface. */ -#include #define SHOW_ME_VAPPEND_PRINTF +#include +#include #include "webcit.h" #include "groupdav.h" #include "webserver.h" -#include -#include /* * String to unset the cookie. @@ -20,7 +19,7 @@ * the exact minute. :) */ static char *unset = "; expires=28-May-1971 18:10:00 GMT"; - +StrBuf *csslocal = NULL; HashList *HandlerHash = NULL; void WebcitAddUrlHandler(const char * UrlString, @@ -39,327 +38,13 @@ void WebcitAddUrlHandler(const char * UrlString, Put(HandlerHash, UrlString, UrlSLen, NewHandler, NULL); } -/* - * remove escaped strings from i.e. the url string (like %20 for blanks) - */ -long unescape_input(char *buf) -{ - int a, b; - char hex[3]; - long buflen; - long len; - - buflen = strlen(buf); - - while ((buflen > 0) && (isspace(buf[buflen - 1]))){ - buf[buflen - 1] = 0; - buflen --; - } - - a = 0; - while (a < buflen) { - if (buf[a] == '+') - buf[a] = ' '; - if (buf[a] == '%') { - /* don't let % chars through, rather truncate the input. */ - if (a + 2 > buflen) { - buf[a] = '\0'; - buflen = a; - } - else { - hex[0] = buf[a + 1]; - hex[1] = buf[a + 2]; - hex[2] = 0; - b = 0; - sscanf(hex, "%02x", &b); - buf[a] = (char) b; - len = buflen - a - 2; - if (len > 0) - memmove(&buf[a + 1], &buf[a + 3], len); - - buflen -=2; - } - } - a++; - } - return a; -} - -void free_url(void *U) -{ - urlcontent *u = (urlcontent*) U; - FreeStrBuf(&u->url_data); - free(u); -} - -/* - * Extract variables from the URL. - */ -void addurls(StrBuf *url) -{ - const char *aptr, *bptr, *eptr, *up; -/// char *buf; - int len, keylen; - urlcontent *u; - struct wcsession *WCC = WC; - - if (WCC->urlstrings == NULL) - WCC->urlstrings = NewHash(1, NULL); -// buf = (char*) malloc (ulen + 1); -// memcpy(buf, url, ulen); -/// buf[ulen] = '\0'; - eptr = ChrPtr(url) + StrLength(url); - up = ChrPtr(url); - while ((up < eptr) && (!IsEmptyStr(up))) { - aptr = up; - while ((aptr < eptr) && (*aptr != '\0') && (*aptr != '=')) - aptr++; - if (*aptr != '=') { - ///free(buf); - return; - } - ///*aptr = '\0'; - aptr++; - bptr = aptr; - while ((bptr < eptr) && (*bptr != '\0') - && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) { - bptr++; - } - //*bptr = '\0'; - keylen = aptr - up - 1; /* -1 -> '=' */ - if(keylen > sizeof(u->url_key)) { - lprintf(1, "URLkey to long! [%s]", up); - continue; - } - - u = (urlcontent *) malloc(sizeof(urlcontent)); - memcpy(u->url_key, up, keylen); - u->url_key[keylen] = '\0'; - if (keylen < 0) { - lprintf(1, "URLkey to long! [%s]", up); - free(u); - continue; - } - - Put(WCC->urlstrings, u->url_key, keylen, u, free_url); - len = bptr - aptr; - u->url_data = NewStrBufPlain(aptr, len); - StrBufUnescape(u->url_data, 1); - - up = bptr; - ++up; -#ifdef DEBUG_URLSTRINGS - lprintf(9, "%s = [%ld] %s\n", - u->url_key, - StrLength(u->url_data), - ChrPtr(u->url_data)); -#endif - } - //free(buf); -} - -/* - * free urlstring memory - */ -void free_urls(void) -{ - DeleteHash(&WC->urlstrings); -} - -/* - * Diagnostic function to display the contents of all variables - */ - -void dump_vars(void) -{ - struct wcsession *WCC = WC; - urlcontent *u; - void *U; - long HKLen; - const char *HKey; - HashPos *Cursor; - - Cursor = GetNewHashPos (); - while (GetNextHashPos(WCC->urlstrings, Cursor, &HKLen, &HKey, &U)) { - u = (urlcontent*) U; - wprintf("%38s = %s\n", u->url_key, ChrPtr(u->url_data)); - } -} - -/* - * Return the value of a variable supplied to the current web page (from the url or a form) - */ - -const char *XBstr(const char *key, size_t keylen, size_t *len) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, keylen, &U)) { - *len = StrLength(((urlcontent *)U)->url_data); - return ChrPtr(((urlcontent *)U)->url_data); - } - else { - *len = 0; - return (""); - } -} - -const char *XBSTR(const char *key, size_t *len) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen (key), &U)){ - *len = StrLength(((urlcontent *)U)->url_data); - return ChrPtr(((urlcontent *)U)->url_data); - } - else { - *len = 0; - return (""); - } -} - - -const char *BSTR(const char *key) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen (key), &U)) - return ChrPtr(((urlcontent *)U)->url_data); - else - return (""); -} - -const char *Bstr(const char *key, size_t keylen) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, keylen, &U)) - return ChrPtr(((urlcontent *)U)->url_data); - else - return (""); -} - -const StrBuf *SBSTR(const char *key) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen (key), &U)) - return ((urlcontent *)U)->url_data; - else - return NULL; -} - -const StrBuf *SBstr(const char *key, size_t keylen) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, keylen, &U)) - return ((urlcontent *)U)->url_data; - else - return NULL; -} - -long LBstr(const char *key, size_t keylen) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, keylen, &U)) - return StrTol(((urlcontent *)U)->url_data); - else - return (0); -} - -long LBSTR(const char *key) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen(key), &U)) - return StrTol(((urlcontent *)U)->url_data); - else - return (0); -} - -int IBstr(const char *key, size_t keylen) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, keylen, &U)) - return StrTol(((urlcontent *)U)->url_data); - else - return (0); -} - -int IBSTR(const char *key) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen(key), &U)) - return StrToi(((urlcontent *)U)->url_data); - else - return (0); -} - -int HaveBstr(const char *key, size_t keylen) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, keylen, &U)) - return (StrLength(((urlcontent *)U)->url_data) != 0); - else - return (0); -} - -int HAVEBSTR(const char *key) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen(key), &U)) - return (StrLength(((urlcontent *)U)->url_data) != 0); - else - return (0); -} - - -int YesBstr(const char *key, size_t keylen) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, keylen, &U)) - return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0; - else - return (0); -} - -int YESBSTR(const char *key) -{ - void *U; - - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen(key), &U)) - return strcmp( ChrPtr(((urlcontent *)U)->url_data), "yes") == 0; - else - return (0); -} /* * web-printing funcion. uses our vsnprintf wrapper */ void wprintf(const char *format,...) { - struct wcsession *WCC = WC; + wcsession *WCC = WC; va_list arg_ptr; if (WCC->WBuf == NULL) @@ -368,9 +53,6 @@ void wprintf(const char *format,...) va_start(arg_ptr, format); StrBufVAppendPrintf(WCC->WBuf, format, arg_ptr); va_end(arg_ptr); - -/// if (StrLength(WCC-WBuf) > 2048) - ///client_write(wbuf, strlen(wbuf)); } /* @@ -378,30 +60,27 @@ void wprintf(const char *format,...) */ void hprintf(const char *format,...) { - struct wcsession *WCC = WC; + wcsession *WCC = WC; va_list arg_ptr; va_start(arg_ptr, format); StrBufVAppendPrintf(WCC->HBuf, format, arg_ptr); va_end(arg_ptr); - -/// if (StrLength(WCC-WBuf) > 2048) - ///client_write(wbuf, strlen(wbuf)); } + /* * wrap up an HTTP session, closes tags, etc. * * print_standard_html_footer should be set to: - * 0 to transmit only, - * 1 to append the main menu and closing tags, - * 2 to append the closing tags only. + * 0 - to transmit only, + * nonzero - to append the closing tags */ void wDumpContent(int print_standard_html_footer) { if (print_standard_html_footer) { - wprintf("\n"); /* end of "text" div */ + wprintf(" \n"); do_template("trailing", NULL); } @@ -413,227 +92,6 @@ void wDumpContent(int print_standard_html_footer) -/* - * Copy a string, escaping characters which have meaning in HTML. - * - * target target buffer - * strbuf source buffer - * nbsp If nonzero, spaces are converted to non-breaking spaces. - * nolinebreaks if set, linebreaks are removed from the string. - */ -long stresc(char *target, long tSize, char *strbuf, int nbsp, int nolinebreaks) -{ - char *aptr, *bptr, *eptr; - - *target = '\0'; - aptr = strbuf; - bptr = target; - eptr = target + tSize - 6; // our biggest unit to put in... - - - while ((bptr < eptr) && !IsEmptyStr(aptr) ){ - if (*aptr == '<') { - memcpy(bptr, "<", 4); - bptr += 4; - } - else if (*aptr == '>') { - memcpy(bptr, ">", 4); - bptr += 4; - } - else if (*aptr == '&') { - memcpy(bptr, "&", 5); - bptr += 5; - } - else if (*aptr == '\"') { - memcpy(bptr, """, 6); - bptr += 6; - } - else if (*aptr == '\'') { - memcpy(bptr, "'", 5); - bptr += 5; - } - else if (*aptr == LB) { - *bptr = '<'; - bptr ++; - } - else if (*aptr == RB) { - *bptr = '>'; - bptr ++; - } - else if (*aptr == QU) { - *bptr ='"'; - bptr ++; - } - else if ((*aptr == 32) && (nbsp == 1)) { - memcpy(bptr, " ", 6); - bptr += 6; - } - else if ((*aptr == '\n') && (nolinebreaks)) { - *bptr='\0'; /* nothing */ - } - else if ((*aptr == '\r') && (nolinebreaks)) { - *bptr='\0'; /* nothing */ - } - else{ - *bptr = *aptr; - bptr++; - } - aptr ++; - } - *bptr = '\0'; - if ((bptr = eptr - 1 ) && !IsEmptyStr(aptr) ) - return -1; - return (bptr - target); -} - - -void escputs1(char *strbuf, int nbsp, int nolinebreaks) -{ - StrEscAppend(WC->WBuf, NULL, strbuf, nbsp, nolinebreaks); -} - -void StrEscputs1(const StrBuf *strbuf, int nbsp, int nolinebreaks) -{ - StrEscAppend(WC->WBuf, strbuf, NULL, nbsp, nolinebreaks); -} - -/* - * static wrapper for ecsputs1 - */ -void escputs(char *strbuf) -{ - escputs1(strbuf, 0, 0); -} - - -/* - * static wrapper for ecsputs1 - */ -void StrEscPuts(const StrBuf *strbuf) -{ - StrEscputs1(strbuf, 0, 0); -} - - -/* - * urlescape buffer and print it to the client - */ -void urlescputs(const char *strbuf) -{ - StrBufUrlescAppend(WC->WBuf, NULL, strbuf); -} - -/* - * urlescape buffer and print it to the client - */ -void UrlescPutStrBuf(const StrBuf *strbuf) -{ - StrBufUrlescAppend(WC->WBuf, strbuf, NULL); -} - -/** - * urlescape buffer and print it as header - */ -void hurlescputs(const char *strbuf) -{ - StrBufUrlescAppend(WC->HBuf, NULL, strbuf); -} - - -/* - * Copy a string, escaping characters for JavaScript strings. - */ -void jsesc(char *target, size_t tlen, char *strbuf) -{ - int len; - char *tend; - char *send; - char *tptr; - char *sptr; - - target[0]='\0'; - len = strlen (strbuf); - send = strbuf + len; - tend = target + tlen; - sptr = strbuf; - tptr = target; - - while (!IsEmptyStr(sptr) && - (sptr < send) && - (tptr < tend)) { - - if (*sptr == '<') - *tptr = '['; - else if (*sptr == '>') - *tptr = ']'; - else if (*sptr == '\'') { - if (tend - tptr < 3) - return; - *(tptr++) = '\\'; - *tptr = '\''; - } - else if (*sptr == '"') { - if (tend - tptr < 8) - return; - *(tptr++) = '&'; - *(tptr++) = 'q'; - *(tptr++) = 'u'; - *(tptr++) = 'o'; - *(tptr++) = 't'; - *tptr = ';'; - } - else if (*sptr == '&') { - if (tend - tptr < 7) - return; - *(tptr++) = '&'; - *(tptr++) = 'a'; - *(tptr++) = 'm'; - *(tptr++) = 'p'; - *tptr = ';'; - } else { - *tptr = *sptr; - } - tptr++; sptr++; - } - *tptr = '\0'; -} - -/* - * escape and print javascript - */ -void jsescputs(char *strbuf) -{ - char outbuf[SIZ]; - - jsesc(outbuf, SIZ, strbuf); - wprintf("%s", outbuf); -} - -/* - * print a string to the client after cleaning it with msgesc() and stresc() - */ -void msgescputs1( char *strbuf) -{ - StrBuf *OutBuf; - - if ((strbuf == NULL) || IsEmptyStr(strbuf)) - return; - OutBuf = NewStrBuf(); - StrMsgEscAppend(OutBuf, NULL, strbuf); - StrEscAppend(WC->WBuf, OutBuf, NULL, 0, 0); - FreeStrBuf(&OutBuf); -} - -/* - * print a string to the client after cleaning it with msgesc() - */ -void msgescputs(char *strbuf) { - if ((strbuf != NULL) && !IsEmptyStr(strbuf)) - StrMsgEscAppend(WC->WBuf, NULL, strbuf); -} - - - /* * Output HTTP headers and leading HTML for a page @@ -650,6 +108,7 @@ void output_headers( int do_httpheaders, /* 1 = output HTTP headers int suppress_check, /* 1 = suppress check for instant messages */ int cache /* 1 = allow browser to cache this page */ ) { + wcsession *WCC = WC; char cookie[1024]; char httpnow[128]; @@ -657,11 +116,17 @@ void output_headers( int do_httpheaders, /* 1 = output HTTP headers http_datestring(httpnow, sizeof httpnow, time(NULL)); if (do_httpheaders) { - hprintf("Content-type: text/html; charset=utf-8\r\n" - "Server: %s / %s\n" - "Connection: close\r\n", - PACKAGE_STRING, serv_info.serv_software - ); + if (WCC->serv_info != NULL) + hprintf("Content-type: text/html; charset=utf-8\r\n" + "Server: %s / %s\n" + "Connection: close\r\n", + PACKAGE_STRING, + ChrPtr(WCC->serv_info->serv_software)); + else + hprintf("Content-type: text/html; charset=utf-8\r\n" + "Server: %s / [n/a]\n" + "Connection: close\r\n", + PACKAGE_STRING); } if (cache) { @@ -685,8 +150,9 @@ void output_headers( int do_httpheaders, /* 1 = output HTTP headers ); } - stuff_to_cookie(cookie, 1024, WC->wc_session, WC->wc_username, - WC->wc_password, WC->wc_roomname); + stuff_to_cookie(cookie, 1024, + WCC->wc_session, WCC->wc_username, + WCC->wc_password, WCC->wc_roomname); if (unset_cookies) { hprintf("Set-cookie: webcit=%s; path=/\r\n", unset); @@ -699,37 +165,38 @@ void output_headers( int do_httpheaders, /* 1 = output HTTP headers if (do_htmlhead) { begin_burst(); - if (!access("static.local/webcit.css", R_OK)) { - svprintf(HKEY("CSSLOCAL"), WCS_STRING, - "" - ); - } do_template("head", NULL); - } - - /* ICONBAR */ - if (do_htmlhead) { - begin_burst(); /* check for ImportantMessages (these display in a div overlaying the main screen) */ - if (!IsEmptyStr(WC->ImportantMessage)) { + if (!IsEmptyStr(WCC->ImportantMessage)) { wprintf("
\n" ""); - escputs(WC->ImportantMessage); + StrEscAppend(WCC->WBuf, NULL, WCC->ImportantMessage, 0, 0); wprintf("
\n" "
\n" - "\n"); - WC->ImportantMessage[0] = 0; + ); + StrBufAppendBufPlain(WCC->trailing_javascript, + HKEY("setTimeout('hide_imsg_popup()', 5000); \n"), + 0 + ); + WCC->ImportantMessage[0] = 0; } - - if ( (WC->logged_in) && (!unset_cookies) ) { - wprintf("
"); - do_selected_iconbar(); - /** check for instant messages (these display in a new window) */ + else if (StrLength(WCC->ImportantMsg) > 0) { + wprintf("
\n" + ""); + StrEscAppend(WCC->WBuf, WCC->ImportantMsg, NULL, 0, 0); + wprintf("
\n" + "
\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);*/ page_popup(); - wprintf("
"); } if (do_room_banner == 1) { @@ -744,6 +211,13 @@ void output_headers( int do_httpheaders, /* 1 = output HTTP headers } } +void output_custom_content_header(const char *ctype) { + hprintf("HTTP/1.1 200 OK\r\n"); + hprintf("Content-type: %s; charset=utf-8\r\n",ctype); + hprintf("Server: %s / %s\r\n", PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software)); + hprintf("Connection: close\r\n"); +} + /* * Generic function to do an HTTP redirect. Easy and fun. @@ -767,10 +241,12 @@ void http_redirect(const char *whichpage) { void http_transmit_thing(const char *content_type, int is_static) { +#ifndef TECH_PREVIEW lprintf(9, "http_transmit_thing(%s)%s\n", content_type, (is_static ? " (static)" : "") ); +#endif output_headers(0, 0, 0, 0, 0, is_static); hprintf("Content-type: %s\r\n" @@ -796,7 +272,7 @@ void print_menu_box(char* Title, char *Class, int nLines, ...) long i; svput("BOXTITLE", WCS_STRING, Title); - do_template("beginbox", NULL); + do_template("beginboxx", NULL); wprintf("
    ", Class); @@ -820,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; @@ -865,7 +341,9 @@ void output_static(char *what) close(fd); +#ifndef TECH_PREVIEW lprintf(9, "output_static('%s') %s\n", what, content_type); +#endif http_transmit_thing(content_type, 1); } if (yesbstr("force_close_session")) { @@ -873,152 +351,6 @@ void output_static(char *what) } } -/* - * When the browser requests an image file from the Citadel server, - * this function is called to transmit it. - */ -void output_image() -{ - struct wcsession *WCC = WC; - char buf[SIZ]; - off_t bytes; - const char *MimeType; - - serv_printf("OIMG %s|%s", bstr("name"), bstr("parm")); - serv_getln(buf, sizeof buf); - if (buf[0] == '2') { - bytes = extract_long(&buf[4], 0); - - /** Read it from the server */ - - if (read_server_binary(WCC->WBuf, bytes) > 0) { - serv_puts("CLOS"); - serv_getln(buf, sizeof buf); - - MimeType = GuessMimeType (ChrPtr(WCC->WBuf), StrLength(WCC->WBuf)); - /** Write it to the browser */ - if (!IsEmptyStr(MimeType)) - { - http_transmit_thing(MimeType, 0); - return; - } - } - /* hm... unknown mimetype? fallback to blank gif */ - } - - - /* - * Instead of an ugly 404, send a 1x1 transparent GIF - * when there's no such image on the server. - */ - char blank_gif[SIZ]; - snprintf (blank_gif, SIZ, "%s%s", static_dirs[0], "/blank.gif"); - output_static(blank_gif); -} - -/* - * Extract an embedded photo from a vCard for display on the client - */ -void display_vcard_photo_img(void) -{ - long msgnum = 0L; - char *vcard; - struct vCard *v; - char *photosrc; - const char *contentType; - struct wcsession *WCC = WC; - - msgnum = StrTol(WCC->UrlFragment1); - - vcard = load_mimepart(msgnum,"1"); - v = vcard_load(vcard); - - photosrc = vcard_get_prop(v, "PHOTO", 1,0,0); - FlushStrBuf(WCC->WBuf); - StrBufAppendBufPlain(WCC->WBuf, photosrc, -1, 0); - if (StrBufDecodeBase64(WCC->WBuf) <= 0) { - FlushStrBuf(WCC->WBuf); - - hprintf("HTTP/1.1 500 %s\n","Unable to get photo"); - output_headers(0, 0, 0, 0, 0, 0); - hprintf("Content-Type: text/plain\r\n"); - wprintf(_("Could Not decode vcard photo\n")); - end_burst(); - return; - } - contentType = GuessMimeType(ChrPtr(WCC->WBuf), StrLength(WCC->WBuf)); - http_transmit_thing(contentType, 0); - free(v); - free(photosrc); -} - -/* - * Generic function to output an arbitrary MIME part from an arbitrary - * message number on the server. - * - * msgnum Number of the item on the citadel server - * partnum The MIME part to be output - * force_download Nonzero to force set the Content-Type: header to "application/octet-stream" - */ -void mimepart(const char *msgnum, const char *partnum, int force_download) -{ - char buf[256]; - off_t bytes; - char content_type[256]; - - serv_printf("OPNA %s|%s", msgnum, partnum); - serv_getln(buf, sizeof buf); - if (buf[0] == '2') { - bytes = extract_long(&buf[4], 0); - if (force_download) { - strcpy(content_type, "application/octet-stream"); - } - else { - extract_token(content_type, &buf[4], 3, '|', sizeof content_type); - } - output_headers(0, 0, 0, 0, 0, 0); - - read_server_binary(WC->WBuf, bytes); - serv_puts("CLOS"); - serv_getln(buf, sizeof buf); - http_transmit_thing(content_type, 0); - } else { - hprintf("HTTP/1.1 404 %s\n", &buf[4]); - output_headers(0, 0, 0, 0, 0, 0); - hprintf("Content-Type: text/plain\r\n"); - wprintf(_("An error occurred while retrieving this part: %s\n"), &buf[4]); - end_burst(); - } -} - - -/* - * Read any MIME part of a message, from the server, into memory. - */ -char *load_mimepart(long msgnum, char *partnum) -{ - char buf[SIZ]; - off_t bytes; - char content_type[SIZ]; - char *content; - - serv_printf("DLAT %ld|%s", msgnum, partnum); - serv_getln(buf, sizeof buf); - if (buf[0] == '6') { - bytes = extract_long(&buf[4], 0); - extract_token(content_type, &buf[4], 3, '|', sizeof content_type); - - content = malloc(bytes + 2); - serv_read(content, bytes); - - content[bytes] = 0; /* null terminate for good measure */ - return(content); - } - else { - return(NULL); - } -} - /* * Convenience functions to display a page containing only a string @@ -1027,7 +359,7 @@ char *load_mimepart(long msgnum, char *partnum) * 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); @@ -1056,52 +388,11 @@ void blank_page(void) { * A template has been requested */ void url_do_template(void) { + const StrBuf *MimeType; const StrBuf *Tmpl = sbstr("template"); begin_burst(); - output_headers(1, 0, 0, 0, 1, 0); - DoTemplate(ChrPtr(Tmpl), StrLength(Tmpl), NULL, NULL, 0); - end_burst(); -} - - - -/* - * Offer to make any page the user's "start page." - */ -void offer_start_page(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) { - wprintf("this_page); - wprintf("\">"); - wprintf(_("Make this my start page")); - wprintf(""); -#ifdef TECH_PREVIEW - wprintf("
    wc_roomname); - wprintf("\" title=\"RSS 2.0 feed for "); - escputs(WC->wc_roomname); - wprintf("\">\"RSS\"\n"); -#endif -} - - -/* - * Change the user's start page - */ -void change_start_page(void) { - - if (bstr("startpage") == NULL) { - safestrncpy(WC->ImportantMessage, - _("You no longer have a start page selected."), - sizeof WC->ImportantMessage); - display_main_menu(); - return; - } - - set_preference("startpage", NewStrBufPlain(bstr("startpage"), -1), 1); - - output_headers(1, 1, 0, 0, 0, 0); - do_template("newstartpage", NULL); - wDumpContent(1); + MimeType = DoTemplate(SKEY(Tmpl), NULL, &NoCtx); + http_transmit_thing(ChrPtr(MimeType), 0); } @@ -1122,7 +413,7 @@ void display_success(char *successmessage) void authorization_required(const char *message) { hprintf("HTTP/1.1 401 Authorization Required\r\n"); - hprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n", serv_info.serv_humannode); + hprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n", ChrPtr(WC->serv_info->serv_humannode)); hprintf("Content-Type: text/html\r\n"); wprintf("

    "); wprintf(_("Authorization Required")); @@ -1133,73 +424,11 @@ void authorization_required(const char *message) } -/* - * This function is called by the MIME parser to handle data uploaded by - * the browser. Form data, uploaded files, and the data from HTTP PUT - * operations (such as those found in GroupDAV) all arrive this way. - * - * name Name of the item being uploaded - * filename Filename of the item being uploaded - * partnum MIME part identifier (not needed) - * disp MIME content disposition (not needed) - * content The actual data - * cbtype MIME content-type - * cbcharset Character set - * length Content length - * encoding MIME encoding type (not needed) - * cbid Content ID (not needed) - * userdata Not used here - */ -void upload_handler(char *name, char *filename, char *partnum, char *disp, - void *content, char *cbtype, char *cbcharset, - size_t length, char *encoding, char *cbid, void *userdata) -{ - urlcontent *u; -#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); - - /* Form fields */ - if ( (length > 0) && (IsEmptyStr(cbtype)) ) { - u = (urlcontent *) malloc(sizeof(urlcontent)); - - 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); -#ifdef DEBUG_URLSTRINGS - lprintf(9, "Key: <%s> len: [%ld] Data: <%s>\n", - u->url_key, - StrLength(u->url_data), - ChrPtr(u->url_data)); -#endif - } - - /** Uploaded files */ - if ( (length > 0) && (!IsEmptyStr(cbtype)) ) { - WC->upload = malloc(length); - if (WC->upload != NULL) { - WC->upload_length = length; - safestrncpy(WC->upload_filename, filename, - sizeof(WC->upload_filename)); - safestrncpy(WC->upload_content_type, cbtype, - sizeof(WC->upload_content_type)); - memcpy(WC->upload, content, length); - } - else { - lprintf(3, "malloc() failed: %s\n", strerror(errno)); - } - } - -} - /* * Convenience functions to wrap around asynchronous ajax responses */ void begin_ajax_response(void) { - struct wcsession *WCC = WC; + wcsession *WCC = WC; FlushStrBuf(WCC->HBuf); output_headers(0, 0, 0, 0, 0, 0); @@ -1224,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(); /* @@ -1271,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); } @@ -1288,7 +528,7 @@ void seconds_since_last_gexp(void) wprintf("NO\n"); } else { - memset(buf, 5, 0); + memset(buf, 0, 5); serv_puts("NOOP"); serv_getln(buf, sizeof buf); if (buf[3] == '*') { @@ -1313,7 +553,7 @@ int is_mobile_ua(char *user_agent) { } 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. + /* For some reason a new install of Opera 9.51beta decided to spoof. */ return 1; } return 0; @@ -1323,8 +563,12 @@ 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(StrBuf *ReqLine, + StrBuf *request_method, + StrBuf *ReadBuf, + const char **Pos) { + StrBuf *Buf; const char *pch, *pchs, *pche; void *vLine; char action[1024]; @@ -1338,44 +582,46 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method StrBuf *UrlLine = NULL; StrBuf *content = NULL; const char *content_end = NULL; - char browser_host[256]; + 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. */ - char c_username[SIZ]; - char c_password[SIZ]; - char c_roomname[SIZ]; + StrBuf *c_username; + StrBuf *c_password; + StrBuf *c_roomname; char c_httpauth_string[SIZ]; - char c_httpauth_user[SIZ]; - char c_httpauth_pass[SIZ]; - struct wcsession *WCC; + StrBuf *c_httpauth_user; + StrBuf *c_httpauth_pass; + wcsession *WCC; + + gettimeofday(&tx_start, NULL); /* start a stopwatch for performance timing */ - safestrncpy(c_username, "", sizeof c_username); - safestrncpy(c_password, "", sizeof c_password); - safestrncpy(c_roomname, "", sizeof c_roomname); + Buf = NewStrBuf(); + c_username = NewStrBuf(); + c_password = NewStrBuf(); + c_roomname = NewStrBuf(); safestrncpy(c_httpauth_string, "", sizeof c_httpauth_string); - safestrncpy(c_httpauth_user, DEFAULT_HTTPAUTH_USER, sizeof c_httpauth_user); - safestrncpy(c_httpauth_pass, DEFAULT_HTTPAUTH_PASS, sizeof c_httpauth_pass); - strcpy(browser_host, ""); + c_httpauth_user = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_USER)); + c_httpauth_pass = NewStrBufPlain(HKEY(DEFAULT_HTTPAUTH_PASS)); WCC= WC; - if (WCC->WBuf == NULL) - WC->WBuf = NewStrBufPlain(NULL, 32768); - FlushStrBuf(WCC->WBuf); - - if (WCC->HBuf == NULL) - WCC->HBuf = NewStrBuf(); - FlushStrBuf(WCC->HBuf); WCC->upload_length = 0; WCC->upload = NULL; WCC->is_mobile = 0; + WCC->trailing_javascript = NewStrBuf(); + WCC->nWildfireHeaders = 0; /** Figure out the action */ index[0] = action; @@ -1385,7 +631,6 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method index[a] = arg[a-1]; sizes[a] = sizeof arg[a-1]; } -//// index[9] = &foo; todo nBackDots = 0; nEmpty = 0; for ( a = 0; a < 9; ++a) @@ -1401,28 +646,28 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method } - if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && + if (GetHash(WCC->headers, HKEY("COOKIE"), &vLine) && (vLine != NULL)){ cookie_to_stuff((StrBuf *)vLine, NULL, - c_username, sizeof c_username, - c_password, sizeof c_password, - c_roomname, sizeof c_roomname); + c_username, + c_password, + c_roomname); } - if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && + if (GetHash(WCC->headers, HKEY("AUTHORIZATION"), &vLine) && (vLine!=NULL)) { - CtdlDecodeBase64(c_httpauth_string, ChrPtr((StrBuf*)vLine), StrLength((StrBuf*)vLine)); - extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user); - extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass); + StrBufDecodeBase64((StrBuf*)vLine); + StrBufExtract_token(c_httpauth_user, (StrBuf*)vLine, 0, ':'); + StrBufExtract_token(c_httpauth_pass, (StrBuf*)vLine, 1, ':'); } - if (GetHash(HTTPHeaders, HKEY("CONTENT-LENGTH"), &vLine) && + if (GetHash(WCC->headers, HKEY("CONTENT-LENGTH"), &vLine) && (vLine!=NULL)) { ContentLength = StrToi((StrBuf*)vLine); } - if (GetHash(HTTPHeaders, HKEY("CONTENT-TYPE"), &vLine) && + if (GetHash(WCC->headers, HKEY("CONTENT-TYPE"), &vLine) && (vLine!=NULL)) { ContentType = (StrBuf*)vLine; } - if (GetHash(HTTPHeaders, HKEY("USER-AGENT"), &vLine) && + if (GetHash(WCC->headers, HKEY("USER-AGENT"), &vLine) && (vLine!=NULL)) { safestrncpy(user_agent, ChrPtr((StrBuf*)vLine), sizeof user_agent); #ifdef TECH_PREVIEW @@ -1435,29 +680,24 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method #endif } if ((follow_xff) && - GetHash(HTTPHeaders, HKEY("X-FORWARDED-HOST"), &vLine) && + GetHash(WCC->headers, HKEY("X-FORWARDED-HOST"), &vLine) && (vLine != NULL)) { - safestrncpy(WCC->http_host, - ChrPtr((StrBuf*)vLine), - sizeof WCC->http_host); + WCC->http_host = (StrBuf*)vLine; } - if (IsEmptyStr(WCC->http_host) && - GetHash(HTTPHeaders, HKEY("HOST"), &vLine) && + if ((StrLength(WCC->http_host) == 0) && + GetHash(WCC->headers, HKEY("HOST"), &vLine) && (vLine!=NULL)) { - safestrncpy(WCC->http_host, - ChrPtr((StrBuf*)vLine), - sizeof WCC->http_host); - + WCC->http_host = (StrBuf*)vLine; } - if (GetHash(HTTPHeaders, HKEY("X-FORWARDED-FOR"), &vLine) && + + if (GetHash(WCC->headers, HKEY("X-FORWARDED-FOR"), &vLine) && (vLine!=NULL)) { - safestrncpy(browser_host, - ChrPtr((StrBuf*) vLine), - sizeof browser_host); - while (num_tokens(browser_host, ',') > 1) { - remove_token(browser_host, 0, ','); + browser_host = (StrBuf*) vLine; + + while (StrBufNum_tokens(browser_host, ',') > 1) { + StrBufRemove_token(browser_host, 0, ','); } - striplt(browser_host); + StrBufTrim(browser_host); } if (ContentLength > 0) { @@ -1473,11 +713,15 @@ 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); - addurls(content); + 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); @@ -1487,9 +731,9 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method } /* make a note of where we are in case the user wants to save it */ - safestrncpy(WCC->this_page, ChrPtr(ReqLine), sizeof(WCC->this_page)); - remove_token(WCC->this_page, 2, ' '); - remove_token(WCC->this_page, 0, ' '); + 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); @@ -1499,7 +743,7 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method while (pch < pche) { if ((*pch == '?') || (*pch == '&')) { StrBufCutLeft(UrlLine, pch - pchs + 1); - addurls(UrlLine); + ParseURLParams(UrlLine); break; } pch ++; @@ -1545,7 +789,7 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method { lprintf(9, "Suspicious request. Ignoring."); hprintf("HTTP/1.1 404 Security check failed\r\n"); - hprintf("Content-Type: text/plain\r\n"); + hprintf("Content-Type: text/plain\r\n\r\n"); wprintf("You have sent a malformed or invalid request.\r\n"); end_burst(); } @@ -1553,13 +797,13 @@ 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) { lprintf(9, "Ignoring request with mismatched nonce.\n"); hprintf("HTTP/1.1 404 Security check failed\r\n"); - hprintf("Content-Type: text/plain\r\n"); + hprintf("Content-Type: text/plain\r\n\r\n"); wprintf("Security check failed.\r\n"); end_burst(); goto SKIP_ALL_THIS_CRAP; @@ -1571,6 +815,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); @@ -1583,40 +829,68 @@ 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 { WCC->connected = 1; - serv_getln(buf, sizeof buf); /** get the server welcome message */ + 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) || (strlen(browser_host) == 0) ) { + 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); } - - get_serv_info(browser_host, user_agent); - if (serv_info.serv_rev_level < MINIMUM_CIT_VERSION) { + 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"), - serv_info.serv_rev_level / 100, - serv_info.serv_rev_level % 100, + 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; } } } -////////todo: restore language in this case + /* * Functions which can be performed without logging in */ @@ -1634,21 +908,34 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method * try logging in to Citadel using that. */ if ((!WCC->logged_in) - && (strlen(c_httpauth_user) > 0) - && (strlen(c_httpauth_pass) > 0)) { - serv_printf("USER %s", c_httpauth_user); - serv_getln(buf, sizeof buf); - if (buf[0] == '3') { - serv_printf("PASS %s", c_httpauth_pass); - serv_getln(buf, sizeof buf); - if (buf[0] == '2') { + && (StrLength(c_httpauth_user) > 0) + && (StrLength(c_httpauth_pass) > 0)) + { + FlushStrBuf(Buf); + serv_printf("USER %s", ChrPtr(c_httpauth_user)); + StrBuf_ServGetln(Buf); + if (GetServerStatus(Buf, NULL) == 3) { + serv_printf("PASS %s", ChrPtr(c_httpauth_pass)); + StrBuf_ServGetln(Buf); + if (GetServerStatus(Buf, NULL) == 2) { become_logged_in(c_httpauth_user, - c_httpauth_pass, buf); - safestrncpy(WCC->httpauth_user, c_httpauth_user, sizeof WCC->httpauth_user); - safestrncpy(WCC->httpauth_pass, c_httpauth_pass, sizeof WCC->httpauth_pass); + 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); + } } else { /* Should only display when password is wrong */ authorization_required(&buf[4]); + FreeStrBuf(&Buf); goto SKIP_ALL_THIS_CRAP; } } @@ -1657,7 +944,7 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method /* This needs to run early */ #ifdef TECH_PREVIEW if (!strcasecmp(action, "rss")) { - display_rss(bstr("room"), request_method); + display_rss(sbstr("room"), request_method); goto SKIP_ALL_THIS_CRAP; } #endif @@ -1667,7 +954,7 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method * our session's authentication. */ if (!strncasecmp(action, "groupdav", 8)) { - groupdav_main(HTTPHeaders, + groupdav_main(WCC->headers, ReqLine, request_method, ContentType, /* do GroupDAV methods */ ContentLength, content, body_start); @@ -1683,7 +970,7 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method * POST to the GroupDAV code as well. */ if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) { - groupdav_main(HTTPHeaders, ReqLine, + groupdav_main(WCC->headers, ReqLine, request_method, ContentType, /** do GroupDAV methods */ ContentLength, content, body_start); if (!WCC->logged_in) { @@ -1697,66 +984,74 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method * supplied by the browser, try using them to log in. */ if ((!WCC->logged_in) - && (!IsEmptyStr(c_username)) - && (!IsEmptyStr(c_password))) { - serv_printf("USER %s", c_username); - serv_getln(buf, sizeof buf); - if (buf[0] == '3') { - serv_printf("PASS %s", c_password); - serv_getln(buf, sizeof buf); - if (buf[0] == '2') { - StrBuf *Lang; - become_logged_in(c_username, c_password, buf); - if (get_preference("language", &Lang)) { - set_selected_language(ChrPtr(Lang)); - go_selected_language(); /* set locale */ - } + && (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); } } } + /* - * If we don't have a current room, but a cookie specifying the - * current room is supplied, make an effort to go there. + * If a 'gotofirst' parameter has been specified, attempt to goto that room + * prior to doing anything else. */ - if ((IsEmptyStr(WCC->wc_roomname)) && (!IsEmptyStr(c_roomname))) { - serv_printf("GOTO %s", c_roomname); - serv_getln(buf, sizeof buf); - if (buf[0] == '2') { - safestrncpy(WCC->wc_roomname, c_roomname, sizeof WCC->wc_roomname); - } + if (havebstr("gotofirst")) { + gotoroom(sbstr("gotofirst")); /* do this quietly to avoid session output! */ } - if (!strcasecmp(action, "image")) { - output_image(); - } else if (!strcasecmp(action, "display_mime_icon")) { - display_mime_icon(); - } - else { - void *vHandler; - WebcitHandler *Handler; - - GetHash(HandlerHash, action, strlen(action) /* TODO*/, &vHandler), - Handler = (WebcitHandler*) vHandler; - if (Handler != NULL) { - if (!WCC->logged_in && ((Handler->Flags & ANONYMOUS) == 0)) { - display_login(NULL); + /* + * 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 { - if((Handler->Flags & NEED_URL)) { - if (WCC->UrlFragment1 == NULL) - WCC->UrlFragment1 = NewStrBuf(); - if (WCC->UrlFragment2 == NULL) - WCC->UrlFragment2 = NewStrBuf(); - StrBufPrintf(WCC->UrlFragment1, "%s", index[1]); - StrBufPrintf(WCC->UrlFragment2, "%s", index[2]); - } - if ((Handler->Flags & AJAX) != 0) - begin_ajax_response(); - Handler->F(); - if ((Handler->Flags & AJAX) != 0) - end_ajax_response(); + 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)) { + display_login(NULL); + } + else { + if((Handler->Flags & NEED_URL)) { + if (WCC->UrlFragment1 == NULL) + WCC->UrlFragment1 = NewStrBuf(); + if (WCC->UrlFragment2 == NULL) + WCC->UrlFragment2 = NewStrBuf(); + if (WCC->UrlFragment3 == NULL) + WCC->UrlFragment3 = NewStrBuf(); + 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(); + Handler->F(); + if ((Handler->Flags & AJAX) != 0) + end_ajax_response(); + } + } /* When all else fais, display the main menu. */ else { if (!WCC->logged_in) @@ -1764,18 +1059,39 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method else display_main_menu(); } -} + SKIP_ALL_THIS_CRAP: + if (WCC->SavePrefsToServer) { + save_preferences(); + 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; } - free_urls(); + DeleteHash(&WCC->urlstrings); if (WCC->upload_length > 0) { free(WCC->upload); WCC->upload_length = 0; } + FreeStrBuf(&WCC->trailing_javascript); + WCC->http_host = NULL; + + /* How long did this transaction take? */ + 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 + ); } @@ -1791,89 +1107,125 @@ void sleeeeeeeeeep(int seconds) select(0, NULL, NULL, NULL, &tv); } -void diagnostics(void) -{ - output_headers(1, 1, 1, 0, 0, 0); - wprintf("Session: %d
    \n", WC->wc_session); - wprintf("Command:
    \n");
    -	StrEscPuts(WC->UrlFragment1);
    -	wprintf("
    \n"); - StrEscPuts(WC->UrlFragment2); - wprintf("

    \n"); - wprintf("Variables:
    \n");
    -	dump_vars();
    -	wprintf("

    \n"); - wDumpContent(1); -} - -void view_mimepart(void) { - mimepart(ChrPtr(WC->UrlFragment1), - ChrPtr(WC->UrlFragment2), - 0); -} - -void download_mimepart(void) { - mimepart(ChrPtr(WC->UrlFragment1), - ChrPtr(WC->UrlFragment2), - 1); -} - -int ConditionalImportantMesage(WCTemplateToken *Tokens, void *Context, int ContextType) +int ConditionalImportantMesage(StrBuf *Target, WCTemplputParams *TP) { - struct wcsession *WCC = WC; + wcsession *WCC = WC; if (WCC != NULL) - return (!IsEmptyStr(WCC->ImportantMessage)); + return ((!IsEmptyStr(WCC->ImportantMessage)) || + (StrLength(WCC->ImportantMsg) > 0)); else return 0; } -void tmplput_importantmessage(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +void tmplput_importantmessage(StrBuf *Target, WCTemplputParams *TP) { - struct wcsession *WCC = WC; + wcsession *WCC = WC; if (WCC != NULL) { - StrEscAppend(Target, NULL, 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); + } } } -int ConditionalBstr(WCTemplateToken *Tokens, void *Context, int ContextType) +void tmplput_trailing_javascript(StrBuf *Target, WCTemplputParams *TP) { - if(Tokens->nParameters == 1) - return HaveBstr(Tokens->Params[0]->Start, - Tokens->Params[0]->len); - else - return strcmp(Bstr(Tokens->Params[0]->Start, - Tokens->Params[0]->len), - Tokens->Params[1]->Start) == 0; + wcsession *WCC = WC; + + if (WCC != NULL) + StrBufAppendTemplate(Target, TP, WCC->trailing_javascript, 0); } -void tmplput_bstr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +void tmplput_csslocal(StrBuf *Target, WCTemplputParams *TP) { StrBufAppendBuf(Target, - SBstr(Tokens->Params[0]->Start, - Tokens->Params[0]->len), 0); + csslocal, 0); } +extern char static_local_dir[PATH_MAX]; + void InitModule_WEBCIT (void) { + char dir[SIZ]; WebcitAddUrlHandler(HKEY("blank"), blank_page, ANONYMOUS); WebcitAddUrlHandler(HKEY("do_template"), url_do_template, ANONYMOUS); WebcitAddUrlHandler(HKEY("sslg"), seconds_since_last_gexp, AJAX); WebcitAddUrlHandler(HKEY("ajax_servcmd"), ajax_servcmd, 0); - WebcitAddUrlHandler(HKEY("change_start_page"), change_start_page, 0); - WebcitAddUrlHandler(HKEY("toggle_self_service"), toggle_self_service, 0); - WebcitAddUrlHandler(HKEY("vcardphoto"), display_vcard_photo_img, NEED_URL); - WebcitAddUrlHandler(HKEY("mimepart"), view_mimepart, NEED_URL); - WebcitAddUrlHandler(HKEY("mimepart_download"), download_mimepart, NEED_URL); - WebcitAddUrlHandler(HKEY("diagnostics"), diagnostics, NEED_URL); RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE); - RegisterConditional(HKEY("COND:BSTR"), 1, ConditionalBstr, CTX_NONE); - RegisterNamespace("BSTR", 1, 2, tmplput_bstr, CTX_NONE); + RegisterNamespace("CSSLOCAL", 0, 0, tmplput_csslocal, CTX_NONE); RegisterNamespace("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, CTX_NONE); - RegisterNamespace("OFFERSTARTPAGE", 0, 0, offer_start_page, CTX_NONE); + RegisterNamespace("TRAILING_JAVASCRIPT", 0, 0, tmplput_trailing_javascript, CTX_NONE); + + snprintf(dir, SIZ, "%s/static.local/webcit.css", static_local_dir); + if (!access(dir, R_OK)) { + lprintf(9, "Using local Stylesheet [%s]\n", dir); + csslocal = NewStrBufPlain(HKEY("")); + } + else + lprintf(9, "Didn't find site local Stylesheet [%s]\n", dir); + } + +void +ServerStartModule_WEBCIT +(void) +{ + HandlerHash = NewHash(1, NULL); +} + + +void +ServerShutdownModule_WEBCIT +(void) +{ + FreeStrBuf(&csslocal); + DeleteHash(&HandlerHash); +} + + + +void +SessionNewModule_WEBCIT +(wcsession *sess) +{ + sess->ImportantMsg = NewStrBuf(); + sess->WBuf = NewStrBuf(); + sess->HBuf = NewStrBuf(); +} + +void +SessionDetachModule_WEBCIT +(wcsession *sess) +{ + if (StrLength(sess->WBuf) > SIZ * 30) /* Bigger than 120K? release. */ + { + FreeStrBuf(&sess->WBuf); + sess->WBuf = NewStrBuf(); + } + else + FlushStrBuf(sess->WBuf); + FlushStrBuf(sess->HBuf); +} + +void +SessionDestroyModule_WEBCIT +(wcsession *sess) +{ + FreeStrBuf(&sess->WBuf); + FreeStrBuf(&sess->HBuf); + FreeStrBuf(&sess->UrlFragment1); + FreeStrBuf(&sess->UrlFragment2); + FreeStrBuf(&sess->UrlFragment3); + FreeStrBuf(&sess->UrlFragment4); + FreeStrBuf(&sess->ImportantMsg); +} +