diff options
-rw-r--r-- | configure.ac | 31 | ||||
-rw-r--r-- | data/dbus/tracker-miner-web.xml | 98 | ||||
-rw-r--r-- | examples/libtracker-miner/Makefile.am | 16 | ||||
-rw-r--r-- | examples/libtracker-miner/password-provider-test.c | 88 | ||||
-rw-r--r-- | src/libtracker-miner/Makefile.am | 47 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-gnome-password-provider.c | 291 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-keyfile-password-provider.c | 396 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner-0.7.deps | 1 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner-0.7.vapi | 158 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner-web-dbus.h | 47 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner-web.c | 263 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner-web.deps.in | 1 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner-web.h | 136 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner.c | 4 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-password-provider.c | 137 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-password-provider.h | 88 |
16 files changed, 1795 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac index 37484e471..f0d83c140 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,7 @@ EDS_REQUIRED=2.25.5 LIBSTREAMANALYZER_REQUIRED=0.7.0 GEE_REQUIRED=0.3 ID3LIB_REQUIRED=3.8.3 +GNOME_KEYRING_REQUIRED=2.26 # Library Checks PKG_CHECK_MODULES(GLIB2, [glib-2.0 >= $GLIB_REQUIRED]) @@ -761,6 +762,36 @@ fi AM_CONDITIONAL(HAVE_UNAC, test "x$have_unac" = "xyes") +################################################################## +# Enable Gnome Keyring support to store credentials (for web miners) +################################################################## + +AC_ARG_ENABLE(gnome_keyring, + AS_HELP_STRING([--enable-gnome-keyring], + [enable Gnome Keyring support to store credentials [[default=auto]]]),, + [enable_gnome_keyring=auto]) + +if test "x$enable_gnome_keyring" != "xno"; then + PKG_CHECK_MODULES(GNOME_KEYRING, + [ gnome-keyring-1 >= $GNOME_KEYRING_REQUIRED ], + [have_gnome_keyring=yes], + [have_gnome_keyring=no]) + AC_SUBST(GNOME_KEYRING_LIBS) + AC_SUBST(GNOME_KEYRING_CFLAGS) + + if test "x$have_gnome_keyring" = "xyes"; then + AC_DEFINE(HAVE_GNOME_KEYRING, [], [Define if we have Gnome Keyring for password storage]) + fi +fi + +if test "x$enable_gnome_keyring" = "xyes"; then + if test "x$have_gnome_keyring" != "xyes"; then + AC_MSG_ERROR([Couldn't find Gnome Keyring >= $GNOME_KEYRING_REQUIRED.]) + fi +fi + +AM_CONDITIONAL(HAVE_GNOME_KEYRING, test "x$have_gnome_keyring" = "xyes") + #################################################################### # Mail miners #################################################################### diff --git a/data/dbus/tracker-miner-web.xml b/data/dbus/tracker-miner-web.xml new file mode 100644 index 000000000..7b54da23e --- /dev/null +++ b/data/dbus/tracker-miner-web.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<node name="/"> + <interface name="org.freedesktop.Tracker1.Miner.Web"> + <method name="Authenticate"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <doc:doc> + <doc:description> + <doc:para> + Tries to authenticate the miner against the remote web service. + </doc:para> + </doc:description> + </doc:doc> + </method> + <method name="GetAssociationData"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <doc:doc> + <doc:description> + <doc:para> + Returns a hash containing the information necessary to know how to + associate the miner to its web service. + </doc:para> + </doc:description> + </doc:doc> + <arg name="result" type="a{ss}" direction="out"> + <doc:doc> + <doc:summary> + <doc:para> + A hash containing the association information. Its keys depend on + the type of association. + For a token based association, the following keys are always + defined: + * url: A url where the user can follow the association procedure + For a token based association, the following keys might be + defined: + * post_message: A message to display after he returns from the + association procedure + * post_url: A url to point the user to after he returns from the + association procedure + If both post_message and post_url are defined, the message will + shown to the user before he is pointer to post_url. + For a user/pass based based association, the hash table should be + empty. + </doc:para> + </doc:summary> + </doc:doc> + </arg> + </method> + <method name="Associate"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <doc:doc> + <doc:description> + <doc:para> + Associates the miner with its web service. + </doc:para> + </doc:description> + </doc:doc> + <arg name="data" type="a{ss}" direction="in"> + <doc:doc> + <doc:summary> + <doc:para> + A hash containing the association information. Its keys depend on + the type of association. + For a token based association, the hash should be empty. + For a user/pass based based association, the following keys + should be defined: + * url: A url where the user can follow the association procedure + For a token based association, the following keys might be + defined: + * username: The username provided by the user + * password: The password provided by the user + </doc:para> + </doc:summary> + </doc:doc> + </arg> + </method> + <method name="Dissociate"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <doc:doc> + <doc:description> + <doc:para> + Dissociates the miner from its web service. + </doc:para> + </doc:description> + </doc:doc> + </method> + <property name="AssociationStatus" type="u" access="read"> + <doc:doc> + <doc:description> + <doc:para> + Holds the current association status of the miner. The possible values are + defined in tracker-miner-web.h. + </doc:para> + </doc:description> + </doc:doc> + </property> + </interface> +</node> diff --git a/examples/libtracker-miner/Makefile.am b/examples/libtracker-miner/Makefile.am index 5f753ce7a..6e1da788c 100644 --- a/examples/libtracker-miner/Makefile.am +++ b/examples/libtracker-miner/Makefile.am @@ -17,7 +17,7 @@ INCLUDES = \ $(DBUS_CFLAGS) \ $(UNAC_CFLAGS) -noinst_PROGRAMS = tracker-miner-test +noinst_PROGRAMS = tracker-miner-test password-provider-test tracker_miner_test_SOURCES = \ tracker-miner-test.c \ @@ -36,3 +36,17 @@ tracker_miner_test_LDADD = \ $(GLIB2_LIBS) \ -lz \ -lm + +password_provider_test_SOURCES = \ + password-provider-test.c + +password_provider_test_LDADD = \ + $(top_builddir)/src/libtracker-miner/libtracker-miner-@TRACKER_API_VERSION@.la \ + $(DBUS_LIBS) \ + $(GMODULE_LIBS) \ + $(GTHREAD_LIBS) \ + $(GIO_LIBS) \ + $(GCOV_LIBS) \ + $(GLIB2_LIBS) \ + -lz \ + -lm diff --git a/examples/libtracker-miner/password-provider-test.c b/examples/libtracker-miner/password-provider-test.c new file mode 100644 index 000000000..14178042b --- /dev/null +++ b/examples/libtracker-miner/password-provider-test.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include <libtracker-miner/tracker-password-provider.h> + +#define SERVICE_NAME "TestService" + +int main (int argc, char **argv) +{ + gchar *username = NULL; + gchar *password = NULL; + GError *error = NULL; + + g_type_init (); + g_set_application_name ("PasswordBackendTest"); + + TrackerPasswordProvider *provider = tracker_password_provider_get (); + + tracker_password_provider_store_password (provider, + SERVICE_NAME, + "This is the test service", + "testUser", + "testPass", + &error); + + if (error) { + g_critical ("tracker_password_provider_store: %s", error->message); + g_error_free (error); + + return 1; + } + + password = tracker_password_provider_get_password (provider, + SERVICE_NAME, + &username, + &error); + + if (error) { + g_critical ("tracker_password_provider_get: %s", error->message); + g_error_free (error); + g_free (username); + g_free (password); + + return 1; + } else { + g_message ("Username: %s , Password:%s", username, password); + } + + g_free (username); + g_free (password); + + // Also test without getting the username + password = tracker_password_provider_get_password (provider, + SERVICE_NAME, + NULL, + &error); + + if (error) { + g_critical ("tracker_password_provider_get: %s", error->message); + g_error_free (error); + g_free (password); + + return 1; + } else { + g_message ("Password:%s", password); + } + + g_free (password); + g_object_unref (provider); + return 0; +} diff --git a/src/libtracker-miner/Makefile.am b/src/libtracker-miner/Makefile.am index 91aa559d9..405588a12 100644 --- a/src/libtracker-miner/Makefile.am +++ b/src/libtracker-miner/Makefile.am @@ -36,6 +36,8 @@ libtracker_miner_@TRACKER_API_VERSION@_la_SOURCES = \ tracker-miner-dbus.h \ tracker-miner-fs.c \ tracker-miner-fs.h \ + tracker-miner-web.c \ + tracker-miner-web.h \ tracker-miner-manager.c \ tracker-miner-manager.h \ tracker-monitor.c \ @@ -43,8 +45,9 @@ libtracker_miner_@TRACKER_API_VERSION@_la_SOURCES = \ tracker-storage.c \ tracker-storage.h \ tracker-utils.c \ + tracker-thumbnailer.c \ tracker-utils.h \ - tracker-thumbnailer.c + tracker-password-provider.c libtracker_minerinclude_HEADERS = \ tracker-crawler.h \ @@ -53,11 +56,13 @@ libtracker_minerinclude_HEADERS = \ tracker-miner-fs.h \ tracker-miner-manager.h \ tracker-storage.h \ - tracker-thumbnailer.h + tracker-thumbnailer.h \ + tracker-miner-web.h \ + tracker-password-provider.h libtracker_miner_@TRACKER_API_VERSION@_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ - -export-symbols-regex '^tracker_(miner|thumbnailer|crawler|storage)_.*' + -export-symbols-regex '^tracker_(miner|thumbnailer|crawler|storage|password_provider)_.*' libtracker_miner_@TRACKER_API_VERSION@_la_LIBADD = \ $(top_builddir)/src/libtracker-common/libtracker-common.la \ @@ -73,6 +78,28 @@ libtracker_miner_@TRACKER_API_VERSION@_la_LIBADD = \ $(GLIB2_LIBS) \ $(GDKPIXBUF_LIBS) +if HAVE_GNOME_KEYRING +libtracker_miner_@TRACKER_API_VERSION@_la_SOURCES += \ + tracker-gnome-password-provider.c + +libtracker_miner_@TRACKER_API_VERSION@_la_LIBADD += \ + $(GNOME_KEYRING_LIBS) + +INCLUDES += \ + $(GNOME_KEYRING_CFLAGS) +else +libtracker_miner_@TRACKER_API_VERSION@_la_SOURCES += \ + tracker-keyfile-password-provider.c +endif + +vapidir=$(datadir)/vala/vapi +vapi_DATA = \ + tracker-miner-$(TRACKER_API_VERSION).vapi + +tracker-miner-web-$(TRACKER_API_VERSION).deps: tracker-miner-web.deps.in + $(SED) -e "s|@VERSION[@]|${TRACKER_API_VERSION}|" $< > $@ + + tracker-marshal.h: tracker-marshal.list $(AM_V_GEN)$(GLIB_GENMARSHAL) $< --prefix=tracker_marshal --header > $@ @@ -86,15 +113,27 @@ marshal_sources = \ dbus_sources = \ tracker-miner-glue.h \ + tracker-miner-web-glue.h \ tracker-miner-client.h +# Custom rule to avoid API duplication. There is also a workaround for bug +# in dbus-binding-tool where it generates bad code when two files are passed +# on the command line (though the man page says it supports it) +# This bug is reported at https://bugs.freedesktop.org/show_bug.cgi?id=25056 +tracker-miner-web-glue.h: $(top_srcdir)/data/dbus/tracker-miner-web.xml $(top_srcdir)/data/dbus/tracker-miner.xml + echo '<?xml version="1.0" encoding="UTF-8"?>' > $(top_srcdir)/src/libtracker-miner/tracker-miner-web-full.xml + echo '<node name="/">' >> $(top_srcdir)/src/libtracker-miner/tracker-miner-web-full.xml + cat $^ | grep -v -e '<node' -e '<?xml' -e '</node>' >> $(top_srcdir)/src/libtracker-miner/tracker-miner-web-full.xml + echo '</node>' >> $(top_srcdir)/src/libtracker-miner/tracker-miner-web-full.xml + $(AM_V_GEN)$(DBUSBINDINGTOOL) --mode=glib-server --output=$@ --prefix=tracker_miner_web_dbus $(top_srcdir)/src/libtracker-miner/tracker-miner-web-full.xml + %-glue.h: $(top_srcdir)/data/dbus/%.xml $(AM_V_GEN)$(DBUSBINDINGTOOL) --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^ %-client.h: $(top_srcdir)/data/dbus/%.xml $(AM_V_GEN)$(DBUSBINDINGTOOL) --mode=glib-client --output=$@ --prefix=$(subst -,_,$*) $^ -BUILT_SOURCES = $(dbus_sources) $(marshal_sources) +BUILT_SOURCES = $(dbus_sources) $(marshal_sources) tracker-miner-web-full.xml CLEANFILES = $(BUILT_SOURCES) diff --git a/src/libtracker-miner/tracker-gnome-password-provider.c b/src/libtracker-miner/tracker-gnome-password-provider.c new file mode 100644 index 000000000..5adc2c783 --- /dev/null +++ b/src/libtracker-miner/tracker-gnome-password-provider.c @@ -0,0 +1,291 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <glib-object.h> +#include <gnome-keyring.h> + +#include "tracker-password-provider.h" + +#define TRACKER_TYPE_PASSWORD_PROVIDER_GNOME (tracker_password_provider_gnome_get_type()) +#define TRACKER_PASSWORD_PROVIDER_GNOME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnome)) +#define TRACKER_PASSWORD_PROVIDER_GNOME_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnomeClass)) +#define TRACKER_IS_PASSWORD_PROVIDER_GNOME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME)) +#define TRACKER_IS_PASSWORD_PROVIDER_GNOME_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME)) +#define TRACKER_PASSWORD_PROVIDER_GNOME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnomeClass)) + +#define TRACKER_PASSWORD_PROVIDER_GNOME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnomePrivate)) + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, TrackerPasswordProviderGnomePrivate)) + +#define PASSWORD_PROVIDER_GNOME_NAME "Gnome keyring" + +typedef struct TrackerPasswordProviderGnome TrackerPasswordProviderGnome; +typedef struct TrackerPasswordProviderGnomeClass TrackerPasswordProviderGnomeClass; +typedef struct TrackerPasswordProviderGnomePrivate TrackerPasswordProviderGnomePrivate; + +struct TrackerPasswordProviderGnome { + GObject parent; +}; + +struct TrackerPasswordProviderGnomeClass { + GObjectClass parent_class; +}; + +struct TrackerPasswordProviderGnomePrivate { + gchar *name; +}; + +const GnomeKeyringPasswordSchema password_schema = { + GNOME_KEYRING_ITEM_GENERIC_SECRET, { + { "service", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { "username", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { NULL, 0 } + } +}; + +enum { + PROP_0, + PROP_NAME +}; + +GType tracker_password_provider_gnome_get_type (void) G_GNUC_CONST; + +static void tracker_password_provider_iface_init (TrackerPasswordProviderIface *iface); +static void password_provider_gnome_finalize (GObject *object); +static void password_provider_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void password_provider_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void password_provider_gnome_store (TrackerPasswordProvider *provider, + const gchar *service, + const gchar *description, + const gchar *username, + const gchar *password, + GError **error); +static gchar* password_provider_gnome_get (TrackerPasswordProvider *provider, + const gchar *service, + gchar **username, + GError **error); +static void password_provider_gnome_forget (TrackerPasswordProvider *provider, + const gchar *service, + GError **error); + +G_DEFINE_TYPE_WITH_CODE (TrackerPasswordProviderGnome, + tracker_password_provider_gnome, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TRACKER_TYPE_PASSWORD_PROVIDER, + tracker_password_provider_iface_init)) + +static void +tracker_password_provider_gnome_class_init (TrackerPasswordProviderGnomeClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = password_provider_gnome_finalize; + object_class->set_property = password_provider_set_property; + object_class->get_property = password_provider_get_property; + + g_object_class_override_property (object_class, + PROP_NAME, + "name"); + g_type_class_add_private (object_class, + sizeof (TrackerPasswordProviderGnomePrivate)); +} + +static void +tracker_password_provider_gnome_init (TrackerPasswordProviderGnome *provider) +{ +} + +static void +tracker_password_provider_iface_init (TrackerPasswordProviderIface *iface) +{ + iface->store_password = password_provider_gnome_store; + iface->get_password = password_provider_gnome_get; + iface->forget_password = password_provider_gnome_forget; +} + +static void +password_provider_gnome_finalize (GObject *object) +{ + G_OBJECT_CLASS (tracker_password_provider_gnome_parent_class)->finalize (object); +} + +static void +password_provider_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + TrackerPasswordProviderGnomePrivate *priv = GET_PRIV (object); + + switch (prop_id) { + case PROP_NAME: + g_free (priv->name); + priv->name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + }; +} + +static void +password_provider_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + TrackerPasswordProviderGnomePrivate *priv = GET_PRIV (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + }; +} + +static void +password_provider_gnome_store (TrackerPasswordProvider *provider, + const gchar *service, + const gchar *description, + const gchar *username, + const gchar *password, + GError **error) +{ + GnomeKeyringResult r = gnome_keyring_store_password_sync (&password_schema, + NULL, + description, + password, + "service", service, + "username", username, + NULL); + if (r != GNOME_KEYRING_RESULT_OK) { + g_set_error (error, + TRACKER_PASSWORD_PROVIDER_ERROR, + TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE, + "Cannot store password: %s", + gnome_keyring_result_to_message (r)); + } +} + +static gchar* +password_provider_gnome_get (TrackerPasswordProvider *provider, + const gchar *service, + gchar **username, + GError **error) +{ + gchar *password; + GnomeKeyringAttributeList *search_attributes; + GList *found_items = NULL; + GnomeKeyringFound *found; + GnomeKeyringResult r; + gint i; + + search_attributes = gnome_keyring_attribute_list_new (); + gnome_keyring_attribute_list_append_string (search_attributes, + "service", service); + + r = gnome_keyring_find_items_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET, + search_attributes, + &found_items); + + gnome_keyring_attribute_list_free (search_attributes); + + if (r != GNOME_KEYRING_RESULT_OK) { + if (r == GNOME_KEYRING_RESULT_NO_MATCH) { + g_set_error_literal (error, + TRACKER_PASSWORD_PROVIDER_ERROR, + TRACKER_PASSWORD_PROVIDER_ERROR_NOTFOUND, + "Password not found"); + } else { + g_set_error (error, + TRACKER_PASSWORD_PROVIDER_ERROR, + TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE, + "Keyring error: %s", + gnome_keyring_result_to_message (r)); + } + + gnome_keyring_found_list_free (found_items); + return NULL; + } + + found = (GnomeKeyringFound *)(found_items->data); + + /* Walk through all attributes and select the ones we're interested in */ + for (i = 0 ; i < found->attributes->len ; ++i) { + GnomeKeyringAttribute *attr = &gnome_keyring_attribute_list_index (found->attributes, i); + if (username && !g_strcmp0 (attr->name, "username")) { + *username = g_strdup (attr->value.string); + } + } + + password = tracker_password_provider_strdup_mlock (found->secret); + + gnome_keyring_found_list_free (found_items); + + return password; +} + +static void +password_provider_gnome_forget (TrackerPasswordProvider *provider, + const gchar *service, + GError **error) +{ + GnomeKeyringResult r = gnome_keyring_delete_password_sync (&password_schema, + "service", service, + NULL); + + if (r != GNOME_KEYRING_RESULT_OK) { + g_set_error (error, + TRACKER_PASSWORD_PROVIDER_ERROR, + TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE, + "Cannot delete password: %s", + gnome_keyring_result_to_message (r)); + } +} + +const TrackerPasswordProvider* +tracker_password_provider_get (void) +{ + static TrackerPasswordProvider *instance = NULL; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + g_static_mutex_lock (&mutex); + if (instance == NULL) { + instance = g_object_new (TRACKER_TYPE_PASSWORD_PROVIDER_GNOME, + "name", PASSWORD_PROVIDER_GNOME_NAME, + NULL); + } + g_static_mutex_unlock (&mutex); + + g_assert (instance != NULL); + + return instance; +} + diff --git a/src/libtracker-miner/tracker-keyfile-password-provider.c b/src/libtracker-miner/tracker-keyfile-password-provider.c new file mode 100644 index 000000000..f82f7f4c1 --- /dev/null +++ b/src/libtracker-miner/tracker-keyfile-password-provider.c @@ -0,0 +1,396 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <glib-object.h> + +#include <sys/mman.h> + +#include "tracker-password-provider.h" + +#define TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE (tracker_password_provider_keyfile_get_type()) +#define TRACKER_PASSWORD_PROVIDER_KEYFILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE, TrackerPasswordProviderKeyfile)) +#define TRACKER_PASSWORD_PROVIDER_KEYFILE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE, TrackerPasswordProviderKeyfileClass)) +#define TRACKER_IS_PASSWORD_PROVIDER_KEYFILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE)) +#define TRACKER_IS_PASSWORD_PROVIDER_KEYFILE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE)) +#define TRACKER_PASSWORD_PROVIDER_KEYFILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE, TrackerPasswordProviderKeyfileClass)) + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE, TrackerPasswordProviderKeyfilePrivate)) + +#define PASSWORD_PROVIDER_KEYFILE_NAME "KeyFile" + +/* GKeyFile settings */ +#define KEYFILE_FILENAME "passwords.cfg" +#define GROUP_GENERAL "General" + +typedef struct TrackerPasswordProviderKeyfile TrackerPasswordProviderKeyfile; +typedef struct TrackerPasswordProviderKeyfileClass TrackerPasswordProviderKeyfileClass; +typedef struct TrackerPasswordProviderKeyfilePrivate TrackerPasswordProviderKeyfilePrivate; + +struct TrackerPasswordProviderKeyfile { + GObject parent; +}; + +struct TrackerPasswordProviderKeyfileClass { + GObjectClass parent_class; +}; + +struct TrackerPasswordProviderKeyfilePrivate { + gchar *name; + GKeyFile *password_file; +}; + +enum { + PROP_0, + PROP_NAME +}; + +GType tracker_password_provider_keyfile_get_type (void) G_GNUC_CONST; + +static void tracker_password_provider_iface_init (TrackerPasswordProviderIface *iface); +static void password_provider_keyfile_constructed (GObject *object); +static void password_provider_keyfile_finalize (GObject *object); +static void password_provider_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void password_provider_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +void password_provider_keyfile_store (TrackerPasswordProvider *provider, + const gchar *service, + const gchar *description, + const gchar *username, + const gchar *password, + GError **error); +gchar* password_provider_keyfile_get (TrackerPasswordProvider *provider, + const gchar *service, + gchar **username, + GError **error); +void password_provider_keyfile_forget (TrackerPasswordProvider *provider, + const gchar *service, + GError **error); + +static void load_password_file (TrackerPasswordProviderKeyfile *kf, + GError **error); +static gboolean save_password_file (TrackerPasswordProviderKeyfile *kf, + GError **error); + +G_DEFINE_TYPE_WITH_CODE (TrackerPasswordProviderKeyfile, + tracker_password_provider_keyfile, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TRACKER_TYPE_PASSWORD_PROVIDER, + tracker_password_provider_iface_init)) + +static void +tracker_password_provider_keyfile_class_init (TrackerPasswordProviderKeyfileClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = password_provider_keyfile_finalize; + object_class->constructed = password_provider_keyfile_constructed; + object_class->set_property = password_provider_set_property; + object_class->get_property = password_provider_get_property; + + g_object_class_override_property (object_class, + PROP_NAME, + "name"); + + g_type_class_add_private (object_class, sizeof (TrackerPasswordProviderKeyfilePrivate)); +} + +static void +tracker_password_provider_keyfile_init (TrackerPasswordProviderKeyfile *provider) +{ +} + +static void +tracker_password_provider_iface_init (TrackerPasswordProviderIface *iface) +{ + iface->store_password = password_provider_keyfile_store; + iface->get_password = password_provider_keyfile_get; + iface->forget_password = password_provider_keyfile_forget; +} + +static void +password_provider_keyfile_constructed (GObject *object) +{ + TrackerPasswordProviderKeyfile *kf = TRACKER_PASSWORD_PROVIDER_KEYFILE (object); + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (object); + GError *error = NULL; + + priv->password_file = g_key_file_new (); + + load_password_file (kf, &error); + + if (error) { + g_critical ("Cannot load password file: %s", error->message); + g_error_free (error); + } +} + +static void +password_provider_keyfile_finalize (GObject *object) +{ + G_OBJECT_CLASS (tracker_password_provider_keyfile_parent_class)->finalize (object); +} + +static void +password_provider_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (object); + + switch (prop_id) { + case PROP_NAME: + g_free (priv->name); + priv->name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + }; +} + +static void +password_provider_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + }; +} + +void +password_provider_keyfile_store (TrackerPasswordProvider *provider, + const gchar *service, + const gchar *description, + const gchar *username, + const gchar *password, + GError **error) +{ + TrackerPasswordProviderKeyfile *kf = TRACKER_PASSWORD_PROVIDER_KEYFILE (provider); + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (provider); + GError *local_error = NULL; + + g_key_file_set_string (priv->password_file, + service, + "description", + description); + g_key_file_set_string (priv->password_file, + service, + "username", + username); + g_key_file_set_string (priv->password_file, + service, + "password", + password); + + if (!save_password_file (kf, &local_error)) { + g_propagate_error (error, local_error); + } +} + +gchar* +password_provider_keyfile_get (TrackerPasswordProvider *provider, + const gchar *service, + gchar **username, + GError **error) +{ + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (provider); + gchar *password = NULL; + GError *error_password = NULL; + GError *error_username = NULL; + + password = g_key_file_get_string (priv->password_file, + service, + "password", + &error_password); + + mlock (password, sizeof (password)); + + if (username) { + *username = g_key_file_get_string (priv->password_file, + service, + "username", + &error_username); + } + + if (error_password || error_username) { + g_set_error_literal (error, + TRACKER_PASSWORD_PROVIDER_ERROR, + TRACKER_PASSWORD_PROVIDER_ERROR_NOTFOUND, + "Password not found"); + } + + if (error_password) + g_error_free (error_password); + if (error_username) + g_error_free (error_username); + + return password; +} + +void +password_provider_keyfile_forget (TrackerPasswordProvider *provider, + const gchar *service, + GError **error) +{ + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (provider); + + GError *e = NULL; + + if (!g_key_file_remove_group (priv->password_file, service, &e)) { + g_warning ("Cannot remove group '%s' from password file: %s", + service, + e->message); + g_error_free (e); + + g_set_error_literal (error, + TRACKER_PASSWORD_PROVIDER_ERROR, + TRACKER_PASSWORD_PROVIDER_ERROR_NOTFOUND, + "Service not found"); + } +} + +const TrackerPasswordProvider* +tracker_password_provider_get (void) +{ + static TrackerPasswordProvider *instance = NULL; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + g_static_mutex_lock (&mutex); + if (instance == NULL) { + instance = g_object_new (TRACKER_TYPE_PASSWORD_PROVIDER_KEYFILE, + "name", PASSWORD_PROVIDER_KEYFILE_NAME, + NULL); + } + g_static_mutex_unlock (&mutex); + + g_assert (instance != NULL); + + return instance; +} + +/* Copied from tracker-config-file.c */ +static gchar * +config_dir_ensure_exists_and_return (GError **error) +{ + gchar *directory; + + directory = g_build_filename (g_get_user_config_dir (), + "tracker", + NULL); + + if (!g_file_test (directory, G_FILE_TEST_EXISTS)) { + g_print ("Creating config directory:'%s'\n", directory); + + if (g_mkdir_with_parents (directory, 0700) == -1) { + if (error) { + *error = g_error_new (TRACKER_PASSWORD_PROVIDER_ERROR, + TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE, + "Impossible to create directory: '%s'", + directory); + } + g_free (directory); + return NULL; + } + } + + return directory; +} + +static void +load_password_file (TrackerPasswordProviderKeyfile *kf, + GError **error) +{ + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (kf); + gchar *filename; + gchar *directory; + GError *local_error = NULL; + + directory = config_dir_ensure_exists_and_return (&local_error); + if (!directory) { + g_propagate_error (error, local_error); + return; + } + + filename = g_build_filename (directory, KEYFILE_FILENAME, NULL); + g_free (directory); + + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { + return; + } + + g_key_file_load_from_file (priv->password_file, + filename, + G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, + &local_error); + + if (local_error) { + g_propagate_error (error, local_error); + } +} + +static gboolean +save_password_file (TrackerPasswordProviderKeyfile *kf, + GError **error) +{ + TrackerPasswordProviderKeyfilePrivate *priv = GET_PRIV (kf); + gchar *filename; + gchar *directory; + gchar *data; + gsize size; + GError *local_error = NULL; + + directory = config_dir_ensure_exists_and_return (&local_error); + if (!directory) { + g_propagate_error (error, local_error); + return FALSE; + } + + filename = g_build_filename (directory, KEYFILE_FILENAME, NULL); + g_free (directory); + + data = g_key_file_to_data (priv->password_file, &size, NULL); + + g_file_set_contents (filename, data, size, &local_error); + g_free (data); + g_free (filename); + + if (local_error) { + g_propagate_error (error, local_error); + return FALSE; + } + + return TRUE; +} diff --git a/src/libtracker-miner/tracker-miner-0.7.deps b/src/libtracker-miner/tracker-miner-0.7.deps new file mode 100644 index 000000000..cd10dfde4 --- /dev/null +++ b/src/libtracker-miner/tracker-miner-0.7.deps @@ -0,0 +1 @@ +gio-2.0 diff --git a/src/libtracker-miner/tracker-miner-0.7.vapi b/src/libtracker-miner/tracker-miner-0.7.vapi new file mode 100644 index 000000000..d44b23101 --- /dev/null +++ b/src/libtracker-miner/tracker-miner-0.7.vapi @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2010, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +[CCode (cprefix = "Tracker", lower_case_cprefix = "tracker_")] +namespace Tracker { + [Compact] + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public class Crawler { + public weak GLib.Object parent; + [CCode (has_construct_function = false)] + public Crawler (); + public void pause (); + public void resume (); + public void set_throttle (double throttle); + public bool start (GLib.File file, bool recurse); + public void stop (); + } + [Compact] + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public class CrawlerClass { + public weak GLib.Callback check_directory; + public weak GLib.Callback check_directory_contents; + public weak GLib.Callback check_file; + public weak GLib.Callback directory_crawled; + public weak GLib.Callback finished; + public weak GLib.ObjectClass parent; + } + [CCode (cheader_filename = "libtracker-miner/tracker-miner.h")] + public class Miner : GLib.Object { + public async void commit (GLib.Cancellable? cancellable = null) throws GLib.Error; + public static GLib.Quark error_quark (); + public async void execute_batch_update (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async unowned GLib.PtrArray execute_sparql (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async void execute_update (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error; + public void ignore_next_update (string[] urls); + public bool is_started (); + public int pause (string reason) throws GLib.Error; + public virtual void paused (); + public bool resume (int cookie) throws GLib.Error; + public virtual void resumed (); + public void start (); + public virtual void started (); + public void stop (); + public virtual void stopped (); + public virtual void writeback ([CCode (array_length = false)] string[] subjects); + public signal void error (GLib.Error e); + } + [CCode (ref_function = "tracker_miner_fs_ref", unref_function = "tracker_miner_fs_unref", cheader_filename = "libtracker-miner/tracker-miner-fs.h")] + public class MinerFS { + public virtual bool check_directory (GLib.File directory); + public virtual bool check_directory_contents (GLib.File directory, GLib.List<GLib.File> children); + public virtual bool check_file (GLib.File file); + public void directory_add (GLib.File file, bool recurse); + public bool directory_remove (GLib.File file); + public void file_add (GLib.File file); + public void file_notify (GLib.File file, GLib.Error error); + public unowned string get_parent_urn (GLib.File file); + public double get_throttle (); + public unowned string get_urn (GLib.File file); + public virtual bool monitor_directory (GLib.File directory); + public void set_throttle (double throttle); + public signal void finished (double elapsed, uint directories_found, uint directories_ignored, uint files_found, uint files_ignored); + } + [Compact] + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public class MinerManager { + public weak GLib.Object parent_instance; + [CCode (has_construct_function = false)] + public MinerManager (); + public unowned GLib.SList get_available (); + public unowned string get_description (string miner); + public unowned string get_display_name (string miner); + public unowned GLib.SList get_running (); + public bool get_status (string miner, string status, double progress); + public bool ignore_next_update (string miner, string urls); + public bool is_active (string miner); + public bool is_paused (string miner, string[] applications, string[] reasons); + public bool pause (string miner, string reason, uint32 cookie); + public bool resume (string miner, uint32 cookie); + } + [Compact] + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public class MinerManagerClass { + public weak GLib.Callback miner_activated; + public weak GLib.Callback miner_deactivated; + public weak GLib.Callback miner_paused; + public weak GLib.Callback miner_progress; + public weak GLib.Callback miner_resumed; + public weak GLib.ObjectClass parent_class; + } + [CCode (cheader_filename = "libtracker-miner/tracker-miner-web.h")] + public class MinerWeb : Tracker.Miner { + public virtual void associate (GLib.HashTable association_data) throws Tracker.MinerWebError; + public virtual void authenticate () throws Tracker.MinerWebError; + public virtual void dissociate () throws Tracker.MinerWebError; + public static GLib.Quark error_quark (); + public virtual GLib.HashTable get_association_data () throws Tracker.MinerWebError; + } + [CCode (cheader_filename = "libtracker-miner/tracker-password-provider.h")] + public interface PasswordProvider : GLib.Object { + public void forget_password (string service) throws GLib.Error; + public static unowned Tracker.PasswordProvider @get (); + public unowned string get_name (); + public string get_password (string service, out string username) throws GLib.Error; + public void store_password (string service, string description, string username, string password) throws GLib.Error; + } + [CCode (cprefix = "TRACKER_MINER_WEB_", has_type_id = false, cheader_filename = "libtracker-miner/tracker-miner-web.h")] + public enum MinerWebAssociationStatus { + UNASSOCIATED, + ASSOCIATED + } + [CCode (cprefix = "TRACKER_MINER_WEB_ERROR_", cheader_filename = "libtracker-miner/tracker-miner-web.h")] + public errordomain MinerWebError { + WRONG_CREDENTIALS, + TOKEN_EXPIRED, + NO_CREDENTIALS, + KEYRING, + SERVICE, + TRACKER, + } + [CCode (cprefix = "TRACKER_PASSWORD_PROVIDER_ERROR_", cheader_filename = "libtracker-miner/tracker-password-provider.h")] + public errordomain PasswordProviderError { + SERVICE, + NOTFOUND, + } + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public const int MAX_TIMEOUT_INTERVAL; + [CCode (cheader_filename = "libtracker-miner/tracker-miner.h")] + public const string MINER_WEB_DBUS_INTERFACE; + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public static bool thumbnailer_cleanup (string uri_prefix); + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public static bool thumbnailer_init (); + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public static bool thumbnailer_move_add (string from_uri, string mime_type, string to_uri); + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public static bool thumbnailer_remove_add (string uri, string mime_type); + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public static void thumbnailer_send (); + [CCode (cheader_filename = "tracker-miner-0.7.h")] + public static void thumbnailer_shutdown (); +} diff --git a/src/libtracker-miner/tracker-miner-web-dbus.h b/src/libtracker-miner/tracker-miner-web-dbus.h new file mode 100644 index 000000000..7faa16d4d --- /dev/null +++ b/src/libtracker-miner/tracker-miner-web-dbus.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010, Adrien Bustany <abustany@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __LIBTRACKERMINER_WEB_DBUS_H__ +#define __LIBTRACKERMINER_WEB_DBUS_H__ + +#include <glib-object.h> + +#include "tracker-miner-dbus.h" +#include "tracker-miner-web.h" + +G_BEGIN_DECLS + +void tracker_miner_web_dbus_authenticate (TrackerMinerWeb *miner, + DBusGMethodInvocation *context, + GError **error); +void tracker_miner_web_dbus_get_association_data (TrackerMinerWeb *miner, + DBusGMethodInvocation *context, + GError **error); +void tracker_miner_web_dbus_associate (TrackerMinerWeb *miner, + const GHashTable *association_data, + DBusGMethodInvocation *context, + GError **error); +void tracker_miner_web_dbus_dissociate (TrackerMinerWeb *miner, + DBusGMethodInvocation *context, + GError **error); + +G_END_DECLS + +#endif /* __LIBTRACKERMINER_DBUS_H__ */ diff --git a/src/libtracker-miner/tracker-miner-web.c b/src/libtracker-miner/tracker-miner-web.c new file mode 100644 index 000000000..757e1ae75 --- /dev/null +++ b/src/libtracker-miner/tracker-miner-web.c @@ -0,0 +1,263 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "tracker-miner-web.h" +#include "tracker-dbus.h" +#include "tracker-miner-web-dbus.h" +#include "tracker-miner-web-glue.h" + +/** + * SECTION:tracker-miner-web + * @short_description: Abstract base class for miners using web services + * @include: libtracker-miner/tracker-miner-web.h + * + * #TrackerMinerWeb is an abstract base class for miners retrieving data + * from web services. It's a very thin layer above #TrackerMiner, only + * adding virtual methods needed to handle association with the remote + * service. + **/ + +#define TRACKER_MINER_WEB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_WEB, TrackerMinerWebPrivate)) + +struct TrackerMinerWebPrivate { + TrackerMinerWebAssociationStatus association_status; +}; + +enum { + PROP_0, + PROP_ASSOCIATION_STATUS +}; + +static void miner_web_set_property (GObject * object, + guint param_id, + const GValue *value, + GParamSpec *pspec); +static void miner_web_get_property (GObject * object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void miner_web_constructed (GObject *object); +static void miner_web_finalize (GObject *object); + +G_DEFINE_ABSTRACT_TYPE (TrackerMinerWeb, tracker_miner_web, TRACKER_TYPE_MINER) + +static void +tracker_miner_web_class_init (TrackerMinerWebClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = miner_web_set_property; + object_class->get_property = miner_web_get_property; + object_class->constructed = miner_web_constructed; + object_class->finalize = miner_web_finalize; + + g_object_class_install_property (object_class, + PROP_ASSOCIATION_STATUS, + g_param_spec_uint ("association-status", + "Association status", + "Tells if the miner is associated with the remote service", + TRACKER_MINER_WEB_UNASSOCIATED, /* min value */ + TRACKER_MINER_WEB_ASSOCIATED, /* max value */ + TRACKER_MINER_WEB_UNASSOCIATED, /* default value */ + G_PARAM_READWRITE)); + + g_type_class_add_private (object_class, sizeof (TrackerMinerWebPrivate)); +} + +static void +tracker_miner_web_init (TrackerMinerWeb *miner) +{ + TrackerMinerWebPrivate *priv; + priv = TRACKER_MINER_WEB_GET_PRIVATE (miner); + priv->association_status = TRACKER_MINER_WEB_UNASSOCIATED; +} + +static void +miner_web_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + TrackerMinerWeb *miner = TRACKER_MINER_WEB (object); + TrackerMinerWebPrivate *priv; + priv = TRACKER_MINER_WEB_GET_PRIVATE (object); + + switch (param_id) { + case PROP_ASSOCIATION_STATUS: + priv->association_status = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +miner_web_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + TrackerMinerWeb *miner = TRACKER_MINER_WEB (object); + TrackerMinerWebPrivate *priv; + priv = TRACKER_MINER_WEB_GET_PRIVATE (object); + + switch (param_id) { + case PROP_ASSOCIATION_STATUS: + g_value_set_uint (value, priv->association_status); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +miner_web_constructed (GObject *object) +{ + tracker_miner_dbus_init (TRACKER_MINER (object), + &dbus_glib_tracker_miner_web_dbus_object_info); + + G_OBJECT_CLASS (tracker_miner_web_parent_class)->constructed (object); +} + +static void +miner_web_finalize (GObject *object) +{ + /* TrackerMinerWeb *miner = TRACKER_MINER_WEB (object); */ + + G_OBJECT_CLASS (tracker_miner_web_parent_class)->finalize (object); +} + +GQuark +tracker_miner_web_error_quark (void) +{ + return g_quark_from_static_string (TRACKER_MINER_WEB_ERROR_DOMAIN); +} + +void +tracker_miner_web_dbus_authenticate (TrackerMinerWeb *miner, + DBusGMethodInvocation *context, + GError **error) +{ + GError *local_error = NULL; + + g_assert (TRACKER_IS_MINER_WEB (miner)); + + TRACKER_MINER_WEB_GET_CLASS (miner)->authenticate (miner, &local_error); + + if (local_error != NULL) { + dbus_g_method_return_error (context, local_error); + g_error_free (local_error); + } else { + dbus_g_method_return (context); + } +} + +void +tracker_miner_web_dbus_get_association_data (TrackerMinerWeb *miner, + DBusGMethodInvocation *context, + GError **error) +{ + GError *local_error = NULL; + + g_assert (TRACKER_IS_MINER_WEB (miner)); + + GHashTable *association_data = TRACKER_MINER_WEB_GET_CLASS (miner)->get_association_data (miner, &local_error); + + if (local_error != NULL) { + dbus_g_method_return_error (context, local_error); + g_error_free (local_error); + } else { + dbus_g_method_return (context, association_data); + } +} + +void +tracker_miner_web_dbus_associate (TrackerMinerWeb *miner, + const GHashTable *association_data, + DBusGMethodInvocation *context, + GError **error) +{ + GError *local_error = NULL; + + g_assert (TRACKER_IS_MINER_WEB (miner)); + + TRACKER_MINER_WEB_GET_CLASS (miner)->associate (miner, association_data, &local_error); + + if (local_error != NULL) { + dbus_g_method_return_error (context, local_error); + g_error_free (local_error); + } else { + dbus_g_method_return (context); + } +} + +void +tracker_miner_web_dbus_dissociate (TrackerMinerWeb *miner, + DBusGMethodInvocation *context, + GError **error) +{ + GError *local_error = NULL; + + g_assert (TRACKER_IS_MINER_WEB (miner)); + + TRACKER_MINER_WEB_GET_CLASS (miner)->dissociate (miner, &local_error); + + if (local_error != NULL) { + dbus_g_method_return_error (context, local_error); + g_error_free (local_error); + } else { + dbus_g_method_return (context); + } +} + +void +tracker_miner_web_authenticate (TrackerMinerWeb *miner, + GError **error) +{ + g_assert (TRACKER_IS_MINER_WEB (miner)); + TRACKER_MINER_WEB_GET_CLASS (miner)->authenticate (miner, error); +} + +GHashTable* +tracker_miner_web_get_association_data (TrackerMinerWeb *miner, + GError **error) +{ + g_assert (TRACKER_IS_MINER_WEB (miner)); + return TRACKER_MINER_WEB_GET_CLASS (miner)->get_association_data (miner, error); +} + +void +tracker_miner_web_associate (TrackerMinerWeb *miner, + const GHashTable *association_data, + GError **error) +{ + g_assert (TRACKER_IS_MINER_WEB (miner)); + TRACKER_MINER_WEB_GET_CLASS (miner)->associate (miner, association_data, error); +} + +void +tracker_miner_web_dissociate (TrackerMinerWeb *miner, + GError **error) +{ + g_assert (TRACKER_IS_MINER_WEB (miner)); + TRACKER_MINER_WEB_GET_CLASS (miner)->dissociate (miner, error); +} diff --git a/src/libtracker-miner/tracker-miner-web.deps.in b/src/libtracker-miner/tracker-miner-web.deps.in new file mode 100644 index 000000000..0f1fc536e --- /dev/null +++ b/src/libtracker-miner/tracker-miner-web.deps.in @@ -0,0 +1 @@ +tracker-miner-@VERSION@ diff --git a/src/libtracker-miner/tracker-miner-web.h b/src/libtracker-miner/tracker-miner-web.h new file mode 100644 index 000000000..655267472 --- /dev/null +++ b/src/libtracker-miner/tracker-miner-web.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2009, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __TRACKER_MINER_WEB_H__ +#define __TRACKER_MINER_WEB_H__ + +#include <libtracker-miner/tracker-miner.h> + +#define TRACKER_TYPE_MINER_WEB (tracker_miner_web_get_type()) +#define TRACKER_MINER_WEB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_WEB, TrackerMinerWeb)) +#define TRACKER_MINER_WEB_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_WEB, TrackerMinerWebClass)) +#define TRACKER_IS_MINER_WEB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_WEB)) +#define TRACKER_IS_MINER_WEB_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_MINER_WEB)) +#define TRACKER_MINER_WEB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_WEB, TrackerMinerWebClass)) + +G_BEGIN_DECLS + +typedef struct TrackerMinerWeb TrackerMinerWeb; +typedef struct TrackerMinerWebPrivate TrackerMinerWebPrivate; + +/** + * The name of the DBus interface exposed by the web miners + **/ +#define TRACKER_MINER_WEB_DBUS_INTERFACE "org.freedesktop.Tracker1.MinerWeb" + +/** + * TrackerMinerWebError: + * @TRACKER_MINER_WEB_ERROR_WRONG_CREDENTIALS: The stored credentials are refused by the remote service + * @TRACKER_MINER_WEB_ERROR_TOKEN_EXPIRED : The service says the stored token has expired + * @TRACKER_MINER_WEB_ERROR_NO_CREDENTIALS : There are currenty no credentials stored for this service + * @TRACKER_MINER_WEB_ERROR_KEYRING : Error while contacting the credentials storage + * @TRACKER_MINER_WEB_ERROR_SERVICE : Error while contacting the remote service + * @TRACKER_MINER_WEB_ERROR_TRACKER : Error while contacting Tracker + * + * Describes the different errors that can occur while operating with the remote service. + **/ +typedef enum { + TRACKER_MINER_WEB_ERROR_WRONG_CREDENTIALS, + TRACKER_MINER_WEB_ERROR_TOKEN_EXPIRED, + TRACKER_MINER_WEB_ERROR_NO_CREDENTIALS, + TRACKER_MINER_WEB_ERROR_KEYRING, + TRACKER_MINER_WEB_ERROR_SERVICE, + TRACKER_MINER_WEB_ERROR_TRACKER +} TrackerMinerWebError; +#define TRACKER_MINER_WEB_ERROR tracker_miner_web_error_quark () +#define TRACKER_MINER_WEB_ERROR_DOMAIN "TrackerMinerWeb" + +/** + * TrackerMinerWebAssociationStatus: + * @TRACKER_MINER_WEB_UNASSOCIATED : The miner is currently unassociated with the remote service + * @TRACKER_MINER_WEB_ASSOCIATED : The miner is currently associated with the remote service + * + * Describes if the miner can currently communicate (import data) with the web service. + **/ +typedef enum { + TRACKER_MINER_WEB_UNASSOCIATED, + TRACKER_MINER_WEB_ASSOCIATED +} TrackerMinerWebAssociationStatus; + +struct TrackerMinerWeb { + TrackerMiner parent_instance; +}; + +/** + * TrackerMinerWebClass + * @parent_class : parent object class + * @authenticate : called when the miner is told to authenticate against the remote service + * @get_association_data: called when one requests the miner's association data. + * In the case of a user/pass based authentication, this should return + * an empty hash table. + * In the case of a token based authentication, the following keys must + * be defined in the returned hash table: + * - url: the url to point the user too + * Additionally, the miner can define the following keys : + * - post_message: a message to display after the user completes the + * association process + * - post_url: a url to point the user after he completes the association + * + * If both post_message and post_url are defined, the message will be + * displayed before the url is opened. + * @associate : called when the miner is told to associate with the web service. + * In the case of a user/pass based authentication, the following keys must be defined + * - username: the provided username + * - password: the provided password + * In the case of a token based authentication, the hash table can be ignored + * since it will be empty. + * @dissociate : called when the miner is told to forget any user credentials it has stored + **/ +typedef struct { + TrackerMinerClass parent_class; + + /* vmethods */ + void (* authenticate) (TrackerMinerWeb *miner, + GError **error); + GHashTable* (* get_association_data) (TrackerMinerWeb *miner, + GError **error); + void (* associate) (TrackerMinerWeb *miner, + const GHashTable *association_data, + GError **error); + void (* dissociate) (TrackerMinerWeb *miner, + GError **error); +} TrackerMinerWebClass; + +GType tracker_miner_web_get_type (void) G_GNUC_CONST; +GQuark tracker_miner_web_error_quark (void); + +void tracker_miner_web_authenticate (TrackerMinerWeb *miner, + GError **error); +GHashTable* tracker_miner_web_get_association_data (TrackerMinerWeb *miner, + GError **error); +void tracker_miner_web_associate (TrackerMinerWeb *miner, + const GHashTable *association_data, + GError **error); +void tracker_miner_web_dissociate (TrackerMinerWeb *miner, + GError **error); + +G_END_DECLS + +#endif /* __TRACKER_MINER_WEB_H__ */ diff --git a/src/libtracker-miner/tracker-miner.c b/src/libtracker-miner/tracker-miner.c index d4833c04e..61f040f79 100644 --- a/src/libtracker-miner/tracker-miner.c +++ b/src/libtracker-miner/tracker-miner.c @@ -435,8 +435,8 @@ miner_constructed (GObject *object) static void store_name_monitor_cb (TrackerMiner *miner, - const gchar *name, - gboolean available) + const gchar *name, + gboolean available) { GError *error = NULL; diff --git a/src/libtracker-miner/tracker-password-provider.c b/src/libtracker-miner/tracker-password-provider.c new file mode 100644 index 000000000..7059eaae9 --- /dev/null +++ b/src/libtracker-miner/tracker-password-provider.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2009, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "tracker-password-provider.h" + +#include <sys/mman.h> +#include <string.h> + +#include "config.h" + +static void +tracker_password_provider_init (gpointer object_class) +{ + static gboolean is_initialized = FALSE; + + if (!is_initialized) { + g_object_interface_install_property (object_class, + g_param_spec_string ("name", + "Password provider name", + "Password provider name", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + is_initialized = TRUE; + } +} + +/* That would be better done with G_DECLARE_INTERFACE, but it's GLib 2.24 */ +GType +tracker_password_provider_get_type (void) +{ + static GType iface_type = 0; + + if (iface_type == 0) { + static const GTypeInfo info = { + sizeof (TrackerPasswordProviderIface), + tracker_password_provider_init, + NULL + }; + + iface_type = g_type_register_static (G_TYPE_INTERFACE, + "TrackerPasswordProvider", + &info, + 0); + } + + return iface_type; +} + +GQuark +tracker_password_provider_error_quark (void) +{ + return g_quark_from_static_string (TRACKER_PASSWORD_PROVIDER_ERROR_DOMAIN); +} + +gchar* +tracker_password_provider_get_name (TrackerPasswordProvider *provider) +{ + g_assert (TRACKER_IS_PASSWORD_PROVIDER (provider)); + + gchar *name; + g_object_get (provider, "name", &name, NULL); + + return name; +} + +void +tracker_password_provider_store_password (TrackerPasswordProvider *provider, + const gchar *service, + const gchar *description, + const gchar *username, + const gchar *password, + GError **error) +{ + g_assert (TRACKER_IS_PASSWORD_PROVIDER (provider)); + + TRACKER_PASSWORD_PROVIDER_GET_INTERFACE (provider)->store_password (provider, + service, + description, + username, + password, + error); +} + +gchar* +tracker_password_provider_get_password (TrackerPasswordProvider *provider, + const gchar *service, + gchar **username, + GError **error) +{ + g_assert (TRACKER_IS_PASSWORD_PROVIDER (provider)); + + gchar *password = TRACKER_PASSWORD_PROVIDER_GET_INTERFACE (provider)->get_password (provider, + service, + username, + error); + return password; +} + +void +tracker_password_provider_forget_password (TrackerPasswordProvider *provider, + const gchar *service, + GError **error) +{ + g_assert (TRACKER_IS_PASSWORD_PROVIDER (provider)); + + TRACKER_PASSWORD_PROVIDER_GET_INTERFACE (provider)->forget_password (provider, + service, + error); +} + +gchar* +tracker_password_provider_strdup_mlock (const gchar *source) +{ + gchar *dest; + dest = malloc (1 + strlen (source)); + dest = memset (dest, 0, 1 + strlen (source)); + mlock (dest, sizeof (dest)); + memcpy (dest, source, strlen (source)); + + return dest; +} diff --git a/src/libtracker-miner/tracker-password-provider.h b/src/libtracker-miner/tracker-password-provider.h new file mode 100644 index 000000000..87db4025b --- /dev/null +++ b/src/libtracker-miner/tracker-password-provider.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2009, Adrien Bustany (abustany@gnome.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __TRACKER_PASSWORD_PROVIDER_H__ +#define __TRACKER_PASSWORD_PROVIDER_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define TRACKER_TYPE_PASSWORD_PROVIDER (tracker_password_provider_get_type()) +#define TRACKER_PASSWORD_PROVIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_PASSWORD_PROVIDER, TrackerPasswordProvider)) +#define TRACKER_IS_PASSWORD_PROVIDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_PASSWORD_PROVIDER)) +#define TRACKER_PASSWORD_PROVIDER_GET_INTERFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), TRACKER_TYPE_PASSWORD_PROVIDER, TrackerPasswordProviderIface)) + +#define TRACKER_PASSWORD_PROVIDER_ERROR_DOMAIN "TrackerPasswordProvider" +#define TRACKER_PASSWORD_PROVIDER_ERROR tracker_password_provider_error_quark() + +typedef struct TrackerPasswordProvider TrackerPasswordProvider; +typedef struct TrackerPasswordProviderIface TrackerPasswordProviderIface; + +typedef enum { + TRACKER_PASSWORD_PROVIDER_ERROR_SERVICE, + TRACKER_PASSWORD_PROVIDER_ERROR_NOTFOUND +} TrackerPasswordProviderError; + +struct TrackerPasswordProviderIface +{ + GTypeInterface parent_iface; + + void (* store_password) (TrackerPasswordProvider *provider, + const gchar *service, + const gchar *description, + const gchar *username, + const gchar *password, + GError **error); + gchar* (* get_password) (TrackerPasswordProvider *provider, + const gchar *service, + gchar **username, + GError **error); + void (* forget_password) (TrackerPasswordProvider *provider, + const gchar *service, + GError **error); +}; + +GType tracker_password_provider_get_type (void) G_GNUC_CONST; +GQuark tracker_password_provider_error_quark (void); + +gchar* tracker_password_provider_get_name (TrackerPasswordProvider *provider); +/* Must be defined by the selected implementation */ +const TrackerPasswordProvider* + tracker_password_provider_get (void); +void tracker_password_provider_store_password (TrackerPasswordProvider *provider, + const gchar *service, + const gchar *description, + const gchar *username, + const gchar *password, + GError **error); + +gchar* tracker_password_provider_get_password (TrackerPasswordProvider *provider, + const gchar *service, + gchar **username, + GError **error); +void tracker_password_provider_forget_password (TrackerPasswordProvider *provider, + const gchar *service, + GError **error); + +gchar* tracker_password_provider_strdup_mlock (const gchar *source); + +G_END_DECLS + +#endif |