* More license declarations
[citadel.git] / citadel / modules / imap / imap_fetch.c
index 3cd92cb32717722bd7f9e0ca19fad11d651a7137..19d92dafd4422147f5ab0ca77250c9620e3b9971 100644 (file)
@@ -4,6 +4,21 @@
  * Implements the FETCH command in IMAP.
  * This is a good example of the protocol's gratuitous complexity.
  *
+ * Copyright (c) 2001-2009 by the citadel.org team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 
@@ -49,6 +64,7 @@
 #include "imap_tools.h"
 #include "imap_fetch.h"
 #include "genstamp.h"
+#include "ctdl_module.h"
 
 
 
@@ -173,8 +189,9 @@ void imap_fetch_rfc822(long msgnum, char *whichfmt) {
                CC->redirect_len = 0;
                CC->redirect_alloc = SIZ;
                CtdlOutputMsg(msgnum, MT_RFC822,
-                       (need_body ? HEADERS_ALL : HEADERS_ONLY),
-                       0, 1, NULL);
+                       (need_body ? HEADERS_ALL : HEADERS_FAST),
+                       0, 1, NULL, SUPPRESS_ENV_TO
+               );
                if (!need_body) cprintf("\r\n");        /* extra trailing newline */
                IMAP->cached_rfc822_data = CC->redirect_buffer;
                IMAP->cached_rfc822_len = CC->redirect_len;
@@ -218,7 +235,7 @@ void imap_fetch_rfc822(long msgnum, char *whichfmt) {
                text_size = 0;
        }
 
