From c881934110f3c99194fad96c923b7d0ecb24ecdc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Sat, 13 Dec 2008 18:39:49 +0000 Subject: [PATCH] * BIG shuffle: * move several mimepart handlers to messages.c * move utility string formating stuff into utils.c; hopefully we get rid of that one day because of everything using strbuf * moved vcard stuff out of messages.c into vcard_edit.c * did some late followups of the urlhash (how did they get through?) * move binary downloads / viewing function into downloads.c ->webcit.c is getting small ;) --- webcit/Makefile.in | 3 +- webcit/downloads.c | 55 ++- webcit/fmt_date.c | 4 + webcit/messages.c | 295 +++++++------ webcit/paramhandling.c | 334 ++++++++++++++ webcit/preferences.c | 45 ++ webcit/roomops.c | 1 + webcit/utils.c | 279 ++++++++++++ webcit/vcard_edit.c | 171 ++++++++ webcit/webcit.c | 960 ++--------------------------------------- webcit/webcit.h | 16 +- 11 files changed, 1102 insertions(+), 1061 deletions(-) create mode 100644 webcit/paramhandling.c create mode 100644 webcit/utils.c diff --git a/webcit/Makefile.in b/webcit/Makefile.in index fce0b3e88..bb2e11ebe 100644 --- a/webcit/Makefile.in +++ b/webcit/Makefile.in @@ -51,7 +51,7 @@ webcit: webserver.o context_loop.o ical_dezonify.o \ groupdav_options.o autocompletion.o gettext.o tabs.o sieve.o \ groupdav_delete.o groupdav_put.o http_datestring.o setup_wizard.o \ downloads.o addressbook_popup.o pushemail.o sysdep.o openid.o \ - decode.o modules_init.o \ + decode.o modules_init.o paramhandling.o utils.o \ $(LIBOBJS) $(CC) $(LDFLAGS) $(LIBOBJS) $(LIBS) \ webserver.o context_loop.o cookie_conversion.o \ @@ -65,6 +65,7 @@ webcit: webserver.o context_loop.o ical_dezonify.o \ groupdav_options.o autocompletion.o tabs.o smtpqueue.o sieve.o \ groupdav_put.o http_datestring.o setup_wizard.o fmt_date.o modules_init.o \ gettext.o downloads.o addressbook_popup.o pushemail.o sysdep.o decode.o \ + paramhandling.o utils.o \ -o webcit \ $(LIBS) diff --git a/webcit/downloads.c b/webcit/downloads.c index d980ce1d3..23e1ccd23 100644 --- a/webcit/downloads.c +++ b/webcit/downloads.c @@ -426,8 +426,8 @@ void upload_file(void) { const char *MimeType; char buf[1024]; - size_t bytes_transmitted = 0; - size_t blocksize; + long bytes_transmitted = 0; + long blocksize; struct wcsession *WCC = WC; /* stack this for faster access (WC is a function) */ MimeType = GuessMimeType(WCC->upload, WCC->upload_length); @@ -463,10 +463,61 @@ void upload_file(void) display_room_directory(); } + + +/* + * 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); +} + + + + void InitModule_DOWNLOAD (void) { + WebcitAddUrlHandler(HKEY("image"), output_image, 0); + WebcitAddUrlHandler(HKEY("display_mime_icon"), display_mime_icon , 0); + WebcitAddUrlHandler(HKEY("display_room_directory"), display_room_directory, 0); WebcitAddUrlHandler(HKEY("display_pictureview"), display_pictureview, 0); WebcitAddUrlHandler(HKEY("download_file"), download_file, NEED_URL); diff --git a/webcit/fmt_date.c b/webcit/fmt_date.c index c541b7b17..779d458f4 100644 --- a/webcit/fmt_date.c +++ b/webcit/fmt_date.c @@ -5,6 +5,10 @@ #include "webcit.h" #include "webserver.h" +#ifdef HAVE_USELOCALE +extern locale_t wc_locales[]; +#endif + typedef unsigned char byte; #define FALSE 0 /**< no. */ diff --git a/webcit/messages.c b/webcit/messages.c index 9a1dc2e45..bad4b3e8b 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -364,138 +364,6 @@ message_summary *ReadOneMessageSummary(StrBuf *RawMessage, const char *DefaultSu } -/** - * \brief display the adressbook overview - * \param msgnum the citadel message number - * \param alpha what???? - */ -void display_addressbook(long msgnum, char alpha) { - //char buf[SIZ]; - /* char mime_partnum[SIZ]; */ -/* char mime_filename[SIZ]; */ -/* char mime_content_type[SIZ]; */ - ///char mime_disposition[SIZ]; - //int mime_length; - char vcard_partnum[SIZ]; - char *vcard_source = NULL; - message_summary summ;////TODO: this will leak - - memset(&summ, 0, sizeof(summ)); - ///safestrncpy(summ.subj, _("(no subject)"), sizeof summ.subj); -///Load Message headers -// Msg = - if (!IsEmptyStr(vcard_partnum)) { - vcard_source = load_mimepart(msgnum, vcard_partnum); - if (vcard_source != NULL) { - - /** Display the summary line */ - display_vcard(WC->WBuf, vcard_source, alpha, 0, NULL,msgnum); - - /** If it's my vCard I can edit it */ - if ( (!strcasecmp(WC->wc_roomname, USERCONFIGROOM)) - || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM)) - || (WC->wc_view == VIEW_ADDRESSBOOK) - ) { - wprintf("", - msgnum, vcard_partnum); - wprintf("[%s]", _("edit")); - } - - free(vcard_source); - } - } - -} - - - -/** - * \brief If it's an old "Firstname Lastname" style record, try to convert it. - * \param namebuf name to analyze, reverse if nescessary - */ -void lastfirst_firstlast(char *namebuf) { - char firstname[SIZ]; - char lastname[SIZ]; - int i; - - if (namebuf == NULL) return; - if (strchr(namebuf, ';') != NULL) return; - - i = num_tokens(namebuf, ' '); - if (i < 2) return; - - extract_token(lastname, namebuf, i-1, ' ', sizeof lastname); - remove_token(namebuf, i-1, ' '); - strcpy(firstname, namebuf); - sprintf(namebuf, "%s; %s", lastname, firstname); -} - -/** - * \brief fetch what??? name - * \param msgnum the citadel message number - * \param namebuf where to put the name in??? - */ -void fetch_ab_name(message_summary *Msg, char *namebuf) { - char buf[SIZ]; - char mime_partnum[SIZ]; - char mime_filename[SIZ]; - char mime_content_type[SIZ]; - char mime_disposition[SIZ]; - int mime_length; - char vcard_partnum[SIZ]; - char *vcard_source = NULL; - int i, len; - message_summary summ;/// TODO this will lak - - if (namebuf == NULL) return; - strcpy(namebuf, ""); - - memset(&summ, 0, sizeof(summ)); - //////safestrncpy(summ.subj, "(no subject)", sizeof summ.subj); - - sprintf(buf, "MSG0 %ld|0", Msg->msgnum); /** unfortunately we need the mime info now */ - serv_puts(buf); - serv_getln(buf, sizeof buf); - if (buf[0] != '1') return; - - while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { - if (!strncasecmp(buf, "part=", 5)) { - extract_token(mime_filename, &buf[5], 1, '|', sizeof mime_filename); - extract_token(mime_partnum, &buf[5], 2, '|', sizeof mime_partnum); - extract_token(mime_disposition, &buf[5], 3, '|', sizeof mime_disposition); - extract_token(mime_content_type, &buf[5], 4, '|', sizeof mime_content_type); - mime_length = extract_int(&buf[5], 5); - - if ( (!strcasecmp(mime_content_type, "text/x-vcard")) - || (!strcasecmp(mime_content_type, "text/vcard")) ) { - strcpy(vcard_partnum, mime_partnum); - } - - } - } - - if (!IsEmptyStr(vcard_partnum)) { - vcard_source = load_mimepart(Msg->msgnum, vcard_partnum); - if (vcard_source != NULL) { - - /* Grab the name off the card */ - display_vcard(WC->WBuf, vcard_source, 0, 0, namebuf, Msg->msgnum); - - free(vcard_source); - } - } - - lastfirst_firstlast(namebuf); - striplt(namebuf); - len = strlen(namebuf); - for (i=0; iattachments, SKEY(partnum), &vPart) && + (vPart != NULL)) { + part = (wc_mime_attachment*) vPart; + if (force_download) { + content_type = NewStrBufPlain(HKEY("application/octet-stream")); + } + else { + content_type = NewStrBufDup(part->ContentType); + } + output_headers(0, 0, 0, 0, 0, 0); + StrBufAppendBuf(WC->WBuf, part->Data, 0); + http_transmit_thing(ChrPtr(content_type), 0); + } else { + hprintf("HTTP/1.1 404 %s\n", ChrPtr(partnum)); + output_headers(0, 0, 0, 0, 0, 0); + hprintf("Content-Type: text/plain\r\n"); + wprintf(_("An error occurred while retrieving this part: %s/%s\n"), + ChrPtr(partnum), ChrPtr(filename)); + end_burst(); + } + FreeStrBuf(&content_type); +} + + +/* + * 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); + } +} + +/* + * Read any MIME part of a message, from the server, into memory. + */ +void MimeLoadData(wc_mime_attachment *Mime) +{ + char buf[SIZ]; + off_t bytes; +//// TODO: is there a chance the contenttype is different to the one we know? + serv_printf("DLAT %ld|%s", Mime->msgnum, ChrPtr(Mime->PartNum)); + serv_getln(buf, sizeof buf); + if (buf[0] == '6') { + bytes = extract_long(&buf[4], 0); + + if (Mime->Data == NULL) + Mime->Data = NewStrBufPlain(NULL, bytes); + StrBuf_ServGetBLOB(Mime->Data, bytes); + + } + else { + FlushStrBuf(Mime->Data); + /// TODO XImportant message + } +} + + + + +void view_mimepart(void) { + mimepart(ChrPtr(WC->UrlFragment2), + ChrPtr(WC->UrlFragment3), + 0); +} + +void download_mimepart(void) { + mimepart(ChrPtr(WC->UrlFragment2), + ChrPtr(WC->UrlFragment3), + 1); +} + +void view_postpart(void) { + postpart(WC->UrlFragment2, + WC->UrlFragment3, + 0); +} + +void download_postpart(void) { + postpart(WC->UrlFragment2, + WC->UrlFragment3, + 1); +} + + + void h_readnew(void) { readloop(readnew);} void h_readold(void) { readloop(readold);} void h_readfwd(void) { readloop(readfwd);} @@ -1579,6 +1606,10 @@ InitModule_MSG WebcitAddUrlHandler(HKEY("mobilemsg"), mobile_message_view, NEED_URL); WebcitAddUrlHandler(HKEY("msgheaders"), display_headers, NEED_URL); + WebcitAddUrlHandler(HKEY("mimepart"), view_mimepart, NEED_URL); + WebcitAddUrlHandler(HKEY("mimepart_download"), download_mimepart, NEED_URL); + WebcitAddUrlHandler(HKEY("postpart"), view_postpart, NEED_URL); + WebcitAddUrlHandler(HKEY("postpart_download"), download_postpart, NEED_URL); return ; } diff --git a/webcit/paramhandling.c b/webcit/paramhandling.c new file mode 100644 index 000000000..628f914f6 --- /dev/null +++ b/webcit/paramhandling.c @@ -0,0 +1,334 @@ +/* + * $Id: paramhandling.c 6808 2008-12-11 00:00:36Z dothebart $ + * + * parse urlparts and post data + */ + +#include "webcit.h" +#include "webserver.h" + +void free_url(void *U) +{ + urlcontent *u = (urlcontent*) U; + FreeStrBuf(&u->url_data); + free(u); +} + +/* + * Extract variables from the URL. + */ +void ParseURLParams(StrBuf *url) +{ + const char *aptr, *bptr, *eptr, *up; + int len, keylen; + urlcontent *u; + struct wcsession *WCC = WC; + + if (WCC->urlstrings == NULL) + WCC->urlstrings = NewHash(1, NULL); + eptr = ChrPtr(url) + StrLength(url); + up = ChrPtr(url); + while ((up < eptr) && (!IsEmptyStr(up))) { + aptr = up; + while ((aptr < eptr) && (*aptr != '\0') && (*aptr != '=')) + aptr++; + if (*aptr != '=') { + return; + } + aptr++; + bptr = aptr; + while ((bptr < eptr) && (*bptr != '\0') + && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) { + bptr++; + } + 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 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 (WCC->urlstrings, 0); + 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); +} + + + + +/* + * 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)); + } + } + +} diff --git a/webcit/preferences.c b/webcit/preferences.c index 086a244e3..64001d7a4 100644 --- a/webcit/preferences.c +++ b/webcit/preferences.c @@ -617,6 +617,50 @@ void display_preferences(void) wDumpContent(1); } + + + +/* + * 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); +} + + + /** * \brief Commit new preferences and settings */ @@ -801,6 +845,7 @@ InitModule_PREFERENCES { WebcitAddUrlHandler(HKEY("display_preferences"), display_preferences, 0); WebcitAddUrlHandler(HKEY("set_preferences"), set_preferences, 0); + WebcitAddUrlHandler(HKEY("change_start_page"), change_start_page, 0); RegisterPreference("roomlistview",_("Room list view"),PRF_STRING); RegisterPreference("calhourformat",_("Time format"), PRF_INT); diff --git a/webcit/roomops.c b/webcit/roomops.c index 35a150e3f..51dd72788 100644 --- a/webcit/roomops.c +++ b/webcit/roomops.c @@ -3865,6 +3865,7 @@ InitModule_ROOMOPS WebcitAddUrlHandler(HKEY("set_room_policy"), set_room_policy, 0); WebcitAddUrlHandler(HKEY("set_floordiv_expanded"), set_floordiv_expanded, NEED_URL|AJAX); WebcitAddUrlHandler(HKEY("changeview"), change_view, 0); + WebcitAddUrlHandler(HKEY("toggle_self_service"), toggle_self_service, 0); RegisterNamespace("ROOMBANNER", 0, 1, tmplput_roombanner, 0); RegisterConditional(HKEY("COND:ROOM:FLAGS:QR_PERMANENT"), 0, ConditionalRoomHas_QR_PERMANENT, CTX_NONE); diff --git a/webcit/utils.c b/webcit/utils.c new file mode 100644 index 000000000..78b6b8c25 --- /dev/null +++ b/webcit/utils.c @@ -0,0 +1,279 @@ +/* + * $Id: utils.c 6808 2008-12-11 00:00:36Z dothebart $ + * + * de/encoding stuff. hopefully mostly to be depricated in favour of subst.c + strbuf + */ + +#define SHOW_ME_VAPPEND_PRINTF +#include +#include +#include "webcit.h" + + +/* + * 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; +} + +/* + * 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); +} + + + diff --git a/webcit/vcard_edit.c b/webcit/vcard_edit.c index ae699c660..d137d191e 100644 --- a/webcit/vcard_edit.c +++ b/webcit/vcard_edit.c @@ -33,6 +33,138 @@ void nametab(char *tabbuf, long len, char *name) { } +/** + * \brief display the adressbook overview + * \param msgnum the citadel message number + * \param alpha what???? + */ +void display_addressbook(long msgnum, char alpha) { + //char buf[SIZ]; + /* char mime_partnum[SIZ]; */ +/* char mime_filename[SIZ]; */ +/* char mime_content_type[SIZ]; */ + ///char mime_disposition[SIZ]; + //int mime_length; + char vcard_partnum[SIZ]; + char *vcard_source = NULL; + message_summary summ;////TODO: this will leak + + memset(&summ, 0, sizeof(summ)); + ///safestrncpy(summ.subj, _("(no subject)"), sizeof summ.subj); +///Load Message headers +// Msg = + if (!IsEmptyStr(vcard_partnum)) { + vcard_source = load_mimepart(msgnum, vcard_partnum); + if (vcard_source != NULL) { + + /** Display the summary line */ + display_vcard(WC->WBuf, vcard_source, alpha, 0, NULL,msgnum); + + /** If it's my vCard I can edit it */ + if ( (!strcasecmp(WC->wc_roomname, USERCONFIGROOM)) + || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM)) + || (WC->wc_view == VIEW_ADDRESSBOOK) + ) { + wprintf("", + msgnum, vcard_partnum); + wprintf("[%s]", _("edit")); + } + + free(vcard_source); + } + } + +} + + + +/** + * \brief If it's an old "Firstname Lastname" style record, try to convert it. + * \param namebuf name to analyze, reverse if nescessary + */ +void lastfirst_firstlast(char *namebuf) { + char firstname[SIZ]; + char lastname[SIZ]; + int i; + + if (namebuf == NULL) return; + if (strchr(namebuf, ';') != NULL) return; + + i = num_tokens(namebuf, ' '); + if (i < 2) return; + + extract_token(lastname, namebuf, i-1, ' ', sizeof lastname); + remove_token(namebuf, i-1, ' '); + strcpy(firstname, namebuf); + sprintf(namebuf, "%s; %s", lastname, firstname); +} + +/** + * \brief fetch what??? name + * \param msgnum the citadel message number + * \param namebuf where to put the name in??? + */ +void fetch_ab_name(message_summary *Msg, char *namebuf) { + char buf[SIZ]; + char mime_partnum[SIZ]; + char mime_filename[SIZ]; + char mime_content_type[SIZ]; + char mime_disposition[SIZ]; + int mime_length; + char vcard_partnum[SIZ]; + char *vcard_source = NULL; + int i, len; + message_summary summ;/// TODO this will lak + + if (namebuf == NULL) return; + strcpy(namebuf, ""); + + memset(&summ, 0, sizeof(summ)); + //////safestrncpy(summ.subj, "(no subject)", sizeof summ.subj); + + sprintf(buf, "MSG0 %ld|0", Msg->msgnum); /** unfortunately we need the mime info now */ + serv_puts(buf); + serv_getln(buf, sizeof buf); + if (buf[0] != '1') return; + + while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { + if (!strncasecmp(buf, "part=", 5)) { + extract_token(mime_filename, &buf[5], 1, '|', sizeof mime_filename); + extract_token(mime_partnum, &buf[5], 2, '|', sizeof mime_partnum); + extract_token(mime_disposition, &buf[5], 3, '|', sizeof mime_disposition); + extract_token(mime_content_type, &buf[5], 4, '|', sizeof mime_content_type); + mime_length = extract_int(&buf[5], 5); + + if ( (!strcasecmp(mime_content_type, "text/x-vcard")) + || (!strcasecmp(mime_content_type, "text/vcard")) ) { + strcpy(vcard_partnum, mime_partnum); + } + + } + } + + if (!IsEmptyStr(vcard_partnum)) { + vcard_source = load_mimepart(Msg->msgnum, vcard_partnum); + if (vcard_source != NULL) { + + /* Grab the name off the card */ + display_vcard(WC->WBuf, vcard_source, 0, 0, namebuf, Msg->msgnum); + + free(vcard_source); + } + } + + lastfirst_firstlast(namebuf); + striplt(namebuf); + len = strlen(namebuf); + for (i=0; iUrlFragment2); + + 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); +} + + + void InitModule_VCARD (void) { WebcitAddUrlHandler(HKEY("edit_vcard"), edit_vcard, 0); WebcitAddUrlHandler(HKEY("submit_vcard"), submit_vcard, 0); + WebcitAddUrlHandler(HKEY("vcardphoto"), display_vcard_photo_img, NEED_URL); } diff --git a/webcit/webcit.c b/webcit/webcit.c index 0c8d142c6..7054c7d95 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. @@ -39,312 +38,6 @@ 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 ParseURLParams(StrBuf *url) -{ - const char *aptr, *bptr, *eptr, *up; - int len, keylen; - urlcontent *u; - struct wcsession *WCC = WC; - - if (WCC->urlstrings == NULL) - WCC->urlstrings = NewHash(1, NULL); - eptr = ChrPtr(url) + StrLength(url); - up = ChrPtr(url); - while ((up < eptr) && (!IsEmptyStr(up))) { - aptr = up; - while ((aptr < eptr) && (*aptr != '\0') && (*aptr != '=')) - aptr++; - if (*aptr != '=') { - return; - } - aptr++; - bptr = aptr; - while ((bptr < eptr) && (*bptr != '\0') - && (*bptr != '&') && (*bptr != '?') && (*bptr != ' ')) { - bptr++; - } - 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 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 (WCC->urlstrings, 0); - 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 @@ -360,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)); } /* @@ -376,20 +66,9 @@ void hprintf(const char *format,...) 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)); } -void tmplput_trailing_javascript(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *vContext, int ContextType) -{ - struct wcsession *WCC = WC; - - if (WCC != NULL) - StrBufAppendTemplate(Target, nArgs, Tokens, vContext, ContextType, - WCC->trailing_javascript, 0); -} /* * wrap up an HTTP session, closes tags, etc. @@ -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 @@ -872,214 +330,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->UrlFragment2); - - 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 attachment from - * message being composed - * - * partnum The MIME part to be output - * filename Fake filename to give - * force_download Nonzero to force set the Content-Type: header to "application/octet-stream" - */ -void postpart(StrBuf *partnum, StrBuf *filename, int force_download) -{ - void *vPart; - StrBuf *content_type; - wc_mime_attachment *part; - - if (GetHash(WC->attachments, SKEY(partnum), &vPart) && - (vPart != NULL)) { - part = (wc_mime_attachment*) vPart; - if (force_download) { - content_type = NewStrBufPlain(HKEY("application/octet-stream")); - } - else { - content_type = NewStrBufDup(part->ContentType); - } - output_headers(0, 0, 0, 0, 0, 0); - StrBufAppendBuf(WC->WBuf, part->Data, 0); - http_transmit_thing(ChrPtr(content_type), 0); - } else { - hprintf("HTTP/1.1 404 %s\n", ChrPtr(partnum)); - output_headers(0, 0, 0, 0, 0, 0); - hprintf("Content-Type: text/plain\r\n"); - wprintf(_("An error occurred while retrieving this part: %s/%s\n"), - ChrPtr(partnum), ChrPtr(filename)); - end_burst(); - } - FreeStrBuf(&content_type); -} - - -/* - * 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); - } -} - -/* - * Read any MIME part of a message, from the server, into memory. - */ -void MimeLoadData(wc_mime_attachment *Mime) -{ - char buf[SIZ]; - off_t bytes; -//// TODO: is there a chance the contenttype is different to the one we know? - serv_printf("DLAT %ld|%s", Mime->msgnum, ChrPtr(Mime->PartNum)); - serv_getln(buf, sizeof buf); - if (buf[0] == '6') { - bytes = extract_long(&buf[4], 0); - - if (Mime->Data == NULL) - Mime->Data = NewStrBufPlain(NULL, bytes); - StrBuf_ServGetBLOB(Mime->Data, bytes); - - } - else { - FlushStrBuf(Mime->Data); - /// TODO XImportant message - } -} - /* * Convenience functions to display a page containing only a string @@ -1126,47 +376,6 @@ void url_do_template(void) { -/* - * 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); -} - - - /* * convenience function to indicate success */ @@ -1194,68 +403,6 @@ 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 */ @@ -1405,6 +552,9 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method int is_static = 0; int n_static = 0; int len = 0; + void *vHandler; + WebcitHandler *Handler; + /* * 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. @@ -1790,41 +940,32 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method safestrncpy(WCC->wc_roomname, c_roomname, sizeof WCC->wc_roomname); } } - - 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); - } - 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(); - StrBufPrintf(WCC->UrlFragment1, "%s", index[0]); - StrBufPrintf(WCC->UrlFragment2, "%s", index[1]); - StrBufPrintf(WCC->UrlFragment3, "%s", index[2]); - } - if ((Handler->Flags & AJAX) != 0) - begin_ajax_response(); - Handler->F(); - if ((Handler->Flags & AJAX) != 0) - end_ajax_response(); + + 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(); + StrBufPrintf(WCC->UrlFragment1, "%s", index[0]); + StrBufPrintf(WCC->UrlFragment2, "%s", index[1]); + StrBufPrintf(WCC->UrlFragment3, "%s", index[2]); } + 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) @@ -1832,14 +973,14 @@ void session_loop(HashList *HTTPHeaders, StrBuf *ReqLine, StrBuf *request_method else display_main_menu(); } -} + SKIP_ALL_THIS_CRAP: 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; @@ -1877,30 +1018,6 @@ void diagnostics(void) wDumpContent(1); } -void view_mimepart(void) { - mimepart(ChrPtr(WC->UrlFragment2), - ChrPtr(WC->UrlFragment3), - 0); -} - -void download_mimepart(void) { - mimepart(ChrPtr(WC->UrlFragment2), - ChrPtr(WC->UrlFragment3), - 1); -} - -void view_postpart(void) { - postpart(WC->UrlFragment2, - WC->UrlFragment3, - 0); -} - -void download_postpart(void) { - postpart(WC->UrlFragment2, - WC->UrlFragment3, - 1); -} - int ConditionalImportantMesage(WCTemplateToken *Tokens, void *Context, int ContextType) { @@ -1946,6 +1063,14 @@ void tmplput_bstr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Cont Buf, 1); } +void tmplput_trailing_javascript(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *vContext, int ContextType) +{ + struct wcsession *WCC = WC; + + if (WCC != NULL) + StrBufAppendTemplate(Target, nArgs, Tokens, vContext, ContextType, + WCC->trailing_javascript, 0); +} void tmplput_csslocal(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) { @@ -1983,13 +1108,6 @@ InitModule_WEBCIT 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("postpart"), view_postpart, NEED_URL); - WebcitAddUrlHandler(HKEY("postpart_download"), download_postpart, NEED_URL); WebcitAddUrlHandler(HKEY("diagnostics"), diagnostics, NEED_URL); RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE); diff --git a/webcit/webcit.h b/webcit/webcit.h index fdb2a095d..51462a1a4 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -55,9 +55,6 @@ #endif #include #include -#ifdef HAVE_USELOCALE -extern locale_t wc_locales[]; -#endif #define _(string) gettext(string) #else #define _(string) (string) @@ -729,6 +726,15 @@ void wDumpContent(int); int Flathash(const char *str, long len); + +/* URL / Mime Post parsing -> paramhandling.c */ +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); + +void ParseURLParams(StrBuf *url); + + /* These may return NULL if not foud */ #define sbstr(a) SBstr(a, sizeof(a) - 1) const StrBuf *SBSTR(const char *key); @@ -778,7 +784,7 @@ void output_headers( int do_httpheaders, void wprintf(const char *format,...)__attribute__((__format__(__printf__,1,2))); void hprintf(const char *format,...)__attribute__((__format__(__printf__,1,2))); void output_static(char *what); -void display_mime_icon(void); + void print_menu_box(char* Title, char *Class, int nLines, ...); long stresc(char *target, long tSize, char *strbuf, int nbsp, int nolinebreaks); void escputs(char *strbuf); @@ -810,6 +816,7 @@ typedef struct _readloopstruct { void readloop(long oper); int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, int printable_view, const StrBuf *section); void do_addrbook_view(addrbookent *addrbook, int num_ab); +void fetch_ab_name(message_summary *Msg, char *namebuf); void display_vcard(StrBuf *Target, const char *vcard_source, char alpha, int full, char *storename, long msgnum); void text_to_server(char *ptr); void text_to_server_qp(char *ptr); @@ -897,7 +904,6 @@ void offer_start_page(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *C void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext); void output_html(const char *, int, int, StrBuf *, StrBuf *); void do_listsub(void); -void toggle_self_service(void); ssize_t write(int fd, const void *buf, size_t count); void cal_process_attachment(wc_mime_attachment *Mime); void load_calendar_item(message_summary *Msg, int unread, struct calview *c); -- 2.30.2