← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~bac/launchpadlib/bug-745801 into lp:launchpadlib

 

Brad Crittenden has proposed merging lp:~bac/launchpadlib/bug-745801 into lp:launchpadlib.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #745801 in launchpadlib : "system-based authorization broken in gnome-keyring: NoOptionError: No option 'consumer_key' in section: '1'"
  https://bugs.launchpad.net/launchpadlib/+bug/745801

For more details, see:
https://code.launchpad.net/~bac/launchpadlib/bug-745801/+merge/82560

Since some users experienced problems saving the configuration containing lplib keys into their keyring, this branch base64 encodes the values before putting into the keyring in an attempt to avoid freaking out the Gnome keyring or KDE wallet.

When decoding credentials a test is made to see if we have an unencoded string to provide backwards compatibility.

-- 
https://code.launchpad.net/~bac/launchpadlib/bug-745801/+merge/82560
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~bac/launchpadlib/bug-745801 into lp:launchpadlib.
=== added file 'krdebug.py'
--- krdebug.py	1970-01-01 00:00:00 +0000
+++ krdebug.py	2011-11-17 16:47:38 +0000
@@ -0,0 +1,14 @@
+import launchpadlib
+from launchpadlib.launchpad import Launchpad
+from launchpadlib import uris
+
+
+def main():
+    lp = Launchpad.login_with(
+        application_name='keyringdebug',
+        service_root=uris.LPNET_SERVICE_ROOT)
+    print "lp.me =", lp.me.name
+    print launchpadlib.__file__
+
+if __name__ == '__main__':
+    main()

=== modified file 'src/launchpadlib/credentials.py'
--- src/launchpadlib/credentials.py	2011-11-10 15:29:38 +0000
+++ src/launchpadlib/credentials.py	2011-11-17 16:47:38 +0000
@@ -36,6 +36,11 @@
 from urllib import urlencode
 from urlparse import urljoin
 import webbrowser
+import ConfigParser
+from base64 import (
+    b64decode,
+    b64encode,
+    )
 
 import simplejson
 
@@ -69,6 +74,8 @@
 
     URI_TOKEN_FORMAT = "uri"
     DICT_TOKEN_FORMAT = "dict"
+    ITEM_SEPARATOR = '<BR>'
+    NEWLINE = '\n'
 
     def serialize(self):
         """Turn this object into a string.
@@ -77,7 +84,12 @@
         """
         sio = StringIO()
         self.save(sio)
-        return sio.getvalue()
+        serialized = sio.getvalue()
+        # Some users have reported problems with corrupted keyrings, both in
+        # Gnome and KDE, when newlines are included in the password.  Avoid
+        # this problem by base 64 encoding the serialized value.
+        serialized = b64encode(serialized)
+        return serialized
 
     @classmethod
     def from_string(cls, value):
@@ -86,6 +98,8 @@
         This should probably be moved into OAuthAuthorizer.
         """
         credentials = cls()
+        if 'consumer_key' not in value:
+            value = b64decode(value)
         credentials.load(StringIO(value))
         return credentials
 
@@ -121,7 +135,7 @@
             oauth_signature_method='PLAINTEXT',
             oauth_signature='&')
         url = web_root + request_token_page
-        headers = {'Referer' : web_root}
+        headers = {'Referer': web_root}
         if token_format == self.DICT_TOKEN_FORMAT:
             headers['Accept'] = 'application/json'
         response, content = httplib2.Http().request(
@@ -310,8 +324,9 @@
     def do_save(self, credentials, unique_key):
         """Store newly-authorized credentials in the keyring."""
         self._ensure_keyring_imported()
+        serialized = credentials.serialize()
         keyring.set_password(
-            'launchpadlib', unique_key, credentials.serialize())
+            'launchpadlib', unique_key, serialized)
 
     def do_load(self, unique_key):
         """Retrieve credentials from the keyring."""
@@ -320,7 +335,14 @@
             'launchpadlib', unique_key)
         if credential_string is not None:
             credential_string = credential_string.encode('utf8')
-            return Credentials.from_string(credential_string)
+            try:
+                credentials = Credentials.from_string(credential_string)
+                return credentials
+            except ConfigParser.NoOptionError as noe:
+                print "OOPS"
+                print "%r" % credential_string
+                print noe
+                return None
         return None