summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Varshavchik2018-07-21 10:43:40 -0400
committerSam Varshavchik2018-07-21 10:44:43 -0400
commit14179a773e02455620b8db480e5cde990301bdb1 (patch)
tree26f00c12281c8488e37fbfe07f4324f2e641f1eb
parentf7786ceaa39b846007a38495c169fbaa23a3f7d0 (diff)
downloadcourier-libs-14179a773e02455620b8db480e5cde990301bdb1.tar.bz2
courier-imap: implement UTF8 mode in the POP3 server.
-rw-r--r--imap/ChangeLog5
-rw-r--r--imap/Makefile.am6
-rw-r--r--imap/fetch.c4
-rw-r--r--imap/pop3dcapa.c9
-rw-r--r--imap/pop3dserver.c138
-rw-r--r--imap/pop3login.c13
6 files changed, 99 insertions, 76 deletions
diff --git a/imap/ChangeLog b/imap/ChangeLog
index ba51db1..4c10f8e 100644
--- a/imap/ChangeLog
+++ b/imap/ChangeLog
@@ -1,3 +1,8 @@
+2018-07-21 Sam Varshavchik <mrsam@courier-mta.com>
+
+ * pop3dserver.c: update Courier-IMAP to support UTF8 POP3. Update
+ version of the courierpop3dsizelist cache file.
+
2018-07-17 Sam Varshavchik <mrsam@courier-mta.com>
* courier-imap, sqwebmail: update Courier-IMAP to support UTF8 IMAP.
diff --git a/imap/Makefile.am b/imap/Makefile.am
index 7a7f4f5..7d8f5ff 100644
--- a/imap/Makefile.am
+++ b/imap/Makefile.am
@@ -85,14 +85,16 @@ pop3login_DEPENDENCIES=../tcpd/libspipe.la ../tcpd/libspipe.la libpop3d.la
pop3login_LDADD=../tcpd/libtlsclient.la ../tcpd/libspipe.la libpop3d.la ../tcpd/libspipe.la @LDAUTH@ -lcourierauth -lcourierauthsasl @NETLIBS@
libpop3d_la_SOURCES=externalauth.c
-libpop3d_la_LIBADD=../maildir/libmaildir.la ../rfc822/librfc822.la \
+libpop3d_la_LIBADD=../maildir/libmaildir.la \
+ ../rfc2045/librfc2045.la \
+ ../rfc822/librfc822.la \
../numlib/libnumlib.la
libpop3d_la_DEPENDENCIES=$(libpop3d_la_LIBADD)
libpop3d_la_LDFLAGS=-static
pop3d_SOURCES=pop3dserver.c pop3dcapa.c
pop3d_DEPENDENCIES=libpop3d.la
-pop3d_LDADD=libpop3d.la @LDAUTH@ -lcourierauth
+pop3d_LDADD=libpop3d.la @LDAUTH@ -lcourierauth -lcourier-unicode
HTML2TXT=links -dump -no-numbering
diff --git a/imap/fetch.c b/imap/fetch.c
index 1eb52dd..fd25265 100644
--- a/imap/fetch.c
+++ b/imap/fetch.c
@@ -287,8 +287,8 @@ int do_fetch(unsigned long n, int byuid, void *p)
open_err=1;
cannot_open_because=
" because it is a Unicode message and your"
- " mail client did not enable Unicode support."
- " Please use a mail client that supports"
+ " E-mail reader did not enable Unicode support."
+ " Please use an E-mail reader that supports"
" IMAP with UTF-8 (see"
" https://tools.ietf.org/html/rfc6855.html)";
}
diff --git a/imap/pop3dcapa.c b/imap/pop3dcapa.c
index 5d0eef4..ca9e12e 100644
--- a/imap/pop3dcapa.c
+++ b/imap/pop3dcapa.c
@@ -1,5 +1,5 @@
/*
-** Copyright 1998 - 2008 Double Precision, Inc.
+** Copyright 1998 - 2018 Double Precision, Inc.
** See COPYING for distribution information.
*/
@@ -78,10 +78,13 @@ void pop3dcapa()
printf("SASL %s%s%s\r\n", p, *p && *external ? " ":"",
*external ? "EXTERNAL":"");
}
-
+
if (have_starttls())
printf("STLS\r\n");
- printf("TOP\r\nUSER\r\nLOGIN-DELAY 10\r\nPIPELINING\r\nUIDL\r\nIMPLEMENTATION Courier Mail Server\r\n.\r\n");
+ printf("TOP\r\nUSER\r\nLOGIN-DELAY 10\r\n"
+ "PIPELINING\r\nUIDL\r\n"
+ "UTF8 USER\r\n"
+ "IMPLEMENTATION Courier Mail Server\r\n.\r\n");
fflush(stdout);
}
diff --git a/imap/pop3dserver.c b/imap/pop3dserver.c
index 13aced9..beca04a 100644
--- a/imap/pop3dserver.c
+++ b/imap/pop3dserver.c
@@ -1,5 +1,5 @@
/*
-** Copyright 1998 - 2011 Double Precision, Inc.
+** Copyright 1998 - 2018 Double Precision, Inc.
** See COPYING for distribution information.
**
*/
@@ -54,12 +54,20 @@
#include "maildir/maildirgetquota.h"
#include "maildir/maildircreate.h"
#include "maildir/loginexec.h"
+#include "rfc2045/rfc2045.h"
#include "courierauth.h"
#define POP3DLIST "courierpop3dsizelist"
+#define LISTVERSION 3
extern void pop3dcapa();
static void acctout(const char *disc);
+void rfc2045_error(const char *p)
+{
+ if (write(2, p, strlen(p)) < 0)
+ _exit(1);
+ _exit(0);
+}
static const char *authaddr, *remoteip, *remoteport;
@@ -68,13 +76,14 @@ struct msglist {
char *filename;
int isdeleted;
int isnew;
+ int isutf8;
off_t size;
struct {
unsigned long uidv;
unsigned long n;
} uid;
- } ;
+} ;
static struct msglist *msglist_l;
static struct msglist **msglist_a;
@@ -82,6 +91,7 @@ static unsigned msglist_cnt;
static struct stat enomem_stat;
static int enomem_1msg;
+int utf8_enabled;
/*
** When a disk error occurs while saving an updated courierpop3dsizelist
@@ -109,7 +119,6 @@ static unsigned long bytes_sent_count=0;
static unsigned long bytes_received_count=0;
static unsigned long uidv=0;
-static int convert_v0=0;
static time_t start_time;
@@ -120,29 +129,18 @@ static time_t start_time;
static void calcsize(struct msglist *m)
{
-FILE *f=fopen(m->filename, "r");
-int c, lastc;
+ FILE *f=fopen(m->filename, "r");
+ struct rfc2045 *p=rfc2045_fromfp(f);
- m->size=0;
- if (f == 0)
- {
- perror("calcsize fopen");
- return;
- }
- lastc='\n';
- while ((c=getc(f)) >= 0)
- {
- if (c == '\n') ++m->size;
- ++m->size;
- lastc=c;
- }
- if (lastc != '\n') m->size += 2;
+ m->size=p->nlines + p->endpos;
- if (ferror(f))
- {
- perror("calcsize ferror");
- return;
- }
+ clearerr(f);
+ if (m->size > 0 && fseek(f, -1, SEEK_SET) == 0 && getc(f) != '\n')
+ m->size+=2; /* We'll add an extra CRLF ourselves */
+
+ if (p->rfcviolation & RFC2045_ERR8BITHEADER)
+ m->isutf8=1;
+ rfc2045_free(p);
fclose(f);
}
@@ -189,27 +187,15 @@ static struct msglist **readpop3dlist(unsigned long *uid)
uidv=time(NULL);
- convert_v0=0;
-
if (fp == NULL ||
fgets(linebuf, sizeof(linebuf)-1, fp) == NULL ||
linebuf[0] != '/' || sscanf(linebuf+1, "%d %lu %lu", &vernum,
uid, &uidv)
- < 2 || (vernum != 1 && vernum != 2))
+ < 2 || vernum != LISTVERSION)
{
- if (fp == NULL)
- convert_v0=1;
-
- if (vernum == 0 && fp && fseek(fp, 0L, SEEK_SET) >= 0)
- {
- /* Old version 0 format courierpop3dsizelist file */
- }
- else
- {
- if (fp)
- fclose(fp);
- fp=NULL;
- }
+ if (fp)
+ fclose(fp);
+ fp=NULL;
}
if (fp)
@@ -223,8 +209,6 @@ static struct msglist **readpop3dlist(unsigned long *uid)
while ((ch=getc(fp)) != EOF)
{
- unsigned long sz;
-
if (ch != '\n')
{
if (n < sizeof(linebuf)-3)
@@ -234,10 +218,6 @@ static struct msglist **readpop3dlist(unsigned long *uid)
linebuf[n]=0;
n=0;
- if (vernum == 0)
- strcat(linebuf, " 0");
- /* Convert version 0 to version 1 format - PRESTO! */
-
if ((p=strrchr(linebuf, ' ')) == NULL)
continue;
*p=0;
@@ -263,18 +243,16 @@ static struct msglist **readpop3dlist(unsigned long *uid)
exit(1);
}
- switch (sscanf(p, "%lu %lu:%lu", &sz,
- &m->uid.n, &m->uid.uidv)) {
- case 2:
- m->uid.uidv=0;
- /* FALLTHROUGH */
- case 3:
- m->size=sz;
+ if (sscanf(p, "%lu %lu:%lu:%d", &m->size,
+ &m->uid.n, &m->uid.uidv,
+ &m->isutf8) == 4)
+ {
m->next=list;
list=m;
++mcnt;
- break;
- default:
+ }
+ else
+ {
free(m->filename);
free(m);
}
@@ -316,7 +294,7 @@ static int savepop3dlist(struct msglist **a, size_t cnt,
return -1;
}
- fprintf(fp, "/2 %lu %lu\n", uid, uidv);
+ fprintf(fp, "/%d %lu %lu\n", LISTVERSION, uid, uidv);
for (i=0; i<cnt; i++)
{
@@ -326,8 +304,8 @@ static int savepop3dlist(struct msglist **a, size_t cnt,
if ((q=strrchr(p, '/')) != NULL)
p=q+1;
- fprintf(fp, "%s %lu %lu:%lu\n", p, (unsigned long)a[i]->size,
- a[i]->uid.n, a[i]->uid.uidv);
+ fprintf(fp, "%s %lu %lu:%lu:%d\n", p, (unsigned long)a[i]->size,
+ a[i]->uid.n, a[i]->uid.uidv, a[i]->isutf8);
}
if (fflush(fp) || ferror(fp))
@@ -411,7 +389,7 @@ static int cmpmsgs(const void *a, const void *b)
++bp;
else
bp=bname;
-
+
na=atol(ap);
nb=atol(bp);
@@ -480,6 +458,7 @@ static void sortmsgs()
{
msglist_a[i]->size=prev_list[n]->size;
msglist_a[i]->uid=prev_list[n]->uid;
+ msglist_a[i]->isutf8=prev_list[n]->isutf8;
n++;
}
else
@@ -487,12 +466,10 @@ static void sortmsgs()
msglist_a[i]->uid.n=nextuid++;
msglist_a[i]->uid.uidv=uidv;
msglist_a[i]->isnew=1;
- if (convert_v0)
- msglist_a[i]->uid.n=0;
calcsize(msglist_a[i]);
savesizes=1;
- }
+ }
}
if (prev_list[n])
@@ -662,12 +639,27 @@ char buf[NUMBUFSIZE];
static void do_retr(unsigned i, unsigned *lptr)
{
-FILE *f=fopen(msglist_a[i]->filename, "r");
-char *p;
-int c, lastc='\n';
-int inheader=1;
-char buf[NUMBUFSIZE];
-unsigned long *cntr;
+ FILE *f;
+ char *p;
+ int c, lastc='\n';
+ int inheader=1;
+ char buf[NUMBUFSIZE];
+ unsigned long *cntr;
+
+ if (msglist_a[i]->isutf8 && !utf8_enabled)
+ {
+ printed(printf("-ERR Cannot open message %u because it is"
+ " a Unicode message and your E-mail reader"
+ " did not enable Unicode support. Please"
+ " use an E-mail reader that supports POP3"
+ " with UTF-8 (see"
+ " https://tools.ietf.org/html/rfc6856.html)\r\n",
+ i+1));
+ fflush(stdout);
+ return;
+ }
+
+ f=fopen(msglist_a[i]->filename, "r");
if (!f)
{
@@ -1045,6 +1037,14 @@ char *p;
authaddr="nobody";
}
+ utf8_enabled=1; /* Until proven otherwise */
+
+ {
+ const char *utf8=getenv("UTF8");
+
+ if (utf8)
+ utf8_enabled=atoi(utf8);
+ }
if ((remoteip=getenv("TCPREMOTEIP")) == NULL)
remoteip="127.0.0.1";
@@ -1078,7 +1078,7 @@ char *p;
fflush(stdout);
exit(1);
}
-
+
maildir_loginexec();
if (auth_getoptionenvint("disablepop3"))
diff --git a/imap/pop3login.c b/imap/pop3login.c
index d541254..be96d0e 100644
--- a/imap/pop3login.c
+++ b/imap/pop3login.c
@@ -37,6 +37,7 @@ extern const char *pop3_externalauth();
static const char *pop3d;
static const char *defaultmaildir;
+int utf8_enabled=0;
static const char *safe_getenv(const char *p)
{
@@ -223,6 +224,10 @@ static int login_callback(struct authinfo *ainfo, void *dummy)
ainfo->address);
putenv(p);
+ if (utf8_enabled)
+ putenv("UTF8=1");
+ else
+ putenv("UTF8=0");
alarm(0);
execl(pop3d, pop3d,
ainfo->maildir ?
@@ -306,6 +311,14 @@ char *q ;
break;
}
+ if ( strcmp(p, "UTF8") == 0)
+ {
+ printf("+OK UTF8 enabled\r\n");
+ fflush(stdout);
+ utf8_enabled=1;
+ continue;
+ }
+
if ( strcmp(p, "USER") == 0)
{
if (tls_required())