/*
 * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.ejte.ccl.webrunner.proxy;

import java.net.*;
import java.io.*;
import java.text.*;
import java.util.*;

/**
* This is the Main class for proxy functionality.http supports GET,POST,HEAD requests.The proxy HTTP server is single
 *threaded,in that each request is handled in turn while all others wait.
* Gets requests from browser and forwards to web server.
* Receives response from web server and forwards to web browser.Writes transaction in a file.
*
* @author       Deepa Singh (deepa.singh@sun.com)
 *Company       Sun Microsystems Inc.
*
*/
public class httpd implements Runnable,LogMessage
{
        private int port;
        private LogMessage log;
        private boolean stopFlag;
        private static String version="1.0";
        private static String CRLF="\r\n";
        private static int buffer_size=8192;
        private String host;
        private String methodSupported;
        private int content_length;

        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @param                s        The string to be converted
        * @return                byte[]
        */
        private final byte[] toBytes(String s)
        {
                byte b[]=s.getBytes();
                return b;
        }


        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @param                out        The output stream
        * @param                s        The string
        * @return                void
        */
        private void writeString(OutputStream out,String s)
        throws IOException
        {
                out.write(toBytes(s));
        }

        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @param                in        The InputStream
        * @param                url        The string URL
        * @param                mh Mimeheader
        * @return                TempStore
        */
        private TempStore loadFile(InputStream in,String url,MimeHeader mh)
        throws IOException
        {
                TempStore temp;
                byte file_buf[]=new byte[buffer_size];
                temp=new TempStore(url,mh);
                int size=0;
                int n;
                while((n=in.read(file_buf))>=0)
                {
                        temp.append(file_buf,n);
                        size+=n;
                }
                in.close();
                return temp;
        }




        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @param                cmd        String
        * @param                url        The string URL
        * @param                code integer
        * @param        size Integer
        * @return                void
        */
        private void logEntry(String cmd,String url,int code,int size)
        {

                log.log(host+ "--" + cmd+ "" + url+ "HTTP/1.0 \" " +
                code+ "" +
                size+ "\n");
        }



        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @param                in        The InputStream
        * @param                url        The string URL
        * @param                mh Mimeheader
        * @return                TempStore
        */
        private String getRawRequest(InputStream in)
        throws IOException
        {
                byte buf[]=new byte[buffer_size];
                int pos=0;
                int c;
                while((c=in.read()) != -1)
                {
                        switch((char)c)
                        {

                                case '\r':
                                break;

                                case '\n':
                                if(buf[pos-1] == c)
                                {
                                        String temp=new String(buf,0,pos);
                                        //System.out.print("\nString returned is " + temp);
                                        return temp;
                                }

                        default:
                                buf[pos++]=(byte)c;

                        }


                }
                return null;
        }

