/* Copyright (C) 2003 Gervase Gallant gervasegallant@yahoo.com
 *
 * This program is free software; you can use it, redistribute it
 * and / or modify it under the terms of the GNU General Public License
 * (GPL) as published by the Free Software Foundation; either version 2
 * of the License or (at your option) any later version.
 *
 * This program 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.
 * http://www.gnu.org/licenses/gpl.txt OR
 * Write to the Free Software Foundation Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
 * Created on Sept 15, 2002, 9:53 PM
 */
import java.net.*;
import java.io.*;
/**
 * Proxy server socket.
 * Creation date: (10/28/2001 9:41:46 AM)
 * @author: Gervase Gallant
 */
public class Proxy {
	/**
	 * Proxy constructor comment.
	 */
	public Proxy() {
		super();
	}
	/**
	 * Listen for incoming sockets.
	 * Creation date: (10/28/2001 9:42:46 AM)
	 */
	private void go(int listenPort, String server, int port) {
		ServerSocket serverSocket = null;
		Socket in = null;
		Socket out = null;

		try {
			serverSocket = new ServerSocket(listenPort);
		} catch (IOException ioe) {
			System.out.println("Error creating server Socket..." + ioe);
		}
		while (true) {
			try {
				System.out.println("Proxy listening on port " + listenPort);
				in = serverSocket.accept();
				System.out.println("Socket accepted: " + in);
				out = new Socket(server, port);
				System.out.println(this.send(in, server, port));
				out.close();
			} catch (IOException ioe) {
				System.out.println("IOException: " + ioe);
			}

		}
	}
	/**
	 * Starts the application.
	 * @param args an array of command-line arguments
	 */
	public static void main(java.lang.String[] args) {

		System.out.println(
			"Usage java Proxy <listenPort> <targetServer> <targetPort>");
		if ((args == null) || (args.length != 3)) {
			System.out.println("Incorrect arguments..." + args);
			System.exit(0);
		}

		new Proxy().go(
			Integer.parseInt(args[0]),
			args[1],
			Integer.parseInt(args[2]));

	}
	/**
	 * pass the contents of the "in" Socket, create a new
	 * Socket to the target Server, and return the data from the
	 * target to the "in" socket's outputstream.
	 * Creation date: (10/28/2001 9:31:30 AM)
	 */
	public String send(Socket in, String target, int port) throws IOException {
		byte[] bytes = new byte[1024];
		int numread = 0;
		BufferedInputStream bis = new BufferedInputStream(in.getInputStream());
		BufferedOutputStream bos =
			new BufferedOutputStream(in.getOutputStream());
		Socket targetSocket = new Socket(target, port);
		BufferedInputStream targetBis =
			new BufferedInputStream(targetSocket.getInputStream());
		BufferedOutputStream targetBos =
			new BufferedOutputStream(targetSocket.getOutputStream());
		StringBuffer sb = new StringBuffer();
		String temp;
		try {
			//send something to the target
			sb.append("SENT:\n");
			while ((numread = bis.read(bytes, 0, bytes.length)) != -1) {

				targetBos.write(bytes, 0, numread);
				//caputre the request
				temp = new String(bytes, 0, numread, "latin1");
				sb.append(temp);
				//since the browser socket remains open, you need some
				//means of preventing the blocking on the read();
				if (numread < bytes.length)
					break;

			}
			targetBos.flush();

			sb.append("\nRETURNED:\n");
			//wait and return any traffic from the target
			temp = "";
			while ((numread = targetBis.read(bytes, 0, bytes.length)) > -1) {
				bos.write(bytes, 0, numread);
				// clear comments to capture response
				//if (temp.equals("")){ //grab the header only!
				//temp = new String(bytes, 0, numread, "latin1");
				//sb.append(temp);
				//}

			}
			bos.flush();
			return sb.toString();
		} finally {

			try {
				bis.close();
			} catch (Exception e) {
			}
			try {
				bos.close();
			} catch (Exception e) {
			}
			try {
				targetBos.close();
			} catch (Exception e) {
			}
			try {
				targetBis.close();
			} catch (Exception e) {
			}
			try {
				targetSocket.close();
			} catch (Exception e) {
			}
		}
	}
}