com.substanceofcode.twitter.XAuth.java Source code

Java tutorial

Introduction

Here is the source code for com.substanceofcode.twitter.XAuth.java

Source

/*
 * XAuth.java
 *
 * Copyright (C) 2005-2010 Tommi Laukkanen
 * http://www.substanceofcode.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.substanceofcode.twitter;

import com.substanceofcode.utils.Base64;
import com.substanceofcode.utils.HttpUtil;
import com.substanceofcode.utils.ResultParser;
import com.substanceofcode.utils.StringUtil;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Random;
import java.util.Vector;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

/**
 *
 * @author Tommi Laukkanen (tlaukkanen at gmail dot com)
 */
public class XAuth {

    private String xauthUsername;
    private String xauthPassword;
    private String token;
    private String tokenSecret;
    private String verifier;

    private static final String OAuthVersion = "1.0";
    private static final String OAuthParameterPrefix = "oauth_";

    private static final String OAuthConsumerKeyKey = "oauth_consumer_key";
    private static final String OAuthCallbackKey = "oauth_callback";
    private static final String OAuthVersionKey = "oauth_version";
    private static final String OAuthSignatureMethodKey = "oauth_signature_method";
    private static final String OAuthSignatureKey = "oauth_signature";
    private static final String OAuthTimestampKey = "oauth_timestamp";
    private static final String OAuthNonceKey = "oauth_nonce";
    private static final String OAuthTokenKey = "oauth_token";
    private static final String OAuthTokenSecretKey = "oauth_token_secret";
    private static final String OAuthVerifier = "oauth_verifier";
    private static final String XAuthUsername = "x_auth_username";
    private static final String XAuthPassword = "x_auth_password";
    private static final String XAuthMode = "x_auth_mode";

    private static final String OAUTH_CONSUMER_TOKEN = "xxx";
    private static final String OAUTH_CONSUMER_SECRET = "xxx";

    private static final String HMACSHA1SignatureType = "HMAC-SHA1";

    private String normalizedUrl = "";
    private String normalizedRequestParameters = "";

    public XAuth(String username, String password) {
        this.xauthUsername = username;
        this.xauthPassword = password;
    }

    public void setTokenAndSecret(String token, String secret) {
        this.token = token;
        this.tokenSecret = secret;
    }

    public String xAuthWebRequest(boolean isPost, String url, QueryParameter[] parameters, ResultParser parser)
            throws Exception {
        String outUrl = "";
        String querystring = "";
        String ret = "";
        String postData = "";
        String method = "GET";

        //Setup postData for signing.
        //Add the postData to the querystring.
        if (isPost) {
            method = "POST";
            if (parameters != null && parameters.length > 0) {
                //Decode the parameters and re-encode using the oAuth UrlEncode method.
                for (int i = 0; i < parameters.length; i++) {
                    QueryParameter q = parameters[i];
                    if (postData.length() > 0) {
                        postData += "&";
                    }
                    postData += q.getName() + "=" + encode(q.getValue());
                }
                if (url.indexOf("?") > 0) {
                    url += "&";
                } else {
                    url += "?";
                }
                url += postData;
            }
        }
        String nonce = this.generateNonce();
        String timeStamp = this.generateTimeStamp();

        //Generate Signature
        String sig = this.generateSignature(url, OAUTH_CONSUMER_TOKEN, OAUTH_CONSUMER_SECRET, this.token,
                this.tokenSecret, this.verifier, this.xauthUsername, this.xauthPassword, method, timeStamp, nonce);

        outUrl = normalizedUrl;
        querystring = normalizedRequestParameters;

        System.out.println("Signature: " + sig);

        if (querystring.length() > 0) {
            querystring += "&";
        }
        querystring += "oauth_signature=" + encode(sig);

        //Convert the querystring to postData
        /*if (isPost)
        {
        postData = querystring;
        querystring = "";
        }*/
        if (querystring.length() > 0) {
            outUrl += "?";
        }

        ret = webRequest(method, outUrl + querystring, postData, parser);

        return ret;
    }

    private String webRequest(String method, String url, String postData, ResultParser parser) throws Exception {
        String result = "";
        System.out.println("web request URL: " + url);
        if (method.equals("POST")) {
            if (parser != null) {
                result = HttpUtil.doPost(url, parser);
            } else {
                result = HttpUtil.doPost(url);
            }
        } else {
            if (parser != null) {
                result = HttpUtil.doGet(url, parser);
            } else {
                result = HttpUtil.doGet(url);
            }
        }
        return result;
    }

    private Vector getQueryParameters(String url) {
        int questionMarkIndex = url.indexOf("?");
        if (questionMarkIndex < 0) {
            return new Vector();
        }

        String parameters = url.substring(questionMarkIndex + 1);
        Vector params = new Vector();
        String[] para = StringUtil.split(parameters, "&");
        for (int i = 0; i < para.length; i++) {
            if (para[i].startsWith(OAuthParameterPrefix) == false) {
                String[] nameValue = StringUtil.split(para[i], "=");
                QueryParameter q = new QueryParameter(nameValue[0], nameValue[1]);
                params.addElement(q);
            }
        }
        return params;
    }

