format proxy code, allow to change swf on the fly

This commit is contained in:
honfika@gmail.com
2014-09-01 16:56:55 +02:00
parent 8325d07b24
commit ed53ba9d0f
37 changed files with 1847 additions and 2267 deletions

View File

@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.OutputStream;
public class ByteArray {
public byte[] bytes;
public int offset = 0;

View File

@@ -1,19 +1,21 @@
package com.jpexs.proxy;
import java.io.InputStream;
/**
* Interface to catch contentTypes
*
* @author JPEXS
*/
public interface CatchedListener {
/**
* Method called when specified contentType is received
*
* @param contentType Content type
* @param url URL of the method
* @param data Data stream
*/
public void catched(String contentType, String url, InputStream data);
}
package com.jpexs.proxy;
import java.io.InputStream;
/**
* Interface to catch contentTypes
*
* @author JPEXS
*/
public interface CatchedListener {
/**
* Method called when specified contentType is received
*
* @param contentType Content type
* @param url URL of the method
* @param data Data stream
* @return replacement data
*/
public byte[] catched(String contentType, String url, InputStream data);
}

View File

@@ -1,6 +1,6 @@
package com.jpexs.proxy;
public interface Cleanable
{
public interface Cleanable {
public void clean();
}

View File

@@ -3,40 +3,35 @@ package com.jpexs.proxy;
import java.io.*;
import java.net.Socket;
public class Client extends Connection
{
@Override
public void promoteToServerSSL() {
super.promoteToServerSSL();
in = new BufferedInputStream(in);
out = new BufferedOutputStream(out);
}
public class Client extends Connection {
@Override
public void promoteToServerSSL() {
super.promoteToServerSSL();
in = new BufferedInputStream(in);
out = new BufferedOutputStream(out);
}
/**
* Create a Client from a Socket.
*/
Client(Socket s) throws IOException
{
super(s);
in = new BufferedInputStream(in);
//out = new DebugOutputStream(new BufferedOutputStream(out));
out = new BufferedOutputStream(out);
Client(Socket s) throws IOException {
super(s);
in = new BufferedInputStream(in);
//out = new DebugOutputStream(new BufferedOutputStream(out));
out = new BufferedOutputStream(out);
}
/**
* Read a Request.
*
* @returns a Request.
* @see Request
*/
Request read() throws IOException
{
Request request = new Request(this);
request.read(getInputStream());
return request;
Request read() throws IOException {
Request request = new Request(this);
request.read(getInputStream());
return request;
}
/**
@@ -44,8 +39,7 @@ public class Client extends Connection
*
* @see Reply
*/
void write(Reply reply) throws IOException
{
reply.write(getOutputStream());
void write(Reply reply) throws IOException {
reply.write(getOutputStream());
}
}

View File

@@ -17,58 +17,58 @@ import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
class Connection
{
class Connection {
Socket socket = null;
InputStream in = null;
OutputStream out = null;
static SSLSocketFactory sf;
static{
String ksName = ProxyConfig.httpsKeyStoreFile;
if(ksName!=null){
static {
String ksName = ProxyConfig.httpsKeyStoreFile;
if (ksName != null) {
char[] ksPass = ProxyConfig.httpsKeyStorePass.toCharArray();
char[] ctPass = ProxyConfig.httpsKeyPass.toCharArray();
try{
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(ksName), ksPass);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ctPass);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
sf=sc.getSocketFactory();
}catch(Exception ex){
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(ksName), ksPass);
KeyManagerFactory kmf
= KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ctPass);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
sf = sc.getSocketFactory();
} catch (Exception ex) {
}
}
}
}
}
public void promoteToClientSSL(){
SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
try {
socket = (SSLSocket) f.createSocket(socket,null,socket.getPort(),false);
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException ex) {
public void promoteToClientSSL() {
SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
try {
socket = (SSLSocket) f.createSocket(socket, null, socket.getPort(), false);
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException ex) {
}
}
}
public void promoteToServerSSL(){
try{
socket=sf.createSocket(socket,null,socket.getPort(),false);
((SSLSocket)socket).setUseClientMode(false);
}catch(Exception ex){
ex.printStackTrace();
}
try {
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException ex) {
public void promoteToServerSSL() {
try {
socket = sf.createSocket(socket, null, socket.getPort(), false);
((SSLSocket) socket).setUseClientMode(false);
} catch (Exception ex) {
ex.printStackTrace();
}
try {
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException ex) {
}
}
}
@@ -77,11 +77,10 @@ class Connection
*
* @param socket a socket
*/
Connection(Socket socket) throws IOException
{
this.socket = socket;
in = socket.getInputStream();
out = socket.getOutputStream();
Connection(Socket socket) throws IOException {
this.socket = socket;
in = socket.getInputStream();
out = socket.getOutputStream();
}
/**
@@ -90,82 +89,66 @@ class Connection
* @param host remote hostname
* @param port remote port
*/
Connection(String host, int port) throws IOException
{
this(new Socket(InetAddress.getByName(host), port));
Connection(String host, int port) throws IOException {
this(new Socket(InetAddress.getByName(host), port));
}
Connection()
{
Connection() {
}
/**
* Return the input stream.
*/
InputStream getInputStream()
{
return in;
InputStream getInputStream() {
return in;
}
/**
* Return the output stream.
*/
OutputStream getOutputStream()
{
return out;
OutputStream getOutputStream() {
return out;
}
void setInputStream(InputStream in)
{
this.in = in;
void setInputStream(InputStream in) {
this.in = in;
}
void setOutputStream(OutputStream out)
{
this.out = out;
void setOutputStream(OutputStream out) {
this.out = out;
}
/**
* Close the connection.
*/
void close()
{
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
void close() {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
public Socket getSocket()
{
return socket;
public Socket getSocket() {
return socket;
}
public InetAddress getInetAddress()
{
return socket.getInetAddress();
}
public int getPort()
{
return socket.getPort();
public InetAddress getInetAddress() {
return socket.getInetAddress();
}
public String toString()
{
return getInetAddress().getHostAddress() + ":" + getPort();
public int getPort() {
return socket.getPort();
}
public String toString() {
return getInetAddress().getHostAddress() + ":" + getPort();
}
public void setTimeout(int timeout)
throws SocketException
{
socket.setSoTimeout(timeout);
throws SocketException {
socket.setSoTimeout(timeout);
}
}

View File

@@ -5,35 +5,29 @@ import java.io.OutputStream;
import java.io.IOException;
import java.net.SocketException;
class Copy implements Runnable
{
class Copy implements Runnable {
InputStream in = null;
OutputStream out = null;
Copy(InputStream in, OutputStream out)
{
this.in = in;
this.out = out;
Copy(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}
public void run()
{
int n;
byte[] buffer = new byte[8192];
public void run() {
int n;
byte[] buffer = new byte[8192];
try
{
while ((n = in.read(buffer, 0, buffer.length)) > 0)
{
out.write(buffer, 0, n);
out.flush();
}
out.flush();
}catch(SocketException e){
}
catch (IOException e)
{
//Ignore errors
}
try {
while ((n = in.read(buffer, 0, buffer.length)) > 0) {
out.write(buffer, 0, n);
out.flush();
}
out.flush();
} catch (SocketException e) {
} catch (IOException e) {
//Ignore errors
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,15 +6,13 @@ import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
class Http extends HttpConnection
{
class Http extends HttpConnection {
/* XXX - more than 1 should work now. */
static final int MAX_PENDING_REQUESTS = 1;
static Hashtable cache = new Hashtable(33);
private static Object httpLock = new Object();
String host;
int port;
@@ -24,334 +22,263 @@ class Http extends HttpConnection
long idle = 0;
Vector queue = new Vector();
public Http(String host, int port) throws IOException
{
this(host, port, false);
}
public Http(String host, int port, boolean isProxy) throws IOException
{
super(host, port);
this.host = host;
this.port = port;
this.proxy = isProxy;
public Http(String host, int port) throws IOException {
this(host, port, false);
}
public Http(String host, int port, boolean isProxy,Socket sock) throws IOException
{
super(sock);
this.host = host;
this.port = port;
this.proxy = isProxy;
public Http(String host, int port, boolean isProxy) throws IOException {
super(host, port);
this.host = host;
this.port = port;
this.proxy = isProxy;
}
public Http(String host, int port, boolean isProxy, Socket sock) throws IOException {
super(sock);
this.host = host;
this.port = port;
this.proxy = isProxy;
}
public synchronized void sendRequest(Request request)
throws IOException, RetryRequestException
{
queue.addElement(request);
try
{
send(request);
}
catch (IOException e)
{
if (persistent)
{
persistent = false;
throw new RetryRequestException();
}
throw e;
}
throws IOException, RetryRequestException {
queue.addElement(request);
try {
send(request);
} catch (IOException e) {
if (persistent) {
persistent = false;
throw new RetryRequestException();
}
throw e;
}
}
public synchronized Reply recvReply(Request request)
throws IOException, RetryRequestException
{
while (queue.firstElement() != request)
{
try
{
wait();
}
catch (InterruptedException e)
{
}
}
throws IOException, RetryRequestException {
while (queue.firstElement() != request) {
try {
wait();
} catch (InterruptedException e) {
}
}
if (closed)
{
throw new RetryRequestException();
}
if (closed) {
throw new RetryRequestException();
}
try
{
return recv();
}
catch (IOException e)
{
if (persistent)
{
persistent = false;
throw new RetryRequestException();
}
throw e;
}
try {
return recv();
} catch (IOException e) {
if (persistent) {
persistent = false;
throw new RetryRequestException();
}
throw e;
}
}
public void reallyClose()
{
persistent = false;
close();
public void reallyClose() {
persistent = false;
close();
}
public synchronized void close()
{
if (persistent)
{
idle = System.currentTimeMillis();
}
else
{
cacheRemove(host, port, this);
super.close();
closed = true;
}
public synchronized void close() {
if (persistent) {
idle = System.currentTimeMillis();
} else {
cacheRemove(host, port, this);
super.close();
closed = true;
}
if (queue.size() > 0)
{
queue.removeElementAt(0);
notify();
}
if (queue.size() > 0) {
queue.removeElementAt(0);
notify();
}
}
private void send(Request request) throws IOException
{
/* Prepare HTTP/1.1 request */
request.removeHeaderField("Proxy-Connection");
private void send(Request request) throws IOException {
if(!proxy){
if(request.containsHeaderField("Connection")&&(request.getHeaderField("Connection").toLowerCase().equals("keep-alive"))){
/* Prepare HTTP/1.1 request */
request.removeHeaderField("Proxy-Connection");
}else{
request.setHeaderField("Connection", "open");
}
if (!request.containsHeaderField("Host"))
{
request.setHeaderField("Host", request.getHost());
}
}
if (!proxy) {
if (request.containsHeaderField("Connection") && (request.getHeaderField("Connection").toLowerCase().equals("keep-alive"))) {
if (proxy)
{
request.write(getOutputStream());
}
else
{
String oldStatusLine = request.statusLine;
StringBuffer head = new StringBuffer();
head.append(request.getCommand());
head.append(" ");
head.append(request.getPath());
head.append(" ");
head.append("HTTP/1.0");
request.statusLine = head.toString();
} else {
request.setHeaderField("Connection", "open");
}
if (!request.containsHeaderField("Host")) {
request.setHeaderField("Host", request.getHost());
}
}
request.write(getOutputStream());
if (proxy) {
request.write(getOutputStream());
} else {
String oldStatusLine = request.statusLine;
StringBuffer head = new StringBuffer();
head.append(request.getCommand());
head.append(" ");
head.append(request.getPath());
head.append(" ");
head.append("HTTP/1.0");
request.statusLine = head.toString();
/* flush? */
request.statusLine = oldStatusLine;
}
request.write(getOutputStream());
/* flush? */
request.statusLine = oldStatusLine;
}
}
private Reply recv() throws IOException
{
Reply reply = new Reply(getInputStream());
reply.read();
private Reply recv() throws IOException {
Reply reply = new Reply(getInputStream());
reply.read();
String conn = reply.getHeaderField("Connection");
String conn = reply.getHeaderField("Connection");
if (reply.containsHeaderField("Connection")
&& reply.getHeaderField("Connection").equals("close"))
{
persistent = false;
}
else if (reply.getProtocol().equals("HTTP/1.1"))
{
persistent = true;
}
else
{
persistent = false;
}
if (reply.containsHeaderField("Connection")
&& reply.getHeaderField("Connection").equals("close")) {
persistent = false;
} else if (reply.getProtocol().equals("HTTP/1.1")) {
persistent = true;
} else {
persistent = false;
}
/* Received HTTP/1.1 "Continue". Read another Reply. */
if (reply.getStatusCode() == 100)
{
reply = recv();
}
/* Received HTTP/1.1 "Continue". Read another Reply. */
if (reply.getStatusCode() == 100) {
reply = recv();
}
return reply;
return reply;
}
protected boolean isBusy()
{
return queue.size() >= MAX_PENDING_REQUESTS;
protected boolean isBusy() {
return queue.size() >= MAX_PENDING_REQUESTS;
}
protected boolean isPersistent()
{
return persistent;
protected boolean isPersistent() {
return persistent;
}
private static String cacheKey(String host, int port)
{
return host.toLowerCase() + ":" + port;
private static String cacheKey(String host, int port) {
return host.toLowerCase() + ":" + port;
}
private static Vector cacheLookup(String host, int port)
{
Vector v = (Vector) cache.get(cacheKey(host, port));
return v;
private static Vector cacheLookup(String host, int port) {
Vector v = (Vector) cache.get(cacheKey(host, port));
return v;
}
private static boolean cacheContains(Http http)
{
Vector v = (Vector) cache.get(cacheKey(http.host, http.port));
return v != null ? v.contains(http) : false;
private static boolean cacheContains(Http http) {
Vector v = (Vector) cache.get(cacheKey(http.host, http.port));
return v != null ? v.contains(http) : false;
}
private static void cacheInsert(String host, int port, Http http)
{
String key = cacheKey(host, port);
Vector v = (Vector) cache.get(key);
if (v == null)
{
v = new Vector();
}
v.addElement(http);
cache.put(key, v);
private static void cacheInsert(String host, int port, Http http) {
String key = cacheKey(host, port);
Vector v = (Vector) cache.get(key);
if (v == null) {
v = new Vector();
}
v.addElement(http);
cache.put(key, v);
}
private static void cacheRemove(String host, int port, Http http)
{
Vector v = (Vector) cache.get(cacheKey(host, port));
if (v != null)
{
v.removeElement(http);
if (v.isEmpty())
{
cache.remove(cacheKey(host, port));
}
}
private static void cacheRemove(String host, int port, Http http) {
Vector v = (Vector) cache.get(cacheKey(host, port));
if (v != null) {
v.removeElement(http);
if (v.isEmpty()) {
cache.remove(cacheKey(host, port));
}
}
}
private static void cacheClean()
{
long now = System.currentTimeMillis();
Enumeration e = cache.keys();
while (e.hasMoreElements())
{
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++)
{
Http http = (Http) v.elementAt(i);
if (http.idle > 0 && now - http.idle > 30000) /* 30 seconds */
{
http.persistent = false;
http.close();
}
}
}
private static void cacheClean() {
long now = System.currentTimeMillis();
Enumeration e = cache.keys();
while (e.hasMoreElements()) {
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++) {
Http http = (Http) v.elementAt(i);
if (http.idle > 0 && now - http.idle > 30000) /* 30 seconds */ {
http.persistent = false;
http.close();
}
}
}
}
static Http open(String host, int port, boolean isProxy)
throws IOException
{
Http http = null;
throws IOException {
Http http = null;
synchronized (httpLock)
{
Vector v = cacheLookup(host, port);
if (v != null)
{
for (int i = 0; i < v.size(); i++)
{
Http pick = (Http) v.elementAt(i);
synchronized (httpLock) {
Vector v = cacheLookup(host, port);
if (v != null) {
for (int i = 0; i < v.size(); i++) {
Http pick = (Http) v.elementAt(i);
/* find an http connection that isn't busy */
if (pick.isPersistent() && !pick.isBusy())
{
http = pick;
break;
}
}
/* find an http connection that isn't busy */
if (pick.isPersistent() && !pick.isBusy()) {
http = pick;
break;
}
}
if (http != null)
{
http.idle = 0;
}
}
}
if (http == null)
{
http = new Http(host, port, isProxy);
cacheInsert(host, port, http);
}
return http;
if (http != null) {
http.idle = 0;
}
}
}
if (http == null) {
http = new Http(host, port, isProxy);
cacheInsert(host, port, http);
}
return http;
}
static Http open(String host, int port) throws IOException
{
return open(host, port, false);
static Http open(String host, int port) throws IOException {
return open(host, port, false);
}
static Enumeration enumerate()
{
Vector list = new Vector();
Enumeration e = cache.keys();
while (e.hasMoreElements())
{
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++)
{
list.addElement(v.elementAt(i));
}
}
return list.elements();
static Enumeration enumerate() {
Vector list = new Vector();
Enumeration e = cache.keys();
while (e.hasMoreElements()) {
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++) {
list.addElement(v.elementAt(i));
}
}
return list.elements();
}
static synchronized void clean()
{
cacheClean();
static synchronized void clean() {
cacheClean();
}
public String toString()
{
StringBuffer buf = new StringBuffer();
buf.append("SERVER ");
buf.append(super.toString());
if (isPersistent())
{
buf.append(" - ");
if (queue.size() > 0)
{
buf.append(queue.size());
buf.append(" pending");
}
else
{
buf.append("idle " + ((System.currentTimeMillis() - idle) / 1000.0) + " sec");
}
}
return buf.toString();
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("SERVER ");
buf.append(super.toString());
if (isPersistent()) {
buf.append(" - ");
if (queue.size() > 0) {
buf.append(queue.size());
buf.append(" pending");
} else {
buf.append("idle " + ((System.currentTimeMillis() - idle) / 1000.0) + " sec");
}
}
return buf.toString();
}
}

View File

@@ -5,54 +5,45 @@ import java.io.OutputStream;
import java.io.IOException;
import java.net.Socket;
abstract class HttpConnection extends Connection implements HttpRelay
{
HttpConnection(String host, int port) throws IOException
{
super(host, port);
abstract class HttpConnection extends Connection implements HttpRelay {
HttpConnection(String host, int port) throws IOException {
super(host, port);
}
HttpConnection(Socket s) throws IOException
{
super(s);
HttpConnection(Socket s) throws IOException {
super(s);
}
public void sendRequest(Request request)
throws IOException, RetryRequestException
{
request.write(getOutputStream());
throws IOException, RetryRequestException {
request.write(getOutputStream());
}
public Reply recvReply(Request request)
throws IOException, RetryRequestException
{
Reply reply = new Reply(getInputStream());
reply.read();
return reply;
}
public void setInputStream(InputStream in)
{
super.setInputStream(in);
}
public void setOutputStream(OutputStream out)
{
super.setOutputStream(out);
throws IOException, RetryRequestException {
Reply reply = new Reply(getInputStream());
reply.read();
return reply;
}
public InputStream getInputStream()
{
return super.getInputStream();
}
public OutputStream getOutputStream()
{
return super.getOutputStream();
public void setInputStream(InputStream in) {
super.setInputStream(in);
}
public void close()
{
super.close();
public void setOutputStream(OutputStream out) {
super.setOutputStream(out);
}
public InputStream getInputStream() {
return super.getInputStream();
}
public OutputStream getOutputStream() {
return super.getOutputStream();
}
public void close() {
super.close();
}
}

View File

@@ -1,70 +1,62 @@
package com.jpexs.proxy;
class HttpError
{
class HttpError {
StringBuffer content = null;
Reply reply = null;
HttpError(int code, String message)
{
String error;
switch (code)
{
case 400:
error = "Bad Request";
break;
case 403:
error = "Forbidden";
break;
HttpError(int code, String message) {
String error;
switch (code) {
case 400:
error = "Bad Request";
break;
case 404:
error = "Not found";
break;
case 403:
error = "Forbidden";
break;
case 503:
error = "Service Unavailable";
break;
case 404:
error = "Not found";
break;
default:
error = "Error";
break;
}
case 503:
error = "Service Unavailable";
break;
reply = new Reply();
reply.statusLine = "HTTP/1.0 " + code + " " + error;
reply.setHeaderField("Content-type", "text/html");
reply.setHeaderField("Server", ProxyConfig.appName+"/" +ProxyConfig.appVersion);
default:
error = "Error";
break;
}
content = new StringBuffer();
content.append(message);
reply = new Reply();
reply.statusLine = "HTTP/1.0 " + code + " " + error;
reply.setHeaderField("Content-type", "text/html");
reply.setHeaderField("Server", ProxyConfig.appName + "/" + ProxyConfig.appVersion);
content = new StringBuffer();
content.append(message);
}
Reply getReply()
{
return reply;
Reply getReply() {
return reply;
}
String getContent()
{
if (content == null)
{
return null;
}
return content.toString();
String getContent() {
if (content == null) {
return null;
}
return content.toString();
}
public String toString()
{
StringBuffer buf = new StringBuffer();
if (reply != null)
{
buf.append(reply.toString());
}
if (content != null)
{
buf.append(content.toString());
}
return buf.toString();
public String toString() {
StringBuffer buf = new StringBuffer();
if (reply != null) {
buf.append(reply.toString());
}
if (content != null) {
buf.append(content.toString());
}
return buf.toString();
}
}

View File

@@ -4,9 +4,11 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
public interface HttpRelay
{
public interface HttpRelay {
void sendRequest(Request request) throws IOException, RetryRequestException;
Reply recvReply(Request request) throws IOException, RetryRequestException;
void close();
}

View File

@@ -10,143 +10,118 @@ import java.util.Vector;
* @author JPEXS
*/
public class Https extends Http {
/* XXX - more than 1 should work now. */
/* XXX - more than 1 should work now. */
static final int MAX_PENDING_REQUESTS = 1;
static Hashtable cache = new Hashtable(33);
private static Object httpLock = new Object();
public Https(String host, int port) throws IOException
{
this(host, port, false);
public Https(String host, int port) throws IOException {
this(host, port, false);
}
public Https(String host, int port, boolean isProxy) throws IOException
{
super(host, port,isProxy);
public Https(String host, int port, boolean isProxy) throws IOException {
super(host, port, isProxy);
}
private static String cacheKey(String host, int port)
{
return host.toLowerCase() + ":" + port;
private static String cacheKey(String host, int port) {
return host.toLowerCase() + ":" + port;
}
private static Vector cacheLookup(String host, int port)
{
Vector v = (Vector) cache.get(cacheKey(host, port));
return v;
private static Vector cacheLookup(String host, int port) {
Vector v = (Vector) cache.get(cacheKey(host, port));
return v;
}
private static boolean cacheContains(Https http)
{
Vector v = (Vector) cache.get(cacheKey(http.host, http.port));
return v != null ? v.contains(http) : false;
private static boolean cacheContains(Https http) {
Vector v = (Vector) cache.get(cacheKey(http.host, http.port));
return v != null ? v.contains(http) : false;
}
private static void cacheInsert(String host, int port, Https http)
{
String key = cacheKey(host, port);
Vector v = (Vector) cache.get(key);
if (v == null)
{
v = new Vector();
}
v.addElement(http);
cache.put(key, v);
private static void cacheInsert(String host, int port, Https http) {
String key = cacheKey(host, port);
Vector v = (Vector) cache.get(key);
if (v == null) {
v = new Vector();
}
v.addElement(http);
cache.put(key, v);
}
private static void cacheRemove(String host, int port, Https http)
{
Vector v = (Vector) cache.get(cacheKey(host, port));
if (v != null)
{
v.removeElement(http);
if (v.isEmpty())
{
cache.remove(cacheKey(host, port));
}
}
private static void cacheRemove(String host, int port, Https http) {
Vector v = (Vector) cache.get(cacheKey(host, port));
if (v != null) {
v.removeElement(http);
if (v.isEmpty()) {
cache.remove(cacheKey(host, port));
}
}
}
private static void cacheClean()
{
long now = System.currentTimeMillis();
Enumeration e = cache.keys();
while (e.hasMoreElements())
{
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++)
{
Https http = (Https) v.elementAt(i);
if (http.idle > 0 && now - http.idle > 30000) /* 30 seconds */
{
http.persistent = false;
http.close();
}
}
}
private static void cacheClean() {
long now = System.currentTimeMillis();
Enumeration e = cache.keys();
while (e.hasMoreElements()) {
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++) {
Https http = (Https) v.elementAt(i);
if (http.idle > 0 && now - http.idle > 30000) /* 30 seconds */ {
http.persistent = false;
http.close();
}
}
}
}
static Https open(String host, int port, boolean isProxy)
throws IOException
{
Https http = null;
throws IOException {
Https http = null;
synchronized (httpLock)
{
Vector v = cacheLookup(host, port);
if (v != null)
{
for (int i = 0; i < v.size(); i++)
{
Https pick = (Https) v.elementAt(i);
synchronized (httpLock) {
Vector v = cacheLookup(host, port);
if (v != null) {
for (int i = 0; i < v.size(); i++) {
Https pick = (Https) v.elementAt(i);
/* find an http connection that isn't busy */
if (pick.isPersistent() && !pick.isBusy())
{
http = pick;
break;
}
}
/* find an http connection that isn't busy */
if (pick.isPersistent() && !pick.isBusy()) {
http = pick;
break;
}
}
if (http != null)
{
http.idle = 0;
}
}
}
if (http != null) {
http.idle = 0;
}
}
}
if (http == null)
{
http = new Https(host, port, isProxy);
cacheInsert(host, port, http);
}
if (http == null) {
http = new Https(host, port, isProxy);
cacheInsert(host, port, http);
}
return http;
return http;
}
static Https open(String host, int port) throws IOException
{
return open(host, port, false);
static Https open(String host, int port) throws IOException {
return open(host, port, false);
}
static Enumeration enumerate()
{
Vector list = new Vector();
Enumeration e = cache.keys();
while (e.hasMoreElements())
{
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++)
{
list.addElement(v.elementAt(i));
}
}
return list.elements();
static Enumeration enumerate() {
Vector list = new Vector();
Enumeration e = cache.keys();
while (e.hasMoreElements()) {
Vector v = (Vector) cache.get(e.nextElement());
for (int i = 0; i < v.size(); i++) {
list.addElement(v.elementAt(i));
}
}
return list.elements();
}
static synchronized void clean()
{
cacheClean();
static synchronized void clean() {
cacheClean();
}
}

View File

@@ -4,36 +4,36 @@ import java.io.IOException;
class HttpsThrough extends HttpConnection {
boolean proxy = false;
boolean proxy = false;
HttpsThrough(String host, int port) throws IOException {
super(host, port);
}
HttpsThrough(String host, int port) throws IOException {
super(host, port);
}
HttpsThrough(String host, int port, boolean isProxy) throws IOException {
this(host, port);
proxy = isProxy;
}
HttpsThrough(String host, int port, boolean isProxy) throws IOException {
this(host, port);
proxy = isProxy;
}
public void sendRequest(Request request)
throws IOException, RetryRequestException {
if (proxy) {
super.sendRequest(request);
} else {
/* nothing */
}
}
public void sendRequest(Request request)
throws IOException, RetryRequestException {
if (proxy) {
super.sendRequest(request);
} else {
/* nothing */
}
}
public Reply recvReply(Request request)
throws java.io.IOException, RetryRequestException {
Reply reply = new Reply(getInputStream());
if (proxy) {
reply.read();
} else {
reply.statusLine = "HTTP/1.0 200 Connection established";
reply.setHeaderField("Proxy-agent", ProxyConfig.appName);
}
public Reply recvReply(Request request)
throws java.io.IOException, RetryRequestException {
Reply reply = new Reply(getInputStream());
if (proxy) {
reply.read();
} else {
reply.statusLine = "HTTP/1.0 200 Connection established";
reply.setHeaderField("Proxy-agent", ProxyConfig.appName);
}
return reply;
}
return reply;
}
}

View File

@@ -3,39 +3,32 @@ package com.jpexs.proxy;
import java.util.Enumeration;
import java.util.Vector;
class Janitor implements Runnable
{
class Janitor implements Runnable {
private Vector cleanable = new Vector();
public void add(Cleanable c)
{
cleanable.addElement(c);
public void add(Cleanable c) {
cleanable.addElement(c);
}
public void run()
{
Thread.currentThread().setName("Janitor");
for (;;)
{
try
{
Thread.sleep(30 * 1000); /* 30 seconds */
}
catch (Exception e)
{
}
for (Enumeration e = cleanable.elements();
e.hasMoreElements(); )
{
((Cleanable)e.nextElement()).clean();
}
public void run() {
Thread.currentThread().setName("Janitor");
Http.clean();
for (;;) {
try {
Thread.sleep(30 * 1000); /* 30 seconds */
}
} catch (Exception e) {
}
for (Enumeration e = cleanable.elements();
e.hasMoreElements();) {
((Cleanable) e.nextElement()).clean();
}
Http.clean();
}
}
}

View File

@@ -1,6 +1,7 @@
package com.jpexs.proxy;
class Key {
private String name = null;
/**
@@ -31,4 +32,4 @@ class Key {
public String toString() {
return name;
}
}
}

View File

@@ -8,22 +8,22 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Main
{
public class Main {
public static final String REPLACEMENTSFILE = "." + File.separator + "config" + File.separator + "replacements.ini";
public static boolean DEBUG_MODE = false;
public static void main(String[] argv)
{
List<Replacement> replacements = new ArrayList<Replacement>();
public static void main(String[] argv) {
List<Replacement> replacements = new ArrayList<Replacement>();
if ((new File(REPLACEMENTSFILE)).exists()) {
try {
BufferedReader br = new BufferedReader(new FileReader(REPLACEMENTSFILE));
String s = "";
while ((s = br.readLine()) != null) {
String fileName = br.readLine();
if (fileName == null) break;
if (fileName == null) {
break;
}
fileName = fileName.replaceAll("[\\\\/]", File.separator);
Replacement r = new Replacement(s, fileName);
if (DEBUG_MODE) {
@@ -40,25 +40,26 @@ public class Main
System.out.println("WARNING:REPLACEMENTS FILE NOT FOUND.");
}
}
Server.startServer(ProxyConfig.port, replacements, new ArrayList<String>(), new CatchedListener() {
Server.startServer(ProxyConfig.port, replacements, new ArrayList<String>(), new CatchedListener() {
/**
* Method called when specified contentType is received
*
* @param contentType Content type
* @param url URL of the method
* @param data Data stream
* @param url URL of the method
* @param data Data stream
*/
public void catched(String contentType, String url, InputStream data) {
public byte[] catched(String contentType, String url, InputStream data) {
return null;
}
}, new ReplacedListener() {
}, new ReplacedListener() {
public void replaced(Replacement replacement, String url, String contentType) {
if (DEBUG_MODE) {
System.out.println("REPLACED:" + url + " (Content-type:" + contentType + ") WITH FILE " + replacement.targetFile);
}
if (DEBUG_MODE) {
System.out.println("REPLACED:" + url + " (Content-type:" + contentType + ") WITH FILE " + replacement.targetFile);
}
}
});
});
}
}

View File

@@ -5,8 +5,8 @@ import java.util.Enumeration;
import java.util.Vector;
import java.io.*;
public abstract class Message
{
public abstract class Message {
/**
* Hashtable used to store message headers.
*/
@@ -17,199 +17,155 @@ public abstract class Message
*/
String statusLine = null;
public String readLine(InputStream in) throws IOException
{
char[] buf = new char[128];
int offset = 0;
int ch;
public String readLine(InputStream in) throws IOException {
char[] buf = new char[128];
int offset = 0;
int ch;
for (;;)
{
ch = in.read();
if (ch == -1 || ch == '\n')
{
break;
}
else if (ch == '\r')
{
int tmpch = in.read();
if (tmpch != '\n')
{
if (! (in instanceof PushbackInputStream))
{
in = new PushbackInputStream(in);
}
((PushbackInputStream) in).unread(tmpch);
}
break;
}
else
{
if (offset == buf.length)
{
char[] tmpbuf = buf;
buf = new char[tmpbuf.length * 2];
System.arraycopy(tmpbuf, 0, buf, 0, offset);
}
buf[offset++] = (char) ch;
}
}
return String.copyValueOf(buf, 0, offset);
for (;;) {
ch = in.read();
if (ch == -1 || ch == '\n') {
break;
} else if (ch == '\r') {
int tmpch = in.read();
if (tmpch != '\n') {
if (!(in instanceof PushbackInputStream)) {
in = new PushbackInputStream(in);
}
((PushbackInputStream) in).unread(tmpch);
}
break;
} else {
if (offset == buf.length) {
char[] tmpbuf = buf;
buf = new char[tmpbuf.length * 2];
System.arraycopy(tmpbuf, 0, buf, 0, offset);
}
buf[offset++] = (char) ch;
}
}
return String.copyValueOf(buf, 0, offset);
}
/**
* Read headers and store them in the hashtable.
*/
void readHeaders(InputStream in) throws IOException
{
int i;
Key key = null;
for (;;)
{
String s = readLine(in);
if (s == null)
{
break;
}
i = s.indexOf(':');
if (i == -1)
{
/* end of header */
if (s.length() == 0)
{
break;
}
/* multi-line headers */
else if (key != null
&& (s.startsWith(" ") || s.startsWith("\t")))
{
int index = getHeaderValueCount(key.toString());
index--;
Vector v = (Vector) headers.get(key);
v.setElementAt(v.elementAt(index) + "\n" + s, index);
}
}
else
{
key = new Key(s.substring(0, i));
Vector v;
if (headers.containsKey(key))
{
v = (Vector) headers.get(key);
}
else
{
v = new Vector();
}
v.addElement(s.substring(i+1).trim());
headers.put(key, v);
}
}
void readHeaders(InputStream in) throws IOException {
int i;
Key key = null;
for (;;) {
String s = readLine(in);
if (s == null) {
break;
}
i = s.indexOf(':');
if (i == -1) {
/* end of header */
if (s.length() == 0) {
break;
} /* multi-line headers */ else if (key != null
&& (s.startsWith(" ") || s.startsWith("\t"))) {
int index = getHeaderValueCount(key.toString());
index--;
Vector v = (Vector) headers.get(key);
v.setElementAt(v.elementAt(index) + "\n" + s, index);
}
} else {
key = new Key(s.substring(0, i));
Vector v;
if (headers.containsKey(key)) {
v = (Vector) headers.get(key);
} else {
v = new Vector();
}
v.addElement(s.substring(i + 1).trim());
headers.put(key, v);
}
}
}
public int headerCount()
{
return headers.size();
public int headerCount() {
return headers.size();
}
/**
* Set the Status line.
*/
public void setStatusLine(String l)
{
public void setStatusLine(String l) {
statusLine = l;
}
public int getHeaderValueCount(String name)
{
Vector v = (Vector) headers.get(new Key(name));
return v.size();
}
public String getHeaderField(String name)
{
return getHeaderField(name, 0);
}
public String getHeaderField(String name, int index)
{
Vector v = (Vector) headers.get(new Key(name));
if (v == null)
{
return null;
}
return (String) v.elementAt(index);
public int getHeaderValueCount(String name) {
Vector v = (Vector) headers.get(new Key(name));
return v.size();
}
public void setHeaderField(String name, String value)
{
setHeaderField(name, value, 0);
public String getHeaderField(String name) {
return getHeaderField(name, 0);
}
public void setHeaderField(String name, String value, int index)
{
Vector v;
Key key = new Key(name);
if (headers.containsKey(key))
{
v = (Vector) headers.get(key);
}
else
{
v = new Vector();
if (index == 0)
{
v.addElement("");
}
headers.put(key, v);
}
v.setElementAt(value, index);
}
public void setHeaderField(String name, int value)
{
setHeaderField(name, value, 0);
public String getHeaderField(String name, int index) {
Vector v = (Vector) headers.get(new Key(name));
if (v == null) {
return null;
}
return (String) v.elementAt(index);
}
public void setHeaderField(String name, int value, int index)
{
setHeaderField(name, new Integer(value).toString(), index);
public void setHeaderField(String name, String value) {
setHeaderField(name, value, 0);
}
public void setHeaderField(String name, String value, int index) {
Vector v;
Key key = new Key(name);
if (headers.containsKey(key)) {
v = (Vector) headers.get(key);
} else {
v = new Vector();
if (index == 0) {
v.addElement("");
}
headers.put(key, v);
}
v.setElementAt(value, index);
}
public void setHeaderField(String name, int value) {
setHeaderField(name, value, 0);
}
public void setHeaderField(String name, int value, int index) {
setHeaderField(name, new Integer(value).toString(), index);
}
/**
* Set all header fields with the give name to the
* specified value.
* Set all header fields with the give name to the specified value.
*/
public void setHeaderFields(String name, String value)
{
Vector v;
Key key = new Key(name);
public void setHeaderFields(String name, String value) {
Vector v;
Key key = new Key(name);
v = (Vector) headers.get(key);
if (v != null)
{
for (int i = 0; i < v.size(); i++)
{
v.setElementAt(value, i);
}
}
v = (Vector) headers.get(key);
if (v != null) {
for (int i = 0; i < v.size(); i++) {
v.setElementAt(value, i);
}
}
}
public void appendHeaderField(String name, String value)
{
appendHeaderField(name, value, 0);
public void appendHeaderField(String name, String value) {
appendHeaderField(name, value, 0);
}
public void appendHeaderField(String name, String value, int index)
{
setHeaderField(name, getHeaderField(name, index) + value, index);
public void appendHeaderField(String name, String value, int index) {
setHeaderField(name, getHeaderField(name, index) + value, index);
}
public void removeHeaderField(String name)
{
headers.remove(new Key(name));
public void removeHeaderField(String name) {
headers.remove(new Key(name));
}
/**
@@ -217,81 +173,70 @@ public abstract class Message
*
* @param name header name
*/
public boolean containsHeaderField(String name)
{
return headers.containsKey(new Key(name));
public boolean containsHeaderField(String name) {
return headers.containsKey(new Key(name));
}
/**
* @return an Enumeration of Strings
*/
public Enumeration getHeaders()
{
Vector v = new Vector();
public Enumeration getHeaders() {
Vector v = new Vector();
for (Enumeration e = headers.keys(); e.hasMoreElements(); )
{
v.addElement(e.nextElement().toString());
}
for (Enumeration e = headers.keys(); e.hasMoreElements();) {
v.addElement(e.nextElement().toString());
}
return v.elements();
return v.elements();
}
private final static byte[] COLON_SPACE = ": ".getBytes();
private final static byte[] CRLF = "\r\n".getBytes();
private ByteArray toByteArray(byte[] sep)
{
ByteArray buf = new ByteArray();
Key key;
String value;
Vector v;
int i = 0;
buf.append(statusLine);
buf.append(sep);
for (Enumeration e = headers.keys(); e.hasMoreElements(); )
{
key = (Key) e.nextElement();
v = (Vector) headers.get(key);
for (i = 0; i < v.size(); i++)
{
buf.append(key.toString());
buf.append(COLON_SPACE);
buf.append(v.elementAt(i).toString());
buf.append(sep);
}
}
buf.append(sep);
return buf;
private ByteArray toByteArray(byte[] sep) {
ByteArray buf = new ByteArray();
Key key;
String value;
Vector v;
int i = 0;
buf.append(statusLine);
buf.append(sep);
for (Enumeration e = headers.keys(); e.hasMoreElements();) {
key = (Key) e.nextElement();
v = (Vector) headers.get(key);
for (i = 0; i < v.size(); i++) {
buf.append(key.toString());
buf.append(COLON_SPACE);
buf.append(v.elementAt(i).toString());
buf.append(sep);
}
}
buf.append(sep);
return buf;
}
private ByteArray toByteArray()
{
return toByteArray(CRLF);
private ByteArray toByteArray() {
return toByteArray(CRLF);
}
private ByteArray toByteArray(String sep)
{
return toByteArray(sep.getBytes());
private ByteArray toByteArray(String sep) {
return toByteArray(sep.getBytes());
}
public String toString()
{
return toByteArray().toString();
public String toString() {
return toByteArray().toString();
}
public String toString(String sep)
{
return toByteArray(sep).toString();
public String toString(String sep) {
return toByteArray(sep).toString();
}
public void write(OutputStream out)
throws IOException
{
toByteArray().writeTo(out);
out.flush();
throws IOException {
toByteArray().writeTo(out);
out.flush();
}
}

View File

@@ -9,35 +9,35 @@ import java.util.List;
*/
public class ProxyConfig {
public static boolean dontLogFilters=false;
public static boolean dontLogFilters = false;
public static String appVersion="1.1";
public static String appName="JPProxy";
public static int port=55555;
public static String bindAddress;
public static String appVersion = "1.1";
public static String appName = "JPProxy";
public static int port = 55555;
public static String bindAddress;
public static int readTimeout=50000;
public static boolean proxyKeepAlive=false;
public static boolean dontUncompress=false;
public static int readTimeout = 50000;
public static boolean proxyKeepAlive = false;
public static boolean dontUncompress = false;
public static final int HTTPS_PASSTHRU=0;
public static final int HTTPS_FILTER=1;
public static final int HTTPS_FILTERLIST=2;
public static final int HTTPS_PASSTHRU = 0;
public static final int HTTPS_FILTER = 1;
public static final int HTTPS_FILTERLIST = 2;
public static int httpsMode=HTTPS_PASSTHRU;
public static int httpsMode = HTTPS_PASSTHRU;
public static List<String> enabledHttpsServers=new ArrayList<String>();
public static List<String> enabledHttpsServers = new ArrayList<String>();
public static boolean useHTTPSProxy=false;
public static String httpsProxyHost="";
public static int httpsProxyPort=0;
public static boolean useHTTPSProxy = false;
public static String httpsProxyHost = "";
public static int httpsProxyPort = 0;
public static boolean useHTTPProxy=false;
public static String httpProxyHost="";
public static int httpProxyPort=0;
public static boolean useHTTPProxy = false;
public static String httpProxyHost = "";
public static int httpProxyPort = 0;
public static String httpsKeyStoreFile=null;
public static String httpsKeyStorePass=null;
public static String httpsKeyPass=null;
public static String httpsKeyStoreFile = null;
public static String httpsKeyStorePass = null;
public static String httpsKeyPass = null;
}

View File

@@ -1,5 +1,6 @@
package com.jpexs.proxy;
public interface ReplacedListener {
public void replaced(Replacement replacement, String url, String contentType);
}
package com.jpexs.proxy;
public interface ReplacedListener {
public void replaced(Replacement replacement, String url, String contentType);
}

View File

@@ -8,238 +8,195 @@ import java.io.SequenceInputStream;
import java.util.Hashtable;
import java.util.StringTokenizer;
public class Reply extends Message
{
public class Reply extends Message {
InputStream in = null;
int statusCode = -1;
public Reply()
{
public Reply() {
}
public Reply(InputStream in)
{
setContent(in);
public Reply(InputStream in) {
setContent(in);
}
public void setContent(InputStream in)
{
this.in = in;
public void setContent(InputStream in) {
this.in = in;
}
public InputStream getContent()
{
return in;
}
void read() throws IOException
{
if (in != null)
{
read(in);
}
}
void read(InputStream in) throws IOException
{
statusLine = readLine(in);
if (statusLine == null || statusLine.length() == 0)
{
throw new IOException("Missing HTTP status line");
}
/* Look for HTTP/0.9 */
if (!statusLine.startsWith("HTTP"))
{
/* Put back the line */
if (this.in != null)
{
String putback = new String(statusLine + "\n");
this.in = new SequenceInputStream(new StringBufferInputStream(putback), in);
}
/* Fake a status line and upgrade to HTTP/1.0 */
statusLine = "HTTP/1.0 200 OK";
return;
}
readHeaders(in);
int code = getStatusCode();
/* RFC 2068: 204 and 304 MUST NOT contain a message body. */
switch (code)
{
case 204: /* No Content */
case 304: /* Not Modified */
/* Ignore the message body if it exists */
if (containsHeaderField("Content-length"))
{
int contentLength = 0;
try
{
contentLength = Integer.parseInt(getHeaderField("Content-length"));
}
catch (NumberFormatException e)
{
}
int n;
byte[] buffer = new byte[8192];
while ((n = in.read(buffer, 0, buffer.length)) > 0)
{
/* ignore */
}
removeHeaderField("Content-length");
}
break;
}
public InputStream getContent() {
return in;
}
public boolean hasContent()
{
switch (getStatusCode())
{
case 204:
case 304:
return false;
default:
return true;
}
void read() throws IOException {
if (in != null) {
read(in);
}
}
public String getProtocol()
{
StringTokenizer st = new StringTokenizer(statusLine);
String protocol = (String) st.nextToken();
return protocol;
void read(InputStream in) throws IOException {
statusLine = readLine(in);
if (statusLine == null || statusLine.length() == 0) {
throw new IOException("Missing HTTP status line");
}
/* Look for HTTP/0.9 */
if (!statusLine.startsWith("HTTP")) {
/* Put back the line */
if (this.in != null) {
String putback = new String(statusLine + "\n");
this.in = new SequenceInputStream(new StringBufferInputStream(putback), in);
}
/* Fake a status line and upgrade to HTTP/1.0 */
statusLine = "HTTP/1.0 200 OK";
return;
}
readHeaders(in);
int code = getStatusCode();
/* RFC 2068: 204 and 304 MUST NOT contain a message body. */
switch (code) {
case 204: /* No Content */
case 304: /* Not Modified */
/* Ignore the message body if it exists */
if (containsHeaderField("Content-length")) {
int contentLength = 0;
try {
contentLength = Integer.parseInt(getHeaderField("Content-length"));
} catch (NumberFormatException e) {
}
int n;
byte[] buffer = new byte[8192];
while ((n = in.read(buffer, 0, buffer.length)) > 0) {
/* ignore */
}
removeHeaderField("Content-length");
}
break;
}
}
public int getStatusCode()
{
if (statusCode == -1)
{
StringTokenizer st = new StringTokenizer(statusLine);
String protocol = (String) st.nextToken();
String status = (String) st.nextToken();
public boolean hasContent() {
switch (getStatusCode()) {
case 204:
case 304:
return false;
try
{
statusCode = Integer.parseInt(status);
}
catch (NumberFormatException e)
{
System.out.println("Malformed or missing status code");
statusCode = 0;
}
}
return statusCode;
default:
return true;
}
}
private Hashtable headerParser(String header)
{
Hashtable table = new Hashtable();
String type = getHeaderField(header);
if (type == null)
{
return table;
}
StringTokenizer st = new StringTokenizer(type, ";");
int count = 0;
while (st.hasMoreTokens())
{
String token = st.nextToken();
token = token.trim();
String name;
String value;
int i = token.indexOf('=');
if (i != -1)
{
name = token.substring(0, i);
value = token.substring(i+1);
}
else
{
name = token;
value = "";
}
if (count == 0)
{
table.put(header, name);
}
else
{
table.put(name, value);
}
count++;
}
return table;
public String getProtocol() {
StringTokenizer st = new StringTokenizer(statusLine);
String protocol = (String) st.nextToken();
return protocol;
}
public String getContentType()
{
Hashtable table = headerParser("Content-type");
return(String) table.get("Content-type");
public int getStatusCode() {
if (statusCode == -1) {
StringTokenizer st = new StringTokenizer(statusLine);
String protocol = (String) st.nextToken();
String status = (String) st.nextToken();
try {
statusCode = Integer.parseInt(status);
} catch (NumberFormatException e) {
System.out.println("Malformed or missing status code");
statusCode = 0;
}
}
return statusCode;
}
public String getBoundary()
{
Hashtable table = headerParser("Content-type");
return(String) table.get("boundary");
private Hashtable headerParser(String header) {
Hashtable table = new Hashtable();
String type = getHeaderField(header);
if (type == null) {
return table;
}
StringTokenizer st = new StringTokenizer(type, ";");
int count = 0;
while (st.hasMoreTokens()) {
String token = st.nextToken();
token = token.trim();
String name;
String value;
int i = token.indexOf('=');
if (i != -1) {
name = token.substring(0, i);
value = token.substring(i + 1);
} else {
name = token;
value = "";
}
if (count == 0) {
table.put(header, name);
} else {
table.put(name, value);
}
count++;
}
return table;
}
public String getTransferEncoding()
{
Hashtable table = headerParser("Transfer-Encoding");
return(String) table.get("Transfer-Encoding");
public String getContentType() {
Hashtable table = headerParser("Content-type");
return (String) table.get("Content-type");
}
public int getChunkSize(InputStream in) throws IOException
{
String line = readLine(in);
line = line.trim(); /* apache can have trailing spaces */
int size = -1;
try
{
size = Integer.valueOf(line, 16).intValue();
}
catch (NumberFormatException e)
{
System.out.println(e);
}
return size;
public String getBoundary() {
Hashtable table = headerParser("Content-type");
return (String) table.get("boundary");
}
public void getChunkedFooter(InputStream in) throws IOException
{
for (;;)
{
String line = readLine(in);
if (line == null)
{
break;
}
int i = line.indexOf(':');
if (i == -1)
{
break;
}
}
public String getTransferEncoding() {
Hashtable table = headerParser("Transfer-Encoding");
return (String) table.get("Transfer-Encoding");
}
public void setStatusLine(String line)
{
this.statusLine = line;
public int getChunkSize(InputStream in) throws IOException {
String line = readLine(in);
line = line.trim(); /* apache can have trailing spaces */
int size = -1;
try {
size = Integer.valueOf(line, 16).intValue();
} catch (NumberFormatException e) {
System.out.println(e);
}
return size;
}
public static Reply createRedirect(String url)
{
Reply r = new Reply();
r.setStatusLine("HTTP/1.0 302 Moved Temporarily");
r.setHeaderField("Location", url);
return r;
public void getChunkedFooter(InputStream in) throws IOException {
for (;;) {
String line = readLine(in);
if (line == null) {
break;
}
int i = line.indexOf(':');
if (i == -1) {
break;
}
}
}
public void setStatusLine(String line) {
this.statusLine = line;
}
public static Reply createRedirect(String url) {
Reply r = new Reply();
r.setStatusLine("HTTP/1.0 302 Moved Temporarily");
r.setHeaderField("Location", url);
return r;
}
}

View File

@@ -8,9 +8,8 @@ import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
public class Request extends Message
{
public class Request extends Message {
private String command = null;
private String url = null;
private String protocol = null;
@@ -18,264 +17,207 @@ public class Request extends Message
private Client client = null;
private Hashtable log;
private Vector logHeaders;
public boolean hadKeepalive=false;
public boolean hadKeepalive = false;
Request(Client c)
{
client = c;
Request(Client c) {
client = c;
}
void read(InputStream in) throws IOException
{
statusLine = readLine(in);
if (statusLine == null || statusLine.length() == 0)
{
throw new IOException("Empty request");
}
void read(InputStream in) throws IOException {
statusLine = readLine(in);
if (statusLine == null || statusLine.length() == 0) {
throw new IOException("Empty request");
}
StringTokenizer st = new StringTokenizer(statusLine);
command = (String) st.nextToken();
url = (String) st.nextToken();
protocol = (String) st.nextToken();
StringTokenizer st = new StringTokenizer(statusLine);
command = (String) st.nextToken();
url = (String) st.nextToken();
protocol = (String) st.nextToken();
if (!url.startsWith("http"))
{
//TODO do something here
}
if (!url.startsWith("http")) {
//TODO do something here
}
readHeaders(in);
readHeaders(in);
if ("POST".equals(command) || "PUT".equals(command))
{
try
{
int n = Integer.parseInt(getHeaderField("Content-length"));
data = new byte[n];
int offset = 0;
while (offset < data.length)
{
n = in.read(data, offset, data.length - offset);
if (n < 0)
{
throw new IOException("Not enough " + command + " data");
}
offset += n;
}
}
catch (NumberFormatException e)
{
}
}
if ("POST".equals(command) || "PUT".equals(command)) {
try {
int n = Integer.parseInt(getHeaderField("Content-length"));
data = new byte[n];
int offset = 0;
while (offset < data.length) {
n = in.read(data, offset, data.length - offset);
if (n < 0) {
throw new IOException("Not enough " + command + " data");
}
offset += n;
}
} catch (NumberFormatException e) {
}
}
}
public void write(OutputStream out)
throws IOException
{
super.write(out);
if (data != null)
{
out.write(data);
out.flush();
}
throws IOException {
super.write(out);
if (data != null) {
out.write(data);
out.flush();
}
}
public String getRequest()
{
return statusLine;
public String getRequest() {
return statusLine;
}
public String getCommand()
{
return command;
}
public void setCommand(String command)
{
this.command = command;
public String getCommand() {
return command;
}
public String getURL()
{
return url;
public void setCommand(String command) {
this.command = command;
}
public void setURL(String url)
{
this.url = url;
public String getURL() {
return url;
}
public String getProtocol()
{
return protocol;
public void setURL(String url) {
this.url = url;
}
public void setProtocol(String protocol)
{
this.protocol = protocol;
public String getProtocol() {
return protocol;
}
public void addSecureHostToURL(String host){
url="https://"+host+url;
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getHost()
{
String url = getURL();
String s;
if (url.startsWith("http://"))
{
s = url.substring(7, url.indexOf('/', 7));
}
else if (url.startsWith("https://"))
{
s = url.substring(8, url.indexOf('/', 8));
}
else
{
s = url;
}
int at = s.indexOf('@');
if (at != -1 )
{
s = s.substring(at+1);
}
if (s.indexOf(':') != -1)
{
return s.substring(0, s.indexOf(':'));
}
return s;
public void addSecureHostToURL(String host) {
url = "https://" + host + url;
}
public int getPort()
{
int port = 80;
String url = getURL();
String s;
public String getHost() {
String url = getURL();
String s;
if (url.startsWith("http://"))
{
s = url.substring(7, url.indexOf('/', 7));
}
else if (url.startsWith("https://"))
{
s = url.substring(8, url.indexOf('/', 8));
port=443;
}
else
{
s = url;
}
if (url.startsWith("http://")) {
s = url.substring(7, url.indexOf('/', 7));
} else if (url.startsWith("https://")) {
s = url.substring(8, url.indexOf('/', 8));
} else {
s = url;
}
int at = s.indexOf('@');
if (at != -1 )
{
s = s.substring(at+1);
}
int at = s.indexOf('@');
if (at != -1) {
s = s.substring(at + 1);
}
if (s.indexOf(':') != -1)
{
try
{
port = Integer.parseInt(s.substring(s.indexOf(':') + 1));
}
catch (NumberFormatException e)
{
}
}
return port;
if (s.indexOf(':') != -1) {
return s.substring(0, s.indexOf(':'));
}
return s;
}
public String getData()
{
if (data == null)
{
return null;
}
return new String(data);
public int getPort() {
int port = 80;
String url = getURL();
String s;
if (url.startsWith("http://")) {
s = url.substring(7, url.indexOf('/', 7));
} else if (url.startsWith("https://")) {
s = url.substring(8, url.indexOf('/', 8));
port = 443;
} else {
s = url;
}
int at = s.indexOf('@');
if (at != -1) {
s = s.substring(at + 1);
}
if (s.indexOf(':') != -1) {
try {
port = Integer.parseInt(s.substring(s.indexOf(':') + 1));
} catch (NumberFormatException e) {
}
}
return port;
}
public String getPath()
{
String str = getURL();
int pos = 0;
for (int i = 0; i < 3; i++)
{
pos = str.indexOf('/', pos);
pos++;
}
pos--;
return str.substring(pos);
}
public String getDocument()
{
String path = getPath();
int n = path.lastIndexOf('/');
if (n == path.length() - 1)
{
n = path.lastIndexOf('/', n - 1);
}
if (n < 0)
{
return "/";
}
else
{
return path.substring(n + 1);
}
public String getData() {
if (data == null) {
return null;
}
return new String(data);
}
public Client getClient()
{
return client;
public String getPath() {
String str = getURL();
int pos = 0;
for (int i = 0; i < 3; i++) {
pos = str.indexOf('/', pos);
pos++;
}
pos--;
return str.substring(pos);
}
public String getQueryString()
{
String path = getPath();
int n = path.indexOf('?');
if (n < 0)
{
return null;
}
return path.substring(n + 1);
public String getDocument() {
String path = getPath();
int n = path.lastIndexOf('/');
if (n == path.length() - 1) {
n = path.lastIndexOf('/', n - 1);
}
if (n < 0) {
return "/";
} else {
return path.substring(n + 1);
}
}
public Client getClient() {
return client;
}
public String getQueryString() {
String path = getPath();
int n = path.indexOf('?');
if (n < 0) {
return null;
}
return path.substring(n + 1);
}
public synchronized void addLogEntry(String header,
String message)
{
if (log == null)
{
log = new Hashtable();
logHeaders = new Vector();
}
String message) {
if (log == null) {
log = new Hashtable();
logHeaders = new Vector();
}
Vector v = (Vector)log.get(header);
if (log.get(header) == null)
{
v = new Vector();
log.put(header, v);
logHeaders.addElement(header);
}
v.addElement(message);
Vector v = (Vector) log.get(header);
if (log.get(header) == null) {
v = new Vector();
log.put(header, v);
logHeaders.addElement(header);
}
v.addElement(message);
}
public Enumeration getLogHeaders()
{
return logHeaders != null ? logHeaders.elements() : null;
public Enumeration getLogHeaders() {
return logHeaders != null ? logHeaders.elements() : null;
}
public Enumeration getLogEntries(String header)
{
return log != null ? ((Vector)log.get(header)).elements() : null;
public Enumeration getLogEntries(String header) {
return log != null ? ((Vector) log.get(header)).elements() : null;
}
}

View File

@@ -1,14 +1,12 @@
package com.jpexs.proxy;
class RetryRequestException extends Exception
{
RetryRequestException()
{
super();
class RetryRequestException extends Exception {
RetryRequestException() {
super();
}
RetryRequestException(String message)
{
super(message);
RetryRequestException(String message) {
super(message);
}
}

View File

@@ -1,70 +1,57 @@
package com.jpexs.proxy;
public class ReusableThread extends Thread
{
public class ReusableThread extends Thread {
private ThreadPool pool = null;
private Runnable runnable = null;
private boolean alive = true;
private long lastrun = 0;
private int used = 0;
public ReusableThread(ThreadPool pool)
{
this.pool = pool;
public ReusableThread(ThreadPool pool) {
this.pool = pool;
}
public synchronized void setRunnable(Runnable runnable)
{
this.runnable = runnable;
notify();
public synchronized void setRunnable(Runnable runnable) {
this.runnable = runnable;
notify();
}
public synchronized void terminate()
{
alive = false;
notify();
public synchronized void terminate() {
alive = false;
notify();
}
public long getLastRunTime()
{
return lastrun;
public long getLastRunTime() {
return lastrun;
}
public int useCount()
{
return used;
public int useCount() {
return used;
}
public void run()
{
while (alive)
{
setName("ReusableThread: idle");
while (runnable == null && alive)
{
synchronized (this)
{
try
{
wait();
}
catch (InterruptedException ie)
{
}
}
}
if (alive)
{
setName("ReusableThread: busy");
setPriority(Thread.NORM_PRIORITY);
lastrun = System.currentTimeMillis();
used++;
runnable.run();
runnable = null;
pool.put(this);
}
}
public void run() {
while (alive) {
setName("ReusableThread: idle");
while (runnable == null && alive) {
synchronized (this) {
try {
wait();
} catch (InterruptedException ie) {
}
}
}
if (alive) {
setName("ReusableThread: busy");
setPriority(Thread.NORM_PRIORITY);
lastrun = System.currentTimeMillis();
used++;
runnable.run();
runnable = null;
pool.put(this);
}
}
}
}

View File

@@ -7,8 +7,8 @@ import java.io.IOException;
import java.io.DataOutputStream;
import java.util.List;
public class Server implements Runnable
{
public class Server implements Runnable {
ServerSocket server = null;
boolean running = false;
@@ -17,145 +17,121 @@ public class Server implements Runnable
private ReplacedListener replacedListener;
private List<Replacement> replacements;
static ThreadPool pool;
static ThreadPool pool;
static Server myServer;
static boolean serverRunning=false;
static boolean serverRunning = false;
static boolean stopping=false;
static boolean stopping = false;
public static ReusableThread getThread()
{
return pool.get();
public static ReusableThread getThread() {
return pool.get();
}
/**
* Starts proxy server
*
* @param port Listening port
* @param replacements List of replacements
* @param port Listening port
* @param replacements List of replacements
* @param catchedContentTypes Content types to sniff
* @param catchedListener Catched listener
* @param catchedListener Catched listener
*/
public static boolean startServer(int port, List<Replacement> replacements, List<String> catchedContentTypes, CatchedListener catchedListener, ReplacedListener replacedListener) {
stopServer();
try {
myServer = new Server(port, replacements, catchedContentTypes, catchedListener, replacedListener);
} catch (IOException ex) {
return false;
}
pool = new ThreadPool(ProxyConfig.appName+" Threads");
try {
myServer = new Server(port, replacements, catchedContentTypes, catchedListener, replacedListener);
} catch (IOException ex) {
return false;
}
pool = new ThreadPool(ProxyConfig.appName + " Threads");
/* Startup the Janitor */
Janitor j = new Janitor();
j.add(pool);
getThread().setRunnable(j);
serverRunning=true;
getThread().setRunnable(myServer);
return true;
Janitor j = new Janitor();
j.add(pool);
getThread().setRunnable(j);
serverRunning = true;
getThread().setRunnable(myServer);
return true;
}
public static void stopServer() {
if (serverRunning) {
serverRunning = false;
try {
myServer.server.close();
} catch (IOException ex) {
public static void stopServer()
{
if(serverRunning){
serverRunning=false;
try {
myServer.server.close();
} catch (IOException ex) {
}
pool.clean();
}
}
pool.clean();
}
}
Server(int port,List<Replacement> replacements, List<String> catchedContentTypes, CatchedListener catchedListener, ReplacedListener replacedListener) throws IOException
{
this.replacements = replacements;
this.catchedContentTypes = catchedContentTypes;
Server(int port, List<Replacement> replacements, List<String> catchedContentTypes, CatchedListener catchedListener, ReplacedListener replacedListener) throws IOException {
this.replacements = replacements;
this.catchedContentTypes = catchedContentTypes;
this.catchedListener = catchedListener;
this.replacedListener = replacedListener;
try
{
String bindaddr = ProxyConfig.bindAddress;
if (bindaddr != null && bindaddr.length() > 0)
{
server = new ServerSocket(port, 512,
InetAddress.getByName(bindaddr));
}
else
{
server = new ServerSocket(port, 512);
}
}
catch (IOException e)
{
throw e;
}
/* Initialize internal Httpd */
try {
String bindaddr = ProxyConfig.bindAddress;
if (bindaddr != null && bindaddr.length() > 0) {
server = new ServerSocket(port, 512,
InetAddress.getByName(bindaddr));
} else {
server = new ServerSocket(port, 512);
}
} catch (IOException e) {
throw e;
}
/* Initialize internal Httpd */
}
synchronized void suspend()
{
running = false;
synchronized void suspend() {
running = false;
}
synchronized void resume()
{
running = true;
synchronized void resume() {
running = true;
}
public void run() {
Thread.currentThread().setName(ProxyConfig.appName + " Server");
running = true;
for (;;) {
Socket socket;
public void run()
{
Thread.currentThread().setName(ProxyConfig.appName+" Server");
running = true;
for (;;)
{
Socket socket;
try {
socket = server.accept();
} catch (IOException e) {
if (stopping) {
break;
}
continue;
}
try
{
socket = server.accept();
}
catch (IOException e)
{
if(stopping){
break;
}
continue;
}
if (stopping) {
break;
}
if(stopping){
break;
}
if (running)
{
Handler h = new Handler(socket,replacements,catchedContentTypes,catchedListener,replacedListener);
ReusableThread rt = getThread();
rt.setRunnable(h);
}
else
{
error(socket, 503, ProxyConfig.appName+" proxy service is suspended.");
}
}
if (running) {
Handler h = new Handler(socket, replacements, catchedContentTypes, catchedListener, replacedListener);
ReusableThread rt = getThread();
rt.setRunnable(h);
} else {
error(socket, 503, ProxyConfig.appName + " proxy service is suspended.");
}
}
}
void error(Socket socket, int code, String message)
{
try
{
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeBytes((new HttpError(code, message)).toString());
out.close();
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
void error(Socket socket, int code, String message) {
try {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeBytes((new HttpError(code, message)).toString());
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -2,52 +2,44 @@ package com.jpexs.proxy;
import java.util.*;
public class ThreadPool implements Cleanable
{
public class ThreadPool implements Cleanable {
private String name;
private Vector pool = new Vector();
public ThreadPool(String name)
{
this.name = name;
public ThreadPool(String name) {
this.name = name;
}
public synchronized ReusableThread get()
{
ReusableThread rt = null;
public synchronized ReusableThread get() {
ReusableThread rt = null;
if (pool.size() > 0)
{
rt = (ReusableThread)pool.firstElement();
pool.removeElement(rt);
}
if (pool.size() > 0) {
rt = (ReusableThread) pool.firstElement();
pool.removeElement(rt);
}
if (rt == null)
{
rt = new ReusableThread(this);
rt.start();
}
if (rt == null) {
rt = new ReusableThread(this);
rt.start();
}
return rt;
return rt;
}
public synchronized void put(ReusableThread rt)
{
pool.addElement(rt);
public synchronized void put(ReusableThread rt) {
pool.addElement(rt);
}
public synchronized void clean()
{
long now = System.currentTimeMillis();
for (Enumeration e = pool.elements(); e.hasMoreElements(); )
{
ReusableThread rt = (ReusableThread) e.nextElement();
if (now - rt.getLastRunTime() >= 30000)
{
rt.terminate();
pool.removeElement(rt);
}
}
public synchronized void clean() {
long now = System.currentTimeMillis();
for (Enumeration e = pool.elements(); e.hasMoreElements();) {
ReusableThread rt = (ReusableThread) e.nextElement();
if (now - rt.getLastRunTime() >= 30000) {
rt.terminate();
pool.removeElement(rt);
}
}
}
}

View File

@@ -2,132 +2,133 @@ package com.jpexs.proxy;
import java.util.*;
public class WorkerThread extends Thread {
private Runnable task;
private String name;
private Runnable task;
private String name;
private static int nactive = 0;
private static Vector list = new Vector();
private static int max = 10;
private static long lifetime = 900 * 1000; /* 15 minute default */
private static int nactive = 0;
private static Vector list = new Vector();
private static int max = 10;
private static long lifetime = 900 * 1000; /* 15 minute default */
private
WorkerThread() {
setDaemon(true);
}
/**
* Sets the lifetime of an idle WorkerThread (in ms). A WorkerThread
* will remain on the idle list for this much time before exiting. This
* does not affect WorkerThreads currently idling.
*/
synchronized static void
setLifetime(long time) {
lifetime = time;
}
private
WorkerThread() {
setDaemon(true);
}
/**
* Sets the maximum number of WorkerThreads that can exist at any given
* time. If this value is decreased below the current number of
* WorkerThreads, this will not take effect immediately.
*/
synchronized static void
setMaxThreads(int maxThreads) {
max = maxThreads;
}
/**
* Sets the lifetime of an idle WorkerThread (in ms). A WorkerThread will
* remain on the idle list for this much time before exiting. This does not
* affect WorkerThreads currently idling.
*/
synchronized static void
setLifetime(long time) {
lifetime = time;
}
/**
* Obtains a WorkerThread to which a task can be assigned. If an idle
* WorkerThread is present, it is removed from the idle list and returned.
* If not, and the maximum number of WorkerThreads has not been reached,
* a new WorkerThread is created. If the maximum number has been reached,
* this blocks until a WorkerThread is free.
*/
static WorkerThread
getThread() {
WorkerThread t;
synchronized (list) {
if (list.size() > 0) {
t = (WorkerThread) list.firstElement();
list.removeElement(t);
}
else if (nactive >= max) {
while (true) {
try {
list.wait();
}
catch (InterruptedException e) {
}
if (list.size() == 0)
continue;
t = (WorkerThread) list.firstElement();
list.removeElement(t);
break;
}
}
else
t = new WorkerThread();
nactive++;
}
return t;
}
/**
* Sets the maximum number of WorkerThreads that can exist at any given
* time. If this value is decreased below the current number of
* WorkerThreads, this will not take effect immediately.
*/
synchronized static void
setMaxThreads(int maxThreads) {
max = maxThreads;
}
/**
* Assigns a task to a WorkerThread
* @param task The task to be run
* @param name The name of the task
*/
public static void
assignThread(Runnable task, String name) {
while (true) {
try {
WorkerThread t = getThread();
synchronized (t) {
t.task = task;
t.name = name;
if (!t.isAlive())
t.start();
else
t.notify();
}
return;
}
catch (IllegalThreadStateException e) {
}
}
}
/**
* Obtains a WorkerThread to which a task can be assigned. If an idle
* WorkerThread is present, it is removed from the idle list and returned.
* If not, and the maximum number of WorkerThreads has not been reached, a
* new WorkerThread is created. If the maximum number has been reached, this
* blocks until a WorkerThread is free.
*/
static WorkerThread
getThread() {
WorkerThread t;
synchronized (list) {
if (list.size() > 0) {
t = (WorkerThread) list.firstElement();
list.removeElement(t);
} else if (nactive >= max) {
while (true) {
try {
list.wait();
} catch (InterruptedException e) {
}
if (list.size() == 0) {
continue;
}
t = (WorkerThread) list.firstElement();
list.removeElement(t);
break;
}
} else {
t = new WorkerThread();
}
nactive++;
}
return t;
}
/** Performs the task */
synchronized public void
run() {
while (true) {
setName(name);
try {
task.run();
}
catch (Throwable t) {
System.err.println(t);
}
setName("idle thread");
synchronized (list) {
list.addElement(this);
if (nactive >= max)
list.notify();
nactive--;
}
task = null;
try {
wait(lifetime);
}
catch (InterruptedException e) {
}
if (task == null) {
list.removeElement(this);
return;
}
}
}
/**
* Assigns a task to a WorkerThread
*
* @param task The task to be run
* @param name The name of the task
*/
public static void
assignThread(Runnable task, String name) {
while (true) {
try {
WorkerThread t = getThread();
synchronized (t) {
t.task = task;
t.name = name;
if (!t.isAlive()) {
t.start();
} else {
t.notify();
}
}
return;
} catch (IllegalThreadStateException e) {
}
}
}
/**
* Performs the task
*/
synchronized public void
run() {
while (true) {
setName(name);
try {
task.run();
} catch (Throwable t) {
System.err.println(t);
}
setName("idle thread");
synchronized (list) {
list.addElement(this);
if (nactive >= max) {
list.notify();
}
nactive--;
}
task = null;
try {
wait(lifetime);
} catch (InterruptedException e) {
}
if (task == null) {
list.removeElement(this);
return;
}
}
}
}