diff options
Diffstat (limited to 'imap/pop3dserver.c')
| -rw-r--r-- | imap/pop3dserver.c | 126 |
1 files changed, 108 insertions, 18 deletions
diff --git a/imap/pop3dserver.c b/imap/pop3dserver.c index beca04a..ea5ed99 100644 --- a/imap/pop3dserver.c +++ b/imap/pop3dserver.c @@ -92,6 +92,7 @@ static unsigned msglist_cnt; static struct stat enomem_stat; static int enomem_1msg; int utf8_enabled; +int savesizes=0; /* ** When a disk error occurs while saving an updated courierpop3dsizelist @@ -138,6 +139,7 @@ static void calcsize(struct msglist *m) if (m->size > 0 && fseek(f, -1, SEEK_SET) == 0 && getc(f) != '\n') m->size+=2; /* We'll add an extra CRLF ourselves */ + m->isutf8=0; if (p->rfcviolation & RFC2045_ERR8BITHEADER) m->isutf8=1; rfc2045_free(p); @@ -178,12 +180,13 @@ static struct msglist **readpop3dlist(unsigned long *uid) struct msglist *list=NULL; size_t mcnt=0; - char linebuf[1024]; + char linebuf[2048]; FILE *fp=openpop3dlist(); size_t i; int vernum=0; + unsigned long size; uidv=time(NULL); @@ -191,12 +194,18 @@ static struct msglist **readpop3dlist(unsigned long *uid) fgets(linebuf, sizeof(linebuf)-1, fp) == NULL || linebuf[0] != '/' || sscanf(linebuf+1, "%d %lu %lu", &vernum, uid, &uidv) - < 2 || vernum != LISTVERSION) + < 2 || (vernum != LISTVERSION && + vernum != (LISTVERSION-1))) { if (fp) fclose(fp); fp=NULL; } + else + { + if (vernum != LISTVERSION) + savesizes=1; + } if (fp) { @@ -211,7 +220,7 @@ static struct msglist **readpop3dlist(unsigned long *uid) { if (ch != '\n') { - if (n < sizeof(linebuf)-3) + if (n < sizeof(linebuf)-20) linebuf[n++]=ch; continue; } @@ -243,10 +252,15 @@ static struct msglist **readpop3dlist(unsigned long *uid) exit(1); } - if (sscanf(p, "%lu %lu:%lu:%d", &m->size, + // Converting from LISTVERSION 2, assuming no UTF-8. + // We have extra room at the end. + strcat(p, ":0"); + + if (sscanf(p, "%lu %lu:%lu:%d", &size, &m->uid.n, &m->uid.uidv, &m->isutf8) == 4) { + m->size=size; m->next=list; list=m; ++mcnt; @@ -417,7 +431,6 @@ static void sortmsgs() size_t i, n; struct msglist *m; struct msglist **prev_list; - int savesizes=0; unsigned long nextuid; @@ -545,9 +558,10 @@ static void cleanup() } if (log_deletions) - fprintf(stderr, "INFO: DELETED, user=%s, ip=[%s], filename=%s\n", + fprintf(stderr, "INFO: DELETED, user=%s, ip=[%s], port=[%s], filename=%s\n", getenv("AUTHENTICATED"), - getenv("TCPREMOTEIP"), + remoteip, + remoteport, msglist_a[i]->filename); if (unlink(msglist_a[i]->filename)) @@ -637,6 +651,59 @@ char buf[NUMBUFSIZE]; /* RETR and TOP POP3 commands */ +#define MIMEWRAPTXT \ + "From: Mail Delivery Subsystem <postmaster>\n" \ + "Subject: Cannot display Unicode content\n" \ + "Mime-Version: 1.0\n" \ + "Content-Type: multipart/mixed; boundary=\"%s\"\n" \ + "\n\n\n--%s\n" \ + "Content-Type: text/plain\n\n" \ + "This E-mail message was determined to be Unicode-formatted\n" \ + "but your E-mail reader does not support Unicode E-mail.\n\n" \ + "Please use an E-mail reader that supports POP3 with UTF-8\n" \ + "(see https://tools.ietf.org/html/rfc6856.html).\n\n" \ + "This can also happen when the sender's E-mail program does not\n" \ + "correctly format the sent message.\n\n" \ + "The original message is included as a separate attachment\n" \ + "so that it can be downloaded manually.\n\n" \ + "--%s\n" \ + "Content-Type: %s\n\n" + +struct retr_source { + char *wrapheader; + FILE *f; + char *wrapfooter; +}; + +static int get_retr_source(struct retr_source *s) +{ + int c=(unsigned char)*s->wrapheader; + + if (c) + { + ++s->wrapheader; + return c; + } + + if (s->f) + { + int c=getc(s->f); + + if (c >= 0) + return c; + s->f=0; + } + + if (*s->wrapfooter) + { + int c=(unsigned char)*s->wrapfooter; + + ++s->wrapfooter; + return c; + } + return -1; +} + static void do_retr(unsigned i, unsigned *lptr) { FILE *f; @@ -645,18 +712,25 @@ static void do_retr(unsigned i, unsigned *lptr) int inheader=1; char buf[NUMBUFSIZE]; unsigned long *cntr; + char boundary[256]; + char wrapheader[sizeof(MIMEWRAPTXT)+1024]; + char wrapfooter[512]; + const char *mime_message_type=getenv("MIME_UNICODE_MESSAGE_TYPE"); + struct retr_source rs; + + wrapheader[0]=0; + wrapfooter[0]=0; + + if (!mime_message_type) + mime_message_type="message/global"; 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; + sprintf(boundary, "=_%d-%d", (int)getpid(), (int)time(NULL)); + + sprintf(wrapheader, MIMEWRAPTXT, boundary, boundary, boundary, + mime_message_type); + sprintf(wrapfooter, "\n--%s--\n", boundary); } f=fopen(msglist_a[i]->filename, "r"); @@ -668,13 +742,20 @@ static void do_retr(unsigned i, unsigned *lptr) return; } printed(printf( (lptr ? "+OK headers follow.\r\n":"+OK %s octets follow.\r\n"), - libmail_str_off_t(msglist_a[i]->size, buf))); + libmail_str_off_t(msglist_a[i]->size + + strlen(wrapheader) + + strlen(wrapfooter), + buf))); cntr= &retr_count; if (lptr) cntr= &top_count; - for (lastc=0; (c=getc(f)) >= 0; lastc=c) + rs.wrapheader=wrapheader; + rs.f=f; + rs.wrapfooter=wrapfooter; + + for (lastc=0; (c=get_retr_source(&rs)) >= 0; lastc=c) { if (lastc == '\n') { @@ -983,6 +1064,15 @@ int c; continue; } + if (strcmp(p, "UTF8") == 0) + { + /* XXX workaround for MS Outlook */ + utf8_enabled=1; + printed(printf("+OK UTF8 enabled\r\n")); + fflush(stdout); + continue; + } + error: printed(printf("-ERR Invalid command.\r\n")); fflush(stdout); |
