summaryrefslogtreecommitdiffstats
path: root/imap/pop3dserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap/pop3dserver.c')
-rw-r--r--imap/pop3dserver.c138
1 files changed, 69 insertions, 69 deletions
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"))