        /**
         *If browser is set to this proxy server then the requests that will be sent to it will include the complete URL.Complete URL is parsed
         *and remote website name an optional non standard port number is extracted.Then a socket is opened to remote site.A GET or POST request
         * is sent asking for the URL that was sent.Whatever response header is received from the external web server ,it is passed back to the client i.e browser.
         *Transaction is logged in a file if it was success ,socket is closed and method returns.
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @param                out        The OutputStream
        * @param                url        The string URL
        * @param                inmh Mimeheader
        * @param                in   The input stream
        * @return                void
        */
        private void handleProxy(OutputStream out,String url,MimeHeader inmh,InputStream in) {
            try {
                int start=url.indexOf("://") +3;

                int path=url.indexOf('/',start);

                String site=url.substring(start,path).toLowerCase();

                String server_url=url.substring(path);

                int colon=site.indexOf(':');
                if(colon > 0) {
                    port=Integer.parseInt(site.substring(colon+1));
                    site=site.substring(0,colon);
                }

                FileOutputStream fileout=new FileOutputStream("script.txt",true);
                //System.out.print("\n Server at port" + port + "\n");
                Socket server=new Socket(site,port);
                InputStream server_in=server.getInputStream();
                OutputStream server_out=server.getOutputStream();
                inmh.put("User-Agent",inmh.get("User-Agent") + version);
                double first,end;
                if(methodSupported.equalsIgnoreCase("post")) {
                    int i;
                    byte postbuf[]=new byte[content_length];
                    for (i =0; i < content_length; i++)
                        postbuf[i]=(byte)in.read();

                  String postdata=new String(postbuf,0,i);
                  //  System.out.print("\n POST data without mime header is " + postdata + "\n");

                  String post="POST" + " " + server_url+ " " + "HTTP/1.0" + CRLF + inmh
                  + CRLF + postdata+ CRLF+CRLF;

                  System.out.print("\nPOST request sent is " + post);
                  byte filebuf[]=post.getBytes();
                  for( i=0;i<filebuf.length;i++)
                      fileout.write(filebuf[i]);


                    String token="!"+"\n"+"!";
                    byte tokenbytes[]=token.getBytes();
                    for(i=0;i<tokenbytes.length;i++)
                        fileout.write(tokenbytes[i]);

                    fileout.close();

                    first=System.currentTimeMillis();
                    writeString(server_out,post);

                    String raw_request=getRawRequest(server_in);
                    System.out.print("\n Server Response Header is--------------------------\n " + raw_request + "\n");

                    HttpResponse server_response=new HttpResponse(raw_request);
                    writeString(out,server_response.toString());
                    end=System.currentTimeMillis();
                    //System.out.print("\n Server Response Header is--------------------------\n " + server_response.statusCode + "\n");

                    if(server_response.statusCode==200) {

                        TempStore uce=loadFile(server_in,url,server_response.mh);
                        out.write(uce.data,0,uce.length);

                    /*    byte filebuf[]=post.getBytes();
                        for( i=0;i<filebuf.length;i++)
                            fileout.write(filebuf[i]);


                        String token="!"+"\n"+"!";
                        byte tokenbytes[]=token.getBytes();
                        for(i=0;i<tokenbytes.length;i++)
                            fileout.write(tokenbytes[i]);

                        fileout.close();*/

                        logEntry("POST",site + server_url,200,uce.length);
                    }
                    else if(server_response.statusCode==302 || server_response.statusCode==307) {
                        System.out.println("Inside Redirection******************************");
                        String Host=server_response.mh.get("Location");
                        URL newurl=new URL(Host);
                        String actualhost=newurl.getHost();
                        Socket serversocket=new Socket(actualhost,80);
                        start=Host.indexOf("://")+3;
                        path=Host.indexOf('/',start);
                        String redirectURL=Host.substring(path);
                        String redirectreq=new String("GET"+" " +redirectURL+" " + "HTTP/1.0"+CRLF+CRLF);
                        InputStream re_in=serversocket.getInputStream();
                        OutputStream re_out=serversocket.getOutputStream();
                        writeString(re_out,redirectreq);
                        String raw_request1=getRawRequest(re_in);
                        HttpResponse re_response=new HttpResponse(raw_request1);
                        writeString(out,re_response.toString()); //out is proxy's outputstream
                        //now chk the status code and write to proxy's output.Just like above.
                        if(re_response.statusCode==200) {
                    //        System.out.println("Chking redirected request response code"+"*******************");
                            TempStore uce1=loadFile(re_in,Host,re_response.mh);
                            out.write(uce1.data,0,uce1.length);

                            logEntry("GET",Host,200,uce1.length);

                            /*byte filebuf[]=redirectreq.getBytes();
                            for( i=0;i<filebuf.length;i++)
                                fileout.write(filebuf[i]);

                            String token="!"+"\n"+"!";
                            byte tokenbytes[]=token.getBytes();
                            for(i=0;i<tokenbytes.length;i++)
                                fileout.write(tokenbytes[i]);

                            fileout.close();*/
                        }
                    }
                    else if (server_response.statusCode==304) {
                        System.out.println("*************304 status code************************");

                    }
                }
                else {
                    String req=methodSupported + " "  + server_url + " " +"HTTP/1.0" + CRLF + inmh + CRLF + CRLF;

                    System.out.print("\n Request string sent to server\n" + req );
                    byte filebuf2[]=req.getBytes();
                    for(int i=0;i<filebuf2.length;i++)
                        fileout.write(filebuf2[i]);

                    String newtoken="!"+"\n"+"!";
                    byte tokenbytes1[]=newtoken.getBytes();

                    for(int i=0;i<tokenbytes1.length;i++)
                        fileout.write(tokenbytes1[i]);

                    fileout.close();

                    writeString(server_out,req);
                    String raw_request=getRawRequest(server_in);
                    System.out.print("\n Server Response is " + raw_request + "\n");
                    HttpResponse server_response=new HttpResponse(raw_request);
                    writeString(out,server_response.toString());
                    //System.out.print("\n Server Response is " + server_response.statusCode + "\n");

                    if(server_response.statusCode==200) {
                        TempStore uce=loadFile(server_in,url,server_response.mh);
                        out.write(uce.data,0,uce.length);
                    }

                    if(server_response.statusCode==302 || server_response.statusCode==307) {
                        //System.out.println("******Inside Redirection*********");
                        String Host=server_response.mh.get("Location");
                        //System.out.println("New host is"+Host);

                        URL newurl=new URL(Host);
                        String actualhost=newurl.getHost();
                        Socket serversocket=new Socket(actualhost,80);
                        start=Host.indexOf("://")+3;
                        path=Host.indexOf('/',start);
                        String redirectURL=Host.substring(path);
                        //System.out.println("redirected URL is"+redirectURL);
                        String redirectreq="GET" + " " + redirectURL + " "  + "HTTP/1.0"+CRLF+CRLF;
                        //System.out.println("new GET request sent"+redirectreq);
                        InputStream re_in=serversocket.getInputStream();
                        OutputStream re_out=serversocket.getOutputStream();
                        writeString(re_out,redirectreq);
                        String raw_request1=getRawRequest(re_in);
                        HttpResponse re_response=new HttpResponse(raw_request1);
                        writeString(out,re_response.toString()); //out is proxy's outputstream
                        //now chk the status code and write to proxy's output.Just like above.
                        if(re_response.statusCode==200) {
                          //  System.out.println("Chking redirected request response code"+"*******************");
                            TempStore uce1=loadFile(re_in,Host,re_response.mh);
                            out.write(uce1.data,0,uce1.length);
                            //System.out.println("Proxy wrote");
                            //logEntry("GET",Host,200,uce1.length);
                            byte filebuf[]=redirectreq.getBytes();
                            for(int i=0;i<filebuf.length;i++)
                                fileout.write(filebuf[i]);

                            String token="!"+"\n"+"!";
                            byte tokenbytes[]=token.getBytes();
                            for(int i=0;i<tokenbytes.length;i++)
                                fileout.write(tokenbytes[i]);

                            fileout.close();
                        }
                    }
                    if(server_response.statusCode==304) {
                        System.out.println("*******************************304 status code****************************");
                    }
                }

                server_out.close();

            }
            catch(IOException e) {
                log.log("Exception" + e);
                e.printStackTrace();
            }
            catch(Exception e) {
                log.log("Exception"+e);
                e.printStackTrace();
            }
        }



