FolderItem item;
guint lastuid;
+ guint uid_next;
GSList *uid_list;
};
FolderItem *item,
guint32 first_uid,
guint32 last_uid);
-static GSList *imap_delete_cached_messages (GSList *mlist,
- FolderItem *item,
- guint32 first_uid,
- guint32 last_uid);
static void imap_delete_all_cached_messages (FolderItem *item);
#if USE_OPENSSL
gint *recent,
gint *unseen,
guint32 *uid_validity);
-static gint imap_get_uid (IMAPSession *session,
- gint msgnum,
- guint32 *uid);
static gint imap_status (IMAPSession *session,
IMAPFolder *folder,
const gchar *path,
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,
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);
gboolean imap_check_msgnum_validity (Folder *folder,
FolderItem *item);
+FolderClass imap_class =
+{
+ F_IMAP,
+ "imap",
+ "IMAP4",
+
+ /* Folder functions */
+ imap_folder_new,
+ imap_folder_destroy,
+ imap_scan_tree,
+ imap_create_tree,
+
+ /* FolderItem functions */
+ imap_folder_item_new,
+ imap_folder_item_destroy,
+ imap_create_folder,
+ imap_rename_folder,
+ imap_remove_folder,
+ imap_get_num_list,
+ NULL,
+ NULL,
+ NULL,
+ imap_check_msgnum_validity,
+
+ /* Message functions */
+ imap_get_msginfo,
+ imap_get_msginfos,
+ imap_fetch_msg,
+ imap_add_msg,
+ imap_move_msg,
+ NULL,
+ imap_copy_msg,
+ NULL,
+ imap_remove_msg,
+ imap_remove_msgs,
+ imap_remove_all_msg,
+ imap_is_msg_changed,
+ NULL,
+};
+
+FolderClass *imap_get_class()
+{
+ return &imap_class;
+}
+
Folder *imap_folder_new(const gchar *name, const gchar *path)
{
Folder *folder;
folder = (Folder *)g_new0(IMAPFolder, 1);
+ folder->class = &imap_class;
imap_folder_init(folder, name, path);
return folder;
static void imap_folder_init(Folder *folder, const gchar *name,
const gchar *path)
{
- folder->type = F_IMAP;
-
folder_remote_folder_init((Folder *)folder, name, path);
-
-/*
- folder->get_msg_list = imap_get_msg_list;
-*/
- folder->item_new = imap_folder_item_new;
- folder->item_destroy = imap_folder_item_destroy;
- folder->fetch_msg = imap_fetch_msg;
- folder->add_msg = imap_add_msg;
- folder->move_msg = imap_move_msg;
-/*
- folder->move_msgs_with_dest = imap_move_msgs_with_dest;
-*/
- folder->copy_msg = imap_copy_msg;
-/*
- folder->copy_msgs_with_dest = imap_copy_msgs_with_dest;
-*/
- folder->remove_msg = imap_remove_msg;
- folder->remove_msgs = imap_remove_msgs;
- folder->remove_all_msg = imap_remove_all_msg;
- folder->is_msg_changed = imap_is_msg_changed;
-/*
- folder->scan = imap_scan_folder;
-*/
- folder->scan_tree = imap_scan_tree;
- folder->create_tree = imap_create_tree;
- folder->create_folder = imap_create_folder;
- folder->rename_folder = imap_rename_folder;
- folder->remove_folder = imap_remove_folder;
- folder->destroy = imap_folder_destroy;
- folder->check_msgnum_validity = imap_check_msgnum_validity;
-
- folder->get_num_list = imap_get_num_list;
- folder->get_msginfo = imap_get_msginfo;
}
static FolderItem *imap_folder_item_new(Folder *folder)
item = g_new0(IMAPFolderItem, 1);
item->lastuid = 0;
+ item->uid_next = 0;
item->uid_list = NULL;
return (FolderItem *)item;
IMAPFolderItem *item = (IMAPFolderItem *)node->data;
item->lastuid = 0;
+ item->uid_next = 0;
g_slist_free(item->uid_list);
item->uid_list = NULL;
gushort port;
g_return_val_if_fail(folder != NULL, NULL);
- g_return_val_if_fail(folder->type == F_IMAP, NULL);
+ g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, NULL);
g_return_val_if_fail(folder->account != NULL, NULL);
#if USE_OPENSSL
SSLType ssl_type;
port = account->set_imapport ? account->imapport
- : account->ssl_imap ? IMAPS_PORT : IMAP4_PORT;
- ssl_type = account->ssl_imap ? TRUE : FALSE;
+ : account->ssl_imap == SSL_TUNNEL ? IMAPS_PORT : IMAP4_PORT;
+ ssl_type = account->ssl_imap;
#else
port = account->set_imapport ? account->imapport
: IMAP4_PORT;
}
}
-#define THROW goto catch
-
-GSList *imap_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache)
-{
- GSList *mlist = NULL;
- IMAPSession *session;
- gint ok, exists = 0, recent = 0, unseen = 0;
- guint32 uid_validity = 0;
- guint32 first_uid = 0, last_uid = 0, begin;
-
- g_return_val_if_fail(folder != NULL, NULL);
- g_return_val_if_fail(item != NULL, NULL);
- g_return_val_if_fail(folder->type == F_IMAP, NULL);
- g_return_val_if_fail(folder->account != NULL, NULL);
-
- session = imap_session_get(folder);
-
- if (!session) {
- mlist = procmsg_read_cache(item, FALSE);
- item->last_num = procmsg_get_last_num_in_msg_list(mlist);
- procmsg_set_flags(mlist, item);
- return mlist;
- }
-
- ok = imap_select(session, IMAP_FOLDER(folder), item->path,
- &exists, &recent, &unseen, &uid_validity);
- if (ok != IMAP_SUCCESS) THROW;
- if (exists > 0) {
- ok = imap_get_uid(session, 1, &first_uid);
- if (ok != IMAP_SUCCESS) THROW;
- if (1 != exists) {
- ok = imap_get_uid(session, exists, &last_uid);
- if (ok != IMAP_SUCCESS) THROW;
- } else
- last_uid = first_uid;
- } else {
- imap_delete_all_cached_messages(item);
- return NULL;
- }
-
- if (use_cache) {
- guint32 cache_last;
-
- mlist = procmsg_read_cache(item, FALSE);
- procmsg_set_flags(mlist, item);
- cache_last = procmsg_get_last_num_in_msg_list(mlist);
-
- /* calculating the range of envelope to get */
- if (item->mtime != uid_validity) {
- /* mailbox is changed (get all) */
- begin = first_uid;
- } else if (last_uid < cache_last) {
- /* mailbox is changed (get all) */
- begin = first_uid;
- } else if (last_uid == cache_last) {
- /* mailbox unchanged (get none)*/
- begin = 0;
- } else {
- begin = cache_last + 1;
- }
-
- item->mtime = uid_validity;
-
- if (first_uid > 0 && last_uid > 0) {
- mlist = imap_delete_cached_messages(mlist, item,
- 0, first_uid - 1);
- mlist = imap_delete_cached_messages(mlist, item,
- last_uid + 1,
- UINT_MAX);
- }
- if (begin > 0)
- mlist = imap_delete_cached_messages(mlist, item,
- begin, UINT_MAX);
- } else {
- imap_delete_all_cached_messages(item);
- begin = first_uid;
- }
-
- if (begin > 0 && begin <= last_uid) {
- GSList *newlist;
- newlist = imap_get_uncached_messages(session, item,
- begin, last_uid);
- mlist = g_slist_concat(mlist, newlist);
- }
-
- item->last_num = last_uid;
-
-catch:
- return mlist;
-}
-
-#undef THROW
-
gchar *imap_fetch_msg(Folder *folder, FolderItem *item, gint uid)
{
gchar *path, *filename;
gint ok;
g_return_val_if_fail(folder != NULL, -1);
- g_return_val_if_fail(folder->type == F_IMAP, -1);
+ g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, -1);
g_return_val_if_fail(dest != NULL, -1);
g_return_val_if_fail(msginfo != NULL, -1);
gchar *dir;
g_return_val_if_fail(folder != NULL, -1);
- g_return_val_if_fail(folder->type == F_IMAP, -1);
+ g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, -1);
g_return_val_if_fail(item != NULL, -1);
session = imap_session_get(folder);
guint32 uid;
g_return_val_if_fail(folder != NULL, -1);
- g_return_val_if_fail(folder->type == F_IMAP, -1);
+ g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, -1);
g_return_val_if_fail(item != NULL, -1);
g_return_val_if_fail(msglist != NULL, -1);
g_return_val_if_fail(session != NULL, NULL);
g_return_val_if_fail(item != NULL, NULL);
g_return_val_if_fail(item->folder != NULL, NULL);
- g_return_val_if_fail(item->folder->type == F_IMAP, NULL);
+ g_return_val_if_fail(FOLDER_CLASS(item->folder) == &imap_class, NULL);
g_return_val_if_fail(first_uid <= last_uid, NULL);
if (imap_cmd_envelope(SESSION(session)->sock, first_uid, last_uid)
return newlist;
}
-static GSList *imap_delete_cached_messages(GSList *mlist, FolderItem *item,
- guint32 first_uid, guint32 last_uid)
-{
- GSList *cur, *next;
- MsgInfo *msginfo;
- gchar *dir;
-
- g_return_val_if_fail(item != NULL, mlist);
- g_return_val_if_fail(item->folder != NULL, mlist);
- g_return_val_if_fail(item->folder->type == F_IMAP, mlist);
-
- debug_print("Deleting cached messages %u - %u ... ",
- first_uid, last_uid);
-
- dir = folder_item_get_path(item);
- if (is_dir_exist(dir))
- remove_numbered_files(dir, first_uid, last_uid);
- g_free(dir);
-
- for (cur = mlist; cur != NULL; ) {
- next = cur->next;
-
- msginfo = (MsgInfo *)cur->data;
- if (msginfo != NULL && first_uid <= msginfo->msgnum &&
- msginfo->msgnum <= last_uid) {
- procmsg_msginfo_free(msginfo);
- mlist = g_slist_remove(mlist, msginfo);
- }
-
- cur = next;
- }
-
- debug_print("done.\n");
-
- return mlist;
-}
-
static void imap_delete_all_cached_messages(FolderItem *item)
{
gchar *dir;
g_return_if_fail(item != NULL);
g_return_if_fail(item->folder != NULL);
- g_return_if_fail(item->folder->type == F_IMAP);
+ g_return_if_fail(FOLDER_CLASS(item->folder) == &imap_class);
debug_print("Deleting all cached messages...\n");
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;
} 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);
g_return_val_if_fail(msginfo->folder->folder != NULL, -1);
folder = msginfo->folder->folder;
- g_return_val_if_fail(folder->type == F_IMAP, -1);
+ g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, -1);
session = imap_session_get(folder);
if (!session) return -1;
g_return_val_if_fail(msginfo->folder->folder != NULL, -1);
folder = msginfo->folder->folder;
- g_return_val_if_fail(folder->type == F_IMAP, -1);
+ g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, -1);
session = imap_session_get(folder);
if (!session) return -1;
#define THROW(err) { ok = err; goto catch; }
-static gint imap_get_uid(IMAPSession *session, gint msgnum, guint32 *uid)
-{
- gint ok;
- GPtrArray *argbuf;
- gchar *str;
- gint num;
-
- *uid = 0;
- argbuf = g_ptr_array_new();
-
- imap_cmd_gen_send(SESSION(session)->sock, "FETCH %d (UID)", msgnum);
- if ((ok = imap_cmd_ok(SESSION(session)->sock, argbuf)) != IMAP_SUCCESS)
- THROW(ok);
-
- str = search_array_contain_str(argbuf, "FETCH");
- if (!str) THROW(IMAP_ERROR);
-
- if (sscanf(str, "%d FETCH (UID %d)", &num, uid) != 2 ||
- num != msgnum) {
- g_warning("imap_get_uid(): invalid FETCH line.\n");
- THROW(IMAP_ERROR);
- }
-
-catch:
- ptr_array_free_strings(argbuf);
- g_ptr_array_free(argbuf, TRUE);
-
- return ok;
-}
-
static gint imap_status(IMAPSession *session, IMAPFolder *folder,
const gchar *path,
gint *messages, gint *recent,
return imap_cmd_ok(sock, NULL);
}
+static gint imap_cmd_search(SockInfo *sock, const gchar *criteria, GSList **list)
+{
+ gint ok;
+ gchar *uidlist;
+ GPtrArray *argbuf;
+
+ g_return_val_if_fail(criteria != NULL, IMAP_ERROR);
+ g_return_val_if_fail(list != NULL, IMAP_ERROR);
+
+ *list = NULL;
+
+ argbuf = g_ptr_array_new();
+ imap_cmd_gen_send(sock, "UID SEARCH %s", criteria);
+
+ ok = imap_cmd_ok(sock, argbuf);
+ if (ok != IMAP_SUCCESS) {
+ ptr_array_free_strings(argbuf);
+ g_ptr_array_free(argbuf, TRUE);
+ return ok;
+ }
+
+ if ((uidlist = search_array_str(argbuf, "SEARCH ")) != NULL) {
+ gchar **strlist, **p;
+
+ strlist = g_strsplit(uidlist + 7, " ", 0);
+ for (p = strlist; *p != NULL; ++p) {
+ guint msgnum;
+
+ if (sscanf(*p, "%d", &msgnum) == 1)
+ *list = g_slist_append(*list, GINT_TO_POINTER(msgnum));
+ }
+ g_strfreev(strlist);
+ }
+ ptr_array_free_strings(argbuf);
+ g_ptr_array_free(argbuf, TRUE);
+
+ return IMAP_SUCCESS;
+}
+
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;
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;
}
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;
gint ok;
gint size;
gchar *destfolder_;
- gchar buf[BUFFSIZE];
+ gchar buf[BUFFSIZE], *imapbuf;
FILE *fp;
g_return_val_if_fail(file != NULL, IMAP_ERROR);
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...)"));
log_warning(_("can't copy %d to %s\n"), msgnum, destfolder_);
else if (imap_has_capability(session, "UIDPLUS") && reply->len > 0)
if ((okmsginfo = g_ptr_array_index(reply, reply->len - 1)) != NULL &&
- sscanf(okmsginfo, "%*u OK [COPYUID %*llu %u %u]", &olduid, &newuid) == 2 &&
+ sscanf(okmsginfo, "%*u OK [COPYUID %*u %u %u]", &olduid, &newuid) == 2 &&
olduid == msgnum)
*new_uid = newuid;
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);
+
+ /* Header fields ending with space are not rfc822 headers */
+ if (elem->name[namelen - 1] == ' ')
+ continue;
+
+ /* strip : at the of header field */
+ if(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;
}
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)
!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;
}
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;
}
{
IMAPFolderItem *item = (IMAPFolderItem *)_item;
IMAPSession *session;
- gint ok, i, lastuid_old, nummsgs = 0, exists, resent, unseen, uid_val;
- GPtrArray *argbuf;
- gchar *cmdbuf = NULL;
- gchar *dir;
+ gint ok, lastuid_old, nummsgs = 0, exists, recent, unseen, uid_val, uid_next;
+ GSList *uidlist, *elem;
+ gchar *dir, *cmd_buf;
g_return_val_if_fail(folder != NULL, -1);
g_return_val_if_fail(item != NULL, -1);
g_return_val_if_fail(item->item.path != NULL, -1);
- g_return_val_if_fail(folder->type == F_IMAP, -1);
+ g_return_val_if_fail(FOLDER_CLASS(folder) == &imap_class, -1);
g_return_val_if_fail(folder->account != NULL, -1);
session = imap_session_get(folder);
g_return_val_if_fail(session != NULL, -1);
- ok = imap_select(session, IMAP_FOLDER(folder), item->item.path,
- &exists, &resent, &unseen, &uid_val);
+ ok = imap_status(session, IMAP_FOLDER(folder), item->item.path,
+ &exists, &recent, &uid_next, &uid_val, &unseen);
if (ok != IMAP_SUCCESS)
return -1;
- if (exists == 0)
+ /* If old uid_next matches new uid_next we can be sure no message
+ was added to the folder */
+ if (uid_next == item->uid_next) {
+ nummsgs = g_slist_length(item->uid_list);
+
+ /* If number of messages is still the same we
+ know our caches message numbers are still valid,
+ otherwise if the number of messages has decrease
+ we discard our cache to start a new scan to find
+ out which numbers have been removed */
+ if (exists == nummsgs) {
+ *msgnum_list = g_slist_copy(item->uid_list);
+ return nummsgs;
+ } else if (exists < nummsgs) {
+ debug_print("Freeing imap uid cache");
+ item->lastuid = 0;
+ g_slist_free(item->uid_list);
+ item->uid_list = NULL;
+ }
+ }
+ item->uid_next = uid_next;
+
+ if (exists == 0) {
+ *msgnum_list = NULL;
return 0;
+ }
- argbuf = g_ptr_array_new();
- if(item->lastuid) {
- cmdbuf = g_strdup_printf("UID FETCH %d:* (UID)", (item->lastuid + 1));
- } else {
- cmdbuf = g_strdup("FETCH 1:* (UID)");
+ ok = imap_select(session, IMAP_FOLDER(folder), item->item.path,
+ &exists, &recent, &unseen, &uid_val);
+ if (ok != IMAP_SUCCESS)
+ return -1;
+
+ cmd_buf = g_strdup_printf("UID %d:*", item->lastuid + 1);
+ ok = imap_cmd_search(SESSION(session)->sock, cmd_buf, &uidlist);
+ g_free(cmd_buf);
+
+ if (ok == IMAP_SOCKET) {
+ session_destroy((Session *)session);
+ ((RemoteFolder *)folder)->session = NULL;
+ return -1;
}
- imap_cmd_gen_send(SESSION(session)->sock, cmdbuf);
- g_free(cmdbuf);
- ok = imap_cmd_ok(SESSION(session)->sock, argbuf);
+
if (ok != IMAP_SUCCESS) {
+ gint i;
+ GPtrArray *argbuf;
+
+ argbuf = g_ptr_array_new();
+
+ cmd_buf = g_strdup_printf("UID FETCH %d:* (UID)", item->lastuid + 1);
+ imap_cmd_gen_send(SESSION(session)->sock, cmd_buf);
+ g_free(cmd_buf);
+ ok = imap_cmd_ok(SESSION(session)->sock, argbuf);
+ if (ok != IMAP_SUCCESS) {
+ ptr_array_free_strings(argbuf);
+ g_ptr_array_free(argbuf, TRUE);
+ return -1;
+ }
+
+ for(i = 0; i < argbuf->len; i++) {
+ int ret, msgnum;
+
+ if((ret = sscanf(g_ptr_array_index(argbuf, i),
+ "%*d FETCH (UID %d)", &msgnum)) == 1)
+ uidlist = g_slist_prepend(uidlist, GINT_TO_POINTER(msgnum));
+ }
ptr_array_free_strings(argbuf);
g_ptr_array_free(argbuf, TRUE);
- return -1;
}
lastuid_old = item->lastuid;
*msgnum_list = g_slist_copy(item->uid_list);
+ nummsgs = g_slist_length(*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;
- }
+
+ for (elem = uidlist; elem != NULL; elem = g_slist_next(elem)) {
+ guint msgnum;
+
+ msgnum = GPOINTER_TO_INT(elem->data);
+ 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;
}
}
+ g_slist_free(uidlist);
+
+ if (nummsgs != exists) {
+ /* Cache contains more messages then folder, we have cached
+ an old UID of a message that was removed and new messages
+ have been added too, otherwise the uid_next check would
+ not have failed */
+ debug_print("Freeing imap uid cache");
+ item->lastuid = 0;
+ g_slist_free(item->uid_list);
+ item->uid_list = NULL;
+
+ g_slist_free(*msgnum_list);
+
+ return imap_get_num_list(folder, _item, msgnum_list);
+ }
dir = folder_item_get_path((FolderItem *)item);
debug_print("removing old messages from %s\n", dir);
remove_numbered_files_not_in_list(dir, *msgnum_list);
g_free(dir);
- ptr_array_free_strings(argbuf);
- g_ptr_array_free(argbuf, TRUE);
-
return nummsgs;
}
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)
{
g_return_val_if_fail(folder != NULL, FALSE);
g_return_val_if_fail(item != NULL, FALSE);
g_return_val_if_fail(item->item.folder != NULL, FALSE);
- g_return_val_if_fail(item->item.folder->type == F_IMAP, FALSE);
+ g_return_val_if_fail(FOLDER_CLASS(item->item.folder) == &imap_class, FALSE);
session = imap_session_get(folder);
g_return_val_if_fail(session != NULL, FALSE);