[frogr] Added support for OAuth in FspSession. Still using the old API.
- From: Mario Sanchez Prada <msanchez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [frogr] Added support for OAuth in FspSession. Still using the old API.
- Date: Wed, 4 Apr 2012 01:39:33 +0000 (UTC)
commit 9ab933974bc7f3cabbfeb29107a9b4c177ac886a
Author: Mario Sanchez Prada <msanchez igalia com>
Date: Wed Apr 4 01:50:36 2012 +0200
Added support for OAuth in FspSession. Still using the old API.
src/flicksoup/fsp-session.c | 327 +++++++++++++++++++++++++++++++++----------
1 files changed, 254 insertions(+), 73 deletions(-)
---
diff --git a/src/flicksoup/fsp-session.c b/src/flicksoup/fsp-session.c
index e29e481..0868c8c 100644
--- a/src/flicksoup/fsp-session.c
+++ b/src/flicksoup/fsp-session.c
@@ -29,6 +29,7 @@
#include "fsp-session.h"
#include <config.h>
+#include <gcrypt.h>
#ifdef HAVE_LIBSOUP_GNOME
#include <libsoup/soup-gnome.h>
@@ -42,6 +43,12 @@
#define FLICKR_API_AUTH_URL "http://flickr.com/services/auth"
#define FLICKR_API_BASE_URL "http://api.flickr.com/services/rest"
#define FLICKR_API_UPLOAD_URL "http://api.flickr.com/services/upload"
+#define FLICKR_REQUEST_TOKEN_OAUTH_URL "http://www.flickr.com/services/oauth/request_token"
+#define FLICKR_ACCESS_TOKEN_OAUTH_URL "http://www.flickr.com/services/oauth/access_token"
+
+#define OAUTH_CALLBACK_URL "oob"
+#define OAUTH_SIGNATURE_METHOD "HMAC-SHA1"
+#define OAUTH_VERSION "1.0"
#if DEBUG_ENABLED
#define DEBUG(...) g_debug (__VA_ARGS__)
@@ -161,6 +168,13 @@ _wrote_body_data_cb (SoupMessage *msg,
SoupBuffer *buffer,
gpointer data);
+static gchar *
+_encode_uri (const gchar *uri);
+
+static gchar *
+_hmac_sha1_signature (const gchar *message,
+ const gchar *signing_key);
+
static GHashTable *
_get_params_table_from_valist (const gchar *first_param,
va_list args);
@@ -170,9 +184,15 @@ _get_params_table_from_valist (const gchar *first_param,
static gchar *
_encode_query_value (const char *value);
+static gboolean
+_should_encode_key (const gchar *key,
+ gboolean old_auth_api);
+
static gchar *
_get_signed_query_with_params (const gchar *api_sig,
- GHashTable *params_table);
+ GHashTable *params_table,
+ gboolean old_auth_api);
+
static gboolean
_disconnect_cancellable_on_idle (GCancellableData *clos);
@@ -186,16 +206,31 @@ _check_async_errors_on_finish (GObject *object,
gpointer source_tag,
GError **error);
-gchar *
-_get_api_signature_from_hash_table (FspSession *self,
- GHashTable *params_table);
-gchar *
-_get_signed_url (FspSession *self,
- const gchar *base_url,
- const gchar *first_param,
- ... );
+static gchar *
+_get_params_str_for_signature (GHashTable *params_table,
+ const gchar *signing_key,
+ gboolean old_auth_api);
-void
+static gchar *
+_calculate_api_signature (const gchar *url,
+ const gchar *params_str,
+ const gchar *signing_key,
+ gboolean old_auth_api);
+
+static gchar *
+_get_api_signature_from_hash_table (const gchar *url,
+ GHashTable *params_table,
+ const gchar *signing_key,
+ gboolean old_auth_api);
+
+static gchar *
+_get_signed_url (FspSession *self,
+ const gchar *url,
+ gboolean old_auth_api,
+ const gchar *first_param,
+ ... );
+
+static void
_perform_async_request (SoupSession *soup_session,
const gchar *url,
SoupSessionCallback request_cb,
@@ -205,21 +240,21 @@ _perform_async_request (SoupSession *soup_session,
gpointer source_tag,
gpointer data);
-void
+static void
_soup_session_cancelled_cb (GCancellable *cancellable,
gpointer data);
-void
+static void
_handle_soup_response (SoupMessage *msg,
FspParserFunc parserFunc,
gpointer data);
-void
+static void
_build_async_result_and_complete (AsyncRequestData *clos,
gpointer result,
GError *error);
-gpointer
+static gpointer
_finish_async_request (GObject *object,
GAsyncResult *res,
gpointer source_tag,
@@ -693,6 +728,41 @@ _wrote_body_data_cb (SoupMessage *msg,
g_signal_emit (self, signals[DATA_FRACTION_SENT], 0, clos->progress);
}
+static gchar *
+_encode_uri (const gchar *uri)
+{
+ return soup_uri_encode (uri, "%!*'();:@&=+$,/?#[] ");
+}
+
+static gchar *
+_hmac_sha1_signature (const gchar *message,
+ const gchar *signing_key)
+{
+ gchar *signature = NULL;
+ gchar *encoded_signature = NULL;
+ gcry_md_hd_t digest_obj;
+ unsigned char *hmac_digest;
+ guint digest_len;
+
+ gcry_md_open(&digest_obj,
+ GCRY_MD_SHA1,
+ GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(digest_obj, signing_key, strlen (signing_key));
+ gcry_md_write (digest_obj, message, strlen (message));
+ gcry_md_final (digest_obj);
+ hmac_digest = gcry_md_read (digest_obj, 0);
+
+ digest_len = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
+ signature = g_base64_encode (hmac_digest, digest_len);
+
+ gcry_md_close (digest_obj);
+
+ encoded_signature = _encode_uri (signature);
+ g_free(signature);
+
+ return encoded_signature;
+}
+
static GHashTable *
_get_params_table_from_valist (const gchar *first_param,
va_list args)
@@ -746,9 +816,25 @@ _encode_query_value (const char *value)
return g_string_free (result, FALSE);
}
+static gboolean
+_should_encode_key (const gchar *key,
+ gboolean old_auth_api)
+{
+ if (old_auth_api)
+ return g_strcmp0 (key, "api_key") && g_strcmp0 (key, "auth_token")
+ && g_strcmp0 (key, "method") && g_strcmp0 (key, "frob");
+
+ /* Using the new OAuth-based authentication API */
+ return g_strcmp0 (key, "oauth_token") && g_strcmp0 (key, "oauth_verifier")
+ && g_strcmp0 (key, "oauth_consumer_key") && g_strcmp0 (key, "oauth_signature_method")
+ && g_strcmp0 (key, "oauth_version") && g_strcmp0 (key, "oauth_signature")
+ && g_strcmp0 (key, "oauth_callback") && g_strcmp0 (key, "method");
+}
+
static gchar *
_get_signed_query_with_params (const gchar *api_sig,
- GHashTable *params_table)
+ GHashTable *params_table,
+ gboolean old_auth_api)
{
GList *keys = NULL;
gchar *retval = NULL;
@@ -779,8 +865,7 @@ _get_signed_query_with_params (const gchar *api_sig,
gchar *actual_value = NULL;
/* Do not encode basic pairs key-value */
- if (g_strcmp0 (key, "api_key") && g_strcmp0 (key, "auth_token")
- && g_strcmp0 (key, "method") && g_strcmp0 (key, "frob"))
+ if (_should_encode_key (key, old_auth_api))
actual_value = _encode_query_value (value);
else
actual_value = g_strdup (value);
@@ -790,8 +875,10 @@ _get_signed_query_with_params (const gchar *api_sig,
}
/* Add those to the params array (space previously reserved) */
- url_params_array[i] = g_strdup_printf ("api_sig=%s", api_sig);
-
+ url_params_array[i] = g_strdup_printf (old_auth_api
+ ? "api_sig=%s"
+ : "oauth_signature=%s",
+ api_sig);
/* Build the signed query */
retval = g_strjoinv ("&", url_params_array);
@@ -884,98 +971,178 @@ _check_async_errors_on_finish (GObject *object,
return errors_found;
}
-gchar *
-_get_api_signature_from_hash_table (FspSession *self,
- GHashTable *params_table)
+
+static gchar *
+_get_params_str_for_signature (GHashTable *params_table,
+ const gchar *signing_key,
+ gboolean old_auth_api)
{
GList *keys = NULL;
- gchar *api_sig = NULL;
-
- g_return_val_if_fail (FSP_IS_SESSION (self), NULL);
- g_return_val_if_fail (params_table != NULL, NULL);
-
- /* Get ownership of the table */
- g_hash_table_ref (params_table);
+ gchar **params_str_array = NULL;
+ gchar *params_str = NULL;
+ GList *k = NULL;
+ gint i = 0;
/* Get a list of keys */
keys = g_hash_table_get_keys (params_table);
- if (keys != NULL)
- {
- gchar **sign_str_array = NULL;
- gchar *sign_str = NULL;
- GList *k = NULL;
- gint i = 0;
+ if (!keys)
+ return NULL;
- /* Sort the list */
- keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
+ /* Sort the list */
+ keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
- /* Build gchar** arrays for building the signature string */
- sign_str_array = g_new0 (gchar*, (2 * g_list_length (keys)) + 2);
+ /* Build gchar** arrays for building the signature string */
+ if (old_auth_api)
+ {
+ params_str_array = g_new0 (gchar*, (2 * g_list_length (keys)) + 2);
+ params_str_array[i++] = g_strdup (signing_key);
+ }
+ else
+ params_str_array = g_new0 (gchar*, g_list_length (keys) + 1);
- /* Fill arrays */
- sign_str_array[i++] = g_strdup (self->priv->secret);
- for (k = keys; k; k = g_list_next (k))
- {
- const gchar *key = (gchar*) k->data;
- const gchar *value = g_hash_table_lookup (params_table, key);
+ /* Fill arrays */
+ for (k = keys; k; k = g_list_next (k))
+ {
+ const gchar *key = (gchar*) k->data;
+ const gchar *value = g_hash_table_lookup (params_table, key);
- sign_str_array[i++] = g_strdup (key);
- sign_str_array[i++] = g_strdup (value);
+ if (old_auth_api)
+ {
+ params_str_array[i++] = g_strdup (key);
+ params_str_array[i++] = g_strdup (value);
}
- sign_str_array[i] = NULL;
-
- /* Get the signature string and calculate the api_sig value */
- sign_str = g_strjoinv (NULL, sign_str_array);
- api_sig = g_compute_checksum_for_string (G_CHECKSUM_MD5, sign_str, -1);
-
- /* Free */
- g_free (sign_str);
- g_strfreev (sign_str_array);
+ else
+ params_str_array[i++] = g_strdup_printf ("%s=%s", key, value);
}
+ params_str_array[i] = NULL;
+
+ params_str = g_strjoinv (old_auth_api ? NULL : "&", params_str_array);
+ g_strfreev (params_str_array);
g_list_free (keys);
- g_hash_table_unref (params_table);
+
+ return params_str;
+}
+
+static gchar *
+_calculate_api_signature (const gchar *url,
+ const gchar *params_str,
+ const gchar *signing_key,
+ gboolean old_auth_api)
+{
+ gchar *base_string = NULL;
+ gchar *encoded_params = NULL;
+ gchar *encoded_url = NULL;
+ gchar *api_sig = NULL;
+
+ if (!params_str)
+ return NULL;
+
+ if (old_auth_api)
+ return g_compute_checksum_for_string (G_CHECKSUM_MD5, params_str, -1);
+
+ /* Using the new OAuth-based authentication API */
+ encoded_url = _encode_uri (url);
+ encoded_params = _encode_uri (params_str);
+
+ base_string = g_strdup_printf ("GET&%s&%s", encoded_url, encoded_params);
+ g_free (encoded_url);
+ g_free (encoded_params);
+
+ api_sig = _hmac_sha1_signature (base_string, signing_key);
+ g_free (base_string);
return api_sig;
}
-gchar *
-_get_signed_url (FspSession *self,
- const gchar *base_url,
- const gchar *first_param,
- ... )
+static gchar *
+_get_api_signature_from_hash_table (const gchar *url,
+ GHashTable *params_table,
+ const gchar *signing_key,
+ gboolean old_auth_api)
{
+ gchar *api_sig = NULL;
+ gchar *params_str = NULL;
+
+ g_return_val_if_fail (params_table != NULL, NULL);
+
+ /* Get the signature string and calculate the api_sig value */
+ params_str = _get_params_str_for_signature (params_table, signing_key, old_auth_api);
+ api_sig = _calculate_api_signature (url, params_str, signing_key, old_auth_api);
+ g_free (params_str);
+
+ return api_sig;
+}
+
+static gchar *
+_get_signed_url (FspSession *self,
+ const gchar *url,
+ gboolean old_auth_api,
+ const gchar *first_param,
+ ... )
+{
+ FspSessionPrivate *priv = NULL;
va_list args;
GHashTable *table = NULL;
- gchar *api_sig = NULL;
+ gchar *signing_key = NULL;
gchar *signed_query = NULL;
+ gchar *api_sig = NULL;
gchar *retval = NULL;
g_return_val_if_fail (FSP_IS_SESSION (self), NULL);
+ g_return_val_if_fail (url != NULL, NULL);
g_return_val_if_fail (first_param != NULL, NULL);
+ priv = self->priv;
va_start (args, first_param);
- /* Get the hash table for the params and the API signature from it */
+ /* Get the hash table for the params */
table = _get_params_table_from_valist (first_param, args);
- api_sig = _get_api_signature_from_hash_table (self, table);
+
+ if (!old_auth_api)
+ {
+ gchar *timestamp = NULL;
+ gchar *random_str = NULL;
+ gchar *nonce = NULL;
+
+ /* Add mandatory parameters to the hash table */
+ timestamp = g_strdup_printf ("%d", (gint) time(NULL));
+ random_str = g_strdup_printf ("%d_%s", g_random_int (), timestamp);
+ nonce = g_compute_checksum_for_string (G_CHECKSUM_MD5, random_str, -1);
+ g_free (random_str);
+
+ g_hash_table_insert (table, g_strdup ("oauth_timestamp"), timestamp);
+ g_hash_table_insert (table, g_strdup ("oauth_nonce"), nonce);
+ g_hash_table_insert (table, g_strdup ("oauth_consumer_key"), g_strdup (priv->api_key));
+ g_hash_table_insert (table, g_strdup ("oauth_signature_method"), g_strdup (OAUTH_SIGNATURE_METHOD));
+ g_hash_table_insert (table, g_strdup ("oauth_version"), g_strdup (OAUTH_VERSION));
+ }
+
+ /* Get the API signature from it */
+ if (old_auth_api)
+ signing_key = g_strdup (priv->secret);
+ else
+ signing_key = g_strdup_printf ("%s&%s", priv->secret, priv->token_secret ? priv->token_secret : "");
+
+ api_sig = _get_api_signature_from_hash_table (url, table, signing_key, old_auth_api);
+ g_free (signing_key);
/* Get the signed URL with the needed params */
if ((table != NULL) && (api_sig != NULL))
- signed_query = _get_signed_query_with_params (api_sig, table);
+ signed_query = _get_signed_query_with_params (api_sig, table, old_auth_api);
g_hash_table_unref (table);
g_free (api_sig);
va_end (args);
- retval = g_strdup_printf ("%s/?%s", base_url, signed_query);
+ retval = g_strdup_printf ("%s?%s", url, signed_query);
g_free (signed_query);
return retval;
}
-void
+static void
_perform_async_request (SoupSession *soup_session,
const gchar *url,
SoupSessionCallback request_cb,
@@ -1028,7 +1195,7 @@ _perform_async_request (SoupSession *soup_session,
DEBUG ("\nRequested URL:\n%s\n", url);
}
-void
+static void
_soup_session_cancelled_cb (GCancellable *cancellable,
gpointer data)
{
@@ -1047,7 +1214,7 @@ _soup_session_cancelled_cb (GCancellable *cancellable,
DEBUG ("%s", "Remote request cancelled!");
}
-void
+static void
_handle_soup_response (SoupMessage *msg,
FspParserFunc parserFunc,
gpointer data)
@@ -1085,7 +1252,7 @@ _handle_soup_response (SoupMessage *msg,
g_free (response_str);
}
-void
+static void
_build_async_result_and_complete (AsyncRequestData *clos,
gpointer result,
GError *error)
@@ -1134,7 +1301,7 @@ _build_async_result_and_complete (AsyncRequestData *clos,
g_object_unref (G_OBJECT (res));
}
-gpointer
+static gpointer
_finish_async_request (GObject *object,
GAsyncResult *res,
gpointer source_tag,
@@ -1494,6 +1661,7 @@ fsp_session_get_auth_url_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.auth.getFrob",
"api_key", priv->api_key,
NULL);
@@ -1531,6 +1699,7 @@ fsp_session_get_auth_url_finish (FspSession *self,
/* Build the authorization url */
auth_url = _get_signed_url (self,
FLICKR_API_AUTH_URL,
+ TRUE,
"api_key", priv->api_key,
"perms", "write",
"frob", priv->frob,
@@ -1561,6 +1730,7 @@ fsp_session_complete_auth_async (FspSession *self,
/* Build the signed url */
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.auth.getToken",
"api_key", priv->api_key,
"frob", priv->frob,
@@ -1625,6 +1795,7 @@ fsp_session_check_auth_info_async (FspSession *self,
/* Build the signed url */
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.auth.checkToken",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -1684,6 +1855,7 @@ fsp_session_get_upload_status_async (FspSession *self,
/* Build the signed url */
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.people.getUploadStatus",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -1765,7 +1937,7 @@ fsp_session_upload_async (FspSession *self,
g_strdup (priv->token));
/* Build the api signature and add it to the hash table */
- api_sig = _get_api_signature_from_hash_table (self, extra_params);
+ api_sig = _get_api_signature_from_hash_table (FLICKR_API_UPLOAD_URL, extra_params, priv->secret, TRUE);
g_hash_table_insert (extra_params, g_strdup ("api_sig"), api_sig);
/* Save important data for the callback */
@@ -1819,6 +1991,7 @@ fsp_session_get_info_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.photos.getInfo",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -1867,6 +2040,7 @@ fsp_session_get_photosets_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.photosets.getList",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -1914,6 +2088,7 @@ fsp_session_add_to_photoset_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.photosets.addPhoto",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -1967,6 +2142,7 @@ fsp_session_create_photoset_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.photosets.create",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -2017,6 +2193,7 @@ fsp_session_get_groups_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.groups.pools.getGroups",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -2064,6 +2241,7 @@ fsp_session_add_to_group_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.groups.pools.add",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -2112,6 +2290,7 @@ fsp_session_get_tags_list_async (FspSession *self,
priv = self->priv;
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.tags.getListUser",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -2159,6 +2338,7 @@ fsp_session_set_license_async (FspSession *self,
license_str = g_strdup_printf ("%d", license);
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.photos.licenses.setLicense",
"api_key", priv->api_key,
"auth_token", priv->token,
@@ -2224,6 +2404,7 @@ fsp_session_set_location_async (FspSession *self,
/* FIXME: not sure how to handle the optional 'accuracy' here... */
url = _get_signed_url (self,
FLICKR_API_BASE_URL,
+ TRUE,
"method", "flickr.photos.geo.setLocation",
"api_key", priv->api_key,
"auth_token", priv->token,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]