]> code.citadel.org Git - citadel.git/blobdiff - webcit/messages.c
Allow multiple addresses to be selected.
[citadel.git] / webcit / messages.c
index ed89b48996db86c67f916db45f7b91e95b161733..db930c7230b05f611aa25b94398e76b396d380ad 100644 (file)
@@ -32,7 +32,7 @@ struct addrbookent {
 /**
  * \brief      Wrapper around iconv_open()
  *             Our version adds aliases for non-standard Microsoft charsets
- *              such as 'MS950', aliasing them to names like 'CP950'
+ *           such as 'MS950', aliasing them to names like 'CP950'
  *
  * \param      tocode          Target encoding
  * \param      fromcode        Source encoding
@@ -254,13 +254,10 @@ void url(char *buf)
 
        int pos;
        int start, end;
-       char ench;
        char urlbuf[SIZ];
        char outbuf[1024];
-
        start = (-1);
        end = strlen(buf);
-       ench = 0;
 
        for (pos = 0; pos < strlen(buf); ++pos) {
                if (!strncasecmp(&buf[pos], "http://", 7))
@@ -272,18 +269,24 @@ void url(char *buf)
        if (start < 0)
                return;
 
-       if ((start > 0) && (buf[start - 1] == '<'))
-               ench = '>';
-       if ((start > 0) && (buf[start - 1] == '['))
-               ench = ']';
-       if ((start > 0) && (buf[start - 1] == '('))
-               ench = ')';
-       if ((start > 0) && (buf[start - 1] == '{'))
-               ench = '}';
-
        for (pos = strlen(buf); pos > start; --pos) {
-               if ((buf[pos] == ' ') || (buf[pos] == ench))
+               if (  (!isprint(buf[pos]))
+                  || (isspace(buf[pos]))
+                  || (buf[pos] == '{')
+                  || (buf[pos] == '}')
+                  || (buf[pos] == '|')
+                  || (buf[pos] == '\\')
+                  || (buf[pos] == '^')
+                  || (buf[pos] == '[')
+                  || (buf[pos] == ']')
+                  || (buf[pos] == '`')
+                  || (buf[pos] == '<')
+                  || (buf[pos] == '>')
+                  || (buf[pos] == '(')
+                  || (buf[pos] == ')')
+               ) {
                        end = pos;
+               }
        }
 
        strncpy(urlbuf, &buf[start], end - start);
@@ -631,6 +634,12 @@ void display_vcard(char *vcard_source, char alpha, int full, char *storename) {
 }
 
 
+struct attach_link {
+       char partnum[32];
+       char html[1024];
+};
+
+
 /**
  * \brief I wanna SEE that message!  
  * \param msgnum the citadel number of the message to display
@@ -640,12 +649,14 @@ void display_vcard(char *vcard_source, char alpha, int full, char *storename) {
 void read_message(long msgnum, int printable_view, char *section) {
        char buf[SIZ];
        char mime_partnum[256];
+       char mime_name[256];
        char mime_filename[256];
        char mime_content_type[256];
        char mime_charset[256];
        char mime_disposition[256];
        int mime_length;
-       char mime_http[SIZ];
+       struct attach_link *attach_links = NULL;
+       int num_attach_links = 0;
        char mime_submessages[256];
        char m_subject[256];
        char m_cc[1024];
@@ -662,6 +673,7 @@ void read_message(long msgnum, int printable_view, char *section) {
        char vcard_partnum[256];
        char cal_partnum[256];
        char *part_source = NULL;
+       char msg4_partnum[32];
 #ifdef HAVE_ICONV
        iconv_t ic = (iconv_t)(-1) ;
        char *ibuf;                /**< Buffer of characters to be converted */
@@ -678,7 +690,6 @@ void read_message(long msgnum, int printable_view, char *section) {
        strcpy(reply_all, "");
        strcpy(vcard_partnum, "");
        strcpy(cal_partnum, "");
-       strcpy(mime_http, "");
        strcpy(mime_content_type, "text/plain");
        strcpy(mime_charset, "us-ascii");
        strcpy(mime_submessages, "");
@@ -711,7 +722,7 @@ void read_message(long msgnum, int printable_view, char *section) {
                if (!strcmp(buf, "000")) {
                        wprintf("<i>");
                        wprintf(_("unexpected end of message"));
-                       wprintf("</i><br /><br />\n");
+                       wprintf(" (1)</i><br /><br />\n");
                        wprintf("</span>\n");
                        return;
                }
@@ -790,12 +801,19 @@ void read_message(long msgnum, int printable_view, char *section) {
                }
 
                if (!strncasecmp(buf, "part=", 5)) {
+                       extract_token(mime_name, &buf[5], 0, '|', sizeof mime_filename);
                        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);
 
+                       striplt(mime_name);
+                       striplt(mime_filename);
+                       if ( (strlen(mime_filename) == 0) && (strlen(mime_name) > 0) ) {
+                               strcpy(mime_filename, mime_name);
+                       }
+
                        if (!strcasecmp(mime_content_type, "message/rfc822")) {
                                if (strlen(mime_submessages) > 0) {
                                        strcat(mime_submessages, "|");
@@ -804,15 +822,24 @@ void read_message(long msgnum, int printable_view, char *section) {
                        }
                        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),
+                               ++num_attach_links;
+                               attach_links = realloc(attach_links,
+                                       (num_attach_links*sizeof(struct attach_link)));
+                               safestrncpy(attach_links[num_attach_links-1].partnum, mime_partnum, 32);
+                               snprintf(attach_links[num_attach_links-1].html, 1024,
                                        "<img src=\"mimepart/%ld/%s/%s\">",
                                        msgnum, mime_partnum, mime_filename);
                        }
-                       else if ( (!strcasecmp(mime_disposition, "attachment")) 
-                            || (!strcasecmp(mime_disposition, "inline")) ) {
-                               snprintf(&mime_http[strlen(mime_http)],
-                                       (sizeof(mime_http) - strlen(mime_http) - 1),
+                       else if ( ( (!strcasecmp(mime_disposition, "attachment")) 
+                            || (!strcasecmp(mime_disposition, "inline"))
+                            || (!strcasecmp(mime_disposition, ""))
+                            ) && (strlen(mime_content_type) > 0)
+                       ) {
+                               ++num_attach_links;
+                               attach_links = realloc(attach_links,
+                                       (num_attach_links*sizeof(struct attach_link)));
+                               safestrncpy(attach_links[num_attach_links-1].partnum, mime_partnum, 32);
+                               snprintf(attach_links[num_attach_links-1].html, 1024,
                                        "<img src=\"static/diskette_24x.gif\" "
                                        "border=0 align=middle>\n"
                                        "%s (%s, %d bytes) [ "
@@ -832,7 +859,8 @@ void read_message(long msgnum, int printable_view, char *section) {
                        }
 
                        /** begin handler prep ***/
-                       if (!strcasecmp(mime_content_type, "text/x-vcard")) {
+                       if (  (!strcasecmp(mime_content_type, "text/x-vcard"))
+                          || (!strcasecmp(mime_content_type, "text/vcard")) ) {
                                strcpy(vcard_partnum, mime_partnum);
                        }
 
@@ -848,7 +876,12 @@ void read_message(long msgnum, int printable_view, char *section) {
 
        /** Generate a reply-to address */
        if (strlen(rfca) > 0) {
-               strcpy(reply_to, rfca);
+               if (strlen(from) > 0) {
+                       snprintf(reply_to, sizeof(reply_to), "%s <%s>", from, rfca);
+               }
+               else {
+                       strcpy(reply_to, rfca);
+               }
        }
        else {
                if ( (strlen(node) > 0)
@@ -950,7 +983,7 @@ void read_message(long msgnum, int printable_view, char *section) {
                }
 
                /** 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) ) {
+               if ( (WC->is_room_aide) || (WC->is_mailbox) || (WC->room_flags2 & QR2_COLLABDEL) ) {
                        /** Move */
                        wprintf("<a href=\"confirm_move_msg?msgid=%ld\">[%s]</a> ",
                                msgnum, _("Move"));
@@ -988,12 +1021,16 @@ void read_message(long msgnum, int printable_view, char *section) {
                if (!strcmp(buf, "000")) {
                        wprintf("<i>");
                        wprintf(_("unexpected end of message"));
-                       wprintf("</i><br /><br />\n");
+                       wprintf(" (2)</i><br /><br />\n");
                        goto ENDBODY;
                }
-               if (!strncasecmp(buf, "Content-type: ", 14)) {
-                       safestrncpy(mime_content_type, &buf[14],
-                               sizeof(mime_content_type));
+               if (!strncasecmp(buf, "X-Citadel-MSG4-Partnum:", 23)) {
+                       safestrncpy(msg4_partnum, &buf[23], sizeof(msg4_partnum));
+                       striplt(msg4_partnum);
+               }
+               if (!strncasecmp(buf, "Content-type:", 13)) {
+                       safestrncpy(mime_content_type, &buf[13], sizeof(mime_content_type));
+                       striplt(mime_content_type);
                        for (i=0; i<strlen(mime_content_type); ++i) {
                                if (!strncasecmp(&mime_content_type[i], "charset=", 8)) {
                                        safestrncpy(mime_charset, &mime_content_type[i+8],
@@ -1098,8 +1135,12 @@ void read_message(long msgnum, int printable_view, char *section) {
 
 
        /** Afterwards, offer links to download attachments 'n' such */
-       if ( (strlen(mime_http) > 0) && (!section[0]) ) {
-               wprintf("%s", mime_http);
+       if ( (num_attach_links > 0) && (!section[0]) ) {
+               for (i=0; i<num_attach_links; ++i) {
+                       if (strcasecmp(attach_links[i].partnum, msg4_partnum)) {
+                               wprintf("%s", attach_links[i].html);
+                       }
+               }
        }
 
        /** Handler for vCard parts */
@@ -1146,6 +1187,10 @@ ENDBODY:
                wprintf("</div><br />\n");
        }
 
+       if (num_attach_links > 0) {
+               free(attach_links);
+       }
+
 #ifdef HAVE_ICONV
        if (ic != (iconv_t)(-1) ) {
                iconv_close(ic);
@@ -1234,7 +1279,7 @@ void display_headers(char *msgnum_as_string) {
 
 /**
  * \brief Read message in simple, JavaScript-embeddable form for 'forward'
- *        or 'reply quoted' operations.
+ *     or 'reply quoted' operations.
  *
  * NOTE: it is VITALLY IMPORTANT that we output no single-quotes or linebreaks
  *       in this function.  Doing so would throw a JavaScript error in the
@@ -1293,7 +1338,7 @@ void pullquote_message(long msgnum, int forward_attachments, int include_headers
 
        while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) {
                if (!strcmp(buf, "000")) {
-                       wprintf(_("unexpected end of message"));
+                       wprintf("%s (3)", _("unexpected end of message"));
                        return;
                }
                if (include_headers) {
@@ -1396,7 +1441,7 @@ void pullquote_message(long msgnum, int forward_attachments, int include_headers
        strcpy(mime_content_type, "text/plain");
        while (serv_getln(buf, sizeof buf), (strlen(buf) > 0)) {
                if (!strcmp(buf, "000")) {
-                       wprintf(_("unexpected end of message"));
+                       wprintf("%s (4)", _("unexpected end of message"));
                        goto ENDBODY;
                }
                if (!strncasecmp(buf, "Content-type: ", 14)) {
@@ -1620,7 +1665,8 @@ void display_addressbook(long msgnum, char alpha) {
                        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")) {
+                       if (  (!strcasecmp(mime_content_type, "text/x-vcard"))
+                          || (!strcasecmp(mime_content_type, "text/vcard")) ) {
                                strcpy(vcard_partnum, mime_partnum);
                        }
 
@@ -1697,7 +1743,7 @@ void fetch_ab_name(long msgnum, char *namebuf) {
        memset(&summ, 0, sizeof(summ));
        safestrncpy(summ.subj, "(no subject)", sizeof summ.subj);
 
-       sprintf(buf, "MSG0 %ld|1", msgnum);     /** ask for headers only */
+       sprintf(buf, "MSG0 %ld|0", msgnum);     /** unfortunately we need the mime info now */
        serv_puts(buf);
        serv_getln(buf, sizeof buf);
        if (buf[0] != '1') return;
@@ -1710,7 +1756,8 @@ void fetch_ab_name(long msgnum, char *namebuf) {
                        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")) {
+                       if (  (!strcasecmp(mime_content_type, "text/x-vcard"))
+                          || (!strcasecmp(mime_content_type, "text/vcard")) ) {
                                strcpy(vcard_partnum, mime_partnum);
                        }
 
@@ -2591,7 +2638,7 @@ void post_mime_to_server(void) {
        }
 
        if (is_multipart) {
-               sprintf(boundary, "=_Citadel_Multipart_%s_%04x%04x",
+               sprintf(boundary, "Citadel--Multipart--%s--%04x--%04x",
                        serv_info.serv_fqdn,
                        getpid(),
                        ++seq
@@ -2667,6 +2714,7 @@ void post_message(void)
 
        if (WC->upload_length > 0) {
 
+               lprintf(9, "%s:%d: we are uploading %d bytes\n", __FILE__, __LINE__, WC->upload_length);
                /** There's an attachment.  Save it to this struct... */
                att = malloc(sizeof(struct wc_attachment));
                memset(att, 0, sizeof(struct wc_attachment));
@@ -2720,14 +2768,15 @@ void post_message(void)
                        "saved this message."));
        } else {
                rfc2047encode(encoded_subject, sizeof encoded_subject, bstr("subject"));
-               sprintf(buf, "ENT0 1|%s|%d|4|%s|%s||%s|%s|%s",
+               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("wikipage"),
+                       bstr("my_email_addr")
                );
                serv_puts(buf);
                serv_getln(buf, sizeof buf);
@@ -2744,6 +2793,7 @@ void post_message(void)
                        }
                        dont_post = atol(bstr("postseq"));
                } else {
+                       lprintf(9, "%s:%d: server post error: %s\n", __FILE__, __LINE__, buf);
                        sprintf(WC->ImportantMessage, "%s", &buf[4]);
                        display_enter();
                        return;
@@ -2903,6 +2953,8 @@ void display_enter(void)
 
        wprintf(_(" <I>from</I> "));
 
+       /* Allow the user to select any of his valid screen names */
+
        wprintf("<select name=\"display_name\" size=1>\n");
 
        serv_puts("GVSN");
@@ -2928,6 +2980,25 @@ void display_enter(void)
 
        wprintf("</select>\n");
 
+       /* If this is an email (not a post), allow the user to select any of his
+        * valid email addresses.
+        */
+       if (recipient_required) {
+               serv_puts("GVEA");
+               serv_getln(buf, sizeof buf);
+               if (buf[0] == '1') {
+                       wprintf("<select name=\"my_email_addr\" size=1>\n");
+                       while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
+                               wprintf("<option value=\"");
+                               escputs(buf);
+                               wprintf("\">&lt;");
+                               escputs(buf);
+                               wprintf("&gt;</option>\n");
+                       }
+                       wprintf("</select>\n");
+               }
+       }
+
        wprintf(_(" <I>in</I> "));
        escputs(WC->wc_roomname);
        wprintf("<br>\n");      /** header bar */
@@ -2944,6 +3015,15 @@ void display_enter(void)
                escputs(bstr("recp"));
                wprintf("\" size=50 maxlength=1000 />");
                wprintf("<div class=\"auto_complete\" id=\"recp_name_choices\"></div>");
+
+               /** Pop open an address book -- begin **/
+               wprintf(
+                       "&nbsp;<a href=\"javascript:PopOpenAddressBook('recp_id');\" title=\"%s\">"
+                       "<img align=middle border=0 width=16 height=16 src=\"static/viewcontacts_16x.gif\">"
+                       "</a>", _("Contacts")
+               );
+               /** Pop open an address book -- end **/
+
                wprintf("</td><td></td></tr>\n");
 
                wprintf("<tr><td>");
@@ -2955,6 +3035,15 @@ void display_enter(void)
                escputs(bstr("cc"));
                wprintf("\" size=50 maxlength=1000 />");
                wprintf("<div class=\"auto_complete\" id=\"cc_name_choices\"></div>");
+
+               /** Pop open an address book -- begin **/
+               wprintf(
+                       "&nbsp;<a href=\"javascript:PopOpenAddressBook('cc_id');\" title=\"%s\">"
+                       "<img align=middle border=0 width=16 height=16 src=\"static/viewcontacts_16x.gif\">"
+                       "</a>", _("Contacts")
+               );
+               /** Pop open an address book -- end **/
+
                wprintf("</td><td></td></tr>\n");
 
                wprintf("<tr><td>");
@@ -2966,6 +3055,14 @@ void display_enter(void)
                escputs(bstr("bcc"));
                wprintf("\" size=50 maxlength=1000 />");
                wprintf("<div class=\"auto_complete\" id=\"bcc_name_choices\"></div>");
+
+               /** Pop open an address book -- begin **/
+               wprintf(
+                       "&nbsp;<a href=\"javascript:PopOpenAddressBook('bcc_id');\" title=\"%s\">"
+                       "<img align=middle border=0 width=16 height=16 src=\"static/viewcontacts_16x.gif\">"
+                       "</a>", _("Contacts")
+               );
+               /** Pop open an address book -- end **/
                wprintf("</td><td></td></tr>\n");
 
                /** Initialize the autocomplete ajax helpers (found in wclib.js) */
@@ -2977,7 +3074,12 @@ void display_enter(void)
 
        wprintf("<tr><td>");
        wprintf("<font size=-1>");
-       wprintf(_("Subject (optional):"));
+       if (recipient_required) {
+               wprintf(_("Subject:"));
+       }
+       else {
+               wprintf(_("Subject (optional):"));
+       }
        wprintf("</font>");
        wprintf("</td><td>"
                "<input type=\"text\" name=\"subject\" value=\"");
@@ -3121,11 +3223,11 @@ void display_enter(void)
        }
 
        wprintf("</form>\n");
-
        wprintf("</td></tr></table></div>\n");
-DONE:  wDumpContent(1);
-}
 
+DONE:  address_book_popup();
+       wDumpContent(1);
+}
 
 
 /**