X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fwebcit.c;h=df08bd8e026ef9ecc20f3ef079b65e6a69dd4766;hb=2362c3d4de86f20822ab81015222a196137fd20e;hp=580772a803970833ffd070db807567fedc9d171a;hpb=172af31bec540db82b61d6c0d9c7372bb7142607;p=citadel.git diff --git a/webcit/webcit.c b/webcit/webcit.c index 580772a80..df08bd8e0 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -1,13 +1,11 @@ /* * $Id$ - */ -/** - * \defgroup MainServer This is the main transaction loop of the web service. It maintains a + * + * This is the main transaction loop of the web service. It maintains a * persistent session to the Citadel server, handling HTTP WebCit requests as * they arrive and presenting a user interface. - * \ingroup WebcitHttpServer */ -/*@{*/ + #include "webcit.h" #include "groupdav.h" #include "webserver.h" @@ -15,22 +13,39 @@ #include #include -/** +/* * String to unset the cookie. * Any date "in the past" will work, so I chose my birthday, right down to * the exact minute. :) */ 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, int IsAjax) +{ + WebcitHandler *NewHandler; + + if (HandlerHash == NULL) + HandlerHash = NewHash(1, NULL); + + NewHandler = (WebcitHandler*) malloc(sizeof(WebcitHandler)); + NewHandler->F = F; + NewHandler->IsAjax = IsAjax; + + Put(HandlerHash, UrlString, UrlSLen, NewHandler, NULL); +} + +/* + * remove escaped strings from i.e. the url string (like %20 for blanks) */ -void unescape_input(char *buf) +long unescape_input(char *buf) { int a, b; char hex[3]; long buflen; + long len; buflen = strlen(buf); @@ -44,125 +59,268 @@ void unescape_input(char *buf) if (buf[a] == '+') buf[a] = ' '; if (buf[a] == '%') { - hex[0] = buf[a + 1]; - hex[1] = buf[a + 2]; - hex[2] = 0; - b = 0; - sscanf(hex, "%02x", &b); - buf[a] = (char) b; - memmove(&buf[a + 1], &buf[a + 3], buflen - a - 2); + /* 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; + buflen -=2; + } } a++; } + return a; +} +void free_url(void *U) +{ + urlcontent *u = (urlcontent*) U; + free(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(char *url, long ulen) { - char *up, *ptr; - char buf[SIZ]; - int a, b, len; - struct urlcontent *u; - - up = url; + char *aptr, *bptr, *eptr; + char *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 = buf + ulen; + up = buf; while (!IsEmptyStr(up)) { - - /** locate the = sign */ - safestrncpy(buf, up, sizeof buf); - b = (-1); - for (a = 255; a >= 0; --a) - if (buf[a] == '=') - b = a; - if (b < 0) + aptr = up; + while ((aptr < eptr) && (*aptr != '\0') && (*aptr != '=')) + aptr++; + if (*aptr != '=') return; - buf[b] = 0; - - u = (struct urlcontent *) malloc(sizeof(struct urlcontent)); - u->next = WC->urlstrings; - WC->urlstrings = u; - safestrncpy(u->url_key, buf, sizeof u->url_key); - - /** now chop that part off */ - for (a = 0; a <= b; ++a) - ++up; - - /** locate "&" and "?" delimiters */ - ptr = up; - len = b = strlen(up); - for (a = 0; a < len; ++a) { - if ( (ptr[0] == '&') || (ptr[0] == '?') ) { - b = a; - break; - } - ++ptr; + *aptr = '\0'; + aptr++; + bptr = aptr; + while ((bptr < eptr) && (*bptr != '\0') + && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) { + bptr++; + } + *bptr = '\0'; + u = (urlcontent *) malloc(sizeof(urlcontent)); + + keylen = safestrncpy(u->url_key, up, sizeof u->url_key); + if (keylen < 0){ + lprintf(1, "URLkey to long! [%s]", up); + continue; } - ptr = up + b; - *ptr = '\0'; - len = b; + Put(WCC->urlstrings, u->url_key, keylen, u, free_url); + len = bptr - aptr; u->url_data = malloc(len + 2); - safestrncpy(u->url_data, up, b + 1); - u->url_data[b] = 0; - unescape_input(u->url_data); - up = ptr; + safestrncpy(u->url_data, aptr, len + 2); + u->url_data_size = unescape_input(u->url_data); + u->url_data[u->url_data_size] = '\0'; + up = bptr; ++up; - - /* lprintf(9, "%s = %s\n", u->url_key, u->url_data); */ +#ifdef DEBUG_URLSTRINGS + lprintf(9, "%s = [%ld] %s\n", u->url_key, u->url_data_size, u->url_data); +#endif } } -/** - * \brief free urlstring memory +/* + * free urlstring memory */ void free_urls(void) { - struct urlcontent *u; - - while (WC->urlstrings != NULL) { - free(WC->urlstrings->url_data); - u = WC->urlstrings->next; - free(WC->urlstrings); - WC->urlstrings = u; - } + 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) { - struct urlcontent *u; - - for (u = WC->urlstrings; u != NULL; u = u->next) { + struct wcsession *WCC = WC; + urlcontent *u; + void *U; + long HKLen; + 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); } } -/** - * \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) */ -char *bstr(char *key) + +const char *XBstr(char *key, size_t keylen, size_t *len) { - struct urlcontent *u; + void *U; - for (u = WC->urlstrings; u != NULL; u = u->next) { - if (!strcasecmp(u->url_key, key)) - return (u->url_data); + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, keylen, &U)) { + *len = ((urlcontent *)U)->url_data_size; + return ((urlcontent *)U)->url_data; + } + else { + *len = 0; + return (""); } - return (""); } -/** - * \brief web-printing funcion. uses our vsnprintf wrapper - * \param format printf format string - * \param ... the varargs to put into formatstring +const char *XBSTR(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; + } + else { + *len = 0; + return (""); + } +} + + +const char *BSTR(char *key) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, strlen (key), &U)) + return ((urlcontent *)U)->url_data; + else + return (""); +} + +const char *Bstr(char *key, size_t keylen) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, keylen, &U)) + return ((urlcontent *)U)->url_data; + else + return (""); +} + +long LBstr(char *key, size_t keylen) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, keylen, &U)) + return atol(((urlcontent *)U)->url_data); + else + return (0); +} + +long LBSTR(char *key) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, strlen(key), &U)) + return atol(((urlcontent *)U)->url_data); + else + return (0); +} + +int IBstr(char *key, size_t keylen) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, keylen, &U)) + return atoi(((urlcontent *)U)->url_data); + else + return (0); +} + +int IBSTR(char *key) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, strlen(key), &U)) + return atoi(((urlcontent *)U)->url_data); + else + return (0); +} + +int HaveBstr(char *key, size_t keylen) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, keylen, &U)) + return ((urlcontent *)U)->url_data_size != 0; + else + return (0); +} + +int HAVEBSTR(char *key) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, strlen(key), &U)) + return ((urlcontent *)U)->url_data_size != 0; + else + return (0); +} + + +int YesBstr(char *key, size_t keylen) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, keylen, &U)) + return strcmp( ((urlcontent *)U)->url_data, "yes") == 0; + else + return (0); +} + +int YESBSTR(char *key) +{ + void *U; + + if ((WC->urlstrings != NULL) && + GetHash(WC->urlstrings, key, strlen(key), &U)) + return strcmp( ((urlcontent *)U)->url_data, "yes") == 0; + else + return (0); +} + +/* + * web-printing funcion. uses our vsnprintf wrapper */ void wprintf(const char *format,...) { @@ -177,12 +335,13 @@ void wprintf(const char *format,...) } -/** - * \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) { @@ -198,12 +357,13 @@ 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) { @@ -269,12 +429,6 @@ long stresc(char *target, long tSize, char *strbuf, int nbsp, int nolinebreaks) 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; @@ -288,9 +442,8 @@ void escputs1(char *strbuf, int nbsp, int nolinebreaks) free(buf); } -/** - * \brief static wrapper for ecsputs1 - * \param strbuf buffer to print escaped to client +/* + * static wrapper for ecsputs1 */ void escputs(char *strbuf) { @@ -298,9 +451,8 @@ void escputs(char *strbuf) } -/** - * \brief urlescape buffer and print it to the client - * \param strbuf buffer to urlescape +/* + * urlescape buffer and print it to the client */ void urlescputs(char *strbuf) { @@ -311,10 +463,8 @@ void urlescputs(char *strbuf) } -/** - * \brief Copy a string, escaping characters for JavaScript strings. - * \param target output string - * \param strbuf input string +/* + * Copy a string, escaping characters for JavaScript strings. */ void jsesc(char *target, size_t tlen, char *strbuf) { @@ -371,9 +521,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) { @@ -383,10 +532,8 @@ 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 +/* + * Copy a string, escaping characters for message text hold */ void msgesc(char *target, size_t tlen, char *strbuf) { @@ -427,9 +574,8 @@ void msgesc(char *target, size_t tlen, char *strbuf) *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) { @@ -448,9 +594,8 @@ void msgescputs1( char *strbuf) free(outbuf2); } -/** - * \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; @@ -467,20 +612,20 @@ void msgescputs(char *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]; @@ -497,10 +642,17 @@ void output_headers( int do_httpheaders, /**< 1 = output HTTP headers } if (cache) { + char httpTomorow[128]; + + http_datestring(httpTomorow, sizeof httpTomorow, + time(NULL) + 60 * 60 * 24 * 2); + wprintf("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 { @@ -525,27 +677,28 @@ void output_headers( int do_httpheaders, /**< 1 = output HTTP headers 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"); } - /** ICONBAR */ + /* ICONBAR */ if (do_htmlhead) { - /** 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"); - wprintf("" - "%s
\n", WC->ImportantMessage); - wprintf("
\n"); - wprintf("\n"); - safestrncpy(WC->ImportantMessage, "", sizeof WC->ImportantMessage); + WC->ImportantMessage[0] = 0; } if ( (WC->logged_in) && (!unset_cookies) ) { @@ -569,11 +722,10 @@ 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) { +void http_redirect(const char *whichpage) { wprintf("HTTP/1.1 302 Moved Temporarily\n"); wprintf("Location: %s\r\n", whichpage); wprintf("URI: %s\r\n", whichpage); @@ -585,10 +737,10 @@ void http_redirect(char *whichpage) { -/** - * \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, char *content_type, +void http_transmit_thing(char *thing, size_t length, const char *content_type, int is_static) { output_headers(0, 0, 0, 0, 0, is_static); @@ -600,7 +752,7 @@ void http_transmit_thing(char *thing, size_t length, char *content_type, PACKAGE_STRING); #ifdef HAVE_ZLIB - /** If we can send the data out compressed, please do so. */ + /* If we can send the data out compressed, please do so. */ if (WC->gzip_ok) { char *compressed_data = NULL; size_t compressed_len; @@ -624,7 +776,7 @@ void http_transmit_thing(char *thing, size_t length, char *content_type, } #endif - /** No compression ... just send it out as-is */ + /* No compression ... just send it out as-is */ wprintf("Content-length: %ld\r\n" "\r\n", (long) length @@ -632,20 +784,20 @@ void http_transmit_thing(char *thing, size_t length, char *content_type, client_write(thing, (size_t)length); } -/** - * \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); + svput("BOXTITLE", WCS_STRING, Title); do_template("beginbox"); wprintf("