aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChenthill Palanisamy <pchen@src.gnome.org>2005-12-19 18:08:10 +0800
committerChenthill Palanisamy <pchen@src.gnome.org>2005-12-19 18:08:10 +0800
commit58245bd32da1d2779a802b16a4e04d9fdae3b348 (patch)
tree598e35f1fad6185115470da8f76e7c2afa550d73
parenteb46584e35649fc451af2e3ec3b60a7bba399738 (diff)
downloadgsoc2013-evolution-58245bd32da1d2779a802b16a4e04d9fdae3b348.tar
gsoc2013-evolution-58245bd32da1d2779a802b16a4e04d9fdae3b348.tar.gz
gsoc2013-evolution-58245bd32da1d2779a802b16a4e04d9fdae3b348.tar.bz2
gsoc2013-evolution-58245bd32da1d2779a802b16a4e04d9fdae3b348.tar.lz
gsoc2013-evolution-58245bd32da1d2779a802b16a4e04d9fdae3b348.tar.xz
gsoc2013-evolution-58245bd32da1d2779a802b16a4e04d9fdae3b348.tar.zst
gsoc2013-evolution-58245bd32da1d2779a802b16a4e04d9fdae3b348.zip
Committing the intial patch for calendar publishing.
svn path=/trunk/; revision=30875
-rw-r--r--plugins/publish-calendar/ChangeLog35
-rw-r--r--plugins/publish-calendar/Makefile.am29
-rw-r--r--plugins/publish-calendar/org-gnome-publish-calendar.eplug.in47
-rw-r--r--plugins/publish-calendar/org-gnome-publish-calendar.xml13
-rw-r--r--plugins/publish-calendar/publish-calendar.c564
-rw-r--r--plugins/publish-calendar/publish-calendar.glade1098
-rw-r--r--plugins/publish-calendar/publish-format-fb.c115
-rw-r--r--plugins/publish-calendar/publish-format-fb.h30
-rw-r--r--plugins/publish-calendar/publish-format-ical.c107
-rw-r--r--plugins/publish-calendar/publish-format-ical.h30
-rw-r--r--plugins/publish-calendar/publish-location.c211
-rw-r--r--plugins/publish-calendar/publish-location.h77
-rw-r--r--plugins/publish-calendar/url-editor-dialog.c554
-rw-r--r--plugins/publish-calendar/url-editor-dialog.h112
14 files changed, 3022 insertions, 0 deletions
diff --git a/plugins/publish-calendar/ChangeLog b/plugins/publish-calendar/ChangeLog
new file mode 100644
index 0000000000..2aec0581f5
--- /dev/null
+++ b/plugins/publish-calendar/ChangeLog
@@ -0,0 +1,35 @@
+2005-12-19 Chenthill Palanisamy <pchenthill@novell.com>
+
+ Committing for: David Trowbridge <trowbrds cs colorado edu>
+
+ * Makefile.am:
+ * org-gnome-publish-calendar.eplug.in:
+ * org-gnome-publish-calendar.xml:
+ * publish-calendar.c: (publish), (add_timeout), (update_timestamp),
+ (add_offset_timeout), (url_list_changed),
+ (url_list_enable_toggled), (selection_changed), (url_add_clicked),
+ (url_edit_clicked), (url_list_double_click), (url_remove_clicked),
+ (url_enable_clicked), (online_state_changed),
+ (publish_calendar_locations), (publish_urls), (action_publish),
+ (e_plugin_lib_enable):
+ * publish-calendar.glade:
+ * publish-format-fb.c: (write_calendar), (publish_calendar_as_fb):
+ * publish-format-fb.h:
+ * publish-format-ical.c: (write_calendar),
+ (publish_calendar_as_ical):
+ * publish-format-ical.h:
+ * publish-location.c: (migrateURI), (e_publish_uri_from_xml),
+ (e_publish_uri_to_xml):
+ * publish-location.h:
+ * url-editor-dialog.c: (create_uri), (check_input),
+ (source_selection_changed), (publish_service_changed),
+ (type_selector_changed), (server_entry_changed),
+ (file_entry_changed), (port_entry_changed),
+ (username_entry_changed), (password_entry_changed),
+ (remember_pw_toggled), (set_from_uri),
+ (url_editor_dialog_construct), (url_editor_dialog_new),
+ (url_editor_dialog_dispose), (url_editor_dialog_class_init),
+ (url_editor_dialog_init), (url_editor_dialog_get_type),
+ (url_editor_dialog_run):
+ * url-editor-dialog.h: Committing the intial patch.
+
diff --git a/plugins/publish-calendar/Makefile.am b/plugins/publish-calendar/Makefile.am
new file mode 100644
index 0000000000..3d4002e0ae
--- /dev/null
+++ b/plugins/publish-calendar/Makefile.am
@@ -0,0 +1,29 @@
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(EVOLUTION_CALENDAR_CFLAGS) \
+ -DPLUGINDIR="\"$(plugindir)\""
+
+@EVO_PLUGIN_RULE@
+
+plugin_DATA = \
+ org-gnome-publish-calendar.eplug \
+ org-gnome-publish-calendar.xml \
+ publish-calendar.glade
+plugin_LTLIBRARIES = liborg-gnome-publish-calendar.la
+
+liborg_gnome_publish_calendar_la_SOURCES = \
+ publish-calendar.c \
+ publish-format-fb.c \
+ publish-format-fb.h \
+ publish-format-ical.c \
+ publish-format-ical.h \
+ publish-location.c \
+ publish-location.h \
+ url-editor-dialog.c \
+ url-editor-dialog.h
+
+liborg_gnome_publish_calendar_la_LDFLAGS = -module -avoid-version
+
+EXTRA_DIST = \
+ org-gnome-publish-calendar.eplug.in \
+ publish-calendar.glade
diff --git a/plugins/publish-calendar/org-gnome-publish-calendar.eplug.in b/plugins/publish-calendar/org-gnome-publish-calendar.eplug.in
new file mode 100644
index 0000000000..7277918b23
--- /dev/null
+++ b/plugins/publish-calendar/org-gnome-publish-calendar.eplug.in
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<e-plugin-list>
+ <e-plugin
+ type="shlib"
+ location="@PLUGINDIR@/liborg-gnome-publish-calendar.so"
+ id="org.gnome.evolution.calendar.publish"
+ name="Calendar Publishing">
+ <description>Allows calendars to be published to the web</description>
+ <author name="David Trowbridge" email="trowbrds@cs.colorado.edu"/>
+ <!-- calendar main menu -->
+ <hook class="org.gnome.evolution.shell.bonobomenu:1.0">
+ <menu id="org.gnome.evolution.shell" target="shell">
+ <ui file="@PLUGINDIR@/org-gnome-publish-calendar.xml" />
+ <item
+ type="item"
+ verb="EPublishCalendarPublish"
+ path="/commands/EPublishCalendarPublish"
+ activate="action_publish" />
+ </menu>
+ </hook>
+
+ <!-- config page -->
+ <hook class="org.gnome.evolution.calendar.config:1.0">
+ <group
+ target="prefs"
+ id="org.gnome.evolution.calendar.prefs">
+ <item
+ type="page"
+ path="30.publishing"
+ label="Calendar Publishing"/>
+ <item
+ type="section"
+ path="30.publishing/00.urls"
+ label="Locations"/>
+ <item
+ type="item"
+ path="30.publishing/00.urls/00.locations"
+ factory="publish_calendar_locations"/>
+ </group>
+ </hook>
+
+ <!-- shell hooks -->
+ <hook class="org.gnome.evolution.shell.events:1.0">
+ <event id="state.changed" handle="online_state_changed" target="state" />
+ </hook>
+ </e-plugin>
+</e-plugin-list>
diff --git a/plugins/publish-calendar/org-gnome-publish-calendar.xml b/plugins/publish-calendar/org-gnome-publish-calendar.xml
new file mode 100644
index 0000000000..6eaa4256b7
--- /dev/null
+++ b/plugins/publish-calendar/org-gnome-publish-calendar.xml
@@ -0,0 +1,13 @@
+<Root>
+ <commands>
+ <cmd name="EPublishCalendarPublish"/>
+ </commands>
+
+ <menu>
+ <placeholder name="ActionsPlaceholder">
+ <submenu name="Actions">
+ <menuitem verb="EPublishCalendarPublish" _label="_Publish Calendar Information" />
+ </submenu>
+ </placeholder>
+ </menu>
+</Root>
diff --git a/plugins/publish-calendar/publish-calendar.c b/plugins/publish-calendar/publish-calendar.c
new file mode 100644
index 0000000000..356e8934c4
--- /dev/null
+++ b/plugins/publish-calendar/publish-calendar.c
@@ -0,0 +1,564 @@
+/*
+ * Authors: David Trowbridge <trowbrds@cs.colorado.edu>
+ *
+ * Copyright (C) 2005 Novell, Inc. (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <gconf/gconf-client.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libedataserverui/e-passwords.h>
+#include <calendar/gui/e-cal-popup.h>
+#include <calendar/gui/e-cal-config.h>
+#include <calendar/gui/e-cal-menu.h>
+#include <shell/es-event.h>
+#include "url-editor-dialog.h"
+#include "publish-format-fb.h"
+#include "publish-format-ical.h"
+
+static GtkListStore *store = NULL;
+static GHashTable *uri_timeouts = NULL;
+static GSList *publish_uris = NULL;
+static GSList *queued_publishes = NULL;
+static gint online = 0;
+
+int e_plugin_lib_enable (EPlugin *ep, int enable);
+void action_publish (EPlugin *ep, ECalMenuTargetSelect *t);
+void online_state_changed (EPlugin *ep, ESEventTargetState *target);
+void publish_calendar_context_activate (EPlugin *ep, ECalPopupTargetSource *target);
+GtkWidget *publish_calendar_locations (EPlugin *epl, EConfigHookItemFactoryData *data);
+static void update_timestamp (EPublishUri *uri);
+
+static void
+publish (EPublishUri *uri)
+{
+ if (online) {
+ GnomeVFSURI *vfs_uri = NULL;
+ GnomeVFSResult result;
+ GnomeVFSHandle *handle;
+ gchar *password;
+
+ if (g_slist_find (queued_publishes, uri))
+ queued_publishes = g_slist_remove (queued_publishes, uri);
+
+ if (!uri->enabled)
+ return;
+
+ vfs_uri = gnome_vfs_uri_new (uri->location);
+
+ password = e_passwords_get_password ("Calendar", uri->location);
+ gnome_vfs_uri_set_password (vfs_uri, password);
+
+ if (vfs_uri == NULL) {
+ fprintf (stderr, "Couldn't create uri %s\n", uri->location);
+ /* FIXME: EError */
+ g_free (password);
+ return;
+ }
+
+ result = gnome_vfs_create_uri (&handle, vfs_uri, GNOME_VFS_OPEN_WRITE, FALSE, 0666);
+ if (result != GNOME_VFS_OK) {
+ /* FIXME: EError */
+ fprintf (stderr, "Couldn't open %s: %s\n", uri->location, gnome_vfs_result_to_string (result));
+ g_free (password);
+ return;
+ }
+
+ switch (uri->publish_format) {
+ case URI_PUBLISH_AS_ICAL:
+ publish_calendar_as_ical (handle, uri);
+ break;
+ case URI_PUBLISH_AS_FB:
+ publish_calendar_as_fb (handle, uri);
+ break;
+/*
+ case URI_PUBLISH_AS_HTML:
+ publish_calendar_as_html (handle, uri);
+ break;
+*/
+ }
+
+ update_timestamp (uri);
+
+ result = gnome_vfs_close (handle);
+ gnome_vfs_uri_unref (vfs_uri);
+ g_free (password);
+ } else {
+ if (g_slist_find (queued_publishes, uri) == NULL)
+ queued_publishes = g_slist_prepend (queued_publishes, uri);
+ }
+}
+
+typedef struct {
+ GConfClient *gconf;
+ GtkWidget *treeview;
+ GtkWidget *url_add;
+ GtkWidget *url_edit;
+ GtkWidget *url_remove;
+ GtkWidget *url_enable;
+} PublishUIData;
+
+static void
+add_timeout (EPublishUri *uri)
+{
+ guint id;
+
+ /* Set the timeout for now+frequency */
+ switch (uri->publish_frequency) {
+ case URI_PUBLISH_DAILY:
+ id = g_timeout_add (24 * 60 * 60 * 1000, (GSourceFunc) publish, uri);
+ g_hash_table_insert (uri_timeouts, uri, GUINT_TO_POINTER (id));
+ break;
+ case URI_PUBLISH_WEEKLY:
+ id = g_timeout_add (7 * 24 * 60 * 60 * 1000, (GSourceFunc) publish, uri);
+ g_hash_table_insert (uri_timeouts, uri, GUINT_TO_POINTER (id));
+ break;
+ }
+}
+
+static void
+update_timestamp (EPublishUri *uri)
+{
+ GConfClient *client;
+ GSList *uris, *l;
+ gchar *xml;
+ guint id;
+
+ /* Remove timeout if we have one */
+ id = GPOINTER_TO_UINT (g_hash_table_lookup (uri_timeouts, uri));
+ if (id) {
+ g_source_remove (id);
+ add_timeout (uri);
+ }
+
+ /* Update timestamp in gconf */
+ xml = e_publish_uri_to_xml (uri);
+
+ client = gconf_client_get_default ();
+ uris = gconf_client_get_list (client, "/apps/evolution/calendar/publish/uris", GCONF_VALUE_STRING, NULL);
+ for (l = uris; l; l = g_slist_next (l)) {
+ gchar *d = l->data;
+ if (strcmp (d, xml) == 0) {
+ uris = g_slist_remove (uris, d);
+ g_free (d);
+ break;
+ }
+ }
+ g_free (xml);
+
+ if (uri->last_pub_time)
+ g_free (uri->last_pub_time);
+ uri->last_pub_time = g_strdup_printf ("%d", (int) time (NULL));
+
+ uris = g_slist_prepend (uris, e_publish_uri_to_xml (uri));
+
+ gconf_client_set_list (client, "/apps/evolution/calendar/publish/uris", GCONF_VALUE_STRING, uris, NULL);
+
+ g_slist_foreach (uris, (GFunc) g_free, NULL);
+ g_slist_free (uris);
+ g_object_unref (client);
+}
+
+static void
+add_offset_timeout (EPublishUri *uri)
+{
+ guint id;
+ time_t offset = atoi (uri->last_pub_time);
+ time_t current = time (NULL);
+ gint elapsed = current - offset;
+
+ switch (uri->publish_frequency) {
+ case URI_PUBLISH_DAILY:
+ if (elapsed > 24 * 60 * 60) {
+ publish (uri);
+ add_timeout (uri);
+ } else {
+ id = g_timeout_add (((24 * 60 * 60) - elapsed) * 1000, (GSourceFunc) publish, uri);
+ g_hash_table_insert (uri_timeouts, uri, GUINT_TO_POINTER (id));
+ break;
+ }
+ break;
+ case URI_PUBLISH_WEEKLY:
+ if (elapsed > 7 * 24 * 60 * 60) {
+ publish (uri);
+ add_timeout (uri);
+ } else {
+ id = g_timeout_add (((7 * 24 * 60 * 60) - elapsed) * 1000, (GSourceFunc) publish, uri);
+ g_hash_table_insert (uri_timeouts, uri, GUINT_TO_POINTER (id));
+ break;
+ }
+ break;
+ }
+}
+
+static void
+url_list_changed (PublishUIData *ui)
+{
+ GtkTreeModel *model = NULL;
+ GSList *url_list = NULL;
+ GtkTreeIter iter;
+ gboolean valid;
+ GConfClient *client;
+
+ url_list = NULL;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (ui->treeview));
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+ while (valid) {
+ EPublishUri *url;
+ char *xml;
+
+ gtk_tree_model_get (model, &iter, URL_LIST_URL_COLUMN, &url, -1);
+
+ if ((xml = e_publish_uri_to_xml (url)))
+ url_list = g_slist_append (url_list, xml);
+
+ valid = gtk_tree_model_iter_next (model, &iter);
+ }
+ client = gconf_client_get_default ();
+ gconf_client_set_list (client, "/apps/evolution/calendar/publish/uris", GCONF_VALUE_STRING, url_list, NULL);
+ g_slist_foreach (url_list, (GFunc) g_free, NULL);
+ g_slist_free (url_list);
+}
+
+static void
+url_list_enable_toggled (GtkCellRendererToggle *renderer,
+ const char *path_string,
+ PublishUIData *ui)
+{
+ GtkTreeSelection *selection;
+ EPublishUri *url = NULL;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ path = gtk_tree_path_new_from_string (path_string);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (ui->treeview));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
+
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ gtk_tree_model_get (model, &iter, URL_LIST_URL_COLUMN, &url, -1);
+
+ url->enabled = !url->enabled;
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter, URL_LIST_ENABLED_COLUMN, url->enabled, -1);
+ }
+
+ gtk_tree_path_free (path);
+}
+
+static void
+selection_changed (GtkTreeSelection *selection, PublishUIData *ui)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ gtk_widget_set_sensitive (ui->url_edit, TRUE);
+ gtk_widget_set_sensitive (ui->url_remove, TRUE);
+ gtk_widget_set_sensitive (ui->url_enable, TRUE);
+ } else {
+ gtk_widget_set_sensitive (ui->url_edit, FALSE);
+ gtk_widget_set_sensitive (ui->url_remove, FALSE);
+ gtk_widget_set_sensitive (ui->url_enable, FALSE);
+ }
+}
+
+static void
+url_add_clicked (GtkButton *button, PublishUIData *ui)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *url_editor;
+ EPublishUri *uri;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (ui->treeview));
+ url_editor = url_editor_dialog_new (model, NULL);
+ url_editor_dialog_run ((UrlEditorDialog *) url_editor);
+
+ uri = URL_EDITOR_DIALOG (url_editor)->uri;
+ if (uri->location) {
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ URL_LIST_ENABLED_COLUMN, uri->enabled,
+ URL_LIST_LOCATION_COLUMN, uri->location,
+ URL_LIST_URL_COLUMN, uri, -1);
+ url_list_changed (ui);
+ publish_uris = g_slist_prepend (publish_uris, uri);
+ add_timeout (uri);
+ publish (uri);
+ } else {
+ g_free (uri);
+ }
+ gtk_widget_destroy (url_editor);
+}
+
+static void
+url_edit_clicked (GtkButton *button, PublishUIData *ui)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ EPublishUri *uri;
+ GtkWidget *url_editor;
+ guint id;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 2, &uri, -1);
+ url_editor = url_editor_dialog_new (model, uri);
+ url_editor_dialog_run ((UrlEditorDialog *) url_editor);
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ URL_LIST_ENABLED_COLUMN, uri->enabled,
+ URL_LIST_LOCATION_COLUMN, uri->location,
+ URL_LIST_URL_COLUMN, uri, -1);
+
+ id = GPOINTER_TO_UINT (g_hash_table_lookup (uri_timeouts, uri));
+ if (id)
+ g_source_remove (id);
+ add_timeout (uri);
+ url_list_changed (ui);
+ publish (uri);
+ }
+}
+
+static void
+url_list_double_click (GtkTreeView *treeview,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ PublishUIData *ui)
+{
+ url_edit_clicked (NULL, ui);
+}
+
+static void
+url_remove_clicked (GtkButton *button, PublishUIData *ui)
+{
+ EPublishUri *url = NULL;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *confirm;
+ gint response;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+
+ gtk_tree_model_get (model, &iter, URL_LIST_URL_COLUMN, &url, -1);
+
+ confirm = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+ _("Are you sure you want to remove this URL?"));
+ gtk_dialog_add_button (GTK_DIALOG (confirm), GTK_STOCK_CANCEL, GTK_RESPONSE_NO);
+ gtk_dialog_add_button (GTK_DIALOG (confirm), GTK_STOCK_REMOVE, GTK_RESPONSE_YES);
+ gtk_dialog_set_default_response (GTK_DIALOG (confirm), GTK_RESPONSE_CANCEL);
+
+ response = gtk_dialog_run (GTK_DIALOG (confirm));
+ gtk_widget_destroy (confirm);
+
+ if (response == GTK_RESPONSE_YES) {
+ int len;
+ guint id;
+ gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+
+ len = gtk_tree_model_iter_n_children (model, NULL);
+ if (len > 0) {
+ gtk_tree_selection_select_iter (selection, &iter);
+ } else {
+ gtk_widget_set_sensitive (ui->url_edit, FALSE);
+ gtk_widget_set_sensitive (ui->url_remove, FALSE);
+ gtk_widget_set_sensitive (ui->url_enable, FALSE);
+ }
+
+ publish_uris = g_slist_remove (publish_uris, url);
+ id = GPOINTER_TO_UINT (g_hash_table_lookup (uri_timeouts, url));
+ if (id)
+ g_source_remove (id);
+
+ g_free (url);
+ url_list_changed (ui);
+ }
+}
+
+static void
+url_enable_clicked (GtkButton *button, PublishUIData *ui)
+{
+ EPublishUri *url = NULL;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ gtk_tree_model_get (model, &iter, URL_LIST_URL_COLUMN, &url, -1);
+ url->enabled = !url->enabled;
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter, URL_LIST_URL_COLUMN, url->enabled, -1);
+ gtk_tree_selection_select_iter (selection, &iter);
+ url_list_changed (ui);
+ }
+}
+
+void
+online_state_changed (EPlugin *ep, ESEventTargetState *target)
+{
+ online = target->state;
+ if (online)
+ while (queued_publishes)
+ publish (queued_publishes->data);
+}
+
+GtkWidget *
+publish_calendar_locations (EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ GladeXML *xml;
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+ GtkWidget *toplevel;
+ PublishUIData *ui = g_new0 (PublishUIData, 1);
+ GSList *l;
+ GtkTreeIter iter;
+ GConfClient *client;
+
+ xml = glade_xml_new (PLUGINDIR "/publish-calendar.glade", "toplevel", NULL);
+
+ ui->treeview = glade_xml_get_widget (xml, "url list");
+ if (store == NULL)
+ store = gtk_list_store_new (URL_LIST_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (ui->treeview), GTK_TREE_MODEL (store));
+
+ renderer = gtk_cell_renderer_toggle_new ();
+ g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (ui->treeview), -1, _("Enabled"),
+ renderer, "active", URL_LIST_ENABLED_COLUMN, NULL);
+ g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK (url_list_enable_toggled), ui);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (ui->treeview), -1, _("Location"),
+ renderer, "text", URL_LIST_LOCATION_COLUMN, NULL);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->treeview));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (selection_changed), ui);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ui->treeview), TRUE);
+ g_signal_connect (G_OBJECT (ui->treeview), "row-activated", G_CALLBACK (url_list_double_click), ui);
+
+ ui->url_add = glade_xml_get_widget (xml, "url add");
+ ui->url_edit = glade_xml_get_widget (xml, "url edit");
+ ui->url_remove = glade_xml_get_widget (xml, "url remove");
+ ui->url_enable = glade_xml_get_widget (xml, "url enable");
+ g_signal_connect (G_OBJECT (ui->url_add), "clicked", G_CALLBACK (url_add_clicked), ui);
+ g_signal_connect (G_OBJECT (ui->url_edit), "clicked", G_CALLBACK (url_edit_clicked), ui);
+ g_signal_connect (G_OBJECT (ui->url_remove), "clicked", G_CALLBACK (url_remove_clicked), ui);
+ g_signal_connect (G_OBJECT (ui->url_enable), "clicked", G_CALLBACK (url_enable_clicked), ui);
+ gtk_widget_set_sensitive (GTK_WIDGET (ui->url_edit), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (ui->url_remove), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (ui->url_enable), FALSE);
+
+ client = gconf_client_get_default ();
+ l = publish_uris;
+ while (l) {
+ EPublishUri *url = (EPublishUri *) l->data;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ URL_LIST_ENABLED_COLUMN, url->enabled,
+ URL_LIST_LOCATION_COLUMN, url->location,
+ URL_LIST_URL_COLUMN, url, -1);
+
+ l = g_slist_next (l);
+ }
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ toplevel = glade_xml_get_widget (xml, "toplevel");
+ gtk_widget_show_all (toplevel);
+ gtk_box_pack_start (GTK_BOX (data->parent), toplevel, FALSE, TRUE, 0);
+
+ g_object_unref (xml);
+
+ return toplevel;
+}
+
+static gpointer
+publish_urls (gpointer data)
+{
+ GSList *l;
+
+ for (l = publish_uris; l; l = g_slist_next (l)) {
+ EPublishUri *uri = l->data;
+ publish (uri);
+ }
+
+ return GINT_TO_POINTER (0);
+}
+
+void
+action_publish (EPlugin *ep, ECalMenuTargetSelect *t)
+{
+ GThread *thread = NULL;
+ GError *error = NULL;
+
+ thread = g_thread_create ((GThreadFunc) publish_urls, NULL, FALSE, &error);
+ if (!thread) {
+ g_warning (G_STRLOC ": %s", error->message);
+ g_error_free (error);
+ }
+
+}
+
+int
+e_plugin_lib_enable (EPlugin *ep, int enable)
+{
+ GSList *uris, *l;
+ GConfClient *client;
+
+ if (enable) {
+ client = gconf_client_get_default ();
+ uris = gconf_client_get_list (client, "/apps/evolution/calendar/publish/uris", GCONF_VALUE_STRING, NULL);
+
+ uri_timeouts = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ l = uris;
+ while (l) {
+ gchar *xml = l->data;
+
+ EPublishUri *uri = e_publish_uri_from_xml (xml);
+
+ if (!uri->location) {
+ g_free (uri);
+ continue;
+ }
+
+ publish_uris = g_slist_prepend (publish_uris, uri);
+
+ /* Add a timeout based on the last publish time */
+ add_offset_timeout (uri);
+
+ l = g_slist_next (l);
+ }
+ g_slist_foreach (uris, (GFunc) g_free, NULL);
+ g_slist_free (uris);
+
+ g_object_unref (client);
+ }
+
+ return 0;
+}
diff --git a/plugins/publish-calendar/publish-calendar.glade b/plugins/publish-calendar/publish-calendar.glade
new file mode 100644
index 0000000000..3336426a07
--- /dev/null
+++ b/plugins/publish-calendar/publish-calendar.glade
@@ -0,0 +1,1098 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="window1">
+ <property name="border_width">12</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">window1</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+ <child>
+ <widget class="GtkHBox" id="toplevel">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="url list">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_START</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkButton" id="url add">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="url edit">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-properties</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="url remove">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-remove</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="url enable">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-apply</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">E_nable</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="publishing dialog">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">dialog1</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area2">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="cancelbutton2">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="okbutton2">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkNotebook" id="publishing toplevel">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">True</property>
+ <property name="show_border">True</property>
+ <property name="tab_pos">GTK_POS_TOP</property>
+ <property name="scrollable">False</property>
+ <property name="enable_popup">False</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox7">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label22">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;General&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox14">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkLabel" id="label25">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label28">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Publish as:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">type_selector</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label29">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Publishing _Frequency:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">publish_frequency</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="publish_frequency">
+ <property name="visible">True</property>
+ <property name="items" translatable="yes">Daily
+Weekly
+Manual (via Actions menu)</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="type_selector">
+ <property name="visible">True</property>
+ <property name="items" translatable="yes">iCal
+Free/Busy</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label23">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Sources&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox15">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkLabel" id="label26">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="events_swin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label20">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Calendar</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox8">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label30">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Location&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox17">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox9">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox19">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label34">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Service _type:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="publish_service">
+ <property name="visible">True</property>
+ <property name="items" translatable="yes">SSH
+Public FTP
+FTP (with login)
+Windows share
+WebDAV (HTTP)
+Secure WebDAV (HTTPS)
+Custom Location</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="server_hbox">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="server_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Server:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">server_entry</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="server_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="file_hbox">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label36">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_File:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">file_entry</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="file_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="optional_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Optional Information&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox18">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox10">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="port_hbox">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="port_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Port:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">port_entry</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="port_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="username_hbox">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="username_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Username:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">username_entry</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="password_hbox">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="password_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Password:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">password_entry</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="remember_pw">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Remember password</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label21">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Publishing Location</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/plugins/publish-calendar/publish-format-fb.c b/plugins/publish-calendar/publish-format-fb.c
new file mode 100644
index 0000000000..2e65dcfbf0
--- /dev/null
+++ b/plugins/publish-calendar/publish-format-fb.c
@@ -0,0 +1,115 @@
+/*
+ * Authors: David Trowbridge <trowbrds@cs.colorado.edu>
+ *
+ * Copyright (C) 2005 Novell, Inc. (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <string.h>
+#include <time.h>
+#include <gconf/gconf-client.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-list.h>
+#include <libecal/e-cal.h>
+#include <libecal/e-cal-util.h>
+#include <calendar/common/authentication.h>
+#include "publish-format-fb.h"
+
+static gboolean
+write_calendar (gchar *uid, ESourceList *source_list, GnomeVFSHandle *handle)
+{
+ ESource *source;
+ ECal *client = NULL;
+ GError *error = NULL;
+ GList *objects;
+ icaltimezone *utc;
+ time_t start = time(NULL), end;
+ icalcomponent *top_level;
+
+ utc = icaltimezone_get_utc_timezone ();
+ start = time_day_begin_with_zone (start, utc);
+ end = time_add_week_with_zone (start, 6, utc);
+
+ source = e_source_list_peek_source_by_uid (source_list, uid);
+ if (source)
+ client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_EVENT);
+ if (!client) {
+ g_warning (G_STRLOC ": Could not publish calendar: Calendar backend no longer exists");
+ return FALSE;
+ }
+
+ if (!e_cal_open (client, TRUE, &error)) {
+ /* FIXME: EError */
+ g_object_unref (client);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ top_level = e_cal_util_new_top_level ();
+ error = NULL;
+
+ if (e_cal_get_free_busy (client, NULL, start, end, &objects, &error)) {
+ char *ical_string;
+ GnomeVFSFileSize bytes_written;
+ GnomeVFSResult result;
+
+ while (objects) {
+ ECalComponent *comp = objects->data;
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
+ icalcomponent_add_component (top_level, icalcomp);
+ objects = g_list_remove (objects, comp);
+ }
+
+ ical_string = icalcomponent_as_ical_string (top_level);
+ if ((result = gnome_vfs_write (handle, (gconstpointer) ical_string, strlen (ical_string), &bytes_written)) != GNOME_VFS_OK) {
+ /* FIXME: EError */
+ gnome_vfs_close (handle);
+ return FALSE;
+ }
+ } else {
+ /* FIXME: EError */
+ g_object_unref (client);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ g_object_unref (client);
+ return TRUE;
+}
+
+void
+publish_calendar_as_fb (GnomeVFSHandle *handle, EPublishUri *uri)
+{
+ GSList *l;
+ ESourceList *source_list;
+ GConfClient *gconf_client;
+
+ gconf_client = gconf_client_get_default ();
+
+ /* events */
+ source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/calendar/sources");
+ l = uri->events;
+ while (l) {
+ gchar *uid = l->data;
+ write_calendar (uid, source_list, handle);
+ l = g_slist_next (l);
+ }
+ g_object_unref (source_list);
+
+ g_object_unref (gconf_client);
+}
diff --git a/plugins/publish-calendar/publish-format-fb.h b/plugins/publish-calendar/publish-format-fb.h
new file mode 100644
index 0000000000..d94851e6d0
--- /dev/null
+++ b/plugins/publish-calendar/publish-format-fb.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: David Trowbridge <trowbrds@cs.colorado.edu>
+ *
+ * Copyright (C) 2005 Novell, Inc. (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <libgnomevfs/gnome-vfs.h>
+#include "publish-location.h"
+
+#ifndef PUBLISH_FORMAT_FB_H
+#define PUBLISH_FORMAT_FB_H
+
+void publish_calendar_as_fb (GnomeVFSHandle *handle, EPublishUri *uri);
+
+#endif
diff --git a/plugins/publish-calendar/publish-format-ical.c b/plugins/publish-calendar/publish-format-ical.c
new file mode 100644
index 0000000000..901a3c079e
--- /dev/null
+++ b/plugins/publish-calendar/publish-format-ical.c
@@ -0,0 +1,107 @@
+/*
+ * Authors: David Trowbridge <trowbrds@cs.colorado.edu>
+ *
+ * Copyright (C) 2005 Novell, Inc. (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <string.h>
+#include <gconf/gconf-client.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-list.h>
+#include <libecal/e-cal.h>
+#include <libecal/e-cal-util.h>
+#include <calendar/common/authentication.h>
+#include "publish-format-ical.h"
+
+static gboolean
+write_calendar (gchar *uid, ESourceList *source_list, GnomeVFSHandle *handle)
+{
+ ESource *source;
+ ECal *client = NULL;
+ GError *error = NULL;
+ GList *objects;
+ icalcomponent *top_level;
+
+ source = e_source_list_peek_source_by_uid (source_list, uid);
+ if (source)
+ client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_EVENT);
+ if (!client) {
+ g_warning (G_STRLOC ": Could not publish calendar: Calendar backend no longer exists");
+ return FALSE;
+ }
+
+ if (!e_cal_open (client, TRUE, &error)) {
+ /* FIXME: EError */
+ g_object_unref (client);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ top_level = e_cal_util_new_top_level ();
+ error = NULL;
+
+ if (e_cal_get_object_list (client, "#t", &objects, &error)) {
+ char *ical_string;
+ GnomeVFSFileSize bytes_written = 0;
+ GnomeVFSResult result;
+
+ while (objects) {
+ icalcomponent *icalcomp = objects->data;
+ icalcomponent_add_component (top_level, icalcomp);
+ objects = g_list_remove (objects, icalcomp);
+ }
+
+ ical_string = icalcomponent_as_ical_string (top_level);
+ if ((result = gnome_vfs_write (handle, (gconstpointer) ical_string, strlen (ical_string), &bytes_written)) != GNOME_VFS_OK) {
+ /* FIXME: EError */
+ gnome_vfs_close (handle);
+ return FALSE;
+ }
+ } else {
+ /* FIXME: EError */
+ g_object_unref (client);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ g_object_unref (client);
+ return TRUE;
+}
+
+void
+publish_calendar_as_ical (GnomeVFSHandle *handle, EPublishUri *uri)
+{
+ GSList *l;
+ ESourceList *source_list;
+ GConfClient *gconf_client;
+
+ gconf_client = gconf_client_get_default ();
+
+ /* events */
+ source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/calendar/sources");
+ l = uri->events;
+ while (l) {
+ gchar *uid = l->data;
+ write_calendar (uid, source_list, handle);
+ l = g_slist_next (l);
+ }
+ g_object_unref (source_list);
+
+ g_object_unref (gconf_client);
+}
diff --git a/plugins/publish-calendar/publish-format-ical.h b/plugins/publish-calendar/publish-format-ical.h
new file mode 100644
index 0000000000..8886688fff
--- /dev/null
+++ b/plugins/publish-calendar/publish-format-ical.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: David Trowbridge <trowbrds@cs.colorado.edu>
+ *
+ * Copyright (C) 2005 Novell, Inc. (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <libgnomevfs/gnome-vfs.h>
+#include "publish-location.h"
+
+#ifndef PUBLISH_FORMAT_ICAL_H
+#define PUBLISH_FORMAT_ICAL_H
+
+void publish_calendar_as_ical (GnomeVFSHandle *handle, EPublishUri *uri);
+
+#endif
diff --git a/plugins/publish-calendar/publish-location.c b/plugins/publish-calendar/publish-location.c
new file mode 100644
index 0000000000..4c2b36780b
--- /dev/null
+++ b/plugins/publish-calendar/publish-location.c
@@ -0,0 +1,211 @@
+/*
+ * Authors:
+ * David Trowbridge <trowbrds@cs.colorado.edu>
+ * Gary Ekker <gekker@novell.com>
+ *
+ * Copyright (C) 2005 Novell, Inc (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "publish-location.h"
+#include <libxml/tree.h>
+#include <gconf/gconf-client.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libedataserverui/e-passwords.h>
+#include <string.h>
+
+static EPublishUri *
+migrateURI (const gchar *xml, xmlDocPtr doc)
+{
+ GConfClient *client;
+ GSList *uris, *l, *events = NULL;
+ xmlChar *location, *enabled, *frequency, *username;
+ xmlNodePtr root, p;
+ EPublishUri *uri;
+ GnomeVFSURI *vfs_uri;
+ gchar *password, *temp;
+
+ client = gconf_client_get_default ();
+ uris = gconf_client_get_list (client, "/apps/evolution/calendar/publish/uris", GCONF_VALUE_STRING, NULL);
+ l = uris;
+ while (l && l->data) {
+ gchar *str = l->data;
+ if (strcmp (xml, str) == 0) {
+ uris = g_slist_remove (uris, str);
+ g_free (str);
+ }
+ l = g_slist_next (l);
+ }
+
+ uri = g_new0 (EPublishUri, 1);
+
+ root = doc->children;
+ location = xmlGetProp (root, "location");
+ enabled = xmlGetProp (root, "enabled");
+ frequency = xmlGetProp (root, "frequency");
+ username = xmlGetProp (root, "username");
+
+ vfs_uri = gnome_vfs_uri_new (location);
+ gnome_vfs_uri_set_user_name (vfs_uri, username);
+ temp = gnome_vfs_uri_to_string (vfs_uri, GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD | GNOME_VFS_URI_HIDE_PASSWORD);
+ uri->location = g_strdup_printf ("dav://%s", temp);
+ g_free (temp);
+ gnome_vfs_uri_unref (vfs_uri);
+
+ if (enabled != NULL)
+ uri->enabled = atoi (enabled);
+ if (frequency != NULL)
+ uri->publish_frequency = atoi (frequency);
+ uri->publish_format = URI_PUBLISH_AS_FB;
+
+ password = e_passwords_get_password ("Calendar", location);
+ if (password) {
+ e_passwords_forget_password ("Calendar", location);
+ e_passwords_add_password (uri->location, password);
+ e_passwords_remember_password ("Calendar", uri->location);
+ }
+
+ for (p = root->children; p != NULL; p = p->next) {
+ xmlChar *uid = xmlGetProp (p, "uid");
+ if (strcmp (p->name, "source") == 0) {
+ events = g_slist_append (events, uid);
+ } else {
+ g_free (uid);
+ }
+ }
+ uri->events = events;
+
+ uris = g_slist_prepend (uris, e_publish_uri_to_xml (uri));
+ gconf_client_set_list (client, "/apps/evolution/calendar/publish/uris", GCONF_VALUE_STRING, uris, NULL);
+ g_slist_foreach (uris, (GFunc) g_free, NULL);
+ g_slist_free (uris);
+ g_object_unref (client);
+
+ xmlFree (location);
+ xmlFree (enabled);
+ xmlFree (frequency);
+ xmlFreeDoc (doc);
+
+ return uri;
+}
+
+EPublishUri *
+e_publish_uri_from_xml (const gchar *xml)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root, p;
+ xmlChar *location, *enabled, *frequency;
+ xmlChar *publish_time, *format;
+ GSList *events = NULL;
+ EPublishUri *uri;
+
+ doc = xmlParseDoc ((char *) xml);
+ if (doc == NULL)
+ return NULL;
+
+ root = doc->children;
+ if (strcmp (root->name, "uri") != 0)
+ return NULL;
+
+ if (xmlGetProp (root, "username"))
+ return migrateURI (xml, doc);
+
+ uri = g_new0 (EPublishUri, 1);
+
+ location = xmlGetProp (root, "location");
+ enabled = xmlGetProp (root, "enabled");
+ frequency = xmlGetProp (root, "frequency");
+ format = xmlGetProp (root, "format");
+ publish_time = xmlGetProp (root, "publish_time");
+
+ if (location != NULL)
+ uri->location = location;
+ if (enabled != NULL)
+ uri->enabled = atoi (enabled);
+ if (frequency != NULL)
+ uri->publish_frequency = atoi (frequency);
+ if (format != NULL)
+ uri->publish_format = atoi (format);
+ if (publish_time != NULL)
+ uri->last_pub_time = publish_time;
+
+ uri->password = g_strdup ("");
+
+ for (p = root->children; p != NULL; p = p->next) {
+ xmlChar *uid = xmlGetProp (p, "uid");
+ if (strcmp (p->name, "event") == 0) {
+ events = g_slist_append (events, uid);
+ } else {
+ g_free (uid);
+ }
+ }
+ uri->events = events;
+
+ xmlFree (enabled);
+ xmlFree (frequency);
+ xmlFree (format);
+ xmlFreeDoc (doc);
+
+ return uri;
+}
+
+gchar *
+e_publish_uri_to_xml (EPublishUri *uri)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ gchar *enabled, *frequency, *format;
+ GSList *calendars = NULL;
+ xmlChar *xml_buffer;
+ char *returned_buffer;
+ int xml_buffer_size;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+ g_return_val_if_fail (uri->location != NULL, NULL);
+
+ doc = xmlNewDoc ("1.0");
+
+ root = xmlNewDocNode (doc, NULL, "uri", NULL);
+ enabled = g_strdup_printf ("%d", uri->enabled);
+ frequency = g_strdup_printf ("%d", uri->publish_frequency);
+ format = g_strdup_printf ("%d", uri->publish_format);
+ xmlSetProp (root, "location", uri->location);
+ xmlSetProp (root, "enabled", enabled);
+ xmlSetProp (root, "frequency", frequency);
+ xmlSetProp (root, "format", format);
+ xmlSetProp (root, "publish_time", uri->last_pub_time);
+
+ for (calendars = uri->events; calendars != NULL; calendars = g_slist_next (calendars)) {
+ xmlNodePtr node;
+ node = xmlNewChild (root, NULL, "event", NULL);
+ xmlSetProp (node, "uid", calendars->data);
+ }
+ xmlDocSetRootElement (doc, root);
+
+ xmlDocDumpMemory (doc, &xml_buffer, &xml_buffer_size);
+ xmlFreeDoc (doc);
+
+ returned_buffer = g_malloc (xml_buffer_size + 1);
+ memcpy (returned_buffer, xml_buffer, xml_buffer_size);
+ returned_buffer[xml_buffer_size] = '\0';
+ xmlFree (xml_buffer);
+ g_free (enabled);
+ g_free (frequency);
+ g_free (format);
+
+ return returned_buffer;
+}
diff --git a/plugins/publish-calendar/publish-location.h b/plugins/publish-calendar/publish-location.h
new file mode 100644
index 0000000000..bd918ca071
--- /dev/null
+++ b/plugins/publish-calendar/publish-location.h
@@ -0,0 +1,77 @@
+/*
+ * Authors:
+ * David Trowbridge <trowbrds@cs.colorado.edu>
+ * Gary Ekker <gekker@novell.com>
+ *
+ * Copyright (C) 2005 Novell, Inc (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef PUBLISH_LOCATION_H
+#define PUBLISH_LOCATION_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+enum publish_frequency {
+ URI_PUBLISH_DAILY,
+ URI_PUBLISH_WEEKLY,
+ URI_PUBLISH_MANUAL,
+ /* URI_PUBLISH_AUTO, */
+};
+
+static const int publish_frequency_type_map[] = {
+ URI_PUBLISH_DAILY,
+ URI_PUBLISH_WEEKLY,
+ URI_PUBLISH_MANUAL,
+ /* URI_PUBLISH_AUTO, */
+ -1,
+};
+
+enum publish_format {
+ URI_PUBLISH_AS_ICAL,
+ URI_PUBLISH_AS_FB,
+ /* URI_PUBLISH_AS_HTML, */
+};
+
+static const int publish_format_type_mask[] = {
+ URI_PUBLISH_AS_ICAL,
+ URI_PUBLISH_AS_FB,
+ /* URI_PUBLISH_AS_HTML, */
+ -1,
+};
+
+typedef struct _EPublishUri EPublishUri;
+struct _EPublishUri {
+ gboolean enabled;
+ gchar *location;
+ gint publish_frequency;
+ gint publish_format;
+ gchar *password;
+ GSList *events;
+ gchar *last_pub_time;
+
+ gint service_type;
+};
+
+EPublishUri *e_publish_uri_from_xml (const gchar *xml);
+gchar *e_publish_uri_to_xml (EPublishUri *uri);
+
+G_END_DECLS
+
+#endif
diff --git a/plugins/publish-calendar/url-editor-dialog.c b/plugins/publish-calendar/url-editor-dialog.c
new file mode 100644
index 0000000000..63210d6743
--- /dev/null
+++ b/plugins/publish-calendar/url-editor-dialog.c
@@ -0,0 +1,554 @@
+/*
+ * Authors:
+ * David Trowbridge
+ *
+ * Copyright (C) 2005 Novell, Inc (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "url-editor-dialog.h"
+#include <libedataserverui/e-passwords.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <string.h>
+
+static GtkDialogClass *parent_class = NULL;
+
+static void
+create_uri (UrlEditorDialog *dialog)
+{
+ EPublishUri *uri;
+
+ uri = dialog->uri;
+
+ if (uri->service_type == TYPE_URI) {
+ if (uri->location)
+ g_free (uri->location);
+ uri->location = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->server_entry)));
+ } else {
+ char *method = "", *server, *file, *port, *username, *password;
+
+ server = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->server_entry)));
+ file = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->file_entry)));
+ port = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->port_entry)));
+ username = gnome_vfs_escape_string (gtk_entry_get_text (GTK_ENTRY (dialog->username_entry)));
+ password = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->password_entry)));
+
+ switch (uri->service_type) {
+ case TYPE_SMB:
+ method = "smb";
+ break;
+
+ case TYPE_SSH:
+ method = "sftp";
+ break;
+
+ case TYPE_ANON_FTP:
+ g_free (username);
+ username = g_strdup ("anonymous");
+ case TYPE_FTP:
+ method = "ftp";
+ break;
+
+ case TYPE_DAV:
+ method = "dav";
+ break;
+
+ case TYPE_DAVS:
+ method = "davs";
+ break;
+ }
+
+ if (uri->location)
+ g_free (uri->location);
+ uri->location = g_strdup_printf ("%s://%s%s%s%s%s%s%s",
+ method,
+ username, (username[0] != '\0') ? "@" : "",
+ server,
+ (port[0] != '\0') ? ":" : "", port,
+ (file[0] != '/') ? "/" : "", file);
+
+ g_free (server);
+ g_free (file);
+ g_free (port);
+ g_free (username);
+ g_free (password);
+ }
+}
+
+static void
+check_input (UrlEditorDialog *dialog)
+{
+ gint n = 0;
+ GSList *sources;
+ EPublishUri *uri;
+
+ uri = dialog->uri;
+
+ if (GTK_WIDGET_IS_SENSITIVE (dialog->events_selector)) {
+ sources = e_source_selector_get_selection (E_SOURCE_SELECTOR (dialog->events_selector));
+ n += g_slist_length (sources);
+ }
+ if (n == 0)
+ goto fail;
+
+ /* This should probably be more complex, since ' ' isn't a valid server name */
+ switch (uri->service_type) {
+ case TYPE_SMB:
+ case TYPE_SSH:
+ case TYPE_FTP:
+ case TYPE_DAV:
+ case TYPE_DAVS:
+ case TYPE_ANON_FTP:
+ if (!strlen (gtk_entry_get_text (GTK_ENTRY (dialog->server_entry)))) goto fail;
+ if (!strlen (gtk_entry_get_text (GTK_ENTRY (dialog->file_entry)))) goto fail;
+ break;
+ case TYPE_URI:
+ if (!strlen (gtk_entry_get_text (GTK_ENTRY (dialog->server_entry)))) goto fail;
+ break;
+ }
+
+ create_uri (dialog);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
+ return;
+fail:
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+}
+
+static void
+source_selection_changed (ESourceSelector *selector, UrlEditorDialog *dialog)
+{
+ check_input (dialog);
+}
+
+static void
+publish_service_changed (GtkComboBox *combo, UrlEditorDialog *dialog)
+{
+ gint selected = gtk_combo_box_get_active (combo);
+ EPublishUri *uri;
+
+ uri = dialog->uri;
+
+ /* Big mess that switches around all the fields to match the source type
+ * the user has selected. Tries to keep field contents where possible */
+ switch (selected) {
+ case TYPE_SMB:
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->server_label), "_Server:");
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->port_label), "_Port:");
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->port_label), "S_hare:");
+ gtk_entry_set_text (GTK_ENTRY (dialog->port_entry), "");
+ gtk_widget_show (dialog->file_hbox);
+ gtk_widget_show (dialog->optional_label);
+ gtk_widget_show (dialog->port_hbox);
+ gtk_widget_show (dialog->username_hbox);
+ gtk_widget_show (dialog->password_hbox);
+ gtk_widget_show (dialog->remember_pw);
+ break;
+ case TYPE_SSH:
+ case TYPE_FTP:
+ case TYPE_DAV:
+ case TYPE_DAVS:
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->server_label), "_Server:");
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->port_label), "_Port:");
+ if (uri->service_type == TYPE_SMB)
+ gtk_entry_set_text (GTK_ENTRY (dialog->port_entry), "");
+ else if (uri->service_type == TYPE_URI)
+ gtk_entry_set_text (GTK_ENTRY (dialog->server_entry), "");
+ gtk_widget_show (dialog->file_hbox);
+ gtk_widget_show (dialog->optional_label);
+ gtk_widget_show (dialog->port_hbox);
+ gtk_widget_show (dialog->username_hbox);
+ gtk_widget_show (dialog->password_hbox);
+ gtk_widget_show (dialog->remember_pw);
+ break;
+ case TYPE_ANON_FTP:
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->server_label), "_Server:");
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->port_label), "_Port:");
+ if (uri->service_type == TYPE_SMB)
+ gtk_entry_set_text (GTK_ENTRY (dialog->port_entry), "");
+ else if (uri->service_type == TYPE_URI)
+ gtk_entry_set_text (GTK_ENTRY (dialog->server_entry), "");
+ gtk_widget_show (dialog->file_hbox);
+ gtk_widget_show (dialog->optional_label);
+ gtk_widget_show (dialog->port_hbox);
+ gtk_widget_hide (dialog->username_hbox);
+ gtk_widget_hide (dialog->password_hbox);
+ gtk_widget_hide (dialog->remember_pw);
+ break;
+ case TYPE_URI:
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->server_label), "_Location (URI):");
+ gtk_entry_set_text (GTK_ENTRY (dialog->server_entry), "");
+ gtk_widget_hide (dialog->file_hbox);
+ gtk_widget_hide (dialog->optional_label);
+ gtk_widget_hide (dialog->port_hbox);
+ gtk_widget_hide (dialog->username_hbox);
+ gtk_widget_hide (dialog->password_hbox);
+ gtk_widget_hide (dialog->remember_pw);
+ }
+ uri->service_type = selected;
+ check_input (dialog);
+}
+
+static void
+type_selector_changed (GtkComboBox *combo, UrlEditorDialog *dialog)
+{
+ gint selected = gtk_combo_box_get_active (combo);
+ EPublishUri *uri;
+
+ uri = dialog->uri;
+ uri->publish_format = selected;
+
+ check_input (dialog);
+}
+
+static void
+server_entry_changed (GtkEntry *entry, UrlEditorDialog *dialog)
+{
+ check_input (dialog);
+}
+
+static void
+file_entry_changed (GtkEntry *entry, UrlEditorDialog *dialog)
+{
+ check_input (dialog);
+}
+
+static void
+port_entry_changed (GtkEntry *entry, UrlEditorDialog *dialog)
+{
+}
+
+static void
+username_entry_changed (GtkEntry *entry, UrlEditorDialog *dialog)
+{
+}
+
+static void
+password_entry_changed (GtkEntry *entry, UrlEditorDialog *dialog)
+{
+}
+
+static void
+remember_pw_toggled (GtkToggleButton *toggle, UrlEditorDialog *dialog)
+{
+}
+
+static void
+set_from_uri (UrlEditorDialog *dialog)
+{
+ EPublishUri *uri;
+ char *method, *username, *server, *port;
+ char *tmp1, *tmp2, *tmp3;
+
+ uri = dialog->uri;
+
+ /* determine our method */
+ tmp1 = strchr (uri->location, ':');
+ method = g_strndup (uri->location, tmp1 - uri->location);
+ if (strcmp (method, "smb") == 0)
+ uri->service_type = TYPE_SMB;
+ else if (strcmp (method, "sftp") == 0)
+ uri->service_type = TYPE_SSH;
+ else if (strcmp (method, "ftp") == 0)
+ /* we set TYPE_FTP here for now. if we don't find a
+ * username later, we'll change it to TYPE_ANON_FTP */
+ uri->service_type = TYPE_FTP;
+ else if (strcmp (method, "dav") == 0)
+ uri->service_type = TYPE_DAV;
+ else if (strcmp (method, "davs") == 0)
+ uri->service_type = TYPE_DAVS;
+ else
+ uri->service_type = TYPE_URI;
+ g_free (method);
+
+ /* We've eliminated the protocol field. Now we need
+ * to figure out whether we've got a username */
+ tmp2 = tmp1 + 3;
+ tmp1 = strchr (tmp2, '@');
+ tmp3 = strchr (tmp2, '/');
+ if (tmp1) {
+ if (tmp1 < tmp3) {
+ /* We've got an @, and it's inside the hostname
+ * field. Extract and set the username */
+ username = g_strndup (tmp2, tmp1 - tmp2);
+ gtk_entry_set_text (GTK_ENTRY (dialog->username_entry), username);
+ g_free (username);
+
+ /* Move tmp2 up to the server field */
+ tmp2 = tmp1 + 1;
+ }
+ }
+
+ /* Do we have a port? */
+ tmp1 = strchr (tmp2, ':');
+ if (tmp1 && (tmp1 < tmp3)) {
+ server = g_strndup (tmp2, tmp1 - tmp2);
+ gtk_entry_set_text (GTK_ENTRY (dialog->server_entry), server);
+ g_free (server);
+
+ tmp1++;
+ port = g_strndup (tmp1, tmp3 - tmp1);
+ gtk_entry_set_text (GTK_ENTRY (dialog->port_entry), port);
+ g_free (port);
+ } else {
+ server = g_strndup (tmp2, tmp3 - tmp2);
+ gtk_entry_set_text (GTK_ENTRY (dialog->server_entry), server);
+ g_free (server);
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (dialog->file_entry), tmp3);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->publish_service), uri->service_type);
+}
+
+static gboolean
+url_editor_dialog_construct (UrlEditorDialog *dialog)
+{
+ GladeXML *gui;
+ GtkWidget *toplevel;
+ GConfClient *gconf;
+ GtkSizeGroup *group;
+ EPublishUri *uri;
+
+ gconf = gconf_client_get_default ();
+
+ gui = glade_xml_new (PLUGINDIR "/publish-calendar.glade", "publishing toplevel", NULL);
+ dialog->gui = gui;
+
+#define GW(name) ((dialog->name) = glade_xml_get_widget (dialog->gui, #name))
+ GW(publish_frequency);
+ GW(type_selector);
+
+ GW(events_swin);
+
+ GW(publish_service);
+ GW(server_entry);
+ GW(file_entry);
+
+ GW(port_entry);
+ GW(username_entry);
+ GW(password_entry);
+ GW(remember_pw);
+
+ GW(optional_label);
+
+ GW(port_hbox);
+ GW(username_hbox);
+ GW(password_hbox);
+ GW(server_hbox);
+ GW(file_hbox);
+
+ GW(port_label);
+ GW(username_label);
+ GW(password_label);
+ GW(server_label);
+ GW(file_label);
+#undef GW
+
+ g_return_val_if_fail (gui != NULL, FALSE);
+
+ uri = dialog->uri;
+
+ toplevel = glade_xml_get_widget (gui, "publishing toplevel");
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), toplevel);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+ dialog->cancel = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ dialog->ok = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+
+ dialog->events_source_list = e_source_list_new_for_gconf (gconf, "/apps/evolution/calendar/sources");
+ dialog->events_selector = e_source_selector_new (dialog->events_source_list);
+ gtk_widget_show (dialog->events_selector);
+ gtk_container_add (GTK_CONTAINER (dialog->events_swin), dialog->events_selector);
+
+ group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget (group, dialog->type_selector);
+ gtk_size_group_add_widget (group, dialog->publish_frequency);
+ g_object_unref (group);
+
+ group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget (group, dialog->publish_service);
+ gtk_size_group_add_widget (group, dialog->server_entry);
+ gtk_size_group_add_widget (group, dialog->file_entry);
+ gtk_size_group_add_widget (group, dialog->port_entry);
+ gtk_size_group_add_widget (group, dialog->username_entry);
+ gtk_size_group_add_widget (group, dialog->password_entry);
+ g_object_unref (group);
+
+ if (uri == NULL) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->publish_frequency), 0);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->type_selector), 0);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->publish_service), 0);
+
+ dialog->uri = g_new0 (EPublishUri, 1);
+ uri = dialog->uri;
+ uri->enabled = TRUE;
+ } else {
+ ESource *source;
+ GSList *p;
+
+ for (p = uri->events; p; p = g_slist_next (p)) {
+ gchar *source_uid = g_strdup (p->data);
+ source = e_source_list_peek_source_by_uid (dialog->events_source_list, source_uid);
+ e_source_selector_select_source ((ESourceSelector *) dialog->events_selector, source);
+ g_free (source_uid);
+ }
+
+ if (uri->location && strlen (uri->location)) {
+ set_from_uri (dialog);
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->publish_frequency), uri->publish_frequency);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->type_selector), uri->publish_format);
+
+ uri->password = e_passwords_get_password ("Calendar", uri->location);
+ if (uri->password) {
+ if (strlen (uri->password) != 0) {
+ gtk_entry_set_text (GTK_ENTRY (dialog->password_entry), uri->password);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->remember_pw), TRUE);
+ } else {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->remember_pw), FALSE);
+ }
+ }
+ }
+
+ g_signal_connect (G_OBJECT (dialog->publish_service), "changed", G_CALLBACK (publish_service_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->type_selector), "changed", G_CALLBACK (type_selector_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->events_selector), "selection_changed", G_CALLBACK (source_selection_changed), dialog);
+
+ g_signal_connect (G_OBJECT (dialog->server_entry), "changed", G_CALLBACK (server_entry_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->file_entry), "changed", G_CALLBACK (file_entry_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->port_entry), "changed", G_CALLBACK (port_entry_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->username_entry), "changed", G_CALLBACK (username_entry_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->password_entry), "changed", G_CALLBACK (password_entry_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->remember_pw), "toggled", G_CALLBACK (remember_pw_toggled), dialog);
+
+ g_object_unref (gconf);
+
+ check_input (dialog);
+
+ return TRUE;
+}
+
+GtkWidget *
+url_editor_dialog_new (GtkTreeModel *url_list_model, EPublishUri *uri)
+{
+ UrlEditorDialog *dialog;
+
+ dialog = (UrlEditorDialog *) g_object_new (URL_EDITOR_DIALOG_TYPE, NULL);
+ dialog->url_list_model = g_object_ref (url_list_model);
+ dialog->uri = uri;
+
+ if (url_editor_dialog_construct (dialog))
+ return GTK_WIDGET (dialog);
+
+ g_object_unref (dialog);
+ return NULL;
+}
+
+static void
+url_editor_dialog_dispose (GObject *obj)
+{
+ UrlEditorDialog *dialog = (UrlEditorDialog *) obj;
+
+ if (dialog->url_list_model) {
+ g_object_unref (dialog->url_list_model);
+ dialog->url_list_model = NULL;
+ }
+ if (dialog->gui) {
+ g_object_unref (dialog->gui);
+ dialog->gui = NULL;
+ }
+
+ ((GObjectClass *)(parent_class))->dispose (obj);
+}
+
+static void
+url_editor_dialog_class_init (UrlEditorDialogClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = (GObjectClass *) klass;
+ parent_class = g_type_class_ref (GTK_TYPE_DIALOG);
+
+ object_class->dispose = url_editor_dialog_dispose;
+}
+
+static void
+url_editor_dialog_init (UrlEditorDialog *dialog)
+{
+}
+
+GType
+url_editor_dialog_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static GTypeInfo info = {
+ sizeof (UrlEditorDialogClass),
+ NULL, NULL,
+ (GClassInitFunc) url_editor_dialog_class_init,
+ NULL, NULL,
+ sizeof (UrlEditorDialog),
+ 0,
+ (GInstanceInitFunc) url_editor_dialog_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_DIALOG, "UrlEditorDialog", &info, 0);
+ }
+
+ return type;
+}
+
+void
+url_editor_dialog_run (UrlEditorDialog *dialog)
+{
+ gint response;
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (response == GTK_RESPONSE_OK) {
+ GSList *l, *p;
+
+ if (dialog->uri->password)
+ g_free (dialog->uri->password);
+ if (dialog->uri->events) {
+ g_slist_foreach (dialog->uri->events, (GFunc) g_free, NULL);
+ dialog->uri->events = NULL;
+ }
+
+ create_uri (dialog);
+
+ dialog->uri->password = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->password_entry)));
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->remember_pw))) {
+ e_passwords_add_password (dialog->uri->location, dialog->uri->password);
+ e_passwords_remember_password ("Calendar", dialog->uri->location);
+ } else {
+ e_passwords_forget_password ("Calendar", dialog->uri->location);
+ }
+
+ l = e_source_selector_get_selection (E_SOURCE_SELECTOR (dialog->events_selector));
+ for (p = l; p; p = g_slist_next (p))
+ dialog->uri->events = g_slist_append (dialog->uri->events, g_strdup (e_source_peek_uid (p->data)));
+ }
+ gtk_widget_hide_all (GTK_WIDGET (dialog));
+}
diff --git a/plugins/publish-calendar/url-editor-dialog.h b/plugins/publish-calendar/url-editor-dialog.h
new file mode 100644
index 0000000000..88f9455d7f
--- /dev/null
+++ b/plugins/publish-calendar/url-editor-dialog.h
@@ -0,0 +1,112 @@
+/*
+ * Authors:
+ * David Trowbridge
+ *
+ * Copyright (C) 2005 Novell, Inc (www.novell.com)
+ *
+ * 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
+ * of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef URL_EDITOR_DIALOG_H
+#define URL_EDITOR_DIALOG_H
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <libedataserverui/e-source-selector.h>
+#include "publish-location.h"
+
+G_BEGIN_DECLS
+
+#define URL_EDITOR_DIALOG_TYPE (url_editor_dialog_get_type ())
+#define URL_EDITOR_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), URL_EDITOR_DIALOG_TYPE, UrlEditorDialog))
+#define URL_EDITOR_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), URL_EDITOR_DIALOG_TYPE, UrlEditorDialogClass))
+#define IS_URL_EDITOR_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), URL_EDITOR_DIALOG_TYPE))
+#define IS_URL_EDITOR_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), URL_EDITOR_DIALOG_TYPE))
+
+enum {
+ URL_LIST_ENABLED_COLUMN,
+ URL_LIST_LOCATION_COLUMN,
+ URL_LIST_URL_COLUMN,
+ URL_LIST_N_COLUMNS,
+};
+
+enum {
+ TYPE_SSH,
+ TYPE_ANON_FTP,
+ TYPE_FTP,
+ TYPE_SMB,
+ TYPE_DAV,
+ TYPE_DAVS,
+ TYPE_URI,
+};
+
+typedef struct _UrlEditorDialog UrlEditorDialog;
+typedef struct _UrlEditorDialogClass UrlEditorDialogClass;
+
+struct _UrlEditorDialog {
+ GtkDialog parent;
+
+ GtkTreeModel *url_list_model;
+ EPublishUri *uri;
+
+ GladeXML *gui;
+
+ GtkWidget *publish_frequency;
+ GtkWidget *type_selector;
+
+ GtkWidget *events_swin;
+
+ ESourceList *events_source_list;
+ GtkWidget *events_selector;
+
+ GtkWidget *publish_service;
+ GtkWidget *server_entry;
+ GtkWidget *file_entry;
+
+ GtkWidget *port_entry;
+ GtkWidget *username_entry;
+ GtkWidget *password_entry;
+ GtkWidget *remember_pw;
+
+ GtkWidget *optional_label;
+
+ GtkWidget *port_hbox;
+ GtkWidget *username_hbox;
+ GtkWidget *password_hbox;
+ GtkWidget *server_hbox;
+ GtkWidget *file_hbox;
+
+ GtkWidget *port_label;
+ GtkWidget *username_label;
+ GtkWidget *password_label;
+ GtkWidget *server_label;
+ GtkWidget *file_label;
+
+ GtkWidget *ok;
+ GtkWidget *cancel;
+};
+
+struct _UrlEditorDialogClass {
+ GtkDialogClass parent_class;
+};
+
+GtkWidget *url_editor_dialog_new (GtkTreeModel *url_list_model, EPublishUri *uri);
+GType url_editor_dialog_get_type (void);
+void url_editor_dialog_run (UrlEditorDialog *dialog);
+
+G_END_DECLS
+
+#endif /* _URL_EDITOR_DIALOG_H_ */