Mega Code Archive

 
Categories / Android / Network
 

Http Request

/*  * This class was copied from this Stackoverflow Q&A:  * http://stackoverflow.com/questions/2253061/secure-http-post-in-android/2253280#2253280  * Thanks go to MattC!    */ //package org.acra.util; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLEncoder; import java.security.GeneralSecurityException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Map; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.LayeredSocketFactory; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.scheme.SocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; public final class HttpRequest {   // private static ACRALog log = new AndroidLogDelegate();   private static class SocketTimeOutRetryHandler implements       HttpRequestRetryHandler {     private final HttpParams httpParams;     private final int maxNrRetries;     /**      * @param httpParams      *            HttpParams that will be used in the HttpRequest.      * @param maxNrRetries      *            Max number of times to retry Request on failure due to      *            SocketTimeOutException.      */     private SocketTimeOutRetryHandler(HttpParams httpParams,         int maxNrRetries) {       this.httpParams = httpParams;       this.maxNrRetries = maxNrRetries;     }     @Override     public boolean retryRequest(IOException exception, int executionCount,         HttpContext context) {       if (exception instanceof SocketTimeoutException) {         if (executionCount <= maxNrRetries) {           if (httpParams != null) {             final int newSocketTimeOut = HttpConnectionParams                 .getSoTimeout(httpParams) * 2;             HttpConnectionParams.setSoTimeout(httpParams,                 newSocketTimeOut);             // log.d(ACRA.LOG_TAG,             // "SocketTimeOut - increasing time out to " +             // newSocketTimeOut + " millis and trying again");           } else {             // log.d(ACRA.LOG_TAG,             // "SocketTimeOut - no HttpParams, cannot increase time out. Trying again with current settings");           }           return true;         }         // log.d(ACRA.LOG_TAG,         // "SocketTimeOut but exceeded max number of retries : " +         // maxNrRetries);       }       return false; // To change body of implemented methods use File |               // Settings | File Templates.     }   }   private String login;   private String password;   private int connectionTimeOut = 3000;   private int socketTimeOut = 3000;   private int maxNrRetries = 3;   public void setLogin(String login) {     this.login = login;   }   public void setPassword(String password) {     this.password = password;   }   public void setConnectionTimeOut(int connectionTimeOut) {     this.connectionTimeOut = connectionTimeOut;   }   public void setSocketTimeOut(int socketTimeOut) {     this.socketTimeOut = socketTimeOut;   }   /**    * The default number of retries is 3.    *     * @param maxNrRetries    *            Max number of times to retry Request on failure due to    *            SocketTimeOutException.    */   public void setMaxNrRetries(int maxNrRetries) {     this.maxNrRetries = maxNrRetries;   }   /**    * Posts to a URL.    *     * @param url    *            URL to which to post.    * @param parameters    *            Map of parameters to post to a URL.    * @throws IOException    *             if the data cannot be posted.    */   public void sendPost(URL url, Map<?, ?> parameters) throws IOException {     final HttpClient httpClient = getHttpClient();     final HttpPost httpPost = getHttpPost(url, parameters);     // log.d(ACRA.LOG_TAG, "Sending request to " + url);     // TODO Consider using a RequestRetryHandler and if its a     // SocketTimeoutException to up the SocketTimeout and try again.     // See     // http://stackoverflow.com/questions/693997/how-to-set-httpresponse-timeout-for-android-in-java     // I think SocketTimeOut while waiting for response may be the cause of     // the multiple crash reports () - I     final HttpResponse response = httpClient.execute(httpPost,         new BasicHttpContext());     if (response != null) {       final StatusLine statusLine = response.getStatusLine();       if (statusLine != null) {         final String statusCode = Integer.toString(response             .getStatusLine().getStatusCode());         if (statusCode.startsWith("4") || statusCode.startsWith("5")) {           throw new IOException("Host returned error code "               + statusCode);         }       }       final String ret = EntityUtils.toString(response.getEntity());       // if (ACRA.DEV_LOGGING) log.d(ACRA.LOG_TAG,       // "HTTP " + (statusLine != null ? statusLine.getStatusCode() :       // "NoStatusLine#noCode") + " - Returning value:"       // + ret.substring(0, Math.min(ret.length(), 200)));     } else {       // if (ACRA.DEV_LOGGING) log.d(ACRA.LOG_TAG, "HTTP no Response!!");     }   }   /**    * @return HttpClient to use with this HttpRequest.    */   private HttpClient getHttpClient() {     final HttpParams httpParams = new BasicHttpParams();     httpParams.setParameter(ClientPNames.COOKIE_POLICY,         CookiePolicy.RFC_2109);     HttpConnectionParams         .setConnectionTimeout(httpParams, connectionTimeOut);     HttpConnectionParams.setSoTimeout(httpParams, socketTimeOut);     HttpConnectionParams.setSocketBufferSize(httpParams, 8192);     final SchemeRegistry registry = new SchemeRegistry();     registry.register(new Scheme("http", new PlainSocketFactory(), 80));     registry.register(new Scheme("https", (new FakeSocketFactory()), 443));     final ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(         httpParams, registry);     final DefaultHttpClient httpClient = new DefaultHttpClient(         clientConnectionManager, httpParams);     final HttpRequestRetryHandler retryHandler = new SocketTimeOutRetryHandler(         httpParams, maxNrRetries);     httpClient.setHttpRequestRetryHandler(retryHandler);     return httpClient;   }   /**    * @return Credentials to use with this HttpRequest or null if no    *         credentials were supplied.    */   private UsernamePasswordCredentials getCredentials() {     if (login != null || password != null) {       return new UsernamePasswordCredentials(login, password);     }     return null;   }   private HttpPost getHttpPost(URL url, Map<?, ?> parameters)       throws UnsupportedEncodingException {     final HttpPost httpPost = new HttpPost(url.toString());     // log.d(ACRA.LOG_TAG, "Setting httpPost headers");     final UsernamePasswordCredentials creds = getCredentials();     if (creds != null) {       httpPost.addHeader(BasicScheme.authenticate(creds, "UTF-8", false));     }     httpPost.setHeader("User-Agent", "Android");     httpPost.setHeader(         "Accept",         "text/html,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");     httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");     final String paramsAsString = getParamsAsString(parameters);     httpPost.setEntity(new StringEntity(paramsAsString, "UTF-8"));     return httpPost;   }   /**    * Converts a Map of parameters into a URL encoded Sting.    *     * @param parameters    *            Map of parameters to convert.    * @return URL encoded String representing the parameters.    * @throws UnsupportedEncodingException    *             if one of the parameters couldn't be converted to UTF-8.    */   private String getParamsAsString(Map<?, ?> parameters)       throws UnsupportedEncodingException {     final StringBuilder dataBfr = new StringBuilder();     for (final Object key : parameters.keySet()) {       if (dataBfr.length() != 0) {         dataBfr.append('&');       }       final Object preliminaryValue = parameters.get(key);       final Object value = (preliminaryValue == null) ? ""           : preliminaryValue;       dataBfr.append(URLEncoder.encode(key.toString(), "UTF-8"));       dataBfr.append('=');       dataBfr.append(URLEncoder.encode(value.toString(), "UTF-8"));     }     return dataBfr.toString();   } } /**  * Accepts any certificate, ideal for self-signed certificates.  */ class NaiveTrustManager implements X509TrustManager {   /*    * (non-Javadoc)    *     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()    */   @Override   public X509Certificate[] getAcceptedIssuers() {     return new X509Certificate[0];   }   /*    * (non-Javadoc)    *     * @see    * javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.    * X509Certificate[], java.lang.String)    */   @Override   public void checkClientTrusted(X509Certificate[] x509CertificateArray,       String string) throws CertificateException {   }   /*    * (non-Javadoc)    *     * @see    * javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.    * X509Certificate[], java.lang.String)    */   @Override   public void checkServerTrusted(X509Certificate[] x509CertificateArray,       String string) throws CertificateException {   } } class FakeSocketFactory implements SocketFactory, LayeredSocketFactory {   private SSLContext sslcontext = null;   private static SSLContext createEasySSLContext() throws IOException {     try {       final SSLContext context = SSLContext.getInstance("TLS");       context.init(null, new TrustManager[] { new NaiveTrustManager() },           null);       return context;     } catch (GeneralSecurityException e) {       throw new IOException(e);     }   }   private SSLContext getSSLContext() throws IOException {     if (this.sslcontext == null) {       this.sslcontext = createEasySSLContext();     }     return this.sslcontext;   }   @Override   public Socket connectSocket(Socket sock, String host, int port,       InetAddress localAddress, int localPort, HttpParams params)       throws IOException {     final int connTimeout = HttpConnectionParams         .getConnectionTimeout(params);     final int soTimeout = HttpConnectionParams.getSoTimeout(params);     final InetSocketAddress remoteAddress = new InetSocketAddress(host,         port);     final SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock         : createSocket());     if ((localAddress != null) || (localPort > 0)) {       // we need to bind explicitly       if (localPort < 0) {         localPort = 0; // indicates "any"       }       final InetSocketAddress isa = new InetSocketAddress(localAddress,           localPort);       sslsock.bind(isa);     }     sslsock.connect(remoteAddress, connTimeout);     sslsock.setSoTimeout(soTimeout);     return sslsock;   }   @Override   public Socket createSocket() throws IOException {     return getSSLContext().getSocketFactory().createSocket();   }   @Override   public boolean isSecure(Socket arg0) throws IllegalArgumentException {     return true;   }   @Override   public Socket createSocket(Socket socket, String host, int port,       boolean autoClose) throws IOException {     return getSSLContext().getSocketFactory().createSocket(socket, host,         port, autoClose);   } }