[patch] content encoding etc.
Hatuka*nezumi - IKEDA Soji <[email protected]> Wed, 5 May 2004 15:48:03 +0900
| Newsgroups | gmane.mail.sqwebmail |
|---|---|
| Message-ID | <[email protected]> |
This is a patch against sqwebmail-4.0.3.
Enhancements:
rfc2045/rfc2045.h
rfc2045/rfc2045charsetinfo.c (new file)
rfc2045/rfc2045encode.c
rfc2045/makemime.c
sqwebmail/autoresponse.c
sqwebmail/newmsg.c
sqwebmail/newmsg_create.c
sqwebmail/pcp.c
o On some charsets, base64 header/body encoding is preferred.
o Some languages (charsets) are not suitable for RFC2646 flowed
format.
rfc822/rfc2047.c
o Supports base64 header encoding.
Fixes:
cgi/cgi.c (cgiurldecode)
o 0xA0 may occur as normal octet of some charsets (e.g. UTF-8).
[from Ichikawa's patch]
rfc2045/rfc2045reply.c (mkreply)
o Supply charset of reply content. [from Ichikawa's patch]
sqwebmail/newmsg.c
o Convert charset of draft message to content charset so that
content charset (language) may be changed over sessions.
NOTE:
* Please update rfc2045/Makefile.in
--- nezumi
sqwebmail-4.0.3-te-20040505.patch
(application/octet-stream, 27 KB)
? mkpatch.sh
? sqwebmail-000-4.0.3-japanese-20040502.patch
? sqwebmail-4.0.3-te-20040505.patch
? rfc2045/rfc2045charsetinfo.c
? sqwebmail/html/en-us/OUTGOING_CHARSETS
Index: sqwebmail-4.0.3/cgi/cgi.c
===================================================================
RCS file: /cvsroot/courier/libs/cgi/cgi.c,v
retrieving revision 1.27
diff -u -r1.27 cgi.c
--- sqwebmail-4.0.3/cgi/cgi.c 22 Sep 2003 21:44:40 -0000 1.27
+++ sqwebmail-4.0.3/cgi/cgi.c 5 May 2004 06:08:53 -0000
@@ -362,9 +362,6 @@
q=nybble(q, &c);
q=nybble(q, &c);
- if ((char)c == (char)0xA0) c=' ';
- /* See above */
-
if (c && c != '\r')
/* Ignore CRs we get in TEXTAREAS */
*p++=c;
Index: sqwebmail-4.0.3/rfc2045/Makefile.am
===================================================================
RCS file: /cvsroot/courier/libs/rfc2045/Makefile.am,v
retrieving revision 1.28
diff -u -r1.28 Makefile.am
--- sqwebmail-4.0.3/rfc2045/Makefile.am 15 Nov 2003 18:38:33 -0000 1.28
+++ sqwebmail-4.0.3/rfc2045/Makefile.am 5 May 2004 06:08:53 -0000
@@ -26,6 +26,7 @@
rfc2045searchcontenttype.c rfc2045decodemimesection.c \
rfc2045decodemimesectionu.c rfc2045header.c \
rfc2045replyplain.c rfc2045replyunicode.c rfc2045reply.c \
+ rfc2045charsetinfo.c \
rfc2231.c rfc2231encode.c \
rfc2646.h rfc2646.c rfc2646create.c rfc2646fwd.c \
rfc2646reply.c rfc2646rewrap.c \
Index: sqwebmail-4.0.3/rfc2045/makemime.c
===================================================================
RCS file: /cvsroot/courier/libs/rfc2045/makemime.c,v
retrieving revision 1.11
diff -u -r1.11 makemime.c
--- sqwebmail-4.0.3/rfc2045/makemime.c 7 Mar 2003 00:47:30 -0000 1.11
+++ sqwebmail-4.0.3/rfc2045/makemime.c 5 May 2004 06:08:53 -0000
@@ -652,7 +652,8 @@
goodexit(m, 1);
}
- m->mimeencoding=rfc2045_encode_autodetect_fp(m->inputfp1, 1);
+ m->mimeencoding=rfc2045_encode_autodetect_fppos(m->inputfp1,
+ m->textplaincharset, 0, -1);
if (ferror(m->inputfp1)
|| fseek(m->inputfp1, orig_pos, SEEK_SET)<0)
Index: sqwebmail-4.0.3/rfc2045/rfc2045.h
===================================================================
RCS file: /cvsroot/courier/libs/rfc2045/rfc2045.h,v
retrieving revision 1.29
diff -u -r1.29 rfc2045.h
--- sqwebmail-4.0.3/rfc2045/rfc2045.h 7 Mar 2003 01:49:32 -0000 1.29
+++ sqwebmail-4.0.3/rfc2045/rfc2045.h 5 May 2004 06:08:54 -0000
@@ -151,6 +151,8 @@
};
const char *rfc2045_encode_autodetect_fp(FILE *, int okQp);
+const char *rfc2045_encode_autodetect_fppos(FILE *, const char *, off_t, off_t);
+const char *rfc2045_encode_autodetect_str(const char *, const char *);
void rfc2045_encode_start(struct rfc2045_encode_info *info,
const char *transfer_encoding,
@@ -451,6 +453,19 @@
int *langLen,
int *textLen);
+#define RFC2045_NOENC 0
+#define RFC2045_QP 1
+#define RFC2045_B64 2
+
+struct rfc2045_charset_info {
+ char *charset; /* charset name */
+ int header_enc; /* encoding method for message headers */
+ int body_enc; /* encoding method for message body */
+ int word_wrap; /* word wrap capability */
+};
+
+struct rfc2045_charset_info rfc2045_unknown_charset;
+struct rfc2045_charset_info *rfc2045_find_charset_info (const char *);
#ifdef __cplusplus
}
Index: sqwebmail-4.0.3/rfc2045/rfc2045encode.c
===================================================================
RCS file: /cvsroot/courier/libs/rfc2045/Attic/rfc2045encode.c,v
retrieving revision 1.3
diff -u -r1.3 rfc2045encode.c
--- sqwebmail-4.0.3/rfc2045/rfc2045encode.c 5 Mar 2003 02:35:55 -0000 1.3
+++ sqwebmail-4.0.3/rfc2045/rfc2045encode.c 5 May 2004 06:08:54 -0000
@@ -18,33 +18,101 @@
const char *rfc2045_encode_autodetect_fp(FILE *fp, int okQp)
{
+ if (okQp)
+ return rfc2045_encode_autodetect_fppos(fp, "ISO-8859-1", 0, -1);
+ else
+ return rfc2045_encode_autodetect_fppos(fp, "US-ASCII", 0, -1);
+}
+
+const char *rfc2045_encode_autodetect_fppos(FILE *fp, const char *charset,
+ off_t start_pos, off_t end_pos)
+{
const char *encoding="7bit";
int l=0;
- int longline=0;
int c;
+ off_t orig_pos, pos=0;
+ const struct rfc2045_charset_info *ci =
+ rfc2045_find_charset_info(charset);
+
+ orig_pos = ftell(fp);
+ if (start_pos >= 0)
+ if ((pos=fseek(fp, start_pos, SEEK_SET)) == (off_t)-1)
+ return NULL;
- while ((c=getc(fp)) != EOF)
+ while ((c=getc(fp)) != EOF && (pos++ < end_pos || end_pos < 0))
{
unsigned char ch= (unsigned char)c;
if (ch >= 0x80)
- encoding="8bit";
+ {
+ if (ci->body_enc == RFC2045_QP)
+ encoding="quoted-printable";
+ else if (ci->body_enc == RFC2045_B64)
+ encoding="base64";
+ else
+ encoding="8bit";
+ }
if (ch == 0)
+ {
+ if ((pos=fseek(fp, orig_pos, SEEK_SET)) == (off_t)-1)
+ return NULL;
return "base64";
+ }
if (ch == '\n') l=0;
else if (++l > 990)
{
- longline=1;
- if (!okQp)
+ if ((pos=fseek(fp, orig_pos, SEEK_SET)) == (off_t)-1)
+ return NULL;
+ if (ci->body_enc == RFC2045_QP)
+ return "quoted-printable";
+ else
return "base64";
}
}
- if (longline && okQp)
- encoding="quoted-printable";
+ if ((pos=fseek(fp, orig_pos, SEEK_SET)) == (off_t)-1)
+ return NULL;
+ return encoding;
+}
+
+const char *rfc2045_encode_autodetect_str(const char *str, const char *charset)
+{
+ const char *encoding="7bit";
+ int l=0;
+ int c;
+ const struct rfc2045_charset_info *ci =
+ rfc2045_find_charset_info(charset);
+
+ while ((c = *str++))
+ {
+ unsigned char ch= (unsigned char)c;
+
+ if (ch >= 0x80)
+ {
+ if (ci->body_enc == RFC2045_QP)
+ encoding="quoted-printable";
+ else if (ci->body_enc == RFC2045_B64)
+ encoding="base64";
+ else
+ encoding="8bit";
+ }
+
+ if (ch == 0)
+ return "base64";
+
+ if (ch == '\n') l=0;
+ else if (++l > 990)
+ {
+ if (ci->body_enc == RFC2045_QP)
+ return "quoted-printable";
+ else
+ return "base64";
+ }
+
+ }
return encoding;
}
Index: sqwebmail-4.0.3/rfc2045/rfc2045reply.c
===================================================================
RCS file: /cvsroot/courier/libs/rfc2045/rfc2045reply.c,v
retrieving revision 1.10
diff -u -r1.10 rfc2045reply.c
--- sqwebmail-4.0.3/rfc2045/rfc2045reply.c 20 Jun 2003 20:49:48 -0000 1.10
+++ sqwebmail-4.0.3/rfc2045/rfc2045reply.c 5 May 2004 06:08:54 -0000
@@ -829,8 +829,11 @@
if (s) free(s);
free(subject);
}
-
- writes(ri, "\n\n");
+ writes(ri, "\n");
+ writes(ri, "Content-Type: text/plain; charset=\"");
+ writes(ri, ri->charset);
+ writes(ri, "\"\n");
+ writes(ri, "\n");
if (whowrote)
{
writes(ri, whowrote);
Index: sqwebmail-4.0.3/rfc822/rfc2047.c
===================================================================
RCS file: /cvsroot/courier/libs/rfc822/rfc2047.c,v
retrieving revision 1.12
diff -u -r1.12 rfc2047.c
--- sqwebmail-4.0.3/rfc822/rfc2047.c 21 Mar 2003 04:43:39 -0000 1.12
+++ sqwebmail-4.0.3/rfc822/rfc2047.c 5 May 2004 06:08:54 -0000
@@ -11,6 +11,7 @@
#include "rfc822.h"
#include "rfc2047.h"
+#include "../rfc2045/rfc2045.h"
static const char rcsid[]="$Id: rfc2047.c,v 1.12 2003/03/21 04:43:39 mrsam Exp $";
@@ -424,13 +425,81 @@
while (*c) save(*c++, p);
}
+static char *encode64tab =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
int rfc2047_encode_callback(const char *str, const char *charset,
int (*func)(const char *, size_t, void *), void *arg)
{
int rc;
+struct rfc2045_charset_info *ci = rfc2045_find_charset_info(charset);
+const char *ptr;
+unsigned char ibuf[3], obuf[4], bbuf[76+1];
+
+#define ISSPACE(i) (i=='\t' || i=='\r' || i=='\n' || i==' ')
+#define DOENCODE(i) ((str[i] & 0x80) || str[i] == '"' || str[i] == '=' || \
+ (str[i] < 0x20 && !ISSPACE(str[i])))
+
+ if (ci->header_enc == RFC2045_NOENC)
+ return (*func)(str, strlen(str), arg);
+
+ if (ci->header_enc == RFC2045_B64)
+ {
+ size_t i;
+ for (i=0; str[i]; i++)
+ if (DOENCODE(i))
+ break;
+ if (str[i] == 0)
+ return i? (*func)(str, strlen(str), arg): 0;
-#define DOENCODE(i) ((str[i] & 0x80) || str[i] == '"' || str[i] == '=')
-#define ISSPACE(i) ( ((i) & 0x80) == 0 && isspace(i))
+ i = 0;
+ ptr = str;
+ while (*ptr)
+ {
+ if (i == 0)
+ {
+ if ((rc=(*func)("=?", 2, arg)) ||
+ (rc=(*func)(charset,strlen(charset),arg))||
+ (rc=(*func)("?b?", 3, arg)))
+ return rc;
+ i = 2 + strlen(charset) + 3;
+ *bbuf = 0;
+ }
+
+ strncpy(ibuf, ptr, 3);
+ if (ibuf[1] == 0) ibuf[2] = 0;
+ ptr += strlen(ptr) >= 3? 3: strlen(ptr);
+
+ obuf[0] = encode64tab[ ibuf[0] >>2 ];
+ obuf[1] = encode64tab[(ibuf[0] & 0x03)<<4|ibuf[1]>>4];
+ obuf[2] = encode64tab[(ibuf[1] & 0x0F)<<2|ibuf[2]>>6];
+ obuf[3] = encode64tab[ ibuf[2] & 0x3F ];
+ if (!ibuf[1] && !ibuf[2])
+ obuf[2] = '=';
+ if (!ibuf[2])
+ obuf[3] = '=';
+ strncat(bbuf, obuf, 4);
+ i += 4;
+ if (i > 76 - 1 - 4 - 2)
+ {
+ if ((rc = (*func)(bbuf, strlen(bbuf), arg)) ||
+ (rc=(*func)("?=", 2, arg)))
+ return rc;
+ if (*ptr)
+ if ((rc=(*func)(" ", 1, arg)))
+ return rc;
+ i = 0;
+ }
+ }
+ if (i)
+ {
+
+ if ((rc=(*func)(bbuf, strlen(bbuf), arg)) ||
+ (rc=(*func)("?=", 2, arg)))
+ return rc;
+ }
+ return 0;
+ }
while (*str)
{
@@ -501,12 +570,12 @@
if ( (rc=(*func)("=?", 2, arg)) != 0 ||
(rc=(*func)(charset, strlen(charset),
arg)) != 0 ||
- (rc=(*func)("?Q?", 3, arg)) != 0)
+ (rc=(*func)("?q?", 3, arg)) != 0)
return (rc);
c += strlen(charset)+5;
}
- if ((*str & 0x80) || *str == '"' || *str == ' ' ||
+ if ((*str & 0x80) || *str == '"' || *str <= 0x20 ||
*str == '_' || *str == '=' || *str == '?')
{
char buf[3];
@@ -527,7 +596,7 @@
size_t j;
for (j=0; j < i && !(str[j] & 0x80) &&
- str[j] != ' ' &&
+ str[j] > 0x20 &&
str[j] != '_' &&
str[j] != '?' &&
str[j] != '=' &&
Index: sqwebmail-4.0.3/sqwebmail/autoresponse.c
===================================================================
RCS file: /cvsroot/courier/courier/webmail/autoresponse.c,v
retrieving revision 1.15
diff -u -r1.15 autoresponse.c
--- sqwebmail-4.0.3/sqwebmail/autoresponse.c 17 Jun 2003 15:38:37 -0000 1.15
+++ sqwebmail-4.0.3/sqwebmail/autoresponse.c 5 May 2004 06:08:55 -0000
@@ -67,6 +67,9 @@
void autoresponse()
{
+struct rfc2045_charset_info *ci=
+ rfc2045_find_charset_info(sqwebmail_content_charset);
+
if ( *cgi("do.newautoresp"))
{
const char *name=cgi("newname");
@@ -96,8 +99,9 @@
printf("\" /><br /><br />\n");
free(p);
- printf("<textarea style=\"font-family: courier;\" cols=\"75\" rows=\"10\" "
- "name=\"text\" wrap=\"soft\">");
+ printf("<textarea style=\"font-family: courier;\" cols=\"75\""
+ "rows=\"10\" name=\"text\" wrap=\"%s\">",
+ ci->word_wrap? "soft": "hard");
printf("</textarea><br />\n");
printf("%s<input type=\"file\" size=\"20\" name=\"uploadfile\" /><br />",
getarg("UPLOAD"));
@@ -158,8 +162,9 @@
printf("\" /><br /><br />\n");
free(s);
- printf("<textarea style=\"font-family: courier;\" cols=\"75\" rows=\"10\" "
- "name=\"text\" wrap=\"soft\">");
+ printf("<textarea style=\"font-family: courier;\" cols=\"75\""
+ " rows=\"10\" name=\"text\" wrap=\"%s\">",
+ ci->word_wrap? "soft": "hard");
if (pp && *pp)
output_attrencoded(pp);
@@ -254,13 +259,16 @@
const char *autorespname=cgi("autoresponse");
const char *autoresptxt=cgi("text");
FILE *fp;
- struct rfc2646create *create_ptr;
+ struct rfc2646create *create_ptr=NULL;
size_t l;
+ struct rfc2045_charset_info *ci=
+ rfc2045_find_charset_info(sqwebmail_content_charset);
if ((fp=upload_attachment(autorespname)) == NULL)
{
+ if (ci->word_wrap)
if ((create_ptr=
- rfc2646create_alloc(&save_autoresponse, &fp))
+ rfc2646create_alloc(&save_autoresponse, &fp))
== NULL ||
(fp=maildir_autoresponse_create(NULL,
autorespname))
@@ -277,14 +285,22 @@
autoresptxt[l-1] == '\n'))
--l;
- fprintf(fp, "Content-Type: text/plain; format=flowed; "
- "charset=\"%s\"\n"
- "Content-Transfer-Encoding: 8bit\n\n",
+ fprintf(fp, "Content-Type: text/plain");
+ fprintf(fp, "; charset=\"%s\"",
sqwebmail_content_charset);
+ if (ci->word_wrap)
+ fprintf(fp, "; format=flowed");
+ fprintf(fp, "\n");
+ fprintf(fp, "Content-Transfer-Encoding: 8bit\n\n");
- rfc2646create_parse(create_ptr, autoresptxt, l);
- rfc2646create_parse(create_ptr, "\n\n", 2);
- rfc2646create_free(create_ptr);
+ if (ci->word_wrap)
+ {
+ rfc2646create_parse(create_ptr, autoresptxt, l);
+ rfc2646create_parse(create_ptr, "\n\n", 2);
+ rfc2646create_free(create_ptr);
+ }
+ else
+ save_autoresponse(autoresptxt, l, &fp);
}
if (fflush(fp) || ferror(fp))
@@ -293,7 +309,8 @@
printf(getarg("SAVEFAILED"), strerror(errno));
return;
}
- if (maildir_autoresponse_create_finish(NULL, autorespname, fp))
+ if (!ci->word_wrap ||
+ maildir_autoresponse_create_finish(NULL, autorespname, fp))
{
if (errno == ENOSPC)
{
Index: sqwebmail-4.0.3/sqwebmail/newmsg.c
===================================================================
RCS file: /cvsroot/courier/courier/webmail/newmsg.c,v
retrieving revision 1.52
diff -u -r1.52 newmsg.c
--- sqwebmail-4.0.3/sqwebmail/newmsg.c 5 Apr 2004 22:47:48 -0000 1.52
+++ sqwebmail-4.0.3/sqwebmail/newmsg.c 5 May 2004 06:08:56 -0000
@@ -42,6 +42,9 @@
#endif
#include <errno.h>
#include "htmllibdir.h"
+#if HAVE_SQWEBMAIL_UNICODE
+#include "unicode/unicode.h"
+#endif
extern const char *sqwebmail_content_charset;
extern int spell_start(const char *);
@@ -65,6 +68,9 @@
static void newmsg_header(const char *label, const char *field, const char *val)
{
+#if HAVE_SQWEBMAIL_UNICODE
+const struct unicode_info *uiptr=unicode_find(sqwebmail_content_charset);
+#endif
printf("<tr><th align=\"right\"><p class=\"new-message-header\">"
"<span class=\"new-message-header-%s\">%s</span></p></th>"
"<td width=\"6\"> </td>",
@@ -76,7 +82,11 @@
{
char *s;
+#if HAVE_SQWEBMAIL_UNICODE
+ s=rfc2047_decode_unicode(val, uiptr, 0);
+#else
s=rfc2047_decode_simple(val);
+#endif
if (!s) enomem();
output_attrencoded(s);
free(s);
@@ -304,8 +314,14 @@
q=rfc2045_searchcontenttype(p, "text/plain");
if (q)
+#if HAVE_SQWEBMAIL_UNICODE
+ rfc2045_decodetextmimesection(fileno(fp), q,
+ sqwebmail_content_charset,
+ &show_textarea, NULL);
+#else
rfc2045_decodemimesection(fileno(fp), q,
&show_textarea, NULL);
+#endif
rfc2045_free(p);
}
@@ -352,6 +368,8 @@
FILE *fp;
int attachcnt=0;
char *cursubj, *curto, *curcc, *curbcc, *curfrom, *curreplyto;
+ struct rfc2045_charset_info *ci=
+ rfc2045_find_charset_info(sqwebmail_content_charset);
/* Picking up an existing draft? */
@@ -544,8 +562,8 @@
"<span class=\"new-message-header-message\">"
"%s</span></p></th><td width=\"6\"> </td>", messagelab);
- printf("<td><textarea name=\"message\" cols=\"%d\" rows=\"15\" wrap=\"soft\">",
- MYLINESIZE);
+ printf("<td><textarea name=\"message\" cols=\"%d\" rows=\"15\" "
+ "wrap=\"%s\">", MYLINESIZE, ci->word_wrap? "soft": "hard");
if (fp)
{
Index: sqwebmail-4.0.3/sqwebmail/newmsg_create.c
===================================================================
RCS file: /cvsroot/courier/courier/webmail/newmsg_create.c,v
retrieving revision 1.51
diff -u -r1.51 newmsg_create.c
--- sqwebmail-4.0.3/sqwebmail/newmsg_create.c 5 Apr 2004 22:47:48 -0000 1.51
+++ sqwebmail-4.0.3/sqwebmail/newmsg_create.c 5 May 2004 06:08:56 -0000
@@ -513,7 +513,7 @@
/* Create message in the sent folder */
static void sentmsg_copy(FILE *, struct rfc2045 *);
-static void sentmsg_reformat(FILE *, struct rfc2045 *, int);
+static void sentmsg_reformat(FILE *, struct rfc2045 *, int, int, const char *);
extern void header_uc(char *h);
@@ -658,6 +658,8 @@
#if 0
off_t transferencodingpos;
#endif
+struct rfc2045_charset_info *ci=NULL;
+const char *transfer_encoding=NULL;
*isgpgerr=0;
@@ -692,8 +694,8 @@
fclose(fp);
enomem();
}
- /* First, copy all headers except X- headers */
+ /* First, copy all headers except X- headers */
while ((header=maildir_readheader(fp, &value, 1)) != 0)
{
if (strncmp(header, "x-", 2) == 0) continue;
@@ -719,15 +721,58 @@
if (strcasecmp(header, "Content-Type") == 0 &&
!rfcp->firstpart) /* Need to punt this header */
{
+ const char *content_type;
+ const char *content_transfer_encoding;
+ const char *charset;
+ off_t end_pos, start_body, dummy;
+ rfc2045_mimeinfo(rfcp, &content_type,
+ &content_transfer_encoding, &charset);
+ if (charset && *charset)
+ {
+ rfc2045_mimepos(rfcp, &dummy,
+ &end_pos, &start_body,
+ &dummy, &dummy);
+ ci = rfc2045_find_charset_info(charset);
+ transfer_encoding =
+ rfc2045_encode_autodetect_fppos(fp,
+ charset, start_body,
+ end_pos);
+ }
+ else
+ {
+ ci = &rfc2045_unknown_charset;
+ transfer_encoding = NULL;
+ }
maildir_writemsgstr(newdraftfd,
- "Content-Type: text/plain;"
- " format=flowed; charset=\"");
- maildir_writemsgstr(newdraftfd,
- sqwebmail_content_charset);
- maildir_writemsgstr(newdraftfd, "\"\n");
+ "Content-Type: text/plain");
+ if (charset && *charset)
+ {
+ maildir_writemsgstr(newdraftfd,
+ "; charset=\"");
+ maildir_writemsgstr(newdraftfd,
+ charset);
+ maildir_writemsgstr(newdraftfd, "\"");
+ }
+ if (ci->word_wrap)
+ maildir_writemsgstr(newdraftfd,
+ "; format=flowed");
+ maildir_writemsgstr(newdraftfd, "\n");
+
+ if (transfer_encoding)
+ {
+ maildir_writemsgstr(newdraftfd,
+ "Content-Transfer-Encoding: ");
+ maildir_writemsgstr(newdraftfd,
+ transfer_encoding);
+ maildir_writemsgstr(newdraftfd, "\n");
+ }
continue;
}
+ if (strcasecmp(header, "Content-Transfer-Encoding") == 0 &&
+ !rfcp->firstpart) /* Need to regenerate this header */
+ continue;
+
maildir_writemsgstr(newdraftfd, header);
maildir_writemsgstr(newdraftfd, ": ");
maildir_writemsgstr(newdraftfd, value);
@@ -749,7 +794,8 @@
maildir_writemsgstr(newdraftfd, "\n");
if (!rfcp->firstpart)
- sentmsg_reformat(fp, rfcp, footer);
+ sentmsg_reformat(fp, rfcp, footer, ci->word_wrap,
+ transfer_encoding);
else
{
int found_textplain=0;
@@ -760,6 +806,7 @@
const char *content_type;
const char *content_transfer_encoding;
const char *charset;
+ off_t end_pos, start_body, dummy;
rfc2045_mimeinfo(p, &content_type,
&content_transfer_encoding, &charset);
@@ -767,17 +814,50 @@
if (strcmp(content_type, "text/plain") == 0 &&
!p->isdummy && !found_textplain)
{
+ if (charset && *charset)
+ {
+ rfc2045_mimepos(p, &dummy,
+ &end_pos, &start_body,
+ &dummy, &dummy);
+ ci = rfc2045_find_charset_info(charset);
+ transfer_encoding =
+ rfc2045_encode_autodetect_fppos(fp,
+ charset, start_body,
+ end_pos);
+ }
+ else
+ {
+ ci = &rfc2045_unknown_charset;
+ transfer_encoding = NULL;
+ }
+
maildir_writemsgstr(newdraftfd,
- "Content-Type: text/plain;"
- " format=flowed;"
- " charset=");
- maildir_writemsgstr(newdraftfd, charset);
- maildir_writemsgstr(newdraftfd,
- "\nContent-Transfer-Encoding: ");
- maildir_writemsgstr(newdraftfd,
- content_transfer_encoding);
- maildir_writemsgstr(newdraftfd, "\n\n");
- sentmsg_reformat(fp, p, footer);
+ "Content-Type: text/plain");
+ if (charset && *charset)
+ {
+ maildir_writemsgstr(newdraftfd,
+ "; charset=\"");
+ maildir_writemsgstr(newdraftfd,
+ charset);
+ maildir_writemsgstr(newdraftfd, "\"");
+ }
+ if (ci->word_wrap)
+ maildir_writemsgstr(newdraftfd,
+ "; format=flowed");
+ maildir_writemsgstr(newdraftfd, "\n");
+
+ if (transfer_encoding)
+ {
+ maildir_writemsgstr(newdraftfd,
+ "Content-Transfer-Encoding: ");
+ maildir_writemsgstr(newdraftfd,
+ transfer_encoding);
+ maildir_writemsgstr(newdraftfd, "\n");
+ }
+ maildir_writemsgstr(newdraftfd, "\n");
+
+ sentmsg_reformat(fp, p, footer, ci->word_wrap,
+ transfer_encoding);
found_textplain=1;
}
else sentmsg_copy(fp, p);
@@ -948,14 +1028,23 @@
return (0);
}
-static void sentmsg_reformat(FILE *f, struct rfc2045 *p, int do_footer)
+static int write_to_draft_encode(const char *p, size_t l, void *arg)
+{
+ rfc2045_encode((struct rfc2047_encode_info *)arg, p, l);
+ return (0);
+}
+
+static void sentmsg_reformat(FILE *f, struct rfc2045 *p, int do_footer,
+ int do_flowed,
+ const char *transfer_encoding)
{
off_t start_pos, end_pos, start_body;
char buf[BUFSIZ];
int n;
off_t dummy;
FILE *fp;
- struct rfc2646create *createptr;
+ struct rfc2045_encode_info encode_info;
+ struct rfc2646create *createptr=NULL;
rfc2045_mimepos(p, &start_pos, &end_pos, &start_body,
&dummy, &dummy);
@@ -966,17 +1055,22 @@
enomem();
}
- createptr=rfc2646create_alloc( &write_to_draft, NULL);
- if (!createptr)
+ rfc2045_encode_start(&encode_info, transfer_encoding, &write_to_draft,
+ NULL);
+
+ if (do_flowed &&
+ !(createptr=rfc2646create_alloc( &write_to_draft_encode,
+ &encode_info)))
{
fclose(f);
close(newdraftfd);
enomem();
}
- while (start_body < end_pos)
- {
- int cnt=sizeof(buf);
+ if (do_flowed)
+ while (start_body < end_pos)
+ {
+ int cnt=sizeof(buf);
if (cnt > end_pos - start_body)
cnt=end_pos - start_body;
@@ -989,8 +1083,26 @@
close(newdraftfd);
enomem();
}
+ else
+ rfc2045_encode(&encode_info, buf, n);
start_body += n;
- }
+ }
+ else
+ while (start_body < end_pos)
+ {
+ int cnt=sizeof(buf);
+
+ if (cnt > end_pos - start_body)
+ cnt=end_pos - start_body;
+ if ((n=fread(buf, 1, cnt, f)) <= 0)
+ {
+ fclose(f);
+ close(newdraftfd);
+ enomem();
+ }
+ rfc2045_encode(&encode_info, buf, strlen(buf));
+ start_body += n;
+ }
if (do_footer)
{
@@ -1001,18 +1113,22 @@
if (fp != 0)
{
while ((n=fread(buf, 1, sizeof(buf), fp)) > 0)
- rfc2646create_parse(createptr, buf, n);
+ if (do_flowed)
+ rfc2646create_parse(createptr, buf, n);
+ else
+ rfc2045_encode(&encode_info, buf, n);
fclose(fp);
}
}
- if (rfc2646create_free(createptr))
+ if (do_flowed && rfc2646create_free(createptr))
{
fclose(f);
close(newdraftfd);
enomem();
}
+ rfc2045_encode_end(&encode_info);
}
/* ---------------------------------------------------------------------- */
Index: sqwebmail-4.0.3/sqwebmail/pcp.c
===================================================================
RCS file: /cvsroot/courier/courier/webmail/pcp.c,v
retrieving revision 1.24
diff -u -r1.24 pcp.c
--- sqwebmail-4.0.3/sqwebmail/pcp.c 8 Feb 2004 04:37:08 -0000 1.24
+++ sqwebmail-4.0.3/sqwebmail/pcp.c 5 May 2004 06:08:58 -0000
@@ -19,6 +19,7 @@
#include "rfc822/rfc822.h"
#include "rfc822/rfc822hdr.h"
#include "rfc822/rfc2047.h"
+#include "rfc2045/rfc2045.h"
#include "maildir/maildircreate.h"
#include "maildir/maildirmisc.h"
#include "maildir/maildirquota.h"
@@ -1054,10 +1055,12 @@
void sqpcp_eventtext()
{
+ struct rfc2045_charset_info *ci=
+ rfc2045_find_charset_info(sqwebmail_content_charset);
const char *p;
- printf("<textarea name=\"message\" cols=\"%d\" rows=\"15\" wrap=\"soft\">",
- MYLINESIZE);
+ printf("<textarea name=\"message\" cols=\"%d\" rows=\"15\""
+ " wrap=\"%s\">", MYLINESIZE, ci->word_wrap? "soft": "hard");
p=cgi("draftmessage");
if (p && *p)
Index: sqwebmail-4.0.3/rfc2045/rfc2045charsetinfo.c
===================================================================
--- /dev/null 2003-01-30 19:24:37.000000000 +0900
+++ sqwebmail-4.0.3/rfc2045/rfc2045charsetinfo.c 2004-05-05 12:12:00.000000000 +0900
@@ -0,0 +1,88 @@
+#include "rfc2045.h"
+
+struct rfc2045_charset_info rfc2045_charsets[] = {
+ /* charset name header enc. body enc. word wrap */
+ { "US-ASCII", RFC2045_NOENC, RFC2045_NOENC, 0 },
+ { "ISO-8859-1", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-2", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-3", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-4", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-5", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-6", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-6-E", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-6-I", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-7", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-8", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-8-E", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-8-I", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-9", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-10", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-11", RFC2045_B64, RFC2045_B64, 0 },
+ { "ISO-8859-13", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-14", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-15", RFC2045_QP, RFC2045_QP, 1 },
+ { "ISO-8859-16", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-874", RFC2045_B64, RFC2045_B64, 0 },
+ { "WINDOWS-1250", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1251", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1252", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1253", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1254", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1255", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1256", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1257", RFC2045_QP, RFC2045_QP, 1 },
+ { "WINDOWS-1258", RFC2045_QP, RFC2045_QP, 1 },
+ { "KOI8-R", RFC2045_B64, RFC2045_B64, 1 },
+ { "KOI8-U", RFC2045_B64, RFC2045_B64, 1 },
+ { "KOI8-RU", RFC2045_B64, RFC2045_B64, 1 },
+ { "TIS-620", RFC2045_B64, RFC2045_B64, 0 },
+ { "GB2312", RFC2045_B64, RFC2045_B64, 0 },
+ { "EUC-JP", RFC2045_B64, RFC2045_B64, 0 },
+ { "EUC-JISX0213", RFC2045_B64, RFC2045_B64, 0 },
+ { "EUC-KR", RFC2045_B64, RFC2045_B64, 0 },
+ { "EUC-TW", RFC2045_B64, RFC2045_B64, 0 },
+ { "ISO-2022-CN", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "ISO-2022-CN-EXT", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "ISO-2022-JP", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "ISO-2022-JP-1", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "ISO-2022-JP-2", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "ISO-2022-JP-3", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "ISO-2022-KR", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "GBK", RFC2045_B64, RFC2045_B64, 0 },
+ { "GB18030", RFC2045_B64, RFC2045_B64, 0 },
+ { "BIG5", RFC2045_B64, RFC2045_B64, 0 },
+ { "BIG5-HKSCS", RFC2045_B64, RFC2045_B64, 0 },
+ { "SHIFT_JIS", RFC2045_B64, RFC2045_B64, 0 },
+ { "SHIFT_JISX0213", RFC2045_B64, RFC2045_B64, 0 },
+ { "KS_C_5601-1987", RFC2045_B64, RFC2045_B64, 0 },
+ { "KS_C_5601-1992", RFC2045_B64, RFC2045_B64, 0 },
+ { "VISCII", RFC2045_QP, RFC2045_QP, 1 },
+ { "HZ-GB-2312", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "UTF-7", RFC2045_B64, RFC2045_NOENC, 0 },
+ { "UTF-8", RFC2045_B64, RFC2045_B64, 0 },
+ { NULL /* default */, RFC2045_B64, RFC2045_B64, 0 }
+};
+
+struct rfc2045_charset_info rfc2045_unknown_charset =
+ { NULL, RFC2045_NOENC, RFC2045_NOENC, 0 };
+
+struct rfc2045_charset_info rfc2045_binary =
+ { NULL, RFC2045_B64, RFC2045_B64, 0 };
+
+struct rfc2045_charset_info *rfc2045_find_charset_info(const char *charset)
+{
+struct rfc2045_charset_info *p = rfc2045_charsets;
+
+ if (!charset || !*charset)
+ return &rfc2045_binary;
+
+ while (p->charset)
+ {
+ if (strcasecmp(charset, p->charset) == 0)
+ return p;
+ p++;
+ }
+
+ return &rfc2045_binary;
+}
+