update copyright year
[claws.git] / src / plugins / vcalendar / vcal_folder.c
index 97e7ded8de2b6d545a14a8a4362ce9ba04d0e4ec..1581691a8351a5658aca29603a4565d623783b8e 100644 (file)
@@ -1,7 +1,6 @@
 /*
- * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2015 Colin Leroy <colin@colino.net> and
- * the Claws Mail team
+ * Claws Mail -- a GTK based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2024 the Claws Mail team and Colin Leroy <colin@colino.net>
  *
  * 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
 #include <unistd.h>
 #include <curl/curl.h>
 #include <curl/curlver.h>
+#include <ctype.h>
 
 #include "account.h"
+#include "file-utils.h"
 #include "utils.h"
 #include "procmsg.h"
 #include "procheader.h"
@@ -65,9 +66,6 @@
 #include "messageview.h"
 
 #include <gtk/gtk.h>
-#include <dirent.h>
-
-#define VCAL_FOLDERITEM(item) ((VCalFolderItem *) item)
 
 #ifdef USE_PTHREAD
 #include <pthread.h>
@@ -1168,8 +1166,8 @@ static void vcal_set_mtime(Folder *folder, FolderItem *item)
        }
 
        item->mtime = s.st_mtime;
-       debug_print("VCAL: forced mtime of %s to %lld\n",
-                       item->name?item->name:"(null)", (long long)item->mtime);
+       debug_print("VCAL: forced mtime of %s to %"CM_TIME_FORMAT"\n",
+                       item->name?item->name:"(null)", item->mtime);
        g_free(path);
 }
 
@@ -1294,7 +1292,8 @@ void vcal_folder_gtk_done(void)
                if (!file)                      
                        continue;
                debug_print("removing %s\n", file);
-               g_unlink(file);
+               if (g_unlink(file) < 0)
+                        FILE_OP_ERROR(file, "g_unlink");
                g_free(file);
        }
        g_slist_free(created_files);
@@ -1469,14 +1468,13 @@ gchar* get_item_event_list_for_date(FolderItem *item, EventTime date)
                        if (days != date)
                                continue;
                        prop = icalcomponent_get_first_property((icalcomponent *)fdata->event, ICAL_SUMMARY_PROPERTY);
-                       if (prop) {
-                               if (!g_utf8_validate(icalproperty_get_summary(prop), -1, NULL))
-                                       summary = conv_codeset_strdup(icalproperty_get_summary(prop), 
+                       summary = g_strdup(icalproperty_get_summary(prop));
+                       if (summary) {
+                               if (!g_utf8_validate(summary, -1, NULL))
+                                       summary = conv_codeset_strdup(summary, 
                                                conv_get_locale_charset_str(), CS_UTF_8);
-                               else
-                                       summary = g_strdup(icalproperty_get_summary(prop));
                        } else
-                               summary = g_strdup("-");
+                               summary = g_strdup(_("[no summary]"));
 
                        strs = g_slist_prepend(strs, summary);
                }
@@ -1531,8 +1529,7 @@ gchar* get_item_event_list_for_date(FolderItem *item, EventTime date)
                        strcpy(result+e_len+2, (gchar *)cur->data);
                }
        }
-       slist_free_strings(strs);
-       g_slist_free(strs);
+       slist_free_strings_full(strs);
        return result;
 }
 
@@ -1549,17 +1546,20 @@ static size_t curl_recv(void *buf, size_t size, size_t nmemb, void *stream)
 {
        struct CBuf *buffer = (struct CBuf *)stream;
        gchar *tmp = NULL;
-       gchar tmpbuf[size*nmemb + 1];
+       gchar *tmpbuf = g_malloc0(size*nmemb + 1);
+
+       g_return_val_if_fail(tmpbuf != NULL, 0);
 
        memcpy(tmpbuf, buf, size*nmemb);
-       tmpbuf[size*nmemb] = '\0';
 
        if (buffer->str) {
+               /* If the buffer already has contents, append the new data. */
                tmp = g_strconcat(buffer->str, tmpbuf, NULL);
+               g_free(tmpbuf);
                g_free(buffer->str);
                buffer->str = tmp;
        } else {
-               buffer->str = g_strdup(tmpbuf);
+               buffer->str = tmpbuf;
        }
 
        return size*nmemb;
@@ -1591,6 +1591,9 @@ void *url_read_thread(void *data)
        curl_easy_setopt(curl_ctx, CURLOPT_WRITEDATA, &buffer);
        curl_easy_setopt(curl_ctx, CURLOPT_TIMEOUT, prefs_common_get_prefs()->io_timeout_secs);
        curl_easy_setopt(curl_ctx, CURLOPT_NOSIGNAL, 1);
