[shotwell/wip/pluggable-auth: 14/20] WIP



commit 96831a6a582f3b9d87cabe77b927b93946cb8057
Author: Jens Georg <mail jensge org>
Date:   Tue Feb 7 21:42:16 2017 +0100

    WIP

 authenticator.am                                   |   23 +++
 .../shotwell/FlickrPublishingAuthenticator.vala    |  155 +++++++++++++++++---
 .../shotwell}/flickr_pin_entry_pane.ui             |    0
 .../org.gnome.Shotwell.Authenticator.gresource.xml |    6 +
 plugins/shotwell-publishing/FlickrPublishing.vala  |   21 ---
 .../org.gnome.Shotwell.Publishing.gresource.xml    |    1 -
 publish.am                                         |    2 +-
 7 files changed, 166 insertions(+), 42 deletions(-)
---
diff --git a/authenticator.am b/authenticator.am
index a0c9b37..442ad5b 100644
--- a/authenticator.am
+++ b/authenticator.am
@@ -1,4 +1,8 @@
 lib_LTLIBRARIES += plugins/authenticator/libshotwell-authenticator.la
+
+dist_noinst_DATA += \
+       plugins/authenticator/shotwell/flickr_pin_entry_pane.ui
+
 plugins_authenticator_libshotwell_authenticator_la_SOURCES = \
        $(abs_top_srcdir)/plugins/shotwell-plugin-common.vapi
 
@@ -21,7 +25,26 @@ plugins_authenticator_libshotwell_authenticator_la_CFLAGS = \
        -I $(top_srcdir)/plugins \
        -DPLUGIN_RESOURCE_PATH='"/org/gnome/Shotwell/Authenticator"'
 
+## Resource handling
+
+nodist_plugins_authenticator_libshotwell_authenticator_la_SOURCES = \
+       plugins/authenticator/resource.c
+MOSTLYCLEANFILES += plugins/authenticator/resource.c
+
+AUTHENTICATOR_RESOURCE_DEPS = $(shell $(GLIB_COMPILE_RESOURCES) \
+               --sourcedir=$(AUTHENTICATOR_RESOURCE_SOURCEDIR) \
+               --generate-dependencies $(AUTHENTICATOR_SHOTWELL_RESOURCE_FILE))
+
+plugins/authenticator/resource.c: $(AUTHENTICATOR_RESOURCE_DEPS) $(AUTHENTICATOR_RESOURCE_FILE)
+       $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) \
+               --target=$@ \
+               --sourcedir=$(AUTHENTICATOR_RESOURCE_SOURCEDIR) \
+               --generate $(AUTHENTICATOR_RESOURCE_FILE)
+
 if AUTHENTICATOR_SHOTWELL
+AUTHENTICATOR_RESOURCE_FILE := 
$(abs_top_srcdir)/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml
+AUTHENTICATOR_RESOURCE_SOURCEDIR := $(abs_top_srcdir)/plugins/authenticator/shotwell
+
 plugins_authenticator_libshotwell_authenticator_la_SOURCES += \
        plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala \
        plugins/authenticator/shotwell/FacebookPublishingAuthenticator.vala \
