[gnome-online-accounts] Add Flickr



commit 947b7729f9d1202b890062b5142227b71584ec0f
Author: Willem van Engen <gnome willem engen nl>
Date:   Thu Jan 19 00:05:02 2012 +0100

    Add Flickr
    
    There are 2 things that need further investigation.
    
    The perms (or scopes) parameter is specified in the Flickr project
    page because we do not have a way to specify it in our OAuth 1.0
    implementation. We have the get_request_uri_params method but it is
    used when fetching a request token, while Flickr wants it while getting
    the authorization token [1].
    
    Denying access via the OAuth web page takes you to
    http://www.gnome.org/ This is because the "NO, THANKS" widget in the
    web page is an anchor element whose href property is set to the URL
    specified as GNOME's website in Flickr's App Garden. We can not
    intercept the click on this element because the "click" event handler
    is not being called (WebKit bug?).
    
    [1] http://www.flickr.com/services/api/auth.oauth.html#authorization
    
    Fixes: https://bugzilla.gnome.org/678151

 configure.ac                       |   25 +++
 po/POTFILES.in                     |    1 +
 src/goabackend/Makefile.am         |    2 +
 src/goabackend/goabackendtypes.h   |    3 +
 src/goabackend/goaflickrprovider.c |  377 ++++++++++++++++++++++++++++++++++++
 src/goabackend/goaflickrprovider.h |   42 ++++
 src/goabackend/goaprovider.c       |    4 +
 7 files changed, 454 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3f8ca5d..c50fcb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,6 +91,30 @@ if test "$enable_exchange" != "no"; then
   AC_DEFINE(GOA_EXCHANGE_ENABLED, 1, [Enable Microsoft Exchange data provider])
 fi
 
