Commit 0444fd83 authored by Andrej Shadura's avatar Andrej Shadura

Merge and update the libsecret port

Signed-off-by: Andrej Shadura's avatarAndrej Shadura <andrew.shadura@collabora.co.uk>
parents f9920939 bd98d036
......@@ -18,7 +18,7 @@ Architecture: all
Conflicts: gtimelog
Replaces: gtimelog
Depends: gir1.2-appindicator3-0.1,
gir1.2-gnomekeyring-1.0,
gir1.2-secret-1,
gir1.2-gtk-3.0,
gir1.2-soup-2.4,
gir1.2-pango-1.0 (>= 1.29.3+git20110916),
......
......@@ -770,13 +770,28 @@ class TaskList(object):
# Global HTTP stuff
class Authenticator(object):
# try to use GNOME Keyring if available
# Try to use LibSecret if available
try:
gi.require_version('GnomeKeyring', '1.0')
from gi.repository import GnomeKeyring as gnomekeyring
gi.require_version('Secret', '1')
from gi.repository import Secret
# This is defined by libsecret for migration from gnome-keyring, but it
# isn't exported by gobject-introspection, so we redefine it here.
SECRET_SCHEMA_COMPAT_NETWORK = Secret.Schema.new(
"org.gnome.keyring.NetworkPassword",
Secret.SchemaFlags.NONE,
{
"user": Secret.SchemaAttributeType.STRING,
"domain": Secret.SchemaAttributeType.STRING,
"object": Secret.SchemaAttributeType.STRING,
"protocol": Secret.SchemaAttributeType.STRING,
"port": Secret.SchemaAttributeType.INTEGER,
"server": Secret.SchemaAttributeType.STRING,
"authtype": Secret.SchemaAttributeType.STRING,
}
)
except ImportError:
print("GnomeKeyring not found. You will not be able to use the password keyring.")
gnomekeyring = None
print("LibSecret not found. You will not be able to use the password keyring.")
Secret = None
def __init__(self):
object.__init__(self)
......@@ -786,54 +801,57 @@ class Authenticator(object):
def find_in_keyring(self, uri, callback):
"""Attempts to load a username and password from the keyring, if the
keyring is available"""
if self.gnomekeyring is None:
if self.Secret is None:
callback(None, None)
return
username = None
password = None
# FIXME - would be nice to make all keyring calls async, to dodge
# the possibility of blocking the UI. The code is all set up for
# that, but there's no easy way to use the keyring asynchronously
# from Python (as of Gnome 3.2)...
l = self.gnomekeyring.find_network_password_sync (
None, # user
uri.get_host(), # domain
uri.get_host(), # server
None, # object
uri.get_scheme(),# protocol
None, # authtype
uri.get_port()) # port
result, keys = l
if result == self.gnomekeyring.Result.NO_MATCH:
# We didn't find any passwords, just continue
pass
elif result == self.gnomekeyring.Result.NO_KEYRING_DAEMON:
pass
else:
entry = keys[-1] # take the last key (Why?)
username = entry.user
password = entry.password
try:
# FIXME: would be nice to make all keyring calls async, to dodge
# the possibility of blocking the UI. The code is all set up for it.
# It can be done with libsecret from Python; docs have examples.
attrs = {
"domain": uri.get_host(),
"server": uri.get_host(),
"protocol": uri.get_scheme(),
}
service = self.Secret.Service.get_sync(0, None)
# This doesn't give us the password; only details from the schema
results = service.search_sync(
self.SECRET_SCHEMA_COMPAT_NETWORK,
attrs, 0, None)
if results:
username = results[0].get_attributes()['user']
# This gives us only the password
password = self.Secret.password_lookup_sync(
self.SECRET_SCHEMA_COMPAT_NETWORK, attrs, None)
except self.gi._glib.GError as e:
# Couldn't contact daemon, or other errors
print ("Unable to contact keyring: {0}".format(e.streerror))
callback(username, password)
def save_to_keyring(self, uri, username, password):
result, keys = self.gnomekeyring.set_network_password_sync (
None, # keyring
username, # user
uri.get_host(), # domain
uri.get_host(), # server
None, # object
uri.get_scheme(),# protocol
None, # authtype
uri.get_port(), # port
password) # password
if result == self.gnomekeyring.Result.OK:
print("Password saved successfully")
else:
print("Failed to save password, error={}", result)
try:
attrs = {
"user": username,
"domain": uri.get_host(),
"server": uri.get_host(),
# BUG: Passing 'None' for a string causes a segfault
# https://bugzilla.gnome.org/show_bug.cgi?id=685394
"object": "",
"protocol": uri.get_scheme(),
}
self.Secret.password_store_sync(
self.SECRET_SCHEMA_COMPAT_NETWORK,
attrs,
self.Secret.COLLECTION_DEFAULT,
"Chronophage password for GTimelog", password, None)
except self.gi._glib.GError as e:
# Couldn't contact daemon, or other errors
print ("Unable to contact keyring: {0}".format(e.streerror))
def ask_the_user(self, auth, uri, callback):
"""Pops up a username/password dialog for uri"""
......@@ -868,7 +886,7 @@ class Authenticator(object):
grid.attach_next_to(userentry, username_label, Gtk.PositionType.RIGHT, 1, 1)
grid.attach_next_to(passentry, password_label, Gtk.PositionType.RIGHT, 1, 1)
if self.gnomekeyring:
if self.Secret:
savepasstoggle = Gtk.CheckButton ("Save Password in Keyring")
savepasstoggle.set_active (True)
grid.attach_next_to(savepasstoggle, passentry,
......@@ -886,7 +904,7 @@ class Authenticator(object):
update_ok_sensitivity()
def on_response(dialog, r):
save_to_keyring = self.gnomekeyring and savepasstoggle.get_active()
save_to_keyring = self.Secret and savepasstoggle.get_active()
if r == Gtk.ResponseType.OK:
username = userentry.get_text ()
......@@ -2749,7 +2767,7 @@ class SubmitWindow(object):
def upload(self, data, automatic):
if not os.path.exists(self.settings.server_cert):
print("Server certificate %s not found" % self.settings.server_cert)
print("Server certificate file '%s' not found" % self.settings.server_cert)
message = Soup.Message.new('POST', self.report_url)
message.request_headers.set_content_type('application/x-www-form-urlencoded', None)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment