#include "webcit.h"
#include "vcard.h"
#include "webserver.h"
+#include "groupdav.h"
/* Address book entry (keep it short and sweet, it's just a quickie lookup
char encoding[16];
char istr[1024];
iconv_t ic = (iconv_t)(-1) ;
- char *ibuf; /* Buffer of characters to be converted */
- char *obuf; /* Buffer for converted characters */
- size_t ibuflen; /* Length of input buffer */
- size_t obuflen; /* Length of output buffer */
- char *isav; /* Saved pointer to input buffer */
- char *osav; /* Saved pointer to output buffer */
+ char *ibuf; /* Buffer of characters to be converted */
+ char *obuf; /* Buffer for converted characters */
+ size_t ibuflen; /* Length of input buffer */
+ size_t obuflen; /* Length of output buffer */
+ char *isav; /* Saved pointer to input buffer */
+ char *osav; /* Saved pointer to output buffer */
+ int passes = 0;
while (start=strstr(buf, "=?"), end=strstr(buf, "?="),
((start != NULL) && (end != NULL) && (end > start)) )
iconv_close(ic);
}
else {
+ end = start;
+ end++;
+ strcpy(start, "");
+ remove_token(end, 0, '?');
+ remove_token(end, 0, '?');
+ remove_token(end, 0, '?');
+ remove_token(end, 0, '?');
+ strcpy(end, &end[1]);
+
snprintf(newbuf, sizeof newbuf, "%s(unreadable)%s", buf, end);
strcpy(buf, newbuf);
}
free(isav);
+
+ /* Since spammers will go to all sorts of absurd lengths to get their
+ * messages through, there are LOTS of corrupt headers out there.
+ * So, prevent a really badly formed RFC2047 header from throwing
+ * this function into an infinite loop.
+ */
+ ++passes;
+ if (passes > 20) return;
}
}
strcat(mailto,
"<A HREF=\"/display_enter"
"?force_room=_MAIL_?recp=");
+
+ urlesc(&mailto[strlen(mailto)], displayname);
+ urlesc(&mailto[strlen(mailto)], " <");
urlesc(&mailto[strlen(mailto)], thisvalue);
+ urlesc(&mailto[strlen(mailto)], ">");
+
strcat(mailto, "\">");
- urlesc(&mailto[strlen(mailto)], thisvalue);
+ stresc(&mailto[strlen(mailto)], thisvalue, 1, 1);
strcat(mailto, "</A>");
}
else if (!strcasecmp(firsttoken, "tel")) {
/*
- * I wanna SEE that message!
+ * I wanna SEE that message! (Optional 'section' for encapsulated message/rfc822 submessage)
*/
-void read_message(long msgnum, int printable_view) {
+void read_message(long msgnum, int printable_view, char *section) {
char buf[SIZ];
char mime_partnum[256];
char mime_filename[256];
char mime_disposition[256];
int mime_length;
char mime_http[SIZ];
+ char mime_submessages[256];
char m_subject[256];
char m_cc[1024];
char from[256];
char *part_source = NULL;
#ifdef HAVE_ICONV
iconv_t ic = (iconv_t)(-1) ;
- char *ibuf; /* Buffer of characters to be converted */
- char *obuf; /* Buffer for converted characters */
- size_t ibuflen; /* Length of input buffer */
- size_t obuflen; /* Length of output buffer */
- char *osav; /* Saved pointer to output buffer */
+ char *ibuf; /* Buffer of characters to be converted */
+ char *obuf; /* Buffer for converted characters */
+ size_t ibuflen; /* Length of input buffer */
+ size_t obuflen; /* Length of output buffer */
+ char *osav; /* Saved pointer to output buffer */
#endif
strcpy(from, "");
strcpy(mime_http, "");
strcpy(mime_content_type, "text/plain");
strcpy(mime_charset, "us-ascii");
+ strcpy(mime_submessages, "");
- serv_printf("MSG4 %ld", msgnum);
+ serv_printf("MSG4 %ld|%s", msgnum, section);
serv_getln(buf, sizeof buf);
if (buf[0] != '1') {
wprintf("<STRONG>");
extract_token(mime_content_type, &buf[5], 4, '|', sizeof mime_content_type);
mime_length = extract_int(&buf[5], 5);
- if ((!strcasecmp(mime_disposition, "inline"))
+ if (!strcasecmp(mime_content_type, "message/rfc822")) {
+ if (strlen(mime_submessages) > 0) {
+ strcat(mime_submessages, "|");
+ }
+ strcat(mime_submessages, mime_partnum);
+ }
+ else if ((!strcasecmp(mime_disposition, "inline"))
&& (!strncasecmp(mime_content_type, "image/", 6)) ){
snprintf(&mime_http[strlen(mime_http)],
(sizeof(mime_http) - strlen(mime_http) - 1),
"TARGET=\"wc.%ld.%s\">"
"<IMG SRC=\"/static/diskette_24x.gif\" "
"BORDER=0 ALIGN=MIDDLE>\n"
- "Part %s: %s (%s, %d bytes)</A><br />\n",
+ "%s (%s, %d bytes)</A><br />\n",
msgnum, mime_partnum, mime_filename,
msgnum, mime_partnum,
- mime_partnum, mime_filename,
- mime_content_type, mime_length);
+ mime_filename,
+ mime_content_type, mime_length
+ );
}
/*** begin handler prep ***/
wprintf("<td align=right>\n");
/* Reply */
- wprintf("<a href=\"/display_enter?recp=");
- urlescputs(reply_to);
- wprintf("?subject=");
- if (strncasecmp(m_subject, "Re:", 3)) wprintf("Re:%20");
- urlescputs(m_subject);
- wprintf("\">[%s]</a> ", _("Reply"));
+ if ( (WC->wc_view == VIEW_MAILBOX) || (WC->wc_view == VIEW_BBS) ) {
+ wprintf("<a href=\"/display_enter");
+ if (WC->is_mailbox) {
+ wprintf("?replyquote=%ld", msgnum);
+ }
+ wprintf("?recp=");
+ urlescputs(reply_to);
+ wprintf("?subject=");
+ if (strncasecmp(m_subject, "Re:", 3)) wprintf("Re:%20");
+ urlescputs(m_subject);
+ wprintf("\">[%s]</a> ", _("Reply"));
+ }
+
+ /* ReplyQuoted */
+ if ( (WC->wc_view == VIEW_MAILBOX) || (WC->wc_view == VIEW_BBS) ) {
+ if (!WC->is_mailbox) {
+ wprintf("<a href=\"/display_enter");
+ wprintf("?replyquote=%ld", msgnum);
+ wprintf("?recp=");
+ urlescputs(reply_to);
+ wprintf("?subject=");
+ if (strncasecmp(m_subject, "Re:", 3)) wprintf("Re:%20");
+ urlescputs(m_subject);
+ wprintf("\">[%s]</a> ", _("ReplyQuoted"));
+ }
+ }
/* ReplyAll */
if (WC->wc_view == VIEW_MAILBOX) {
- wprintf("<a href=\"/display_enter?recp=");
+ wprintf("<a href=\"/display_enter");
+ wprintf("?replyquote=%ld", msgnum);
+ wprintf("?recp=");
urlescputs(reply_to);
wprintf("?cc=");
urlescputs(reply_all);
- wprintf("?subject=");
- if (strncasecmp(m_subject, "Re:", 3)) wprintf("Re:%20");
- urlescputs(m_subject);
+ if (strlen(m_subject) > 0) {
+ wprintf("?subject=");
+ if (strncasecmp(m_subject, "Re:", 3)) wprintf("Re:%20");
+ urlescputs(m_subject);
+ }
wprintf("\">[%s]</a> ", _("ReplyAll"));
}
/* Forward */
if (WC->wc_view == VIEW_MAILBOX) {
- wprintf("<a href=\"/display_enter?pullquote=%ld?subject=", msgnum);
+ wprintf("<a href=\"/display_enter?fwdquote=%ld?subject=", msgnum);
if (strncasecmp(m_subject, "Fwd:", 4)) wprintf("Fwd:%20");
urlescputs(m_subject);
wprintf("\">[%s]</a> ", _("Forward"));
}
- if (WC->is_room_aide) {
+ /* If this is one of my own rooms, or if I'm an Aide or Room Aide, I can move/delete */
+ if ( (WC->is_room_aide) || (WC->is_mailbox) ) {
/* Move */
wprintf("<a href=\"/confirm_move_msg?msgid=%ld\">[%s]</a> ",
msgnum, _("Move"));
/* Set up a character set conversion if we need to (and if we can) */
#ifdef HAVE_ICONV
+ if (strchr(mime_charset, ';')) strcpy(strchr(mime_charset, ';'), "");
if ( (strcasecmp(mime_charset, "us-ascii"))
- && (strcasecmp(mime_charset, "UTF-8")) ) {
+ && (strcasecmp(mime_charset, "UTF-8"))
+ && (strcasecmp(mime_charset, ""))
+ ) {
ic = iconv_open("UTF-8", mime_charset);
if (ic == (iconv_t)(-1) ) {
- lprintf(5, "iconv_open() failed: %s\n", strerror(errno));
+ lprintf(5, "%s:%d iconv_open(UTF-8, %s) failed: %s\n",
+ __FILE__, __LINE__, mime_charset, strerror(errno));
}
}
#endif
/* Boring old 80-column fixed format text gets handled this way... */
else if ( (!strcasecmp(mime_content_type, "text/plain"))
- || (!strcasecmp(mime_content_type, "text")) ) {
+ || (!strcasecmp(mime_content_type, "text")) ) {
while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
if (buf[strlen(buf)-1] == '\r') buf[strlen(buf)-1] = 0;
while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { }
}
+ /* If there are attached submessages, display them now... */
+ if ( (strlen(mime_submessages) > 0) && (!section[0]) ) {
+ for (i=0; i<num_tokens(mime_submessages, '|'); ++i) {
+ extract_token(buf, mime_submessages, i, '|', sizeof buf);
+ /* use printable_view to suppress buttons */
+ wprintf("<blockquote>");
+ read_message(msgnum, 1, buf);
+ wprintf("</blockquote>");
+ }
+ }
+
+
/* Afterwards, offer links to download attachments 'n' such */
- if (strlen(mime_http) > 0) {
+ if ( (strlen(mime_http) > 0) && (!section[0]) ) {
wprintf("%s", mime_http);
}
msgnum = atol(bstr("msgnum"));
begin_ajax_response();
- read_message(msgnum, 0);
+ read_message(msgnum, 0, "");
end_ajax_response();
}
long msgnum = 0L;
msgnum = atol(bstr("msgnum"));
- output_headers(0, 0, 0, 0, 0, 0);
+ output_headers(0, 0, 0, 0, 0, 0);
- wprintf("Content-type: text/html\r\n"
- "Server: %s\r\n"
- "Connection: close\r\n",
- SERVER);
- begin_burst();
+ wprintf("Content-type: text/html\r\n"
+ "Server: %s\r\n"
+ "Connection: close\r\n",
+ SERVER);
+ begin_burst();
wprintf("\r\n\r\n<html>\n"
"<head><title>Printable view</title></head>\n"
"<body onLoad=\" window.print(); window.close(); \">\n"
);
- read_message(msgnum, 1);
+ read_message(msgnum, 1, "");
wprintf("\n</body></html>\n\n");
wDumpContent(0);
int i = 0;
#ifdef HAVE_ICONV
iconv_t ic = (iconv_t)(-1) ;
- char *ibuf; /* Buffer of characters to be converted */
- char *obuf; /* Buffer for converted characters */
- size_t ibuflen; /* Length of input buffer */
- size_t obuflen; /* Length of output buffer */
- char *osav; /* Saved pointer to output buffer */
+ char *ibuf; /* Buffer of characters to be converted */
+ char *obuf; /* Buffer for converted characters */
+ size_t ibuflen; /* Length of input buffer */
+ size_t obuflen; /* Length of output buffer */
+ char *osav; /* Saved pointer to output buffer */
#endif
strcpy(from, "");
/* Set up a character set conversion if we need to (and if we can) */
#ifdef HAVE_ICONV
if ( (strcasecmp(mime_charset, "us-ascii"))
- && (strcasecmp(mime_charset, "UTF-8")) ) {
+ && (strcasecmp(mime_charset, "UTF-8"))
+ && (strcasecmp(mime_charset, ""))
+ ) {
ic = iconv_open("UTF-8", mime_charset);
if (ic == (iconv_t)(-1) ) {
- lprintf(5, "iconv_open() failed: %s\n", strerror(errno));
+ lprintf(5, "%s:%d iconv_open() failed: %s\n",
+ __FILE__, __LINE__, strerror(errno));
}
}
#endif
* If there were attachments, we have to download them and insert them
* into the attachment chain for the forwarded message we are composing.
*/
- if (num_attachments) {
+ if ( (forward_attachments) && (num_attachments) ) {
for (i=0; i<num_attachments; ++i) {
extract_token(buf, attachments, i, '\n', sizeof buf);
- extract_token(mime_filename, buf, 1, '|', sizeof mime_filename);
- extract_token(mime_partnum, buf, 2, '|', sizeof mime_partnum);
- extract_token(mime_disposition, buf, 3, '|', sizeof mime_disposition);
- extract_token(mime_content_type, buf, 4, '|', sizeof mime_content_type);
- mime_length = extract_int(buf, 5);
+ extract_token(mime_filename, buf, 1, '|', sizeof mime_filename);
+ extract_token(mime_partnum, buf, 2, '|', sizeof mime_partnum);
+ extract_token(mime_disposition, buf, 3, '|', sizeof mime_disposition);
+ extract_token(mime_content_type, buf, 4, '|', sizeof mime_content_type);
+ mime_length = extract_int(buf, 5);
/*
* tracing ... uncomment if necessary
void display_summarized(int num) {
char datebuf[64];
+ wprintf("<tr bgcolor=\"#%s\" ",
+ ((num % 2) ? "DDDDDD" : "FFFFFF")
+ );
+
+ wprintf("onClick=\" new Ajax.Updater('preview_pane', '/msg', { method: 'get', parameters: 'msgnum=%ld' } ); \" ", WC->summ[num].msgnum);
+ wprintf(">");
+
wprintf("<TD>");
if (WC->summ[num].is_new) wprintf("<B>");
escputs(WC->summ[num].subj);
wprintf(" </TD>");
wprintf("<TD>"
"<INPUT TYPE=\"checkbox\" NAME=\"msg_%ld\" VALUE=\"yes\">"
- "</TD>\n",
+ "</TD>",
WC->summ[num].msgnum
);
+
+ wprintf("</tr>\n");
}
long pn_previous = 0L;
long pn_current = 0L;
long pn_next = 0L;
- int bg = 0;
struct addrbookent *addrbook = NULL;
int num_ab = 0;
char *sortby = NULL;
set_preference(sortpref_name, sortby, 1);
}
if (strlen(sortby) == 0) sortby = sortpref_value;
- if (strlen(sortby) == 0) sortby = "msgid";
+ if (strlen(sortby) == 0) sortby = "rdate";
output_headers(1, 1, 1, 0, 0, 0);
datesort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=date\"><img border=\"0\" src=\"/static/up_pointer.gif\" /></a>" ;
}
else {
- datesort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=date\"><img border=\"0\" src=\"/static/sort_none.gif\" /></a>" ;
+ datesort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rdate\"><img border=\"0\" src=\"/static/sort_none.gif\" /></a>" ;
}
if (is_summary) {
"<form name=\"msgomatic\" "
"method=\"POST\" action=\"/do_stuff_to_msgs\">\n"
+ "<span class=\"mailbox_summary\">"
"<table border=0 cellspacing=0 "
"cellpadding=0 width=100%%>\n"
"<TR>"
if (a > 0) pn_previous = WC->msgarr[a-1];
if (a < (nummsgs-1)) pn_next = WC->msgarr[a+1];
- /* If a tabular view, set up the line */
- if (is_summary) {
- bg = 1 - bg;
- wprintf("<tr bgcolor=\"#%s\" ",
- (bg ? "DDDDDD" : "FFFFFF")
- );
-
- wprintf("onClick=\" new Ajax.Updater('preview_pane', '/msg', { method: 'get', parameters: 'msgnum=%ld' } ); \" ", WC->summ[a].msgnum);
-
- wprintf(">");
- }
-
/* Display the message */
if (is_summary) {
display_summarized(a);
display_note(WC->msgarr[a]);
}
else {
- read_message(WC->msgarr[a], 0);
- }
-
- /* If a tabular view, finish the line */
- if (is_summary) {
- wprintf("</TR>\n");
+ read_message(WC->msgarr[a], 0, "");
}
if (lowest_displayed < 0) lowest_displayed = a;
}
if (is_summary) {
- wprintf("</table></form>"
+ wprintf("</table></span></form>"
"</div>\n"); /* end of 'fix_scrollbar_bug' div */
wprintf("</div>"); /* end of 'message_list' div */
wprintf("<div id=\"ml_slider\"></div>"); /* slider */
wprintf("<div id=\"preview_pane\">"); /* The preview pane will initially be empty */
+
+ /* Now register each message (whose element ID is "m9999",
+ * where "9999" is the message number) as draggable.
+ wprintf("<script type=\"text/javascript\">\n");
+ for (a = 0; a < nummsgs; ++a) {
+ wprintf("new Draggable('m%ld',{revert:true});\n",
+ WC->summ[a].msgnum);
+ }
+ wprintf("</script>\n");
+ */
}
/* Bump these because although we're thinking in zero base, the user
void display_enter(void)
{
char buf[SIZ];
+ char ebuf[SIZ];
long now;
struct wc_attachment *att;
int recipient_required = 0;
int recipient_bad = 0;
+ int i;
if (strlen(bstr("force_room")) > 0) {
gotoroom(bstr("force_room"));
wprintf("<textarea name=\"msgtext\" cols=\"80\" rows=\"15\">");
+ /* If we're continuing from a previous edit, put our partially-composed message back... */
msgescputs(bstr("msgtext"));
- if (atol(bstr("pullquote")) > 0L) {
+
+ /* If we're forwarding a message, insert it here... */
+ if (atol(bstr("fwdquote")) > 0L) {
wprintf("<br><div align=center><i>");
wprintf(_("--- forwarded message ---"));
wprintf("</i></div><br>");
- pullquote_message(atol(bstr("pullquote")), 1);
+ pullquote_message(atol(bstr("fwdquote")), 1);
+ }
+
+ /* If we're replying quoted, insert the quote here... */
+ else if (atol(bstr("replyquote")) > 0L) {
+ wprintf("<br>"
+ "<blockquote>");
+ pullquote_message(atol(bstr("replyquote")), 0);
+ wprintf("</blockquote>");
+ }
+
+ /* Insert our signature if appropriate... */
+ if ( (WC->is_mailbox) && (strcmp(bstr("sig_inserted"), "yes")) ) {
+ get_preference("use_sig", buf, sizeof buf);
+ if (!strcasecmp(buf, "yes")) {
+ get_preference("signature", ebuf, sizeof ebuf);
+ euid_unescapize(buf, ebuf);
+ wprintf("<br>--<br>");
+ for (i=0; i<strlen(buf); ++i) {
+ if (buf[i] == '\n') {
+ wprintf("<br>");
+ }
+ else if (buf[i] == '<') {
+ wprintf("<");
+ }
+ else if (buf[i] == '>') {
+ wprintf(">");
+ }
+ else if (buf[i] == '&') {
+ wprintf("&");
+ }
+ else if (buf[i] == '\"') {
+ wprintf(""");
+ }
+ else if (buf[i] == '\'') {
+ wprintf("'");
+ }
+ else if (isprint(buf[i])) {
+ wprintf("%c", buf[i]);
+ }
+ }
+ }
}
+
wprintf("</textarea>");
wprintf("</center><br />\n");
"<script language=\"javascript\" type=\"text/javascript\" src=\"tiny_mce/tiny_mce.js\"></script>\n"
"<script language=\"javascript\" type=\"text/javascript\">"
"tinyMCE.init({"
- " mode : \"textareas\", width : \"100%%\" "
+ " mode : \"textareas\", width : \"100%%\", browsers : \"msie,gecko\" "
"});"
"</script>\n"
);
wprintf("\"> "
"<input type=\"submit\" name=\"cancel_button\" value=\"%s\">\n", _("Cancel"));
+ /* Make sure we only insert our signature once */
+ if (strcmp(bstr("sig_inserted"), "yes")) {
+ wprintf("<INPUT TYPE=\"hidden\" NAME=\"sig_inserted\" VALUE=\"yes\">\n");
+ }
+
wprintf("</form>\n");
wprintf("</td></tr></table></div>\n");
output_headers(1, 1, 1, 0, 0, 0);
- sprintf(buf, "DELE %ld", msgid);
- serv_puts(buf);
+ serv_printf("MOVE %ld|_TRASH_|0", msgid);
serv_getln(buf, sizeof buf);
wprintf("<EM>%s</EM><br />\n", &buf[4]);
msgid = atol(bstr("msgid"));
- output_headers(1, 1, 1, 0, 0, 0);
- wprintf("<div id=\"fix_scrollbar_bug\">"
- "<table width=100%% border=0 bgcolor=\"#444455\"><tr><td>");
- wprintf("<font size=+1 color=\"#ffffff\"");
- wprintf("<b>");
+ output_headers(1, 1, 2, 0, 0, 0);
+ wprintf("<div id=\"banner\">\n");
+ wprintf("<TABLE WIDTH=100%% BORDER=0><TR><TD>");
+ wprintf("<SPAN CLASS=\"titlebar\">");
wprintf(_("Confirm move of message"));
- wprintf("</b>\n");
- wprintf("</font></td></tr></table></div>\n");
+ wprintf("</SPAN>\n");
+ wprintf("</TD></TR></TABLE>\n");
+ wprintf("</div>\n<div id=\"content\">\n");
wprintf("<CENTER>");
wprintf("<br />\n");
wprintf("<form METHOD=\"POST\" ACTION=\"/move_msg\">\n");
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgid\" VALUE=\"%s\">\n",
- bstr("msgid"));
-
+ wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgid\" VALUE=\"%s\">\n", bstr("msgid"));
wprintf("<SELECT NAME=\"target_room\" SIZE=5>\n");
serv_puts("LKRA");
msgid = atol(bstr("msgid"));
- output_headers(1, 1, 1, 0, 0, 0);
-
if (strlen(bstr("move_button")) > 0) {
sprintf(buf, "MOVE %ld|%s", msgid, bstr("target_room"));
serv_puts(buf);
serv_getln(buf, sizeof buf);
- wprintf("<EM>%s</EM><br />\n", &buf[4]);
+ sprintf(WC->ImportantMessage, "%s", &buf[4]);
} else {
- wprintf("<EM>");
- wprintf(_("The message was not moved."));
- wprintf("</EM><br />\n");
+ sprintf(WC->ImportantMessage, (_("The message was not moved.")));
}
- wDumpContent(1);
+ readloop("readnew");
+
}
/*
if (!strcasecmp(bstr(buf), "yes")) {
if (delete_button_pressed) {
- serv_printf("DELE %ld", stuff->msgnum);
+ serv_printf("MOVE %ld|_TRASH_|0", stuff->msgnum);
serv_getln(buf, sizeof buf);
}