All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.deathbycaptcha.HttpClient Maven / Gradle / Ivy

There is a newer version: 0.2.5
Show newest version
package com.deathbycaptcha;

import org.json.JSONObject;
import org.json.JSONException;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;


/**
 * Death by Captcha HTTP API client.
 *
 */
public class HttpClient extends Client
{
    final static public String CRLF = "\r\n";
    final static public String SERVER_URL = "http://api.dbcapi.me/api";


    /**
     * Proxy to use, defaults to none.
     */
    public Proxy proxy = Proxy.NO_PROXY;


    private class HttpClientCaller
    {
        final static public String RESPONSE_CONTENT_TYPE = "application/json";


        public String call(Proxy proxy, URL url, byte[] payload, String contentType, Date deadline)
            throws IOException, com.deathbycaptcha.Exception
        {
            String response = null;
            while (deadline.after(new Date()) && null != url && null == response) {
                HttpURLConnection req = null;
                try {
                    req = (HttpURLConnection)url.openConnection(proxy);
                } catch (IOException e) {
                    throw new IOException("API connection failed: " + e.toString());
                }

                req.setRequestProperty("Accept", HttpClientCaller.RESPONSE_CONTENT_TYPE);
                req.setRequestProperty("User-Agent", Client.API_VERSION);
                req.setInstanceFollowRedirects(false);

                if (0 < payload.length) {
                    try {
                        req.setRequestMethod("POST");
                    } catch (java.lang.Exception e) {
                        //
                    }
                    req.setRequestProperty("Content-Type", contentType);
                    req.setRequestProperty("Content-Length", String.valueOf(payload.length));
                    req.setDoOutput(true);
                    OutputStream st = null;
                    try {
                        st = req.getOutputStream();
                        st.write(payload);
                        st.flush();
                    } catch (IOException e) {
                        throw new IOException("Failed sending API request: " + e.toString());
                    } finally {
                        try {
                            st.close();
                        } catch (java.lang.Exception e) {
                            //
                        }
                    }
                    payload = new byte[0];
                } else {
                    try {
                        req.setRequestMethod("GET");
                    } catch (java.lang.Exception e) {
                        //
                    }
                }

                url = null;
                req.setConnectTimeout(3 * Client.POLLS_INTERVAL * 1000);
                req.setReadTimeout(3 * Client.POLLS_INTERVAL * 1000);
                try {
                    req.connect();
                } catch (IOException e) {
                    throw new IOException("API connection failed: " + e.toString());
                }

                try {
                    int responseLength = 0;
                    int i = 1;
                    String k = null;
                    while (null != (k = req.getHeaderFieldKey(i))) {
                        if (k.equals("Content-Length")) {
                            responseLength = Integer.parseInt(req.getHeaderField(i), 10);
                        } else if (k.equals("Location")) {
                            try {
                                url = new URL(req.getHeaderField(i));
                            } catch (java.lang.Exception e) {
                                //
                            }
                        }
                        i++;
                    }

                    switch (req.getResponseCode()) {
                    case HttpURLConnection.HTTP_FORBIDDEN:
                        throw new AccessDeniedException("Access denied, check your credentials and/or balance");

                    case HttpURLConnection.HTTP_BAD_REQUEST:
                        throw new InvalidCaptchaException("CAPTCHA was rejected, check if it's a valid image");

                    case HttpURLConnection.HTTP_UNAVAILABLE:
                        throw new ServiceOverloadException("CAPTCHA was rejected due to service overload, try again later");

                    case HttpURLConnection.HTTP_SEE_OTHER:
                        if (null == url) {
                            throw new IOException("Invalid API redirection response");
                        }
                        break;
                    }

                    InputStream st = null;
                    try {
                        st = req.getInputStream();
                    } catch (IOException e) {
                        st = null;
                    } catch (java.lang.Exception e) {
                        st = req.getErrorStream();
                    }
                    if (null == st) {
                        throw new IOException("Failed receiving API response");
                    }

                    int offset = 0;
                    byte[] buff = new byte[responseLength];
                    try {
                        while (responseLength > offset) {
                            offset += st.read(buff, offset, responseLength - offset);
                        }
                        st.close();
                    } catch (IOException e) {
                        throw new IOException("Failed receiving API response: " + e.toString());
                    }
                    if (0 < buff.length) {
                        response = new String(buff, 0, buff.length);
                    }
                } catch (IOException e) {
                    throw e;
                } catch (com.deathbycaptcha.Exception e) {
                    throw e;
                } catch (java.lang.Exception e) {
                    throw new IOException("API communication failed: " + e.toString());
                } finally {
                    try {
                        req.disconnect();
                    } catch (java.lang.Exception e) {
                        //
                    }
                }
            }
            return response;
        }
    }


