From: Wilfried Göesgens Date: Wed, 27 Feb 2008 00:18:36 +0000 (+0000) Subject: * sample aproach to use the citadel commandline client html renderer to create a... X-Git-Tag: v7.86~2460 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=7465c5bdbaeb6548db295ef8b5b8ffdd160f4edb * sample aproach to use the citadel commandline client html renderer to create a plaintext part for multipart alternative mails. this is considered to be more polite to text users. --- diff --git a/webcit/Makefile.in b/webcit/Makefile.in index 6b2a321b9..abb8efbb6 100644 --- a/webcit/Makefile.in +++ b/webcit/Makefile.in @@ -51,7 +51,7 @@ webserver: webserver.o context_loop.o ical_dezonify.o \ groupdav_main.o groupdav_get.o groupdav_propfind.o fmt_date.o \ groupdav_options.o autocompletion.o gettext.o tabs.o sieve.o \ groupdav_delete.o groupdav_put.o http_datestring.o setup_wizard.o \ - downloads.o addressbook_popup.o pushemail.o sysdep.o \ + downloads.o addressbook_popup.o pushemail.o sysdep.o html.o\ $(LIBOBJS) $(CC) webserver.o context_loop.o cookie_conversion.o \ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o listsub.o \ @@ -63,7 +63,7 @@ webserver: webserver.o context_loop.o ical_dezonify.o \ groupdav_main.o groupdav_get.o groupdav_propfind.o groupdav_delete.o \ groupdav_options.o autocompletion.o tabs.o smtpqueue.o sieve.o \ groupdav_put.o http_datestring.o setup_wizard.o fmt_date.o \ - gettext.o downloads.o addressbook_popup.o pushemail.o sysdep.o \ + gettext.o downloads.o addressbook_popup.o pushemail.o sysdep.o html.o \ $(LIBOBJS) $(LIBS) $(LDFLAGS) -o webserver .c.o: diff --git a/webcit/html.c b/webcit/html.c new file mode 100644 index 000000000..19cd38d89 --- /dev/null +++ b/webcit/html.c @@ -0,0 +1,551 @@ +/* + * $Id: html.c 6014 2008-02-04 18:38:35Z ajc $ + * + * Functions which handle translation between HTML and plain text + * Copyright (c) 2000-2005 by Art Cancro and others. This program is + * released under the terms of the GNU General Public License. + */ + +#include "sysdep.h" +#include +#include +#include +#include +#include + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include +#include +#include "citadel.h" +#include "server.h" +#include "control.h" +#include "sysdep_decls.h" +#include "support.h" +#include "config.h" +#include "msgbase.h" +#include "room_ops.h" +#include "html.h" + + +/* + * Convert HTML to plain text. + * + * inputmsg = pointer to raw HTML message + * screenwidth = desired output screenwidth + * do_citaformat = set to 1 to indent newlines with spaces + */ +char *html_to_ascii(char *inputmsg, int msglen, int screenwidth, int do_citaformat) { + char inbuf[SIZ]; + int inbuf_len = 0; + char outbuf[SIZ]; + char tag[1024]; + int done_reading = 0; + char *inptr; + char *outptr; + size_t outptr_buffer_size; + size_t output_len = 0; + int i, j, ch, did_out, rb, scanch; + int nest = 0; /* Bracket nesting level */ + int blockquote = 0; /* BLOCKQUOTE nesting level */ + int styletag = 0; /* STYLE tag nesting level */ + int styletag_start = 0; + int bytes_processed = 0; + char nl[128]; + + strcpy(nl, "\n"); + inptr = inputmsg; + strcpy(inbuf, ""); + strcpy(outbuf, ""); + if (msglen == 0) msglen = strlen(inputmsg); + + outptr_buffer_size = strlen(inptr) + SIZ; + outptr = malloc(outptr_buffer_size); + if (outptr == NULL) return NULL; + strcpy(outptr, ""); + output_len = 0; + + do { + /* Fill the input buffer */ + inbuf_len = strlen(inbuf); + if ( (done_reading == 0) && (inbuf_len < (SIZ-128)) ) { + + ch = *inptr++; + if (ch != 0) { + inbuf[inbuf_len++] = ch; + inbuf[inbuf_len] = 0; + } + else { + done_reading = 1; + } + + ++bytes_processed; + if (bytes_processed > msglen) { + done_reading = 1; + } + + } + + /* Do some parsing */ + if (!IsEmptyStr(inbuf)) { + + + /* Fold in all the spacing */ + for (i=0; !IsEmptyStr(&inbuf[i]); ++i) { + if (inbuf[i]==10) inbuf[i]=32; + if (inbuf[i]==13) inbuf[i]=32; + if (inbuf[i]==9) inbuf[i]=32; + /*** we like foreign characters now. + if ((inbuf[i]<32) || (inbuf[i]>126)) { + inbuf[i] = '?'; + } */ + } + for (i=0; !IsEmptyStr(&inbuf[i]); ++i) { + while ((inbuf[i]==32)&&(inbuf[i+1]==32)) + strcpy(&inbuf[i], &inbuf[i+1]); + } + + for (i=0; !IsEmptyStr(&inbuf[i]); ++i) { + + ch = inbuf[i]; + + if (ch == '<') { + ++nest; + strcpy(tag, ""); + } + + else if (ch == '>') { /* We have a tag. */ + if (nest > 0) --nest; + + /* Unqualify the tag (truncate at first space) */ + if (strchr(tag, ' ') != NULL) { + strcpy(strchr(tag, ' '), ""); + } + + if (!strcasecmp(tag, "P")) { + strcat(outbuf, nl); + strcat(outbuf, nl); + } + + if (!strcasecmp(tag, "/DIV")) { + strcat(outbuf, nl); + strcat(outbuf, nl); + } + + if (!strcasecmp(tag, "LI")) { + strcat(outbuf, nl); + strcat(outbuf, " * "); + } + + else if (!strcasecmp(tag, "/UL")) { + strcat(outbuf, nl); + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "H1")) { + strcat(outbuf, nl); + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "H2")) { + strcat(outbuf, nl); + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "H3")) { + strcat(outbuf, nl); + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "H4")) { + strcat(outbuf, nl); + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "/H1")) { + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "/H2")) { + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "/H3")) { + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "/H4")) { + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "HR")) { + strcat(outbuf, nl); + strcat(outbuf, " "); + for (j=0; j"); + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "/BLOCKQUOTE")) { + strcat(outbuf, "\n"); + --blockquote; + strcpy(nl, "\n"); + for (j=0; j"); + strcat(outbuf, nl); + } + + else if (!strcasecmp(tag, "STYLE")) { + ++styletag; + if (styletag == 1) { + styletag_start = strlen(outbuf); + } + } + + else if (!strcasecmp(tag, "/STYLE")) { + --styletag; + if (styletag == 0) { + outbuf[styletag_start] = 0; + } + } + + } + + else if ((nest > 0) && (strlen(tag)<(sizeof(tag)-1))) { + tag[strlen(tag)+1] = 0; + tag[strlen(tag)] = ch; + } + + else if (!nest) { + outbuf[strlen(outbuf)+1] = 0; + outbuf[strlen(outbuf)] = ch; + } + } + strcpy(inbuf, &inbuf[i]); + } + + /* Convert &; tags to the forbidden characters */ + if (!IsEmptyStr(outbuf)) for (i=0; !IsEmptyStr(&outbuf[i]); ++i) { + + /* Character entity references */ + if (!strncasecmp(&outbuf[i], " ", 6)) { + outbuf[i] = ' '; + strcpy(&outbuf[i+1], &outbuf[i+6]); + } + + if (!strncasecmp(&outbuf[i], " ", 6)) { + outbuf[i] = ' '; + strcpy(&outbuf[i+1], &outbuf[i+6]); + } + + if (!strncasecmp(&outbuf[i], " ", 6)) { + outbuf[i] = ' '; + strcpy(&outbuf[i+1], &outbuf[i+6]); + } + + if (!strncasecmp(&outbuf[i], " ", 8)) { + outbuf[i] = ' '; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "<", 4)) { + outbuf[i] = '<'; + strcpy(&outbuf[i+1], &outbuf[i+4]); + } + + else if (!strncasecmp(&outbuf[i], ">", 4)) { + outbuf[i] = '>'; + strcpy(&outbuf[i+1], &outbuf[i+4]); + } + + else if (!strncasecmp(&outbuf[i], "&", 5)) { + strcpy(&outbuf[i+1], &outbuf[i+5]); + } + + else if (!strncasecmp(&outbuf[i], """, 6)) { + outbuf[i] = '\"'; + strcpy(&outbuf[i+1], &outbuf[i+6]); + } + + else if (!strncasecmp(&outbuf[i], "‘", 7)) { + outbuf[i] = '`'; + strcpy(&outbuf[i+1], &outbuf[i+7]); + } + + else if (!strncasecmp(&outbuf[i], "’", 7)) { + outbuf[i] = '\''; + strcpy(&outbuf[i+1], &outbuf[i+7]); + } + + else if (!strncasecmp(&outbuf[i], "©", 6)) { + outbuf[i] = '('; + outbuf[i+1] = 'c'; + outbuf[i+2] = ')'; + strcpy(&outbuf[i+3], &outbuf[i+6]); + } + + else if (!strncasecmp(&outbuf[i], "•", 6)) { + outbuf[i] = ' '; + outbuf[i+1] = '*'; + outbuf[i+2] = ' '; + strcpy(&outbuf[i+3], &outbuf[i+6]); + } + + else if (!strncasecmp(&outbuf[i], "…", 8)) { + outbuf[i] = '.'; + outbuf[i+1] = '.'; + outbuf[i+2] = '.'; + strcpy(&outbuf[i+3], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "™", 7)) { + outbuf[i] = '('; + outbuf[i+1] = 't'; + outbuf[i+2] = 'm'; + outbuf[i+3] = ')'; + strcpy(&outbuf[i+4], &outbuf[i+7]); + } + + else if (!strncasecmp(&outbuf[i], "®", 5)) { + outbuf[i] = '('; + outbuf[i+1] = 'r'; + outbuf[i+2] = ')'; + strcpy(&outbuf[i+3], &outbuf[i+5]); + } + + else if (!strncasecmp(&outbuf[i], "¼", 8)) { + outbuf[i] = '1'; + outbuf[i+1] = '/'; + outbuf[i+2] = '4'; + strcpy(&outbuf[i+3], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "½", 8)) { + outbuf[i] = '1'; + outbuf[i+1] = '/'; + outbuf[i+2] = '2'; + strcpy(&outbuf[i+3], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "¾", 8)) { + outbuf[i] = '3'; + outbuf[i+1] = '/'; + outbuf[i+2] = '4'; + strcpy(&outbuf[i+3], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "–", 7)) { + outbuf[i] = '-'; + outbuf[i+1] = '-'; + strcpy(&outbuf[i+2], &outbuf[i+7]); + } + + else if (!strncasecmp(&outbuf[i], "—", 7)) { + outbuf[i] = '-'; + outbuf[i+1] = '-'; + outbuf[i+2] = '-'; + strcpy(&outbuf[i+3], &outbuf[i+7]); + } + + else if (!strncmp(&outbuf[i], "Ç", 8)) { + outbuf[i] = 'C'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "ç", 8)) { + outbuf[i] = 'c'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncmp(&outbuf[i], "È", 8)) { + outbuf[i] = 'E'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "è", 8)) { + outbuf[i] = 'e'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncmp(&outbuf[i], "Ê", 7)) { + outbuf[i] = 'E'; + strcpy(&outbuf[i+1], &outbuf[i+7]); + } + + else if (!strncasecmp(&outbuf[i], "ê", 7)) { + outbuf[i] = 'e'; + strcpy(&outbuf[i+1], &outbuf[i+7]); + } + + else if (!strncmp(&outbuf[i], "É", 8)) { + outbuf[i] = 'E'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "é", 8)) { + outbuf[i] = 'e'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncmp(&outbuf[i], "À", 8)) { + outbuf[i] = 'A'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "à", 8)) { + outbuf[i] = 'a'; + strcpy(&outbuf[i+1], &outbuf[i+8]); + } + + else if (!strncasecmp(&outbuf[i], "“", 7)) { + outbuf[i] = '\"'; + strcpy(&outbuf[i+1], &outbuf[i+7]); + } + + else if (!strncasecmp(&outbuf[i], "”", 7)) { + outbuf[i] = '\"'; + strcpy(&outbuf[i+1], &outbuf[i+7]); + } + + else if (!strncasecmp(&outbuf[i], "´", 7)) { + outbuf[i] = '\''; + strcpy(&outbuf[i+1], &outbuf[i+7]); + } + + /* two-digit decimal equivalents */ + else if ((!strncmp(&outbuf[i], "&#", 2)) + && (outbuf[i+4] == ';') ) { + scanch = 0; + sscanf(&outbuf[i+2], "%02d", &scanch); + outbuf[i] = scanch; + strcpy(&outbuf[i+1], &outbuf[i+5]); + } + + /* three-digit decimal equivalents */ + else if ((!strncmp(&outbuf[i], "&#", 2)) + && (outbuf[i+5] == ';') ) { + scanch = 0; + sscanf(&outbuf[i+2], "%03d", &scanch); + outbuf[i] = scanch; + strcpy(&outbuf[i+1], &outbuf[i+6]); + } + + } + + /* Make sure the output buffer is big enough */ + if ((output_len + strlen(outbuf) + SIZ) > outptr_buffer_size) { + outptr_buffer_size += SIZ; + outptr = realloc(outptr, outptr_buffer_size); + if (outptr == NULL) { + abort(); + } + } + + /* Output any lines terminated with hard line breaks */ + do { + did_out = 0; + if (strlen(outbuf) > 0) { + for (i = 0; i (screenwidth - 2 )) { + rb = (-1); + for (i=0; i<(screenwidth-2); ++i) { + if (outbuf[i]==32) rb = i; + } + if (rb>=0) { + strncpy(&outptr[output_len], outbuf, rb); + output_len += rb; + strcpy(&outptr[output_len], nl); + output_len += strlen(nl); + if (do_citaformat) { + strcpy(&outptr[output_len], " "); + ++output_len; + } + strcpy(outbuf, &outbuf[rb+1]); + } else { + strncpy(&outptr[output_len], outbuf, + screenwidth-2); + output_len += (screenwidth-2); + strcpy(&outptr[output_len], nl); + output_len += strlen(nl); + if (do_citaformat) { + strcpy(&outptr[output_len], " "); + ++output_len; + } + strcpy(outbuf, &outbuf[screenwidth-2]); + } + } + + } while (done_reading == 0); + + strcpy(&outptr[output_len], outbuf); + output_len += strlen(outbuf); + + /* Strip leading/trailing whitespace. We can't do this with + * striplt() because it uses too many strlen()'s + */ + while ((output_len > 0) && (isspace(outptr[0]))) { + strcpy(outptr, &outptr[1]); + --output_len; + } + while ((output_len > 0) && (isspace(outptr[output_len-1]))) { + outptr[output_len-1] = 0; + --output_len; + } + + if (outptr[output_len-1] != '\n') { + strcat(outptr, "\n"); + ++output_len; + } + + return outptr; + +} diff --git a/webcit/html.h b/webcit/html.h new file mode 100644 index 000000000..10f714d8e --- /dev/null +++ b/webcit/html.h @@ -0,0 +1,6 @@ +/* + * $Id: html.h 5148 2007-05-08 15:40:16Z ajc $ + * + */ + +char *html_to_ascii(char *inputmsg, int msglen, int screenwidth, int do_citaformat); diff --git a/webcit/messages.c b/webcit/messages.c index 76dd1ab0f..2bf9619c1 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -10,6 +10,7 @@ #include "webcit.h" #include "webserver.h" #include "groupdav.h" +#include "html.h" #define SUBJ_COL_WIDTH_PCT 50 /**< Mailbox view column width */ #define SENDER_COL_WIDTH_PCT 30 /**< Mailbox view column width */ @@ -2855,6 +2856,7 @@ void post_mime_to_server(void) { static int seq = 0; struct wc_attachment *att; char *encoded; + char *txtmail; size_t encoded_length; size_t encoded_strlen; @@ -2867,7 +2869,7 @@ void post_mime_to_server(void) { is_multipart = 1; } - if (is_multipart) { +// if (is_multipart) { sprintf(boundary, "Citadel--Multipart--%s--%04x--%04x", serv_info.serv_fqdn, getpid(), @@ -2875,11 +2877,15 @@ void post_mime_to_server(void) { ); /** Remember, serv_printf() appends an extra newline */ - serv_printf("Content-type: multipart/mixed; " - "boundary=\"%s\"\n", boundary); + if (is_multipart) + serv_printf("Content-type: multipart/mixed; " + "boundary=\"%s\"\n", boundary); + else + serv_printf("Content-type: multipart/alternative; " + "boundary=\"%s\"\n", boundary); serv_printf("This is a multipart message in MIME format.\n"); serv_printf("--%s", boundary); - } +// } serv_puts("Content-type: text/html; charset=utf-8"); serv_puts("Content-Transfer-Encoding: quoted-printable"); @@ -2887,6 +2893,16 @@ void post_mime_to_server(void) { serv_puts("\r\n"); text_to_server_qp(bstr("msgtext")); /** Transmit message in quoted-printable encoding */ serv_puts("\r\n"); + + serv_puts("Content-type: text/plain; charset=utf-8"); + serv_puts("Content-Transfer-Encoding: quoted-printable"); + serv_puts(""); + + txtmail = html_to_ascii(bstr("msgtext"), 0, 80, 0); + text_to_server_qp(txtmail); /** Transmit message in quoted-printable encoding */ + free(txtmail); + if (!is_multipart) + serv_printf("--%s", boundary); if (is_multipart) {