        /**Called once per connection to the server.It parses the request String and incoming MIME header.
         *Calls handleProxy() if request is of type GET or POST.
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @param                s        Socket
        * @return                void
        * @throws                 IOException
        */
    private void doRequest(Socket s) throws IOException
        {
                if(stopFlag==true)
                        return;
                InputStream in=s.getInputStream();
                OutputStream out=s.getOutputStream();
                String request=getRawRequest(in);

                int fsp=request.indexOf(' ');
                int nsp=request.indexOf(' ',fsp+1);
                int eol=request.indexOf('\n');
                String method=request.substring(0,fsp);
                methodSupported=method.toUpperCase();
                String url=request.substring(fsp+1,nsp);
                String raw_mime_header=request.substring(eol+1);

                MimeHeader inmh=new MimeHeader(raw_mime_header);

                String str_length=inmh.get("Content-Length");
                if(str_length!=null)
                {
                      content_length = Integer.parseInt(str_length);
                }
                else
                {
                      content_length = 0;
                 }
                request=request.substring(0,eol);
                if(method.equalsIgnoreCase("get") || method.equalsIgnoreCase("post") || method.equalsIgnoreCase("head"))
                        handleProxy(out,url,inmh,in);
                else
                        writeString(out,"Method Not allowed");
                in.close();
                out.close();
        }

        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @return                void
        *
        */
        public void run()
        {
                try
                {
                ServerSocket acceptSocket;
                 acceptSocket=new ServerSocket(port);
                System.out.print("\nServer Socket created at " + port+ "\n");
                while(true)
                        {
                        Socket s=acceptSocket.accept();
                        doRequest(s);
                        s.close();
                        }
                }
                catch(IOException e)
                {
                log.log("accept loop IOException: " + e + "\n");
                }
                catch(Exception e)
                {
                log.log("Exception :" +e);
                }
        }


        private Thread t=null;


        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @return                void
        *
        */
        public synchronized void start()
        {
                stopFlag=false;
                if(t==null)
                {
                        t=new Thread(this);
                        t.start();
                }
        }


        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @return                void
        *
        */
        public synchronized void stop()
        {
                stopFlag=true;
                log.log("Stopped at" + new Date() + "\n");
        }



        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @return                void
        *
        */
        public httpd(int p, LogMessage lm)
        {
                port =p;
                log=lm;
        }



        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @return                void
        *
        */
        public static void main(String args[])
        {
                System.out.print(" Before Httpd object created");
                httpd h=new httpd(1235,null);
                h.log=h;
                h.start();
                try
        {

                        Thread.currentThread().join();
                }
                catch(InterruptedException e){};
        }



        /**
        *
        * @author       Deepa Singh(deepa.singh@sun.com)
        *
        * @return                void
        *
        */
        public void log(String m)
        {
                System.out.print(m);
        }

}
