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