/*
 *    © Darren McDonald 2010
 *
 *    This file is part of athena-ssl-cipher-check.
 *
 *    athena-ssl-cipher-check is free software: you can redistribute it
 *    and/or modify it under the terms of the GNU General Public License
 *    as published by the Free Software Foundation, either version 3 of
 *    the License, or (at your option) any later version.
 *
 *    athena-ssl-cipher-check is distributed in the hope that it will be
 *    useful, but WITHOUT ANY WARRANTY; without even the implied
 *    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *    See the GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with athena-ssl-cipher-check. If not, see
 *    <http://www.gnu.org/licenses/>.
 *
 */

package athenasslciphercheck;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.Socket;

/**
 * A one use socket class
 */

public class connection
{
    private InputStream in;
    private OutputStream out;
    private Socket sock;

    public static Settings settings;

    public boolean connect(  )
    {
        if( settings == null)
        {
            System.err.println("Unexpected error, settings is null");
            return false;
        }

        try
        {
            Thread.sleep( settings.getThrottle() );

            if( settings.getProxyType() == Settings.DIRECT )
                sock = new Socket( settings.getHost(), settings.getPort() );
            else if ( settings.getProxyType() == Settings.HTTP )
                sock = new Socket( settings.getProxyHost(), settings.getProxyPort() );
            else //WTF?
            {
                System.err.println("Proxy Type Unsupported");
                return false;
            }

            sock.setSoTimeout( settings.getTimeout() );

            in = sock.getInputStream();
            out = sock.getOutputStream();

            //Send Connect command if HTTP Proxy
            if( settings.getProxyType() == Settings.HTTP )
            {
                StringBuilder HTTPConnectString = new StringBuilder();

                //Method Line
                HTTPConnectString.append( "CONNECT " );
                HTTPConnectString.append( settings.getHost() );
                HTTPConnectString.append( ":" );
                HTTPConnectString.append( settings.getPort() );
                HTTPConnectString.append( " HTTP/1.0\r\n" );

                //Misc
                HTTPConnectString.append( "User-Agent: Athena SSL Cipher Check v"+Settings.VERSION+"\r\n" );
                HTTPConnectString.append( "Poxy-Connect: Keep-Alive\r\n" );
                HTTPConnectString.append( "Content-Length: 0\r\n" );
                HTTPConnectString.append( "Host: "+settings.getHost()+"\r\n" );

                //Basic Auth
                if( settings.getBasicAuth().length() > 0 )
                {
                    HTTPConnectString.append( "Authorization: Basic "+settings.getBasicAuth()+"\r\n" );
                    HTTPConnectString.append( "Proxy-Authorization: Basic "+settings.getBasicAuth()+"\r\n" );
                }

                //Misc
                HTTPConnectString.append( "Pragma: no-cache\r\n" );
                HTTPConnectString.append( "\r\n" );

                //Turn into ASCII byte array
                byte[] message = new byte[HTTPConnectString.length()];
                for( int i = 0; i < HTTPConnectString.length(); i++ )
                {
                    message[i] = (byte) HTTPConnectString.charAt(i);
                }

                this.send(message);

                BufferedReader br = new BufferedReader( new InputStreamReader(sock.getInputStream()) );
                String line = br.readLine();
                if( line.contains(" 403 ") )
                {
                    System.out.println("HTTP Proxy: 403 Access Denied");
                    return false;
                }
                if( line.contains(" 407 ") )
                {
                    System.out.println("HTTP Proxy: 407 Proxy Authentication Required");
                    return false;
                }
                if( !line.contains(" 200 ") )
                {
                    System.out.println("HTTP Proxy: Unknown Error");
                    return false;
                }
                
                //Read remaining characters, such as nl
                while( in.available() > 0 )
                {
                    in.read();
                }
                //Proxy Connection Ready
            }

        }
        catch( InterruptedException e )
        {
            System.out.println("Unable to connect to "+settings.getHost());
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
            return false;
        }
        catch( IOException e )
        {
            System.out.print("Unable to connect to "+settings.getHost());
            System.out.println(", " + e.getMessage());
            //System.out.println(e.getStackTrace());
            return false;
        }

        return true;
    }

    public boolean send( byte byteArray[] )
    {
        try
        {
            out.write(byteArray, 0, byteArray.length );
        }
        catch( IOException e )
        {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
            return false;
        }
        return true;
    }

    public int recv()
    {
        try
        {
            return in.read();                        
        }
        catch( InterruptedIOException e )
        {
            return -3;
        }
        catch( Exception e )
        {
            //System.out.println(e.getMessage());
            //System.out.println(e.getStackTrace());
            return -1;
        }

        //return -3;
    }

    public void close()
    {
        try
        {
            sock.close();
        }
        catch( IOException e )
        {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace());
        }
    }

}
