summaryrefslogtreecommitdiff
path: root/plugins/shotwell-publishing/PiwigoPublishing.vala
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff.email>2023-06-14 20:36:37 +0200
committerJörg Frings-Fürst <debian@jff.email>2023-06-14 20:36:37 +0200
commitbb80d3feebdc9acc52e3f4ad24084d8425f043a2 (patch)
tree2084a84c39f159c6aea254775dc0880d52579d45 /plugins/shotwell-publishing/PiwigoPublishing.vala
parentb26ff0798252a1a8072dd2c7a67f6205de9fde11 (diff)
parent31804433d72460cbe0a39f9f8ea5e76058d84cda (diff)
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'plugins/shotwell-publishing/PiwigoPublishing.vala')
-rw-r--r--plugins/shotwell-publishing/PiwigoPublishing.vala445
1 files changed, 240 insertions, 205 deletions
diff --git a/plugins/shotwell-publishing/PiwigoPublishing.vala b/plugins/shotwell-publishing/PiwigoPublishing.vala
index d311ac5..9bf0013 100644
--- a/plugins/shotwell-publishing/PiwigoPublishing.vala
+++ b/plugins/shotwell-publishing/PiwigoPublishing.vala
@@ -1,18 +1,28 @@
-/* Copyright 2016 Software Freedom Conservancy Inc.
- *
- * This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
- */
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2016 Software Freedom Conservancy Inc.
-public class PiwigoService : Object, Spit.Pluggable, Spit.Publishing.Service {
- private const string ICON_FILENAME = "piwigo.svg";
+internal class Publishing.Piwigo.Account : Spit.Publishing.Account, Object {
+ public string server_uri;
+ public string user;
- private static Gdk.Pixbuf[] icon_pixbuf_set = null;
-
- public PiwigoService(GLib.File resource_directory) {
- if (icon_pixbuf_set == null)
- icon_pixbuf_set = Resources.load_from_resource
- (Resources.RESOURCE_PATH + "/" + ICON_FILENAME);
+ public Account(string server_uri, string user) {
+ this.server_uri = server_uri;
+ this.user = user;
+ }
+
+ public string display_name() {
+ try {
+ var uri = Uri.parse(server_uri, UriFlags.NONE);
+ return user + "@" + uri.get_host();
+ } catch (Error err) {
+ debug("Failed to parse uri in Piwigo account. %s", err.message);
+ return user + "@" + server_uri;
+ }
+ }
+}
+
+public class PiwigoService : Object, Spit.Pluggable, Spit.Publishing.Service {
+ public PiwigoService() {
}
public int get_pluggable_interface(int min_host_interface, int max_host_interface) {
@@ -21,35 +31,68 @@ public class PiwigoService : Object, Spit.Pluggable, Spit.Publishing.Service {
}
public unowned string get_id() {
- return "org.yorba.shotwell.publishing.piwigo";
+ return "org.gnome.shotwell.publishing.piwigo";
}
public unowned string get_pluggable_name() {
return "Piwigo";
}
- public void get_info(ref Spit.PluggableInfo info) {
+ public Spit.PluggableInfo get_info() {
+ var info = new Spit.PluggableInfo();
+
info.authors = "Bruno Girin";
info.copyright = _("Copyright 2016 Software Freedom Conservancy Inc.");
info.translators = Resources.TRANSLATORS;
info.version = _VERSION;
- info.website_name = Resources.WEBSITE_NAME;
- info.website_url = Resources.WEBSITE_URL;
- info.is_license_wordwrapped = false;
- info.license = Resources.LICENSE;
- info.icons = icon_pixbuf_set;
+ info.icon_name = "piwigo";
+
+ return info;
}
public void activation(bool enabled) {
}
public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) {
- return new Publishing.Piwigo.PiwigoPublisher(this, host);
+ return new Publishing.Piwigo.PiwigoPublisher(this, host, null);
+ }
+
+ public Spit.Publishing.Publisher create_publisher_with_account(Spit.Publishing.PluginHost host,
+ Spit.Publishing.Account? account) {
+ return new Publishing.Piwigo.PiwigoPublisher(this, host, account);
}
public Spit.Publishing.Publisher.MediaType get_supported_media() {
return (Spit.Publishing.Publisher.MediaType.PHOTO);
}
+
+ public Gee.List<Spit.Publishing.Account>? get_accounts(string profile_id) {
+ var list = new Gee.ArrayList<Spit.Publishing.Account>();
+
+ // Always add the empty default account to allow new logins
+ list.add(new Spit.Publishing.DefaultAccount());
+
+ // Collect information from saved logins
+ var schema = new Secret.Schema (Publishing.Piwigo.PiwigoPublisher.PASSWORD_SCHEME, Secret.SchemaFlags.NONE,
+ Publishing.Piwigo.PiwigoPublisher.SCHEMA_KEY_PROFILE_ID, Secret.SchemaAttributeType.STRING,
+ "url", Secret.SchemaAttributeType.STRING,
+ "user", Secret.SchemaAttributeType.STRING);
+
+ var attributes = new HashTable<string, string>(str_hash, str_equal);
+ attributes[Publishing.Piwigo.PiwigoPublisher.SCHEMA_KEY_PROFILE_ID] = profile_id;
+ try {
+ var entries = Secret.password_searchv_sync(schema, attributes, Secret.SearchFlags.ALL, null);
+
+ foreach (var entry in entries) {
+ var found_attributes = entry.get_attributes();
+ list.add(new Publishing.Piwigo.Account(found_attributes["url"], found_attributes["user"]));
+ }
+ } catch (Error err) {
+ warning("Failed to look up accounts for Piwigo: %s", err.message);
+ }
+
+ return list;
+ }
}
namespace Publishing.Piwigo {
@@ -117,12 +160,16 @@ internal class PublishingParameters {
public SizeEntry photo_size = null;
public bool title_as_comment = false;
public bool no_upload_tags = false;
+ public bool no_upload_ratings = false;
public PublishingParameters() {
}
}
public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
+ internal const string PASSWORD_SCHEME = "org.gnome.Shotwell.Piwigo";
+ internal const string SCHEMA_KEY_PROFILE_ID = "shotwell-profile-id";
+
private Spit.Publishing.Service service;
private Spit.Publishing.PluginHost host;
private bool running = false;
@@ -131,13 +178,26 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
private Category[] categories = null;
private PublishingParameters parameters = null;
private Spit.Publishing.ProgressCallback progress_reporter = null;
+ private Secret.Schema? schema = null;
+ private Publishing.Piwigo.Account? account = null;
public PiwigoPublisher(Spit.Publishing.Service service,
- Spit.Publishing.PluginHost host) {
+ Spit.Publishing.PluginHost host,
+ Spit.Publishing.Account? account) {
debug("PiwigoPublisher instantiated.");
this.service = service;
this.host = host;
session = new Session();
+
+ // This should only ever be the default account which we don't care about
+ if (account is Publishing.Piwigo.Account) {
+ this.account = (Publishing.Piwigo.Account)account;
+ }
+
+ this.schema = new Secret.Schema (PASSWORD_SCHEME, Secret.SchemaFlags.NONE,
+ SCHEMA_KEY_PROFILE_ID, Secret.SchemaAttributeType.STRING,
+ "url", Secret.SchemaAttributeType.STRING,
+ "user", Secret.SchemaAttributeType.STRING);
}
// Publisher interface implementation
@@ -164,14 +224,16 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
if (session.is_authenticated()) {
debug("PiwigoPublisher: session is authenticated.");
- do_fetch_categories();
+ do_fetch_categories.begin();
} else {
debug("PiwigoPublisher: session is not authenticated.");
string? persistent_url = get_persistent_url();
string? persistent_username = get_persistent_username();
- string? persistent_password = get_persistent_password();
+ string? persistent_password = get_persistent_password(persistent_url, persistent_username);
+
+ // This will only be null if either of the other two was null or the password did not exist
if (persistent_url != null && persistent_username != null && persistent_password != null)
- do_network_login(persistent_url, persistent_username,
+ do_network_login.begin(persistent_url, persistent_username,
persistent_password, get_remember_password());
else
do_show_authentication_pane();
@@ -185,27 +247,65 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
// Session and persistent data
public string? get_persistent_url() {
- return host.get_config_string("url", null);
+ if (account != null) {
+ return account.server_uri;
+ }
+
+ return null;
}
private void set_persistent_url(string url) {
- host.set_config_string("url", url);
+ // Do nothing
}
public string? get_persistent_username() {
- return host.get_config_string("username", null);
+ if (account != null) {
+ return account.user;
+ }
+
+ return null;
}
private void set_persistent_username(string username) {
- host.set_config_string("username", username);
+ // Do nothing
}
- public string? get_persistent_password() {
- return host.get_config_string("password", null);
+ public string? get_persistent_password(string? url, string? user) {
+ if (url != null && user != null) {
+ try {
+ var pw = Secret.password_lookup_sync(this.schema, null,
+ SCHEMA_KEY_PROFILE_ID, host.get_current_profile_id(),
+ "url", url, "user", user);
+
+ return pw;
+ } catch (Error err) {
+ critical("Failed to lookup the password for url %s and user %s: %s", url, user, err.message);
+
+ return null;
+ }
+ }
+
+ return null;
}
- private void set_persistent_password(string? password) {
- host.set_config_string("password", password);
+ private void set_persistent_password(string? url, string? user, string? password) {
+ try {
+ if (password == null) {
+ // remove
+ Secret.password_clear_sync(this.schema, null,
+ SCHEMA_KEY_PROFILE_ID, host.get_current_profile_id(),
+ "url", url, "user", user);
+ } else {
+ Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+ "Shotwell publishing (Piwigo account %s@%s)".printf(user, url),
+ password,
+ null,
+ SCHEMA_KEY_PROFILE_ID, host.get_current_profile_id(),
+ "url", url, "user", user);
+ }
+ } catch (Error err) {
+ critical("Failed to store password for %s@%s: %s", user, url, err.message);
+ }
}
public bool get_remember_password() {
@@ -256,6 +356,14 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
host.set_config_bool("last-no-upload-tags", no_upload_tags);
}
+ private bool get_last_no_upload_ratings() {
+ return host.get_config_bool("last-no-upload-ratings", false);
+ }
+
+ private void set_last_no_upload_ratings(bool no_upload_ratings) {
+ host.set_config_bool("last-no-upload-ratings", no_upload_ratings);
+ }
+
private bool get_metadata_removal_choice() {
return host.get_config_bool("strip_metadata", false);
}
@@ -290,9 +398,14 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
private void do_show_ssl_downgrade_pane (SessionLoginTransaction trans,
string url) {
- var uri = new Soup.URI (url);
+ string host_name = "";
+ try {
+ host_name = GLib.Uri.parse (url, GLib.UriFlags.NONE).get_host();
+ } catch (Error err) {
+ debug("Failed to parse URL: %s", err.message);
+ }
host.set_service_locked (false);
- var ssl_pane = new SSLErrorPane (trans, uri.get_host ());
+ var ssl_pane = new SSLErrorPane (trans, host_name);
ssl_pane.proceed.connect (() => {
debug ("SSL: User wants us to retry with broken certificate");
this.session = new Session ();
@@ -300,9 +413,9 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
string? persistent_url = get_persistent_url();
string? persistent_username = get_persistent_username();
- string? persistent_password = get_persistent_password();
+ string? persistent_password = get_persistent_password(persistent_url, persistent_username);
if (persistent_url != null && persistent_username != null && persistent_password != null)
- do_network_login(persistent_url, persistent_username,
+ do_network_login.begin(persistent_url, persistent_username,
persistent_password, get_remember_password());
else
do_show_authentication_pane();
@@ -330,7 +443,7 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
if (!running)
return;
- do_network_login(url, username, password, remember_password);
+ do_network_login.begin(url, username, password, remember_password);
}
/**
@@ -344,24 +457,24 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
* @param username the name of the Piwigo user used to login
* @param password the password of the Piwigo user used to login
*/
- private void do_network_login(string url, string username, string password, bool remember_password) {
+ private async void do_network_login(string url, string username, string password, bool remember_password) {
debug("ACTION: logging in");
host.set_service_locked(true);
host.install_login_wait_pane();
set_remember_password(remember_password);
- if (remember_password)
- set_persistent_password(password);
- else
- set_persistent_password(null);
+ if (remember_password) {
+ set_persistent_password(url, username, password);
+ } else {
+ set_persistent_password(url, username, null);
+ }
SessionLoginTransaction login_trans = new SessionLoginTransaction(
session, normalise_url(url), username, password);
- login_trans.network_error.connect(on_login_network_error);
- login_trans.completed.connect(on_login_network_complete);
try {
- login_trans.execute();
+ yield login_trans.execute_async();
+ on_login_network_complete(login_trans);
} catch (Spit.Publishing.PublishingError err) {
if (err is Spit.Publishing.PublishingError.SSL_FAILED) {
debug ("ERROR: SSL connection problems");
@@ -405,8 +518,6 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
*/
private void on_login_network_complete(Publishing.RESTSupport.Transaction txn) {
debug("EVENT: on_login_network_complete");
- txn.completed.disconnect(on_login_network_complete);
- txn.network_error.disconnect(on_login_network_error);
try {
Publishing.RESTSupport.XmlDocument.parse_string(
@@ -435,34 +546,9 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
debug("Setting session pwg_id to %s", pwg_id);
session.set_pwg_id(pwg_id);
- do_fetch_session_status(endpoint_url, pwg_id);
- }
-
- /**
- * Event triggered when a network login action fails due to a network error.
- *
- * This event triggered as a result of a network error during the login
- * transaction. As a result, it assumes that the service URL entered in the
- * authentication dialog is incorrect and re-presents the authentication
- * dialog with FAILED_RETRY_URL mode.
- *
- * @param bad_txn the received REST transaction
- * @param err the received error
- */
- private void on_login_network_error(
- Publishing.RESTSupport.Transaction bad_txn,
- Spit.Publishing.PublishingError err
- ) {
- debug("EVENT: on_login_network_error");
- bad_txn.completed.disconnect(on_login_network_complete);
- bad_txn.network_error.disconnect(on_login_network_error);
-
- if (session.is_authenticated()) // ignore these events if the session is already auth'd
- return;
-
- do_show_authentication_pane(AuthenticationPane.Mode.FAILED_RETRY_URL);
+ do_fetch_session_status.begin(endpoint_url, pwg_id);
}
-
+
/**
* Action to fetch the session status for a known Piwigo user.
*
@@ -473,29 +559,27 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
* persisted. In this case, it will log the user in and confirm the
* identity.
*/
- private void do_fetch_session_status(string url = "", string pwg_id = "") {
+ private async void do_fetch_session_status(string url = "", string pwg_id = "") {
debug("ACTION: fetching session status");
host.set_service_locked(true);
host.install_account_fetch_wait_pane();
if (!session.is_authenticated()) {
SessionGetStatusTransaction status_txn = new SessionGetStatusTransaction.unauthenticated(session, url, pwg_id);
- status_txn.network_error.connect(on_session_get_status_error);
- status_txn.completed.connect(on_session_get_status_complete);
try {
- status_txn.execute();
+ yield status_txn.execute_async();
+ on_session_get_status_complete(status_txn);
} catch (Spit.Publishing.PublishingError err) {
debug("ERROR: do_fetch_session_status, not authenticated");
do_show_error(err);
}
} else {
SessionGetStatusTransaction status_txn = new SessionGetStatusTransaction(session);
- status_txn.network_error.connect(on_session_get_status_error);
- status_txn.completed.connect(on_session_get_status_complete);
try {
- status_txn.execute();
+ yield status_txn.execute_async();
+ on_session_get_status_complete(status_txn);
} catch (Spit.Publishing.PublishingError err) {
debug("ERROR: do_fetch_session_status, authenticated");
do_show_error(err);
@@ -512,8 +596,6 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
*/
private void on_session_get_status_complete(Publishing.RESTSupport.Transaction txn) {
debug("EVENT: on_session_get_status_complete");
- txn.completed.disconnect(on_session_get_status_complete);
- txn.network_error.disconnect(on_session_get_status_error);
if (!session.is_authenticated()) {
string endpoint_url = txn.get_endpoint_url();
@@ -533,7 +615,7 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
session.authenticate(endpoint_url, username, pwg_id);
set_persistent_url(session.get_pwg_url());
set_persistent_username(session.get_username());
- do_fetch_categories();
+ do_fetch_categories.begin();
} catch (Spit.Publishing.PublishingError err2) {
debug("ERROR: on_session_get_status_complete, inner");
do_show_error(err2);
@@ -548,43 +630,30 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
// This should never happen as the session should not be
// authenticated at that point so this call is a safeguard
// against the interaction not happening properly.
- do_fetch_categories();
+ do_fetch_categories.begin();
}
}
/**
- * Event triggered when the get session status fails due to a network error.
- */
- private void on_session_get_status_error(
- Publishing.RESTSupport.Transaction bad_txn,
- Spit.Publishing.PublishingError err
- ) {
- debug("EVENT: on_session_get_status_error");
- bad_txn.completed.disconnect(on_session_get_status_complete);
- bad_txn.network_error.disconnect(on_session_get_status_error);
- on_network_error(bad_txn, err);
- }
-
- /**
* Action that fetches all available categories from the Piwigo service.
*
* This action fetches all categories from the Piwigo service in order
* to populate the publishing pane presented to the user.
*/
- private void do_fetch_categories() {
+ private async void do_fetch_categories() {
debug("ACTION: fetching categories");
host.set_service_locked(true);
host.install_account_fetch_wait_pane();
CategoriesGetListTransaction cat_trans = new CategoriesGetListTransaction(session);
- cat_trans.network_error.connect(on_category_fetch_error);
- cat_trans.completed.connect(on_category_fetch_complete);
try {
- cat_trans.execute();
+ yield cat_trans.execute_async();
+ on_category_fetch_complete(cat_trans);
} catch (Spit.Publishing.PublishingError err) {
debug("ERROR: do_fetch_categories");
do_show_error(err);
+ return;
}
}
@@ -597,8 +666,6 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
*/
private void on_category_fetch_complete(Publishing.RESTSupport.Transaction txn) {
debug("EVENT: on_category_fetch_complete");
- txn.completed.disconnect(on_category_fetch_complete);
- txn.network_error.disconnect(on_category_fetch_error);
debug("PiwigoConnector: list of categories: %s", txn.get_response());
// Empty the categories
if (categories != null) {
@@ -654,20 +721,6 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
}
/**
- * Event triggered when the fetch categories transaction fails due to a
- * network error.
- */
- private void on_category_fetch_error(
- Publishing.RESTSupport.Transaction bad_txn,
- Spit.Publishing.PublishingError err
- ) {
- debug("EVENT: on_category_fetch_error");
- bad_txn.completed.disconnect(on_category_fetch_complete);
- bad_txn.network_error.disconnect(on_category_fetch_error);
- on_network_error(bad_txn, err);
- }
-
- /**
* Action that shows the publishing options pane.
*
* This action method shows the publishing options pane.
@@ -678,8 +731,8 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
host.set_service_locked(false);
PublishingOptionsPane opts_pane = new PublishingOptionsPane(
this, categories, get_last_category(), get_last_permission_level(), get_last_photo_size(),
- get_last_title_as_comment(), get_last_no_upload_tags(), get_metadata_removal_choice());
- opts_pane.logout.connect(on_publishing_options_pane_logout_clicked);
+ get_last_title_as_comment(), get_last_no_upload_tags(), get_last_no_upload_ratings(), get_metadata_removal_choice());
+ opts_pane.logout.connect(() => { on_publishing_options_pane_logout_clicked.begin(); });
opts_pane.publish.connect(on_publishing_options_pane_publish_clicked);
host.install_dialog_pane(opts_pane, Spit.Publishing.PluginHost.ButtonMode.CLOSE);
host.set_dialog_default_widget(opts_pane.get_default_widget());
@@ -688,14 +741,12 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
/**
* Event triggered when the user clicks logout in the publishing options pane.
*/
- private void on_publishing_options_pane_logout_clicked() {
+ private async void on_publishing_options_pane_logout_clicked() {
debug("EVENT: on_publishing_options_pane_logout_clicked");
- SessionLogoutTransaction logout_trans = new SessionLogoutTransaction(session);
- logout_trans.network_error.connect(on_logout_network_error);
- logout_trans.completed.connect(on_logout_network_complete);
try {
- logout_trans.execute();
+ yield new SessionLogoutTransaction(session).execute_async();
+ on_logout_network_complete();
} catch (Spit.Publishing.PublishingError err) {
debug("ERROR: on_publishing_options_pane_logout_clicked");
do_show_error(err);
@@ -708,29 +759,14 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
* This event de-authenticates the session and shows the authentication
* pane again.
*/
- private void on_logout_network_complete(Publishing.RESTSupport.Transaction txn) {
+ private void on_logout_network_complete() {
debug("EVENT: on_logout_network_complete");
- txn.completed.disconnect(on_logout_network_complete);
- txn.network_error.disconnect(on_logout_network_error);
session.deauthenticate();
do_show_authentication_pane(AuthenticationPane.Mode.INTRO);
}
-
- /**
- * Event triggered when the logout action fails due to a network error.
- */
- private void on_logout_network_error(
- Publishing.RESTSupport.Transaction bad_txn,
- Spit.Publishing.PublishingError err
- ) {
- debug("EVENT: on_logout_network_error");
- bad_txn.completed.disconnect(on_logout_network_complete);
- bad_txn.network_error.disconnect(on_logout_network_error);
- on_network_error(bad_txn, err);
- }
-
+
/**
* Event triggered when the user clicks publish in the publishing options pane.
*
@@ -748,9 +784,9 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
this.strip_metadata = strip_metadata;
if (parameters.category.is_local()) {
- do_create_category(parameters.category);
+ do_create_category.begin(parameters.category);
} else {
- do_upload(this.strip_metadata);
+ do_upload.begin(this.strip_metadata);
}
}
@@ -760,12 +796,12 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
* This actions runs a REST transaction to create a new category in the
* Piwigo library. It displays a wait pane with an information message
* while the transaction is running. This action should only be called with
- * a local cateogory, i.e. one that does not exist on the server and does
+ * a local category, i.e. one that does not exist on the server and does
* not yet have an ID.
*
* @param category the new category to create on the server
*/
- private void do_create_category(Category category) {
+ private async void do_create_category(Category category) {
debug("ACTION: creating a new category: %s".printf(category.name));
assert(category.is_local());
@@ -774,11 +810,10 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
CategoriesAddTransaction creation_trans = new CategoriesAddTransaction(
session, category.name.strip(), int.parse(category.uppercats), category.comment);
- creation_trans.network_error.connect(on_category_add_error);
- creation_trans.completed.connect(on_category_add_complete);
try {
- creation_trans.execute();
+ yield creation_trans.execute_async();
+ on_category_add_complete(creation_trans);
} catch (Spit.Publishing.PublishingError err) {
debug("ERROR: do_create_category");
do_show_error(err);
@@ -794,8 +829,6 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
*/
private void on_category_add_complete(Publishing.RESTSupport.Transaction txn) {
debug("EVENT: on_category_add_complete");
- txn.completed.disconnect(on_category_add_complete);
- txn.network_error.disconnect(on_category_add_error);
// Parse the response
try {
@@ -808,30 +841,17 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
string id_string = id_node->get_content();
int id = int.parse(id_string);
parameters.category.id = id;
- do_upload(strip_metadata);
+ do_upload.begin(strip_metadata);
} catch (Spit.Publishing.PublishingError err) {
debug("ERROR: on_category_add_complete");
do_show_error(err);
}
}
-
- /**
- * Event triggered when the add category action fails due to a network error.
- */
- private void on_category_add_error(
- Publishing.RESTSupport.Transaction bad_txn,
- Spit.Publishing.PublishingError err
- ) {
- debug("EVENT: on_category_add_error");
- bad_txn.completed.disconnect(on_category_add_complete);
- bad_txn.network_error.disconnect(on_category_add_error);
- on_network_error(bad_txn, err);
- }
-
+
/**
* Upload action: the big one, the one we've been waiting for!
*/
- private void do_upload(bool strip_metadata) {
+ private async void do_upload(bool strip_metadata) {
this.strip_metadata = strip_metadata;
debug("ACTION: uploading pictures");
@@ -842,25 +862,27 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
set_last_photo_size(parameters.photo_size.id);
set_last_title_as_comment(parameters.title_as_comment);
set_last_no_upload_tags(parameters.no_upload_tags);
+ set_last_no_upload_ratings(parameters.no_upload_ratings);
set_metadata_removal_choice(strip_metadata);
progress_reporter = host.serialize_publishables(parameters.photo_size.id, this.strip_metadata);
Spit.Publishing.Publishable[] publishables = host.get_publishables();
Uploader uploader = new Uploader(session, publishables, parameters);
- uploader.upload_complete.connect(on_upload_complete);
- uploader.upload_error.connect(on_upload_error);
- uploader.upload(on_upload_status_updated);
+ try {
+ var num_published = yield uploader.upload_async(on_upload_status_updated);
+ on_upload_complete(num_published);
+ } catch (Spit.Publishing.PublishingError err) {
+ do_show_error(err);
+ }
}
/**
* Event triggered when the batch uploader reports that at least one of the
* network transactions encapsulating uploads has completed successfully
*/
- private void on_upload_complete(Publishing.RESTSupport.BatchUploader uploader, int num_published) {
+ private void on_upload_complete(int num_published) {
debug("EVENT: on_upload_complete");
- uploader.upload_complete.disconnect(on_upload_complete);
- uploader.upload_error.disconnect(on_upload_error);
// TODO: should a message be displayed to the user if num_published is zero?
@@ -869,22 +891,7 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
do_show_success_pane();
}
-
- /**
- * Event triggered when the batch uploader reports that at least one of the
- * network transactions encapsulating uploads has caused a network error
- */
- private void on_upload_error(
- Publishing.RESTSupport.BatchUploader uploader,
- Spit.Publishing.PublishingError err
- ) {
- debug("EVENT: on_upload_error");
- uploader.upload_complete.disconnect(on_upload_complete);
- uploader.upload_error.disconnect(on_upload_error);
-
- do_show_error(err);
- }
-
+
/**
* Event triggered when upload progresses and the status needs to be updated.
*/
@@ -910,17 +917,6 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
}
/**
- * Helper event to handle network errors.
- */
- private void on_network_error(
- Publishing.RESTSupport.Transaction bad_txn,
- Spit.Publishing.PublishingError err
- ) {
- debug("EVENT: on_network_error");
- do_show_error(err);
- }
-
- /**
* Action to display an error to the user.
*/
private void do_show_error(Spit.Publishing.PublishingError e) {
@@ -1029,8 +1025,9 @@ internal class SSLErrorPane : Shotwell.Plugins.Common.BuilderPane {
base.constructed ();
var label = this.get_builder ().get_object ("main_text") as Gtk.Label;
+ var bold_host = "<b>%s</b>".printf(host);
// %s is the host name that we tried to connect to
- label.set_text (_("This does not look like the real <b>%s</b>. Attackers might be trying to steal or alter information going to or from this site (for example, private messages, credit card information, or passwords).").printf (host));
+ label.set_text (_("This does not look like the real %s. Attackers might be trying to steal or alter information going to or from this site (for example, private messages, credit card information, or passwords).").printf(bold_host));
label.use_markup = true;
label = this.get_builder ().get_object ("ssl_errors") as Gtk.Label;
@@ -1136,7 +1133,7 @@ internal class AuthenticationPane : Shotwell.Plugins.Common.BuilderPane {
username_entry.set_text(persistent_username);
}
password_entry = builder.get_object ("password_entry") as Gtk.Entry;
- string? persistent_password = publisher.get_persistent_password();
+ string? persistent_password = publisher.get_persistent_password(persistent_url, persistent_username);
if (persistent_password != null) {
password_entry.set_text(persistent_password);
}
@@ -1205,6 +1202,7 @@ internal class PublishingOptionsPane : Shotwell.Plugins.Common.BuilderPane {
private Gtk.CheckButton strip_metadata_check = null;
private Gtk.CheckButton title_as_comment_check = null;
private Gtk.CheckButton no_upload_tags_check = null;
+ private Gtk.CheckButton no_upload_ratings_check = null;
private Gtk.Button logout_button;
private Gtk.Button publish_button;
private Gtk.TextView album_comment;
@@ -1218,6 +1216,7 @@ internal class PublishingOptionsPane : Shotwell.Plugins.Common.BuilderPane {
public int last_photo_size { private get; construct; }
public bool last_title_as_comment { private get; construct; }
public bool last_no_upload_tags { private get; construct; }
+ public bool last_no_upload_ratings { private get; construct; }
public bool strip_metadata_enabled { private get; construct; }
public Gee.List<Category> existing_categories { private get; construct; }
public string default_comment { private get; construct; }
@@ -1232,6 +1231,7 @@ internal class PublishingOptionsPane : Shotwell.Plugins.Common.BuilderPane {
int last_photo_size,
bool last_title_as_comment,
bool last_no_upload_tags,
+ bool last_no_upload_ratings,
bool strip_metadata_enabled) {
Object (resource_path : Resources.RESOURCE_PATH +
"/piwigo_publishing_options_pane.ui",
@@ -1242,6 +1242,7 @@ internal class PublishingOptionsPane : Shotwell.Plugins.Common.BuilderPane {
last_photo_size : last_photo_size,
last_title_as_comment : last_title_as_comment,
last_no_upload_tags : last_no_upload_tags,
+ last_no_upload_ratings : last_no_upload_ratings,
strip_metadata_enabled : strip_metadata_enabled,
existing_categories : new Gee.ArrayList<Category>.wrap (categories,
Category.equal),
@@ -1275,6 +1276,9 @@ internal class PublishingOptionsPane : Shotwell.Plugins.Common.BuilderPane {
no_upload_tags_check = builder.get_object("no_upload_tags_check") as Gtk.CheckButton;
no_upload_tags_check.set_active(last_no_upload_tags);
+ no_upload_ratings_check = builder.get_object("no_upload_ratings_check") as Gtk.CheckButton;
+ no_upload_ratings_check.set_active(last_no_upload_ratings);
+
logout_button = builder.get_object("logout_button") as Gtk.Button;
logout_button.clicked.connect(on_logout_button_clicked);
@@ -1325,6 +1329,7 @@ internal class PublishingOptionsPane : Shotwell.Plugins.Common.BuilderPane {
params.photo_size = photo_sizes[size_combo.get_active()];
params.title_as_comment = title_as_comment_check.get_active();
params.no_upload_tags = no_upload_tags_check.get_active();
+ params.no_upload_ratings = no_upload_ratings_check.get_active();
if (create_new_radio.get_active()) {
string uploadcomment = album_comment.buffer.text.strip();
int a = within_existing_combo.get_active();
@@ -1720,12 +1725,14 @@ private class CategoriesAddTransaction : Transaction {
private class ImagesAddTransaction : Publishing.RESTSupport.UploadTransaction {
private PublishingParameters parameters = null;
+ private Session session = null;
public ImagesAddTransaction(Session session, PublishingParameters parameters, Spit.Publishing.Publishable publishable) {
base.with_endpoint_url(session, publishable, session.get_pwg_url());
if (session.is_authenticated()) {
add_header("Cookie", "pwg_id=".concat(session.get_pwg_id()));
}
+ this.session = session;
this.parameters = parameters;
string[] keywords = publishable.get_publishing_keywords();
@@ -1785,12 +1792,40 @@ private class ImagesAddTransaction : Publishing.RESTSupport.UploadTransaction {
!basename.down().has_suffix(".jpg")) {
basename += ".jpg";
}
- disposition_table.insert("filename", Soup.URI.encode(basename, null));
+ disposition_table.insert("filename", GLib.Uri.escape_string(basename, null));
disposition_table.insert("name", "image");
set_binary_disposition_table(disposition_table);
+ base.completed.connect(on_completed);
+ }
+
+ private void on_completed() {
+ try{
+ Publishing.RESTSupport.XmlDocument resp_doc = Publishing.RESTSupport.XmlDocument.parse_string(
+ base.get_response(), Transaction.validate_xml);
+ Xml.Node* image_node = resp_doc.get_named_child(resp_doc.get_root_node(), "image_id");
+ string image_id = image_node->get_content();
+
+ if (!parameters.no_upload_ratings)
+ new ImagesAddRating(session, publishable, image_id);
+ } catch(Spit.Publishing.PublishingError err) {
+ debug("Response parse error");
+ }
}
}
-} // namespace
+private class ImagesAddRating : Publishing.RESTSupport.UploadTransaction {
+ public ImagesAddRating(Session session, Spit.Publishing.Publishable publishable, string image_id) {
+ base.with_endpoint_url(session, publishable, session.get_pwg_url());
+ if (session.is_authenticated()) {
+ add_header("Cookie", "pwg_id=".concat(session.get_pwg_id()));
+ }
+ add_argument("method", "pwg.images.rate");
+ add_argument("image_id", image_id);
+ add_argument("rate", publishable.get_rating().to_string());
+ base.execute_async.begin();
+ }
+}
+
+} // namespace