    protected JSONObject call(String cmd, byte[] data, String contentType)
        throws IOException, com.deathbycaptcha.Exception
    {
        this.log("SEND", cmd);
        URL url = null;
        try {
            url = new URL(HttpClient.SERVER_URL + '/' + cmd);
        } catch (java.lang.Exception e) {
            throw new IOException("Invalid API command " + cmd);
        }
        String response = (new HttpClientCaller()).call(
            this.proxy,
            url,
            data,
            (null != contentType ? contentType : "application/x-www-form-urlencoded"),
            new Date(System.currentTimeMillis() + Client.DEFAULT_TIMEOUT * 1000)
        );
        this.log("RECV", response);
        try {
            return new JSONObject(response);
        } catch (JSONException e) {
            throw new IOException("Invalid API response");
        }
    }

    protected JSONObject call(String cmd, byte[] data)
        throws IOException, com.deathbycaptcha.Exception
    {
        return this.call(cmd, data, null);
    }

    protected JSONObject call(String cmd, JSONObject args)
        throws IOException, com.deathbycaptcha.Exception
    {
        StringBuilder data = new StringBuilder();
        java.util.Iterator args_keys = args.keys();
        String k = null;
        while (args_keys.hasNext()) {
            k = args_keys.next().toString();
            try {
                data.append(URLEncoder.encode(k, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                return new JSONObject();
            }
            data.append("=");
            try {
                data.append(URLEncoder.encode(args.optString(k, ""), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                return new JSONObject();
            }
            if (args_keys.hasNext()) {
                data.append("&");
            }
        }
        return this.call(cmd, data.toString().getBytes());
    }

    protected JSONObject call(String cmd)
        throws IOException, com.deathbycaptcha.Exception
    {
        return this.call(cmd, new byte[0]);
    }


    /**
     * @see com.deathbycaptcha.Client#Client(String, String)
     */
    public HttpClient(String username, String password)
    {
        super(username, password);
    }


    /**
     * @see com.deathbycaptcha.Client#close
     */
    public void close()
    {}

    /**
     * @see com.deathbycaptcha.Client#connect
     */
    public boolean connect()
        throws IOException
    {
        return true;
    }


    /**
     * @see com.deathbycaptcha.Client#getUser
     */
    public User getUser()
        throws IOException, com.deathbycaptcha.Exception
    {
        return new User(this.call("user", this.getCredentials()));
    }

    /**
     * @see com.deathbycaptcha.Client#upload
     */
    public Captcha upload(byte[] img)
        throws IOException, com.deathbycaptcha.Exception
    {
        String boundary = null;
        try {
            boundary = (new java.math.BigInteger(1, (java.security.MessageDigest.getInstance("SHA1")).digest(
                (new java.util.Date()).toString().getBytes()
            ))).toString(16);
        } catch (java.security.NoSuchAlgorithmException e) {
            return null;
        }

        byte[] hdr = (
            "--" + boundary + HttpClient.CRLF + "Content-Disposition: form-data; name=\"username\"" + HttpClient.CRLF + "Content-Type: text/plain" + HttpClient.CRLF + "Content-Length: " + this._username.length() + HttpClient.CRLF + HttpClient.CRLF + this._username + HttpClient.CRLF +
            "--" + boundary + HttpClient.CRLF + "Content-Disposition: form-data; name=\"password\"" + HttpClient.CRLF + "Content-Type: text/plain" + HttpClient.CRLF + "Content-Length: " + this._password.length() + HttpClient.CRLF + HttpClient.CRLF + this._password + HttpClient.CRLF +
            "--" + boundary + HttpClient.CRLF + "Content-Disposition: form-data; name=\"swid\"" + HttpClient.CRLF + "Content-Type: text/plain" + HttpClient.CRLF + HttpClient.CRLF + Client.SOFTWARE_VENDOR_ID + HttpClient.CRLF +
            "--" + boundary + HttpClient.CRLF + "Content-Disposition: form-data; name=\"captchafile\"; filename=\"captcha\"" + HttpClient.CRLF + "Content-Type: application/octet-stream" + HttpClient.CRLF + "Content-Length: " + img.length + HttpClient.CRLF + HttpClient.CRLF
        ).getBytes();
        byte[] ftr = (HttpClient.CRLF + "--" + boundary + "--").getBytes();
        byte[] body = new byte[hdr.length + img.length + ftr.length];
        System.arraycopy(hdr, 0, body, 0, hdr.length);
        System.arraycopy(img, 0, body, hdr.length, img.length);
        System.arraycopy(ftr, 0, body, hdr.length + img.length, ftr.length);

        Captcha c = new Captcha(this.call("captcha", body,
                                          "multipart/form-data; boundary=" + boundary));
        return c.isUploaded() ? c : null;
    }

    /**
     * @see com.deathbycaptcha.Client#getCaptcha
     */
    public Captcha getCaptcha(int id)
        throws IOException, com.deathbycaptcha.Exception
    {
        return new Captcha(this.call("captcha/" + id));
    }

    /**
     * @see com.deathbycaptcha.Client#report
     */
    public boolean report(int id)
        throws IOException, com.deathbycaptcha.Exception
    {
        return !(new Captcha(this.call("captcha/" + id + "/report",
                                       this.getCredentials()))).isCorrect();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy