0.8.10claws34
authorChristoph Hohmann <reboot@gmx.ch>
Thu, 20 Feb 2003 21:53:30 +0000 (21:53 +0000)
committerChristoph Hohmann <reboot@gmx.ch>
Thu, 20 Feb 2003 21:53:30 +0000 (21:53 +0000)
* src/imap.c
* src/procheader.c
* src/procheader.h
        IMAP header fetch speedup

Patch submitted by Simon 'corecode' Schubert <corecode@corecode.ath.cx>

* src/imap.c
        Rewrite imap_cmd_gen_recv use sock_getline instead
        of sock_gets to avoid problems with too long reply
        lines

ChangeLog.claws
configure.ac
src/imap.c
src/procheader.c
src/procheader.h

index cd97097fafc2a183ac16c208e149b07218af02cb..fa6bc16ad6fac80c8b14a5fbb24078a50b68d4ab 100644 (file)
@@ -1,3 +1,17 @@
+2003-02-20 [christoph] 0.8.10claws34
+
+       * src/imap.c
+       * src/procheader.c
+       * src/procheader.h
+               IMAP header fetch speedup
+
+       Patch submitted by Simon 'corecode' Schubert <corecode@corecode.ath.cx>
+
+       * src/imap.c
+               Rewrite imap_cmd_gen_recv use sock_getline instead
+               of sock_gets to avoid problems with too long reply
+               lines
+    
 2003-02-20 [colin]     0.8.10claws33
        
        * src/prefs_account.c
