return (mutt_mktime (&t, 0) + tz);
}
-/* imap_read_bytes: read bytes bytes from server into file */
-int imap_read_bytes (FILE *fp, CONNECTION *conn, long bytes)
+/* imap_read_literal: read bytes bytes from server into file. Not explicitly
+ * buffered, relies on FILE buffering. NOTE: strips \r from \r\n.
+ * Apparently even literals use \r\n-terminated strings ?! */
+int imap_read_literal (FILE* fp, CONNECTION* conn, long bytes)
{
long pos;
- long len;
- char buf[LONG_STRING];
+ char c;
+
+ int r = 0;
- for (pos = 0; pos < bytes; )
+ dprint (2, (debugfile, "imap_read_literal: reading %ld bytes\n", bytes));
+
+ for (pos = 0; pos < bytes; pos++)
{
- len = mutt_socket_readln_d (buf, sizeof (buf), conn, IMAP_LOG_HDR);
- if (len < 0)
+ if (mutt_socket_readchar (conn, &c) != 1)
+ {
+ dprint (1, (debugfile, "imap_read_literal: error during read, %ld bytes read\n", pos));
return -1;
+ }
+
+ if (r == 1 && c != '\n')
+ fputc ('\r', fp);
- pos += len;
- fputs (buf, fp);
- fputs ("\n", fp);
+ if (c == '\r')
+ {
+ r = 1;
+ continue;
+ }
+ else
+ r = 0;
+
+ fputc (c, fp);
+#ifdef DEBUG
+ if (debuglevel >= IMAP_LOG_LTRL)
+ fputc (c, debugfile);
+#endif
}
return 0;
/* logging levels */
#define IMAP_LOG_CMD 2
-#define IMAP_LOG_HDR 3
-#define IMAP_LOG_BODY 4
+#define IMAP_LOG_LTRL 4
#define IMAP_LOG_PASS 5
/* number of entries in the hash table */
time_t imap_parse_date (char* s);
int imap_parse_list_response(CONNECTION* conn, char* buf, int buflen,
char** name, int* noselect, int* noinferiors, char* delim);
-int imap_read_bytes (FILE* fp, CONNECTION* conn, long bytes);
+int imap_read_literal (FILE* fp, CONNECTION* conn, long bytes);
int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint);
void imap_logout (CONNECTION* conn);
return -1;
unlink (tempfile);
+ /* make sure context has room to hold the mailbox */
+ while ((msgend) >= ctx->hdrmax)
+ mx_alloc_memory (ctx);
+
for (msgno = msgbegin; msgno <= msgend ; msgno++)
{
mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1,
if (buf[0] == '*')
{
rc = msg_fetch_header (ctx, h, buf, fp);
+ /* make sure we don't get remnants from older larger message headers */
+ fputs ("\n\n", fp);
+
if ((rc == -1 && imap_handle_untagged (CTX_DATA, buf)) || rc == -2)
{
imap_free_header_data ((void**) &(h->data));
}
/* update context with message header */
+
ctx->hdrs[ctx->msgcount] = mutt_new_header ();
ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
while ((msgno + 1) >= fetchlast && mutt_strncmp (seq, buf, SEQLEN) != 0);
/* in case we get new mail while fetching the headers */
- if (((IMAP_DATA *) ctx->data)->status == IMAP_NEW_MAIL)
+ if (CTX_DATA->status == IMAP_NEW_MAIL)
{
- msgend = ((IMAP_DATA *) ctx->data)->newMailCount - 1;
- while ((msgend + 1) > ctx->hdrmax)
- mx_alloc_memory (ctx);
- ((IMAP_DATA *) ctx->data)->status = 0;
+ msgend = CTX_DATA->newMailCount - 1;
+ while ((msgend) >= ctx->hdrmax)
+ mx_alloc_memory (ctx);
+ CTX_DATA->status = 0;
}
}
int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
{
- char seq[8];
+ char seq[SEQLEN+1];
char buf[LONG_STRING];
char path[_POSIX_PATH_MAX];
char *pc;
long bytes;
- int pos, len;
IMAP_CACHE *cache;
/* see if we already have the message in our cache */
imap_error ("imap_fetch_message()", buf);
goto bail;
}
- for (pos = 0; pos < bytes; )
- {
- len = mutt_socket_readln_d (buf, sizeof (buf), CTX_DATA->conn,
- IMAP_LOG_BODY);
- if (len < 0)
- goto bail;
- pos += len;
- fputs (buf, msg->fp);
- fputs ("\n", msg->fp);
- }
- if (mutt_socket_readln_d (buf, sizeof (buf), CTX_DATA->conn,
- IMAP_LOG_BODY) < 0)
+ if (imap_read_literal (msg->fp, CTX_DATA->conn, bytes) < 0)
+ goto bail;
+ /* pick up trailing line */
+ if (mutt_socket_readln (buf, sizeof (buf), CTX_DATA->conn) < 0)
goto bail;
pc = buf;
}
if (imap_get_literal_count (buf, &bytes) < 0)
return rc;
- imap_read_bytes (fp, CTX_DATA->conn, bytes);
+ imap_read_literal (fp, CTX_DATA->conn, bytes);
/* we may have other fields of the FETCH _after_ the literal
* (eg Domino puts FLAGS here). Nothing wrong with that, either.
char ch;
int i;
- for (i = 0; i < buflen; i++)
+ for (i = 0; i < buflen-1; i++)
{
if (mutt_socket_readchar (conn, &ch) != 1)
- return (-1);
+ {
+ dprint (1, (debugfile, "mutt_socket_readln_d: read error"));
+ buf[i] = '\0';
+ return -1;
+ }
if (ch == '\n')
break;
buf[i] = ch;
}
- if (i)
+
+ /* strip \r from \r\n termination */
+ if (i && buf[i-1] == '\r')
buf[i-1] = '\0';
else
buf[i] = '\0';
dprint (dbg, (debugfile, "< %s\n", buf));
- return (i + 1);
+ return i+1;
}
CONNECTION* mutt_socket_find (const IMAP_MBOX* mx, int newconn)
* form, such as &ACY- (instead of &-) or &AMA-&AMA- (instead
* of &AMAAwA-).
*/
-char *utf7_to_utf8 (const char *u7, size_t u7len, char **u8, size_t *u8len)
+static char *utf7_to_utf8 (const char *u7, size_t u7len, char **u8,
+ size_t *u8len)
{
char *buf, *p;
int b, ch, k;
* Unicode characters above U+FFFF are replaced by U+FFFE.
* If input data is invalid, return 0 and don't store anything.
*/
-char *utf8_to_utf7 (const char *u8, size_t u8len, char **u7, size_t *u7len)
+static char *utf8_to_utf7 (const char *u8, size_t u8len, char **u7,
+ size_t *u7len)
{
char *buf, *p;
int ch;