summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Karapetsas <[email protected]>2013-10-17 17:40:03 +0200
committerStefano Karapetsas <[email protected]>2013-10-17 17:40:03 +0200
commiteae33615af610f84fc2be016c5b222f44e741cc1 (patch)
tree8b7032af97743608cca3fbe60cca06d419e42ce2
parenteb157f54f3dbbbcf3b63f43073c9687f66497b45 (diff)
downloadcaja-extensions-eae33615af610f84fc2be016c5b222f44e741cc1.tar.bz2
caja-extensions-eae33615af610f84fc2be016c5b222f44e741cc1.tar.xz
Add sendto extension
-rw-r--r--AUTHORS7
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac46
-rw-r--r--po/POTFILES.in12
-rw-r--r--sendto/Makefile.am82
-rw-r--r--sendto/caja-nste.c162
-rw-r--r--sendto/caja-nste.h51
-rw-r--r--sendto/caja-sendto-command.c843
-rw-r--r--sendto/caja-sendto-convert3
-rw-r--r--sendto/caja-sendto-module.c60
-rw-r--r--sendto/caja-sendto-plugin.h116
-rw-r--r--sendto/caja-sendto.127
-rw-r--r--sendto/caja-sendto.pc.in10
-rw-r--r--sendto/caja-sendto.ui498
-rw-r--r--sendto/docs/Makefile.am100
-rw-r--r--sendto/docs/caja-sendto-docs.sgml29
-rw-r--r--sendto/docs/caja-sendto-overrides.txt0
-rw-r--r--sendto/docs/caja-sendto-sections.txt14
-rw-r--r--sendto/docs/caja-sendto.types1
-rw-r--r--sendto/docs/html/annotation-glossary.html36
-rw-r--r--sendto/docs/html/api-index-full.html66
-rw-r--r--sendto/docs/html/caja-sendto-caja-sendto-plugin.html219
-rw-r--r--sendto/docs/html/caja-sendto.devhelp17
-rw-r--r--sendto/docs/html/caja-sendto.devhelp220
-rw-r--r--sendto/docs/html/ch01.html33
-rw-r--r--sendto/docs/html/home.pngbin0 -> 654 bytes
-rw-r--r--sendto/docs/html/index.html39
-rw-r--r--sendto/docs/html/index.sgml14
-rw-r--r--sendto/docs/html/left.pngbin0 -> 459 bytes
-rw-r--r--sendto/docs/html/right.pngbin0 -> 472 bytes
-rw-r--r--sendto/docs/html/style.css265
-rw-r--r--sendto/docs/html/up.pngbin0 -> 406 bytes
-rw-r--r--sendto/docs/tmpl/caja-sendto-mimetype.sgml33
-rw-r--r--sendto/docs/tmpl/caja-sendto-packer.sgml112
-rw-r--r--sendto/docs/tmpl/caja-sendto-plugin.sgml63
-rw-r--r--sendto/docs/tmpl/caja-sendto-unused.sgml368
-rw-r--r--sendto/docs/tmpl/nst-common.sgml31
-rw-r--r--sendto/docs/tmpl/nst-enum-types.sgml38
-rw-r--r--sendto/docs/tmpl/nst-plugin-marshal.sgml50
-rw-r--r--sendto/docs/version.xml.in1
-rw-r--r--sendto/org.mate.Caja.Sendto.gschema.xml.in21
-rw-r--r--sendto/plugins/Makefile.am16
-rw-r--r--sendto/plugins/caja-burn/Makefile.am19
-rw-r--r--sendto/plugins/caja-burn/caja-burn.c189
-rw-r--r--sendto/plugins/emailclient/Makefile.am17
-rw-r--r--sendto/plugins/emailclient/emailclient.c274
-rw-r--r--sendto/plugins/gajim/Makefile.am18
-rw-r--r--sendto/plugins/gajim/gajim.c516
-rw-r--r--sendto/plugins/nst-common.c98
-rw-r--r--sendto/plugins/nst-common.h23
-rw-r--r--sendto/plugins/pidgin/Makefile.am18
-rw-r--r--sendto/plugins/pidgin/pidgin.c475
-rw-r--r--sendto/plugins/removable-devices/Makefile.am19
-rw-r--r--sendto/plugins/removable-devices/removable-devices.c259
-rw-r--r--sendto/plugins/upnp/Makefile.am18
-rw-r--r--sendto/plugins/upnp/upnp.c320
56 files changed, 5765 insertions, 4 deletions
diff --git a/AUTHORS b/AUTHORS
index e4c3f2f..349ab29 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,5 @@
MATE:
+
Perberos <[email protected]>
Steve Zesch <[email protected]>
Stefano Karapetsas <[email protected]>
@@ -12,3 +13,9 @@ Allan Douglas <[email protected]>
nautilus-open-terminal:
Christian Neumair <[email protected]>
+
+nautilus-sendto:
+Roberto Majadas <[email protected]>
+This module it's highly influenced by file-roller module
+Thanks Paolo Bacchilega :)
+Bluetooth plugin: Bastien Nocera <[email protected]> \ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
index c43bfa5..09c018c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,7 +3,8 @@
SUBDIRS = \
po \
gksu \
- open-terminal
+ open-terminal \
+ sendto
EXTRA_DIST = \
intltool-extract.in \
diff --git a/configure.ac b/configure.ac
index ffcdfc8..7643ac7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,14 +3,24 @@ AC_INIT([caja-extensions], 1.7.0, [https://github.com/mate-desktop/caja-extensio
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS(config.h)
+AM_DISABLE_STATIC
+AC_PROG_CC
+AM_PROG_LIBTOOL
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
CAJA_REQUIRED=1.5.0
LIBMATE_DESKTOP_REQUIRED=1.5.0
-GLIB_REQUIRED=2.14.0
+GLIB_REQUIRED=2.26.0
GLIB_GSETTINGS
-AC_PROG_CC
-AM_PROG_LIBTOOL
+GTK_DOC_CHECK(1.9)
+
+MATE_COMMON_INIT
+
+GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
+AC_SUBST(GLIB_GENMARSHAL)
# Check for pkgconfig first
AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, yes, no)
@@ -31,6 +41,25 @@ PKG_CHECK_MODULES(OPENTERMINAL, glib-2.0 >= $GLIB_REQUIRED mate-desktop-2.0 >= $
AC_SUBST(OPENTERMINAL_CFLAGS)
AC_SUBST(OPENTERMINAL_LIBS)
+# sendto
+GTHREAD_REQUIRED=2.6.0
+GTK_REQUIRED=2.18
+DBUS_REQUIRED=1.0
+DBUS_GLIB_REQUIRED=0.60
+GUPNP_REQUIRED=0.13
+PKG_CHECK_MODULES(SENDTO,
+ glib-2.0 >= $GLIB_REQUIRED
+ gio-2.0 >= $GLIB_REQUIRED
+ gthread-2.0 >= $GTHREAD_REQUIRED
+ gmodule-2.0 >= $GLIB_REQUIRED
+ gtk+-2.0 >= $GTK_REQUIRED
+ dbus-1 >= $DBUS_REQUIRED
+ dbus-glib-1 >= $DBUS_GLIB_REQUIRED
+ gupnp-1.0 >= $GUPNP_REQUIRED)
+AC_SUBST(SENDTO_CFLAGS)
+AC_SUBST(SENDTO_LIBS)
+AC_DEFINE_UNQUOTED(GAJIM_SHARE_DIR, "$prefix/share/gajim", [path to gajim share dir])
+
# Get caja extensions directory
CAJA_EXTENSION_DIR=`$PKG_CONFIG --variable=extensiondir libcaja-extension`
AC_SUBST(CAJA_EXTENSION_DIR)
@@ -47,6 +76,17 @@ AC_OUTPUT([
Makefile
gksu/Makefile
open-terminal/Makefile
+ sendto/Makefile
+ sendto/caja-sendto.pc
+ sendto/docs/Makefile
+ sendto/docs/version.xml
+ sendto/plugins/Makefile
+ sendto/plugins/emailclient/Makefile
+ sendto/plugins/gajim/Makefile
+ sendto/plugins/caja-burn/Makefile
+ sendto/plugins/pidgin/Makefile
+ sendto/plugins/removable-devices/Makefile
+ sendto/plugins/upnp/Makefile
po/Makefile.in
])
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6dfb3c2..32776c2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,3 +3,15 @@
gksu/libcaja-gksu.c
open-terminal/caja-open-terminal.c
open-terminal/org.mate.caja-open-terminal.gschema.xml.in
+sendto/caja-nste.c
+sendto/caja-nste.h
+sendto/caja-sendto-command.c
+sendto/caja-sendto-module.c
+sendto/org.mate.Caja.Sendto.gschema.xml.in
+[type: gettext/glade]sendto/caja-sendto.ui
+sendto/plugins/emailclient/emailclient.c
+sendto/plugins/gajim/gajim.c
+sendto/plugins/caja-burn/caja-burn.c
+sendto/plugins/pidgin/pidgin.c
+sendto/plugins/removable-devices/removable-devices.c
+sendto/plugins/upnp/upnp.c
diff --git a/sendto/Makefile.am b/sendto/Makefile.am
new file mode 100644
index 0000000..030b731
--- /dev/null
+++ b/sendto/Makefile.am
@@ -0,0 +1,82 @@
+SUBDIRS = docs plugins
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DPLUGINDIR=\"$(libdir)/caja-sendto/plugins\" \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -DUIDIR=\""$(uidir)"\" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
+ $(SENDTO_CFLAGS) \
+ $(CAJA_CFLAGS) \
+ $(DISABLE_DEPRECATED) \
+ $(WARN_CFLAGS)
+
+caja_sendto_includedir = $(includedir)/caja-sendto/
+caja_sendto_include_HEADERS = caja-sendto-plugin.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = caja-sendto.pc
+
+ui_DATA = caja-sendto.ui
+uidir = $(datadir)/caja-sendto/ui
+
+noinst_LTLIBRARIES = libnstplugin.la
+libnstplugin_la_SOURCES = \
+ caja-sendto-plugin.h \
+ nst-enum-types.c \
+ nst-enum-types.h
+libnstplugin_la_LIBADD = $(SENDTO_LIBS)
+
+bin_PROGRAMS = caja-sendto
+
+caja_sendto_SOURCES = caja-sendto-command.c
+caja_sendto_LDADD = $(SENDTO_LIBS) libnstplugin.la
+
+caja_extensiondir = $(CAJA_EXTENSION_DIR)
+caja_extension_LTLIBRARIES = libcaja-sendto.la
+libcaja_sendto_la_SOURCES = \
+ caja-nste.c \
+ caja-nste.h \
+ caja-sendto-module.c
+
+libcaja_sendto_la_LDFLAGS = -module -avoid-version -no-undefined
+libcaja_sendto_la_LIBADD = $(CAJA_LIBS)
+
+nst_headers_to_scan_for_enums = caja-sendto-plugin.h
+# Generate the enums source code, with glib-mkenums:
+# This is based on the same Makefile.am stuff in pango:
+nst_built_headers = nst-enum-types.h
+nst_built_cfiles = nst-enum-types.c
+
+nst-enum-types.h: $(nst_headers_to_scan_for_enums) Makefile
+ $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \
+ --fhead "#ifndef __NST_ENUM_TYPES_H__\n#define __NST_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@[email protected]\" */\n" \
+ --vhead "GType @[email protected]_get_type (void);\n#define [email protected]@ (@[email protected]_get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* __NST_ENUM_TYPES_H__ */" \
+ $(nst_headers_to_scan_for_enums)) > [email protected]
+
+nst-enum-types.c: $(nst_headers_to_scan_for_enums) Makefile nst-enum-types.h
+ $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \
+ --fhead "#include <caja-sendto-plugin.h>\n" \
+ --fhead "#include \"nst-enum-types.h\"\n" \
+ --fhead "#include <glib-object.h>" \
+ --fprod "\n/* enumerations from \"@[email protected]\" */" \
+ --vhead "GType\[email protected][email protected]_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const [email protected]@Value values[] = {" \
+ --vtail " { 0, NULL, NULL }\n };\n etype = [email protected]@_register_static (\"@[email protected]\", values);\n }\n return etype;\n}\n" \
+ $(nst_headers_to_scan_for_enums)) > [email protected]
+
+convertdir=$(datadir)/MateConf/gsettings
+convert_DATA = caja-sendto-convert
+
+gsettingsschema_in_files = org.mate.Caja.Sendto.gschema.xml.in
+gsettings_SCHEMAS = $(gsettingsschema_in_files:.xml.in=.xml)
+
+man_MANS = caja-sendto.1
+
+EXTRA_DIST = $(ui_DATA) $(man_MANS) caja-sendto.pc.in $(convert_DATA) $(gsettingsschema_in_files)
+CLEANFILES = $(nst_built_headers) $(nst_built_cfiles)
diff --git a/sendto/caja-nste.c b/sendto/caja-nste.c
new file mode 100644
index 0000000..62b62b4
--- /dev/null
+++ b/sendto/caja-nste.c
@@ -0,0 +1,162 @@
+/*
+ * Caja-sendto
+ *
+ * Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * This library 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 library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author: Roberto Majadas <[email protected]>
+ *
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-file-info.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include "caja-nste.h"
+
+
+static GObjectClass *parent_class;
+
+static void
+sendto_callback (CajaMenuItem *item,
+ gpointer user_data)
+{
+ GList *files, *scan;
+ CajaFileInfo *file;
+ gchar *uri;
+ GString *cmd;
+
+ files = g_object_get_data (G_OBJECT (item), "files");
+ file = files->data;
+
+ cmd = g_string_new ("caja-sendto");
+
+ for (scan = files; scan; scan = scan->next) {
+ CajaFileInfo *file = scan->data;
+
+ uri = caja_file_info_get_uri (file);
+ g_string_append_printf (cmd, " \"%s\"", uri);
+ g_free (uri);
+ }
+
+ g_spawn_command_line_async (cmd->str, NULL);
+
+ g_string_free (cmd, TRUE);
+}
+
+static GList *
+caja_nste_get_file_items (CajaMenuProvider *provider,
+ GtkWidget *window,
+ GList *files)
+{
+ GList *items = NULL;
+ gboolean one_item;
+ CajaMenuItem *item;
+
+ if (files == NULL)
+ return NULL;
+
+ one_item = (files != NULL) && (files->next == NULL);
+ if (one_item &&
+ !caja_file_info_is_directory ((CajaFileInfo *)files->data)) {
+ item = caja_menu_item_new ("CajaNste::sendto",
+ _("Send To..."),
+ _("Send file by mail, instant message..."),
+ "document-send");
+ } else {
+ item = caja_menu_item_new ("CajaNste::sendto",
+ _("Send To..."),
+ _("Send files by mail, instant message..."),
+ "document-send");
+ }
+ g_signal_connect (item,
+ "activate",
+ G_CALLBACK (sendto_callback),
+ provider);
+ g_object_set_data_full (G_OBJECT (item),
+ "files",
+ caja_file_info_list_copy (files),
+ (GDestroyNotify) caja_file_info_list_free);
+
+ items = g_list_append (items, item);
+
+ return items;
+}
+
+
+static void
+caja_nste_menu_provider_iface_init (CajaMenuProviderIface *iface)
+{
+ iface->get_file_items = caja_nste_get_file_items;
+}
+
+
+static void
+caja_nste_instance_init (CajaNste *nste)
+{
+}
+
+
+static void
+caja_nste_class_init (CajaNsteClass *class)
+{
+ parent_class = g_type_class_peek_parent (class);
+}
+
+
+static GType nste_type = 0;
+
+
+GType
+caja_nste_get_type (void)
+{
+ return nste_type;
+}
+
+
+void
+caja_nste_register_type (GTypeModule *module)
+{
+ static const GTypeInfo info = {
+ sizeof (CajaNsteClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) caja_nste_class_init,
+ NULL,
+ NULL,
+ sizeof (CajaNste),
+ 0,
+ (GInstanceInitFunc) caja_nste_instance_init,
+ };
+
+ static const GInterfaceInfo menu_provider_iface_info = {
+ (GInterfaceInitFunc) caja_nste_menu_provider_iface_init,
+ NULL,
+ NULL
+ };
+
+ nste_type = g_type_module_register_type (module,
+ G_TYPE_OBJECT,
+ "CajaNste",
+ &info, 0);
+
+ g_type_module_add_interface (module,
+ nste_type,
+ CAJA_TYPE_MENU_PROVIDER,
+ &menu_provider_iface_info);
+}
diff --git a/sendto/caja-nste.h b/sendto/caja-nste.h
new file mode 100644
index 0000000..87b5222
--- /dev/null
+++ b/sendto/caja-nste.h
@@ -0,0 +1,51 @@
+/*
+ * Caja SendTo extension
+ *
+ * Copyright (C) 2005 Roberto Majadas
+ *
+ * This library 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 library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author: Roberto Majadas <[email protected]>
+ *
+ */
+
+#ifndef CAJA_NSTE_H
+#define CAJA_NSTE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CAJA_TYPE_NSTE (caja_nste_get_type ())
+#define CAJA_NSTE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CAJA_TYPE_NSTE, CajaNste))
+#define CAJA_IS_NSTE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CAJA_TYPE_NSTE))
+
+typedef struct _CajaNste CajaNste;
+typedef struct _CajaNsteClass CajaNsteClass;
+
+struct _CajaNste {
+ GObject __parent;
+};
+
+struct _CajaNsteClass {
+ GObjectClass __parent;
+};
+
+GType caja_nste_get_type (void);
+void caja_nste_register_type (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* CAJA_NSTE_H */
diff --git a/sendto/caja-sendto-command.c b/sendto/caja-sendto-command.c
new file mode 100644
index 0000000..27753e0
--- /dev/null
+++ b/sendto/caja-sendto-command.c
@@ -0,0 +1,843 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Copyright (C) 2004 Roberto Majadas
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Author: Roberto Majadas <[email protected]>
+ */
+
+#include "config.h"
+#include <string.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include "caja-sendto-plugin.h"
+
+#define CAJA_SENDTO_LAST_MEDIUM "last-medium"
+#define CAJA_SENDTO_LAST_COMPRESS "last-compress"
+#define CAJA_SENDTO_STATUS_LABEL_TIMEOUT_SECONDS 10
+
+#define UNINSTALLED_PLUGINDIR "plugins/removable-devices"
+#define UNINSTALLED_SOURCE "caja-sendto-command.c"
+
+#define SOEXT ("." G_MODULE_SUFFIX)
+#define SOEXT_LEN (strlen (SOEXT))
+
+enum {
+ COLUMN_ICON,
+ COLUMN_DESCRIPTION,
+ NUM_COLUMNS,
+};
+
+/* Options */
+static char **filenames = NULL;
+
+GList *file_list = NULL;
+gboolean has_dirs = FALSE;
+GList *plugin_list = NULL;
+GHashTable *hash ;
+guint option = 0;
+
+static GSettings *settings = NULL;
+
+typedef struct _NS_ui NS_ui;
+
+struct _NS_ui {
+ GtkWidget *dialog;
+ GtkWidget *options_combobox;
+ GtkWidget *send_to_label;
+ GtkWidget *hbox_contacts_ws;
+ GtkWidget *cancel_button;
+ GtkWidget *send_button;
+ GtkWidget *pack_combobox;
+ GtkWidget *pack_checkbutton;
+ GtkWidget *pack_entry;
+ GList *contact_widgets;
+
+ GtkWidget *status_box;
+ GtkWidget *status_image;
+ GtkWidget *status_label;
+ guint status_timeoutid;
+};
+
+static const GOptionEntry entries[] = {
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, "Files to send", "[FILES...]" },
+ { NULL }
+};
+
+static void
+destroy_dialog (GtkWidget *widget, gpointer data )
+{
+ gtk_main_quit ();
+}
+
+static char *
+get_filename_from_list (void)
+{
+ GList *l;
+ GString *common_part = NULL;
+ gboolean matches = TRUE;
+ guint offset = 0;
+ const char *encoding;
+ gboolean use_utf8 = TRUE;
+
+ encoding = g_getenv ("G_FILENAME_ENCODING");
+
+ if (encoding != NULL && strcasecmp(encoding, "UTF-8") != 0)
+ use_utf8 = FALSE;
+
+ if (file_list == NULL)
+ return NULL;
+
+ common_part = g_string_new("");
+
+ while (TRUE) {
+ gunichar cur_char = '\0';
+ for (l = file_list; l ; l = l->next) {
+ char *path = NULL, *name = NULL;
+ char *offset_name = NULL;
+
+ path = g_filename_from_uri ((char *) l->data,
+ NULL, NULL);
+ if (!path)
+ break;
+
+ name = g_path_get_basename (path);
+
+ if (!use_utf8) {
+ char *tmp;
+
+ tmp = g_filename_to_utf8 (name, -1,
+ NULL, NULL, NULL);
+ g_free (name);
+ name = tmp;
+ }
+
+ if (!name) {
+ g_free (path);
+ break;
+ }
+
+ if (offset >= g_utf8_strlen (name, -1)) {
+ g_free(name);
+ g_free(path);
+ matches = FALSE;
+ break;
+ }
+
+ offset_name = g_utf8_offset_to_pointer (name, offset);
+
+ if (offset_name == g_utf8_strrchr (name, -1, '.')) {
+ g_free (name);
+ g_free (path);
+ matches = FALSE;
+ break;
+ }
+ if (cur_char == '\0') {
+ cur_char = g_utf8_get_char (offset_name);
+ } else if (cur_char != g_utf8_get_char (offset_name)) {
+ g_free (name);
+ g_free (path);
+ matches = FALSE;
+ break;
+ }
+ g_free (name);
+ g_free (path);
+ }
+ if (matches == TRUE && cur_char != '\0') {
+ offset++;
+ common_part = g_string_append_unichar (common_part,
+ cur_char);
+ } else {
+ break;
+ }
+ }
+
+ if (g_utf8_strlen (common_part->str, -1) < 4) {
+ g_string_free (common_part, TRUE);
+ return NULL;
+ }
+
+ return g_string_free (common_part, FALSE);
+}
+
+static char *
+pack_files (NS_ui *ui)
+{
+ char *engrampa_cmd;
+ const char *filename;
+ GList *l;
+ GString *cmd, *tmp;
+ char *pack_type, *tmp_dir, *tmp_work_dir, *packed_file;
+
+ engrampa_cmd = g_find_program_in_path ("engrampa");
+ filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
+
+ g_assert (filename != NULL && *filename != '\0');
+
+ tmp_dir = g_strdup_printf ("%s/caja-sendto-%s",
+ g_get_tmp_dir(), g_get_user_name());
+ g_mkdir (tmp_dir, 0700);
+ tmp_work_dir = g_strdup_printf ("%s/caja-sendto-%s/%li",
+ g_get_tmp_dir(), g_get_user_name(),
+ time(NULL));
+ g_mkdir (tmp_work_dir, 0700);
+ g_free (tmp_dir);
+
+ switch (gtk_combo_box_get_active (GTK_COMBO_BOX(ui->pack_combobox)))
+ {
+ case 0:
+ pack_type = g_strdup (".zip");
+ break;
+ case 1:
+ pack_type = g_strdup (".tar.gz");
+ break;
+ case 2:
+ pack_type = g_strdup (".tar.bz2");
+ break;
+ default:
+ pack_type = NULL;
+ g_assert_not_reached ();
+ }
+
+ g_settings_set_int (settings,
+ CAJA_SENDTO_LAST_COMPRESS,
+ gtk_combo_box_get_active(GTK_COMBO_BOX(ui->pack_combobox)));
+
+ cmd = g_string_new ("");
+ g_string_printf (cmd, "%s --add-to=\"%s/%s%s\"",
+ engrampa_cmd, tmp_work_dir,
+ filename,
+ pack_type);
+
+ /* engrampa doesn't understand URIs */
+ for (l = file_list ; l; l=l->next){
+ char *file;
+
+ file = g_filename_from_uri (l->data, NULL, NULL);
+ g_string_append_printf (cmd," \"%s\"", file);
+ g_free (file);
+ }
+
+ g_spawn_command_line_sync (cmd->str, NULL, NULL, NULL, NULL);
+ g_string_free (cmd, TRUE);
+ tmp = g_string_new("");
+ g_string_printf (tmp,"%s/%s%s", tmp_work_dir,
+ filename,
+ pack_type);
+ g_free (tmp_work_dir);
+ packed_file = g_filename_to_uri (tmp->str, NULL, NULL);
+ g_string_free(tmp, TRUE);
+ return packed_file;
+}
+
+static gboolean
+status_label_clear (gpointer data)
+{
+ NS_ui *ui = (NS_ui *) data;
+ gtk_label_set_label (GTK_LABEL (ui->status_label), "");
+ gtk_widget_hide (ui->status_image);
+
+ ui->status_timeoutid = 0;
+
+ return FALSE;
+}
+
+static void
+send_button_cb (GtkWidget *widget, NS_ui *ui)
+{
+ char *error;
+ NstPlugin *p;
+ GtkWidget *w;
+
+ gtk_widget_set_sensitive (ui->dialog, FALSE);
+
+ p = (NstPlugin *) g_list_nth_data (plugin_list, option);
+ w = (GtkWidget *) g_list_nth_data (ui->contact_widgets, option);
+
+ if (ui->status_timeoutid != 0) {
+ g_source_remove (ui->status_timeoutid);
+ status_label_clear (ui);
+ }
+
+ if (p == NULL)
+ return;
+
+ if (p->info->validate_destination != NULL) {
+ error = NULL;
+ if (p->info->validate_destination (p, w, &error) == FALSE) {
+ char *message;
+
+ message = g_strdup_printf ("<b>%s</b>", error);
+ g_free (error);
+ gtk_label_set_markup (GTK_LABEL (ui->status_label), message);
+ g_free (message);
+ ui->status_timeoutid = g_timeout_add_seconds (CAJA_SENDTO_STATUS_LABEL_TIMEOUT_SECONDS,
+ status_label_clear,
+ ui);
+ gtk_widget_show (ui->status_image);
+ gtk_widget_show (ui->status_box);
+ gtk_widget_set_sensitive (ui->dialog, TRUE);
+ return;
+ }
+ }
+
+ g_settings_set_string (settings,
+ CAJA_SENDTO_LAST_MEDIUM,
+ p->info->id);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ui->pack_checkbutton))){
+ char *f;
+
+ f = pack_files (ui);
+ if (f != NULL) {
+ GList *packed_file = NULL;
+ packed_file = g_list_append (packed_file, f);
+ if (!p->info->send_files (p, w, packed_file)) {
+ g_free (f);
+ g_list_free (packed_file);
+ return;
+ }
+ g_list_free (packed_file);
+ } else {
+ gtk_widget_set_sensitive (ui->dialog, TRUE);
+ return;
+ }
+ g_free (f);
+ } else {
+ if (!p->info->send_files (p, w, file_list)) {
+ g_list_foreach (file_list, (GFunc) g_free, NULL);
+ g_list_free (file_list);
+ file_list = NULL;
+ return;
+ }
+ g_list_free (file_list);
+ file_list = NULL;
+ }
+ destroy_dialog (NULL,NULL);
+}
+
+static void
+send_if_no_pack_cb (GtkWidget *widget, NS_ui *ui)
+{
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton))) {
+ if (gtk_widget_is_sensitive (ui->pack_entry)) {
+ gtk_widget_grab_focus (ui->pack_entry);
+ } else {
+ gtk_widget_grab_focus (ui->pack_checkbutton);
+ }
+ } else {
+ send_button_cb (widget, ui);
+ }
+}
+
+static void
+toggle_pack_check (GtkWidget *widget, NS_ui *ui)
+{
+ GtkToggleButton *t = GTK_TOGGLE_BUTTON (widget);
+ gboolean enabled, send_enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (t));
+ gtk_widget_set_sensitive (ui->pack_combobox, enabled);
+ gtk_widget_set_sensitive (ui->pack_entry, enabled);
+
+ send_enabled = TRUE;
+
+ if (enabled) {
+ const char *filename;
+
+ filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
+ if (filename == NULL || *filename == '\0')
+ send_enabled = FALSE;
+ }
+
+ gtk_widget_set_sensitive (ui->send_button, send_enabled);
+}
+
+static void
+option_changed (GtkComboBox *cb, NS_ui *ui)
+{
+ GList *aux;
+ NstPlugin *p;
+ gboolean supports_dirs = FALSE;
+
+ aux = g_list_nth (ui->contact_widgets, option);
+ option = gtk_combo_box_get_active (GTK_COMBO_BOX(cb));
+ gtk_widget_hide ((GtkWidget *) aux->data);
+ aux = g_list_nth (ui->contact_widgets, option);
+ gtk_widget_show ((GtkWidget *) aux->data);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (ui->send_to_label), aux->data);
+
+ p = (NstPlugin *) g_list_nth_data (plugin_list, option);
+ supports_dirs = (p->info->capabilities & CAJA_CAPS_SEND_DIRECTORIES);
+
+ if (has_dirs == FALSE || supports_dirs != FALSE) {
+ gboolean toggle;
+
+ toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton));
+ gtk_widget_set_sensitive (ui->pack_combobox, toggle);
+ gtk_widget_set_sensitive (ui->pack_entry, toggle);
+ gtk_widget_set_sensitive (ui->pack_checkbutton, TRUE);
+ } else {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE);
+ gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE);
+ }
+}
+
+static void
+set_contact_widgets (NS_ui *ui)
+{
+ GList *aux ;
+ GtkWidget *w;
+ NstPlugin *p;
+
+ ui->contact_widgets = NULL;
+
+ for (aux = plugin_list; aux; aux = aux->next){
+ p = (NstPlugin *) aux->data;
+ w = p->info->get_contacts_widget(p);
+ gtk_box_pack_end (GTK_BOX(ui->hbox_contacts_ws),w, TRUE, TRUE, 0);
+ gtk_widget_hide (GTK_WIDGET(w));
+ ui->contact_widgets = g_list_append (ui->contact_widgets, w);
+ if (GTK_IS_ENTRY (w)) {
+ g_signal_connect_after (G_OBJECT (w), "activate",
+ G_CALLBACK (send_if_no_pack_cb), ui);
+ }
+ }
+}
+
+static gboolean
+set_model_for_options_combobox (NS_ui *ui)
+{
+ GdkPixbuf *pixbuf;
+ GtkTreeIter iter;
+ GtkListStore *model;
+ GtkIconTheme *it;
+ GtkCellRenderer *renderer;
+ GtkWidget *widget;
+ GList *aux;
+ NstPlugin *p;
+ char *last_used = NULL;
+ int i = 0;
+ gboolean last_used_support_dirs = FALSE;
+
+ it = gtk_icon_theme_get_default ();
+
+ model = gtk_list_store_new (NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+
+ last_used = g_settings_get_string (settings,
+ CAJA_SENDTO_LAST_MEDIUM);
+
+ for (aux = plugin_list; aux; aux = aux->next) {
+ p = (NstPlugin *) aux->data;
+ pixbuf = gtk_icon_theme_load_icon (it, p->info->icon, 16,
+ GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_ICON, pixbuf,
+ COLUMN_DESCRIPTION, dgettext(p->info->gettext_package, p->info->description),
+ -1);
+ if (last_used != NULL && !strcmp(last_used, p->info->id)) {
+ option = i;
+ last_used_support_dirs = (p->info->capabilities & CAJA_CAPS_SEND_DIRECTORIES);
+ }
+ i++;
+ }
+ g_free(last_used);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX(ui->options_combobox),
+ GTK_TREE_MODEL (model));
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox),
+ renderer,
+ FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox),
+ renderer,
+ "pixbuf", COLUMN_ICON,
+ NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox),
+ renderer,
+ TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox),
+ renderer,
+ "text", COLUMN_DESCRIPTION,
+ NULL);
+
+ g_signal_connect (G_OBJECT (ui->options_combobox), "changed",
+ G_CALLBACK (option_changed), ui);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (ui->options_combobox), option);
+
+ /* Grab the focus for the most recently used widget */
+ widget = g_list_nth_data (ui->contact_widgets, option);
+ gtk_widget_grab_focus (widget);
+
+ return last_used_support_dirs;
+}
+
+static void
+pack_entry_changed_cb (GObject *object, GParamSpec *spec, NS_ui *ui)
+{
+ gboolean send_enabled;
+
+ send_enabled = TRUE;
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton))) {
+ const char *filename;
+
+ filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
+ if (filename == NULL || *filename == '\0')
+ send_enabled = FALSE;
+ }
+
+ gtk_widget_set_sensitive (ui->send_button, send_enabled);
+}
+
+static void
+update_button_image (GtkSettings *settings,
+ GParamSpec *spec,
+ GtkWidget *widget)
+{
+ gboolean show_images;
+
+ g_object_get (settings, "gtk-button-images", &show_images, NULL);
+ if (show_images == FALSE)
+ gtk_widget_hide (widget);
+ else
+ gtk_widget_show (widget);
+}
+
+static void
+caja_sendto_create_ui (void)
+{
+ GtkBuilder *app;
+ GError* error = NULL;
+ NS_ui *ui;
+ gboolean one_file = FALSE;
+ gboolean supports_dirs;
+ GtkSettings *gtk_settings;
+ GtkWidget *button_image;
+
+ app = gtk_builder_new ();
+ if (!gtk_builder_add_from_file (app, UIDIR "/" "caja-sendto.ui", &error)) {
+ g_warning ("Couldn't load builder file: %s", error->message);
+ g_error_free (error);
+ }
+
+ ui = g_new0 (NS_ui, 1);
+
+ ui->hbox_contacts_ws = GTK_WIDGET (gtk_builder_get_object (app, "hbox_contacts_widgets"));
+ ui->send_to_label = GTK_WIDGET (gtk_builder_get_object (app, "send_to_label"));
+ ui->options_combobox = GTK_WIDGET (gtk_builder_get_object (app, "options_combobox"));
+ ui->dialog = GTK_WIDGET (gtk_builder_get_object (app, "caja_sendto_dialog"));
+ ui->cancel_button = GTK_WIDGET (gtk_builder_get_object (app, "cancel_button"));
+ ui->send_button = GTK_WIDGET (gtk_builder_get_object (app, "send_button"));
+ ui->pack_combobox = GTK_WIDGET (gtk_builder_get_object (app, "pack_combobox"));
+ ui->pack_entry = GTK_WIDGET (gtk_builder_get_object (app, "pack_entry"));
+ ui->pack_checkbutton = GTK_WIDGET (gtk_builder_get_object (app, "pack_checkbutton"));
+ ui->status_box = GTK_WIDGET (gtk_builder_get_object (app, "status_box"));
+ ui->status_label = GTK_WIDGET (gtk_builder_get_object (app, "status_label"));
+ ui->status_image = GTK_WIDGET (gtk_builder_get_object (app, "status_image"));
+
+ gtk_settings = gtk_settings_get_default ();
+ button_image = GTK_WIDGET (gtk_builder_get_object (app, "image1"));
+ g_signal_connect (G_OBJECT (gtk_settings), "notify::gtk-button-images",
+ G_CALLBACK (update_button_image), button_image);
+ update_button_image (gtk_settings, NULL, button_image);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX(ui->pack_combobox),
+ g_settings_get_int (settings,
+ CAJA_SENDTO_LAST_COMPRESS));
+
+ if (file_list != NULL && file_list->next != NULL)
+ one_file = FALSE;
+ else if (file_list != NULL)
+ one_file = TRUE;
+
+ gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), _("Files"));
+
+ if (one_file) {
+ char *filepath = NULL, *filename = NULL;
+
+ filepath = g_filename_from_uri ((char *)file_list->data,
+ NULL, NULL);
+
+ if (filepath != NULL)
+ filename = g_path_get_basename (filepath);
+ if (filename != NULL && filename[0] != '\0')
+ gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), filename);
+
+ g_free (filename);
+ g_free (filepath);
+ } else {
+ char *filename = get_filename_from_list ();
+ if (filename != NULL && filename[0] != '\0') {
+ gtk_entry_set_text (GTK_ENTRY (ui->pack_entry),
+ filename);
+ }
+ g_free (filename);
+ }
+
+ set_contact_widgets (ui);
+ supports_dirs = set_model_for_options_combobox (ui);
+ g_signal_connect (G_OBJECT (ui->dialog), "destroy",
+ G_CALLBACK (destroy_dialog), NULL);
+ g_signal_connect (G_OBJECT (ui->cancel_button), "clicked",
+ G_CALLBACK (destroy_dialog), NULL);
+ g_signal_connect (G_OBJECT (ui->send_button), "clicked",
+ G_CALLBACK (send_button_cb), ui);
+ g_signal_connect (G_OBJECT (ui->pack_entry), "activate",
+ G_CALLBACK (send_button_cb), ui);
+ g_signal_connect (G_OBJECT (ui->pack_entry), "notify::text",
+ G_CALLBACK (pack_entry_changed_cb), ui);
+ g_signal_connect (G_OBJECT (ui->pack_checkbutton), "toggled",
+ G_CALLBACK (toggle_pack_check), ui);
+
+ if (has_dirs == FALSE || supports_dirs != FALSE) {
+ gboolean toggle;
+
+ toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton));
+ gtk_widget_set_sensitive (ui->pack_combobox, toggle);
+ gtk_widget_set_sensitive (ui->pack_entry, toggle);
+ } else {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE);
+ gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE);
+ }
+
+ gtk_widget_show (ui->dialog);
+
+}
+
+static void
+caja_sendto_plugin_dir_process (const char *plugindir)
+{
+ GDir *dir;
+ const char *item;
+ NstPlugin *p = NULL;
+ gboolean (*nst_init_plugin)(NstPlugin *p);
+ GError *err = NULL;
+
+ dir = g_dir_open (plugindir, 0, &err);
+
+ if (dir == NULL) {
+ g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason");
+ if (err)
+ g_error_free (err);
+ } else {
+ while ((item = g_dir_read_name(dir))) {
+ if (g_str_has_suffix (item, SOEXT)) {
+ char *module_path;
+
+ p = g_new0(NstPlugin, 1);
+ module_path = g_module_build_path (plugindir, item);
+ p->module = g_module_open (module_path, 0);
+ if (!p->module) {
+ g_warning ("error opening %s: %s", module_path, g_module_error ());
+ g_free (module_path);
+ continue;
+ }
+ g_free (module_path);
+
+ if (!g_module_symbol (p->module, "nst_init_plugin", (gpointer *) &nst_init_plugin)) {
+ g_warning ("error: %s", g_module_error ());
+ g_module_close (p->module);
+ continue;
+ }
+
+ nst_init_plugin (p);
+ if (p->info->init(p)) {
+ plugin_list = g_list_append (plugin_list, p);
+ } else {
+ g_free (p);
+ }
+ }
+ }
+ g_dir_close (dir);
+ }
+}
+
+static gboolean
+caja_sendto_plugin_init (void)
+{
+ if (g_file_test (UNINSTALLED_PLUGINDIR, G_FILE_TEST_IS_DIR) != FALSE) {
+ /* Try to load the local plugins */
+ GError *err = NULL;
+ GDir *dir;
+ const char *item;
+
+ dir = g_dir_open ("plugins/", 0, &err);
+ if (dir == NULL) {
+ g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason");
+ if (err)
+ g_error_free (err);
+ return FALSE;
+ }
+ while ((item = g_dir_read_name(dir))) {
+ char *plugindir;
+
+ plugindir = g_strdup_printf ("plugins/%s/.libs/", item);
+ if (g_file_test (plugindir, G_FILE_TEST_IS_DIR) != FALSE)
+ caja_sendto_plugin_dir_process (plugindir);
+ g_free (plugindir);
+ }
+ g_dir_close (dir);
+ }
+
+ if (g_list_length (plugin_list) == 0)
+ caja_sendto_plugin_dir_process (PLUGINDIR);
+
+ return g_list_length (plugin_list) != 0;
+}
+
+static char *
+escape_ampersands_and_commas (const char *url)
+{
+ int i;
+ char *str, *ptr;
+
+ /* Count the number of ampersands & commas */
+ i = 0;
+ ptr = (char *) url;
+ while ((ptr = strchr (ptr, '&')) != NULL) {
+ i++;
+ ptr++;
+ }
+ ptr = (char *) url;
+ while ((ptr = strchr (ptr, ',')) != NULL) {
+ i++;
+ ptr++;
+ }
+
+ /* No ampersands or commas ? */
+ if (i == 0)
+ return NULL;
+
+ /* Replace the '&' */
+ str = g_malloc0 (strlen (url) - i + 3 * i + 1);
+ ptr = str;
+ for (i = 0; url[i] != '\0'; i++) {
+ if (url[i] == '&') {
+ *ptr++ = '%';
+ *ptr++ = '2';
+ *ptr++ = '6';
+ } else if (url[i] == ',') {
+ *ptr++ = '%';
+ *ptr++ = '2';
+ *ptr++ = 'C';
+ } else {
+ *ptr++ = url[i];
+ }
+ }
+
+ return str;
+}
+
+static void
+caja_sendto_init (void)
+{
+ int i;
+
+ if (g_module_supported() == FALSE)
+ g_error ("Could not initialize gmodule support");
+
+ for (i = 0; filenames != NULL && filenames[i] != NULL; i++) {
+ GFile *file;
+ char *filename, *escaped, *uri;
+
+ file = g_file_new_for_commandline_arg (filenames[i]);
+ filename = g_file_get_path (file);
+ g_object_unref (file);
+ if (filename == NULL)
+ continue;
+
+ if (g_file_test (filename, G_FILE_TEST_IS_DIR) != FALSE)
+ has_dirs = TRUE;
+
+ uri = g_filename_to_uri (filename, NULL, NULL);
+ g_free (filename);
+ escaped = escape_ampersands_and_commas (uri);
+
+ if (escaped == NULL) {
+ file_list = g_list_prepend (file_list, uri);
+ } else {
+ file_list = g_list_prepend (file_list, escaped);
+ g_free (uri);
+ }
+ }
+
+ if (file_list == NULL) {
+ g_print (_("Expects URIs or filenames to be passed as options\n"));
+ exit (1);
+ }
+
+ file_list = g_list_reverse (file_list);
+}
+
+int main (int argc, char **argv)
+{
+ GOptionContext *context;
+ GError *error = NULL;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ g_thread_init (NULL);
+ context = g_option_context_new ("");
+ g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+ if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
+ g_print (_("Could not parse command-line options: %s\n"), error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ settings = g_settings_new ("org.mate.Caja.Sendto");
+ caja_sendto_init ();
+ if (caja_sendto_plugin_init () == FALSE) {
+ GtkWidget *error_dialog;
+
+ error_dialog =
+ gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Could not load any plugins."));
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (error_dialog),
+ _("Please verify your installation"));
+
+ gtk_window_set_title (GTK_WINDOW (error_dialog), ""); /* as per HIG */
+ gtk_container_set_border_width (GTK_CONTAINER (error_dialog), 5);
+ gtk_dialog_set_default_response (GTK_DIALOG (error_dialog),
+ GTK_RESPONSE_OK);
+ gtk_dialog_run (GTK_DIALOG (error_dialog));
+ return 1;
+ }
+ caja_sendto_create_ui ();
+
+ gtk_main ();
+ g_object_unref(settings);
+
+ return 0;
+}
+
diff --git a/sendto/caja-sendto-convert b/sendto/caja-sendto-convert
new file mode 100644
index 0000000..4555b9a
--- /dev/null
+++ b/sendto/caja-sendto-convert
@@ -0,0 +1,3 @@
+[org.mate.Caja.Sendto]
+last-medium = /org/mate/caja-sendto/last_medium
+last-compress = /org/mate/caja-sendto/last_compress
diff --git a/sendto/caja-sendto-module.c b/sendto/caja-sendto-module.c
new file mode 100644
index 0000000..f3746ff
--- /dev/null
+++ b/sendto/caja-sendto-module.c
@@ -0,0 +1,60 @@
+/*
+ * Caja SendTo
+ *
+ * Copyright (C) 2005 Roberto Majadas
+ *
+ * This library 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 library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author: Roberto Majadas <[email protected]>
+ *
+ */
+
+#include <config.h>
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-column-provider.h>
+#include <glib/gi18n-lib.h>
+#include "caja-nste.h"
+
+
+void
+caja_module_initialize (GTypeModule*module)
+{
+ caja_nste_register_type (module);
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+}
+
+
+void
+caja_module_shutdown (void)
+{
+}
+
+
+void
+caja_module_list_types (const GType **types,
+ int *num_types)
+{
+ static GType type_list[1];
+
+ type_list[0] = CAJA_TYPE_NSTE;
+ *types = type_list;
+
+ *num_types = 1;
+}
+
+
+
diff --git a/sendto/caja-sendto-plugin.h b/sendto/caja-sendto-plugin.h
new file mode 100644
index 0000000..f208718
--- /dev/null
+++ b/sendto/caja-sendto-plugin.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Copyright (C) 2004 Roberto Majadas
+ * Copyright (C) 2009 Bastien Nocera <[email protected]>
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Authors: Roberto Majadas <[email protected]>
+ * Bastien Nocera <[email protected]>
+ */
+
+#ifndef _CAJA_SENDTO_PLUGIN_H_
+#define _CAJA_SENDTO_PLUGIN_H_
+
+#include <gmodule.h>
+#include <gtk/gtk.h>
+
+/**
+ * SECTION:caja-sendto-plugin
+ * @short_description: caja-sento plug-in
+ * @stability: Stable
+ * @include: bluetooth-plugin.h
+ *
+ * Plug-ins can be used to extend caja-sendto.
+ **/
+
+typedef struct _NstPluginInfo NstPluginInfo;
+typedef struct _NstPlugin NstPlugin;
+
+/**
+ * NstPluginCapabilities:
+ * @CAJA_CAPS_NONE: No capabilities
+ * @CAJA_CAPS_SEND_DIRECTORIES: The plugin can send whole directories without compression
+ * @CAJA_CAPS_SEND_IMAGES: The plugin only sends images which could be resized
+ *
+ * Capabilities of the plugin.
+ **/
+typedef enum {
+ CAJA_CAPS_NONE = 0,
+ CAJA_CAPS_SEND_DIRECTORIES = 1 << 0,
+ CAJA_CAPS_SEND_IMAGES = 1 << 1,
+} NstPluginCapabilities;
+
+/**
+ * NstPluginInfo:
+ * @icon: The icon name for the plugin selection drop-down
+ * @id: A unique ID representing the plugin
+ * @description: The label used in the plugin selection drop-down
+ * @gettext_package: The domain to use to translate the description, %NULL if the plugin is part of caja-sendto
+ * @capabilities: a bitmask of #NstPluginCapabilities
+ * @init: Check for dependencies, and return %FALSE if dependencies such as programs are missing.
+ * @get_contacts_widget: Return the contact widget, the widget to select the destination of the files
+ * @validate_destination: Validate whether the destination can receive the file. This callback is optional.
+ * @send_files: Actually send the files to the selected destination. The file list is a #GList of URI strings.
+ * @destroy: Free all the resources used by the plugin.
+ *
+ * A structure representing a caja-sendto plugin. You should also call NST_INIT_PLUGIN() on the plugin structure to export it.
+ **/
+struct _NstPluginInfo
+{
+ gchar *icon;
+ gchar *id;
+ gchar *description;
+ gchar *gettext_package;
+ NstPluginCapabilities capabilities;
+ gboolean (*init) (NstPlugin *plugin);
+ GtkWidget* (*get_contacts_widget) (NstPlugin *plugin);
+ gboolean (*validate_destination) (NstPlugin *plugin, GtkWidget *contact_widget, char **error);
+ gboolean (*send_files) (NstPlugin *plugin,
+ GtkWidget *contact_widget,
+ GList *file_list);
+ gboolean (*destroy) (NstPlugin *plugin) ;
+};
+
+/**
+ * NstPlugin:
+ * @module: the #GModule for the opened shared library
+ * @info: a #NstPluginInfo structure
+ *
+ * A structure as used in caja-sendto.
+ **/
+struct _NstPlugin
+{
+ GModule *module;
+ NstPluginInfo *info;
+};
+
+/**
+ * NST_INIT_PLUGIN:
+ * @plugininfo: a #NstPluginInfo structure representing the plugin
+ *
+ * Call this on an #NstPluginInfo structure to make it available to caja-sendto.
+ **/
+# define NST_INIT_PLUGIN(plugininfo) \
+ gboolean nst_init_plugin(NstPlugin *plugin); \
+ G_MODULE_EXPORT gboolean nst_init_plugin(NstPlugin *plugin) { \
+ plugin->info = &(plugininfo); \
+ return TRUE; \
+ }
+
+#endif /* _CAJA_SENDTO_PLUGIN_H_ */
+
diff --git a/sendto/caja-sendto.1 b/sendto/caja-sendto.1
new file mode 100644
index 0000000..bcb8430
--- /dev/null
+++ b/sendto/caja-sendto.1
@@ -0,0 +1,27 @@
+.TH CAJA-SENDTO 1 2006\-07\-18 "MATE" "MATE"
+.SH NAME
+caja\-sendto \- convenience application to send a file via email or instant messenger
+.SH SYNOPSIS
+.B caja-sendto
+.RI [ OPTIONS " " | " " FILES... ]
+.SH DESCRIPTION
+Send FILE(s) via email or instant messenger.
+
+A dialog window presents a choice of carrier application and recipient of the file(s).
+Recipent names can be selected from a list or autocompleted. The selected application
+is then opened with the file(s) and recipient ready for transfer.
+
+The application is intented to integrate with caja and is
+written for the MATE graphical desktop.
+.SH OPTIONS
+.TP
+.B \-?, \-\-help
+Show a help message listing all the options and their meanings.
+.SH AUTHOR
+Written by Roberto Majadas <[email protected]>
+.PP
+This manual page was originally written by Oystein Gisnas for the
+Debian system.
+.\" Copyright 2006 Oystein Gisnas
+.\" You may copy this manual page under the terms of the version 2 of
+.\" the GNU General Public License.
diff --git a/sendto/caja-sendto.pc.in b/sendto/caja-sendto.pc.in
new file mode 100644
index 0000000..50f629f
--- /dev/null
+++ b/sendto/caja-sendto.pc.in
@@ -0,0 +1,10 @@
[email protected]@/caja-sendto/plugins
+
+Name: caja-sendto
+Description: Extend caja-sendto through plugins
+Requires: glib-2.0 gmodule-2.0 gtk+-2.0
+Cflags: -I${includedir}/caja-sendto
diff --git a/sendto/caja-sendto.ui b/sendto/caja-sendto.ui
new file mode 100644
index 0000000..44db667
--- /dev/null
+++ b/sendto/caja-sendto.ui
@@ -0,0 +1,498 @@
+<?xml version="1.0"?>
+<!--*- mode: xml -*-->
+<interface>
+ <object class="GtkListStore" id="model1">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0">.zip</col>
+ </row>
+ <row>
+ <col id="0">.tar.gz</col>
+ </row>
+ <row>
+ <col id="0">.tar.bz2</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkDialog" id="caja_sendto_dialog">
+ <property name="border_width">5</property>
+ <property name="width_request">370</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Send To...</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_CENTER</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="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <property name="has_separator">False</property>
+ <property name="icon_name">document-send</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <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>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="send_button">
+ <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>
+ <object 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>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="icon_name">document-send</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>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Send</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>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <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>
+ <object class="GtkVBox" id="vbox1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Destination&lt;/b&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>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+ <child>
+ <object class="GtkTable" id="table2">
+ <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">12</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Send _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">options_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </object>
+ <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"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="options_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </object>
+ <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="y_options">fill</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="send_to_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Send t_o:</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="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </object>
+ <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"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_contacts_widgets">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <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="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">6</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Compression&lt;/b&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>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+ <child>
+ <object class="GtkVBox" id="vbox4">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="pack_checkbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Send _packed in:</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>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkEntry" id="pack_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 name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="pack_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ <property name="model">model1</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="status_box">
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkImage" id="status_image">
+ <property name="stock">gtk-dialog-error</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>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="status_label">
+ <property name="visible">True</property>
+ <property name="label"> </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</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancel_button</action-widget>
+ <action-widget response="-5">send_button</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/sendto/docs/Makefile.am b/sendto/docs/Makefile.am
new file mode 100644
index 0000000..830ec37
--- /dev/null
+++ b/sendto/docs/Makefile.am
@@ -0,0 +1,100 @@
+## Process this file with automake to produce Makefile.in
+
+# We require automake 1.6 at least.
+AUTOMAKE_OPTIONS = 1.6
+
+# This is a blank Makefile.am for using gtk-doc.
+# Copy this to your project's API docs directory and modify the variables to
+# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
+# of using the various options.
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE=caja-sendto
+
+# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
+#DOC_MODULE_VERSION=2
+
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting the functions and macros.
+# e.g. DOC_SOURCE_DIR=../../../gtk
+DOC_SOURCE_DIR=../../src
+
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
+SCANGOBJ_OPTIONS=
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS=
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS=
+
+# Extra options to supply to gtkdoc-mkhtml
+MKHTML_OPTIONS=
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS=
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+HFILE_GLOB=$(top_srcdir)/src/*.h
+CFILE_GLOB=$(top_srcdir)/src/*.c
+
+# Header files to ignore when scanning.
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
+IGNORE_HFILES=caja-nste.h bluetooth-marshal.h e-contact-entry.h econtactentry-marshal.h nst-common.h
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES=
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+content_files=version.xml
+
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# e.g. expand_content_files=running.sgml
+expand_content_files=
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+GTKDOC_CFLAGS=$(CAJA_SENDTO_CFLAGS)
+GTKDOC_LIBS=$(top_builddir)/src/libnstplugin.la
+
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+include $(top_srcdir)/gtk-doc.make
+
+# Other files to distribute
+# e.g. EXTRA_DIST += version.xml.in
+EXTRA_DIST += version.xml.in
+
+# Files not to distribute
+# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
+# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
+#DISTCLEANFILES +=
+
+# Comment this out if you want your docs-status tested during 'make check'
+#TESTS = $(GTKDOC_CHECK)
+
+if ENABLE_GTK_DOC
+TESTS_ENVIRONMENT = cd $(srcdir) &&
+TESTS = $(GTKDOC_CHECK)
+endif
+
+
diff --git a/sendto/docs/caja-sendto-docs.sgml b/sendto/docs/caja-sendto-docs.sgml
new file mode 100644
index 0000000..5e849f2
--- /dev/null
+++ b/sendto/docs/caja-sendto-docs.sgml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
+<!ENTITY version SYSTEM "version.xml">
+]>
+<book id="index">
+ <bookinfo>
+ <title>caja-sendto Reference Manual</title>
+ <releaseinfo>
+ for caja-sendto &version;
+ The latest version of this documentation can be found on-line at
+ <ulink role="online-location" url="http://library.mate.org/devel/caja-sendto/index.html">http://library.mate.org/devel/caja-sendto/index.html</ulink>.
+ </releaseinfo>
+ </bookinfo>
+
+ <chapter>
+ <title>caja-sendto documentation</title>
+ <xi:include href="xml/caja-sendto-plugin.xml"/>
+
+ </chapter>
+ <index id="api-index-full">
+ <title>API Index</title>
+ <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
+ </index>
+
+ <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+</book>
diff --git a/sendto/docs/caja-sendto-overrides.txt b/sendto/docs/caja-sendto-overrides.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sendto/docs/caja-sendto-overrides.txt
diff --git a/sendto/docs/caja-sendto-sections.txt b/sendto/docs/caja-sendto-sections.txt
new file mode 100644
index 0000000..9a94c9d
--- /dev/null
+++ b/sendto/docs/caja-sendto-sections.txt
@@ -0,0 +1,14 @@
+<SECTION>
+<FILE>caja-sendto-plugin</FILE>
+NstPluginInfo
+NstPlugin
+NstPluginCapabilities
+NST_INIT_PLUGIN
+</SECTION>
+
+<SECTION>
+<FILE>nst-enum-types</FILE>
+nst_plugin_capabilities_get_type
+NST_TYPE_PLUGIN_CAPABILITIES
+</SECTION>
+
diff --git a/sendto/docs/caja-sendto.types b/sendto/docs/caja-sendto.types
new file mode 100644
index 0000000..a177dee
--- /dev/null
+++ b/sendto/docs/caja-sendto.types
@@ -0,0 +1 @@
+nst_plugin_capabilities_get_type
diff --git a/sendto/docs/html/annotation-glossary.html b/sendto/docs/html/annotation-glossary.html
new file mode 100644
index 0000000..b088d39
--- /dev/null
+++ b/sendto/docs/html/annotation-glossary.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Annotation Glossary</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
+<link rel="home" href="index.html" title="caja-sendto Reference Manual">
+<link rel="up" href="index.html" title="caja-sendto Reference Manual">
+<link rel="prev" href="api-index-full.html" title="API Index">
+<meta name="generator" content="GTK-Doc V1.15 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2">
+<tr valign="middle">
+<td><a accesskey="p" href="api-index-full.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
+<td> </td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
+<th width="100%" align="center">caja-sendto Reference Manual</th>
+<td> </td>
+</tr>
+<tr><td colspan="5" class="shortcuts"><a class="shortcut" href="#glsE">E</a></td></tr>
+</table>
+<div class="glossary" title="Annotation Glossary">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="annotation-glossary"></a>Annotation Glossary</h2></div></div></div>
+<a name="glsE"></a><h3 class="title">E</h3>
+<dt>
+<a name="annotation-glossterm-element-type"></a>element-type</dt>
+<dd><p>Generics and defining elements of containers and arrays.</p></dd>
+</div>
+<div class="footer">
+<hr>
+ Generated by GTK-Doc V1.15</div>
+</body>
+</html> \ No newline at end of file
diff --git a/sendto/docs/html/api-index-full.html b/sendto/docs/html/api-index-full.html
new file mode 100644
index 0000000..f373472
--- /dev/null
+++ b/sendto/docs/html/api-index-full.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>API Index</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
+<link rel="home" href="index.html" title="caja-sendto Reference Manual">
+<link rel="up" href="index.html" title="caja-sendto Reference Manual">
+<link rel="prev" href="caja-sendto-caja-sendto-plugin.html" title="caja-sendto-plugin">
+<link rel="next" href="annotation-glossary.html" title="Annotation Glossary">
+<meta name="generator" content="GTK-Doc V1.15 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2">
+<tr valign="middle">
+<td><a accesskey="p" href="caja-sendto-caja-sendto-plugin.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
+<td> </td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
+<th width="100%" align="center">caja-sendto Reference Manual</th>
+<td><a accesskey="n" href="annotation-glossary.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
+</tr>
+<tr><td colspan="5" class="shortcuts">
+<a class="shortcut" href="#idxI">I</a>
+  | 
+ <a class="shortcut" href="#idxP">P</a>
+  | 
+ <a class="shortcut" href="#idxT">T</a>
+</td></tr>
+</table>
+<div class="index" title="API Index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-full"></a>API Index</h2></div></div></div>
+<a name="idx"></a><a name="idxI"></a><h3 class="title">I</h3>
+<dt>
+<a class="link" href="caja-sendto-caja-sendto-plugin.html#NST-INIT-PLUGIN:CAPS" title="NST_INIT_PLUGIN()">NST_INIT_PLUGIN</a>, macro in <a class="link" href="caja-sendto-caja-sendto-plugin.html" title="caja-sendto-plugin">caja-sendto-plugin</a>
+</dt>
+<dd></dd>
+<a name="idxP"></a><h3 class="title">P</h3>
+<dt>
+<a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPlugin" title="NstPlugin">NstPlugin</a>, struct in <a class="link" href="caja-sendto-caja-sendto-plugin.html" title="caja-sendto-plugin">caja-sendto-plugin</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginCapabilities" title="enum NstPluginCapabilities">NstPluginCapabilities</a>, enum in <a class="link" href="caja-sendto-caja-sendto-plugin.html" title="caja-sendto-plugin">caja-sendto-plugin</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginInfo" title="NstPluginInfo">NstPluginInfo</a>, struct in <a class="link" href="caja-sendto-caja-sendto-plugin.html" title="caja-sendto-plugin">caja-sendto-plugin</a>
+</dt>
+<dd></dd>
+<dt>
+nst_plugin_capabilities_get_type, function in nst-enum-types
+</dt>
+<dd></dd>
+<a name="idxT"></a><h3 class="title">T</h3>
+<dt>
+NST_TYPE_PLUGIN_CAPABILITIES, macro in nst-enum-types
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>
+ Generated by GTK-Doc V1.15</div>
+</body>
+</html> \ No newline at end of file
diff --git a/sendto/docs/html/caja-sendto-caja-sendto-plugin.html b/sendto/docs/html/caja-sendto-caja-sendto-plugin.html
new file mode 100644
index 0000000..e8961cb
--- /dev/null
+++ b/sendto/docs/html/caja-sendto-caja-sendto-plugin.html
@@ -0,0 +1,219 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>caja-sendto-plugin</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
+<link rel="home" href="index.html" title="caja-sendto Reference Manual">
+<link rel="up" href="ch01.html" title="caja-sendto documentation">
+<link rel="prev" href="ch01.html" title="caja-sendto documentation">
+<link rel="next" href="api-index-full.html" title="API Index">
+<meta name="generator" content="GTK-Doc V1.15 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2">
+<tr valign="middle">
+<td><a accesskey="p" href="ch01.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
+<td><a accesskey="u" href="ch01.html"><img src="up.png" width="24" height="24" border="0" alt="Up"></a></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
+<th width="100%" align="center">caja-sendto Reference Manual</th>
+<td><a accesskey="n" href="api-index-full.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
+</tr>
+<tr><td colspan="5" class="shortcuts">
+<a href="#caja-sendto-caja-sendto-plugin.synopsis" class="shortcut">Top</a>
+  | 
+ <a href="#caja-sendto-caja-sendto-plugin.description" class="shortcut">Description</a>
+</td></tr>
+</table>
+<div class="refentry" title="caja-sendto-plugin">
+<a name="caja-sendto-caja-sendto-plugin"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="caja-sendto-caja-sendto-plugin.top_of_page"></a>caja-sendto-plugin</span></h2>
+<p>caja-sendto-plugin — caja-sento plug-in</p>
+</td>
+<td valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1" title="Stability Level">
+<a name="caja-sendto-caja-sendto-plugin.stability-level"></a><h2>Stability Level</h2>
+Stable, unless otherwise indicated
+</div>
+<div class="refsynopsisdiv" title="Synopsis">
+<a name="caja-sendto-caja-sendto-plugin.synopsis"></a><h2>Synopsis</h2>
+<pre class="synopsis">
+#include &lt;bluetooth-plugin.h&gt;
+
+ <a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginInfo" title="NstPluginInfo">NstPluginInfo</a>;
+ <a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPlugin" title="NstPlugin">NstPlugin</a>;
+enum <a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginCapabilities" title="enum NstPluginCapabilities">NstPluginCapabilities</a>;
+#define <a class="link" href="caja-sendto-caja-sendto-plugin.html#NST-INIT-PLUGIN:CAPS" title="NST_INIT_PLUGIN()">NST_INIT_PLUGIN</a> (plugininfo)
+</pre>
+</div>
+<div class="refsect1" title="Description">
+<a name="caja-sendto-caja-sendto-plugin.description"></a><h2>Description</h2>
+<p>
+Plug-ins can be used to extend caja-sendto.
+</p>
+</div>
+<div class="refsect1" title="Details">
+<a name="caja-sendto-caja-sendto-plugin.details"></a><h2>Details</h2>
+<div class="refsect2" title="NstPluginInfo">
+<a name="NstPluginInfo"></a><h3>NstPluginInfo</h3>
+<pre class="programlisting">typedef struct {
+ gchar *icon;
+ gchar *id;
+ gchar *description;
+ gchar *gettext_package;
+ NstPluginCapabilities capabilities;
+ gboolean (*init) (NstPlugin *plugin);
+ GtkWidget* (*get_contacts_widget) (NstPlugin *plugin);
+ gboolean (*validate_destination) (NstPlugin *plugin, GtkWidget *contact_widget, char **error);
+ gboolean (*send_files) (NstPlugin *plugin,
+ GtkWidget *contact_widget,
+ GList *file_list);
+ gboolean (*destroy) (NstPlugin *plugin) ;
+} NstPluginInfo;
+</pre>
+<p>
+A structure representing a caja-sendto plugin. You should also call <a class="link" href="caja-sendto-caja-sendto-plugin.html#NST-INIT-PLUGIN:CAPS" title="NST_INIT_PLUGIN()"><code class="function">NST_INIT_PLUGIN()</code></a> on the plugin structure to export it.
+</p>
+<div class="variablelist"><table border="0">
+<col align="left" valign="top">
+<tbody>
+<tr>
+<td><p><span class="term"><a href="http://library.mate.org/devel/glib/unstable/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="NstPluginInfo.icon"></a>icon</code></em>;</span></p></td>
+<td>The icon name for the plugin selection drop-down
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><a href="http://library.mate.org/devel/glib/unstable/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="NstPluginInfo.id"></a>id</code></em>;</span></p></td>
+<td>A unique ID representing the plugin
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><a href="http://library.mate.org/devel/glib/unstable/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="NstPluginInfo.description"></a>description</code></em>;</span></p></td>
+<td>The label used in the plugin selection drop-down
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><a href="http://library.mate.org/devel/glib/unstable/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="NstPluginInfo.gettext-package"></a>gettext_package</code></em>;</span></p></td>
+<td>The domain to use to translate the description, <a href="/usr/share/gtk-doc/html/liboil/liboil-liboiljunk.html#NULL:CAPS"><code class="literal">NULL</code></a> if the plugin is part of caja-sendto
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginCapabilities" title="enum NstPluginCapabilities"><span class="type">NstPluginCapabilities</span></a> <em class="structfield"><code><a name="NstPluginInfo.capabilities"></a>capabilities</code></em>;</span></p></td>
+<td>a bitmask of <a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginCapabilities" title="enum NstPluginCapabilities"><span class="type">NstPluginCapabilities</span></a>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><em class="structfield"><code><a name="NstPluginInfo.init"></a>init</code></em> ()</span></p></td>
+<td>Check for dependencies, and return <a href="http://library.mate.org/devel/glib/unstable/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if dependencies such as programs are missing.
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><em class="structfield"><code><a name="NstPluginInfo.get-contacts-widget"></a>get_contacts_widget</code></em> ()</span></p></td>
+<td>Return the contact widget, the widget to select the destination of the files
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><em class="structfield"><code><a name="NstPluginInfo.validate-destination"></a>validate_destination</code></em> ()</span></p></td>
+<td>Validate whether the destination can receive the file. This callback is optional.
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><em class="structfield"><code><a name="NstPluginInfo.send-files"></a>send_files</code></em> ()</span></p></td>
+<td>Actually send the files to the selected destination. The file list is a <a href="http://library.mate.org/devel/glib/unstable/glib-Doubly-Linked-Lists.html#GList"><span class="type">GList</span></a> of URI strings.
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><em class="structfield"><code><a name="NstPluginInfo.destroy"></a>destroy</code></em> ()</span></p></td>
+<td>Free all the resources used by the plugin.
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<hr>
+<div class="refsect2" title="NstPlugin">
+<a name="NstPlugin"></a><h3>NstPlugin</h3>
+<pre class="programlisting">typedef struct {
+ GModule *module;
+ NstPluginInfo *info;
+} NstPlugin;
+</pre>
+<p>
+A structure as used in caja-sendto.
+</p>
+<div class="variablelist"><table border="0">
+<col align="left" valign="top">
+<tbody>
+<tr>
+<td><p><span class="term"><a href="http://library.mate.org/devel/glib/unstable/glib-Dynamic-Loading-of-Modules.html#GModule"><span class="type">GModule</span></a> *<em class="structfield"><code><a name="NstPlugin.module"></a>module</code></em>;</span></p></td>
+<td>the <a href="http://library.mate.org/devel/glib/unstable/glib-Dynamic-Loading-of-Modules.html#GModule"><span class="type">GModule</span></a> for the opened shared library
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginInfo" title="NstPluginInfo"><span class="type">NstPluginInfo</span></a> *<em class="structfield"><code><a name="NstPlugin.info"></a>info</code></em>;</span></p></td>
+<td>a <a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginInfo" title="NstPluginInfo"><span class="type">NstPluginInfo</span></a> structure
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<hr>
+<div class="refsect2" title="enum NstPluginCapabilities">
+<a name="NstPluginCapabilities"></a><h3>enum NstPluginCapabilities</h3>
+<pre class="programlisting">typedef enum {
+ CAJA_CAPS_NONE = 0,
+ CAJA_CAPS_SEND_DIRECTORIES = 1 &lt;&lt; 0,
+ CAJA_CAPS_SEND_IMAGES = 1 &lt;&lt; 1,
+} NstPluginCapabilities;
+</pre>
+<p>
+Capabilities of the plugin.
+</p>
+<div class="variablelist"><table border="0">
+<col align="left" valign="top">
+<tbody>
+<tr>
+<td><p><a name="CAJA-CAPS-NONE:CAPS"></a><span class="term"><code class="literal">CAJA_CAPS_NONE</code></span></p></td>
+<td>No capabilities
+</td>
+</tr>
+<tr>
+<td><p><a name="CAJA-CAPS-SEND-DIRECTORIES:CAPS"></a><span class="term"><code class="literal">CAJA_CAPS_SEND_DIRECTORIES</code></span></p></td>
+<td>The plugin can send whole directories without compression
+</td>
+</tr>
+<tr>
+<td><p><a name="CAJA-CAPS-SEND-IMAGES:CAPS"></a><span class="term"><code class="literal">CAJA_CAPS_SEND_IMAGES</code></span></p></td>
+<td>The plugin only sends images which could be resized
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<hr>
+<div class="refsect2" title="NST_INIT_PLUGIN()">
+<a name="NST-INIT-PLUGIN:CAPS"></a><h3>NST_INIT_PLUGIN()</h3>
+<pre class="programlisting">#define NST_INIT_PLUGIN(plugininfo)</pre>
+<p>
+Call this on an <a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginInfo" title="NstPluginInfo"><span class="type">NstPluginInfo</span></a> structure to make it available to caja-sendto.
+</p>
+<div class="variablelist"><table border="0">
+<col align="left" valign="top">
+<tbody><tr>
+<td><p><span class="term"><em class="parameter"><code>plugininfo</code></em> :</span></p></td>
+<td>a <a class="link" href="caja-sendto-caja-sendto-plugin.html#NstPluginInfo" title="NstPluginInfo"><span class="type">NstPluginInfo</span></a> structure representing the plugin
+</td>
+</tr></tbody>
+</table></div>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>
+ Generated by GTK-Doc V1.15</div>
+</body>
+</html> \ No newline at end of file
diff --git a/sendto/docs/html/caja-sendto.devhelp b/sendto/docs/html/caja-sendto.devhelp
new file mode 100644
index 0000000..a536a45
--- /dev/null
+++ b/sendto/docs/html/caja-sendto.devhelp
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE book PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">
+<book xmlns="http://www.devhelp.net/book" title="caja-sendto Reference Manual" link="index.html" author="" name="caja-sendto">
+ <chapters>
+ <sub name="caja-sendto documentation" link="ch01.html">
+ <sub name="caja-sendto-plugin" link="caja-sendto-caja-sendto-plugin.html"/>
+ </sub>
+ <sub name="API Index" link="api-index-full.html"/>
+ <sub name="Annotation Glossary" link="annotation-glossary.html"/>
+ </chapters>
+ <functions>
+ <function name="NstPluginInfo" link="caja-sendto-caja-sendto-plugin.html#NstPluginInfo"/>
+ <function name="NstPlugin" link="caja-sendto-caja-sendto-plugin.html#NstPlugin"/>
+ <function name="enum NstPluginCapabilities" link="caja-sendto-caja-sendto-plugin.html#NstPluginCapabilities"/>
+ <function name="NST_INIT_PLUGIN()" link="caja-sendto-caja-sendto-plugin.html#NST-INIT-PLUGIN:CAPS"/>
+ </functions>
+</book>
diff --git a/sendto/docs/html/caja-sendto.devhelp2 b/sendto/docs/html/caja-sendto.devhelp2
new file mode 100644
index 0000000..de85c9d
--- /dev/null
+++ b/sendto/docs/html/caja-sendto.devhelp2
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE book PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">
+<book xmlns="http://www.devhelp.net/book" title="caja-sendto Reference Manual" link="index.html" author="" name="caja-sendto" version="2" language="c">
+ <chapters>
+ <sub name="caja-sendto documentation" link="ch01.html">
+ <sub name="caja-sendto-plugin" link="caja-sendto-caja-sendto-plugin.html"/>
+ </sub>
+ <sub name="API Index" link="api-index-full.html"/>
+ <sub name="Annotation Glossary" link="annotation-glossary.html"/>
+ </chapters>
+ <functions>
+ <keyword type="struct" name="NstPluginInfo" link="caja-sendto-caja-sendto-plugin.html#NstPluginInfo"/>
+ <keyword type="struct" name="NstPlugin" link="caja-sendto-caja-sendto-plugin.html#NstPlugin"/>
+ <keyword type="enum" name="enum NstPluginCapabilities" link="caja-sendto-caja-sendto-plugin.html#NstPluginCapabilities"/>
+ <keyword type="macro" name="NST_INIT_PLUGIN()" link="caja-sendto-caja-sendto-plugin.html#NST-INIT-PLUGIN:CAPS"/>
+ <keyword type="constant" name="CAJA_CAPS_NONE" link="caja-sendto-caja-sendto-plugin.html#CAJA-CAPS-NONE:CAPS"/>
+ <keyword type="constant" name="CAJA_CAPS_SEND_DIRECTORIES" link="caja-sendto-caja-sendto-plugin.html#CAJA-CAPS-SEND-DIRECTORIES:CAPS"/>
+ <keyword type="constant" name="CAJA_CAPS_SEND_IMAGES" link="caja-sendto-caja-sendto-plugin.html#CAJA-CAPS-SEND-IMAGES:CAPS"/>
+ </functions>
+</book>
diff --git a/sendto/docs/html/ch01.html b/sendto/docs/html/ch01.html
new file mode 100644
index 0000000..ff74863
--- /dev/null
+++ b/sendto/docs/html/ch01.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>caja-sendto documentation</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
+<link rel="home" href="index.html" title="caja-sendto Reference Manual">
+<link rel="up" href="index.html" title="caja-sendto Reference Manual">
+<link rel="prev" href="index.html" title="caja-sendto Reference Manual">
+<link rel="next" href="caja-sendto-caja-sendto-plugin.html" title="caja-sendto-plugin">
+<meta name="generator" content="GTK-Doc V1.15 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"><tr valign="middle">
+<td><a accesskey="p" href="index.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
+<td> </td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
+<th width="100%" align="center">caja-sendto Reference Manual</th>
+<td><a accesskey="n" href="caja-sendto-caja-sendto-plugin.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter" title="caja-sendto documentation">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="id443984"></a>caja-sendto documentation</h2></div></div></div>
+<div class="toc"><dl><dt>
+<span class="refentrytitle"><a href="caja-sendto-caja-sendto-plugin.html">caja-sendto-plugin</a></span><span class="refpurpose"> — caja-sento plug-in</span>
+</dt></dl></div>
+</div>
+<div class="footer">
+<hr>
+ Generated by GTK-Doc V1.15</div>
+</body>
+</html> \ No newline at end of file
diff --git a/sendto/docs/html/home.png b/sendto/docs/html/home.png
new file mode 100644
index 0000000..1700361
--- /dev/null
+++ b/sendto/docs/html/home.png
Binary files differ
diff --git a/sendto/docs/html/index.html b/sendto/docs/html/index.html
new file mode 100644
index 0000000..6183dbf
--- /dev/null
+++ b/sendto/docs/html/index.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>caja-sendto Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
+<link rel="home" href="index.html" title="caja-sendto Reference Manual">
+<link rel="next" href="ch01.html" title="caja-sendto documentation">
+<meta name="generator" content="GTK-Doc V1.15 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="book" title="caja-sendto Reference Manual">
+<div class="titlepage">
+<div>
+<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">caja-sendto Reference Manual</p></th></tr></table></div>
+<div><p class="releaseinfo">
+ for caja-sendto 2.32.0
+
+ The latest version of this documentation can be found on-line at
+ <a class="ulink" href="http://library.mate.org/devel/caja-sendto/index.html" target="_top">http://library.mate.org/devel/caja-sendto/index.html</a>.
+ </p></div>
+</div>
+<hr>
+</div>
+<div class="toc"><dl>
+<dt><span class="chapter"><a href="ch01.html">caja-sendto documentation</a></span></dt>
+<dd><dl><dt>
+<span class="refentrytitle"><a href="caja-sendto-caja-sendto-plugin.html">caja-sendto-plugin</a></span><span class="refpurpose"> — caja-sento plug-in</span>
+</dt></dl></dd>
+<dt><span class="index"><a href="api-index-full.html">API Index</a></span></dt>
+<dt><span class="glossary"><a href="annotation-glossary.html">Annotation Glossary</a></span></dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>
+ Generated by GTK-Doc V1.15</div>
+</body>
+</html> \ No newline at end of file
diff --git a/sendto/docs/html/index.sgml b/sendto/docs/html/index.sgml
new file mode 100644
index 0000000..de59262
--- /dev/null
+++ b/sendto/docs/html/index.sgml
@@ -0,0 +1,14 @@
+<ONLINE href="http://library.mate.org/devel/caja-sendto/index.html">
+<ANCHOR id="caja-sendto-caja-sendto-plugin" href="caja-sendto/caja-sendto-caja-sendto-plugin.html">
+<ANCHOR id="caja-sendto-caja-sendto-plugin.stability-level" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#caja-sendto-caja-sendto-plugin.stability-level">
+<ANCHOR id="caja-sendto-caja-sendto-plugin.synopsis" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#caja-sendto-caja-sendto-plugin.synopsis">
+<ANCHOR id="caja-sendto-caja-sendto-plugin.description" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#caja-sendto-caja-sendto-plugin.description">
+<ANCHOR id="caja-sendto-caja-sendto-plugin.details" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#caja-sendto-caja-sendto-plugin.details">
+<ANCHOR id="NstPluginInfo" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#NstPluginInfo">
+<ANCHOR id="NstPlugin" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#NstPlugin">
+<ANCHOR id="NstPluginCapabilities" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#NstPluginCapabilities">
+<ANCHOR id="CAJA-CAPS-NONE:CAPS" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#CAJA-CAPS-NONE:CAPS">
+<ANCHOR id="CAJA-CAPS-SEND-DIRECTORIES:CAPS" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#CAJA-CAPS-SEND-DIRECTORIES:CAPS">
+<ANCHOR id="CAJA-CAPS-SEND-IMAGES:CAPS" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#CAJA-CAPS-SEND-IMAGES:CAPS">
+<ANCHOR id="NST-INIT-PLUGIN:CAPS" href="caja-sendto/caja-sendto-caja-sendto-plugin.html#NST-INIT-PLUGIN:CAPS">
+<ANCHOR id="annotation-glossterm-element-type" href="caja-sendto/annotation-glossary.html#annotation-glossterm-element-type">
diff --git a/sendto/docs/html/left.png b/sendto/docs/html/left.png
new file mode 100644
index 0000000..2d05b3d
--- /dev/null
+++ b/sendto/docs/html/left.png
Binary files differ
diff --git a/sendto/docs/html/right.png b/sendto/docs/html/right.png
new file mode 100644
index 0000000..92832e3
--- /dev/null
+++ b/sendto/docs/html/right.png
Binary files differ
diff --git a/sendto/docs/html/style.css b/sendto/docs/html/style.css
new file mode 100644
index 0000000..d544a2c
--- /dev/null
+++ b/sendto/docs/html/style.css
@@ -0,0 +1,265 @@
+.synopsis, .classsynopsis
+{
+ /* tango:aluminium 1/2 */
+ background: #eeeeec;
+ border: solid 1px #d3d7cf;
+ padding: 0.5em;
+}
+.programlisting
+{
+ /* tango:sky blue 0/1 */
+ background: #e6f3ff;
+ border: solid 1px #729fcf;
+ padding: 0.5em;
+}
+.variablelist
+{
+ padding: 4px;
+ margin-left: 3em;
+}
+.variablelist td:first-child
+{
+ vertical-align: top;
+}
+
+ sup a.footnote
+ {
+ position: relative;
+ top: 0em ! important;
+
+ }
+ /* this is needed so that the local anchors are displayed below the naviagtion */
+ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name]
+ {
+ position: relative;
+ padding-top:4.5em;
+ }
+ /* this seems to be a bug in the xsl style sheets when generating indexes */
+ div.index div.index
+ {
+ top: 0em;
+ }
+ /* make space for the fixed navigation bar and add space at the bottom so that
+ * link targets appear somewhat close to top
+ */
+ body
+ {
+ padding-top: 3.2em;
+ padding-bottom: 20em;
+ }
+ /* style and size the navigation bar */
+ table.navigation#top
+ {
+ position: fixed;
+ /* tango:scarlet red 0/1 */
+ background: #ffe6e6;
+ border: solid 1px #ef2929;
+ margin-top: 0;
+ margin-bottom: 0;
+ top: 0;
+ left: 0;
+ height: 3em;
+ z-index: 10;
+ }
+ .navigation a, .navigation a:visited
+ {
+ /* tango:scarlet red 3 */
+ color: #a40000;
+ }
+ .navigation a:hover
+ {
+ /* tango:scarlet red 1 */
+ color: #ef2929;
+ }
+ td.shortcuts
+ {
+ /* tango:scarlet red 1 */
+ color: #ef2929;
+ font-size: 80%;
+ white-space: nowrap;
+ }
+}
+ table.navigation {
+ visibility: collapse;
+ display: none;
+ }
+ div.titlepage table.navigation {
+ visibility: visible;
+ display: table;
+ /* tango:scarlet red 0/1 */
+ background: #ffe6e6;
+ border: solid 1px #ef2929;
+ margin-top: 0;
+ margin-bottom: 0;
+ top: 0;
+ left: 0;
+ height: 3em;
+ }
+}
+
+.navigation .title
+{
+ font-size: 200%;
+}
+
+div.gallery-float
+{
+ float: left;
+ padding: 10px;
+}
+div.gallery-float img
+{
+ border-style: none;
+}
+div.gallery-spacer
+{
+ clear: both;
+}
+
+a, a:visited
+{
+ text-decoration: none;
+ /* tango:sky blue 2 */
+ color: #3465a4;
+}
+a:hover
+{
+ text-decoration: underline;
+ /* tango:sky blue 1 */
+ color: #729fcf;
+}
+
+div.table table
+{
+ border-collapse: collapse;
+ border-spacing: 0px;
+ /* tango:aluminium 3 */
+ border: solid 1px #babdb6;
+}
+
+div.table table td, div.table table th
+{
+ /* tango:aluminium 3 */
+ border: solid 1px #babdb6;
+ padding: 3px;
+ vertical-align: top;
+}
+
+div.table table th
+{
+ /* tango:aluminium 2 */
+ background-color: #d3d7cf;
+}
+
+hr
+{
+ /* tango:aluminium 3 */
+ color: #babdb6;
+ background: #babdb6;
+ border: none 0px;
+ height: 1px;
+ clear: both;
+}
+
+.footer
+{
+ padding-top: 3.5em;
+ /* tango:aluminium 3 */
+ color: #babdb6;
+ text-align: center;
+ font-size: 80%;
+}
+
+.warning
+{
+ /* tango:orange 0/1 */
+ background: #ffeed9;
+ border-color: #ffb04f;
+}
+.note
+{
+ /* tango:chameleon 0/0.5 */
+ background: #d8ffb2;
+ border-color: #abf562;
+}
+.note, .warning
+{
+ padding: 0.5em;
+ border-width: 1px;
+ border-style: solid;
+}
+.note h3, .warning h3
+{
+ margin-top: 0.0em
+}
+.note p, .warning p
+{
+ margin-bottom: 0.0em
+}
+
+/* blob links */
+h2 .extralinks, h3 .extralinks
+{
+ float: right;
+ /* tango:aluminium 3 */
+ color: #babdb6;
+ font-size: 80%;
+ font-weight: normal;
+}
+
+.annotation
+{
+ /* tango:aluminium 5 */
+ color: #555753;
+ font-size: 80%;
+ font-weight: normal;
+}
+
+/* code listings */
+
+.listing_code .programlisting .cbracket { color: #a40000; } /* tango: scarlet red 3 */
+.listing_code .programlisting .comment { color: #a1a39d; } /* tango: aluminium 4 */
+.listing_code .programlisting .function { color: #000000; font-weight: bold; }
+.listing_code .programlisting .function a { color: #11326b; font-weight: bold; } /* tango: sky blue 4 */
+.listing_code .programlisting .keyword { color: #4e9a06; } /* tango: chameleon 3 */
+.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */
+.listing_code .programlisting .normal { color: #000000; }
+.listing_code .programlisting .number { color: #75507b; } /* tango: plum 2 */
+.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */
+.listing_code .programlisting .string { color: #c17d11; } /* tango: chocolate 2 */
+.listing_code .programlisting .type { color: #000000; }
+.listing_code .programlisting .type a { color: #11326b; } /* tango: sky blue 4 */
+.listing_code .programlisting .symbol { color: #ce5c00; } /* tango: orange 3 */
+
+.listing_frame {
+ /* tango:sky blue 1 */
+ border: solid 1px #729fcf;
+ padding: 0px;
+}
+
+.listing_lines, .listing_code {
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0.5em;
+}
+.listing_lines {
+ /* tango:sky blue 0.5 */
+ background: #a6c5e3;
+ /* tango:aluminium 6 */
+ color: #2e3436;
+}
+.listing_code {
+ /* tango:sky blue 0 */
+ background: #e6f3ff;
+}
+.listing_code .programlisting {
+ /* override from previous */
+ border: none 0px;
+ padding: 0px;
+}
+.listing_lines pre, .listing_code pre {
+ margin: 0px;
+}
+
diff --git a/sendto/docs/html/up.png b/sendto/docs/html/up.png
new file mode 100644
index 0000000..85b3e2a
--- /dev/null
+++ b/sendto/docs/html/up.png
Binary files differ
diff --git a/sendto/docs/tmpl/caja-sendto-mimetype.sgml b/sendto/docs/tmpl/caja-sendto-mimetype.sgml
new file mode 100644
index 0000000..e54fb59
--- /dev/null
+++ b/sendto/docs/tmpl/caja-sendto-mimetype.sgml
@@ -0,0 +1,33 @@
+<!-- ##### SECTION Title ##### -->
+caja-sendto-mimetype
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### FUNCTION nst_title_from_mime_types ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/sendto/docs/tmpl/caja-sendto-packer.sgml b/sendto/docs/tmpl/caja-sendto-packer.sgml
new file mode 100644
index 0000000..08dc602
--- /dev/null
+++ b/sendto/docs/tmpl/caja-sendto-packer.sgml
@@ -0,0 +1,112 @@
+<!-- ##### SECTION Title ##### -->
+NstPackWidget
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### TYPEDEF NstPackWidgetPrivate ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### STRUCT NstPackWidget ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG NstPackWidget:can-send ##### -->
+<para>
+
+</para>
+
+<!-- ##### STRUCT NstPackWidgetClass ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_new ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION nst_pack_widget_pack_files ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION nst_pack_widget_set_from_names ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION nst_pack_widget_set_enabled ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION nst_pack_widget_get_enabled ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION nst_pack_widget_set_force_enabled ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION nst_pack_widget_get_force_enabled ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/sendto/docs/tmpl/caja-sendto-plugin.sgml b/sendto/docs/tmpl/caja-sendto-plugin.sgml
new file mode 100644
index 0000000..89ae0d7
--- /dev/null
+++ b/sendto/docs/tmpl/caja-sendto-plugin.sgml
@@ -0,0 +1,63 @@
+<!-- ##### SECTION Title ##### -->
+caja-sendto-plugin
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### STRUCT NstPluginInfo ##### -->
+<para>
+
+</para>
+
[email protected]_contacts_widget:
[email protected]_destination:
+
+<!-- ##### STRUCT NstPlugin ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ENUM NstPluginCapabilities ##### -->
+<para>
+
+</para>
+
[email protected]_CAPS_NONE:
[email protected]_CAPS_SEND_DIRECTORIES:
[email protected]_CAPS_SEND_IMAGES:
+
+<!-- ##### MACRO NST_INIT_PLUGIN ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/sendto/docs/tmpl/caja-sendto-unused.sgml b/sendto/docs/tmpl/caja-sendto-unused.sgml
new file mode 100644
index 0000000..c275685
--- /dev/null
+++ b/sendto/docs/tmpl/caja-sendto-unused.sgml
@@ -0,0 +1,368 @@
+<!-- ##### SECTION ./tmpl/caja-sendto-mimetype.sgml:Image ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-mimetype.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-mimetype.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-mimetype.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-mimetype.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-mimetype.sgml:Title ##### -->
+caja-sendto-mimetype
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-packer.sgml:Image ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-packer.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-packer.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-packer.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-packer.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/caja-sendto-packer.sgml:Title ##### -->
+NstPackWidget
+
+
+<!-- ##### SECTION ./tmpl/nst-common.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/nst-common.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/nst-common.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/nst-common.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/nst-common.sgml:Title ##### -->
+nst-common
+
+
+<!-- ##### SECTION ./tmpl/nst-plugin-marshal.sgml:Image ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/nst-plugin-marshal.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/nst-plugin-marshal.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/nst-plugin-marshal.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/nst-plugin-marshal.sgml:Stability_Level ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/nst-plugin-marshal.sgml:Title ##### -->
+nst-plugin-marshal
+
+
+<!-- ##### MACRO CAJA_PLUGIN_REGISTER ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO CAJA_SENDTO_PLUGIN_IFACE ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO NST_TYPE_SENDTO_SEND_STATUS ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### STRUCT CajaSendtoPlugin ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SIGNAL CajaSendtoPlugin::add-widget ##### -->
+<para>
+
+</para>
+
[email protected]: the object which received the signal.
+
+<!-- ##### SIGNAL CajaSendtoPlugin::can-send ##### -->
+<para>
+
+</para>
+
[email protected]: the object which received the signal.
+
+<!-- ##### STRUCT CajaSendtoPluginInterface ##### -->
+<para>
+
+</para>
+
[email protected]_mime_types:
+
+<!-- ##### ENUM CajaSendtoSendStatus ##### -->
+<para>
+
+</para>
+
[email protected]_SEND_STATUS_SUCCESS:
[email protected]_SEND_STATUS_SUCCESS_DONE:
[email protected]_SEND_STATUS_FAILED:
+
+<!-- ##### STRUCT NstPackWidget ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG NstPackWidget:can-send ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### STRUCT NstPackWidgetClass ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### TYPEDEF NstPackWidgetPrivate ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO SOEXT ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO SOEXT_LEN ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION copy_files_to ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION caja_sendto_plugin_get_object ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION caja_sendto_plugin_get_widget ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION caja_sendto_plugin_send_files ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION caja_sendto_plugin_send_files_finish ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION caja_sendto_plugin_supports_mime_types ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION caja_sendto_send_status_get_type ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_get_enabled ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_get_force_enabled ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_new ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_pack_files ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_set_enabled ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_set_force_enabled ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_pack_widget_set_from_names ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION nst_plugin_marshal_VOID__STRING_BOOLEAN ##### -->
+<para>
+
+</para>
+
[email protected]_param_values:
[email protected]ram_values:
+
+<!-- ##### FUNCTION nst_plugin_marshal_VOID__STRING_STRING_STRING_OBJECT ##### -->
+<para>
+
+</para>
+
[email protected]_param_values:
+
+<!-- ##### FUNCTION nst_title_from_mime_types ##### -->
+<para>
+
+</para>
+
+
diff --git a/sendto/docs/tmpl/nst-common.sgml b/sendto/docs/tmpl/nst-common.sgml
new file mode 100644
index 0000000..295aa9a
--- /dev/null
+++ b/sendto/docs/tmpl/nst-common.sgml
@@ -0,0 +1,31 @@
+<!-- ##### SECTION Title ##### -->
+nst-common
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION copy_files_to ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/sendto/docs/tmpl/nst-enum-types.sgml b/sendto/docs/tmpl/nst-enum-types.sgml
new file mode 100644
index 0000000..abba0dc
--- /dev/null
+++ b/sendto/docs/tmpl/nst-enum-types.sgml
@@ -0,0 +1,38 @@
+<!-- ##### SECTION Title ##### -->
+nst-enum-types
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### FUNCTION nst_plugin_capabilities_get_type ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO NST_TYPE_PLUGIN_CAPABILITIES ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/sendto/docs/tmpl/nst-plugin-marshal.sgml b/sendto/docs/tmpl/nst-plugin-marshal.sgml
new file mode 100644
index 0000000..9731804
--- /dev/null
+++ b/sendto/docs/tmpl/nst-plugin-marshal.sgml
@@ -0,0 +1,50 @@
+<!-- ##### SECTION Title ##### -->
+nst-plugin-marshal
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### SECTION Image ##### -->
+
+
+<!-- ##### FUNCTION nst_plugin_marshal_VOID__STRING_STRING_STRING_OBJECT ##### -->
+<para>
+
+</para>
+
[email protected]_param_values:
+
+
+<!-- ##### FUNCTION nst_plugin_marshal_VOID__STRING_BOOLEAN ##### -->
+<para>
+
+</para>
+
[email protected]_param_values:
+
+
diff --git a/sendto/docs/version.xml.in b/sendto/docs/version.xml.in
new file mode 100644
index 0000000..d78bda9
--- /dev/null
+++ b/sendto/docs/version.xml.in
@@ -0,0 +1 @@
diff --git a/sendto/org.mate.Caja.Sendto.gschema.xml.in b/sendto/org.mate.Caja.Sendto.gschema.xml.in
new file mode 100644
index 0000000..cc48a5d
--- /dev/null
+++ b/sendto/org.mate.Caja.Sendto.gschema.xml.in
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+ <schema id="org.mate.Caja.Sendto" path="/org/mate/caja-sendto/" gettext-domain="caja-sendto">
+ <key name="last-medium" type="s">
+ <default>''</default>
+ <summary>Last plugin used to send</summary>
+ <description>
+ Used to store which plugin was used the last time
+ files were sent using caja-sendto.
+ </description>
+ </key>
+ <key name="last-compress" type="i">
+ <default>0</default>
+ <summary>Last type of archive used</summary>
+ <description>
+ Used to store which type of archive was used the last time
+ (0: zip, 1: tar.gz, 2: tar.bz2).
+ </description>
+ </key>
+ </schema>
+</schemalist>
diff --git a/sendto/plugins/Makefile.am b/sendto/plugins/Makefile.am
new file mode 100644
index 0000000..10097e8
--- /dev/null
+++ b/sendto/plugins/Makefile.am
@@ -0,0 +1,16 @@
+SUBDIRS = . \
+ caja-burn \
+ emailclient \
+ gajim \
+ pidgin \
+ removable-devices \
+ upnp
+
+NST_COMMON_SOURCES = nst-common.c nst-common.h
+
+noinst_LTLIBRARIES = libnstcommon.la
+libnstcommon_la_SOURCES = $(NST_COMMON_SOURCES)
+libnstcommon_la_CFLAGS = $(SENDTO_CFLAGS)
+libnstcommon_la_LIBADD = $(SENDTO_LIBS)
+
+EXTRA_DIST = $(NST_COMMON_SOURCES)
diff --git a/sendto/plugins/caja-burn/Makefile.am b/sendto/plugins/caja-burn/Makefile.am
new file mode 100644
index 0000000..50c309b
--- /dev/null
+++ b/sendto/plugins/caja-burn/Makefile.am
@@ -0,0 +1,19 @@
+plugindir = $(libdir)/caja-sendto/plugins
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DICONDIR=\"$(icondir)\" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
+ -I$(top_srcdir)/sendto \
+ -I$(top_builddir) \
+ -I$(srcdir)/../ \
+ $(SENDTO_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(DISABLE_DEPRECATED)
+
+plugin_LTLIBRARIES = libnstburn.la
+
+libnstburn_la_SOURCES = caja-burn.c
+libnstburn_la_LDFLAGS = -module -avoid-version
+libnstburn_la_LIBADD = $(SENDTO_LIBS) $(builddir)/../libnstcommon.la
+
diff --git a/sendto/plugins/caja-burn/caja-burn.c b/sendto/plugins/caja-burn/caja-burn.c
new file mode 100644
index 0000000..07d2e41
--- /dev/null
+++ b/sendto/plugins/caja-burn/caja-burn.c
@@ -0,0 +1,189 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Copyright (C) 2008 Jader Henrique da Silva
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Author: Jader Henrique da Silva <[email protected]>
+ */
+
+#include "config.h"
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include "nst-common.h"
+#include "caja-sendto-plugin.h"
+
+enum {
+ COL_PIXBUF,
+ COL_LABEL,
+ NUM_COLS,
+};
+
+#define COMBOBOX_OPTION_NEW_DVD 0
+#define COMBOBOX_OPTION_EXISTING_DVD 1
+
+static GFile *burn = NULL;
+
+static
+gboolean init (NstPlugin *plugin)
+{
+ GtkIconTheme *it;
+ char *cmd;
+
+ g_print ("Init caja burn plugin\n");
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ it = gtk_icon_theme_get_default ();
+ gtk_icon_theme_append_search_path (it, DATADIR "/brasero/icons");
+
+ cmd = g_find_program_in_path ("brasero");
+ if (cmd == NULL)
+ return FALSE;
+ g_free (cmd);
+
+ burn = g_file_new_for_uri ("burn:/");
+
+ return TRUE;
+}
+
+static
+GtkWidget* get_contacts_widget (NstPlugin *plugin)
+{
+ GtkWidget *widget;
+ GtkCellRenderer *renderer;
+ GtkListStore *store;
+ GtkTreeModel *model;
+ GFileEnumerator *fenum;
+ GFileInfo *file_info = NULL;
+ int selection = COMBOBOX_OPTION_NEW_DVD;
+
+ fenum = g_file_enumerate_children (burn,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+
+ if (fenum != NULL) {
+ file_info = g_file_enumerator_next_file (fenum, NULL, NULL);
+ g_object_unref (fenum);
+ }
+
+ store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
+
+ gtk_list_store_insert_with_values (store, NULL,
+ INT_MAX,
+ COL_PIXBUF, "media-optical-blank",
+ COL_LABEL, _("New CD/DVD"),
+ -1);
+
+ if (file_info != NULL) {
+ gtk_list_store_insert_with_values (store, NULL,
+ INT_MAX,
+ COL_PIXBUF, "media-optical-data-new",
+ COL_LABEL, _("Existing CD/DVD"),
+ -1);
+ g_object_unref (file_info);
+ selection = COMBOBOX_OPTION_EXISTING_DVD;
+ }
+
+ model = GTK_TREE_MODEL (store);
+ widget = gtk_combo_box_new_with_model (model);
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget),
+ renderer,
+ FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget),
+ renderer,
+ "icon-name", COL_PIXBUF,
+ NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget),
+ renderer,
+ TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget),
+ renderer,
+ "text", COL_LABEL,
+ NULL);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), selection);
+
+ return widget;
+}
+
+static
+gboolean send_files (NstPlugin *plugin,
+ GtkWidget *burntype_widget,
+ GList *file_list)
+{
+ GFileEnumerator *fenum;
+ GFileInfo *file_info;
+ GFile *child;
+
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (burntype_widget)) == COMBOBOX_OPTION_NEW_DVD) {
+ fenum = g_file_enumerate_children (burn,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+
+ if (fenum != NULL) {
+ while ((file_info = g_file_enumerator_next_file (fenum, NULL, NULL)) != NULL) {
+ child = g_file_get_child (burn,
+ g_file_info_get_name(file_info));
+
+ g_object_unref (file_info);
+ g_file_delete (child, NULL, NULL);
+ g_object_unref (child);
+ }
+ g_object_unref (fenum);
+ }
+ }
+
+ copy_files_to (file_list, burn);
+
+ gtk_show_uri (NULL, "burn:///", GDK_CURRENT_TIME, NULL);
+
+ return TRUE;
+}
+
+static
+gboolean destroy (NstPlugin *plugin){
+
+ g_object_unref (burn);
+ burn = NULL;
+ return TRUE;
+
+}
+
+static
+NstPluginInfo plugin_info = {
+ "brasero",
+ "caja-burn",
+ N_("CD/DVD Creator"),
+ NULL,
+ CAJA_CAPS_SEND_DIRECTORIES,
+ init,
+ get_contacts_widget,
+ NULL,
+ send_files,
+ destroy
+};
+
+NST_INIT_PLUGIN (plugin_info)
+
diff --git a/sendto/plugins/emailclient/Makefile.am b/sendto/plugins/emailclient/Makefile.am
new file mode 100644
index 0000000..31ba40e
--- /dev/null
+++ b/sendto/plugins/emailclient/Makefile.am
@@ -0,0 +1,17 @@
+plugindir = $(libdir)/caja-sendto/plugins
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DICONDIR=\"$(icondir)\" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
+ -I$(top_srcdir)/sendto \
+ -I$(top_builddir) \
+ $(SENDTO_CFLAGS) \
+ $(DISABLE_DEPRECATED) \
+ $(WARN_CFLAGS)
+
+plugin_LTLIBRARIES = libnstemailclient.la
+
+libnstemailclient_la_SOURCES = emailclient.c
+libnstemailclient_la_LDFLAGS = -module -avoid-version
+libnstemailclient_la_LIBADD = $(SENDTO_LIBS)
diff --git a/sendto/plugins/emailclient/emailclient.c b/sendto/plugins/emailclient/emailclient.c
new file mode 100644
index 0000000..14cb998
--- /dev/null
+++ b/sendto/plugins/emailclient/emailclient.c
@@ -0,0 +1,274 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Copyright (C) 2004 Roberto Majadas <[email protected]>
+ * Copyright (C) 2012 Stefano Karapetsas <[email protected]>
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Authors: Roberto Majadas <[email protected]>
+ * Stefano Karapetsas <[email protected]>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include "caja-sendto-plugin.h"
+#include <gio/gio.h>
+
+typedef enum {
+ MAILER_UNKNOWN,
+ MAILER_EVO,
+ MAILER_BALSA,
+ MAILER_SYLPHEED,
+ MAILER_THUNDERBIRD,
+} MailerType;
+
+static char *mail_cmd = NULL;
+static MailerType type = MAILER_UNKNOWN;
+
+static char *
+get_evo_cmd (void)
+{
+ char *tmp = NULL;
+ char *retval;
+ char *cmds[] = {"evolution",
+ "evolution-2.0",
+ "evolution-2.2",
+ "evolution-2.4",
+ "evolution-2.6",
+ "evolution-2.8", /* for the future */
+ "evolution-3.0", /* but how far to go ? */
+ NULL};
+ guint i;
+
+
+ for (i = 0; cmds[i] != NULL; i++) {
+ tmp = g_find_program_in_path (cmds[i]);
+ if (tmp != NULL)
+ break;
+ }
+
+ if (tmp == NULL)
+ return NULL;
+
+ retval = g_strdup_printf ("%s --component=mail %%s", tmp);
+ g_free (tmp);
+ return retval;
+}
+
+static gboolean
+init (NstPlugin *plugin)
+{
+ GAppInfo *app_info = NULL;
+
+ g_print ("Init email client plugin\n");
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ app_info = g_app_info_get_default_for_uri_scheme ("mailto");
+ if (app_info) {
+ mail_cmd = g_strdup(g_app_info_get_executable (app_info));
+ g_object_unref (app_info);
+ }
+
+ if (mail_cmd == NULL || *mail_cmd == '\0') {
+ g_free (mail_cmd);
+ mail_cmd = get_evo_cmd ();
+ type = MAILER_EVO;
+ } else {
+ /* Find what the default mailer is */
+ if (strstr (mail_cmd, "balsa"))
+ type = MAILER_BALSA;
+ else if (strstr (mail_cmd, "thunder") || strstr (mail_cmd, "seamonkey")) {
+ char **strv;
+
+ type = MAILER_THUNDERBIRD;
+
+ /* Thunderbird sucks, see
+ * https://bugzilla.gnome.org/show_bug.cgi?id=614222 */
+ strv = g_strsplit (mail_cmd, " ", -1);
+ g_free (mail_cmd);
+ mail_cmd = g_strdup_printf ("%s %%s", strv[0]);
+ g_strfreev (strv);
+ } else if (strstr (mail_cmd, "sylpheed") || strstr (mail_cmd, "claws"))
+ type = MAILER_SYLPHEED;
+ else if (strstr (mail_cmd, "anjal"))
+ type = MAILER_EVO;
+ }
+
+ if (mail_cmd == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static
+GtkWidget* get_contacts_widget (NstPlugin *plugin)
+{
+ GtkWidget *entry;
+
+ // TODO: add an email address format check
+ entry = gtk_entry_new();
+
+ return entry;
+}
+
+static void
+get_evo_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+{
+ GList *l;
+
+ g_string_append (mailto, "mailto:");
+
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+ if (text != NULL && *text != '\0')
+ g_string_append_printf (mailto, "\"%s\"", text);
+ else
+ g_string_append (mailto, "\"\"");
+
+ g_string_append_printf (mailto,"?attach=\"%s\"", (char *)file_list->data);
+ for (l = file_list->next ; l; l=l->next){
+ g_string_append_printf (mailto,"&attach=\"%s\"", (char *)l->data);
+ }
+}
+
+static void
+get_balsa_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+{
+ GList *l;
+
+ if (strstr (mail_cmd, " -m ") == NULL && strstr (mail_cmd, " --compose=") == NULL)
+ g_string_append (mailto, " --compose=");
+
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+ if (text != NULL && *text != '\0')
+ g_string_append_printf (mailto, "\"%s\"", text);
+ else
+ g_string_append (mailto, "\"\"");
+
+ g_string_append_printf (mailto," --attach=\"%s\"", (char *)file_list->data);
+ for (l = file_list->next ; l; l=l->next){
+ g_string_append_printf (mailto," --attach=\"%s\"", (char *)l->data);
+ }
+}
+
+static void
+get_thunderbird_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+{
+ GList *l;
+
+ g_string_append (mailto, "-compose \"");
+
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+ if (text != NULL && *text != '\0')
+ g_string_append_printf (mailto, "to='%s',", text);
+
+ g_string_append_printf (mailto,"attachment='%s", (char *)file_list->data);
+ for (l = file_list->next ; l; l=l->next){
+ g_string_append_printf (mailto,",%s", (char *)l->data);
+ }
+ g_string_append (mailto, "'\"");
+}
+
+static void
+get_sylpheed_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+{
+ GList *l;
+
+ g_string_append (mailto, "--compose ");
+
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+ if (text != NULL && *text != '\0')
+ g_string_append_printf (mailto, "\"%s\" ", text);
+ else
+ g_string_append (mailto, "\"\"");
+
+ g_string_append_printf (mailto,"--attach \"%s\"", (char *)file_list->data);
+ for (l = file_list->next ; l; l=l->next){
+ g_string_append_printf (mailto," \"%s\"", (char *)l->data);
+ }
+}
+
+static gboolean
+send_files (NstPlugin *plugin,
+ GtkWidget *contact_widget,
+ GList *file_list)
+{
+ gchar *cmd;
+ GString *mailto;
+
+ mailto = g_string_new ("");
+ switch (type) {
+ case MAILER_BALSA:
+ get_balsa_mailto (contact_widget, mailto, file_list);
+ break;
+ case MAILER_SYLPHEED:
+ get_sylpheed_mailto (contact_widget, mailto, file_list);
+ break;
+ case MAILER_THUNDERBIRD:
+ get_thunderbird_mailto (contact_widget, mailto, file_list);
+ break;
+ case MAILER_EVO:
+ default:
+ get_evo_mailto (contact_widget, mailto, file_list);
+ }
+
+ cmd = g_strdup_printf (mail_cmd, mailto->str);
+ g_string_free (mailto, TRUE);
+
+ g_message ("Mailer type: %d", type);
+ g_message ("Command: %s", cmd);
+
+ g_spawn_command_line_async (cmd, NULL);
+ g_free (cmd);
+
+ return TRUE;
+}
+
+static
+gboolean destroy (NstPlugin *plugin){
+ g_free (mail_cmd);
+ mail_cmd = NULL;
+ return TRUE;
+}
+
+static
+NstPluginInfo plugin_info = {
+ "emblem-mail",
+ "emailclient",
+ N_("Email"),
+ NULL,
+ CAJA_CAPS_NONE,
+ init,
+ get_contacts_widget,
+ NULL,
+ send_files,
+ destroy
+};
+
+NST_INIT_PLUGIN (plugin_info)
+
diff --git a/sendto/plugins/gajim/Makefile.am b/sendto/plugins/gajim/Makefile.am
new file mode 100644
index 0000000..5acd5b0
--- /dev/null
+++ b/sendto/plugins/gajim/Makefile.am
@@ -0,0 +1,18 @@
+plugindir = $(libdir)/caja-sendto/plugins
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DICONDIR=\"$(icondir)\" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
+ -I$(top_srcdir)/sendto \
+ -I$(top_builddir) \
+ $(SENDTO_CFLAGS) \
+ $(DISABLE_DEPRECATED) \
+ $(WARN_CFLAGS)
+
+plugin_LTLIBRARIES = libnstgajim.la
+
+libnstgajim_la_SOURCES = gajim.c
+libnstgajim_la_LDFLAGS = -module -avoid-version
+libnstgajim_la_LIBADD = $(SENDTO_LIBS)
+
diff --git a/sendto/plugins/gajim/gajim.c b/sendto/plugins/gajim/gajim.c
new file mode 100644
index 0000000..bb00d1d
--- /dev/null
+++ b/sendto/plugins/gajim/gajim.c
@@ -0,0 +1,516 @@
+/*
+ * gajim.c
+ * gajim plugin for caja-sendto
+ *
+ * Copyright (C) 2006 Dimitur Kirov
+ * 2006 Roberto Majadas <[email protected]>
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include "caja-sendto-plugin.h"
+
+#define OBJ_PATH "/org/gajim/dbus/RemoteObject"
+#define INTERFACE "org.gajim.dbus.RemoteInterface"
+#define SERVICE "org.gajim.dbus"
+
+const gchar *COMPLETION_PROPS[] = {"name", "jid"};
+/* list of contacts, which are not offline */
+static GHashTable *jid_table = NULL;
+static gchar *iconset;
+
+
+DBusGProxy *proxy = NULL;
+
+/*
+ * contact cb, gets property from contact dict
+ * and put online contacts to jid_table
+ */
+static void
+_foreach_contact(gpointer contact, gpointer user_data)
+{
+ const gchar *show;
+
+ GValue *value;
+ GHashTable *contact_table;
+
+ /* holds contact props of already exisiting jid/nick */
+ GHashTable *existing_contact;
+
+ /* name of the contact in completion list
+ it may be jid, nick, jid (account), or nick(account) */
+ GString *contact_str;
+
+ gchar *jid;
+ gchar *account;
+ gint i;
+
+ if (contact == NULL) {
+ g_warning("Null contact in the list");
+ return;
+ }
+ contact_table = (GHashTable *) contact;
+ account = (gchar *) user_data;
+
+ value = g_hash_table_lookup(contact_table, "show");
+ if (value == NULL || !G_VALUE_HOLDS_STRING(value)) {
+ g_warning("String expected (contact - show)");
+ g_hash_table_destroy(contact_table);
+ return;
+ }
+ show = g_value_get_string ((GValue *)value);
+ if(g_str_equal(show, "offline") || g_str_equal(show, "error")) {
+ g_hash_table_destroy(contact_table);
+ return;
+ }
+ /* remove unneeded item with key resource and add account
+ to contact properties */
+ g_hash_table_insert(contact_table, "account", account);
+ g_hash_table_remove(contact_table, "resource");
+
+ /* add nick the same way as jid */
+ for(i=0;i<2;i++) {
+ value = g_hash_table_lookup(contact_table, COMPLETION_PROPS[i]);
+ if(value == NULL || !G_VALUE_HOLDS_STRING(value)) {
+ g_warning("String expected (contact - name)");
+ return;
+ }
+ jid = g_value_dup_string((GValue *)value);
+ existing_contact = g_hash_table_lookup(jid_table, jid);
+ if(existing_contact) {
+ /* add existing contact as nick (account) */
+ contact_str = g_string_new(jid);
+ g_string_append(contact_str, " (");
+ g_string_append(contact_str,
+ g_hash_table_lookup(existing_contact, "account"));
+ g_string_append(contact_str, ")");
+ g_hash_table_insert(jid_table, contact_str->str,
+ existing_contact);
+ g_string_free(contact_str, FALSE);
+
+ /* add current contact as nick (account) */
+ contact_str = g_string_new(jid);
+ g_string_append(contact_str, " (");
+ g_string_append(contact_str,
+ g_hash_table_lookup(contact_table, "account"));
+ g_string_append(contact_str, ")");
+ g_hash_table_insert(jid_table, contact_str->str,
+ contact_table);
+ g_string_free(contact_str, FALSE);
+ }
+ else {
+ g_hash_table_insert(jid_table, jid, contact_table);
+ }
+ }
+
+}
+
+/*
+ * connect to session bus, onsuccess return TRUE
+ */
+static gboolean
+init_dbus (void)
+{
+ DBusGConnection *connection;
+ GError *error;
+ gchar **accounts;
+
+ error = NULL;
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if(error != NULL) {
+ g_warning("[Gajim] unable to get session bus, error was:\n %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
+ proxy = dbus_g_proxy_new_for_name(connection,
+ SERVICE,
+ OBJ_PATH,
+ INTERFACE);
+ dbus_g_connection_unref(connection);
+ if (proxy == NULL){
+ return FALSE;
+ }
+
+ error = NULL;
+ if (!dbus_g_proxy_call (proxy, "list_accounts", &error, G_TYPE_INVALID,
+ G_TYPE_STRV, &accounts, G_TYPE_INVALID))
+ {
+ g_object_unref(proxy);
+ g_error_free(error);
+ return FALSE;
+ }
+ g_strfreev(accounts);
+ return TRUE;
+}
+
+/*
+ * Print appropriate warnings when dbus raised error
+ * on queries
+ */
+static void
+_handle_dbus_exception (GError *error, gboolean empty_list_messages)
+{
+ if (error == NULL) {
+ g_warning("[Gajim] unable to parse result");
+ return;
+ }
+ else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+ g_warning ("[Gajim] caught remote method exception %s: %s",
+ dbus_g_error_get_name (error),
+ error->message);
+ }
+ else if(empty_list_messages) {
+ /* empty list and error goes here */
+ g_warning ("[Gajim] empty result set: %d %d %s\n", error->domain,
+ error->code, error->message);
+ }
+ g_error_free (error);
+}
+
+/*
+ * query object, about the contact list for each account
+ * and fill all available contacts in the contacts table
+ */
+static gboolean
+_get_contacts (void)
+{
+ GError *error;
+ GSList *contacts_list;
+ GHashTable *prefs_map;
+ gchar **accounts;
+ gchar **account_iter;
+ gchar *account;
+
+ error = NULL;
+
+ if (proxy == NULL) {
+ g_warning("[Gajim] unable to connect to session bus");
+ return FALSE;
+ }
+ /* get gajim prefs and lookup for iconset */
+ if (!dbus_g_proxy_call(proxy, "prefs_list", &error, G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING),
+ &prefs_map, G_TYPE_INVALID))
+ {
+ _handle_dbus_exception(error, TRUE);
+ return FALSE;
+ }
+ gpointer iconset_ptr = g_hash_table_lookup(prefs_map, "iconset");
+ if (iconset_ptr != NULL) {
+ iconset = g_strdup((gchar *)iconset_ptr);
+ } else {
+ g_warning("[Gajim] unable to get prefs value for iconset");
+ return FALSE;
+ }
+ g_hash_table_destroy(prefs_map);
+ /* END get gajim prefs */
+ error= NULL;
+ if (!dbus_g_proxy_call (proxy, "list_accounts", &error, G_TYPE_INVALID,
+ G_TYPE_STRV,
+ &accounts, G_TYPE_INVALID))
+ {
+ _handle_dbus_exception(error, TRUE);
+ return FALSE;
+ }
+ for(account_iter = accounts; *account_iter ; account_iter++) {
+ account = g_strdup(*account_iter);
+ error = NULL;
+ /* query gajim remote object and put results in 'contacts_list' */
+ if (!dbus_g_proxy_call (proxy, "list_contacts", &error,
+ G_TYPE_STRING, account, /* call arguments */
+ G_TYPE_INVALID, /* delimiter */
+ /* return value is collection of maps */
+ dbus_g_type_get_collection ("GSList",
+ dbus_g_type_get_map ("GHashTable",
+ G_TYPE_STRING, G_TYPE_VALUE)),
+ &contacts_list, G_TYPE_INVALID))
+ {
+ _handle_dbus_exception(error, FALSE);
+ error = NULL;
+ continue;
+ }
+ g_slist_foreach (contacts_list, _foreach_contact, account);
+ g_slist_free(contacts_list);
+ }
+ g_strfreev (accounts);
+ return TRUE;
+}
+
+static gboolean
+init (NstPlugin *plugin)
+{
+ g_print ("Init gajim plugin\n");
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ /* connect to gajim dbus service */
+ jid_table = g_hash_table_new (g_str_hash, g_str_equal);
+ if (!init_dbus()) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+static void
+_set_pixbuf_from_status (const gchar *show, GdkPixbuf **pixbuf)
+{
+ GString *pixbuf_path;
+ GError *error;
+
+ pixbuf_path = g_string_new(GAJIM_SHARE_DIR);
+ g_string_append_c(pixbuf_path, '/');
+ g_string_append(pixbuf_path, "data");
+ g_string_append_c(pixbuf_path, '/');
+ g_string_append(pixbuf_path, "iconsets");
+ g_string_append_c(pixbuf_path, '/');
+ g_string_append(pixbuf_path, iconset);
+ g_string_append_c(pixbuf_path, '/');
+ g_string_append(pixbuf_path, "16x16");
+ g_string_append_c(pixbuf_path, '/');
+ g_string_append(pixbuf_path, show);
+ g_string_append(pixbuf_path, ".png");
+ if(g_file_test(pixbuf_path->str, G_FILE_TEST_EXISTS) &&
+ g_file_test(pixbuf_path->str, G_FILE_TEST_IS_REGULAR)) {
+ error = NULL;
+ *pixbuf = gdk_pixbuf_new_from_file(pixbuf_path->str, &error);
+ if(error != NULL) {
+ g_error_free(error);
+ }
+ }
+ g_string_free(pixbuf_path, FALSE);
+}
+
+static void
+_add_contact_to_model(gpointer key, gpointer value, gpointer user_data)
+{
+ GtkTreeIter *iter;
+ GtkListStore *store;
+ GdkPixbuf *pixbuf;
+ GValue *val;
+ GHashTable *contact_props;
+ const gchar *show;
+
+ contact_props = (GHashTable *) value;
+ pixbuf = NULL;
+ val = g_hash_table_lookup(contact_props, "show");
+ if (value == NULL || !G_VALUE_HOLDS_STRING(val)) {
+ g_warning("String expected (contact - show)");
+ pixbuf = NULL;
+ } else {
+ show = g_value_get_string ((GValue *)val);
+ _set_pixbuf_from_status(show, &pixbuf);
+ }
+
+ store = (GtkListStore *) user_data;
+ iter = g_malloc (sizeof(GtkTreeIter));
+ gtk_list_store_append (store, iter);
+ gtk_list_store_set (store, iter, 0, pixbuf, 1, key, -1);
+ g_free (iter);
+}
+
+/*
+ * put gajim contacts to jid_list
+ * filtering only these which are connected
+ */
+static gboolean
+add_gajim_contacts_to_model (GtkListStore *store)
+{
+ if(!_get_contacts()) {
+ return FALSE;
+ }
+ if(g_hash_table_size(jid_table) == 0) {
+ return FALSE;
+ }
+ g_hash_table_foreach(jid_table, _add_contact_to_model, store);
+ return TRUE;
+}
+
+/*
+ * fill completion model for the entry, using list of
+ * available gajim contacts
+ */
+static GtkWidget *
+get_contacts_widget (NstPlugin *plugin)
+{
+ GtkWidget *entry;
+ GtkEntryCompletion *completion;
+ GtkListStore *store;
+ GtkCellRenderer *renderer;
+ GtkTreeModel *completion_model;
+
+ entry = gtk_entry_new ();
+ completion = gtk_entry_completion_new ();
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
+ renderer,
+ FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), renderer,
+ "pixbuf", 0, NULL);
+
+
+ store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+ if(!add_gajim_contacts_to_model (store)) {
+ gtk_widget_set_sensitive(entry, FALSE);
+ }
+ completion_model = GTK_TREE_MODEL (store);
+ gtk_entry_completion_set_model (completion, completion_model);
+ gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+ gtk_entry_completion_set_text_column (completion, 1);
+ g_object_unref (completion_model);
+ g_object_unref (completion);
+ return entry;
+}
+
+static void
+show_error (const gchar *title, const gchar *message)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new_with_markup(NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE, NULL);
+ gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
+ g_markup_printf_escaped("<b>%s</b>\n\n%s", title, message));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+}
+
+static gboolean
+send_files (NstPlugin *plugin,
+ GtkWidget *contact_widget,
+ GList *file_list)
+{
+ GError *error;
+ GValue *value;
+ GList *file_iter;
+ GHashTable *contact_props;
+
+ gchar *send_to;
+ gchar *jid;
+ gchar *account;
+ gchar *file_path;
+
+ if(proxy == NULL) {
+ show_error(_("Unable to send file"),
+ _("There is no connection to gajim remote service."));
+ return FALSE;
+ }
+ send_to = (gchar *) gtk_entry_get_text (GTK_ENTRY(contact_widget));
+ g_debug("[Gajim] sending to: %s", send_to);
+ if (strlen (send_to) != 0){
+ contact_props = g_hash_table_lookup (jid_table, send_to);
+ if(contact_props == NULL) {
+ jid = send_to;
+ account = NULL;
+ }
+ else {
+ value = g_hash_table_lookup(contact_props, "jid");
+ if(value == NULL || !G_VALUE_HOLDS_STRING(value)) {
+ g_warning("[Gajim] string expected (contact - jid)");
+ return FALSE;
+ }
+
+ jid = g_value_dup_string((GValue *)value);
+ account = g_hash_table_lookup(contact_props, "account");
+ }
+ }
+ else {
+ g_warning("[Gajim] missing recipient");
+ show_error(_("Sending file failed"),
+ _("Recipient is missing."));
+ return FALSE;
+ }
+
+ error= NULL;
+ for(file_iter = file_list; file_iter != NULL; file_iter = file_iter->next) {
+ char *uri = file_iter->data;
+
+ g_debug("[Gajim] file: %s", uri);
+ error= NULL;
+ file_path = g_filename_from_uri(uri, NULL, &error);
+ if(error != NULL) {
+ g_warning("%d Unable to convert URI `%s' to absolute file path",
+ error->code, uri);
+ g_error_free(error);
+ continue;
+ }
+
+ g_debug("[Gajim] file: %s", file_path);
+ if(account) {
+ dbus_g_proxy_call (proxy, "send_file", &error,
+ G_TYPE_STRING, file_path,
+ G_TYPE_STRING, jid,
+ G_TYPE_STRING, account,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ } else {
+ dbus_g_proxy_call (proxy, "send_file", &error,
+ G_TYPE_STRING, file_path,
+ G_TYPE_STRING, jid,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ }
+ g_free(file_path);
+ if(error != NULL)
+ {
+ if(error->domain != DBUS_GERROR || error->code != DBUS_GERROR_INVALID_ARGS) {
+ g_warning("[Gajim] sending file %s to %s failed:", uri, send_to);
+ g_error_free(error);
+ show_error(_("Sending file failed"), _("Unknown recipient."));
+ return FALSE;
+ }
+ g_error_free(error);
+ }
+ }
+ return TRUE;
+}
+
+static gboolean
+destroy (NstPlugin *plugin)
+{
+ if (proxy != NULL) {
+ g_object_unref(proxy);
+ }
+ g_hash_table_destroy(jid_table);
+ return TRUE;
+}
+
+static
+NstPluginInfo plugin_info = {
+ "im-jabber",
+ "gajim",
+ N_("Instant Message (Gajim)"),
+ NULL,
+ CAJA_CAPS_NONE,
+ init,
+ get_contacts_widget,
+ NULL,
+ send_files,
+ destroy
+};
+
+NST_INIT_PLUGIN (plugin_info)
+
diff --git a/sendto/plugins/nst-common.c b/sendto/plugins/nst-common.c
new file mode 100644
index 0000000..2d2f102
--- /dev/null
+++ b/sendto/plugins/nst-common.c
@@ -0,0 +1,98 @@
+/*
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Author: Maxim Ermilov <[email protected]>
+ */
+
+#include <gio/gio.h>
+
+static gboolean
+copy_fobject (GFile* source, GFile* dst)
+{
+ GFileEnumerator* en;
+ GFileInfo* info;
+ GError *err = NULL;
+ char *file_name;
+ GFile *dest;
+
+ file_name = g_file_get_basename (source);
+ dest = g_file_get_child (dst, file_name);
+ g_free (file_name);
+
+ if (g_file_query_file_type (source, G_FILE_QUERY_INFO_NONE, NULL) != G_FILE_TYPE_DIRECTORY) {
+ gboolean ret;
+ ret = g_file_copy (source, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, NULL);
+
+ g_object_unref (dest);
+
+ return ret;
+ }
+
+ en = g_file_enumerate_children (source, "*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ if (!g_file_make_directory (dest, NULL, NULL)) {
+ g_object_unref (en);
+ g_object_unref (dest);
+ return FALSE;
+ }
+
+ while ((info = g_file_enumerator_next_file (en, NULL, &err)) != NULL) {
+ const char *name;
+
+ name = g_file_info_get_name (G_FILE_INFO (info));
+
+ if (name != NULL) {
+ GFile *child;
+
+ child = g_file_get_child (source, name);
+
+ if (!copy_fobject (child, dest)) {
+ g_object_unref (en);
+ g_object_unref (dest);
+ g_object_unref (child);
+
+ return FALSE;
+ }
+ g_object_unref (child);
+ }
+
+ g_object_unref (info);
+ }
+ g_object_unref (en);
+ g_object_unref (dest);
+
+ if (err != NULL)
+ return FALSE;
+ return TRUE;
+}
+
+gboolean
+copy_files_to (GList *file_list, GFile *dest)
+{
+ GList *l;
+ gboolean retval = TRUE;
+
+ for (l = file_list; l != NULL; l = l->next) {
+ GFile *source;
+
+ source = g_file_new_for_commandline_arg (l->data);
+ if (copy_fobject (source, dest) == FALSE)
+ retval = FALSE;
+ g_object_unref (source);
+ }
+
+ return retval;
+}
diff --git a/sendto/plugins/nst-common.h b/sendto/plugins/nst-common.h
new file mode 100644
index 0000000..5a5e1dd
--- /dev/null
+++ b/sendto/plugins/nst-common.h
@@ -0,0 +1,23 @@
+/*
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Author: Maxim Ermilov <[email protected]>
+ */
+
+#include <gio/gio.h>
+
+gboolean copy_files_to (GList *file_list, GFile *dest);
diff --git a/sendto/plugins/pidgin/Makefile.am b/sendto/plugins/pidgin/Makefile.am
new file mode 100644
index 0000000..b7f650a
--- /dev/null
+++ b/sendto/plugins/pidgin/Makefile.am
@@ -0,0 +1,18 @@
+plugindir = $(libdir)/caja-sendto/plugins
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DICONDIR=\"$(icondir)\" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
+ -I$(top_srcdir)/sendto \
+ -I$(top_builddir) \
+ $(SENDTO_CFLAGS) \
+ $(DISABLE_DEPRECATED) \
+ $(WARN_CFLAGS)
+
+plugin_LTLIBRARIES = libnstpidgin.la
+
+libnstpidgin_la_SOURCES = pidgin.c
+libnstpidgin_la_LDFLAGS = -module -avoid-version
+libnstpidgin_la_LIBADD = $(SENDTO_LIBS)
+
diff --git a/sendto/plugins/pidgin/pidgin.c b/sendto/plugins/pidgin/pidgin.c
new file mode 100644
index 0000000..941d2b6
--- /dev/null
+++ b/sendto/plugins/pidgin/pidgin.c
@@ -0,0 +1,475 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * pidgin.c
+ * pidgin plugin for caja-sendto
+ *
+ * Copyright (C) 2004 Roberto Majadas
+ * Copyright (C) 2009 Pascal Terjan
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Author: Roberto Majadas <[email protected]>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include "caja-sendto-plugin.h"
+
+#define OBJ_PATH "/im/pidgin/purple/PurpleObject"
+#define INTERFACE "im.pidgin.purple.PurpleInterface"
+#define SERVICE "im.pidgin.purple.PurpleService"
+
+static DBusGProxy *proxy = NULL;
+static GHashTable *contact_hash = NULL;
+
+typedef struct _ContactData {
+ int account;
+ int id;
+ char *name;
+ char *alias;
+} ContactData;
+
+enum {
+ COL_ICON,
+ COL_ALIAS,
+ NUM_COLS
+};
+
+/*
+ * Print appropriate warnings when dbus raised error
+ * on queries
+ */
+static void
+handle_dbus_exception(GError *error)
+{
+ if (error == NULL) {
+ g_warning("[Pidgin] unable to parse result");
+ return;
+ }
+ else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
+ g_warning ("[Pidgin] caught remote method exception %s: %s",
+ dbus_g_error_get_name (error),
+ error->message);
+ }
+ g_error_free (error);
+}
+
+static gboolean
+init (NstPlugin *plugin)
+{
+ DBusGConnection *connection;
+ GError *error;
+ GArray *accounts;
+
+ g_print ("Init pidgin plugin\n");
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ error = NULL;
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if(error != NULL) {
+ g_warning("[Pidgin] unable to get session bus, error was:\n %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ proxy = dbus_g_proxy_new_for_name(connection,
+ SERVICE,
+ OBJ_PATH,
+ INTERFACE);
+ dbus_g_connection_unref(connection);
+ if (proxy == NULL)
+ return FALSE;
+
+ error = NULL;
+ if (!dbus_g_proxy_call (proxy, "PurpleAccountsGetAllActive", &error, G_TYPE_INVALID,
+ DBUS_TYPE_G_INT_ARRAY, &accounts, G_TYPE_INVALID)) {
+ g_object_unref(proxy);
+ g_error_free(error);
+ return FALSE;
+ }
+ g_array_free(accounts, TRUE);
+
+ return TRUE;
+}
+
+static GdkPixbuf *
+get_buddy_icon(int id)
+{
+ GError *error;
+ GdkPixbuf *pixbuf = NULL;
+ gchar *path = NULL;
+ int icon;
+
+ error=NULL;
+ if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetIcon", &error,
+ G_TYPE_INT, id,
+ G_TYPE_INVALID,
+ G_TYPE_INT, &icon, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ }
+ if (icon) {
+ if (!dbus_g_proxy_call (proxy, "PurpleBuddyIconGetFullPath", &error,
+ G_TYPE_INT, icon,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &path, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ }
+ //FIXME Get the size from somewhere
+ pixbuf = gdk_pixbuf_new_from_file_at_scale(path, 24, 24, TRUE, NULL);
+ }
+
+ return pixbuf;
+}
+
+static void
+add_pidgin_contacts_to_model (GtkTreeStore *store,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ GError *error;
+ GArray *contacts_list;
+ GArray *accounts;
+ int i, j;
+
+ GdkPixbuf *icon;
+ GHashTableIter hiter;
+ GPtrArray *contacts_group;
+ ContactData *dat;
+ GValue val = {0,};
+
+ if(proxy == NULL)
+ return;
+
+ error = NULL;
+ if (!dbus_g_proxy_call (proxy, "PurpleAccountsGetAllActive", &error, G_TYPE_INVALID,
+ DBUS_TYPE_G_INT_ARRAY,
+ &accounts, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ return;
+ }
+
+ contact_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for(i = 0; i < accounts->len; i++) {
+ int account = g_array_index(accounts, int, i);
+ error = NULL;
+ if (!dbus_g_proxy_call (proxy, "PurpleFindBuddies", &error,
+ G_TYPE_INT, account,
+ G_TYPE_STRING, NULL,
+ G_TYPE_INVALID,
+ DBUS_TYPE_G_INT_ARRAY, &contacts_list, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ continue;
+ }
+ for(j = 0; j < contacts_list->len ; j++) {
+ int id = g_array_index(contacts_list, int, j);
+ int online;
+
+ error = NULL;
+ if (!dbus_g_proxy_call (proxy, "PurpleBuddyIsOnline", &error,
+ G_TYPE_INT, id,
+ G_TYPE_INVALID,
+ G_TYPE_INT, &online, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ continue;
+ }
+ if (!online)
+ continue;
+
+ dat = g_new0 (ContactData, 1);
+
+ dat->account = account;
+ dat->id = id;
+
+ error = NULL;
+ if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetName", &error,
+ G_TYPE_INT, id,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &dat->name, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ g_free(dat);
+ continue;
+ }
+ if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetAlias", &error,
+ G_TYPE_INT, id,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &dat->alias, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ }
+
+ contacts_group = g_hash_table_lookup (contact_hash, dat->alias);
+ if (contacts_group == NULL){
+ GPtrArray *new_group = g_ptr_array_new ();
+ g_ptr_array_add (new_group, dat);
+ g_hash_table_insert (contact_hash, dat->alias, new_group);
+ } else {
+ g_ptr_array_add (contacts_group, dat);
+ }
+ }
+ g_array_free(contacts_list, TRUE);
+ }
+ g_array_free (accounts, TRUE);
+
+ g_hash_table_iter_init (&hiter, contact_hash);
+ while (g_hash_table_iter_next (&hiter, NULL, (gpointer)&contacts_group)) {
+ gint accounts;
+
+ dat = g_ptr_array_index (contacts_group, 0);
+
+ accounts = contacts_group->len;
+
+ gtk_tree_store_append (store, parent, NULL);
+ gtk_tree_store_set (store, parent, COL_ICON, NULL, COL_ALIAS, dat->alias, -1);
+
+ gint i;
+ for (i = 0; i < accounts; ++i) {
+ dat = g_ptr_array_index (contacts_group, i);
+
+ icon = get_buddy_icon(dat->id);
+
+ if (accounts == 1) {
+ g_value_init(&val, GDK_TYPE_PIXBUF);
+ g_value_set_object (&val, (gpointer)icon);
+ gtk_tree_store_set_value (store, parent, COL_ICON, &val);
+ g_value_unset (&val);
+ break;
+ }
+ gtk_tree_store_append (store, iter, parent);
+ gtk_tree_store_set (store, iter,
+ COL_ICON, icon,
+ COL_ALIAS, dat->alias,
+ -1);
+ }
+ }
+}
+
+static void
+customize (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer text)
+{
+ gboolean has_child;
+ has_child = gtk_tree_model_iter_has_child (tree_model, iter);
+ if (text) {
+ if (has_child)
+ g_object_set (G_OBJECT(cell), "xpad", 18, NULL);
+ else
+ g_object_set (G_OBJECT(cell), "xpad", 2, NULL);
+ }
+ g_object_set (G_OBJECT(cell), "sensitive", !has_child, NULL);
+}
+
+static GtkWidget *
+get_contacts_widget (NstPlugin *plugin)
+{
+ GtkWidget *cb;
+ GtkCellRenderer *renderer;
+ GtkTreeStore *store;
+ GtkTreeModel *model;
+ GtkTreeIter *iter, *iter2;
+
+ iter = g_malloc (sizeof(GtkTreeIter));
+ iter2 = g_malloc (sizeof(GtkTreeIter));
+ store = gtk_tree_store_new (NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+ add_pidgin_contacts_to_model (store, iter, iter2);
+ model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), COL_ALIAS,
+ GTK_SORT_ASCENDING);
+ cb = gtk_combo_box_new_with_model (model);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb),
+ renderer,
+ FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb),
+ renderer,
+ "pixbuf", COL_ICON,
+ NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (cb), renderer,
+ customize,
+ (gboolean *)FALSE, NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb),
+ renderer,
+ TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb),
+ renderer,
+ "text", COL_ALIAS,
+ NULL);
+ g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (cb), renderer,
+ customize,
+ (gboolean *)TRUE, NULL);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0);
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX(cb), iter);
+ if (gtk_tree_model_iter_has_child (model, iter)) {
+ GtkTreePath *path = gtk_tree_path_new_from_indices (0, 0, -1);
+ gtk_tree_model_get_iter (model, iter2, path);
+ gtk_tree_path_free (path);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (cb), iter2);
+ }
+
+ g_free (iter);
+ g_free (iter2);
+ return cb;
+}
+
+static
+gboolean send_file(int account, const char *who, const char *filename)
+{
+ GError *error;
+ int connection;
+
+ error = NULL;
+ if (!dbus_g_proxy_call(proxy, "PurpleAccountGetConnection", &error,
+ G_TYPE_INT, account,
+ G_TYPE_INVALID,
+ G_TYPE_INT, &connection, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ return FALSE;
+ }
+
+ if (!connection) {
+ g_warning("[Pidgin] account is not connected");
+ return FALSE;
+ }
+
+ error = NULL;
+ if (!dbus_g_proxy_call(proxy, "ServSendFile", &error,
+ G_TYPE_INT, connection,
+ G_TYPE_STRING, who,
+ G_TYPE_STRING, filename,
+ G_TYPE_INVALID, G_TYPE_INVALID)) {
+ handle_dbus_exception(error);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static
+gboolean send_files (NstPlugin *plugin, GtkWidget *contact_widget,
+ GList *file_list)
+{
+ GError *error;
+ GList *file_iter;
+
+ GFile *file;
+ gchar *file_path;
+
+ gint depth;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ gint *indices;
+ const gchar *alias;
+ GPtrArray *contacts_group;
+ ContactData *dat;
+ GValue val = {0,};
+
+
+ if(proxy == NULL)
+ return FALSE;
+
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (contact_widget), &iter);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (
+ gtk_combo_box_get_model (GTK_COMBO_BOX(
+ contact_widget))), &iter);
+ depth = gtk_tree_path_get_depth(path);
+ indices = gtk_tree_path_get_indices(path);
+ gtk_tree_path_free (path);
+ gtk_tree_model_get_value (GTK_TREE_MODEL (gtk_combo_box_get_model (
+ GTK_COMBO_BOX(contact_widget))),
+ &iter, COL_ALIAS, &val);
+ alias = g_value_get_string (&val);
+ contacts_group = g_hash_table_lookup (contact_hash, alias);
+ g_value_unset (&val);
+ dat = g_ptr_array_index (contacts_group, (depth == 2)?indices[1]:0);
+
+ for(file_iter = file_list; file_iter != NULL;
+ file_iter = g_list_next(file_iter)) {
+ error= NULL;
+
+ file = g_file_new_for_uri ((gchar *)file_iter->data);
+ file_path = g_file_get_path (file);
+ g_object_unref (file);
+
+ if(file_path == NULL) {
+ g_warning("[Pidgin] %d Unable to convert URI `%s' to absolute file path",
+ error->code, (gchar *)file_iter->data);
+ g_error_free(error);
+ continue;
+ }
+
+ if(!send_file(dat->account, dat->name, file_path))
+ g_warning("[Pidgin] Failed to send %s file to %s", file_path, dat->name);
+ }
+ return TRUE;
+}
+
+static void
+free_contact (ContactData *dat)
+{
+ g_free(dat->name);
+ g_free(dat->alias);
+ g_free(dat);
+}
+
+static gboolean
+destroy (NstPlugin *plugin)
+{
+ GHashTableIter iter;
+ GPtrArray *contacts_group;
+ ContactData *dat;
+
+ g_hash_table_iter_init (&iter, contact_hash);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer)&contacts_group)) {
+ gint accounts;
+ accounts = contacts_group->len;
+
+ gint i;
+ for (i = 0; i < accounts; ++i) {
+ dat = g_ptr_array_index (contacts_group, i);
+ free_contact (dat);
+ }
+ g_ptr_array_free (contacts_group, TRUE);
+ }
+ g_hash_table_destroy (contact_hash);
+ return TRUE;
+}
+
+static
+NstPluginInfo plugin_info = {
+ "im",
+ "pidgin",
+ N_("Instant Message (Pidgin)"),
+ NULL,
+ CAJA_CAPS_NONE,
+ init,
+ get_contacts_widget,
+ NULL,
+ send_files,
+ destroy
+};
+
+NST_INIT_PLUGIN (plugin_info)
+
diff --git a/sendto/plugins/removable-devices/Makefile.am b/sendto/plugins/removable-devices/Makefile.am
new file mode 100644
index 0000000..294ca90
--- /dev/null
+++ b/sendto/plugins/removable-devices/Makefile.am
@@ -0,0 +1,19 @@
+plugindir = $(libdir)/caja-sendto/plugins
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DICONDIR=\"$(icondir)\" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
+ -I$(top_srcdir)/sendto \
+ -I$(top_builddir) \
+ -I$(srcdir)/../ \
+ $(SENDTO_CFLAGS) \
+ $(DISABLE_DEPRECATED) \
+ $(WARN_CFLAGS)
+
+plugin_LTLIBRARIES = libnstremovable_devices.la
+
+libnstremovable_devices_la_SOURCES = removable-devices.c
+libnstremovable_devices_la_LDFLAGS = -module -avoid-version
+libnstremovable_devices_la_LIBADD = $(SENDTO_LIBS) $(builddir)/../libnstcommon.la
+
diff --git a/sendto/plugins/removable-devices/removable-devices.c b/sendto/plugins/removable-devices/removable-devices.c
new file mode 100644
index 0000000..0ecea14
--- /dev/null
+++ b/sendto/plugins/removable-devices/removable-devices.c
@@ -0,0 +1,259 @@
+/*
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Authors: Maxim Ermilov <[email protected]>
+ * Bastien Nocera <[email protected]>
+ */
+
+#include "config.h"
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+#include "nst-common.h"
+#include "caja-sendto-plugin.h"
+
+enum {
+ NAME_COL,
+ ICON_COL,
+ MOUNT_COL,
+ NUM_COLS,
+};
+
+GVolumeMonitor* vol_monitor = NULL;
+GtkWidget *cb;
+
+static void
+cb_mount_removed (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ NstPlugin *plugin)
+{
+ GtkTreeIter iter;
+ GtkListStore *store;
+ gboolean b, found;
+
+ store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb)));
+ b = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
+ found = FALSE;
+
+ while (b) {
+ GMount *m;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &m, -1);
+ if (m == mount) {
+ gtk_list_store_remove (store, &iter);
+ g_object_unref (m);
+ found = TRUE;
+ break;
+ }
+ g_object_unref (m);
+ b = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
+ }
+
+ /* If a mount was removed */
+ if (found != FALSE) {
+ /* And it was the selected one */
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (cb)) == -1) {
+ /* Select the first item in the list */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0);
+ }
+ }
+}
+
+static void
+cb_mount_changed (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ NstPlugin *plugin)
+{
+ GtkTreeIter iter;
+ gboolean b;
+ GtkListStore *store;
+
+ if (g_mount_is_shadowed (mount) != FALSE) {
+ cb_mount_removed (volume_monitor, mount, plugin);
+ return;
+ }
+
+ store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb)));
+ b = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
+
+ while (b) {
+ GMount *m;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &m, -1);
+
+ if (m == mount) {
+ char *name;
+
+ name = g_mount_get_name (mount);
+ gtk_list_store_set (store, &iter,
+ NAME_COL, name,
+ ICON_COL, g_mount_get_icon (mount),
+ -1);
+ g_free (name);
+ g_object_unref (m);
+ break;
+ }
+ g_object_unref (m);
+ b = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
+ }
+}
+
+static void
+cb_mount_added (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ NstPlugin *plugin)
+{
+ char *name;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gboolean select_added;
+
+ if (g_mount_is_shadowed (mount) != FALSE)
+ return;
+
+ name = g_mount_get_name (mount);
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (cb));
+
+ select_added = gtk_tree_model_iter_n_children (model, NULL) == 0;
+
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ NAME_COL, name,
+ ICON_COL, g_mount_get_icon (mount),
+ MOUNT_COL, mount,
+ -1);
+
+ g_free (name);
+
+ if (select_added != FALSE)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0);
+
+}
+
+static gboolean
+init (NstPlugin *plugin)
+{
+ g_print ("Init removable-devices plugin\n");
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ vol_monitor = g_volume_monitor_get ();
+ cb = gtk_combo_box_new ();
+
+ return TRUE;
+}
+
+static GtkWidget*
+get_contacts_widget (NstPlugin *plugin)
+{
+ GtkListStore *store;
+ GList *l, *mounts;
+ GtkTreeIter iter;
+ GtkCellRenderer *text_renderer, *icon_renderer;
+
+ mounts = g_volume_monitor_get_mounts (vol_monitor);
+
+ store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_OBJECT);
+
+ for (l = mounts; l != NULL; l = l->next) {
+ char *name;
+
+ if (g_mount_is_shadowed (l->data) != FALSE) {
+ g_object_unref (l->data);
+ continue;
+ }
+
+ name = g_mount_get_name (l->data);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ NAME_COL, name,
+ ICON_COL, g_mount_get_icon (l->data),
+ MOUNT_COL, l->data,
+ -1);
+ g_free (name);
+
+ g_object_unref (l->data);
+ }
+ g_list_free (mounts);
+
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (cb));
+ gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (store));
+
+ text_renderer = gtk_cell_renderer_text_new ();
+ icon_renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), icon_renderer, FALSE);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), text_renderer, TRUE);
+
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), text_renderer, "text", 0, NULL);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), icon_renderer, "gicon", 1, NULL);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0);
+
+ g_signal_connect (G_OBJECT (vol_monitor), "mount-removed", G_CALLBACK (cb_mount_removed), plugin);
+ g_signal_connect (G_OBJECT (vol_monitor), "mount-added", G_CALLBACK (cb_mount_added), plugin);
+ g_signal_connect (G_OBJECT (vol_monitor), "mount-changed", G_CALLBACK (cb_mount_changed), plugin);
+
+ return cb;
+}
+
+static gboolean
+send_files (NstPlugin *plugin, GtkWidget *contact_widget,
+ GList *file_list)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GMount *dest_mount;
+ GFile *mount_root;
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (contact_widget), &iter) == FALSE)
+ return TRUE;
+
+ store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb)));
+ gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &dest_mount, -1);
+ mount_root = g_mount_get_root (dest_mount);
+
+ copy_files_to (file_list, mount_root);
+
+ g_object_unref (mount_root);
+
+ return TRUE;
+}
+
+static gboolean
+destroy (NstPlugin *plugin)
+{
+ gtk_widget_destroy (cb);
+
+ g_object_unref (vol_monitor);
+ return TRUE;
+}
+
+static
+NstPluginInfo plugin_info = {
+ "folder-remote",
+ "folder-remote",
+ N_("Removable disks and shares"),
+ NULL,
+ CAJA_CAPS_SEND_DIRECTORIES,
+ init,
+ get_contacts_widget,
+ NULL,
+ send_files,
+ destroy
+};
+
+NST_INIT_PLUGIN (plugin_info)
+
diff --git a/sendto/plugins/upnp/Makefile.am b/sendto/plugins/upnp/Makefile.am
new file mode 100644
index 0000000..4127abd
--- /dev/null
+++ b/sendto/plugins/upnp/Makefile.am
@@ -0,0 +1,18 @@
+plugindir = $(libdir)/caja-sendto/plugins
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DICONDIR=\"$(icondir)\" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
+ -I$(top_srcdir)/sendto \
+ -I$(top_builddir) \
+ $(SENDTO_CFLAGS) \
+ $(DISABLE_DEPRECATED) \
+ $(WARN_CFLAGS)
+
+plugin_LTLIBRARIES = libnstupnp.la
+
+libnstupnp_la_SOURCES = upnp.c
+libnstupnp_la_LDFLAGS = -module -avoid-version
+libnstupnp_la_LIBADD = $(SENDTO_LIBS)
+
diff --git a/sendto/plugins/upnp/upnp.c b/sendto/plugins/upnp/upnp.c
new file mode 100644
index 0000000..b381587
--- /dev/null
+++ b/sendto/plugins/upnp/upnp.c
@@ -0,0 +1,320 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Copyright (C) 2008 Zeeshan Ali (Khattak)
+ * Copyright (C) 2006 Peter Enseleit
+ *
+ * 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 av.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Author: Zeeshan Ali (Khattak) <[email protected]>
+ * Peter Enseleit <[email protected]>
+ * Roberto Majadas <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <libgupnp/gupnp.h>
+#include "caja-sendto-plugin.h"
+
+#define MEDIA_SERVER "urn:schemas-upnp-org:device:MediaServer:1"
+#define CDS "urn:schemas-upnp-org:service:ContentDirectory"
+
+enum {
+ UDN_COL,
+ NAME_COL,
+ INTERFACE_COL,
+ NUM_COLS
+};
+
+static GtkWidget *combobox;
+static GtkTreeModel *model;
+static GUPnPContextManager *context_manager;
+
+static gboolean
+find_device (const gchar *udn,
+ GtkTreeIter *iter)
+{
+ gboolean found = FALSE;
+
+ if (!gtk_tree_model_get_iter_first (model, iter))
+ return FALSE;
+
+ do {
+ gchar *tmp;
+
+ gtk_tree_model_get (model,
+ iter,
+ UDN_COL, &tmp,
+ -1);
+
+ if (tmp != NULL && strcmp (tmp, udn) == 0)
+ found = TRUE;
+
+ g_free (tmp);
+ } while (!found && gtk_tree_model_iter_next (model, iter));
+
+ return found;
+}
+
+static gboolean
+check_required_actions (GUPnPServiceIntrospection *introspection)
+{
+ if (gupnp_service_introspection_get_action (introspection,
+ "CreateObject") == NULL)
+ return FALSE;
+ if (gupnp_service_introspection_get_action (introspection,
+ "ImportResource") == NULL)
+ return FALSE;
+ return TRUE;
+}
+
+static void
+get_introspection_cb (GUPnPServiceInfo *service_info,
+ GUPnPServiceIntrospection *introspection, const GError *error,
+ gpointer user_data)
+{
+ GUPnPDeviceInfo *device_info;
+ gchar *name;
+ const gchar *udn, *interface;
+ GtkTreeIter iter;
+ GUPnPContext *context;
+
+ device_info = GUPNP_DEVICE_INFO (user_data);
+
+ if (introspection != NULL) {
+ /* If introspection is available, make sure required actions
+ * are implemented.
+ */
+ if (!check_required_actions (introspection))
+ goto error;
+ }
+
+ udn = gupnp_device_info_get_udn (device_info);
+ if (G_UNLIKELY (udn == NULL))
+ goto error;
+
+ /* First check if the device is already added */
+ if (find_device (udn, &iter))
+ goto error;
+
+ name = gupnp_device_info_get_friendly_name (device_info);
+ if (name == NULL)
+ name = g_strdup (udn);
+
+ context = gupnp_device_info_get_context (device_info);
+ interface = gssdp_client_get_interface (GSSDP_CLIENT (context));
+
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (model), NULL, -1,
+ UDN_COL, udn,
+ NAME_COL, name,
+ INTERFACE_COL, interface,
+ -1);
+
+ g_free (name);
+
+error:
+ /* We don't need the proxy objects anymore */
+ g_object_unref (service_info);
+ g_object_ref (device_info);
+}
+
+static void
+device_proxy_available_cb (GUPnPControlPoint *cp,
+ GUPnPDeviceProxy *proxy)
+{
+ GUPnPServiceInfo *info;
+
+ info = gupnp_device_info_get_service (GUPNP_DEVICE_INFO (proxy), CDS);
+ if (G_UNLIKELY (info == NULL)) {
+ /* No ContentDirectory implemented? Not interesting. */
+ return;
+ }
+
+ gupnp_service_info_get_introspection_async (info,
+ get_introspection_cb,
+ g_object_ref (proxy));
+}
+
+static void
+device_proxy_unavailable_cb (GUPnPControlPoint *cp,
+ GUPnPDeviceProxy *proxy)
+{
+ GtkTreeIter iter;
+ const gchar *udn;
+
+ udn = gupnp_device_info_get_udn (GUPNP_DEVICE_INFO (proxy));
+ if (udn == NULL)
+ return;
+
+ /* First check if the device is already added */
+ if (find_device (udn, &iter))
+ gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+}
+
+static void
+on_context_available (GUPnPContextManager *context_manager,
+ GUPnPContext *context,
+ gpointer user_data)
+{
+ GUPnPControlPoint *cp;
+
+ cp = gupnp_control_point_new (context, MEDIA_SERVER);
+
+ g_signal_connect (cp,
+ "device-proxy-available",
+ G_CALLBACK (device_proxy_available_cb),
+ NULL);
+ g_signal_connect (cp,
+ "device-proxy-unavailable",
+ G_CALLBACK (device_proxy_unavailable_cb),
+ NULL);
+
+ gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE);
+
+ /* Let context manager take care of the control point life cycle */
+ gupnp_context_manager_manage_control_point (context_manager, cp);
+ g_object_unref (cp);
+}
+
+static gboolean
+init (NstPlugin *plugin)
+{
+ GtkListStore *store;
+ GtkCellRenderer *renderer;
+ char *upload_cmd;
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ upload_cmd = g_find_program_in_path ("gupnp-upload");
+ if (upload_cmd == NULL)
+ return FALSE;
+ g_free (upload_cmd);
+
+ context_manager = gupnp_context_manager_new (NULL, 0);
+ g_assert (context_manager != NULL);
+ g_signal_connect (context_manager, "context-available",
+ G_CALLBACK (on_context_available), NULL);
+
+ combobox = gtk_combo_box_new ();
+
+ store = gtk_list_store_new (NUM_COLS,
+ G_TYPE_STRING, /* UDN */
+ G_TYPE_STRING, /* Name */
+ G_TYPE_STRING); /* Network Interface */
+ model = GTK_TREE_MODEL (store);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combobox), model);
+
+ renderer = gtk_cell_renderer_text_new ();
+
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox),
+ renderer,
+ TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox),
+ renderer,
+ "text", NAME_COL);
+
+ return TRUE;
+}
+
+static GtkWidget*
+get_contacts_widget (NstPlugin *plugin)
+{
+ return combobox;
+}
+
+static gboolean
+send_files (NstPlugin *plugin,
+ GtkWidget *contact_widget,
+ GList *file_list)
+{
+ gchar *upload_cmd, *udn, *interface;
+ GPtrArray *argv;
+ gboolean ret;
+ GList *l;
+ GtkTreeIter iter;
+ GError *err = NULL;
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combobox), &iter))
+ return FALSE;
+
+ gtk_tree_model_get (model, &iter, UDN_COL, &udn, INTERFACE_COL,
+ &interface, -1);
+
+ upload_cmd = g_find_program_in_path ("gupnp-upload");
+ if (upload_cmd == NULL)
+ return FALSE;
+
+ argv = g_ptr_array_new ();
+ g_ptr_array_add (argv, upload_cmd);
+ g_ptr_array_add (argv, "-t");
+ g_ptr_array_add (argv, "15"); /* discovery timeout (seconds) */
+ g_ptr_array_add (argv, "-e");
+ g_ptr_array_add (argv, interface);
+ g_ptr_array_add (argv, udn);
+ for (l = file_list ; l; l=l->next) {
+ gchar *file_path;
+
+ file_path = g_filename_from_uri (l->data, NULL, NULL);
+ g_ptr_array_add (argv, file_path);
+ }
+ g_ptr_array_add (argv, NULL);
+
+ ret = g_spawn_async (NULL, (gchar **) argv->pdata,
+ NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err);
+
+ if (ret == FALSE) {
+ g_warning ("Could not send files to MediaServer: %s",
+ err->message);
+ g_error_free (err);
+ }
+
+ g_ptr_array_free (argv, TRUE);
+ g_free (upload_cmd);
+ g_free (udn);
+
+ return ret;
+}
+
+static gboolean
+destroy (NstPlugin *plugin)
+{
+ gtk_widget_destroy (combobox);
+ g_object_unref (model);
+
+ g_object_unref (context_manager);
+
+ return TRUE;
+}
+
+static
+NstPluginInfo plugin_info = {
+ "folder-remote",
+ "upnp",
+ N_("UPnP Media Server"),
+ NULL,
+ CAJA_CAPS_NONE,
+ init,
+ get_contacts_widget,
+ NULL,
+ send_files,
+ destroy
+};
+
+NST_INIT_PLUGIN (plugin_info)
+