
package info.guardianproject.netcipher.client;

import android.content.Context;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

import javax.net.ssl.TrustManagerFactory;

import ch.boye.httpclientandroidlib.HttpHost;
import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
import ch.boye.httpclientandroidlib.conn.params.ConnRoutePNames;
import ch.boye.httpclientandroidlib.conn.scheme.PlainSocketFactory;
import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
import ch.boye.httpclientandroidlib.impl.conn.tsccm.ThreadSafeClientConnManager;
import info.guardianproject.onionkit.R;

public class StrongHttpsClient extends DefaultHttpClient {

    final Context context;
    private HttpHost proxyHost;
    private String proxyType;
    private SocksAwareProxyRoutePlanner routePlanner;

    private StrongSSLSocketFactory sFactory;
    private SchemeRegistry mRegistry;

    private final static String TRUSTSTORE_TYPE = "BKS";
    private final static String TRUSTSTORE_PASSWORD = "changeit";

    public StrongHttpsClient(Context context) {
        this.context = context;

        mRegistry = new SchemeRegistry();
        mRegistry.register(
                new Scheme(TYPE_HTTP, 80, PlainSocketFactory.getSocketFactory()));


        try {
            KeyStore keyStore = loadKeyStore();
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sFactory = new StrongSSLSocketFactory(context, trustManagerFactory.getTrustManagers(), keyStore, TRUSTSTORE_PASSWORD);
            mRegistry.register(new Scheme("https", 443, sFactory));
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }

    private KeyStore loadKeyStore () throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
    {

        KeyStore trustStore = KeyStore.getInstance(TRUSTSTORE_TYPE);
        // load our bundled cacerts from raw assets
        InputStream in = context.getResources().openRawResource(R.raw.debiancacerts);
        trustStore.load(in, TRUSTSTORE_PASSWORD.toCharArray());

        return trustStore;
    }

    public StrongHttpsClient(Context context, KeyStore keystore) {
        this.context = context;

        mRegistry = new SchemeRegistry();
        mRegistry.register(
                new Scheme(TYPE_HTTP, 80, PlainSocketFactory.getSocketFactory()));

        try {
        	TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            sFactory = new StrongSSLSocketFactory(context, trustManagerFactory.getTrustManagers(), keystore, TRUSTSTORE_PASSWORD);
            mRegistry.register(new Scheme("https", 443, sFactory));
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }

    @Override
    protected ThreadSafeClientConnManager createClientConnectionManager() {

        return new ThreadSafeClientConnManager(getParams(), mRegistry)
        {
            @Override
            protected ClientConnectionOperator createConnectionOperator(
                    SchemeRegistry schreg) {

                return new SocksAwareClientConnOperator(schreg, proxyHost, proxyType,
                        routePlanner);
            }
        };
    }

    public void useProxy(boolean enableTor, String type, String host, int port)
    {
        if (enableTor)
        {
            this.proxyType = type;

            if (type.equalsIgnoreCase(TYPE_SOCKS))
            {
                proxyHost = new HttpHost(host, port);
            }
            else
            {
            	proxyHost = new HttpHost(host, port, type);
                getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxyHost);
            }
        }
        else
        {
        	getParams().removeParameter(ConnRoutePNames.DEFAULT_PROXY);
            proxyHost = null;
        }

    }

    public void disableProxy ()
    {
    	getParams().removeParameter(ConnRoutePNames.DEFAULT_PROXY);
        proxyHost = null;
    }

    public void useProxyRoutePlanner(SocksAwareProxyRoutePlanner proxyRoutePlanner)
    {
        routePlanner = proxyRoutePlanner;
        setRoutePlanner(proxyRoutePlanner);
    }

    public final static String TYPE_SOCKS = "socks";
    public final static String TYPE_HTTP = "http";

}

@@ -4600,24 +4600,415 @@
 nner);%0A    %7D
+%0A    %0A    /**%0A     * NOT ADVISED, but some sites don't yet have latest protocols and ciphers available, and some%0A     * apps still need to support them%0A     * https://dev.guardianproject.info/issues/5644%0A     */%0A    public void enableSSLCompatibilityMode() %7B%0A        sFactory.setEnableStongerDefaultProtocalVersion(false);%0A        sFactory.setEnableStongerDefaultSSLCipherSuite(false);%0A    %7D
 %0A%0A    public

add method to enable SSL compat mode https://dev.guardianproject.info/issues/5644