update copyright year
[claws.git] / src / plugins / vcalendar / vcal_manager.c
index 1432e0f36ee6640e5037e4d8f015dcd059f6eccb..b7f6c6d25baa52226d97ad937d51040b06b81f8d 100644 (file)
@@ -1,7 +1,6 @@
 /*
- * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and 
- * the Claws Mail team
+ * Claws Mail -- a GTK based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2023 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
@@ -32,7 +31,7 @@
 #ifdef USE_PTHREAD
 #include <pthread.h>
 #endif
-#include <ical.h>
+#include <libical/ical.h>
 #include "vcalendar.h"
 #include "vcal_folder.h"
 #include "vcal_manager.h"
@@ -49,7 +48,9 @@
 #include <time.h>
 #include "folder.h"
 #include "quoted-printable.h"
+#include "file-utils.h"
 #include "utils.h"
+#include "defs.h"
 
 #ifdef G_OS_WIN32
 #define getuid() 0
@@ -57,8 +58,8 @@
 
 Answer *answer_new(const gchar *attendee, 
                          const gchar *name,
-                         enum icalparameter_partstat ans,
-                         enum icalparameter_cutype cutype)
+                         icalparameter_partstat ans,
+                         icalparameter_cutype cutype)
 {
        Answer *answer = g_new0(Answer, 1);
        answer->attendee = g_strdup(attendee);
@@ -103,7 +104,7 @@ void vcal_manager_copy_attendees(VCalEvent *src, VCalEvent *dest)
        dest->answers = g_slist_reverse(dest->answers);
 }
 
-gchar *vcal_manager_answer_get_text(enum icalparameter_partstat ans) 
+gchar *vcal_manager_answer_get_text(icalparameter_partstat ans) 
 {
        static gchar *replies[5]={
                N_("accepted"),
@@ -130,13 +131,14 @@ gchar *vcal_manager_answer_get_text(enum icalparameter_partstat ans)
        case ICAL_PARTSTAT_X:
        case ICAL_PARTSTAT_INPROCESS:
        case ICAL_PARTSTAT_NONE:
+  case ICAL_PARTSTAT_FAILED:
                return _(replies[4]);
                break;                  
        }
        return NULL;
 }
 
-gchar *vcal_manager_cutype_get_text(enum icalparameter_cutype type) 
+gchar *vcal_manager_cutype_get_text(icalparameter_cutype type) 
 {
        static gchar *replies[5]={
                N_("individual"),
@@ -195,11 +197,11 @@ GSList *vcal_manager_get_answers_emails(VCalEvent *event)
        return new;     
 }
 
-enum icalparameter_partstat vcal_manager_get_reply_for_attendee(VCalEvent *event, const gchar *att)
+icalparameter_partstat vcal_manager_get_reply_for_attendee(VCalEvent *event, const gchar *att)
 {
        Answer *a = answer_new(att, NULL, 0, 0);
        GSList *ans = answer_find(event, a);
-       enum icalparameter_partstat res = 0;
+       icalparameter_partstat res = 0;
        if (ans) {
                Answer *b = (Answer *)ans->data;
                res = b->answer;
@@ -210,7 +212,7 @@ enum icalparameter_partstat vcal_manager_get_reply_for_attendee(VCalEvent *event
 
 gchar *vcal_manager_get_cutype_text_for_attendee(VCalEvent *event, const gchar *att)
 {
-       enum icalparameter_cutype status = vcal_manager_get_cutype_for_attendee(event, att);
+       icalparameter_cutype status = vcal_manager_get_cutype_for_attendee(event, att);
        gchar *res = NULL;
        if (status != 0) 
                res = g_strdup(vcal_manager_cutype_get_text(status));
@@ -218,11 +220,11 @@ gchar *vcal_manager_get_cutype_text_for_attendee(VCalEvent *event, const gchar *
        return res;
 }
 
-enum icalparameter_partstat vcal_manager_get_cutype_for_attendee(VCalEvent *event, const gchar *att)
+icalparameter_cutype vcal_manager_get_cutype_for_attendee(VCalEvent *event, const gchar *att)
 {
        Answer *a = answer_new(att, NULL, 0, 0);
        GSList *ans = answer_find(event, a);
-       enum icalparameter_cutype res = 0;
+       icalparameter_cutype res = 0;
        if (ans) {
                Answer *b = (Answer *)ans->data;
                res = b->cutype;
@@ -233,7 +235,7 @@ enum icalparameter_partstat vcal_manager_get_cutype_for_attendee(VCalEvent *even
 
 gchar *vcal_manager_get_reply_text_for_attendee(VCalEvent *event, const gchar *att)
 {
-       enum icalparameter_partstat status = vcal_manager_get_reply_for_attendee(event, att);
+       icalparameter_partstat status = vcal_manager_get_reply_for_attendee(event, att);
        gchar *res = NULL;
        if (status != 0) 
                res = g_strdup(vcal_manager_answer_get_text(status));
@@ -311,7 +313,7 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
        icalcomponent *calendar, *ievent, *timezone, *tzc;
        icalproperty *attprop;
        icalproperty *orgprop;
-       enum icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
+       icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
        gchar *sanitized_uid = g_strdup(event->uid);
        
        subst_for_filename(sanitized_uid);
@@ -351,7 +353,7 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
                            );  
 
        if (!calendar) {
-               g_warning ("can't generate calendar");
+               g_warning("can't generate calendar");
                g_free(organizer);
                g_free(tmpfile);
                g_free(attendee);
@@ -383,7 +385,7 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
                 ICAL_VEVENT_COMPONENT, (void*)0);
 
        if (!ievent) {
-               g_warning ("can't generate event");
+               g_warning("can't generate event");
                g_free(organizer);
                g_free(tmpfile);
                g_free(attendee);
@@ -393,14 +395,14 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
        icalcomponent_add_property(ievent,
                 icalproperty_new_uid(event->uid));
        icalcomponent_add_property(ievent,
-               icalproperty_vanew_dtstamp(icaltime_from_timet(time(NULL), TRUE), 0));
+               icalproperty_vanew_dtstamp(icaltime_from_timet_with_zone(time(NULL), TRUE, NULL), (void*)0));
        icalcomponent_add_property(ievent,
-               icalproperty_vanew_dtstart((icaltime_from_string(event->dtstart)), 0));
+               icalproperty_vanew_dtstart((icaltime_from_string(event->dtstart)), (void*)0));
        icalcomponent_add_property(ievent,
-               icalproperty_vanew_dtend((icaltime_from_string(event->dtend)), 0));
+               icalproperty_vanew_dtend((icaltime_from_string(event->dtend)), (void*)0));
        if (event->recur && *(event->recur)) {
                icalcomponent_add_property(ievent,
-                       icalproperty_vanew_rrule((icalrecurrencetype_from_string(event->recur)), 0));
+                       icalproperty_vanew_rrule((icalrecurrencetype_from_string(event->recur)), (void*)0));
        }
        icalcomponent_add_property(ievent,
                icalproperty_new_description(event->description));
@@ -409,9 +411,9 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
        icalcomponent_add_property(ievent,
                icalproperty_new_sequence(modif && !is_reply ? event->sequence + 1 : event->sequence));
        icalcomponent_add_property(ievent,
-               icalproperty_new_class("PUBLIC"));
+               icalproperty_new_class(ICAL_CLASS_PUBLIC));
        icalcomponent_add_property(ievent,
-               icalproperty_new_transp("OPAQUE"));
+               icalproperty_new_transp(ICAL_TRANSP_OPAQUE));
        if (event->location && *event->location)
                icalcomponent_add_property(ievent,
                        icalproperty_new_location(event->location));
@@ -421,9 +423,9 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
        icalcomponent_add_property(ievent,
                icalproperty_new_status(ICAL_STATUS_CONFIRMED));
        icalcomponent_add_property(ievent,
-               icalproperty_vanew_created(icaltime_from_timet(time(NULL), TRUE), 0));
+               icalproperty_vanew_created(icaltime_from_timet_with_zone(time(NULL), TRUE, NULL), (void*)0));
        icalcomponent_add_property(ievent,
-               icalproperty_vanew_lastmodified(icaltime_from_timet(time(NULL), TRUE), 0));
+               icalproperty_vanew_lastmodified(icaltime_from_timet_with_zone(time(NULL), TRUE, NULL), (void*)0));
        icalcomponent_add_property(ievent,              
                 orgprop);
 
@@ -448,7 +450,7 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
                                ICAL_ROLE_REQPARTICIPANT),
                            icalparameter_new_rsvp(ICAL_RSVP_TRUE),
                            icalparameter_new_partstat(status),
-                           0
+                           (void*)0
                            );
                icalcomponent_add_property(ievent, attprop);
        } else {
@@ -470,7 +472,7 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
                                    icalparameter_new_rsvp(ICAL_RSVP_TRUE),
                                    icalparameter_new_cutype(a->cutype),
                                    icalparameter_new_partstat(a->answer),
-                                   0
+                                   (void*)0
                                    );
 
                        icalcomponent_add_property(ievent, attprop);
@@ -499,7 +501,7 @@ gchar *vcal_manager_event_dump(VCalEvent *event, gboolean is_reply, gboolean is_
                               "\n"
                               "%s", headers, icalcomponent_as_ical_string(calendar));
        
-       if (str_write_to_file(body, tmpfile) < 0) {
+       if (str_write_to_file(body, tmpfile, FALSE) < 0) {
                g_free(tmpfile);
                tmpfile = NULL;
        }
@@ -527,15 +529,30 @@ static void get_rfc822_date_from_time_t(gchar *buf, gint len, time_t t)
        struct tm buft2;
 
        lt = localtime_r(&t, &buft2);
-       sscanf(asctime_r(lt, buft1), "%3s %3s %d %d:%d:%d %d\n",
-              day, mon, &dd, &hh, &mm, &ss, &yyyy);
+       if (sscanf(asctime_r(lt, buft1), "%3s %3s %d %d:%d:%d %d\n",
+              day, mon, &dd, &hh, &mm, &ss, &yyyy) != 7)
+               g_warning("failed reading date/time");
        g_snprintf(buf, len, "%s, %d %s %d %02d:%02d:%02d %s",
                   day, dd, mon, yyyy, hh, mm, ss, tzoffset(&t));
 #else
        GDateTime *dt = g_date_time_new_from_unix_local(t);
-       gchar *buf2 = g_date_time_format(dt, "%a, %e %b %Y %H:%M:%S %Z");
-       strncpy(buf, buf2, len);
-       g_free(buf2);
+       if (dt == NULL) {
+               g_warning("failed getting date/time");
+               g_snprintf(buf, len, "(NULL)");
+               return;
+       }
+
+       gchar *ret = g_date_time_format(dt, "%a, %e %b %Y %T %z");
+       g_date_time_unref(dt);
+
+       if (ret == NULL) {
+               g_warning("failed formatting date/time");
+               g_snprintf(buf, len, "(NULL)");
+               return;
+       }
+
+       g_snprintf(buf, len, ret);
+       g_free(ret);
 #endif
 }
 
@@ -543,10 +560,9 @@ static gchar *write_headers_date(const gchar *uid)
 {
        gchar subject[512];
        gchar *t_subject;
-       gchar date[128];
+       gchar date[RFC822_DATE_BUFFSIZE];
        time_t t;
        struct tm lt;
-       struct tm buft;
 
        memset(subject, 0, sizeof(subject));
        memset(date, 0, sizeof(date));
@@ -572,6 +588,7 @@ static gchar *write_headers_date(const gchar *uid)
        } 
        
 #ifndef G_OS_WIN32
+       struct tm buft;
        lt = *localtime_r(&t, &buft);
 #else
        if (t < 0)
@@ -635,7 +652,7 @@ gchar *vcal_manager_dateevent_dump(const gchar *uid, FolderItem *item)
                               "\n"
                               "%s", headers, lines);
        g_free(lines);
-       if (str_write_to_file(body, tmpfile) < 0) {
+       if (str_write_to_file(body, tmpfile, FALSE) < 0) {
                g_free(tmpfile);
                tmpfile = NULL;
        } else
@@ -704,7 +721,7 @@ gchar *vcal_manager_icalevent_dump(icalcomponent *event, gchar *orga, icalcompon
                            );  
 
        if (!calendar) {
-               g_warning ("can't generate calendar");
+               g_warning("can't generate calendar");
                g_free(tmpfile);
                icalcomponent_free(ievent);
                return NULL;
@@ -749,7 +766,7 @@ gchar *vcal_manager_icalevent_dump(icalcomponent *event, gchar *orga, icalcompon
                               "\n"
                               "%s", headers, qpbody);
        
-       if (str_write_to_file(body, tmpfile) < 0) {
+       if (str_write_to_file(body, tmpfile, FALSE) < 0) {
                g_free(tmpfile);
                tmpfile = NULL;
        } else
@@ -775,9 +792,9 @@ VCalEvent * vcal_manager_new_event  (const gchar    *uid,
                                         const gchar    *recur,
                                         const gchar    *tzid,
                                         const gchar    *url,
-                                        enum icalproperty_method method,
+                                        icalproperty_method method,
                                         gint            sequence,
-                                        enum icalcomponent_kind type)
+                                        icalcomponent_kind type)
 {
        VCalEvent *event = g_new0(VCalEvent, 1);
 
@@ -787,16 +804,16 @@ VCalEvent * vcal_manager_new_event        (const gchar    *uid,
 
        if (dtend && *(dtend)) {
                time_t tmp = icaltime_as_timet((icaltime_from_string(dtend)));
-               gchar buft[512];
-               tzset();
-               event->end      = g_strdup(ctime_r(&tmp, buft));
+               GDateTime *dt = g_date_time_new_from_unix_local(tmp);
+               event->end = g_date_time_format(dt, "%a, %e %b %Y %H:%M:%S %Z");
+               g_date_time_unref(dt);
        }
        
        if (dtstart && *(dtstart)) {
                time_t tmp = icaltime_as_timet((icaltime_from_string(dtstart)));
-               gchar buft[512];
-               tzset();
-               event->start    = g_strdup(ctime_r(&tmp, buft));
+               GDateTime *dt = g_date_time_new_from_unix_local(tmp);
+               event->start = g_date_time_format(dt, "%a, %e %b %Y %H:%M:%S %Z");
+               g_date_time_unref(dt);
        }
        event->dtstart          = g_strdup(dtstart?dtstart:"");
        event->dtend            = g_strdup(dtend?dtend:"");
@@ -809,7 +826,7 @@ VCalEvent * vcal_manager_new_event  (const gchar    *uid,
        event->method           = method;
        event->sequence         = sequence;
        event->type             = type;
-       event->rec_occurence            = FALSE;
+       event->rec_occurrence           = FALSE;
        while (strchr(event->summary, '\n'))
                *(strchr(event->summary, '\n')) = ' ';
 
@@ -921,12 +938,12 @@ void vcal_manager_save_event (VCalEvent *event, gboolean export_after)
        xml_tag_add_attr(tag, xml_attr_new("type", tmp));
        g_free(tmp);
        
-       tmp = g_strdup_printf("%lld", (long long)event->postponed);
+       tmp = g_strdup_printf("%"CM_TIME_FORMAT, event->postponed);
        xml_tag_add_attr(tag, xml_attr_new("postponed", tmp));
        g_free(tmp);
        
-       tmp = g_strdup_printf("%d", event->rec_occurence);
-       xml_tag_add_attr(tag, xml_attr_new("rec_occurence", tmp));
+       tmp = g_strdup_printf("%d", event->rec_occurrence);
+       xml_tag_add_attr(tag, xml_attr_new("rec_occurrence", tmp));
        g_free(tmp);
        
        xmlnode = xml_node_new(tag, NULL);
@@ -973,7 +990,7 @@ void vcal_manager_save_event (VCalEvent *event, gboolean export_after)
        xml_free_tree(rootnode);
 
        if (prefs_file_close(pfile) < 0) {
-               g_warning("failed to write event.");
+               g_warning("failed to write event");
                return;
        }
  
@@ -989,15 +1006,15 @@ static VCalEvent *event_get_from_xml (const gchar *uid, GNode *node)
        gchar *dtstart = NULL, *dtend = NULL, *tzid = NULL;
        gchar *description = NULL, *url = NULL, *recur = NULL;
        VCalEvent *event = NULL;
-       enum icalproperty_method method = ICAL_METHOD_REQUEST;
-       enum icalcomponent_kind type = ICAL_VEVENT_COMPONENT;
-       gint sequence = 0, rec_occurence = 0;
+       icalproperty_method method = ICAL_METHOD_REQUEST;
+       icalcomponent_kind type = ICAL_VEVENT_COMPONENT;
+       gint sequence = 0, rec_occurrence = 0;
        time_t postponed = (time_t)0;
        
        g_return_val_if_fail(node->data != NULL, NULL);
 
        xmlnode = node->data;
-       if (strcmp2(xmlnode->tag->tag, "event") != 0) {
+       if (g_strcmp0(xmlnode->tag->tag, "event") != 0) {
                g_warning("tag name != \"event\"");
                return NULL;
        }
@@ -1035,8 +1052,8 @@ static VCalEvent *event_get_from_xml (const gchar *uid, GNode *node)
                        sequence = atoi(attr->value);
                if (!strcmp(attr->name, "postponed"))
                        postponed = atoi(attr->value);
-               if (!strcmp(attr->name, "rec_occurence"))
-                       rec_occurence = atoi(attr->value);
+               if (!strcmp(attr->name, "rec_occurrence"))
+                       rec_occurrence = atoi(attr->value);
        }
 
        event = vcal_manager_new_event(uid, org, orgname, location, summary, description, 
@@ -1044,7 +1061,7 @@ static VCalEvent *event_get_from_xml (const gchar *uid, GNode *node)
                                        sequence, type);
 
        event->postponed = postponed;
-       event->rec_occurence = rec_occurence;
+       event->rec_occurrence = rec_occurrence;
 
        g_free(org); 
        g_free(orgname); 
@@ -1061,11 +1078,11 @@ static VCalEvent *event_get_from_xml (const gchar *uid, GNode *node)
        while (node != NULL) {
                gchar *attendee = NULL;
                gchar *name = NULL;
-               enum icalparameter_partstat answer = ICAL_PARTSTAT_NEEDSACTION;
-               enum icalparameter_cutype cutype   = ICAL_CUTYPE_INDIVIDUAL;
+               icalparameter_partstat answer = ICAL_PARTSTAT_NEEDSACTION;
+               icalparameter_cutype cutype   = ICAL_CUTYPE_INDIVIDUAL;
                
                xmlnode = node->data;
-               if (strcmp2(xmlnode->tag->tag, "answer") != 0) {
+               if (g_strcmp0(xmlnode->tag->tag, "answer") != 0) {
                        g_warning("tag name != \"answer\"");
                        return event;
                }
@@ -1133,8 +1150,8 @@ VCalEvent *vcal_manager_load_event (const gchar *uid)
 void vcal_manager_update_answer (VCalEvent     *event, 
                                 const gchar    *attendee,
                                 const gchar    *name,
-                                enum icalparameter_partstat ans,
-                                enum icalparameter_cutype cutype)
+                                icalparameter_partstat ans,
+                                icalparameter_cutype cutype)
 {
        Answer *answer = NULL;
        GSList *existing = NULL;
@@ -1169,16 +1186,16 @@ static gchar *write_headers(PrefsAccount        *account,
                            gboolean             is_pseudo_display)
 {
        gchar *subject = NULL;
-       gchar date[128];
+       gchar date[RFC822_DATE_BUFFSIZE];
        gchar *save_folder = NULL;
        gchar *result = NULL;
        gchar *queue_headers = NULL;
        gchar *method_str = NULL;
        gchar *attendees = NULL;
-       enum icalparameter_partstat status;
+       icalparameter_partstat status;
        gchar *prefix = NULL;
        gchar enc_subject[512], enc_from[512], *from = NULL;
-       gchar msgid[128];       
+       gchar *msgid;
        gchar *calmsgid = NULL;
 
        cm_return_val_if_fail(account != NULL, NULL);
@@ -1269,18 +1286,7 @@ static gchar *write_headers(PrefsAccount         *account,
                calmsgid = g_strdup("");
        }
 
-       if (account && account->set_domain && account->domain) {
-               g_snprintf(msgid, sizeof(msgid), "%s", account->domain); 
-       } else if (!strncmp(get_domain_name(), "localhost", strlen("localhost"))) {
-               g_snprintf(msgid, sizeof(msgid), "%s", 
-                       strchr(account->address, '@') ?
-                               strchr(account->address, '@')+1 :
-                               account->address);
-       } else {
-               g_snprintf(msgid, sizeof(msgid), "%s", "");
-       }
-
-       generate_msgid(msgid, sizeof(msgid), account->address);
+       msgid = prefs_account_generate_msgid(account);
 
        result = g_strdup_printf("%s"
                                "From: %s <%s>\n"
@@ -1310,6 +1316,7 @@ static gchar *write_headers(PrefsAccount  *account,
        g_free(save_folder);
        g_free(queue_headers);
        g_free(attendees);
+       g_free(msgid);
        return result;                  
                                                                                
 
@@ -1320,7 +1327,7 @@ static gchar *write_headers_ical(PrefsAccount     *account,
                            gchar               *orga)
 {
        gchar subject[512];
-       gchar date[128];
+       gchar date[RFC822_DATE_BUFFSIZE];
        gchar *result = NULL;
        gchar *method_str = NULL;
        gchar *summary = NULL;
@@ -1335,12 +1342,10 @@ static gchar *write_headers_ical(PrefsAccount   *account,
        memset(date, 0, sizeof(date));
        
        prop = icalcomponent_get_first_property(ievent, ICAL_SUMMARY_PROPERTY);
-       if (prop) {
-               summary = g_strdup(icalproperty_get_summary(prop));
-               icalproperty_free(prop);
-       } else {
-               summary = g_strdup("");
-       }
+       summary = g_strdup(icalproperty_get_summary(prop));
+       icalproperty_free(prop);
+       if (!summary)
+               summary = g_strdup(_("[no summary]"));
        
        while (strchr(summary, '\n'))
                *(strchr(summary, '\n')) = ' ';
@@ -1458,10 +1463,11 @@ static gboolean vcal_manager_send (PrefsAccount         *account,
        g_free(msgpath);
 
        folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
-       if (folder)
+       if (folder) {
                folder_item_scan(folder->inbox);
-
-       vcalviewer_reload(folder->inbox);
+               vcalviewer_reload(folder->inbox);
+       } else
+               g_warning("couldn't find vCalendar folder class");
        return TRUE;
 }
 
@@ -1482,7 +1488,6 @@ EventTime event_to_today(VCalEvent *event, time_t t)
        struct tm evtstart, today;
        time_t evtstart_t, today_t;
        struct icaltimetype itt;
-       struct tm buft;
 
        tzset();
        
@@ -1495,6 +1500,7 @@ EventTime event_to_today(VCalEvent *event, time_t t)
        }
        
 #ifndef G_OS_WIN32
+       struct tm buft;
        today = *localtime_r(&today_t, &buft);
        localtime_r(&evtstart_t, &evtstart);
 #else