From c3820723d665e75fc7f8f7e54e87dd3b0ba503ef Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Wed, 2 Apr 2008 23:45:08 +0000 Subject: [PATCH] * moved url argument list to hash. * carry length of parameter value in the hash for later use * added Bstr, BSTR and bstr. bstr mustn't be used for dynamic keys, use BSTR instead. * use BSTR where apropriate. * fixed crash condition with message posting Mrs. Foobar found out --- webcit/addressbook_popup.c | 2 +- webcit/calendar_tools.c | 16 ++-- webcit/iconbar.c | 4 +- webcit/messages.c | 179 +++++++++++++++++++++++++++---------- webcit/sieve.c | 24 ++--- webcit/webcit.c | 94 ++++++++++++------- webcit/webcit.h | 11 ++- 7 files changed, 227 insertions(+), 103 deletions(-) diff --git a/webcit/addressbook_popup.c b/webcit/addressbook_popup.c index 89c52b5bc..3004a8260 100644 --- a/webcit/addressbook_popup.c +++ b/webcit/addressbook_popup.c @@ -158,7 +158,7 @@ void display_address_book_inner_div() { } DeleteHashPos(&it); DeleteHash(&List); - gotoroom(bstr(saved_roomname)); + gotoroom((char*)BSTR(saved_roomname)); /* TODO: get rid of typecast */ } wprintf("\n"); diff --git a/webcit/calendar_tools.c b/webcit/calendar_tools.c index 17862aa6c..d07fd6f38 100644 --- a/webcit/calendar_tools.c +++ b/webcit/calendar_tools.c @@ -153,11 +153,11 @@ void icaltime_from_webform(struct icaltimetype *t, char *prefix) { char timestr[32]; int month, mday, year, hour, minute; - sprintf(vname, "%s_month", prefix); month = atoi(bstr(vname)); - sprintf(vname, "%s_day", prefix); mday = atoi(bstr(vname)); - sprintf(vname, "%s_year", prefix); year = atoi(bstr(vname)); - sprintf(vname, "%s_hour", prefix); hour = atoi(bstr(vname)); - sprintf(vname, "%s_minute", prefix); minute = atoi(bstr(vname)); + sprintf(vname, "%s_month", prefix); month = atoi(BSTR(vname)); + sprintf(vname, "%s_day", prefix); mday = atoi(BSTR(vname)); + sprintf(vname, "%s_year", prefix); year = atoi(BSTR(vname)); + sprintf(vname, "%s_hour", prefix); hour = atoi(BSTR(vname)); + sprintf(vname, "%s_minute", prefix); minute = atoi(BSTR(vname)); sprintf(timestr, "%04d%02d%02dT%02d%02d00", year, month, mday, hour, minute); t2 = icaltime_from_string(timestr); @@ -177,9 +177,9 @@ void icaltime_from_webform_dateonly(struct icaltimetype *t, char *prefix) { memset(t, 0, sizeof(struct icaltimetype)); - sprintf(vname, "%s_month", prefix); t->month = atoi(bstr(vname)); - sprintf(vname, "%s_day", prefix); t->day = atoi(bstr(vname)); - sprintf(vname, "%s_year", prefix); t->year = atoi(bstr(vname)); + sprintf(vname, "%s_month", prefix); t->month = atoi(BSTR(vname)); + sprintf(vname, "%s_day", prefix); t->day = atoi(BSTR(vname)); + sprintf(vname, "%s_year", prefix); t->year = atoi(BSTR(vname)); t->is_utc = 1; t->is_date = 1; } diff --git a/webcit/iconbar.c b/webcit/iconbar.c index 6dd17c810..eceb4c864 100644 --- a/webcit/iconbar.c +++ b/webcit/iconbar.c @@ -773,10 +773,10 @@ void commit_iconbar(void) { for (i=0; i<(sizeof(boxen)/sizeof(char *)); ++i) { char *Val; - if (!strcasecmp(bstr(boxen[i]), "yes")) { + if (!strcasecmp(BSTR(boxen[i]), "yes")) { Val = "1"; } - else if (!strcasecmp(bstr(boxen[i]), "yeslist")) { + else if (!strcasecmp(BSTR(boxen[i]), "yeslist")) { Val = "2"; } else { diff --git a/webcit/messages.c b/webcit/messages.c index a9353a93e..f42def11a 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -275,39 +275,59 @@ inline void utf8ify_rfc822_string(char *a){}; * \param target Target buffer. * \param maxlen Maximum size of target buffer. * \param source Source string to be encoded. + * \param SourceLen Length of the source string + * \returns encoded length; -1 if non success. */ -void webcit_rfc2047encode(char *target, int maxlen, char *source) +int webcit_rfc2047encode(char *target, int maxlen, char *source, long SourceLen) { + const char headerStr[] = "=?UTF-8?Q?"; int need_to_encode = 0; - int i, len; + int i = 0; + int len; unsigned char ch; - if (target == NULL) return; - len = strlen(source); - for (i=0; i 126)) { + if ((source == NULL) || + (target == NULL) || + (SourceLen > maxlen)) return -1; + + while ((!IsEmptyStr (&source[i])) && + (need_to_encode == 0) && + (i < SourceLen) ) { + if (((unsigned char) source[i] < 32) || + ((unsigned char) source[i] > 126)) { need_to_encode = 1; - i = len; ///< shortcut. won't become more than 1 } + i++; } if (!need_to_encode) { - safestrncpy(target, source, maxlen); - return; + memcpy (target, source, SourceLen); + return SourceLen; } - - strcpy(target, "=?UTF-8?Q?"); - for (i=0; i maxlen) + return -1; + memcpy (target, headerStr, sizeof (headerStr)); + len = sizeof (headerStr); + for (i=0; (i < SourceLen) && (len < maxlen) ; ++i) { ch = (unsigned char) source[i]; if ((ch < 32) || (ch > 126) || (ch == 61)) { - sprintf(&target[strlen(target)], "=%02X", ch); + sprintf(&target[len], "=%02X", ch); + len += 3; } else { - sprintf(&target[strlen(target)], "%c", ch); + sprintf(&target[len], "%c", ch); + len ++; } } - strcat(target, "?="); + if (len + 2 < maxlen) { + strcat(&target[len], "?="); + len +=2; + return len; + } + else + return -1; } @@ -2973,40 +2993,51 @@ void post_mime_to_server(void) { */ void post_message(void) { + urlcontent *u; + void *U; char buf[1024]; - char encoded_subject[1024]; + char *encoded_subject; static long dont_post = (-1L); struct wc_attachment *att, *aptr; int is_anonymous = 0; - char *display_name; + const char *display_name; + long dpLen = 0; + struct wcsession *WCC = WC; if (!IsEmptyStr(bstr("force_room"))) { gotoroom(bstr("force_room")); } - display_name = bstr("display_name"); + if (GetHash(WCC->urlstrings, HKEY("display_name"), &U)) { + u = (urlcontent*) U; + display_name = u->url_data; + dpLen = u->url_data_size; + } + else { + display_name=""; + } if (!strcmp(display_name, "__ANONYMOUS__")) { display_name = ""; is_anonymous = 1; } - if (WC->upload_length > 0) { + if (WCC->upload_length > 0) { - lprintf(9, "%s:%d: we are uploading %d bytes\n", __FILE__, __LINE__, WC->upload_length); + lprintf(9, "%s:%d: we are uploading %d bytes\n", __FILE__, __LINE__, WCC->upload_length); /** There's an attachment. Save it to this struct... */ att = malloc(sizeof(struct wc_attachment)); memset(att, 0, sizeof(struct wc_attachment)); - att->length = WC->upload_length; - strcpy(att->content_type, WC->upload_content_type); - strcpy(att->filename, WC->upload_filename); + att->length = WCC->upload_length; + strcpy(att->content_type, WCC->upload_content_type); + strcpy(att->filename, WCC->upload_filename); att->next = NULL; /** And add it to the list. */ - if (WC->first_attachment == NULL) { - WC->first_attachment = att; + if (WCC->first_attachment == NULL) { + WCC->first_attachment = att; } else { - aptr = WC->first_attachment; + aptr = WCC->first_attachment; while (aptr->next != NULL) aptr = aptr->next; aptr->next = att; } @@ -3027,44 +3058,102 @@ void post_message(void) * Transfer control of this memory from the upload struct * to the attachment struct. */ - att->data = WC->upload; - WC->upload_length = 0; - WC->upload = NULL; + att->data = WCC->upload; + WCC->upload_length = 0; + WCC->upload = NULL; display_enter(); return; } if (!IsEmptyStr(bstr("cancel_button"))) { - sprintf(WC->ImportantMessage, + sprintf(WCC->ImportantMessage, _("Cancelled. Message was not posted.")); } else if (!IsEmptyStr(bstr("attach_button"))) { display_enter(); return; } else if (atol(bstr("postseq")) == dont_post) { - sprintf(WC->ImportantMessage, + sprintf(WCC->ImportantMessage, _("Automatically cancelled because you have already " "saved this message.")); } else { - webcit_rfc2047encode(encoded_subject, sizeof encoded_subject, bstr("subject")); - sprintf(buf, "ENT0 1|%s|%d|4|%s|%s||%s|%s|%s|%s", - bstr("recp"), - is_anonymous, - encoded_subject, - display_name, - bstr("cc"), - bstr("bcc"), - bstr("wikipage"), - bstr("my_email_addr") - ); - serv_puts(buf); + const char CMD[] = "ENT0 1|%s|%d|4|%s|%s||%s|%s|%s|%s"; + const char *Recp = ""; + const char *Cc = ""; + const char *Bcc = ""; + const char *Wikipage = ""; + const char *my_email_addr = ""; + char *CmdBuf = NULL;; + long len = 0; + + if (GetHash(WCC->urlstrings, HKEY("subject"), &U)) { + u = (urlcontent*) U; + /** + * make enough room for the encoded string; + * plus the QP header + */ + len = u->url_data_size * 3 + 32; + encoded_subject = malloc (len); + len = webcit_rfc2047encode(encoded_subject, len, + u->url_data, u->url_data_size); + if (len < 0) { + free (encoded_subject); + return; + } + } + len += sizeof (CMD) + dpLen; + + if (GetHash(WCC->urlstrings, HKEY("recp"), &U)) { + u = (urlcontent*) U; + Recp = u->url_data; + len += u->url_data_size; } + + if (GetHash(WCC->urlstrings, HKEY("cc"), &U)) { + u = (urlcontent*) U; + Cc = u->url_data; + len += u->url_data_size; + } + + if (GetHash(WCC->urlstrings, HKEY("bcc"), &U)) { + u = (urlcontent*) U; + Bcc = u->url_data; + len += u->url_data_size; + } + + if (GetHash(WCC->urlstrings, HKEY("wikipage"), &U)) { + u = (urlcontent*) U; + Wikipage = u->url_data; + len += u->url_data_size; + } + + if (GetHash(WCC->urlstrings, HKEY("my_email_addr"), &U)) { + u = (urlcontent*) U; + my_email_addr = u->url_data; + len += u->url_data_size; + } + + CmdBuf = (char*) malloc (len + 1); + + + snprintf(CmdBuf, len + 1, CMD, + Recp, + is_anonymous, + encoded_subject, + display_name, + Cc, + Bcc, + Wikipage, + my_email_addr); + serv_puts(CmdBuf); serv_getln(buf, sizeof buf); + free (CmdBuf); + free (encoded_subject); if (buf[0] == '4') { post_mime_to_server(); if ( (!IsEmptyStr(bstr("recp"))) || (!IsEmptyStr(bstr("cc" ))) || (!IsEmptyStr(bstr("bcc" ))) ) { - sprintf(WC->ImportantMessage, _("Message has been sent.\n")); + sprintf(WCC->ImportantMessage, _("Message has been sent.\n")); } else { sprintf(WC->ImportantMessage, _("Message has been posted.\n")); @@ -3078,7 +3167,7 @@ void post_message(void) } } - free_attachments(WC); + free_attachments(WCC); /** * We may have been supplied with instructions regarding the location diff --git a/webcit/sieve.c b/webcit/sieve.c index 494555b31..2187d8296 100644 --- a/webcit/sieve.c +++ b/webcit/sieve.c @@ -496,39 +496,39 @@ void parse_fields_from_rule_editor(void) { strcpy(rule, ""); sprintf(fname, "active%d", i); - active = !strcasecmp(bstr(fname), "on") ; + active = !strcasecmp(BSTR(fname), "on") ; if (active) { sprintf(fname, "hfield%d", i); - safestrncpy(hfield, bstr(fname), sizeof hfield); + safestrncpy(hfield, BSTR(fname), sizeof hfield); sprintf(fname, "compare%d", i); - safestrncpy(compare, bstr(fname), sizeof compare); + safestrncpy(compare, BSTR(fname), sizeof compare); sprintf(fname, "htext%d", i); - safestrncpy(htext, bstr(fname), sizeof htext); + safestrncpy(htext, BSTR(fname), sizeof htext); sprintf(fname, "sizecomp%d", i); - safestrncpy(sizecomp, bstr(fname), sizeof sizecomp); + safestrncpy(sizecomp, BSTR(fname), sizeof sizecomp); sprintf(fname, "sizeval%d", i); - sizeval = atoi(bstr(fname)); + sizeval = atoi(BSTR(fname)); sprintf(fname, "action%d", i); - safestrncpy(action, bstr(fname), sizeof action); + safestrncpy(action, BSTR(fname), sizeof action); sprintf(fname, "fileinto%d", i); - safestrncpy(fileinto, bstr(fname), sizeof fileinto); + safestrncpy(fileinto, BSTR(fname), sizeof fileinto); sprintf(fname, "redirect%d", i); - safestrncpy(redirect, bstr(fname), sizeof redirect); + safestrncpy(redirect, BSTR(fname), sizeof redirect); sprintf(fname, "automsg%d", i); - safestrncpy(automsg, bstr(fname), sizeof automsg); + safestrncpy(automsg, BSTR(fname), sizeof automsg); sprintf(fname, "final%d", i); - safestrncpy(final, bstr(fname), sizeof final); + safestrncpy(final, BSTR(fname), sizeof final); snprintf(rule, sizeof rule, "%d|%s|%s|%s|%s|%d|%s|%s|%s|%s|%s", active, hfield, compare, htext, sizecomp, sizeval, action, fileinto, @@ -613,7 +613,7 @@ void save_sieve(void) { serv_getln(buf, sizeof buf); if (buf[0] == '4') { snprintf(this_name, sizeof this_name, "text_%s", script_names[i]); - striplt(bstr(this_name)); + striplt((char*)BSTR(this_name)); /* TODO: get rid of typecast*/ serv_printf("%s", bstr(this_name)); serv_puts("000"); } diff --git a/webcit/webcit.c b/webcit/webcit.c index 22d816ac9..f578fe98b 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -24,7 +24,7 @@ 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 */ -void unescape_input(char *buf) +long unescape_input(char *buf) { int a, b; char hex[3]; @@ -64,7 +64,14 @@ void unescape_input(char *buf) } a++; } + return a; +} +void free_url(void *U) +{ + urlcontent *u = (urlcontent*) U; + free(u->url_data); + free(u); } /** @@ -76,9 +83,12 @@ void addurls(char *url) char *aptr, *bptr, *eptr; char *up; char buf[SIZ]; - int len, n; - struct urlcontent *u; + int len, n, keylen; + urlcontent *u; + struct wcsession *WCC = WC; + if (WCC->urlstrings == NULL) + WCC->urlstrings = NewHash(); eptr = buf + sizeof (buf); up = url; /** locate the = sign */ @@ -101,22 +111,25 @@ void addurls(char *url) (*bptr != '&') && (*bptr != ' ')) bptr++; *bptr = '\0'; - u = (struct urlcontent *) malloc(sizeof(struct urlcontent)); - u->next = WC->urlstrings; - WC->urlstrings = u; + u = (urlcontent *) malloc(sizeof(urlcontent)); - if (safestrncpy(u->url_key, up, sizeof u->url_key) < 0) + + keylen = safestrncpy(u->url_key, up, sizeof u->url_key); + if (keylen < 0){ lprintf(1, "URLkey to long! [%s]", up); + 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[len] = 0; - unescape_input(u->url_data); + 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); + lprintf(9, "%s = [%ld] %s\n", u->url_key, u->url_data_size, u->url_data); } } @@ -125,24 +138,25 @@ void addurls(char *url) */ 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 */ + 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); } } @@ -151,15 +165,26 @@ void dump_vars(void) * \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 */ -char *bstr(char *key) +const char *BSTR(char *key) { - struct urlcontent *u; + void *U; - for (u = WC->urlstrings; u != NULL; u = u->next) { - if (!strcasecmp(u->url_key, key)) - return (u->url_data); - } - return (""); + 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 (""); } /** @@ -988,19 +1013,24 @@ void upload_handler(char *name, char *filename, char *partnum, char *disp, void *content, char *cbtype, char *cbcharset, size_t length, char *encoding, void *userdata) { - struct urlcontent *u; + urlcontent *u; lprintf(9, "upload_handler() name=%s, type=%s, len=%d\n", name, cbtype, length); + if (WC->urlstrings == NULL) + WC->urlstrings = NewHash(); + /* Form fields */ if ( (length > 0) && (IsEmptyStr(cbtype)) ) { - u = (struct urlcontent *) malloc(sizeof(struct urlcontent)); - u->next = WC->urlstrings; - WC->urlstrings = u; + 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; + 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); */ } diff --git a/webcit/webcit.h b/webcit/webcit.h index ce0be5daa..c0f37eb0f 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -225,10 +225,12 @@ struct httprequest { /** * \brief Linked list of session variables encoded in an x-www-urlencoded content type */ +typedef struct urlcontent urlcontent; struct urlcontent { struct urlcontent *next; /**< the next variable in the list */ char url_key[32]; /**< the variable name */ char *url_data; /**< its value */ + size_t url_data_size; /**< how big is it? */ }; /** @@ -383,7 +385,7 @@ struct wcsession { int num_summ; /**< number of messages in mailbox summary view */ struct message_summary *summ; /**< array of messages for mailbox summary view */ int is_wap; /**< Client is a WAP gateway */ - struct urlcontent *urlstrings; /**< variables passed to webcit in a URL */ + HashList *urlstrings; /**< variables passed to webcit in a URL */ struct wcsubst *vars; /**< HTTP variable substitutions for this page */ char this_page[512]; /**< URL of current page */ char http_host[512]; /**< HTTP Host: header */ @@ -501,7 +503,10 @@ void fmout(char *align); void pullquote_fmout(void); void wDumpContent(int); void serv_printf(const char *format,...); -char *bstr(char *key); +const char *Bstr(char *key, size_t keylen); +/* TODO: get rid of the non-const-typecast */ +#define bstr(a) (char*) Bstr(a, sizeof(a) - 1) +const char *BSTR(char *key); void urlescputs(char *); void jsesc(char *, size_t, char *); void jsescputs(char *); @@ -731,7 +736,7 @@ long locate_user_vcard(char *username, long usernum); void sleeeeeeeeeep(int); void http_transmit_thing(char *thing, size_t length, const char *content_type, int is_static); -void unescape_input(char *buf); +long unescape_input(char *buf); void do_iconbar(void); void do_iconbar_roomlist(void); void do_selected_iconbar(void); -- 2.30.2