index b0e90fab1b1d2da857d1bf2a624f7a60b319731b..0554bdbdfb79776d16cc41eb09cb7a3ea0e4b45b 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=8
 MICRO_VERSION=10
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws33
+EXTRA_VERSION=claws34
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl set $target
index 480dfbe83eb017567ab1bd0101588e310214f8e1..73f6505e138b10e741b5b063eba09b4a44523410 100644 (file)
@@ -266,8 +266,7 @@ static gint imap_cmd_ok             (SockInfo       *sock,
 static void imap_cmd_gen_send  (SockInfo       *sock,
                                 const gchar    *format, ...);
 static gint imap_cmd_gen_recv  (SockInfo       *sock,
-                                gchar          *buf,
-                                gint            size);
+                                gchar         **buf);
 
 /* misc utility functions */
 static gchar *strchr_cpy                       (const gchar    *src,
@@ -293,6 +292,9 @@ static gboolean imap_rename_folder_func             (GNode          *node,
 gint imap_get_num_list                         (Folder         *folder,
                                                 FolderItem     *item,
                                                 GSList        **list);
+GSList *imap_get_msginfos                      (Folder         *folder,
+                                                FolderItem     *item,
+                                                GSList         *msgnum_list);
 MsgInfo *imap_get_msginfo                      (Folder         *folder,
                                                 FolderItem     *item,
                                                 gint            num);
@@ -360,6 +362,7 @@ static void imap_folder_init(Folder *folder, const gchar *name,
 
        folder->get_num_list          = imap_get_num_list;
        folder->get_msginfo           = imap_get_msginfo;
+       folder->get_msginfos          = imap_get_msginfos;
 }
 
 static FolderItem *imap_folder_item_new(Folder *folder)
@@ -2180,7 +2183,7 @@ static gchar *imap_get_header(SockInfo *sock, gchar *cur_pos, gchar **headers,
                g_free(nextline);
        } while (block_len < len);
 
-       debug_print("IMAP4< [contents of RFC822.HEADER]\n");
+       debug_print("IMAP4< [contents of BODY.PEEK[HEADER.FIELDS (...)]]\n");
 
        *headers = g_strndup(cur_pos, len);
        cur_pos += len;
@@ -2289,10 +2292,24 @@ static MsgInfo *imap_parse_envelope(SockInfo *sock, FolderItem *item,
                } else if (!strncmp(cur_pos, "RFC822.SIZE ", 12)) {
                        cur_pos += 12;
                        size = strtol(cur_pos, &cur_pos, 10);
-               } else if (!strncmp(cur_pos, "RFC822.HEADER ", 14)) {
+               } else if (!strncmp(cur_pos, "BODY[HEADER.FIELDS ", 19)) {
                        gchar *headers;
 
-                       cur_pos += 14;
+                       cur_pos += 19;
+                       if (*cur_pos != '(') {
+                               g_warning("*cur_pos != '('\n");
+                               procmsg_msginfo_free(msginfo);
+                               return NULL;
+                       }
+                       cur_pos++;
+                       PARSE_ONE_ELEMENT(')');
+                       if (*cur_pos != ']') {
+                               g_warning("*cur_pos != ']'\n");
+                               procmsg_msginfo_free(msginfo);
+                               return NULL;
+                       }
+                       cur_pos++;
+
                        cur_pos = imap_get_header(sock, cur_pos, &headers,
                                                  line_str);
                        msginfo = procheader_parse_str(headers, flags, FALSE, FALSE);
@@ -2795,7 +2812,7 @@ static gint imap_cmd_delete(SockInfo *sock, const gchar *folder)
 static gint imap_cmd_fetch(SockInfo *sock, guint32 uid, const gchar *filename)
 {
        gint ok;
-       gchar buf[IMAPBUFSIZE];
+       gchar *buf;
        gchar *cur_pos;
        gchar size_str[32];
        glong size_num;
@@ -2804,10 +2821,12 @@ static gint imap_cmd_fetch(SockInfo *sock, guint32 uid, const gchar *filename)
 
        imap_cmd_gen_send(sock, "UID FETCH %d BODY[]", uid);
 
-       while ((ok = imap_cmd_gen_recv(sock, buf, sizeof(buf)))
+       while ((ok = imap_cmd_gen_recv(sock, &buf))
               == IMAP_SUCCESS) {
-               if (buf[0] != '*' || buf[1] != ' ')
+               if (buf[0] != '*' || buf[1] != ' ') {
+                       g_free(buf);
                        return IMAP_ERROR;
+               }
                if (strstr(buf, "FETCH") != NULL)
                        break;
        }
@@ -2815,22 +2834,38 @@ static gint imap_cmd_fetch(SockInfo *sock, guint32 uid, const gchar *filename)
                return ok;
 
        cur_pos = strchr(buf, '{');
-       g_return_val_if_fail(cur_pos != NULL, IMAP_ERROR);
+       if (cur_pos == NULL) {
+               g_free(buf);
+               return IMAP_ERROR;
+       }
        cur_pos = strchr_cpy(cur_pos + 1, '}', size_str, sizeof(size_str));
-       g_return_val_if_fail(cur_pos != NULL, IMAP_ERROR);
+       if (cur_pos == NULL) {
+               g_free(buf);
+               return IMAP_ERROR;
+       }
        size_num = atol(size_str);
 
-       if (*cur_pos != '\0') return IMAP_ERROR;
+       if (*cur_pos != '\0') {
+               g_free(buf);
+               return IMAP_ERROR;
+       }
 
-       if (recv_bytes_write_to_file(sock, size_num, filename) != 0)
+       if (recv_bytes_write_to_file(sock, size_num, filename) != 0) {
+               g_free(buf);
                return IMAP_ERROR;
+       }
 
-       if (imap_cmd_gen_recv(sock, buf, sizeof(buf)) != IMAP_SUCCESS)
+       if (imap_cmd_gen_recv(sock, &buf) != IMAP_SUCCESS) {
+               g_free(buf);
                return IMAP_ERROR;
+       }
 
-       if (buf[0] == '\0' || buf[strlen(buf) - 1] != ')')
+       if (buf[0] == '\0' || buf[strlen(buf) - 1] != ')') {
+               g_free(buf);
                return IMAP_ERROR;
+       }
 
+       g_free(buf);
        ok = imap_cmd_ok(sock, NULL);
 
        return ok;
@@ -2842,7 +2877,7 @@ static gint imap_cmd_append(SockInfo *sock, const gchar *destfolder,
        gint ok;
        gint size;
        gchar *destfolder_;
-       gchar buf[BUFFSIZE];
+       gchar buf[BUFFSIZE], *imapbuf;
        FILE *fp;
 
        g_return_val_if_fail(file != NULL, IMAP_ERROR);
@@ -2855,12 +2890,14 @@ static gint imap_cmd_append(SockInfo *sock, const gchar *destfolder,
        QUOTE_IF_REQUIRED(destfolder_, destfolder);
        imap_cmd_gen_send(sock, "APPEND %s (\\Seen) {%d}", destfolder_, size);
 
-       ok = imap_cmd_gen_recv(sock, buf, sizeof(buf));
-       if (ok != IMAP_SUCCESS || buf[0] != '+' || buf[1] != ' ') {
+       ok = imap_cmd_gen_recv(sock, &imapbuf);
+       if (ok != IMAP_SUCCESS || imapbuf[0] != '+' || imapbuf[1] != ' ') {
                log_warning(_("can't append %s to %s\n"), file, destfolder_);
+               g_free(imapbuf);
                fclose(fp);
                return IMAP_ERROR;
        }
+       g_free(imapbuf);
 
        log_print("IMAP4> %s\n", _("(sending file...)"));
 
@@ -2953,9 +2990,34 @@ static gint imap_cmd_copy(IMAPSession *session,
 
 gint imap_cmd_envelope(SockInfo *sock, guint32 first_uid, guint32 last_uid)
 {
+       static GString *header_fields = NULL;
+
+       if (header_fields == NULL) {
+               const HeaderEntry *headers, *elem;
+
+               headers = procheader_get_headernames(FALSE);
+               header_fields = g_string_new("");
+
+               for (elem = headers; elem->name != NULL; ++elem) {
+                       gint namelen = strlen(elem->name);
+
+                       while(namelen && (elem->name[namelen - 1] == ' ' ||
+                               elem->name[namelen - 1] == ':'))
+                               namelen--;
+                       
+                       if (namelen == 0)
+                               continue;
+
+                       g_string_sprintfa(header_fields, "%s%.*s",
+                                       header_fields->str[0] != '\0' ? " " : "",
+                                       namelen, elem->name);
+               }
+       }
+       
        imap_cmd_gen_send
-               (sock, "UID FETCH %d:%d (UID FLAGS RFC822.SIZE RFC822.HEADER)",
-                first_uid, last_uid);
+               (sock, "UID FETCH %d:%d (UID FLAGS RFC822.SIZE BODY.PEEK[HEADER.FIELDS (%s)])",
+                first_uid, last_uid,
+                header_fields->str);
 
        return IMAP_SUCCESS;
 }
@@ -2993,11 +3055,11 @@ static gint imap_cmd_expunge(SockInfo *sock)
 static gint imap_cmd_ok(SockInfo *sock, GPtrArray *argbuf)
 {
        gint ok;
-       gchar buf[IMAPBUFSIZE];
+       gchar *buf;
        gint cmd_num;
        gchar cmd_status[IMAPBUFSIZE];
 
-       while ((ok = imap_cmd_gen_recv(sock, buf, sizeof(buf)))
+       while ((ok = imap_cmd_gen_recv(sock, &buf))
               == IMAP_SUCCESS) {
                if (buf[0] == '*' && buf[1] == ' ') {
                        if (argbuf)
@@ -3011,10 +3073,14 @@ static gint imap_cmd_ok(SockInfo *sock, GPtrArray *argbuf)
                         !strcmp(cmd_status, "OK")) {
                        if (argbuf)
                                g_ptr_array_add(argbuf, g_strdup(buf));
+                       g_free(buf);
                        return IMAP_SUCCESS;
-               } else
+               } else {
+                       g_free(buf);
                        return IMAP_ERROR;
+               }
        }
+       g_free(buf);
 
        return ok;
 }
@@ -3042,14 +3108,14 @@ static void imap_cmd_gen_send(SockInfo *sock, const gchar *format, ...)
        sock_write(sock, buf, strlen(buf));
 }
 
-static gint imap_cmd_gen_recv(SockInfo *sock, gchar *buf, gint size)
+static gint imap_cmd_gen_recv(SockInfo *sock, gchar **buf)
 {
-       if (sock_gets(sock, buf, size) == -1)
+       if ((*buf = sock_getline(sock)) == NULL)
                return IMAP_SOCKET;
 
-       strretchomp(buf);
+       strretchomp(*buf);
 
-       log_print("IMAP4< %s\n", buf);
+       log_print("IMAP4< %s\n", *buf);
 
        return IMAP_SUCCESS;
 }
@@ -3375,7 +3441,7 @@ gint imap_get_num_list(Folder *folder, FolderItem *_item, GSList **msgnum_list)
        if(item->lastuid) {
                cmdbuf = g_strdup_printf("UID FETCH %d:* (UID)", (item->lastuid + 1));
        } else {
-               cmdbuf = g_strdup("FETCH 1:* (UID)");
+               cmdbuf = g_strdup("UID SEARCH ALL");
        }
        imap_cmd_gen_send(SESSION(session)->sock, cmdbuf);
        g_free(cmdbuf);
@@ -3391,17 +3457,33 @@ gint imap_get_num_list(Folder *folder, FolderItem *_item, GSList **msgnum_list)
        debug_print("Got %d uids from cache\n", g_slist_length(item->uid_list));
        for(i = 0; i < argbuf->len; i++) {
                int ret, msgidx, msgnum;
-       
-               if((ret = sscanf(g_ptr_array_index(argbuf, i), "%d FETCH (UID %d)", &msgidx, &msgnum)) == 2) {
-                       if(msgnum > lastuid_old) {
-                               *msgnum_list = g_slist_prepend(*msgnum_list, GINT_TO_POINTER(msgnum));
-                               item->uid_list = g_slist_prepend(item->uid_list, GINT_TO_POINTER(msgnum));
-                               nummsgs++;
-
-                               if(msgnum > item->lastuid)
-                                       item->lastuid = msgnum;
-                       }
+
+               if (!strncmp(g_ptr_array_index(argbuf, i), "SEARCH ", 7)) {
+                       gchar **p, **list = g_strsplit(g_ptr_array_index(argbuf, i) + 7, " ", 0);
+
+                       for (p = list; *p != NULL; ++p)
+                               if (sscanf(*p, "%d", &msgnum) == 1 && msgnum > lastuid_old) {
+                                       *msgnum_list = g_slist_prepend(*msgnum_list, GINT_TO_POINTER(msgnum));
+                                       item->uid_list = g_slist_prepend(item->uid_list, GINT_TO_POINTER(msgnum));
+                                       nummsgs++;
+               
+                                       if(msgnum > item->lastuid)
+                                               item->lastuid = msgnum;
+                               }
+
+                       g_strfreev(list);
+                               
+               } else if((ret = sscanf(g_ptr_array_index(argbuf, i),
+                               "%d FETCH (UID %d)", &msgidx, &msgnum)) == 2 &&
+                               msgnum > lastuid_old) {
+                       *msgnum_list = g_slist_prepend(*msgnum_list, GINT_TO_POINTER(msgnum));
+                       item->uid_list = g_slist_prepend(item->uid_list, GINT_TO_POINTER(msgnum));
+                       nummsgs++;
+
+                       if(msgnum > item->lastuid)
+                               item->lastuid = msgnum;
                }
+               
        }
 
        dir = folder_item_get_path((FolderItem *)item);
@@ -3440,6 +3522,73 @@ static MsgInfo *imap_parse_msg(const gchar *file, FolderItem *item)
        return msginfo;
 }
 
+static int compare_uint(gconstpointer a, gconstpointer b)
+{
+       return a-b;
+}
+
+GSList *imap_get_msginfos(Folder *folder, FolderItem *item, GSList *msgnum_list)
+{
+       IMAPSession *session;
+       GSList *sorted_list, *elem, *ret = NULL;
+       gint ok, startnum, lastnum;
+
+       g_return_val_if_fail(folder != NULL, NULL);
+       g_return_val_if_fail(item != NULL, NULL);
+       g_return_val_if_fail(msgnum_list != NULL, NULL);
+
+       session = imap_session_get(folder);
+       g_return_val_if_fail(session != NULL, NULL);
+
+       ok = imap_select(session, IMAP_FOLDER(folder), item->path,
+                        NULL, NULL, NULL, NULL);
+       if (ok != IMAP_SUCCESS)
+               return NULL;
+
+       sorted_list = g_slist_sort(g_slist_copy(msgnum_list), compare_uint);
+
+       startnum = lastnum = GPOINTER_TO_INT(sorted_list->data);
+
+       for (elem = sorted_list;; elem = g_slist_next(elem)) {
+               guint num;
+
+               if (elem)
+                       num = GPOINTER_TO_INT(elem->data);
+
+               if (num > lastnum + 1 || elem == NULL) {
+                       if (!(item->stype == F_QUEUE || item->stype == F_DRAFT)) {
+                               ret = g_slist_concat(ret,
+                                       imap_get_uncached_messages(
+                                               session, item, startnum, lastnum));
+                       } else {
+                               int i;
+                               for (i = startnum; i <= lastnum; ++i) {
+                                       gchar *file;
+                       
+                                       file = imap_fetch_msg(folder, item, i);
+                                       if (file != NULL) {
+                                               MsgInfo *msginfo = imap_parse_msg(file, item);
+                                               if (msginfo != NULL) {
+                                                       msginfo->msgnum = i;
+                                                       ret = g_slist_append(ret, msginfo);
+                                               }
+                                               g_free(file);
+                                       }
+                               }
+                       }
+
+                       if (elem == NULL)
+                               break;
+
+                       startnum = num;
+               }
+               lastnum = num;
+       }
+
+       g_slist_free(sorted_list);
+
+       return ret;
+}
 
 MsgInfo *imap_get_msginfo(Folder *folder, FolderItem *item, gint uid)
 {
index a72ac865d45fe63a9333dca9eb7ae6f34ef1d589..9bd66a78afd6140ceecf201209310b297c57806c 100644 (file)
@@ -486,53 +486,58 @@ enum
        H_RETURN_RECEIPT_TO = 16
 };
 
+static HeaderEntry hentry_full[] = {{"Date:",          NULL, FALSE},
+                                  {"From:",            NULL, TRUE},
+                                  {"To:",              NULL, TRUE},
+                                  {"Cc:",              NULL, TRUE},
+                                  {"Newsgroups:",      NULL, TRUE},
+                                  {"Subject:",         NULL, TRUE},
+                                  {"Message-Id:",      NULL, FALSE},
+                                  {"References:",      NULL, FALSE},
+                                  {"In-Reply-To:",     NULL, FALSE},
+                                  {"Content-Type:",    NULL, FALSE},
+                                  {"Seen:",            NULL, FALSE},
+                                  {"Status:",          NULL, FALSE},
+                                  {"X-Status:",        NULL, FALSE},
+                                  {"From ",            NULL, FALSE},
+                                  {"X-Face:",          NULL, FALSE},
+                                  {"Disposition-Notification-To:", NULL, FALSE},
+                                  {"Return-Receipt-To:", NULL, FALSE},
+                                  {NULL,               NULL, FALSE}};
+
+static HeaderEntry hentry_short[] = {{"Date:",         NULL, FALSE},
+                                   {"From:",           NULL, TRUE},
+                                   {"To:",             NULL, TRUE},
+                                   {"Cc:",             NULL, TRUE},
+                                   {"Newsgroups:",     NULL, TRUE},
+                                   {"Subject:",        NULL, TRUE},
+                                   {"Message-Id:",     NULL, FALSE},
+                                   {"References:",     NULL, FALSE},
+                                   {"In-Reply-To:",    NULL, FALSE},
+                                   {"Content-Type:",   NULL, FALSE},
+                                   {"Seen:",           NULL, FALSE},
+                                   {"Status:",         NULL, FALSE},
+                                   {"X-Status:",       NULL, FALSE},
+                                   {"From ",           NULL, FALSE},
+                                   {NULL,              NULL, FALSE}};
+
+const HeaderEntry* procheader_get_headernames(gboolean full)
+{
+       return full ? hentry_full : hentry_short;
+}
+
 MsgInfo *procheader_parse_stream(FILE *fp, MsgFlags flags, gboolean full, 
                                 gboolean decrypted)
 {
-       static HeaderEntry hentry_full[] = {{"Date:",           NULL, FALSE},
-                                          {"From:",            NULL, TRUE},
-                                          {"To:",              NULL, TRUE},
-                                          {"Cc:",              NULL, TRUE},
-                                          {"Newsgroups:",      NULL, TRUE},
-                                          {"Subject:",         NULL, TRUE},
-                                          {"Message-Id:",      NULL, FALSE},
-                                          {"References:",      NULL, FALSE},
-                                          {"In-Reply-To:",     NULL, FALSE},
-                                          {"Content-Type:",    NULL, FALSE},
-                                          {"Seen:",            NULL, FALSE},
-                                          {"Status:",          NULL, FALSE},
-                                          {"X-Status:",        NULL, FALSE},
-                                          {"From ",            NULL, FALSE},
-                                          {"X-Face:",          NULL, FALSE},
-                                          {"Disposition-Notification-To:", NULL, FALSE},
-                                          {"Return-Receipt-To:", NULL, FALSE},
-                                          {NULL,               NULL, FALSE}};
-
-       static HeaderEntry hentry_short[] = {{"Date:",          NULL, FALSE},
-                                           {"From:",           NULL, TRUE},
-                                           {"To:",             NULL, TRUE},
-                                           {"Cc:",             NULL, TRUE},
-                                           {"Newsgroups:",     NULL, TRUE},
-                                           {"Subject:",        NULL, TRUE},
-                                           {"Message-Id:",     NULL, FALSE},
-                                           {"References:",     NULL, FALSE},
-                                           {"In-Reply-To:",    NULL, FALSE},
-                                           {"Content-Type:",   NULL, FALSE},
-                                           {"Seen:",           NULL, FALSE},
-                                           {"Status:",         NULL, FALSE},
-                                           {"X-Status:",       NULL, FALSE},
-                                           {"From ",           NULL, FALSE},
-                                           {NULL,              NULL, FALSE}};
-
        MsgInfo *msginfo;
        gchar buf[BUFFSIZE], tmp[BUFFSIZE];
        gchar *reference = NULL;
        gchar *p;
        gchar *hp;
-       HeaderEntry *hentry;
+       const HeaderEntry *hentry;
        gint hnum;
 
-       hentry = full ? hentry_full : hentry_short;
+       hentry = procheader_get_headernames(full);
 
        if (MSG_IS_QUEUED(flags) || MSG_IS_DRAFT(flags)) {
                while (fgets(buf, sizeof(buf), fp) != NULL)
index fbf70dd8286ad1f6180d577f9acc5c6e57d143a0..71f5b2d9eb2ee3237f49036b7d4b9c44c0bbf504 100644 (file)
@@ -58,6 +58,8 @@ void procheader_header_list_destroy           (GSList         *hlist);
 void procheader_header_array_destroy           (GPtrArray      *harray);
 void procheader_header_free                    (Header         *header);
 
+const HeaderEntry* procheader_get_headernames  (gboolean       full);
+
 void procheader_get_header_fields      (FILE           *fp,
                                         HeaderEntry     hentry[]);
 MsgInfo *procheader_parse_file         (const gchar    *file,