[Xfce4-commits] <orage:master> Added missing files.
Juha Kautto
juha at xfce.org
Wed Sep 9 13:08:02 CEST 2009
Updating branch refs/heads/master
to a3c5d30aa75ab587ff5406697bbc43b2e3af3d31 (commit)
from 02d841558c61df4393c0da9c12584108caec5d28 (commit)
commit a3c5d30aa75ab587ff5406697bbc43b2e3af3d31
Author: Juha Kautto <juha at xfce.org>
Date: Wed Sep 9 14:05:30 2009 +0300
Added missing files.
Forgot to add these.
src/ical-archive.c | 538 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/ical-expimp.c | 450 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 988 insertions(+), 0 deletions(-)
diff --git a/src/ical-archive.c b/src/ical-archive.c
new file mode 100644
index 0000000..3390247
--- /dev/null
+++ b/src/ical-archive.c
@@ -0,0 +1,538 @@
+/* Orage - Calendar and alarm handler
+ *
+ * Copyright (c) 2005-2008 Juha Kautto (juha at xfce.org)
+ * Copyright (c) 2003-2005 Mickael Graf (korbinus at xfce.org)
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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
+ 51 Franklin Street, 5th Floor
+ Boston, MA 02110-1301 USA
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <unistd.h>
+#include <time.h>
+#include <math.h>
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+#include <glib/gstdio.h>
+#include <ical.h>
+#include <icalss.h>
+
+#include "orage-i18n.h"
+#include "functions.h"
+#include "mainbox.h"
+#include "reminder.h"
+#include "ical-code.h"
+#include "event-list.h"
+#include "appointment.h"
+#include "parameters.h"
+#include "interface.h"
+
+
+/*
+#define ORAGE_DEBUG 1
+*/
+
+
+
+/* this is in ical-code.c, too. ugly. should be in h file */
+typedef struct
+{
+ struct icaltimetype stime; /* start time */
+ struct icaltimetype etime; /* end time */
+ struct icaldurationtype duration;
+ struct icaltimetype ctime; /* completed time for VTODO appointmnets */
+ icalcomponent_kind ikind; /* type of component, VEVENt, VTODO... */
+} xfical_period;
+
+/* in ical-code.c: */
+char *ic_get_char_timezone(icalproperty *p);
+struct icaltimetype ic_convert_to_timezone(struct icaltimetype t
+ , icalproperty *p);
+xfical_period ic_get_period(icalcomponent *c) ;
+gboolean ic_internal_file_open(icalcomponent **p_ical
+ , icalset **p_fical, gchar *file_icalpath, gboolean test);
+
+
+extern icalset *ic_fical;
+extern icalcomponent *ic_ical;
+#ifdef HAVE_ARCHIVE
+extern icalset *ic_afical;
+extern icalcomponent *ic_aical;
+#endif
+
+extern gboolean ic_file_modified; /* has any ical file been changed */
+
+
+#ifdef HAVE_ARCHIVE
+gboolean xfical_archive_open(void)
+{
+#undef P_N
+#define P_N "xfical_archive_open: "
+#ifdef ORAGE_DEBUG
+ orage_message(-100, P_N);
+#endif
+ if (!g_par.archive_limit)
+ return(FALSE);
+ if (!ORAGE_STR_EXISTS(g_par.archive_file))
+ return(FALSE);
+
+ return(ic_internal_file_open(&ic_aical, &ic_afical, g_par.archive_file
+ , FALSE));
+}
+#endif
+
+#ifdef HAVE_ARCHIVE
+void xfical_archive_close(void)
+{
+#undef P_N
+#define P_N "xfical_archive_close: "
+#ifdef ORAGE_DEBUG
+ orage_message(-100, P_N);
+#endif
+ if (!ORAGE_STR_EXISTS(g_par.archive_file))
+ return;
+
+ if (ic_afical == NULL)
+ orage_message(150, P_N "afical is NULL");
+ icalset_free(ic_afical);
+ ic_afical = NULL;
+}
+#endif
+
+static icalproperty *replace_repeating(icalcomponent *c, icalproperty *p
+ , icalproperty_kind k)
+{
+#undef P_N
+#define P_N "replace_repeating: "
+ icalproperty *s, *n;
+ const char *text;
+ const gint x_len = strlen("X-ORAGE-ORIG-");
+
+#ifdef ORAGE_DEBUG
+ orage_message(-300, P_N);
+#endif
+ text = g_strdup(icalproperty_as_ical_string(p));
+ n = icalproperty_new_from_string(text + x_len);
+ g_free((gchar *)text);
+ s = icalcomponent_get_first_property(c, k);
+ /* remove X-ORAGE-ORIG...*/
+ icalcomponent_remove_property(c, p);
+ /* remove old k (=either DTSTART or DTEND) */
+ icalcomponent_remove_property(c, s);
+ /* add new DTSTART or DTEND */
+ icalcomponent_add_property(c, n);
+ /* we need to start again from the first since we messed the order,
+ * but there are not so many X- propoerties that this is worth worring */
+ return(icalcomponent_get_first_property(c, ICAL_X_PROPERTY));
+}
+
+#ifdef HAVE_ARCHIVE
+static void xfical_icalcomponent_archive_normal(icalcomponent *e)
+{
+#undef P_N
+#define P_N "xfical_icalcomponent_archive_normal: "
+ icalcomponent *d;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-200, P_N);
+#endif
+ /* Add to the archive file */
+ d = icalcomponent_new_clone(e);
+ icalcomponent_add_component(ic_aical, d);
+
+ /* Remove from the main file */
+ icalcomponent_remove_component(ic_ical, e);
+}
+
+static void xfical_icalcomponent_archive_recurrent(icalcomponent *e
+ , struct tm *threshold, char *uid)
+{
+#undef P_N
+#define P_N "xfical_icalcomponent_archive_recurrent: "
+ struct icaltimetype sdate, edate, nsdate, nedate;
+ struct icalrecurrencetype rrule;
+ struct icaldurationtype duration;
+ icalrecur_iterator* ri;
+ gchar *stz_loc = NULL, *etz_loc = NULL;
+ const char *text;
+ char *text2;
+ icalproperty *p, *pdtstart, *pdtend;
+ icalproperty *p_orig, *p_origdtstart = NULL, *p_origdtend = NULL;
+ gboolean upd_edate = FALSE;
+ gboolean has_orig_dtstart = FALSE, has_orig_dtend = FALSE;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-200, P_N);
+#endif
+
+ /* We must not remove recurrent events, but just modify start- and
+ * enddates and actually only the date parts since time will stay.
+ * Note that we may need to remove limited recurrency events. We only
+ * add X-ORAGE-ORIG... dates if those are not there already.
+ */
+ sdate = icalcomponent_get_dtstart(e);
+ pdtstart = icalcomponent_get_first_property(e, ICAL_DTSTART_PROPERTY);
+ stz_loc = ic_get_char_timezone(pdtstart);
+ sdate = ic_convert_to_timezone(sdate, pdtstart);
+
+ edate = icalcomponent_get_dtend(e);
+ if (icaltime_is_null_time(edate)) {
+ edate = sdate;
+ }
+ pdtend = icalcomponent_get_first_property(e, ICAL_DTEND_PROPERTY);
+ if (pdtend) { /* we have DTEND, so we need to adjust it. */
+ etz_loc = ic_get_char_timezone(pdtend);
+ edate = ic_convert_to_timezone(edate, pdtend);
+ duration = icaltime_subtract(edate, sdate);
+ upd_edate = TRUE;
+ }
+ else {
+ p = icalcomponent_get_first_property(e, ICAL_DURATION_PROPERTY);
+ if (p) /* we have DURATION, which does not need changes */
+ duration = icalproperty_get_duration(p);
+ else /* neither duration, nor dtend, assume dtend=dtstart */
+ duration = icaltime_subtract(edate, sdate);
+ }
+ p_orig = icalcomponent_get_first_property(e, ICAL_X_PROPERTY);
+ while (p_orig) {
+ text = icalproperty_get_x_name(p_orig);
+ if (g_str_has_prefix(text, "X-ORAGE-ORIG-DTSTART")) {
+ if (has_orig_dtstart) {
+ /* This fixes bug which existed prior to 4.5.9.7:
+ * It was possible that multiple entries were generated.
+ * They are in order: oldest first.
+ * And we only need the oldest, so delete the rest */
+ orage_message(150, P_N "Corrupted X-ORAGE-ORIG-DTSTART setting. Fixing");
+ icalcomponent_remove_property(e, p_orig);
+ /* we need to start from scratch since counting may go wrong
+ * bcause delete moves the pointer. */
+ has_orig_dtstart = FALSE;
+ has_orig_dtend = FALSE;
+ p_orig = icalcomponent_get_first_property(e, ICAL_X_PROPERTY);
+ }
+ else {
+ has_orig_dtstart = TRUE;
+ p_origdtstart = p_orig;
+ p_orig = icalcomponent_get_next_property(e, ICAL_X_PROPERTY);
+ }
+ }
+ else if (g_str_has_prefix(text, "X-ORAGE-ORIG-DTEND")) {
+ if (has_orig_dtend) {
+ orage_message(150, P_N "Corrupted X-ORAGE-ORIG-DTEND setting. Fixing");
+ icalcomponent_remove_property(e, p_orig);
+ has_orig_dtstart = FALSE;
+ has_orig_dtend = FALSE;
+ p_orig = icalcomponent_get_first_property(e, ICAL_X_PROPERTY);
+ }
+ else {
+ has_orig_dtend = TRUE;
+ p_origdtend = p_orig;
+ p_orig = icalcomponent_get_next_property(e, ICAL_X_PROPERTY);
+ }
+ }
+ else /* it was not our X-PROPERTY */
+ p_orig = icalcomponent_get_next_property(e, ICAL_X_PROPERTY);
+ }
+
+ p = icalcomponent_get_first_property(e, ICAL_RRULE_PROPERTY);
+ nsdate = icaltime_null_time();
+ rrule = icalproperty_get_rrule(p);
+ ri = icalrecur_iterator_new(rrule, sdate);
+
+ /* We must do a loop for finding the first occurence after the threshold */
+ for (nsdate = icalrecur_iterator_next(ri),
+ nedate = icaltime_add(nsdate, duration);
+ !icaltime_is_null_time(nsdate)
+ && (nedate.year*12 + nedate.month)
+ < ((threshold->tm_year)*12 + threshold->tm_mon);
+ nsdate = icalrecur_iterator_next(ri),
+ nedate = icaltime_add(nsdate, duration)){
+ }
+ icalrecur_iterator_free(ri);
+
+ if (icaltime_is_null_time(nsdate)) { /* remove since it has ended */
+ orage_message(20, _("\tRecur ended, moving to archive file."));
+ if (has_orig_dtstart)
+ replace_repeating(e, p_origdtstart, ICAL_DTSTART_PROPERTY);
+ if (has_orig_dtend)
+ replace_repeating(e, p_origdtend, ICAL_DTEND_PROPERTY);
+ xfical_icalcomponent_archive_normal(e);
+ }
+ else { /* modify times*/
+ if (!has_orig_dtstart) {
+ text = g_strdup(icalproperty_as_ical_string(pdtstart));
+ text2 = g_strjoin(NULL, "X-ORAGE-ORIG-", text, NULL);
+ p = icalproperty_new_from_string(text2);
+ g_free((gchar *)text2);
+ g_free((gchar *)text);
+ icalcomponent_add_property(e, p);
+ }
+ icalcomponent_remove_property(e, pdtstart);
+ if (stz_loc == NULL)
+ icalcomponent_add_property(e, icalproperty_new_dtstart(nsdate));
+ else
+ icalcomponent_add_property(e
+ , icalproperty_vanew_dtstart(nsdate
+ , icalparameter_new_tzid(stz_loc)
+ , 0));
+ if (upd_edate) {
+ if (!has_orig_dtend) {
+ text = g_strdup(icalproperty_as_ical_string(pdtend));
+ text2 = g_strjoin(NULL, "X-ORAGE-ORIG-", text, NULL);
+ p = icalproperty_new_from_string(text2);
+ g_free((gchar *)text2);
+ g_free((gchar *)text);
+ icalcomponent_add_property(e, p);
+ }
+ icalcomponent_remove_property(e, pdtend);
+ if (etz_loc == NULL)
+ icalcomponent_add_property(e, icalproperty_new_dtend(nedate));
+ else
+ icalcomponent_add_property(e
+ , icalproperty_vanew_dtend(nedate
+ , icalparameter_new_tzid(etz_loc)
+ , 0));
+ }
+ }
+}
+
+gboolean xfical_archive(void)
+{
+#undef P_N
+#define P_N "xfical_archive: "
+ /*
+ struct icaltimetype sdate, edate;
+ */
+ xfical_period per;
+ icalcomponent *c, *c2;
+ icalproperty *p;
+ struct tm *threshold;
+ char *uid;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-100, P_N);
+#endif
+ if (g_par.archive_limit == 0) {
+ orage_message(20, _("Archiving not enabled. Exiting"));
+ return(TRUE);
+ }
+ if (!xfical_file_open(FALSE) || !xfical_archive_open()) {
+ orage_message(250, P_N "file open error");
+ return(FALSE);
+ }
+ threshold = orage_localtime();
+ threshold->tm_mday = 1;
+ threshold->tm_year += 1900;
+ threshold->tm_mon += 1; /* convert from 0...11 to 1...12 */
+
+ threshold->tm_mon -= g_par.archive_limit;
+ if (threshold->tm_mon <= 0) {
+ threshold->tm_mon += 12;
+ threshold->tm_year--;
+ }
+
+ orage_message(20, _("Archiving threshold: %d month(s)")
+ , g_par.archive_limit);
+ /* yy mon day */
+ orage_message(20, _("\tArchiving events, which are older than: %04d-%02d-%02d")
+ , threshold->tm_year, threshold->tm_mon, threshold->tm_mday);
+
+ /* Check appointment file for items older than the threshold */
+ /* Note: remove moves the "c" pointer to next item, so we need to store it
+ * first to process all of them or we end up skipping entries */
+ for (c = icalcomponent_get_first_component(ic_ical, ICAL_ANY_COMPONENT);
+ c != 0;
+ c = c2) {
+ c2 = icalcomponent_get_next_component(ic_ical, ICAL_ANY_COMPONENT);
+ /*
+ sdate = icalcomponent_get_dtstart(c);
+ edate = icalcomponent_get_dtend(c);
+ if (icaltime_is_null_time(edate)) {
+ edate = sdate;
+ }
+ */
+ per = ic_get_period(c);
+ uid = (char *)icalcomponent_get_uid(c);
+ /* Items with endate before threshold => archived.
+ * Recurring events are marked in the main file by adding special
+ * X-ORAGE_ORIG-DTSTART/X-ORAGE_ORIG-DTEND to save the original
+ * start/end dates. Then start_date is changed. These are NOT
+ * written in archive file (unless of course they really have ended).
+ */
+ if ((per.etime.year*12 + per.etime.month)
+ < (threshold->tm_year*12 + threshold->tm_mon)) {
+ orage_message(20, _("Archiving uid: %s"), uid);
+ /* FIXME: check VTODO completed before archiving it */
+ if (per.ikind == ICAL_VTODO_COMPONENT
+ && ((per.ctime.year*12 + per.ctime.month)
+ < (per.stime.year*12 + per.stime.month))) {
+ /* VTODO not completed, do not archive */
+ orage_message(20, _("\tVTODO not complete; not archived"));
+ }
+ else {
+ p = icalcomponent_get_first_property(c, ICAL_RRULE_PROPERTY);
+ if (p) { /* it is recurrent event */
+ orage_message(20, _("\tRecurring. End year: %04d, month: %02d, day: %02d")
+ , per.etime.year, per.etime.month, per.etime.day);
+ xfical_icalcomponent_archive_recurrent(c, threshold, uid);
+ }
+ else
+ xfical_icalcomponent_archive_normal(c);
+ }
+ }
+ }
+
+ ic_file_modified = TRUE;
+ icalset_mark(ic_afical);
+ icalset_commit(ic_afical);
+ xfical_archive_close();
+ icalset_mark(ic_fical);
+ icalset_commit(ic_fical);
+ xfical_file_close(FALSE);
+ orage_message(25, _("Archiving done\n"));
+ return(TRUE);
+}
+
+gboolean xfical_unarchive(void)
+{
+#undef P_N
+#define P_N "xfical_unarchive: "
+ icalcomponent *c, *d;
+ icalproperty *p;
+ const char *text;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-100, P_N);
+#endif
+ /* PHASE 1: go through base orage file and remove "repeat" shortcuts */
+ orage_message(25, _("Starting archive removal."));
+ orage_message(20, _("\tPHASE 1: reset recurring appointments"));
+ if (!xfical_file_open(FALSE)) {
+ orage_message(250, P_N "file open error");
+ return(FALSE);
+ }
+
+ for (c = icalcomponent_get_first_component(ic_ical, ICAL_VEVENT_COMPONENT);
+ c != 0;
+ c = icalcomponent_get_next_component(ic_ical, ICAL_VEVENT_COMPONENT)) {
+ p = icalcomponent_get_first_property(c, ICAL_X_PROPERTY);
+ while (p) {
+ text = icalproperty_get_x_name(p);
+ if (g_str_has_prefix(text, "X-ORAGE-ORIG-DTSTART"))
+ p = replace_repeating(c, p, ICAL_DTSTART_PROPERTY);
+ else if (g_str_has_prefix(text, "X-ORAGE-ORIG-DTEND"))
+ p = replace_repeating(c, p, ICAL_DTEND_PROPERTY);
+ else /* it was not our X-PROPERTY */
+ p = icalcomponent_get_next_property(c, ICAL_X_PROPERTY);
+ }
+ }
+ /* PHASE 2: go through archive file and add everything back to base orage.
+ * After that delete the whole arch file */
+ orage_message(20, _("\tPHASE 2: return archived appointments"));
+ if (!xfical_archive_open()) {
+ /* we have risk to delete the data permanently, let's stop here */
+ orage_message(350, P_N "archive file open error");
+ /*
+ icalset_mark(ic_fical);
+ icalset_commit(ic_fical);
+ */
+ xfical_file_close(FALSE);
+ return(FALSE);
+ }
+ for (c = icalcomponent_get_first_component(ic_aical, ICAL_VEVENT_COMPONENT);
+ c != 0;
+ c = icalcomponent_get_next_component(ic_aical, ICAL_VEVENT_COMPONENT)) {
+ /* Add to the base file */
+ d = icalcomponent_new_clone(c);
+ icalcomponent_add_component(ic_ical, d);
+ }
+ xfical_archive_close();
+ if (g_remove(g_par.archive_file) == -1) {
+ orage_message(190, P_N "Failed to remove archive file %s", g_par.archive_file);
+ }
+ ic_file_modified = TRUE;
+ icalset_mark(ic_fical);
+ icalset_commit(ic_fical);
+ xfical_file_close(FALSE);
+ orage_message(25, _("Archive removal done\n"));
+ return(TRUE);
+}
+
+gboolean xfical_unarchive_uid(char *uid)
+{
+#undef P_N
+#define P_N "xfical_unarchive_uid: "
+ icalcomponent *c, *d;
+ gboolean key_found = FALSE;
+ const char *text;
+ char *ical_uid;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-100, P_N);
+#endif
+ ical_uid = uid+4; /* skip file id (which is A00. now)*/
+ if (!xfical_file_open(FALSE) || !xfical_archive_open()) {
+ orage_message(250, P_N "file open error");
+ return(FALSE);
+ }
+ for (c = icalcomponent_get_first_component(ic_aical, ICAL_ANY_COMPONENT);
+ c != 0 && !key_found;
+ c = icalcomponent_get_next_component(ic_aical, ICAL_ANY_COMPONENT)) {
+ text = icalcomponent_get_uid(c);
+ if (strcmp(text, ical_uid) == 0) { /* we found our uid (=event) */
+ /* Add to the base file */
+ d = icalcomponent_new_clone(c);
+ icalcomponent_add_component(ic_ical, d);
+ /* Remove from the archive file */
+ icalcomponent_remove_component(ic_aical, c);
+ key_found = TRUE;
+ ic_file_modified = TRUE;
+ }
+ }
+ icalset_mark(ic_afical);
+ icalset_commit(ic_afical);
+ xfical_archive_close();
+ icalset_mark(ic_fical);
+ icalset_commit(ic_fical);
+ xfical_file_close(FALSE);
+
+ return(TRUE);
+}
+#endif
diff --git a/src/ical-expimp.c b/src/ical-expimp.c
new file mode 100644
index 0000000..0705839
--- /dev/null
+++ b/src/ical-expimp.c
@@ -0,0 +1,450 @@
+/* Orage - Calendar and alarm handler
+ *
+ * Copyright (c) 2005-2008 Juha Kautto (juha at xfce.org)
+ * Copyright (c) 2003-2005 Mickael Graf (korbinus at xfce.org)
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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
+ 51 Franklin Street, 5th Floor
+ Boston, MA 02110-1301 USA
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <unistd.h>
+#include <time.h>
+#include <math.h>
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+#include <glib/gstdio.h>
+#include <ical.h>
+#include <icalss.h>
+
+#include "orage-i18n.h"
+#include "functions.h"
+#include "mainbox.h"
+#include "reminder.h"
+#include "ical-code.h"
+#include "event-list.h"
+#include "appointment.h"
+#include "parameters.h"
+#include "interface.h"
+
+/*
+#define ORAGE_DEBUG 1
+*/
+
+
+
+/* in ical-code.c: */
+char *ic_generate_uid();
+
+extern icalset *ic_fical;
+extern icalcomponent *ic_ical;
+
+extern gboolean ic_file_modified; /* has any ical file been changed */
+
+typedef struct _foreign_ical_files
+{;
+ icalset *fical;
+ icalcomponent *ical;
+} ic_foreign_ical_files;
+
+extern ic_foreign_ical_files ic_f_ical[10];
+
+
+static gboolean add_event(icalcomponent *c)
+{
+#undef P_N
+#define P_N "add_event: "
+ icalcomponent *ca = NULL;
+ char *uid;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-300, P_N);
+#endif
+ ca = icalcomponent_new_clone(c);
+ if ((uid = (char *)icalcomponent_get_uid(ca)) == NULL) {
+ uid = ic_generate_uid();
+ icalcomponent_add_property(ca, icalproperty_new_uid(uid));
+ orage_message(15, "Generated UID %s", uid);
+ g_free(uid);
+
+ }
+ if (!xfical_file_open(FALSE)) {
+ orage_message(250, P_N "ical file open failed");
+ return(FALSE);
+ }
+ icalcomponent_add_component(ic_ical, ca);
+ ic_file_modified = TRUE;
+ icalset_mark(ic_fical);
+ icalset_commit(ic_fical);
+ xfical_file_close(FALSE);
+ return(TRUE);
+}
+
+/* pre process the file to rule out some features, which orage does not
+ * support so that we can do better conversion
+ */
+static gboolean pre_format(char *file_name_in, char *file_name_out)
+{
+#undef P_N
+#define P_N "pre_format: "
+ gchar *text, *tmp, *tmp2, *tmp3;
+ gsize text_len;
+ GError *error = NULL;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-200, P_N);
+#endif
+ orage_message(15, _("Starting import file preprocessing"));
+ if (!g_file_get_contents(file_name_in, &text, &text_len, &error)) {
+ orage_message(250, P_N "Could not open ical file (%s) error:%s"
+ , file_name_in, error->message);
+ g_error_free(error);
+ return(FALSE);
+ }
+ /***** Check utf8 coformtability *****/
+ if (!g_utf8_validate(text, -1, NULL)) {
+ orage_message(250, P_N "is not in utf8 format. Conversion needed.\n (Use iconv and convert it into UTF-8 and import it again.)\n");
+ return(FALSE);
+ /* we don't know the real characterset, so we can't convert
+ tmp = g_locale_to_utf8(text, -1, NULL, &cnt, NULL);
+ if (tmp) {
+ g_strlcpy(text, tmp, text_len);
+ g_free(tmp);
+ }*/
+ }
+
+ /***** 1: change DCREATED to CREATED *****/
+ for (tmp = g_strstr_len(text, text_len, "DCREATED:");
+ tmp != NULL;
+ tmp = g_strstr_len(tmp, strlen(tmp), "DCREATED:")) {
+ tmp2 = tmp+strlen("DCREATED:yyyymmddThhmmss");
+ if (*tmp2 == 'Z') {
+ /* it is already in UTC, so just fix the parameter name */
+ *tmp = ' ';
+ }
+ else {
+ /* needs to be converted to UTC also */
+ for (tmp3 = tmp; tmp3 < tmp2; tmp3++) {
+ *tmp3 = *(tmp3+1);
+ }
+ *(tmp3-1) = 'Z'; /* this is 'bad'...but who cares...it is fast */
+ }
+ orage_message(15, _("... Patched DCREATED to be CREATED."));
+ }
+
+ /***** 2: change absolute timezones into libical format *****/
+ /* At least evolution uses absolute timezones.
+ * We assume format has /xxx/xxx/timezone and we should remove the
+ * extra /xxx/xxx/ from it */
+ for (tmp = g_strstr_len(text, text_len, ";TZID=/");
+ tmp != NULL;
+ tmp = g_strstr_len(tmp, strlen(tmp), ";TZID=/")) {
+ /* tmp = original TZID start
+ * tmp2 = end of line
+ * tmp3 = current search and eventually the real tzid */
+ tmp = tmp+6; /* 6 = skip ";TZID=" */
+ if (!(tmp2 = g_strstr_len(tmp, 100, "\n"))) { /* no end of line */
+ orage_message(150, P_N "timezone patch failed 1. no end-of-line found: %s", tmp);
+ continue;
+ }
+ tmp3 = tmp;
+
+ tmp3++; /* skip '/' */
+ if (!(tmp3 = g_strstr_len(tmp3, tmp2-tmp3, "/"))) { /* no more '/' */
+ orage_message(150, P_N "timezone patch failed 2. no / found: %s", tmp);
+ continue;
+ }
+ tmp3++; /* skip '/' */
+ if (!(tmp3 = g_strstr_len(tmp3, tmp2-tmp3, "/"))) { /* no more '/' */
+ orage_message(150, P_N "timezone patch failed 3. no / found: %s", tmp);
+ continue;
+ }
+
+ /* we found the real tzid since we came here */
+ tmp3++; /* skip '/' */
+ /* move the real tzid (=tmp3) to the beginning (=tmp) */
+ for (; tmp3 < tmp2; tmp3++, tmp++)
+ *tmp = *tmp3;
+ /* fill the end of the line with spaces */
+ for (; tmp < tmp2; tmp++)
+ *tmp = ' ';
+ orage_message(15, _("... Patched timezone to Orage format."));
+ }
+
+ /***** All done: write file *****/
+ if (!g_file_set_contents(file_name_out, text, -1, NULL)) {
+ orage_message(250, P_N "Could not write ical file (%s)", file_name_out);
+ return(FALSE);
+ }
+ g_free(text);
+ orage_message(15, _("Import file preprocessing done"));
+ return(TRUE);
+}
+
+gboolean xfical_import_file(char *file_name)
+{
+#undef P_N
+#define P_N "xfical_import_file: "
+ icalset *file_ical = NULL;
+ char *ical_file_name = NULL;
+ icalcomponent *c1, *c2;
+ int cnt1 = 0, cnt2 = 0;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-100, P_N);
+#endif
+ ical_file_name = g_strdup_printf("%s.orage", file_name);
+ if (!pre_format(file_name, ical_file_name)) {
+ return(FALSE);
+ }
+ if ((file_ical = icalset_new_file(ical_file_name)) == NULL) {
+ orage_message(250, P_N "Could not open ical file (%s) %s"
+ , ical_file_name, icalerror_strerror(icalerrno));
+ return(FALSE);
+ }
+ for (c1 = icalset_get_first_component(file_ical);
+ c1 != 0;
+ c1 = icalset_get_next_component(file_ical)) {
+ if (icalcomponent_isa(c1) == ICAL_VCALENDAR_COMPONENT) {
+ cnt1++;
+ for (c2=icalcomponent_get_first_component(c1, ICAL_ANY_COMPONENT);
+ c2 != 0;
+ c2=icalcomponent_get_next_component(c1, ICAL_ANY_COMPONENT)){
+ if ((icalcomponent_isa(c2) == ICAL_VEVENT_COMPONENT)
+ || (icalcomponent_isa(c2) == ICAL_VTODO_COMPONENT)
+ || (icalcomponent_isa(c2) == ICAL_VJOURNAL_COMPONENT)) {
+ cnt2++;
+ add_event(c2);
+ }
+ /* we ignore TIMEZONE component; Orage only uses internal
+ * timezones from libical */
+ else if (icalcomponent_isa(c2) != ICAL_VTIMEZONE_COMPONENT)
+ orage_message(140, P_N "unknown component %s %s"
+ , icalcomponent_kind_to_string(
+ icalcomponent_isa(c2))
+ , ical_file_name);
+ }
+
+ }
+ else
+ orage_message(140, P_N "unknown icalset component %s in %s"
+ , icalcomponent_kind_to_string(icalcomponent_isa(c1))
+ , ical_file_name);
+ }
+ if (cnt1 == 0) {
+ orage_message(150, P_N "No valid icalset components found");
+ return(FALSE);
+ }
+ if (cnt2 == 0) {
+ orage_message(150, P_N "No valid ical components found");
+ return(FALSE);
+ }
+
+ g_free(ical_file_name);
+ return(TRUE);
+}
+
+static gboolean export_prepare_write_file(char *file_name)
+{
+#undef P_N
+#define P_N "export_prepare_write_file: "
+ gchar *tmp;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-200, P_N);
+#endif
+ if (strcmp(file_name, g_par.orage_file) == 0) {
+ orage_message(150, P_N "You do not want to overwrite Orage ical file! (%s)"
+ , file_name);
+ return(FALSE);
+ }
+ tmp = g_path_get_dirname(file_name);
+ if (g_mkdir_with_parents(tmp, 0755)) { /* octal */
+ orage_message(250, P_N "Could not create directories (%s)"
+ , file_name);
+ return(FALSE);
+ }
+ g_free(tmp);
+ if (g_remove(file_name) == -1) { /* note that it may not exist */
+ orage_message(150, P_N "Failed to remove export file %s", file_name);
+ }
+ return(TRUE);
+}
+
+static gboolean export_all(char *file_name)
+{
+#undef P_N
+#define P_N "export_all: "
+ gchar *text;
+ gsize text_len;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-200, P_N);
+#endif
+ if (!export_prepare_write_file(file_name))
+ return(FALSE);
+ /* read Orage's ical file */
+ if (!g_file_get_contents(g_par.orage_file, &text, &text_len, NULL)) {
+ orage_message(250, P_N "Could not open Orage ical file (%s)"
+ , g_par.orage_file);
+ return(FALSE);
+ }
+ if (!g_file_set_contents(file_name, text, -1, NULL)) {
+ orage_message(150, P_N "Could not write file (%s)"
+ , file_name);
+ g_free(text);
+ return(FALSE);
+ }
+ g_free(text);
+ return(TRUE);
+}
+
+static void export_selected_uid(icalcomponent *base, gchar *uid_int
+ , icalcomponent *x_ical)
+{
+#undef P_N
+#define P_N "export_selected_uid: "
+ icalcomponent *c, *d;
+ gboolean key_found = FALSE;
+ gchar *uid_ical;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-200, P_N);
+#endif
+ key_found = FALSE;
+ for (c = icalcomponent_get_first_component(base, ICAL_ANY_COMPONENT);
+ c != 0 && !key_found;
+ c = icalcomponent_get_next_component(base, ICAL_ANY_COMPONENT)) {
+ uid_ical = (char *)icalcomponent_get_uid(c);
+ if (strcmp(uid_int, uid_ical) == 0) { /* we found our uid */
+ d = icalcomponent_new_clone(c);
+ icalcomponent_add_component(x_ical, d);
+ key_found = TRUE;
+ }
+ }
+ if (!key_found)
+ orage_message(150, P_N "not found %s from Orage", uid_int);
+}
+
+static gboolean export_selected(char *file_name, char *uids)
+{
+#undef P_N
+#define P_N "export_selected: "
+ icalcomponent *x_ical = NULL;
+ icalset *x_fical = NULL;
+ gchar *uid, *uid_end, *uid_int;
+ gboolean more_uids;
+ int i;
+
+#ifdef ORAGE_DEBUG
+ orage_message(-200, P_N);
+#endif
+ if (!export_prepare_write_file(file_name))
+ return(FALSE);
+ if (!ORAGE_STR_EXISTS(uids)) {
+ orage_message(150, P_N "UID list is empty");
+ return(FALSE);
+ }
+ if (!ic_internal_file_open(&x_ical, &x_fical, file_name, FALSE)) {
+ orage_message(150, P_N "Failed to create export file %s"
+ , file_name);
+ return(FALSE);
+ }
+ if (!xfical_file_open(TRUE)) {
+ return(FALSE);
+ }
+
+ /* checks done, let's start the real work */
+ more_uids = TRUE;
+ for (uid = uids; more_uids; ) {
+ uid_int = uid+4;
+ uid_end = g_strstr_len((const gchar *)uid, strlen(uid), ",");
+ if (uid_end != NULL)
+ *uid_end = 0; /* uid ends here */
+ /* FIXME: proper messages to screen */
+ if (uid[0] == 'O') {
+ export_selected_uid(ic_ical, uid_int, x_ical);
+ }
+ else if (uid[0] == 'F') {
+ sscanf(uid, "F%02d", &i);
+ if (i < g_par.foreign_count && ic_f_ical[i].ical != NULL) {
+ export_selected_uid(ic_f_ical[i].ical, uid_int, x_ical);
+ }
+ else {
+ orage_message(250, P_N "unknown foreign file number %s", uid);
+ return(FALSE);
+ }
+
+ }
+ else {
+ orage_message(250, P_N "Unknown uid type %s", uid);
+ }
+
+ if (uid_end != NULL) /* we have more uids */
+ uid = uid_end+1; /* next uid starts here */
+ else
+ more_uids = FALSE;
+ }
+
+ xfical_file_close(TRUE);
+ icalset_mark(x_fical);
+ icalset_commit(x_fical);
+ icalset_free(x_fical);
+ return(TRUE);
+}
+
+gboolean xfical_export_file(char *file_name, int type, char *uids)
+{
+#undef P_N
+#define P_N "xfical_export_file: "
+#ifdef ORAGE_DEBUG
+ orage_message(-100, P_N);
+#endif
+ if (type == 0) { /* copy the whole file */
+ return(export_all(file_name));
+ }
+ else if (type == 1) { /* copy only selected appointments */
+ return(export_selected(file_name, uids));
+ }
+ else {
+ orage_message(260, P_N "Unknown app count");
+ return(FALSE);
+ }
+}
More information about the Xfce4-commits
mailing list