Make procmsg_msginfo_free() zero out pointers to freed memory.
[claws.git] / src / partial_download.c
index 94e55b4d68271c2edd748413eee3f4d153ae08c3..5694b0d8e6b60701339ae4e706c848a997deca29 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2004 Hiroyuki Yamamoto
- * This file (C) 2004 Colin Leroy
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2012 Colin Leroy <colin@colino.net> 
+ * and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -14,8 +14,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 /* Partial download:
@@ -44,6 +44,7 @@
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
+#include "claws-features.h"
 #endif
 
 #include <glib.h>
@@ -71,26 +72,30 @@ int partial_msg_in_uidl_list(MsgInfo *msginfo)
        gchar uidl[POPBUFSIZE];
        time_t recv_time;
        time_t now;
-       gint partial_recv;
-       gchar *sanitized_uid = g_strdup(msginfo->account_login);
+       gchar *sanitized_uid = NULL;
+       
+       if (!msginfo->extradata)
+               return FALSE;
+
+       sanitized_uid = g_strdup(msginfo->extradata->account_login);
        
        subst_for_filename(sanitized_uid);
 
-       if (!msginfo->account_server
-       ||  !msginfo->account_login
-       ||  !msginfo->partial_recv)
+       if (!msginfo->extradata->account_server
+       ||  !msginfo->extradata->account_login
+       ||  !msginfo->extradata->partial_recv)
                return FALSE;
        
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
-                          "uidl", G_DIR_SEPARATOR_S, msginfo->account_server,
-                          "-", msginfo->account_login, NULL);
-       if ((fp = fopen(path, "rb")) == NULL) {
+                          "uidl", G_DIR_SEPARATOR_S, msginfo->extradata->account_server,
+                          "-", msginfo->extradata->account_login, NULL);
+       if ((fp = g_fopen(path, "rb")) == NULL) {
                if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
                g_free(path);
                path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
-                                  "uidl-", msginfo->account_server,
+                                  "uidl-", msginfo->extradata->account_server,
                                   "-", sanitized_uid, NULL);
-               if ((fp = fopen(path, "rb")) == NULL) {
+               if ((fp = g_fopen(path, "rb")) == NULL) {
                        if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
                        g_free(sanitized_uid);
                        g_free(path);
@@ -106,16 +111,16 @@ int partial_msg_in_uidl_list(MsgInfo *msginfo)
                gchar tmp[POPBUFSIZE];
                strretchomp(buf);
                recv_time = RECV_TIME_NONE;
-               partial_recv = POP3_TOTALLY_RECEIVED;
                
-               if (sscanf(buf, "%s\t%ld\t%s", uidl, &recv_time, tmp) < 2) {
+               if (sscanf(buf, "%s\t%ld\t%s", uidl, (long int *) &recv_time, 
+                          tmp) < 2) {
                        if (sscanf(buf, "%s", uidl) != 1)
                                continue;
                        else {
                                recv_time = now;
                        }
                }
-               if (!strcmp(uidl, msginfo->partial_recv)) {
+               if (!strcmp(uidl, msginfo->extradata->partial_recv)) {
                        fclose(fp);
                        return TRUE;
                }
@@ -135,8 +140,6 @@ static int partial_uidl_mark_mail(MsgInfo *msginfo, int download)
        gchar uidl[POPBUFSIZE];
        time_t recv_time;
        time_t now;
-       int len;
-       int start = TRUE;
        gchar partial_recv[POPBUFSIZE];
        int err = -1;
        gchar *filename;
@@ -145,44 +148,49 @@ static int partial_uidl_mark_mail(MsgInfo *msginfo, int download)
 
        filename = procmsg_get_message_file_path(msginfo);
        if (!filename) {
-               g_warning("can't get message file path.\n");
+               g_warning("can't get message file path.");
                return err;
        }
        tinfo = procheader_parse_file(filename, msginfo->flags, TRUE, TRUE);
+       
+       if (!tinfo->extradata) {
+               g_free(filename);
+               return err;
+       }
 
-       sanitized_uid = g_strdup(tinfo->account_login);
+       sanitized_uid = g_strdup(tinfo->extradata->account_login);
        subst_for_filename(sanitized_uid);
 
-       if (!tinfo->account_server
-       ||  !tinfo->account_login
-       ||  !tinfo->partial_recv) {
+       if (!tinfo->extradata->account_server
+       ||  !tinfo->extradata->account_login
+       ||  !tinfo->extradata->partial_recv) {
                goto bail;
        }
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
-                          "uidl", G_DIR_SEPARATOR_S, tinfo->account_server,
+                          "uidl", G_DIR_SEPARATOR_S, tinfo->extradata->account_server,
                           "-", sanitized_uid, NULL);
 
-       if ((fp = fopen(path, "rb")) == NULL) {
+       if ((fp = g_fopen(path, "rb")) == NULL) {
                perror("fopen1");
                if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
                g_free(path);
                path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
-                                  "uidl-", tinfo->account_server,
-                                  "-", tinfo->account_login, NULL);
-               if ((fp = fopen(path, "rb")) == NULL) {
+                                  "uidl-", tinfo->extradata->account_server,
+                                  "-", tinfo->extradata->account_login, NULL);
+               if ((fp = g_fopen(path, "rb")) == NULL) {
                        if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
                        g_free(path);
+                       goto bail;
                }
-               goto bail;
        }
 
        pathnew = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
-                          "uidl", G_DIR_SEPARATOR_S, tinfo->account_server,
+                          "uidl", G_DIR_SEPARATOR_S, tinfo->extradata->account_server,
                           "-", sanitized_uid, ".new", NULL);
        
        g_free(sanitized_uid);
 
-       if ((fpnew = fopen(pathnew, "wb")) == NULL) {
+       if ((fpnew = g_fopen(pathnew, "wb")) == NULL) {
                perror("fopen2");
                fclose(fp);
                g_free(pathnew);
@@ -197,16 +205,23 @@ static int partial_uidl_mark_mail(MsgInfo *msginfo, int download)
                sprintf(partial_recv,"0");
                
                if (sscanf(buf, "%s\t%ld\t%s", 
-                          uidl, &recv_time, partial_recv) < 2) {
+                          uidl, (long int *) &recv_time, partial_recv) < 2) {
                        if (sscanf(buf, "%s", uidl) != 1)
                                continue;
                        else {
                                recv_time = now;
                        }
                }
-               if (strcmp(tinfo->partial_recv, uidl)) {
-                       fprintf(fpnew, "%s\t%ld\t%s\n", 
-                               uidl, recv_time, partial_recv);
+               if (strcmp(tinfo->extradata->partial_recv, uidl)) {
+                       if (fprintf(fpnew, "%s\t%ld\t%s\n", 
+                               uidl, (long int) recv_time, partial_recv) < 0) {
+                               FILE_OP_ERROR(pathnew, "fprintf");
+                               fclose(fpnew);
+                               fclose(fp);
+                               g_free(path);
+                               g_free(pathnew);
+                               goto bail;
+                       }
                } else {
                        gchar *stat = NULL;
                        if (download == POP3_PARTIAL_DLOAD_DLOAD) {
@@ -221,12 +236,25 @@ static int partial_uidl_mark_mail(MsgInfo *msginfo, int download)
                        else if (download == POP3_PARTIAL_DLOAD_DELE)
                                stat = g_strdup("0");
                        
-                       fprintf(fpnew, "%s\t%ld\t%s\n", 
-                               uidl, recv_time, stat);
+                       if (fprintf(fpnew, "%s\t%ld\t%s\n", 
+                               uidl, (long int) recv_time, stat) < 0) {
+                               FILE_OP_ERROR(pathnew, "fprintf");
+                               fclose(fpnew);
+                               fclose(fp);
+                               g_free(path);
+                               g_free(pathnew);
+                               goto bail;
+                       }
                        g_free(stat);
                }
        }
-       fclose(fpnew);
+       if (fclose(fpnew) == EOF) {
+               FILE_OP_ERROR(pathnew, "fclose");
+               fclose(fp);
+               g_free(path);
+               g_free(pathnew);
+               goto bail;
+       }
        fclose(fp);
 
        move_file(pathnew, path, TRUE);
@@ -234,39 +262,65 @@ static int partial_uidl_mark_mail(MsgInfo *msginfo, int download)
        g_free(path);
        g_free(pathnew);
        
-       if ((fp = fopen(filename,"rb")) == NULL) {
+       if ((fp = g_fopen(filename,"rb")) == NULL) {
                perror("fopen3");
                goto bail;
        }
        pathnew = g_strdup_printf("%s.new", filename);
-       if ((fpnew = fopen(pathnew, "wb")) == NULL) {
+       if ((fpnew = g_fopen(pathnew, "wb")) == NULL) {
                perror("fopen4");
                fclose(fp);
                g_free(pathnew);
                goto bail;
        }
        
-       while ((len = fread(buf, sizeof(gchar), sizeof(buf)-1, fp)) > 0) {
-               buf[len]='\0';
-               if (start) {
-                       start = FALSE;
-                       fprintf(fpnew, "SC-Marked-For-Download: %d\n", 
-                                       download);
-                       
-                       if(strlen(buf) > strlen("SC-Marked-For-Download: x\n")
-                       && !strncmp(buf, "SC-Marked-For-Download:", 
-                                   strlen("SC-Marked-For-Download:"))) {
-                               fprintf(fpnew, "%s", 
-                                buf+strlen("SC-Marked-For-Download: x\n"));
-                               continue;
+       if (fprintf(fpnew, "SC-Marked-For-Download: %d\n", 
+                       download) < 0) {
+               FILE_OP_ERROR(pathnew, "fprintf");
+               fclose(fpnew);
+               fclose(fp);
+               g_free(pathnew);
+               goto bail;
+       }
+       while (fgets(buf, sizeof(buf)-1, fp) != NULL) {
+               if(strlen(buf) > strlen("SC-Marked-For-Download: x\n")
+               && !strncmp(buf, "SC-Marked-For-Download:", 
+                           strlen("SC-Marked-For-Download:"))) {
+                       if (fprintf(fpnew, "%s", 
+                        buf+strlen("SC-Marked-For-Download: x\n")) < 0) {
+                               FILE_OP_ERROR(pathnew, "fprintf");
+                               fclose(fpnew);
+                               fclose(fp);
+                               g_free(pathnew);
+                               goto bail;
                        }
+                       continue;
+               } else if (strlen(buf) == strlen("SC-Marked-For-Download: x\n")
+               && !strncmp(buf, "SC-Marked-For-Download:", 
+                           strlen("SC-Marked-For-Download:"))) {
+                       continue;
+               }
+               if (fprintf(fpnew, "%s", buf) < 0) {
+                       FILE_OP_ERROR(pathnew, "fprintf");
+                       fclose(fpnew);
+                       fclose(fp);
+                       g_free(pathnew);
+                       goto bail;
                }
-               fprintf(fpnew, "%s", buf);
        }
-       fclose(fpnew);
+       if (fclose(fpnew) == EOF) {
+               FILE_OP_ERROR(pathnew, "fclose");
+               fclose(fp);
+               g_free(pathnew);
+               goto bail;
+       }
+
        fclose(fp);
-       unlink(filename);
-       rename(pathnew, filename);
+       if (rename_force(pathnew, filename) != 0) {
+               g_free(pathnew);
+               goto bail;
+       }
+
        g_free(pathnew);
        msginfo->planned_download = download;
        msgcache_update_msg(msginfo->folder->cache, msginfo);
@@ -274,7 +328,7 @@ static int partial_uidl_mark_mail(MsgInfo *msginfo, int download)
        err = 0;
 bail:
        g_free(filename);
-       procmsg_msginfo_free(tinfo);
+       procmsg_msginfo_free(&tinfo);
        
        return err;
 }
@@ -301,7 +355,7 @@ void partial_delete_old(const gchar *file)
        int num = 0;
        FolderItem *item = NULL;
 
-       debug_print("too big message updated,should remove %s\n", file);
+       debug_print("too big message updated, should remove %s\n", file?file:"(null)");
 
        if (snum) {
                snum++;
@@ -333,7 +387,6 @@ gchar *partial_get_filename(const gchar *server, const gchar *login,
        gchar uidl[POPBUFSIZE];
        time_t recv_time;
        time_t now;
-       gint partial_recv;
        gchar *sanitized_uid = g_strdup(login); 
 
        subst_for_filename(sanitized_uid);
@@ -341,13 +394,13 @@ gchar *partial_get_filename(const gchar *server, const gchar *login,
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                           "uidl", G_DIR_SEPARATOR_S, 
                           server, "-", sanitized_uid, NULL);
-       if ((fp = fopen(path, "rb")) == NULL) {
+       if ((fp = g_fopen(path, "rb")) == NULL) {
                if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
                g_free(path);
                path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                   "uidl-", server,
                                   "-", sanitized_uid, NULL);
-               if ((fp = fopen(path, "rb")) == NULL) {
+               if ((fp = g_fopen(path, "rb")) == NULL) {
                        if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
                        g_free(sanitized_uid);
                        g_free(path);
@@ -363,9 +416,9 @@ gchar *partial_get_filename(const gchar *server, const gchar *login,
                gchar tmp[POPBUFSIZE];
                strretchomp(buf);
                recv_time = RECV_TIME_NONE;
-               partial_recv = POP3_TOTALLY_RECEIVED;
                
-               if (sscanf(buf, "%s\t%ld\t%s", uidl, &recv_time, tmp) < 2) {
+               if (sscanf(buf, "%s\t%ld\t%s", uidl, (long int *) &recv_time, 
+                          tmp) < 2) {
                        if (sscanf(buf, "%s", uidl) != 1)
                                continue;
                        else {