X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fwebcit.c;h=ed2eefc54bb4670794e31eb0a197948d4b8f32d8;hb=b4ad306de9560ec731db113ed509a1172209c444;hp=40ccb261e5e915ab36f8c5e2d2ac383acd24f632;hpb=1cbc91b714f7fcf7cc564fb3d67c1ca0239cc21f;p=citadel.git diff --git a/webcit/webcit.c b/webcit/webcit.c index 40ccb261e..ed2eefc54 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -5,7 +5,8 @@ * 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 "webcit.h" #include "groupdav.h" #include "webserver.h" @@ -20,9 +21,26 @@ */ static char *unset = "; expires=28-May-1971 18:10:00 GMT"; -/** - * \brief remove escaped strings from i.e. the url string (like %20 for blanks) - * \param buf the buffer to examine +HashList *HandlerHash = NULL; + +void WebcitAddUrlHandler(const char * UrlString, + long UrlSLen, + WebcitHandlerFunc F, + long Flags) +{ + WebcitHandler *NewHandler; + + if (HandlerHash == NULL) + HandlerHash = NewHash(1, NULL); + + NewHandler = (WebcitHandler*) malloc(sizeof(WebcitHandler)); + NewHandler->F = F; + NewHandler->Flags = Flags; + Put(HandlerHash, UrlString, UrlSLen, NewHandler, NULL); +} + +/* + * remove escaped strings from i.e. the url string (like %20 for blanks) */ long unescape_input(char *buf) { @@ -70,79 +88,86 @@ long unescape_input(char *buf) void free_url(void *U) { urlcontent *u = (urlcontent*) U; - free(u->url_data); + FreeStrBuf(&u->url_data); free(u); } -/** - * \brief Extract variables from the URL. - * \param url URL supplied by the HTTP parser +/* + * Extract variables from the URL. */ -void addurls(char *url) +void addurls(StrBuf *url) { - char *aptr, *bptr, *eptr; - char *up; - char buf[SIZ]; - int len, n, keylen; + const char *aptr, *bptr, *eptr, *up; +/// char *buf; + int len, keylen; urlcontent *u; struct wcsession *WCC = WC; if (WCC->urlstrings == NULL) - WCC->urlstrings = NewHash(); - eptr = buf + sizeof (buf); - up = url; - /** locate the = sign */ - n = safestrncpy(buf, up, sizeof buf); - if (n < 0) /** hm, we exceeded the buffer... hmmm what todo now? */ - n = -n; - up = buf; -// while ((up < eptr) && (*up != '?') && (*up != '&')) -// up++; - while (!IsEmptyStr(up)) { + 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 != '=') + if (*aptr != '=') { + ///free(buf); return; - *aptr = '\0'; + } + ///*aptr = '\0'; aptr++; bptr = aptr; while ((bptr < eptr) && (*bptr != '\0') && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) { bptr++; } - *bptr = '\0'; - u = (urlcontent *) malloc(sizeof(urlcontent)); + //*bptr = '\0'; + keylen = aptr - up - 1; /* -1 -> '=' */ + if(keylen > sizeof(u->url_key)) { + lprintf(1, "URLkey to long! [%s]", up); + continue; + } - keylen = safestrncpy(u->url_key, up, sizeof u->url_key); - if (keylen < 0){ + 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 = malloc(len + 2); - safestrncpy(u->url_data, aptr, len + 2); - u->url_data_size = unescape_input(u->url_data); - u->url_data[u->url_data_size] = '\0'; + u->url_data = NewStrBufPlain(aptr, len); + StrBufUnescape(u->url_data, 1); + up = bptr; ++up; - - lprintf(9, "%s = [%ld] %s\n", u->url_key, u->url_data_size, u->url_data); +#ifdef DEBUG_URLSTRINGS + lprintf(9, "%s = [%ld] %s\n", + u->url_key, + StrLength(u->url_data), + ChrPtr(u->url_data)); +#endif } + //free(buf); } -/** - * \brief free urlstring memory +/* + * free urlstring memory */ void free_urls(void) { DeleteHash(&WC->urlstrings); } -/** - * \brief Diagnostic function to display the contents of all variables +/* + * Diagnostic function to display the contents of all variables */ void dump_vars(void) @@ -151,39 +176,43 @@ void dump_vars(void) urlcontent *u; void *U; long HKLen; - char *HKey; + 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, u->url_data); + wprintf("%38s = %s\n", u->url_key, ChrPtr(u->url_data)); } } -/** - * \brief Return the value of a variable supplied to the current web page (from the url or a form) - * \param key The name of the variable we want +/* + * Return the value of a variable supplied to the current web page (from the url or a form) */ -const char *BSTR(char *key) + +const char *XBstr(const char *key, size_t keylen, size_t *len) { void *U; - if ((WC->urlstrings != NULL) && - GetHash(WC->urlstrings, key, strlen (key), &U)) - return ((urlcontent *)U)->url_data; - else + 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(char *key, size_t *len) +const char *XBSTR(const char *key, size_t *len) { void *U; if ((WC->urlstrings != NULL) && GetHash(WC->urlstrings, key, strlen (key), &U)){ - *len = ((urlcontent *)U)->url_data_size; - return ((urlcontent *)U)->url_data; + *len = StrLength(((urlcontent *)U)->url_data); + return ChrPtr(((urlcontent *)U)->url_data); } else { *len = 0; @@ -191,62 +220,189 @@ const char *XBSTR(char *key, size_t *len) } } -const char *Bstr(char *key, size_t keylen) + +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 ((urlcontent *)U)->url_data; + return ChrPtr(((urlcontent *)U)->url_data); else return (""); } -const char *XBstr(char *key, size_t keylen, size_t *len) +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)) { - *len = ((urlcontent *)U)->url_data_size; + GetHash(WC->urlstrings, key, keylen, &U)) return ((urlcontent *)U)->url_data; - } - else { - *len = 0; - return (""); - } + else + return NULL; } -/** - * \brief web-printing funcion. uses our vsnprintf wrapper - * \param format printf format string - * \param ... the varargs to put into formatstring +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; + va_list arg_ptr; + + if (WCC->WBuf == NULL) + WCC->WBuf = NewStrBuf(); + + 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)); +} + +/* + * http-header-printing funcion. uses our vsnprintf wrapper + */ +void hprintf(const char *format,...) +{ + struct wcsession *WCC = WC; va_list arg_ptr; - char wbuf[4096]; va_start(arg_ptr, format); - vsnprintf(wbuf, sizeof wbuf, format, arg_ptr); + StrBufVAppendPrintf(WCC->HBuf, format, arg_ptr); va_end(arg_ptr); - client_write(wbuf, strlen(wbuf)); +/// if (StrLength(WCC-WBuf) > 2048) + ///client_write(wbuf, strlen(wbuf)); } -/** - * \brief wrap up an HTTP session, closes tags, etc. - * \todo multiline params? - * \param print_standard_html_footer should be set to 0 to transmit only, 1 to - * append the main menu and closing tags, or 2 to - * append the closing tags only. +/* + * 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. */ void wDumpContent(int print_standard_html_footer) { if (print_standard_html_footer) { wprintf("\n"); /* end of "text" div */ - do_template("trailing"); + do_template("trailing", NULL); } /* If we've been saving it all up for one big output burst, @@ -256,99 +412,93 @@ void wDumpContent(int print_standard_html_footer) } -/** - * \brief Copy a string, escaping characters which have meaning in HTML. - * \param target target buffer - * \param strbuf source buffer - * \param nbsp If nonzero, spaces are converted to non-breaking spaces. - * \param nolinebreaks if set, linebreaks are removed from the string. + +/* + * 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); + 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); } -/** - * \brief WHAT??? - * \param strbuf what??? - * \param nbsp If nonzero, spaces are converted to non-breaking spaces. - * \param nolinebreaks if set, linebreaks are removed from the string. - */ + void escputs1(char *strbuf, int nbsp, int nolinebreaks) { - char *buf; - long Siz; + StrEscAppend(WC->WBuf, NULL, strbuf, nbsp, nolinebreaks); +} - if (strbuf == NULL) return; - Siz = (3 * strlen(strbuf)) + SIZ ; - buf = malloc(Siz); - stresc(buf, Siz, strbuf, nbsp, nolinebreaks); - wprintf("%s", buf); - free(buf); +void StrEscputs1(const StrBuf *strbuf, int nbsp, int nolinebreaks) +{ + StrEscAppend(WC->WBuf, strbuf, NULL, nbsp, nolinebreaks); } -/** - * \brief static wrapper for ecsputs1 - * \param strbuf buffer to print escaped to client +/* + * static wrapper for ecsputs1 */ void escputs(char *strbuf) { @@ -356,23 +506,42 @@ void escputs(char *strbuf) } -/** - * \brief urlescape buffer and print it to the client - * \param strbuf buffer to urlescape +/* + * static wrapper for ecsputs1 */ -void urlescputs(char *strbuf) +void StrEscPuts(const StrBuf *strbuf) { - char outbuf[SIZ]; - - urlesc(outbuf, SIZ, strbuf); - wprintf("%s", outbuf); + 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); +} + /** - * \brief Copy a string, escaping characters for JavaScript strings. - * \param target output string - * \param strbuf input string + * 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) { @@ -429,9 +598,8 @@ void jsesc(char *target, size_t tlen, char *strbuf) *tptr = '\0'; } -/** - * \brief escape and print java script - * \param strbuf the js code +/* + * escape and print javascript */ void jsescputs(char *strbuf) { @@ -441,113 +609,55 @@ void jsescputs(char *strbuf) wprintf("%s", outbuf); } -/** - * \brief Copy a string, escaping characters for message text hold - * \param target target buffer - * \param strbuf source buffer - */ -void msgesc(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 == '\n') - *tptr = ' '; - else if (*sptr == '\r') - *tptr = ' '; - else if (*sptr == '\'') { - if (tend - tptr < 8) - return; - *(tptr++) = '&'; - *(tptr++) = '#'; - *(tptr++) = '3'; - *(tptr++) = '9'; - *tptr = ';'; - } else { - *tptr = *sptr; - } - tptr++; sptr++; - } - *tptr = '\0'; -} - -/** - * \brief print a string to the client after cleaning it with msgesc() and stresc() - * \param strbuf string to be printed +/* + * print a string to the client after cleaning it with msgesc() and stresc() */ void msgescputs1( char *strbuf) { - char *outbuf; - char *outbuf2; - int buflen; + StrBuf *OutBuf; - if (strbuf == NULL) return; - buflen = 3 * strlen(strbuf) + SIZ; - outbuf = malloc( buflen); - outbuf2 = malloc( buflen); - msgesc(outbuf, buflen, strbuf); - stresc(outbuf2, buflen, outbuf, 0, 0); - wprintf("%s", outbuf2); - free(outbuf); - free(outbuf2); + if ((strbuf == NULL) || IsEmptyStr(strbuf)) + return; + OutBuf = NewStrBuf(); + StrMsgEscAppend(OutBuf, NULL, strbuf); + StrEscAppend(WC->WBuf, OutBuf, NULL, 0, 0); + FreeStrBuf(&OutBuf); } -/** - * \brief print a string to the client after cleaning it with msgesc() - * \param strbuf string to be printed +/* + * print a string to the client after cleaning it with msgesc() */ void msgescputs(char *strbuf) { - char *outbuf; - size_t len; - - if (strbuf == NULL) return; - len = (3 * strlen(strbuf)) + SIZ; - outbuf = malloc(len); - msgesc(outbuf, len, strbuf); - wprintf("%s", outbuf); - free(outbuf); + if ((strbuf != NULL) && !IsEmptyStr(strbuf)) + StrMsgEscAppend(WC->WBuf, NULL, strbuf); } -/** - * \brief Output all that important stuff that the browser will want to see +/* + * Output HTTP headers and leading HTML for a page */ -void output_headers( int do_httpheaders, /**< 1 = output HTTP headers */ - int do_htmlhead, /**< 1 = output HTML section and opener */ +void output_headers( int do_httpheaders, /* 1 = output HTTP headers */ + int do_htmlhead, /* 1 = output HTML section and opener */ - int do_room_banner, /**< 0=no, 1=yes, - * 2 = I'm going to embed my own, so don't open the - *
either. - */ + int do_room_banner, /* 0=no, 1=yes, + * 2 = I'm going to embed my own, so don't open the + *
either. + */ - int unset_cookies, /**< 1 = session is terminating, so unset the cookies */ - int suppress_check, /**< 1 = suppress check for instant messages */ - int cache /**< 1 = allow browser to cache this page */ + int unset_cookies, /* 1 = session is terminating, so unset the cookies */ + int suppress_check, /* 1 = suppress check for instant messages */ + int cache /* 1 = allow browser to cache this page */ ) { char cookie[1024]; char httpnow[128]; - wprintf("HTTP/1.1 200 OK\n"); + hprintf("HTTP/1.1 200 OK\n"); http_datestring(httpnow, sizeof httpnow, time(NULL)); if (do_httpheaders) { - wprintf("Content-type: text/html; charset=utf-8\r\n" + hprintf("Content-type: text/html; charset=utf-8\r\n" "Server: %s / %s\n" "Connection: close\r\n", PACKAGE_STRING, serv_info.serv_software @@ -555,14 +665,21 @@ void output_headers( int do_httpheaders, /**< 1 = output HTTP headers } if (cache) { - wprintf("Pragma: public\r\n" + char httpTomorow[128]; + + http_datestring(httpTomorow, sizeof httpTomorow, + time(NULL) + 60 * 60 * 24 * 2); + + hprintf("Pragma: public\r\n" "Cache-Control: max-age=3600, must-revalidate\r\n" - "Last-modified: %s\r\n", - httpnow + "Last-modified: %s\r\n" + "Expires: %s\r\n", + httpnow, + httpTomorow ); } else { - wprintf("Pragma: no-cache\r\n" + hprintf("Pragma: no-cache\r\n" "Cache-Control: no-store\r\n" "Expires: -1\r\n" ); @@ -572,29 +689,29 @@ void output_headers( int do_httpheaders, /**< 1 = output HTTP headers WC->wc_password, WC->wc_roomname); if (unset_cookies) { - wprintf("Set-cookie: webcit=%s; path=/\r\n", unset); + hprintf("Set-cookie: webcit=%s; path=/\r\n", unset); } else { - wprintf("Set-cookie: webcit=%s; path=/\r\n", cookie); + hprintf("Set-cookie: webcit=%s; path=/\r\n", cookie); if (server_cookie != NULL) { - wprintf("%s\n", server_cookie); + hprintf("%s\n", server_cookie); } } if (do_htmlhead) { begin_burst(); if (!access("static.local/webcit.css", R_OK)) { - svprintf("CSSLOCAL", WCS_STRING, + svprintf(HKEY("CSSLOCAL"), WCS_STRING, "" ); } - do_template("head"); + do_template("head", NULL); } - /** ICONBAR */ + /* ICONBAR */ if (do_htmlhead) { + begin_burst(); - - /** check for ImportantMessages (these display in a div overlaying the main screen) */ + /* check for ImportantMessages (these display in a div overlaying the main screen) */ if (!IsEmptyStr(WC->ImportantMessage)) { wprintf("
\n" ""); @@ -628,84 +745,58 @@ void output_headers( int do_httpheaders, /**< 1 = output HTTP headers } -/** - * \brief Generic function to do an HTTP redirect. Easy and fun. - * \param whichpage target url to 302 to +/* + * Generic function to do an HTTP redirect. Easy and fun. */ -void http_redirect(char *whichpage) { - wprintf("HTTP/1.1 302 Moved Temporarily\n"); - wprintf("Location: %s\r\n", whichpage); - wprintf("URI: %s\r\n", whichpage); - wprintf("Content-type: text/html; charset=utf-8\r\n\r\n"); +void http_redirect(const char *whichpage) { + hprintf("HTTP/1.1 302 Moved Temporarily\n"); + hprintf("Location: %s\r\n", whichpage); + hprintf("URI: %s\r\n", whichpage); + hprintf("Content-type: text/html; charset=utf-8\r\n"); wprintf(""); wprintf("Go here.", whichpage); wprintf("\n"); + end_burst(); } -/** - * \brief Output a piece of content to the web browser +/* + * Output a piece of content to the web browser using conformant HTTP and MIME semantics */ -void http_transmit_thing(char *thing, size_t length, const char *content_type, +void http_transmit_thing(const char *content_type, int is_static) { + lprintf(9, "http_transmit_thing(%s)%s\n", + content_type, + (is_static ? " (static)" : "") + ); output_headers(0, 0, 0, 0, 0, is_static); - wprintf("Content-type: %s\r\n" + hprintf("Content-type: %s\r\n" "Server: %s\r\n" "Connection: close\r\n", content_type, PACKAGE_STRING); -#ifdef HAVE_ZLIB - /** If we can send the data out compressed, please do so. */ - if (WC->gzip_ok) { - char *compressed_data = NULL; - size_t compressed_len; - - compressed_len = ((length * 101) / 100) + 100; - compressed_data = malloc(compressed_len); - - if (compress_gzip((Bytef *) compressed_data, - &compressed_len, - (Bytef *) thing, - (uLongf) length, Z_BEST_SPEED) == Z_OK) { - wprintf("Content-encoding: gzip\r\n" - "Content-length: %ld\r\n" - "\r\n", - (long) compressed_len - ); - client_write(compressed_data, (size_t)compressed_len); - free(compressed_data); - return; - } - } -#endif - - /** No compression ... just send it out as-is */ - wprintf("Content-length: %ld\r\n" - "\r\n", - (long) length - ); - client_write(thing, (size_t)length); + end_burst(); } -/** - * \brief print menu box like used in the floor view or admin interface. +/* + * print menu box like used in the floor view or admin interface. * This function takes pair of strings as va_args, - * \param Title Title string of the box - * \param Class CSS Class for the box - * \param nLines How many string pairs should we print? (URL, UrlText) - * \param ... Pairs of URL Strings and their Names + * Title Title string of the box + * Class CSS Class for the box + * nLines How many string pairs should we print? (URL, UrlText) + * ... Pairs of URL Strings and their Names */ void print_menu_box(char* Title, char *Class, int nLines, ...) { va_list arg_list; long i; - svprintf("BOXTITLE", WCS_STRING, Title); - do_template("beginbox"); + svput("BOXTITLE", WCS_STRING, Title); + do_template("beginbox", NULL); wprintf("
    ", Class); @@ -722,115 +813,101 @@ void print_menu_box(char* Title, char *Class, int nLines, ...) wprintf("
"); - do_template("endbox"); + do_template("endbox", NULL); } -/** - * \brief dump out static pages from disk - * \param what the file urs to print +/* + * dump out static pages from disk */ void output_static(char *what) { - FILE *fp; + int fd; struct stat statbuf; off_t bytes; off_t count = 0; - size_t res; - char *bigbuffer; const char *content_type; int len; + const char *Err; - fp = fopen(what, "rb"); - if (fp == NULL) { + fd = open(what, O_RDONLY); + if (fd <= 0) { lprintf(9, "output_static('%s') -- NOT FOUND --\n", what); - wprintf("HTTP/1.1 404 %s\r\n", strerror(errno)); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); + hprintf("HTTP/1.1 404 %s\r\n", strerror(errno)); + hprintf("Content-Type: text/plain\r\n"); wprintf("Cannot open %s: %s\r\n", what, strerror(errno)); + end_burst(); } else { len = strlen (what); content_type = GuessMimeByFilename(what, len); - if (fstat(fileno(fp), &statbuf) == -1) { + if (fstat(fd, &statbuf) == -1) { lprintf(9, "output_static('%s') -- FSTAT FAILED --\n", what); - wprintf("HTTP/1.1 404 %s\r\n", strerror(errno)); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); + hprintf("HTTP/1.1 404 %s\r\n", strerror(errno)); + hprintf("Content-Type: text/plain\r\n"); wprintf("Cannot fstat %s: %s\n", what, strerror(errno)); + end_burst(); return; } count = 0; bytes = statbuf.st_size; - if ((bigbuffer = malloc(bytes + 2)) == NULL) { - lprintf(9, "output_static('%s') -- MALLOC FAILED (%s) --\n", what, strerror(errno)); - wprintf("HTTP/1.1 500 internal server error\r\n"); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); - return; - } - while (count < bytes) { - if ((res = fread(bigbuffer + count, 1, bytes - count, fp)) == 0) { - lprintf(9, "output_static('%s') -- FREAD FAILED (%s) %zu bytes of %zu --\n", what, strerror(errno), bytes - count, bytes); - wprintf("HTTP/1.1 500 internal server error \r\n"); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); + + if (StrBufReadBLOB(WC->WBuf, &fd, 1, bytes, &Err) < 0) + { + if (fd > 0) close(fd); + lprintf(9, "output_static('%s') -- FREAD FAILED (%s) --\n", what, strerror(errno)); + hprintf("HTTP/1.1 500 internal server error \r\n"); + hprintf("Content-Type: text/plain\r\n"); + end_burst(); return; - } - count += res; } - fclose(fp); + close(fd); lprintf(9, "output_static('%s') %s\n", what, content_type); - http_transmit_thing(bigbuffer, (size_t)bytes, content_type, 1); - free(bigbuffer); + http_transmit_thing(content_type, 1); } - if (!strcasecmp(bstr("force_close_session"), "yes")) { + if (yesbstr("force_close_session")) { end_webcit_session(); } } -/** - * \brief When the browser requests an image file from the Citadel server, +/* + * 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]; - char *xferbuf = NULL; 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); - xferbuf = malloc(bytes + 2); /** Read it from the server */ - read_server_binary(xferbuf, bytes); - serv_puts("CLOS"); - serv_getln(buf, sizeof buf); - - MimeType = GuessMimeType (xferbuf, bytes); - /** Write it to the browser */ - if (!IsEmptyStr(MimeType)) - { - http_transmit_thing(xferbuf, - (size_t)bytes, - MimeType, - 0); - free(xferbuf); - return; + + 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 */ - free(xferbuf); } - /** + /* * Instead of an ugly 404, send a 1x1 transparent GIF * when there's no such image on the server. */ @@ -839,27 +916,60 @@ void output_image() output_static(blank_gif); } -/** - * \brief Generic function to output an arbitrary MIME part from an arbitrary - * message number on the server. +/* + * 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. * - * \param msgnum Number of the item on the citadel server - * \param partnum The MIME part to be output - * \param force_download Nonzero to force set the Content-Type: header - * to "application/octet-stream" + * 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(char *msgnum, char *partnum, int force_download) +void mimepart(const char *msgnum, const char *partnum, int force_download) { char buf[256]; off_t bytes; char content_type[256]; - char *content = NULL; serv_printf("OPNA %s|%s", msgnum, partnum); serv_getln(buf, sizeof buf); if (buf[0] == '2') { bytes = extract_long(&buf[4], 0); - content = malloc(bytes + 2); if (force_download) { strcpy(content_type, "application/octet-stream"); } @@ -867,26 +977,23 @@ void mimepart(char *msgnum, char *partnum, int force_download) extract_token(content_type, &buf[4], 3, '|', sizeof content_type); } output_headers(0, 0, 0, 0, 0, 0); - read_server_binary(content, bytes); + + read_server_binary(WC->WBuf, bytes); serv_puts("CLOS"); serv_getln(buf, sizeof buf); - http_transmit_thing(content, bytes, content_type, 0); - free(content); + http_transmit_thing(content_type, 0); } else { - wprintf("HTTP/1.1 404 %s\n", &buf[4]); + hprintf("HTTP/1.1 404 %s\n", &buf[4]); output_headers(0, 0, 0, 0, 0, 0); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); + hprintf("Content-Type: text/plain\r\n"); wprintf(_("An error occurred while retrieving this part: %s\n"), &buf[4]); + end_burst(); } - } -/** - * \brief Read any MIME part of a message, from the server, into memory. - * \param msgnum number of the message on the citadel server - * \param partnum the MIME part to be loaded +/* + * Read any MIME part of a message, from the server, into memory. */ char *load_mimepart(long msgnum, char *partnum) { @@ -910,19 +1017,19 @@ char *load_mimepart(long msgnum, char *partnum) else { return(NULL); } - } -/** - * \brief Convenience functions to display a page containing only a string - * \param titlebarcolor color of the titlebar of the frame - * \param titlebarmsg text to display in the title bar - * \param messagetext body of the box +/* + * Convenience functions to display a page containing only a string + * + * titlebarcolor color of the titlebar of the frame + * titlebarmsg text to display in the title bar + * messagetext body of the box */ void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext) { - wprintf("HTTP/1.1 200 OK\n"); + hprintf("HTTP/1.1 200 OK\n"); output_headers(1, 1, 2, 0, 0, 0); wprintf("
\n"); wprintf("
", titlebarcolor); @@ -936,8 +1043,8 @@ void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext) } -/** - * \brief Display a blank page. +/* + * Display a blank page. */ void blank_page(void) { output_headers(1, 1, 0, 0, 0, 0); @@ -945,19 +1052,23 @@ void blank_page(void) { } -/** - * \brief A template has been requested +/* + * A template has been requested */ void url_do_template(void) { - do_template(bstr("template")); + 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(); } -/** - * \brief Offer to make any page the user's "start page." +/* + * Offer to make any page the user's "start page." */ -void offer_start_page(void) { +void offer_start_page(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) { wprintf("this_page); wprintf("\">"); @@ -973,8 +1084,8 @@ void offer_start_page(void) { } -/** - * \brief Change the user's start page +/* + * Change the user's start page */ void change_start_page(void) { @@ -986,18 +1097,17 @@ void change_start_page(void) { return; } - set_preference("startpage", bstr("startpage"), 1); + set_preference("startpage", NewStrBufPlain(bstr("startpage"), -1), 1); output_headers(1, 1, 0, 0, 0, 0); - do_template("newstartpage"); + do_template("newstartpage", NULL); wDumpContent(1); } -/** - * \brief convenience function to indicate success - * \param successmessage the mesage itself +/* + * convenience function to indicate success */ void display_success(char *successmessage) { @@ -1005,63 +1115,65 @@ void display_success(char *successmessage) } -/** - * \brief Authorization required page +/* + * Authorization required page * This is probably temporary and should be revisited - * \param message message to put in header -*/ + */ void authorization_required(const char *message) { - wprintf("HTTP/1.1 401 Authorization Required\r\n"); - wprintf("WWW-Authenticate: Basic realm=\"\"\r\n", serv_info.serv_humannode); - wprintf("Content-Type: text/html\r\n\r\n"); + hprintf("HTTP/1.1 401 Authorization Required\r\n"); + hprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n", serv_info.serv_humannode); + hprintf("Content-Type: text/html\r\n"); wprintf("

"); wprintf(_("Authorization Required")); wprintf("

\r\n"); wprintf(_("The resource you requested requires a valid username and password. " "You could not be logged in: %s\n"), message); wDumpContent(0); + } -/** - * \brief 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. +/* + * 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. * - * \param name Name of the item being uploaded - * \param filename Filename of the item being uploaded - * \param partnum MIME part identifier (not needed) - * \param disp MIME content disposition (not needed) - * \param content The actual data - * \param cbtype MIME content-type - * \param cbcharset Character set - * \param length Content length - * \param encoding MIME encoding type (not needed) - * \param userdata Not used here + * 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) + * 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, 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(); + 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 = malloc(length + 1); - u->url_data_size = length; - memcpy(u->url_data, content, length); - u->url_data[length] = 0; + u->url_data = NewStrBufPlain(content, length); + Put(WC->urlstrings, u->url_key, strlen(u->url_key), u, free_url); - - /* lprintf(9, "Key: <%s> Data: <%s>\n", u->url_key, u->url_data); */ +#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 */ @@ -1082,33 +1194,32 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp, } -/** - * \brief Convenience functions to wrap around asynchronous ajax responses +/* + * Convenience functions to wrap around asynchronous ajax responses */ void begin_ajax_response(void) { + struct wcsession *WCC = WC; + + FlushStrBuf(WCC->HBuf); output_headers(0, 0, 0, 0, 0, 0); - wprintf("Content-type: text/html; charset=UTF-8\r\n" + hprintf("Content-type: text/html; charset=UTF-8\r\n" "Server: %s\r\n" "Connection: close\r\n" - "Pragma: no-cache\r\n" - "Cache-Control: no-cache\r\n" - "Expires: -1\r\n" , PACKAGE_STRING); begin_burst(); } -/** - * \brief print ajax response footer +/* + * print ajax response footer */ void end_ajax_response(void) { - wprintf("\r\n"); wDumpContent(0); } -/** - * \brief Wraps a Citadel server command in an AJAX transaction. +/* + * Wraps a Citadel server command in an AJAX transaction. */ void ajax_servcmd(void) { @@ -1152,7 +1263,7 @@ void ajax_servcmd(void) end_ajax_response(); - /** + /* * This is kind of an ugly hack, but this is the only place it can go. * If the command was GEXP, then the instant messenger window must be * running, so reset the "last_pager_check" watchdog timer so @@ -1164,19 +1275,19 @@ void ajax_servcmd(void) } -/** - * \brief Helper function for the asynchronous check to see if we need +/* + * Helper function for the asynchronous check to see if we need * to open the instant messenger window. */ void seconds_since_last_gexp(void) { char buf[256]; - begin_ajax_response(); if ( (time(NULL) - WC->last_pager_check) < 30) { wprintf("NO\n"); } else { + memset(buf, 5, 0); serv_puts("NOOP"); serv_getln(buf, sizeof buf); if (buf[3] == '*') { @@ -1186,39 +1297,53 @@ void seconds_since_last_gexp(void) wprintf("NO"); } } - end_ajax_response(); } +/** + * \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; +} - -/** - * \brief Entry point for WebCit transaction +/* + * Entry point for WebCit transaction */ -void session_loop(struct httprequest *req) +void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method, StrBuf *ReadBuf) { - char cmd[1024]; + const char *pch, *pchs, *pche; + void *vLine; char action[1024]; char arg[8][128]; size_t sizes[10]; char *index[10]; char buf[SIZ]; - char request_method[128]; - char pathname[1024]; - int a, b, nBackDots, nEmpty; + int a, nBackDots, nEmpty; int ContentLength = 0; - int BytesRead = 0; - char ContentType[512]; - char *content = NULL; - char *content_end = NULL; - struct httprequest *hptr; + StrBuf *ContentType = NULL; + StrBuf *UrlLine = NULL; + StrBuf *content = NULL; + const char *content_end = NULL; char browser_host[256]; char user_agent[256]; int body_start = 0; int is_static = 0; int n_static = 0; int len = 0; - /** + /* * 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. */ @@ -1228,8 +1353,8 @@ void session_loop(struct httprequest *req) char c_httpauth_string[SIZ]; char c_httpauth_user[SIZ]; char c_httpauth_pass[SIZ]; - char cookie[SIZ]; - + struct wcsession *WCC; + safestrncpy(c_username, "", sizeof c_username); safestrncpy(c_password, "", sizeof c_password); safestrncpy(c_roomname, "", sizeof c_roomname); @@ -1238,18 +1363,18 @@ void session_loop(struct httprequest *req) safestrncpy(c_httpauth_pass, DEFAULT_HTTPAUTH_PASS, sizeof c_httpauth_pass); strcpy(browser_host, ""); - WC->upload_length = 0; - WC->upload = NULL; - WC->vars = NULL; - WC->is_wap = 0; + WCC= WC; + if (WCC->WBuf == NULL) + WC->WBuf = NewStrBufPlain(NULL, 32768); + FlushStrBuf(WCC->WBuf); - hptr = req; - if (hptr == NULL) return; + if (WCC->HBuf == NULL) + WCC->HBuf = NewStrBuf(); + FlushStrBuf(WCC->HBuf); - safestrncpy(cmd, hptr->line, sizeof cmd); - hptr = hptr->next; - extract_token(request_method, cmd, 0, ' ', sizeof request_method); - extract_token(pathname, cmd, 1, ' ', sizeof pathname); + WCC->upload_length = 0; + WCC->upload = NULL; + WCC->is_mobile = 0; /** Figure out the action */ index[0] = action; @@ -1264,7 +1389,7 @@ void session_loop(struct httprequest *req) nEmpty = 0; for ( a = 0; a < 9; ++a) { - extract_token(index[a], pathname, a + 1, '/', sizes[a]); + extract_token(index[a], ChrPtr(ReqLine), a + 1, '/', sizes[a]); if (strstr(index[a], "?")) *strstr(index[a], "?") = 0; if (strstr(index[a], "&")) *strstr(index[a], "&") = 0; if (strstr(index[a], " ")) *strstr(index[a], " ") = 0; @@ -1274,109 +1399,122 @@ void session_loop(struct httprequest *req) nEmpty++; } - while (hptr != NULL) { - safestrncpy(buf, hptr->line, sizeof buf); - /* lprintf(9, "HTTP HEADER: %s\n", buf); */ - hptr = hptr->next; - if (!strncasecmp(buf, "Cookie: webcit=", 15)) { - safestrncpy(cookie, &buf[15], sizeof cookie); - cookie_to_stuff(cookie, NULL, - c_username, sizeof c_username, - c_password, sizeof c_password, - c_roomname, sizeof c_roomname); - } - else if (!strncasecmp(buf, "Authorization: Basic ", 21)) { - CtdlDecodeBase64(c_httpauth_string, &buf[21], strlen(&buf[21])); - extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user); - extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass); - } - else if (!strncasecmp(buf, "Content-length: ", 16)) { - ContentLength = atoi(&buf[16]); - } - else if (!strncasecmp(buf, "Content-type: ", 14)) { - safestrncpy(ContentType, &buf[14], sizeof ContentType); - } - else if (!strncasecmp(buf, "User-agent: ", 12)) { - safestrncpy(user_agent, &buf[12], sizeof user_agent); - } - else if (!strncasecmp(buf, "X-Forwarded-Host: ", 18)) { - if (follow_xff) { - safestrncpy(WC->http_host, &buf[18], sizeof WC->http_host); - } - } - else if (!strncasecmp(buf, "Host: ", 6)) { - if (IsEmptyStr(WC->http_host)) { - safestrncpy(WC->http_host, &buf[6], sizeof WC->http_host); - } + if (GetHash(HTTPHeaders, HKEY("COOKIE"), &vLine) && + (vLine != NULL)){ + cookie_to_stuff((StrBuf *)vLine, NULL, + c_username, sizeof c_username, + c_password, sizeof c_password, + c_roomname, sizeof c_roomname); + } + if (GetHash(HTTPHeaders, HKEY("AUTHORIZATION"), &vLine) && + (vLine!=NULL)) { + CtdlDecodeBase64(c_httpauth_string, ChrPtr((StrBuf*)vLine), StrLength((StrBuf*)vLine)); + extract_token(c_httpauth_user, c_httpauth_string, 0, ':', sizeof c_httpauth_user); + extract_token(c_httpauth_pass, c_httpauth_string, 1, ':', sizeof c_httpauth_pass); + } + if (GetHash(HTTPHeaders, HKEY("CONTENT-LENGTH"), &vLine) && + (vLine!=NULL)) { + ContentLength = StrToi((StrBuf*)vLine); + } + if (GetHash(HTTPHeaders, HKEY("CONTENT-TYPE"), &vLine) && + (vLine!=NULL)) { + ContentType = (StrBuf*)vLine; + } + if (GetHash(HTTPHeaders, HKEY("USER-AGENT"), &vLine) && + (vLine!=NULL)) { + safestrncpy(user_agent, ChrPtr((StrBuf*)vLine), sizeof user_agent); +#ifdef TECH_PREVIEW + if ((WCC->is_mobile < 0) && is_mobile_ua(&buf[12])) { + WCC->is_mobile = 1; } - else if (!strncasecmp(buf, "X-Forwarded-For: ", 17)) { - safestrncpy(browser_host, &buf[17], sizeof browser_host); - while (num_tokens(browser_host, ',') > 1) { - remove_token(browser_host, 0, ','); - } - striplt(browser_host); + else { + WCC->is_mobile = 0; } - /** Only WAP gateways explicitly name this content-type */ - else if (strstr(buf, "text/vnd.wap.wml")) { - WC->is_wap = 1; +#endif + } + if ((follow_xff) && + GetHash(HTTPHeaders, HKEY("X-FORWARDED-HOST"), &vLine) && + (vLine != NULL)) { + safestrncpy(WCC->http_host, &buf[18], sizeof WCC->http_host); + } + if (IsEmptyStr(WCC->http_host) && + GetHash(HTTPHeaders, HKEY("HOST"), &vLine) && + (vLine!=NULL)) { + safestrncpy(WCC->http_host, + ChrPtr((StrBuf*)vLine), + sizeof WCC->http_host); + + } + if (GetHash(HTTPHeaders, HKEY("X-FORWARDED-FOR"), &vLine) && + (vLine!=NULL)) { + safestrncpy(browser_host, + ChrPtr((StrBuf*) vLine), + sizeof browser_host); + while (num_tokens(browser_host, ',') > 1) { + remove_token(browser_host, 0, ','); } + striplt(browser_host); } if (ContentLength > 0) { - content = malloc(ContentLength + SIZ); - memset(content, 0, ContentLength + SIZ); - snprintf(content, ContentLength + SIZ, "Content-type: %s\n" - "Content-length: %d\n\n", - ContentType, ContentLength); - body_start = strlen(content); + 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); +*/ + body_start = StrLength(content); /** Read the entire input data at once. */ - client_read(WC->http_sock, &content[BytesRead+body_start], ContentLength); - - if (!strncasecmp(ContentType, "application/x-www-form-urlencoded", 33)) { - addurls(&content[body_start]); - } else if (!strncasecmp(ContentType, "multipart", 9)) { - content_end = content + ContentLength + body_start; - mime_parser(content, content_end, *upload_handler, NULL, NULL, NULL, 0); + client_read(&WCC->http_sock, content, ReadBuf, ContentLength); + + if (!strncasecmp(ChrPtr(ContentType), "application/x-www-form-urlencoded", 33)) { + StrBufCutLeft(content, body_start); + addurls(content); + } else if (!strncasecmp(ChrPtr(ContentType), "multipart", 9)) { + content_end = ChrPtr(content) + ContentLength + body_start; + mime_parser(ChrPtr(content), content_end, *upload_handler, NULL, NULL, NULL, 0); } } else { content = NULL; } - /** make a note of where we are in case the user wants to save it */ - safestrncpy(WC->this_page, cmd, sizeof(WC->this_page)); - remove_token(WC->this_page, 2, ' '); - remove_token(WC->this_page, 0, ' '); - - /** If there are variables in the URL, we must grab them now */ - len = strlen(cmd); - for (a = 0; a < len; ++a) { - if ((cmd[a] == '?') || (cmd[a] == '&')) { - for (b = a; b < len; ++b) { - if (isspace(cmd[b])){ - cmd[b] = 0; - len = b - 1; - } - } - addurls(&cmd[a + 1]); - cmd[a] = 0; - len = a - 1; + /* 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, ' '); + + /* 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); + addurls(UrlLine); + break; } + pch ++; } + FreeStrBuf(&UrlLine); - /** If it's a "force 404" situation then display the error and bail. */ + /* If it's a "force 404" situation then display the error and bail. */ if (!strcmp(action, "404")) { - wprintf("HTTP/1.1 404 Not found\r\n"); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); + 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. */ + /* Static content can be sent without connecting to Citadel. */ is_static = 0; - for (a=0; a 0) { lprintf(9, "Comparing supplied nonce %s to session nonce %ld\n", - bstr("nonce"), WC->nonce); - if (atoi(bstr("nonce")) != WC->nonce) { + bstr("nonce"), WCC->nonce); + if (ibstr("nonce") != WCC->nonce) { lprintf(9, "Ignoring request with mismatched nonce.\n"); - wprintf("HTTP/1.1 404 Security check failed\r\n"); - wprintf("Content-Type: text/plain\r\n"); - wprintf("\r\n"); + hprintf("HTTP/1.1 404 Security check failed\r\n"); + hprintf("Content-Type: text/plain\r\n"); wprintf("Security check failed.\r\n"); + end_burst(); goto SKIP_ALL_THIS_CRAP; } } - /** + /* * If we're not connected to a Citadel server, try to hook up the * connection now. */ - if (!WC->connected) { + if (!WCC->connected) { if (!strcasecmp(ctdlhost, "uds")) { /* unix domain socket */ snprintf(buf, SIZ, "%s/citadel.socket", ctdlport); - WC->serv_sock = uds_connectsock(buf); + WCC->serv_sock = uds_connectsock(buf); } else { /* tcp socket */ - WC->serv_sock = tcp_connectsock(ctdlhost, ctdlport); + WCC->serv_sock = tcp_connectsock(ctdlhost, ctdlport); } - if (WC->serv_sock < 0) { + if (WCC->serv_sock < 0) { do_logout(); goto SKIP_ALL_THIS_CRAP; } else { - WC->connected = 1; + WCC->connected = 1; serv_getln(buf, sizeof buf); /** get the server welcome message */ /** @@ -1455,7 +1593,7 @@ void session_loop(struct httprequest *req) * and such a header has already turned up something. */ if ( (!follow_xff) || (strlen(browser_host) == 0) ) { - locate_host(browser_host, WC->http_sock); + locate_host(browser_host, WCC->http_sock); } get_serv_info(browser_host, user_agent); @@ -1475,8 +1613,8 @@ void session_loop(struct httprequest *req) } } } - - /** +////////todo: restore language in this case + /* * Functions which can be performed without logging in */ if (!strcasecmp(action, "listsub")) { @@ -1484,15 +1622,15 @@ void session_loop(struct httprequest *req) goto SKIP_ALL_THIS_CRAP; } if (!strcasecmp(action, "freebusy")) { - do_freebusy(cmd); + do_freebusy(ChrPtr(ReqLine)); goto SKIP_ALL_THIS_CRAP; } - /** + /* * If we're not logged in, but we have HTTP Authentication data, * try logging in to Citadel using that. */ - if ((!WC->logged_in) + if ((!WCC->logged_in) && (strlen(c_httpauth_user) > 0) && (strlen(c_httpauth_pass) > 0)) { serv_printf("USER %s", c_httpauth_user); @@ -1503,17 +1641,17 @@ void session_loop(struct httprequest *req) if (buf[0] == '2') { become_logged_in(c_httpauth_user, c_httpauth_pass, buf); - safestrncpy(WC->httpauth_user, c_httpauth_user, sizeof WC->httpauth_user); - safestrncpy(WC->httpauth_pass, c_httpauth_pass, sizeof WC->httpauth_pass); + safestrncpy(WCC->httpauth_user, c_httpauth_user, sizeof WCC->httpauth_user); + safestrncpy(WCC->httpauth_pass, c_httpauth_pass, sizeof WCC->httpauth_pass); } else { - /** Should only display when password is wrong */ + /* Should only display when password is wrong */ authorization_required(&buf[4]); goto SKIP_ALL_THIS_CRAP; } } } - /** This needs to run early */ + /* This needs to run early */ #ifdef TECH_PREVIEW if (!strcasecmp(action, "rss")) { display_rss(bstr("room"), request_method); @@ -1521,38 +1659,41 @@ void session_loop(struct httprequest *req) } #endif - /** + /* * The GroupDAV stuff relies on HTTP authentication instead of * our session's authentication. */ if (!strncasecmp(action, "groupdav", 8)) { - groupdav_main(req, ContentType, /* do GroupDAV methods */ - ContentLength, content+body_start); - if (!WC->logged_in) { - WC->killthis = 1; /* If not logged in, don't */ + groupdav_main(HTTPHeaders, + ReqLine, request_method, + ContentType, /* do GroupDAV methods */ + ContentLength, content, body_start); + if (!WCC->logged_in) { + WCC->killthis = 1; /* If not logged in, don't */ } /* keep the session active */ goto SKIP_ALL_THIS_CRAP; } - /** + /* * Automatically send requests with any method other than GET or * POST to the GroupDAV code as well. */ - if ((strcasecmp(request_method, "GET")) && (strcasecmp(request_method, "POST"))) { - groupdav_main(req, ContentType, /** do GroupDAV methods */ - ContentLength, content+body_start); - if (!WC->logged_in) { - WC->killthis = 1; /** If not logged in, don't */ + if ((strcasecmp(ChrPtr(request_method), "GET")) && (strcasecmp(ChrPtr(request_method), "POST"))) { + groupdav_main(HTTPHeaders, ReqLine, + request_method, ContentType, /** do GroupDAV methods */ + ContentLength, content, body_start); + if (!WCC->logged_in) { + WCC->killthis = 1; /** If not logged in, don't */ } /** keep the session active */ goto SKIP_ALL_THIS_CRAP; } - /** + /* * If we're not logged in, but we have username and password cookies * supplied by the browser, try using them to log in. */ - if ((!WC->logged_in) + if ((!WCC->logged_in) && (!IsEmptyStr(c_username)) && (!IsEmptyStr(c_password))) { serv_printf("USER %s", c_username); @@ -1561,19 +1702,24 @@ void session_loop(struct httprequest *req) 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 */ + } } } } - /** + /* * If we don't have a current room, but a cookie specifying the * current room is supplied, make an effort to go there. */ - if ((IsEmptyStr(WC->wc_roomname)) && (!IsEmptyStr(c_roomname))) { + if ((IsEmptyStr(WCC->wc_roomname)) && (!IsEmptyStr(c_roomname))) { serv_printf("GOTO %s", c_roomname); serv_getln(buf, sizeof buf); if (buf[0] == '2') { - safestrncpy(WC->wc_roomname, c_roomname, sizeof WC->wc_roomname); + safestrncpy(WCC->wc_roomname, c_roomname, sizeof WCC->wc_roomname); } } @@ -1581,377 +1727,57 @@ void session_loop(struct httprequest *req) output_image(); } else if (!strcasecmp(action, "display_mime_icon")) { display_mime_icon(); - - /** - * All functions handled below this point ... make sure we log in - * before doing anything else! - */ - } else if ((!WC->logged_in) && (!strcasecmp(action, "login"))) { - do_login(); - } else if (!WC->logged_in) { - display_login(NULL); } - - /** - * Various commands... - */ - - else if (!strcasecmp(action, "do_welcome")) { - do_welcome(); - } else if (!strcasecmp(action, "blank")) { - blank_page(); - } else if (!strcasecmp(action, "do_template")) { - url_do_template(); - } else if (!strcasecmp(action, "display_aide_menu")) { - display_aide_menu(); - } else if (!strcasecmp(action, "server_shutdown")) { - display_shutdown(); - } else if (!strcasecmp(action, "display_main_menu")) { - display_main_menu(); - } else if (!strcasecmp(action, "who")) { - who(); - } else if (!strcasecmp(action, "sslg")) { - seconds_since_last_gexp(); - } else if (!strcasecmp(action, "who_inner_html")) { - begin_ajax_response(); - who_inner_div(); - end_ajax_response(); - } else if (!strcasecmp(action, "wholist_section")) { - begin_ajax_response(); - wholist_section(); - end_ajax_response(); - } else if (!strcasecmp(action, "new_messages_html")) { - begin_ajax_response(); - new_messages_section(); - end_ajax_response(); - } else if (!strcasecmp(action, "tasks_inner_html")) { - begin_ajax_response(); - tasks_section(); - end_ajax_response(); - } else if (!strcasecmp(action, "calendar_inner_html")) { - begin_ajax_response(); - calendar_section(); - end_ajax_response(); - } else if (!strcasecmp(action, "mini_calendar")) { - begin_ajax_response(); - ajax_mini_calendar(); - end_ajax_response(); - } else if (!strcasecmp(action, "iconbar_ajax_menu")) { - begin_ajax_response(); - do_iconbar(); - end_ajax_response(); - } else if (!strcasecmp(action, "iconbar_ajax_rooms")) { - begin_ajax_response(); - do_iconbar_roomlist(); - end_ajax_response(); - } else if (!strcasecmp(action, "knrooms")) { - knrooms(); - } else if (!strcasecmp(action, "gotonext")) { - slrp_highest(); - gotonext(); - } else if (!strcasecmp(action, "skip")) { - gotonext(); - } else if (!strcasecmp(action, "ungoto")) { - ungoto(); - } else if (!strcasecmp(action, "dotgoto")) { - if (WC->wc_view != VIEW_MAILBOX) { /* dotgoto acts like dotskip when we're in a mailbox view */ - slrp_highest(); + 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); + } + 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(); + } } - smart_goto(bstr("room")); - } else if (!strcasecmp(action, "dotskip")) { - smart_goto(bstr("room")); - } else if (!strcasecmp(action, "termquit")) { - do_logout(); - } else if (!strcasecmp(action, "readnew")) { - readloop("readnew"); - } else if (!strcasecmp(action, "readold")) { - readloop("readold"); - } else if (!strcasecmp(action, "readfwd")) { - readloop("readfwd"); - } else if (!strcasecmp(action, "headers")) { - readloop("headers"); - } else if (!strcasecmp(action, "do_search")) { - readloop("do_search"); - } else if (!strcasecmp(action, "msg")) { - embed_message(index[1]); - } else if (!strcasecmp(action, "printmsg")) { - print_message(index[1]); - } else if (!strcasecmp(action, "msgheaders")) { - display_headers(index[1]); - } else if (!strcasecmp(action, "wiki")) { - display_wiki_page(); - } else if (!strcasecmp(action, "display_enter")) { - display_enter(); - } else if (!strcasecmp(action, "post")) { - post_message(); - } else if (!strcasecmp(action, "move_msg")) { - move_msg(); - } else if (!strcasecmp(action, "delete_msg")) { - delete_msg(); - } else if (!strcasecmp(action, "userlist")) { - userlist(); - } else if (!strcasecmp(action, "showuser")) { - showuser(); - } else if (!strcasecmp(action, "display_page")) { - display_page(); - } else if (!strcasecmp(action, "page_user")) { - page_user(); - } else if (!strcasecmp(action, "chat")) { - do_chat(); - } else if (!strcasecmp(action, "display_private")) { - display_private("", 0); - } else if (!strcasecmp(action, "goto_private")) { - goto_private(); - } else if (!strcasecmp(action, "zapped_list")) { - zapped_list(); - } else if (!strcasecmp(action, "display_zap")) { - display_zap(); - } else if (!strcasecmp(action, "zap")) { - zap(); - } else if (!strcasecmp(action, "display_entroom")) { - display_entroom(); - } else if (!strcasecmp(action, "entroom")) { - entroom(); - } else if (!strcasecmp(action, "display_whok")) { - display_whok(); - } else if (!strcasecmp(action, "do_invt_kick")) { - do_invt_kick(); - } else if (!strcasecmp(action, "display_editroom")) { - display_editroom(); - } else if (!strcasecmp(action, "netedit")) { - netedit(); - } else if (!strcasecmp(action, "editroom")) { - editroom(); - } else if (!strcasecmp(action, "display_editinfo")) { - display_edit(_("Room info"), "EINF 0", "RINF", "editinfo", 1); - } else if (!strcasecmp(action, "editinfo")) { - save_edit(_("Room info"), "EINF 1", 1); - } else if (!strcasecmp(action, "display_editbio")) { - snprintf(buf, SIZ, "RBIO %s", WC->wc_fullname); - display_edit(_("Your bio"), "NOOP", buf, "editbio", 3); - } else if (!strcasecmp(action, "editbio")) { - save_edit(_("Your bio"), "EBIO", 0); - } else if (!strcasecmp(action, "confirm_move_msg")) { - confirm_move_msg(); - } else if (!strcasecmp(action, "delete_room")) { - delete_room(); - } else if (!strcasecmp(action, "validate")) { - validate(); - /* The users photo display / upload facility */ - } else if (!strcasecmp(action, "display_editpic")) { - display_graphics_upload(_("your photo"), - "_userpic_", - "editpic"); - } else if (!strcasecmp(action, "editpic")) { - do_graphics_upload("_userpic_"); - /* room picture dispay / upload facility */ - } else if (!strcasecmp(action, "display_editroompic")) { - display_graphics_upload(_("the icon for this room"), - "_roompic_", - "editroompic"); - } else if (!strcasecmp(action, "editroompic")) { - do_graphics_upload("_roompic_"); - /* the greetingpage hello pic */ - } else if (!strcasecmp(action, "display_edithello")) { - display_graphics_upload(_("the Greetingpicture for the login prompt"), - "hello", - "edithellopic"); - } else if (!strcasecmp(action, "edithellopic")) { - do_graphics_upload("hello"); - /* the logoff banner */ - } else if (!strcasecmp(action, "display_editgoodbyepic")) { - display_graphics_upload(_("the Logoff banner picture"), - "UIMG 0|%s|goodbuye", - "editgoodbuyepic"); - } else if (!strcasecmp(action, "editgoodbuyepic")) { - do_graphics_upload("UIMG 1|%s|goodbuye"); - - } else if (!strcasecmp(action, "delete_floor")) { - delete_floor(); - } else if (!strcasecmp(action, "rename_floor")) { - rename_floor(); - } else if (!strcasecmp(action, "create_floor")) { - create_floor(); - } else if (!strcasecmp(action, "display_editfloorpic")) { - snprintf(buf, SIZ, "UIMG 0|_floorpic_|%s", - bstr("which_floor")); - display_graphics_upload(_("the icon for this floor"), - buf, - "editfloorpic"); - } else if (!strcasecmp(action, "editfloorpic")) { - snprintf(buf, SIZ, "UIMG 1|_floorpic_|%s", - bstr("which_floor")); - do_graphics_upload(buf); - } else if (!strcasecmp(action, "display_reg")) { - display_reg(0); - } else if (!strcasecmp(action, "display_changepw")) { - display_changepw(); - } else if (!strcasecmp(action, "changepw")) { - changepw(); - } else if (!strcasecmp(action, "display_edit_node")) { - display_edit_node(); - } else if (!strcasecmp(action, "edit_node")) { - edit_node(); - } else if (!strcasecmp(action, "display_netconf")) { - display_netconf(); - } else if (!strcasecmp(action, "display_confirm_delete_node")) { - display_confirm_delete_node(); - } else if (!strcasecmp(action, "delete_node")) { - delete_node(); - } else if (!strcasecmp(action, "display_add_node")) { - display_add_node(); - } else if (!strcasecmp(action, "terminate_session")) { - slrp_highest(); - terminate_session(); - } else if (!strcasecmp(action, "edit_me")) { - edit_me(); - } else if (!strcasecmp(action, "display_siteconfig")) { - display_siteconfig(); - } else if (!strcasecmp(action, "chat_recv")) { - chat_recv(); - } else if (!strcasecmp(action, "chat_send")) { - chat_send(); - } else if (!strcasecmp(action, "siteconfig")) { - siteconfig(); - } else if (!strcasecmp(action, "display_generic")) { - display_generic(); - } else if (!strcasecmp(action, "do_generic")) { - do_generic(); - } else if (!strcasecmp(action, "ajax_servcmd")) { - ajax_servcmd(); - } else if (!strcasecmp(action, "display_menubar")) { - display_menubar(1); - } else if (!strcasecmp(action, "mimepart")) { - mimepart(index[1], index[2], 0); - } else if (!strcasecmp(action, "mimepart_download")) { - mimepart(index[1], index[2], 1); - } else if (!strcasecmp(action, "edit_vcard")) { - edit_vcard(); - } else if (!strcasecmp(action, "submit_vcard")) { - submit_vcard(); - } else if (!strcasecmp(action, "select_user_to_edit")) { - select_user_to_edit(NULL, NULL); - } else if (!strcasecmp(action, "display_edituser")) { - display_edituser(NULL, 0); - } else if (!strcasecmp(action, "edituser")) { - edituser(); - } else if (!strcasecmp(action, "create_user")) { - create_user(); - } else if (!strcasecmp(action, "changeview")) { - change_view(); - } else if (!strcasecmp(action, "change_start_page")) { - change_start_page(); - } else if (!strcasecmp(action, "display_floorconfig")) { - display_floorconfig(NULL); - } else if (!strcasecmp(action, "toggle_self_service")) { - toggle_self_service(); - } else if (!strcasecmp(action, "display_edit_task")) { - display_edit_task(); - } else if (!strcasecmp(action, "save_task")) { - save_task(); - } else if (!strcasecmp(action, "display_edit_event")) { - display_edit_event(); - } else if (!strcasecmp(action, "save_event")) { - save_event(); - } else if (!strcasecmp(action, "respond_to_request")) { - respond_to_request(); - } else if (!strcasecmp(action, "handle_rsvp")) { - handle_rsvp(); - } else if (!strcasecmp(action, "summary")) { - summary(); - } else if (!strcasecmp(action, "summary_inner_div")) { - begin_ajax_response(); - summary_inner_div(); - end_ajax_response(); - } else if (!strcasecmp(action, "display_customize_iconbar")) { - display_customize_iconbar(); - } else if (!strcasecmp(action, "commit_iconbar")) { - commit_iconbar(); - } else if (!strcasecmp(action, "set_room_policy")) { - set_room_policy(); - } else if (!strcasecmp(action, "display_inetconf")) { - display_inetconf(); - } else if (!strcasecmp(action, "save_inetconf")) { - save_inetconf(); - } else if (!strcasecmp(action, "display_smtpqueue")) { - display_smtpqueue(); - } else if (!strcasecmp(action, "display_smtpqueue_inner_div")) { - display_smtpqueue_inner_div(); - } else if (!strcasecmp(action, "display_sieve")) { - display_sieve(); - } else if (!strcasecmp(action, "save_sieve")) { - save_sieve(); - } else if (!strcasecmp(action, "display_pushemail")) { - display_pushemail(); - } else if (!strcasecmp(action, "save_pushemail")) { - save_pushemail(); - } else if (!strcasecmp(action, "display_add_remove_scripts")) { - display_add_remove_scripts(NULL); - } else if (!strcasecmp(action, "create_script")) { - create_script(); - } else if (!strcasecmp(action, "delete_script")) { - delete_script(); - } else if (!strcasecmp(action, "setup_wizard")) { - do_setup_wizard(); - } else if (!strcasecmp(action, "display_preferences")) { - display_preferences(); - } else if (!strcasecmp(action, "set_preferences")) { - set_preferences(); - } else if (!strcasecmp(action, "recp_autocomplete")) { - recp_autocomplete(bstr("recp")); - } else if (!strcasecmp(action, "cc_autocomplete")) { - recp_autocomplete(bstr("cc")); - } else if (!strcasecmp(action, "bcc_autocomplete")) { - recp_autocomplete(bstr("bcc")); - } else if (!strcasecmp(action, "display_address_book_middle_div")) { - display_address_book_middle_div(); - } else if (!strcasecmp(action, "display_address_book_inner_div")) { - display_address_book_inner_div(); - } else if (!strcasecmp(action, "set_floordiv_expanded")) { - set_floordiv_expanded(index[1]); - } else if (!strcasecmp(action, "diagnostics")) { - output_headers(1, 1, 1, 0, 0, 0); - wprintf("Session: %d
\n", WC->wc_session); - wprintf("Command:
\n");
-		escputs(cmd);
-		wprintf("

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

\n"); - wDumpContent(1); - } else if (!strcasecmp(action, "updatenote")) { - updatenote(); - } else if (!strcasecmp(action, "display_room_directory")) { - display_room_directory(); - } else if (!strcasecmp(action, "display_pictureview")) { - display_pictureview(); - } else if (!strcasecmp(action, "download_file")) { - download_file(index[1]); - } else if (!strcasecmp(action, "upload_file")) { - upload_file(); - } - - /** When all else fais, display the main menu. */ + /* When all else fais, display the main menu. */ else { - display_main_menu(); + if (!WCC->logged_in) + display_login(NULL); + else + display_main_menu(); } - +} SKIP_ALL_THIS_CRAP: fflush(stdout); if (content != NULL) { - free(content); + FreeStrBuf(&content); content = NULL; } free_urls(); - if (WC->upload_length > 0) { - free(WC->upload); - WC->upload_length = 0; + if (WCC->upload_length > 0) { + free(WCC->upload); + WCC->upload_length = 0; } } -/** - * \brief Replacement for sleep() that uses select() in order to avoid SIGALRM - * \param seconds how many seconds should we sleep? + +/* + * Replacement for sleep() that uses select() in order to avoid SIGALRM */ void sleeeeeeeeeep(int seconds) { @@ -1962,5 +1788,89 @@ 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) +{ + struct wcsession *WCC = WC; + if (WCC != NULL) + return (!IsEmptyStr(WCC->ImportantMessage)); + else + return 0; +} + +void tmplput_importantmessage(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +{ + struct wcsession *WCC = WC; + + if (WCC != NULL) { + StrEscAppend(Target, NULL, WCC->ImportantMessage, 0, 0); + WCC->ImportantMessage[0] = '\0'; + } +} + +int ConditionalBstr(WCTemplateToken *Tokens, void *Context, int ContextType) +{ + 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; +} + +void tmplput_bstr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +{ + StrBufAppendBuf(Target, + SBstr(Tokens->Params[0]->Start, + Tokens->Params[0]->len), 0); +} + +void +InitModule_WEBCIT +(void) +{ + 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("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, CTX_NONE); + RegisterNamespace("OFFERSTARTPAGE", 0, 0, offer_start_page, CTX_NONE); +}