Make procmsg_msginfo_free() zero out pointers to freed memory.
[claws.git] / src / plugins / vcalendar / vcal_folder.c
index e18240a95a9dbe0e1ded0b13df2e4ffaea6ecb66..c52a399701ff9ba484e5e1681d7fc875e9e2d8a7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and 
+ * Copyright (C) 1999-2015 Colin Leroy <colin@colino.net> and
  * the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,8 +14,7 @@
  * 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/>.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -706,9 +705,10 @@ add_new:
 
 GSList *vcal_get_events_list(FolderItem *item)
 {
-       DIR *dp;
-       struct dirent *d;
+       GDir *dp;
+       const gchar *d;
        GSList *events = NULL;
+       GError *error = NULL;
 
        if (item != item->folder->inbox) {
                GSList *subs = vcal_folder_get_webcal_events_for_folder(item);
@@ -725,27 +725,29 @@ GSList *vcal_get_events_list(FolderItem *item)
                return events;
        }
 
-       dp = opendir(vcal_manager_get_event_path());
+       dp = g_dir_open(vcal_manager_get_event_path(), 0, &error);
        
        if (!dp) {
-               FILE_OP_ERROR(vcal_manager_get_event_path(), "opendir");
+               debug_print("couldn't open dir '%s': %s (%d)\n",
+                               vcal_manager_get_event_path(), error->message, error->code);
+               g_error_free(error);
                return 0;
        }
 
-       while ((d = readdir(dp)) != NULL) {
+       while ((d = g_dir_read_name(dp)) != NULL) {
                VCalEvent *event = NULL;
-               if (d->d_name[0] == '.' || strstr(d->d_name, ".bak")
-               ||  !strcmp(d->d_name, "internal.ics")
-               ||  !strcmp(d->d_name, "internal.ifb")
-               ||  !strcmp(d->d_name, "multisync")) 
+               if (d[0] == '.' || strstr(d, ".bak")
+               ||  !strcmp(d, "internal.ics")
+               ||  !strcmp(d, "internal.ifb")
+               ||  !strcmp(d, "multisync")) 
                        continue;
 
-               event = vcal_manager_load_event(d->d_name);
+               event = vcal_manager_load_event(d);
                if (!event)
                        continue;
                if (event->rec_occurence) {
                        vcal_manager_free_event(event);
-                       claws_unlink(d->d_name);
+                       claws_unlink(d);
                        continue;
                }
 
@@ -771,7 +773,7 @@ GSList *vcal_get_events_list(FolderItem *item)
                                struct icaldurationtype ical_dur;
                                int i = 0;
 
-                               debug_print("dumping recurring events from main event %s\n", d->d_name);
+                               debug_print("dumping recurring events from main event %s\n", d);
                                recur = icalrecurrencetype_from_string(event->recur);
                                dtstart = icaltime_from_string(event->dtstart);
 
@@ -822,7 +824,7 @@ GSList *vcal_get_events_list(FolderItem *item)
                        vcal_manager_free_event(event);
                }
        }
-       closedir(dp);
+       g_dir_close(dp);
        return g_slist_reverse(events);
 }
 
@@ -1051,7 +1053,7 @@ static gint vcal_remove_msg(Folder *folder, FolderItem *_item, gint num)
        if (_item == folder->inbox)
                vcal_remove_event(folder, msginfo);
 
-       procmsg_msginfo_free(msginfo);
+       procmsg_msginfo_free(&msginfo);
        return 0;
 }
 
@@ -1124,7 +1126,7 @@ static gint vcal_remove_folder(Folder *folder, FolderItem *fitem)
 
 static gboolean vcal_scan_required(Folder *folder, FolderItem *item)
 {
-       struct stat s;
+       GStatBuf s;
        VCalFolderItem *vitem = (VCalFolderItem *)item;
 
        g_return_val_if_fail(item != NULL, FALSE);
@@ -1144,7 +1146,7 @@ static gint vcal_folder_lock_count = 0;
 
 static void vcal_set_mtime(Folder *folder, FolderItem *item)
 {
-       struct stat s;
+       GStatBuf s;
        gchar *path = folder_item_get_path(item);
 
        if (folder->inbox != item)
@@ -1159,7 +1161,8 @@ static void vcal_set_mtime(Folder *folder, FolderItem *item)
        }
 
        item->mtime = s.st_mtime;
-       debug_print("VCAL: forced mtime of %s to %ld\n", item->name?item->name:"(null)", item->mtime);
+       debug_print("VCAL: forced mtime of %s to %lld\n",
+                       item->name?item->name:"(null)", (long long)item->mtime);
        g_free(path);
 }
 
