gnome-control-center-signon-0.1.8+16.04.20160201/0000755000015600001650000000000012653651300021411 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/doc/0000755000015600001650000000000012653651300022156 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/doc/account-plugin/0000755000015600001650000000000012653651300025106 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/doc/account-plugin/account-plugin-docs.xml0000644000015600001650000000322712653650644031524 0ustar pbuserpbgroup00000000000000 ]> account-plugin Reference Manual for account-plugin &version;. The latest version of this documentation can be found on-line at account-plugin account-plugin provides a plugin interface for authentication providers and applications. Object Hierarchy API Index Index of deprecated symbols gnome-control-center-signon-0.1.8+16.04.20160201/doc/account-plugin/Makefile.am0000644000015600001650000000633112653650644027157 0ustar pbuserpbgroup00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=account-plugin # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=$(top_srcdir)/libaccount-plugin # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS=--source-dir=$(top_srcdir)/libaccount-plugin --rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--source-dir=$(top_srcdir)/libaccount-plugin --sgml-mode --output-format=xml --name-space=ap # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Add the builddir to the HTML path so that version.xml is found MKHTML_OPTIONS=--path="$(abs_builddir)" # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB=$(top_srcdir)/libaccount-plugin/*.h CFILE_GLOB=$(top_srcdir)/libaccount-plugin/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = module.h # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES = # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. AM_CPPFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) AM_CFLAGS = $(LIBACCOUNT_PLUGIN_CFLAGS) GTKDOC_LIBS = $(top_builddir)/libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make if ENABLE_GTK_DOC # Temporary disabled, for a gtk-doc bug. See also # http://cgit.freedesktop.org/systemd/systemd/commit/?id=bff9cfcc5c065e7ff0a6ccaf5d0b844c7ebc8081 #TESTS_ENVIRONMENT = cd $(builddir) && #TESTS = $(GTKDOC_CHECK) endif sgml.stamp: $(DOC_MODULE)-sections.txt $(DOC_MAIN_SGML_FILE): sgml.stamp gnome-control-center-signon-0.1.8+16.04.20160201/doc/account-plugin/version.xml.in0000644000015600001650000000002212653650644027726 0ustar pbuserpbgroup00000000000000@PACKAGE_VERSION@ gnome-control-center-signon-0.1.8+16.04.20160201/doc/account-plugin/account-plugin-sections.txt0000644000015600001650000000372012653650644032440 0ustar pbuserpbgroup00000000000000
ap-application-plugin ApApplicationPlugin ApApplicationPlugin ap_application_plugin_build_widget ap_application_plugin_get_account ap_application_plugin_get_application ap_application_plugin_get_error ap_application_plugin_set_error ap_application_plugin_emit_finished ApApplicationPluginClass ApApplicationPluginPrivate AP_APPLICATION_PLUGIN AP_IS_APPLICATION_PLUGIN AP_TYPE_APPLICATION_PLUGIN ap_application_plugin_get_type AP_APPLICATION_PLUGIN_CLASS AP_IS_APPLICATION_PLUGIN_CLASS AP_APPLICATION_PLUGIN_GET_CLASS
ap-client ApClient ap_client_load_plugin ap_client_load_application_plugin
ap-oauth-plugin ApOAuthPlugin ApOAuthPlugin ApOAuthMechanism ap_oauth_plugin_set_mechanism ap_oauth_plugin_set_oauth_parameters ap_oauth_plugin_set_account_oauth_parameters ApOAuthPluginClass ApOAuthPluginPrivate AP_OAUTH_PLUGIN AP_IS_OAUTH_PLUGIN AP_TYPE_OAUTH_PLUGIN ap_oauth_plugin_get_type AP_OAUTH_PLUGIN_CLASS AP_IS_OAUTH_PLUGIN_CLASS AP_OAUTH_PLUGIN_GET_CLASS
ap-plugin ApPlugin ApPlugin AP_PLUGIN_CREDENTIALS_ID_FIELD ap_plugin_build_widget ap_plugin_act_headless ap_plugin_delete_account ap_plugin_delete_account_finish ap_plugin_emit_finished ap_plugin_get_account ap_plugin_get_provider ap_plugin_get_need_authentication ap_plugin_set_need_authentication ap_plugin_set_credentials ap_plugin_get_username ap_plugin_get_password ap_plugin_get_cookies ap_plugin_set_cookies ap_plugin_get_ignore_cookies ap_plugin_set_ignore_cookies ap_plugin_get_user_cancelled ap_plugin_set_user_cancelled ap_plugin_get_error ap_plugin_set_error ApPluginClass ApPluginPrivate AP_PLUGIN AP_IS_PLUGIN AP_TYPE_PLUGIN ap_plugin_get_type AP_PLUGIN_CLASS AP_IS_PLUGIN_CLASS AP_PLUGIN_GET_CLASS
gnome-control-center-signon-0.1.8+16.04.20160201/autogen.sh0000755000015600001650000000075012653650644023426 0ustar pbuserpbgroup00000000000000#!/bin/sh # Run this to generate all the initial makefiles, etc. srcdir=`dirname $0` test -z "$srcdir" && srcdir=. PKG_NAME=credentials-control-center (test -f $srcdir/src/cc-credentials-panel.c) || { echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" echo " top-level $PKG_NAME directory" exit 1 } which gnome-autogen.sh || { echo "You need to install gnome-common" exit 1 } ACLOCAL_FLAGS="$ACLOCAL_FLAGS" USE_GNOME2_MACROS=1 . gnome-autogen.sh gnome-control-center-signon-0.1.8+16.04.20160201/tests/0000755000015600001650000000000012653651300022553 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-account-applications-model.vala0000644000015600001650000000310012653650644031617 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); Test.add_func ("/credentials/accountapplicationsmodel/create", accountapplicationsmodel_create); Test.add_func ("/credentials/accountapplicationsmodel/add_account", accountapplicationsmodel_add_account); Test.run (); return Posix.EXIT_SUCCESS; } void accountapplicationsmodel_create () { var accountapplications_model = new Cc.Credentials.AccountApplicationsModel (); } void accountapplicationsmodel_add_account () { var accountapplications_model = new Cc.Credentials.AccountApplicationsModel (); var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); try { account.store_blocking (); } catch (Error err) { error ("Failed to store new account: %s", err.message); } accountapplications_model.account = account; } gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-account-plugin.vala0000644000015600001650000002010312653650644027333 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Alberto Mardegan */ extern GLib.Variant prepare_session_data_test (Ap.OAuthPlugin self); public class TestPlugin : Ap.Plugin { public Gtk.Widget widget_to_build; public TestPlugin(Ag.Account account) { Object(account: account); } public override unowned Gtk.Widget build_widget () { return widget_to_build; } } public class TestOAuthPlugin : Ap.OAuthPlugin { public TestOAuthPlugin(Ag.Account account) { Object(account: account); } construct { var account_oauth_params = new HashTable (str_hash, null); account_oauth_params.insert ("long", "short"); account_oauth_params.insert ("wide", "narrow"); set_account_oauth_parameters (account_oauth_params); var oauth_params = new HashTable (str_hash, null); oauth_params.insert ("long", "not short"); oauth_params.insert ("wide", "not narrow"); set_oauth_parameters (oauth_params); } } public class TestApplicationPlugin : Ap.ApplicationPlugin { public Gtk.Widget widget_to_build; public TestApplicationPlugin(Ag.Application application, Ag.Account account) { Object(account: account, application: application); } public override unowned Gtk.Widget build_widget () { return widget_to_build; } } int main (string[] args) { Gtk.test_init (ref args); Test.add_func ("/libaccount-plugin/client/load_plugin/null", client_load_plugin_null); Test.add_func ("/libaccount-plugin/client/load_application_plugin/null", client_load_application_plugin_null); Test.add_func ("/libaccount-plugin/plugin/create", accountplugin_create); Test.add_func ("/libaccount-plugin/plugin/create-headless", accountplugin_create_headless); Test.add_func ("/libaccount-plugin/application-plugin/create", applicationplugin_create); Test.add_func ("/libaccount-plugin/oauth-plugin/params", oauthplugin_params); Test.run (); return Posix.EXIT_SUCCESS; } void client_load_plugin_null () { Test.log_set_fatal_handler (log_is_fatal); var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); var plugin = Ap.client_load_plugin (account); assert (plugin == null); } void client_load_application_plugin_null () { Test.log_set_fatal_handler (log_is_fatal); var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); var application = manager.get_application ("Gallery"); var plugin = Ap.client_load_application_plugin (application, account); assert (plugin == null); } void accountplugin_create () { var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); var plugin = new TestPlugin (account); assert (plugin.account == account); assert (plugin.get_account () == account); plugin.need_authentication = true; assert (plugin.need_authentication == true); assert (plugin.get_need_authentication () == true); /* Make sure that the virtual method is called */ plugin.widget_to_build = new Gtk.Label ("Hello world!"); assert (plugin.build_widget () == plugin.widget_to_build); } void accountplugin_create_headless () { /* Making warnings non-fatal is needed because at-spi2 emits a g_warning * ("AT-SPI: Could not obtain desktop path or name") which we couldn't find * a way to remove. Any hint on how to avoid that warning (or even on * avoiding starting up at-spi2 in the first place) is very welcome. */ Test.log_set_fatal_handler (log_is_fatal); var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); var plugin = new TestOAuthPlugin (account); assert (plugin.account == account); assert (plugin.get_account () == account); string test_username = "Long John Silver"; plugin.need_authentication = false; plugin.set_credentials (test_username, "irrelevant password"); var main_loop = new GLib.MainLoop (null, false); plugin.finished.connect (() => { main_loop.quit (); }); GLib.Idle.add (() => { plugin.act_headless (); return false; }); main_loop.run (); /* check that the account was stored */ assert (account.id != 0); assert (account.get_display_name () == test_username); /* The accounts created in headless mode must be disabled */ account.select_service (null); assert (!account.get_enabled ()); var service = manager.get_service ("MyService"); var account_service = new Ag.AccountService (account, service); var auth_data = account_service.get_auth_data (); assert (auth_data.get_method () == "oauth2"); assert (auth_data.get_mechanism () == "user_agent"); var parameters = auth_data.get_parameters (); assert (parameters["long"].get_string () == "short"); assert (parameters["wide"].get_string () == "narrow"); /* delete the account */ GLib.Idle.add (() => { plugin.delete_account.begin ((obj, res) => { try { plugin.delete_account.end (res); } catch (Error error) { critical ("Error deleting account: %s", error.message); assert_not_reached (); } main_loop.quit (); }); return false; }); main_loop.run (); } void applicationplugin_create () { var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); var application = manager.get_application ("Gallery"); assert (application != null); var plugin = new TestApplicationPlugin (application, account); assert (plugin.account == account); assert (plugin.get_account () == account); assert (plugin.application == application); assert (plugin.get_application () == application); /* Make sure that the virtual method is called */ plugin.widget_to_build = new Gtk.Label ("Hello world!"); assert (plugin.build_widget () == plugin.widget_to_build); } void oauthplugin_params () { var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); var plugin = new TestOAuthPlugin (account); plugin.need_authentication = false; var cookies = new HashTable (str_hash, str_equal); cookies.insert("first cookie", "KEY=VALUE"); cookies.insert("second", "SILLY=TRUE"); plugin.set_cookies (cookies); var session_data = prepare_session_data_test (plugin); assert (session_data != null); assert (session_data.n_children() == 4); assert (session_data.lookup_value ("long", null).get_string () == "not short"); assert (session_data.lookup_value ("wide", null).get_string () == "not narrow"); assert (session_data.lookup_value ("medium", null).get_string () == "like this"); var cookies_variant = session_data.lookup_value ("Cookies", null); assert (cookies_variant != null); assert (cookies_variant.n_children() == 2); assert (cookies_variant.lookup_value ("second", null).get_string() == "SILLY=TRUE"); } bool log_is_fatal (string? log_domain, LogLevelFlags log_level, string message) { return (log_level & (LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_ERROR)) != 0; } gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-account-plugin.sh0000755000015600001650000000122312653650644027027 0ustar pbuserpbgroup00000000000000#!/bin/sh # If dbus-test-runner doesn't exist, don't run the test: it would create # unwanted records in the signon DB. command -v dbus-test-runner > /dev/null || { echo "dbus-test-runner is not installed; skipping the test." exit 0 } export SSO_LOGGING_LEVEL=2 export SSO_STORAGE_PATH="/tmp" export SSO_DAEMON_TIMEOUT=5 export SSO_IDENTITY_TIMEOUT=5 export SSO_AUTHSESSION_TIMEOUT=5 # we don't want any extensions to be loaded export SSO_EXTENSIONS_DIR="/non/existing/path" xvfb-run --auto-servernum -- dbus-test-runner -m 360 \ -t signond --ignore-return \ -t ./tests/test-account-plugin \ -f com.google.code.AccountsSSO.SingleSignOn gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-preferences.vala0000644000015600001650000000255612653650644026720 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); /* Skip until a mock webcredentials indicator is developed. Test.add_func ("/credentials/preferences/create", preferences_create); */ Test.run (); return Posix.EXIT_SUCCESS; } void preferences_create () { /* Prevent warnings from making the test fail. */ Test.log_set_fatal_handler (log_is_fatal); var preferences = Gtk.test_create_widget (typeof (Cc.Credentials.Preferences)); } bool log_is_fatal (string? log_domain, LogLevelFlags log_level, string message) { return (log_level & (LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_ERROR)) != 0; } gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-accounts-page.vala0000644000015600001650000000255312653650644027145 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); /* Skip until a mock webcredentials indicator is developed. Test.add_func ("/credentials/accountspage/create", accountspage_create); */ Test.run (); return Posix.EXIT_SUCCESS; } void accountspage_create () { /* Prevent warnings from making the test fail. */ Test.log_set_fatal_handler (log_is_fatal); var page = Gtk.test_create_widget (typeof (Cc.Credentials.AccountsPage)); } bool log_is_fatal (string? log_domain, LogLevelFlags log_level, string message) { return (log_level & (LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_ERROR)) != 0; } gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-providers-model.vala0000644000015600001650000000215012653650644027520 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); Test.add_func ("/credentials/providersmodel/create", providersmodel_create); Test.run (); return Posix.EXIT_SUCCESS; } void providersmodel_create () { var treeview = Gtk.test_create_widget (typeof (Gtk.TreeView)) as Gtk.TreeView; var providers_model = new Cc.Credentials.ProvidersModel (); treeview.model = providers_model; } gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-authorization-page.vala0000644000015600001650000000212112653650644030215 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); /* Skip until a mock webcredentials indicator is developed. Test.add_func ("/credentials/authorizationpage/create", authorizationpage_create); */ Test.run (); return Posix.EXIT_SUCCESS; } void authorizationpage_create () { var page = Gtk.test_create_widget (typeof (Cc.Credentials.AuthorizationPage)); } gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-accounts-model.vala0000644000015600001650000000632112653650644027326 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); /* Skip until a mock webcredentials indicator is developed. Test.add_func ("/credentials/accountsmodel/create", accountsmodel_create); Test.add_func ("/credentials/accountsmodel/add_account", accountsmodel_add_account); Test.add_func ("/credentials/accountsmodel/toggle_account_enabled", accountsmodel_toggle_account_enabled); Test.add_func ("/credentials/accountsmodel/delete_account", accountsmodel_delete_account); */ Test.run (); return Posix.EXIT_SUCCESS; } void accountsmodel_create () { var treeview = Gtk.test_create_widget (typeof (Gtk.TreeView)) as Gtk.TreeView; var accounts_model = new Cc.Credentials.AccountsModel (); treeview.model = accounts_model; } void accountsmodel_add_account () { var treeview = Gtk.test_create_widget (typeof (Gtk.TreeView)) as Gtk.TreeView; var accounts_model = new Cc.Credentials.AccountsModel (); treeview.model = accounts_model; // Add an account. var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); try { account.store_blocking (); } catch (Error error) { assert_not_reached (); } } void accountsmodel_toggle_account_enabled () { var treeview = Gtk.test_create_widget (typeof (Gtk.TreeView)) as Gtk.TreeView; var accounts_model = new Cc.Credentials.AccountsModel (); treeview.model = accounts_model; // Update an existing account (by adding one first). var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); try { account.store_blocking (); } catch (Error error) { assert_not_reached (); } account.set_enabled (!account.get_enabled ()); try { account.store_blocking (); } catch (Error error) { assert_not_reached (); } } void accountsmodel_delete_account () { var treeview = Gtk.test_create_widget (typeof (Gtk.TreeView)) as Gtk.TreeView; var accounts_model = new Cc.Credentials.AccountsModel (); treeview.model = accounts_model; // Delete an existing account (by adding one first). var manager = new Ag.Manager (); var account = manager.create_account ("MyProvider"); try { account.store_blocking (); } catch (Error error) { assert_not_reached (); } account.delete (); try { account.store_blocking (); } catch (Error error) { assert_not_reached (); } } gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/0000755000015600001650000000000012653651300023464 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/MyProvider.provider0000644000015600001650000000071212653650644027352 0ustar pbuserpbgroup00000000000000 My Provider general_myprovider gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/Mailer.application0000644000015600001650000000050412653650644027133 0ustar pbuserpbgroup00000000000000 Mailer application mailer-catalog Mailer can retrieve your e-mails gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/MyService.service0000644000015600001650000000443212653650644026771 0ustar pbuserpbgroup00000000000000 e-mail My Service general_myservice MyProvider talkdemo.google.com googledemo@gmail.com demo GTalk demo chat-p2p, voice-p2p, video-p2p, chat-room, chat-room-list, avatars, alias, roster X-JABBER pres_bd_gtalk_available general_presence_online available pres_bd_gtalk_busy general_presence_busy away addr_bd_cont_starter_im_service_chat general_sms X-JABBER org.freedesktop.Telepathy.Channel.Type.Text addr_bd_cont_starter_im_service_call general_call X-JABBER org.freedesktop.Telepathy.Channel.Type.StreamedMedia gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/Gallery.application0000644000015600001650000000063212653650644027323 0ustar pbuserpbgroup00000000000000 Image gallery Publish images on OtherService Share your images with your friends gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/OtherService.service0000644000015600001650000000422612653650644027466 0ustar pbuserpbgroup00000000000000 sharing Other Service general_otherservice MyProvider talkdemo.google.com googledemo@gmail.com demo GTalk demo chat-p2p, voice-p2p, video-p2p, chat-room, chat-room-list, avatars, alias, roster X-JABBER pres_bd_gtalk_available general_presence_online available pres_bd_gtalk_busy general_presence_busy away addr_bd_cont_starter_im_service_chat general_sms X-JABBER org.freedesktop.Telepathy.Channel.Type.Text addr_bd_cont_starter_im_service_call general_call X-JABBER org.freedesktop.Telepathy.Channel.Type.StreamedMedia gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/e-mail.service-type0000644000015600001650000000027412653650644027206 0ustar pbuserpbgroup00000000000000 translation_file Electronic mail email_icon gnome-control-center-signon-0.1.8+16.04.20160201/tests/data/MyService2.service0000644000015600001650000000061312653650644027050 0ustar pbuserpbgroup00000000000000 calendar My Service #2 general_myservice2 MyProvider gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-applications-model.vala0000644000015600001650000000217212653650644030175 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); Test.add_func ("/credentials/applicationsmodel/create", applicationsmodel_create); Test.run (); return Posix.EXIT_SUCCESS; } void applicationsmodel_create () { var treeview = Gtk.test_create_widget (typeof (Gtk.TreeView)) as Gtk.TreeView; var applications_model = new Cc.Credentials.ApplicationsModel (); treeview.model = applications_model; } gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-account-details-page.vala0000644000015600001650000000441412653650644030403 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); /* Skip until a mock webcredentials indicator is developed. Test.add_func ("/credentials/accountdetailspage/create", accountdetailspage_create); Test.add_func ("/credentials/accountdetailspage/set_account", accountdetailspage_set_get_account); */ Test.run (); return Posix.EXIT_SUCCESS; } void accountdetailspage_create () { var accounts_model = new Cc.Credentials.AccountsModel (); // Instantiate by calling g_object_new () on the type. var page = Gtk.test_create_widget (typeof (Cc.Credentials.AccountDetailsPage)); // Instantiate by calling cc_credentials_accounts_details_page_new (). var other_page = new Cc.Credentials.AccountDetailsPage (accounts_model); } void accountdetailspage_set_get_account () { var accounts_model = new Cc.Credentials.AccountsModel (); var page = new Cc.Credentials.AccountDetailsPage (accounts_model); var manager = accounts_model.manager; // Make sure that at least one account exists. var account = manager.create_account ("MyProvider"); try { account.store_blocking (); } catch (Error error) { assert_not_reached (); } /* prevent warnings from making the test fail */ Test.log_set_fatal_handler (log_is_fatal); page.account = account; assert (page.account == account); } bool log_is_fatal (string? log_domain, LogLevelFlags log_levels, string message) { return (log_levels & (LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_ERROR)) != 0; } gnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/0000755000015600001650000000000012653651300024573 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/__init__.py0000644000015600001650000000000012653650644026704 0ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/unity_control_center_signon/0000755000015600001650000000000012653651300032420 5ustar pbuserpbgroup00000000000000././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/unity_control_center_signon/__init__.pygnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/unity_control_center_signon/__init_0000644000015600001650000000000012653650644033743 0ustar pbuserpbgroup00000000000000././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/unity_control_center_signon/test_control_center_signon.pygnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/unity_control_center_signon/test_co0000644000015600001650000001702612653650644034023 0ustar pbuserpbgroup00000000000000#! /usr/bin/env python # -*- coding: utf-8 -*- # # Copyright (C) 2013 Canonical Ltd. # Contact: Alberto Mardegan # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. from autopilot.testcase import AutopilotTestCase from autopilot.matchers import Eventually from testtools.matchers import Contains, Equals, NotEquals, GreaterThan from autopilot.introspection.dbus import StateNotFoundError from time import sleep import BaseHTTPServer, SimpleHTTPServer, SocketServer, ssl, cgi import threading class Handler(BaseHTTPServer.BaseHTTPRequestHandler): def do_HEAD(self): self.send_response(200) self.send_header("Content-type", "text/html") s.end_headers() def do_GET(self): self.send_response(200) self.send_header("Content-type", "text/html") self.send_header('Content-Encoding', 'utf-8') self.end_headers() self.wfile.write(""" Login here

Login form

Username:
Password:

""" % { 'port': self.server.server_port }) self.server.show_login_event.set() def do_POST(self): form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], }) self.send_response(301) self.send_header("Location", "https://localhost:%(port)s/success.html#access_token=%(username)s%(password)s&expires_in=3600" % { 'port': self.server.server_port, 'username': form['username'].value, 'password': form['password'].value }) self.end_headers() self.server.login_done_event.set() class LocalServer: def __init__(self): self.PORT = 5120 #self.handler = SimpleHTTPServer.SimpleHTTPRequestHandler self.handler = Handler self.httpd = BaseHTTPServer.HTTPServer(("localhost", self.PORT), self.handler) self.httpd.show_login_event = threading.Event() self.httpd.login_done_event = threading.Event() self.httpd.socket = ssl.wrap_socket (self.httpd.socket, certfile='/etc/ssl/certs/uoa-test-server.pem', server_side=True) self.httpd_thread = threading.Thread(target=self.httpd.serve_forever) def run(self): self.httpd_thread.setDaemon(True) self.httpd_thread.start() class ControlCenterTests(AutopilotTestCase): def setUp(self): super(ControlCenterTests, self).setUp() self.app = self.launch_test_application('unity-control-center', 'credentials', capture_output=True) def test_title(self): """ Checks whether the Online Accounts window title is correct """ window = self.app.select_single('GtkApplicationWindow') self.assertThat(window, NotEquals(None)) self.assertThat(window.title, Eventually(Equals('Online Accounts'))) def test_available_providers(self): """ Checks whether all the expected providers are available """ add_account_btn = self.app.select_single('GtkTextCellAccessible', accessible_name=u'Add account…') self.assertThat(add_account_btn, NotEquals(None)) self.mouse.move_to_object(add_account_btn) self.mouse.click() required_providers = [ 'FakeOAuth', ] for provider in required_providers: provider_item = self.app.select_single('GtkTextCellAccessible', accessible_name=provider) self.assertThat(add_account_btn, NotEquals(None)) def test_create_oauth2_account(self): """ Test the creation of an OAuth 2.0 account """ self.server = LocalServer() self.server.run() add_account_btn = self.app.select_single('GtkTextCellAccessible', accessible_name=u'Add account…') self.assertThat(add_account_btn, NotEquals(None)) self.mouse.move_to_object(add_account_btn) self.mouse.click() filter_box = self.app.select_single('GtkComboBoxAccessible', accessible_name='all') self.assertThat(filter_box, NotEquals(None)) self.mouse.move_to_object(filter_box) self.mouse.click() sleep(1) filter_item_test = None # We can't use select_single, because the menu items appear twice in # the hirarchy filter_item_tests = self.app.select_many('GtkMenuItemAccessible', accessible_name='IntegrationTests') self.assertThat(len(filter_item_tests), GreaterThan(0)) filter_item_test = filter_item_tests[0] self.assertThat(filter_item_test, NotEquals(None)) self.mouse.move_to_object(filter_item_test) self.mouse.click() provider_item = self.app.wait_select_single('GtkTextCellAccessible', accessible_name='FakeOAuth') self.assertThat(provider_item, NotEquals(None)) self.mouse.move_to_object(provider_item) self.mouse.click() # At this point, the signon-ui process should be spawned by D-Bus and # try to connect to our local webserver. # Here we wait until we know that the webserver has served the login page: self.server.httpd.show_login_event.wait(30) self.assertThat(self.server.httpd.show_login_event.is_set(), Equals(True)) self.server.httpd.show_login_event.clear() # Give some time to signon-ui to render the page sleep(2) # Move to the username field self.keyboard.press_and_release('Tab') self.keyboard.press_and_release('Tab') self.keyboard.press_and_release('Tab') self.keyboard.press_and_release('Tab') self.keyboard.type('john') self.keyboard.press_and_release('Tab') self.keyboard.type('loser') self.keyboard.press_and_release('Enter') # At this point signon-ui should make a post request with the login # data; let's wait for it: self.server.httpd.login_done_event.wait(30) self.assertThat(self.server.httpd.login_done_event.is_set(), Equals(True)) self.server.httpd.login_done_event.clear() # The account should be created shortly account_item = self.app.wait_select_single('GtkTextCellAccessible', accessible_name='FakeOAuth\njohn') self.assertThat(account_item, NotEquals(None)) # Delete it self.mouse.move_to_object(account_item) self.mouse.click() remove_button = self.app.wait_select_single('GtkButtonAccessible', accessible_name='Remove Account') self.assertThat(remove_button, NotEquals(None)) self.mouse.move_to_object(remove_button) self.mouse.click() sleep(1) self.keyboard.press_and_release('Tab') self.keyboard.press_and_release('Enter') # Check that the account has been deleted sleep(1) try: account_item = self.app.select_single('GtkTextCellAccessible', accessible_name='FakeOAuth\njohn') except StateNotFoundError: account_item = None self.assertThat(account_item, Equals(None)) gnome-control-center-signon-0.1.8+16.04.20160201/tests/autopilot/setup.py0000644000015600001650000000073312653650644026322 0ustar pbuserpbgroup00000000000000#!/usr/bin/env python # from distutils.core import setup from DistUtilsExtra.command import build_extra setup(name="unity-control-center-signon-autopilot", version="0.1", author="Alberto Mardegan", author_email="alberto.mardegan@canonical.com", url="http://launchpad.net/uoa-integration-tests", license="GNU General Public License v3 (GPLv3)", packages=["unity_control_center_signon"], cmdclass={"build": build_extra.build_extra,}) gnome-control-center-signon-0.1.8+16.04.20160201/tests/test-providers-page.vala0000644000015600001650000000227312653650644027342 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ int main (string[] args) { Gtk.test_init (ref args); Test.add_func ("/credentials/providerspage/create", providerspage_create); Test.run (); return Posix.EXIT_SUCCESS; } void providerspage_create () { // Instantiate by calling g_object_new () on the type. var page = Gtk.test_create_widget (typeof (Cc.Credentials.ProvidersPage)); // Instantiate by calling cc_credentials_accounts_details_page_new (). var other_page = new Cc.Credentials.ProvidersPage (); } gnome-control-center-signon-0.1.8+16.04.20160201/src/0000755000015600001650000000000012653651300022200 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-login-capture.vala0000644000015600001650000000426612653650644030516 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Alberto Mardegan */ /** * Used to receive credentials captured from other applications (browser). */ [DBus (name = "com.canonical.webcredentials.capture")] public class Cc.Credentials.LoginCapture : Object { public LoginCapture() { Bus.own_name (BusType.SESSION, "com.canonical.webcredentials.capture", BusNameOwnerFlags.NONE, on_bus_acquired, () => {}, () => warning ("Could not acquire name.")); } [DBus (visible = false)] public signal void new_account_request (string provider_name, string username, string? password, HashTable cookies); public void login_captured (string provider_name, string username, string? password, HashTable cookies) { debug ("Login captured: %s, %s", provider_name, username); new_account_request (provider_name, username, password, cookies); } private void on_bus_acquired (DBusConnection conn) { try { conn.register_object ("/com/canonical/webcredentials/capture", this); } catch (IOError e) { warning ("Could not register service."); } } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-account-details-page.vala0000644000015600001650000006461012653650644031735 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ /** * Button widget, additionally storing an AccountApplicationRow. */ private class Cc.Credentials.AccountApplicationButton : Gtk.Button { /** * An AccountApplicationRow, for showing the configuration widget from * on_options_button_clicked(). * * This property is necessary because Vala generates incorrect C code if * using g_object_set_data() and g_object_get_data() with a boxed type. */ public AccountApplicationRow application_row { get; construct; } public AccountApplicationButton (string label, AccountApplicationRow row) { Object (label: label, application_row: row); } } /** * Switch widget, additionally storing an AccountApplicationRow. */ private class Cc.Credentials.AccountApplicationSwitch : Gtk.Switch { public Ag.Account account { get; construct; } public Ag.Service service { get; construct; } bool store_in_progress; public AccountApplicationSwitch (Ag.Account acc, Ag.Service serv) { Object (account: acc, service: serv); } construct { store_in_progress = false; // Fetch current state from service. account.select_service (service); active = account.get_enabled (); account.select_service (null); account.set_data ("switch", this); account.enabled.connect (on_app_account_enabled); set_tooltip_text (_("Control whether this application integrates with Online Accounts")); notify["active"].connect (on_app_switch_activated); } /** * Handle the account being enabled or disabled and update the switch state * accordingly. */ private void on_app_account_enabled (Ag.Account account, string service, bool enabled) { // If the global account is toggled, toggle the switch sensitivity. if (service == "global" || service == null) { sensitive = enabled; return; } if (this.service.get_name () == service && active != enabled) { active = enabled; } } /** * Handle the per-application switch being activated. */ private void on_app_switch_activated () { // Toggle the enabled state. account.select_service (service); account.set_enabled (active); account.select_service (null); try { account.store_blocking (); } catch (Ag.AccountsError err) { if (err is Ag.AccountsError.DELETED) { debug ("Enabled state changed during deletion of account ID: %u", account.id); } else if (err is Ag.AccountsError.STORE_IN_PROGRESS) { debug ("Enabled state changed while store in progress of account ID: %u", account.id); } else { critical ("Error changing enabled state of account: %s\nMessage: %s", account.get_display_name (), err.message); } } } } /** * Web credentials account details widget. Used inside a notebook page to list * the applications that use an account, provide a switch to enable or disable * the account and to provide a button for removing the account. */ public class Cc.Credentials.AccountDetailsPage : Gtk.Grid { private AccountsModel accounts_store; private Ap.Plugin plugin; private Gtk.Frame frame; private Gtk.Label frame_label; private Gtk.Notebook action_notebook; private Gtk.Switch enabled_switch; private Gtk.Button grant_button; private Gtk.Label applications_grid_description; private Gtk.ScrolledWindow applications_scroll; private Gtk.Grid applications_grid; private Gtk.ButtonBox buttonbox; private Gtk.Button edit_options_button; private AccountApplicationsModel applications_model; private Ag.Account current_account; private bool edit_options_button_present = false; private bool needs_attention = false; private bool store_in_progress = false; /** * Pages for the action widget notebook. * * @param ENABLED_SWITCH the page containing the switch to enable or * disable the current account * @param ACCESS_BUTTON the page containing the button to trigger * reauthentication */ private enum ActionPage { ENABLED_SWITCH = 0, ACCESS_BUTTON = 1 } /** * Signal the preferences widget to switch to the authentication page. */ public signal void reauthenticate_account_request (Ag.Account account); /** * Signal the preferences widget to switch to the options page. */ public signal void account_options_request (AccountApplicationRow application_row); /** * Signal the preferences widget to switch to the options page and show the * edit options widget. */ public signal void account_edit_options_request (Ap.Plugin plugin); /** * Index of the selected account in the model. */ public Gtk.TreeIter account_iter { set { Ag.AccountId account_id; bool iter_needs_attention; accounts_store.get (value, AccountsModel.ModelColumns.ACCOUNT_ID, out account_id, AccountsModel.ModelColumns.NEEDS_ATTENTION, out iter_needs_attention, -1); account = accounts_store.manager.get_account (account_id); if (iter_needs_attention != needs_attention) { needs_attention = iter_needs_attention; update_needs_attention_ui_state (); } } } /** * Keep the UI state consistent when the account is changed. */ public Ag.Account account { get { return current_account; } set { // Skip if the account has not changed. if (current_account != null && (current_account.id == value.id)) { return; } current_account = value; /* TODO: if needs_attention is true, we might want to hide the list * of the integrated applications. */ plugin = Ap.client_load_plugin (value); if (plugin == null) { warning ("No valid plugin found for provider %s", value.get_provider_name ()); } else { var widget = plugin.build_widget (); if (widget == null) { debug ("No configuration widget for provider %s", value.get_provider_name ()); if (edit_options_button_present) { buttonbox.remove (edit_options_button); edit_options_button_present = false; } } else { if (!edit_options_button_present) { buttonbox.add (edit_options_button); buttonbox.set_child_secondary (edit_options_button, true); edit_options_button_present = true; } /* The configuration widget is instantiated by Preferences * when the edit options button is clicked. */ widget.destroy (); } } enabled_switch.active = value.get_enabled (); value.enabled.connect (on_account_enabled); var manager = accounts_store.manager; var provider = manager.get_provider (value.get_provider_name ()); var provider_display_name = provider.get_display_name (); update_needs_attention_ui_state (); // Update the applications model. applications_model.account = value; // Special-case having no consumer applications installed. unowned List applications = applications_model.application_rows; if (applications == null) { applications_grid_description.label = _("There are currently no applications installed which integrate with your %s account.").printf (provider_display_name); } else { applications_grid_description.label = _("The following applications integrate with your %s account:").printf (provider_display_name); } populate_applications_grid (); } } public AccountDetailsPage (AccountsModel accounts_store) { Object (); this.accounts_store = accounts_store; accounts_store.row_changed.connect (on_accounts_store_row_changed); } construct { orientation = Gtk.Orientation.VERTICAL; expand = true; this.add (create_description_frame ()); this.add (create_applications_frame ()); show (); } /** * Create the frame to contain the other widgets for the account and show * it. * * @return a Gtk.Frame for presenting details of the account */ private Gtk.Widget create_applications_frame () { var eventbox = new Gtk.EventBox (); var frame = new Gtk.Frame (null); var context = frame.get_style_context (); context.add_class ("ubuntu-online-accounts"); frame.shadow_type = Gtk.ShadowType.ETCHED_IN; var grid = new Gtk.Grid (); grid.orientation = Gtk.Orientation.VERTICAL; grid.add (create_applications_grid_description ()); grid.add (create_applications_grid ()); grid.add (create_remove_account_box ()); frame.add (grid); eventbox.add (frame); // Override theme colors according to the UI specification. Gdk.RGBA color; context = eventbox.get_style_context (); if (context.lookup_color ("base_color", out color)) { eventbox.override_background_color (Gtk.StateFlags.NORMAL, color); } else { warning ("Error looking up theme color"); } return eventbox; } /** * Create the frame for the account details header and show it. * * @return a Gtk.Frame for presenting details of the account */ private Gtk.Widget create_description_frame () { frame = new Gtk.Frame (null); action_notebook = new Gtk.Notebook (); enabled_switch = new Gtk.Switch (); frame_label = new Gtk.Label (null); var grid = new Gtk.Grid (); grid.margin = 6; action_notebook.show_tabs = false; action_notebook.show_border = false; action_notebook.halign = Gtk.Align.END; action_notebook.valign = Gtk.Align.FILL; frame_label.hexpand = true; frame_label.use_markup = true; frame_label.wrap = true; frame_label.valign = Gtk.Align.CENTER; frame_label.xalign = 0.0f; grid.add (frame_label); enabled_switch.valign = Gtk.Align.CENTER; action_notebook.append_page (enabled_switch, null); grant_button = new Gtk.Button.with_label (_("Grant access")); grant_button.valign = Gtk.Align.CENTER; action_notebook.append_page (grant_button, null); grid.add (action_notebook); enabled_switch.notify["active"].connect (on_enabled_switch_activated); grant_button.clicked.connect (on_grant_button_clicked); frame.add (grid); frame.set_size_request (-1, 48); frame.show_all (); return frame; } /** * Create a description to place above the applications grid. * * @return a Gtk.Label for a description of the applications grid */ private Gtk.Widget create_applications_grid_description () { applications_grid_description = new Gtk.Label (null); applications_grid_description.margin = 6; applications_grid_description.xalign = 0.0f; applications_grid_description.set_line_wrap (true); applications_grid_description.set_size_request (414, -1); applications_grid_description.show (); return applications_grid_description; } /** * Create the grid with a list of applications using the current account. * * @return a Gtk.Grid containing a list of applications */ private Gtk.Widget create_applications_grid () { applications_model = new AccountApplicationsModel (); applications_scroll = new Gtk.ScrolledWindow (null, null); var context = applications_scroll.get_style_context (); context.add_class ("ubuntu-online-accounts"); // Instantiates applications_grid. populate_applications_grid (); applications_scroll.window_placement_set = true; // Override theme colors according to the UI specification. Gdk.RGBA color; var viewport = applications_scroll.get_child (); context = viewport.get_style_context (); if (context.lookup_color ("base_color", out color)) { viewport.override_background_color (Gtk.StateFlags.NORMAL, color); } else { warning ("Error looking up theme color"); } return applications_scroll; } /** * Create a button box for the account editing buttons. * * @return a Gtk.ButtonBox for the remove or edit account buttons */ private Gtk.Widget create_remove_account_box () { buttonbox = new Gtk.ButtonBox (Gtk.Orientation.HORIZONTAL); buttonbox.set_layout (Gtk.ButtonBoxStyle.END); buttonbox.margin = 6; var remove_button = new Gtk.Button.with_label (_("Remove Account")); edit_options_button = new Gtk.Button.with_label (_("Edit Options")); remove_button.clicked.connect (on_remove_account_clicked); edit_options_button.clicked.connect (on_edit_options_button_clicked); buttonbox.add (remove_button); buttonbox.show_all (); edit_options_button.show (); return buttonbox; } /** * Populate the grid of applications from the model. Instantiates * applications_grid. */ private void populate_applications_grid () { if (applications_grid != null) { applications_grid.destroy (); } applications_grid = new Gtk.Grid (); applications_grid.border_width = 6; applications_grid.column_spacing = 12; applications_grid.row_spacing = 12; applications_grid.expand = true; unowned List applications = applications_model.application_rows; applications.foreach (add_application); applications_scroll.add_with_viewport (applications_grid); applications_scroll.show_all (); } /** * Add an individual application from the model to the applications grid. * * @param application the description of the application */ private void add_application (AccountApplicationRow? application) { applications_grid.insert_row (0); var image = new Gtk.Image.from_gicon (application.icon, Gtk.IconSize.DND); image.margin_left = 4; applications_grid.attach (image, 0, 0, 1, 1); var label = new Gtk.Label (application.description); label.hexpand = true; label.use_markup = true; label.xalign = 0.0f; applications_grid.attach_next_to (label, image, Gtk.PositionType.RIGHT, 1, 1); var service = accounts_store.manager.get_service (application.service_name); var app_switch = new AccountApplicationSwitch (account, service); if (application.plugin_widget != null) { var button = new AccountApplicationButton (_("Options"), application); applications_grid.attach_next_to (button, label, Gtk.PositionType.RIGHT, 1, 1); applications_grid.attach_next_to (app_switch, button, Gtk.PositionType.RIGHT, 1, 1); button.clicked.connect (on_options_button_clicked); } else { applications_grid.attach (app_switch, 3, 0, 1, 1); } } /** * Update the state of the action notebook and frame label when the * needs-attention state changes. */ private void update_needs_attention_ui_state () { var manager = accounts_store.manager; var provider = manager.get_provider (current_account.get_provider_name ()); var provider_display_name = provider.get_display_name (); if (needs_attention) { frame_label.label = _("Please authorize Ubuntu to access your %s account:").printf (provider_display_name); action_notebook.page = ActionPage.ACCESS_BUTTON; } else { frame_label.label = "" + provider_display_name + "\n" + "" + current_account.get_display_name () + ""; action_notebook.page = ActionPage.ENABLED_SWITCH; } } /** * Handle the remove account button being clicked. The removal is * asynchronous, and on_remove_account_finished() is called when the * operation is complete. * * @see AccountDetailsPage.on_remove_account_finished */ private void on_remove_account_clicked () { // TODO: Pass parent window ID as first argument. var confirmation = new Gtk.MessageDialog (null, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, "%s", _("Are you sure that you wish to remove this Ubuntu Web Account?")); var manager = accounts_store.manager; var provider = manager.get_provider (current_account.get_provider_name ()); var provider_display_name = provider.get_display_name (); var secondary_text = _("The Web Account which manages the integration of %s with your applications will be removed.").printf (provider_display_name) + "\n\n" + _("Your online %s account is not affected.").printf (provider_display_name); confirmation.secondary_text = secondary_text; confirmation.add_buttons (Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, Gtk.Stock.REMOVE, Gtk.ResponseType.ACCEPT, null); var response = confirmation.run (); switch (response) { case Gtk.ResponseType.ACCEPT: // TODO: Set the UI to be insensitive during account removal? var plugin = Ap.client_load_plugin (current_account); if (plugin == null) { /* This can really happen, if the plugin has been * uninstalled; in this case, the user can still access the * account (to disable or delete it). */ warning ("No valid plugin found for provider %s", current_account.get_provider_name ()); // TODO: Delete the account in this case. break; } plugin.delete_account.begin ((obj, res) => { try { plugin.delete_account.end (res); } catch (Error error) { critical ("Error deleting account: %s", error.message); } on_remove_account_finished (current_account); }); break; case Gtk.ResponseType.CANCEL: case Gtk.ResponseType.DELETE_EVENT: break; default: assert_not_reached (); } confirmation.destroy (); } /** * Handle the completion of the asynchronous account removal operation. * * @param account the account that was removed */ private void on_remove_account_finished (Ag.Account account) { /* TODO: Set the UI to be sensitive again? Switch to the add account * view. */ } /** * Asynchronously store the current account. */ private void store_current_account () { if (store_in_progress) { debug ("Enabled state changed while store in progress of account ID: %u", account.id); return; } store_in_progress = true; current_account.store_async.begin (null, (obj, res) => { try { store_in_progress = false; current_account.store_async.end (res); } catch (Ag.AccountsError err) { if (err is Ag.AccountsError.DELETED) { debug ("Enabled state changed during deletion of account ID: %u", account.id); } else if (err is Ag.AccountsError.STORE_IN_PROGRESS) { debug ("Enabled state changed while store in progress of account ID: %u", account.id); } else { critical ("Error changing enabled state of account: %s\nMessage: %s", current_account.get_display_name (), err.message); } } }); } /** * Handle the account enabled switch being activated. Change the current * account to be the same state as the switch. */ private void on_enabled_switch_activated () { current_account.set_enabled (enabled_switch.active); store_current_account (); } /** * Handle the reauthentication button being clicked. */ private void on_grant_button_clicked () { reauthenticate_account_request (current_account); } /** * Handle the account being enabled or disabled from elsewhere, and update * the switch state accordingly. */ private void on_account_enabled (string? service, bool enabled) { // Ignore service-level changes. // FIXME: http://code.google.com/p/accounts-sso/issues/detail?id=157 if (service != "global" || service != null) { return; } if (enabled != enabled_switch.active) { enabled_switch.active = enabled; } } /** * Handle the options button for an application being clicked. * * @param button the AccountApplicationButton that emitted the clicked * signal. The account application plugin is a property on the button. */ private void on_options_button_clicked (Gtk.Button button) { var app_button = button as AccountApplicationButton; var application_row = app_button.application_row; if (application_row.plugin_widget != null) { account_options_request (application_row); } } /** * Handle the edit options button for an account being clicked. */ private void on_edit_options_button_clicked () { account_edit_options_request (plugin); } /** * Handle a row in the accounts model being changed. * * Check to see whether the current account was changed, and then check to * see if the needs-attention flag is set, and update the action notebook * state accordingly. * * @param model the Gtk.TreeModel * @param path the Gtk.TreePath of the changed row * @param iter the Gtk.TreeIter of the changed row */ private void on_accounts_store_row_changed (Gtk.TreeModel model, Gtk.TreePath path, Gtk.TreeIter iter) { Ag.AccountId account_id; bool changed_account_needs_attention; accounts_store.get (iter, AccountsModel.ModelColumns.ACCOUNT_ID, out account_id, AccountsModel.ModelColumns.NEEDS_ATTENTION, out changed_account_needs_attention, -1); if (current_account.id == account_id) { if (changed_account_needs_attention != needs_attention) { needs_attention = changed_account_needs_attention; update_needs_attention_ui_state (); } } } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-webcredentials-indicator.vala0000644000015600001650000000250512653650644030411 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Alberto Mardegan */ /** * Used to monitor the Failures property, so that accounts with login failures * can be marked as needing attention. */ [DBus (name = "com.canonical.indicators.webcredentials")] public interface Cc.WebcredentialsIndicator : Object { public abstract uint[] failures { owned get; } public abstract async void report_failure (uint account_id, HashTable notification) throws IOError; public abstract async void remove_failures (uint[] account_ids) throws IOError; public abstract async void clear_error_status () throws IOError; } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-panel.c0000644000015600001650000001631112653650644026335 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Alvaro Lopez Ortega * David King */ #include #include #include #include #include "config.h" extern void* cc_credentials_preferences_new (void); extern void* cc_credentials_preferences_new_with_account_details (guint account_id); extern void* cc_credentials_preferences_new_with_application (const gchar *application); GType cc_credentials_panel_get_type(void); #define CC_TYPE_CREDENTIALS_PANEL (cc_credentials_panel_get_type ()) #define CC_CREDENTIALS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_CREDENTIALS_PANEL, CcCredentialsPanel)) typedef struct _CcCredentialsPanel CcCredentialsPanel; typedef struct _CcCredentialsPanelClass CcCredentialsPanelClass; typedef struct _CcCredentialsPanelPrivate CcCredentialsPanelPrivate; typedef enum _StartupAction StartupAction; /** * StartupAction: * @CREDENTIALS_ACTION_DEFAULT: the default action, which shows the list of * accounts * @CREDENTAILS_ACTION_ACCOUNT_DETAILS: show the details of a specific account * * The action to perform when the panel is first displayed. */ enum _StartupAction { CREDENTIALS_ACTION_DEFAULT, CREDENTIALS_ACTION_ACCOUNT_DETAILS, CREDENTIALS_ACTION_APPLICATION }; struct _CcCredentialsPanel { CcPanel parent_instance; CcCredentialsPanelPrivate *priv; }; struct _CcCredentialsPanelClass { CcPanelClass parent_class; }; struct _CcCredentialsPanelPrivate { StartupAction startup_action; guint account_id; gchar *application_name; }; enum { PROP_0, PROP_ARGV }; G_DEFINE_DYNAMIC_TYPE (CcCredentialsPanel, cc_credentials_panel, CC_TYPE_PANEL) static void cc_credentials_panel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void cc_credentials_panel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { CcCredentialsPanel *self = CC_CREDENTIALS_PANEL (object); CcCredentialsPanelPrivate *priv = self->priv; switch (property_id) { case PROP_ARGV: { gchar **argv; priv->startup_action = CREDENTIALS_ACTION_DEFAULT; argv = g_value_get_boxed (value); if (argv && argv[0]) { static const gchar ACCOUNT_DETAILS[] = "account-details="; static const gchar APPLICATION[] = "application="; g_debug ("Startup argument given: %s", argv[0]); if (g_str_has_prefix (argv[0], ACCOUNT_DETAILS)) { priv->startup_action = CREDENTIALS_ACTION_ACCOUNT_DETAILS; /* Strip off the argument text. */ priv->account_id = atoi (argv[0] + sizeof (ACCOUNT_DETAILS) - 1); } else if (g_str_has_prefix (argv[0], APPLICATION)) { /* Providing an application changes the startup action, but the * effect is not visible until the account details view is * displayed. */ priv->startup_action = CREDENTIALS_ACTION_APPLICATION; /* Strip off the argument text. */ priv->application_name = g_strdup (argv[0] + sizeof (APPLICATION) - 1); } } } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void cc_credentials_panel_constructed (GObject *object) { GtkWidget *widget; CcCredentialsPanel *self; CcCredentialsPanelPrivate *priv; self = CC_CREDENTIALS_PANEL (object); priv = self->priv; switch (priv->startup_action) { case CREDENTIALS_ACTION_APPLICATION: widget = GTK_WIDGET (cc_credentials_preferences_new_with_application (priv->application_name)); break; case CREDENTIALS_ACTION_ACCOUNT_DETAILS: widget = GTK_WIDGET (cc_credentials_preferences_new_with_account_details (priv->account_id)); break; case CREDENTIALS_ACTION_DEFAULT: widget = GTK_WIDGET (cc_credentials_preferences_new ()); break; default: g_assert_not_reached (); } gtk_widget_show_all (widget); gtk_container_add (GTK_CONTAINER (self), widget); } static void cc_credentials_panel_finalize (GObject *object) { CcCredentialsPanelPrivate *priv = ((CcCredentialsPanel *) object)->priv; if (priv->application_name) { g_free (priv->application_name); } G_OBJECT_CLASS (cc_credentials_panel_parent_class)->finalize (object); } static void cc_credentials_panel_class_finalize (CcCredentialsPanelClass *klass) { } static const char * cc_credentials_panel_get_help_uri (CcPanel *panel) { return "help:ubuntu-help/accounts"; } static void cc_credentials_panel_class_init (CcCredentialsPanelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); CcPanelClass *panel_class = CC_PANEL_CLASS (klass); g_type_class_add_private (klass, sizeof (CcCredentialsPanelPrivate)); object_class->get_property = cc_credentials_panel_get_property; object_class->set_property = cc_credentials_panel_set_property; object_class->constructed = cc_credentials_panel_constructed; object_class->finalize = cc_credentials_panel_finalize; panel_class->get_help_uri = cc_credentials_panel_get_help_uri; g_object_class_override_property (object_class, PROP_ARGV, "argv"); } static void cc_credentials_panel_init (CcCredentialsPanel *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CC_TYPE_CREDENTIALS_PANEL, CcCredentialsPanelPrivate); } void g_io_module_load (GIOModule *module) { bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); /* Generated by G_DEFINE_DYNAMIC_TYPE. */ cc_credentials_panel_register_type (G_TYPE_MODULE (module)); g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT, CC_TYPE_CREDENTIALS_PANEL, "credentials", 0); } void g_io_module_unload (GIOModule *module) { } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-account-applications-model.vala0000644000015600001650000001344112653650644033156 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ namespace Cc.Credentials { /** * An individual application associated with an account. * * @param name the name, as supplied to Ag.Manager.get_provider () * @param icon the icon of the application * @param description the description of the application * @param plugin the plugin to configure account options, if any * @param plugin_widget the widget to show when configuring account options * @param service_name the service name, as supplied to * Ag.Manager.get_service () */ public struct AccountApplicationRow { public string name; public Icon icon; public string description; public Ap.ApplicationPlugin plugin; public Gtk.Widget plugin_widget; public string service_name; } } /** * Web credentials account applications model. Used to store details about * applications that can be integrated with an account, to be used in creating * widgets in a grid for describing the applications. */ public class Cc.Credentials.AccountApplicationsModel : Object { private Ag.Manager manager; private Ag.Account current_account; public List application_rows; /** * Update the model when the current account changes. */ public Ag.Account account { get { return current_account; } set { /* Skip clearing and repopulating the model if the account has not * changed. */ if (value == current_account) { return; } current_account = value; // Empty the model and repopulate it. application_rows = new List (); populate_model (); } } /** * Create a new model for storing applications that can be used with an * account. * * @param widget a Gtk.Widget to be used for looking up themed icons */ public AccountApplicationsModel () { manager = new Ag.Manager (); } /** * Populate the model with a list of applications that can use the services * of the current account. */ private void populate_model () { var services = current_account.list_services (); var service_application = new HashTable (str_hash, null); foreach (var service in services) { var applications = manager.list_applications_by_service (service); foreach (var application in applications) { service_application.insert (service.get_name (), application); } } service_application.foreach (add_application); // Reverse the list, as it was prepended to for efficiency. application_rows.reverse (); } /** * Add a single application to the model. * * @param service_name the name of the Ag.Service * @param application the Ag.Application to add to the model */ private void add_application (string service_name, Ag.Application? application) { var desktop_info = application.get_desktop_app_info (); if (desktop_info == null) { message ("No desktop app info found for application name: %s", application.get_name ()); return; } // Load a themed application icon. var app_icon = desktop_info.get_icon (); var service = manager.get_service (service_name); var app_description = dgettext (application.get_i18n_domain (), application.get_description ()); var app_service_usage = dgettext (application.get_i18n_domain (), application.get_service_usage (service)); var description_markup = app_description + "\n" + app_service_usage + ""; var app_plugin = Ap.client_load_application_plugin (application, current_account); Gtk.Widget app_plugin_widget = null; if (app_plugin == null) { /* There might not be a plugin (for OAuth accounts, or if there are * no settings). */ message ("No valid plugin found for application '%s' with account '%u'", application.get_name (), current_account.id); } else { app_plugin_widget = app_plugin.build_widget (); } var application_row = AccountApplicationRow () { name = application.get_name (), icon = app_icon, description = description_markup, plugin = app_plugin, plugin_widget = app_plugin_widget, service_name = service_name }; application_rows.prepend (application_row); } } gnome-control-center-signon-0.1.8+16.04.20160201/src/assertions.vapi0000644000015600001650000000133412653650644025266 0ustar pbuserpbgroup00000000000000[CCode (cprefix = "G", lower_case_cprefix = "g_", cheader_filename = "glib.h")] namespace Assertions { public enum OperatorType { [CCode (cname = "==")] EQUAL, [CCode (cname = "!=")] NOT_EQUAL, [CCode (cname = "<")] LESS_THAN, [CCode (cname = ">")] GREATER_THAN, [CCode (cname = "<=")] LESS_OR_EQUAL, [CCode (cname = ">=")] GREATER_OR_EQUAL } public void assert_cmpstr (string? s1, OperatorType op, string? s2); public void assert_cmpint (int n1, OperatorType op, int n2); public void assert_cmpuint (uint n1, OperatorType op, uint n2); public void assert_cmphex (uint n1, OperatorType op, uint n2); public void assert_cmpfloat (float n1, OperatorType op, float n2); } gnome-control-center-signon-0.1.8+16.04.20160201/src/signon.vapi0000644000015600001650000002125612653650644024376 0ustar pbuserpbgroup00000000000000/* signon.vapi generated by vapigen, do not modify. */ [CCode (cprefix = "Signon", gir_namespace = "Signon", gir_version = "1.0", lower_case_cprefix = "signon_")] namespace Signon { [CCode (cheader_filename = "libsignon-glib/signon-glib.h", type_id = "signon_auth_service_get_type ()")] public class AuthService : GLib.Object { [CCode (has_construct_function = false)] public AuthService (); public void query_mechanisms (string method, Signon.QueryMechanismCb cb); public void query_methods (Signon.QueryMethodsCb cb); } [CCode (cheader_filename = "libsignon-glib/signon-glib.h", type_id = "signon_auth_session_get_type ()")] public class AuthSession : GLib.Object { [CCode (has_construct_function = false)] public AuthSession (int id, string method_name) throws GLib.Error; public void cancel (); public unowned string get_method (); public void process (GLib.HashTable session_data, string mechanism, Signon.AuthSessionProcessCb cb); public void query_available_mechanisms (string wanted_mechanisms, Signon.AuthSessionQueryAvailableMechanismsCb cb); public signal void state_changed (int object, string p0); } [CCode (cheader_filename = "libsignon-glib/signon-glib.h", type_id = "signon_identity_get_type ()")] public class Identity : GLib.Object { [CCode (has_construct_function = false)] public Identity (); public void add_reference (string reference, Signon.IdentityReferenceAddedCb cb, void* user_data); public Signon.AuthSession create_session (string method) throws GLib.Error; [CCode (has_construct_function = false)] public Identity.from_db (uint32 id); public unowned GLib.Error get_last_error (); public void query_info (Signon.IdentityInfoCb cb); public void remove (Signon.IdentityRemovedCb cb, void* user_data); public void remove_reference (string reference, Signon.IdentityReferenceRemovedCb cb, void* user_data); public void store_credentials_with_args (string username, string secret, bool store_secret, GLib.HashTable methods, string caption, string realms, string access_control_list, Signon.IdentityType type, Signon.IdentityStoreCredentialsCb cb); public void store_credentials_with_info (Signon.IdentityInfo info, Signon.IdentityStoreCredentialsCb cb); public void verify_secret (string secret, Signon.IdentityVerifyCb cb); [NoAccessorMethod] public uint id { get; set; } [HasEmitter] public signal void signout (); } [CCode (cheader_filename = "libsignon-glib/signon-glib.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "signon_identity_info_get_type ()")] [Compact] public class IdentityInfo { [CCode (has_construct_function = false)] public IdentityInfo (); public Signon.IdentityInfo copy (); public void free (); [CCode (array_length = false, array_null_terminated = true)] public unowned string[] get_access_control_list (); public unowned string get_caption (); public int get_id (); public Signon.IdentityType get_identity_type (); public unowned GLib.HashTable get_methods (); [CCode (array_length = false, array_null_terminated = true)] public unowned string[] get_realms (); public bool get_storing_secret (); public unowned string get_username (); public void remove_method (string method); public void set_access_control_list (string access_control_list); public void set_caption (string caption); public void set_identity_type (Signon.IdentityType type); public void set_method (string method, string mechanisms); public void set_realms (string realms); public void set_secret (string secret, bool store_secret); public void set_username (string username); } [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cprefix = "SIGNON_IDENTITY_TYPE_")] [Flags] public enum IdentityType { OTHER, APP, WEB, NETWORK } [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cprefix = "SIGNON_POLICY_")] public enum SessionDataUiPolicy { DEFAULT, REQUEST_PASSWORD, NO_USER_INTERACTION, VALIDATION } [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cprefix = "SIGNON_ERROR_")] public errordomain Error { UNKNOWN, INTERNAL_SERVER, INTERNAL_COMMUNICATION, PERMISSION_DENIED, METHOD_NOT_KNOWN, SERVICE_NOT_AVAILABLE, INVALID_QUERY, METHOD_NOT_AVAILABLE, IDENTITY_NOT_FOUND, STORE_FAILED, REMOVE_FAILED, SIGNOUT_FAILED, IDENTITY_OPERATION_CANCELED, CREDENTIALS_NOT_AVAILABLE, REFERENCE_NOT_FOUND, MECHANISM_NOT_AVAILABLE, MISSING_DATA, INVALID_CREDENTIALS, NOT_AUTHORIZED, WRONG_STATE, OPERATION_NOT_SUPPORTED, NO_CONNECTION, NETWORK, SSL, RUNTIME, SESSION_CANCELED, TIMED_OUT, USER_INTERACTION, OPERATION_FAILED, ENCRYPTION_FAILED, TOS_NOT_ACCEPTED, FORGOT_PASSWORD, METHOD_OR_MECHANISM_NOT_ALLOWED, INCORRECT_DATE, USER_ERROR; public static GLib.Quark quark (); } [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 3.9)] public delegate void AuthSessionProcessCb (Signon.AuthSession self, owned GLib.HashTable session_data, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 3.9)] public delegate void AuthSessionQueryAvailableMechanismsCb (Signon.AuthSession self, [CCode (array_length = false, array_null_terminated = true)] owned string[] mechanisms, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 3.9)] public delegate void AuthSessionQueryAvailableMethodsCb (Signon.AuthSession self, [CCode (array_length = false, array_null_terminated = true)] owned string[] mechanisms, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 3.9)] public delegate void IdentityInfoCb (Signon.Identity self, Signon.IdentityInfo info, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 2.9)] public delegate void IdentityReferenceAddedCb (Signon.Identity self, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 2.9)] public delegate void IdentityReferenceRemovedCb (Signon.Identity self, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 2.9)] public delegate void IdentityRemovedCb (Signon.Identity self, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 2.9)] public delegate void IdentitySignedOutCb (Signon.Identity self, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 3.9)] public delegate void IdentityStoreCredentialsCb (Signon.Identity self, uint32 id, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 3.9)] public delegate void IdentityVerifyCb (Signon.Identity self, bool valid, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 2.9)] public delegate void IdentityVoidCb (Signon.Identity self, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 4.9)] public delegate void QueryMechanismCb (Signon.AuthService auth_service, string method, [CCode (array_length = false, array_null_terminated = true)] owned string[] mechanisms, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", instance_pos = 3.9)] public delegate void QueryMethodsCb (Signon.AuthService auth_service, [CCode (array_length = false, array_null_terminated = true)] owned string[] methods, GLib.Error error); [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_CAPTION")] public const string SESSION_DATA_CAPTION; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_PROXY")] public const string SESSION_DATA_PROXY; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_REALM")] public const string SESSION_DATA_REALM; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_RENEW_TOKEN")] public const string SESSION_DATA_RENEW_TOKEN; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_SECRET")] public const string SESSION_DATA_SECRET; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_TIMEOUT")] public const string SESSION_DATA_TIMEOUT; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_UI_POLICY")] public const string SESSION_DATA_UI_POLICY; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_USERNAME")] public const string SESSION_DATA_USERNAME; [CCode (cheader_filename = "libsignon-glib/signon-glib.h", cname = "SIGNON_SESSION_DATA_WINDOW_ID")] public const string SESSION_DATA_WINDOW_ID; } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-accounts-model.vala0000644000015600001650000004256112653650644030662 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ // FIXME: Make the model sortable. /** * Web credentials accounts Gtk.ListStore. Used as a model for the accounts * stored by libaccounts-glib. */ public class Cc.Credentials.AccountsModel : Gtk.ListStore { private Ag.Manager accounts_manager; private uint[] past_failures; private WebcredentialsIndicator indicator; /** * Identifiers for columns in the accounts model. * * @param ACCOUNT_ID the Ag.AccountId for the Ag.Account * @param ACCOUNT the Ag.Account * @param PROVIDER_ICON the icon of the account provider * @param TRANSLUCENT_PIXBUF the translucent icon to show when the account * is disabled * @param ACCOUNT_DESCRIPTION the description of the account or provider * @param ENABLED whether the account is enabled * @param NEEDS_ATTENTION whether there is a problem with the account that * needs the attention of the user */ public enum ModelColumns { ACCOUNT_ID = 0, ACCOUNT = 1, PROVIDER_ICON = 2, TRANSLUCENT_PIXBUF = 3, ACCOUNT_DESCRIPTION = 4, ENABLED = 5, NEEDS_ATTENTION = 6 } private struct ColumnRecord { public uint account_id; public Ag.Account account; public Icon icon; public Gdk.Pixbuf translucent_pixbuf; public string description; public bool enabled; public bool attention; } /** * The account manager. */ public Ag.Manager manager { get { return accounts_manager; } } /** * The Webcredentials interface used to report account authentication * failures. */ public WebcredentialsIndicator webcredentials_interface { get { return indicator; } } /** * Create a new data model for the list of accounts. */ public AccountsModel () { Type[] types = { typeof (uint), typeof (Ag.Account), typeof (Icon), typeof (Gdk.Pixbuf), typeof (string), typeof (bool), typeof (bool) }; set_column_types (types); accounts_manager = new Ag.Manager (); // Add a placeholder row at the end of the list. var add_account_text = _("Add account…"); // Load a themed icon for the action of adding accounts. Icon provider_icon = null; try { provider_icon = Icon.new_for_string ("credentials-add-account"); } catch (Error error) { message ("Error looking up themed add icon: %s", error.message); } insert_with_values (null, 0, ModelColumns.ACCOUNT_ID, 0, ModelColumns.PROVIDER_ICON, provider_icon, ModelColumns.ACCOUNT_DESCRIPTION, add_account_text, ModelColumns.ENABLED, true, ModelColumns.NEEDS_ATTENTION, false, -1); var accounts = accounts_manager.list (); // Sort by account ID. accounts.sort ((a, b) => { return (int)a - (int)b; }); accounts.foreach (add_account); try { indicator = Bus.get_proxy_sync (BusType.SESSION, "com.canonical.indicators.webcredentials", "/com/canonical/indicators/webcredentials"); var indicator_proxy = indicator as DBusProxy; indicator_proxy.g_properties_changed.connect (on_proxy_properties_changed); // Get the current list of failures. on_indicator_notify_failures (); } catch (IOError err) { warning ("Error initializing indicator proxy: %s\nAccount attention monitoring will be disabled", err.message); } accounts_manager.account_created.connect (on_account_created); accounts_manager.account_deleted.connect (on_account_deleted); accounts_manager.account_updated.connect (on_account_updated); } /** * Instantiate an account from the supplied account ID, and add it to the * list of accounts. * * This method is intended to be used with the foreach method of GLib * containers. * * @param account_id an Ag.AccountId to add to the list of accounts */ private void add_account (uint account_id) { Ag.Account account; try { account = accounts_manager.load_account (account_id); } catch (Error error) { critical ("Unable to instantiate account: %s", error.message); return; } /* Insert the new account at the bottom of the list of accounts, but * before the ‘Add account’ row. */ var record = fill_column_record (account_id); insert_with_values (null, this.iter_n_children (null) - 1, ModelColumns.ACCOUNT_ID, record.account_id, ModelColumns.ACCOUNT, record.account, ModelColumns.PROVIDER_ICON, record.icon, ModelColumns.TRANSLUCENT_PIXBUF, record.translucent_pixbuf, ModelColumns.ACCOUNT_DESCRIPTION, record.description, ModelColumns.ENABLED, record.enabled, ModelColumns.NEEDS_ATTENTION, record.attention, -1); } /** * Get an iter to a row in the model with a matching Ag.AccountId. * * The row in the model for adding a new account (which has an accound ID * of 0) is special, as it is always the last row. Additionally, false is * always returned when searching for that row. * * @param account_id the Ag.AccountId of an Ag.Account described in the * model * @return true if the account_id existed in the model, false otherwise */ public bool find_iter_for_account_id (Ag.AccountId account_id, out Gtk.TreeIter iter) { Gtk.TreeIter local_iter; this.get_iter_first (out local_iter); // Special-case the "Add account…" row so that it is never changed. if (account_id == 0) { iter = local_iter; return false; } var found = false; do { Ag.AccountId model_account_id; this.get (local_iter, ModelColumns.ACCOUNT_ID, out model_account_id, -1); if (account_id == model_account_id) { found = true; break; } } while (this.iter_next (ref local_iter)); iter = local_iter; return found; } /** * Create a translucent Gdk.Pixbuf from a GLib.Icon. * * @param gicon the GLib.Icon to create a translucent pixbuf for */ private Gdk.Pixbuf translucent_from_gicon (Icon gicon) { var icon_theme = Gtk.IconTheme.get_default (); try { var pixbuf = icon_theme.load_icon (gicon.to_string (), 32, // Size in pixels. 0); // No lookup flags. var temp_pixbuf = new Gdk.Pixbuf (pixbuf.get_colorspace (), true, pixbuf.get_bits_per_sample (), pixbuf.get_width (), pixbuf.get_height ()); temp_pixbuf.fill (0); // Make the icon translucent. pixbuf.composite (temp_pixbuf, 0, 0, pixbuf.get_width (), pixbuf.get_height (), 0.0, 0.0, 1.0, 1.0, Gdk.InterpType.BILINEAR, 255 / 2); return temp_pixbuf; } catch (Error err) { message ("Error loading icon '%s': %s", gicon.to_string (), err.message); return new Gdk.Pixbuf (Gdk.Colorspace.RGB, true, // Has alpha channel. 8, // Bits per sample. 32, // Width. 32); // Height. } } /** * Handle D-Bus property changes on the indicator proxy. * * @param changed_properties dictionary of changed property names and * values * @param invalidated_properties array of names of invalidated properties */ private void on_proxy_properties_changed (Variant changed_properties, string invalidated_properties[]) { var iter = changed_properties.iterator (); Variant change; while ((change = iter.next_value ()) != null) { string property_name; change.get ("{sv}", out property_name, null); if (property_name == "Failures") { on_indicator_notify_failures (); } } } /** * Handle account authentication failures, marking the failing accounts as * needing attention. */ private void on_indicator_notify_failures () { var failures = indicator.failures; if (past_failures == null && failures == null) { return; } /* Vala uses the _TO_POINTER macros to insert bools and uints, so use * direct_hash and direct_equal. */ var failures_hash = new HashTable (direct_hash, direct_equal); if (past_failures != null) { foreach (var past_failure in past_failures) { failures_hash.insert (past_failure, false); } } if (failures != null) { foreach (var failure in failures) { failures_hash.insert (failure, true); } } past_failures = failures; failures_hash.foreach (set_failure); } /** * Set the failure state for an account id in the model. * * @param account_id the account ID for which to set the failure * @param failure true if the account should be marked as failing, false if * the account failure state should be cleared */ private void set_failure (uint account_id, bool failure) { Gtk.TreeIter iter; if (find_iter_for_account_id (account_id, out iter)) { this.set (iter, ModelColumns.NEEDS_ATTENTION, failure, -1); } else { message ("Failure change reported for non-existent account ID: %u", account_id); } } /** * Handle the account-created signal on Ag.Manager. * * @param id the Ag.AccountId of the Ag.Account that was created */ private void on_account_created (uint id) { Ag.AccountId account_id = (Ag.AccountId) id; add_account (account_id); } /** * Handle the account-deleted signal on Ag.Manager. * * @param id the Ag.AccountId of the Ag.Account that was deleted */ private void on_account_deleted (uint id) { Ag.AccountId account_id = (Ag.AccountId) id; Gtk.TreeIter iter; if (find_iter_for_account_id (account_id, out iter)) { this.remove (iter); } else { warning ("Account with ID %u was already removed", id); } } /** * Handle the account-updated signal on Ag.Manager. * * @param id the Ag.AccountId of the Ag.Account that was updated */ private void on_account_updated (uint id) { Ag.AccountId account_id = (Ag.AccountId) id; Gtk.TreeIter iter; if (find_iter_for_account_id (account_id, out iter)) { // Unconditionally copy the data from the changed account. var record = fill_column_record (account_id); this.set (iter, ModelColumns.PROVIDER_ICON, record.icon, ModelColumns.TRANSLUCENT_PIXBUF, record.translucent_pixbuf, ModelColumns.ACCOUNT_DESCRIPTION, record.description, ModelColumns.ENABLED, record.enabled, ModelColumns.NEEDS_ATTENTION, record.attention, -1); } else { warning ("Account with ID %u was updated, but did not already exist in the model", id); add_account (account_id); } } /** * Handle the account enabled state being changed, and update the model * accordingly. * * @param account the account which was updated * @param service the service which was changed. Ignored * @param enabled the current state of the account */ private void on_account_enabled (Ag.Account account, string? service, bool enabled) { // Ignore service-level changes. // FIXME: http://code.google.com/p/accounts-sso/issues/detail?id=157 if (service != "global" || service != null) { return; } Gtk.TreeIter iter; bool model_enabled; if (find_iter_for_account_id (account.id, out iter)) { this.get (iter, ModelColumns.ENABLED, out model_enabled); if (model_enabled != enabled) { this.set (iter, ModelColumns.ACCOUNT_DESCRIPTION, format_account_description (account), ModelColumns.ENABLED, enabled, -1); } } else { message ("Enabled state change reported for non-existent account ID: %u", account.id); } } /** * Handle the account display name being changed, and update the model * accordingly. * * @param account the account which was updated */ private void on_account_display_name_changed (Ag.Account account) { Gtk.TreeIter iter; if (find_iter_for_account_id (account.id, out iter)) { this.set (iter, ModelColumns.ACCOUNT_DESCRIPTION, format_account_description (account), -1); } else { message ("Enabled state change reported for non-existent account ID: %u", account.id); } } /** * Fill in a ColumnRecord structure with details of the account, for using * to fill in a row in the model. * * @param account_id the ID of the Ag.Account * @return a new ColumnRecord */ private ColumnRecord fill_column_record (uint account_id) { var account = accounts_manager.get_account ((Ag.AccountId) account_id); var record = ColumnRecord (); // FIXME: Add provider property to Ag.Account, and use it here. var display_name = account.get_display_name (); record.enabled = account.get_enabled (); var name_markup = record.enabled ? display_name : "" + display_name + ""; var provider = manager.get_provider (account.get_provider_name ()); record.account_id = account_id; record.account = account; try { record.icon = Icon.new_for_string (provider.get_icon_name ()); } catch (Error error) { message ("Error looking up themed provider icon: %s", error.message); record.icon = null; } record.translucent_pixbuf = translucent_from_gicon (record.icon); // Also see format_account_description (). record.description = provider.get_display_name () + "\n" + "" + name_markup + ""; record.attention = false; account.enabled.connect (on_account_enabled); account.display_name_changed.connect (on_account_display_name_changed); return record; } /** * Provide a string describing the account for display to the user. * * @param account the account for which to generate the description * @return the account description */ private string format_account_description (Ag.Account account) { var provider = manager.get_provider (account.get_provider_name ()); var display_name = account.get_display_name (); var name_markup = account.get_enabled () ? display_name : "" + display_name + ""; return provider.get_display_name () + "\n" + "" + name_markup + ""; } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-authorization-page.vala0000644000015600001650000001233412653650644031552 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ /** * Web credentials authorization page. This is designed to take the full width * of the parent widget, for display of an authorization widget, such as a * WebKit view. */ public class Cc.Credentials.AuthorizationPage : Gtk.Grid { private Ap.Plugin plugin; private weak Gtk.Widget widget; private Ag.Account current_account; private WebcredentialsIndicator indicator; private bool needs_reauthentication = false; /** * Emitted when the authorization process was cancelled. */ public signal void cancelled (); /** * Keep the UI state consistent when the account is changed. */ public Ag.Account account { get { return current_account; } set { current_account = value; plugin = Ap.client_load_plugin (account); if (plugin == null) { critical ("No valid plugin found for provider %s", value.get_provider_name ()); return; } plugin.finished.connect (on_plugin_finished); if (needs_reauthentication) { plugin.need_authentication = true; } var plugin_widget = plugin.build_widget (); if (plugin_widget != null) { set_plugin_widget (plugin.build_widget ()); } else { critical ("Plugin failed to build widget for account ID: %u", value.id); return; } } } public AuthorizationPage () { Object (); } construct { expand = true; orientation = Gtk.Orientation.VERTICAL; try { indicator = Bus.get_proxy_sync (BusType.SESSION, "com.canonical.indicators.webcredentials", "/com/canonical/indicators/webcredentials"); } catch (IOError err) { warning ("Error initializing indicator proxy: %s\nAccount attention notifications will not function", err.message); } show (); } /** * Trigger a re-authentication with the supplied account. * * @param account the account to re-authenticate */ public void reauthenticate_account (Ag.Account account) { needs_reauthentication = true; this.account = account; } /** * Set the login data that the plugin might use while performing the * authentication. * * @param username the user login name. * @param password the user password. * @param cookies a dictionary of cookies. */ public void set_login_data (string username, string? password, HashTable? cookies) { plugin.set_credentials (username, password); if (cookies != null) { plugin.set_cookies (cookies); } } /** * Set a plugin widget and show it, removing the old widget if necessary. * * @param plugin_widget the Gtk.Widget to set as the new plugin widget */ private void set_plugin_widget (Gtk.Widget plugin_widget) { remove_plugin_widget (); widget = plugin_widget; widget.show (); this.add (widget); } /** * Remove the plugin widget. */ private void remove_plugin_widget () { if (widget != null) { this.remove (widget); widget = null; } } /** * Handle the "finished" signal from the plugin. */ private void on_plugin_finished () { var user_cancelled = plugin.get_user_cancelled (); var plugin_err = plugin.get_error (); remove_plugin_widget (); plugin = null; if (user_cancelled) { cancelled (); } else { /* TODO handle normal termination and improve handling of * termination with error */ if (plugin_err != null) { critical ("Error completing auth session process: %s", plugin_err.message); } else { // TODO: Can this be called unconditionally? indicator.remove_failures ( {current_account.id} ); indicator.clear_error_status (); } cancelled (); } } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-accounts-page.vala0000644000015600001650000003524112653650644030473 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ /** * Web credentials accounts page. This is for selecting an account, or for * showing details of an existing account. */ public class Cc.Credentials.AccountsPage : Gtk.Grid { public uint account_details_id { get; construct; } public string application_id { get; construct; } private Gtk.TreeView accounts_tree; private AccountsModel accounts_store; private Gtk.Notebook accounts_notebook; private AccountDetailsPage account_details_page; /** * Emitted when a new account should be added. Copied from ProvidersPage, * to be emitted again to the main panel. * * @param provider_name the name of the provider for which an account * should be added */ public signal void new_account_request (string provider_name); /** * Emitted when an existing account needs to be reauthenticated. Copied * from AccountDetailsPage, to be emitted again to the main panel. * * @param account the account to authenticate */ public signal void reauthenticate_account_request (Ag.Account account); /** * Emitted when an application needs to show options. Copied from * AccountDetailsPage, to be emitted again to the main panel. * * @param application_row the AccountApplicationRow for the application * that needs configuration */ public signal void account_options_request (AccountApplicationRow application_row); /** * Emitted when an account needs to show options. Copied from * AccountDetailsPage, to be emitted again to the main panel. * * @param plugin the Ap.Plugin for the account that needs configuration */ public signal void account_edit_options_request (Ap.Plugin plugin); /** * Select the desired page of @link accounts_notebook to select an account * to view settings of, or for showing details of an existing account. * * @param SELECT_PROVIDER select a provider for a new account * @param ACCOUNT_DETAILS display details of an existing account */ private enum NotebookPage { SELECT_PROVIDER = 0, ACCOUNT_DETAILS = 1 } public AccountsPage () { Object (); } public AccountsPage.with_account_details (Ag.AccountId account_id) { Object (account_details_id: account_id); } public AccountsPage.with_application (string application) { Object (application_id: application); } construct { row_spacing = 6; column_spacing = 12; this.attach (create_accounts_tree (), 0, 0, 1, 1); this.attach (create_accounts_notebook (), 1, 0, 1, 1); this.attach (create_legal_button (), 0, 1, 2, 1); // Force handling of the changed signal. var selection = accounts_tree.get_selection (); on_accounts_selection_changed (selection); // Update the selection if a new account was added. accounts_store.row_inserted.connect (on_accounts_store_row_inserted); set_size_request (-1, 400); show (); } /** * Create the buttonbox containing the button to display a legal notice. * * @return a Gtk.ButtonBox for presecting the legal notice button */ private Gtk.Widget create_legal_button () { var buttonbox = new Gtk.ButtonBox (Gtk.Orientation.HORIZONTAL); var legal_button = new Gtk.LinkButton.with_label ("help:" + "web-credentials" + "/legal-notice", _("Legal notice")); buttonbox.layout_style = Gtk.ButtonBoxStyle.END; buttonbox.add (legal_button); buttonbox.show_all (); return buttonbox; } /** * Create the treeview for the list of accounts and show it. * * @return a Gtk.ScrolledWindow containing a treeview of accounts */ private Gtk.Widget create_accounts_tree () { accounts_tree = new Gtk.TreeView (); accounts_store = new AccountsModel (); accounts_tree.model = accounts_store; accounts_tree.headers_visible = false; var provider_icon_renderer = new Gtk.CellRendererPixbuf (); provider_icon_renderer.stock_size = Gtk.IconSize.DND; provider_icon_renderer.set_padding (8, 8); var text_renderer = new Gtk.CellRendererText (); text_renderer.ellipsize = Pango.EllipsizeMode.END; var accounts_tree_column = new Gtk.TreeViewColumn (); accounts_tree_column.pack_start (provider_icon_renderer, false); accounts_tree_column.set_cell_data_func (provider_icon_renderer, provider_icon_cell_data_func); accounts_tree_column.pack_start (text_renderer, true); accounts_tree_column.add_attribute (text_renderer, "markup", AccountsModel.ModelColumns.ACCOUNT_DESCRIPTION); var attention_icon_renderer = new Gtk.CellRendererPixbuf (); attention_icon_renderer.icon_name = "dialog-error-symbolic"; accounts_tree_column.pack_end (attention_icon_renderer, false); accounts_tree_column.add_attribute (attention_icon_renderer, "visible", AccountsModel.ModelColumns.NEEDS_ATTENTION); accounts_tree.append_column (accounts_tree_column); var scrolled_window = new Gtk.ScrolledWindow (null, null); scrolled_window.min_content_height = 250; scrolled_window.min_content_width = 250; scrolled_window.shadow_type = Gtk.ShadowType.ETCHED_IN; scrolled_window.add (accounts_tree); var accounts_selection = accounts_tree.get_selection (); // Select the row with the account ID passed in at construction time. if (account_details_id != 0) { Gtk.TreeIter iter; if (accounts_store.find_iter_for_account_id (account_details_id, out iter)) { accounts_selection.select_iter (iter); } else { warning ("Passed-in account ID '%u' not found.", (uint) account_details_id); } } // Check if any changes occured on the selected row. accounts_store.row_changed.connect (on_accounts_store_row_changed); // The changed handler depends on the notebook being constructed. accounts_selection.changed.connect (on_accounts_selection_changed); scrolled_window.show_all (); return scrolled_window; } /** * Create the notebook with a page for adding providers. * * @return a Gtk.Notebook containing a provider selection tree view */ private Gtk.Widget create_accounts_notebook () { accounts_notebook = new Gtk.Notebook (); accounts_notebook.show_tabs = false; accounts_notebook.show_border = false; accounts_notebook.expand = true; ProvidersPage providers_page; if (application_id != null) { providers_page = new ProvidersPage.with_application (application_id); } else { providers_page = new ProvidersPage (); } var account_details_page = create_account_details_page () as AccountDetailsPage; providers_page.new_account_request.connect (on_providers_page_new_account_request); account_details_page.reauthenticate_account_request.connect (on_account_details_page_reauthenticate_account_request); account_details_page.account_options_request.connect (on_account_details_page_account_options_request); account_details_page.account_edit_options_request.connect (on_account_details_page_account_edit_options_request); accounts_notebook.append_page (providers_page); accounts_notebook.append_page (account_details_page); accounts_notebook.set_current_page (NotebookPage.SELECT_PROVIDER); accounts_notebook.show_all (); return accounts_notebook; } /** * Create a notebook page for showing details for an account, such as the * list of applications which use that account. * * @return a Gtk.Grid containing widgets for listing account details */ private Gtk.Widget create_account_details_page () { account_details_page = new AccountDetailsPage (accounts_store); return account_details_page; } /** * Show the translucent provider icon if the account is disabled, and the * standard icon when the account is enabled. * * @param column the TreeModelColumn. Unused * @param cell the Gtk.CellRendererPixbuf for the column * @param model the AccountsModel to get data from * @param iter the oter in AccountsModel to get data from */ private void provider_icon_cell_data_func (Gtk.CellLayout column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { bool enabled; Icon icon; Gdk.Pixbuf pixbuf; var renderer = cell as Gtk.CellRendererPixbuf; model.get (iter, AccountsModel.ModelColumns.ENABLED, out enabled, AccountsModel.ModelColumns.PROVIDER_ICON, out icon, AccountsModel.ModelColumns.TRANSLUCENT_PIXBUF, out pixbuf, -1); if (enabled) { renderer.pixbuf = null; renderer.gicon = icon; } else { renderer.gicon = null; renderer.pixbuf = pixbuf; } } /** * Reload the account details page if the currently-selected row changed. * * @param tree_model the AccountsModel * @param path the Gtk.TreePath of the changed row * @param iter the Gtk.TreeIter of the changed row */ private void on_accounts_store_row_changed (Gtk.TreeModel tree_model, Gtk.TreePath path, Gtk.TreeIter iter) { var selection = accounts_tree.get_selection (); if (selection.path_is_selected (path)) { // Set the selected iter again. account_details_page.account_iter = iter; } } /** * Show an appropriate page in the notebook, depending on which row was * selected in the accounts treeview. * * @param selection the selection of the accounts treeview */ private void on_accounts_selection_changed (Gtk.TreeSelection selection) { Gtk.TreeModel model; Gtk.TreeIter iter; if (selection.get_selected (out model, out iter)) { Gtk.TreeIter test_iter; var n_rows = model.iter_n_children (null); // n_rows is not an index, which is what iter_nth_child() expects if (model.iter_nth_child (out test_iter, null, n_rows - 1)) { if (iter == test_iter) { // Last row selected, switch to add account notebook page. accounts_notebook.set_current_page (NotebookPage.SELECT_PROVIDER); } else { // Account row selected, show the relevant account page. account_details_page.account_iter = iter; accounts_notebook.set_current_page (NotebookPage.ACCOUNT_DETAILS); } } else { // Selection was past the final row. assert_not_reached (); } } else { // Select the first row if nothing else is selected. if (model.iter_n_children (null) > 0) { selection.select_path (new Gtk.TreePath.first ()); } } } /** * Tell the main panel to show a new account page for the provider selected * in the tree view of available providers. * * @param provider_name the name of the provider for which to add an * account */ private void on_providers_page_new_account_request (string provider_name) { new_account_request (provider_name); } /** * Tell the main panel to show the authentication page for an account that * requires attention in the account details view. * * @param account the account to reauthenticate */ private void on_account_details_page_reauthenticate_account_request (Ag.Account account) { reauthenticate_account_request (account); } /** * Tell the main panel to show the options page for an application that * required configuration in the account details view. * * @param application_row the AccountApplicationRow of the application to * show options for */ private void on_account_details_page_account_options_request (AccountApplicationRow application_row) { account_options_request (application_row); } /** * Tell the main panel to show the options page for an account that * required configuration in the account details view. * * @param plugin the Ap.Plugin of the account to show options for */ private void on_account_details_page_account_edit_options_request (Ap.Plugin plugin) { account_edit_options_request (plugin); } /** * Select the newly-added row, as required by the UI specification. * * @param path the Gtk.TreePath of the newly-added row * @param iter the Gtk.TreeIter of the newly-added row */ private void on_accounts_store_row_inserted (Gtk.TreePath path, Gtk.TreeIter iter) { var selection = accounts_tree.get_selection (); selection.select_iter (iter); } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-preferences.vala0000644000015600001650000002154512653650644030245 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ /** * Web credentials preferences widget. This can be packed into the Unity * Control Center or used in a standalone application. */ public class Cc.Credentials.Preferences : Gtk.Notebook { private AuthorizationPage authorization_page; private Ag.Manager accounts_manager; private LoginCapture login_capture; /* This must be a construct property so that is is called before the * construct block. */ public uint account_details_id { get; construct; } public string application_id { get; construct; } /** * Select the desired page of @link Preferences to query the current * accounts and providers, or to authorize an account. * * @param ACCOUNTS select an account or provider in a two-pane view * @param AUTHORIZATION authorize an account in a full-size widget, such as * a WebKit view * @param ACCOUNT_OPTIONS set options on an account for either a specific * application or for the account globally */ private enum PreferencesPage { ACCOUNTS = 0, AUTHORIZATION = 1, ACCOUNT_OPTIONS = 2, } public Preferences () { Object (); } public Preferences.with_account_details (Ag.AccountId account_id) { Object (account_details_id: account_id); } public Preferences.with_application (string application) { Object (application_id: application); } construct { show_tabs = false; show_border = false; expand = true; border_width = 18; accounts_manager = new Ag.Manager (); /* invoke the update-accounts tool to enable any newly installed * services on the existing accounts. * We are doing this after initializing our own Ag.Manager in order to * avoid being slowed down due to any possible locking issues. */ try { DesktopAppInfo appInfo = new DesktopAppInfo ("update-accounts.desktop"); appInfo.launch (null, null); } catch (Error e) { warning ("Error launching update-accounts tool: %s", e.message); } AccountsPage accounts_page; if (account_details_id != 0) { accounts_page = new AccountsPage.with_account_details (account_details_id); } else if (application_id != null) { accounts_page = new AccountsPage.with_application (application_id); } else { accounts_page = new AccountsPage (); } accounts_page.new_account_request.connect (on_accounts_page_new_account_request); accounts_page.reauthenticate_account_request.connect (on_accounts_page_reauthenticate_account_request); accounts_page.account_options_request.connect (on_accounts_page_account_options_request); accounts_page.account_edit_options_request.connect (on_accounts_page_account_edit_options_request); this.append_page (accounts_page); authorization_page = new AuthorizationPage (); authorization_page.cancelled.connect (on_authorization_page_cancelled); this.append_page (authorization_page); set_current_page (PreferencesPage.ACCOUNTS); set_size_request (-1, 400); show (); login_capture = new LoginCapture (); login_capture.new_account_request.connect ( on_login_capture_new_account_request); } /** * Handle the new-account-request signal from LoginCapture, switching * notebook page to the new account view. * * @param provider_name the name of the provider for which to add an * account. * @param username the user login name. * @param password the user password. * @param cookies a dictionary of cookies. */ private void on_login_capture_new_account_request (string provider_name, string username, string? password, HashTable cookies) { var account = accounts_manager.create_account (provider_name); authorization_page.account = account; authorization_page.set_login_data (username, password, cookies); set_current_page (PreferencesPage.AUTHORIZATION); } /** * Handle the new-account-request signal from AccountsPage (and in turn * ProvidersPage), switching notebook page to the new account view. * * @param provider_name the name of the provider for which to add an * account */ private void on_accounts_page_new_account_request (string provider_name) { var account = accounts_manager.create_account (provider_name); authorization_page.account = account; set_current_page (PreferencesPage.AUTHORIZATION); } /** * Handle the reauthenticate-account-request signal from AccountsPage (and * in turn AccountDetailsPage), switching notebook page to the account * authentication view. * * @param account the account to authenticate */ private void on_accounts_page_reauthenticate_account_request (Ag.Account account) { authorization_page.reauthenticate_account (account); set_current_page (PreferencesPage.AUTHORIZATION); } /** * Handle the authorization process for a new account being cancelled, * switching the current notebook page to the provider selection view. */ private void on_authorization_page_cancelled () { set_current_page (PreferencesPage.ACCOUNTS); } /** * Handle the account-options-request signal from AccountsPage (and in turn * AccountDetailsPage), switching notebook page to the application account * options view. * * @param application_row the AccountApplicationRow to show options for */ private void on_accounts_page_account_options_request (AccountApplicationRow application_row) { assert (application_row.plugin_widget != null); this.append_page (application_row.plugin_widget); application_row.plugin.finished.connect (on_account_application_options_finished); set_current_page (PreferencesPage.ACCOUNT_OPTIONS); } /** * Handle the account options editing process finishing, and switch back to * the accounts view. * * @param plugin the plugin that emitted the finished signal */ private void on_account_application_options_finished (Ap.ApplicationPlugin plugin) { var plugin_err = plugin.get_error (); if (plugin_err != null) { warning ("Error during account application options process: %s", plugin_err.message); } this.remove_page (PreferencesPage.ACCOUNT_OPTIONS); set_current_page (PreferencesPage.ACCOUNTS); } /** * Handle the account-edit-options-request signal from AccountsPage (and ini * turn AccountDetailsPage), switching notebook page to the application * account options view. * * @param application_row the AccountApplicationRow to show options for */ private void on_accounts_page_account_edit_options_request (Ap.Plugin plugin) { var widget = plugin.build_widget (); if (widget == null) { critical ("Error building configuration widget"); return; } widget.show (); this.append_page (widget); plugin.finished.connect (on_account_edit_options_finished); set_current_page (PreferencesPage.ACCOUNT_OPTIONS); } /** * Handle the account options editing process finishing, and switch back to * the accounts view. * * @param plugin the plugin that emitted the finished signal */ private void on_account_edit_options_finished (Ap.Plugin plugin) { var plugin_err = plugin.get_error (); if (plugin_err != null) { warning ("Error during account edit options process: %s", plugin_err.message); } this.remove_page (PreferencesPage.ACCOUNT_OPTIONS); set_current_page (PreferencesPage.ACCOUNTS); } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-application.vala0000644000015600001650000001074412653650644030246 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ /** * Standalone application for configuring web credentials accounts outside of * Unity Control Center. */ public class Cc.Credentials.Application : Gtk.Application { static bool version; private Gtk.Window main_window; const OptionEntry[] options = { { "version", 'V', 0, OptionArg.NONE, ref version, N_("Output version information and exit"), null }, { null } }; public Application (string app_id, ApplicationFlags flags) { GLib.Object (application_id: app_id, flags: flags); } /** * Raise the window if the application already has a running instance. */ public void on_app_activate () { if (get_windows () != null) { main_window.present (); } else { Environment.set_application_name (_("Online Accounts preferences")); main_window = new Gtk.Window (); main_window.add (new Preferences ()); main_window.set_application (this); main_window.show (); } } /** * Overriden method of GLib.Application, to handle command-line arguments * in the local instance. This is especially important for --version, so * that only the local instance exits. * * @param arguments the command-line arguments * @param exit_status the exit code to return to the OS * @return true if the arguments were successfully processed, false * otherwise */ public override bool local_command_line ([CCode (array_length = false, array_null_terminated = true)] ref unowned string[] args, out int exit_status) { try { register (); } catch (Error e) { critical ("Error during Application registration: %s", e.message); exit_status = 1; return true; } // Ugly workaround for GNOME bug 642885. unowned string[] arguments = args; if (arguments.length <= 1) { activate (); exit_status = 0; } else { try { var context = new OptionContext (_(" - Edit Web credentials settings")); context.set_translation_domain (Config.GETTEXT_PACKAGE); context.set_help_enabled (true); context.add_main_entries (options, null); context.add_group (Gtk.get_option_group (true)); context.parse (ref arguments); } catch (OptionError e) { stdout.printf ("Error parsing command-line: %s\n", e.message); stdout.printf (_("Run '%s --help' to see a full list of available command line options.\n"), arguments[0]); exit_status = 1; return true; } if (version) { stdout.printf ("%s %s\n", Config.PACKAGE_NAME, Config.PACKAGE_VERSION); exit_status = 1; return true; } if (get_is_remote ()) { stdout.printf ("%s\n", _("Another instance is already running")); exit_status = 1; return true; } else { exit_status = 0; } } return true; } } public static int main (string[] arguments) { var app = new Cc.Credentials.Application ("com.Canonical.WebCredentials.Preferences", ApplicationFlags.FLAGS_NONE); app.activate.connect (app.on_app_activate); return app.run (arguments); } gnome-control-center-signon-0.1.8+16.04.20160201/src/config.vapi0000644000015600001650000000040412653650644024336 0ustar pbuserpbgroup00000000000000[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")] namespace Config { public const string GETTEXT_PACKAGE; public const string GNOMELOCALEDIR; public const string PACKAGE_NAME; public const string PACKAGE_VERSION; } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-applications-model.vala0000644000015600001650000001063212653650644031523 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ // FIXME: Make the model sortable. /** * Web credentials applications Gtk.ListStore. Used as a model for the * applications managed by libaccounts-glib, for display in a combo box for * selecting an application. */ public class Cc.Credentials.ApplicationsModel : Gtk.ListStore { private Ag.Manager manager; /** * Identifiers for columns in the applications model. * * @param APPLICATION_NAME the name of the application, for passing to * Ag.Manager.get_application () * @param APPLICATION_DESCRIPTION the description of the application */ public enum ModelColumns { APPLICATION_NAME = 0, APPLICATION_DESCRIPTION = 1 } /** * Create a new data model for the list of applications. */ public ApplicationsModel () { Type[] types = { typeof (string), typeof (string) }; set_column_types (types); // TODO: Use the same Ag.Manager throughout. manager = new Ag.Manager (); populate_model (); // FIXME: No notification signals for adding new applications. } /** * Populate the model with the current list of applications, by querying * for available services and then listing the applications available for * each service. */ private void populate_model () { var services = manager.list_services (); var application_hash = new HashTable (str_hash, str_equal); foreach (var service in services) { var applications = manager.list_applications_by_service (service); foreach (var application in applications) { application_hash.insert (dgettext (application.get_i18n_domain (), application.get_name ()), dgettext (application.get_i18n_domain (), application.get_description ())); } } application_hash.foreach (add_application); // Magic value! Must always be the first item in the list. insert_with_values (null, 0, ModelColumns.APPLICATION_NAME, "all", ModelColumns.APPLICATION_DESCRIPTION, _("All applications")); } /** * Insert a single application and application display name into the model. */ private void add_application (string application_name, string application_description) { insert_with_values (null, -1, ModelColumns.APPLICATION_NAME, application_name, ModelColumns.APPLICATION_DESCRIPTION, application_description, -1); } /** * Find an iter for a given application. * * @param application the name of an Ag.Application described in the model * @param iter the iter to set * @return true if the application existed in the model, false otherwise */ public bool find_iter_for_application (string application, out Gtk.TreeIter iter) { Gtk.TreeIter local_iter; this.get_iter_first (out local_iter); var found = false; do { string model_application; this.get (local_iter, ModelColumns.APPLICATION_NAME, out model_application, -1); if (model_application == application) { found = true; break; } } while (this.iter_next (ref local_iter)); iter = local_iter; return found; } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-providers-page.vala0000644000015600001650000002703412653650644030672 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ /** * Web credentials providers page. This is for selecting an available provider * to add a new account for. */ public class Cc.Credentials.ProvidersPage : Gtk.Grid { /** * Emitted when a new account should be added. * * @param provider_name the name of the provider for which an account * should be added */ public signal void new_account_request (string provider_name); /** * Select the desired page of @link providers_notebook to select a provider * tree view or label describing no applications for this provider. * * @param TREE show the tree view of providers for this application * @param LABEL show the label explaining the lack of available * applications */ private enum NotebookPage { TREE = 0, LABEL = 1 } private Ag.Manager manager; private Gtk.ComboBox applications_combo; private Gtk.Notebook providers_notebook; private Gtk.TreeModelFilter filter_model; private string current_application; public string application_id { get; construct; } public ProvidersPage () { Object (); } public ProvidersPage.with_application (string application) { Object (application_id: application); } construct { orientation = Gtk.Orientation.VERTICAL; expand = true; // TODO: Use common Ag.Manager. manager = new Ag.Manager (); this.add (create_providers_selector ()); this.add (create_providers_notebook ()); /* This defaults to -1, no selection, so force it to have the first * item selected. */ applications_combo.active = 0; // Trigger a refilter if an application was passed in. if (application_id != null) { current_application = application_id; Gtk.TreeIter iter; var applications_model = applications_combo.model as ApplicationsModel; if (applications_model.find_iter_for_application (application_id, out iter)) { applications_combo.set_active_iter (iter); } else { message ("Passed-in application '%s' was not found", application_id); } } set_size_request (-1, 400); show (); } /** * Create the infobar which describes the treeview of account providers. * * @return a Gtk.InfoBar describing the account providers */ private Gtk.Widget create_providers_selector () { var label = new Gtk.Label (_("Show accounts that integrate with:")); var applications_model = new ApplicationsModel (); applications_combo = new Gtk.ComboBox.with_model (applications_model); applications_combo.hexpand = true; var text_renderer = new Gtk.CellRendererText (); applications_combo.pack_start (text_renderer, false); applications_combo.set_attributes (text_renderer, "markup", ApplicationsModel.ModelColumns.APPLICATION_DESCRIPTION); var grid = new Gtk.Grid (); grid.column_spacing = 6; grid.add (label); grid.add (applications_combo); applications_combo.changed.connect (on_applications_combo_changed); // Height matches infobar of AccountDetailsPage. grid.set_size_request (-1, 48); grid.show_all (); return grid; } /** * Create the notebook for holding the provider treeview or a label. * * @return a Gtk.Notebook */ private Gtk.Widget create_providers_notebook () { providers_notebook = new Gtk.Notebook (); providers_notebook.show_border = false; providers_notebook.show_tabs = false; providers_notebook.append_page (create_providers_tree ()); var no_applications_label = new Gtk.Label (_("There are currently no account providers available which integrate with this application")); no_applications_label.wrap = true; providers_notebook.append_page (no_applications_label); providers_notebook.show_all (); return providers_notebook; } /** * Create the treeview of account providers, for setting up a new account. * * @return a Gtk.ScrolledWindow containing the account provider treeview */ private Gtk.Widget create_providers_tree () { var providers_model = new ProvidersModel (); filter_model = new Gtk.TreeModelFilter (providers_model, null); filter_model.set_visible_func (filter_model_visible); var providers_tree = new Gtk.TreeView.with_model (filter_model); providers_tree.headers_visible = false; providers_tree.hover_selection = true; providers_tree.tooltip_column = ProvidersModel.ModelColumns.TOOLTIP; var pixbuf_renderer = new Gtk.CellRendererPixbuf (); pixbuf_renderer.stock_size = Gtk.IconSize.DND; pixbuf_renderer.set_padding (8, 8); var text_renderer = new Gtk.CellRendererText (); var providers_tree_column = new Gtk.TreeViewColumn (); providers_tree_column.pack_start (pixbuf_renderer, false); providers_tree_column.add_attribute (pixbuf_renderer, "gicon", ProvidersModel.ModelColumns.PROVIDER_ICON); providers_tree_column.pack_start (text_renderer, true); providers_tree_column.add_attribute (text_renderer, "markup", ProvidersModel.ModelColumns.PROVIDER_DESCRIPTION); providers_tree.append_column (providers_tree_column); var scrolled_window = new Gtk.ScrolledWindow (null, null); scrolled_window.min_content_height = 250; scrolled_window.min_content_width = 400; scrolled_window.expand = true; scrolled_window.shadow_type = Gtk.ShadowType.ETCHED_IN; scrolled_window.add (providers_tree); /* Add a new account when a row is single-clicked, as selection is * already handled on hover. */ providers_tree.button_press_event.connect (on_providers_tree_button_press_event); providers_tree.row_activated.connect (on_providers_tree_row_activated); scrolled_window.show_all (); return scrolled_window; } /** * Visible filter function for the filter tree model of applications. * * @param model the child tree model to filter * @param iter the iter to query data from */ private bool filter_model_visible (Gtk.TreeModel model, Gtk.TreeIter iter) { string application_name; model.get (iter, ApplicationsModel.ModelColumns.APPLICATION_NAME, out application_name, -1); return application_name == current_application; } /** * Handle the application combo box selection being changed, by updating * the current application being filtered by the filter model. * * @param applications_combo the combo box for selecting from a list of * applications */ private void on_applications_combo_changed (Gtk.ComboBox applications_combo) { Gtk.TreeIter iter; if (applications_combo.get_active_iter (out iter)) { string application_name; var model = applications_combo.model; model.get (iter, ApplicationsModel.ModelColumns.APPLICATION_NAME, out application_name, -1); current_application = application_name; filter_model.refilter (); // Update the widget shown in the providers notebook. var n_items = filter_model.iter_n_children (null); update_notebook_widget (n_items); } } /** * Use the current selection (either with the pointer or keyboard * navigation) to select a provider for which to create a new account. * * @param providers_tree the treeview from which to get the current * selection */ private void add_account_for_current_selection (Gtk.TreeView providers_tree) { var selection = providers_tree.get_selection (); Gtk.TreeModel model; Gtk.TreeIter iter; if (selection.get_selected (out model, out iter)) { string provider_name; model.get (iter, ProvidersModel.ModelColumns.PROVIDER_NAME, out provider_name, -1); /* Unselect the row, as otherwise it is impossible to add * another account from the same provider immediately * afterwards. */ selection.unselect_all (); // Emit signal for the main panel to switch notebook page. new_account_request (provider_name); } } /** * Update which widget the providers notebook is showing, based on the * number of items in the filter model. * * @param n_items the number of items shown in the providers tree view, * from the filter model */ private void update_notebook_widget (int n_items) { if (n_items > 0) { providers_notebook.set_current_page (NotebookPage.TREE); } else { providers_notebook.set_current_page (NotebookPage.LABEL); } } /** * Check which row the pointer was clicked over, and create a new account * for the associated provider. * * @param widget the widget (providers_tree) that generated the event * @param event the button press event * @return true if the event was handled, false if the event should be * propagated */ private bool on_providers_tree_button_press_event (Gtk.Widget widget, Gdk.EventButton event) { if (event.button == 1 && event.type == Gdk.EventType.BUTTON_PRESS) { /* The selected row will be the row that the button press event * occurred on. */ add_account_for_current_selection (widget as Gtk.TreeView); return true; } else { // Propagate the event if it is not for creating a new account. return false; } } /** * Make activations (with the keyboard, presumably) act the same as * single-clicking on a row. * * @param tree_view the tree view which had a row activated * @param path the path of the activated row (unused) * @param column the column for the activated row (unused) */ private void on_providers_tree_row_activated (Gtk.TreeView tree_view, Gtk.TreePath path, Gtk.TreeViewColumn column) { add_account_for_current_selection (tree_view); } } gnome-control-center-signon-0.1.8+16.04.20160201/src/cc-credentials-providers-model.vala0000644000015600001650000002751712653650644031064 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * David King */ /** * Web credentials providers Gtk.ListStore. Used as a model for the providers * managed by libaccounts-glib. */ public class Cc.Credentials.ProvidersModel : Gtk.ListStore { private Ag.Manager manager; /** * Identifiers for columns in the providers model. * * @param APPLICATION_NAME the name of the application, for passing to * Ag.Manager.get_application () * @param APPLICATION_ICON the icon of the application * @param APPLICATION_DESCRIPTION the description of the application * @param PROVIDER_NAME the name of the provider, for passing to * Ag.Manager.get_provider () * @param PROVIDER_ICON the icon of the account provider * @param PROVIDER_DESCRIPTION the description of the provider * @param TOOLTIP the tooltip to show for the row * @param ROW_SORT the sort priority of the row, with more negative numbers * being sorted first */ public enum ModelColumns { APPLICATION_NAME = 0, APPLICATION_ICON = 1, APPLICATION_DESCRIPTION = 2, PROVIDER_NAME = 3, PROVIDER_ICON = 4, PROVIDER_DESCRIPTION = 5, TOOLTIP = 6, ROW_SORT = 7 } /** * Create a new data model for the list of providers. */ public ProvidersModel () { Object (); } construct { Type[] types = { typeof (string), typeof (Icon), typeof (string), typeof (string), typeof (Icon), typeof (string), typeof (string), typeof (int) }; set_column_types (types); // TODO: Use the same Ag.Manager throughout. manager = new Ag.Manager (); populate_model (); set_sort_column_id (ModelColumns.ROW_SORT, Gtk.SortType.ASCENDING); // FIXME: No notification signals for adding new providers. } /** * Populate the model with the current list of providers and associated * application, by querying for available services and then listing the * applications available for each service. */ private void populate_model () { var services = manager.list_services (); var providers = manager.list_providers (); // Add list of providers with unfilled application fields. providers.foreach (add_provider); foreach (var service in services) { var applications = manager.list_applications_by_service (service); var provider_name = service.get_provider (); var provider = manager.get_provider (provider_name); if (provider == null) continue; foreach (var application in applications) { var desktop_info = application.get_desktop_app_info (); var application_name = application.get_name (); Icon app_icon = null; string application_description = ""; if (desktop_info == null) { message ("No desktop app info found for application name: %s", application_name); } else { // Load a themed application icon. app_icon = desktop_info.get_icon (); application_description = desktop_info.get_display_name () + "\n" + desktop_info.get_description () + ""; } // Load a themed provider icon. Icon provider_icon = null; try { provider_icon = Icon.new_for_string (provider.get_icon_name ()); } catch (Error error) { message ("Failed to load provider icon: %s", error.message); } // Determine the sort order. int sort_order; if (application_name == "gwibber") sort_order = determine_sort_order_gwibber (provider_name); else if (application_name == "empathy") sort_order = determine_sort_order_empathy (provider_name); else if (application_name == "shotwell") sort_order = determine_sort_order_shotwell (provider_name); else if (application_name == "thunderbird") sort_order = determine_sort_order_thunderbird (provider_name); else sort_order = determine_sort_order_dash (provider_name); insert_with_values (null, 0, ModelColumns.APPLICATION_NAME, application.get_name (), ModelColumns.APPLICATION_ICON, app_icon, ModelColumns.APPLICATION_DESCRIPTION, application_description, ModelColumns.PROVIDER_NAME, provider.get_name (), ModelColumns.PROVIDER_ICON, provider_icon, ModelColumns.PROVIDER_DESCRIPTION, format_provider_description (provider), ModelColumns.TOOLTIP, format_provider_tooltip (provider), ModelColumns.ROW_SORT, sort_order, -1); } } } /** * Add the supplied provider to the store of providers. * * This method is intended to be used with the foreach method of GLib * containers. * * @param provider an Ag.Provider to add to the list of providers */ private void add_provider (Ag.Provider provider) { Icon provider_icon = null; if (!Ap.client_has_plugin (provider)) return; try { provider_icon = Icon.new_for_string (provider.get_icon_name ()); } catch (Error error) { message ("Failed to load provider icon: %s", error.message); } // Determine the sort order. var provider_name = provider.get_name (); var sort_order = determine_sort_order_dash (provider_name); insert_with_values (null, 0, ModelColumns.APPLICATION_NAME, "all", ModelColumns.PROVIDER_NAME, provider_name, ModelColumns.PROVIDER_ICON, provider_icon, ModelColumns.PROVIDER_DESCRIPTION, format_provider_description (provider), ModelColumns.TOOLTIP, format_provider_tooltip (provider), ModelColumns.ROW_SORT, sort_order, -1); } /** * Determine the sort order for service providers for an unspecified * application, or the dash, given a provider name. * * @param provider_name the provider name * @return the sort order, with a more negative number coming before others */ private int determine_sort_order_dash (string provider_name) { if (provider_name == "facebook") return -5; else if (provider_name == "flickr") return -4; else if (provider_name == "google") return -3; else if (provider_name == "twitter") return -2; else return 0; } /** * Determine the sort order for service providers for Gwibber, given a * provider name. * * @param provider_name the provider name * @return the sort order, with a more negative number coming before others */ private int determine_sort_order_gwibber (string provider_name) { if (provider_name == "facebook") return -5; else if (provider_name == "google") return -4; else if (provider_name == "identica") return -3; else if (provider_name == "twitter") return -2; else return 0; } /** * Determine the sort order for service providers for Empathy, given a * provider name. * * @param provider_name the provider name * @return the sort order, with a more negative number coming before others */ private int determine_sort_order_empathy (string provider_name) { if (provider_name == "salut") return -5; else if (provider_name == "facebook") return -4; else if (provider_name == "google") return -3; else return 0; } /** * Determine the sort order for service providers for Shotwell, given a * provider name. * * @param provider_name the provider name * @return the sort order, with a more negative number coming before others */ private int determine_sort_order_shotwell (string provider_name) { if (provider_name == "facebook") return -5; else if (provider_name == "flickr") return -4; else if (provider_name == "google") return -3; else return 0; } /** * Determine the sort order for service providers for Thunderbird, given a * provider name. * * @param provider_name the provider name * @return the sort order, with a more negative number coming before others */ private int determine_sort_order_thunderbird (string provider_name) { if (provider_name == "google") return -5; else if (provider_name == "yahoo") return -4; else return 0; } /** * Provide a Pango-markup description of the provider for adding to the * model. * * Add a second line of descriptive text if the provider supplies a * description. * * @param provider the provider to add * @return the description, with Pango markup */ private string format_provider_description (Ag.Provider provider) { var description = provider.get_description (); string provider_description; if (description == null) { provider_description = dgettext (provider.get_i18n_domain (), provider.get_display_name ()); } else { provider_description = dgettext (provider.get_i18n_domain (), provider.get_display_name ()) + "\n" + "" + dgettext (provider.get_i18n_domain (), description) + ""; } return provider_description; } /** * Provider a description for the tooltip for each provider, for display * when hovering over a row in the tree view. * * @param provider the provider for which to create tooltip text * @return the tooltip text */ private string format_provider_tooltip (Ag.Provider provider) { return _("Select to configure a new %s account").printf (provider.get_display_name ()); } } gnome-control-center-signon-0.1.8+16.04.20160201/README0000644000015600001650000000164612653650644022312 0ustar pbuserpbgroup00000000000000Ubuntu Online Accounts configuration panel ------------------------------------------ This project is a configuration interface for the Online Accounts framework in Ubuntu. Under Unity, it appears as a panel in the Unity Control Center. Alternatively, a standalone credentials-preferences binary can be built, which allows distributions without the Unity Control Center to use the configuration UI. libaccount-plugin ----------------- libaccount-plugin is an auxiliary library which provides support for account plugins. See the gtk-doc documentation or the online-accounts-account-plugins project for more details. Dependencies ------------ The panel and libaccount-plugin depend on: gtk+ libaccounts-glib libsignon-glib signond Licence ------- The UI is licensed under the GNU GPL version 3. libaccount-plugin is licensed under the GNU LGPL version 3. Resources --------- https://launchpad.net/gnome-control-center-signon gnome-control-center-signon-0.1.8+16.04.20160201/po/0000755000015600001650000000000012653651300022027 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/po/POTFILES.skip0000644000015600001650000000057312653650644024163 0ustar pbuserpbgroup00000000000000data/credentials-preferences.desktop.in data/unity-credentials-panel.desktop.in src/cc-credentials-account-details-page.c src/cc-credentials-accounts-model.c src/cc-credentials-accounts-page.c src/cc-credentials-application.c src/cc-credentials-applications-model.c src/cc-credentials-authorization-page.c src/cc-credentials-providers-model.c src/cc-credentials-providers-page.c gnome-control-center-signon-0.1.8+16.04.20160201/po/POTFILES.in0000644000015600001650000000067212653650644023623 0ustar pbuserpbgroup00000000000000data/credentials-preferences.desktop.in.in data/unity-credentials-panel.desktop.in.in src/cc-credentials-account-details-page.vala src/cc-credentials-accounts-model.vala src/cc-credentials-accounts-page.vala src/cc-credentials-application.vala src/cc-credentials-applications-model.vala src/cc-credentials-authorization-page.vala src/cc-credentials-providers-model.vala src/cc-credentials-providers-page.vala libaccount-plugin/oauth-plugin.c gnome-control-center-signon-0.1.8+16.04.20160201/Makefile.am0000644000015600001650000004055612653650644023471 0ustar pbuserpbgroup00000000000000SUBDIRS = help po DISTCHECK_CONFIGURE_FLAGS = \ --enable-gtk-doc \ --enable-introspection=yes \ --with-unity-control-center # libaccount-plugin. lib_LTLIBRARIES = libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la libaccount_plugin_@LIBACCOUNT_PLUGIN_API_VERSION@_la_CPPFLAGS = \ -include $(top_builddir)/config.h \ -DLIBACCOUNT_PLUGIN_DIR=\"$(LIBACCOUNT_PLUGIN_DIR)\" \ -DG_LOG_DOMAIN=\"account-plugin\" \ $(LIBACCOUNT_PLUGIN_CFLAGS) \ $(WARN_CFLAGS) libaccount_plugin_@LIBACCOUNT_PLUGIN_API_VERSION@_la_LIBADD = \ $(LIBACCOUNT_PLUGIN_LIBS) libaccount_plugin_@LIBACCOUNT_PLUGIN_API_VERSION@_la_LDFLAGS = \ -version-info $(LIBACCOUNT_PLUGIN_SO_VERSION) \ -export-symbols-regex '^ap_' libaccount_plugin_@LIBACCOUNT_PLUGIN_API_VERSION@_la_SOURCES = \ libaccount-plugin/application-plugin.c \ libaccount-plugin/client.c \ libaccount-plugin/oauth-plugin.c \ libaccount-plugin/plugin.c libaccount_plugin_includedir = $(includedir)/libaccount-plugin libaccount_plugin_include_HEADERS = \ libaccount-plugin/account-plugin.h \ libaccount-plugin/application-plugin.h \ libaccount-plugin/client.h \ libaccount-plugin/oauth-plugin.h \ libaccount-plugin/plugin.h \ libaccount-plugin/module.h vapidir = $(datadir)/vala/vapi dist_vapi_DATA = libaccount-plugin/AccountPlugin.vapi pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libaccount-plugin/account-plugin.pc # Credentials control center applet. cappletname = credentials if WITH_UNITY_CONTROL_CENTER ccpanelsdir = $(CCPANELDIR) ccpanels_LTLIBRARIES = libcredentials.la endif common_cppflags = \ $(CREDENTIALS_PANEL_CFLAGS) \ -include $(top_builddir)/config.h \ -DG_LOG_DOMAIN=\"\$(cappletname)-cc-panel\" \ -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \ -DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \ $(WARN_CFLAGS) libcredentials_la_CPPFLAGS = \ $(common_cppflags) VALAFLAGS = \ --vapidir $(top_srcdir)/src \ --vapidir $(top_srcdir)/libaccount-plugin \ --pkg config \ --pkg AccountPlugin \ --pkg libaccounts-glib \ --pkg assertions \ --pkg posix \ --pkg signon \ --pkg gtk+-3.0 \ --pkg gmodule-2.0 common_vala_sources = \ src/cc-credentials-account-applications-model.vala \ src/cc-credentials-account-details-page.vala \ src/cc-credentials-accounts-model.vala \ src/cc-credentials-accounts-page.vala \ src/cc-credentials-applications-model.vala \ src/cc-credentials-authorization-page.vala \ src/cc-credentials-login-capture.vala \ src/cc-credentials-preferences.vala \ src/cc-credentials-providers-model.vala \ src/cc-credentials-providers-page.vala \ src/cc-webcredentials-indicator.vala libcredentials_la_SOURCES = \ $(common_vala_sources) \ src/cc-credentials-panel.c libcredentials_la_LIBADD = \ $(CREDENTIALS_PANEL_LIBS) \ libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la libcredentials_la_LDFLAGS = \ -export_dynamic \ -avoid-version \ -module \ -no-undefined \ -export-symbols-regex '^g_io_module_(load|unload)' if ENABLE_STANDALONE_PREFERENCES bin_PROGRAMS = credentials-preferences else !ENABLE_STANDALONE_PREFERENCES noinst_PROGRAMS = credentials-preferences if WITH_UNITY_CONTROL_CENTER preferences_ldadd = libcredentials.la endif endif online-accounts-preferences: online-accounts-preferences.in Makefile $(AM_V_GEN)$(SED) -e "s|\@DESKTOPDIR\@|$(desktopdir)|" $< > $@ $(AM_V_at)chmod +x $@ bin_SCRIPTS = \ online-accounts-preferences credentials_preferences_CPPFLAGS = \ $(common_cppflags) credentials_preferences_SOURCES = \ $(common_vala_sources) \ src/cc-credentials-application.vala credentials_preferences_LDADD = \ $(CREDENTIALS_PANEL_LIBS) \ libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la \ $(preferences_ldadd) # Account update tool for enabling new services libexec_PROGRAMS = update-accounts update_accounts_CPPFLAGS = \ -include $(top_builddir)/config.h \ $(UPDATE_ACCOUNTS_CFLAGS) \ $(WARN_CFLAGS) update_accounts_SOURCES = \ tools/update-accounts.c update_accounts_LDADD = \ $(UPDATE_ACCOUNTS_LIBS) # Tests. tests/test-control-center.sh: Makefile $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ echo "for testcase in $(tests_nodbus)" >> $@; \ echo "do" >> $@; \ echo " $(XVFB_RUN) --auto-servernum -- $(DBUS_TEST_RUNNER) --task=$(top_builddir)/\$$testcase || exit 1" >> $@; \ echo "done" >> $@; \ chmod +x $@ tests_nodbus = \ tests/test-account-applications-model \ tests/test-account-details-page \ tests/test-accounts-model \ tests/test-accounts-page \ tests/test-applications-model \ tests/test-authorization-page \ tests/test-preferences \ tests/test-providers-model \ tests/test-providers-page tests_dbus = \ tests/test-account-plugin if CREDENTIALS_ENABLE_TESTS check_PROGRAMS = \ $(tests_nodbus) \ $(tests_dbus) dist_check_SCRIPTS = \ tests/test-account-plugin.sh check_SCRIPTS = \ tests/test-control-center.sh endif if WITH_UNITY_CONTROL_CENTER tests_ldadd = \ $(CREDENTIALS_PANEL_LIBS) \ libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la \ libcredentials.la else !WITH_UNITY_CONTROL_CENTER tests_ldadd = \ $(CREDENTIALS_PANEL_LIBS) \ libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la endif tests_test_account_applications_model_SOURCES = \ $(common_vala_sources) \ tests/test-account-applications-model.vala tests_test_account_applications_model_CPPFLAGS = \ $(common_cppflags) tests_test_account_applications_model_LDADD = \ $(tests_ldadd) tests_test_account_details_page_SOURCES = \ $(common_vala_sources) \ tests/test-account-details-page.vala tests_test_account_details_page_CPPFLAGS = \ $(common_cppflags) tests_test_account_details_page_LDADD = \ $(tests_ldadd) tests_test_accounts_model_SOURCES = \ $(common_vala_sources) \ tests/test-accounts-model.vala tests_test_accounts_model_CPPFLAGS = \ $(common_cppflags) tests_test_accounts_model_LDADD = \ $(tests_ldadd) tests_test_accounts_page_SOURCES = \ $(common_vala_sources) \ tests/test-accounts-page.vala tests_test_accounts_page_CPPFLAGS = \ $(common_cppflags) tests_test_accounts_page_LDADD = \ $(tests_ldadd) tests_test_applications_model_SOURCES = \ $(common_vala_sources) \ tests/test-applications-model.vala tests_test_applications_model_CPPFLAGS = \ $(common_cppflags) tests_test_applications_model_LDADD = \ $(tests_ldadd) tests_test_authorization_page_SOURCES = \ $(common_vala_sources) \ tests/test-authorization-page.vala tests_test_authorization_page_CPPFLAGS = \ $(common_cppflags) tests_test_authorization_page_LDADD = \ $(tests_ldadd) tests_test_preferences_SOURCES = \ $(common_vala_sources) \ tests/test-preferences.vala tests_test_preferences_CPPFLAGS = \ $(common_cppflags) tests_test_preferences_LDADD = \ $(tests_ldadd) tests_test_providers_model_SOURCES = \ $(common_vala_sources) \ tests/test-providers-model.vala tests_test_providers_model_CPPFLAGS = \ $(common_cppflags) tests_test_providers_model_LDADD = \ $(tests_ldadd) tests_test_providers_page_SOURCES = \ $(common_vala_sources) \ tests/test-providers-page.vala tests_test_providers_page_CPPFLAGS = \ $(common_cppflags) tests_test_providers_page_LDADD = \ $(tests_ldadd) tests_test_account_plugin_SOURCES = \ $(common_vala_sources) \ libaccount-plugin/oauth-plugin.c \ tests/test-account-plugin.vala tests_test_account_plugin_CPPFLAGS = \ $(common_cppflags) \ -DBUILDING_UNIT_TESTS tests_test_account_plugin_LDADD = \ $(CREDENTIALS_PANEL_LIBS) \ libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la if CREDENTIALS_ENABLE_TESTS TESTS_ENVIRONMENT = \ MALLOC_CHECK_=2 \ MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) \ ACCOUNTS=/tmp \ AG_APPLICATIONS=$(top_srcdir)/tests/data \ AG_SERVICES=$(top_srcdir)/tests/data \ AG_SERVICE_TYPES=$(top_srcdir)/tests/data \ AG_PROVIDERS=$(top_srcdir)/tests/data \ AG_DEBUG=all \ G_DEBUG=gc-friendly \ G_MESSAGES_DEBUG=all \ G_SLICE=always-malloc,debug-blocks \ SSO_LOGGING_LEVEL=2 \ SSO_STORAGE_PATH="/tmp" \ SSO_DAEMON_TIMEOUT=5 \ SSO_IDENTITY_TIMEOUT=5 \ SSO_AUTHSESSION_TIMEOUT=5 \ SSO_EXTENSIONS_DIR="/non/existing/path" \ UBUNTU_MENUPROXY="" TESTS = \ $(dist_check_SCRIPTS) \ $(check_SCRIPTS) # test-report: run tests and generate report. # perf-report: run tests with -m perf and generate report. # full-report: like test-report: with -m perf and -m slow. test-report perf-report full-report: $(check_PROGRAMS) $(AM_V_at)test -z "$(check_PROGRAMS)" || { \ case $@ in \ test-report) test_options="-k";; \ perf-report) test_options="-k -m=perf";; \ full-report) test_options="-k -m=perf -m=slow";; \ esac ; \ $(TESTS_ENVIRONMENT) $(GTESTER) --verbose $$test_options -o test-log.xml $(tests_nodbus) ; \ if test -d "$(top_srcdir)/.bzr" ; then \ REVISION=`bzr revision-info` ; \ else \ REVISION=$(PACKAGE_VERSION) ; \ fi ; \ echo '' > $@.xml ; \ echo '' >> $@.xml ; \ echo '' >> $@.xml ; \ echo ' $(PACKAGE_NAME)' >> $@.xml ; \ echo ' $(PACKAGE_VERSION)' >> $@.xml ; \ echo " $$REVISION" >> $@.xml ; \ echo '' >> $@.xml ; \ sed '1,1s/^?]*?>//' < test-log.xml >> $@.xml ; \ rm test-log.xml ; \ echo >> $@.xml ; \ echo '' >> $@.xml ; \ $(GTESTER_REPORT) --version 2>/dev/null 1>&2 ; test "$$?" != 0 || $(GTESTER_REPORT) $@.xml >$@.html ; \ } else # !CREDENTIALS_ENABLE_TESTS test: echo "Test run disabled due to the lack of GLib testing utilities" endif noinst_test_data = \ tests/data/e-mail.service-type \ tests/data/Gallery.application \ tests/data/Mailer.application \ tests/data/MyProvider.provider \ tests/data/MyService2.service \ tests/data/MyService.service \ tests/data/OtherService.service # Code coverage reporting. if CREDENTIALS_ENABLE_COVERAGE # Depend on full-report so that all the tests are run. lcov: full-report $(AM_V_at)$(LCOV) --base-directory $(top_builddir) \ --directory $(top_builddir)/libaccount-plugin \ --directory $(top_builddir)/src --capture \ --output-file credentials-lcov.info --test-name CREDENTIALS \ --no-checksum --compat-libtool $(AM_V_at)LANG=C $(LCOV_GENHTML) --prefix $(top_builddir) \ --output-directory credentials-lcov \ --title "Credentials code coverage" --legend --show-details \ credentials-lcov.info lcov-clean: $(AM_V_at)$(LCOV) --directory $(top_builddir) -z $(AM_V_at)rm -rf credentials-lcov.info credentials-lcov $(AM_V_at)find -name '*.gcda' -delete else # !CREDENTIALS_ENABLE_COVERAGE lcov: $(AM_V_at)echo "Code coverage reporting not available" lcov-clean: $(AM_V_at)rm -rf credentials-lcov.info credentials-lcov $(AM_V_at)find -name '*.gcda' -delete endif @INTLTOOL_DESKTOP_RULE@ desktopdir = $(datadir)/applications if WITH_UNITY_CONTROL_CENTER if ENABLE_STANDALONE_PREFERENCES desktop_in_files = \ data/credentials-preferences.desktop.in \ data/unity-credentials-panel.desktop.in \ data/update-accounts.desktop.in else !ENABLE_STANDALONE_PREFERENCES desktop_in_files = \ data/unity-credentials-panel.desktop.in \ data/update-accounts.desktop.in endif else !WITH_UNITY_CONTROL_CENTER if ENABLE_STANDALONE_PREFERENCES desktop_in_files = \ data/credentials-preferences.desktop.in \ data/update-accounts.desktop.in else !ENABLE_STANDALONE_PREFERENCES desktop_in_files = \ data/update-accounts.desktop.in endif endif desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) data/update-accounts.desktop: data/update-accounts.desktop.in $(AM_V_GEN)$(SED) -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@ dbus_servicedir = $(datadir)/dbus-1/services dbus_service_in_files = data/com.canonical.webcredentials.capture.service.in dbus_service_DATA = $(dbus_service_in_files:.service.in=.service) service_executable = $(bindir)/online-accounts-preferences data/com.canonical.webcredentials.capture.service: data/com.canonical.webcredentials.capture.service.in $(AM_V_GEN)$(SED) -e "s|\@SERVICE_EXECUTABLE\@|$(service_executable)|" $< > $@ iconthemedir = $(datadir)/icons/hicolor credentialsicon = credentials-preferences.png icon16dir = $(iconthemedir)/16x16/apps icon22dir = $(iconthemedir)/22x22/apps icon24dir = $(iconthemedir)/24x24/apps icon32dir = $(iconthemedir)/32x32/apps icon48dir = $(iconthemedir)/48x48/apps icon64dir = $(iconthemedir)/64x64/apps icon128dir = $(iconthemedir)/128x128/apps dist_icon16_DATA = icons/16x16/$(credentialsicon) dist_icon22_DATA = icons/22x22/$(credentialsicon) dist_icon24_DATA = icons/24x24/$(credentialsicon) dist_icon32_DATA = \ icons/32x32/$(credentialsicon) \ icons/32x32/credentials-add-account.png dist_icon48_DATA = icons/48x48/$(credentialsicon) dist_icon64_DATA = icons/64x64/$(credentialsicon) dist_icon128_DATA = icons/128x128/$(credentialsicon) update_icon_cache = gtk-update-icon-cache --ignore-theme-index --force $(iconthemedir) install-data-hook: install-update-icon-cache uninstall-hook: uninstall-update-icon-cache install-update-icon-cache: $(AM_V_at)$(POST_INSTALL) test -n "$(DESTDIR)" || $(update_icon_cache) uninstall-update-icon-cache: $(AM_V_at)$(POST_UNINSTALL) test -n "$(DESTDIR)" || $(update_icon_cache) # Gtk-doc. gtkdoc_builddir = $(top_builddir)/doc/account-plugin gtkdoc_distdir = $(top_distdir)/doc/account-plugin gtkdoc_srcdir = $(top_srcdir)/doc/account-plugin all-local: cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) all check-local: test cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) check clean-local: lcov-clean cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) clean find -name '*.gcno' -delete distclean-local: cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) distclean docs: $(lib_LTLIBRARIES) cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) docs install-data-local: cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) install-data uninstall-local: cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) uninstall dist-hook: bzr-changelog-hook $(MKDIR_P) $(gtkdoc_distdir) cp $(gtkdoc_srcdir)/Makefile.am $(gtkdoc_srcdir)/Makefile.in $(gtkdoc_distdir) cd $(gtkdoc_builddir) && $(MAKE) $(AM_MAKEFLAGS) \ distdir="../../$(gtkdoc_distdir)" \ top_distdir="../../$(top_distdir)" \ dist-hook bzr-changelog-hook: Makefile $(AM_V_at)cd $(top_srcdir) && \ if $(top_srcdir)/build-aux/missing --run bzr log \ --gnu-changelog > .ChangeLog.tmp; \ then mv -f .ChangeLog.tmp "$(top_distdir)/ChangeLog"; \ else rm -f .ChangeLog.tmp; exit 1; fi dist_noinst_SCRIPTS = \ autogen.sh dist_noinst_DATA = \ $(dbus_service_in_files) \ $(gtkdoc_srcdir)/account-plugin-docs.xml \ $(gtkdoc_srcdir)/account-plugin-sections.txt \ $(gtkdoc_srcdir)/version.xml.in \ $(noinst_test_data) \ COPYING.LGPL \ gtk-doc.make \ intltool-extract.in \ intltool-merge.in \ intltool-update.in \ online-accounts-preferences.in \ src/config.vapi \ src/assertions.vapi \ src/signon.vapi CLEANFILES = \ $(dbus_service_DATA) \ $(desktop_in_files) \ $(desktop_DATA) \ tests/test-control-center.sh DISTCLEANFILES = \ doc/account-plugin/version.xml \ intltool-extract \ intltool-merge \ intltool-update \ po/.intltool-merge-cache MAINTAINERCLEANFILES = \ build-aux/compile \ build-aux/config.guess \ build-aux/config.sub \ build-aux/depcomp \ build-aux/install-sh \ build-aux/ltmain.sh \ build-aux/missing \ aclocal.m4 \ config.h.in # libaccount-plugin introspection. -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) if HAVE_INTROSPECTION introspection_sources = \ libaccount-plugin/account-plugin.h \ libaccount-plugin/application-plugin.c \ libaccount-plugin/application-plugin.h \ libaccount-plugin/client.c \ libaccount-plugin/client.h \ libaccount-plugin/module.h \ libaccount-plugin/oauth-plugin.c \ libaccount-plugin/oauth-plugin.h \ libaccount-plugin/plugin.c \ libaccount-plugin/plugin.h AccountPlugin-1.0.gir: libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la AccountPlugin_1_0_gir_INCLUDES = \ Accounts-1.0 \ GObject-2.0 \ Gtk-3.0 AccountPlugin_1_0_gir_SCANNERFLAGS = \ --identifier-prefix=Ap \ --symbol-prefix=ap \ --c-include="libaccount-plugin/account-plugin.h" \ --warn-all AccountPlugin_1_0_gir_CFLAGS = $(LIBACCOUNT_PLUGIN_CFLAGS) AccountPlugin_1_0_gir_LIBS = libaccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@.la AccountPlugin_1_0_gir_FILES = $(introspection_sources) INTROSPECTION_GIRS += AccountPlugin-1.0.gir girdir = $(datadir)/gir-1.0 gir_DATA = $(INTROSPECTION_GIRS) typelibdir = $(libdir)/girepository-1.0 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) CLEANFILES += $(gir_DATA) $(typelib_DATA) endif .PHONY: bzr-changelog-hook .PHONY: docs .PHONY: install-update-icon-cache uninstall-update-icon-cache .PHONY: test test-report perf-report full-report .PHONY: lcov lcov-clean gnome-control-center-signon-0.1.8+16.04.20160201/help/0000755000015600001650000000000012653651300022341 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/help/Makefile.am0000644000015600001650000000034612653650644024412 0ustar pbuserpbgroup00000000000000@YELP_HELP_RULES@ HELP_ID = web-credentials HELP_FILES = \ index.page \ introduction.page \ add-account.page \ disable-account.page \ http-warning.page \ legal-notice.page \ remove-account.page \ supported-services.page gnome-control-center-signon-0.1.8+16.04.20160201/help/C/0000755000015600001650000000000012653651300022523 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/help/C/supported-services.page0000644000015600001650000000215412653650644027243 0ustar pbuserpbgroup00000000000000 David King david.king@canonical.com 2012 Canonical Ltd. 2012

Creative Commons Attribution-ShareAlike 3.0

Find out which online service providers are supported by Online Accounts.
Supported online services Online services supported by <app>Online Accounts</app> Google

Google Docs lens for Unity.

Facebook

gnome-control-center-signon-0.1.8+16.04.20160201/help/C/http-warning.page0000644000015600001650000000455112653650644026022 0ustar pbuserpbgroup00000000000000 Alberto Mardegan alberto.mardegan@canonical.com 2013 Canonical Ltd. 2013

Creative Commons Attribution-ShareAlike 3.0

Explanation of the HTTP security warning.
Sites using insecure connections

When performing the web-based authentication, you might be warned of a security risk caused by the use of an insecure connection.

Meaning of the security warning Security warning

Web-based authentications usually require the user to enter personal indentification information, such as a username and password. The information is then transmitted to the authenticating website over an encrypted connection, which guarantees that the information provided won't be accessible to other, potentially malicious, third parties.

Sometimes an encrypted connection cannot be established; this can happen when the site itself does not implement all the requirements for setting up such a channel, or when your internet connection does not allow the transmission of encrypted data.

If you fully trust the internet connection you are using, there's a good chance that the warning is shown because the website itself doesn't support the encrypted channel, and in this case the associated security risk is relatively low. If, on the other hand, you cannot trust your internet provider or if you are using a public wireless network (also known as WLAN or WI-FI), there's a higher risk that a malicious third party could steal your account information.

In particular, if you start seeing this warning when authenticating to a website for which you have previously never seen such a warning, it's highly recommended that you don't continue with the authentication and press the Cancel button instead.

gnome-control-center-signon-0.1.8+16.04.20160201/help/C/remove-account.page0000644000015600001650000000325212653650644026324 0ustar pbuserpbgroup00000000000000 David King david.king@canonical.com 2012 Canonical Ltd. 2012

Creative Commons Attribution-ShareAlike 3.0

Remove your online accounts from Online Accounts.
Remove an online account

Remove your account from Online Accounts if you no longer wish to use it in your applications.

Accounts which are removed from Online Accounts are not deleted from the provider, so you can still use them with other applications.

Open System Settings from the system menu.

Select the Online Accounts panel.

Select the account that you wish to remove. Details for the account will be shown, including applications which can make use of it.

Click the Remove account button and a confirmation dialog will be displayed.

Click the Remove button if you want to remove the account, or the Cancel button if you do not.

gnome-control-center-signon-0.1.8+16.04.20160201/help/C/index.page0000644000015600001650000000176312653650644024511 0ustar pbuserpbgroup00000000000000 David King david.king@canonical.com 2012 Canonical Ltd. 2012

Creative Commons Attribution-ShareAlike 3.0

A single way to store and manage your login details for a variety of online services.
Online Accounts <!-- TODO: Add image. <media type="image" mime="image/png" src="figures/online-accounts.png" width="40" height="40"> </media> -->
Main features
Additional information
gnome-control-center-signon-0.1.8+16.04.20160201/help/C/legal-notice.page0000644000015600001650000000711312653650644025740 0ustar pbuserpbgroup00000000000000 David King david.king@canonical.com 2012 Canonical Ltd. 2012

Creative Commons Attribution-ShareAlike 3.0

Important information about Online Accounts.
Legal notice

Ubuntu Online Accounts is provided by Canonical Group Limited (Canonical). This Ubuntu Online Accounts legal notice applies to your use of Ubuntu Online Accounts and incorporates the terms of Canonical's legal notice (and privacy policy).

Collection and use of credential information

You provide Ubuntu Online Accounts with your name and password(s) (credentials) for those online services you want Ubuntu Online Accounts to authenticate while using Ubuntu.

Ubuntu Online Accounts collects and stores your credentials when you enter them in the web authentication dialog and uses them, and authentication cookies, to provide authentication to those online services each time you access them while using Ubuntu.

By using Ubuntu Online Accounts you consent to:

the collection and use of your credentials in this way;

the use of authentication cookies; and

the storage of your credentials and the authentication cookies on your Ubuntu computer.

Canonical will not access or use your credentials or authentication cookies in any other way.

Ceasing use

You may cease using Ubuntu Online Accounts at any time. If you cease using Ubuntu Online Accounts, or wish to cease using it for certain online services, please ensure that you have removed all of your credentials from the “Online Accounts†entry of your Ubuntu System Settings.

Changes

Although most changes are likely to be minor, Canonical may change this legal notice from time to time, and at Canonical's sole discretion. Please check this page from time to time for any changes to this legal notice as we will not be able to notify you directly.

How to contact us

Please submit any questions or comments about Ubuntu Online Accounts or this legal notice by contacting us at the following address: Canonical Group Ltd, 5th Floor, Blue Fin Building, 110 Southwark Street, London, England, SE1 0SU.

gnome-control-center-signon-0.1.8+16.04.20160201/help/C/disable-account.page0000644000015600001650000000312712653650644026433 0ustar pbuserpbgroup00000000000000 David King david.king@canonical.com 2012 Canonical Ltd. 2012

Creative Commons Attribution-ShareAlike 3.0

Disable your online accounts for use in Online Accounts.
Disable an online account

Disable your account from Online Accounts if you temporarily do not want to use it in your applications.

Open System Settings from the system menu.

Select the Online Accounts panel.

Select the account that you wish to disable. Details for the account will be shown, including applications which can make use of it.

Click the enabled switch and the account will then be disabled immediately. The icon and description for the account in the list on the left will go translucent to show that it has been disabled. Clicking the switch again will enable the account.

gnome-control-center-signon-0.1.8+16.04.20160201/help/C/introduction.page0000644000015600001650000000155512653650644026122 0ustar pbuserpbgroup00000000000000 David King david.king@canonical.com 2012 Canonical Ltd. 2012

Creative Commons Attribution-ShareAlike 3.0

Introduction to Online Accounts.
Introduction

Online Accounts provides a single way to store and manage your login details with a variety of online services; enter your details once and they are used across your desktop.

gnome-control-center-signon-0.1.8+16.04.20160201/help/C/add-account.page0000644000015600001650000000347512653650644025566 0ustar pbuserpbgroup00000000000000 David King david.king@canonical.com 2012 Canonical Ltd. 2012

Creative Commons Attribution-ShareAlike 3.0

Setup your online accounts with Online Accounts.
Add an online account

Online Accounts provides a single way to store and manage your login details for a variety of online services.

Open System Settings from the system menu.

Select the Online Accounts panel.

Select Add account….

Select the account provider for the online account that you want.

Use the drop-down list at the top of the panel to filter the list of providers by application.

Follow the instructions to enter your login details. This normally involves entering your username and password.

If the authentication process was successful, you will be returned to the Online Accounts panel and the account will be ready to use. Launch a supporting application to test your account.

gnome-control-center-signon-0.1.8+16.04.20160201/tools/0000755000015600001650000000000012653651300022551 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/tools/update-accounts.c0000644000015600001650000000575612653650644026043 0ustar pbuserpbgroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Alberto Mardegan */ #include #include #include #include /* Check if new services have been installed for this account and, if so, * enable them. */ static void update_account (AgAccount *account, GError **error) { GList *service_list, *iter; gboolean account_changed = FALSE; service_list = ag_account_list_services (account); for (iter = service_list; iter != NULL; iter = g_list_next (iter)) { AgService *service = iter->data; AgSettingSource from; ag_account_select_service (account, service); /* To determine whether the service is new, we retrieve the "enabled" * flag as a setting: if it comes from the account, then the service * has been previously used on this account; otherwise, it's a new * service and we should enable it. */ ag_account_get_variant (account, "enabled", &from); if (from != AG_SETTING_SOURCE_ACCOUNT) { ag_account_set_enabled (account, TRUE); account_changed = TRUE; } } if (account_changed) { ag_account_store_blocking (account, error); } } int main (int argc, char **argv) { AgManager *manager; GList *account_list, *iter; #if !GLIB_CHECK_VERSION (2, 35, 1) g_type_init (); #endif manager = ag_manager_new (); account_list = ag_manager_list (manager); for (iter = account_list; iter != NULL; iter = g_list_next (iter)) { AgAccountId account_id; AgAccount *account; GError *error = NULL; account_id = GPOINTER_TO_UINT (iter->data); account = ag_manager_load_account (manager, account_id, &error); if (G_UNLIKELY (error != NULL)) { g_warning ("Could not load account %d: %s", account_id, error->message); g_clear_error (&error); continue; } update_account (account, &error); if (G_UNLIKELY (error != NULL)) { g_warning ("Could not update account %d: %s", account_id, error->message); g_clear_error (&error); continue; } } ag_manager_list_free (account_list); g_object_unref (manager); return EXIT_SUCCESS; } gnome-control-center-signon-0.1.8+16.04.20160201/COPYING0000644000015600001650000010451312653650644022462 0ustar pbuserpbgroup00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . gnome-control-center-signon-0.1.8+16.04.20160201/AUTHORS0000644000015600001650000000020312653650644022466 0ustar pbuserpbgroup00000000000000Alberto Mardegan Alvaro Lopez Ortega David King gnome-control-center-signon-0.1.8+16.04.20160201/icons/0000755000015600001650000000000012653651300022524 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/icons/64x64/0000755000015600001650000000000012653651300023317 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/icons/64x64/credentials-preferences.png0000644000015600001650000002003012653650644030626 0ustar pbuserpbgroup00000000000000‰PNG  IHDR@@ªiqÞsBIT|dˆ pHYsììu85tEXtSoftwarewww.inkscape.org›î<•IDATxœí›y”œWyæ÷~[­]Ý]½·¶Öb-Þ°llÀ8¶c–@ØB0 `'“0LÄÀ02 93I2ä„É ÛÆ&f3v0Ø`¼`[6²ld!Y²d-­n©Õ{mßz—ù£ªÛmK&@øc¦úÜóÕ×Uç«û<÷y—ûÞ{…µ–ÿ—_òÝ_ôëÿð‹îÀ/úåþküÈÆßøÀ5Jë×Ï]'Œ¬ZUQQ7iÖcA8vŽ \sË=­j1³™~¢§ÐuëßxÇÖòsuRâçá¯þ7ŸÏ•F’÷vw—~«ÖJViI^‡ Fú¨]Ÿåð\‹Bàrtr›ÆHÏÅæJX«16£àX y?ZSÎMW{ûwÌØÉß½éÝïŽ~Ö}ý™põÛ?Þ7¶nà»[Öõ]0Öß+æ˜I$].ì:|‚ =^|ñù8Aבä¸ù¾GøÆ£a¹z]‰“-ZqŠFàKM¿§t#^|ñv»ëÈÉ'&gë¿õñwüYõùgBÀ;¿üåR:®ïX;Òÿ‚-kFÅH%`f¾Fª ¿tÑ9|àóßᑇ *Šßåå¤Ê … søöðµG§ nb‰‘¤‡ÉY[-ÑHYÜâ]—rd:æÄìœÕÆìíß0z凯}ÙüOÛ÷ŸÚüÖŸ|ú7oZÝàùý¢¿\ÄD5âVÆþC‡™–]l?'æP]á%^»½—œçø¾+i“Œ/âyd–bŒÇÃäK\0RàmWKœd˜,dÏþƒôTúRŠ4NÎ õÙë?ðWÿç ö®ëšþÿ‹ >rûÖÜÑ'Îß¶ul´»—Ãïâ›'ˆ/Ùy÷ªê¾Uë¥ï:TË9šOW9Gà:䋲4å‰ý?¢ÑhÐÓ]a¡ã¹%|+q­iƒwŒpB¢A*X •ìÙÑ¢`ÒàׯxŸüÎndö0a«ÅêÑ.Þþ]Ç KF´8YBw¥‹=ûö108"6v—ö­{ÞkŽþð––ÂæÙˆxNsß~¢¶ÓúM…¼çQÎû4f'éï­€Ñr.®”ä}Ébæð•p-ÝC«¥nr® çJÏÅ\\ßà <<ßÅñ]¤ëà¸W \ÇáÑñÏ¥`#n¸ý>Þråó¸ðùW°í¢°ÐÒ|ý–Û8zô›Võâ©3˜9ö÷ÝKýä~6®dÏã{i5¼«ù’#@ÈžÂBˆÓ÷Ç™À>ð7wÅ /}{o©B>pé-ôä,¥2úûÙ»oåR‰£3u¾5®X8ö8ëª%Lï:r&ÁíŒhé`(cPIJ–$¨4#‰R §X-yÕ ·ÑH ^¸\±‚RŠV³É¡ý{9~ô å@±zízúWñäž;éë©0ºþzúW#¤Ãää;wâ–ïÝÿ­Û¿ô÷ÿ¨- ôJ5œ•€?ÿÂÍUívͬëRÌy”ó•R@OÑgjò8÷ïÜÅ÷jý¸“]Uº»º\×xÂàJ R`¤@#ÐB¢‘hcIÓŒ,ŽQq‚ŽâV‹ùùÖå"®½æ,‚þ‘µH×ãÑ? Dôq€ù…&ãS57½„žÞ>êõccc‹E\·mÕRJr¹iš{å+_ù›‡ê@¼’„³šÀøT}GWWU8Râ{×ÎàržÃCíà#_ÛÉz¤¡¯:D! $EWSr¡àK|ßÅ<|ÏÃó\<×Áq$Ò¸ŽÀu$Ž#Ââø>¥þ5lݺ™]íÃsG±ïnöïgPîCè„Ñuyíõ¤Ò]ejêq³wï^„äóyz{{éëë#Œ1k|ðÁûn¸á†ßz€<°lÏJÀÛþâ†sÖ¯_·©Z*’ó\r¾CΗsÍ…þá¡Yò…^rYL`3að¤Àu§mÛŽçâù®ëây.®×±{atš°kÛpÒ4¥R©på•W’$ 'Ožäá‡î%IÒ4%Š"èêê"Žc^ò’—üÑæÍ›×EÀÄ}À%¿÷{Þ¯<ÿW’ ƒâc·þ€‚ yåù£c¸ûTŽ¢€¢ç’ÏûmÓ<\O¶%î9øKÎwñüö玔$Æ’HŒ&Ëi¦Q™n;¨EÆd©"².IX£šœ`Uw‘$絕Ñ:£wý˰^/ÝÝÝÄqŒëºø¾O–e|æ3ŸÅ÷=æÇwpé‹^Âå×¼ ¨Õjø¾OOO³³³Xk§6oÞ|0 „gT@-xÓêÁAñïÞCÎÍ!*k 2Ìž…“&H#0í/;FJ¬ã ¤Ä < ……BR1G¡#Èò…œOÞp|×uq§­¤”H)pµÂ溩®ÛÆ—]Ì«·wc´¢6)õ¬Áó<¤”dYF.— IŒ5ÜûýûªÒ\<1†'žx‚™™jµFƒr¹L.—zÍk^³vxtΘ­èÿ×ZŽ˜*ž08B/Î0“ñ‰BbG`…ÀÀ…|ÞgÛœ[U UKt•ºÈ’&“G9zjž“ â—WãHIÝ€N3„5 Žh \ÞxùFŽ;†—†øA'?Œ±– ˆ¢ß÷‰ã˜(ŠÈårüòÕWRÖOÒ×Ûͯz+ÆV­ZE–eXkIÓÏóÐZó–·¼å7o¹å–Ç€Ö èÊ9çÎÍÎà•{ ¤ «RâÞé&žL‘Ê‚”X)1B „%p*ù<×ŒÔØÔ“°xêOî;Lka‚Be„b÷0›+ýl'¹óÀq¶¼ŒEÇ1J°t|‡ÒÅWM²LѨ×èqâXÑ=z ®ëb­EA†ø¾OWWFƒþþA~û>ŽëºÌÎÎâ¢1ÆP¯×QJÑßßOEÄqÌúõë/£ ÜÓL`ãkÞóKi’æ Åo¸ Ÿs+ jS¼î¼ 8Ö °®u )*%7¬§»q/ÜþIŽ=ÊbœÃÏa>t9|ô8;ï»™S㻹rÕ4ƒ>I BÊA€#@ Û¤9V ”¹îÊsQ¤ëÓj-Ò;°c ÖZÇannŽÉÉIÒ4ÅC´Z-æççÛ¦%%õzžžr¹Q‘eQQ©T†pOS@f“Wž˜m°fxO¾ºg× KÆVustÚE£Q¢íÑÝÀã…¹=ÔÝËÔ¢Ëú­/†p’ËÞø‰åg>pãÛˆ*Û8xtœ°1džÁ1&÷ßDéüë }4RXábü×_¶†\®ÀäÄ8žL±F“Å Æ´+¥ÈårlÙ²…Z­†‚jµÊøø8½½½”ËeÂ0$ CÇ¡Z­R,i4XkQJ‰¥(pšD¦W©ÌrÏÎrèÄ ¾ç#LÆÎSŠ‘²àõÛGˆóe´çc±|Qõ(S _¼‚lrìЮ¸ì¼N¢#hE‚56 q|ZS[8Å¥# ÂcR*äp‰2 ¸ôõõh›„Wè%jÖP:ãԉø®»ìçææRR.—IÓ”®®.„¤iÊâââÒHS(p‡S§NÑl6 ‚€éééSKxOV Ø4æá'OpîÆ1.í'˘«%ìØý${ví ßÏH¥‹çI.uïcòäIÖnÜFà æ¦O‘+Txë¯]@à9\vñ¹ä‹e4è&Õ¾~¦¦gɲ”ÑÅ{Èç|ÇÁÁ«/ÙB ¥ ð}¤p˜]Œ°V±÷‘;q€(ŠÐZ`Œ¡Ùl’¦)GŽY®ë¶ó )™Åq’$!ŸÏ³{÷îÝ€ôé 0  -Yáðá#<91*ÁÕ"Wå°XÃl=EFÕt;-¬?ÂH5Àñ|´±øùÿó3÷¸’wþÛk rü|!Ýù&¡Êc´f¤+£9?‹çI,p|b¸Žƒä &k9ÇN?F†cÐZc­eff†'N¦)år™sÏ=—ÑÑÑee¬Y³† ‚ :B¾ô¥/}HÏHŽ­b4V%ÌÖ›Ì#X'Àx9¬ë‚1¸*ÅÑ UfÐ*!ðsXÚ*_(á8n{àIææçñó%|Ï X‹kYšŸ<€ï9,“3óíQ’\.O¥»§kÒ èï+óäGBP¯×ñ<¾¾>Êå2ù|¾]\QŠz½NÇLOO/|ÌÎÎR(8~üøÌŽ; NW€U+6Óܵï8¯¿ ®*ï~ù9¼ç¥ëêïÅ8ÖqèŠO’¥1nàat†Îªýà öÇoblí7ÞtBxXÝÄvJXR€1)I¢PsGv>1Øßß¶ËŽ*•núûØ99D_ÿ ‡¹‘V³‚ééi¦§§™ššb~~žz½Îìì,Íf“8ŽÉ²Œ……&&&8~üxÛ̬åÚk¯ýc`¾CÀL@:BJ‰°óT¸óûðžpñ–1ÖVK¼ÿå¸öâQ6•Ȳ GJ²¸…ÊR²,Æq`xt]9Ãú5C¼ñ×^ŽŽO¢’:Öh¬1¤q )$i’‘¤™±X)éën×û„xžK©\¦pB©ŸÝ‡5½•<;îø4ÝÝÝtww“Ïç)‹äóy¤”!–3Lß÷ñ}Ÿ\.·<;üÓ¿ü;3;;{„v}àÌX×™3BbF¦ …uÌÍΑd†B¹›|±‹—_²…w½êùØ®µX¢°ÊbT‘¥R(Ò4bb|’«.éEÅó£0ZcŒFkƒÒ‚4ͰåU¤i†1š[ïÝÖ ¤À‘.ù|žÞ*Ã#£Œ×º |“GçËŸûh‡$Ïóž–é-e{Kï—Rçÿþ±¿ä[÷í S´ë)`N÷™·B€°Xc°X\ÏÇX‹6c,J°’7\õ"ÒÔ’D-T»>J#TÑ5ïø½76O UŠQFg­0âX“ÄÁðf²T!²ŒÝéñ÷_Àu„×u)–JôV«ôõ2Ó˜4ä·ßôßHÓöZÈÎ;Ù¿?sss<öØcË£Ñlò‡ïûÿ|ß#¸A¾ÌÒ®)Àž®É¼e-Ú•œ7\dÃúhmžþ=kéêécrÁ¡¿'ÇÑñ©ediÌ`%c¬:Îb´JÑ*C댉é&«GY˜86AO‰ÒX­pMÄ¡Ü9Üñï ¥Àq\‚ G¡X¤«R!p%ýÕ7¬¥§høäÿx/Y–R¯×±Öb­err)%Åb‘ïÝ}/ïÿП’$ ºA04h—ÆŒµöLÈi‹iQRrõú ‰Ò(mÁv9`,k©^t=‚< ‹5šÍæS*HãvË’vS a“i«æf™ê¿†ùVB¨Úy;IŠ—¶¸éI͇ÿ⯙™>ÉŽûïáŸo»v7_?§ƒ,¸=ø6¦Ú×M)HÐJ1Ô_!kxžG.—[ž'xž‡‚\z1ckW³¹BÈc<£D~†LP|M[Ñ6Kq¥D)ƒÒ§oÕXzÌ5oþ#¾ûà,CýCäò>Îràð ?9ÃGç9r¢EOu€¡þQºf<œËßÊt3¤¥ J´ãa#ݶÒ”J¥’¦µÈy)Žt÷ á;) ó-ÆÖV <‰çy €å" €‚—]ýb”ŸGÖz_…§Ã8€cßøÄÝJ«“¦è$涇~Hš)”6(e°+ÌÚËSù\ž·|à³<|r”铊þž!6ŽqÑÛ8gÃ&6lºŒf³‹<°ŸGš¯üM·@#µ(é`\ãy(×kß#ȬBëvÒ$fÛ°fh°B©«)q”QíëæG[&`I¾ï†!óéä«·~!]„W¨Øñåï=ïëÖ˜{­ŠÝ$-Žç˜š8Êêuc¤Jâ¹²cÄ’ ÚE‘7¾í}ì}ìa¾ÇW‰¦×s­™7Òâ(¬½žÂ† ™ 5‰Xé`…ƒ±«-Èv¢„#°Z`-h,*K)&¬­bU €ï îß×âð‰ë·xäóùe‚ àãÿëSLžlg"ȱ¦§kâ$§‰øÌ•~Mûë2 1YÈ}»áu㸎‹ï:m„í¥‹5íйõüíl»àŒm *Sì92É÷¶Xl†„ͤí‚+½Žš,¦Sè@vù/ÓŠ¡RŠŽ[Åu„ifç*En¾e’ó7-+ MSÇ!NRRr` œøþƒ÷sóý»©™ÅÕ[I«m¢½WÑVÖÖ´å1X£Ð*ÅÆ*jò‚Õ†¸ã{iMO07#}Ÿßùã/qhÆR*d+Âò’¦¦¦žè€—g#à9m‘±ÖZ›d¯0Yx\5963sj‚f+¤Vo±Xo«`¡Ö`±ÑàñSMZå xåAt}•DíÍYJ–&diL…¨$F¥)F¥X«±Ö`MÛùeqȹƒ†Þž"Â-xõZÄÐ@ÇN¶@ZYûû+ µ–ÅÅÅÚu×]÷Ñç‚í9Ÿ˜xèësÚšW«¨QOÃÿðQZÍ‹õ:µz“f+¤Õ yòàìØ?jÕQa4n‘¦1J'(•’©´=eN"TaÒ£5*Ë0J· '*AÅ-V—2‡Ê$qŒpÒ4a`d=¯¸|-Æj žC6VBÊåréúë¯ßÊSÓ–gÝ󘘼ÿ»-\nâæäá“ „YÂ0¤Õj‘„uŽø7ï¬SÄ$!:KQ&C«Œ,ËPY‚N#²$B%!:MÚ…’4Ád)*‹ÑiŒŠC† " )J4æOÐj¥t•¼Ò(ŽNa•e±ÑàøLƒgú7)¥óæ7¿ùß?L?ñ‰‘‰où‘·ÆiöÃû¸›†è,fvú${s<ΣšmÙk­:õ?…ÑY»pš¶k‡*IÐYҟƨ$DE-T¡£&/Zï’%)n©aBff›éð»ïû {7À*È2PðTX]zŸe™â)ûÿéœ`'„¸´×Ô}À^g.ý§zè¾—\}Å/±ëÐ8ûç5NRCk‹p]¤ h ëaUÍ1 …ÑN„5` :QQÄꮌÖæñ=‡(JqrEÜs?_ :#ç;û…[–€¤iš~âŸøøsÁvV„^tоÔÀ?yÿ×>dοrwi×;ÆÖ¬‘§OF!ƒ0.X…Ô LŠð|¬l¯!:©²àijµj×Óˆ/Þy’¿}ŒVs×õH¢˜Ë/¿‚ ·eß±&X³˜†‹_«l‰€NŸIÓ4}ôÑG›t–À9‹8#Bgð³¶S{î¹óÖ};~pÕ¯¾ácýn¾ï˜ÎaBeí¦S„ k/¦,gJ0fùÖZl–`²„#‹š/Ý;Ëë_(ÂÒW- EÍV”fQã¾Ú‰ƒ_Ek²ìE—ÂÓM X,–>õ©O½gûöíÐÞ”MÚ•à³ÐÙ8õl€ŸIJû^§îÝ·Üð‘|¹:6vÉU¯[ŒÒµë å"L†Ð88OW@;gÖbHgòh ƒp<>ýíqÖõJ…€¯ÝsÌÜõÁO6g&¿cuv´Ówqÿý÷OoÛ¶maûöí=+ç;ù|¾‹¶©.)6BkíÓÊÛ§m’ê°ôÌ€Ï|Ÿë°] ]#çœT‡·¹¥®a\ÏÇuŽƒ!VhÒÖ÷ÆJ¥²&MSæææŽ|ìcûë½{÷> œ ½Ñ% CÂs5ÿ ïs´m/¿ô¾8ºqCa`íf™Ë—Eàç®o¥ðÚ›ék5ZgVe©Í’PÇa3š?N]:¥;€;­A{ǧíŒrÐõÞ÷¾÷eÃÃÕ÷¿ÿýŸÉ²ìp¼CV­µ§™ÀY·Ê®p‚ËŽg8BžŠ ϼº+®+ÿçÒO+ST yR¬^q¿D@Fg;-í|¾d²ùÎïd´×þN3ÀgùçDÀYÈX t©­¼²9<•“¯¾2>¯ÌØÌŠ+«ê´´0íÜ/%WüFJÛáÕh«$ã,çþ処Úf²Úàg_9)Y9ò+ Xº®$`eSghYçÚ‰+8çhž"謇&~.'G;‰ÓØgŽü™ˆx&ð3pF +æùgR?îÄÈÿB¨ˆF\+è&IEND®B`‚gnome-control-center-signon-0.1.8+16.04.20160201/icons/32x32/0000755000015600001650000000000012653651300023305 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/icons/32x32/credentials-add-account.png0000644000015600001650000000142112653650644030500 0ustar pbuserpbgroup00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<ŽIDATX…ÅVANë0}±MSQºbù÷]røû¿DbÉ)Ør.Qé_õH,{‚f]!Çãù ä(‰[š´(ÿ­’Ø™y3óÆž$Ïó_Ƙ'w2ŒƒÀ_­õ“2Æ<Íçó‡Ùl†$IFñÎÌÙûûûÃv»…p§µFY–£8ÐZc»ÝÞ)ï}æœ-úç¼÷™bf0ó¨Î øýÿ†þ˜$ „õs0ÞûÁÁ ΀J)H)[߉UUÁ{ßËÎI%Râúúº&ADx{{CUU½mM 콸¸@š¦P·ð['e€™¡”ÂÙÙ€¯ ƒ qD„J „h­ Híc$ ¤”Ñ:@)¥TýÖºâdæV†šßoº@J‰ÉdRï“RÖká=MÓÈ–seYÂ98¨)%noo£L03f³Ym𦏹¹‰öV«U+â^š†æó9ÎÏÏ#rÍ=J)h­£=‘ÓˆÀÎÐh¦z(ºzØ…½%ßB}»èŠsŸŽÂZ×Ï·%`fxïQU–ËeäXJ‰ûû{dÙ×U–ËåNµ‡ã¹{D¡sÆ|~~¶œ‡zw»€ˆ`Œs.Št_~K€ˆ@D;S=N#ÌŒªª`­öïBo6 4¯ß¦6CNwáè˨›°Ö×ÞÉ·a7GhíóÁZ‹çççVI¬µ ¢A pD œs(ŠI’´0sÔ‡5zïa­íuõÁÑSñ©“t!sÜO"œ*Ïssuu¥û\? "BžçFm6›!ÄŸÅbÉd2Šsk-Öë56›Í‹’R>®×kõúúúÛ{ŸŽA@QfY¶º¼¼|üzÇNJ U‚IEND®B`‚gnome-control-center-signon-0.1.8+16.04.20160201/icons/32x32/credentials-preferences.png0000644000015600001650000000535112653650644030625 0ustar pbuserpbgroup00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î< fIDATX…¥—i]ÅuÇ}—·Î›}Ñhž¤‘-‘°l!#㨠f±²Ë€‰CY*—]ª²6Ù—/T%B!e§‚b>B0K± í0ZÌ‚S!•®:Õ]÷Ö=ÿ_÷ésú¶PJñYÛwÿìg•‘0¾çMgJ?èüïÿg€Gž|öW›nÙt_*•æÒ•>¾ùµ-œ9ßC8â;÷ÞÌÏŸÛÍ–/ÝLûñ‹Dk“t÷ö±®v|{;•1^x~7U‰ÃãÓªkpæâHÏùGÔÇ/ÀÃOî>»bÙògÎ_ais#­KÂ3+ÑdÀ]›WòrûäÔ{ð^ڼυºøÞךÉe§(ul¸¹cGñЃ¢/] NŸþÝëííí?UJu~*À£ñó·î¾û+Û~õ›Ã¤g<ÿYÑÂñ3—8;\@™¸ž¯`¼ï2…y•µIWöŸdÕÆí çhnn&N³k×.b±étš\yúé§<99yðÛw>µkûÛþuy²™úÊÙì4­É&l×#3gï‘ Dè:.×è:ÜN²ÜÉŸ?º_{‡Ûîû1[¶Þƒiš¼ñÆŒ£—?yâILÓ¤T*±wïÞkO<ñÄýJ©m^ü©§Ð6lÚð\²¹‰ªxˆXØ`YK¶írú|7¯þú$õÕ1bQbñ(‘X„H$Œ´2<üÕ$ç?覾u 6~™x®ëa{>–`{¶/±\—ºÊ_Ø´‰Ó=‚¯ßÞBo×»XV™H$B,#‘HPUUEmmíÂF|ûX'*Z¥/¤á{ç&^Ù÷6]}£|ÿÛwâZ%nŽÊr†âøÅt§ì`ÛŽãc¹³®/)–l¢ÑZ¨ŽxÔdã’¿õd24MCÓ4&&&Ð4Á¡a~ñúA:{S  ÀÐ"¡±±r°üµWÙ²*ö/.çîÛ¾@$¤S*Û<¿÷E+J % ¡::`ê&½c|iÃ4V¹€&LL nYpæÝ_s×¶ï ¥Ä²,lÛfht‚Êšz”6‰&ô̇…(i‰Ò9R¦³k€XÄD×uª++xì¾[it³hއæ»àû(%ñ¤Âl\Ì?üÛa¥"jb•þ µžìø%ŠÅ"A ”" QS£«gh6©OúçàûRÜÝö9”(¥hn¨áÑû·°˜ÖT <À—øJái9Û¦¥ÞR)FRCÙ8A,œ3étšÞþ!ÐAI‰ÚéßõéYEåÙ%«ÄÚ•IfõÕlqAQSçGßÉïÝ@¢0‰ïyøÂC0=5Âúe1r¹š¦q¨KcõúÍÀì‚ àüÅ+¼yj„BÙAª@Ò_\>ôbŸ_.t¹Ö ¾Sd*;ƒR 5Wñ”©¾T´&X\G’@JlסQ›¢¶Ò$—+£›)·f}¶Y–EÙ¸ŽEà{Eïð¡Wû>r¥ü?{¥BHþ}ï!ÄÚE±ˆ‰í¸½Ž2qgá[!Ò³ñ­ßÔîyÝ€þ#¯¼à3—íbžë¹»_ØeYHŬI…TP²=<ÝÄS_Jòc¬Oš¸®® RE GŸ­ýóÅb)}„ô¯ uìßó §\ú‰3“ñ<«Àå‘Iö¿sŠ™™®ë̆A*z‡ÆÁŒHA ödkšCär%¢Ñ·lÜ@v|Û¶otMf:JùJ7~tãó {õ`PÊÿ¥ŸÂ.d˜Ÿdpt‚É© ÓÓY^|ó /º@`8¾Ci:ÅŠÈ4qƒ™½Çú(ˆ£©…‡Ãì|ä[hRýõð{û~*@ßÑ_>ëó?³s)º{z¼>ÅÀ胣“|Ð3ˆ4BØå"v©@¶ÿ2kiDîëSQÕÀ±¥ F®O,øô}ŸÎ³Rƒï¿õÌÇõ>ÐÿÞ»¥üOtgLÀêRªùÖ3ÛLî|¸££c¨­­mYÄb±èÜ{çÆëÙÿz;žÛÆœ qÃXÄ;3;sx¨c¥%ü¥ßëG:ÿÿ9çïá>%¥ô<5üÊK¥rá`Àëë‹„Cm¡]½›Ï 1»¸6õõ‡·%‹«éÜ¥k3ÉDb1d÷®áù<:ôâ¯ú ¥ü_jmW?ßfŽ–Fr¥*¯¾1Jo`Ž'÷7Ó¹ëQÚ;{ð‚†áÆãñ‡‡‡Ÿ>þü5q/úÌ ?ÿ­×+.ùôÖ]GŽ¥uÇnÚ¶E8óá,¿?ýõyžÚçcߣÏÒº½‡¿½5“Ou._]]]=###ãýýýû??>ôã—ƒ~ÿ«uÚŸÿ¶”>ÞŸa©db—Ò<ö …¿åjŽ$—Ëq{:Aû•ÆÞ"—ËaYVàøñã'€ ðÝ—_ÛÓ ýlðkáÕT<ÀîŽfr–‹«iHW"eœlj‰m½[(‹|ç‰#ܹòý¾‡iš˜¦I$‰{U€°¦{äáѮë bÉ,7×ÐõzlU Ø[µÈd×ù‚Gò,:;»èë{‰|>O.—@UÕzŸÏ׬~zøèήö-;¶·!<þ~q†Å¼AD¡}‹k†áµYHL³%Ú@&“!“É|føÉd2kš¦­nݺíùööV$’s7\_Ê£7„°²»qo$Tµfu&oŽnŒòÿjlâÂ"pGm‡¿ôî¥iNŽÎñƒTGâØÂ#p—í{pã? ¶(³TJ«44µþº˜Jsft¢ ¤D(èúuø}*%ðk˜V²iS¬:”-ÓvèŠn¥ûCìØÅØ;Ç)×Ð4m3ñÄ<¿þÝY)Ëy1~åF©·;Ê@OŸT0ò%*Å*äTµ1L¯*hï褮.ÄÁ¾6Æþõ¼^/“““¸®Ë¹‰+¬¸_0 V …é?^gqµÈsGöð£oîcèÐN<†Aµd`VL »ÆítØtŒ¦z/ÂãÖŠ!B ¥äÙo bä–ñ(Ú-Q³­˜e•™Nçˆ6Õ£ª‚ÞŽ&†¾ÜCЩeá8eG’]žÆ¨šTmx憎EQ8?~‘~ú*¥rWcB:öE#—¡¹Þ^çGJ‰”’î–/%„m×(lÓ0ªZšü„š¢(Š‚„Ž·¾±¦(«ÿþ¶åˆ±ž^ÏÏ“^-âºàJ‰+%>MÅqjµk©íl Z©ðË—K›­°,›âÊ"®ë\H¼ÿ~@,}8²j­~ò“|&α¿Ž²²^øw%Ž+™Mç±j.º1Ôp“Žf/;zv£( Š¢P®Tª·¤)Úsw¯žX¸üÎo K³£ñ™)ÎŒ]g%›¥bT¸[ ]2±¤‡¾Æ fµŒOSpœñÄü&<øÕ¯`çRoÌ}ðfò.¬n~̦Ê%oÅ&õîhƒŸ†Hˆ?›Âöú°lƒþ¦Qd|ªÈ/ßΪoÜlÅÈ©®,|ãõ{Ë&¼píÔr$²}¿ÜûÐÙ;±©øò:k¦€P=•̽ßî%ŸJñÅî ÞH…Õ•Íá5„ƒ3@ê^X šóù¤~êõW†¦nßúÅ«s¹…)»˜œ¤¸4ÇÙñ› m²ëUŠŸ¤L³˜Ÿº >|ø®ëGºÏ¯&?ño$¤ïèßçÓõ3›<°³Iˆë“K7³rˆ;vl¸³³³çôéÓœ8qâ5à,`ßwçmœB½O¼'KµìÀ•{‘ÿžHe¼7ØIEND®B`‚gnome-control-center-signon-0.1.8+16.04.20160201/icons/48x48/0000755000015600001650000000000012653651300023323 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/icons/48x48/credentials-preferences.png0000644000015600001650000001063012653650644030637 0ustar pbuserpbgroup00000000000000‰PNG  IHDR00Wù‡sBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<IDAThí™y°U€¿ÓÝ·ïí{ß½oä-Ù“—¼a ™@L@ã0 8Š#J©èÈT±8”hc•Tiá^R*3â.ƒÊ"b©Œè@"*’/!$/Ë[“·åݷܽïíõœùã-¼„$ 0eMÕtÕ¯úÜîÛÝß׿sútŸ#”Rü_^´¿4À›]þ_à/½oõ ׯ¿92Q,4 ¹È 64´rÈH%G¯]|ÑðÝwÄ~+¯'ÞŠF|Å­_¾<”ÜXÊ—.ŽÆêêdJË ¨PQ®”‘HMC‚Œšz_Ô4w­^¼ì™¾øñÿE>xç÷¿‘H&o6P©ˆfP(•)Ù{Åšk Ãïýà~>Û?в ‰t&ÏžA{¶“BYÒ±|q%—+üøg߸ýÀŸòg |ô‹|¦ñœ¦Ï/ok®Šêû»zikn¤óÐù²Ç7]i茦'8°û÷ŒOLPñCÚ—-æÊK߯êöå ŒñÛí{ñEŒ±©¼3™É~éá¯ßþÕÿU!„¸ñ+>}þšŽ·{%›ÝûS_WKSC çÔWóÜ+Cܰå<–·ÔÒ50ÁKGG(wÿ‘µí‹Øv,BÎÔ«,ËbÖ_°–Í/¦ëÈQ~ó»g°Ë.#SùC;ð®ë|Ë®ÿÜwšZ÷]бºµ.ã±m»H¥ª¸îÊu<¾ã0鬦iÜüîõ<¶«›‘©"T„Ã{¹tu- øÕ+%Ö¬^Í.m箯ßÈvsí5×Òѱ–gžúnþ™’ê965º§³ë§Ù¼ý8°G)å¿)ﺯ©qÁâþs—/MÔÆ£˜† x‚Mç-Á2 ¶½ÔÇþÞ4B×PšFˆF(A( \Ÿ¾óÞÍl¸p->?Hº§“÷ÿµÎús›xæù.^è*rù–÷P,Y±r+V´31>FooŸ½wßË»¾ûÝïþ;ðßê4°oHàÿöØðº5«[cí ¬l%•0ñÃS7x¥?Íö®!Ðõi¡ ðCIèùx—ûŸåmKlyÇ¥Lõü–ó—§8x¨‹g÷eyçµÿDב>ª««±m›øÃTUU!¥$—˱sçÎÑ{î¹çÛßRJÉ?IàÆ¯<ø»ëÖmiLYLNåHXQ.ZÕ‚†lÝÓ‡®k$,“ÞñÒÐèxjZ p}|ÇEó†ö>Å% C|èªeôõvóTgÝö/Y‚išüò—¿ddd„J¹ÌÍ·ÜBmm-J)ÇáàÁƒå[n¹å³½½½÷Îç;kOü‘/>tëÚŽŽ-µ‰(U±‹šëXÚ\ËàxŽç£”b,W"]¨`YQ¬x+ÃŒG1­fÔ$31ÍJ×Ki®¸ ß-ðô ý¼óÚ›XÐÜŒeY†Á¦M›°í2ãC¯ðä/î%—ˆ!†a°|ùòøwÜñ)!Dë|Æ3öÄwÝ…ÖÚvÎÝ ªS$¢1S7ÙúB#“ ÃÀŠ™˜–‰¯B„‰Y B]„ ¡ @A`P™œà¢¶ µ©=}ÇiX¼™öÕ…eY!R’Ïpì ~q€‰Á™Ì‡°, )%‘H„7.»á†>ÜñºýúC_]×°6a™:VT'¢ ¶½ØK÷p†¸e¢‰5ÚÚR´.hBÓtzzw² M¾õÝÄêZJbè[$‘è"d`8KkÇ»0M“X,†ëº¸®K*•$¦»,[T˵בL&ñ})%J),ËbÉ’%›ßPñØ­½½ý àò üà¹#„R‹G±‚47žg# ãä‡^b÷þ"µ)“TM#W®ŒsàÈרqâ}Ô¬º%a@D |L®ÂšsÚPJ¡”Â0 „D">~Ûç(äó$S)¢Ñ(A†!RN·ÝÖÖÖBˆ˜RÊ9c8÷Ýÿ|nU<‘Úw —Ãc¼Ü3F¡â‚® &øÇµÇ;²•L)BWºœ\Dw¦…)¯ÁÁAÕüüOÆ÷ÿ &ÀJÖàyaàã`Å“H)‘R†ád2™œk¾ïãyÞÜÚó<ª««@õY3pNkË'Š)4"f”þÑ,ˆégüÆÈ“ õy4-Ý„´Ó|ú ÷Í÷ƒ¯~ˆ‹Ö_ÆpÏKXf…%Ç&¿t=‚êê:wê¼½dcÅt&Ó#Ô××ÏÁŸ³w~~ø¾ÏððpÈÎ^󴍨•M +ÆÅvк ¸e‚¦/t²4•ê]Ic2ÀÎrß]×c™±ˆŽIÓ¡®y .Z0±ã„M×YzîåŒO•h®22<@†‹Å9à ð}.fïºçy8Žƒëº (¥¼3 !D>W\ÝØPÇÀè㛄¡&§]½HÁ¯eaK ß«à8.O<}ÓÐxçå—ÐѾ×qh¬±… Ei(¿ J²¢¹†›?vi·ó×.grô(ù|ž‘‘|ß? ~>¸ëº8ŽC¹\&“É„Ìç}@û5·´¡™]Ý\rÞJÎUXÜ”¢5é%Pž CУìí"fj\±ù|âÉz„’žCÄ0ÐD„:³Bàºlîh&•L±áªÛ9‘¬^¨x¹s®ërìØ1FFFc||œÉÉI²Ù,ù|žb±H¹\FJÉ“[·î{â‰':«€ïË4M£ÿø ²E¥ \ñxe`‚Æ*]7— p©«¯áî;o`qëîûþ#ŠE‚ B¸ z$FCdÓ#”œ¬hogÐ^ÌšM¨âF†1M“D"AUU©TŠššjkk©¯¯§±±‘T*EwO/¿ÞñòÝJ©à¬R3 ìŠGCuœ+×-¥>i‚fâ{ÂÀ# <V„å‹kXÁr¶¼ãm$M{nŸïØhºIà+üÀ'¯¾ÂÔ4,ÄBÞûŽåxî'ôõÆ÷}t]G×ulÛÆqt]'—˱{Ï‹<ðøsD¬†Ä©¼¯PB×Ð4”&è;‘áo6¬äŠ ó©÷l SÏ-ÍA†K1—¦sïA>xÍZBÿUÀ«à8>ÃS’šÆ6âfdä„ÈP¡k‚Mç/ û…ŸÒs´‹0 QJÑÛÛ‹ïû”J%žq½ã.R7AÓOÅ}­€¦ä Ô5‚²¢q3B<Á«Q*Äu+„K¸$bðÃ{n!ªÒsÛÂÀÅó*T쀴EÄâü× ýdK.J)²'5u첋®i\sE;}‡÷P*•(‹ÓµAJ4Ã$T’l¾ˆD?öºž)ú¥.uAª:Î’5s«ñ…—QmEéœ$ð½¹È§â{ÎÜïÁ‘ 5)ÆF'8[M€ [ xlO?C£TéñÙl‰XÌ *%7~„|>ÏìÛ±RŠªª*V-m£Ëã…XVÏë Œþú?†¥R¾BÒŠ¥@¡Øø®Òyئ¾6Åñ‘켪ôj¤' DÍÃÇÆéRÔ^ú1ü$µU1S§X¬`F vÊr ÓFœÔ>£ëðQ<¯ŒD#Ï<<òºJ)Êð`øx¾‡H¼ œÙk¯þ†&il¨§÷x–þ¡ ùB‰ã#ú‡²Äb Їî¾q^‹–ªÅ:¾®áéScƒ,oŽ"¥ÄsJNÀŽÌ…ÄSMsw^)…mÛt¾r˜ñŠN÷h]׺O÷EvÚž8½§ÂУ{è'2y\?döÐR{É'Ù±ë8Mu ,]´-ZÇ¢…‹Y{ÑÕ õeyú…AžK^Kã¦ëð…ÀÓ5<ÍÀÓt´QR‰…B…HDçØ” «·0˜Î3϶m|-Žã¸øa€i%þx:ÖÓ¾ E¤öHèTþÕ7ËtvÒ\S…e˜ ”à¼õ—±pÙ¹Øyé—Kt÷g"›g|*O®PÀóý“$Ê®O(¡€`>(E(¥Ñã¬j’$b¹|ÓÔ™*jôއøžC±d#¥šk---Üxõf²vé¶³1žU`àÉïoó+åïx¥,¹ì$½ƒcLfr¤'sd²9ìR×už(°uïÔB5Ý‚€üñ£¬iŽ ”Ë~¨øÙîÛGñ2Aà3|WÓ4jª“þàö_l;ãëÎ üîGw,»â#kü-ô’ŒEð<ŸŠãJX MùÅΈDÑ(R“( ¤ Q@)J’È¥¥.‚ëø š°Æ3ÙÙ_žð¤z5*›Í~àõøÞÐG93þÞXªz÷‘#]k—µ6⸎§\®°ãåc¸n0A(”(B”®£4RŠ RbU:{]Û¶åÄÄÄÿ,!„b3àóâC·:¸ý}í_u} µ÷)¿rŽð,„k!"&„((‰ %“Z3>}„·­ªâ÷ý#<Ó3Lèyã~~ü¡ñC»¶A0W´d2ù b1àÎé^æ^#0oÍÇβŽuïÙú°/Ѱhe¢yéf#U·J˜fÐ 6¯yIHvšÔž¬žu‹SG+'úvǺÓU=>øàK7ÝtÓz¥”‘ËåÈçó½3,b­rªÄk†×…ú,àé ç•- 1UóʉXª¡IOÔ4VU5J8¥\hg'œBf°çEi^¹D×­[÷ÑË.»ìªB¡ðèý÷ßÿ%À™ÍÀLNzi:íü€˜—…ùc¦²Í:åÿ¦³;›Éô8?ãÎWæΆ4 #Á±S¶WN‘8£À<‘È<èù92o›1ó[Ÿ)ë3à3ãìÀô>œ gd¡ðfŸY»ó¶9ozŽlFf4zèYðYèÙáƒùÌ@ÏÊÌŠœ*ãþéîö›8ã „Ð8ùŽÏ–™·ç­å< yêœ×Ÿºü_‘¤æÇW{ÖIEND®B`‚gnome-control-center-signon-0.1.8+16.04.20160201/icons/128x128/0000755000015600001650000000000012653651300023461 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/icons/128x128/credentials-preferences.png0000644000015600001650000006173412653650644031010 0ustar pbuserpbgroup00000000000000‰PNG  IHDR€€Ã>aËsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î< IDATxœì¼y¼¥WUçýÝÃ3ñÎó½ukLU†ªŒ@H"„"¨ˆ-(6Ž­ Ò´/Ýmè·EàHK 2$`$„$„JBUÆ U•ªÔ<Üy8÷Lϰwÿ±Ÿs* ¾D$F_Øõy>çVÝ[ç>çYk¯õ[¿õ[[XkùáúÁ]ò™¾®gvýÐ~À×à|ýÐ~À×à|ýÐ~À×à|égúžŽ5õ‚Ÿõ¤ö·[í]‚”gcÙ„°c[ Ë"km„5¡µ6´„°-h!d¥ÚR{MëE³: ž7=UJÝ5\*ÞöÁß|õê3ýÙ¾ßKüÿZÿ’_¢Pþ «ôµXηJŒ"µB ,HcYŠÈ2ÈR„1ã^Áº¿[ƒ”‡õCð=¢v–iéÀ(©–ŠÑÁéÁê7+š÷~øwnï3ýÙÿ¥ëß­¬¿þÍ/ P~ÃÈÈȳÍdx°ZÕ(àÄBOIZ©¡Zñ¥$MÒ$a­Þ€,Åda Ö¬0ˆ4›‚!VûàûXå!„ÀØ a-FLÖÄ’ ôì¹CuO{GšÍÖŸ|ÇëßÿL?“ïeý»r€Ÿz×_^=<Ôÿž¯=²oÝEÛ6ömŸègç{8ëNÍ-²óñ  ³y¸Êå['ÐRÐ_)’e–ã³ Ü÷Ä<{O-1Ö[br Âѹv>~›¥ˆ$c°R‚Ö =´§I’›&`2¬ ;}üžîÜyÕˆW_}1ÒL­-ŸZ¬½åƒ¿þª›ŸégõT׿ øÙÿç#ÿkýÔØ/ô£™Ù9¶LO±y°‡[ïºST¹÷þûxûÏ^Ïã§–I¬b00,ž8LªB ¥"›&'èÀJ‚ …Åfg–ùèßïâÈri R¢Ÿ»`š¾‚Ç-æèÌ6ÝÍ(EܬcVfÙqÞv,íº—»`𡱠ˆJ,µ²öJ=þÔŽ³/øÙ7\wö¿éüoÖþûǾâͬ¬~¢·§ø²¾Š²ÍéÚ*?zÕe<¼g/Ÿ¿{ÏÎ…è ¢ÜÓË_¹“MS£üåí÷±°sÉEÏâ'/c˦ͬ6ÚÄi†5`%Àӊ޲Ͼýûyû­&…$Fa­eùÐ#\¼®9YeI÷bÓÅ …Q+¦µF1^æâã<6×À[9Æ›^þB|ÏçÄâ*+í̬´ùÊøÀÐKÿã_Ö|¦Ÿé?¶þÍ9Àö/Â%~â£Ãý? ªZ˜ê­0\øØ—S¶n9‹™ùyž{ñvÖ VQRrß·ñÛŸ}•ˆO³Ù[å]¿ús¬Ô’,|B … Њ¾rÀÒò¿ö©h5[ˆv›&X HÒ4Ei`‘ VjŒ”$VBšÄˆ,Ãf o»rŠ ,±²Ö¦Ç4“„µ86³µø–Ú¦+^ñ±—¯3ÏäóýÎõoÊÞôÇŸ}soµxC¹\ žGo¡@)ôé)EŒöˆ|I) øÔí÷09½£ÜËK_t •r‰wôVnŸóÀ„X)yç ׳ndˆµV‚1 „û=Z G¨ 'Nâw¿x„¬Y‡V·\E€{#B ¬Våç>ל5ÌéÕËÍ¥§Ò—Tš¬Û°™Ù¥­v‚1°†•¸¬eÞ;ÿøW_ù‡Ïì“>³þMð¿ÿ_Ún¤½}Ýäð–šþb‘‚硵" =¢Ð'‰ÊaÄüâ2—·…·Üðg l¿Šë•bu­I!#„0$—Œ…”UŠV_+¬=³ûCO¡E‰S3üÕm÷ÚI”Ò¡R»RQ€0i Ra•^€ðC^ºm€ëwLÒŠSÚqе% Y–òÙ¯ÞÇÙa@$d™!N-Yª¾ï•±ÿõ÷Þ÷©_¼âÞüãÏxùŒ3¿òÞÏüEX,õT†zÂ"½½T Š…€j)$m¬rÿ]_æè±£¼ï¯oâoz;?þîpÑU/áMWn¡Z*püÔ ·ÍxhßGùʨ×VÙ8½­\¸|Eà) ¡¦Tð¨­,øšÉ©)”ï#•ð}„磴‡R ¡4žÐh塵‡ò„ö÷[©1H”Rx¾ÆËÞCÇÙ{z…•¥yJ…0ð=­5Vj#0T´ì/ˆø±×ÿá‡?òL?ÿg,üò·ô—|ñpïXàyôJ„¾Gx˜¸Éλîà–۾Ăª°íÂK¹~û8_ØsškŸw)WŸ=Îh5ÄÃÎû¾ÉØÄ$o»sÕv†‚7\2ÄU›ÑZÓl§dÆ"…@JA·hÖk¬¬¬ð©/ÜÁ=Ù4au’62i"Z ˆc°9fP ´‡ñCLP Ó>¯©ñ²«/§ÕN8}ò_ûʼú'_Kš¦¤iÆâò©Õ,ç8 I2’$!MSâ4…,C ƒÀ0߈gEPÚ~ï¼bæ™°Ã3âo~ßß½v¨þePˆT%(P"|OS =ÝuøèÇñ·\F4¶á‡[z³©ÇéCsËï¾’žr‰CÇOñÛq ‡gðâ¡Â—‡¼é9ã êíc,Z Ò4æÔ‰ãüú»Þ¨OSÞt!RûXk È ŽI[kÐn;^ÀZ„’X¥±~€ñ daÄäÚãÜðÆWÑNR´„ÿõ¥‡øùg¯§•A;NH3C³Õ¦ÞLˆã˜8͈“”$IÜkš¥)´°41‹‰zÓŸþÚ«ÿì_Ûÿêà7Þ÷ùOOŒô¿RIM_±H¨´–µå9>{÷ƒô\új„Ò)RráºA~ëê ¤YÆÏ¶ÀG>ùijõ8Iºýz&&.Ä ÂraŸ¥ú¤™AI0I̼ëyèèhÑËš¢1.|KÁ\3IµD_1àôÒ¿ùÉ]Ä©A‹0)í! \Î<ïÜí¾B $¬Î⮯ãÊ+_€’’f«….„!iJˆcÝ×HÒ”8Kñ…½²ýÁŸ}ç¯üÈ;ÞðÓÿšöPðð¯öË~íO?{ïÈØð í3P*ã+)]Ž.E‹‹óì\) •Bj…RšW]´Ž×\8A©·Ü~h•ÇV}Ž%%ôä´IÑdh@Á Ö˜ 3·üñþŒýã×RZÕáid£Ò …ŘŒ=_¿ƒéªbqq‘?ÿ³2N"­m‹@!•õ

ÅBÈ.£§T$É,R*6ŽòÇ;çX}ìN¦Æ‡ù?Ÿø4ý½e†‡†ÈŒ„û#q_ B`­ÅXÈL†–Ðêó>ú¥{_zý•ý«E‚µðkï»ùÀèèðÆ‚ÒÒådO)B_Q-øœ>~ˆ÷|c†ü9±e¸Ê[_z!ZI”0¼ý=7^øÎêÕÜú­%tÖBe Òº2-ÓW–fø™—<ŸB±ÀþñØœ‹ïGÈ´…ˆ[ˆ4q=©Ò$I›ÚüIÒæ•És‘6ƒ4,¾O¦|ŒçCÖæÆWlaxd”8³HÖaù½¿¹—¯}íïyÏ^ÁÖ‰–1+kMZí”8‰i')IìÒ@œ¤´ã˜8NHÒ„4N"C`Xj¦ÇÏÞþœuo¸îì§3xÚàoý€¿~jìØðÈàPÙ¨„„(é.ÏsÐSð1i‹?ºãqæV›l,ó¦çm¤·§Œ‚ÐW´ã„ÞrÄÛ?ðI÷×ã'-tš ­ÁJMêyÔg‡¾ÁÙ£비¨:ˆJcDÖF& 6M±X¬…LJ¬¤sŠ4%K3lš`0`%™räÐs2bÿW¸ñ·Ï¹ïþ{yѵ/Â÷4oûøÝÈJ\âÏqņÆ'¦!”Ä$qJ;Iˆ;ð¤Wc’$›¡„aµ®|ý»ï½é}ÉÓiŸ§Õ~ö¿2ê+žè¯V£"%?DH’­žxZQ 4•¢Ïç?óqŽFÓüÂó/ ¿RtL›pÞS’ÐSÄq“7l'‰WÆOÚxYŒ²‰QFk2kÉL†çù`k§˜›¹®ŸÅbŒÀ á~>³Î LBšZ’,¥RôøéçnáùçMvyc 8vâ4{öîc_#"9ú0¿òK¿@bàg>ú áüÞÿË/Cê€Z½M3nç;þŒÑÏ|»¯ã˜v“>É ×«ŸÿâWûßý©ôé²ÑÓ {¢cÕ¾¨H!<¥ðµDK‰RŽ“|ÅÉc‡¸c¾À ¯ÛAOc\¶Œ°dÂÉá£'hy<%™BÇí»²-Áf+¤£s³XkÒ+Ö@–’Î˜Ò ¤²¤Öb` *ãCoº%%ÖZ”R(¥ÒÕþgŸµ‰-§I’„v|3ssÕr‘Í×36:JE(¥h·Û4 ­6Ë+k/ Cc X ÆšnÞoç ƒÚqJœ¸( 0Ú·‡ñ©4Z-°ËÍìÈ{ßö†õöi0ÖÓÞøžO~uýÆ©M¥ àv>àkE1ôX<ñ_ýò­éóÆ_~3ifRpöÖmxJbŒÛ Ý~ŒÛ'H)€Ö’çLùÒ„t;F+0Ž¿wÛËba]4P2w6‹Aamžó͹s £Êd¤YÂôP…Ûîø "‹9|jžpÑùÛ™©î:°À桇ØBHzµÄ…É2ŒR•a=5Èj!x䨬ÃECãÔ)Ï®{ýÛÿd§â2\CÓ~¿œáûN¿þ>þÓë'®,z!e?J _RŽ4ýÃÃÌN_Íæg]Mà)<%¸OÕ¼JŒ1”Ëe¦'FX?R¡¬šõšõ:&I‘Ö ­E ‹§@e12káI‹°[×OòÈ¡c„žtœAjé ì³^ùæwþ) Ü#òI—ø^íõ}M¿ý¿{m_寢°@_¡äо„ž¦Zð¨FÌ8„Ë|E_ßíÄÑ·ZËîn^Y^ä‰ûùÓ~ßÄìØ²žmÛ¶ñù¿¿›×¼êÇøè®“xÛÒAÚDÛ ‰q¶+rÇ òÊ9˜±cȬíF€,Ë0™Áf–$ˈӔÕÕe.–l©:Qk¿=.yóœÃºñ¤Rì9pˆïã?^Òƒ5†¹…%‘6¡§\drrœ³·m# Cêõ:µZ“³‹,¯%(O#„Àf øÂ­_¤¿ZejãYÄ툹í¡C,~ë~.»ô9„…ÚIJ–¥vïáÓ/ÿâÿ¹áÜ~ÉÈ#ßcdø¾9À¯üù—û‡#f£RYöË9È“øJQŠ4}å€ãOìE–ûi5ë|äæÛyÿÛßB;ÍÜ Ëé™ôõöQ,D|q×>>:Âf1#v•ß|ñù<øs2$mµÒ~㉔ã=ÉFºž¾é` &€:ÃgØÌU 61$™!1†Zm•úÂi^{Ñ •@¡µf¶íL²}Ã?°›G—ù½7½ŽÁž «õ&«µ5j«+,-.²¸¸@ÒªÓW-148ÀöóÎÅóÓ©„Ì+Ea°dÆ`3Cf &Kɲ ›L’‘YK’f´[mV—g©¤Ë¼üÂu” ZköŸç“.qÉåWñóWlfó`‘fœÑj'¤YJ»Ý¢Õh°¼¼ÄÒâ" ósÔV–êczzŠ ë×cŒauu•……N¸—v¶BEÆåÒ—É µµ˜XVhÚ^öŽÙùðc\¸a”ÀZÊü_ÿɹˆÉYe\4Ⱦþ«#|_àuïþèû¶žµáM•°@1ˆœ1ór¯hªEŸÙ™“ô!¾4зþl†kûx`×nz6î Tê£gxO TŽö¥(kÑÒ84Aä9ßq÷9ÒÕùR8ãœStvk²4uÑ M1I†5yDHÚ­:kËËÔWæyþ9Ã\¸ušžJ­5qš«ôô£ô~VVjÔÎ%:+/ƒòö¤#)´Ä•JyI'¥@åÄNg×+!02ç×òÝo#Dþ*± cÈó†I Y’8`èP6&N1iB–d$iF«Ý¢Q_¥¾ºÄù£!WŸ¿™©ñ´Ö(­I­Dú%<¥iÇM–—–øOÿí½ì˜ðù•ë×£¼€Å…yâ8%CÖ1u1H¢F È(Š( 4›MZ­“““LMME.å‘wñ8}ú4sss¤iÊôô4“““Ôj5»gÏž/^wÝu¿ßh4V5þaZøGqÁ÷ìÓ×þ¼¸þ%×6§¦Öý…2B:z××òÛ"€¯%¾' =M!Ô˜¸É‰ãÇøð'obqÝó ”D‘á[ƒ%,:¯çµPîUI´RH)\/AåEZdÞ§·Ò›Nøï8€uL ±¹c䨿²,Å&鸔&NHÚ6ÐN ‘JÐmTs™Ë¶M°uóF<ÏCkMf,»ÚÃïÿéÿ!ˆžÿüKø¥KÆZæN£ÜSÁÓšF+¡Ó‹éÙÀ±cÇøú׿N†T«UÊå2­V‹f³ÉYgÅÄÄ…‚kœiíøºï,÷=ÊÒÒÛ¶m£··—“'O.ÿâ/þâO|ùË_> Ô8ƒÒ';Á÷Å^õÎÿÕÅÛ·½¶¿PF+ù$žÿÉÀ׊ÐS„¢ú|íίñù»î§6t1aà`ºý|-,JJ<R;Î]k…T®¤TÊqBI¤´¡\¿@8Ç膞ä6ÿäG/ëÊÀÔä@0ŤÎL’º”¤yCÉM¢<^¼Ñç9Û¦9rô'¥R8ë¬-‹E¤”H)¹ÿ î}ð~^sAŒ¯CæO§§¯H’Z±dýůe|r{öìa~~žjµÊÌÌ sssXk)‹´Z-Úí6çŸ>ƒƒƒAÐu€NZºÑàÈ‘#œsÎ9,..¦7ÜpÃ/Ýpà ÷æNÐÈ áIBÇ ¾'&ð½7ßçM÷üTÉ÷ñ”F +—wú”r»T+ç^´|üî=ÔF.!ð$A– ³•eh›æÀ .× G+á0€ì_8ш¹p$O J¢dþý\M$¤èN 7 ŒÈ?¸Ü(\ÏAžk`M.Bjþþ‘côö 0>9ÅøÔzV ÷Þ¿‹ƒŸ€ü=¶¯æ§/ÈÐB2ê=ýâ8¡™Y¶\öz&×mâÀ÷}vìØÁÈÈŒŽŽbŒayyp\Å®]»X]]ÅCÇ4 jµ«««Äqì@¬1(¥Ø¸q#ìÞ½›jµªçw~ç/ÞñŽw<(^çcç÷+¾g¸k×î÷ ªJ¡”$ðÝ.÷=…çÉnÈv@yO >ö×#îÛŒ/ÚdÈÌ]ÊÚ¼S‰"7¸³œËõR ”³T¢Ë­KI×ðJÉn¹õ6ææçiœþ ÃÜ©“ôô´[1v̺¯edtœ;w288Èðð0RJÂ0¤¯¯¾¾>ªÕ*Y–±¶¶@»Ý桇baa!år™0 IÓ”Z­Æòò2Fƒf³‰µ–žž6nÜÈîÝ»)•Jâõ¯ý×\sÍ „¹¨Üæ²ãßS3¨R _ÓS*jÏ÷ˆ|…Ϋ”N÷æi׿}Ícìæ–[þ–‡Ì:¦Bd–¢I]äèìN!@:à %óQíÜ?en<¤Ûœ€#÷ò¨ B¸œ¯,d¹3!p¹zÇVX:=OHÛIùÜ`ÞÃ0ù÷û{ÑRø¥J™¡ÌäÛÉðå;¿Îâüã¼æÚó8yø$½ý%ÚqJ£Õfü¼W³nz »víbllŒr¹L–eÝb»Ý&Ë2¦¦¦R2??O»ÄñãÇYœ?Îö—0:6ÁÀÀQu«‚Nº0ÆP(‚€­[·òðÃsÁ¨o¼ñãW\qÅ5333߆èÖ_Øv¸þ7oø/cCQoúšúâi>ù¿o$®/’5— •¡\ð)š¤Uç­oýmþóÿ¾ýWÐ7¶•¶Ñ&Eá "¤@h…PÊñã΃‡yß¹_“; É›: •7w´T(í.¡$BH¼»DNuÿEºh"”û7Ùq*,Ø\Ë;ušÓ'Oâ+‰–š0 )—K ŒMxáŽ^šµe‚RD–Zꥡ­¬ßr!û÷ï§X,R,ɲ !kkkÄqL¡P`ûöílÚ´‰sÏ=CwJÀ¯ÜñE>ÿÉ?áÖ›þŒ¥¥%|ß'Žã®cX[[£^¯Ç1ZkÆÇÇyôÑGY·n]ùSŸúÔÿô<¯Ì?Œ¾‡vp-³¯›¦à¬®,ò{ÿïû)Ÿ{%'>ô—,7bF+ÿíío,¯ûí·áo1CJ»ž½ÍÒ"sŠV g$‘;‚Tn ™3xùÎÒ)ƒŽSÊC‰ëŠÜø‰u )Æ „Íó¾n‡ç¦—Öõ „ŵ‘Eþïy„pN‰Ì\¤&%(Tø«OŽåÓG¹îE×Ríéãö/ÝÊ®‡ã?üèFzûûYžŸ# Cê&Qä3¼ñ¤iÊòò27nÄCš¦Ýü…B……Ò4¥R©0·°ÈÌìÆX”’9Ý`Ëtµ¾ÿ.½êeDQD†´Ûí®Ñëõz·b(—ËÔj5زeË¥W]uÕºÛo¿½¿-ü³"À†WüÆÆžJq¢7ïôÝ}Ï×éÙ~5ZyÌöí ÞpGú.àÓ7ŽcGá_üãµ§md#Ò•e2·‹m¾Á¥Ê¯œ±£Ó¦Å¥)Ê=­¥« ¤Äó5ÚÓxJ#”Ä—Ok´Txh ºPÊCJ… )Õ“pìîzÈSOG]"­#›L†L´“žº–?¹õ¾|ïƒìIð6=›Mã}4ë ŠÅˆÄâ$CVÏe|bŠG}”©©)Wvfnò¸âZ­sssc¹ÇÔV–‰Û-¬5cðNœ8Á† ¶\tÑE#;wî씄qî柇‚ðåçm˜F ¸õޝm€4A¤12M6E[ËÅÛ6òÀ¡90©®è Zà¦ÛùnÊ"³ä\½Ûñ—©ž§ ƒ€ ˆBßó |Ï x*…TÊõìU‡ˆò=ÈÓÝy@ß×xžB+” ”<Ó=Dæ9çÂȺáP‡SãTGU_pÕÖ±\þÕ¤'jЮ/¢´&I f288ÌO<Áøø8¾ï“$ žçÑ××Goo/SSS(åfZ­”JeÚqÂ-·ÞF³ÙâùϧÚS!4ÅRÏóX[[ëFŒååeY\\dee…¤ÃlCoo/‹‹‹ôõõñ[¿õ[oà–„ò)G€ /ûW¯ß¾}tzxˆÅžÕ(,"Ÿ»¹öMK×fÝ·àùÂf F*DsKëZ³V %˜\Ée¬@ Wv)-ñóYÁÀó(†’óR&+¥B„—s&‹iÖW©­-³¸²Êášf%š"ÃC)ƒ–--mRÚV`mBšÈ.Mì ¥í‚B+@vFÃ]—Ç…RÐ_ yãë&evnŽf³…_¬Õ– "Ÿz½‰ åÑ ‰¢¨ ø’$A)E’$$IB__33npuu•B¡€ïûø¾ÏÔÔ$Ÿ»å DQÄ›ËLŽ "²v‹m¾ ‹‚ Š"¦§§»ÑCJI«Õr]ËcH)‰ã˜-[¶<7Š¢B³Ù¬ã°ŸÒ§ìÖ ^¿}´J!ð¹gÏü¾DÜv.$¥›¬U•´¹éó‡WìAÄ-¬É5}¯DÞ§§+â´¹W(Ø<_ÅÀg¬b¸|´ÍøðÚ/8bé´ý&EZETˆð=è)j¦Ú5šõGxôÐGÂíxå'B¤Ž9ÌbŒ¹ðÔ8š0‰„rJâL8¨$ÏÑ”‹‹ ‹´[mõa_•f}‰&MS¬1 ŽžÅòò2år)%ZkZ­– ¢AÐeüVVV£Ýn3;;K¡Pàºë®#T1‡½jµ— i4œ³ã¹lØr!Y–±°°@±X`ii©Ë¤iе–4Mñ}Ÿ4MéííåÈ‘#T«Õžâ±cÇVrøçE‚ಉž2Bf×Z {Üž1¥ãùà´|ê‘CË“å¡Væ´[>„hØ|×#…£v•À÷<‚À£)®YfÛäÚ¨/cîè7Y;H»±D»¾ˆ‚B~T¥Ü;IßèYa --çŒK66îážÇ%Í©%aíúÒ“k]Ù)EGMd±h\.Ч&;gÚÍôÅ1E1GX ¾2C* Íf‹,K(–ÊÌÍÍ144@’¸ÙŽB¡Àââ"³³³$IB£Ñ`mmjµŠçy<þøãlÛ¶ç=ÿ%\ú¼khÔWÁ¤”«ƒD…Æ<ÈÈȈ:cÖÖÖºú‚µµ5†‡‡»·Õj!„ V«188Èk_ûÚg½ûÝïþ»'E€§æë¯ý…;:=ÙSp¿¹F ~@¡Qò „© #½eöά"Ƕ!’–ËŸÖ°€R®¬ë”x¹r§CÈ(¥ðrã¯+^º1¦\êeîÈ}ÝsÍÚÜ?zo•Ó4VN³|zǾuA¡‡‘u;(WûÑÒpÅTƒ“ Í7í•G7ƒ–X+1©˜Yê6¹À¥0peªTÒm~!±B!Œ¡oh”,oeYFH›ÅH푤1õVB¹XÁó¼îÎ7Ætwc«ÕB)ÅÂÂLL8r§Ñh$ sssìÞ½›Í›73::JµÚÓýœóóóìß¿Ÿ.–H’)%I’†!ããã!h4ݨãyY–Q*•Þ¿žZ`ƒÂ ¤Ì’-%˪„ðÞpÙãýe~÷óÑ<±—²äÝ×_ίò!læÎÒÚæVN¨™ ×7¹†%Qž&ð5[{[\7mÈÚ+<|ß_R[< @½myâTJ¡g‚R¥ ,a­¥Ý¨±º2Oc囯„XæèÞ¯{žØŒçù WÏ­™;-SXw¡R-H•" K†¡s?® ´X2¡H…sØgM÷ñâ#¬®®:'ÈR²vå\9׈°ŸB¡ÀÜœsXcL·i“eY÷ÿwrÿ±cÇ0Æt+ƒ;v0??Ï]wÝEEî³×ë S*•XXX Žã. TJ±ººŠï»Q÷I”$ B²,ëüìz¾ƒ zJ ¤z¡²–ùÅE¤¼ô’³Yˆ5lç¼÷F¨\À\qš¿}ô üÚßð£ç]Áç<å:ð©k¬ …Ûy9êîP´Á+BO³¥ÜàE“Mê '9øàç0YB­)Ø:àÂg]ÁõÏéA™Òæ iÒÀ˜ ©B¤·…T^‘+|ãþ{8{Ò8G8°‹‘ñ-„…¥HðõMnÝ×¢²å2Ï#õ2²X`¤‰#$‚L@frnBI~ç…›ªDÔëÍ|š×é âf‚ö+¤qÝ–¥ K :]ÖNíŸe===´Z-¢("Iêõ:Zk …•J¥Ë†aÈŽ;ˆãØSh-Í\f¶¼¼L† ²²²ÂÊÊ }}}ŒŒŒ0;;ÛQe³¶>‡µÖ:MÓN?à)FÄ%ÊØ„ç]þ\ž·mVÌœ>Í£Ù0^š‚TG7ó•µEn˜RèÛÊ«^¹[?†©/sÖuÿã½ÇÝ7ý c…S/½Š/ݵ½Göñœs{9u|?ýƒ“J=Ha¹´´›§Ç) N’úš8Ñ$iŠR†ÄŒq`5“.:\½©ñþZí¶õÎ k­Å Ê´›+áaL‚±†4sR<­uw7 !‚€r¹L£Ñèî^)%žç¹*‚€J¥Â¾}û°Öv•AÍf“‘‘úû]dñüÍò>×Ziš’¬<Á5Ïâ‚ç\ËWw/c­eqî8z,ͨD09ÿ9’V ßSJáçÃ#y›€ GUW"W>g3&˜n3ä$:`dÚòÊ ÈÒ--IÓuéd>SØyøÆÆÂ0$Ë2Úí6J©®ñWVV¨V«Œ322Boo/ãããÝ’Ïó<¢(bnnŽC‡qðàAöïßÏÁƒ™ÅZK>ᜧà xžÇÌÌÌlîõÝ#€°â<‘-ÓQä– ^l]ùqÏ©Ý/À¤¬E)Ío|ø6Ò•Y~ìçÞL’fì><&%ËÏÅAä$ r@éìèÃþ"Çìà¡#>?ñS?ŽŸÆÄ®´Ú÷èn7¤)Å?q£Šù¹†Fz‰ë Œ‹¼â¯à _ø—Ÿ[deá8=ýS©Ù2 {¸‰áçüAà¢@;I‘‰ì‚ÓÌ ÎPÝ”ÿ’¼ãé sÍõÚ|>îå&‹[k34nÞ—Rvùÿ]Ûá:=¥Üï©T*]> ó3RJÖÖÖX\\$Ë2ŠÅ"cccŒ92ª£"J’„µµµn èD–Î=c8}úô©ï|lß5XìL†ÌD#ŠÌÏÏ⯾î…ô–"GçZ‹È2®LØzé5¼æ—ÞÂ¥)ðâ­¼éò 2?$S>™ôH•«B„”„žäü`/s''Ëö0\pÉó²S¹“x?ô8BH¯¾üœ3RóüAJÙŸ8ÉW}m™°ÜC»UäMæDQDÇH)¿­ù388HµZeýúõŒ388Ø-ïNž<ÉÜÜKKK]ãÕëuêõ:ëÖ­cÇŽ!8uê=ô'Nœ`vv¥SSSLNN¢µÆ÷ýî®ïT!«««>|ø0Oˆò”šAž#:È2MiÊ<@±Pâšm#¼ö¡\LaiÂmgîô _ü»[øÄg>Çg>óÔÒ1ÆÊFkŒRt&?=­8[ «4jK´bÁJ:ʶé’kÜ(Mš&,ÎÏ¢½Ï(Ù“üÎ_ŠçQMŽ¡ý?(bð]`s$Öõ·YhõRo¦$íIÒ"Ë }¨ïùBž‡5ZK„T ©¼pC ß÷0ö IÔÝýJáyÏ÷Y\m»Cš`³˜Vc…••ez{{»è½Õja­evv–ãÇw)Ü8Ž»ï9>>NµZedd¤‹êëõ:išEÍf³Û1¬T*ݱuëV<Ïc~~žùùyÚí6B–——QJP©T˜åæ›o~ˆïy Pl’ÖZ L&æ³÷bÝÄ(çŸ!½È[¦"ˈ‚2BHüñmÌ(Í=IRèí窩ˆ{æ½Ü>-`“<@mi!àÁ'R^ñÊ+0É Ri„P´‹(ÏG{Ú°&áK·ßáh¬<¼úׂIñ‚3„AŒ7xÑUçqëmwð‚K†IÚk(¯6N2×hài×9úU¸…/?w½ã€ò¦UÇPJ)<íãå=‰…ú ³Gñ£ ÍfЇc‡ãÜsÏë¢ð'†!QQ.»ãl›Í& ¬¬¬tX.—»y»Ñhàû>ívß÷WÚ­¬¬tÃúÊÊ B|ß§R©tuƒq†!Íf“ééi|ðÁ•z½Þæ;æ¾{ °fRd‘w‚fšâŸÃCOœBJÁCîAXGËŠ,¤Hòóxâ6ÅÊå¡ ”_ä«Gšîç’i-U35h·ê´ÁÖó.¥¬Vs-Ÿkô´š ”òÜáÚçßô0ïýÈÝÐÙ³/àÿÃ+°&Æ xAÒï(ßämbÓYPoe˜¬å†?2ÃDŸàäG]$ÉO-‘°ŸøÄ'è„~Ài:àyø¾O„¬™k+³‹'M#eßî¿cii‰0 1ÆEQ—•3ÆtÏ ìt;ßcjjŠõë×3::ÊØØëÖ­£R©tyý6lØÀÆ™žžîÎtdbJ)²,ë I;Žwÿý÷ßÇq›ï‡>… ‹Ý&Nfº¾'æVQR°óñ“îøÛ‘ZYlfi†È§ˆÛÈv“@jTœ¸ƒ1LŠcÄI‚5)Gf2ÎZßyËS‘;î^Jy|éîouuJI~ÿ­o¡];Žç‡x~ˆò<¿È¬.°&ezXñøÑ¬É@Ø\n3;M€r£Øw~P\§sÜ@'ü+)PJãû΢0Â÷ÎE›ú¾¤µ'8yâDwУ3ÑÓ„{÷îe×®]9r„F£Ñ}ÔßÌÌ J)†††º]½r¹Ü í°×)#£§§ÇÓ¹9¤”´ÛmFFF8räüà?Ë·‹d€ù®)À Qpxĉ%óÉ u™¤Ýæ„7NБrYWâ ¥ó°éÀ!6CZ‹0® ¬„DÅ@rÄ´-T ndÛýbÀZ ¥Jî 2Ÿ=øö*`ei޾…öCÀa)þá¹J‘ª“‰jŽÎñ­µôØè@áÔBÃGŽuûBؼ_‘KÕ= ŠÅ"'—Fi¶ŽSéís'}d5vßóYÖMÿF×ZkæççéëëcãÆ uÙAþõzf³ÉÄÄD·r˜ŸŸ'˹…ÞÞÞ®¶ IÆÆÆ‚€ÅÅÅ.áÓh4¾­ছn:tøðáÜÄP™‰â§D¨\¯.·1`2|­iµšT{±Zc¼DîŠB(1~€Õ>2o9Xkùƒ—@Dc‚R¹,n¸ö«1¹"&#Œ 9wëúëž÷mèÿ-¿ù_Ùõèñî÷ƒBi²Æ±‡{MZ«J¥ü½ iŠ:!ŽÛ®tŽ™ÕCî!v¤‰ —X¾F…R‰B±È7ž(šJo/•J ‡îfïc211ÁÒÒív›$Ih6›dYÆ©S§h6›ÝÐÞQö„aÈÜܵZ­Ëòõ÷÷ÓÓÓÓíöxžÇÜÜ ]®ÁZÛ­ Z­SSSì߿߾ãïøÓ,Ëž,éF€§ ‘+s±´°XáŽS[mfÜüÅ;ØÖ/°^€ lX༣¼üY›xÛ‹Ï¢Ið}ŒöÜQëB9-^.ÀEÛ•B¸ýüü“ßd)ZkF¦ò ¿ðêgóßÞõ[ ôUÑJÐn7yߟÆûf J l’;R.>éT>h#Ä™ÑR`Y[©áÇ9$$ë‡{»µ|ׄÌei^®ç‹(•J”+UêI‘Ç·(•JT{{©ööòð½Ÿayy¹Û½B0??ßôL’„v»M«ÕêÖü«³ëã8>sÒyþì´Ö]Øy¯,Ë8tèз5¢(âž{îyôÀ§ù‡3ƒO­ ’“‡`€Ì l†UŠ=s-þóuxö¹ûà7?:Ï›Ÿ7Å`o3³³ÜðÏfÿÌ*ï¹m?Òd™t't*'ø,È´cˆB/?,C7Å#òÉ¡Ñ1Úí”vc™úÊi6 Tø½ÿôz~÷íÿ€( ^DÁ/ÑXx8ל98ÃUr–ÀW4[)•@’eŽÖ-P[]#(•\€Ë5—¬«’o«o›Rº„aR±L¹R¦R­²ëH‰¡˜À×¢€åÕ#|sçWxîÕ/îµNK¸Ó°ù~-!Õjk-a²~ýz¾òÕ;yË[Þr#nhôß½ ”]q.ä°Ø,A¥ ³Þþ‘Q(WøÑy.[ž¿žÞj…ÌnºíÞø^óŠ!¯¿2ãáãËìzbÖß‹Á ISƒ,jÐjÔ°¦’k@H{fGb¦Vdmy†vc…¢htYÁ×üÔ+Ñ^HcþQlÚL—ÁsQÀ»ÙXQ@jM–ŸL’¥ÖÍæ¯@àKÃE‡Ö1¯b¤¬BIwa† år…JµJ­Vãs;OòSÏ )„š8ÖzèÓTûF8ûœíÝ)ŸB:–”’±±1{ì1Þòûï¶I’t†E;ããߦ þ®)@ [„åÔf­qBχíßXð™ŸçÂu$©!N ?óªWÒN2âÔpåYüùêM¼õÅÛ¸ñgžMÉw;m¥åúQ ©­Ö\Ø7Ƥùé)&K0YŠ$¥\Hécpòví]B+ÁË_ö£\}ÙY4f¿‰IjÎèîü7—R¬éF„µµ&ÅÈÇZA–9°\7„ÅB®Úu‘"6š?ûøÍ$q»+ºÃ§ªµŠ¥2Õj•žjt™ûö6(ò(„š{oÿ ‡¢§§§;õût\A000ÀéÓ§ù­ÿr˵z ¬pfZøÉðÔx£hZ!óÃ@ƒHSHc¼ ˆ?0Á½{‘d¶ëÆ Ú‰!I³üï’-cDÏ»^ù,*¥Zâu‡/²¼ìß>áÿ6wÞq–\ÕÿÞ /¿×ÝÓ=A¥å„–`l0Y°²e{aƒÓvmd¼^cÙþ€[€ñÈcL²Y…„„’Ê9LÐMêžÓÓù¥ªºÁÜ[õ^÷tOÒÈv}>5U]óB½:çž|~GeŒ 1J0ÇØà¾õí»ØxÆzþ×ÿxÓCc´rÆcjK˜ÌH7 Fk›#WJ3]7”Ë%‹¢v ‚8׃1Ú¶Ÿ ²³TûO˜‚¥•jZO/=Õ/ {äÂr1G¥”ctp˜ÏßðA†dq„n}ß½ …E¯§ÈK½/eÊññq>ðGÆ–]{~ %À¼.¡cKãµÓYkÆUðmG®Ù)œ”¤oÙr»ª´…`‘2EiÛe+•&QŠD*¥"oÜØG]å1"‡‚VkÎ@u¯þ#¤’@+É7ïØ‚1Š_ºö]4Ç·8ÆQYÍ2ʼ «‰«©×:@IRš©äJE”êš&ªûÅ ~õƒB}nß…¤=Ei@(³Š%Êå •j…jO\¡ÊÁÃ1ÅB@©˜£QoQ %ÿúÙë>¸?K/Ügffxøá‡çᤙ½;w266¶èû„Y¨ù7û÷xzÇ>¼ Ä ÂÈ1À¢âßJôc1€mcY9¿ýÚ®c즢—XGgp¹z¶kcì*3–®ºàt–­9Ÿv3 ô–=Fǧºˆ.çíJ9é %;v "€óÎ^CYÕat‡è)#è.&Ÿn1Ð[Ä ÌÍ6³¤Ðaµ ¥ ±’H­1ZáiIäàâ«ùÐG?ÁÌô¤kVµÅ¨™GàyÖÈç) ”ÊU*å*år…½‡4Å|ÈÄ¡YÊEŸžJÞž ÞöIvolÑg}çw2::Êààà¼ëCCC<ÿüó4,¾ß½cxà¡Gøò;l)ýÏÛÌG IW–:ždPÖPkÇ6ƒ¶l$Ü4 ‚0LêÜ]ußaz£ “(cØtÁk˜™!Ì×8k]•ÇžÙ?O÷«®½›>{Ãÿá[_ý3 f­e—pŒÐåR¦LñÜÎIÎÛ¸œ0WcâÐd¦ÌÊ‹‘Z“$Úâ[× É>³^Ïo]ÿ—N©œð›Êå¬_,—)•Ë(òäs“³ôõVèí­Ð?ÐG­²åá›xâGßÌŠKÜBË‚8QÍ#Áèèhæ’æóùy„ñÅ=|àCÄWoú6žïÓ Ê?tíó~“ùøG …;ˆ‚Wh—ñK]k;3Ï?àü•UÞñú‹²áþ")û¬Â`gø X¹ží+tŽbÁ'ŠZ N±zeÍžºüpR×ÎæÆwvbŽÈ)ñµQ.7ßa‚±‰Ÿr)G;ö‰£c`dÖcÕ«/$–šX)el‹Ñ¡ð…!_,¢.}7O?õ$¯¸äR ± ÏFx®95pÑÁ<…bb¡HAåÉå<Ú͘+käÊ5 å Q³‰1ðÂÓ÷2=£yã;~€éi[¼AV–n‡ÊD}¹\ΊH?öןfÿÐAÂ0O±Tfrj‚ XEb!„£,.ú B v)DfIk\‘§0(ß#—ËqÍ¥kÂC*WgOG˜E?Õ¹gÚPÝô:ƇÇÉ—û¹ê’|û®­(™tyÎÔ mƒŽJ°b üè!Û5·?<Ì.?|¹ŸÁ½þWì¨/§ÚßO$•Ã+Thkßh‰Ð1¾Œ ÐüÅ—oå®;o£-î€ka÷ä}.gë raŽ\>$ó=–õUèí­Ñ[j9Gµ’£Ùhó£»¾ÉäáQ&&&2CnAÕNÛO¥O­Vc˶í:H¡P¢X,Q,•˜iĈÀfQð¿‹E ¿nˆ˜ãˆšíu Òa;kœÙã±vűLÁ™Ç½‹±€u$lgèy¯ùiF'câ$¤ZÊqé¹ý<ðä¾yÀ̰À>È\Ç®=Um=ÌåF­R Ùò˜žœ±Íu¨½òjÚRÑŠ$±RHaãFZãI‰§b<©è½ð'ùìùµÿýÛL>”…¢S £V«a›<}ŸÁû9<º—ááIzúJTÊEj½}”óŠr1G¹˜£ÝŠ)æáGßÿ@Ö=†áz>ÅH¥@T+Uò…"¹|ž|±ˆÑ†iòx"mx~°e!ñÒâ8JÂxJ{Ì“IÃrÃÙ=ž³ôÊ·g])?  ¤R|Á¹öõ¡P=÷m ³Î;ƒWžc¸ýÁA†F§Y½¢2ŸqœEi»‚¬[§èúLhÅèD‹FËð“W¬!,­bË£Û²Ðssk9ә̶bšR+÷„å2F!ŒÀÓ6ƒºâŒsgœÃÿýòþŸû)^yéñÍoÜÄí?|˜‰8@µëq]YÁ§~m=£/¯L¹V¦T«`Z3`B”2¨DÑ[-QŸ%j7ç¹rÝ@æþu3Ʀ§s榌š ó $(TÀØÉØEöøBâ/„‰;¦ðµzÆ€B[±-hW8ñØ“OÒ¨7þžbšÿ‹ª—yE8ÿÊw3\/±oϹòo¹j?>¾;Ø'Ð2S öZ*J+~nœçvÍñŽŸ8‡\y€¶î§Q·ÖÿÞ©åWý ¹âÚ?fpd†‘áÅÊrÞõ†£øÒÍÏ33לçÌs0A½ñµ;ö„~æÍçS¬,gÿÞ)ÆŽ¡¤f¦‡6ü*+WQoG4â„Dƒl‚Úi IDATr9íÙ —öm¨Å¶þ¯À”ILÿê39ûµWS,•ð“–;µ nqÁiš™¹9òÅ<Õjb¹_5=‹š6y¸NµV¢oY™jo/3“ÖH#zi:7Ý»@Ù¢2†R±È{ñ§) Ìh—礤𼱉µF|8^„ÃS³Ös™:q·æ43M¢ÚøxžCâ46ªæ{.p œü·ñ˜¬ +Eìž o`%g¼ñ·Ø{×_Ón °ñ¬Uüø«<.>«Å½í§§rá¦>zª¹#"|Æh¦fÚlÛ;ÃlSóso¾¾žai€í[Þ?‚1†D ž—qÎ+¯`.ŠiD’HÚQ1Æ3YœÃ(;ƒXƒåêŒAèÄâ H‰”:nC¡“6&‰xÅz¡¡ z{Jä EŠ¥ rnájçê-jÕµJ‘B­£ãy*`¡ `áòæƒF¦[_o6ß~ׂ3?÷ô±ˆÜ Ðw)û<£ðµÂ([ª-TÂèt ™hSôўɘÀ§s³Ý&À¼Ï®âÖÀ¦ ¯ I~›=w|’ú\ƒs.<‹+üÌ›ŠÌÔ#žÙ>ÂätÓ2Tá³?—þÞ W¾êlV¬ZO¾<@½ñÄý151ÁÐL<žÏ½†3ßz sqB=NhKmE¾NÕaÔǸVqçûmU‚V ZÆv¨ŒÔl‚J.ÞcïökÖôS*Wð}íp …ði×Û¬XÕG­§— \A»“2@Zÿ—)2øØÅfC¬ZÞOKÉKnî>Ú'ˆ›´ÑŸD*ßÑ#cŒ”lžbûÖg8ç‚K0£È$€ñLB]Œ:RÀrvÎ\|ÙëéXÁC_üC&ÇeÝÆõœ~Æi¬X)ù‰ZcÔ‘7äË+èY}^®ŸÝÏ?Åã÷Þ…”vüëd;dÏò·³éõo¡Kê±¢@b°½€`CÝZƒ¯1ÊOŠTÊ›Â~¿²C'µ±ÑFíÂÈZ%,+)ÖôûìL$ýËJäË5LÒ°OÃØ¡ ¥ZOjß &æê<ÿâ$¯}ýÆy6@ZÌ‹÷ !ˆã˜;p?s&ÃC® ÚGø€–Z'ñ×OìûÎg­{÷û–§ ¥‡HbòËNãæ>ÂϿؚÌ+PÚø"£}ª R50, @6l<—¾ßý'¾ý¹¿¤ýÂ3ìݹ—Þ¾^Öž¾†j­F>ç“Ë[1E’8V4f¶m½Ÿ¡}{‰šs V°½¹šÒe¿À†›¨G ÍXÒVÆN õ(<‡8 |'î5ž¶a_• VÑ%<ÚáÛbžBÏ_t†Ç¡CÓT«Êe«ÿ§F÷xVÝŸ¥Z)ÒÛ[a®¥Ùü¥òc—]q„ØÍ© HH>úñOr`h?ÌQ,h¶š˜ °]ÍžÀ FFúÖè)caôc NZ[WCIÐZE Ö0:<ĪÕëPRây:c€îµßÍ ŽðN €µ¸mçGo­—÷|àÏÙµëîûÚ'©ìåð¡ =5óƤ%„€¡%}´z‰Îü)Ö]z‰¹¶¤­‘ÒØ`¯Kl9 `³€‘ÌT¦Æ àäYçœËÞÌôÜÝq3CÏݪ&¤EÙ·S@ë±OSåhR¡Õ勯¤oÕjŒ64ÚvÅÇÚ®fiRdqöÜìœ{ëÂÔÎÑaY Ó$~¡q k„°ØÃZ¡dÂEŠ<ÿtÄÚµË(”kh™F>ebhµ#VVãÙ}Oîœ"ðlæÛ «…S&øþÝ÷ø!~ØtRŸ7l»¯ä11ÓÜLWÂç”0ÀïÞx÷º«cP)µÎ íI„Ÿ`d *æÑýã¼C+”«¢ñ]˜T*m™8R ,¥ Ò[·6Ò¶¼·—w^ó^ôÏþW äl SÓ³´ÛmzjUÚ;Íö±9òZÑh+ ö¬lzZyÆ&¯ÜJÇ·HiiÌB9o9«"²<Ò¹o‹h•J.ÏîiÜC+ÉY+… ACOO‰°Paf²l1vh–J)G¥Rà+ÿú"~X€0t¢Û;B¤[f&bçî½øaÏóm¯„2×j#¼*gõ—hL·‡øÆ=Ù£<ø‰Ö&}Wó~ÏHŒìŒÝ$AÄ1íÞÓyò±‡¸ôÕW¡$2m¢´Õ7ï-¦:„ïRnñY´É;WЄŽPåý À÷× ôЊÚ=ÆmÛƒÔxÆŠQ™úøÂ`<\RËå,¬À鸕éEGýôÌs F© 0ƸâU’eü‚u‚Ñ‘j•<¹\€–i7^¤³jfbºMµZàñfšhäKä‰yÔ@P*öì?` ïøAHZ¨Þ¦†\ræ@•Û†ãXùévB0qžám´6JaÒ€ŒŒ@¶A+n~èi—ÈÑ$‰"‘I'LlL×]™ì0/k`ºþoÁ)€ÑÖµ´Ò"m1t炞Rž+Oï#QÂFö´µÖMeÊt`ãµÓßÚ¹•v6°³)³aÜÌN¢+[ùZÙÔ²Œ¹p­Ï¡Ã³ôô” ò%b ¹Àr˜/|f§g©”ó<µk/Èã‡v/—ËYáG ZLìÚ½×çú¶<=BÂÀc¼)yÃÆ~ÆÇÇÈåKènÑkõà 2Àþ[?û¢‚猲cVŒN@Ƙ¤ 2¦µâ<¶>÷ŒíÌUÊ‚)%±«2]DvbØ=ÍŘ`Þ5º RܤD7ÚŽ Mõw_O²Ñ0Ê •Ëbh—Ë4ntl6¢Ö¸‚å;4iQ‹èb‘‹ÆØž©$JÆ“pîê€f#¢oY‰0_&n7³"šF¤‰¤T*0>mð‚áçAHÃ!ˆu·¢§i$PÁl½Y‹Z@.0x`ÅþÓX³¬Æî‘‰Ãîø§]¼\À=øO)ccZÙx€ŽctÔDhÅ>š%dT¢HEÇ6ÒÝõ³à.¼ã4!ÃLBj±/°!„ðؾm sÍ6Fvf t– ± æ“l×6gbtêûwÒÞ˜4,,2&Ðî3lŠ:áU§ÄÍïS­ä óêS£ÙŸ£T.P©æx×ϳ „x^@>_8 <Ïv'ÏNOðÌÁi6T} 1kòNåñ¬~8 üÞçþY ±)!¹¢bT¡ã#ŵ|ë¦/c°A)“lhr"UGt¯ô…¢>û»K˜Œ:»ä”zLOMòÇ“͉ë#%h;Îj†,›˜ê|••h‡¢SØÀŽ*ÀâháÔt,%Q2áüÕ026EOO?Èã…eâÖTvÓS“uÊåR!ÇU—n" lÙV¥”c ¯çˆçœÒ¯;òwé+.´¶‚ïÓn6xpË.ÂXU)òÜ‹ƒƒ?¼éŒÛŽ—ž'50Bï…Õh‰ImtÔÂó|œ ùüŸ´cX\÷J[FHäü‚‘n&8Rtþ¿›Qæÿ:;£ ú‰OQzÅOA"Ý Oã&ó:ÒH볕¬]1‰“).€îbŒE!w`‘Á” ÿž¿6`b²A­V W(Òj'” v¤œ„LLÌP.摸õG»žžÇ¥ëûíXŒ†—\t>?{õ›ñ=ؾs'áê³YVÌ!´dBþâH˜m'Ń·ýãg”0‘‰µÜœ“D˜¨E¾ÚÇÎüF>ñW%n7ÑJKI;ŽíÈôDº™ýÜì°dÿv3+×V2áË_þg&N»!m›º°•)V¤ ›ú&U+Òœ‚N¥„îHã^˜‚I3°ó„\úY&Ôr’Óû}Ú턾Þ2a¾B«>Ýûìl ߇°àó¡·ðÅÛwƒçÓ[*0ÐWe±,ÉR‹øŒ ëØ¹}+ahÍ¥+K<¿ëÅxøþÿÿïÇBøŸ‘FÙ€– cŒŒÐI Úmü0ÏÔÚ«øûÏnF«®^¸Øî)tº4t{ÝvAÚ¹óÝ[¿ÇÍ{! £À‹WtbExú6ë ZÉê|›êNKÈÒr5mRÀIaœûçJÐ;pê5g‡Lž¢ÏQ*‡„…õ©±ì>Ç×)—òì‹Ù²w\ýú^ß~ê%¥É­Ôéº019Åç¾ø5†b/W ‚Ð’‘vðw,žk;ævÒ 0xûçÿÒo‡V›• T‚JZ˜¸…0šý•sÙ³{Gæ¶ã„(r’ Nœ¨Åw>,î"ÎW AXë§¶æL Lmì@IcùdËê©ÌìØi±Kê%¤ ªi—Qª´Ôö\jt£TŒLÚœ· ÆFg¨õðÃZ„ € -OÏ4)—òøžèÖ¦è-å1 ~áÖm|ïŽ{84>Ž—/ƒ”œ–7<½u{{äÁoþÁÉÒñ¤À¾ÛûMeŒ2R:°IŒŽ#ŒŒðs~ê”LHâÄÎåÚQL;Љ“©T† ÐÑ·Ðu°ç ¥s±¸‹}§qF[flvÆû:¨YÑEz®Õ—­Dél­Ñ:A%1IÔ¶(Þk¦gZôÖŠä šˆbÑ–É ?dâð4åRŽ+/ÝÀù›úI#]'P¦ƒ=x¬­EŒÃH…Ib¶½°Ýœ~ídÉ/‘oÿ§{à»ZY€$-¥ªÄŠ¢“Dl°(‰”Äí„(Ž*ˆi·cb™¢U6ïxž¨_øxR&HI)„°P¯F€°Ñ<«÷ÉAYÛ--hsÆi@Ç1^Êt®(Tw¹Š«óU¡Ú2n£’6kû %M"%½½EÂB™ÆÜxÇúŸjر¹•<ùòrþÛÕ¯Èl“ýCö#iXÌxý•—1:]·¶VÒ¯ Ü}ø™ÜJ§d÷„ÕÀK“€ðü_UÆLÙ‚ˆ$hÛsc’ˆ¸ØO³Ù ‘ ±´6@;ŠiÇq—$HH¤$‰“,z·¤ ˜^66|üè³[ÚXìíV¿“Êà8.Äœæ!œ^wœAšʺš Ã$ÐZ¡b‰q¿O&‘e„¸ÍëÎÎsðà•J|>GX¨17Ùñÿ'§š”J!•r°ØÃ+Ï_‹ï[ûcp¢Ž”Ê£ñÛŽtÏ9ûLþìúßAÜ®Ïí}ö:^,V1r”í%3Àïa’ ¸^ki´J0.ÍHK|DcغåYë&Ö%lÇ’v{¾:ˆâ©$I,‘é,ß4‚Ó% „#¤ç²Œã…uö?A% ü¤U§ÇH]>g/Øè®*&c¬¡—$h!“™DVÿ'mTqÞ*±1ÿòEbé‘­t Â㇦)—óù\¡L!ôYÝçƒ14¼2õF½SÅÛµ-åüÌÛÞÄ_}‰Qíú§ãƒuº`_O†~/™ïøâg´çÝldŒ–‘ÈìV‰NlÍÜ[_DJ•Ùql%@äˆßj[uE±S 2‘È$±9e[Ú2¼>ßÖåß|ów˜Óy«Ÿ•D£lXW¤*Ru l±§fH¥ƒÀª±8AÆùø8µdOŒ–1Ê_FF¶9ç´z=bY_™\±L£Þ ³–Z07[§TΖ„öî;ÈC1Æè¬ã·»t±P00ïüºßxn¿ðG¿ ø™“`‚S†T áŒð^drFš9õ±Vy>ÉLb”±Æ¶ØŠXÕÕЩ” ¹0@ûÚ6a<ßnâøFJÏLñ½-cøË—adÊ…}}ƒ0>i¼?Ë!cK¿pV†ÖÆö:hc\œÀ^O[ÎP.ô$h£œŠ{åú€@Û8~µV$ÌW¥èÈ09Õ¤RÊS)çÈûÙöÂ~çS?´Ý@O^dñ‡ÙÊ¥’ßÓÓSh6›Ùô/NRœ2¾û«ñÚ7½ç§•n?„ŒKž6(F´ÂGäËŒŽ Ó¿|J ´¯ÑÚG;}[) R( •e‚0°èc^»v½ÀsÏ<Å×nû‘ö)÷-£zÑÛâZ%x*Õ§N° a zœ¬7ÎH=63˜æ œ[èÜA^€ ¹`—LÐqŒŠ#Tñšs+§ZÍ„~¾Jsf Å^;Imr²N©œ£\Êqǃ»¹~ó}˜ Œ—@Ù“Hµ¸°˜ =ëáám###1óWÿIm§«dèî/?»ö¿ü!DŸFÇžˆí<^°Rà‘Gâ-o»i,^R®›Gi´ \jU£”$ ›f Š9ÍÖí[ø£ü6µõçS»ò—±õ¦d‚Nl‘—1ÚâÉtZ¨²Ö½o K0N«D–À ¤e²¬¡6i‡Ah);®Œ8wU‰=sôTÉåK´[ŠrÑŠô\±ÈðÁY»ºÆ¿Üq€ÍßÙC˜/Ík›C-ï_Ô \Êh4õ뮻¢wo§ÄèÞ†~ðÕ¿Ó~xƒJ$ZFHiW‹‰›ìž¶S°µK[c0±Þ@Y£0ŠiG ­¨cD±d¦•ÐÁëÈ•{¡Ý@·ëèV¢*‰qlS³.¹£´B[§—1–The-y#]“‰”`\g‘ê‚”IsYPÈ©' “°iEH³Ñ×S$Wª277C>g«ŸZm[7Y*†¼æ²s¬t“RÓþª¹Èª?ŽÓp—RÆûØÇþ~Û¶mõSE¯SÎïý×ß3Aøe“DG˜¸…ŠÚȰÌC÷ß” = ¶#wtn¡%~D+5“˜UË—YÃ2j¡Ú LÔBGmTܲ!håZÅdÒÕ6¦0J»Îá™Äè´óXvcXäT£: !ô¬aÊ$–ÞpA•ÆÜ,AP)ç Uf'†ÉÜ¿é¥RŽjµÀ%žÃ¥¬á;ÔÚm¬*H> cìe!é®k<ðÀ›7oÞž}ÉуˆÇµ½, pðþ›Þ«ÿv•Ä訉›è8âÙ¡)ZYdâ<¶ 2AÇDQB”ØÈ¡” ÓÓ“üí?~#-±Q *i£U4H”*mUÊ¥l”TmK·Œt­dRf¯ÓÒá§’ìl˜Ì]ÐZ» (+Ù®<§Ìý‡¨U a”h7mú×÷&Æf(•r !¹R•_zû%.¸å O Ë{mÓÈb3SW\qÅï|ç;Oc>ñ_#¼l `¤¼ZÀZƨvd‹F*ËØ³k;[2%&ˆ;#G«ÄÖÙ)‰J_üÊ×/mÂÄmtbc þ@G0“ÞqJZñoW§¹Ô2ƒ{¯Q.ìÛAÁI™hÂØš?›言sN ™šnRë-+•©7"z*yëÿŠŒŒ¢TÊæ{Èå+\xÖJªíò ÆÐŸ7ŒpðàÐ1Ÿ%@>Ÿ/Ýpà ×U«Õ´wì?¯~äe”|ƒ0Üjd “Øò±½G]{•üE‰‹Æ1JI á ƒ‡¦ÙœåEVã‡9tC¡dÒíNÇD›dŒÒª“§Hb×Ö–ª• s°> -í볆S§RÒH§’Ë pZG%ôÕJ„Å*³‡É…¶=«>†årž\eƒapxÜ¡;¢%ÏîÚÏ3{Gñ µ#žÝR^@___ÿW¾ò•ß=U4zù Ý6ôÄíJ|«×~âêÏ«¸õ?…ç±§±cËSl<÷b0IZZqz{ûxðG÷13>Ìà¡)üµWbâáRÏFX@gáùY(ׂCfmƒZi„Vh‘†{Ý&l&ÁÎ/6®´“2N1q¨eÆ‚”Œ1qÌ[.«2~h‚B!¤P Éz˜ž|–å5[709e³Õjž\±—}†øø??رö›*¶¨ÖÈ#}´¢ž3Î8ãuË—/ϧo:iàe•éf®ÁGoùϘ?7QS{¹"÷=½¤Ý ÏØ‘òV K|¯¾ü2¦.bvÕ+ÑQÕª£’–]ÍZºŠ^ÏW.oßUÖe-~åÐÅl$ÑÈtŒj›Y“)ÌLbãýiRKF¶ÞÑES&¸lS•ûQë±õJ‡iûôÂB‘ёÔJ9òaÈ–Ã\ýëÿÀîÁY² Qmë(1$ÒÞÿ‚h`w$pa”0Š"Ùn[ð6^¢;ø²K!D°øÈêW½uØxþ_y=ˋ߿ý~üõo Ò3€†œohÎLrßí÷0˜ÔÅ~ŒŠ,@ØÉß:€À'Íñ€²?®×Ø~±±P6iûm–îÅØêZDÖé“a»úDZ.®Ç 1&± ræª'w·9sãròÅ*³s új¶°Ó lú÷¬3Wòù[÷òß¾?gë€,क±6‡Jl§õ äp{챯ÎÍÍÉc¿òØÛË"„¾"'„( !*@Õí•á'¿ÿèзšvkèUîùá}¨¸A(4¨ˆ­[·°'¿Át¾ŠŽæ0í*]‰q‚T±3æR]íª’\ƒ¦5ö\ÁªÓãišZËÄ•¯¹s»k±#t’™FILb Ç´⬕!•œ3ôô‹U¦d/3Óm ùj%O; Hg&Û –SEÚ Œm Ñ Gy–óþÞ½{÷ ïÿû¿uªhuJ@Ø-B„e`±½’žOì~bäз½Õ“òž©pÀÜ{ï=`$/¸äâ‹-t¼LÐqÛî2B˶%–Š;¢Z»´lb«’•Š-C¤nž3­Q窖¤ÄÙ1ôâ4} Ü¹Q”¶Iß㼓5}{÷ŒP)ÈåCÂBÓÎÿ÷|Ÿ‰‰YÊ¥åRž÷üìkÝ  ‘{RUeVmŒ’O¬?­ÿã±ÆÇÇGßýîwoƦYþc#Žè"”€â"{iÁÿ¥—dÔÌ?òÿ+§GnlÐzðG÷"ã˜8nãéî«#Fê¾¹¿•²™9-]r&}}Û×%¿µŠÜkÝg¹Un\jWÇ‘Mï&mëOëtÒ¶(e `ï~j‚;¢V-ØæÄP°¹ò¥Cƒ‡(—s„¹nøòÃ`˜KÓ?šyñ>,no ¾1æê/‚ øð‡?|Ým·Ýö+J©€¤ãàŒc&y<BÇ+Òyóþ‚ýhD=ékƒ;o¼spguíù—ý↳/8w. 3³à&{Oàið}ëJù– „Và{Ö^0ï±v5y¦JXÖ¤a¢ôº«J Ct­Ã6gú?àþîþô—7pÆš¹b‰á¡mTkenüÎ^n{ä&g£¦jןoN ?LÓÉß§zÛرcÇÌš5k4]*ùhõ===Ë{zzò“““^×sëÞµ;ÓU<6R¨õáS™ºÔy÷µãÝýEÎÓjhÛã7 m{¼T^µñµ•Ó6]àùÁ€a´@ûÊŠ~ÏChÏI€¤ßbýÙ@çhºOҢЮ\ŠYðZ'„ѧ“=aGä /@ ŸÍßâ¬u5Ì”àŽg&¹çé]$Ê4dÔÜÍŒïÀâõwWý-ŒÞ™Í›7?³cÇsíµ×¾ '–Z¼I’˜{î¹çŽÉÉÉ´ d)Úh!„gR „%¶—@ÐKØ 4F÷<ÐÝóX®Ò;P[sö«‚Rï&ð+®t×*ú´’ÇsÐÂKQ§:c:s€¬*°{ÚõÐqxÆtÐÇ] † ãŒLÅ|àÆmŒj$2jMƳTÜž¦ƒÓßÂjRtôt7Q< ùÁ~°mdd¤þ7ó7ïèYý3ÆÐn·Û7Þxãw?ò‘ÜÖõ9/)(ާ‘tñw,‘~¢*`©ÏMÝœî=»VZ±~}yņ übi%~XÆó„ð<Ëž÷_Pla ÀlË ÁTî§•¢î?mEˆUJcŒ´¡c‹dtÜnËæÜl4=v0ž›šÂ9Æêù«?×Ò 3·ðK¾W¬XÑ÷õ¯ýš±±±þõUGï½5IDATë×S*•x衇ÃpzóæÍ_xòÉ'w“ÀV­Ì¹ÏO-5•1æ˜*àx@p|D|)ÇÅ®u[¹Ý{Ð}ôó¥reÍ™gåzW¬ó‹¥~ãùEá{"mòšu.µ•¢ÝS(ËiQ¨ýZÛ Z¶dÔ˜Š§ÇG£û‡tÒŽ»>XÓa€ˆÎêO‰“ÎìK±û¡£ört¹Î¹\®pÝu×½ãíoûùÕj•{ï½wäãÿøÆÆÆÆ°DŸÆƒšaþH¸„ù pLâtžÙ’nàɺ„‹ý}´kÝ„ïÞ|—ð‹Ë׬Ì/[µ*¨ô x…r†%ð|#ÒÜ„OØßoÅ©Í K£”2*nªvkZÖg&¢™±±öáÑq²ŠA ã4¦[:•;¦Ãéž^K‰“ª€Tg§Ò-õés@ø¾÷½ïªõëׯ¸þúë¿ÇñVšÌ`íŠtXJül,¬1æ¸ÝÀb8Â%Êqáy÷>oˆc×}wÿ®…ß}„:Yâà k[$½Ñ&òO”øév4â/ü{!A#¸9šuÞÕÓ4Uu„:z)„Ͼû?+œÈ¶È<Öê?šp¬ã)%@÷¶Üa)8¥ßûo—äk]OÞIEND®B`‚gnome-control-center-signon-0.1.8+16.04.20160201/icons/16x16/0000755000015600001650000000000012653651300023311 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/icons/16x16/credentials-preferences.png0000644000015600001650000000176312653650644030634 0ustar pbuserpbgroup00000000000000‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<pIDAT8]ÓKh\eÅñÿ½÷›Iš4™iBRRÛIˆI5I‰´4M[šŠ… µ)Ô¢ Aq£ hêÊ…P]Š(ˆ]TZ‹ÆÐ4©™¤Ió˜šÉû5y93™Ç}̽ßçÆñ¬ÏÙøiJ)þ›®óž(,)}³.nJ«b³Ëö`4±·ã3[“}éõ…Ià¾R* ¯\ùµ`*µy­ñPKWÆV¾ö¶f|>ƒxV÷‡–O½qöì©ö¶ËPÒ¾72<‡/ÍÍÍý¦)¥Ð4M»pé«©Œ#^îl£gxžšê±ø™í8¯uìãhKï]þ‚báñÉïÒ××7ÐÝÝ}F¼õé·7^9ÓÙ 4È{’†ÚJ¶I°*ÈúT?µGÉf3¼~îü>A2™$®k:Œh:ðâKÏ?õñþŠ2<¥ˆÌn×E%EH¡“]q¤q?žç ”SXP€išäLSïšZòòwªCe$s6ßýeWY Á@!†O \‰^`tòMõaLÓ|tvÿÀ]ªëv‰ŠPðàÕž1ÒŽÂ,ô¡4á<·‚±Y6²Ò¿?¦»¹ä}+“àñš J)Be»xûô!WïÆq]J£9Åj2‡a()±ó#“1$î¨î¤R_gÿ^µz†þBJRánÞÃÉ»ØRai:yBjöV³²ÇɤÝ–_êó½ßä¶?»þ{/·þœÄqòØy™Í,Oa»Ó²°! KËŒEçPžùùü†ÀÌÍo>ª=qîéÛw÷+òIÆD׳Ȃ<å!MŸ™Å0 B¡ ñÕÅééÈû0)¥”¦iÇŸlmþùæ­;]+Ûº, ‚χ”ž™ÁZ]&2:®–æ77¦#Õ¿Œµÿsnê|õp6ï^ÔŠËŽHC¯×Q ¥Å°­HbâvßN|nB)yØÿygË©~:µÌIEND®B`‚gnome-control-center-signon-0.1.8+16.04.20160201/icons/24x24/0000755000015600001650000000000012653651300023307 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/icons/24x24/credentials-preferences.png0000644000015600001650000000310712653650644030624 0ustar pbuserpbgroup00000000000000‰PNG  IHDRàw=øsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<ÄIDATH‰•–[lWÆgfgo^ï®/I¼¶_"'©Cbì¤iˆH"‘*Tu ¢¨¢‘ª4¼ñREEB‚Š·J!a@"*¥Â%"h,+;—¦¹gml'koÖÞz}ÛûìÌìÌá¡É*›Dˆé{;çûé|ÿÿ¹)%ÿïBù$ ñ?æ‹—_ûÍ|!»×çöô„‚E»|#:—Éf£Vnuòù§7Äs+Éô…+ÓñÙÙDX–R:š¸çüÚw~Ò›ÍgþPÚ–²»#¯ô³±©žt¾ÄœîØï»ÓñâîÆþ¶-ûimëÂëó£ëº‹Ån Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/0000755000015600001650000000000012653651300025030 5ustar pbuserpbgroup00000000000000gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/account-plugin.h0000644000015600001650000000220412653650644030141 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef _AP_ACCOUNT_PLUGIN_H_ #define _AP_ACCOUNT_PLUGIN_H_ #include #include #include #include #endif /* _AP_ACCOUNT_PLUGIN_H_ */ gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/client.h0000644000015600001650000000263612653650644026500 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef _AP_CLIENT_H_ #define _AP_CLIENT_H_ #include #include #include G_BEGIN_DECLS typedef struct _ApPlugin ApPlugin; typedef struct _ApApplicationPlugin ApApplicationPlugin; ApPlugin *ap_client_load_plugin (AgAccount *account); gboolean ap_client_has_plugin (AgProvider *provider); ApApplicationPlugin * ap_client_load_application_plugin (AgApplication *application, AgAccount *account); G_END_DECLS #endif /* _AP_CLIENT_H_ */ gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/account-plugin.pc.in0000644000015600001650000000103612653650644030723 0ustar pbuserpbgroup00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ plugindir=@LIBACCOUNT_PLUGIN_DIR@ provider_plugindir=@LIBACCOUNT_PLUGIN_DIR@/providers application_plugindir=@LIBACCOUNT_PLUGIN_DIR@/applications Name: account-plugin Description: Base classes for developing account plugins Requires: glib-2.0 gobject-2.0 libaccounts-glib libsignon-glib gtk+-3.0 Requires.private: gmodule-2.0 Version: @LIBACCOUNT_PLUGIN_API_VERSION@ Libs: -L${libdir} -laccount-plugin-@LIBACCOUNT_PLUGIN_API_VERSION@ Cflags: -I${includedir} gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/oauth-plugin.h0000644000015600001650000000667512653650644027645 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef _AP_OAUTH_PLUGIN_H_ #define _AP_OAUTH_PLUGIN_H_ #include G_BEGIN_DECLS #define AP_TYPE_OAUTH_PLUGIN (ap_oauth_plugin_get_type ()) #define AP_OAUTH_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), AP_TYPE_OAUTH_PLUGIN, ApOAuthPlugin)) #define AP_OAUTH_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AP_TYPE_OAUTH_PLUGIN, ApOAuthPluginClass)) #define AP_IS_OAUTH_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AP_TYPE_OAUTH_PLUGIN)) #define AP_IS_OAUTH_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AP_TYPE_OAUTH_PLUGIN)) #define AP_OAUTH_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AP_TYPE_OAUTH_PLUGIN, ApOAuthPluginClass)) typedef struct _ApOAuthPluginClass ApOAuthPluginClass; typedef struct _ApOAuthPluginPrivate ApOAuthPluginPrivate; typedef struct _ApOAuthPlugin ApOAuthPlugin; /** * ApOAuthPluginClass: * * Base class for account plugins. */ struct _ApOAuthPluginClass { ApPluginClass parent_class; void (*_ap_reserved1) (void); void (*_ap_reserved2) (void); void (*_ap_reserved3) (void); void (*_ap_reserved4) (void); void (*_ap_reserved5) (void); void (*_ap_reserved6) (void); void (*_ap_reserved7) (void); }; /** * ApOAuthPlugin: * * Use the accessor functions below. */ struct _ApOAuthPlugin { ApPlugin parent_instance; /*< private >*/ ApOAuthPluginPrivate *priv; }; GType ap_oauth_plugin_get_type (void) G_GNUC_CONST; void ap_oauth_plugin_set_oauth_parameters (ApOAuthPlugin *self, GHashTable *oauth_params); void ap_oauth_plugin_set_account_oauth_parameters (ApOAuthPlugin *self, GHashTable *oauth_params); /** * ApOAuthMechanism: * @AP_OAUTH_MECHANISM_USER_AGENT: OAuth 2.0, user-agent flow (default) * @AP_OAUTH_MECHANISM_WEB_SERVER: OAuth 2.0, web-server flow * @AP_OAUTH_MECHANISM_HMAC_SHA1: OAuth 1.0a, signing type: HMAC-SHA1 * @AP_OAUTH_MECHANISM_PLAINTEXT: OAuth 1.0a, signing type: PLAINTEXT * @AP_OAUTH_MECHANISM_RSA_SHA1: OAuth 1.0a, signing type: RSA-SHA1 * * The authentication mechanism to be used. */ typedef enum { AP_OAUTH_MECHANISM_USER_AGENT = 0, AP_OAUTH_MECHANISM_WEB_SERVER, AP_OAUTH_MECHANISM_HMAC_SHA1, AP_OAUTH_MECHANISM_PLAINTEXT, AP_OAUTH_MECHANISM_RSA_SHA1, /*< private >*/ AP_OAUTH_MECHANISM_LAST } ApOAuthMechanism; void ap_oauth_plugin_set_mechanism (ApOAuthPlugin *self, ApOAuthMechanism mechanism); G_END_DECLS #endif /* _AP_OAUTH_PLUGIN_H_ */ gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/oauth-plugin.c0000644000015600001650000007611212653650644027631 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /** * SECTION:ap-oauth-plugin * @short_description: Base class for account plugins using OAuth * authentication. * @include: libaccount-plugin/oauth-plugin.h * * This class helps creating account plugins which use the OAuth authentication * method. */ #include "oauth-plugin.h" #include #include #include #include #include #include #include #include #include enum { PROP_0, PROP_OAUTH_PARAMS, }; struct _ApOAuthPluginPrivate { const gchar *mechanism; GHashTable *oauth_params; GHashTable *account_oauth_params; GtkSocket *socket; AgAuthData *auth_data; SignonIdentity *identity; SignonAuthSession *auth_session; GDBusConnection *connection; GCancellable *cancellable; gboolean identity_stored; gboolean deleting_identity; gboolean authenticating; gboolean storing_account; }; static const gchar signon_id[] = AP_PLUGIN_CREDENTIALS_ID_FIELD; static const gchar oauth_method[] = "oauth2"; /* Keep these in sync with the ApOAuthMechanism enum */ static const gchar *oauth_mechanisms[] = { "user_agent", "web_server", "HMAC-SHA1", "PLAINTEXT", "RSA-SHA1", }; G_DEFINE_TYPE (ApOAuthPlugin, ap_oauth_plugin, AP_TYPE_PLUGIN); #define AP_OAUTH_PLUGIN_PRIV(obj) (AP_OAUTH_PLUGIN(obj)->priv) static const gchar * get_mechanism(ApOAuthPluginPrivate *priv) { const gchar *mechanism = NULL; if (priv->mechanism != NULL) return priv->mechanism; if (priv->auth_data != NULL) mechanism = ag_auth_data_get_mechanism (priv->auth_data); if (mechanism == NULL) mechanism = oauth_mechanisms[AP_OAUTH_MECHANISM_USER_AGENT]; return mechanism; } static GVariant * value_to_variant (GValue *value) { const GVariantType *type; switch (G_VALUE_TYPE (value)) { case G_TYPE_STRING: type = G_VARIANT_TYPE_STRING; break; case G_TYPE_BOOLEAN: type = G_VARIANT_TYPE_BOOLEAN; break; case G_TYPE_UCHAR: type = G_VARIANT_TYPE_BYTE; break; case G_TYPE_INT: type = G_VARIANT_TYPE_INT32; break; case G_TYPE_UINT: type = G_VARIANT_TYPE_UINT32; break; case G_TYPE_INT64: type = G_VARIANT_TYPE_INT64; break; case G_TYPE_UINT64: type = G_VARIANT_TYPE_UINT64; break; case G_TYPE_DOUBLE: type = G_VARIANT_TYPE_DOUBLE; break; default: if (G_VALUE_TYPE (value) == G_TYPE_STRV) { type = G_VARIANT_TYPE_STRING_ARRAY; break; } g_warning ("Unsupported type %s", G_VALUE_TYPE_NAME (value)); return NULL; } return g_dbus_gvalue_to_gvariant (value, type); } static gboolean emit_finished (ApPlugin *plugin) { ap_plugin_emit_finished (plugin); return FALSE; } static void finish_if_ready (ApOAuthPlugin *self) { ApOAuthPluginPrivate *priv = self->priv; /* Check if some asynchronous operations are still running */ if (priv->authenticating) return; if (priv->storing_account) return; if (priv->deleting_identity) return; g_idle_add ((GSourceFunc)emit_finished, self); } static void identity_removed_cb (SignonIdentity *identity, const GError *error, gpointer user_data) { ApOAuthPlugin *self; if (G_UNLIKELY (error != NULL)) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { return; } g_critical ("Error removing identity: %s", error->message); /* No special handling, we are quitting anyways */ } self = AP_OAUTH_PLUGIN (user_data); self->priv->deleting_identity = FALSE; self->priv->identity_stored = FALSE; finish_if_ready (self); } static void finish_with_cleanup (ApOAuthPlugin *self) { ApOAuthPluginPrivate *priv = self->priv; if (priv->auth_session != NULL) { signon_auth_session_cancel (priv->auth_session); } if (priv->identity != NULL && priv->identity_stored && !priv->deleting_identity) { priv->deleting_identity = TRUE; signon_identity_remove (priv->identity, identity_removed_cb, self); } finish_if_ready (self); } static void finish_with_error (ApOAuthPlugin *self, const GError *error) { ap_plugin_set_error ((ApPlugin *)self, error); finish_with_cleanup (self); } static void finish_with_cancellation (ApOAuthPlugin *self) { ap_plugin_set_user_cancelled ((ApPlugin *)self, TRUE); finish_with_cleanup (self); } static void account_store_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { ApOAuthPlugin *self; GError *error = NULL; ag_account_store_finish (AG_ACCOUNT (source_object), res, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); return; } self = AP_OAUTH_PLUGIN (user_data); self->priv->storing_account = FALSE; if (G_UNLIKELY (error != NULL)) { g_critical ("Account write error: %s", error->message); finish_with_error (self, error); g_error_free (error); return; } /* Emit the "finished" signal in an idle callback, or this will cause the * destruction of our instance, and specifically of its priv->auth_session * member, which hasn't returned from its auth_session_process_cb() * callback. */ g_idle_add ((GSourceFunc)emit_finished, self); } static void unset_authentication_settings (AgAccount *account, const gchar *method, const gchar *mechanism) { AgAccountSettingIter iter; const gchar *key; GVariant *variant; gchar *prefix, *full_key; prefix = g_strdup_printf ("auth/%s/%s/", method, mechanism); ag_account_settings_iter_init (account, &iter, prefix); while (ag_account_settings_iter_get_next (&iter, &key, &variant)) { full_key = g_strconcat (prefix, key, NULL); ag_account_set_variant (account, full_key, NULL); g_free (full_key); } g_free (prefix); } static void store_authentication_parameters (ApOAuthPlugin *self, AgAccount *account) { ApOAuthPluginPrivate *priv = self->priv; GHashTableIter iter; gpointer key, value; gchar *full_key; const gchar *mechanism; const gchar *username; username = ap_plugin_get_username ((ApPlugin *)self); if (username != NULL) { ag_account_set_display_name (account, username); } mechanism = get_mechanism (priv); /* Delete any existing parameter (if the account is not new) */ if (account->id != 0) { unset_authentication_settings (account, oauth_method, mechanism); } /* Add all the provider-specific OAuth parameters. */ if (priv->account_oauth_params != NULL) { g_hash_table_iter_init (&iter, priv->account_oauth_params); while (g_hash_table_iter_next (&iter, &key, &value)) { GVariant *variant = value_to_variant (value); full_key = g_strdup_printf ("auth/%s/%s/%s", oauth_method, mechanism, (gchar *)key); ag_account_set_variant (account, full_key, variant); g_variant_unref (variant); g_free (full_key); } } } static void store_account (ApOAuthPlugin *self) { AgAccount *account; account = ap_plugin_get_account ((ApPlugin *)self); store_authentication_parameters (self, account); self->priv->storing_account = TRUE; ag_account_store_async (account, self->priv->cancellable, account_store_cb, self); } static void query_info_cb (SignonIdentity *identity, const SignonIdentityInfo *info, const GError *error, gpointer user_data) { ApOAuthPlugin *self = AP_OAUTH_PLUGIN (user_data); if (G_UNLIKELY (error != NULL)) { g_warning ("Couldn't read back identity information"); // this is not a critical error; continue with the account creation } else { const gchar *username; username = signon_identity_info_get_username (info); if (username != NULL) { ap_plugin_set_credentials ((ApPlugin *)self, username, NULL); } } store_account (self); } static void query_username (ApOAuthPlugin *self) { ApOAuthPluginPrivate *priv = self->priv; signon_identity_query_info (priv->identity, query_info_cb, self); } static void auth_session_process_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { ApOAuthPlugin *self; SignonAuthSession *auth_session = SIGNON_AUTH_SESSION (source_object); AgAccount *account; GVariant *session_data; GError *error = NULL; session_data = signon_auth_session_process_finish (auth_session, res, &error); if (session_data != NULL) { /* We don't care about the response */ g_variant_unref (session_data); } if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); return; } self = AP_OAUTH_PLUGIN (user_data); self->priv->authenticating = FALSE; if (G_UNLIKELY (error != NULL)) { if (error->domain == SIGNON_ERROR && error->code == SIGNON_ERROR_SESSION_CANCELED) { /* Don't report an error if the session has been cancelled by the * user */ finish_with_cancellation (self); } else { g_warning ("AuthSession error: %s", error->message); finish_with_error (self, error); } g_error_free (error); return; } account = ap_plugin_get_account ((ApPlugin *)self); if (account->id == 0) { /* newly created account */ query_username (self); } else { /* re-authenticated account */ ap_plugin_set_need_authentication ((ApPlugin *)self, FALSE); /* Store the authentication parameters, in case they have changed. * This might be removed or reviewed once the following is implemented: * http://code.google.com/p/accounts-sso/issues/detail?id=111 */ store_account (self); } } static GVariant * cookies_to_variant (GHashTable *cookies) { GVariantBuilder builder; GHashTableIter iter; const gchar *key, *value; g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}")); g_hash_table_iter_init (&iter, cookies); while (g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&value)) { g_variant_builder_add (&builder, "{ss}", key, value); } return g_variant_builder_end (&builder); } static GVariant * prepare_session_data (ApOAuthPlugin *self) { ApOAuthPluginPrivate *priv = self->priv; GVariant *session_data; GVariantBuilder builder; GHashTableIter iter; GHashTable *cookies; gpointer key, value; g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); if (priv->socket != NULL) { guint32 window_id = gtk_socket_get_id (priv->socket); g_variant_builder_add (&builder, "{sv}", "WindowId", g_variant_new_uint32 (window_id)); g_variant_builder_add (&builder, "{sv}", "Embedded", g_variant_new_boolean (TRUE)); } cookies = ap_plugin_get_cookies ((ApPlugin *)self); if (cookies != NULL && !ap_plugin_get_ignore_cookies ((ApPlugin *)self)) { g_variant_builder_add (&builder, "{sv}", "Cookies", cookies_to_variant (cookies)); } /* Add all the provider-specific OAuth parameters. */ if (priv->oauth_params != NULL) { g_hash_table_iter_init (&iter, priv->oauth_params); while (g_hash_table_iter_next (&iter, &key, &value)) { GVariant *variant = value_to_variant (value); g_variant_builder_add (&builder, "{sv}", key, variant); g_variant_unref (variant); } } /* Merge the session parameters built so far with the provider's default * parameters */ session_data = g_variant_builder_end (&builder); if (priv->auth_data != NULL) { session_data = ag_auth_data_get_login_parameters (priv->auth_data, session_data); } return session_data; } static void start_authentication_process (ApOAuthPlugin *self) { ApOAuthPluginPrivate *priv = self->priv; GVariant *session_data; GError *error = NULL; session_data = prepare_session_data (self); priv->auth_session = signon_identity_create_session (priv->identity, oauth_method, &error); if (G_UNLIKELY (!priv->auth_session)) { g_critical ("Couldn't create AuthSession: %s", error->message); finish_with_error (self, error); g_clear_error (&error); return; } priv->authenticating = TRUE; signon_auth_session_process_async (priv->auth_session, session_data, get_mechanism (priv), priv->cancellable, auth_session_process_cb, self); } static void identity_store_cb (SignonIdentity *identity, guint32 id, const GError *error, gpointer user_data) { ApOAuthPlugin *self = AP_OAUTH_PLUGIN (user_data); ApOAuthPluginPrivate *priv = self->priv; AgAccount *account; GVariant *v_id; if (G_UNLIKELY (error != NULL)) { g_critical ("Couldn't store identity: %s", error->message); finish_with_error (self, error); return; } priv->identity_stored = TRUE; /* store the identity ID into the account settings */ v_id = g_variant_new_uint32 (id); account = ap_plugin_get_account ((ApPlugin *)self); ag_account_set_variant (account, signon_id, v_id); if (priv->socket != NULL) { start_authentication_process (self); } else { /* operating headless: just store the account */ store_account (self); } } static void setup_authentication (ApOAuthPlugin *self) { SignonIdentityInfo *info; AgProvider *provider; const gchar *acl_all[] = { "*", NULL }; const gchar *username; const gchar *secret; username = ap_plugin_get_username ((ApPlugin *)self); secret = ap_plugin_get_password ((ApPlugin *)self); if (secret == NULL) secret = ""; info = signon_identity_info_new (); provider = ap_plugin_get_provider ((ApPlugin *)self); signon_identity_info_set_caption (info, ag_provider_get_display_name (provider)); signon_identity_info_set_identity_type (info, SIGNON_IDENTITY_TYPE_APP); if (username != NULL) signon_identity_info_set_username (info, username); signon_identity_info_set_secret (info, secret, TRUE); signon_identity_info_set_access_control_list (info, acl_all); self->priv->identity = signon_identity_new (); signon_identity_store_credentials_with_info (self->priv->identity, info, identity_store_cb, self); signon_identity_info_free (info); } static void reauthenticate_account_cb (GDBusConnection *connection, GAsyncResult *res, ApOAuthPlugin *self) { GVariant *result; GError *error = NULL; gboolean authenticated = FALSE; result = g_dbus_connection_call_finish (connection, res, &error); if (G_UNLIKELY (error != NULL)) { if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED) { finish_with_cancellation (self); } else { g_warning ("Reauthentication failed: %s", error->message); finish_with_error (self, error); } g_clear_error (&error); return; } g_assert (result != NULL); g_variant_get (result, "(b)", &authenticated); ap_plugin_set_need_authentication ((ApPlugin *)self, !authenticated); finish_with_cleanup (self); } static void setup_reauthentication (ApOAuthPlugin *self) { ApOAuthPluginPrivate *priv = self->priv; AgAccount *account; GVariantBuilder builder; GVariant *args; guint32 window_id; account = ap_plugin_get_account ((ApPlugin *)self); g_assert (account->id != 0); window_id = gtk_socket_get_id (priv->socket); g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&builder, "{sv}", "WindowId", g_variant_new_uint32 (window_id)); g_variant_builder_add (&builder, "{sv}", "Embedded", g_variant_new_boolean (TRUE)); args = g_variant_new ("(u@a{sv})", account->id, g_variant_builder_end (&builder), NULL); if (priv->connection == NULL) { GError *error = NULL; priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); if (G_UNLIKELY (error != NULL)) { g_critical ("Couldn't connect to D-Bus session: %s", error->message); g_clear_error (&error); return; } } g_dbus_connection_call (priv->connection, "com.canonical.indicators.webcredentials", "/com/canonical/indicators/webcredentials", "com.canonical.indicators.webcredentials", "ReauthenticateAccount", args, NULL, G_DBUS_CALL_FLAGS_NONE, G_MAXINT, priv->cancellable, (GAsyncReadyCallback)reauthenticate_account_cb, self); } static void on_infobar_response (GtkInfoBar *infobar, gint response_id, ApOAuthPlugin *self) { g_assert (response_id == GTK_RESPONSE_CANCEL); finish_with_cancellation (self); } static GtkWidget * create_infobar (ApOAuthPlugin *self) { GtkWidget *infobar; GtkWidget *infobar_label; GtkWidget *content_area; GtkCssProvider *css; GError *error; GtkStyleContext *context; AgProvider *provider; gchar *text; infobar = gtk_info_bar_new_with_buttons (GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); gtk_widget_set_hexpand (infobar, TRUE); gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_QUESTION); gtk_widget_set_name (infobar, "authorization-infobar"); g_signal_connect (infobar, "response", G_CALLBACK (on_infobar_response), self); provider = ap_plugin_get_provider ((ApPlugin *)self); text = g_strdup_printf (_("Please authorize Ubuntu to access " "your %s account"), ag_provider_get_display_name (provider)); infobar_label = gtk_label_new (text); g_free (text); content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar)); gtk_container_add (GTK_CONTAINER (content_area), infobar_label); css = gtk_css_provider_new (); error = NULL; if (gtk_css_provider_load_from_data (css, "@define-color question_bg_color rgb (222, 222, 222); GtkInfoBar#authorization-infobar { color: @fg_color }", -1, &error)) { context = gtk_widget_get_style_context (infobar); gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } else { g_warning ("Error processing CSS theme override: %s", error->message); } gtk_widget_show_all (infobar); return infobar; } static gboolean on_socket_plug_removed (GtkSocket *socket, ApOAuthPlugin *self) { /* Do not destroy the socket when the plug is removed. */ return TRUE; } static GtkWidget * create_socket_frame (ApOAuthPlugin *self) { GtkWidget *frame; GtkWidget *socket; frame = gtk_frame_new (NULL); socket = gtk_socket_new (); self->priv->socket = GTK_SOCKET(socket); gtk_widget_set_hexpand (socket, TRUE); gtk_widget_set_vexpand (socket, TRUE); gtk_widget_set_can_focus (socket, TRUE); gtk_widget_grab_focus (socket); g_signal_connect (socket, "plug-removed", G_CALLBACK (on_socket_plug_removed), self); gtk_widget_show (socket); gtk_container_add (GTK_CONTAINER (frame), socket); gtk_widget_show (frame); return frame; } static GtkWidget * create_legal_button () { GtkWidget *buttonbox; GtkWidget *link_button; buttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); gtk_button_box_set_layout (GTK_BUTTON_BOX (buttonbox), GTK_BUTTONBOX_END); link_button = gtk_link_button_new_with_label ("help:web-credentials/legal-notice", _("Legal notice")); gtk_container_add (GTK_CONTAINER (buttonbox), link_button); gtk_widget_show_all (buttonbox); return buttonbox; } static void ap_oauth_plugin_init (ApOAuthPlugin *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, AP_TYPE_OAUTH_PLUGIN, ApOAuthPluginPrivate); self->priv->mechanism = NULL; self->priv->cancellable = g_cancellable_new (); } static void ap_oauth_plugin_constructed (GObject *object) { ApOAuthPluginPrivate *priv = AP_OAUTH_PLUGIN_PRIV (object); AgAccount *account; AgAccountService *account_service; G_OBJECT_CLASS (ap_oauth_plugin_parent_class)->constructed (object); account = ap_plugin_get_account (AP_PLUGIN (object)); if (account != NULL) { account_service = ag_account_service_new (account, NULL); priv->auth_data = ag_account_service_get_auth_data (account_service); g_object_unref (account_service); } } static void ap_oauth_plugin_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { ApOAuthPluginPrivate *priv = AP_OAUTH_PLUGIN_PRIV (object); switch (property_id) { case PROP_OAUTH_PARAMS: g_assert (priv->oauth_params == NULL); priv->oauth_params = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ap_oauth_plugin_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { ApOAuthPluginPrivate *priv = AP_OAUTH_PLUGIN_PRIV (object); switch (property_id) { case PROP_OAUTH_PARAMS: g_value_set_boxed (value, priv->oauth_params); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ap_oauth_plugin_dispose (GObject *object) { ApOAuthPluginPrivate *priv = AP_OAUTH_PLUGIN_PRIV (object); if (priv->account_oauth_params) { g_hash_table_unref (priv->account_oauth_params); priv->account_oauth_params = NULL; } if (priv->oauth_params) { g_hash_table_unref (priv->oauth_params); priv->oauth_params = NULL; } if (priv->auth_data) { ag_auth_data_unref (priv->auth_data); priv->auth_data = NULL; } if (priv->identity) { g_object_unref (priv->identity); priv->identity = NULL; } if (priv->auth_session) { g_object_unref (priv->auth_session); priv->auth_session = NULL; } if (priv->cancellable) { g_cancellable_cancel (priv->cancellable); g_object_unref (priv->cancellable); priv->cancellable = NULL; } g_clear_object (&priv->connection); G_OBJECT_CLASS (ap_oauth_plugin_parent_class)->dispose (object); } static GtkWidget * build_widget_for_authentication (ApOAuthPlugin *self, gboolean new_account) { GtkWidget *grid; GtkWidget *infobar; GtkWidget *socket_frame; GtkWidget *legal_button; grid = gtk_grid_new (); gtk_widget_set_hexpand (grid, TRUE); gtk_widget_set_vexpand (grid, TRUE); gtk_grid_set_row_spacing (GTK_GRID (grid), 12); gtk_orientable_set_orientation (GTK_ORIENTABLE (grid), GTK_ORIENTATION_VERTICAL); if (new_account) { g_signal_connect_swapped (grid, "map", G_CALLBACK (setup_authentication), self); } else { g_signal_connect_swapped (grid, "map", G_CALLBACK (setup_reauthentication), self); } infobar = create_infobar (self); gtk_container_add (GTK_CONTAINER (grid), infobar); socket_frame = create_socket_frame (self); gtk_container_add (GTK_CONTAINER (grid), socket_frame); legal_button = create_legal_button (); gtk_container_add (GTK_CONTAINER (grid), legal_button); return grid; } static GtkWidget * ap_oauth_plugin_build_widget (ApPlugin *plugin) { ApOAuthPlugin *self = AP_OAUTH_PLUGIN (plugin); AgAccount *account; account = ap_plugin_get_account (plugin); if (account->id == 0) { /* New account: provide UI to create it */ return build_widget_for_authentication (self, TRUE); } else if (ap_plugin_get_need_authentication (plugin)) { return build_widget_for_authentication (self, FALSE); } else { /* Editing an existing account: if the account needs some * configuration, it will be handled in the provider-specific subclass */ return NULL; } } static void ap_oauth_plugin_act_headless (ApPlugin *plugin) { AgAccount *account; account = ap_plugin_get_account (plugin); if (account->id == 0) { /* New account: create it. * If the GtkSocket has not been prepared (and we don't prepare it, for * headless operations) then the authentication phase is skipped, and * we just store the settings into the account. */ setup_authentication (AP_OAUTH_PLUGIN (plugin)); } /* nothing to do for other operations */ } static void ap_oauth_plugin_class_init (ApOAuthPluginClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); ApPluginClass *plugin_class = AP_PLUGIN_CLASS (klass); g_type_class_add_private (object_class, sizeof (ApOAuthPluginPrivate)); object_class->constructed = ap_oauth_plugin_constructed; object_class->set_property = ap_oauth_plugin_set_property; object_class->get_property = ap_oauth_plugin_get_property; object_class->dispose = ap_oauth_plugin_dispose; plugin_class->build_widget = ap_oauth_plugin_build_widget; plugin_class->act_headless = ap_oauth_plugin_act_headless; /** * ApOAuthPlugin:oauth-params: * * A dictionary of OAuth parameters, to be used when authenticating an * account. */ g_object_class_install_property (object_class, PROP_OAUTH_PARAMS, g_param_spec_boxed ("oauth-params", "Dictionary of OAuth parameters", "A dictionary of OAuth parameters", G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } /** * ap_oauth_plugin_set_oauth_parameters: * @self: the #ApOAuthPlugin. * @oauth_params: (element-type utf8 GValue): a dictionary of OAuth parameters. * * Sets the dictionary of OAuth parameters to be used when authenticating the * account. Note that these parameters are not stored in the account and will * be used only by the account plugin. * To set the authentication parameters used by applications, use * ap_oauth_plugin_set_account_oauth_parameters(). */ void ap_oauth_plugin_set_oauth_parameters (ApOAuthPlugin *self, GHashTable *oauth_params) { g_return_if_fail (AP_IS_OAUTH_PLUGIN (self)); g_return_if_fail (oauth_params != NULL); g_return_if_fail (self->priv->oauth_params == NULL); self->priv->oauth_params = g_hash_table_ref (oauth_params); } /** * ap_oauth_plugin_set_account_oauth_parameters: * @self: the #ApOAuthPlugin. * @oauth_params: (element-type utf8 GValue): a dictionary of OAuth parameters. * * Sets the dictionary of OAuth parameters to be used by client applications * when authenticating the account. These are the parameters which will be * stored into the account configuration (those used by the plugin itself when * authenticating are those set with ap_oauth_plugin_set_oauth_parameters()). */ void ap_oauth_plugin_set_account_oauth_parameters (ApOAuthPlugin *self, GHashTable *oauth_params) { g_return_if_fail (AP_IS_OAUTH_PLUGIN (self)); g_return_if_fail (oauth_params != NULL); g_return_if_fail (self->priv->account_oauth_params == NULL); self->priv->account_oauth_params = g_hash_table_ref (oauth_params); } /** * ap_oauth_plugin_set_mechanism: * @self: the #ApOAuthPlugin. * @mechanism: the desired OAuth mechanism. * * Set the OAuth mechanism to be used when authenticating the account. */ void ap_oauth_plugin_set_mechanism (ApOAuthPlugin *self, ApOAuthMechanism mechanism) { g_return_if_fail (AP_IS_OAUTH_PLUGIN (self)); g_return_if_fail (mechanism < AP_OAUTH_MECHANISM_LAST); self->priv->mechanism = oauth_mechanisms[mechanism]; } #ifdef BUILDING_UNIT_TESTS GVariant *prepare_session_data_test (ApOAuthPlugin *self); GVariant *prepare_session_data_test (ApOAuthPlugin *self) { return prepare_session_data (self); } #endif gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/plugin.h0000644000015600001650000001020312653650644026505 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef _AP_PLUGIN_H_ #define _AP_PLUGIN_H_ #include #include #include #include G_BEGIN_DECLS #define AP_TYPE_PLUGIN (ap_plugin_get_type ()) #define AP_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), AP_TYPE_PLUGIN, ApPlugin)) #define AP_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AP_TYPE_PLUGIN, ApPluginClass)) #define AP_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AP_TYPE_PLUGIN)) #define AP_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AP_TYPE_PLUGIN)) #define AP_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AP_TYPE_PLUGIN, ApPluginClass)) typedef struct _ApPluginClass ApPluginClass; typedef struct _ApPluginPrivate ApPluginPrivate; typedef struct _ApPlugin ApPlugin; /** * ApPluginClass: * * Base class for account plugins. */ struct _ApPluginClass { GObjectClass parent_class; GtkWidget *(*build_widget) (ApPlugin *self); void (*delete_account) (ApPlugin *self, GAsyncReadyCallback callback, gpointer user_data); void (*act_headless) (ApPlugin *self); void (*_ap_reserved4) (void); void (*_ap_reserved5) (void); void (*_ap_reserved6) (void); void (*_ap_reserved7) (void); }; /** * ApPlugin: * * Use the accessor functions below. */ struct _ApPlugin { GObject parent_instance; /*< private >*/ ApPluginPrivate *priv; }; GType ap_plugin_get_type (void) G_GNUC_CONST; AgAccount *ap_plugin_get_account (ApPlugin *self); AgProvider *ap_plugin_get_provider (ApPlugin *self); void ap_plugin_emit_finished (ApPlugin *self); void ap_plugin_set_need_authentication (ApPlugin *self, gboolean need_authentication); gboolean ap_plugin_get_need_authentication (ApPlugin *self); void ap_plugin_set_credentials (ApPlugin *self, const gchar *username, const gchar *password); const gchar *ap_plugin_get_username (ApPlugin *self); const gchar *ap_plugin_get_password (ApPlugin *self); void ap_plugin_set_cookies (ApPlugin *self, GHashTable *cookies); GHashTable *ap_plugin_get_cookies (ApPlugin *self); void ap_plugin_set_ignore_cookies (ApPlugin *self, gboolean ignore_cookies); gboolean ap_plugin_get_ignore_cookies (ApPlugin *self); void ap_plugin_set_user_cancelled (ApPlugin *self, gboolean cancelled); gboolean ap_plugin_get_user_cancelled (ApPlugin *self); void ap_plugin_set_error (ApPlugin *self, const GError *error); const GError *ap_plugin_get_error (ApPlugin *self); GtkWidget *ap_plugin_build_widget (ApPlugin *self); void ap_plugin_act_headless (ApPlugin *self); void ap_plugin_delete_account (ApPlugin *self, GAsyncReadyCallback callback, gpointer user_data); gboolean ap_plugin_delete_account_finish (ApPlugin *self, GAsyncResult *result, GError **error); /** * AP_PLUGIN_CREDENTIALS_ID_FIELD: * * The field in the credentials database for storing the signon identity ID. */ #define AP_PLUGIN_CREDENTIALS_ID_FIELD "CredentialsId" G_END_DECLS #endif /* _AP_PLUGIN_H_ */ gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/application-plugin.h0000644000015600001650000000621212653650644031013 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef _AP_APPLICATION_PLUGIN_H_ #define _AP_APPLICATION_PLUGIN_H_ #include #include #include #include G_BEGIN_DECLS #define AP_TYPE_APPLICATION_PLUGIN (ap_application_plugin_get_type ()) #define AP_APPLICATION_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), AP_TYPE_APPLICATION_PLUGIN, ApApplicationPlugin)) #define AP_APPLICATION_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AP_TYPE_APPLICATION_PLUGIN, ApApplicationPluginClass)) #define AP_IS_APPLICATION_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AP_TYPE_APPLICATION_PLUGIN)) #define AP_IS_APPLICATION_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AP_TYPE_APPLICATION_PLUGIN)) #define AP_APPLICATION_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AP_TYPE_APPLICATION_PLUGIN, ApApplicationPluginClass)) typedef struct _ApApplicationPluginClass ApApplicationPluginClass; typedef struct _ApApplicationPluginPrivate ApApplicationPluginPrivate; typedef struct _ApApplicationPlugin ApApplicationPlugin; /** * ApApplicationPluginClass: * * Base class for account application_plugins. */ struct _ApApplicationPluginClass { GObjectClass parent_class; GtkWidget *(*build_widget) (ApApplicationPlugin *self); void (*_ap_reserved2) (void); void (*_ap_reserved3) (void); void (*_ap_reserved4) (void); void (*_ap_reserved5) (void); void (*_ap_reserved6) (void); void (*_ap_reserved7) (void); }; /** * ApApplicationPlugin: * * Use the accessor functions below. */ struct _ApApplicationPlugin { GObject parent_instance; /*< private >*/ ApApplicationPluginPrivate *priv; }; GType ap_application_plugin_get_type (void) G_GNUC_CONST; AgAccount *ap_application_plugin_get_account (ApApplicationPlugin *self); AgApplication * ap_application_plugin_get_application (ApApplicationPlugin *self); void ap_application_plugin_emit_finished (ApApplicationPlugin *self); void ap_application_plugin_set_error (ApApplicationPlugin *self, const GError *error); const GError *ap_application_plugin_get_error (ApApplicationPlugin *self); GtkWidget *ap_application_plugin_build_widget (ApApplicationPlugin *self); G_END_DECLS #endif /* _AP_APPLICATION_PLUGIN_H_ */ gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/plugin.c0000644000015600001650000005040112653650644026504 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /** * SECTION:ap-plugin * @short_description: Base class for account plugins. * @include: libaccount-plugin/plugin.h * * Account plugins for the credentials panel of the Unity control center need * to subclass #ApPlugin and implement its build_widget() virtual method. * This method will be called by the credentials panel when it needs to show a * UI to handle some operations on the account, such as creation, editing or * re-authentication. */ #include "plugin.h" #include #include #include enum { PROP_0, PROP_ACCOUNT, PROP_NEED_AUTHENTICATION, }; enum { FINISHED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static const gchar signon_id[] = AP_PLUGIN_CREDENTIALS_ID_FIELD; struct _ApPluginPrivate { AgAccount *account; AgProvider *provider; GError *error; gchar *username; gchar *password; GHashTable *cookies; gboolean ignore_cookies; gboolean need_authentication; gboolean cancelled; }; G_DEFINE_TYPE (ApPlugin, ap_plugin, G_TYPE_OBJECT); #define AP_PLUGIN_PRIV(obj) (AP_PLUGIN(obj)->priv) static void account_removed_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *result = user_data; GError *error = NULL; ag_account_store_finish (AG_ACCOUNT (source_object), res, &error); if (G_UNLIKELY (error != NULL)) { g_simple_async_result_set_op_res_gboolean (result, FALSE); g_simple_async_result_take_error (result, error); } else { g_simple_async_result_set_op_res_gboolean (result, TRUE); } g_simple_async_result_complete_in_idle (result); g_object_unref (result); } static void delete_account_from_db (ApPlugin *self, GSimpleAsyncResult *result) { ApPluginPrivate *priv = self->priv; ag_account_delete (priv->account); ag_account_store_async (priv->account, NULL, account_removed_cb, result); } static void identity_removed_cb (SignonIdentity *identity, const GError *error, gpointer user_data) { GSimpleAsyncResult *result = user_data; GObject *plugin; if (G_UNLIKELY (error != NULL)) { g_simple_async_result_set_op_res_gboolean (result, FALSE); g_simple_async_result_set_from_error (result, error); g_simple_async_result_complete_in_idle (result); g_object_unref (result); g_object_unref (identity); return; } g_object_unref (identity); plugin = g_async_result_get_source_object ((GAsyncResult *)result); delete_account_from_db (AP_PLUGIN (plugin), result); } static void enable_account_and_services (AgAccount *account) { GList *services, *list; services = ag_account_list_services (account); for (list = services; list != NULL; list = list->next) { AgService *service = list->data; ag_account_select_service (account, service); ag_account_set_enabled (account, TRUE); } ag_service_list_free (services); ag_account_select_service (account, NULL); ag_account_set_enabled (account, TRUE); } static void ap_plugin_init (ApPlugin *plugin) { plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin, AP_TYPE_PLUGIN, ApPluginPrivate); } static void ap_plugin_constructed (GObject *object) { ApPluginPrivate *priv = AP_PLUGIN_PRIV (object); G_OBJECT_CLASS (ap_plugin_parent_class)->constructed (object); if (priv->account) { AgManager *manager; const gchar *provider_name; manager = ag_account_get_manager (priv->account); provider_name = ag_account_get_provider_name (priv->account); priv->provider = ag_manager_get_provider (manager, provider_name); /* if this is a newly created account, enable it and all of its * services */ if (priv->account->id == 0) enable_account_and_services (priv->account); } } static void ap_plugin_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { ApPluginPrivate *priv = AP_PLUGIN_PRIV (object); switch (property_id) { case PROP_ACCOUNT: g_assert (priv->account == NULL); priv->account = g_value_dup_object (value); break; case PROP_NEED_AUTHENTICATION: priv->need_authentication = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ap_plugin_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { ApPluginPrivate *priv = AP_PLUGIN_PRIV (object); switch (property_id) { case PROP_ACCOUNT: g_value_set_object (value, priv->account); break; case PROP_NEED_AUTHENTICATION: g_value_set_boolean (value, priv->need_authentication); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ap_plugin_dispose (GObject *object) { ApPluginPrivate *priv = AP_PLUGIN_PRIV (object); if (priv->account) { g_object_unref (priv->account); priv->account = NULL; } if (priv->provider) { ag_provider_unref (priv->provider); priv->provider = NULL; } G_OBJECT_CLASS (ap_plugin_parent_class)->dispose (object); } static void ap_plugin_finalize (GObject *object) { ApPluginPrivate *priv = AP_PLUGIN_PRIV (object); if (priv->error) { g_error_free (priv->error); priv->error = NULL; } g_free (priv->username); g_free (priv->password); if (priv->cookies != NULL) { g_hash_table_unref (priv->cookies); priv->cookies = NULL; } G_OBJECT_CLASS (ap_plugin_parent_class)->finalize (object); } static void _ap_plugin_delete_account (ApPlugin *self, GAsyncReadyCallback callback, gpointer user_data) { ApPluginPrivate *priv = self->priv; GVariant *v_id; GSimpleAsyncResult *result; gboolean deleting_identity = FALSE; result = g_simple_async_result_new ((GObject *)self, callback, user_data, ap_plugin_delete_account); /* delete the credentials from the SSO database */ ag_account_select_service (priv->account, NULL); v_id = ag_account_get_variant (priv->account, signon_id, NULL); if (v_id != NULL) { SignonIdentity *identity = signon_identity_new_from_db (g_variant_get_uint32 (v_id)); if (identity != NULL) { deleting_identity = TRUE; signon_identity_remove (identity, identity_removed_cb, result); } } /* delete the account; if the identity is being deleted, then this will * happen in the identity_removed_cb function */ if (!deleting_identity) delete_account_from_db (self, result); } static void ap_plugin_class_init (ApPluginClass *klass) { GObjectClass* object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (ApPluginPrivate)); object_class->constructed = ap_plugin_constructed; object_class->set_property = ap_plugin_set_property; object_class->get_property = ap_plugin_get_property; object_class->dispose = ap_plugin_dispose; object_class->finalize = ap_plugin_finalize; klass->delete_account = _ap_plugin_delete_account; /** * ApPlugin:account: * * The #AgAccount associated with the plugin. */ g_object_class_install_property (object_class, PROP_ACCOUNT, g_param_spec_object ("account", "Account for this plugin", "The AgAccount associated with the plugin", AG_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** * ApPlugin:need-authentication: * * Whether the plugin needs to be authenticated again. */ g_object_class_install_property (object_class, PROP_NEED_AUTHENTICATION, g_param_spec_boolean ("need-authentication", "Whether authentication is needed", "Whether the plugin needs further authentication", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** * ApPlugin::finished: * @plugin: the #ApPlugin. * * Emitted when the plugin UI has completed its task and can be dismissed. */ signals[FINISHED] = g_signal_new ("finished", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } /** * ap_plugin_get_account: * @self: the #ApPlugin. * * Get the #AgAccount associated with this plugin instance. * * Returns: (transfer none): the #AgAccount, or %NULL. */ AgAccount * ap_plugin_get_account (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), NULL); return self->priv->account; } /** * ap_plugin_get_provider: * @self: the #ApPlugin. * * Get the #AgProvider associated with this plugin instance. * * Returns: (transfer none): the #AgProvider, or %NULL. */ AgProvider * ap_plugin_get_provider (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), NULL); return self->priv->provider; } /** * ap_plugin_emit_finished: * @self: the #ApPlugin. * * Emits the #ApPlugin::finished signal. This method is useful for subclasses * only. */ void ap_plugin_emit_finished (ApPlugin *self) { g_return_if_fail (AP_IS_PLUGIN (self)); g_signal_emit (self, signals[FINISHED], 0); } /** * ap_plugin_set_need_authentication: * @self: the #ApPlugin. * @need_authentication: whether the plugin must perform the authentication. * * Tell the plugin that the #AgAccount associated with it needs to be * re-authenticated. */ void ap_plugin_set_need_authentication (ApPlugin *self, gboolean need_authentication) { g_return_if_fail (AP_IS_PLUGIN (self)); self->priv->need_authentication = need_authentication; } /** * ap_plugin_get_need_authentication: * @self: the #ApPlugin. * * Get whether the #AgAccount associated with this plugin instance needs to be * re-authenticated. * * Returns: %TRUE if the account needs re-authentication, %FALSE otherwise. */ gboolean ap_plugin_get_need_authentication (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), FALSE); return self->priv->need_authentication; } /** * ap_plugin_set_credentials: * @self: the #ApPlugin. * @username: login username. * @password: the user password, or %NULL. * * Set the user name and password. The plugin could use them for prefilling the * login form (or skip it altogether). */ void ap_plugin_set_credentials (ApPlugin *self, const gchar *username, const gchar *password) { ApPluginPrivate *priv; g_return_if_fail (AP_IS_PLUGIN (self)); g_return_if_fail (username != NULL); priv = self->priv; g_free (priv->username); g_free (priv->password); priv->username = g_strdup (username); priv->password = g_strdup (password); } /** * ap_plugin_get_username: * @self: the #ApPlugin. * * Get the login username. * * Returns: the username, or %NULL. */ const gchar * ap_plugin_get_username (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), NULL); return self->priv->username; } /** * ap_plugin_get_password: * @self: the #ApPlugin. * * Get the login password. * * Returns: the password, or %NULL. */ const gchar * ap_plugin_get_password (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), NULL); return self->priv->password; } /** * ap_plugin_set_cookies: * @self: the #ApPlugin. * @cookies: (element-type utf8 utf8) (transfer none): a #GHashTable with * cookie name and value pairs. * * Set the HTTP cookies. The plugin may use them while performing a web-based * authentication. */ void ap_plugin_set_cookies (ApPlugin *self, GHashTable *cookies) { ApPluginPrivate *priv; g_return_if_fail (AP_IS_PLUGIN (self)); g_return_if_fail (cookies != NULL); priv = self->priv; if (priv->cookies != NULL) { g_hash_table_unref (priv->cookies); } priv->cookies = g_hash_table_ref (cookies); } /** * ap_plugin_get_cookies: * @self: the #ApPlugin. * * Get the HTTP cookies. * * Returns: (element-type utf8 utf8) (transfer none) (allow-none): a dictionary * with cookie name and value pairs, or %NULL. */ GHashTable *ap_plugin_get_cookies (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), NULL); return self->priv->cookies; } /** * ap_plugin_set_ignore_cookies: * @self: the #ApPlugin. * @ignore_cookies: whether provided cookies should be ignored. * * Tells the plugin implementation that all provided cookies should be ignored * when performing the authentication; an ApPlugin subclass might choose to * ignore cookies when the provided cookies are known not to be working. */ void ap_plugin_set_ignore_cookies (ApPlugin *self, gboolean ignore_cookies) { g_return_if_fail (AP_IS_PLUGIN (self)); self->priv->ignore_cookies = ignore_cookies; } /** * ap_plugin_get_ignore_cookies: * @self: the #ApPlugin. * * Get whether the provided cookies should be ignored when performing the * authentication. * * Returns: whether provided cookies should be ignored. */ gboolean ap_plugin_get_ignore_cookies (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), FALSE); return self->priv->ignore_cookies; } /** * ap_plugin_set_user_cancelled: * @self: the #ApPlugin. * @cancelled: whether the plugin operation was cancelled by the user. * * Tell the plugin that the requested operation was cancelled by the user. This * method should be called by #ApPlugin subclasses only. */ void ap_plugin_set_user_cancelled (ApPlugin *self, gboolean cancelled) { g_return_if_fail (AP_IS_PLUGIN (self)); self->priv->cancelled = cancelled; } /** * ap_plugin_get_user_cancelled: * @self: the #ApPlugin. * * Get whether the requested operation was cancelled by the user. * * Returns: %TRUE if the operation was cancelled, %FALSE otherwise. */ gboolean ap_plugin_get_user_cancelled (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), FALSE); return self->priv->cancelled; } /** * ap_plugin_set_error: * @self: the #ApPlugin. * @error: the #GError to set on the plugin. * * Tell the plugin that the requested operation ended in an error. This method * should be called by #ApPlugin subclasses only. */ void ap_plugin_set_error (ApPlugin *self, const GError *error) { ApPluginPrivate *priv; g_return_if_fail (AP_IS_PLUGIN (self)); priv = self->priv; if (priv->error != NULL) { g_error_free (priv->error); priv->error = NULL; } if (error != NULL) { priv->error = g_error_copy (error); } } /** * ap_plugin_get_error: * @self: the #ApPlugin. * * Get whether the requested operation ended in an error. * * Returns: (transfer none): a #GError if an error occurred, %NULL otherwise. */ const GError * ap_plugin_get_error (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), NULL); return self->priv->error; } /** * ap_plugin_build_widget: * @self: the #ApPlugin. * * Build a UI widget to perform the needed operation on the #AgAccount * associated with this plugin: * - if the #AgAccount is a newly allocated instance (not stored on disk), then * the plugin should proceed with the account creation. Otherwise, * - if the #ApPlugin:need-authentication property is set, the returned UI * widget should provide a way for the user to reauthenticate the account; * - if none of the above conditions apply, the plugin should return a widget * to allow editing the account global settings (that is, those settings * which are common for all applications using the account). * The plugin will emit the #ApPlugin::finished signal once the widget has * completed its tasks and can be destroyed. * * Returns: (transfer floating): a #GtkWidget which till take care of * performing the needed tasks, or %NULL. */ GtkWidget * ap_plugin_build_widget (ApPlugin *self) { g_return_val_if_fail (AP_IS_PLUGIN (self), NULL); return AP_PLUGIN_GET_CLASS (self)->build_widget (self); } /** * ap_plugin_act_headless: * @self: the #ApPlugin. * * Perform the needed operation on the #AgAccount associated with this plugin. * This works similarly to the ap_plugin_build_widget() method, with the * difference that in this case there is no UI involved. * The plugin will emit the #ApPlugin::finished signal once it has * completed its tasks. */ void ap_plugin_act_headless (ApPlugin *self) { ApPluginPrivate *priv; g_return_if_fail (AP_IS_PLUGIN (self)); priv = self->priv; if (priv->account->id == 0) { /* Disable the account; when acting headless, let the caller * decide when and whether the created account should be * enabled. */ ag_account_select_service (priv->account, NULL); ag_account_set_enabled (priv->account, FALSE); } AP_PLUGIN_GET_CLASS (self)->act_headless (self); } /** * ap_plugin_delete_account: * @self: the #ApPlugin. * @callback: a callback which will be invoked when the operation has been * completed. * @user_data: user data to be passed to the callback. * * Delete the account. When the operation is finished, @callback will be * invoked; you can then call ap_plugin_delete_account_finish() to know if the * operation was successful. * This is a virtual method; the base implementation removes the account from * the accounts database and the accounts credentials from the Single Sign-On * database. */ void ap_plugin_delete_account (ApPlugin *self, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (AP_IS_PLUGIN (self)); return AP_PLUGIN_GET_CLASS (self)->delete_account (self, callback, user_data); } /** * ap_plugin_delete_account_finish: * @self: the #ApPlugin. * @result: the #GAsyncResult obtained from the #GAsyncReadyCallback passed to * ap_plugin_delete_account(). * @error: location for error, or %NULL. * * Finish the operation started with ap_plugin_delete_account(). * * Returns: %TRUE if the operation succeeded, %FALSE otherwise. */ gboolean ap_plugin_delete_account_finish (ApPlugin *self, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; gboolean ok; g_return_val_if_fail (AP_IS_PLUGIN (self), FALSE); g_return_val_if_fail (g_simple_async_result_is_valid (result, (GObject *)self, ap_plugin_delete_account), FALSE); simple = (GSimpleAsyncResult *) result; ok = g_simple_async_result_get_op_res_gboolean (simple); if (!ok) { g_simple_async_result_propagate_error (simple, error); } return ok; } gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/module.h0000644000015600001650000000204012653650644026474 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef _AP_MODULE_H_ #define _AP_MODULE_H_ #include G_BEGIN_DECLS GType ap_module_get_object_type (void); G_END_DECLS #endif /* _AP_MODULE_H_ */ gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/application-plugin.c0000644000015600001650000002115312653650644031007 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /** * SECTION:ap-application-plugin * @short_description: Base class for application plugins. * @include: libaccount-plugin/application-plugin.h * * Application plugins for the credentials panel of the Unity control center * need to subclass #ApApplicationPlugin and implement its build_widget() * virtual method. * This method will be called by the credentials panel when it needs to show a * UI to edit the application-specific settings of the account. */ #include "application-plugin.h" #include enum { PROP_0, PROP_APPLICATION, PROP_ACCOUNT, N_PROPERTIES }; enum { FINISHED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static GParamSpec *properties[N_PROPERTIES] = { NULL, }; struct _ApApplicationPluginPrivate { AgAccount *account; AgApplication *application; GError *error; }; G_DEFINE_TYPE (ApApplicationPlugin, ap_application_plugin, G_TYPE_OBJECT); #define AP_APPLICATION_PLUGIN_PRIV(obj) (AP_APPLICATION_PLUGIN(obj)->priv) static void ap_application_plugin_init (ApApplicationPlugin *application_plugin) { application_plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (application_plugin, AP_TYPE_APPLICATION_PLUGIN, ApApplicationPluginPrivate); } static void ap_application_plugin_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { ApApplicationPluginPrivate *priv = AP_APPLICATION_PLUGIN_PRIV (object); switch (property_id) { case PROP_ACCOUNT: g_assert (priv->account == NULL); priv->account = g_value_dup_object (value); break; case PROP_APPLICATION: g_assert (priv->application == NULL); priv->application = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ap_application_plugin_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { ApApplicationPluginPrivate *priv = AP_APPLICATION_PLUGIN_PRIV (object); switch (property_id) { case PROP_ACCOUNT: g_value_set_object (value, priv->account); break; case PROP_APPLICATION: g_value_set_boxed (value, priv->application); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ap_application_plugin_dispose (GObject *object) { ApApplicationPluginPrivate *priv = AP_APPLICATION_PLUGIN_PRIV (object); g_clear_object (&priv->account); if (priv->application) { ag_application_unref (priv->application); priv->application = NULL; } G_OBJECT_CLASS (ap_application_plugin_parent_class)->dispose (object); } static void ap_application_plugin_finalize (GObject *object) { ApApplicationPluginPrivate *priv = AP_APPLICATION_PLUGIN_PRIV (object); g_clear_error (&priv->error); G_OBJECT_CLASS (ap_application_plugin_parent_class)->finalize (object); } static void ap_application_plugin_class_init (ApApplicationPluginClass *klass) { GObjectClass* object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (ApApplicationPluginPrivate)); object_class->set_property = ap_application_plugin_set_property; object_class->get_property = ap_application_plugin_get_property; object_class->dispose = ap_application_plugin_dispose; object_class->finalize = ap_application_plugin_finalize; /** * ApApplicationPlugin:account: * * The #AgAccount associated with the plugin. */ properties[PROP_ACCOUNT] = g_param_spec_object ("account", "Account for this plugin", "The AgAccount associated with the plugin", AG_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * ApApplicationPlugin:application: * * The #AgApplication associated with the plugin. */ properties[PROP_APPLICATION] = g_param_spec_boxed ("application", "Application for this plugin", "The AgApplication associated with the plugin", ag_application_get_type(), G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPERTIES, properties); /** * ApApplicationPlugin::finished: * @self: the #ApApplicationPlugin. * * Emitted when the plugin UI has completed its task and can be dismissed. */ signals[FINISHED] = g_signal_new ("finished", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } /** * ap_application_plugin_get_account: * @self: the #ApApplicationPlugin. * * Get the #AgAccount associated with this application_plugin instance. * * Returns: (transfer none): the #AgAccount, or %NULL. */ AgAccount * ap_application_plugin_get_account (ApApplicationPlugin *self) { g_return_val_if_fail (AP_IS_APPLICATION_PLUGIN (self), NULL); return self->priv->account; } /** * ap_application_plugin_get_application: * @self: the #ApApplicationPlugin. * * Get the #AgApplication associated with this plugin instance. * * Returns: (transfer none): the #AgApplication, or %NULL. */ AgApplication * ap_application_plugin_get_application (ApApplicationPlugin *self) { g_return_val_if_fail (AP_IS_APPLICATION_PLUGIN (self), NULL); return self->priv->application; } /** * ap_application_plugin_emit_finished: * @self: the #ApApplicationPlugin. * * Emits the #ApApplicationPlugin::finished signal. This method is useful for * subclasses only. */ void ap_application_plugin_emit_finished (ApApplicationPlugin *self) { g_return_if_fail (AP_IS_APPLICATION_PLUGIN (self)); g_signal_emit (self, signals[FINISHED], 0); } /** * ap_application_plugin_set_error: * @self: the #ApApplicationPlugin. * @error: the #GError to set on the plugin. * * Tell the application plugin that the requested operation ended in an error. * This method should be called by #ApApplicationPlugin subclasses only. */ void ap_application_plugin_set_error (ApApplicationPlugin *self, const GError *error) { ApApplicationPluginPrivate *priv; g_return_if_fail (AP_IS_APPLICATION_PLUGIN (self)); priv = self->priv; g_clear_error (&priv->error); if (error != NULL) { priv->error = g_error_copy (error); } } /** * ap_application_plugin_get_error: * @self: the #ApApplicationPlugin. * * Get whether the requested operation ended in an error. * * Returns: (transfer none): a #GError if an error occurred, %NULL otherwise. */ const GError * ap_application_plugin_get_error (ApApplicationPlugin *self) { g_return_val_if_fail (AP_IS_APPLICATION_PLUGIN (self), NULL); return self->priv->error; } /** * ap_application_plugin_build_widget: * @self: the #ApApplicationPlugin. * * Build a UI widget to edit the application-specific account settings on the * #AgAccount associated with this plugin. * The plugin must emit the #ApApplicationPlugin::finished signal once the * widget has completed its tasks and can be destroyed. * * Returns: (transfer floating): a #GtkWidget which till take care of * performing the needed tasks, or %NULL. */ GtkWidget * ap_application_plugin_build_widget (ApApplicationPlugin *self) { g_return_val_if_fail (AP_IS_APPLICATION_PLUGIN (self), NULL); return AP_APPLICATION_PLUGIN_GET_CLASS (self)->build_widget (self); } gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/AccountPlugin.vapi0000644000015600001650000000701712653650644030503 0ustar pbuserpbgroup00000000000000/* AccountPlugin.vapi generated by vapigen-0.16, do not modify. */ [CCode (cprefix = "Ap", gir_namespace = "AccountPlugin", gir_version = "1.0", lower_case_cprefix = "ap_")] namespace Ap { [CCode (cheader_filename = "libaccount-plugin/account-plugin.h", type_id = "ap_application_plugin_get_type ()")] public class ApplicationPlugin : GLib.Object { [CCode (has_construct_function = false)] protected ApplicationPlugin (); public virtual unowned Gtk.Widget build_widget (); public void emit_finished (); public unowned Ag.Account get_account (); public unowned Ag.Application get_application (); public unowned GLib.Error get_error (); public void set_error (GLib.Error error); public Ag.Account account { get; construct; } public Ag.Application application { get; construct; } public signal void finished (); } [CCode (cheader_filename = "libaccount-plugin/account-plugin.h", type_id = "ap_oauth_plugin_get_type ()")] public class OAuthPlugin : Ap.Plugin { [CCode (has_construct_function = false)] protected OAuthPlugin (); public void set_mechanism (Ap.OAuthMechanism mechanism); public void set_oauth_parameters (GLib.HashTable oauth_params); public void set_account_oauth_parameters (GLib.HashTable oauth_params); [NoAccessorMethod] public GLib.HashTable oauth_params { owned get; construct; } } [CCode (cheader_filename = "libaccount-plugin/account-plugin.h", type_id = "ap_plugin_get_type ()")] public class Plugin : GLib.Object { [CCode (has_construct_function = false)] protected Plugin (); public virtual void act_headless (); public virtual unowned Gtk.Widget build_widget (); public virtual async bool delete_account () throws GLib.Error; public void emit_finished (); public unowned Ag.Account get_account (); public unowned GLib.HashTable get_cookies (); public unowned GLib.Error get_error (); public bool get_ignore_cookies (); public bool get_need_authentication (); public unowned string get_password (); public unowned Ag.Provider get_provider (); public bool get_user_cancelled (); public unowned string get_username (); public void set_cookies (GLib.HashTable cookies); public void set_credentials (string username, string password); public void set_error (GLib.Error error); public void set_ignore_cookies (bool ignore_cookies); public void set_need_authentication (bool need_authentication); public void set_user_cancelled (bool cancelled); public Ag.Account account { get; construct; } public bool need_authentication { get; set; } public signal void finished (); } [CCode (cheader_filename = "libaccount-plugin/account-plugin.h", cprefix = "AP_OAUTH_MECHANISM_")] public enum OAuthMechanism { USER_AGENT, WEB_SERVER, HMAC_SHA1, PLAINTEXT, RSA_SHA1 } [CCode (cheader_filename = "libaccount-plugin/account-plugin.h", cname = "AP_PLUGIN_CREDENTIALS_ID_FIELD")] public const string PLUGIN_CREDENTIALS_ID_FIELD; [CCode (cheader_filename = "libaccount-plugin/account-plugin.h")] public static bool client_has_plugin (Ag.Provider provider); [CCode (cheader_filename = "libaccount-plugin/account-plugin.h")] public static Ap.ApplicationPlugin client_load_application_plugin (Ag.Application application, Ag.Account account); [CCode (cheader_filename = "libaccount-plugin/account-plugin.h")] public static Ap.Plugin client_load_plugin (Ag.Account account); [CCode (cheader_filename = "libaccount-plugin/account-plugin.h")] public static GLib.Type module_get_object_type (); } gnome-control-center-signon-0.1.8+16.04.20160201/libaccount-plugin/client.c0000644000015600001650000001653112653650644026472 0ustar pbuserpbgroup00000000000000/* vi: set et sw=4 ts=4 cino=t0,(0: */ /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of libaccount-plugin * * Copyright (C) 2012 Canonical Ltd. * * Contact: Alberto Mardegan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ /** * SECTION:ap-client * @short_description: Load account and application plugins. * @include: libaccount-plugin/client.h * * Load an #ApApplicationPlugin or #ApPlugin. */ #include "application-plugin.h" #include "client.h" #include "plugin.h" #include #include #include static gchar * get_module_path (AgProvider *provider) { const gchar *plugin_name; const gchar *plugin_dir; plugin_name = ag_provider_get_plugin_name (provider); if (plugin_name == NULL) plugin_name = ag_provider_get_name (provider); plugin_dir = g_getenv ("AP_PROVIDER_PLUGIN_DIR"); if (plugin_dir == NULL) plugin_dir = LIBACCOUNT_PLUGIN_DIR "/providers"; return g_module_build_path (plugin_dir, plugin_name); } /** * ap_client_load_plugin: * @account: the #AgAccount to be created/edited. * * Load the account plugin for @account. * * Returns: (transfer full): a new #ApPlugin if a valid plugin was found, %NULL * otherwise. */ ApPlugin * ap_client_load_plugin (AgAccount *account) { const gchar *provider_name; gchar *module_path; AgManager *manager; AgProvider *provider; GModule *module; ApPlugin *plugin = NULL; gboolean ok; GType (*ap_module_get_object_type) (void); GType object_type; g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL); provider_name = ag_account_get_provider_name (account); if (G_UNLIKELY (provider_name == NULL)) { g_warning ("%s: account has no provider!", G_STRFUNC); return NULL; } manager = ag_account_get_manager (account); g_return_val_if_fail (AG_IS_MANAGER (manager), NULL); provider = ag_manager_get_provider (manager, provider_name); g_return_val_if_fail (provider != NULL, NULL); module_path = get_module_path (provider); module = g_module_open (module_path, 0); if (G_UNLIKELY (module == NULL)) { g_warning ("%s: module %s not found: %s", G_STRFUNC, module_path, g_module_error ()); goto error; } ok = g_module_symbol (module, "ap_module_get_object_type", (gpointer *)&ap_module_get_object_type); if (G_UNLIKELY (!ok || ap_module_get_object_type == NULL)) { g_critical ("%s: module %s does not export ap_module_get_object_type", G_STRFUNC, module_path); g_module_close (module); goto error; } object_type = ap_module_get_object_type (); if (G_UNLIKELY (!G_TYPE_IS_OBJECT (object_type))) { g_critical ("%s: module %s does not create a valid GObject", G_STRFUNC, module_path); g_module_close (module); goto error; } plugin = g_object_new (object_type, "account", account, NULL); if (G_UNLIKELY (!AP_IS_PLUGIN (plugin))) { g_critical ("%s: module %s did not create a valid ApPlugin", G_STRFUNC, module_path); g_module_close (module); goto error; } /* Make sure that the module is not unloaded: the GType system doesn't * support that. */ g_module_make_resident (module); error: ag_provider_unref (provider); g_free (module_path); return plugin; } /** * ap_client_has_plugin: * @provider: the account provider. * * Checks if there is a valid account plugin for creating accounts having * @provider as provider. * * Returns: %TRUE if a plugin is found, %FALSE otherwise. */ gboolean ap_client_has_plugin (AgProvider *provider) { gchar *module_path; gboolean exists; module_path = get_module_path (provider); if (!module_path) return FALSE; exists = g_file_test (module_path, G_FILE_TEST_EXISTS); g_free (module_path); return exists; } /** * ap_client_load_application_plugin: * @application: the #AgApplication. * @account: the #AgAccount to be edited. * * Load the application plugin for editing the @application specific settings * of @account. * * Returns: (transfer full): a new #ApApplicationPlugin if a valid plugin was * found, %NULL otherwise. */ ApApplicationPlugin * ap_client_load_application_plugin (AgApplication *application, AgAccount *account) { const gchar *application_name; const gchar *plugin_dir; gchar *module_path; GModule *module; ApApplicationPlugin *plugin = NULL; gboolean ok; GType (*ap_module_get_object_type) (void); GType object_type; g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL); application_name = ag_application_get_name (application); if (G_UNLIKELY (application_name == NULL)) { g_warning ("%s: application has no name!", G_STRFUNC); return NULL; } plugin_dir = g_getenv ("AP_APPLICATION_PLUGIN_DIR"); if (plugin_dir == NULL) plugin_dir = LIBACCOUNT_PLUGIN_DIR "/applications"; module_path = g_module_build_path (plugin_dir, application_name); module = g_module_open (module_path, 0); if (module == NULL) { /* The absence of an application plugin is not an exceptional * condition; therefore, do not emit any warning here, but just return * quietly. */ goto finish; } ok = g_module_symbol (module, "ap_module_get_object_type", (gpointer *)&ap_module_get_object_type); if (G_UNLIKELY (!ok || ap_module_get_object_type == NULL)) { g_critical ("%s: module %s does not export ap_module_get_object_type", G_STRFUNC, module_path); g_module_close (module); goto error; } object_type = ap_module_get_object_type (); if (G_UNLIKELY (!G_TYPE_IS_OBJECT (object_type))) { g_critical ("%s: module %s does not create a valid GObject", G_STRFUNC, module_path); g_module_close (module); goto error; } plugin = g_object_new (object_type, "application", application, "account", account, NULL); if (G_UNLIKELY (!AP_IS_APPLICATION_PLUGIN (plugin))) { g_critical ("%s: module %s did not create a valid ApApplicationPlugin", G_STRFUNC, module_path); g_module_close (module); goto error; } /* Make sure that the module is not unloaded: the GType system doesn't * support that. */ g_module_make_resident (module); error: finish: g_free (module_path); return plugin; } gnome-control-center-signon-0.1.8+16.04.20160201/ChangeLog0000644000015600001650000000000012653650644023163 0ustar pbuserpbgroup00000000000000