+#ifdef G_OS_WIN32
+       curl_easy_setopt(curl_ctx, CURLOPT_CAINFO, claws_ssl_get_cert_file());
+#endif
 #if LIBCURL_VERSION_NUM >= 0x070a00
        if(vcalprefs.ssl_verify_peer == FALSE) {
                curl_easy_setopt(curl_ctx, CURLOPT_SSL_VERIFYPEER, 0);
@@ -1647,7 +1650,6 @@ gchar *vcal_curl_read(const char *url, const gchar *label, gboolean verbose,
        thread_data *td;
 #ifdef USE_PTHREAD
        pthread_t pt;
-       pthread_attr_t pta;
 #endif
        void *res;
        gchar *error = NULL;
@@ -1662,10 +1664,7 @@ gchar *vcal_curl_read(const char *url, const gchar *label, gboolean verbose,
        STATUSBAR_PUSH(mainwindow_get_mainwindow(), label);
 
 #ifdef USE_PTHREAD
-       if (pthread_attr_init(&pta) != 0 ||
-           pthread_attr_setdetachstate(&pta, PTHREAD_CREATE_JOINABLE) != 0 ||
-           pthread_create(&pt, &pta, 
-                       url_read_thread, td) != 0) {
+       if (pthread_create(&pt, NULL, url_read_thread, td) != 0) {
                url_read_thread(td);    
        }
        while (!td->done)  {
@@ -1718,6 +1717,9 @@ gboolean vcal_curl_put(gchar *url, FILE *fp, gint filesize, const gchar *user, c
        curl_easy_setopt(curl_ctx, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl_ctx, CURLOPT_READDATA, fp);
        curl_easy_setopt(curl_ctx, CURLOPT_HTTPHEADER, headers);
+#ifdef G_OS_WIN32
+       curl_easy_setopt(curl_ctx, CURLOPT_CAINFO, claws_ssl_get_cert_file());
+#endif
 #if LIBCURL_VERSION_NUM >= 0x070a00
        if(vcalprefs.ssl_verify_peer == FALSE) {
                curl_easy_setopt(curl_ctx, CURLOPT_SSL_VERIFYPEER, 0);
@@ -1739,7 +1741,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", response_code);
+               g_warning("can't export calendar, got code %ld", response_code);
                res = FALSE;
        }
        curl_easy_cleanup(curl_ctx);
@@ -1782,19 +1784,10 @@ static gchar *feed_get_title(const gchar *str)
        gchar *title = NULL;
        if (strstr(str, "X-WR-CALNAME:")) {
                title = g_strdup(strstr(str, "X-WR-CALNAME:")+strlen("X-WR-CALNAME:"));
-               if (strstr(title, "\n"))
-                       *(strstr(title, "\n")) = '\0';
-               if (strstr(title, "\r"))
-                       *(strstr(title, "\r")) = '\0';          
        } else if (strstr(str, "X-WR-CALDESC:")) {
                title = g_strdup(strstr(str, "X-WR-CALDESC:")+strlen("X-WR-CALDESC:"));
-               if (strstr(title, "\n"))
-                       *(strstr(title, "\n")) = '\0';
-               if (strstr(title, "\r"))
-                       *(strstr(title, "\r")) = '\0';          
        }
-       
-       return title;
+       return strcrlftrunc(title);
 }
 
 static void update_subscription_finish(const gchar *uri, gchar *feed, gboolean verbose, gchar *error)
@@ -1837,7 +1830,12 @@ static void update_subscription_finish(const gchar *uri, gchar *feed, gboolean v
                        g_free(error);
                return;
        }
-       if (strncmp(feed, "BEGIN:VCALENDAR", strlen("BEGIN:VCALENDAR"))) {
+
+       gchar *tmp = feed;
+       while (*tmp && isspace((unsigned char)*tmp))
+               tmp++;
+
+       if (strncmp(tmp, "BEGIN:VCALENDAR", strlen("BEGIN:VCALENDAR"))) {
                gchar *err_msg = _("This URL does not look like a Webcal URL:\n%s\n%s");
 
                if (verbose && manual_update) {
@@ -1946,8 +1944,45 @@ static void subscribe_cal_cb(GtkAction *action, gpointer data)
 {
        gchar *uri = NULL;
        gchar *tmp = NULL;
+       gchar *clip_text = NULL, *str = NULL;
+
+    clip_text = gtk_clipboard_wait_for_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
+
+    if (clip_text) {
+        str = clip_text;
+#if GLIB_CHECK_VERSION(2,66,0)
+        GError *error = NULL;
+        GUri *uri = NULL;
+
+        /* skip any leading white-space */
+        while (str && *str && g_ascii_isspace(*str))
+            str++;
+        uri = g_uri_parse(str, G_URI_FLAGS_PARSE_RELAXED, &error);
+        if (error) {
+            g_warning("could not parse clipboard text for URI: '%s'", error->message);
+            g_error_free(error);
+        }
+        if (uri) {
+            gchar* newstr = g_uri_to_string(uri);
+
+            debug_print("URI: '%s' -> '%s'\n", str, newstr ? newstr : "N/A");
+            if (newstr)
+                g_free(newstr);
+            g_uri_unref(uri);
+        } else {
+#else
+        if (!is_uri_string(str)) {
+#endif
+            /* if no URL, ignore clipboard text */
+            str = NULL;
+        }
+    }
+
+       tmp = input_dialog(_("Subscribe to Webcal"), _("Enter the Webcal URL:"), str ? str : "");
+
+       if (clip_text)
+               g_free(clip_text);
 
-       tmp = input_dialog(_("Subscribe to Webcal"), _("Enter the WebCal URL:"), NULL);
        if (tmp == NULL)
                return;
        
@@ -1989,8 +2024,9 @@ static void unsubscribe_cal_cb(GtkAction *action, gpointer data)
        message = g_strdup_printf
                (_("Do you really want to unsubscribe?"));
        avalue = alertpanel_full(_("Delete subscription"), message,
-                                GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, 
-                                FALSE, NULL, ALERT_WARNING, G_ALERTDEFAULT);
+                                NULL, _("_Cancel"), "edit-delete", _("_Delete"),
+                                NULL, NULL, ALERTFOCUS_FIRST,
+                                FALSE, NULL, ALERT_WARNING);
        g_free(message);
        if (avalue != G_ALERTALTERNATE) return;
 
@@ -2480,8 +2516,10 @@ gchar* vcal_add_event(const gchar *vevent)
        VCalEvent *event = vcal_get_event_from_ical(vevent, NULL);
        gchar *retVal = NULL;
        Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
-       if (!folder)
+       if (!folder) {
+               vcal_manager_free_event(event);
                return NULL;
+       }
 
        if (event) {
                if (vcal_event_exists(event->uid)) {