static void imap_change_flags (Folder *folder,
FolderItem *item,
MsgInfo *msginfo,
- MsgPermFlags newflags);
+ MsgPermFlags newflags);
+static gint imap_get_flags (Folder *folder,
+ FolderItem *item,
+ MsgInfoList *msglist,
+ GRelation *msgflags);
static gchar *imap_folder_get_path (Folder *folder);
static gchar *imap_item_get_path (Folder *folder,
FolderItem *item);
-static FolderClass imap_class =
-{
- F_IMAP,
- "imap",
- "IMAP4",
-
- /* Folder functions */
- imap_folder_new,
- imap_folder_destroy,
- NULL,
- NULL,
- imap_scan_tree,
- imap_create_tree,
-
- /* FolderItem functions */
- imap_folder_item_new,
- imap_folder_item_destroy,
- NULL,
- NULL,
- imap_item_get_path,
- imap_create_folder,
- imap_rename_folder,
- imap_remove_folder,
- imap_close,
- imap_get_num_list,
- NULL,
- NULL,
- NULL,
- imap_scan_required,
-
- /* Message functions */
- imap_get_msginfo,
- imap_get_msginfos,
- imap_fetch_msg,
- imap_add_msg,
- imap_add_msgs,
- imap_copy_msg,
- imap_copy_msgs,
- imap_remove_msg,
- imap_remove_all_msg,
- imap_is_msg_changed,
- imap_change_flags,
-};
+static FolderClass imap_class;
FolderClass *imap_get_class(void)
{
+ if (imap_class.idstr == NULL) {
+ imap_class.type = F_IMAP;
+ imap_class.idstr = "imap";
+ imap_class.uistr = "IMAP4";
+
+ /* Folder functions */
+ imap_class.new_folder = imap_folder_new;
+ imap_class.destroy_folder = imap_folder_destroy;
+ imap_class.scan_tree = imap_scan_tree;
+ imap_class.create_tree = imap_create_tree;
+
+ /* FolderItem functions */
+ imap_class.item_new = imap_folder_item_new;
+ imap_class.item_destroy = imap_folder_item_destroy;
+ imap_class.item_get_path = imap_item_get_path;
+ imap_class.create_folder = imap_create_folder;
+ imap_class.rename_folder = imap_rename_folder;
+ imap_class.remove_folder = imap_remove_folder;
+ imap_class.close = imap_close;
+ imap_class.get_num_list = imap_get_num_list;
+ imap_class.scan_required = imap_scan_required;
+
+ /* Message functions */
+ imap_class.get_msginfo = imap_get_msginfo;
+ imap_class.get_msginfos = imap_get_msginfos;
+ imap_class.fetch_msg = imap_fetch_msg;
+ imap_class.add_msg = imap_add_msg;
+ imap_class.add_msgs = imap_add_msgs;
+ imap_class.copy_msg = imap_copy_msg;
+ imap_class.copy_msgs = imap_copy_msgs;
+ imap_class.remove_msg = imap_remove_msg;
+ imap_class.remove_all_msg = imap_remove_all_msg;
+ imap_class.is_msg_changed = imap_is_msg_changed;
+ imap_class.change_flags = imap_change_flags;
+ imap_class.get_flags = imap_get_flags;
+ }
+
return &imap_class;
}
/* Check if this is the first try to establish a
connection, if yes we don't try to reconnect */
if (rfolder->session == NULL) {
- log_warning(_("Connecting %s failed"),
+ log_warning("Connecting %s failed",
folder->account->recv_server);
session_destroy(SESSION(session));
session = NULL;
} else {
- log_warning(_("IMAP4 connection to %s has been"
- " disconnected. Reconnecting...\n"),
+ log_warning("IMAP4 connection to %s has been"
+ " disconnected. Reconnecting...\n",
folder->account->recv_server);
session_destroy(SESSION(session));
/* Clear folders session to make imap_session_get create
#endif
if (account->set_tunnelcmd) {
- log_message(_("creating tunneled IMAP4 connection\n"));
+ log_message("creating tunneled IMAP4 connection\n");
#if USE_OPENSSL
if ((imap_sock = imap_open_tunnel(account->recv_server,
account->tunnelcmd,
} else {
g_return_val_if_fail(account->recv_server != NULL, NULL);
- log_message(_("creating IMAP4 connection to %s:%d ...\n"),
+ log_message("creating IMAP4 connection to %s:%d ...\n",
account->recv_server, port);
#if USE_OPENSSL
ok = imap_cmd_starttls(session);
if (ok != IMAP_SUCCESS) {
- log_warning(_("Can't start TLS session.\n"));
+ log_warning("Can't start TLS session.\n");
session_destroy(SESSION(session));
return NULL;
}
(IMAP_SESSION(REMOTE_FOLDER(folder)->session),
&numlist, IMAP_FLAG_DELETED, TRUE);
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't set deleted flags: %d\n"), uid);
+ log_warning("can't set deleted flags: %d\n", uid);
return ok;
}
g_free(uidstr);
}
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't expunge\n"));
+ log_warning("can't expunge\n");
return ok;
}
imap_gen_send(session, "STORE 1:* +FLAGS.SILENT (\\Deleted)");
ok = imap_cmd_ok(session, NULL);
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't set deleted flags: 1:*\n"));
+ log_warning("can't set deleted flags: 1:*\n");
return ok;
}
ok = imap_cmd_expunge(session, NULL);
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't expunge\n"));
+ log_warning("can't expunge\n");
return ok;
}
ok = imap_cmd_close(session);
if (ok != IMAP_SUCCESS)
- log_warning(_("can't close folder\n"));
+ log_warning("can't close folder\n");
g_free(session->mbox);
session->mbox = NULL;
ok = imap_cmd_list(session, NULL, real_path, argbuf);
if (ok != IMAP_SUCCESS ||
search_array_str(argbuf, "LIST ") == NULL) {
- log_warning(_("root folder %s does not exist\n"), real_path);
+ log_warning("root folder %s does not exist\n", real_path);
g_ptr_array_free(argbuf, TRUE);
g_free(real_path);
for (;;) {
if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) <= 0) {
- log_warning(_("error occurred while getting LIST.\n"));
+ log_warning("error occurred while getting LIST.\n");
break;
}
strretchomp(buf);
log_print("IMAP4< %s\n", buf);
if (sscanf(buf, "%*d %16s", buf) < 1 ||
strcmp(buf, "OK") != 0)
- log_warning(_("error occurred while getting LIST.\n"));
+ log_warning("error occurred while getting LIST.\n");
break;
}
ok = imap_cmd_list(session, NULL, imap_path,
argbuf);
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't create mailbox: LIST failed\n"));
+ log_warning("can't create mailbox: LIST failed\n");
g_free(imap_path);
g_free(dirpath);
ptr_array_free_strings(argbuf);
if (!exist) {
ok = imap_cmd_create(session, imap_path);
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't create mailbox\n"));
+ log_warning("can't create mailbox\n");
g_free(imap_path);
g_free(dirpath);
return NULL;
g_return_val_if_fail(item->path != NULL, -1);
g_return_val_if_fail(name != NULL, -1);
+ if (strchr(name, imap_get_path_separator(IMAP_FOLDER(folder), item->path)) != NULL) {
+ g_warning(_("New folder name must not contain the namespace "
+ "path separator"));
+ return -1;
+ }
+
session = imap_session_get(folder);
if (!session) return -1;
ok = imap_cmd_rename(session, real_oldpath, real_newpath);
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't rename mailbox: %s to %s\n"),
+ log_warning("can't rename mailbox: %s to %s\n",
real_oldpath, real_newpath);
g_free(real_oldpath);
g_free(newpath);
ok = imap_cmd_delete(session, path);
if (ok != IMAP_SUCCESS) {
- log_warning(_("can't delete mailbox\n"));
+ log_warning("can't delete mailbox\n");
g_free(path);
return -1;
}
if (imap_cmd_envelope(session, imapset)
!= IMAP_SUCCESS) {
- log_warning(_("can't get envelope\n"));
+ log_warning("can't get envelope\n");
continue;
}
for (;;) {
if ((tmp = sock_getline(SESSION(session)->sock)) == NULL) {
- log_warning(_("error occurred while getting envelope.\n"));
+ log_warning("error occurred while getting envelope.\n");
g_string_free(str, TRUE);
break;
}
msginfo = imap_parse_envelope
(SESSION(session)->sock, item, str);
if (!msginfo) {
- log_warning(_("can't parse envelope: %s\n"), str->str);
+ log_warning("can't parse envelope: %s\n", str->str);
continue;
}
if (item->stype == F_QUEUE) {
SockInfo *sock;
if ((sock = sock_connect_cmd(server, tunnelcmd)) == NULL) {
- log_warning(_("Can't establish IMAP4 session with: %s\n"),
+ log_warning("Can't establish IMAP4 session with: %s\n",
server);
return NULL;
}
SockInfo *sock;
if ((sock = sock_connect(server, port)) == NULL) {
- log_warning(_("Can't connect to IMAP4 server: %s:%d\n"),
+ log_warning("Can't connect to IMAP4 server: %s:%d\n",
server, port);
return NULL;
}
#if USE_OPENSSL
if (ssl_type == SSL_TUNNEL && !ssl_init_socket(sock)) {
- log_warning(_("Can't establish IMAP4 session with: %s:%d\n"),
+ log_warning("Can't establish IMAP4 session with: %s:%d\n",
server, port);
sock_close(sock);
return NULL;
if (imap_cmd_namespace(session, &ns_str)
!= IMAP_SUCCESS) {
- log_warning(_("can't get namespace\n"));
+ log_warning("can't get namespace\n");
return;
}
{
gchar *real_path;
gint ok;
- gint exists_, recent_, unseen_, uid_validity_;
+ gint exists_, recent_, unseen_;
+ guint32 uid_validity_;
if (!exists || !recent || !unseen || !uid_validity) {
if (session->mbox && strcmp(session->mbox, path) == 0)
ok = imap_cmd_select(session, real_path,
exists, recent, unseen, uid_validity);
if (ok != IMAP_SUCCESS)
- log_warning(_("can't select folder: %s\n"), real_path);
+ log_warning("can't select folder: %s\n", real_path);
else {
session->mbox = g_strdup(path);
session->folder_content_changed = FALSE;
sock_puts(SESSION(session)->sock, response64);
ok = imap_cmd_ok(session, NULL);
if (ok != IMAP_SUCCESS)
- log_warning(_("IMAP4 authentication failed.\n"));
+ log_warning("IMAP4 authentication failed.\n");
return ok;
}
ok = imap_cmd_ok(session, NULL);
if (ok != IMAP_SUCCESS)
- log_warning(_("IMAP4 login failed.\n"));
+ log_warning("IMAP4 login failed.\n");
return ok;
}
GPtrArray *argbuf;
gchar *select_cmd;
gchar *folder_;
+ unsigned int uid_validity_;
*exists = *recent = *unseen = *uid_validity = 0;
argbuf = g_ptr_array_new();
resp_str = search_array_contain_str(argbuf, "UIDVALIDITY");
if (resp_str) {
- if (sscanf(resp_str, "OK [UIDVALIDITY %u] ", uid_validity)
+ if (sscanf(resp_str, "OK [UIDVALIDITY %u] ", &uid_validity_)
!= 1) {
g_warning("imap_cmd_select(): invalid UIDVALIDITY line.\n");
THROW;
}
+ *uid_validity = uid_validity_;
}
resp_str = search_array_contain_str(argbuf, "UNSEEN");
for (p = strlist; *p != NULL; ++p) {
guint msgnum;
- if (sscanf(*p, "%d", &msgnum) == 1)
+ if (sscanf(*p, "%u", &msgnum) == 1)
*list = g_slist_append(*list, GINT_TO_POINTER(msgnum));
}
g_strfreev(strlist);
gint size;
gchar *destfolder_;
gchar *flag_str;
- guint32 new_uid_;
+ unsigned int new_uid_;
gchar *ret = NULL;
gchar buf[BUFFSIZE];
FILE *fp;
ok = imap_gen_recv(session, &ret);
if (ok != IMAP_SUCCESS || ret[0] != '+' || ret[1] != ' ') {
- log_warning(_("can't append %s to %s\n"), file, destfolder_);
+ log_warning("can't append %s to %s\n", file, destfolder_);
g_free(ret);
fclose(fp);
return IMAP_ERROR;
}
g_free(ret);
- log_print("IMAP4> %s\n", _("(sending file...)"));
+ log_print("IMAP4> %s\n", "(sending file...)");
while (fgets(buf, sizeof(buf), fp) != NULL) {
strretchomp(buf);
ok = imap_cmd_ok(session, NULL);
if (ok != IMAP_SUCCESS)
- log_warning(_("can't append message to %s\n"),
+ log_warning("can't append message to %s\n",
destfolder_);
return ok;
static MsgNumberList *imapset_to_numlist(IMAPSet imapset)
{
gchar **ranges, **range;
- guint32 low, high;
+ unsigned int low, high;
MsgNumberList *uids = NULL;
ranges = g_strsplit(imapset, ",", 0);
for (range = ranges; *range != NULL; range++) {
printf("%s\n", *range);
- if(sscanf(*range, "%u:%u", &low, &high) == 1)
+ if (sscanf(*range, "%u:%u", &low, &high) == 1)
uids = g_slist_prepend(uids, GINT_TO_POINTER(low));
else {
int i;
ok = imap_cmd_ok(session, NULL);
if (ok != IMAP_SUCCESS)
- log_warning(_("can't copy %s to %s\n"), seq_set, destfolder_);
+ log_warning("can't copy %s to %s\n", seq_set, destfolder_);
return ok;
}
imap_gen_send(session, "UID STORE %s %s", seq_set, sub_cmd);
if ((ok = imap_cmd_ok(session, NULL)) != IMAP_SUCCESS) {
- log_warning(_("error while imap command: STORE %s %s\n"),
+ log_warning("error while imap command: STORE %s %s\n",
seq_set, sub_cmd);
return ok;
}
else
imap_gen_send(session, "EXPUNGE");
if ((ok = imap_cmd_ok(session, NULL)) != IMAP_SUCCESS) {
- log_warning(_("error while imap command: EXPUNGE\n"));
+ log_warning("error while imap command: EXPUNGE\n");
return ok;
}
imap_gen_send(session, "CLOSE");
if ((ok = imap_cmd_ok(session, NULL)) != IMAP_SUCCESS)
- log_warning(_("error while imap command: CLOSE\n"));
+ log_warning("error while imap command: CLOSE\n");
return ok;
}
return;
}
+
+static gint compare_msginfo(gconstpointer a, gconstpointer b)
+{
+ return ((MsgInfo *)a)->msgnum - ((MsgInfo *)b)->msgnum;
+}
+
+static guint gslist_find_next_num(MsgNumberList **list, guint num)
+{
+ GSList *elem;
+
+ g_return_val_if_fail(list != NULL, -1);
+
+ for (elem = *list; elem != NULL; elem = g_slist_next(elem))
+ if (GPOINTER_TO_INT(elem->data) >= num)
+ break;
+ *list = elem;
+ return elem != NULL ? GPOINTER_TO_INT(elem->data) : (gint)-1;
+}
+
+/*
+ * NEW and DELETED flags are not syncronized
+ * - The NEW/RECENT flags in IMAP folders can not really be directly
+ * modified by Sylpheed
+ * - The DELETE/DELETED flag in IMAP and Sylpheed don't have the same
+ * meaning, in IMAP it always removes the messages from the FolderItem
+ * in Sylpheed it can mean to move the message to trash
+ */
+static gint imap_get_flags(Folder *folder, FolderItem *item,
+ MsgInfoList *msginfo_list, GRelation *msgflags)
+{
+ IMAPSession *session;
+ GSList *sorted_list;
+ /*
+ GSList *new = NULL, *p_new;
+ GSList *deleted = NULL, *p_deleted;
+ */
+ GSList *unseen = NULL, *answered = NULL, *flagged = NULL;
+ GSList *p_unseen, *p_answered, *p_flagged;
+ GSList *elem;
+ GSList *seq_list, *cur;
+ gboolean reverse_seen = FALSE;
+ GString *cmd_buf;
+ gint ok;
+ gint exists_cnt, recent_cnt, unseen_cnt, uid_next;
+ guint32 uidvalidity;
+
+ g_return_val_if_fail(folder != NULL, -1);
+ g_return_val_if_fail(item != NULL, -1);
+ g_return_val_if_fail(msginfo_list != NULL, -1);
+
+ session = imap_session_get(folder);
+ g_return_val_if_fail(session != NULL, -1);
+
+ ok = imap_select(session, IMAP_FOLDER(folder), item->path,
+ NULL, NULL, NULL, NULL);
+ if (ok != IMAP_SUCCESS)
+ return -1;
+
+ ok = imap_status(session, IMAP_FOLDER(folder), item->path,
+ &exists_cnt, &recent_cnt, &uid_next, &uidvalidity, &unseen_cnt);
+
+ if (unseen_cnt > exists_cnt / 2)
+ reverse_seen = TRUE;
+
+ cmd_buf = g_string_new(NULL);
+
+ sorted_list = g_slist_sort(g_slist_copy(msginfo_list), compare_msginfo);
+
+ seq_list = imap_get_seq_set_from_msglist(msginfo_list);
+
+ for (cur = seq_list; cur != NULL; cur = g_slist_next(cur)) {
+ IMAPSet imapset = cur->data;
+/*
+ g_string_sprintf(cmd_buf, "RECENT UID %s", imapset);
+ imap_cmd_search(session, cmd_buf->str, &p_new);
+ new = g_slist_concat(new, p_new);
+*/
+ g_string_sprintf(cmd_buf, "%sSEEN UID %s", reverse_seen ? "" : "UN", imapset);
+ imap_cmd_search(session, cmd_buf->str, &p_unseen);
+ unseen = g_slist_concat(unseen, p_unseen);
+
+ g_string_sprintf(cmd_buf, "ANSWERED UID %s", imapset);
+ imap_cmd_search(session, cmd_buf->str, &p_answered);
+ answered = g_slist_concat(answered, p_answered);
+
+ g_string_sprintf(cmd_buf, "FLAGGED UID %s", imapset);
+ imap_cmd_search(session, cmd_buf->str, &p_flagged);
+ flagged = g_slist_concat(flagged, p_flagged);
+/*
+ g_string_sprintf(cmd_buf, "DELETED UID %s", imapset);
+ imap_cmd_search(session, cmd_buf->str, &p_deleted);
+ deleted = g_slist_concat(deleted, p_deleted);
+*/
+ }
+
+/*
+ p_new = new;
+*/
+ p_unseen = unseen;
+ p_answered = answered;
+ p_flagged = flagged;
+/*
+ p_deleted = deleted;
+*/
+ for (elem = sorted_list; elem != NULL; elem = g_slist_next(elem)) {
+ MsgInfo *msginfo;
+ MsgPermFlags flags;
+ gboolean wasnew;
+
+ msginfo = (MsgInfo *) elem->data;
+ flags = msginfo->flags.perm_flags;
+ wasnew = (flags & MSG_NEW);
+ flags &= ~((reverse_seen ? 0 : MSG_UNREAD | MSG_NEW) | MSG_REPLIED | MSG_MARKED);
+ if (reverse_seen)
+ flags |= MSG_UNREAD | (wasnew ? MSG_NEW : 0);
+ /*
+ if (gslist_find_next_num(&p_new, msginfo->msgnum) == msginfo->msgnum)
+ flags |= MSG_NEW;
+ */
+ if (gslist_find_next_num(&p_unseen, msginfo->msgnum) == msginfo->msgnum) {
+ if (!reverse_seen) {
+ flags |= MSG_UNREAD | (wasnew ? MSG_NEW : 0);
+ } else {
+ flags &= ~(MSG_UNREAD | MSG_NEW);
+ }
+ }
+ if (gslist_find_next_num(&p_answered, msginfo->msgnum) == msginfo->msgnum)
+ flags |= MSG_REPLIED;
+ if (gslist_find_next_num(&p_flagged, msginfo->msgnum) == msginfo->msgnum)
+ flags |= MSG_MARKED;
+ /*
+ if (gslist_find_next_num(&p_deleted, msginfo->msgnum) == msginfo->msgnum)
+ MSG_SET_PERM_FLAGS(msginfo->flags, MSG_DELETED);
+ */
+ g_relation_insert(msgflags, msginfo, GINT_TO_POINTER(flags));
+ }
+
+ imap_seq_set_free(seq_list);
+ /* g_slist_free(deleted); */
+ g_slist_free(flagged);
+ g_slist_free(answered);
+ g_slist_free(unseen);
+ /* new not freed in original patch ??? */
+ g_slist_free(sorted_list);
+ g_string_free(cmd_buf, TRUE);
+
+ return 0;
+}