@@ -1626,12 +1629,10 @@ gchar *vcal_curl_read(const char *url, const gchar *label, gboolean verbose,
        pthread_attr_t pta;
 #endif
        void *res;
-       gboolean killed;
        gchar *error = NULL;
        result = NULL;
        td = g_new0(thread_data, 1);
        res = NULL;
-       killed = FALSE;
 
        td->url  = url;
        td->result  = NULL;
@@ -1704,7 +1705,7 @@ gboolean vcal_curl_put(gchar *url, FILE *fp, gint filesize, const gchar *user, c
 #endif
        curl_easy_setopt(curl_ctx, CURLOPT_USERAGENT, 
                "Claws Mail vCalendar plugin "
-               "(http://www.claws-mail.org/plugins.php)");
+               "(" PLUGINS_URI ")");
        curl_easy_setopt(curl_ctx, CURLOPT_INFILESIZE, filesize);
        res = curl_easy_perform(curl_ctx);
        g_free(userpwd);
@@ -1717,7 +1718,7 @@ gboolean vcal_curl_put(gchar *url, FILE *fp, gint filesize, const gchar *user, c
 
        curl_easy_getinfo(curl_ctx, CURLINFO_RESPONSE_CODE, &response_code);
        if (response_code < 200 || response_code >= 300) {
-               g_warning("Can't export calendar, got code %ld\n", response_code);
+               g_warning("Can't export calendar, got code %ld", response_code);
                res = FALSE;
        }
        curl_easy_cleanup(curl_ctx);
@@ -1782,7 +1783,7 @@ static void update_subscription_finish(const gchar *uri, gchar *feed, gboolean v
        icalcomponent *cal = NULL;
        
        if (root == NULL) {
-               g_warning("can't get root folder\n");
+               g_warning("can't get root folder");
                g_free(feed);
                if (error)
                        g_free(error);
@@ -1846,6 +1847,19 @@ static void update_subscription_finish(const gchar *uri, gchar *feed, gboolean v
                        }
                }
                item = folder_create_folder(root->node->data, title);
+               if (!item) {
+                       if (verbose && manual_update) {
+                               alertpanel_error(_("Could not create directory %s"),
+                                       title);
+                       } else  {
+                               log_error(LOG_PROTOCOL, _("Could not create directory %s"),
+                                       title);
+                       }
+                       g_free(feed);
+                       g_free(title);
+                       main_window_cursor_normal(mainwindow_get_mainwindow());
+                       return;
+               }
                debug_print("item done %s\n", title);
                ((VCalFolderItem *)item)->uri = g_strdup(uri);
                ((VCalFolderItem *)item)->feed = feed;
@@ -1941,12 +1955,11 @@ static void unsubscribe_cal_cb(GtkAction *action, gpointer data)
        FolderItem *item;
        gchar *message;
        AlertValue avalue;
-       gchar *old_path;
        gchar *old_id;
 
        if (!folderview->selected) return;
 
-       item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
+       item = folderview_get_selected_item(folderview);
        g_return_if_fail(item != NULL);
        g_return_if_fail(item->path != NULL);
        g_return_if_fail(item->folder != NULL);
@@ -1959,7 +1972,6 @@ static void unsubscribe_cal_cb(GtkAction *action, gpointer data)
        g_free(message);
        if (avalue != G_ALERTALTERNATE) return;
 
-       Xstrdup_a(old_path, item->path, return);
        old_id = folder_item_get_identifier(item);
 
        vcal_item_closed(item);
@@ -2054,14 +2066,16 @@ static void set_view_cb(GtkAction *gaction, GtkRadioAction *current, gpointer da
 {
        FolderView *folderview = (FolderView *)data;
        gint action = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (current));
-       GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
        FolderItem *item = NULL, *oitem = NULL;
 
        if (!folderview->selected) return;
        if (setting_sensitivity) return;
 
-       oitem = gtk_cmctree_node_get_row_data(ctree, folderview->opened);
-       item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
+       oitem = folderview_get_opened_item(folderview);
+       item = folderview_get_selected_item(folderview);
+
+       if (!item)
+               return;
 
        if (((VCalFolderItem *)(item))->use_cal_view == action)
                return;
@@ -2122,6 +2136,43 @@ static gchar *get_email_from_property(icalproperty *p)
        return email;
 }
 
+static void adjust_for_local_time_zone(icalproperty *eventtime, icalproperty *tzoffsetto, int dtstart)
+{
+       int tzoffset;
+       int loctzoffset;
+       time_t loctime, gmttime, evttime;
+       struct icaltimetype icaltime;
+
+       /* calculate local UTC offset */
+       loctime = time(NULL);
+       loctime = mktime(localtime(&loctime));
+       gmttime = mktime(gmtime(&loctime));
+       loctzoffset = loctime - gmttime;
+
+       if (eventtime && tzoffsetto) {
+               tzoffset = icalproperty_get_tzoffsetto(tzoffsetto);
+               if (dtstart) {
+                       evttime = icaltime_as_timet(icalproperty_get_dtstart(eventtime));
+               }
+               else {
+                       evttime = icaltime_as_timet(icalproperty_get_dtend(eventtime));
+               }
+
+               /* convert to UTC */
+               evttime -= tzoffset;
+               /* and adjust for local time zone */
+               evttime += loctzoffset;
+               icaltime = icaltime_from_timet(evttime, 0);
+
+               if (dtstart) {
+                       icalproperty_set_dtstart(eventtime, icaltime);
+               }
+               else {
+                       icalproperty_set_dtend(eventtime, icaltime);
+               } 
+       }
+}
+
 #define GET_PROP(comp,prop,kind) {                                             \
        prop = NULL;                                                            \
        if (!(prop = icalcomponent_get_first_property(comp, kind))) {           \
@@ -2161,6 +2212,7 @@ VCalEvent *vcal_get_event_from_ical(const gchar *ical, const gchar *charset)
        gchar *int_ical = g_strdup(ical);
        icalcomponent *comp = icalcomponent_new_from_string(int_ical);
        icalcomponent *inner = NULL;
+       icalcomponent *tzcomp = NULL;
        icalproperty *prop = NULL;
        GSList *list = NULL, *cur = NULL;
        gchar *uid = NULL;
@@ -2175,7 +2227,7 @@ VCalEvent *vcal_get_event_from_ical(const gchar *ical, const gchar *charset)
        gchar *recur = NULL;
        int sequence = 0;
        enum icalproperty_method method = ICAL_METHOD_REQUEST;
-       enum icalproperty_kind type = ICAL_VEVENT_COMPONENT;
+       enum icalcomponent_kind type = ICAL_VEVENT_COMPONENT;
        GSList *attendees = NULL;
        
        if (comp == NULL) {
@@ -2204,6 +2256,31 @@ VCalEvent *vcal_get_event_from_ical(const gchar *ical, const gchar *charset)
                TO_UTF8(summary);
                icalproperty_free(prop);
        }
+       tzcomp = icalcomponent_get_first_component(comp, ICAL_VTIMEZONE_COMPONENT);
+       if (tzcomp) {
+               icalproperty *evtstart = NULL;
+               icalproperty *evtend = NULL;
+               icalproperty *tzoffsetto = NULL;
+               icalcomponent *tzstd = NULL;
+
+               tzstd = icalcomponent_get_first_component(tzcomp, ICAL_XSTANDARD_COMPONENT);
+               tzoffsetto = icalcomponent_get_first_property(tzstd, ICAL_TZOFFSETTO_PROPERTY);
+
+               GET_PROP(comp, evtstart, ICAL_DTSTART_PROPERTY);
+               adjust_for_local_time_zone(evtstart, tzoffsetto, TRUE);
+
+               GET_PROP(comp, evtend, ICAL_DTEND_PROPERTY);
+               adjust_for_local_time_zone(evtend, tzoffsetto, FALSE);
+
+               if (tzoffsetto)
+                       icalproperty_free(tzoffsetto);
+               if (evtstart)
+                       icalproperty_free(evtstart);
+               if (evtend)
+                       icalproperty_free(evtend);
+               if (tzstd)
+                       icalcomponent_free(tzstd);
+       }
        GET_PROP(comp, prop, ICAL_DTSTART_PROPERTY);
        if (prop) {
                dtstart = g_strdup(icaltime_as_ical_string(icalproperty_get_dtstart(prop)));
@@ -2340,7 +2417,7 @@ gboolean vcal_event_exists(const gchar *id)
 
        info = folder_item_get_msginfo_by_msgid(folder->inbox, id);
        if (info != NULL) {
-               procmsg_msginfo_free(info);
+               procmsg_msginfo_free(&info);
                return TRUE;
        }
        return FALSE;
@@ -2378,7 +2455,7 @@ gboolean vcal_delete_event(const gchar *id)
        if (info != NULL) {
                debug_print("removing event %s\n", id);
                vcal_remove_event(folder, info);
-               procmsg_msginfo_free(info);
+               procmsg_msginfo_free(&info);
                folder_item_scan(folder->inbox);
                return TRUE;
        }