+# Flickr
+AC_ARG_ENABLE([flickr], [AS_HELP_STRING([--enable-flickr], [Enable Flickr provider])], [], [enable_flickr=no])
+AC_ARG_WITH(flickr-consumer-key,
+            [AS_HELP_STRING([--with-flickr-consumer-key],
+                            [Flickr OAuth 1.0 consumer key])],
+                            [],
+                            [])
+AC_ARG_WITH(flickr-consumer-secret,
+            [AS_HELP_STRING([--with-flickr-consumer-secret],
+                            [Flickr OAuth 1.0 consumer secret])],
+                            [],
+                            [])
+if test "$with_flickr_consumer_key" = ""; then
+  with_flickr_consumer_key=ed00ad7e0869897506e23c0d18e34d01
+fi
+if test "$with_flickr_consumer_secret" = ""; then
+  with_flickr_consumer_secret=ebd556dd187188b1
+fi
+AC_DEFINE_UNQUOTED(GOA_FLICKR_CONSUMER_KEY, ["$with_flickr_consumer_key"], [Flickr OAuth 1.0 consumer key])
+AC_DEFINE_UNQUOTED(GOA_FLICKR_CONSUMER_SECRET, ["$with_flickr_consumer_secret"], [Flickr OAuth 1.0 consumer secret])
+if test "$enable_flickr" != "no"; then
+  AC_DEFINE(GOA_FLICKR_ENABLED, 1, [Enable Flickr data provider])
+fi
+
 # Google
 AC_ARG_ENABLE([google], [AS_HELP_STRING([--enable-google], [Enable Google provider])], [], [enable_google=yes])
 AC_ARG_WITH(google-consumer-key,
@@ -344,6 +368,7 @@ echo "
 	cppflags:                       ${CPPFLAGS}
 	introspection:		        ${found_introspection}
 
+	Flickr provider:                ${enable_flickr} (OAuth 1.0, key:${with_flickr_consumer_key} secret:${with_flickr_consumer_secret})
 	Google provider:                ${enable_google} (OAuth 2.0, id:${with_google_client_id} secret:${with_google_client_secret})
 	Microsoft Exchange provider:    ${enable_exchange}
 	Kerberos provider:              ${enable_kerberos}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6986845..23f2944 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,6 +5,7 @@ src/daemon/goadaemon.c
 src/goabackend/goaewsclient.c
 src/goabackend/goaexchangeprovider.c
 src/goabackend/goafacebookprovider.c
+src/goabackend/goaflickrprovider.c
 src/goabackend/goagoogleprovider.c
 src/goabackend/goakerberosprovider.c
 src/goabackend/goaoauth2provider.c
diff --git a/src/goabackend/Makefile.am b/src/goabackend/Makefile.am
index 0f96081..414b3ae 100644
--- a/src/goabackend/Makefile.am
+++ b/src/goabackend/Makefile.am
@@ -55,6 +55,7 @@ libgoa_backend_1_0_la_HEADERS =						\
 	goafacebookprovider.h						\
 	goayahooprovider.h						\
 	goatwitterprovider.h						\
+	goaflickrprovider.h						\
 	goawindowsliveprovider.h					\
 	$(NULL)
 
@@ -78,6 +79,7 @@ libgoa_backend_1_0_la_SOURCES =						\
 	goafacebookprovider.h		goafacebookprovider.c		\
 	goayahooprovider.h		goayahooprovider.c		\
 	goatwitterprovider.h		goatwitterprovider.c		\
+	goaflickrprovider.h		goaflickrprovider.c		\
 	goawindowsliveprovider.h	goawindowsliveprovider.c	\
 	goautils.h			goautils.c			\
 	goaspinnerbutton.h		goaspinnerbutton.c		\
diff --git a/src/goabackend/goabackendtypes.h b/src/goabackend/goabackendtypes.h
index ee8b4bf..af2cc7c 100644
--- a/src/goabackend/goabackendtypes.h
+++ b/src/goabackend/goabackendtypes.h
@@ -63,6 +63,9 @@ typedef struct _GoaYahooProvider GoaYahooProvider;
 struct _GoaTwitterProvider;
 typedef struct _GoaTwitterProvider GoaTwitterProvider;
 
+struct _GoaFlickrProvider;
+typedef struct _GoaFlickrProvider GoaFlickrProvider;
+
 struct _GoaEditableLabel;
 typedef struct _GoaEditableLabel GoaEditableLabel;
 
diff --git a/src/goabackend/goaflickrprovider.c b/src/goabackend/goaflickrprovider.c
new file mode 100644
index 0000000..c2abab4
--- /dev/null
+++ b/src/goabackend/goaflickrprovider.c
@@ -0,0 +1,377 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2011 Willem van Engen <gnome willem engen nl>
+ *
+ * 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 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Willem van Engen <gnome willem engen nl>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <rest/oauth-proxy.h>
+#include <json-glib/json-glib.h>
+
+#include "goaprovider.h"
+#include "goaoauthprovider.h"
+#include "goaflickrprovider.h"
+
+/**
+ * GoaFlickrProvider:
+ *
+ * The #GoaFlickrProvider structure contains only private data and should
+ * only be accessed using the provided API.
+ */
+struct _GoaFlickrProvider
+{
+  /*< private >*/
+  GoaOAuthProvider parent_instance;
+};
+
+typedef struct _GoaFlickrProviderClass GoaFlickrProviderClass;
+
+struct _GoaFlickrProviderClass
+{
+  GoaOAuthProviderClass parent_class;
+};
+
+/**
+ * SECTION:goaflickrprovider
+ * @title: GoaFlickrProvider
+ * @short_description: A provider for Flickr
+ *
+ * #GoaFlickrProvider is used for handling Flickr accounts.
+ */
+
+G_DEFINE_TYPE_WITH_CODE (GoaFlickrProvider, goa_flickr_provider, GOA_TYPE_OAUTH_PROVIDER,
+                         g_io_extension_point_implement (GOA_PROVIDER_EXTENSION_POINT_NAME,
+							 g_define_type_id,
+							 "flickr",
+							 0));
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static const gchar *
+get_provider_type (GoaProvider *_provider)
+{
+  return "flickr";
+}
+
+static gchar *
+get_provider_name (GoaProvider *_provider,
+                   GoaObject   *object)
+{
+  return g_strdup (_("Flickr"));
+}
+
+static const gchar *
+get_consumer_key (GoaOAuthProvider *provider)
+{
+  return GOA_FLICKR_CONSUMER_KEY;
+}
+
+static const gchar *
+get_consumer_secret (GoaOAuthProvider *provider)
+{
+  return GOA_FLICKR_CONSUMER_SECRET;
+}
+
+static const gchar *
+get_request_uri (GoaOAuthProvider *provider)
+{
+  return "http://www.flickr.com/services/oauth/request_token";;
+}
+
+static const gchar *
+get_authorization_uri (GoaOAuthProvider *provider)
+{
+  return "http://www.flickr.com/services/oauth/authorize";;
+}
+
+static const gchar *
+get_token_uri (GoaOAuthProvider *provider)
+{
+  return "http://www.flickr.com/services/oauth/access_token";;
+}
+
+static const gchar *
+get_callback_uri (GoaOAuthProvider *provider)
+{
+  return "https://www.gnome.org/goa-1.0/oauth";;
+}
+
+static const gchar *
+get_authentication_cookie (GoaOAuthProvider *provider)
+{
+  return "cookie_session";
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gchar *
+get_identity_sync (GoaOAuthProvider  *provider,
+                   const gchar       *access_token,
+                   const gchar       *access_token_secret,
+                   gchar            **out_presentation_identity,
+                   GCancellable      *cancellable,
+                   GError           **error)
+{
+  RestProxy *proxy;
+  RestProxyCall *call;
+  JsonParser *parser;
+  JsonObject *json_object;
+  gchar *ret;
+  gchar *id;
+  gchar *presentation_identity;
+
+  ret = NULL;
+  proxy = NULL;
+  call = NULL;
+  parser = NULL;
+  id = NULL;
+  presentation_identity = NULL;
+
+  /* TODO: cancellable */
+
+  proxy = oauth_proxy_new_with_token (goa_oauth_provider_get_consumer_key (provider),
+                                      goa_oauth_provider_get_consumer_secret (provider),
+                                      access_token,
+                                      access_token_secret,
+                                      "http://api.flickr.com/services/rest";,
+                                      FALSE);
+  call = rest_proxy_new_call (proxy);
+  rest_proxy_call_add_param (call, "method", "flickr.test.login");
+  rest_proxy_call_add_param (call, "format", "json");
+  rest_proxy_call_add_param (call, "nojsoncallback", "1");
+  rest_proxy_call_set_method (call, "GET");
+
+  if (!rest_proxy_call_sync (call, error))
+    goto out;
+  if (rest_proxy_call_get_status_code (call) != 200)
+    {
+      g_set_error (error,
+                   GOA_ERROR,
+                   GOA_ERROR_FAILED,
+                   _("Expected status 200 when requesting user id, instead got status %d (%s)"),
+                   rest_proxy_call_get_status_code (call),
+                   rest_proxy_call_get_status_message (call));
+      goto out;
+    }
+
+  parser = json_parser_new ();
+  if (!json_parser_load_from_data (parser,
+                                   rest_proxy_call_get_payload (call),
+                                   rest_proxy_call_get_payload_length (call),
+                                   error))
+    {
+      g_prefix_error (error, _("Error parsing response as JSON: "));
+      goto out;
+    }
+
+  json_object = json_node_get_object (json_parser_get_root (parser));
+  json_object = json_object_get_object_member (json_object, "user");
+  if (json_object == NULL)
+    {
+      g_set_error (error,
+                   GOA_ERROR,
+                   GOA_ERROR_FAILED,
+                   _("Didn't find user member in JSON data"));
+      goto out;
+    }
+  id = g_strdup (json_object_get_string_member (json_object, "id"));
+  if (id == NULL)
+    {
+      g_set_error (error,
+                   GOA_ERROR,
+                   GOA_ERROR_FAILED,
+                   _("Didn't find user.id member in JSON data"));
+      goto out;
+    }
+  json_object = json_object_get_object_member (json_object, "username");
+  if (json_object == NULL)
+    {
+      g_set_error (error,
+                   GOA_ERROR,
+                   GOA_ERROR_FAILED,
+                   _("Didn't find user.username member in JSON data"));
+      goto out;
+    }
+  presentation_identity = g_strdup (json_object_get_string_member (json_object, "_content"));
+  if (presentation_identity == NULL)
+    {
+      g_set_error (error,
+                   GOA_ERROR,
+                   GOA_ERROR_FAILED,
+                   _("Didn't find user.username._content member in JSON data"));
+      goto out;
+    }
+
+  ret = id;
+  id = NULL;
+  if (out_presentation_identity != NULL)
+    {
+      *out_presentation_identity = presentation_identity;
+      presentation_identity = NULL;
+    }
+
+ out:
+  g_free (id);
+  g_free (presentation_identity);
+  if (call != NULL)
+    g_object_unref (call);
+  if (proxy != NULL)
+    g_object_unref (proxy);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+is_deny_node (GoaOAuthProvider *provider, WebKitDOMNode *node)
+{
+  WebKitDOMHTMLElement *element;
+  gboolean ret;
+  gchar *id;
+
+  id = NULL;
+  ret = FALSE;
+
+  if (!WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node))
+    goto out;
+
+  element = WEBKIT_DOM_HTML_ELEMENT (node);
+  id = webkit_dom_html_element_get_id (element);
+  if (g_strcmp0 (id, "auth-disallow") != 0)
+    goto out;
+
+  ret = TRUE;
+
+ out:
+  g_free (id);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gchar *
+parse_request_token_error (GoaOAuthProvider *provider, RestProxyCall *call)
+{
+  const gchar *payload;
+  gchar *msg;
+  guint status;
+
+  msg = NULL;
+
+  payload = rest_proxy_call_get_payload (call);
+  status = rest_proxy_call_get_status_code (call);
+
+  if (status == 401 && g_strcmp0 (payload, "oauth_problem=timestamp_refused") == 0)
+    msg = g_strdup (_("Your system time is invalid. Check your date and time settings."));
+
+  return msg;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+build_object (GoaProvider         *provider,
+              GoaObjectSkeleton   *object,
+              GKeyFile            *key_file,
+              const gchar         *group,
+              GDBusConnection     *connection,
+              gboolean             just_added,
+              GError             **error)
+{
+  gboolean ret;
+  ret = FALSE;
+
+  /* Chain up */
+  if (!GOA_PROVIDER_CLASS (goa_flickr_provider_parent_class)->build_object (provider,
+                                                                            object,
+                                                                            key_file,
+                                                                            group,
+                                                                            connection,
+                                                                            just_added,
+                                                                            error))
+    goto out;
+
+  ret = TRUE;
+
+ out:
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+get_use_external_browser (GoaOAuthProvider *provider)
+{
+  /* For some reason this only works in a browser - bad callback URL? TODO: investigate */
+  return FALSE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+show_account (GoaProvider         *provider,
+              GoaClient           *client,
+              GoaObject           *object,
+              GtkBox              *vbox,
+              GtkGrid             *left,
+              GtkGrid             *right)
+{
+  /* Chain up */
+  GOA_PROVIDER_CLASS (goa_flickr_provider_parent_class)->show_account (provider,
+                                                                       client,
+                                                                       object,
+                                                                       vbox,
+                                                                       left,
+                                                                       right);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+goa_flickr_provider_init (GoaFlickrProvider *client)
+{
+}
+
+static void
+goa_flickr_provider_class_init (GoaFlickrProviderClass *klass)
+{
+  GoaProviderClass *provider_class;
+  GoaOAuthProviderClass *oauth_class;
+
+  provider_class = GOA_PROVIDER_CLASS (klass);
+  provider_class->get_provider_type     = get_provider_type;
+  provider_class->get_provider_name     = get_provider_name;
+  provider_class->build_object          = build_object;
+  provider_class->show_account          = show_account;
+
+  oauth_class = GOA_OAUTH_PROVIDER_CLASS (klass);
+  oauth_class->get_identity_sync        = get_identity_sync;
+  oauth_class->is_deny_node             = is_deny_node;
+  oauth_class->get_consumer_key         = get_consumer_key;
+  oauth_class->get_consumer_secret      = get_consumer_secret;
+  oauth_class->get_request_uri          = get_request_uri;
+  oauth_class->get_authorization_uri    = get_authorization_uri;
+  oauth_class->get_token_uri            = get_token_uri;
+  oauth_class->get_callback_uri         = get_callback_uri;
+  oauth_class->get_authentication_cookie = get_authentication_cookie;
+  oauth_class->get_use_external_browser = get_use_external_browser;
+  oauth_class->parse_request_token_error = parse_request_token_error;
+}
diff --git a/src/goabackend/goaflickrprovider.h b/src/goabackend/goaflickrprovider.h
new file mode 100644
index 0000000..11bd533
--- /dev/null
+++ b/src/goabackend/goaflickrprovider.h
@@ -0,0 +1,42 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2012 Willem van Engen <gnome willem engen nl>
+ *
+ * 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 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Willem van Engen <gnome willem engen nl>
+ */
+
+#if !defined (__GOA_BACKEND_INSIDE_GOA_BACKEND_H__) && !defined (GOA_BACKEND_COMPILATION)
+#error "Only <goabackend/goabackend.h> can be included directly."
+#endif
+
+#ifndef __GOA_FLICKR_PROVIDER_H__
+#define __GOA_FLICKR_PROVIDER_H__
+
+#include <goabackend/goabackendtypes.h>
+
+G_BEGIN_DECLS
+
+#define GOA_TYPE_FLICKR_PROVIDER   (goa_flickr_provider_get_type ())
+#define GOA_FLICKR_PROVIDER(o)     (G_TYPE_CHECK_INSTANCE_CAST ((o), GOA_TYPE_FLICKR_PROVIDER, GoaFlickrProvider))
+#define GOA_IS_FLICKR_PROVIDER(o)  (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOA_TYPE_FLICKR_PROVIDER))
+
+GType goa_flickr_provider_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GOA_FLICKR_PROVIDER_H__ */
diff --git a/src/goabackend/goaprovider.c b/src/goabackend/goaprovider.c
index acfdd1a..b052e94 100644
--- a/src/goabackend/goaprovider.c
+++ b/src/goabackend/goaprovider.c
@@ -32,6 +32,7 @@
 #include "goafacebookprovider.h"
 #include "goayahooprovider.h"
 #include "goatwitterprovider.h"
+#include "goaflickrprovider.h"
 #include "goawindowsliveprovider.h"
 
 #ifdef GOA_KERBEROS_ENABLED
@@ -624,6 +625,9 @@ ensure_ep_and_builtins (void)
 #ifdef GOA_FACEBOOK_ENABLED
       type = GOA_TYPE_FACEBOOK_PROVIDER;
 #endif
+#ifdef GOA_FLICKR_ENABLED
+      type = GOA_TYPE_FLICKR_PROVIDER;
+#endif
 #ifdef GOA_WINDOWS_LIVE_ENABLED
       type = GOA_TYPE_WINDOWS_LIVE_PROVIDER;
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]