import java.net.*;
import javax.net.ssl.*;
import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;

public class Https 
{

    public static void main(String args[]) {

        URL url = null;

        if (args.length != 2) 
        {
            System.out.println("Https: url file");
            System.exit(1);
        }

        try
        {
            url = new URL(args[0]);
        }
        catch (Exception e)
        {
            System.out.println(e);
            System.exit(1);
        }

        Https uwe = new Https(url , args[1]);

    }

    public void doit(HttpsURLConnection con, String dest) 
    {
        try {


            long start = System.currentTimeMillis()/1000 ;


            BufferedReader rd = new BufferedReader( 
                    new InputStreamReader(con.getInputStream()));

            BufferedWriter wr = new BufferedWriter(
                    new FileWriter(dest));

            int contentLength = con.getContentLength();
    
            int c = 0;
            int i = 0;
            int percents = 0;

            float onePercent = (float)(contentLength/100.0);

            System.out.println("File tanmaño: "+contentLength+ " Bytes");
            //System.out.println(onePercent);
    
            while ( (c = rd.read()) != -1 )
            {
                wr.write(c);

                if ( i > percents*onePercent && contentLength != -1 ) 
                {
                    System.out.print(percents+ "% ");
                    if (percents % 10 == 0 && percents != 0) System.out.println();
                    percents++;
                }

                i++;
            }

            System.out.println();
            
    
            rd.close();
            wr.close();

            long stop = System.currentTimeMillis()/1000 ;

            System.out.println("ha durado: "+(stop-start)+" secundos");
            if (contentLength != -1) 
                System.out.println("promediio : "+((contentLength/1024)/(stop-start))+" KB/Second");
    
        }
        catch (Exception e) { e.printStackTrace(); }
    }


    public Https(URL url, String dest) 
    {

        try {

            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

            SSLSocketFactory sslf = getSSLSocketFactory() ;
            con.setSSLSocketFactory(sslf);

            doit(con,dest);

        }
        catch (Exception e) { e.printStackTrace(); }


    }

    private SSLSocketFactory getSSLSocketFactory() throws Exception
    {
        TrustManager[] tms = getTrustManagers();


        SSLContext context = SSLContext.getInstance("SSL");
        context.init(null,tms,null);

        return context.getSocketFactory();
    }

    private TrustManager[] getTrustManagers() throws Exception
    {
        TrustManager[] tms = new TrustManager[1];


        tms[0]=new MyTrustManager("httptrust","geheim");
        return tms;
    }

    class MyTrustManager implements X509TrustManager
    {

        private KeyStore ks = null;
        private File trustStore = null;
        char[] password = null;

        public MyTrustManager(String file, String pw )
        {
            try {

            ks = KeyStore.getInstance("JKS"); 
            trustStore = new File(file);
            password=pw.toCharArray();

            if ( ! trustStore.exists() ) 
            {
                System.out.println("creo TrustStore");
                ks.load(null,password);
                FileOutputStream fos =new FileOutputStream(trustStore);
                ks.store(fos,password);
                fos.close();
            }


            FileInputStream fis=new FileInputStream(trustStore);
            ks.load(fis,password);
            fis.close();

            }
            catch (Exception e)
            {
                System.out.println(e);
            }

        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) 
            throws IllegalArgumentException,CertificateException
        {
            //System.out.println("checkClientTrusted called");
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) 
            throws IllegalArgumentException,CertificateException
        {
            try 
            {
                //System.out.println("checkServerTrusted called");
                //System.out.println("auth type: "+authType);

                if (isIncluded(chain[0])) return ;
                if (storeOK(chain[0])) return ;

            }
            catch (Exception e)
            {
                System.out.println(e);
            }
            System.out.println("no se ecountra el certificado en el trustStore");
            System.exit(1);
        }


        public X509Certificate[] getAcceptedIssuers()
        {
            //System.out.println("fwrAcceptedIssuers called");
            return null;
        }

        private boolean storeOK(X509Certificate cert) throws Exception
        {
            System.out.println(cert);
            System.out.println("este certificato no se encouentra en el keyStore.");
            System.out.println("Debe ser guardado y confiado? s/n");

            BufferedReader stdin = 
                new BufferedReader(new InputStreamReader(System.in));

            String str = stdin.readLine().trim();

            if (str.matches("^s") ) 
            {
                String alias = "entry "+ks.size();
                ks.setCertificateEntry(alias,cert);
                FileOutputStream fos = new FileOutputStream(trustStore);
                ks.store(fos,password);
                fos.close();
                return true;
            }
            else return false ;
        }


        private boolean isSelfSigned(X509Certificate cert)
        {
            return cert.getSubjectDN().equals(cert.getIssuerDN());
        }

        private boolean isIncluded(X509Certificate cert)
        {
            Principal Issuer = cert.getIssuerDN();
            Principal Subject = cert.getSubjectDN();

            X509Certificate scert = null;
            String elem = null;

            boolean foundCert = false ;

            try {

                for (Enumeration e = ks.aliases() ; e.hasMoreElements() && !foundCert ;) 
                {
    	        	elem = (String)e.nextElement();
    		        scert = (X509Certificate)ks.getCertificate(elem);

                    if ( scert.equals(cert) )
                    {
                        foundCert=true;
                    }
                }

            }
            catch (Exception e) 
            {
                System.out.println(e);
            }

            return foundCert ;
        }
        
    }
}

