* Built an initial version of the "forward message" function. It works
authorArt Cancro <ajc@citadel.org>
Mon, 12 Sep 2005 04:08:05 +0000 (04:08 +0000)
committerArt Cancro <ajc@citadel.org>
Mon, 12 Sep 2005 04:08:05 +0000 (04:08 +0000)
  perfectly on the message text now, but we cannot consider it finished
  until it also forwards attachments.

webcit/ChangeLog
webcit/auth.c
webcit/messages.c
webcit/paging.c
webcit/roomops.c
webcit/serv_func.c
webcit/subst.c
webcit/userlist.c
webcit/webcit.h

index 7e417e8639d34114198219a098a3faee7557bca3..31b23c822fa5abdcdd75eb9711eb9d7f5494db60 100644 (file)
@@ -1,4 +1,9 @@
 $Log$
+Revision 621.38  2005/09/12 04:08:05  ajc
+* Built an initial version of the "forward message" function.  It works
+  perfectly on the message text now, but we cannot consider it finished
+  until it also forwards attachments.
+
 Revision 621.37  2005/09/10 03:23:05  ajc
 * Determined where to insert a "Forward" button and the functionality it
   implements.  In order to complete this function we will need a
@@ -2934,3 +2939,4 @@ Sun Dec  6 19:50:55 EST 1998 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
 
 1998-12-03 Nathan Bryant <bryant@cs.usm.maine.edu>
        * webserver.c: warning fix
