aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/save-calendar/rdf-format.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/save-calendar/rdf-format.c')
-rw-r--r--plugins/save-calendar/rdf-format.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/plugins/save-calendar/rdf-format.c b/plugins/save-calendar/rdf-format.c
new file mode 100644
index 0000000000..efa038a1f2
--- /dev/null
+++ b/plugins/save-calendar/rdf-format.c
@@ -0,0 +1,384 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Authors: Philip Van Hoof <pvanhoof@gnome.org>
+ *
+ * Copyright 2004 Novell, Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <glib.h>
+#include <glib/gi18n.h>
+#ifdef USE_GTKFILECHOOSER
+# include <gtk/gtkfilechooser.h>
+# include <gtk/gtkfilechooserdialog.h>
+#else
+# include <gtk/gtkfilesel.h>
+#endif
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+#include <libedataserverui/e-source-selector.h>
+#include <libecal/e-cal.h>
+#include <calendar/gui/e-cal-popup.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xpath.h>
+#include <string.h>
+
+#include "format-handler.h"
+
+static void
+add_string_to_rdf (xmlNodePtr node, const gchar *tag, const char *value);
+
+/* Use { */
+
+/* #include <calendar/gui/calendar-config-keys.h> */
+/* #include <calendar/gui/calendar-config.h> */
+
+/* } or { */
+#define CALENDAR_CONFIG_PREFIX "/apps/evolution/calendar"
+#define CALENDAR_CONFIG_TIMEZONE CALENDAR_CONFIG_PREFIX "/display/timezone"
+
+GConfClient *config = NULL;
+
+static gchar *
+calendar_config_get_timezone (void)
+{
+ gchar *retval = NULL;
+
+ if (!config)
+ config = gconf_client_get_default ();
+
+ retval = gconf_client_get_string (config, CALENDAR_CONFIG_TIMEZONE, NULL);
+
+ if (!retval)
+ retval = g_strdup ("UTC");
+
+ return retval;
+}
+/* } */
+
+enum { /* XML helper enum */
+ ECALCOMPONENTTEXT,
+ ECALCOMPONENTATTENDEE,
+ CONSTCHAR
+};
+
+static void
+display_error_message (GtkWidget *parent, GError *error)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+/* Some helpers for the xml stuff */
+static void
+add_list_to_rdf (xmlNodePtr node, const gchar *tag, GSList *list_in, gint type)
+{
+ if (list_in) {
+ GSList *list = list_in;
+
+ while (list) {
+ const char *str = NULL;
+
+ switch (type) {
+ case ECALCOMPONENTATTENDEE:
+ str = ((ECalComponentAttendee*)list->data)->value;
+ break;
+ case ECALCOMPONENTTEXT:
+ str = ((ECalComponentText*)list->data)->value;
+ break;
+ case CONSTCHAR:
+ default:
+ str = list->data;
+ break;
+ }
+
+ add_string_to_rdf (node, tag, str);
+
+ list = g_slist_next (list);
+ }
+ }
+}
+
+static void
+add_nummeric_to_rdf (xmlNodePtr node, const gchar *tag, gint *nummeric)
+{
+ if (nummeric) {
+ gchar *value = g_strdup_printf ("%d", *nummeric);
+ xmlNodePtr cur_node = xmlNewChild (node, NULL, tag, value);
+ xmlSetProp (cur_node, "rdf:datatype", "http://www.w3.org/2001/XMLSchema#integer");
+ g_free (value);
+ }
+}
+
+static void
+add_time_to_rdf (xmlNodePtr node, const gchar *tag, icaltimetype *time)
+{
+ if (time) {
+ xmlNodePtr cur_node = NULL;
+ gchar *tmp = NULL;
+ gchar *str = g_strdup_printf ("%s%d-%s%d-%s%dT%s%d:%s%d:%s%d",
+ (time->year < 10)?"0":"", time->year,
+ (time->month < 10)?"0":"", time->month,
+ (time->day < 10)?"0":"", time->day,
+ (time->hour < 10)?"0":"", time->hour,
+ (time->minute < 10)?"0":"", time->minute,
+ (time->second < 10)?"0":"", time->second);
+ cur_node = xmlNewChild (node, NULL, tag, str);
+
+ /* Not sure about this property */
+ tmp = g_strdup_printf ("http://www.w3.org/2002/12/cal/tzd/%s#tz", calendar_config_get_timezone ());
+ xmlSetProp (cur_node, "rdf:datatype", tmp);
+ g_free (tmp);
+
+ g_free (str);
+ }
+}
+
+
+static void
+add_string_to_rdf (xmlNodePtr node, const gchar *tag, const char *value)
+{
+ if (value) {
+ xmlNodePtr cur_node = NULL;
+ cur_node = xmlNewChild (node, NULL, tag, value);
+ xmlSetProp (cur_node, "rdf:datatype", "http://www.w3.org/2001/XMLSchema#string");
+ }
+}
+
+
+
+
+static void
+do_save_calendar_rdf (FormatHandler *handler, EPlugin *ep, ECalPopupTargetSource *target, ECalSourceType type, char *dest_uri)
+{
+
+ /*
+ * According to some documentation about CSV, newlines 'are' allowed
+ * in CSV-files. But you 'do' have to put the value between quotes.
+ * The helper 'string_needsquotes' will check for that
+ *
+ * http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm
+ * http://www.creativyst.com/cgi-bin/Prod/15/eg/csv2xml.pl
+ */
+
+ ESource *primary_source;
+ ECal *source_client;
+ GError *error = NULL;
+ GList *objects=NULL;
+ GnomeVFSResult result;
+ GnomeVFSHandle *handle;
+ GnomeVFSURI *uri;
+ gchar *temp = NULL;
+
+ if (!dest_uri)
+ return;
+
+ primary_source = e_source_selector_peek_primary_selection (target->selector);
+
+ /* open source client */
+ source_client = e_cal_new (primary_source, type);
+ if (!e_cal_open (source_client, TRUE, &error)) {
+ display_error_message (gtk_widget_get_toplevel (GTK_WIDGET (target->selector)), error);
+ g_object_unref (source_client);
+ g_error_free (error);
+ return;
+ }
+
+ uri = gnome_vfs_uri_new (dest_uri);
+ result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
+ if (result != GNOME_VFS_OK) {
+ gnome_vfs_create (&handle, dest_uri, GNOME_VFS_OPEN_WRITE, TRUE, GNOME_VFS_PERM_USER_ALL);
+ result = gnome_vfs_open_uri (&handle, uri, GNOME_VFS_OPEN_WRITE);
+ }
+
+ if (result == GNOME_VFS_OK && e_cal_get_object_list_as_comp (source_client, "#t", &objects, NULL)) {
+ xmlBufferPtr buffer=xmlBufferCreate();
+ xmlDocPtr doc = xmlNewDoc((xmlChar *) "1.0");
+ xmlNodePtr fnode = doc->children;
+
+ doc->children = xmlNewDocNode (doc, NULL, "rdf:RDF", NULL);
+ xmlSetProp (doc->children, "xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
+ xmlSetProp (doc->children, "xmlns", "http://www.w3.org/2002/12/cal/ical#");
+
+ fnode = xmlNewChild (doc->children, NULL, "Vcalendar", NULL);
+
+ /* Should Evolution publicise these? */
+ xmlSetProp (fnode, "xmlns:x-wr", "http://www.w3.org/2002/12/cal/prod/Apple_Comp_628d9d8459c556fa#");
+ xmlSetProp (fnode, "xmlns:x-lic", "http://www.w3.org/2002/12/cal/prod/Apple_Comp_628d9d8459c556fa#");
+
+ /* Not sure if it's correct like this */
+ xmlNewChild (fnode, NULL, "prodid", "-//" PACKAGE_STRING "//iCal 1.0//EN");
+
+ /* Assuming GREGORIAN is the only supported calendar scale */
+ xmlNewChild (fnode, NULL, "calscale", "GREGORIAN");
+
+ temp = calendar_config_get_timezone ();
+ xmlNewChild (fnode, NULL, "x-wr:timezone", temp);
+ g_free (temp);
+
+ xmlNewChild (fnode, NULL, "method", "PUBLISH");
+
+ xmlNewChild (fnode, NULL, "x-wr:relcalid", e_source_peek_uid (primary_source));
+
+ xmlNewChild (fnode, NULL, "x-wr:calname", e_source_peek_name (primary_source));
+
+ /* Version of this RDF-format */
+ xmlNewChild (fnode, NULL, "version", "2.0");
+
+ while (objects != NULL) {
+ ECalComponent *comp = objects->data;
+ const char *temp_constchar;
+ gchar *tmp_str = NULL;
+ GSList *temp_list;
+ ECalComponentDateTime temp_dt;
+ struct icaltimetype *temp_time;
+ int *temp_int;
+ ECalComponentText temp_comptext;
+ xmlNodePtr c_node = xmlNewChild (fnode, NULL, "component", NULL);
+ xmlNodePtr node = xmlNewChild (c_node, NULL, "Vevent", NULL);
+
+ /* Getting the stuff */
+ e_cal_component_get_uid (comp, &temp_constchar);
+ tmp_str = g_strdup_printf ("#%s", temp_constchar);
+ xmlSetProp (node, "about", tmp_str);
+ g_free (tmp_str);
+ add_string_to_rdf (node, "uid",temp_constchar);
+
+ e_cal_component_get_summary (comp, &temp_comptext);
+ add_string_to_rdf (node, "summary",&temp_comptext?temp_comptext.value:NULL);
+
+ e_cal_component_get_description_list (comp, &temp_list);
+ add_list_to_rdf (node, "description", temp_list, ECALCOMPONENTTEXT);
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_categories_list (comp, &temp_list);
+ add_list_to_rdf (node, "categories", temp_list, CONSTCHAR);
+ if (temp_list)
+ e_cal_component_free_categories_list (temp_list);
+
+ e_cal_component_get_comment_list (comp, &temp_list);
+ add_list_to_rdf (node, "comment", temp_list, ECALCOMPONENTTEXT);
+
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_completed (comp, &temp_time);
+ add_time_to_rdf (node, "completed", temp_time);
+ if (temp_time)
+ e_cal_component_free_icaltimetype (temp_time);
+
+ e_cal_component_get_created (comp, &temp_time);
+ add_time_to_rdf (node, "created", temp_time);
+ if (temp_time)
+ e_cal_component_free_icaltimetype (temp_time);
+
+ e_cal_component_get_contact_list (comp, &temp_list);
+ add_list_to_rdf (node, "contact", temp_list, ECALCOMPONENTTEXT);
+ if (temp_list)
+ e_cal_component_free_text_list (temp_list);
+
+ e_cal_component_get_dtstart (comp, &temp_dt);
+ add_time_to_rdf (node, "dtstart", temp_dt.value ? temp_dt.value : NULL);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_dtend (comp, &temp_dt);
+ add_time_to_rdf (node, "dtend", temp_dt.value ? temp_dt.value : NULL);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_due (comp, &temp_dt);
+ add_time_to_rdf (node, "due", temp_dt.value ? temp_dt.value : NULL);
+ if (temp_dt.value)
+ e_cal_component_free_datetime (&temp_dt);
+
+ e_cal_component_get_percent (comp, &temp_int);
+ add_nummeric_to_rdf (node, "percentComplete", temp_int);
+
+ e_cal_component_get_priority (comp, &temp_int);
+ add_nummeric_to_rdf (node, "priority", temp_int);
+
+ e_cal_component_get_url (comp, &temp_constchar);
+ add_string_to_rdf (node, "URL", temp_constchar);
+
+ if (e_cal_component_has_attendees (comp)) {
+ e_cal_component_get_attendee_list (comp, &temp_list);
+ add_list_to_rdf (node, "attendee", temp_list, ECALCOMPONENTATTENDEE);
+ if (temp_list)
+ e_cal_component_free_attendee_list (temp_list);
+ }
+
+ e_cal_component_get_location (comp, &temp_constchar);
+ add_string_to_rdf (node, "location", temp_constchar);
+
+ e_cal_component_get_last_modified (comp, &temp_time);
+ add_time_to_rdf (node, "lastModified",temp_time);
+
+
+ /* Important note!
+ * The documentation is not requiring this!
+ *
+ * if (temp_time) e_cal_component_free_icaltimetype (temp_time);
+ *
+ * Please uncomment and fix documentation if untrue
+ * http://www.gnome.org/projects/evolution/developer-doc/libecal/ECalComponent.html
+ * #e-cal-component-get-last-modified
+ */
+
+ objects = g_list_next (objects);
+ }
+
+ /* I used a buffer rather than xmlDocDump: I want gnome-vfs support */
+ xmlNodeDump (buffer, doc, doc->children, 2, 1);
+
+ gnome_vfs_write (handle, xmlBufferContent (buffer), xmlBufferLength (buffer), NULL);
+
+ xmlBufferFree (buffer);
+ xmlFreeDoc (doc);
+ gnome_vfs_close (handle);
+ }
+
+ g_object_unref (source_client);
+
+ return;
+}
+
+FormatHandler *rdf_format_handler_new (void)
+{
+ FormatHandler *handler = g_new (FormatHandler, 1);
+
+ handler->isdefault = FALSE;
+ handler->combo_label = _("RDF format (.rdf)");
+ handler->filename_ext = ".rdf";
+ handler->options_widget = NULL;
+ handler->save = do_save_calendar_rdf;
+
+ return handler;
+}