From 8caae4b7b70e9c44121643683ac1595c202125fc Mon Sep 17 00:00:00 2001
From: Daniel Haas <daniel.haas@childrens.harvard.edu>
Date: Wed, 6 Jun 2012 15:30:52 +0000
Subject: [PATCH 1/5] Always sign requests in the headers, not in the body or
 querystring.

---
 oauth2/__init__.py | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/oauth2/__init__.py b/oauth2/__init__.py
index 835270e3..90fefed6 100644
--- a/oauth2/__init__.py
+++ b/oauth2/__init__.py
@@ -402,7 +402,7 @@ def to_header(self, realm=''):
     def to_postdata(self):
         """Serialize as post data for a POST request."""
         d = {}
-        for k, v in self.iteritems():
+        for k, v in self.get_nonoauth_parameters().iteritems():
             d[k.encode('utf-8')] = to_utf8_optional_iterator(v)
 
         # tell urlencode to deal with sequence values and map them correctly
@@ -419,7 +419,7 @@ def to_url(self):
             # must be python <2.5
             query = base_url[4]
         query = parse_qs(query)
-        for k, v in self.items():
+        for k, v in self.get_nonoauth_parameters().iteritems():
             query.setdefault(k, []).append(v)
         
         try:
@@ -670,12 +670,14 @@ def request(self, uri, method="GET", body='', headers=None,
 
         realm = schema + ':' + hierpart + host
 
+        # Get request data, as the body or as the querystring
         if is_form_encoded:
             body = req.to_postdata()
         elif method == "GET":
             uri = req.to_url()
-        else:
-            headers.update(req.to_header(realm=realm))
+
+        # Always sign the headers
+        headers.update(req.to_header(realm=realm))
 
         return httplib2.Http.request(self, uri, method=method, body=body,
             headers=headers, redirections=redirections,

From 654858cf352e07e63ababbd44d23696ef0865012 Mon Sep 17 00:00:00 2001
From: Daniel Haas <daniel.haas@childrens.harvard.edu>
Date: Fri, 8 Jun 2012 21:05:38 +0000
Subject: [PATCH 2/5] Normalized parameters for sbs still need to include
 form-encoded body data.

---
 oauth2/__init__.py | 35 ++++++++++++++++-------------------
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/oauth2/__init__.py b/oauth2/__init__.py
index 90fefed6..779b0876 100644
--- a/oauth2/__init__.py
+++ b/oauth2/__init__.py
@@ -32,7 +32,7 @@
 import httplib2
 
 try:
-    from urlparse import parse_qs
+    from urlparse import parse_qs, parse_qsl
     parse_qs # placate pyflakes
 except ImportError:
     # fall back for Python 2.5
@@ -450,7 +450,18 @@ def get_parameter(self, parameter):
     def get_normalized_parameters(self):
         """Return a string that contains the parameters that must be signed."""
         items = []
-        for key, value in self.iteritems():
+
+        params = self.items()
+        # Include any query string parameters from the provided URL
+        query = urlparse.urlparse(self.url)[4]
+        url_items = self._split_url_string(query).items()
+        params.extend(url_items)
+        # Include any form-encoded parameters from the body
+        if self.is_form_encoded:
+           params.extend(parse_qsl(self.body)) 
+        
+        for p in params:
+            key, value = p
             if key == 'oauth_signature':
                 continue
             # 1.0a/9.1.1 states that kvp must be sorted by key, then by value,
@@ -466,13 +477,6 @@ def get_normalized_parameters(self):
                 else:
                     items.extend((to_utf8_if_string(key), to_utf8_if_string(item)) for item in value)
 
-        # Include any query string parameters from the provided URL
-        query = urlparse.urlparse(self.url)[4]
-
-        url_items = self._split_url_string(query).items()
-        url_items = [(to_utf8(k), to_utf8(v)) for k, v in url_items if k != 'oauth_signature' ]
-        items.extend(url_items)
-
         items.sort()
         encoded_str = urllib.urlencode(items)
         # Encode signature parameters per Oauth Core 1.0 protocol
@@ -650,14 +654,9 @@ def request(self, uri, method="GET", body='', headers=None,
         is_form_encoded = \
             headers.get('Content-Type') == 'application/x-www-form-urlencoded'
 
-        if is_form_encoded and body:
-            parameters = parse_qs(body)
-        else:
-            parameters = None
-
         req = Request.from_consumer_and_token(self.consumer, 
             token=self.token, http_method=method, http_url=uri, 
-            parameters=parameters, body=body, is_form_encoded=is_form_encoded)
+            parameters=None, body=body, is_form_encoded=is_form_encoded)
 
         req.sign_request(self.method, self.consumer, self.token)
 
@@ -670,10 +669,8 @@ def request(self, uri, method="GET", body='', headers=None,
 
         realm = schema + ':' + hierpart + host
 
-        # Get request data, as the body or as the querystring
-        if is_form_encoded:
-            body = req.to_postdata()
-        elif method == "GET":
+        # Get querystring request data
+        if method == "GET":
             uri = req.to_url()
 
         # Always sign the headers

From 9014d97798280ee4355a4734f45c9443f95c98a4 Mon Sep 17 00:00:00 2001
From: Travers Franckle <travers.franckle@childrens.harvard.edu>
Date: Thu, 14 Jun 2012 11:35:41 -0400
Subject: [PATCH 3/5] Bugfix: keeping blank values in form-encoded body
 parameters, as per the oauth spec

---
 oauth2/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/oauth2/__init__.py b/oauth2/__init__.py
index 779b0876..0be674a9 100644
--- a/oauth2/__init__.py
+++ b/oauth2/__init__.py
@@ -458,7 +458,7 @@ def get_normalized_parameters(self):
         params.extend(url_items)
         # Include any form-encoded parameters from the body
         if self.is_form_encoded:
-           params.extend(parse_qsl(self.body)) 
+           params.extend(parse_qsl(self.body, keep_blank_values=True)) 
         
         for p in params:
             key, value = p

From b75b15108f1e7fdb99951e7bae795aa83d96eb24 Mon Sep 17 00:00:00 2001
From: Travers Franckle <travers.franckle@childrens.harvard.edu>
Date: Thu, 14 Jun 2012 11:39:55 -0400
Subject: [PATCH 4/5] Add support for mod_wsgi style authorization header

---
 oauth2/__init__.py | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/oauth2/__init__.py b/oauth2/__init__.py
index 0be674a9..e3f8c83b 100644
--- a/oauth2/__init__.py
+++ b/oauth2/__init__.py
@@ -523,10 +523,14 @@ def from_request(cls, http_method, http_url, headers=None, parameters=None,
             parameters = {}
  
         # Headers
-        if headers and 'Authorization' in headers:
-            auth_header = headers['Authorization']
+	if headers:
+            auth_header = None
+            if 'Authorization' in headers:
+                auth_header = headers['Authorization']
+            elif 'HTTP_AUTHORIZATION' in headers:
+                auth_header = headers['HTTP_AUTHORIZATION']
             # Check that the authorization header is OAuth.
-            if auth_header[:6] == 'OAuth ':
+            if auth_header and auth_header[:6] == 'OAuth ':
                 auth_header = auth_header[6:]
                 try:
                     # Get the parameters from the header.
@@ -534,9 +538,9 @@ def from_request(cls, http_method, http_url, headers=None, parameters=None,
                     parameters.update(header_params)
                 except:
                     raise Error('Unable to parse OAuth parameters from '
-                        'Authorization header.')
- 
-        # GET or POST query string.
+                        'Authorization header.') 
+        
+	# GET or POST query string.
         if query_string:
             query_params = cls._split_url_string(query_string)
             parameters.update(query_params)

From 0fb769f8c4187c7c5e2380e09191891fc2d7ad32 Mon Sep 17 00:00:00 2001
From: Travers Franckle <travers.franckle@childrens.harvard.edu>
Date: Thu, 14 Jun 2012 11:40:58 -0400
Subject: [PATCH 5/5] don't double de-encode params

---
 oauth2/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/oauth2/__init__.py b/oauth2/__init__.py
index e3f8c83b..228053da 100644
--- a/oauth2/__init__.py
+++ b/oauth2/__init__.py
@@ -616,7 +616,7 @@ def _split_url_string(param_str):
         """Turn URL string into parameters."""
         parameters = parse_qs(param_str.encode('utf-8'), keep_blank_values=True)
         for k, v in parameters.iteritems():
-            parameters[k] = urllib.unquote(v[0])
+            parameters[k] = v[0]
         return parameters
 
 
