Created
August 1, 2010 08:55
-
-
Save shin1ogawa/503142 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.shin1ogawa.ffoauth; | |
import java.io.IOException; | |
import java.security.InvalidKeyException; | |
import java.security.NoSuchAlgorithmException; | |
import com.shin1ogawa.oauth.FFUtil; | |
public class FF { | |
public static void main(String[] args) throws IOException, | |
InvalidKeyException, NoSuchAlgorithmException { | |
if (args.length == 4) { | |
// args: username, password, consumerKey, consumerSecret | |
FFUtil.TokenPair pair = FFUtil.authorize(args[0], args[1], "GET", | |
"https://friendfeed.com/account/oauth/ia_access_token", | |
args[2], args[3]); | |
System.out.println(String.format("token=%s, tokenSecret=%s", | |
pair.token, pair.secret)); | |
} else if (args.length == 5) { | |
// args: consumerKey, consumerSecret, token, tokenSecret, body | |
FFUtil.post("POST", "http://friendfeed-api.com/v2/entry", args[4], | |
args[0], args[1], args[2], args[3]); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.shin1ogawa.oauth; | |
public class FFUtil { | |
static final public String post(String method, String urlString, | |
String body, String consumerKey, String consumerSecret, | |
String token, String tokenSecret) | |
throws java.security.InvalidKeyException, | |
java.security.NoSuchAlgorithmException, java.io.IOException { | |
java.util.Map<String, String> params = new java.util.HashMap<String, String>(); | |
params.put("oauth_consumer_key", consumerKey); | |
params.put("oauth_token", token); | |
params.put("oauth_signature_method", "HMAC-SHA1"); | |
params.put("oauth_version", "1.0"); | |
params.put("oauth_nonce", | |
String.valueOf((long) (Math.random() * Math.pow(2.0, 64.0)))); | |
params.put("oauth_timestamp", | |
String.valueOf(System.currentTimeMillis() / 1000)); | |
params.put("body", java.net.URLEncoder.encode(body, "utf-8")); | |
String signature = OAuthUtil.generateOauthSignature(OAuthUtil | |
.generateSignatureBaseString(method, urlString, params), | |
consumerSecret, tokenSecret); | |
StringBuilder b = new StringBuilder().append(OAuthUtil | |
.formatUrlParams(params)); | |
b.append("&oauth_signature=").append(signature); | |
java.net.URL url = new java.net.URL(urlString); | |
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url | |
.openConnection(); | |
connection.setRequestMethod(method); | |
connection.setDoOutput(true); | |
connection.addRequestProperty("Content-Type", | |
"application/x-www-form-urlencoded"); | |
java.io.PrintWriter out = new java.io.PrintWriter( | |
new java.io.OutputStreamWriter(connection.getOutputStream(), | |
"utf-8")); | |
out.print(b.toString()); | |
out.flush(); | |
connection.connect(); | |
return getResponseAsString(connection); | |
} | |
static final public TokenPair authorize(String user, String password, | |
String method, String urlString, String consumerKey, | |
String consumerSecret) throws java.security.InvalidKeyException, | |
java.security.NoSuchAlgorithmException, java.io.IOException { | |
java.util.Map<String, String> params = new java.util.HashMap<String, String>(); | |
params.put("ff_username", user); | |
params.put("ff_password", password); | |
params.put("oauth_consumer_key", consumerKey); | |
params.put("oauth_signature_method", "HMAC-SHA1"); | |
params.put("oauth_version", "1.0"); | |
params.put("oauth_nonce", | |
String.valueOf((long) (Math.random() * Math.pow(2.0, 64.0)))); | |
params.put("oauth_timestamp", | |
String.valueOf(System.currentTimeMillis() / 1000)); | |
String signature = OAuthUtil.generateOauthSignature(OAuthUtil | |
.generateSignatureBaseString(method, urlString, params), | |
consumerSecret, ""); // empty tokenSecret | |
StringBuilder b = new StringBuilder(urlString).append("?").append( | |
OAuthUtil.formatUrlParams(params)); | |
b.append("&oauth_signature=").append(signature); | |
java.net.URL url = new java.net.URL(b.toString()); | |
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url | |
.openConnection(); | |
connection.setRequestMethod(method); | |
connection.connect(); | |
String response = getResponseAsString(connection); | |
String[] split = response.split("\\&"); | |
String token = null; | |
String secret = null; | |
for (String string : split) { | |
if (string.startsWith("oauth_token=")) { | |
token = string.split("=")[1]; | |
} else if (string.startsWith("oauth_token_secret=")) { | |
secret = string.split("=")[1]; | |
} | |
} | |
return new TokenPair(token, secret); | |
} | |
static final String getResponseAsString( | |
java.net.HttpURLConnection connection) throws java.io.IOException { | |
java.io.BufferedReader in = null; | |
try { | |
in = new java.io.BufferedReader(new java.io.InputStreamReader( | |
connection.getInputStream())); | |
} catch (java.io.IOException ex) { | |
throw new RuntimeException(String.format("IOException: [%d]%s", | |
connection.getResponseCode(), | |
connection.getResponseMessage())); | |
} | |
StringBuilder b = new StringBuilder(); | |
String line; | |
while ((line = in.readLine()) != null) { | |
b.append(line); | |
} | |
in.close(); | |
return b.toString(); | |
} | |
public static class TokenPair { | |
final public String token; | |
final public String secret; | |
TokenPair(String value1, String value2) { | |
this.token = value1; | |
this.secret = value2; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.shin1ogawa.oauth; | |
public class OAuthUtil { | |
static final String ENC = "utf-8"; | |
static final String HMAC_SHA1_ALGORITHM = "HmacSHA1"; | |
public static String generateSignatureBaseString(String method, | |
String requestUrlBase, java.util.Map<String, String> params) | |
throws java.io.UnsupportedEncodingException { | |
return escapeAndJoin(java.util.Arrays.asList(method, requestUrlBase, | |
formatUrlParams(params))); | |
} | |
public static String generateOauthSignature(String baseString, | |
String consumerSecret, String tokenSecret) | |
throws java.security.InvalidKeyException, | |
java.security.NoSuchAlgorithmException, | |
java.io.UnsupportedEncodingException { | |
return java.net.URLEncoder.encode( | |
generateHmacSha1Signature(baseString, | |
escapeAndJoin(java.util.Arrays.asList(consumerSecret, | |
tokenSecret))), ENC); | |
} | |
public static String formatUrlParams(java.util.Map<String, String> params) | |
throws java.io.UnsupportedEncodingException { | |
StringBuilder b = new StringBuilder(); | |
boolean first = true; | |
for (String key : sorted(params)) { | |
if (first == false) { | |
b.append('&'); | |
} else { | |
first = false; | |
} | |
b.append(key) | |
.append('=') | |
.append(java.net.URLEncoder.encode(params.get(key), ENC) | |
.replace("+", "%20")); | |
} | |
return b.toString(); | |
} | |
private static String escapeAndJoin(Iterable<String> params) | |
throws java.io.UnsupportedEncodingException { | |
StringBuilder b = new StringBuilder(); | |
boolean first = true; | |
for (String s : params) { | |
if (first == false) { | |
b.append('&'); | |
} else { | |
first = false; | |
} | |
b.append(java.net.URLEncoder.encode(s, ENC)); | |
} | |
return b.toString(); | |
} | |
private static java.util.List<String> sorted( | |
java.util.Map<String, String> map) { | |
java.util.List<String> list = new java.util.ArrayList<String>( | |
map.keySet()); | |
java.util.Collections.sort(list); | |
return list; | |
} | |
private static String generateHmacSha1Signature(String data, String key) | |
throws java.security.NoSuchAlgorithmException, | |
java.security.InvalidKeyException { | |
javax.crypto.spec.SecretKeySpec signingKey = new javax.crypto.spec.SecretKeySpec( | |
key.getBytes(), HMAC_SHA1_ALGORITHM); | |
javax.crypto.Mac mac = javax.crypto.Mac | |
.getInstance(HMAC_SHA1_ALGORITHM); | |
mac.init(signingKey); | |
return byteArrayToBase64(mac.doFinal(data.getBytes())); | |
} | |
private static String byteArrayToBase64(byte[] bytes) { | |
int aLen = bytes.length; | |
int numFullGroups = aLen / 3; | |
int numBytesInPartialGroup = aLen - 3 * numFullGroups; | |
int resultLen = 4 * ((aLen + 2) / 3); | |
StringBuilder b = new StringBuilder(resultLen); | |
int inCursor = 0; | |
for (int i = 0; i < numFullGroups; i++) { | |
int byte0 = bytes[inCursor++] & 0xff; | |
int byte1 = bytes[inCursor++] & 0xff; | |
int byte2 = bytes[inCursor++] & 0xff; | |
b.append(intToBase64[byte0 >> 2]); | |
b.append(intToBase64[(byte0 << 4) & 0x3f | (byte1 >> 4)]); | |
b.append(intToBase64[(byte1 << 2) & 0x3f | (byte2 >> 6)]); | |
b.append(intToBase64[byte2 & 0x3f]); | |
} | |
if (numBytesInPartialGroup != 0) { | |
int byte0 = bytes[inCursor++] & 0xff; | |
b.append(intToBase64[byte0 >> 2]); | |
if (numBytesInPartialGroup == 1) { | |
b.append(intToBase64[(byte0 << 4) & 0x3f]); | |
b.append("=="); | |
} else { | |
int byte1 = bytes[inCursor++] & 0xff; | |
b.append(intToBase64[(byte0 << 4) & 0x3f | (byte1 >> 4)]); | |
b.append(intToBase64[(byte1 << 2) & 0x3f]); | |
b.append('='); | |
} | |
} | |
return b.toString(); | |
} | |
private static final char intToBase64[] = { 'A', 'B', 'C', 'D', 'E', 'F', | |
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', | |
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', | |
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', | |
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', | |
'6', '7', '8', '9', '+', '/' }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment