curl-library
[imap] imap: Fetch email headers if CURLOPT_HEADER is enabled.
From: Ben Greear <greearb_at_candelatech.com>
Date: Mon, 29 Mar 2010 20:14:49 -0700
Date: Mon, 29 Mar 2010 20:14:49 -0700
Signed-off-by: Ben Greear <greearb_at_candelatech.com>
---
:100644 100644 72ab8da... 2ec2d2e... M lib/imap.c
:100644 100644 2f0b62a... c6d74a4... M lib/imap.h
lib/imap.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
lib/imap.h | 3 +-
2 files changed, 114 insertions(+), 7 deletions(-)
diff --git a/lib/imap.c b/lib/imap.c
index 72ab8da..2ec2d2e 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -108,6 +108,7 @@ static int imap_getsock(struct connectdata *conn,
static CURLcode imap_doing(struct connectdata *conn,
bool *dophase_done);
static CURLcode imap_setup_connection(struct connectdata * conn);
+static CURLcode imap_fetch(struct connectdata *conn);
/*
* IMAP protocol handler.
@@ -272,7 +273,8 @@ static int imap_endofresp(struct pingpong *pp, int *resp)
*resp = line[id_len+1]; /* O, N or B */
return TRUE;
}
- else if((imapc->state == IMAP_FETCH) &&
+ else if(((imapc->state == IMAP_FETCH_HEADER) ||
+ (imapc->state == IMAP_FETCH_BODY)) &&
!memcmp("* ", line, 2) ) {
/* FETCH response we're interested in */
*resp = '*';
@@ -294,7 +296,8 @@ static void state(struct connectdata *conn,
"LOGIN",
"STARTTLS",
"SELECT",
- "FETCH",
+ "FETCH_HEADER",
+ "FETCH_BODY",
"LOGOUT",
/* LAST */
};
@@ -371,6 +374,75 @@ static CURLcode imap_state_login_resp(struct connectdata *conn,
return result;
}
+/* for the (first line of) FETCH BODY[HEADER] response */
+static CURLcode imap_state_fetch_hdr_resp(struct connectdata *conn,
+ int imapcode,
+ imapstate instate)
+{
+ CURLcode result = CURLE_OK;
+ struct SessionHandle *data = conn->data;
+ const char *ptr = data->state.buffer;
+ struct imap_conn *imapc = &conn->proto.imapc;
+ struct pingpong *pp = &imapc->pp;
+
+ (void)instate; /* no use for this yet */
+ if('*' != imapcode) {
+ Curl_pgrsSetDownloadSize(data, 0);
+ state(conn, IMAP_STOP);
+ return CURLE_OK;
+ }
+
+ /* Something like this comes "* 1 FETCH (FLAGS (\Seen) BODY[HEADER] {482}\r" */
+ while(*ptr && (*ptr != '{'))
+ ptr++;
+
+ if(*ptr == '{') {
+ curl_off_t filesize = curlx_strtoofft(ptr+1, NULL, 10);
+ if(filesize)
+ Curl_pgrsSetDownloadSize(data, filesize);
+
+ if(pp->cache) {
+ /* At this point there is a bunch of data in header cache. Do note
+ that there may even be additional "headers" after the body. */
+ size_t chunk = pp->cache_size;
+
+ if(chunk > (size_t)filesize)
+ /* the conversion from curl_off_t to size_t is always fine here */
+ chunk = (size_t)filesize;
+
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
+
+ if(result)
+ return result;
+
+ filesize -= chunk;
+
+ /* we've now used parts of or the entire cache */
+ if(pp->cache_size > chunk) {
+ /* part of, move the trailing data to the start and reduce the size */
+ memmove(pp->cache, pp->cache+chunk,
+ pp->cache_size - chunk);
+ pp->cache_size -= chunk;
+ }
+ else {
+ /* cache is drained */
+ free(pp->cache);
+ pp->cache = NULL;
+ pp->cache_size = 0;
+ }
+ }
+ }
+ else {
+ /* We don't know how to parse this line */
+ result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
+ }
+
+ /* Now, download the body of the email */
+ imap_fetch(conn);
+
+ return result;
+}
+
/* for the (first line of) FETCH BODY[TEXT] response */
static CURLcode imap_state_fetch_resp(struct connectdata *conn,
int imapcode,
@@ -471,6 +543,32 @@ static CURLcode imap_select(struct connectdata *conn)
return result;
}
+static CURLcode imap_fetch_hdr(struct connectdata *conn)
+{
+ CURLcode result = CURLE_OK;
+ const char *str;
+
+ str = getcmdid(conn);
+
+ /* TODO: make this select the correct mail
+ * Use "1 body[header]" to get the mail header of mail 1
+ */
+ result = imapsendf(conn, str, "%s FETCH 1 BODY[HEADER]", str);
+ if(result)
+ return result;
+
+ /*
+ * When issued, the server will respond with a single line similar to
+ * '* 1 FETCH (BODY[TEXT] {2021}'
+ *
+ * Identifying the fetch and how many bytes of contents we can expect. We
+ * must extract that number before continuing to "download as usual".
+ */
+
+ state(conn, IMAP_FETCH_HEADER);
+ return result;
+}
+
static CURLcode imap_fetch(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -493,7 +591,7 @@ static CURLcode imap_fetch(struct connectdata *conn)
* must extract that number before continuing to "download as usual".
*/
- state(conn, IMAP_FETCH);
+ state(conn, IMAP_FETCH_BODY);
return result;
}
@@ -510,8 +608,12 @@ static CURLcode imap_state_select_resp(struct connectdata *conn,
failf(data, "Select failed");
result = CURLE_LOGIN_DENIED;
}
- else
- result = imap_fetch(conn);
+ else {
+ if(data->set.include_header)
+ result = imap_fetch_hdr(conn);
+ else
+ result = imap_fetch(conn);
+ }
return result;
}
@@ -565,7 +667,11 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
result = imap_state_starttls_resp(conn, imapcode, imapc->state);
break;
- case IMAP_FETCH:
+ case IMAP_FETCH_HEADER:
+ result = imap_state_fetch_hdr_resp(conn, imapcode, imapc->state);
+ break;
+
+ case IMAP_FETCH_BODY:
result = imap_state_fetch_resp(conn, imapcode, imapc->state);
break;
diff --git a/lib/imap.h b/lib/imap.h
index 2f0b62a..c6d74a4 100644
--- a/lib/imap.h
+++ b/lib/imap.h
@@ -34,7 +34,8 @@ typedef enum {
IMAP_LOGIN,
IMAP_STARTTLS,
IMAP_SELECT,
- IMAP_FETCH,
+ IMAP_FETCH_HEADER,
+ IMAP_FETCH_BODY,
IMAP_LOGOUT,
IMAP_LAST /* never used */
} imapstate;
--
1.6.2.5
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2010-03-30