More Coverity fixes
[claws.git] / src / imap.c
index ba4a4804162b1ecc3b203801cde159e3773fec60..887071979cd22f74ee88479fbf343487211c0128 100644 (file)
@@ -95,7 +95,7 @@ struct _IMAPFolder
        gchar last_seen_separator;
        guint refcnt;
        guint max_set_size;
-       const gchar *search_charset;
+       gchar *search_charset;
        gboolean search_charset_supported;
 };
 
@@ -124,6 +124,7 @@ struct _IMAPSession
        gboolean busy;
        gboolean cancelled;
        gboolean sens_update_block;
+       gboolean do_destroy;
 };
 
 struct _IMAPNameSpace
@@ -578,6 +579,14 @@ static void imap_disc_session_destroy(IMAPSession *session)
        SESSION(session)->sock = NULL;
 }
 
+static void imap_safe_destroy(IMAPSession *session)
+{
+       if (!session->busy)
+               session_destroy(SESSION(session));
+       else
+               session->do_destroy = TRUE;
+}
+
 static gboolean is_fatal(int libetpan_errcode)
 {
        switch(libetpan_errcode) {
@@ -759,7 +768,9 @@ static void imap_folder_destroy(Folder *folder)
 {
        while (imap_folder_get_refcnt(folder) > 0)
                gtk_main_iteration();
-       
+
+       g_free(IMAP_FOLDER(folder)->search_charset);
+
        folder_remote_folder_destroy(REMOTE_FOLDER(folder));
        imap_done(folder);
 }
@@ -770,7 +781,7 @@ static void imap_folder_init(Folder *folder, const gchar *name,
        folder_remote_folder_init((Folder *)folder, name, path);
        IMAP_FOLDER(folder)->max_set_size = IMAP_SET_MAX_COUNT;
        IMAP_FOLDER(folder)->search_charset_supported = TRUE;
-       IMAP_FOLDER(folder)->search_charset = conv_get_locale_charset_str_no_utf8();
+       IMAP_FOLDER(folder)->search_charset = g_strdup(conv_get_locale_charset_str_no_utf8());
 }
 
 static FolderItem *imap_folder_item_new(Folder *folder)
@@ -952,7 +963,7 @@ static IMAPSession *imap_reconnect_if_possible(Folder *folder, IMAPSession *sess
                log_warning(LOG_PROTOCOL, _("Connecting to %s failed"),
                            folder->account->recv_server);
                SESSION(session)->sock = NULL;
-               session_destroy(SESSION(session));
+               imap_safe_destroy(session);
                session = NULL;
        } else {
                rfolder->session = NULL;
@@ -964,7 +975,7 @@ static IMAPSession *imap_reconnect_if_possible(Folder *folder, IMAPSession *sess
                            folder->account->recv_server);
                SESSION(session)->state = SESSION_DISCONNECTED;
                SESSION(session)->sock = NULL;
-               session_destroy(SESSION(session));
+               imap_safe_destroy(session);
                /* Clear folders session to make imap_session_get create
                   a new session, because of rfolder->session == NULL
                   it will not try to reconnect again and so avoid an
@@ -994,11 +1005,21 @@ static IMAPSession *imap_session_get(Folder *folder)
                return NULL;
        }
 
+       /* check for deferred destroy */
+       if (rfolder->session != NULL) {
+               session = IMAP_SESSION(rfolder->session);
+               if (!session->busy && session->do_destroy) {
+                       rfolder->session = NULL;
+                       imap_safe_destroy(session);
+                       session = NULL;
+               }
+       }
+
        /* Make sure we have a session */
        if (rfolder->session != NULL && rfolder->session->state != SESSION_DISCONNECTED) {
                session = IMAP_SESSION(rfolder->session);
        } else if (rfolder->session != NULL && rfolder->session->state == SESSION_DISCONNECTED) {
-               session_destroy(SESSION(rfolder->session));
+               imap_safe_destroy(IMAP_SESSION(rfolder->session));
                rfolder->session = NULL;
                goto new_conn;
        } else if (rfolder->connecting) {
@@ -1026,10 +1047,10 @@ new_conn:
                rfolder->session = NULL;
                if (!is_fatal(r)) {
                        imap_threaded_disconnect(session->folder);
-                       SESSION(session)->state = SESSION_DISCONNECTED;
-                       SESSION(session)->sock = NULL;
-                       session_destroy(SESSION(session));
                }
+               SESSION(session)->state = SESSION_DISCONNECTED;
+               SESSION(session)->sock = NULL;
+               imap_safe_destroy(session);
                rfolder->last_failure = time(NULL);
                rfolder->connecting = FALSE;
                return NULL;
@@ -1045,13 +1066,18 @@ new_conn:
         * successfully sent. -- mbp */
        if ((time(NULL) - SESSION(session)->last_access_time > SESSION_TIMEOUT_INTERVAL) || session->cancelled) {
                /* verify that the session is still alive */
-               if ((r = imap_cmd_noop(session)) != MAILIMAP_NO_ERROR) {
+               r = imap_cmd_noop(session);
+
+               if (r != MAILIMAP_NO_ERROR) {
                        debug_print("disconnected!\n");
                        if (!is_fatal(r))
                                session = imap_reconnect_if_possible(folder, session);
                        else {
                                rfolder->session = NULL;
                                rfolder->connecting = FALSE;
+                               SESSION(session)->state = SESSION_DISCONNECTED;
+                               SESSION(session)->sock = NULL;
+                               imap_safe_destroy(session);
                                session = imap_session_get(folder);
                        }
                }
@@ -1187,7 +1213,7 @@ static IMAPSession *imap_session_new(Folder * folder,
                        log_warning(LOG_PROTOCOL, _("Can't start TLS session.\n"));
                        if (!is_fatal(ok)) {
                                SESSION(session)->sock = NULL;
-                               session_destroy(SESSION(session));
+                               imap_safe_destroy(session);
                        }
                        return NULL;
                }
@@ -1466,13 +1492,14 @@ static gchar *imap_fetch_msg_full(Folder *folder, FolderItem *item, gint uid,
                if (!cached || !MSG_IS_FULLY_CACHED(cached->flags)) {
                        have_size = get_file_size_with_crs(filename);
                        if (cached && (cached->size <= have_size || !body)) {
-                               procmsg_msginfo_free(cached);
                                ok = file_strip_crs(filename);
                                if (ok == 0 && cached && cached->size <= have_size) {
                                        /* we have it all and stripped */
-                                       debug_print("...fully cached in fact; setting flag.\n");
+                                       debug_print("...fully cached in fact (%u/%zd); setting flag.\n",
+                                                       have_size, cached->size);
                                        procmsg_msginfo_set_flags(cached, MSG_FULLY_CACHED, 0);
                                }
+                               procmsg_msginfo_free(cached);
                                return filename;
                        } else if (!cached && time(NULL) - get_file_mtime(filename) < 60) {
                                debug_print("message not cached and file recent, considering file complete\n");
@@ -1560,8 +1587,10 @@ static gboolean imap_is_msg_fully_cached(Folder *folder, FolderItem *item, gint
                return TRUE;
        }
        path = folder_item_get_path(item);
-       if (!is_dir_exist(path))
+       if (!is_dir_exist(path)) {
+               g_free(path);
                return FALSE;
+       }
 
        filename = g_strconcat(path, G_DIR_SEPARATOR_S, itos(uid), NULL);
        g_free(path);
@@ -1573,8 +1602,9 @@ static gboolean imap_is_msg_fully_cached(Folder *folder, FolderItem *item, gint
                        return TRUE;
                }
                size = get_file_size_with_crs(filename);
-               g_free(filename);
        }
+       g_free(filename);
+       debug_print("msg %d cached, has size %d, full should be %zd.\n", uid, size, cached->size);
        if (cached && size >= cached->size) {
                cached->total_size = cached->size;
                procmsg_msginfo_set_flags(cached, MSG_FULLY_CACHED, 0);
@@ -1642,8 +1672,10 @@ static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
                return -1;
        }
        destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path, &ok);
-       if (is_fatal(ok))
+       if (is_fatal(ok)) {
+               g_free(destdir);
                return -1;
+       }
        statusbar_print_all(_("Adding messages..."));
        total = g_slist_length(file_list);
        for (cur = file_list; cur != NULL; cur = cur->next) {
@@ -1840,8 +1872,10 @@ static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest,
 
        destdir = imap_get_real_path(session, IMAP_FOLDER(folder), dest->path, &ok);
 
-       if (is_fatal(ok))
+       if (is_fatal(ok)) {
+               g_free(destdir);
                return ok;
+       }
 
        seq_list = imap_get_lep_set_from_msglist(IMAP_FOLDER(folder), msglist);
        uid_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -2332,7 +2366,10 @@ static gint      search_msgs             (Folder                 *folder,
                        *msgs = g_slist_prepend(*msgs, GUINT_TO_POINTER(((MsgInfo*) cur->data)->msgnum));
                        count++;
                }
+               procmsg_msg_list_free(list);
+
                *msgs = g_slist_reverse(*msgs);
+
                return count;
        }
 
@@ -2454,10 +2491,8 @@ static gint imap_do_remove_msgs(Folder *folder, FolderItem *dest,
        imap_scan_required(folder, dest);
 
        g_free(destdir);
-       if (ok == MAILIMAP_NO_ERROR)
-               return 0;
-       else
-               return -1;
+
+       return 0;
 }
 
 static gint imap_remove_msgs(Folder *folder, FolderItem *dest, 
@@ -2533,8 +2568,10 @@ static gint imap_scan_tree_real(Folder *folder, gboolean subs_only)
                strtailchomp(root_folder, '/');
                real_path = imap_get_real_path
                        (session, IMAP_FOLDER(folder), root_folder, &r);
-               if (is_fatal(r))
+               if (is_fatal(r)) {
+                       g_free(real_path);
                        return -1;
+               }
                debug_print("IMAP root directory: %s\n", real_path);
 
                /* check if root directory exist */
@@ -2839,6 +2876,7 @@ GList *imap_scan_subtree(Folder *folder, FolderItem *item, gboolean unsubs_only,
                        if (r) {
                                g_free(real_path);
                                statusbar_pop_all();
+                               g_free(tmp);
                                return NULL;
                        }
                        folder_item_destroy(cur_item);
@@ -3195,6 +3233,7 @@ static gint imap_rename_folder(Folder *folder, FolderItem *item,
 
        real_oldpath = imap_get_real_path(session, IMAP_FOLDER(folder), item->path, &ok);
        if (is_fatal(ok)) {
+               g_free(real_oldpath);
                return -1;
        }
 
@@ -3211,8 +3250,10 @@ static gint imap_rename_folder(Folder *folder, FolderItem *item,
        }
 
        separator = imap_get_path_separator(session, IMAP_FOLDER(folder), item->path, &ok);
-       if (is_fatal(ok))
+       if (is_fatal(ok)) {
+               g_free(real_oldpath);
                return -1;
+       }
        if (strchr(item->path, G_DIR_SEPARATOR)) {
                dirpath = g_path_get_dirname(item->path);
                newpath = g_strconcat(dirpath, G_DIR_SEPARATOR_S, name, NULL);
@@ -3309,9 +3350,10 @@ static gint imap_remove_folder_real(Folder *folder, FolderItem *item)
                return -1;
        }
        path = imap_get_real_path(session, IMAP_FOLDER(folder), item->path, &ok);
-       if (is_fatal(ok))
+       if (is_fatal(ok)) {
+               g_free(path);
                return -1;
-
+       }
        imap_threaded_subscribe(folder, path, FALSE);
 
        selected_folder = (session->mbox != NULL) &&
@@ -3480,12 +3522,7 @@ static void *imap_get_uncached_messages_thread(void *data)
                main_window_reflect_tags_changes(mainwindow_get_mainwindow());
        }
 
-       for (cur = seq_list; cur != NULL; cur = g_slist_next(cur)) {
-               struct mailimap_set * imapset;
-               
-               imapset = cur->data;
-               mailimap_set_free(imapset);
-       }
+       imap_lep_set_free(seq_list);
        
        session_set_access_time(SESSION(session));
        stuff->done = TRUE;
@@ -3598,15 +3635,12 @@ gchar imap_get_path_separator_for_item(FolderItem *item)
        if (!item)
                return '/';
        folder = item->folder;
-       
+
        if (!folder)
                return '/';
-       
+
        imap_folder = IMAP_FOLDER(folder);
-       
-       if (!imap_folder)
-               return '/';
-       
+
        debug_print("getting session...");
        session = imap_session_get(FOLDER(folder));
        result = imap_get_path_separator(session, imap_folder, item->path, &ok);
@@ -3802,8 +3836,10 @@ static gint imap_select(IMAPSession *session, IMAPFolder *folder,
        session->expunge = 0;
 
        real_path = imap_get_real_path(session, folder, path, &ok);
-       if (is_fatal(ok))
-               return ok;              
+       if (is_fatal(ok)) {
+               g_free(real_path);
+               return ok;      
+       }       
        g_slist_free(IMAP_FOLDER_ITEM(item)->ok_flags);
        IMAP_FOLDER_ITEM(item)->ok_flags = NULL;
        ok = imap_cmd_select(session, real_path,
@@ -4408,11 +4444,8 @@ static gint get_list_of_uids(IMAPSession *session, Folder *folder, IMAPFolderIte
        }
        
        if (r == MAILIMAP_NO_ERROR) {
-               GSList * fetchuid_list =
-                       imap_uid_list_from_lep(lep_uidlist, NULL);
+               uidlist = imap_uid_list_from_lep(lep_uidlist, NULL);
                mailimap_search_result_free(lep_uidlist);
-               
-               uidlist = g_slist_concat(fetchuid_list, uidlist);
        } else {
                carray * lep_uidtab;
                if (r != -1) { /* inited */
@@ -4423,10 +4456,8 @@ static gint get_list_of_uids(IMAPSession *session, Folder *folder, IMAPFolderIte
                r = imap_threaded_fetch_uid(folder, 1,
                                    &lep_uidtab);
                if (r == MAILIMAP_NO_ERROR) {
-                       GSList * fetchuid_list =
-                               imap_uid_list_from_lep_tab(lep_uidtab);
+                       uidlist = imap_uid_list_from_lep_tab(lep_uidtab);
                        imap_fetch_uid_list_free(lep_uidtab);
-                       uidlist = g_slist_concat(fetchuid_list, uidlist);
                }
        }
        
@@ -5726,7 +5757,7 @@ static MsgInfo *imap_envelope_from_lep(struct imap_fetch_env_info * info,
        guint32 uid = 0;
        goffset size = 0;
        MsgFlags flags = {0, 0};
-       
+
        if (info->headers == NULL)
                return NULL;
 
@@ -5737,11 +5768,11 @@ static MsgInfo *imap_envelope_from_lep(struct imap_fetch_env_info * info,
                MSG_SET_TMP_FLAGS(flags, MSG_DRAFT);
        }
        flags.perm_flags = info->flags;
-       
+
        uid = info->uid;
        size = (goffset) info->size;
        msginfo = procheader_parse_str(info->headers, flags, FALSE, FALSE);
-       
+
        if (msginfo) {
                msginfo->msgnum = uid;
                msginfo->size = size;
@@ -5844,12 +5875,15 @@ void imap_disconnect_all(gboolean have_connectivity)
                if (account->protocol == A_IMAP4) {
                        RemoteFolder *folder = (RemoteFolder *)account->folder;
                        if (folder && folder->session) {
+                               if (imap_is_busy(FOLDER(folder)))
+                                       imap_threaded_cancel(FOLDER(folder));
+
                                IMAPSession *session = (IMAPSession *)folder->session;
                                if (have_connectivity)
                                        imap_threaded_disconnect(FOLDER(folder));
                                SESSION(session)->state = SESSION_DISCONNECTED;
                                SESSION(session)->sock = NULL;
-                               session_destroy(SESSION(session));
+                               imap_safe_destroy(session);
                                folder->session = NULL;
                        }
                }