-       lprintf(CTDL_DEBUG, 
+       CtdlLogPrintf(CTDL_DEBUG, 
                "RFC822: headers=" SIZE_T_FMT 
                ", text=" SIZE_T_FMT
                ", total=" SIZE_T_FMT "\n",
@@ -260,7 +277,7 @@ void imap_fetch_rfc822(long msgnum, char *whichfmt) {
  */
 void imap_load_part(char *name, char *filename, char *partnum, char *disp,
                    void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
-                   void *cbuserdata)
+                   char *cbid, void *cbuserdata)
 {
        char mbuf2[SIZ];
        char *desired_section;
@@ -347,7 +364,7 @@ void imap_output_envelope_from(struct CtdlMessage *msg) {
 
 /*
  * Output an envelope address (or set of addresses) in the official,
- * convuluted, braindead format.  (Note that we can't use this for
+ * convoluted, braindead format.  (Note that we can't use this for
  * the "From" address because its data may come from a number of different
  * fields.  But we can use it for "To" and possibly others.
  */
@@ -529,7 +546,8 @@ void imap_strip_headers(char *section) {
 
        ptr = CC->redirect_buffer;
        ok = 0;
-       while ( (done_headers == 0) && (ptr = memreadline(ptr, buf, sizeof buf), *ptr != 0) ) {
+       do {
+               ptr = memreadline(ptr, buf, sizeof buf);
                if (!isspace(buf[0])) {
                        ok = 0;
                        if (doing_headers == 0) ok = 1;
@@ -555,7 +573,8 @@ void imap_strip_headers(char *section) {
                if (IsEmptyStr(buf)) done_headers = 1;
                if (buf[0]=='\r') done_headers = 1;
                if (buf[0]=='\n') done_headers = 1;
-       }
+               if (*ptr == 0) done_headers = 1;
+       } while (!done_headers);
 
        strcat(boiled_headers, "\r\n");
 
@@ -586,23 +605,10 @@ void imap_fetch_body(long msgnum, char *item, int is_peek) {
        if (strchr(section, '[') != NULL) {
                stripallbut(section, '[', ']');
        }
-       lprintf(CTDL_DEBUG, "Section is: %s%s\n", 
+       CtdlLogPrintf(CTDL_DEBUG, "Section is: %s%s\n", 
                section, 
                IsEmptyStr(section) ? "(empty)" : "");
 
-       /*
-        * We used to have this great optimization in place that would avoid
-        * fetching the entire RFC822 message from disk if the client was only
-        * asking for the headers.  Unfortunately, fetching only the Citadel
-        * headers omits "Content-type:" and this behavior breaks the iPhone
-        * email client.  So we have to fetch the whole message from disk.  The
-        *
-        *      if (!strncasecmp(section, "HEADER", 6)) {
-        *              need_body = 0;
-        *      }
-        *
-        */
-
        /* Burn the cache if we don't have the same section of the 
         * same message again.
         */
@@ -633,7 +639,7 @@ void imap_fetch_body(long msgnum, char *item, int is_peek) {
                is_partial = 1;
        }
        if (is_partial == 0) strcpy(partial, "");
-       /* if (!IsEmptyStr(partial)) lprintf(CTDL_DEBUG, "Partial is %s\n", partial); */
+       /* if (!IsEmptyStr(partial)) CtdlLogPrintf(CTDL_DEBUG, "Partial is %s\n", partial); */
 
        if (IMAP->cached_body == NULL) {
                CC->redirect_buffer = malloc(SIZ);
@@ -650,11 +656,11 @@ void imap_fetch_body(long msgnum, char *item, int is_peek) {
        }
 
        else if ( (!strcmp(section, "1")) && (msg->cm_format_type != 4) ) {
-               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_NONE, 0, 1);
+               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_NONE, 0, 1, SUPPRESS_ENV_TO);
        }
 
        else if (!strcmp(section, "")) {
-               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1);
+               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1, SUPPRESS_ENV_TO);
        }
 
        /*
@@ -662,7 +668,11 @@ void imap_fetch_body(long msgnum, char *item, int is_peek) {
         * fields, strip it down.
         */
        else if (!strncasecmp(section, "HEADER", 6)) {
-               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ONLY, 0, 1);
+               /* This used to work with HEADERS_FAST, but then Apple got stupid with their
+                * IMAP library and this broke Mail.App and iPhone Mail, so we had to change it
+                * to HEADERS_ONLY so the trendy hipsters with their iPhones can read mail.
+                */
+               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ONLY, 0, 1, SUPPRESS_ENV_TO);
                imap_strip_headers(section);
        }
 
@@ -670,7 +680,7 @@ void imap_fetch_body(long msgnum, char *item, int is_peek) {
         * Strip it down if the client asked for everything _except_ headers.
         */
        else if (!strncasecmp(section, "TEXT", 4)) {
-               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_NONE, 0, 1);
+               CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_NONE, 0, 1, SUPPRESS_ENV_TO);
        }
 
        /*
@@ -727,7 +737,7 @@ void imap_fetch_body(long msgnum, char *item, int is_peek) {
 void imap_fetch_bodystructure_pre(
                char *name, char *filename, char *partnum, char *disp,
                void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
-               void *cbuserdata
+               char *cbid, void *cbuserdata
                ) {
 
        cprintf("(");
@@ -741,7 +751,7 @@ void imap_fetch_bodystructure_pre(
 void imap_fetch_bodystructure_post(
                char *name, char *filename, char *partnum, char *disp,
                void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
-               void *cbuserdata
+               char *cbid, void *cbuserdata
                ) {
 
        char subtype[128];
@@ -767,7 +777,7 @@ void imap_fetch_bodystructure_post(
 void imap_fetch_bodystructure_part(
                char *name, char *filename, char *partnum, char *disp,
                void *content, char *cbtype, char *cbcharset, size_t length, char *encoding,
-               void *cbuserdata
+               char *cbid, void *cbuserdata
                ) {
 
        int have_cbtype = 0;
@@ -845,12 +855,11 @@ void imap_fetch_bodystructure_part(
        /* More gratuitous complexity */
        if ((!strcasecmp(cbmaintype, "MESSAGE"))
           && (!strcasecmp(cbsubtype, "RFC822"))) {
-               /* FIXME
-                     A body type of type MESSAGE and subtype RFC822
-                     contains, immediately after the basic fields, the
-                     envelope structure, body structure, and size in
-                     text lines of the encapsulated message.
-               */
+               /* FIXME: message/rfc822 also needs to output the envelope structure,
+                * body structure, and line count of the encapsulated message.  Fortunately
+                * there are not yet any clients depending on this, so we can get away
+                * with not implementing it for now.
+                */
        }
 
        /* MD5 value of body part; we can get away with NIL'ing this */
@@ -915,7 +924,7 @@ void imap_fetch_bodystructure (long msgnum, char *item,
                CC->redirect_buffer = malloc(SIZ);
                CC->redirect_len = 0;
                CC->redirect_alloc = SIZ;
-               CtdlOutputPreLoadedMsg(msg, MT_RFC822, 0, 0, 1);
+               CtdlOutputPreLoadedMsg(msg, MT_RFC822, 0, 0, 1, SUPPRESS_ENV_TO);
                rfc822 = CC->redirect_buffer;
                rfc822_len = CC->redirect_len;
                CC->redirect_buffer = NULL;
@@ -923,12 +932,13 @@ void imap_fetch_bodystructure (long msgnum, char *item,
                CC->redirect_alloc = 0;
 
                ptr = rfc822;
-               while (ptr = memreadline(ptr, buf, sizeof buf), *ptr != 0) {
+               do {
+                       ptr = memreadline(ptr, buf, sizeof buf);
                        ++lines;
                        if ((IsEmptyStr(buf)) && (rfc822_body == NULL)) {
                                rfc822_body = ptr;
                        }
-               }
+               } while (*ptr != 0);
 
                rfc822_headers_len = rfc822_body - rfc822;
                rfc822_body_len = rfc822_len - rfc822_headers_len;