* make QP encoding of senders optional, so we can flag it if we need it.
[citadel.git] / citadel / modules / pop3 / serv_pop3.c
index dcdbb8ec6d8b2c581ed164e883719ce0bfa35759..43a2545d871d81e747c3347cceadce6d545363d1 100644 (file)
@@ -71,7 +71,7 @@ void pop3_cleanup_function(void) {
        /* Don't do this stuff if this is not a POP3 session! */
        if (CC->h_command_function != pop3_command_loop) return;
 
-       lprintf(CTDL_DEBUG, "Performing POP3 cleanup hook\n");
+       CtdlLogPrintf(CTDL_DEBUG, "Performing POP3 cleanup hook\n");
        if (POP3->msgs != NULL) free(POP3->msgs);
 
        free(POP3);
@@ -125,7 +125,7 @@ void pop3_user(char *argbuf) {
        strcpy(username, argbuf);
        striplt(username);
 
-       /* lprintf(CTDL_DEBUG, "Trying <%s>\n", username); */
+       /* CtdlLogPrintf(CTDL_DEBUG, "Trying <%s>\n", username); */
        if (CtdlLoginExistingUser(NULL, username) == login_ok) {
                cprintf("+OK Password required for %s\r\n", username);
        }
@@ -159,7 +159,7 @@ void pop3_add_message(long msgnum, void *userdata) {
                CC->redirect_buffer = malloc(SIZ);
                CC->redirect_len = 0;
                CC->redirect_alloc = SIZ;
-               CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL);
+               CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, 0);
                smi.meta_rfc822_length = CC->redirect_len;
                free(CC->redirect_buffer);
                CC->redirect_buffer = NULL;
@@ -208,7 +208,7 @@ void pop3_login(void)
        if (msgs >= 0) {
                cprintf("+OK %s is logged in (%d messages)\r\n",
                        CC->user.fullname, msgs);
-               lprintf(CTDL_NOTICE, "POP3 authenticated %s\n", CC->user.fullname);
+               CtdlLogPrintf(CTDL_NOTICE, "POP3 authenticated %s\n", CC->user.fullname);
        }
        else {
                cprintf("-ERR Can't open your mailbox\r\n");
@@ -280,7 +280,7 @@ void pop3_pass(char *argbuf) {
        strcpy(password, argbuf);
        striplt(password);
 
-       /* lprintf(CTDL_DEBUG, "Trying <%s>\n", password); */
+       /* CtdlLogPrintf(CTDL_DEBUG, "Trying <%s>\n", password); */
        if (CtdlTryPassword(password) == pass_ok) {
                pop3_login();
        }
@@ -360,6 +360,10 @@ void pop3_stat(char *argbuf) {
  */
 void pop3_retr(char *argbuf) {
        int which_one;
+       char *msgtext;
+       char *nextline;
+       char *chunk_to_send;
+       char prev_char;
 
        which_one = atoi(argbuf);
        if ( (which_one < 1) || (which_one > POP3->num_msgs) ) {
@@ -373,7 +377,41 @@ void pop3_retr(char *argbuf) {
        }
 
        cprintf("+OK Message %d:\r\n", which_one);
-       CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL);
+       CC->redirect_buffer = malloc(SIZ);
+       CC->redirect_len = 0;
+       CC->redirect_alloc = SIZ;
+       CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum,
+                     MT_RFC822, HEADERS_ALL, 0, 1, NULL, 0);
+       msgtext = CC->redirect_buffer;
+       CC->redirect_buffer = NULL;
+       CC->redirect_len = 0;
+       CC->redirect_alloc = 0;
+
+       /* If we reach this point, the client is expecting data.
+        * Need to parse each line of the message here since someone may have sent
+        * a message containing a single dot on a line of its own. In that case we
+        * need to escape it in accordance with RFC821.
+        * We could do this with the tokenizer functions but num_tokens returns an
+        * int and the message may contain more lines than that, also copying each
+        * line would be slow.
+        */
+       nextline = msgtext;
+       while (*nextline)
+       {
+               chunk_to_send = nextline;
+               while (*nextline != '\n')
+                       nextline++;
+               nextline++;
+               prev_char = *nextline;
+               *nextline = '\0';
+               if (!strcmp(chunk_to_send, ".\r\n")) {
+                       client_write("..\r\n", 4);
+               }
+               else {
+                       client_write(chunk_to_send, (size_t)(nextline-chunk_to_send));
+               }
+               *nextline = prev_char;
+       }
        cprintf(".\r\n");
 }
 
@@ -406,7 +444,7 @@ void pop3_top(char *argbuf) {
        CC->redirect_len = 0;
        CC->redirect_alloc = SIZ;
        CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum,
-                       MT_RFC822, HEADERS_ALL, 0, 1, NULL);
+                     MT_RFC822, HEADERS_ALL, 0, 1, NULL, 0);
        msgtext = CC->redirect_buffer;
        CC->redirect_buffer = NULL;
        CC->redirect_len = 0;
@@ -622,15 +660,15 @@ void pop3_command_loop(void) {
        time(&CC->lastcmd);
        memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */
        if (client_getln(cmdbuf, sizeof cmdbuf) < 1) {
-               lprintf(CTDL_ERR, "Client disconnected: ending session.\r\n");
+               CtdlLogPrintf(CTDL_ERR, "Client disconnected: ending session.\r\n");
                CC->kill_me = 1;
                return;
        }
        if (!strncasecmp(cmdbuf, "PASS", 4)) {
-               lprintf(CTDL_INFO, "POP3: PASS...\r\n");
+               CtdlLogPrintf(CTDL_INFO, "POP3: PASS...\r\n");
        }
        else {
-               lprintf(CTDL_INFO, "POP3: %s\r\n", cmdbuf);
+               CtdlLogPrintf(CTDL_INFO, "POP3: %s\r\n", cmdbuf);
        }
        while (strlen(cmdbuf) < 5) strcat(cmdbuf, " ");
 
@@ -716,22 +754,25 @@ const char *CitadelServicePop3S="POP3S";
 
 CTDL_MODULE_INIT(pop3)
 {
-       CtdlRegisterServiceHook(config.c_pop3_port,
-                               NULL,
-                               pop3_greeting,
-                               pop3_command_loop,
-                               NULL,
-                               CitadelServicePop3);
+       if(!threading)
+       {
+               CtdlRegisterServiceHook(config.c_pop3_port,
+                                       NULL,
+                                       pop3_greeting,
+                                       pop3_command_loop,
+                                       NULL,
+                                       CitadelServicePop3);
 #ifdef HAVE_OPENSSL
-       CtdlRegisterServiceHook(config.c_pop3s_port,
-                               NULL,
-                               pop3s_greeting,
-                               pop3_command_loop,
-                               NULL,
-                               CitadelServicePop3S);
+               CtdlRegisterServiceHook(config.c_pop3s_port,
+                                       NULL,
+                                       pop3s_greeting,
+                                       pop3_command_loop,
+                                       NULL,
+                                       CitadelServicePop3S);
 #endif
-       CtdlRegisterSessionHook(pop3_cleanup_function, EVT_STOP);
-
+               CtdlRegisterSessionHook(pop3_cleanup_function, EVT_STOP);
+       }
+       
        /* return our Subversion id for the Log */
        return "$Id$";
 }