blob: 54055bcce23bec47767f3fa83515659c3b241624 [file] [log] [blame]
/*
* 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);
}
}