/*
 * Copyright (c) 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);
        }

}
