2 Commits
Author SHA1 Message Date
krogoth 0386df2606 Fix for basestring URI not properly encoded regarding RFC5849 ch 3.4.1.2
This will prevent failure for non standard port and uppercase host or scheme strings
Added related test cases.

Warning : Request constructor signature changed. A java.net.MalformedURLException exception will be throw when creating a request if not a proper URL
previously this cannot occur until send.
2011-02-03 16:48:11 +01:00
krogoth ca0076c043 Refactored scribe 1.1.0 to handdle properly encodings as per RFC5849. This is the first try for comment. 2011-02-03 00:03:45 +01:00
45 changed files with 281 additions and 739 deletions

No files matched your search

+4 -4
View File
@@ -1,3 +1,5 @@
!http://img411.imageshack.us/img411/2851/scribelogo.png!
h2. Welcome to the home of Scribe, the simple OAuth Java lib!
h1. Why use Scribe?
@@ -18,12 +20,10 @@ h3. Threadsafe
Hit Scribe as hard and with many threads as you like.
h3. Supports all major 1.0a and 2.0 OAuth APIs out-of-the-box
h3. Supports all major OAuth APIs out-of-the-box
* Google
* Facebook
* Yahoo
* LinkedIn
@@ -61,7 +61,7 @@ You can pull scribe from a maven repository, just add this to your __pom.xml__ f
@<dependency>@
@<groupId>org.scribe</groupId>@
@<artifactId>scribe</artifactId>@
@<version>1.1.2</version>@
@<version>1.0.6</version>@
@</dependency>@
h1. Getting started in less than 2 minutes
-2
View File
@@ -1,2 +0,0 @@
#!/bin/sh
mvn source:jar javadoc:jar package gpg:sign repository:bundle-create -Dgpg.passphrase=$1
+1 -16
View File
@@ -28,19 +28,4 @@
[1.1.1]
* FIX: Removed isEmpty() from OAuth2.0 code in order to support older JVMs
* FEATURE: Overloaded provider() method to support instances as well as classes (thanks dustismo)
* FIX: White-space parameter bug (thanks Krogoth)
* FEATURE: OAuth 2.0 now implements server-flow (thanks Diego Silveira)
[1.1.2]
* FIX: Fixed ugly bug that made 1.1.1 practically unusable (thanks Stubbs)
[1.1.3]
* FEATURE: Added rawResponse to Token, for extracting additional parameters (thanks Dirk McCormick)
* FEATURE: Added Dropbox Api
* FIX: Token responses now work despite of the token/secret order
* FEATURE: Added Foursquare OAuth 2.0 Api (thanks Tom Tasche)
* FEATURE: Added support for OAuth1.0a signatures via querystring parameters
* FEATURE: Added ConstantContact Api (thanks Matthew Laudato)
* FEATURE: Overloaded provider() method to support instances as well as classes (thanks dustismo)
+1 -1
View File
@@ -4,7 +4,7 @@
<groupId>org.scribe</groupId>
<artifactId>scribe</artifactId>
<packaging>jar</packaging>
<version>1.1.2</version>
<version>1.1.0</version>
<name>Scribe OAuth Library</name>
<description>The best OAuth library out there</description>
<url>http://github.com/fernandezpablo85/scribe-java</url>
@@ -20,7 +20,6 @@ public class ServiceBuilder
private String callback;
private Api api;
private String scope;
private SignatureType signatureType;
/**
* Default constructor
@@ -123,19 +122,6 @@ public class ServiceBuilder
this.scope = scope;
return this;
}
/**
* Configures the signature type, choose between header, querystring, etc. Defaults to Header
*
* @param scope The OAuth scope
* @return the {@link ServiceBuilder} instance for method chaining
*/
public ServiceBuilder signatureType(SignatureType type)
{
Preconditions.checkNotNull(type, "Signature type can't be null");
this.signatureType = type;
return this;
}
/**
* Returns the fully configured {@link OAuthService}
@@ -147,6 +133,6 @@ public class ServiceBuilder
Preconditions.checkNotNull(api, "You must specify a valid api through the provider() method");
Preconditions.checkEmptyString(apiKey, "You must provide an api key");
Preconditions.checkEmptyString(apiSecret, "You must provide an api secret");
return api.createService(new OAuthConfig(apiKey, apiSecret, callback, signatureType), scope);
return api.createService(new OAuthConfig(apiKey, apiSecret, callback), scope);
}
}
@@ -1,26 +0,0 @@
package org.scribe.builder.api;
import org.scribe.model.*;
public class ConstantContactApi extends DefaultApi10a
{
private static final String AUTHORIZE_URL = "https://oauth.constantcontact.com/ws/oauth/confirm_access?oauth_token=%s";
@Override
public String getAccessTokenEndpoint()
{
return "https://oauth.constantcontact.com/ws/oauth/access_token";
}
@Override
public String getAuthorizationUrl(Token requestToken)
{
return String.format(AUTHORIZE_URL, requestToken.getToken());
}
@Override
public String getRequestTokenEndpoint()
{
return "https://oauth.constantcontact.com/ws/oauth/request_token";
}
}
@@ -1,6 +1,5 @@
package org.scribe.builder.api;
import org.scribe.extractors.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
@@ -23,33 +22,6 @@ import org.scribe.oauth.*;
public abstract class DefaultApi20 implements Api
{
/**
* Returns the access token extractor.
*
* @return access token extractor
*/
public AccessTokenExtractor getAccessTokenExtractor()
{
return new TokenExtractor20Impl();
}
/**
* Returns the verb for the access token endpoint (defaults to GET)
*
* @return access token endpoint verb
*/
public Verb getAccessTokenVerb()
{
return Verb.GET;
}
/**
* Returns the URL that receives the access token requests.
*
* @return access token URL
*/
public abstract String getAccessTokenEndpoint();
/**
* Returns the URL where you should redirect your users to authenticate
* your application.
@@ -1,25 +0,0 @@
package org.scribe.builder.api;
import org.scribe.model.*;
public class DropBoxApi extends DefaultApi10a
{
@Override
public String getAccessTokenEndpoint()
{
return "https://api.dropbox.com/0/oauth/access_token";
}
@Override
public String getAuthorizationUrl(Token requestToken)
{
return "https://www.dropbox.com/0/oauth/authorize?oauth_token="+requestToken.getToken();
}
@Override
public String getRequestTokenEndpoint()
{
return "https://api.dropbox.com/0/oauth/request_token";
}
}
@@ -5,18 +5,12 @@ import org.scribe.utils.*;
public class FacebookApi extends DefaultApi20
{
private static final String AUTHORIZE_URL = "https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s";
private static final String AUTHORIZE_URL = "https://graph.facebook.com/oauth/authorize?response_type=token&client_id=%s&redirect_uri=%s";
@Override
public String getAccessTokenEndpoint()
{
return "https://graph.facebook.com/oauth/access_token";
}
@Override
public String getAuthorizationUrl(OAuthConfig config)
{
Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Facebook does not support OOB");
return String.format(AUTHORIZE_URL, config.getApiKey(), URLUtils.formURLEncode(config.getCallback()));
return String.format(AUTHORIZE_URL, config.getApiKey(), URLUtils.urlEncodeWrapper(config.getCallback()));
}
}
@@ -1,29 +0,0 @@
package org.scribe.builder.api;
import org.scribe.extractors.*;
import org.scribe.model.*;
import org.scribe.utils.*;
public class Foursquare2Api extends DefaultApi20
{
private static final String AUTHORIZATION_URL = "https://foursquare.com/oauth2/authenticate?client_id=%s&response_type=code&redirect_uri=%s";
@Override
public String getAccessTokenEndpoint()
{
return "https://foursquare.com/oauth2/access_token?grant_type=authorization_code";
}
@Override
public String getAuthorizationUrl(OAuthConfig config)
{
Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Foursquare2 does not support OOB");
return String.format(AUTHORIZATION_URL, config.getApiKey(), URLUtils.formURLEncode(config.getCallback()));
}
@Override
public AccessTokenExtractor getAccessTokenExtractor()
{
return new JsonTokenExtractor();
}
}
@@ -1,28 +0,0 @@
package org.scribe.builder.api;
import org.scribe.model.Token;
public class LoveFilmApi extends DefaultApi10a
{
private static final String REQUEST_TOKEN_URL = "http://openapi.lovefilm.com/oauth/request_token";
private static final String ACCESS_TOKEN_URL = "http://openapi.lovefilm.com/oauth/access_token";
private static final String AUTHORIZE_URL = "https://www.lovefilm.com/activate?oauth_token=%s";
@Override
public String getRequestTokenEndpoint()
{
return REQUEST_TOKEN_URL;
}
@Override
public String getAccessTokenEndpoint()
{
return ACCESS_TOKEN_URL;
}
@Override
public String getAuthorizationUrl(Token requestToken)
{
return String.format(AUTHORIZE_URL, requestToken.getToken());
}
}
@@ -32,9 +32,29 @@ public class BaseStringExtractorImpl implements BaseStringExtractor
private String getSortedAndEncodedParams(OAuthRequest request)
{
Map<String, String> params = new HashMap<String, String>();
MapUtils.decodeAndAppendEntries(request.getQueryStringParams(), params);
MapUtils.decodeAndAppendEntries(request.getBodyParams(), params);
MapUtils.decodeAndAppendEntries(request.getOauthParameters(), params);
Map<String, String> tmp = null;
//params.putAll(request.getQueryStringParams());
tmp = request.getQueryStringParams();
for (String key:tmp.keySet()){
params.put(
URLUtils.percentEncode(key),
URLUtils.percentEncode(tmp.get(key))
);
}
tmp = request.getBodyParams();
for (String key:tmp.keySet()){
params.put(
URLUtils.percentEncode(key),
URLUtils.percentEncode(tmp.get(key))
);
}
tmp = request.getOauthParameters();
for (String key:tmp.keySet()){
params.put(
URLUtils.percentEncode(key),
URLUtils.percentEncode(tmp.get(key))
);
}
params = MapUtils.sort(params);
return URLUtils.percentEncode(URLUtils.concatSortedPercentEncodedParams(params));
}
@@ -1,28 +0,0 @@
package org.scribe.extractors;
import java.util.regex.*;
import org.scribe.exceptions.*;
import org.scribe.model.*;
import org.scribe.utils.*;
public class JsonTokenExtractor implements AccessTokenExtractor
{
private Pattern accessTokenPattern = Pattern.compile("\"access_token\":\"(\\S*)\"");
@Override
public Token extract(String response)
{
Preconditions.checkEmptyString(response, "Cannot extract a token from a null or empty String");
Matcher matcher = accessTokenPattern.matcher(response);
if(matcher.find())
{
return new Token(matcher.group(1), "");
}
else
{
throw new OAuthException("Cannot extract an acces token. Response was: "+response);
}
}
}
@@ -1,36 +0,0 @@
package org.scribe.extractors;
import java.util.regex.*;
import org.scribe.exceptions.*;
import org.scribe.model.*;
import org.scribe.utils.*;
/**
* Default implementation of {@AccessTokenExtractor}. Conforms to OAuth 2.0
*
*/
public class TokenExtractor20Impl implements AccessTokenExtractor
{
private static final String TOKEN_REGEX = "access_token=(\\S*?)(&(\\S*))?";
private static final String EMPTY_SECRET = "";
/**
* {@inheritDoc}
*/
public Token extract(String response)
{
Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
Matcher matcher = Pattern.compile(TOKEN_REGEX).matcher(response);
if (matcher.matches())
{
String token = URLUtils.formURLDecode(matcher.group(1));
return new Token(token, EMPTY_SECRET, response);
}
else
{
throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null);
}
}
}
@@ -15,8 +15,7 @@ import org.scribe.utils.*;
*/
public class TokenExtractorImpl implements RequestTokenExtractor, AccessTokenExtractor
{
private static final Pattern TOKEN_REGEX = Pattern.compile("oauth_token=([^&]+)");
private static final Pattern SECRET_REGEX = Pattern.compile("oauth_token_secret=([^&]+)");
private static final String TOKEN_REGEX = "oauth_token=(\\S*)&oauth_token_secret=(\\S*?)(&(.*))?";
/**
* {@inheritDoc}
@@ -24,21 +23,16 @@ public class TokenExtractorImpl implements RequestTokenExtractor, AccessTokenExt
public Token extract(String response)
{
Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
String token = extract(response, TOKEN_REGEX);
String secret = extract(response, SECRET_REGEX);
return new Token(token, secret, response);
}
private String extract(String response, Pattern p)
{
Matcher matcher = p.matcher(response);
if (matcher.find() && matcher.groupCount() >= 1)
Matcher matcher = Pattern.compile(TOKEN_REGEX).matcher(response);
if (matcher.matches())
{
return URLUtils.formURLDecode(matcher.group(1));
}
else
String token = URLUtils.urlDecodeWrapper(matcher.group(1));
String secret = URLUtils.urlDecodeWrapper(matcher.group(2));
return new Token(token, secret);
} else
{
throw new OAuthException("Response body is incorrect. Can't extract token and secret from this: '" + response + "'", null);
throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null);
}
}
}
@@ -10,25 +10,17 @@ public class OAuthConfig
private String apiKey;
private String apiSecret;
private String callback;
private SignatureType signatureType;
public OAuthConfig(String key, String secret)
{
this(key,secret,null);
}
//Kept for backwards compatibility
public OAuthConfig(String key, String secret, String callback)
{
this(key,secret,callback,null);
}
public OAuthConfig(String key, String secret, String callback, SignatureType type)
{
this.apiKey = key;
this.apiSecret = secret;
this.callback = callback;
this.signatureType = type;
}
public String getApiKey()
@@ -60,14 +52,4 @@ public class OAuthConfig
{
this.callback = callback;
}
public SignatureType getSignatureType()
{
return signatureType != null ? signatureType : SignatureType.Header;
}
public void setSignatureType(SignatureType type)
{
this.signatureType = type;
}
}
@@ -41,9 +41,4 @@ public class OAuthConstants
//OAuth 2.0
public static final String ACCESS_TOKEN = "access_token";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
public static final String REDIRECT_URI = "redirect_uri";
public static final String CODE = "code";
}
@@ -1,5 +1,6 @@
package org.scribe.model;
import java.net.MalformedURLException;
import java.util.*;
/**
@@ -19,8 +20,9 @@ public class OAuthRequest extends Request
*
* @param verb Http verb/method
* @param url resource URL
* @throws MalformedURLException
*/
public OAuthRequest(Verb verb, String url)
public OAuthRequest(Verb verb, String url) throws MalformedURLException
{
super(verb, url);
this.oauthParameters = new HashMap<String, String>();
+22 -19
View File
@@ -17,7 +17,7 @@ class Request
{
private static final String CONTENT_LENGTH = "Content-Length";
private String url;
private URL url;
private Verb verb;
private Map<String, String> querystringParams;
private Map<String, String> bodyParams;
@@ -30,11 +30,12 @@ class Request
*
* @param verb Http Verb (GET, POST, etc)
* @param url url with optional querystring parameters.
* @throws MalformedURLException
*/
public Request(Verb verb, String url)
public Request(Verb verb, String url) throws MalformedURLException
{
this.verb = verb;
this.url = url;
this.url = new URL(url);
this.querystringParams = new HashMap<String, String>();
this.bodyParams = new HashMap<String, String>();
this.headers = new HashMap<String, String>();
@@ -61,10 +62,9 @@ class Request
private void createConnection() throws IOException
{
String effectiveUrl = URLUtils.appendParametersToQueryString(url, querystringParams);
String effectiveUrl = URLUtils.appendParametersToQueryString(url.toString(), querystringParams);
if (connection == null)
{
System.setProperty("http.keepAlive", "false");
connection = (HttpURLConnection) new URL(effectiveUrl).openConnection();
}
}
@@ -145,22 +145,25 @@ class Request
* Get a {@link Map} of the query string parameters.
*
* @return a map containing the query string parameters
* @throws OAuthException if the URL is not valid
*/
public Map<String, String> getQueryStringParams()
{
try
{
Map<String, String> params = new HashMap<String, String>();
String queryString = new URL(url).getQuery();
params.putAll(URLUtils.queryStringToMap(queryString));
params.putAll(this.querystringParams);
return params;
}
catch (MalformedURLException mue)
{
throw new OAuthException("Malformed URL", mue);
}
String query = url.getQuery();
if (query != null)
{
for (String param : query.split("&"))
{
String pair[] = param.split("=");
String valuePart = "";
if (pair.length > 1) {
valuePart = URLUtils.urlDecodeWrapper(pair[1]);
}
params.put(URLUtils.urlDecodeWrapper(pair[0]),valuePart );
}
}
params.putAll(querystringParams);
return params;
}
/**
@@ -180,7 +183,7 @@ class Request
*/
public String getUrl()
{
return url;
return url.toString();
}
/**
@@ -190,7 +193,7 @@ class Request
*/
public String getSanitizedUrl()
{
return url.replaceAll("\\?.*", "").replace("\\:\\d{4}", "");
return URLUtils.convertUrlToBaseStringURI(url);
}
/**
@@ -1,7 +0,0 @@
package org.scribe.model;
public enum SignatureType
{
Header,
QueryString
}
-16
View File
@@ -13,7 +13,6 @@ public class Token implements Serializable
private final String token;
private final String secret;
private final String rawResponse;
/**
* Default constructor
@@ -22,15 +21,9 @@ public class Token implements Serializable
* @param secret token secret
*/
public Token(String token, String secret)
{
this(token, secret, null);
}
public Token(String token, String secret, String rawResponse)
{
this.token = token;
this.secret = secret;
this.rawResponse = rawResponse;
}
public String getToken()
@@ -43,15 +36,6 @@ public class Token implements Serializable
return secret;
}
public String getRawResponse()
{
if (rawResponse == null)
{
throw new IllegalStateException("This token object was not constructed by scribe and does not have a rawResponse");
}
return rawResponse;
}
@Override
public String toString()
{
+3 -3
View File
@@ -1,7 +1,5 @@
package org.scribe.model;
import org.scribe.utils.*;
/**
* Represents an OAuth verifier code.
*
@@ -19,7 +17,9 @@ public class Verifier
*/
public Verifier(String value)
{
Preconditions.checkNotNull(value, "Must provide a valid string as verifier");
if (value == null) {
throw new IllegalArgumentException();
}
this.value = value;
}
@@ -1,8 +1,9 @@
package org.scribe.oauth;
import java.util.*;
import java.net.MalformedURLException;
import org.scribe.builder.api.*;
import org.scribe.exceptions.OAuthException;
import org.scribe.model.*;
/**
@@ -37,10 +38,14 @@ public class OAuth10aServiceImpl implements OAuthService
*/
public Token getRequestToken()
{
OAuthRequest request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint());
request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
OAuthRequest request = null;;
try {
request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint());
} catch (MalformedURLException e) {
throw new OAuthException("Problems while creating connection", e);
}
addOAuthParams(request, OAuthConstants.EMPTY_TOKEN);
addSignature(request);
addOAuthHeader(request);
Response response = request.send();
return api.getRequestTokenExtractor().extract(response.getBody());
}
@@ -52,6 +57,7 @@ public class OAuth10aServiceImpl implements OAuthService
request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, config.getApiKey());
request.addOAuthParameter(OAuthConstants.SIGN_METHOD, api.getSignatureService().getSignatureMethod());
request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
request.addOAuthParameter(OAuthConstants.CALLBACK, config.getCallback());
if(scope != NO_SCOPE) request.addOAuthParameter(OAuthConstants.SCOPE, scope);
request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));
}
@@ -61,11 +67,16 @@ public class OAuth10aServiceImpl implements OAuthService
*/
public Token getAccessToken(Token requestToken, Verifier verifier)
{
OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
OAuthRequest request = null;
try {
request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
} catch (MalformedURLException e) {
throw new OAuthException("Problems while creating connection", e);
}
request.addOAuthParameter(OAuthConstants.TOKEN, requestToken.getToken());
request.addOAuthParameter(OAuthConstants.VERIFIER, verifier.getValue());
addOAuthParams(request, requestToken);
addSignature(request);
addOAuthHeader(request);
Response response = request.send();
return api.getAccessTokenExtractor().extract(response.getBody());
}
@@ -77,7 +88,7 @@ public class OAuth10aServiceImpl implements OAuthService
{
request.addOAuthParameter(OAuthConstants.TOKEN, token.getToken());
addOAuthParams(request, token);
addSignature(request);
addOAuthHeader(request);
}
/**
@@ -110,20 +121,9 @@ public class OAuth10aServiceImpl implements OAuthService
return api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret());
}
private void addSignature(OAuthRequest request)
private void addOAuthHeader(OAuthRequest request)
{
switch (config.getSignatureType())
{
case Header:
String oauthHeader = api.getHeaderExtractor().extract(request);
request.addHeader(OAuthConstants.HEADER, oauthHeader);
break;
case QueryString:
for (Map.Entry<String, String> entry : request.getOauthParameters().entrySet())
{
request.addQuerystringParameter(entry.getKey(), entry.getValue());
}
break;
}
String oauthHeader = api.getHeaderExtractor().extract(request);
request.addHeader(OAuthConstants.HEADER, oauthHeader);
}
}
@@ -35,13 +35,7 @@ public class OAuth20ServiceImpl implements OAuthService
*/
public Token getAccessToken(Token requestToken, Verifier verifier)
{
OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
request.addQuerystringParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
request.addQuerystringParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
request.addQuerystringParameter(OAuthConstants.CODE, verifier.getValue());
request.addQuerystringParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
Response response = request.send();
return api.getAccessTokenExtractor().extract(response.getBody());
throw new UnsupportedOperationException("Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
}
/**
@@ -33,19 +33,4 @@ public class MapUtils
Collections.sort(keys);
return keys;
}
/**
* Form-urlDecodes and appends all keys from the source {@link Map} to the
* target {@link Map}
*
* @param source Map from where the keys get copied and decoded
* @param target Map where the decoded keys are copied to
*/
public static void decodeAndAppendEntries(Map<String, String> source, Map<String, String> target)
{
for (String key: source.keySet())
{
target.put(URLUtils.percentEncode(key), URLUtils.percentEncode(source.get(key)));
}
}
}
+76 -70
View File
@@ -13,9 +13,13 @@ public class URLUtils
{
private static final String EMPTY_STRING = "";
private static final String UTF_8 = "UTF-8";
private static final String PAIR_SEPARATOR = "=";
private static final String PARAM_SEPARATOR = "&";
private static final char PAIR_SEPARATOR = '=';
private static final char PARAM_SEPARATOR = '&';
private static final char QUERY_STRING_SEPARATOR = '?';
private static final String HTTP_PROTOCOL = "http";
private static final int HTTP_DEFAULT_PORT = 80;
private static final String HTTPS_PROTOCOL = "https";
private static final int HTTPS_DEFAULT_PORT = 443;
private static final String ERROR_MSG = String.format("Cannot find specified encoding: %s", UTF_8);
@@ -31,7 +35,7 @@ public class URLUtils
}
/**
* Turns a map into a form-urlencoded string
* Turns a map into a form-url-encoded string (key=value&key2&key3=value)
*
* @param map any map
* @return form-url-encoded string
@@ -47,38 +51,49 @@ public class URLUtils
StringBuffer encodedString = new StringBuffer(map.size() * 20);
for (String key : map.keySet())
{
encodedString.append(PARAM_SEPARATOR).append(formURLEncode(key));
if(map.get(key) != null)
if(encodedString.length() > 0)
{
encodedString.append(PAIR_SEPARATOR).append(formURLEncode(map.get(key)));
encodedString.append(PARAM_SEPARATOR);
}
encodedString.append(urlEncodeWrapper(key));
if (map.get(key).length() > 0) {
encodedString.append(PAIR_SEPARATOR).append(urlEncodeWrapper(map.get(key)));
}
}
return encodedString.toString().substring(1);
return encodedString.toString();
}
/**
* Percent encodes a string
*
* @param string plain string
* @param plain
* @return percent encoded string
*/
public static String percentEncode(String string)
{
String encoded = formURLEncode(string);
for (EncodingRule rule : ENCODING_RULES)
Preconditions.checkNotNull(string, "Cannot encode null string");
try
{
encoded = rule.apply(encoded);
String encoded = URLEncoder.encode(string, UTF_8);
for(EncodingRule rule : ENCODING_RULES)
{
encoded = rule.apply(encoded);
}
return encoded;
}
catch (UnsupportedEncodingException uee)
{
throw new IllegalStateException(ERROR_MSG, uee);
}
return encoded;
}
/**
* Translates a string into application/x-www-form-urlencoded format
*
* URL encodes a string
*
* @param plain
* @return form-urlencoded string
* @return percent encoded string
*/
public static String formURLEncode(String string)
public static String urlEncodeWrapper(String string)
{
Preconditions.checkNotNull(string, "Cannot encode null string");
try
@@ -90,14 +105,14 @@ public class URLUtils
throw new IllegalStateException(ERROR_MSG, uee);
}
}
/**
* Decodes a application/x-www-form-urlencoded string
* URL decodes a string
*
* @param string form-urlencoded string
* @param string percent encoded string
* @return plain string
*/
public static String formURLDecode(String string)
public static String urlDecodeWrapper(String string)
{
Preconditions.checkNotNull(string, "Cannot decode null string");
try
@@ -121,57 +136,12 @@ public class URLUtils
{
Preconditions.checkNotNull(url, "Cannot append to null URL");
String queryString = URLUtils.formURLEncodeMap(params);
if (queryString.equals(EMPTY_STRING))
{
return url;
}
else
{
url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR;
url += queryString;
return url;
}
}
if (queryString.length() == 0) return url;
/**
* Concats a key-value map into a querystring-like String
*
* @param params key-value map
* @return querystring-like String
*/
// TODO Move to MapUtils
public static String concatSortedPercentEncodedParams(Map<String, String> params)
{
StringBuilder result = new StringBuilder();
for (String key : params.keySet())
{
result.append(key).append(PAIR_SEPARATOR);
result.append(params.get(key)).append(PARAM_SEPARATOR);
}
return result.toString().substring(0, result.length() - 1);
}
/**
* Parses and form-urldecodes a querystring-like string into a map
*
* @param queryString querystring-like String
* @return a map with the form-urldecoded parameters
*/
// TODO Move to MapUtils
public static Map<String, String> queryStringToMap(String queryString)
{
Map<String, String> result = new HashMap<String, String>();
if (queryString != null && queryString.length() > 0)
{
for (String param : queryString.split(PARAM_SEPARATOR))
{
String pair[] = param.split(PAIR_SEPARATOR);
String key = formURLDecode(pair[0]);
String value = pair.length > 1 ? formURLDecode(pair[1]) : EMPTY_STRING;
result.put(key, value);
}
}
return result;
// Check if there are parameters in the url already and use '&' instead of '?'
url += url.indexOf(QUERY_STRING_SEPARATOR) != -1 ? PARAM_SEPARATOR : QUERY_STRING_SEPARATOR;
url += queryString;
return url;
}
private static final class EncodingRule
@@ -189,4 +159,40 @@ public class URLUtils
return string.replace(ch, toCh);
}
}
public static String concatSortedPercentEncodedParams(Map<String, String> params) {
StringBuilder target = new StringBuilder();
for (String key:params.keySet()){
target.append(key);
target.append(PAIR_SEPARATOR);
target.append(params.get(key));
target.append(PARAM_SEPARATOR);
}
return target.deleteCharAt(target.length() - 1).toString();
}
public static String convertUrlToBaseStringURI(URL url){
URI uri = null;
try {
uri = url.toURI();
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
String scheme = uri.getScheme().toLowerCase();
String host = uri.getHost().toLowerCase();
int port = uri.getPort();
if (
(scheme.equals(HTTP_PROTOCOL) && port == HTTP_DEFAULT_PORT)
|| (scheme.equals(HTTPS_PROTOCOL) && port == HTTPS_DEFAULT_PORT)
){
port = -1;
}
URI baseUri = null;
try {
baseUri = new URI(scheme,null, host, port, uri.getPath(), null, null);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return baseUri.toString();
}
}
@@ -18,13 +18,12 @@ public class ServiceBuilderTest
}
@Test
public void shouldReturnConfigDefaultValues()
public void shouldReturnOOBasDefaultCallback()
{
builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").build();
assertEquals(ApiMock.config.getApiKey(), "key");
assertEquals(ApiMock.config.getApiSecret(), "secret");
assertEquals(ApiMock.config.getCallback(), OAuthConstants.OUT_OF_BAND);
assertEquals(ApiMock.config.getSignatureType(), SignatureType.Header);
}
@Test
@@ -36,15 +35,6 @@ public class ServiceBuilderTest
assertEquals(ApiMock.config.getCallback(), "http://example.com");
}
@Test
public void shouldAcceptASignatureType()
{
builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").signatureType(SignatureType.QueryString).build();
assertEquals(ApiMock.config.getApiKey(), "key");
assertEquals(ApiMock.config.getApiSecret(), "secret");
assertEquals(ApiMock.config.getSignatureType(), SignatureType.QueryString);
}
@Test(expected=IllegalArgumentException.class)
public void shouldNotAcceptAnInvalidUrlAsCallback()
{
@@ -1,5 +1,6 @@
package org.scribe.examples;
import java.net.MalformedURLException;
import java.util.*;
import org.scribe.builder.*;
@@ -11,12 +12,13 @@ public class FacebookExample
{
private static final String NETWORK_NAME = "Facebook";
private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/me";
private static final String NO_SECRET_NEEDED = "";
private static final Token EMPTY_TOKEN = null;
public static void main(String[] args)
public static void main(String[] args) throws MalformedURLException
{
// Replace these with your own api key and secret
String apiKey = "your_app_id";
String apiKey = "your_api_key";
String apiSecret = "your_api_secret";
OAuthService service = new ServiceBuilder()
.provider(FacebookApi.class)
@@ -35,16 +37,9 @@ public class FacebookExample
System.out.println("Got the Authorization URL!");
System.out.println("Now go and authorize Scribe here:");
System.out.println(authorizationUrl);
System.out.println("And paste the authorization code here");
System.out.println("And paste the access token here");
System.out.print(">>");
Verifier verifier = new Verifier(in.nextLine());
System.out.println();
// Trade the Request Token and Verfier for the Access Token
System.out.println("Trading the Request Token for an Access Token...");
Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
System.out.println("Got the Access Token!");
System.out.println("(if your curious it looks like this: " + accessToken + " )");
Token accessToken = new Token(in.nextLine(), NO_SECRET_NEEDED);
System.out.println();
// Now let's go and ask for a protected resource!
@@ -1,63 +0,0 @@
package org.scribe.examples;
import java.util.*;
import org.scribe.builder.*;
import org.scribe.builder.api.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
public class Foursquare2Example
{
private static final String PROTECTED_RESOURCE_URL = "https://api.foursquare.com/v2/users/self/friends?oauth_token=";
private static final Token EMPTY_TOKEN = null;
public static void main(String[] args)
{
// Replace these with your own api key and secret
String apiKey = "FEGFXJUFANVVDHVSNUAMUKTTXCP1AJQD53E33XKJ44YP1S4I";
String apiSecret = "AYWKUL5SWPNC0CTQ202QXRUG2NLZYXMRA34ZSDW4AUYBG2RC";
OAuthService service = new ServiceBuilder()
.provider(Foursquare2Api.class)
.apiKey(apiKey)
.apiSecret(apiSecret)
.callback("http://localhost:9000/")
.build();
Scanner in = new Scanner(System.in);
System.out.println("=== Foursquare2's OAuth Workflow ===");
System.out.println();
// Obtain the Authorization URL
System.out.println("Fetching the Authorization URL...");
String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
System.out.println("Got the Authorization URL!");
System.out.println("Now go and authorize Scribe here:");
System.out.println(authorizationUrl);
System.out.println("And paste the authorization code here");
System.out.print(">>");
Verifier verifier = new Verifier(in.nextLine());
System.out.println();
// Trade the Request Token and Verfier for the Access Token
System.out.println("Trading the Request Token for an Access Token...");
Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
System.out.println("Got the Access Token!");
System.out.println("(if your curious it looks like this: " + accessToken + " )");
System.out.println();
// Now let's go and ask for a protected resource!
System.out.println("Now we're going to access a protected resource...");
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL + accessToken.getToken());
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println("Got it! Lets see what we found...");
System.out.println();
System.out.println(response.getCode());
System.out.println(response.getBody());
System.out.println();
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
}
}
@@ -1,5 +1,6 @@
package org.scribe.examples;
import java.net.MalformedURLException;
import java.util.Scanner;
import org.scribe.builder.*;
@@ -11,7 +12,7 @@ public class FoursquareExample
{
private static final String PROTECTED_RESOURCE_URL = "http://api.foursquare.com/v1/user";
public static void main(String[] args)
public static void main(String[] args) throws MalformedURLException
{
OAuthService service = new ServiceBuilder()
.provider(FoursquareApi.class)
@@ -1,5 +1,6 @@
package org.scribe.examples;
import java.net.MalformedURLException;
import java.util.*;
import org.scribe.builder.*;
@@ -14,7 +15,7 @@ public class GoogleExample
private static final String PROTECTED_RESOURCE_URL = "https://docs.google.com/feeds/default/private/full/";
private static final String SCOPE = "https://docs.google.com/feeds/";
public static void main(String[] args)
public static void main(String[] args) throws MalformedURLException
{
OAuthService service = new ServiceBuilder()
.provider(GoogleApi.class)
@@ -1,5 +1,6 @@
package org.scribe.examples;
import java.net.MalformedURLException;
import java.util.Scanner;
import org.scribe.builder.*;
@@ -11,7 +12,7 @@ public class LinkedInExample
{
private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)";
public static void main(String[] args)
public static void main(String[] args) throws MalformedURLException
{
OAuthService service = new ServiceBuilder()
.provider(LinkedInApi.class)
@@ -1,64 +0,0 @@
package org.scribe.examples;
import java.util.*;
import org.scribe.builder.*;
import org.scribe.builder.api.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
public class LoveFilmExample
{
private static final String NETWORK_NAME = "LoveFilm";
private static final String PROTECTED_RESOURCE_URL = "https://api.lovefilm.com/users";
public static void main(String[] args)
{
// Replace these with your own api key and secret
String apiKey = "your_key";
String apiSecret = "your_secret";
OAuthService service = new ServiceBuilder().provider(LoveFilmApi.class).apiKey(apiKey).apiSecret(apiSecret).build();
Scanner in = new Scanner(System.in);
System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
System.out.println();
// Grab a request token.
System.out.println("Fetching request token.");
Token requestToken = service.getRequestToken();
System.out.println("Got it ... ");
System.out.println(requestToken.getToken());
// Obtain the Authorization URL
System.out.println("Fetching the Authorization URL...");
String authorizationUrl = service.getAuthorizationUrl(requestToken);
System.out.println("Got the Authorization URL!");
System.out.println("Now go and authorize Scribe here:");
System.out.println(authorizationUrl);
System.out.println("And paste the authorization code here");
System.out.print(">>");
Verifier verifier = new Verifier(in.nextLine());
System.out.println();
// Trade the Request Token and Verfier for the Access Token
System.out.println("Trading the Request Token for an Access Token...");
Token accessToken = service.getAccessToken(requestToken, verifier);
System.out.println("Got the Access Token!");
System.out.println("(if your curious it looks like this: " + accessToken + " )");
System.out.println();
// Now let's go and ask for a protected resource!
System.out.println("Now we're going to access a protected resource...");
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println("Got it! Lets see what we found...");
System.out.println();
System.out.println(response.getCode());
System.out.println(response.getBody());
System.out.println();
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
}
}
@@ -1,5 +1,6 @@
package org.scribe.examples;
import java.net.MalformedURLException;
import java.util.Scanner;
import org.scribe.builder.*;
@@ -11,7 +12,7 @@ public class TwitterExample
{
private static final String PROTECTED_RESOURCE_URL = "http://api.twitter.com/1/account/verify_credentials.xml";
public static void main(String[] args)
public static void main(String[] args) throws MalformedURLException
{
OAuthService service = new ServiceBuilder()
.provider(TwitterApi.class)
@@ -1,5 +1,6 @@
package org.scribe.examples;
import java.net.MalformedURLException;
import java.util.Scanner;
import org.scribe.builder.*;
@@ -11,7 +12,7 @@ public class YahooExample
{
private static final String PROTECTED_RESOURCE_URL = "http://social.yahooapis.com/v1/user/A6ROU63MXWDCW3Y5MGCYWVHDJI/profile/status?format=json";
public static void main(String[] args)
public static void main(String[] args) throws MalformedURLException
{
OAuthService service = new ServiceBuilder()
.provider(YahooApi.class)
@@ -2,6 +2,8 @@ package org.scribe.extractors;
import static org.junit.Assert.*;
import java.net.MalformedURLException;
import org.junit.*;
import org.scribe.exceptions.*;
import org.scribe.model.*;
@@ -12,12 +14,16 @@ public class BaseStringExtractorTest
private BaseStringExtractorImpl extractor;
private OAuthRequest request;
private OAuthRequest request2;
@Before
public void setup()
public void setup() throws MalformedURLException
{
request = ObjectMother.createSampleOAuthRequest();
request2 = ObjectMother.createSampleOAuthRequest2();
extractor = new BaseStringExtractorImpl();
}
@Test
@@ -27,6 +33,14 @@ public class BaseStringExtractorTest
String baseString = extractor.extract(request);
assertEquals(expected, baseString);
}
@Test
public void shouldExtractBaseStringFromOAuthRequest2()
{
String expected = "GET&http%3A%2F%2Fexample.com&oauth_callback%3Dhttp%253A%252F%252Fexample%252Fcallback%26oauth_consumer_key%3DAS%2523%2524%255E%252A%2540%2526%26oauth_signature%3DOAuth-Signature%26oauth_timestamp%3D123456";
String baseString = extractor.extract(request2);
assertEquals(expected, baseString);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionIfRquestIsNull()
@@ -36,7 +50,7 @@ public class BaseStringExtractorTest
}
@Test(expected = OAuthParametersMissingException.class)
public void shouldThrowExceptionIfRquestHasNoOAuthParameters()
public void shouldThrowExceptionIfRquestHasNoOAuthParameters() throws MalformedURLException
{
OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
extractor.extract(request);
@@ -2,6 +2,8 @@ package org.scribe.extractors;
import static org.junit.Assert.*;
import java.net.MalformedURLException;
import org.junit.*;
import org.scribe.exceptions.*;
import org.scribe.model.*;
@@ -14,7 +16,7 @@ public class HeaderExtractorTest
private OAuthRequest request;
@Before
public void setup()
public void setup() throws MalformedURLException
{
request = ObjectMother.createSampleOAuthRequest();
extractor = new HeaderExtractorImpl();
@@ -37,7 +39,7 @@ public class HeaderExtractorTest
}
@Test(expected = OAuthParametersMissingException.class)
public void shouldExceptionIfRequestHasNoOAuthParams()
public void shouldExceptionIfRequestHasNoOAuthParams() throws MalformedURLException
{
OAuthRequest emptyRequest = new OAuthRequest(Verb.GET, "http://example.com");
extractor.extract(emptyRequest);
@@ -1,31 +0,0 @@
package org.scribe.extractors;
import static org.junit.Assert.*;
import org.junit.*;
import org.scribe.model.*;
public class JsonTokenExtractorTest
{
private String response = "'{ \"access_token\":\"I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X\"}'";
private JsonTokenExtractor extractor = new JsonTokenExtractor();
@Test
public void shouldParseResponse()
{
Token token = extractor.extract(response);
assertEquals(token.getToken(), "I0122HHJKLEM21F3WLPYHDKGKZULAUO4SGMV3ABKFTDT3T3X");
}
@Test(expected=IllegalArgumentException.class)
public void shouldThrowExceptionIfForNullParameters()
{
extractor.extract(null);
}
@Test(expected=IllegalArgumentException.class)
public void shouldThrowExceptionIfForEmptyStrings()
{
extractor.extract("");
}
}
@@ -1,58 +0,0 @@
package org.scribe.extractors;
import static org.junit.Assert.*;
import org.junit.*;
import org.scribe.exceptions.*;
import org.scribe.model.*;
public class TokenExtractor20Test
{
private TokenExtractor20Impl extractor;
@Before
public void setup()
{
extractor = new TokenExtractor20Impl();
}
@Test
public void shouldExtractTokenFromOAuthStandardResponse()
{
String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE";
Token extracted = extractor.extract(response);
assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken());
assertEquals("", extracted.getSecret());
}
@Test
public void shouldExtractTokenFromResponseWithExpiresParam()
{
String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE&expires=5108";
Token extracted = extractor.extract(response);
assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken());
assertEquals("", extracted.getSecret());
}
@Test(expected = OAuthException.class)
public void shouldThrowExceptionIfTokenIsAbsent()
{
String response = "&expires=5108";
extractor.extract(response);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionIfResponseIsNull()
{
String response = null;
extractor.extract(response);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionIfResponseIsEmptyString()
{
String response = "";
extractor.extract(response);
}
}
@@ -26,15 +26,6 @@ public class TokenExtractorTest
assertEquals("hdhd0244k9j7ao03", extracted.getSecret());
}
@Test
public void shouldExtractTokenFromInvertedOAuthStandardResponse()
{
String response = "oauth_token_secret=hh5s93j4hdidpola&oauth_token=hdhd0244k9j7ao03";
Token extracted = extractor.extract(response);
assertEquals("hh5s93j4hdidpola", extracted.getSecret());
assertEquals("hdhd0244k9j7ao03", extracted.getToken());
}
@Test
public void shouldExtractTokenFromResponseWithCallbackConfirmed()
{
@@ -2,6 +2,8 @@ package org.scribe.model;
import static org.junit.Assert.*;
import java.net.MalformedURLException;
import org.junit.*;
public class OAuthRequestTest
@@ -10,7 +12,7 @@ public class OAuthRequestTest
private OAuthRequest request;
@Before
public void setup()
public void setup() throws MalformedURLException
{
request = new OAuthRequest(Verb.GET, "http://example.com");
}
@@ -2,6 +2,8 @@ package org.scribe.model;
import static org.junit.Assert.*;
import java.net.MalformedURLException;
import org.junit.*;
public class RequestTest
@@ -16,8 +18,6 @@ public class RequestTest
{
connection = new ConnectionStub();
postRequest = new Request(Verb.POST, "http://example.com");
postRequest.addBodyParameter("param", "value");
postRequest.addBodyParameter("param with spaces", "value with spaces");
postRequest.setConnection(connection);
getRequest = new Request(Verb.GET, "http://example.com?qsparam=value&other+param=value+with+spaces");
getRequest.setConnection(connection);
@@ -37,6 +37,7 @@ public class RequestTest
assertEquals(0, postRequest.getQueryStringParams().size());
assertTrue(getRequest.getQueryStringParams().containsKey("qsparam"));
assertTrue(getRequest.getQueryStringParams().get("qsparam").equals("value"));
assertTrue(getRequest.getQueryStringParams().get("other param").equals("value with spaces"));
}
@Test
@@ -50,10 +51,12 @@ public class RequestTest
}
@Test
public void shouldSetBodyParamsAndAddContentLength()
public void shouldSetBodyParamsAndHeaders()
{
assertEquals("param=value&param+with+spaces=value+with+spaces", postRequest.getBodyContents());
postRequest.addBodyParameter("param", "value");
postRequest.addBodyParameter("param two", "value with spaces");
postRequest.send();
assertEquals("param+two=value+with+spaces&param=value", postRequest.getBodyContents());
assertTrue(connection.getHeaders().containsKey("Content-Length"));
}
@@ -67,7 +70,7 @@ public class RequestTest
}
@Test
public void shouldAllowAddingQuerystringParametersAfterCreation()
public void shouldAllowAddingQuerystringParametersAfterCreation() throws MalformedURLException
{
Request request = new Request(Verb.GET, "http://example.com?one=val");
request.addQuerystringParameter("two", "other val");
@@ -76,8 +79,36 @@ public class RequestTest
}
@Test
public void shouldHandleQueryStringSpaceEncodingProperly()
public void sanatizeUrlTest() throws MalformedURLException
{
assertTrue(getRequest.getQueryStringParams().get("other param").equals("value with spaces"));
Request request = new Request(Verb.GET, "http://example.com?one=val");
assertEquals("http://example.com", request.getSanitizedUrl());
request = new Request(Verb.GET, "http://EXAMPLE.com:80/?one=val");
assertEquals("http://example.com/", request.getSanitizedUrl());
request = new Request(Verb.GET, "http://EXAMPLE.com:8080?one=val");
assertEquals("http://example.com:8080", request.getSanitizedUrl());
request = new Request(Verb.GET, "http://EXAMPLE.com:8080?one=val");
assertEquals("http://example.com:8080", request.getSanitizedUrl());
request = new Request(Verb.GET, "http://EXAMPLE.com:80/test/?one=val");
assertEquals("http://example.com/test/", request.getSanitizedUrl());
request = new Request(Verb.GET, "http://EXAMPLE.com:8080/test/?one=val#Hello");
assertEquals("http://example.com:8080/test/", request.getSanitizedUrl());
request = new Request(Verb.GET, "HTTP://EXAMPLE.com:8080/test/?one=val#Hello");
assertEquals("http://example.com:8080/test/", request.getSanitizedUrl());
//From RFC5849 example p.20
request = new Request(Verb.GET, "http://example.com:80/r%20v/X?id=123");
assertEquals("http://example.com/r%20v/X", request.getSanitizedUrl());
//From RFC5849 example p.20
request = new Request(Verb.GET, "https://www.example.com:8080/?q=1");
assertEquals("https://www.example.com:8080/", request.getSanitizedUrl());
}
}
@@ -0,0 +1,14 @@
package org.scribe.model;
import org.junit.*;
public class VerifierTest
{
@Test(expected = IllegalArgumentException.class)
public void shouldThrowErrorForNullString()
{
new Verifier(null);
}
}
@@ -1,11 +1,13 @@
package org.scribe.test.helpers;
import java.net.MalformedURLException;
import org.scribe.model.*;
public class ObjectMother
{
public static OAuthRequest createSampleOAuthRequest()
public static OAuthRequest createSampleOAuthRequest() throws MalformedURLException
{
OAuthRequest request = new OAuthRequest(Verb.GET, "http://example.com");
request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
@@ -14,4 +16,14 @@ public class ObjectMother
request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
return request;
}
public static OAuthRequest createSampleOAuthRequest2() throws MalformedURLException
{
OAuthRequest request = new OAuthRequest(Verb.GET, "http://EXAMPLE.com");
request.addOAuthParameter(OAuthConstants.TIMESTAMP, "123456");
request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "AS#$^*@&");
request.addOAuthParameter(OAuthConstants.CALLBACK, "http://example/callback");
request.addOAuthParameter(OAuthConstants.SIGNATURE, "OAuth-Signature");
return request;
}
}
@@ -28,17 +28,6 @@ public class URLUtilsTest
assertEquals(expected, URLUtils.formURLEncodeMap(params));
}
@Test
public void shouldFormURLEncodeMapWithMissingValues()
{
Map<String, String> params = new LinkedHashMap<String, String>();
params.put("key", "value");
params.put("key with spaces", null);
String expected = "key=value&key+with+spaces";
assertEquals(expected, URLUtils.formURLEncodeMap(params));
}
@Test
public void shouldPercentEncodeString()
{
@@ -48,32 +37,24 @@ public class URLUtilsTest
}
@Test
public void shouldFormURLEncodeString()
{
String toEncode = "this is a test &^";
String expected = "this+is+a+test+%26%5E";
assertEquals(expected, URLUtils.formURLEncode(toEncode));
}
@Test
public void shouldFormURLDecodeString()
public void shouldPercentDecodeString()
{
String toDecode = "this+is+a+test+%26%5E";
String expected = "this is a test &^";
assertEquals(expected, URLUtils.formURLDecode(toDecode));
assertEquals(expected, URLUtils.urlDecodeWrapper(toDecode));
}
@Test
public void shouldPercentEncodeAllSpecialCharacters()
public void shouldEncodeAllSpecialCharacters()
{
String plain = "!*'();:@&=+$,/?#[]";
String encoded = "%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D";
assertEquals(encoded, URLUtils.percentEncode(plain));
assertEquals(plain, URLUtils.formURLDecode(encoded));
assertEquals(plain, URLUtils.urlDecodeWrapper(encoded));
}
@Test
public void shouldNotPercentEncodeReservedCharacters()
public void shouldNotEncodeReservedCharacters()
{
String plain = "abcde123456-._~";
String encoded = plain;
@@ -98,7 +79,7 @@ public class URLUtilsTest
public void shouldThrowExceptionIfStringToDecodeIsNull()
{
String toDecode = null;
URLUtils.formURLDecode(toDecode);
URLUtils.urlDecodeWrapper(toDecode);
}
@Test(expected = IllegalArgumentException.class)
@@ -147,7 +128,7 @@ public class URLUtilsTest
}
@Test
public void shouldPercentEncodePlusSymbol()
public void shouldEncodePlusSymbol()
{
String plain = "7aEP+jNAwvjc0mjhqg0nuXPf";
String encoded = "7aEP%2BjNAwvjc0mjhqg0nuXPf";
@@ -156,11 +137,11 @@ public class URLUtilsTest
}
@Test
public void shouldURLDecodePlusSymbol()
public void shouldDecodePlusSymbol()
{
String encoded = "oauth_verifier=7aEP%2BjNAwvjc0mjhqg0nuXPf";
String expected = "oauth_verifier=7aEP+jNAwvjc0mjhqg0nuXPf";
Assert.assertEquals(expected, URLUtils.formURLDecode(encoded));
Assert.assertEquals(expected, URLUtils.urlDecodeWrapper(encoded));
}
}