From efa5c510f812880225d8c7690a72233333504e88 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Mon, 10 Nov 2008 00:21:19 +0000 Subject: [PATCH] * migrate message creation to templates (citing still missing) * log errors if sv doesn't have a token demanded * move CSSLOCAL from svput to registerns, as its static (ok, it will learn about a new CSS just after a restart, but thats consistent with our other stuff) --- webcit/context_loop.c | 17 +- webcit/html2html.c | 143 ++++++++ webcit/messages.c | 309 ++++++------------ webcit/msg_renderers.c | 30 +- webcit/preferences.c | 93 +++++- webcit/static/t/addressbook_popup.html | 6 + webcit/static/t/edit_message.html | 105 ++++++ webcit/static/t/head.html | 2 +- webcit/static/t/section_attach_select.html | 2 + .../t/section_msg_sender_from_select.html | 1 + .../t/section_msg_sender_name_select.html | 1 + webcit/static/t/view_message.html | 1 - webcit/static/t/view_message_print.html | 41 +++ webcit/subst.c | 8 + webcit/webcit.c | 61 ++-- webcit/webcit.h | 17 +- webcit/webserver.c | 6 +- 17 files changed, 578 insertions(+), 265 deletions(-) create mode 100644 webcit/static/t/addressbook_popup.html create mode 100644 webcit/static/t/edit_message.html create mode 100644 webcit/static/t/section_attach_select.html create mode 100644 webcit/static/t/section_msg_sender_from_select.html create mode 100644 webcit/static/t/section_msg_sender_name_select.html create mode 100644 webcit/static/t/view_message_print.html diff --git a/webcit/context_loop.c b/webcit/context_loop.c index 0107e0a38..7b646fbd4 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -22,15 +22,12 @@ pthread_key_t MyConKey; /**< TSD key for MySession() */ /* * free the memory used for viewing atachments */ -void free_attachments(struct wcsession *sess) { - struct wc_attachment *att; - - while (sess->first_attachment != NULL) { - att = sess->first_attachment; - sess->first_attachment = sess->first_attachment->next; - free(att->data); - free(att); - } +void free_attachment(void *vattach) { + wc_attachment *att = (wc_attachment*) vattach; + FreeStrBuf(&att->content_type); + FreeStrBuf(&att->filename); + free(att->data); + free(att); } @@ -44,7 +41,7 @@ void DestroySession(struct wcsession **sessions_to_kill) if ((*sessions_to_kill)->cache_fold != NULL) { free((*sessions_to_kill)->cache_fold); } - free_attachments((*sessions_to_kill)); + DeleteHash(&((*sessions_to_kill)->attachments)); free_march_list((*sessions_to_kill)); DeleteHash(&((*sessions_to_kill)->hash_prefs)); DeleteHash(&((*sessions_to_kill)->IconBarSetttings)); diff --git a/webcit/html2html.c b/webcit/html2html.c index 7d3e597ae..e77c2a13e 100644 --- a/webcit/html2html.c +++ b/webcit/html2html.c @@ -480,4 +480,147 @@ BAIL: /** A little trailing vertical whitespace... */ if ((msg != NULL) && (Source == NULL)) free(msg); } + + + + + +/* + * Look for URL's embedded in a buffer and make them linkable. We use a + * target window in order to keep the Citadel session in its own window. + */ +void UrlizeText(StrBuf* Target, StrBuf *Source, StrBuf *WrkBuf) +{ + int len, UrlLen, Offset, TrailerLen; + const char *start, *end, *pos; + + FlushStrBuf(Target); + + start = NULL; + len = StrLength(Source); + end = ChrPtr(Source) + len; + for (pos = ChrPtr(Source); (pos < end) && (start == NULL); ++pos) { + if (!strncasecmp(pos, "http://", 7)) + start = pos; + if (!strncasecmp(pos, "ftp://", 6)) + start = pos; + } + + if (start == NULL) { + StrBufAppendBuf(Target, Source, 0); + return; + } + FlushStrBuf(WrkBuf); + + for (pos = ChrPtr(Source) + len; pos > start; --pos) { + if ( (!isprint(*pos)) + || (isspace(*pos)) + || (*pos == '{') + || (*pos == '}') + || (*pos == '|') + || (*pos == '\\') + || (*pos == '^') + || (*pos == '[') + || (*pos == ']') + || (*pos == '`') + || (*pos == '<') + || (*pos == '>') + || (*pos == '(') + || (*pos == ')') + ) { + end = pos; + } + } + + UrlLen = end - start; + StrBufAppendBufPlain(WrkBuf, start, UrlLen, 0); + + Offset = start - ChrPtr(Source); + if (Offset != 0) + StrBufAppendBufPlain(Target, ChrPtr(Source), Offset, 0); + StrBufAppendPrintf(Target, "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c", + LB, QU, ChrPtr(WrkBuf), QU, QU, TARGET, + QU, RB, ChrPtr(WrkBuf), LB, RB); + + TrailerLen = len - (end - start); + if (TrailerLen > 0) + StrBufAppendBufPlain(Target, end, TrailerLen, 0); +} +void url(char *buf, size_t bufsize) +{ + int len, UrlLen, Offset, TrailerLen, outpos; + char *start, *end, *pos; + char urlbuf[SIZ]; + char outbuf[SIZ]; + + start = NULL; + len = strlen(buf); + if (len > bufsize) { + lprintf(1, "URL: content longer than buffer!"); + return; + } + end = buf + len; + for (pos = buf; (pos < end) && (start == NULL); ++pos) { + if (!strncasecmp(pos, "http://", 7)) + start = pos; + if (!strncasecmp(pos, "ftp://", 6)) + start = pos; + } + + if (start == NULL) + return; + + for (pos = buf+len; pos > start; --pos) { + if ( (!isprint(*pos)) + || (isspace(*pos)) + || (*pos == '{') + || (*pos == '}') + || (*pos == '|') + || (*pos == '\\') + || (*pos == '^') + || (*pos == '[') + || (*pos == ']') + || (*pos == '`') + || (*pos == '<') + || (*pos == '>') + || (*pos == '(') + || (*pos == ')') + ) { + end = pos; + } + } + + UrlLen = end - start; + if (UrlLen > sizeof(urlbuf)){ + lprintf(1, "URL: content longer than buffer!"); + return; + } + memcpy(urlbuf, start, UrlLen); + urlbuf[UrlLen] = '\0'; + + Offset = start - buf; + if ((Offset != 0) && (Offset < sizeof(outbuf))) + memcpy(outbuf, buf, Offset); + outpos = snprintf(&outbuf[Offset], sizeof(outbuf) - Offset, + "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c", + LB, QU, urlbuf, QU, QU, TARGET, QU, RB, urlbuf, LB, RB); + if (outpos >= sizeof(outbuf) - Offset) { + lprintf(1, "URL: content longer than buffer!"); + return; + } + + TrailerLen = len - (end - start); + if (TrailerLen > 0) + memcpy(outbuf + Offset + outpos, end, TrailerLen); + if (Offset + outpos + TrailerLen > bufsize) { + lprintf(1, "URL: content longer than buffer!"); + return; + } + memcpy (buf, outbuf, Offset + outpos + TrailerLen); + *(buf + Offset + outpos + TrailerLen) = '\0'; +} + + + + /*@}*/ diff --git a/webcit/messages.c b/webcit/messages.c index fe4d9be45..e82e03379 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -125,6 +125,18 @@ int longcmp_r(const void *s1, const void *s2) { return(0); } +/* + * qsort() compatible function to compare two longs in descending order. + */ +int qlongcmp_r(const void *s1, const void *s2) { + long l1 = (long) s1; + long l2 = (long) s2; + + if (l1 > l2) return(-1); + if (l1 < l2) return(+1); + return(0); +} + /* * qsort() compatible function to compare two message summary structs by ascending subject. @@ -209,152 +221,6 @@ int summcmp_rdate(const void *s1, const void *s2) { - -/* - * Look for URL's embedded in a buffer and make them linkable. We use a - * target window in order to keep the Citadel session in its own window. - */ -void UrlizeText(StrBuf* Target, StrBuf *Source, StrBuf *WrkBuf) -{ - int len, UrlLen, Offset, TrailerLen; - const char *start, *end, *pos; - - FlushStrBuf(Target); - - start = NULL; - len = StrLength(Source); - end = ChrPtr(Source) + len; - for (pos = ChrPtr(Source); (pos < end) && (start == NULL); ++pos) { - if (!strncasecmp(pos, "http://", 7)) - start = pos; - if (!strncasecmp(pos, "ftp://", 6)) - start = pos; - } - - if (start == NULL) { - StrBufAppendBuf(Target, Source, 0); - return; - } - FlushStrBuf(WrkBuf); - - for (pos = ChrPtr(Source) + len; pos > start; --pos) { - if ( (!isprint(*pos)) - || (isspace(*pos)) - || (*pos == '{') - || (*pos == '}') - || (*pos == '|') - || (*pos == '\\') - || (*pos == '^') - || (*pos == '[') - || (*pos == ']') - || (*pos == '`') - || (*pos == '<') - || (*pos == '>') - || (*pos == '(') - || (*pos == ')') - ) { - end = pos; - } - } - - UrlLen = end - start; - StrBufAppendBufPlain(WrkBuf, start, UrlLen, 0); - - Offset = start - ChrPtr(Source); - if (Offset != 0) - StrBufAppendBufPlain(Target, ChrPtr(Source), Offset, 0); - StrBufAppendPrintf(Target, "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c", - LB, QU, ChrPtr(WrkBuf), QU, QU, TARGET, - QU, RB, ChrPtr(WrkBuf), LB, RB); - - TrailerLen = len - (end - start); - if (TrailerLen > 0) - StrBufAppendBufPlain(Target, end, TrailerLen, 0); -} -void url(char *buf, size_t bufsize) -{ - int len, UrlLen, Offset, TrailerLen, outpos; - char *start, *end, *pos; - char urlbuf[SIZ]; - char outbuf[SIZ]; - - start = NULL; - len = strlen(buf); - if (len > bufsize) { - lprintf(1, "URL: content longer than buffer!"); - return; - } - end = buf + len; - for (pos = buf; (pos < end) && (start == NULL); ++pos) { - if (!strncasecmp(pos, "http://", 7)) - start = pos; - if (!strncasecmp(pos, "ftp://", 6)) - start = pos; - } - - if (start == NULL) - return; - - for (pos = buf+len; pos > start; --pos) { - if ( (!isprint(*pos)) - || (isspace(*pos)) - || (*pos == '{') - || (*pos == '}') - || (*pos == '|') - || (*pos == '\\') - || (*pos == '^') - || (*pos == '[') - || (*pos == ']') - || (*pos == '`') - || (*pos == '<') - || (*pos == '>') - || (*pos == '(') - || (*pos == ')') - ) { - end = pos; - } - } - - UrlLen = end - start; - if (UrlLen > sizeof(urlbuf)){ - lprintf(1, "URL: content longer than buffer!"); - return; - } - memcpy(urlbuf, start, UrlLen); - urlbuf[UrlLen] = '\0'; - - Offset = start - buf; - if ((Offset != 0) && (Offset < sizeof(outbuf))) - memcpy(outbuf, buf, Offset); - outpos = snprintf(&outbuf[Offset], sizeof(outbuf) - Offset, - "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c", - LB, QU, urlbuf, QU, QU, TARGET, QU, RB, urlbuf, LB, RB); - if (outpos >= sizeof(outbuf) - Offset) { - lprintf(1, "URL: content longer than buffer!"); - return; - } - - TrailerLen = len - (end - start); - if (TrailerLen > 0) - memcpy(outbuf + Offset + outpos, end, TrailerLen); - if (Offset + outpos + TrailerLen > bufsize) { - lprintf(1, "URL: content longer than buffer!"); - return; - } - memcpy (buf, outbuf, Offset + outpos + TrailerLen); - *(buf + Offset + outpos + TrailerLen) = '\0'; -} - - - - - - - - - - - /* * I wanna SEE that message! * @@ -362,8 +228,7 @@ void url(char *buf, size_t bufsize) * printable_view Nonzero to display a printable view * section Optional for encapsulated message/rfc822 submessage */ -void read_message(long msgnum, int printable_view, char *section) { - struct wcsession *WCC = WC; +void read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, int printable_view, char *section) { StrBuf *Buf; StrBuf *Token; StrBuf *FoundCharset; @@ -389,9 +254,9 @@ void read_message(long msgnum, int printable_view, char *section) { serv_printf("MSG4 %ld|%s", msgnum, section); StrBuf_ServGetln(Buf); if (GetServerStatus(Buf, NULL) != 1) { - wprintf(""); - wprintf(_("ERROR:")); - wprintf(" %s
\n", &buf[4]); + StrBufAppendPrintf(Target, ""); + StrBufAppendPrintf(Target, _("ERROR:")); + StrBufAppendPrintf(Target, " %s
\n", &buf[4]); FreeStrBuf(&Buf); return; } @@ -410,10 +275,10 @@ void read_message(long msgnum, int printable_view, char *section) { { Done = 1; if (state < 2) { - wprintf(""); - wprintf(_("unexpected end of message")); - wprintf(" (1)

\n"); - wprintf("\n"); + StrBufAppendPrintf(Target, ""); + StrBufAppendPrintf(Target, _("unexpected end of message")); + StrBufAppendPrintf(Target, " (1)

\n"); + StrBufAppendPrintf(Target, "\n"); FreeStrBuf(&Buf); FreeStrBuf(&Token); DestroyMessageSummary(Msg); @@ -539,7 +404,7 @@ void read_message(long msgnum, int printable_view, char *section) { StrBufAppendBuf(Msg->reply_to, Msg->from, 0); } } - DoTemplate(HKEY("view_message"), NULL, Msg, CTX_MAILSUM); + DoTemplate(tmpl, tmpllen, Target, Msg, CTX_MAILSUM); @@ -621,9 +486,13 @@ void read_message(long msgnum, int printable_view, char *section) { */ void embed_message(void) { long msgnum = 0L; + const StrBuf *Tmpl = sbstr("template"); msgnum = StrTol(WC->UrlFragment1); - read_message(msgnum, 0, ""); + if (StrLength(Tmpl) > 0) + read_message(WC->WBuf, SKEY(Tmpl), msgnum, 0, ""); + else + read_message(WC->WBuf, HKEY("view_message"), msgnum, 0, ""); } @@ -639,20 +508,13 @@ void print_message(void) { output_headers(0, 0, 0, 0, 0, 0); hprintf("Content-type: text/html\r\n" - "Server: %s\r\n" - "Connection: close\r\n", - PACKAGE_STRING); + "Server: " PACKAGE_STRING "\r\n" + "Connection: close\r\n"); + begin_burst(); - wprintf("\r\n\n"); - escputs(WC->wc_fullname); - wprintf("\n" - "\n" - ); - - read_message(msgnum, 1, ""); + read_message(WC->WBuf, HKEY("view_message_print"), msgnum, 1, ""); - wprintf("\n\n\n"); wDumpContent(0); } @@ -667,7 +529,7 @@ void mobile_message_view(void) { output_headers(1, 0, 0, 0, 0, 1); begin_burst(); do_template("msgcontrols", NULL); - read_message(msgnum,1, ""); + read_message(WC->WBuf, HKEY("view_message"), msgnum,1, ""); wDumpContent(0); } @@ -714,6 +576,7 @@ void display_headers(void) { * \param forward_attachments Nonzero if we want attachments to be forwarded */ void pullquote_message(long msgnum, int forward_attachments, int include_headers) { + struct wcsession *WCC = WC; char buf[SIZ]; char mime_partnum[256]; char mime_filename[256]; @@ -724,7 +587,7 @@ void pullquote_message(long msgnum, int forward_attachments, int include_headers char *attachments = NULL; char *ptr = NULL; int num_attachments = 0; - struct wc_attachment *att, *aptr; + wc_attachment *att; char m_subject[1024]; char from[256]; char node[256]; @@ -997,24 +860,21 @@ ENDBODY: if ( (!strcasecmp(mime_disposition, "inline")) || (!strcasecmp(mime_disposition, "attachment")) ) { + int n; + char N[64]; /* Create an attachment struct from this mime part... */ - att = malloc(sizeof(struct wc_attachment)); - memset(att, 0, sizeof(struct wc_attachment)); + att = malloc(sizeof(wc_attachment)); + memset(att, 0, sizeof(wc_attachment)); att->length = mime_length; - strcpy(att->content_type, mime_content_type); - strcpy(att->filename, mime_filename); - att->next = NULL; + att->content_type = NewStrBufPlain(mime_content_type, -1); + att->filename = NewStrBufPlain(mime_filename, -1); att->data = load_mimepart(msgnum, mime_partnum); + if (WCC->attachments == NULL) + WCC->attachments = NewHash(1, NULL); /* And add it to the list. */ - if (WC->first_attachment == NULL) { - WC->first_attachment = att; - } - else { - aptr = WC->first_attachment; - while (aptr->next != NULL) aptr = aptr->next; - aptr->next = att; - } + n = snprintf(N, sizeof N, "%d", GetCount(WCC->attachments) + 1); + Put(WCC->attachments, N, n, att, free_attachment); } } @@ -1744,13 +1604,13 @@ void readloop(char *oper) /** Output loop */ if (displayed_msgs != NULL) { if (bbs_reverse) { - qsort(displayed_msgs, num_displayed, sizeof(long), longcmp_r); + qsort(displayed_msgs, num_displayed, sizeof(long), qlongcmp_r); } /** if we do a split bbview in the future, begin messages div here */ for (a=0; aWBuf, HKEY("view_message"), displayed_msgs[a], 0, ""); } /** if we do a split bbview in the future, end messages div here */ @@ -1896,11 +1756,12 @@ DONE: * ... this is where the actual message gets transmitted to the server. */ void post_mime_to_server(void) { + struct wcsession *WCC = WC; char top_boundary[SIZ]; char alt_boundary[SIZ]; int is_multipart = 0; static int seq = 0; - struct wc_attachment *att; + wc_attachment *att; char *encoded; size_t encoded_length; size_t encoded_strlen; @@ -1922,7 +1783,7 @@ void post_mime_to_server(void) { serv_puts("X-Mailer: " PACKAGE_STRING); /* If there are attachments, we have to do multipart/mixed */ - if (WC->first_attachment != NULL) { + if (GetCount(WCC->attachments) > 0) { is_multipart = 1; } @@ -1958,18 +1819,23 @@ void post_mime_to_server(void) { serv_printf("--%s--", alt_boundary); if (is_multipart) { + long len; + const char *Key; + void *vAtt; + HashPos *it; /* Add in the attachments */ - for (att = WC->first_attachment; att!=NULL; att=att->next) { - + it = GetNewHashPos(); + while (GetNextHashPos(WCC->attachments, it, &len, &Key, &vAtt)) { + att = (wc_attachment*)vAtt; encoded_length = ((att->length * 150) / 100); encoded = malloc(encoded_length); if (encoded == NULL) break; encoded_strlen = CtdlEncodeBase64(encoded, att->data, att->length, 1); serv_printf("--%s", top_boundary); - serv_printf("Content-type: %s", att->content_type); - serv_printf("Content-disposition: attachment; filename=\"%s\"", att->filename); + serv_printf("Content-type: %s", ChrPtr(att->content_type)); + serv_printf("Content-disposition: attachment; filename=\"%s\"", ChrPtr(att->filename)); serv_puts("Content-transfer-encoding: base64"); serv_puts(""); serv_write(encoded, encoded_strlen); @@ -1978,6 +1844,7 @@ void post_mime_to_server(void) { free(encoded); } serv_printf("--%s--", top_boundary); + DeleteHashPos(&it); } serv_puts("000"); @@ -2000,7 +1867,7 @@ void post_message(void) char buf[1024]; StrBuf *encoded_subject = NULL; static long dont_post = (-1L); - struct wc_attachment *att, *aptr; + wc_attachment *att; int is_anonymous = 0; const StrBuf *display_name = NULL; struct wcsession *WCC = WC; @@ -2018,36 +1885,37 @@ void post_message(void) } if (WCC->upload_length > 0) { + const char *pch; + int n; + char N[64]; 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 = malloc(sizeof(wc_attachment)); + memset(att, 0, sizeof(wc_attachment)); 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 (WCC->first_attachment == NULL) { - WCC->first_attachment = att; - } - else { - aptr = WCC->first_attachment; - while (aptr->next != NULL) aptr = aptr->next; - aptr->next = att; - } + att->content_type = NewStrBufPlain(WCC->upload_content_type, -1); + att->filename = NewStrBufPlain(WCC->upload_filename, -1); + + + if (WCC->attachments == NULL) + WCC->attachments = NewHash(1, NULL); + /* And add it to the list. */ + n = snprintf(N, sizeof N, "%d", GetCount(WCC->attachments) + 1); + Put(WCC->attachments, N, n, att, free_attachment); /** * Mozilla sends a simple filename, which is what we want, * but Satan's Browser sends an entire pathname. Reduce * the path to just a filename if we need to. */ - while (num_tokens(att->filename, '/') > 1) { - remove_token(att->filename, 0, '/'); + pch = strrchr(ChrPtr(att->filename), '/'); + if (pch != NULL) { + StrBufCutLeft(att->filename, pch - ChrPtr(att->filename)); } - while (num_tokens(att->filename, '\\') > 1) { - remove_token(att->filename, 0, '\\'); + pch = strrchr(ChrPtr(att->filename), '\\'); + if (pch != NULL) { + StrBufCutLeft(att->filename, pch - ChrPtr(att->filename)); } /** @@ -2153,7 +2021,7 @@ void post_message(void) } } - free_attachments(WCC); + DeleteHash(&WCC->attachments); /** * We may have been supplied with instructions regarding the location @@ -2189,7 +2057,7 @@ void display_enter(void) StrBuf *ebuf; long now; const StrBuf *display_name = NULL; - struct wc_attachment *att; + /////wc_attachment *att; int recipient_required = 0; int subject_required = 0; int recipient_bad = 0; @@ -2259,12 +2127,14 @@ void display_enter(void) * Do a custom room banner with no navbar... */ output_headers(1, 1, 2, 0, 0, 0); + +/* wprintf("
\n"); embed_room_banner(NULL, navbar_none); wprintf("
\n"); wprintf("
\n" "
"); - +*/ /* Now check our actual recipients if there are any */ if (recipient_required) { const StrBuf *Recp = NULL; @@ -2311,6 +2181,13 @@ void display_enter(void) goto DONE; } } + DoTemplate(HKEY("edit_message"), NULL, NULL, CTX_NONE); + address_book_popup(); + wDumpContent(1); + + + return; + /** If we got this far, we can display the message entry screen. */ @@ -2587,14 +2464,16 @@ void display_enter(void) wprintf(_("Attachments:")); wprintf(" "); wprintf(""); /** Now offer the ability to attach additional files... */ diff --git a/webcit/msg_renderers.c b/webcit/msg_renderers.c index 388ac5060..ca9b264fd 100644 --- a/webcit/msg_renderers.c +++ b/webcit/msg_renderers.c @@ -729,6 +729,30 @@ void tmplput_MIME_Length(StrBuf *Target, int nArgs, WCTemplateToken *Token, void StrBufAppendPrintf(Target, "%ld", mime->length); } +HashList *iterate_get_registered_Attachments(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +{ + return WC->attachments; +} + +void tmplput_ATT_Length(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + wc_attachment *att = (wc_attachment*) Context; + StrBufAppendPrintf(Target, "%ld", att->length); +} + +void tmplput_ATT_Contenttype(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + wc_attachment *att = (wc_attachment*) Context; + StrBufAppendBuf(Target, att->content_type, 0); +} + +void tmplput_ATT_FileName(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + wc_attachment *att = (wc_attachment*) Context; + StrBufAppendBuf(Target, att->filename, 0); +} + + @@ -754,6 +778,9 @@ InitModule_MSGRENDERERS RegisterNamespace("MAIL:SUMM:INREPLYTO", 0, 2, tmplput_MAIL_SUMM_INREPLYTO, CTX_MAILSUM); RegisterNamespace("MAIL:BODY", 0, 2, tmplput_MAIL_BODY, CTX_MAILSUM); + RegisterNamespace("ATT:SIZE", 0, 1, tmplput_ATT_Length, CTX_ATT); + RegisterNamespace("ATT:TYPE", 0, 1, tmplput_ATT_Contenttype, CTX_ATT); + RegisterNamespace("ATT:FILENAME", 0, 1, tmplput_ATT_FileName, CTX_ATT); RegisterConditional(HKEY("COND:MAIL:SUMM:UNREAD"), 0, Conditional_MAIL_SUMM_UNREAD, CTX_MAILSUM); RegisterConditional(HKEY("COND:MAIL:SUMM:H_NODE"), 0, Conditional_MAIL_SUMM_H_NODE, CTX_MAILSUM); @@ -784,7 +811,8 @@ InitModule_MSGRENDERERS RegisterNamespace("MAIL:MIME:LENGTH", 0, 2, tmplput_MIME_Length, CTX_MIME_ATACH); RegisterNamespace("MAIL:MIME:DATA", 0, 2, tmplput_MIME_Data, CTX_MIME_ATACH); - + RegisterIterator("MSG:ATTACHNAMES", 0, NULL, iterate_get_registered_Attachments, + NULL, NULL, CTX_ATT, CTX_NONE); RegisterMimeRenderer(HKEY("message/rfc822"), render_MAIL); RegisterMimeRenderer(HKEY("text/x-vcard"), render_MIME_VCard); diff --git a/webcit/preferences.c b/webcit/preferences.c index f6e4bab14..e4689e8ad 100644 --- a/webcit/preferences.c +++ b/webcit/preferences.c @@ -716,6 +716,87 @@ int ConditionalPreference(WCTemplateToken *Token, void *Context, int ContextType return (StrTol(Pref) == Token->Params[3]->lvalue); } +HashList *GetGVEAHash(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +{ + StrBuf *Rcp; + HashList *List = NULL; + int Done = 0; + int i, n = 1; + char N[64]; + + Rcp = NewStrBuf(); + serv_puts("GVEA"); + StrBuf_ServGetln(Rcp); + if (ChrPtr(Rcp)[0] == '1') { + FlushStrBuf(Rcp); + List = NewHash(1, NULL); + while (!Done && (StrBuf_ServGetln(Rcp)>=0)) { + if ( (StrLength(Rcp)==3) && + !strcmp(ChrPtr(Rcp), "000")) + { + Done = 1; + } + else { + i = snprintf(N, sizeof(N), "%d", n); + Put(List, N, i, Rcp, HFreeStrBuf); + Rcp = NewStrBuf(); + } + n++; + } + } + FreeStrBuf(&Rcp); + return List; +} +void DeleteGVEAHash(HashList **KillMe) +{ + DeleteHash(KillMe); +} +void tmplput_EMAIL_ADDR(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + StrBuf *EmailAddr = (StrBuf*) Context; + StrBufAppendBuf(Target, EmailAddr, 0); +} + +HashList *GetGVSNHash(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +{ + StrBuf *Rcp; + HashList *List = NULL; + int Done = 0; + int i, n = 1; + char N[64]; + + Rcp = NewStrBuf(); + serv_puts("GVSN"); + StrBuf_ServGetln(Rcp); + if (ChrPtr(Rcp)[0] == '1') { + FlushStrBuf(Rcp); + List = NewHash(1, NULL); + while (!Done && (StrBuf_ServGetln(Rcp)>=0)) { + if ( (StrLength(Rcp)==3) && + !strcmp(ChrPtr(Rcp), "000")) + { + Done = 1; + } + else { + i = snprintf(N, sizeof(N), "%d", n); + Put(List, N, i, Rcp, HFreeStrBuf); + Rcp = NewStrBuf(); + } + n++; + } + } + FreeStrBuf(&Rcp); + return List; +} +void DeleteGVSNHash(HashList **KillMe) +{ + DeleteHash(KillMe); +} +void tmplput_EMAIL_NAME(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType) +{ + StrBuf *EmailAddr = (StrBuf*) Context; + StrBufAppendBuf(Target, EmailAddr, 0); +} void InitModule_PREFERENCES @@ -735,10 +816,18 @@ InitModule_PREFERENCES RegisterPreference("default_header_charset", _("Default character set for email headers:") ,PRF_STRING); RegisterPreference("emptyfloors", _("Show empty floors"), PRF_YESNO); - RegisterNamespace("PREF:VALUE", 1, 1, tmplput_CFG_Value, CTX_SESSION); - RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, CTX_SESSION); + RegisterNamespace("PREF:VALUE", 1, 2, tmplput_CFG_Value, CTX_NONE); + RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, CTX_NONE); RegisterIterator("PREF:ZONE", 0, ZoneHash, NULL, CfgZoneTempl, NULL, CTX_PREF, CTX_NONE); RegisterConditional(HKEY("COND:PREF"), 4, ConditionalPreference, CTX_NONE); + + RegisterNamespace("PREF:EMAIL:ADDR", 0, 1, tmplput_EMAIL_ADDR, CTX_GVEA); + RegisterIterator("PREF:VALID:EMAIL:ADDR", 0, NULL, + GetGVEAHash, NULL, DeleteGVEAHash, CTX_GVEA, CTX_NONE); + RegisterNamespace("PREF:EMAIL:NAME", 0, 1, tmplput_EMAIL_NAME, CTX_GVSN); + RegisterIterator("PREF:VALID:EMAIL:NAME", 0, NULL, + GetGVSNHash, NULL, DeleteGVSNHash, CTX_GVSN, CTX_NONE); + } /*@}*/ diff --git a/webcit/static/t/addressbook_popup.html b/webcit/static/t/addressbook_popup.html new file mode 100644 index 000000000..557d7e645 --- /dev/null +++ b/webcit/static/t/addressbook_popup.html @@ -0,0 +1,6 @@ + diff --git a/webcit/static/t/edit_message.html b/webcit/static/t/edit_message.html new file mode 100644 index 000000000..67e96dd62 --- /dev/null +++ b/webcit/static/t/edit_message.html @@ -0,0 +1,105 @@ + + + + +
+
+
+ +"> + + +"> + +

+ ">   + ">  TODO + "> +

+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
" size=45 maxlength=1000 /> +
+
+ |cc_id||bcc_id|');" title=""> +   + +
" size=45 maxlength=1000 /> +
+
" size=45 maxlength=1000 /> +
+
+ " size=45 maxlength=70> +
+ + + + + + +
+ + +    + +  "> + +
+ +
+
+ + + diff --git a/webcit/static/t/head.html b/webcit/static/t/head.html index 23e43a2d2..a57700d03 100644 --- a/webcit/static/t/head.html +++ b/webcit/static/t/head.html @@ -2,7 +2,7 @@ "http://www.w3.org/TR/html4/strict.dtd"> -<?CURRENT_USER> - <?SERV_HUMANNODE> +<?CURRENT_USER> - <?SERV:HUMANNODE> diff --git a/webcit/static/t/section_attach_select.html b/webcit/static/t/section_attach_select.html new file mode 100644 index 000000000..241ea2795 --- /dev/null +++ b/webcit/static/t/section_attach_select.html @@ -0,0 +1,2 @@ + + diff --git a/webcit/static/t/section_msg_sender_from_select.html b/webcit/static/t/section_msg_sender_from_select.html new file mode 100644 index 000000000..d683d6fa9 --- /dev/null +++ b/webcit/static/t/section_msg_sender_from_select.html @@ -0,0 +1 @@ + diff --git a/webcit/static/t/section_msg_sender_name_select.html b/webcit/static/t/section_msg_sender_name_select.html new file mode 100644 index 000000000..41373c54b --- /dev/null +++ b/webcit/static/t/section_msg_sender_name_select.html @@ -0,0 +1 @@ + diff --git a/webcit/static/t/view_message.html b/webcit/static/t/view_message.html index c5264eeb9..311025663 100644 --- a/webcit/static/t/view_message.html +++ b/webcit/static/t/view_message.html @@ -35,4 +35,3 @@ onMouseOut=document.getElementById("msg").style.visibility="hidden -
diff --git a/webcit/static/t/view_message_print.html b/webcit/static/t/view_message_print.html new file mode 100644 index 000000000..f6de22605 --- /dev/null +++ b/webcit/static/t/view_message_print.html @@ -0,0 +1,41 @@ +\n +<?CURRENT_USER> + + + + +

+ +
+ +
+ + + + + + + + + + diff --git a/webcit/subst.c b/webcit/subst.c index c764ce652..690a21f7a 100644 --- a/webcit/subst.c +++ b/webcit/subst.c @@ -505,6 +505,14 @@ void print_value_of(StrBuf *Target, WCTemplateToken *Token, void *Context, int C StrBufAppendPrintf(Target, "
WARNING: \ninvalid value in SV-Hash at %s!\n
", Token->pName); } } + else + lprintf(1, "didn't find Handler [%s] (in '%s' line %ld); " + " [%s]\n", + Token->pName, + ChrPtr(Token->FileName), + Token->Line, + ChrPtr(Token->FlatToken)); + } int CompareSubstToToken(TemplateParam *ParamToCompare, TemplateParam *ParamToLookup) diff --git a/webcit/webcit.c b/webcit/webcit.c index 5856fce8a..c4fd3648c 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -695,11 +695,6 @@ void output_headers( int do_httpheaders, /* 1 = output HTTP headers if (do_htmlhead) { begin_burst(); - if (!access("static.local/webcit.css", R_OK)) { - svprintf(HKEY("CSSLOCAL"), WCS_STRING, - "" - ); - } do_template("head", NULL); } @@ -956,32 +951,30 @@ void display_vcard_photo_img(void) * filename Fake filename to give * force_download Nonzero to force set the Content-Type: header to "application/octet-stream" */ -void postpart(const char *partnum, const char *filename, int force_download) +void postpart(StrBuf *partnum, StrBuf *filename, int force_download) { + void *vPart; char content_type[256]; - int num = atoi(partnum); - struct wc_attachment *part = WC->first_attachment; - - while(num && part) { - num--; - part=part->next; - } + wc_attachment *part; - if (part) { + if (GetHash(WC->attachments, SKEY(partnum), &vPart) && + (vPart != NULL)) { + part = (wc_attachment*) vPart; if (force_download) { strcpy(content_type, "application/octet-stream"); } else { - strncpy(content_type, part->content_type, sizeof content_type); + strncpy(content_type, ChrPtr(part->content_type), sizeof content_type); } output_headers(0, 0, 0, 0, 0, 0); StrBufAppendBufPlain(WC->WBuf, part->data, part->length, 0); http_transmit_thing(content_type, 0); } else { - hprintf("HTTP/1.1 404 %s\n",partnum); + 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"), partnum, filename); + wprintf(_("An error occurred while retrieving this part: %s/%s\n"), + ChrPtr(partnum), ChrPtr(filename)); end_burst(); } } @@ -1883,14 +1876,14 @@ void download_mimepart(void) { } void view_postpart(void) { - postpart(ChrPtr(WC->UrlFragment1), - ChrPtr(WC->UrlFragment2), + postpart(WC->UrlFragment1, + WC->UrlFragment2, 0); } void download_postpart(void) { - postpart(ChrPtr(WC->UrlFragment1), - ChrPtr(WC->UrlFragment2), + postpart(WC->UrlFragment1, + WC->UrlFragment2, 1); } @@ -1916,13 +1909,13 @@ void tmplput_importantmessage(StrBuf *Target, int nArgs, WCTemplateToken *Tokens int ConditionalBstr(WCTemplateToken *Tokens, void *Context, int ContextType) { - if(Tokens->nParameters == 1) - return HaveBstr(Tokens->Params[0]->Start, - Tokens->Params[0]->len); + if(Tokens->nParameters == 3) + return HaveBstr(Tokens->Params[2]->Start, + Tokens->Params[2]->len); else - return strcmp(Bstr(Tokens->Params[0]->Start, - Tokens->Params[0]->len), - Tokens->Params[1]->Start) == 0; + return strcmp(Bstr(Tokens->Params[2]->Start, + Tokens->Params[2]->len), + Tokens->Params[3]->Start) == 0; } void tmplput_bstr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) @@ -1932,6 +1925,19 @@ void tmplput_bstr(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Cont Tokens->Params[0]->len), 0); } + +void tmplput_csslocal(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType) +{ + extern StrBuf *csslocal; + StrBufAppendBuf(Target, + csslocal, 0); +} + + + + + + void InitModule_WEBCIT (void) @@ -1952,6 +1958,7 @@ InitModule_WEBCIT RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE); RegisterConditional(HKEY("COND:BSTR"), 1, ConditionalBstr, CTX_NONE); RegisterNamespace("BSTR", 1, 2, tmplput_bstr, CTX_NONE); + RegisterNamespace("CSSLOCAL", 0, 0, tmplput_csslocal, CTX_NONE); RegisterNamespace("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, CTX_NONE); RegisterNamespace("OFFERSTARTPAGE", 0, 0, offer_start_page, CTX_NONE); } diff --git a/webcit/webcit.h b/webcit/webcit.h index 4509ecb1f..33fe47e2d 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -313,6 +313,9 @@ typedef struct _wcsubst { #define CTX_USERLIST 8 #define CTX_MAILSUM 9 #define CTX_MIME_ATACH 10 +#define CTX_ATT 11 +#define CTX_GVEA 12 +#define CTX_GVSN 13 void RegisterNS(const char *NSName, long len, int nMinArgs, @@ -385,14 +388,14 @@ enum { /* * \brief mail attachment ??? */ -struct wc_attachment { - struct wc_attachment *next;/* pointer to next in list */ +typedef struct _wc_attachment { size_t length; /* length of the contenttype */ - char content_type[SIZ]; /* the content itself ???*/ - char filename[SIZ]; /* the filename hooked to this content ??? */ + StrBuf *content_type; /* the content itself ???*/ + StrBuf *filename; /* the filename hooked to this content ??? */ char *data; /* the data pool; aka this content */ long lvalue; /* if we put a long... */ -}; +} wc_attachment; +void free_attachment(void *vattach); typedef struct wc_mime_attachment wc_mime_attachment; @@ -570,7 +573,7 @@ struct wcsession { char http_host[512]; /**< HTTP Host: header */ HashList *hash_prefs; /**< WebCit preferences for this user */ HashList *disp_cal_items; /**< sorted list of calendar items; startdate is the sort criteria. */ - struct wc_attachment *first_attachment; /**< linked list of attachments for 'enter message' */ + HashList *attachments; /**< list of attachments for 'enter message' */ char last_chat_user[256]; /**< ??? todo */ char ImportantMessage[SIZ]; /**< ??? todo */ int ctdl_pid; /**< Session ID on the Citadel server */ @@ -780,7 +783,7 @@ void dump_vars(void); void embed_main_menu(void); void serv_read(char *buf, int bytes); void readloop(char *oper); -void read_message(long msgnum, int printable_view, char *section); +void read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, int printable_view, char *section); void do_addrbook_view(addrbookent *addrbook, int num_ab); void display_vcard(StrBuf *Target, const char *vcard_source, char alpha, int full, char *storename, long msgnum); void text_to_server(char *ptr); diff --git a/webcit/webserver.c b/webcit/webserver.c index a28e87f35..05ba05176 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -659,7 +659,7 @@ const char *nix(void *vptr) {snprintf(foobuf, 32, "%0x", (long) vptr); return fo void InitTemplateCache(void); extern int LoadTemplates; extern void LoadZoneFiles(void); - +StrBuf *csslocal = NULL; /* * Here's where it all begins. */ @@ -882,6 +882,10 @@ int main(int argc, char **argv) initialize_viewdefs(); initialize_axdefs(); + if (!access("static.local/webcit.css", R_OK)) { + csslocal = NewStrBufPlain(HKEY("")); + } + /* Tell libical to return an error instead of aborting if it sees badly formed iCalendar data. */ icalerror_errors_are_fatal = 0; -- 2.30.2