diff --git a/changelog.txt b/changelog.txt index 93a2cd885..dedcba636 100644 --- a/changelog.txt +++ b/changelog.txt @@ -82,3 +82,7 @@ * FEATURE: Kaixin2, SinaWeibo2 and Renren Apis * FEATURE: ImgUr Api * FEATURE: Freelancer Api (thanks Juan Palacios!) + * FIX: Allow digits in url schemes + * FEATURE: Specific exception for connection problems (OAuthConnectionException) + * FIX: Dropbox Api and Evernote Api updated to their latests versions + * FIX: Digg and Skyrock Apis diff --git a/pom.xml b/pom.xml index a3b01964f..e0c5d9887 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.scribe scribe jar - 1.3.0 + 1.3.1 Scribe OAuth Library The best OAuth library out there http://github.com/fernandezpablo85/scribe-java diff --git a/src/main/java/org/scribe/builder/api/DiggApi.java b/src/main/java/org/scribe/builder/api/DiggApi.java new file mode 100644 index 000000000..b69253eb9 --- /dev/null +++ b/src/main/java/org/scribe/builder/api/DiggApi.java @@ -0,0 +1,29 @@ +package org.scribe.builder.api; + +import org.scribe.model.*; + +public class DiggApi extends DefaultApi10a +{ + + private static final String AUTHORIZATION_URL = "http://digg.com/oauth/authorize?oauth_token=%s"; + private static final String BASE_URL = "http://services.digg.com/oauth/"; + + @Override + public String getRequestTokenEndpoint() + { + return BASE_URL + "request_token"; + } + + @Override + public String getAccessTokenEndpoint() + { + return BASE_URL + "access_token"; + } + + @Override + public String getAuthorizationUrl(Token requestToken) + { + return String.format(AUTHORIZATION_URL, requestToken.getToken()); + } + +} diff --git a/src/main/java/org/scribe/builder/api/DropBoxApi.java b/src/main/java/org/scribe/builder/api/DropBoxApi.java index 73a589533..86f4a71a1 100644 --- a/src/main/java/org/scribe/builder/api/DropBoxApi.java +++ b/src/main/java/org/scribe/builder/api/DropBoxApi.java @@ -7,19 +7,19 @@ public class DropBoxApi extends DefaultApi10a @Override public String getAccessTokenEndpoint() { - return "https://api.dropbox.com/0/oauth/access_token"; + return "https://api.dropbox.com/1/oauth/access_token"; } @Override public String getAuthorizationUrl(Token requestToken) { - return "https://www.dropbox.com/0/oauth/authorize?oauth_token="+requestToken.getToken(); + return "https://www.dropbox.com/1/oauth/authorize?oauth_token="+requestToken.getToken(); } @Override public String getRequestTokenEndpoint() { - return "https://api.dropbox.com/0/oauth/request_token"; + return "https://api.dropbox.com/1/oauth/request_token"; } } \ No newline at end of file diff --git a/src/main/java/org/scribe/builder/api/EvernoteApi.java b/src/main/java/org/scribe/builder/api/EvernoteApi.java index 48d45e920..007f48b1e 100644 --- a/src/main/java/org/scribe/builder/api/EvernoteApi.java +++ b/src/main/java/org/scribe/builder/api/EvernoteApi.java @@ -1,34 +1,21 @@ package org.scribe.builder.api; import org.scribe.model.Token; -import org.scribe.model.Verb; public class EvernoteApi extends DefaultApi10a { private static final String AUTHORIZATION_URL = "https://www.evernote.com/OAuth.action?oauth_token=%s"; - - @Override - public Verb getRequestTokenVerb() - { - return Verb.GET; - } - @Override + @Override public String getRequestTokenEndpoint() { - return "https://www.evernote.com/oauth"; - } - - @Override - public Verb getAccessTokenVerb() - { - return Verb.GET; - } + return "https://www.evernote.com/oauth"; + } @Override public String getAccessTokenEndpoint() { - return "https://www.evernote.com/oauth"; + return "https://www.evernote.com/oauth"; } @Override @@ -39,24 +26,24 @@ public String getAuthorizationUrl(Token requestToken) public static class Sandbox extends EvernoteApi { - private static final String SANDBOX_URL = "https://sandbox.evernote.com/oauth"; + private static final String SANDBOX_URL = "https://sandbox.evernote.com"; @Override public String getRequestTokenEndpoint() { - return SANDBOX_URL; + return SANDBOX_URL + "/oauth"; } @Override public String getAccessTokenEndpoint() { - return SANDBOX_URL; + return SANDBOX_URL + "/oauth"; } @Override public String getAuthorizationUrl(Token requestToken) { - return String.format(SANDBOX_URL + "?oauth_token=%s", requestToken.getToken()); + return String.format(SANDBOX_URL + "/OAuth.action?oauth_token=%s", requestToken.getToken()); } - } + } } diff --git a/src/main/java/org/scribe/builder/api/SkyrockApi.java b/src/main/java/org/scribe/builder/api/SkyrockApi.java new file mode 100644 index 000000000..b0e76a303 --- /dev/null +++ b/src/main/java/org/scribe/builder/api/SkyrockApi.java @@ -0,0 +1,35 @@ +package org.scribe.builder.api; + +import org.scribe.model.*; + +/** + * OAuth API for Skyrock. + * + * @author Nicolas QuiƩnot + * @see Skyrock.com API + */ +public class SkyrockApi extends DefaultApi10a +{ + private static final String API_ENDPOINT = "https://api.skyrock.com/v2"; + private static final String REQUEST_TOKEN_RESOURCE = "/oauth/initiate"; + private static final String AUTHORIZE_URL = "/oauth/authorize?oauth_token=%s"; + private static final String ACCESS_TOKEN_RESOURCE = "/oauth/token"; + + @Override + public String getAccessTokenEndpoint() + { + return API_ENDPOINT + ACCESS_TOKEN_RESOURCE; + } + + @Override + public String getRequestTokenEndpoint() + { + return API_ENDPOINT + REQUEST_TOKEN_RESOURCE; + } + + @Override + public String getAuthorizationUrl(Token requestToken) + { + return String.format(API_ENDPOINT + AUTHORIZE_URL, requestToken.getToken()); + } +} diff --git a/src/main/java/org/scribe/builder/api/YammerApi.java b/src/main/java/org/scribe/builder/api/YammerApi.java index 68bcda511..e06543d97 100644 --- a/src/main/java/org/scribe/builder/api/YammerApi.java +++ b/src/main/java/org/scribe/builder/api/YammerApi.java @@ -5,7 +5,7 @@ public class YammerApi extends DefaultApi10a { - private static final String AUTHORIZATION_URL = "'https://www.yammer.com/oauth/authorize?oauth_token=%s'"; + private static final String AUTHORIZATION_URL = "https://www.yammer.com/oauth/authorize?oauth_token=%s"; @Override public String getRequestTokenEndpoint() diff --git a/src/main/java/org/scribe/exceptions/OAuthConnectionException.java b/src/main/java/org/scribe/exceptions/OAuthConnectionException.java new file mode 100644 index 000000000..918de810c --- /dev/null +++ b/src/main/java/org/scribe/exceptions/OAuthConnectionException.java @@ -0,0 +1,14 @@ +package org.scribe.exceptions; + +/** + * @author: Pablo Fernandez + */ +public class OAuthConnectionException extends OAuthException +{ + private static final String MSG = "There was a problem while creating a connection to the remote service."; + + public OAuthConnectionException(Exception e) + { + super(MSG, e); + } +} diff --git a/src/main/java/org/scribe/exceptions/OAuthSignatureException.java b/src/main/java/org/scribe/exceptions/OAuthSignatureException.java index 50143b5a0..94692be5d 100644 --- a/src/main/java/org/scribe/exceptions/OAuthSignatureException.java +++ b/src/main/java/org/scribe/exceptions/OAuthSignatureException.java @@ -8,6 +8,7 @@ public class OAuthSignatureException extends OAuthException { private static final long serialVersionUID = 1L; + private static final String MSG = "Error while signing string: %s"; /** * Default constructor @@ -17,7 +18,7 @@ public class OAuthSignatureException extends OAuthException */ public OAuthSignatureException(String stringToSign, Exception e) { - super("Error while signing string: " + stringToSign, e); + super(String.format(MSG, stringToSign), e); } } diff --git a/src/main/java/org/scribe/extractors/TokenExtractorImpl.java b/src/main/java/org/scribe/extractors/TokenExtractorImpl.java index c48fe35cb..ba1784b9b 100644 --- a/src/main/java/org/scribe/extractors/TokenExtractorImpl.java +++ b/src/main/java/org/scribe/extractors/TokenExtractorImpl.java @@ -16,7 +16,7 @@ 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 Pattern SECRET_REGEX = Pattern.compile("oauth_token_secret=([^&]*)"); /** * {@inheritDoc} diff --git a/src/main/java/org/scribe/model/Request.java b/src/main/java/org/scribe/model/Request.java index 0b8607e19..07b320312 100644 --- a/src/main/java/org/scribe/model/Request.java +++ b/src/main/java/org/scribe/model/Request.java @@ -61,13 +61,9 @@ public Response send() createConnection(); return doSend(); } - catch (UnknownHostException uhe) + catch (Exception e) { - throw new OAuthException("Could not reach the desired host. Check your network connection.", uhe); - } - catch (IOException ioe) - { - throw new OAuthException("Problems while creating connection.", ioe); + throw new OAuthConnectionException(e); } } diff --git a/src/main/java/org/scribe/utils/Preconditions.java b/src/main/java/org/scribe/utils/Preconditions.java index d7a06c347..0ac134e3c 100644 --- a/src/main/java/org/scribe/utils/Preconditions.java +++ b/src/main/java/org/scribe/utils/Preconditions.java @@ -12,7 +12,9 @@ public class Preconditions { private static final String DEFAULT_MESSAGE = "Received an invalid parameter"; - private static final Pattern URL_PATTERN = Pattern.compile("[a-zA-Z_-]+://\\S+"); + + // scheme = alpha *( alpha | digit | "+" | "-" | "." ) + private static final Pattern URL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*://\\S+"); /** * Checks that an object is not null. diff --git a/src/test/java/org/scribe/examples/DiggExample.java b/src/test/java/org/scribe/examples/DiggExample.java new file mode 100644 index 000000000..63fea8b6a --- /dev/null +++ b/src/test/java/org/scribe/examples/DiggExample.java @@ -0,0 +1,65 @@ +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 DiggExample +{ + private static final String NETWORK_NAME = "Digg"; + private static final String PROTECTED_RESOURCE_URL = "http://services.digg.com/2.0/comment.digg"; + + public static void main(String[] args) + { + // Replace these with your own api key and secret + String apiKey = "myKey"; + String apiSecret = "mySecret"; + OAuthService service = new ServiceBuilder().provider(DiggApi.class).apiKey(apiKey).apiSecret(apiSecret).build(); + Scanner in = new Scanner(System.in); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + Token requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + // 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.POST, PROTECTED_RESOURCE_URL); + request.addBodyParameter("comment_id", "20100729223726:4fef610331ee46a3b5cbd740bf71313e"); + 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! :)"); + + } +} \ No newline at end of file diff --git a/src/test/java/org/scribe/examples/SinaWeibo2Example.java b/src/test/java/org/scribe/examples/SinaWeibo2Example.java index 683efe50e..89b14e117 100644 --- a/src/test/java/org/scribe/examples/SinaWeibo2Example.java +++ b/src/test/java/org/scribe/examples/SinaWeibo2Example.java @@ -15,8 +15,8 @@ public class SinaWeibo2Example public static void main(String[] args) { // Replace these with your own api key and secret - String apiKey = "342348223"; - String apiSecret = "cfdf672e166a4bc954c0e33f03cf0d1b"; + String apiKey = "your_api_key"; + String apiSecret = "your_api_secret"; OAuthService service = new ServiceBuilder() .provider(SinaWeiboApi20.class) .apiKey(apiKey) diff --git a/src/test/java/org/scribe/examples/SkyrockExample.java b/src/test/java/org/scribe/examples/SkyrockExample.java new file mode 100644 index 000000000..422d067e5 --- /dev/null +++ b/src/test/java/org/scribe/examples/SkyrockExample.java @@ -0,0 +1,61 @@ +package org.scribe.examples; + +import java.util.Scanner; + +import org.scribe.builder.*; +import org.scribe.builder.api.*; +import org.scribe.model.*; +import org.scribe.oauth.*; + +public class SkyrockExample +{ + private static final String PROTECTED_RESOURCE_URL = "https://api.skyrock.com/v2/user/get.json"; + + public static void main(String[] args) + { + OAuthService service = new ServiceBuilder() + .provider(SkyrockApi.class) + .apiKey("your-api-key") + .apiSecret("your-api-secret") + .build(); + Scanner in = new Scanner(System.in); + + System.out.println("=== Skyrock's OAuth Workflow ==="); + System.out.println(); + + // Obtain the Request Token + System.out.println("Fetching the Request Token..."); + Token requestToken = service.getRequestToken(); + System.out.println("Got the Request Token!"); + System.out.println(); + + System.out.println("Now go and authorize Scribe here:"); + System.out.println(service.getAuthorizationUrl(requestToken)); + System.out.println("And paste the verifier 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! :)"); + + } + +} diff --git a/src/test/java/org/scribe/extractors/TokenExtractorTest.java b/src/test/java/org/scribe/extractors/TokenExtractorTest.java index 2c9928f3b..aca5ad1a7 100644 --- a/src/test/java/org/scribe/extractors/TokenExtractorTest.java +++ b/src/test/java/org/scribe/extractors/TokenExtractorTest.java @@ -43,6 +43,15 @@ public void shouldExtractTokenFromResponseWithCallbackConfirmed() assertEquals("hh5s93j4hdidpola", extracted.getToken()); assertEquals("hdhd0244k9j7ao03", extracted.getSecret()); } + + @Test + public void shouldExtractTokenWithEmptySecret() + { + String response = "oauth_token=hh5s93j4hdidpola&oauth_token_secret="; + Token extracted = extractor.extract(response); + assertEquals("hh5s93j4hdidpola", extracted.getToken()); + assertEquals("", extracted.getSecret()); + } @Test(expected = OAuthException.class) public void shouldThrowExceptionIfTokenIsAbsent() diff --git a/src/test/java/org/scribe/utils/PreconditionsTest.java b/src/test/java/org/scribe/utils/PreconditionsTest.java index 54ec9f8c5..84bc117e9 100644 --- a/src/test/java/org/scribe/utils/PreconditionsTest.java +++ b/src/test/java/org/scribe/utils/PreconditionsTest.java @@ -43,16 +43,25 @@ public void shouldThrowExceptionForNullUrls() Preconditions.checkValidUrl(null, ERROR_MSG); } + @Test public void shouldAllowValidUrls() { Preconditions.checkValidUrl("http://www.example.com", ERROR_MSG); } + @Test public void shouldAllowSSLUrls() { Preconditions.checkValidUrl("https://www.example.com", ERROR_MSG); } + + @Test + public void shouldAllowSpecialCharsInScheme() + { + Preconditions.checkValidUrl("custom+9.3-1://www.example.com", ERROR_MSG); + } + @Test public void shouldAllowNonStandarProtocolsForAndroid() { Preconditions.checkValidUrl("x-url-custom://www.example.com", ERROR_MSG); @@ -64,6 +73,13 @@ public void shouldNotAllowStrangeProtocolNames() Preconditions.checkValidUrl("$weird*://www.example.com", ERROR_MSG); } + @Test(expected = IllegalArgumentException.class) + public void shouldNotAllowUnderscoreInScheme() + { + Preconditions.checkValidUrl("http_custom://www.example.com", ERROR_MSG); + } + + @Test public void shouldAllowOutOfBandAsValidCallbackValue() { Preconditions.checkValidOAuthCallback("oob", ERROR_MSG);