    public String generateSignatureBase(String url, String consumerKey, String token, String tokenSecret,
            String verifier, String xAuthUsername, String xAuthPassword, String httpMethod, String timeStamp,
            String nonce, String signatureType) {
        if (token == null) {
            token = "";
        }

        if (tokenSecret == null) {
            tokenSecret = "";
        }

        //normalizedUrl = null;
        //normalizedRequestParameters = null;

        Vector parameters = getQueryParameters(url);
        parameters.addElement(new QueryParameter(OAuthVersionKey, OAuthVersion));
        parameters.addElement(new QueryParameter(OAuthNonceKey, nonce));
        parameters.addElement(new QueryParameter(OAuthTimestampKey, timeStamp));
        parameters.addElement(new QueryParameter(OAuthSignatureMethodKey, signatureType));
        parameters.addElement(new QueryParameter(OAuthConsumerKeyKey, consumerKey));

        if (token != null && token.length() != 0) {
            parameters.addElement(new QueryParameter(OAuthTokenKey, token));
        } else {
            if (xAuthUsername != null && xAuthUsername.length() != 0) {
                parameters.addElement(new QueryParameter(XAuthUsername, xAuthUsername));
            }

            if (xAuthPassword != null && xAuthPassword.length() != 0) {
                parameters.addElement(new QueryParameter(XAuthPassword, xAuthPassword));
                parameters.addElement(new QueryParameter(XAuthMode, "client_auth"));
            }
        }

        if (verifier != null && verifier.length() != 0) {
            parameters.addElement(new QueryParameter(OAuthVerifier, verifier));
        }

        sortParameters(parameters);

        normalizedUrl = getSchemeAndHost(url);
        normalizedUrl += getAbsolutePath(url);
        System.out.println("Normalized url: " + normalizedUrl);
        normalizedRequestParameters = normalizeRequestParameters(parameters);
        System.out.println("Normalized params: " + normalizedRequestParameters);

        StringBuffer signatureBase = new StringBuffer();
        signatureBase.append(httpMethod + "&");
        signatureBase.append(encode(normalizedUrl) + "&");
        signatureBase.append(encode(normalizedRequestParameters));

        String sigBase = signatureBase.toString();
        System.out.println("Signature base: " + sigBase);
        return sigBase;
    }

    private static String getSchemeAndHost(String url) {
        int startIndex = url.indexOf("//") + 2;
        int endIndex = url.indexOf("/", startIndex);
        return url.substring(0, endIndex);
    }

    private static String getAbsolutePath(String url) {
        int startIndex = url.indexOf("//") + 2;
        int endIndex = url.indexOf("/", startIndex);
        int questionMark = url.indexOf("?");
        if (questionMark > 0) {
            return url.substring(endIndex, questionMark);
        } else {
            return url.substring(endIndex);
        }
    }

    private static void sortParameters(Vector items) {
        boolean unsorted = true;
        System.out.println("Sorting...");
        while (unsorted) {
            unsorted = false;
            for (int i = items.size() - 1; i > 0; i--) {
                System.out.println("Compare...");
                QueryParameter item1 = (QueryParameter) items.elementAt(i);
                QueryParameter item2 = (QueryParameter) items.elementAt(i - 1);
                if (item1.getName().compareTo(item2.getName()) < 0) {
                    System.out.println("Change...");
                    items.setElementAt(item1, i - 1);
                    items.setElementAt(item2, i);
                    unsorted = true;
                }
            }
        }
    }

    private String generateSignature(String url, String consumerKey, String consumerSecret, String token,
            String tokenSecret, String verifier, String xAuthUsername, String xAuthPassword, String httpMethod,
            String timeStamp, String nonce) {
        String signatureBase = generateSignatureBase(url, consumerKey, token, tokenSecret, verifier, xAuthUsername,
                xAuthPassword, httpMethod, timeStamp, nonce, HMACSHA1SignatureType);

        String tokenSec = "";
        if (tokenSecret != null) {
            tokenSec = tokenSecret;
        }
        String key = encode(consumerSecret) + "&" + encode(tokenSec);
        return getSignature(signatureBase, key);
    }

    public String getSignature(String message, String key) {
        try {
            HMac m = new HMac(new SHA1Digest());
            m.init(new KeyParameter(key.getBytes("UTF-8")));
            byte[] bytes = message.getBytes("UTF-8");
            m.update(bytes, 0, bytes.length);
            byte[] mac = new byte[m.getMacSize()];
            m.doFinal(mac, 0);
            String signature = new Base64().encode(mac);
            return signature;
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        }
        return null;
    }

    protected String normalizeRequestParameters(Vector parameters) {
        StringBuffer sb = new StringBuffer();
        QueryParameter p = null;
        Enumeration en = parameters.elements();
        while (en.hasMoreElements()) {
            p = (QueryParameter) en.nextElement();
            sb.append(p.getName()).append("=").append(p.getValue());
            if (en.hasMoreElements()) {
                sb.append("&");
            }
        }
        return sb.toString();
    }

    public String generateTimeStamp() {
        Date d = new Date();
        String timestamp = Long.toString(d.getTime() / 1000);
        return timestamp;
    }

    public String generateNonce() {
        Random random = new Random();
        String nonce = Long.toString(Math.abs(random.nextLong()), 60000);
        return nonce;
    }

    private String unreservedCharactersPattern = "[a-zA-Z0-9\\-\\._~]";
    private String unreservedCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";

    private String encode(String s) {
        if (s == null || "".equals(s)) {
            return "";
        }
        StringBuffer sb = new StringBuffer(s.length() * 2);
        for (int i = 0; i < s.length(); i++) {
            if (unreservedCharacters.indexOf(s.charAt(i)) == -1) {
                // get byte values of the character
                // and turn them into percent encoding
                String t = String.valueOf(s.charAt(i));
                sb.append(StringUtil.urlEncode(t));
            } else {
                sb.append(s.charAt(i));
            }
        }

        return sb.toString();
    }

}