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,
gboolean imap_check_msgnum_validity (Folder *folder,
FolderItem *item);
+FolderClass imap_class =
+{
+ F_IMAP,
+ "imap",
+
+ /* 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;
- folder->get_msginfos = imap_get_msginfos;
}
static FolderItem *imap_folder_item_new(Folder *folder)
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
}
}
-#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_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;
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;
for (elem = headers; elem->name != NULL; ++elem) {
gint namelen = strlen(elem->name);
- while(namelen && (elem->name[namelen - 1] == ' ' ||
- elem->name[namelen - 1] == ':'))
+ /* 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)
+ if (namelen <= 0)
continue;
g_string_sprintfa(header_fields, "%s%.*s",
IMAPFolderItem *item = (IMAPFolderItem *)_item;
IMAPSession *session;
gint ok, lastuid_old, nummsgs = 0, exists, resent, unseen, uid_val;
- gint msgnum;
- GPtrArray *argbuf;
- gchar *cmdbuf = NULL;
- gchar *dir;
- gchar *uidlist;
- gchar **p, **list;
+ 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);
if (exists == 0)
return 0;
- argbuf = g_ptr_array_new();
- cmdbuf = g_strdup_printf("UID SEARCH UID %d:*", item->lastuid + 1);
- imap_cmd_gen_send(SESSION(session)->sock, cmdbuf);
- g_free(cmdbuf);
- ok = imap_cmd_ok(SESSION(session)->sock, argbuf);
+ 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;
+ }
+
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);
debug_print("Got %d uids from cache\n", g_slist_length(item->uid_list));
- if ((uidlist = search_array_str(argbuf, "SEARCH ")) != NULL) {
- list = g_strsplit(uidlist + 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;
- }
+ 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_strfreev(list);
}
+ g_slist_free(uidlist);
if (g_slist_length(item->uid_list) != exists) {
/* Cache contains more messages then folder, we have cached
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;
}
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);