+
index c86e276b094ee576b59660fa11f6e480ff553e07..075e1da9cb78a41f3c27eef415a8d2b2232712eb 100644 (file)
@@ -229,7 +229,7 @@ void do_logout(void)
 
        if (WC->serv_sock >= 0) {
                if (buf[0] == '1') {
-                       fmout(NULL, "CENTER");
+                       fmout("CENTER");
                } else {
                        wprintf("Goodbye\n");
                }
@@ -406,7 +406,7 @@ void display_changepw(void)
        serv_puts("MESG changepw");
        serv_getln(buf, sizeof buf);
        if (buf[0] == '1') {
-               fmout(NULL, "CENTER");
+               fmout("CENTER");
        }
 
        wprintf("<form name=\"changepwform\" action=\"changepw\" method=\"post\">\n");
index 7edd0323930ce2de6f352af45d44eb018032b4fe..b60e72b0c2dc411e4677a0ddcf2b5db8841d0cda 100644 (file)
@@ -566,7 +566,7 @@ void read_message(long msgnum, int suppress_buttons) {
                    && (strcasecmp(&buf[5], WC->wc_roomname))
                    && (strlen(&buf[5])>0) ) {
                        wprintf(_("in "));
-                       wprintf("%s> ", &buf[5]);
+                       wprintf("%s&gt; ", &buf[5]);
                }
                if (!strncasecmp(buf, "rfca=", 5)) {
                        strcpy(rfca, &buf[5]);
@@ -685,14 +685,13 @@ void read_message(long msgnum, int suppress_buttons) {
                urlescputs(m_subject);
                wprintf("\">[%s]</a> ", _("Reply"));
 
-               /* Forward  (FIXME uncomment when this is done)
+               /* Forward */
                if (WC->wc_view == VIEW_MAILBOX) {
                        wprintf("<a href=\"/display_enter?pullquote=%ld?subject=", msgnum);
                        if (strncasecmp(m_subject, "Fwd:", 4)) wprintf("Fwd:%20");
                        urlescputs(m_subject);
                        wprintf("\">[%s]</a> ", _("Forward"));
                }
-               */
 
                if (WC->is_room_aide)  {
                        /* Move */
@@ -759,11 +758,12 @@ void read_message(long msgnum, int suppress_buttons) {
 
        /* Messages in legacy Citadel variformat get handled thusly... */
        if (!strcasecmp(mime_content_type, "text/x-citadel-variformat")) {
-               fmout(NULL, "JUSTIFY");
+               fmout("JUSTIFY");
        }
 
        /* Boring old 80-column fixed format text gets handled this way... */
-       else if (!strcasecmp(mime_content_type, "text/plain")) {
+       else if ( (!strcasecmp(mime_content_type, "text/plain"))
+               || (!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;
@@ -932,6 +932,263 @@ void embed_message(void) {
 
 
 
+/*
+ * Read message in simple, JavaScript-embeddable form for 'forward'
+ * 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
+ *       'supplied text' argument to the editor.
+ */
+void pullquote_message(long msgnum) {
+       char buf[SIZ];
+       char mime_partnum[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];
+       char m_subject[256];
+       char from[256];
+       char node[256];
+       char rfca[256];
+       char reply_to[512];
+       char now[256];
+       int format_type = 0;
+       int nhdr = 0;
+       int bq = 0;
+       int i = 0;
+       char vcard_partnum[256];
+       char cal_partnum[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       */
+#endif
+
+       strcpy(from, "");
+       strcpy(node, "");
+       strcpy(rfca, "");
+       strcpy(reply_to, "");
+       strcpy(vcard_partnum, "");
+       strcpy(cal_partnum, "");
+       strcpy(mime_http, "");
+       strcpy(mime_content_type, "text/plain");
+       strcpy(mime_charset, "us-ascii");
+
+       serv_printf("MSG4 %ld", msgnum);
+       serv_getln(buf, sizeof buf);
+       if (buf[0] != '1') {
+               wprintf(_("ERROR:"));
+               wprintf("%s<br />", &buf[4]);
+               return;
+       }
+
+       strcpy(m_subject, "");
+
+       while (serv_getln(buf, sizeof buf), strcasecmp(buf, "text")) {
+               if (!strcmp(buf, "000")) {
+                       wprintf(_("unexpected end of message"));
+                       return;
+               }
+               if (!strncasecmp(buf, "nhdr=yes", 8))
+                       nhdr = 1;
+               if (nhdr == 1)
+                       buf[0] = '_';
+               if (!strncasecmp(buf, "type=", 5))
+                       format_type = atoi(&buf[5]);
+               if (!strncasecmp(buf, "from=", 5)) {
+                       strcpy(from, &buf[5]);
+                       wprintf(_("from "));
+#ifdef HAVE_ICONV
+                       utf8ify_rfc822_string(from);
+#endif
+                       escputs(from);
+               }
+               if (!strncasecmp(buf, "subj=", 5)) {
+                       strcpy(m_subject, &buf[5]);
+               }
+               if ((!strncasecmp(buf, "hnod=", 5))
+                   && (strcasecmp(&buf[5], serv_info.serv_humannode))) {
+                       wprintf("(%s) ", &buf[5]);
+               }
+               if ((!strncasecmp(buf, "room=", 5))
+                   && (strcasecmp(&buf[5], WC->wc_roomname))
+                   && (strlen(&buf[5])>0) ) {
+                       wprintf(_("in "));
+                       wprintf("%s&gt; ", &buf[5]);
+               }
+               if (!strncasecmp(buf, "rfca=", 5)) {
+                       strcpy(rfca, &buf[5]);
+                       wprintf("&lt;");
+                       escputs(rfca);
+                       wprintf("&gt; ");
+               }
+
+               if (!strncasecmp(buf, "node=", 5)) {
+                       strcpy(node, &buf[5]);
+                       if ( ((WC->room_flags & QR_NETWORK)
+                       || ((strcasecmp(&buf[5], serv_info.serv_nodename)
+                       && (strcasecmp(&buf[5], serv_info.serv_fqdn)))))
+                       && (strlen(rfca)==0)
+                       ) {
+                               wprintf("@%s ", &buf[5]);
+                       }
+               }
+               if (!strncasecmp(buf, "rcpt=", 5)) {
+                       wprintf(_("to "));
+                       wprintf("%s ", &buf[5]);
+               }
+               if (!strncasecmp(buf, "time=", 5)) {
+                       fmt_date(now, atol(&buf[5]), 0);
+                       wprintf("%s ", now);
+               }
+
+               if (!strncasecmp(buf, "part=", 5)) {
+                       /*
+                        * FIXME
+                        *
+                        * We must forward the attachments.  This is to be done
+                        * by downloading each attachment of the original
+                        * message and inserting it into the new message's
+                        * attachment chain.
+                        */
+               }
+
+       }
+
+       wprintf("<br>");
+
+#ifdef HAVE_ICONV
+       utf8ify_rfc822_string(m_subject);
+#endif
+       if (strlen(m_subject) > 0) {
+               wprintf(_("Subject:"));
+               wprintf(" %s<br />", m_subject);
+       }
+
+       /*
+        * Begin body
+        */
+       wprintf("<br>");
+
+       /* 
+        * Learn the content type
+        */
+       strcpy(mime_content_type, "text/plain");
+       while (serv_getln(buf, sizeof buf), (strlen(buf) > 0)) {
+               if (!strcmp(buf, "000")) {
+                       wprintf(_("unexpected end of message"));
+                       goto ENDBODY;
+               }
+               if (!strncasecmp(buf, "Content-type: ", 14)) {
+                       safestrncpy(mime_content_type, &buf[14],
+                               sizeof(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],
+                                               sizeof mime_charset);
+                               }
+                       }
+                       for (i=0; i<strlen(mime_content_type); ++i) {
+                               if (mime_content_type[i] == ';') {
+                                       mime_content_type[i] = 0;
+                               }
+                       }
+               }
+       }
+
+       /* 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")) ) {
+               ic = iconv_open("UTF-8", mime_charset);
+               if (ic == (iconv_t)(-1) ) {
+                       lprintf(5, "iconv_open() failed: %s\n", strerror(errno));
+               }
+       }
+#endif
+
+       /* Messages in legacy Citadel variformat get handled thusly... */
+       if (!strcasecmp(mime_content_type, "text/x-citadel-variformat")) {
+               pullquote_fmout();
+       }
+
+       /* Boring old 80-column fixed format text gets handled this way... */
+       else if (!strcasecmp(mime_content_type, "text/plain")) {
+               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;
+
+#ifdef HAVE_ICONV
+                       if (ic != (iconv_t)(-1) ) {
+                               ibuf = buf;
+                               ibuflen = strlen(ibuf);
+                               obuflen = SIZ;
+                               obuf = (char *) malloc(obuflen);
+                               osav = obuf;
+                               iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
+                               osav[SIZ-obuflen] = 0;
+                               safestrncpy(buf, osav, sizeof buf);
+                               free(osav);
+                       }
+#endif
+
+                       while ((strlen(buf) > 0) && (isspace(buf[strlen(buf) - 1])))
+                               buf[strlen(buf) - 1] = 0;
+                       if ((bq == 0) &&
+                       ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
+                               wprintf("<BLOCKQUOTE>");
+                               bq = 1;
+                       } else if ((bq == 1) &&
+                               (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) && (strncmp(buf, " :-)", 4))) {
+                               wprintf("</BLOCKQUOTE>");
+                               bq = 0;
+                       }
+                       wprintf("<TT>");
+                       url(buf);
+                       escputs(buf);
+                       wprintf("</TT><br />");
+               }
+               wprintf("</I><br />");
+       }
+
+       /* HTML just gets escaped and stuffed back into the editor */
+       else if (!strcasecmp(mime_content_type, "text/html")) {
+               while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
+                       msgescputs(buf);
+               }
+       }
+
+       /* Unknown weirdness ... don't know how to handle this content type */
+       else {
+               while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { }
+       }
+
+       if (part_source) {
+               free(part_source);
+               part_source = NULL;
+       }
+
+ENDBODY:
+       /* end of body handler */
+#ifdef HAVE_ICONV
+       if (ic != (iconv_t)(-1) ) {
+               iconv_close(ic);
+       }
+#endif
+}
+
+
+
+
+
+
 void display_summarized(int num) {
        char datebuf[64];
 
@@ -2135,7 +2392,8 @@ void display_enter(void)
                "writeRichText('msgtext', '");
        msgescputs(bstr("msgtext"));
        if (atol(bstr("pullquote")) > 0L) {
-               wprintf("FIXME pullquote=%s", bstr("pullquote"));
+               wprintf("<br><div align=center><i>--- original message ---</i></div><br>");
+               pullquote_message(atol(bstr("pullquote")));
        }
        wprintf("', '96%%', '200', true, false); \n"
                "</script></center><br />\n");
index 8b66a6eabba29f6cdd56110f41aa35839f23e527..c244070b2d5217b09d22248852f12309b817f71e 100644 (file)
@@ -162,7 +162,7 @@ void page_popup(void)
                wprintf(_("Instant message from "));
                escputs(pagefrom);
                wprintf("</span></td></tr><tr><td><font color=\"#FFFFFF\">");
-               fmout(NULL, "LEFT");
+               fmout("LEFT");
                wprintf("</font></td></tr>"
                        "<tr><td><div align=center><font color=\"#FFFFFF\">"
                        "<a href=\"javascript:hide_page_popup()\">");
index f0190ab5d82efb761675223738909b7e7373ca65..fbcbb75920d8529e47116c138f6376d09c55c4ec 100644 (file)
@@ -230,7 +230,7 @@ void readinfo(void)
        serv_puts("RINF");
        serv_getln(buf, sizeof buf);
        if (buf[0] == '1') {
-               fmout(NULL, "CENTER");
+               fmout("CENTER");
        }
 }
 
@@ -1945,7 +1945,7 @@ void display_entroom(void)
        serv_printf("MESG roomaccess");
        serv_getln(buf, sizeof buf);
        if (buf[0] == '1') {
-               fmout(NULL, "CENTER");
+               fmout("CENTER");
        }
        wprintf("</td></tr></table></div>\n");
        wDumpContent(1);
index 3eb0375eb105ddbbc89caa157cd2c8202cdef21d..2fc570fe4367fe54a31d240e3ade6a55e7fc4206 100644 (file)
@@ -89,32 +89,17 @@ void get_serv_info(char *browser_host, char *user_agent)
 
 
 /* 
- * Function to spit out Citadel variformat text in HTML
- * If fp is non-null, it is considered to be the file handle to read the
- * text from.  Otherwise, text is read from the server.
+ * Read Citadel variformat text and spit it out as HTML.
  */
-void fmout(FILE *fp, char *align)
+void fmout(char *align)
 {
-
        int intext = 0;
        int bq = 0;
        char buf[SIZ];
 
        wprintf("<div align=%s>\n", align);
-       while (1) {
-               if (fp == NULL)
-                       serv_getln(buf, sizeof buf);
-               if (fp != NULL) {
-                       if (fgets(buf, SIZ, fp) == NULL)
-                               safestrncpy(buf, "000", sizeof buf);
-                       buf[strlen(buf) - 1] = 0;
-               }
-               if (!strcmp(buf, "000")) {
-                       if (bq == 1)
-                               wprintf("</I>");
-                       wprintf("</div><br />\n");
-                       return;
-               }
+       while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
+
                if ((intext == 1) && (isspace(buf[0]))) {
                        wprintf("<br />");
                }
@@ -140,6 +125,52 @@ void fmout(FILE *fp, char *align)
                escputs(buf);
                wprintf("\n");
        }
+       if (bq == 1) {
+               wprintf("</I>");
+       }
+       wprintf("</div><br />\n");
+}
+
+
+
+
+/* 
+ * Read Citadel variformat text and spit it out as HTML in a form
+ * suitable for embedding in another message (forward/quote).
+ * (NO LINEBREAKS ALLOWED HERE!)
+ */
+void pullquote_fmout(void) {
+       int intext = 0;
+       int bq = 0;
+       char buf[SIZ];
+
+       while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
+
+               if ((intext == 1) && (isspace(buf[0]))) {
+                       wprintf("<br />");
+               }
+               intext = 1;
+
+               /* Quoted text should be displayed in italics and in a
+                * different colour.  This code understands Citadel-style
+                * " >" quotes and will convert to <BLOCKQUOTE> tags.
+                */
+               if ((bq == 0) && (!strncmp(buf, " >", 2))) {
+                       wprintf("<BLOCKQUOTE>");
+                       bq = 1;
+               } else if ((bq == 1) && (strncmp(buf, " >", 2))) {
+                       wprintf("</BLOCKQUOTE>");
+                       bq = 0;
+               }
+               if ((bq == 1) && (!strncmp(buf, " >", 2))) {
+                       strcpy(buf, &buf[2]);
+               }
+
+               msgescputs(buf);
+       }
+       if (bq == 1) {
+               wprintf("</I>");
+       }
 }
 
 
index ac73e327ff3c2d2ee19ba6b476f4eb3276592ccd..60e96c633af169c23a6eb2934a380c310baf3ba2 100644 (file)
@@ -103,7 +103,7 @@ void pvo_do_cmd(char *servcmd) {
                        wprintf("%s\n", &buf[4]);
                        break;
                case '1':
-                       fmout(NULL, "CENTER");
+                       fmout("CENTER");
                        break;
                case '4':
                        wprintf("%s\n", &buf[4]);
index 1836e03c57040a7202e6b89b92568b3831c36164..788c6c93bad31e448bdf51b467218aadc569313c 100644 (file)
@@ -144,7 +144,7 @@ void showuser(void)
        serv_printf("RBIO %s", who);
        serv_getln(buf, sizeof buf);
        if (buf[0] == '1') {
-               fmout(NULL, "JUSTIFY");
+               fmout("JUSTIFY");
        }
        wprintf("<br /><A HREF=\"/display_page?recp=");
        urlescputs(who);
index afd341d59a55f0798e1c3042b33c6834c9e7f607..16d8378b6bcc476d762f617f09369f987ee1379f 100644 (file)
@@ -355,7 +355,8 @@ void serv_getln(char *strbuf, int bufsize);
 void serv_puts(char *string);
 void who(void);
 void who_inner_html(void);
-void fmout(FILE *fp, char *align);
+void fmout(char *align);
+void pullquote_fmout(void);
 void wDumpContent(int);
 void serv_printf(const char *format,...);
 char *bstr(char *key);