diff --git a/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala 
b/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
index 2289a3e..006987c 100644
--- a/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
+++ b/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
@@ -5,52 +5,169 @@
  */
 
 namespace Publishing.Flickr {
+    internal const string ENDPOINT_URL = "https://api.flickr.com/services/rest";;
+    internal const string EXPIRED_SESSION_ERROR_CODE = "98";
+    internal const string ENCODE_RFC_3986_EXTRA = "!*'();:@&=+$,/?%#[] \\";
+
     internal class Transaction : Publishing.RESTSupport.Transaction {
-        public Transaction() {
-            var foo = null as Publishing.RESTSupport.Session;
+        public Transaction(Session session, Publishing.RESTSupport.HttpMethod method =
+                Publishing.RESTSupport.HttpMethod.POST) {
+            base(session, method);
 
-            base(foo, Publishing.RESTSupport.HttpMethod.POST);
+            add_argument("oauth_nonce", session.get_oauth_nonce());
+            add_argument("oauth_signature_method", "HMAC-SHA1");
+            add_argument("oauth_version", "1.0");
+            add_argument("oauth_callback", "oob");
+            add_argument("oauth_timestamp", session.get_oauth_timestamp());
+            add_argument("oauth_consumer_key", session.get_consumer_key());
         }
 
-        public Transaction.with_uri (Publishing.RESTSupport.Session session,
-                                     string uri,
-                                     Publishing.RESTSupport.HttpMethod method) {
+        public Transaction.with_uri(Session session, string uri,
+                Publishing.RESTSupport.HttpMethod method = Publishing.RESTSupport.HttpMethod.POST) {
             base.with_endpoint_url(session, uri, method);
+
+            add_argument("oauth_nonce", session.get_oauth_nonce());
+            add_argument("oauth_signature_method", "HMAC-SHA1");
+            add_argument("oauth_version", "1.0");
+            add_argument("oauth_callback", "oob");
+            add_argument("oauth_timestamp", session.get_oauth_timestamp());
+            add_argument("oauth_consumer_key", session.get_consumer_key());
+        }
+
+        public override void execute() throws Spit.Publishing.PublishingError {
+            ((Session) get_parent_session()).sign_transaction(this);
+
+            base.execute();
         }
     }
 
     internal class Session : Publishing.RESTSupport.Session {
+        private string? request_phase_token = null;
+        private string? request_phase_token_secret = null;
+        private string? access_phase_token = null;
+        private string? access_phase_token_secret = null;
+        private string? username = null;
+        private string? consumer_key = null;
+        private string? consumer_secret = null;
+
+        public Session() {
+            base();
+        }
+
         public override bool is_authenticated() {
-            return false;
+            return (access_phase_token != null && access_phase_token_secret != null &&
+                    username != null);
         }
 
-        public void set_api_credentials(string key, string secret) {
+        public void set_api_credentials(string consumer_key, string consumer_secret) {
+            this.consumer_key = consumer_key;
+            this.consumer_secret = consumer_secret;
+        }
+
+        public void sign_transaction(Publishing.RESTSupport.Transaction txn) {
+            string http_method = txn.get_method().to_string();
+
+            debug("signing transaction with parameters:");
+            debug("HTTP method = " + http_method);
+
+            Publishing.RESTSupport.Argument[] base_string_arguments = txn.get_arguments();
+
+            Publishing.RESTSupport.Argument[] sorted_args =
+                Publishing.RESTSupport.Argument.sort(base_string_arguments);
+
+            string arguments_string = "";
+            for (int i = 0; i < sorted_args.length; i++) {
+                arguments_string += (sorted_args[i].key + "=" + sorted_args[i].value);
+                if (i < sorted_args.length - 1)
+                    arguments_string += "&";
+            }
+
+            string? signing_key = null;
+            if (access_phase_token_secret != null) {
+                debug("access phase token secret available; using it as signing key");
+
+                signing_key = consumer_secret + "&" + access_phase_token_secret;
+            } else if (request_phase_token_secret != null) {
+                debug("request phase token secret available; using it as signing key");
+
+                signing_key = consumer_secret + "&" + request_phase_token_secret;
+            } else {
+                debug("neither access phase nor request phase token secrets available; using API " +
+                        "key as signing key");
+
+                signing_key = consumer_secret + "&";
+            }
+
+            string signature_base_string = http_method + "&" + Soup.URI.encode(
+                    txn.get_endpoint_url(), ENCODE_RFC_3986_EXTRA) + "&" +
+                Soup.URI.encode(arguments_string, ENCODE_RFC_3986_EXTRA);
+
+            debug("signature base string = '%s'", signature_base_string);
+
+            debug("signing key = '%s'", signing_key);
+
+            // compute the signature
+            string signature = RESTSupport.hmac_sha1(signing_key, signature_base_string);
+            signature = Soup.URI.encode(signature, ENCODE_RFC_3986_EXTRA);
+
+            debug("signature = '%s'", signature);
+
+            txn.add_argument("oauth_signature", signature);
+        }
+
+        public void set_request_phase_credentials(string token, string secret) {
+            this.request_phase_token = token;
+            this.request_phase_token_secret = secret;
+        }
+
+        public void set_access_phase_credentials(string token, string secret, string username) {
+            this.access_phase_token = token;
+            this.access_phase_token_secret = secret;
+            this.username = username;
+
+            authenticated();
+        }
+
+        public string get_oauth_nonce() {
+            TimeVal currtime = TimeVal();
+            currtime.get_current_time();
+
+            return Checksum.compute_for_string(ChecksumType.MD5, currtime.tv_sec.to_string() +
+                    currtime.tv_usec.to_string());
+        }
+
+        public string get_oauth_timestamp() {
+            return GLib.get_real_time().to_string().substring(0, 10);
+        }
+
+        public string get_consumer_key() {
+            assert(consumer_key != null);
+            return consumer_key;
         }
 
         public string get_request_phase_token() {
-            return "";
+            assert(request_phase_token != null);
+            return request_phase_token;
         }
 
         public string get_request_phase_token_secret() {
-            return "";
+            assert(request_phase_token_secret != null);
+            return request_phase_token_secret;
         }
 
         public string get_access_phase_token() {
-            return "";
+            assert(access_phase_token != null);
+            return access_phase_token;
         }
 
         public string get_access_phase_token_secret() {
-            return "";
+            assert(access_phase_token_secret != null);
+            return access_phase_token_secret;
         }
 
         public string get_username() {
-            return "";
-        }
-
-        public void set_request_phase_credentials (string token, string token_secret) {
-        }
-
-        public void set_access_phase_credentials(string token, string token_secret, string user_name) {
+            assert(is_authenticated());
+            return username;
         }
     }
 }
diff --git a/plugins/shotwell-publishing/flickr_pin_entry_pane.ui 
b/plugins/authenticator/shotwell/flickr_pin_entry_pane.ui
similarity index 100%
rename from plugins/shotwell-publishing/flickr_pin_entry_pane.ui
rename to plugins/authenticator/shotwell/flickr_pin_entry_pane.ui
diff --git a/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml 
b/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml
new file mode 100644
index 0000000..c40e700
--- /dev/null
+++ b/plugins/authenticator/shotwell/org.gnome.Shotwell.Authenticator.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/Shotwell/Authenticator">
+      <file>flickr_pin_entry_pane.ui</file>
+  </gresource>
+</gresources>
diff --git a/plugins/shotwell-publishing/FlickrPublishing.vala 
b/plugins/shotwell-publishing/FlickrPublishing.vala
index 09b655c..6ba3cb8 100644
--- a/plugins/shotwell-publishing/FlickrPublishing.vala
+++ b/plugins/shotwell-publishing/FlickrPublishing.vala
@@ -663,8 +663,6 @@ private class UploadTransaction : Publishing.RESTSupport.UploadTransaction {
 }
 
 internal class Session : Publishing.RESTSupport.Session {
-    private string? request_phase_token = null;
-    private string? request_phase_token_secret = null;
     private string? access_phase_token = null;
     private string? access_phase_token_secret = null;
     private string? username = null;
@@ -735,10 +733,6 @@ internal class Session : Publishing.RESTSupport.Session {
             debug("access phase token secret available; using it as signing key");
 
             signing_key = consumer_secret + "&" + access_phase_token_secret;
-        } else if (request_phase_token_secret != null) {
-            debug("request phase token secret available; using it as signing key");
-
-            signing_key = consumer_secret + "&" + request_phase_token_secret;
         } else {
             debug("neither access phase nor request phase token secrets available; using API " +
                 "key as signing key");
@@ -766,11 +760,6 @@ internal class Session : Publishing.RESTSupport.Session {
             txn.add_argument("oauth_signature", signature);
     }
     
-    public void set_request_phase_credentials(string token, string secret) {
-        this.request_phase_token = token;
-        this.request_phase_token_secret = secret;
-    }
-    
     public void set_access_phase_credentials(string token, string secret, string username) {
         this.access_phase_token = token;
         this.access_phase_token_secret = secret;
@@ -795,16 +784,6 @@ internal class Session : Publishing.RESTSupport.Session {
         assert(consumer_key != null);
         return consumer_key;
     }
-    
-    public string get_request_phase_token() {
-        assert(request_phase_token != null);
-        return request_phase_token;
-    }
-
-    public string get_request_phase_token_secret() {
-        assert(request_phase_token_secret != null);
-        return request_phase_token_secret;
-    }
 
     public string get_access_phase_token() {
         assert(access_phase_token != null);
diff --git a/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml 
b/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml
index af3baad..b09902e 100644
--- a/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml
+++ b/plugins/shotwell-publishing/org.gnome.Shotwell.Publishing.gresource.xml
@@ -7,7 +7,6 @@
       <file>piwigo.png</file>
       <file>youtube.png</file>
       <file>facebook_publishing_options_pane.ui</file>
-      <file>flickr_pin_entry_pane.ui</file>
       <file>flickr_publishing_options_pane.ui</file>
       <file>picasa_publishing_options_pane.ui</file>
       <file>piwigo_authentication_pane.ui</file>
diff --git a/publish.am b/publish.am
index 7762900..0542119 100644
--- a/publish.am
+++ b/publish.am
@@ -7,7 +7,6 @@ dist_noinst_DATA += \
        plugins/shotwell-publishing/piwigo.png \
        plugins/shotwell-publishing/youtube.png \
        plugins/shotwell-publishing/facebook_publishing_options_pane.ui \
-       plugins/shotwell-publishing/flickr_pin_entry_pane.ui \
        plugins/shotwell-publishing/flickr_publishing_options_pane.ui \
        plugins/shotwell-publishing/picasa_publishing_options_pane.ui \
        plugins/shotwell-publishing/piwigo_authentication_pane.ui \
@@ -72,3 +71,4 @@ plugins_shotwell_publishing_shotwell_publishing_la_LIBADD = \
        $(PUBLISHING_LIBS) \
        $(top_builddir)/plugins/common/libshotwell-plugin-common.la \
        $(top_builddir)/plugins/authenticator/libshotwell-authenticator.la
+


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