diff options
Diffstat (limited to 'plugins')
17 files changed, 114 insertions, 110 deletions
diff --git a/plugins/Makefile.plugin.mk b/plugins/Makefile.plugin.mk index 03df7b0..c26c672 100644 --- a/plugins/Makefile.plugin.mk +++ b/plugins/Makefile.plugin.mk @@ -28,9 +28,6 @@ PKGS := $(shell sed ':a;N;$$!ba;s/\n/ /g' ../shotwell-plugin-dev-1.0.deps) $(PKG EXT_PKGS := $(PKGS) PKGS := shotwell-plugin-dev-1.0 $(PKGS) $(PLUGIN_PKGS) -# automatically include the Resources.vala common file -SRC_FILES := ../common/Resources.vala $(SRC_FILES) - CFILES := $(notdir $(SRC_FILES:.vala=.c)) OFILES := $(notdir $(SRC_FILES:.vala=.o)) @@ -41,10 +38,14 @@ DEFINES := -D_VERSION='"$(PLUGINS_VERSION)"' -DGETTEXT_PACKAGE='"shotwell"' all: $(PLUGIN).so +PLUGIN_EXTRAFLAGS ?= --vapidir=../common --pkg shotwell-plugin-common +PLUGIN_EXTRALINKFLAGS ?= -L../common/ -lshotwell-plugin-common + .stamp: $(SRC_FILES) $(MAKE_FILES) $(HEADER_FILES) $(VALAC) --target-glib=$(MIN_GLIB_VERSION) -g --enable-checking --fatal-warnings --ccode --enable-deprecated \ --vapidir=../ $(foreach pkg,$(PKGS),--pkg=$(pkg)) $(foreach pkg,$(CUSTOM_VAPI_PKGS),--pkg=$(pkg)) \ $(USER_VALAFLAGS) \ + $(PLUGIN_EXTRAFLAGS) \ --vapidir=../../vapi \ $(SRC_FILES) @touch .stamp @@ -53,10 +54,10 @@ $(CFILES): .stamp @ .c.o: - $(CC) -c $(CFLAGS) $(DEFINES) -I../.. $< + $(CC) -c $(CFLAGS) $(DEFINES) -I../.. -I ../common $< $(PLUGIN).so: $(OFILES) - $(CC) $(LDFLAGS) -shared $(OFILES) $(LIBS) -o $@ + $(CC) $(LDFLAGS) -shared $(OFILES) $(LIBS) $(PLUGIN_EXTRALINKFLAGS) -o $@ .PHONY: cleantemps cleantemps: @@ -70,8 +71,10 @@ clean: cleantemps .PHONY: distclean distclean: clean +PLUGIN_DIR ?= $(PLUGIN) + .PHONY: listfiles listfiles: - @printf "plugins/$(PLUGIN)/Makefile $(foreach file,$(SRC_FILES),plugins/$(PLUGIN)/$(file)) " - @printf "$(foreach rc,$(RC_FILES),plugins/$(PLUGIN)/$(rc)) " + @printf "plugins/$(PLUGIN_DIR)/Makefile $(foreach file,$(SRC_FILES),plugins/$(PLUGIN_DIR)/$(file)) " + @printf "$(foreach rc,$(RC_FILES),plugins/$(PLUGIN_DIR)/$(rc)) " diff --git a/plugins/common/Makefile b/plugins/common/Makefile new file mode 100644 index 0000000..90714a0 --- /dev/null +++ b/plugins/common/Makefile @@ -0,0 +1,20 @@ + +PLUGIN := libshotwell-plugin-common +PLUGIN_DIR := common + +PLUGIN_PKGS := \ + gee-0.8 \ + libxml-2.0 \ + libsoup-2.4 \ + json-glib-1.0 \ + webkit2gtk-4.0 + +SRC_FILES := Resources.vala RESTSupport.vala + +PLUGIN_EXTRAFLAGS := --vapi=shotwell-plugin-common.vapi \ + --header=shotwell-plugin-common.h + +PLUGIN_EXTRALINKFLAGS := + +include ../Makefile.plugin.mk + diff --git a/plugins/common/RESTSupport.vala b/plugins/common/RESTSupport.vala index b512fe7..d9bf2ce 100644 --- a/plugins/common/RESTSupport.vala +++ b/plugins/common/RESTSupport.vala @@ -4,10 +4,24 @@ * (version 2.1 or later). See the COPYING file in this distribution. */ -extern Soup.Message soup_form_request_new_from_multipart(string uri, Soup.Multipart multipart); - namespace Publishing.RESTSupport { +// Ported from librest +// https://git.gnome.org/browse/librest/tree/rest/sha1.c?id=e412da58080eec2e771482e7e4c509b9e71477ff#n38 + +internal const int SHA1_HMAC_LENGTH = 20; + +public string hmac_sha1(string key, string message) { + uint8 buffer[SHA1_HMAC_LENGTH]; + size_t len = SHA1_HMAC_LENGTH; + + var mac = new Hmac (ChecksumType.SHA1, key.data); + mac.update (message.data); + mac.get_digest (buffer, ref len); + + return Base64.encode (buffer[0:len]); +} + public abstract class Session { private string? endpoint_url = null; private Soup.Session soup_session = null; @@ -109,13 +123,17 @@ public class Argument { } public static Argument[] sort(Argument[] inputArray) { - FixedTreeSet<Argument> sorted_args = new FixedTreeSet<Argument>(Argument.compare); + Gee.TreeSet<Argument> sorted_args = new Gee.TreeSet<Argument>(Argument.compare); foreach (Argument arg in inputArray) sorted_args.add(arg); return sorted_args.to_array(); } + + public string to_string () { + return "%s=%s".printf (this.key, this.value); + } } public class Transaction { @@ -298,7 +316,7 @@ public class Transaction { // concatenate the REST arguments array into an HTTP formdata string string formdata_string = ""; for (int i = 0; i < arguments.length; i++) { - formdata_string += ("%s=%s".printf(arguments[i].key, arguments[i].value)); + formdata_string += arguments[i].to_string (); if (i < arguments.length - 1) formdata_string += "&"; } @@ -338,6 +356,11 @@ public class Transaction { assert(get_is_executed()); return message.response_headers; } + + public Soup.Message get_message() { + assert(get_is_executed()); + return message; + } public void add_argument(string name, string value) { arguments += new Argument(name, value); @@ -437,7 +460,7 @@ public class UploadTransaction : Transaction { image_part_header.set_content_disposition("form-data", binary_disposition_table); Soup.Message outbound_message = - soup_form_request_new_from_multipart(get_endpoint_url(), message_parts); + Soup.Form.request_new_from_multipart(get_endpoint_url(), message_parts); // TODO: there must be a better way to iterate over a map Gee.MapIterator<string, string> i = message_headers.map_iterator(); bool cont = i.next(); @@ -562,7 +585,7 @@ public string decimal_entity_encode(string source) { return encoded_str_builder.str; } -internal abstract class BatchUploader { +public abstract class BatchUploader { private int current_file = 0; private Spit.Publishing.Publishable[] publishables = null; private Session session = null; @@ -659,20 +682,6 @@ public string asciify_string(string s) { return b.str; } -/** @brief Work-around for a problem in libgee where a TreeSet can leak references when it - * goes out of scope; please see https://bugzilla.gnome.org/show_bug.cgi?id=695045 for more - * details. This class merely wraps it and adds a call to clear() to the destructor. - */ -public class FixedTreeSet<G> : Gee.TreeSet<G> { - public FixedTreeSet(owned CompareDataFunc<G>? comp_func = null) { - base((owned) comp_func); - } - - ~FixedTreeSet() { - clear(); - } -} - public abstract class GoogleSession : Session { public abstract string get_user_name(); public abstract string get_access_token(); diff --git a/plugins/plugins.mk b/plugins/plugins.mk index 2f28608..687ceeb 100644 --- a/plugins/plugins.mk +++ b/plugins/plugins.mk @@ -1,5 +1,6 @@ PLUGINS := \ + common \ shotwell-transitions \ shotwell-publishing \ shotwell-data-imports diff --git a/plugins/shotwell-data-imports/Makefile b/plugins/shotwell-data-imports/Makefile index 52329e7..203aeed 100644 --- a/plugins/shotwell-data-imports/Makefile +++ b/plugins/shotwell-data-imports/Makefile @@ -5,12 +5,14 @@ PLUGIN_PKGS := \ gtk+-3.0 \ gexiv2 \ gee-0.8 \ - sqlite3 + sqlite3 \ + libxml-2.0 \ + libsoup-2.4 SRC_FILES := \ shotwell-data-imports.vala \ - ../common/VersionNumber.vala \ - ../common/SqliteSupport.vala \ + VersionNumber.vala \ + SqliteSupport.vala \ FSpotImporter.vala \ FSpotDatabaseBehavior.vala \ FSpotDatabase.vala \ diff --git a/plugins/common/SqliteSupport.vala b/plugins/shotwell-data-imports/SqliteSupport.vala index 0dcc99c..859dc84 100644 --- a/plugins/common/SqliteSupport.vala +++ b/plugins/shotwell-data-imports/SqliteSupport.vala @@ -14,26 +14,26 @@ public errordomain DatabaseError { } public abstract class ImportableDatabaseTable { - + protected static Sqlite.Database db; - + public string table_name = null; - + protected void set_table_name(string table_name) { this.table_name = table_name; } - + // This method will throw an error on an SQLite return code unless it's OK, DONE, or ROW, which // are considered normal results. protected static void throw_error(string method, int res) throws DatabaseError { string msg = "(%s) [%d] - %s".printf(method, res, db.errmsg()); - + switch (res) { case Sqlite.OK: case Sqlite.DONE: case Sqlite.ROW: return; - + case Sqlite.PERM: case Sqlite.BUSY: case Sqlite.READONLY: @@ -45,26 +45,26 @@ public abstract class ImportableDatabaseTable { case Sqlite.FORMAT: case Sqlite.NOTADB: throw new DatabaseError.BACKING(msg); - + case Sqlite.NOMEM: throw new DatabaseError.MEMORY(msg); - + case Sqlite.ABORT: case Sqlite.LOCKED: case Sqlite.INTERRUPT: throw new DatabaseError.ABORT(msg); - + case Sqlite.FULL: case Sqlite.EMPTY: case Sqlite.TOOBIG: case Sqlite.CONSTRAINT: case Sqlite.RANGE: throw new DatabaseError.LIMITS(msg); - + case Sqlite.SCHEMA: case Sqlite.MISMATCH: throw new DatabaseError.TYPESPEC(msg); - + case Sqlite.ERROR: case Sqlite.INTERNAL: case Sqlite.MISUSE: @@ -73,4 +73,3 @@ public abstract class ImportableDatabaseTable { } } } - diff --git a/plugins/common/VersionNumber.vala b/plugins/shotwell-data-imports/VersionNumber.vala index 503cd65..7077597 100644 --- a/plugins/common/VersionNumber.vala +++ b/plugins/shotwell-data-imports/VersionNumber.vala @@ -12,25 +12,25 @@ namespace Utils { */ public class VersionNumber : Object, Gee.Comparable<VersionNumber> { private int[] version; - + public VersionNumber(int[] version) { this.version = version; } - + public VersionNumber.from_string(string str_version, string separator = ".") { string[] version_items = str_version.split(separator); this.version = new int[version_items.length]; for (int i = 0; i < version_items.length; i++) this.version[i] = int.parse(version_items[i]); } - + public string to_string() { string[] version_items = new string[this.version.length]; for (int i = 0; i < this.version.length; i++) version_items[i] = this.version[i].to_string(); return string.joinv(".", version_items); } - + public int compare_to(VersionNumber other) { int max_len = ((this.version.length > other.version.length) ? this.version.length : other.version.length); @@ -47,4 +47,3 @@ public class VersionNumber : Object, Gee.Comparable<VersionNumber> { } } - diff --git a/plugins/shotwell-publishing-extras/Makefile b/plugins/shotwell-publishing-extras/Makefile index 91452cf..83a42c2 100644 --- a/plugins/shotwell-publishing-extras/Makefile +++ b/plugins/shotwell-publishing-extras/Makefile @@ -16,8 +16,6 @@ SRC_FILES := \ YandexPublishing.vala \ TumblrPublishing.vala \ RajcePublishing.vala \ - ../../src/util/string.vala \ - ../common/RESTSupport.vala # RC_FILES must also be added to ../plugins.mk to ensure they're installed properly RC_FILES := \ diff --git a/plugins/shotwell-publishing-extras/RajcePublishing.vala b/plugins/shotwell-publishing-extras/RajcePublishing.vala index 8ae05c6..d282ed5 100644 --- a/plugins/shotwell-publishing-extras/RajcePublishing.vala +++ b/plugins/shotwell-publishing-extras/RajcePublishing.vala @@ -932,10 +932,8 @@ internal class AuthenticationPane : Spit.Publishing.DialogPane, Object private void update_login_button_sensitivity() { - login_button.set_sensitive( - !is_string_empty(username_entry.get_text()) && - !is_string_empty(password_entry.get_text()) - ); + login_button.set_sensitive(username_entry.text_length > 0 && + password_entry.text_length > 0); } public Gtk.Widget get_widget() diff --git a/plugins/shotwell-publishing-extras/TumblrPublishing.vala b/plugins/shotwell-publishing-extras/TumblrPublishing.vala index 6bafb21..9e17b4e 100644 --- a/plugins/shotwell-publishing-extras/TumblrPublishing.vala +++ b/plugins/shotwell-publishing-extras/TumblrPublishing.vala @@ -6,7 +6,6 @@ */ -extern string hmac_sha1(string key, string message); public class TumblrService : Object, Spit.Pluggable, Spit.Publishing.Service { private const string ICON_FILENAME = "tumblr.png"; @@ -656,10 +655,8 @@ internal class AuthenticationPane : Spit.Publishing.DialogPane, Object { } private void update_login_button_sensitivity() { - login_button.set_sensitive( - !is_string_empty(username_entry.get_text()) && - !is_string_empty(password_entry.get_text()) - ); + login_button.set_sensitive(username_entry.text_length > 0 && + password_entry.text_length > 0); } public Gtk.Widget get_widget() { @@ -954,12 +951,7 @@ internal class UploadTransaction : Publishing.RESTSupport.UploadTransaction { string[] keywords = base.publishable.get_publishing_keywords(); string tags = ""; if (keywords != null) { - foreach (string tag in keywords) { - if (!is_string_empty(tags)) { - tags += ","; - } - tags += tag; - } + tags = string.joinv (",", keywords); } add_argument("tags", Soup.URI.encode(tags, ENCODE_RFC_3986_EXTRA)); @@ -1105,7 +1097,7 @@ internal class Session : Publishing.RESTSupport.Session { debug("signing key = '%s'", signing_key); // compute the signature - string signature = hmac_sha1(signing_key, signature_base_string); + string signature = Publishing.RESTSupport.hmac_sha1(signing_key, signature_base_string); debug("signature = '%s'", signature); signature = Soup.URI.encode(signature, ENCODE_RFC_3986_EXTRA); diff --git a/plugins/shotwell-publishing-extras/YandexPublishing.vala b/plugins/shotwell-publishing-extras/YandexPublishing.vala index ec99c2b..6504572 100644 --- a/plugins/shotwell-publishing-extras/YandexPublishing.vala +++ b/plugins/shotwell-publishing-extras/YandexPublishing.vala @@ -338,7 +338,7 @@ private class UploadTransaction: Transaction { image_part_header.set_content_disposition("form-data", result); - Soup.Message outbound_message = soup_form_request_new_from_multipart(get_endpoint_url(), message_parts); + Soup.Message outbound_message = Soup.Form.request_new_from_multipart(get_endpoint_url(), message_parts); outbound_message.request_headers.append("Authorization", ("OAuth %s").printf(session.get_auth_token())); outbound_message.request_headers.append("Connection", "close"); set_message(outbound_message); diff --git a/plugins/shotwell-publishing/FacebookPublishing.vala b/plugins/shotwell-publishing/FacebookPublishing.vala index 04dc51f..f6cccb6 100644 --- a/plugins/shotwell-publishing/FacebookPublishing.vala +++ b/plugins/shotwell-publishing/FacebookPublishing.vala @@ -940,8 +940,7 @@ internal class WebAuthenticationPane : Spit.Publishing.DialogPane, Object { private string get_login_url() { string facebook_locale = get_system_locale_as_facebook_locale(); - - return "https://%s.facebook.com/dialog/oauth?client_id=%s&redirect_uri=https://www.facebook.com/connect/login_success.html&scope=publish_actions,user_photos,user_videos&response_type=token".printf(facebook_locale, APPLICATION_ID); + return "https://%s.facebook.com/dialog/oauth?client_id=%s&redirect_uri=https://www.facebook.com/connect/login_success.html&display=popup&scope=publish_actions,user_photos,user_videos&response_type=token".printf(facebook_locale, APPLICATION_ID); } private void on_page_load() { diff --git a/plugins/shotwell-publishing/Makefile b/plugins/shotwell-publishing/Makefile index 6b3945b..607bc6b 100644 --- a/plugins/shotwell-publishing/Makefile +++ b/plugins/shotwell-publishing/Makefile @@ -17,9 +17,7 @@ SRC_FILES := \ PicasaPublishing.vala \ FlickrPublishing.vala \ YouTubePublishing.vala \ - PiwigoPublishing.vala \ - ../../src/util/string.vala \ - ../common/RESTSupport.vala + PiwigoPublishing.vala RC_FILES := \ facebook.png \ diff --git a/plugins/shotwell-publishing/PicasaPublishing.vala b/plugins/shotwell-publishing/PicasaPublishing.vala index d1af942..cb6352c 100644 --- a/plugins/shotwell-publishing/PicasaPublishing.vala +++ b/plugins/shotwell-publishing/PicasaPublishing.vala @@ -588,7 +588,7 @@ internal class UploadTransaction : // create a message that can be sent over the wire whose payload is the multipart container // that we've been building up Soup.Message outbound_message = - soup_form_request_new_from_multipart(get_endpoint_url(), message_parts); + Soup.Form.request_new_from_multipart(get_endpoint_url(), message_parts); outbound_message.request_headers.append("Authorization", "Bearer " + session.get_access_token()); set_message(outbound_message); diff --git a/plugins/shotwell-publishing/PiwigoPublishing.vala b/plugins/shotwell-publishing/PiwigoPublishing.vala index d7b972b..7dd9090 100644 --- a/plugins/shotwell-publishing/PiwigoPublishing.vala +++ b/plugins/shotwell-publishing/PiwigoPublishing.vala @@ -937,29 +937,18 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object { * @param txn the received transaction * @return the value of pwg_id if present or null if not found */ - private new string? get_pwg_id_from_transaction(Publishing.RESTSupport.Transaction txn) { - string cookie = txn.get_response_headers().get_list("Set-Cookie"); - string pwg_id = null; - debug("Full cookie string: %s".printf(cookie)); - if (!is_string_empty(cookie)) { - string[] cookie_segments = cookie.split(";"); - debug("Split full string into %d individual segments".printf(cookie_segments.length)); - foreach(string cookie_segment in cookie_segments) { - debug("Individual cookie segment: %s".printf(cookie_segment)); - string[] cookie_sub_segments = cookie_segment.split(","); - debug("Split segment into %d individual sub-segments".printf(cookie_sub_segments.length)); - foreach(string cookie_sub_segment in cookie_sub_segments) { - debug("Individual cookie sub-segment: %s".printf(cookie_sub_segment)); - string[] cookie_kv = cookie_sub_segment.split("="); - debug("Split sub-segment into %d chunks".printf(cookie_kv.length)); - if (cookie_kv.length > 1 && cookie_kv[0].strip() == "pwg_id") { - debug("Found pwg_id: %s".printf(cookie_kv[1].strip())); - pwg_id = cookie_kv[1].strip(); - } - } + private string? get_pwg_id_from_transaction(Publishing.RESTSupport.Transaction txn) { + string? pwg_id = null; + + foreach (var cookie in Soup.cookies_from_response(txn.get_message())) { + if (cookie.get_name() == "pwg_id") { + // Collect all ids, last one is the one to use. First one is + // for Guest apparently + pwg_id = cookie.get_value(); + debug ("Found pwg_id %s", pwg_id); } } - + return pwg_id; } } @@ -1093,11 +1082,9 @@ internal class AuthenticationPane : Spit.Publishing.DialogPane, Object { } private void update_login_button_sensitivity() { - login_button.set_sensitive( - !is_string_empty(url_entry.get_text()) && - !is_string_empty(username_entry.get_text()) && - !is_string_empty(password_entry.get_text()) - ); + login_button.set_sensitive(url_entry.text_length != 0 && + username_entry.text_length != 0 && + password_entry.text_length != 0); } public Gtk.Widget get_widget() { @@ -1325,7 +1312,7 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, Object { !( create_new_radio.get_active() && ( - is_string_empty(category_name) || + category_name != "" || category_already_exists(search_name) ) ) @@ -1669,12 +1656,7 @@ private class ImagesAddTransaction : Publishing.RESTSupport.UploadTransaction { string[] keywords = publishable.get_publishing_keywords(); string tags = ""; if (keywords != null) { - foreach (string tag in keywords) { - if (!is_string_empty(tags)) { - tags += ","; - } - tags += tag; - } + tags = string.joinv (",", keywords); } debug("PiwigoConnector: Uploading photo %s to category id %d with perm level %d", @@ -1683,16 +1665,16 @@ private class ImagesAddTransaction : Publishing.RESTSupport.UploadTransaction { string name = publishable.get_publishing_name(); string comment = publishable.get_param_string( Spit.Publishing.Publishable.PARAM_STRING_COMMENT); - if (is_string_empty(name)) { + if (name != "") { name = publishable.get_param_string( Spit.Publishing.Publishable.PARAM_STRING_BASENAME); add_argument("name", name); - if (!is_string_empty(comment)) { + if (comment != null && comment != "") { add_argument("comment", comment); } } else { // name is set - if (!is_string_empty(comment)) { + if (comment != null && comment != "") { add_argument("name", name); add_argument("comment", comment); } else { @@ -1710,7 +1692,7 @@ private class ImagesAddTransaction : Publishing.RESTSupport.UploadTransaction { add_argument("category", parameters.category.id.to_string()); add_argument("level", parameters.perm_level.id.to_string()); if (!parameters.no_upload_tags) - if (!is_string_empty(tags)) + if (tags != "") add_argument("tags", tags); // TODO: update the Publishable interface so that it gives access to // the image's meta-data where the author (artist) is kept diff --git a/plugins/shotwell-publishing/YouTubePublishing.vala b/plugins/shotwell-publishing/YouTubePublishing.vala index ccb835f..15f283f 100644 --- a/plugins/shotwell-publishing/YouTubePublishing.vala +++ b/plugins/shotwell-publishing/YouTubePublishing.vala @@ -592,7 +592,7 @@ internal class UploadTransaction : Publishing.RESTSupport.GooglePublisher.Authen // create a message that can be sent over the wire whose payload is the multipart container // that we've been building up Soup.Message outbound_message = - soup_form_request_new_from_multipart(get_endpoint_url(), message_parts); + Soup.Form.request_new_from_multipart(get_endpoint_url(), message_parts); outbound_message.request_headers.append("X-GData-Key", "key=%s".printf(DEVELOPER_KEY)); outbound_message.request_headers.append("Slug", publishable.get_param_string(Spit.Publishing.Publishable.PARAM_STRING_BASENAME)); diff --git a/plugins/shotwell-transitions/Makefile b/plugins/shotwell-transitions/Makefile index 043891c..9044011 100644 --- a/plugins/shotwell-transitions/Makefile +++ b/plugins/shotwell-transitions/Makefile @@ -1,6 +1,10 @@ PLUGIN := shotwell-transitions +PLUGIN_PKGS := \ + libxml-2.0 \ + libsoup-2.4 + SRC_FILES := \ shotwell-transitions.vala \ FadeEffect.vala \ |