diff options
author | Ross Burton <ross@linux.intel.com> | 2009-10-08 15:30:40 +0100 |
---|---|---|
committer | Ross Burton <ross@linux.intel.com> | 2009-10-08 15:30:40 +0100 |
commit | b7b09e3921c29d2af891382e5c905436984db13e (patch) | |
tree | dd250c86bcef049d5cbee3a0907d6833fddf7558 /rest-extras | |
parent | bd0adec30e6f1e73a08c365902268e486529c07d (diff) |
Split the Facebook and Flickr backends to librest-extras
Diffstat (limited to 'rest-extras')
-rw-r--r-- | rest-extras/Makefile.am | 36 | ||||
-rw-r--r-- | rest-extras/facebook-proxy-call.c | 88 | ||||
-rw-r--r-- | rest-extras/facebook-proxy-call.h | 67 | ||||
-rw-r--r-- | rest-extras/facebook-proxy-private.h | 33 | ||||
-rw-r--r-- | rest-extras/facebook-proxy.c | 354 | ||||
-rw-r--r-- | rest-extras/facebook-proxy.h | 93 | ||||
-rw-r--r-- | rest-extras/flickr-proxy-call.c | 80 | ||||
-rw-r--r-- | rest-extras/flickr-proxy-call.h | 68 | ||||
-rw-r--r-- | rest-extras/flickr-proxy-private.h | 33 | ||||
-rw-r--r-- | rest-extras/flickr-proxy.c | 407 | ||||
-rw-r--r-- | rest-extras/flickr-proxy.h | 94 | ||||
-rw-r--r-- | rest-extras/test-runner.c | 35 |
12 files changed, 1388 insertions, 0 deletions
diff --git a/rest-extras/Makefile.am b/rest-extras/Makefile.am new file mode 100644 index 0000000..e59e235 --- /dev/null +++ b/rest-extras/Makefile.am @@ -0,0 +1,36 @@ +lib_sources = \ + flickr-proxy.c \ + flickr-proxy-call.c \ + flickr-proxy-private.h \ + facebook-proxy.c \ + facebook-proxy-call.c \ + facebook-proxy-private.h +lib_headers = \ + flickr-proxy.h \ + flickr-proxy-call.h \ + facebook-proxy.h \ + facebook-proxy-call.h + + +lib_LTLIBRARIES = librest-extras-@API_VERSION@.la +librest_extras_@API_VERSION@_la_CFLAGS = $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) \ + $(SOUP_CFLAGS) $(SOUP_GNOME_CFLAGS) \ + $(XML_CFLAGS) \ + -I$(top_srcdir) -Wall -DG_LOG_DOMAIN=\"Rest\" +librest_extras_@API_VERSION@_la_LIBADD = $(GLIB_LIBS) $(GTHREAD_LIBS) \ + $(SOUP_LIBS) $(SOUP_GNOME_LIBS) $(XML_LIBS) \ + $(top_builddir)/rest/librest-@API_VERSION@.la +librest_extras_@API_VERSION@_la_SOURCES = $(lib_sources) $(lib_headers) +librest_extras_@API_VERSION@_la_HEADERS = $(lib_headers) +librest_extras_@API_VERSION@_ladir = $(includedir)/rest-@API_VERSION@/rest-extras + + +# Test suite +TESTS = test-runner +check_PROGRAMS = test-runner + +test_runner_SOURCES = test-runner.c $(lib_sources) $(lib_headers) +test_runner_CFLAGS = -DBUILD_TESTS $(librest_extras_@API_VERSION@_la_CFLAGS) +test_runner_LDFLAGS = $(librest_extras_@API_VERSION@_la_LIBADD) + +# TODO: use gtester diff --git a/rest-extras/facebook-proxy-call.c b/rest-extras/facebook-proxy-call.c new file mode 100644 index 0000000..353f119 --- /dev/null +++ b/rest-extras/facebook-proxy-call.c @@ -0,0 +1,88 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <string.h> +#include <libsoup/soup.h> +#include <rest/rest-proxy-call.h> +#include "facebook-proxy-call.h" +#include "facebook-proxy-private.h" +#include "rest/rest-proxy-call-private.h" +#include "rest/sha1.h" + +G_DEFINE_TYPE (FacebookProxyCall, facebook_proxy_call, REST_TYPE_PROXY_CALL) + +static gboolean +_prepare (RestProxyCall *call, GError **error) +{ + FacebookProxy *proxy = NULL; + FacebookProxyPrivate *priv; + RestProxyCallPrivate *call_priv; + char *s; + + g_object_get (call, "proxy", &proxy, NULL); + priv = PROXY_GET_PRIVATE (proxy); + call_priv = call->priv; + + /* First reset the URL because Facebook puts the function in the parameters */ + g_object_get (proxy, "url-format", &call_priv->url, NULL); + + rest_proxy_call_add_params (call, + "method", call_priv->function, + "api_key", priv->api_key, + "v", "1.0", + NULL); + + if (priv->session_key) { + GTimeVal time; + g_get_current_time (&time); + s = g_strdup_printf ("%ld.%ld", time.tv_sec, time.tv_usec); + rest_proxy_call_add_param (call, "call_id", s); + g_free (s); + + rest_proxy_call_add_param (call, "session_key", priv->session_key); + } + + s = facebook_proxy_sign (proxy, call_priv->params); + rest_proxy_call_add_param (call, "sig", s); + g_free (s); + + g_object_unref (proxy); + + return TRUE; +} + +static void +facebook_proxy_call_class_init (FacebookProxyCallClass *klass) +{ + RestProxyCallClass *call_class = REST_PROXY_CALL_CLASS (klass); + + call_class->prepare = _prepare; +} + +static void +facebook_proxy_call_init (FacebookProxyCall *self) +{ +} + +#if BUILD_TESTS +#warning TODO facebook signature test cases +#endif diff --git a/rest-extras/facebook-proxy-call.h b/rest-extras/facebook-proxy-call.h new file mode 100644 index 0000000..9f97ad7 --- /dev/null +++ b/rest-extras/facebook-proxy-call.h @@ -0,0 +1,67 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FACEBOOK_PROXY_CALL +#define _FACEBOOK_PROXY_CALL + +#include <rest/rest-proxy-call.h> + +G_BEGIN_DECLS + +#define FACEBOOK_TYPE_PROXY_CALL facebook_proxy_call_get_type() + +#define FACEBOOK_PROXY_CALL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), FACEBOOK_TYPE_PROXY_CALL, FacebookProxyCall)) + +#define FACEBOOK_PROXY_CALL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), FACEBOOK_TYPE_PROXY_CALL, FacebookProxyCallClass)) + +#define FACEBOOK_IS_PROXY_CALL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FACEBOOK_TYPE_PROXY_CALL)) + +#define FACEBOOK_IS_PROXY_CALL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), FACEBOOK_TYPE_PROXY_CALL)) + +#define FACEBOOK_PROXY_CALL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), FACEBOOK_TYPE_PROXY_CALL, FacebookProxyCallClass)) + +/** + * FacebookProxyCall: + * + * #FacebookProxyCall has no publicly available members. + */ +typedef struct { + RestProxyCall parent; +} FacebookProxyCall; + +typedef struct { + RestProxyCallClass parent_class; + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +} FacebookProxyCallClass; + +GType facebook_proxy_call_get_type (void); + +G_END_DECLS + +#endif /* _FACEBOOK_PROXY_CALL */ diff --git a/rest-extras/facebook-proxy-private.h b/rest-extras/facebook-proxy-private.h new file mode 100644 index 0000000..0f652a6 --- /dev/null +++ b/rest-extras/facebook-proxy-private.h @@ -0,0 +1,33 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "facebook-proxy.h" + +#define PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), FACEBOOK_TYPE_PROXY, FacebookProxyPrivate)) + +struct _FacebookProxyPrivate { + char *api_key; + char *app_secret; + char *session_key; +}; + diff --git a/rest-extras/facebook-proxy.c b/rest-extras/facebook-proxy.c new file mode 100644 index 0000000..2ca5490 --- /dev/null +++ b/rest-extras/facebook-proxy.c @@ -0,0 +1,354 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <config.h> +#include <string.h> +#include <rest/rest-proxy.h> +#include <libsoup/soup.h> +#include "facebook-proxy.h" +#include "facebook-proxy-private.h" +#include "facebook-proxy-call.h" + +G_DEFINE_TYPE (FacebookProxy, facebook_proxy, REST_TYPE_PROXY) + +enum { + PROP_0, + PROP_API_KEY, + PROP_APP_SECRET, + PROP_SESSION_KEY, +}; + +static RestProxyCall * +_new_call (RestProxy *proxy) +{ + RestProxyCall *call; + + call = g_object_new (FACEBOOK_TYPE_PROXY_CALL, + "proxy", proxy, + NULL); + + return call; +} + +static void +facebook_proxy_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + FacebookProxyPrivate *priv = PROXY_GET_PRIVATE (object); + + switch (property_id) { + case PROP_API_KEY: + g_value_set_string (value, priv->api_key); + break; + case PROP_APP_SECRET: + g_value_set_string (value, priv->app_secret); + break; + case PROP_SESSION_KEY: + g_value_set_string (value, priv->session_key); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +facebook_proxy_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + FacebookProxyPrivate *priv = PROXY_GET_PRIVATE (object); + + switch (property_id) { + case PROP_API_KEY: + if (priv->api_key) + g_free (priv->api_key); + priv->api_key = g_value_dup_string (value); + break; + case PROP_APP_SECRET: + if (priv->app_secret) + g_free (priv->app_secret); + priv->app_secret = g_value_dup_string (value); + break; + case PROP_SESSION_KEY: + if (priv->session_key); + g_free (priv->session_key); + priv->session_key = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +facebook_proxy_finalize (GObject *object) +{ + FacebookProxyPrivate *priv = PROXY_GET_PRIVATE (object); + + g_free (priv->api_key); + g_free (priv->app_secret); + g_free (priv->session_key); + + G_OBJECT_CLASS (facebook_proxy_parent_class)->finalize (object); +} + +#ifndef G_PARAM_STATIC_STRINGS +#define G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB) +#endif + +static void +facebook_proxy_class_init (FacebookProxyClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + RestProxyClass *proxy_class = REST_PROXY_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (FacebookProxyPrivate)); + + object_class->get_property = facebook_proxy_get_property; + object_class->set_property = facebook_proxy_set_property; + object_class->finalize = facebook_proxy_finalize; + + proxy_class->new_call = _new_call; + + pspec = g_param_spec_string ("api-key", "api-key", + "The API key", NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_API_KEY, + pspec); + + pspec = g_param_spec_string ("app-secret", "app-secret", + "The application secret", NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_APP_SECRET, + pspec); + + pspec = g_param_spec_string ("session-key", "session-key", + "The session key", NULL, + G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_SESSION_KEY, + pspec); +} + +static void +facebook_proxy_init (FacebookProxy *self) +{ + self->priv = PROXY_GET_PRIVATE (self); +} + +RestProxy * +facebook_proxy_new (const char *api_key, + const char *app_secret) +{ + return facebook_proxy_new_with_session (api_key, + app_secret, + NULL); +} + +RestProxy * +facebook_proxy_new_with_session (const char *api_key, + const char *app_secret, + const char *session_key) +{ + return g_object_new (FACEBOOK_TYPE_PROXY, + "api-key", api_key, + "app-secret", app_secret, + "session-key", session_key, + "url-format", "https://api.facebook.com/restserver.php", + "binding-required", FALSE, + NULL); +} + +/** + * facebook_proxy_get_api_key: + * @proxy: an #FacebookProxy + * + * Get the API key. + * + * Returns: the API key. This string is owned by #FacebookProxy and should not be + * freed. + */ +const char * +facebook_proxy_get_api_key (FacebookProxy *proxy) +{ + FacebookProxyPrivate *priv = PROXY_GET_PRIVATE (proxy); + return priv->api_key; +} + +/** + * facebook_proxy_get_app_secret: + * @proxy: an #FacebookProxy + * + * Get the application secret for authentication. + * + * Returns: the application secret. This string is owned by #FacebookProxy and should not be + * freed. + */ +const char * +facebook_proxy_get_app_secret (FacebookProxy *proxy) +{ + FacebookProxyPrivate *priv = PROXY_GET_PRIVATE (proxy); + return priv->app_secret; +} + +void +facebook_proxy_set_app_secret (FacebookProxy *proxy, const char *secret) +{ + FacebookProxyPrivate *priv; + + g_return_if_fail (FACEBOOK_IS_PROXY (proxy)); + priv = PROXY_GET_PRIVATE (proxy); + + if (priv->app_secret) + g_free (priv->app_secret); + + priv->app_secret = g_strdup (secret); +} + +/** + * facebook_proxy_get_session_key: + * @proxy: an #FacebookProxy + * + * Get the current session key + * + * Returns: the session key, or %NULL if there is no session yet. This string is owned + * by #FacebookProxy and should not be freed. + */ +const char * +facebook_proxy_get_session_key (FacebookProxy *proxy) +{ + FacebookProxyPrivate *priv = PROXY_GET_PRIVATE (proxy); + return priv->session_key; +} + +/** + * facebook_proxy_set_session_key: + * @proxy: an #FacebookProxy + * @session_key: the session key + * + * Set the token. + */ +void +facebook_proxy_set_session_key (FacebookProxy *proxy, const char *session_key) +{ + FacebookProxyPrivate *priv; + + g_return_if_fail (FACEBOOK_IS_PROXY (proxy)); + priv = PROXY_GET_PRIVATE (proxy); + + if (priv->session_key) + g_free (priv->session_key); + + priv->session_key = g_strdup (session_key); +} + +char * +facebook_proxy_sign (FacebookProxy *proxy, GHashTable *params) +{ + FacebookProxyPrivate *priv; + GString *s; + GList *keys; + char *md5; + + g_return_val_if_fail (FACEBOOK_IS_PROXY (proxy), NULL); + g_return_val_if_fail (params, NULL); + + priv = PROXY_GET_PRIVATE (proxy); + + s = g_string_new (NULL); + + keys = g_hash_table_get_keys (params); + keys = g_list_sort (keys, (GCompareFunc)strcmp); + + while (keys) { + const char *key; + const char *value; + + key = keys->data; + value = g_hash_table_lookup (params, key); + + g_string_append_printf (s, "%s=%s", key, value); + + keys = keys->next; + } + + g_string_append (s, priv->app_secret); + + md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, s->str, s->len); + + g_string_free (s, TRUE); + + return md5; +} + +char * +facebook_proxy_build_login_url (FacebookProxy *proxy, const char *token) +{ + SoupURI *uri; + GHashTable *params; + char *s; + + g_return_val_if_fail (FACEBOOK_IS_PROXY (proxy), NULL); + g_return_val_if_fail (token, NULL); + + uri = soup_uri_new ("http://facebook.com/login.php/"); + params = g_hash_table_new (g_str_hash, g_str_equal); + + g_hash_table_insert (params, "api_key", proxy->priv->api_key); + g_hash_table_insert (params, "v", "1.0"); + g_hash_table_insert (params, "auth_token", (gpointer)token); + + soup_uri_set_query_from_form (uri, params); + + s = soup_uri_to_string (uri, FALSE); + + g_hash_table_unref (params); + soup_uri_free (uri); + return s; +} + +char * +facebook_proxy_build_permission_url (FacebookProxy *proxy, const char *perms) +{ + SoupURI *uri; + GHashTable *params; + char *s; + + g_return_val_if_fail (FACEBOOK_IS_PROXY (proxy), NULL); + g_return_val_if_fail (perms, NULL); + + uri = soup_uri_new ("http://facebook.com/authorize.php"); + params = g_hash_table_new (g_str_hash, g_str_equal); + + g_hash_table_insert (params, "api_key", proxy->priv->api_key); + g_hash_table_insert (params, "v", "1.0"); + g_hash_table_insert (params, "ext_perm", (gpointer)perms); + + soup_uri_set_query_from_form (uri, params); + + s = soup_uri_to_string (uri, FALSE); + + g_hash_table_unref (params); + soup_uri_free (uri); + return s; +} diff --git a/rest-extras/facebook-proxy.h b/rest-extras/facebook-proxy.h new file mode 100644 index 0000000..cdee905 --- /dev/null +++ b/rest-extras/facebook-proxy.h @@ -0,0 +1,93 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FACEBOOK_PROXY +#define _FACEBOOK_PROXY + +#include <rest/rest-proxy.h> + +G_BEGIN_DECLS + +#define FACEBOOK_TYPE_PROXY facebook_proxy_get_type() + +#define FACEBOOK_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), FACEBOOK_TYPE_PROXY, FacebookProxy)) + +#define FACEBOOK_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), FACEBOOK_TYPE_PROXY, FacebookProxyClass)) + +#define FACEBOOK_IS_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FACEBOOK_TYPE_PROXY)) + +#define FACEBOOK_IS_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), FACEBOOK_TYPE_PROXY)) + +#define FACEBOOK_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), FACEBOOK_TYPE_PROXY, FacebookProxyClass)) + +typedef struct _FacebookProxyPrivate FacebookProxyPrivate; + +/** + * FacebookProxy: + * + * #FacebookProxy has no publicly available members. + */ +typedef struct { + RestProxy parent; + FacebookProxyPrivate *priv; +} FacebookProxy; + +typedef struct { + RestProxyClass parent_class; + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +} FacebookProxyClass; + +GType facebook_proxy_get_type (void); + +RestProxy* facebook_proxy_new (const char *api_key, + const char *app_secret); + +RestProxy* facebook_proxy_new_with_session (const char *api_key, + const char *app_secret, + const char *session_key); + +const char * facebook_proxy_get_api_key (FacebookProxy *proxy); + +void facebook_proxy_set_app_secret (FacebookProxy *proxy, const char *secret); + +const char * facebook_proxy_get_app_secret (FacebookProxy *proxy); + +const char * facebook_proxy_get_session_key (FacebookProxy *proxy); + +void facebook_proxy_set_session_key (FacebookProxy *proxy, const char *session_key); + +char * facebook_proxy_sign (FacebookProxy *proxy, GHashTable *params); + +char * facebook_proxy_build_login_url (FacebookProxy *proxy, const char *frob); + +char * facebook_proxy_build_permission_url (FacebookProxy *proxy, const char *perms); + +G_END_DECLS + +#endif /* _FACEBOOK_PROXY */ diff --git a/rest-extras/flickr-proxy-call.c b/rest-extras/flickr-proxy-call.c new file mode 100644 index 0000000..a408925 --- /dev/null +++ b/rest-extras/flickr-proxy-call.c @@ -0,0 +1,80 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <string.h> +#include <libsoup/soup.h> +#include <rest/rest-proxy-call.h> +#include "flickr-proxy-call.h" +#include "flickr-proxy-private.h" +#include "rest/rest-proxy-call-private.h" +#include "rest/sha1.h" + +G_DEFINE_TYPE (FlickrProxyCall, flickr_proxy_call, REST_TYPE_PROXY_CALL) + +static gboolean +_prepare (RestProxyCall *call, GError **error) +{ + FlickrProxy *proxy = NULL; + FlickrProxyPrivate *priv; + RestProxyCallPrivate *call_priv; + char *s; + + g_object_get (call, "proxy", &proxy, NULL); + priv = PROXY_GET_PRIVATE (proxy); + call_priv = call->priv; + + /* First reset the URL because Flickr puts the function in the parameters */ + call_priv->url = g_strdup ("http://api.flickr.com/services/rest/"); + + rest_proxy_call_add_params (call, + "method", call_priv->function, + "api_key", priv->api_key, + NULL); + + if (priv->token) + rest_proxy_call_add_param (call, "auth_token", priv->token); + + s = flickr_proxy_sign (proxy, call_priv->params); + rest_proxy_call_add_param (call, "api_sig", s); + g_free (s); + + g_object_unref (proxy); + + return TRUE; +} + +static void +flickr_proxy_call_class_init (FlickrProxyCallClass *klass) +{ + RestProxyCallClass *call_class = REST_PROXY_CALL_CLASS (klass); + + call_class->prepare = _prepare; +} + +static void +flickr_proxy_call_init (FlickrProxyCall *self) +{ +} + +#if BUILD_TESTS +#warning TODO flickr signature test cases +#endif diff --git a/rest-extras/flickr-proxy-call.h b/rest-extras/flickr-proxy-call.h new file mode 100644 index 0000000..195886e --- /dev/null +++ b/rest-extras/flickr-proxy-call.h @@ -0,0 +1,68 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FLICKR_PROXY_CALL +#define _FLICKR_PROXY_CALL + +#include <rest/rest-proxy-call.h> + +G_BEGIN_DECLS + +#define FLICKR_TYPE_PROXY_CALL flickr_proxy_call_get_type() + +#define FLICKR_PROXY_CALL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLICKR_TYPE_PROXY_CALL, FlickrProxyCall)) + +#define FLICKR_PROXY_CALL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), FLICKR_TYPE_PROXY_CALL, FlickrProxyCallClass)) + +#define FLICKR_IS_PROXY_CALL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLICKR_TYPE_PROXY_CALL)) + +#define FLICKR_IS_PROXY_CALL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), FLICKR_TYPE_PROXY_CALL)) + +#define FLICKR_PROXY_CALL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), FLICKR_TYPE_PROXY_CALL, FlickrProxyCallClass)) + +/** + * FlickrProxyCall: + * + * #FlickrProxyCall has no publicly available members. + */ +typedef struct { + RestProxyCall parent; +} FlickrProxyCall; + +typedef struct { + RestProxyCallClass parent_class; + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +} FlickrProxyCallClass; + +GType flickr_proxy_call_get_type (void); + +G_END_DECLS + +#endif /* _FLICKR_PROXY_CALL */ + diff --git a/rest-extras/flickr-proxy-private.h b/rest-extras/flickr-proxy-private.h new file mode 100644 index 0000000..cbf8533 --- /dev/null +++ b/rest-extras/flickr-proxy-private.h @@ -0,0 +1,33 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "flickr-proxy.h" + +#define PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), FLICKR_TYPE_PROXY, FlickrProxyPrivate)) + +struct _FlickrProxyPrivate { + char *api_key; + char *shared_secret; + char *token; +}; + diff --git a/rest-extras/flickr-proxy.c b/rest-extras/flickr-proxy.c new file mode 100644 index 0000000..38ff330 --- /dev/null +++ b/rest-extras/flickr-proxy.c @@ -0,0 +1,407 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * TODO: + * + * Convenience API for authentication so that the user doesn't have to parse the + * XML themselves. + * + * Function to parse a payload and return either a xml document or a GError. + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> +#include <rest/rest-proxy.h> +#include <libsoup/soup.h> +#include "flickr-proxy.h" +#include "flickr-proxy-private.h" +#include "flickr-proxy-call.h" + +G_DEFINE_TYPE (FlickrProxy, flickr_proxy, REST_TYPE_PROXY) + +enum { + PROP_0, + PROP_API_KEY, + PROP_SHARED_SECRET, + PROP_TOKEN, +}; + +GQuark +flickr_proxy_error_quark (void) +{ + return g_quark_from_static_string ("rest-flickr-proxy"); +} + +static RestProxyCall * +_new_call (RestProxy *proxy) +{ + RestProxyCall *call; + + call = g_object_new (FLICKR_TYPE_PROXY_CALL, + "proxy", proxy, + NULL); + + return call; +} + +static void +flickr_proxy_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + FlickrProxyPrivate *priv = PROXY_GET_PRIVATE (object); + + switch (property_id) { + case PROP_API_KEY: + g_value_set_string (value, priv->api_key); + break; + case PROP_SHARED_SECRET: + g_value_set_string (value, priv->shared_secret); + break; + case PROP_TOKEN: + g_value_set_string (value, priv->token); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +flickr_proxy_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + FlickrProxyPrivate *priv = PROXY_GET_PRIVATE (object); + + switch (property_id) { + case PROP_API_KEY: + if (priv->api_key) + g_free (priv->api_key); + priv->api_key = g_value_dup_string (value); + break; + case PROP_SHARED_SECRET: + if (priv->shared_secret) + g_free (priv->shared_secret); + priv->shared_secret = g_value_dup_string (value); + break; + case PROP_TOKEN: + if (priv->token) + g_free (priv->token); + priv->token = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +flickr_proxy_finalize (GObject *object) +{ + FlickrProxyPrivate *priv = PROXY_GET_PRIVATE (object); + + g_free (priv->api_key); + g_free (priv->shared_secret); + g_free (priv->token); + + G_OBJECT_CLASS (flickr_proxy_parent_class)->finalize (object); +} + +#ifndef G_PARAM_STATIC_STRINGS +#define G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB) +#endif + +static void +flickr_proxy_class_init (FlickrProxyClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + RestProxyClass *proxy_class = REST_PROXY_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (FlickrProxyPrivate)); + + object_class->get_property = flickr_proxy_get_property; + object_class->set_property = flickr_proxy_set_property; + object_class->finalize = flickr_proxy_finalize; + + proxy_class->new_call = _new_call; + + pspec = g_param_spec_string ("api-key", "api-key", + "The API key", NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_API_KEY, + pspec); + + pspec = g_param_spec_string ("shared-secret", "shared-secret", + "The shared secret", NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_SHARED_SECRET, + pspec); + + pspec = g_param_spec_string ("token", "token", + "The request or access token", NULL, + G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_TOKEN, + pspec); +} + +static void +flickr_proxy_init (FlickrProxy *self) +{ + self->priv = PROXY_GET_PRIVATE (self); +} + +RestProxy * +flickr_proxy_new (const char *api_key, + const char *shared_secret) +{ + return flickr_proxy_new_with_token (api_key, + shared_secret, + NULL); +} + +RestProxy * +flickr_proxy_new_with_token (const char *api_key, + const char *shared_secret, + const char *token) +{ + return g_object_new (FLICKR_TYPE_PROXY, + "api-key", api_key, + "shared-secret", shared_secret, + "token", token, + "url-format", "http://api.flickr.com/services/rest/", + "binding-required", FALSE, + NULL); +} + +/** + * flickr_proxy_get_api_key: + * @proxy: an #FlickrProxy + * + * Get the API key. + * + * Returns: the API key. This string is owned by #FlickrProxy and should not be + * freed. + */ +const char * +flickr_proxy_get_api_key (FlickrProxy *proxy) +{ + FlickrProxyPrivate *priv = PROXY_GET_PRIVATE (proxy); + return priv->api_key; +} + +/** + * flickr_proxy_get_shared_secret: + * @proxy: an #FlickrProxy + * + * Get the shared secret for authentication. + * + * Returns: the shared secret. This string is owned by #FlickrProxy and should not be + * freed. + */ +const char * +flickr_proxy_get_shared_secret (FlickrProxy *proxy) +{ + FlickrProxyPrivate *priv = PROXY_GET_PRIVATE (proxy); + return priv->shared_secret; +} + +/** + * flickr_proxy_get_token: + * @proxy: an #FlickrProxy + * + * Get the current token. + * + * Returns: the token, or %NULL if there is no token yet. This string is owned + * by #FlickrProxy and should not be freed. + */ +const char * +flickr_proxy_get_token (FlickrProxy *proxy) +{ + FlickrProxyPrivate *priv = PROXY_GET_PRIVATE (proxy); + return priv->token; +} + +/** + * flickr_proxy_set_token: + * @proxy: an #FlickrProxy + * @token: the access token + * + * Set the token. + */ +void +flickr_proxy_set_token (FlickrProxy *proxy, const char *token) +{ + FlickrProxyPrivate *priv; + + g_return_if_fail (FLICKR_IS_PROXY (proxy)); + priv = PROXY_GET_PRIVATE (proxy); + + if (priv->token) + g_free (priv->token); + + priv->token = g_strdup (token); +} + +char * +flickr_proxy_sign (FlickrProxy *proxy, GHashTable *params) +{ + FlickrProxyPrivate *priv; + GString *s; + GList *keys; + char *md5; + + g_return_val_if_fail (FLICKR_IS_PROXY (proxy), NULL); + g_return_val_if_fail (params, NULL); + + priv = PROXY_GET_PRIVATE (proxy); + + s = g_string_new (priv->shared_secret); + + keys = g_hash_table_get_keys (params); + keys = g_list_sort (keys, (GCompareFunc)strcmp); + + while (keys) { + const char *key; + const char *value; + + key = keys->data; + value = g_hash_table_lookup (params, key); + + g_string_append_printf (s, "%s%s", key, value); + + keys = g_list_delete_link (keys, keys); + } + + md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, s->str, s->len); + + g_string_free (s, TRUE); + + return md5; +} + +char * +flickr_proxy_build_login_url (FlickrProxy *proxy, const char *frob) +{ + SoupURI *uri; + GHashTable *params; + char *sig, *s; + + g_return_val_if_fail (FLICKR_IS_PROXY (proxy), NULL); + + uri = soup_uri_new ("http://flickr.com/services/auth/"); + params = g_hash_table_new (g_str_hash, g_str_equal); + + g_hash_table_insert (params, "api_key", proxy->priv->api_key); + /* TODO: parameter */ + g_hash_table_insert (params, "perms", "read"); + if (frob) + g_hash_table_insert (params, "frob", (gpointer)frob); + + sig = flickr_proxy_sign (proxy, params); + g_hash_table_insert (params, "api_sig", sig); + + soup_uri_set_query_from_form (uri, params); + + s = soup_uri_to_string (uri, FALSE); + + g_free (sig); + g_hash_table_destroy (params); + soup_uri_free (uri); + + return s; +} + +/** + * flickr_proxy_is_successful: + * @root: The root node of a parsed Flickr response + * @error: #GError to set if the response was an error + * + * Examines the Flickr response and if it not a successful reply, set @error and + * return FALSE. + * + * Returns: %TRUE if this response is successful, %FALSE otherwise. + */ +gboolean +flickr_proxy_is_successful (RestXmlNode *root, GError **error) +{ + RestXmlNode *node; + + g_return_val_if_fail (root, FALSE); + + if (strcmp (root->name, "rsp") != 0) { + g_set_error (error, FLICKR_PROXY_ERROR, 0, + "Unexpected response from Flickr (root node %s)", + root->name); + return FALSE; + } + + if (strcmp (rest_xml_node_get_attr (root, "stat"), "ok") != 0) { + node = rest_xml_node_find (root, "err"); + g_set_error_literal (error,FLICKR_PROXY_ERROR, + atoi (rest_xml_node_get_attr (node, "code")), + rest_xml_node_get_attr (node, "msg")); + return FALSE; + } + + return TRUE; +} + +#if BUILD_TESTS +void +test_flickr_error (void) +{ + RestXmlParser *parser; + RestXmlNode *root; + GError *error; + const char test_1[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<rsp stat=\"ok\"><auth></auth></rsp>"; + const char test_2[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<foobar/>"; + const char test_3[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<rsp stat=\"fail\"><err code=\"108\" msg=\"Invalid frob\" /></rsp>"; + + parser = rest_xml_parser_new (); + + root = rest_xml_parser_parse_from_data (parser, test_1, sizeof (test_1) - 1); + error = NULL; + flickr_proxy_is_successful (root, &error); + g_assert_no_error (error); + rest_xml_node_unref (root); + + error = NULL; + root = rest_xml_parser_parse_from_data (parser, test_2, sizeof (test_2) - 1); + flickr_proxy_is_successful (root, &error); + g_assert_error (error, FLICKR_PROXY_ERROR, 0); + g_error_free (error); + rest_xml_node_unref (root); + + error = NULL; + root = rest_xml_parser_parse_from_data (parser, test_3, sizeof (test_3) - 1); + flickr_proxy_is_successful (root, &error); + g_assert_error (error, FLICKR_PROXY_ERROR, 108); + g_error_free (error); + rest_xml_node_unref (root); +} +#endif diff --git a/rest-extras/flickr-proxy.h b/rest-extras/flickr-proxy.h new file mode 100644 index 0000000..736056c --- /dev/null +++ b/rest-extras/flickr-proxy.h @@ -0,0 +1,94 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _FLICKR_PROXY +#define _FLICKR_PROXY + +#include <rest/rest-proxy.h> +#include <rest/rest-xml-parser.h> + +G_BEGIN_DECLS + +#define FLICKR_TYPE_PROXY flickr_proxy_get_type() + +#define FLICKR_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLICKR_TYPE_PROXY, FlickrProxy)) + +#define FLICKR_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), FLICKR_TYPE_PROXY, FlickrProxyClass)) + +#define FLICKR_IS_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLICKR_TYPE_PROXY)) + +#define FLICKR_IS_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), FLICKR_TYPE_PROXY)) + +#define FLICKR_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), FLICKR_TYPE_PROXY, FlickrProxyClass)) + +typedef struct _FlickrProxyPrivate FlickrProxyPrivate; + +/** + * FlickrProxy: + * + * #FlickrProxy has no publicly available members. + */ +typedef struct { + RestProxy parent; + FlickrProxyPrivate *priv; +} FlickrProxy; + +typedef struct { + RestProxyClass parent_class; + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +} FlickrProxyClass; + +#define FLICKR_PROXY_ERROR flickr_proxy_error_quark() + +GType flickr_proxy_get_type (void); + +RestProxy* flickr_proxy_new (const char *api_key, + const char *shared_secret); + +RestProxy* flickr_proxy_new_with_token (const char *api_key, + const char *shared_secret, + const char *token); + +const char * flickr_proxy_get_api_key (FlickrProxy *proxy); + +const char * flickr_proxy_get_shared_secret (FlickrProxy *proxy); + +const char * flickr_proxy_get_token (FlickrProxy *proxy); + +void flickr_proxy_set_token (FlickrProxy *proxy, const char *token); + +char * flickr_proxy_sign (FlickrProxy *proxy, GHashTable *params); + +char * flickr_proxy_build_login_url (FlickrProxy *proxy, const char *frob); + +gboolean flickr_proxy_is_successful (RestXmlNode *root, GError **error); + +G_END_DECLS + +#endif /* _FLICKR_PROXY */ diff --git a/rest-extras/test-runner.c b/rest-extras/test-runner.c new file mode 100644 index 0000000..acf688a --- /dev/null +++ b/rest-extras/test-runner.c @@ -0,0 +1,35 @@ +/* + * librest - RESTful web services access + * Copyright (C) 2009 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> +#include <glib-object.h> + +#define test_add(unit_name, func) G_STMT_START { \ + extern void func (void); \ + g_test_add_func (unit_name, func); } G_STMT_END + +int +main (int argc, char *argv[]) +{ + g_type_init (); + g_test_init (&argc, &argv, NULL); + + test_add ("/flickr/error", test_flickr_error); + + return g_test_run (); +} |