Merge lp:~lifeless/launchpad/bug-898638 into lp:launchpad

Proposed by Robert Collins
Status: Merged
Approved by: William Grant
Approved revision: not available
Merged at revision: 14453
Proposed branch: lp:~lifeless/launchpad/bug-898638
Merge into: lp:launchpad
Diff against target: 53 lines (+25/-6)
2 files modified
lib/canonical/launchpad/webapp/login.py (+16/-6)
lib/canonical/launchpad/webapp/tests/test_login.py (+9/-0)
To merge this branch: bzr merge lp:~lifeless/launchpad/bug-898638
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+84891@code.launchpad.net

Commit message

Unbreak forwarding of genuine unicode query parameters to the SSO for login.

Description of the change

This completes the fix I did for non-ascii bad-unicode encodings, making it work with non-ascii unicode parameters too. The zope form API is not type-constant with its parameters (about a -10 on the rusty API scale :().

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/webapp/login.py'
2--- lib/canonical/launchpad/webapp/login.py 2011-11-28 02:12:47 +0000
3+++ lib/canonical/launchpad/webapp/login.py 2011-12-08 04:42:27 +0000
4@@ -263,13 +263,23 @@
5 value_list = value
6 else:
7 value_list = [value]
8+ def restore_url(element):
9+ """Restore a form item to its original url representation.
10+
11+ The form items are byte strings simply url decoded and
12+ sometimes utf8 decoded (for special confusion). They may fail
13+ to coerce to unicode as they can include arbitrary
14+ bytesequences after url decoding. We can restore their original
15+ url value by url quoting them again if they are a bytestring,
16+ with a pre-step of utf8 encoding if they were successfully
17+ decoded to unicode.
18+ """
19+ if isinstance(element, unicode):
20+ element = element.encode('utf8')
21+ return urllib.quote(element)
22 for value_list_item in value_list:
23- # The form items are byte strings simply url decoded. They may
24- # fail to coerce to unicode as they can include arbitrary
25- # bytesequences after url decoding. We can restore their
26- # original url value by url quoting them again.
27- value_list_item = urllib.quote(value_list_item)
28- name = urllib.quote(name)
29+ value_list_item = restore_url(value_list_item)
30+ name = restore_url(name)
31 yield "%s=%s" % (name, value_list_item)
32
33
34
35=== modified file 'lib/canonical/launchpad/webapp/tests/test_login.py'
36--- lib/canonical/launchpad/webapp/tests/test_login.py 2011-11-28 02:51:35 +0000
37+++ lib/canonical/launchpad/webapp/tests/test_login.py 2011-12-08 04:42:27 +0000
38@@ -705,6 +705,15 @@
39 # utf8 even.
40 self.assertThat('key\x85=value', ForwardsCorrectly())
41
42+ def test_unicode_form_params_bug_898638(self):
43+ # Sometimes the form params are unicode because a decode('utf8') worked
44+ # in the form machinery... and if so they cannot be trivially quoted
45+ # but must be encoded first.
46+ key = urllib.quote(u'key\xf3'.encode('utf8'))
47+ value = urllib.quote(u'value\xf3'.encode('utf8'))
48+ query_string = "%s=%s" % (key, value)
49+ self.assertThat(query_string, ForwardsCorrectly())
50+
51 def test_sreg_fields(self):
52 # We request the user's email address and Full Name (through the SREG
53 # extension) to the OpenID provider so that we can automatically