Browse Source

Ensure there is never an empty URI path component when generating the base string.

Tim Fletcher 17 years ago
parent
commit
506a125848
3 changed files with 26 additions and 2 deletions
  1. 9 1
      src/oauth_hmac.erl
  2. 2 1
      src/oauth_unit.erl
  3. 15 0
      src/oauth_util.erl

+ 9 - 1
src/oauth_hmac.erl

@@ -13,11 +13,19 @@ signature(BaseString, ConsumerSecret, TokenSecret) ->
   b64(crypto:sha_mac(key(ConsumerSecret, TokenSecret), BaseString)).
 
 base_string(Method, URL, Params) when is_list(Method) ->
-  string:join(lists:map(fun fmt:percent_encode/1, [Method, URL, normalize(Params)]), "&").
+  string:join(lists:map(fun fmt:percent_encode/1, [Method, uri_normalize(URL), normalize(Params)]), "&").
 
 normalize(Params) ->
   oauth_params:to_string(sort(Params)).
 
+uri_normalize(URL) ->
+  case http_uri:parse(URL) of
+    {error, _Reason} ->
+      URL;
+    Parts ->
+      oauth_util:uri_join(Parts)
+  end.
+
 sort(Params) ->
   lists:sort(fun({K,X},{K,Y}) -> X < Y; ({A,_},{B,_}) -> A < B end, Params).
 

+ 2 - 1
src/oauth_unit.erl

@@ -36,7 +36,8 @@ hmac_normalize_test_() -> [
 
 hmac_base_string_test_() -> [
   % cf. http://wiki.oauth.net/TestCases
-  ?hmac_base_string_test("GET", "http://example.com", [{n,v}], ["GET&http%3A%2F%2Fexample.com&n%3Dv"]),
+  ?hmac_base_string_test("GET", "http://example.com/", [{n,v}], ["GET&http%3A%2F%2Fexample.com%2F&n%3Dv"]),
+  ?hmac_base_string_test("GET", "http://example.com", [{n,v}], ["GET&http%3A%2F%2Fexample.com%2F&n%3Dv"]),
   ?hmac_base_string_test("POST", "https://photos.example.net/request_token", [
     {oauth_version, "1.0"},
     {oauth_consumer_key, "dpf43f3p2l4k3l03"},

+ 15 - 0
src/oauth_util.erl

@@ -32,3 +32,18 @@ percent_decode([$%,A,B|Etc], Decoded) when ?is_hex(A), ?is_hex(B) ->
   percent_decode(Etc, [erlang:list_to_integer([A,B], 16)|Decoded]);
 percent_decode([C|Etc], Decoded) when ?is_unreserved(C) ->
   percent_decode(Etc, [C|Decoded]).
+
+uri_join({Scheme, UserInfo, Host, Port, Path, Query}) ->
+  uri_join(Scheme, UserInfo, Host, Port, [Path, Query]).
+
+uri_join(http, UserInfo, Host, 80, URI) ->
+  uri_join(http, UserInfo, [Host|URI]);
+uri_join(https, UserInfo, Host, 443, URI) ->
+  uri_join(https, UserInfo, [Host|URI]);
+uri_join(Scheme, UserInfo, Host, Port, URI) ->
+  uri_join(Scheme, UserInfo, [Host, ":", Port|URI]).
+
+uri_join(Scheme, [], URI) ->
+  lists:concat([Scheme, "://"|URI]);
+uri_join(Scheme, UserInfo, URI) ->
+  lists:concat([Scheme, "://", UserInfo, "@"|URI]).