Mon, 24 Oct 2016 17:11:11 -0500
Merge to default to fix conflicts
| bitbucket-pipelines.yml | file | annotate | diff | comparison | revisions |
--- a/bitbucket-pipelines.yml Sun Oct 09 18:32:16 2016 -0500 +++ b/bitbucket-pipelines.yml Mon Oct 24 17:11:11 2016 -0500 @@ -8,4 +8,14 @@ - ./autogen.sh --enable-debug --enable-gtk-doc - make -s -j$(nproc) - make -s -j$(nproc) distcheck + branches: + release-2.x.y: + - step: + image: pidgin/release-builder:release-2.x.y + script: + - set -ex + - ./autogen.sh --enable-debug + - make -s -j$(nproc) + - make -s -j$(nproc) check + - make distcheck
--- a/configure.ac Sun Oct 09 18:32:16 2016 -0500 +++ b/configure.ac Mon Oct 24 17:11:11 2016 -0500 @@ -1522,19 +1522,29 @@ dnl # Check for Secret Service headers dnl ####################################################################### -# disabled - see secretservice.c -#AC_ARG_ENABLE(libsecret, [AC_HELP_STRING([--disable-libsecret], [enable Secret Service support])], enable_secret_service=no, enable_secret_service=yes) +AC_ARG_ENABLE(libsecret, + [AC_HELP_STRING([--disable-libsecret], [enable Secret Service support])], + enable_secret_service="$enableval", enable_secret_service="$is_not_win32") -#if test "x$enable_secret_service" = "xyes" ; then -# PKG_CHECK_MODULES(SECRETSERVICE, [libsecret-1], [ -# AC_SUBST(SECRETSERVICE_CFLAGS) -# AC_SUBST(SECRETSERVICE_LIBS) -# AC_DEFINE(HAVE_SECRETSERVICE, 1, [Define if we have Secret Service.]) -# ]) -#fi +if test "x$enable_secret_service" = "xyes" ; then + PKG_CHECK_MODULES(SECRETSERVICE, [libsecret-1], [ + AC_SUBST(SECRETSERVICE_CFLAGS) + AC_SUBST(SECRETSERVICE_LIBS) + AC_DEFINE(HAVE_SECRETSERVICE, 1, [Define if we have Secret Service.]) + ], [ + AC_MSG_RESULT(no) + enable_secret_service="no" + if test "x$force_deps" = "xyes" ; then + AC_MSG_ERROR([ +Libsecret development headers not found +Use --disable-libsecret if you do not need it. +]) + fi + ]) -#AM_CONDITIONAL(ENABLE_SECRETSERVICE, test "x$enable_secret_service" = "xyes") -AM_CONDITIONAL(ENABLE_SECRETSERVICE, test "x1" = "x2") +fi + +AM_CONDITIONAL(ENABLE_SECRETSERVICE, test "x$enable_secret_service" = "xyes") dnl ####################################################################### dnl # Check for GNOME Keyring headers @@ -2254,7 +2264,7 @@ echo echo Build with GNOME Keyring...... : $enable_gnome_keyring echo Build with KWallet............ : $enable_kwallet -#echo Build with Secret Service..... : $enable_secret_service +echo Build with Secret Service..... : $enable_secret_service echo echo Build with plugin support..... : $enable_plugins echo Enable Introspection...........: $enable_introspection
--- a/libpurple/plugins/keyrings/secretservice.c Sun Oct 09 18:32:16 2016 -0500 +++ b/libpurple/plugins/keyrings/secretservice.c Mon Oct 24 17:11:11 2016 -0500 @@ -21,17 +21,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#error "This keyring needs some more work (see TODO)" - /* TODO * - * This keyring needs some more work, so it will be disabled until its quality - * was raised. Some of the pain points: - * - throws a lot of g_warnings - * - it doesn't notify about some backend faults (like access denied), some of - * them are not handled at all - * - it could use libsecret's Complete API - * - code formatting could be better + * This keyring now works (at the time of this writing), but there are + * some inconvenient edge cases. When looking up passwords, libsecret + * doesn't error if the keyring is locked. Therefore, it appears to + * this plugin that there's no stored password. libpurple seems to + * handle this as gracefully as possible, but it's still inconvenient. + * This plugin could possibly be ported to use libsecret's "Complete API" + * to resolve this if desired. */ #include "internal.h" @@ -53,6 +51,7 @@ #define SECRETSERVICE_DOMAIN (g_quark_from_static_string(SECRETSERVICE_ID)) static PurpleKeyring *keyring_handler = NULL; +static GCancellable *keyring_cancellable = NULL; static const SecretSchema purple_schema = { "im.pidgin.Purple", SECRET_SCHEMA_NONE, @@ -78,6 +77,62 @@ /* Keyring interface */ /***********************************************/ static void +ss_g_error_to_keyring_error(GError **error, PurpleAccount *account) +{ + GError *old_error; + GError *new_error = NULL; + + g_return_if_fail(error != NULL); + + old_error = *error; + + if (g_error_matches(old_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_CANCELLED, + _("Operation cancelled.")); + } else if (g_error_matches(old_error, G_DBUS_ERROR, + G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND) || + g_error_matches(old_error, G_DBUS_ERROR, + G_DBUS_ERROR_IO_ERROR)) { + purple_debug_info("keyring-libsecret", + "Failed to communicate with Secret " + "Service (account: %s (%s)).\n", + purple_account_get_username(account), + purple_account_get_protocol_id(account)); + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_BACKENDFAIL, + "Failed to communicate with Secret " + "Service (account: %s).", + purple_account_get_username(account)); + } else if (g_error_matches(old_error, SECRET_ERROR, + SECRET_ERROR_IS_LOCKED)) { + purple_debug_info("keyring-libsecret", + "Secret Service is locked (account: %s (%s)).\n", + purple_account_get_username(account), + purple_account_get_protocol_id(account)); + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_ACCESSDENIED, + "Secret Service is locked (account: %s).", + purple_account_get_username(account)); + } else { + purple_debug_error("keyring-libsecret", + "Unknown error (account: %s (%s), " + "domain: %s, code: %d): %s.\n", + purple_account_get_username(account), + purple_account_get_protocol_id(account), + g_quark_to_string(old_error->domain), + old_error->code, old_error->message); + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_BACKENDFAIL, + "Unknown error (account: %s).", + purple_account_get_username(account)); + } + + g_clear_error(error); + g_propagate_error(error, new_error); +} + +static void ss_read_continue(GObject *object, GAsyncResult *result, gpointer data) { InfoStorage *storage = data; @@ -89,53 +144,19 @@ password = secret_password_lookup_finish(result, &error); if (error != NULL) { - int code = error->code; - - switch (code) { - case G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND: - case G_DBUS_ERROR_IO_ERROR: - error = g_error_new(PURPLE_KEYRING_ERROR, - PURPLE_KEYRING_ERROR_BACKENDFAIL, - "Failed to communicate with Secret " - "Service (account : %s).", - purple_account_get_username(account)); - if (cb != NULL) - cb(account, NULL, error, storage->user_data); - g_error_free(error); - break; - - default: - purple_debug_error("keyring-libsecret", - "Unknown error (account: %s (%s), " - "domain: %s, code: %d): %s.\n", - purple_account_get_username(account), - purple_account_get_protocol_id(account), - g_quark_to_string(error->domain), code, - error->message); - error = g_error_new(PURPLE_KEYRING_ERROR, - PURPLE_KEYRING_ERROR_BACKENDFAIL, - "Unknown error (account : %s).", - purple_account_get_username(account)); - if (cb != NULL) - cb(account, NULL, error, storage->user_data); - g_error_free(error); - break; - } - + ss_g_error_to_keyring_error(&error, account); } else if (password == NULL) { error = g_error_new(PURPLE_KEYRING_ERROR, PURPLE_KEYRING_ERROR_NOPASSWORD, "No password found for account: %s", purple_account_get_username(account)); - if (cb != NULL) - cb(account, NULL, error, storage->user_data); - g_error_free(error); - - } else { - if (cb != NULL) - cb(account, password, NULL, storage->user_data); } + if (cb != NULL) { + cb(account, password, error, storage->user_data); + } + + g_clear_error(&error); g_free(storage); } @@ -148,74 +169,57 @@ storage->cb = cb; storage->user_data = data; - secret_password_lookup(&purple_schema, NULL, ss_read_continue, storage, + secret_password_lookup(&purple_schema, keyring_cancellable, + ss_read_continue, storage, "user", purple_account_get_username(account), "protocol", purple_account_get_protocol_id(account), NULL); } static void -ss_save_continue(GObject *object, GAsyncResult *result, gpointer data) +ss_save_continue(GError *error, gpointer data) { InfoStorage *storage = data; PurpleKeyringSaveCallback cb; - GError *error = NULL; PurpleAccount *account; account = storage->account; cb = storage->cb; - secret_password_store_finish(result, &error); - if (error != NULL) { - int code = error->code; - - switch (code) { - case G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND: - case G_DBUS_ERROR_IO_ERROR: - purple_debug_info("keyring-libsecret", - "Failed to communicate with Secret " - "Service (account : %s (%s)).\n", - purple_account_get_username(account), - purple_account_get_protocol_id(account)); - error = g_error_new(PURPLE_KEYRING_ERROR, - PURPLE_KEYRING_ERROR_BACKENDFAIL, - "Failed to communicate with Secret Service (account : %s).", - purple_account_get_username(account)); - if (cb != NULL) - cb(account, error, storage->user_data); - g_error_free(error); - break; - - default: - purple_debug_error("keyring-libsecret", - "Unknown error (account: %s (%s), " - "domain: %s, code: %d): %s.\n", - purple_account_get_username(account), - purple_account_get_protocol_id(account), - g_quark_to_string(error->domain), code, - error->message); - error = g_error_new(PURPLE_KEYRING_ERROR, - PURPLE_KEYRING_ERROR_BACKENDFAIL, - "Unknown error (account : %s).", - purple_account_get_username(account)); - if (cb != NULL) - cb(account, error, storage->user_data); - g_error_free(error); - break; - } - + ss_g_error_to_keyring_error(&error, account); } else { purple_debug_info("keyring-libsecret", "Password for %s updated.\n", purple_account_get_username(account)); - - if (cb != NULL) - cb(account, NULL, storage->user_data); } + if (cb != NULL) + cb(account, error, storage->user_data); + + g_clear_error(&error); g_free(storage); } static void +ss_store_continue(GObject *object, GAsyncResult *result, gpointer data) +{ + GError *error = NULL; + + secret_password_store_finish(result, &error); + + ss_save_continue(error, data); +} + +static void +ss_clear_continue(GObject *object, GAsyncResult *result, gpointer data) +{ + GError *error = NULL; + + secret_password_clear_finish(result, &error); + + ss_save_continue(error, data); +} + +static void ss_save(PurpleAccount *account, const gchar *password, PurpleKeyringSaveCallback cb, @@ -237,7 +241,8 @@ label = g_strdup_printf(_("Pidgin IM password for account %s"), username); secret_password_store(&purple_schema, SECRET_COLLECTION_DEFAULT, - label, password, NULL, ss_save_continue, storage, + label, password, keyring_cancellable, + ss_store_continue, storage, "user", username, "protocol", purple_account_get_protocol_id(account), NULL); @@ -249,27 +254,42 @@ purple_account_get_username(account), purple_account_get_protocol_id(account)); - secret_password_clear(&purple_schema, NULL, ss_save_continue, - storage, "user", purple_account_get_username(account), + secret_password_clear(&purple_schema, keyring_cancellable, + ss_clear_continue, storage, + "user", purple_account_get_username(account), "protocol", purple_account_get_protocol_id(account), NULL); } } static void +ss_cancel(void) +{ + g_cancellable_cancel(keyring_cancellable); + + /* Swap out cancelled cancellable for new one for further operations */ + g_clear_object(&keyring_cancellable); + keyring_cancellable = g_cancellable_new(); +} + +static void ss_close(void) { + ss_cancel(); } static gboolean ss_init(GError **error) { + keyring_cancellable = g_cancellable_new(); + keyring_handler = purple_keyring_new(); purple_keyring_set_name(keyring_handler, _(SECRETSERVICE_NAME)); purple_keyring_set_id(keyring_handler, SECRETSERVICE_ID); purple_keyring_set_read_password(keyring_handler, ss_read); purple_keyring_set_save_password(keyring_handler, ss_save); + purple_keyring_set_cancel_requests(keyring_handler, ss_cancel); purple_keyring_set_close_keyring(keyring_handler, ss_close); purple_keyring_register(keyring_handler); @@ -284,6 +304,8 @@ purple_keyring_unregister(keyring_handler); purple_keyring_free(keyring_handler); keyring_handler = NULL; + + g_clear_object(&keyring_cancellable); } /***********************************************/
--- a/pidgin/data/pidgin-3-uninstalled.pc.in Sun Oct 09 18:32:16 2016 -0500 +++ b/pidgin/data/pidgin-3-uninstalled.pc.in Mon Oct 24 17:11:11 2016 -0500 @@ -15,7 +15,7 @@ plugindir=${libdir}/pidgin Name: Pidgin -Description: Pidgin is a GTK2-based instant messenger application. +Description: Pidgin is a GTK3-based instant messenger application. Version: @VERSION@ -Requires: gtk+-2.0 purple-3 +Requires: gtk+-3.0 webkitgtk-3.0 purple-3 Cflags: -I${abs_top_srcdir}