diff options
author | Sunil Shetye <sunilshetye@rocketmail.com> | 2011-05-03 01:06:34 +0530 |
---|---|---|
committer | Matthias Andree <matthias.andree@gmx.de> | 2011-05-04 01:11:30 +0200 |
commit | 6fdb9350ecdfd0dc7f65975ac9b4d6ba00161b19 (patch) | |
tree | 6b7d2c8cfc792b8c04f84c1e3060d0878b984d20 /transact.c | |
parent | 6f1c728fcc99e9745b7a5bbb46a9c6f82ce56d33 (diff) | |
download | fetchmail-6fdb9350ecdfd0dc7f65975ac9b4d6ba00161b19.tar.gz fetchmail-6fdb9350ecdfd0dc7f65975ac9b4d6ba00161b19.tar.bz2 fetchmail-6fdb9350ecdfd0dc7f65975ac9b4d6ba00161b19.zip |
Do not search for UNSEEN messages in ranges.
Add gen_recv_split() to split long protocol messages when the message prefix matches
Order of search commands:
IMAP> A010 SEARCH UNSEEN UNDELETED (IMAP4 or higher)
IMAP> A011 SEARCH UNSEEN
IMAP> A012 FETCH 1:n FLAGS
Diffstat (limited to 'transact.c')
-rw-r--r-- | transact.c | 92 |
1 files changed, 92 insertions, 0 deletions
@@ -1586,6 +1586,98 @@ int gen_recv(int sock /** socket to which server is connected */, } } +/* + * gen_recv_split() splits the response from a server which is too + * long to fit into the buffer into multiple lines. If the prefix is + * set as "MY FEATURES" and the response from the server is too long + * to fit in the buffer, as in: + * + * "MY FEATURES ABC DEF GHI JKLMNOPQRS TU VWX YZ" + * + * Repeated calls to gen_recv_split() may return: + * + * "MY FEATURES ABC DEF GHI" + * "MY FEATURES JKLMNOPQRS" + * "MY FEATURES TU VWX YZ" + * + * A response not beginning with the prefix "MY FEATURES" will not be + * split. + * + * To use: + * - Declare a variable of type struct RecvSplit + * - Call gen_recv_split_init() once + * - Call gen_recv_split() in a loop + */ + +void gen_recv_split_init (const char *prefix, struct RecvSplit *rs) +{ + snprintf(rs->prefix, sizeof(rs->prefix), "%s", prefix); + rs->cached = 0; + rs->buf[0] = '\0'; +} + +int gen_recv_split(int sock /** socket to which server is connected */, + char *buf /* buffer to receive input */, + int size /* length of buffer */, + struct RecvSplit *rs /* cached information across calls */) +{ + size_t n = 0; + int foundnewline = 0; + char *p; + int oldphase = phase; /* we don't have to be re-entrant */ + + /* if this is not our first call, prepare the buffer */ + if (rs->cached) + { + snprintf (buf, size, "%s%s", rs->prefix, rs->buf); + n = strlen(buf); + /* clear the cache for the next call */ + rs->cached = 0; + rs->buf[0] = '\0'; + } + + phase = SERVER_WAIT; + set_timeout(mytimeout); + if (SockRead(sock, buf + n, size - n) == -1) + { + set_timeout(0); + phase = oldphase; + return(PS_SOCKET); + } + set_timeout(0); + + n = strlen(buf); + if (n > 0 && buf[n-1] == '\n') + { + buf[--n] = '\0'; + foundnewline = 1; + } + if (n > 0 && buf[n-1] == '\r') + buf[--n] = '\0'; + + if (foundnewline /* we have found a complete line */ + || strncmp(buf, rs->prefix, strlen(rs->prefix)) /* mismatch in prefix */ + || !(p = strrchr(buf, ' ')) /* no space found in response */ + || p < buf + strlen(rs->prefix)) /* space is at the wrong location */ + { + if (outlevel >= O_MONITOR) + report(stdout, "%s< %s\n", protocol->name, buf); + phase = oldphase; + return(PS_SUCCESS); + } + + /* we are ready to cache some information now. */ + rs->cached = 1; + snprintf (rs->buf, sizeof(rs->buf), "%s", p); + *p = '\0'; + if (outlevel >= O_MONITOR) + report(stdout, "%s< %s\n", protocol->name, buf); + if (outlevel >= O_DEBUG) + report(stdout, "%s< %s%s...\n", protocol->name, rs->prefix, rs->buf); + phase = oldphase; + return(PS_SUCCESS); +} + #if defined(HAVE_STDARG_H) int gen_transact(int sock, const char *fmt, ... ) #else |