From e024165eb98df86eb314c5ddea3cb38fcf478e67 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 18 Sep 2007 21:38:15 +0000 Subject: [PATCH] Aggregation of remote POP3 accounts is now working. You can use it by declaring -DPOP3_AGGREGATION in your CFLAGS, and then manually editing the netconfigs file for a room (typically an inbox) with a line like: pop3client|popserver.host.com|username|password Client configuration screens will follow. --- citadel/clientsocket.c | 10 +-- citadel/clientsocket.h | 2 +- citadel/control.c | 3 +- citadel/modules/calendar/serv_calendar.c | 2 +- citadel/modules/funambol/serv_funambol.c | 2 +- citadel/modules/network/serv_network.c | 16 ++-- citadel/modules/pop3client/serv_pop3client.c | 82 +++++++++++++++++++- citadel/modules/sieve/serv_sieve.c | 2 +- citadel/modules/smtp/serv_smtp.c | 2 +- citadel/modules/spam/serv_spam.c | 4 +- citadel/msgbase.c | 13 +++- citadel/msgbase.h | 2 +- 12 files changed, 110 insertions(+), 30 deletions(-) diff --git a/citadel/clientsocket.c b/citadel/clientsocket.c index a1c93a251..eef8a3563 100644 --- a/citadel/clientsocket.c +++ b/citadel/clientsocket.c @@ -189,7 +189,7 @@ int sock_write(int sock, char *buf, int nbytes) * Input string from socket - implemented in terms of sock_read() * */ -int sock_gets(int sock, char *buf) +int sock_getln(int sock, char *buf, int bufsize) { int i; @@ -197,13 +197,13 @@ int sock_gets(int sock, char *buf) */ for (i = 0;; i++) { if (sock_read(sock, &buf[i], 1) < 0) return(-1); - if (buf[i] == '\n' || i == (SIZ-1)) + if (buf[i] == '\n' || i == (bufsize-1)) break; } /* If we got a long line, discard characters until the newline. */ - if (i == (SIZ-1)) + if (i == (bufsize-1)) while (buf[i] != '\n') if (sock_read(sock, &buf[i], 1) < 0) return(-1); @@ -227,12 +227,12 @@ int ml_sock_gets(int sock, char *buf) { char bigbuf[1024]; int g; - g = sock_gets(sock, buf); + g = sock_getln(sock, buf, SIZ); if (g < 4) return(g); if (buf[3] != '-') return(g); do { - g = sock_gets(sock, bigbuf); + g = sock_getln(sock, bigbuf, SIZ); if (g < 0) return(g); } while ( (g >= 4) && (bigbuf[3] == '-') ); diff --git a/citadel/clientsocket.h b/citadel/clientsocket.h index 1fdbcb1af..0e5a6ecb4 100644 --- a/citadel/clientsocket.h +++ b/citadel/clientsocket.h @@ -9,7 +9,7 @@ int sock_read_to(int sock, char *buf, int bytes, int timeout); int sock_read(int sock, char *buf, int bytes); int sock_write(int sock, char *buf, int nbytes); int ml_sock_gets(int sock, char *buf); -int sock_gets(int sock, char *buf); +int sock_getln(int sock, char *buf, int bufsize); int sock_puts(int sock, char *buf); diff --git a/citadel/control.c b/citadel/control.c index 7dc74798b..710c38d63 100644 --- a/citadel/control.c +++ b/citadel/control.c @@ -540,8 +540,7 @@ void cmd_conf(char *argbuf) extract_token(confname, argbuf, 1, '|', sizeof confname); unbuffer_output(); cprintf("%d %s\n", SEND_LISTING, confname); - confptr = CtdlReadMessageBody("000", - config.c_maxmsglen, NULL, 0); + confptr = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0); CtdlPutSysConfig(confname, confptr); free(confptr); } diff --git a/citadel/modules/calendar/serv_calendar.c b/citadel/modules/calendar/serv_calendar.c index 2809ddc96..05fe7d994 100644 --- a/citadel/modules/calendar/serv_calendar.c +++ b/citadel/modules/calendar/serv_calendar.c @@ -1457,7 +1457,7 @@ void ical_putics(void) } cprintf("%d Transmit data now\n", SEND_LISTING); - calstream = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0); + calstream = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0); if (calstream == NULL) { return; } diff --git a/citadel/modules/funambol/serv_funambol.c b/citadel/modules/funambol/serv_funambol.c index 3ea217105..309e33464 100644 --- a/citadel/modules/funambol/serv_funambol.c +++ b/citadel/modules/funambol/serv_funambol.c @@ -202,7 +202,7 @@ void notify_funambol(long msgnum, void *userdata) { /* Response */ lprintf(CTDL_DEBUG, "Awaiting response\n"); - if (sock_gets(sock, buf) < 0) { + if (sock_getln(sock, buf, sizeof buf) < 0) { goto bail; } lprintf(CTDL_DEBUG, "<%s\n", buf); diff --git a/citadel/modules/network/serv_network.c b/citadel/modules/network/serv_network.c index 29ad8379b..8e8847546 100644 --- a/citadel/modules/network/serv_network.c +++ b/citadel/modules/network/serv_network.c @@ -1655,7 +1655,7 @@ void receive_spool(int sock, char *remote_nodename) { CtdlMakeTempFileName(tempfilename, sizeof tempfilename); if (sock_puts(sock, "NDOP") < 0) return; - if (sock_gets(sock, buf) < 0) return; + if (sock_getln(sock, buf, sizeof buf) < 0) return; lprintf(CTDL_DEBUG, "<%s\n", buf); if (buf[0] != '2') { return; @@ -1680,7 +1680,7 @@ void receive_spool(int sock, char *remote_nodename) { unlink(tempfilename); return; } - if (sock_gets(sock, buf) < 0) { + if (sock_getln(sock, buf, sizeof buf) < 0) { fclose(fp); unlink(tempfilename); return; @@ -1702,7 +1702,7 @@ void receive_spool(int sock, char *remote_nodename) { unlink(tempfilename); return; } - if (sock_gets(sock, buf) < 0) { + if (sock_getln(sock, buf, sizeof buf) < 0) { unlink(tempfilename); return; } @@ -1736,7 +1736,7 @@ void transmit_spool(int sock, char *remote_nodename) char sfname[128]; if (sock_puts(sock, "NUOP") < 0) return; - if (sock_gets(sock, buf) < 0) return; + if (sock_getln(sock, buf, sizeof buf) < 0) return; lprintf(CTDL_DEBUG, "<%s\n", buf); if (buf[0] != '2') { return; @@ -1763,7 +1763,7 @@ void transmit_spool(int sock, char *remote_nodename) close(fd); return; } - if (sock_gets(sock, buf) < 0) { + if (sock_getln(sock, buf, sizeof buf) < 0) { close(fd); return; } @@ -1785,7 +1785,7 @@ void transmit_spool(int sock, char *remote_nodename) ABORTUPL: close(fd); if (sock_puts(sock, "UCLS 1") < 0) return; - if (sock_gets(sock, buf) < 0) return; + if (sock_getln(sock, buf, sizeof buf) < 0) return; lprintf(CTDL_NOTICE, "Sent %ld octets to <%s>\n", bytes_written, remote_nodename); lprintf(CTDL_DEBUG, "<%s\n", buf); @@ -1818,14 +1818,14 @@ void network_poll_node(char *node, char *secret, char *host, char *port) { lprintf(CTDL_DEBUG, "Connected!\n"); /* Read the server greeting */ - if (sock_gets(sock, buf) < 0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; lprintf(CTDL_DEBUG, ">%s\n", buf); /* Identify ourselves */ snprintf(buf, sizeof buf, "NETP %s|%s", config.c_nodename, secret); lprintf(CTDL_DEBUG, "<%s\n", buf); if (sock_puts(sock, buf) <0) goto bail; - if (sock_gets(sock, buf) < 0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; lprintf(CTDL_DEBUG, ">%s\n", buf); if (buf[0] != '2') goto bail; diff --git a/citadel/modules/pop3client/serv_pop3client.c b/citadel/modules/pop3client/serv_pop3client.c index 0782894dd..449dcc95e 100644 --- a/citadel/modules/pop3client/serv_pop3client.c +++ b/citadel/modules/pop3client/serv_pop3client.c @@ -29,6 +29,8 @@ #include "room_ops.h" #include "ctdl_module.h" #include "clientsocket.h" +#include "msgbase.h" +#include "internet_addressing.h" struct pop3aggr { struct pop3aggr *next; @@ -47,6 +49,14 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3 { int sock; char buf[SIZ]; + int msg_to_fetch = 0; + int *msglist = NULL; + int num_msgs = 0; + int alloc_msgs = 0; + int i; + char *body = NULL; + struct CtdlMessage *msg = NULL; + long msgnum = 0; lprintf(CTDL_DEBUG, "POP3: %s %s %s %s\n", roomname, pop3host, pop3user, pop3pass); lprintf(CTDL_NOTICE, "Connecting to <%s>\n", pop3host); @@ -59,7 +69,7 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3 lprintf(CTDL_DEBUG, "Connected!\n"); /* Read the server greeting */ - if (sock_gets(sock, buf) < 0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; lprintf(CTDL_DEBUG, ">%s\n", buf); if (strncasecmp(buf, "+OK", 3)) goto bail; @@ -67,7 +77,7 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3 snprintf(buf, sizeof buf, "USER %s", pop3user); lprintf(CTDL_DEBUG, "<%s\n", buf); if (sock_puts(sock, buf) <0) goto bail; - if (sock_gets(sock, buf) < 0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; lprintf(CTDL_DEBUG, ">%s\n", buf); if (strncasecmp(buf, "+OK", 3)) goto bail; @@ -75,12 +85,76 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3 snprintf(buf, sizeof buf, "PASS %s", pop3pass); lprintf(CTDL_DEBUG, "<%s\n", buf); if (sock_puts(sock, buf) <0) goto bail; - if (sock_gets(sock, buf) < 0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; lprintf(CTDL_DEBUG, ">%s\n", buf); if (strncasecmp(buf, "+OK", 3)) goto bail; - sock_puts(sock, "QUIT"); + /* Get the list of messages */ + snprintf(buf, sizeof buf, "LIST"); + lprintf(CTDL_DEBUG, "<%s\n", buf); + if (sock_puts(sock, buf) <0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; + lprintf(CTDL_DEBUG, ">%s\n", buf); + if (strncasecmp(buf, "+OK", 3)) goto bail; + + do { + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; + lprintf(CTDL_DEBUG, ">%s\n", buf); + msg_to_fetch = atoi(buf); + if (msg_to_fetch > 0) { + if (alloc_msgs == 0) { + alloc_msgs = 100; + msglist = malloc((alloc_msgs * (sizeof(int)))); + } + else if (num_msgs >= alloc_msgs) { + alloc_msgs = alloc_msgs * 2; + msglist = realloc(msglist, (alloc_msgs * sizeof(int))); + } + if (msglist == NULL) goto bail; + msglist[num_msgs++] = msg_to_fetch; + } + } while (buf[0] != '.'); + + if (num_msgs) for (i=0; i%s\n", buf); + if (strncasecmp(buf, "+OK", 3)) goto bail; + + /* If we get to this point, the message is on its way. Read it. */ + body = CtdlReadMessageBody(".", config.c_maxmsglen, NULL, 1, sock); + if (body == NULL) goto bail; + + lprintf(CTDL_DEBUG, "Converting message...\n"); + msg = convert_internet_message(body); + body = NULL; /* yes, this should be dereferenced, NOT freed */ + + /* Do Something With It (tm) */ + msgnum = CtdlSubmitMsg(msg, NULL, roomname); + if (msgnum > 0L) { + /* Message has been committed to the store, so delete it from the remote server */ + snprintf(buf, sizeof buf, "DELE %d", msglist[i]); + lprintf(CTDL_DEBUG, "<%s\n", buf); + if (sock_puts(sock, buf) <0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; + lprintf(CTDL_DEBUG, ">%s\n", buf); + if (strncasecmp(buf, "+OK", 3)) goto bail; + } + CtdlFreeMessage(msg); + } + + /* Log out */ + snprintf(buf, sizeof buf, "QUIT"); + lprintf(CTDL_DEBUG, "<%s\n", buf); + if (sock_puts(sock, buf) <0) goto bail; + if (sock_getln(sock, buf, sizeof buf) < 0) goto bail; + lprintf(CTDL_DEBUG, ">%s\n", buf); bail: sock_close(sock); + if (msglist) free(msglist); } diff --git a/citadel/modules/sieve/serv_sieve.c b/citadel/modules/sieve/serv_sieve.c index 010e76b43..fe485b41e 100644 --- a/citadel/modules/sieve/serv_sieve.c +++ b/citadel/modules/sieve/serv_sieve.c @@ -1114,7 +1114,7 @@ void cmd_msiv(char *argbuf) { extract_token(script_name, argbuf, 1, '|', sizeof script_name); if (!IsEmptyStr(script_name)) { cprintf("%d Transmit script now\n", SEND_LISTING); - script_content = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0); + script_content = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0); msiv_putscript(&u, script_name, script_content); changes_made = 1; } diff --git a/citadel/modules/smtp/serv_smtp.c b/citadel/modules/smtp/serv_smtp.c index 960e105d0..df9b3d632 100644 --- a/citadel/modules/smtp/serv_smtp.c +++ b/citadel/modules/smtp/serv_smtp.c @@ -673,7 +673,7 @@ void smtp_data(void) { config.c_fqdn, nowstamp); - body = CtdlReadMessageBody(".", config.c_maxmsglen, body, 1); + body = CtdlReadMessageBody(".", config.c_maxmsglen, body, 1, 0); if (body == NULL) { cprintf("550 5.6.5 " "Unable to save message: internal error.\r\n"); diff --git a/citadel/modules/spam/serv_spam.c b/citadel/modules/spam/serv_spam.c index 64ad1f5cb..cdf81557a 100644 --- a/citadel/modules/spam/serv_spam.c +++ b/citadel/modules/spam/serv_spam.c @@ -118,14 +118,14 @@ int spam_assassin(struct CtdlMessage *msg) { /* Response */ lprintf(CTDL_DEBUG, "Awaiting response\n"); - if (sock_gets(sock, buf) < 0) { + if (sock_getln(sock, buf, sizeof buf) < 0) { goto bail; } lprintf(CTDL_DEBUG, "<%s\n", buf); if (strncasecmp(buf, "SPAMD", 5)) { goto bail; } - if (sock_gets(sock, buf) < 0) { + if (sock_getln(sock, buf, sizeof buf) < 0) { goto bail; } lprintf(CTDL_DEBUG, "<%s\n", buf); diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 361f791a3..b5732fe88 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -53,6 +53,7 @@ #include "euidindex.h" #include "journaling.h" #include "citadel_dirs.h" +#include "clientsocket.h" long config_msgnum; @@ -2819,7 +2820,8 @@ char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */ size_t maxlen, /* maximum message length */ char *exist, /* if non-null, append to it; exist is ALWAYS freed */ - int crlf /* CRLF newlines instead of LF */ + int crlf, /* CRLF newlines instead of LF */ + int sock /* socket handle or 0 for this session's client socket */ ) { char buf[1024]; int linelen; @@ -2859,7 +2861,12 @@ char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */ /* read in the lines of message text one by one */ do { - if (client_getln(buf, (sizeof buf - 3)) < 1) finished = 1; + if (sock > 0) { + if (sock_getln(sock, buf, (sizeof buf - 3)) < 0) finished = 1; + } + else { + if (client_getln(buf, (sizeof buf - 3)) < 1) finished = 1; + } if (!strcmp(buf, terminator)) finished = 1; if (crlf) { strcat(buf, "\r\n"); @@ -3029,7 +3036,7 @@ struct CtdlMessage *CtdlMakeMessage( msg->cm_fields['M'] = preformatted_text; } else { - msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0); + msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0); } return(msg); diff --git a/citadel/msgbase.h b/citadel/msgbase.h index 6a6f5e109..50a1a6487 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -126,7 +126,7 @@ void ReplicationChecks(struct CtdlMessage *); int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newmsgs, int do_repl_check, struct CtdlMessage *supplied_msg); int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int do_repl_check, struct CtdlMessage *msg); -char *CtdlReadMessageBody(char *terminator, size_t maxlen, char *exist, int crlf); +char *CtdlReadMessageBody(char *terminator, size_t maxlen, char *exist, int crlf, int sock); char *CtdlGetSysConfig(char *sysconfname); void CtdlPutSysConfig(char *sysconfname, char *sysconfdata); int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ -- 2.30.2