aboutsummaryrefslogtreecommitdiffstats
path: root/transact.c
diff options
context:
space:
mode:
authorSunil Shetye <sunilshetye@rocketmail.com>2011-05-03 01:06:34 +0530
committerMatthias Andree <matthias.andree@gmx.de>2011-05-04 01:11:30 +0200
commit6fdb9350ecdfd0dc7f65975ac9b4d6ba00161b19 (patch)
tree6b7d2c8cfc792b8c04f84c1e3060d0878b984d20 /transact.c
parent6f1c728fcc99e9745b7a5bbb46a9c6f82ce56d33 (diff)
downloadfetchmail-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.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/transact.c b/transact.c
index 758e5aaf..ff3a12ec 100644
--- a/transact.c
+++ b/transact.c
@@ -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