beginning of branch i2p.i2p.i2p

This commit is contained in:
cvs_import
2004-04-08 04:41:54 +00:00
committed by zzz
commit 77bd69c5e5
292 changed files with 41035 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="httptunnel">
<target name="all" depends="clean, build" />
<target name="build" depends="builddep, jar" />
<target name="builddep">
<ant dir="../../ministreaming/java/" target="build" />
<ant dir="../../../core/java/" target="build" />
</target>
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/httptunnel.jar" basedir="./build/obj" includes="**/*.class">
<manifest>
<attribute name="Main-Class" value="net.i2p.httptunnel.HTTPTunnel" />
<attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
</manifest>
</jar>
</target>
<target name="javadoc">
<mkdir dir="./build" />
<mkdir dir="./build/javadoc" />
<javadoc
sourcepath="./src:../../../core/java/src:../../ministreaming/java/src" destdir="./build/javadoc"
packagenames="*"
use="true"
splitindex="true"
windowtitle="HTTPTunnel" />
</target>
<target name="clean">
<delete dir="./build" />
</target>
<target name="cleandep" depends="clean">
<ant dir="../../../core/java/" target="cleandep" />
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
<target name="distclean" depends="clean">
<ant dir="../../../core/java/" target="distclean" />
<ant dir="../../ministreaming/java/" target="distclean" />
</target>
</project>

View File

@@ -0,0 +1,67 @@
package net.i2p.httptunnel;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import net.i2p.util.Log;
/**
* Listens on a port for HTTP connections.
*/
public class HTTPListener extends Thread {
private static final Log _log = new Log(HTTPListener.class);
private int port;
private String listenHost;
private SocketManagerProducer smp;
public HTTPListener(SocketManagerProducer smp, int port,
String listenHost) {
this.smp = smp;
this.port = port;
start();
}
public void run() {
try {
InetAddress lh = listenHost == null
? null
: InetAddress.getByName(listenHost);
ServerSocket ss = new ServerSocket(port, 0, lh);
while(true) {
Socket s = ss.accept();
new HTTPSocketHandler(this, s);
}
} catch (IOException ex) {
_log.error("Error while accepting connections", ex);
}
}
private boolean proxyUsed=false;
public boolean firstProxyUse() {
// FIXME: check a config option here
if (true) return false;
if (proxyUsed) {
return false;
} else {
proxyUsed=true;
return true;
}
}
public SocketManagerProducer getSMP() {
return smp;
}
/** @deprecated */
public void handleNotImplemented(OutputStream out) throws IOException {
out.write(("HTTP/1.1 200 Document following\n\n"+
"<h1>Feature not implemented</h1>").getBytes("ISO-8859-1"));
out.flush();
}
}

View File

@@ -0,0 +1,54 @@
package net.i2p.httptunnel;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import net.i2p.httptunnel.handler.RootHandler;
import net.i2p.util.Log;
/**
* Handles a single HTTP socket connection.
*/
public class HTTPSocketHandler extends Thread {
private static final Log _log = new Log(HTTPSocketHandler.class);
private Socket s;
private HTTPListener httpl;
private RootHandler h;
public HTTPSocketHandler(HTTPListener httpl, Socket s) {
this.httpl = httpl;
this.s=s;
h = RootHandler.getInstance();
start();
}
public void run() {
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(s.getInputStream());
out = new BufferedOutputStream(s.getOutputStream());
Request req = new Request(in);
h.handle(req, httpl, out);
} catch (IOException ex) {
_log.error("Error while handling data", ex);
} finally {
try {
if (in != null) in.close();
if (out != null) {
out.flush();
out.close();
}
s.close();
} catch (IOException ex) {
_log.error("IOException in finalizer", ex);
}
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* HTTPTunnel
* (c) 2003 - 2004 mihi
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* In addition, as a special exception, mihi gives permission to link
* the code of this program with the proprietary Java implementation
* provided by Sun (or other vendors as well), and distribute linked
* combinations including the two. You must obey the GNU General
* Public License in all respects for all of the code used other than
* the proprietary Java implementation. If you modify this file, you
* may extend this exception to your version of the file, but you are
* not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package net.i2p.httptunnel;
import net.i2p.client.streaming.I2PSocketManager;
/**
* HTTPTunnel main class.
*/
public class HTTPTunnel {
/**
* Create a HTTPTunnel instance.
*
* @param initialManagers a list of socket managers to use
* @param maxManagers how many managers to have in the cache
* @param mcDonaldsMode whether to throw away a manager after use
* @param listenPort which port to listen on
*/
public HTTPTunnel(I2PSocketManager[] initialManagers, int maxManagers,
boolean mcDonaldsMode, int listenPort) {
this(initialManagers, maxManagers, mcDonaldsMode, listenPort,
"127.0.0.1", 7654);
}
/**
* Create a HTTPTunnel instance.
*
* @param initialManagers a list of socket managers to use
* @param maxManagers how many managers to have in the cache
* @param mcDonaldsMode whether to throw away a manager after use
* @param listenPort which port to listen on
* @param i2cpAddress the I2CP address
* @param i2cpPort the I2CP port
*/
public HTTPTunnel(I2PSocketManager[] initialManagers, int maxManagers,
boolean mcDonaldsMode, int listenPort,
String i2cpAddress, int i2cpPort) {
SocketManagerProducer smp =
new SocketManagerProducer(initialManagers, maxManagers,
mcDonaldsMode, i2cpAddress, i2cpPort);
new HTTPListener(smp, listenPort, "127.0.0.1");
}
public static void main(String[] args) {
String host = "127.0.0.1";
int port = 7654, max = 1;
boolean mc = false;
if (args.length >1) {
if (args.length == 4) {
host = args[2];
port = Integer.parseInt(args[3]);
} else if (args.length != 2) {
showInfo(); return;
}
max = Integer.parseInt(args[1]);
} else if (args.length != 1) {
showInfo(); return;
}
if (max == 0) {
max = 1;
} else if (max <0) {
max = -max;
mc = true;
}
new HTTPTunnel(null, max, mc, Integer.parseInt(args[0]), host, port);
}
private static void showInfo() {
System.out.println
("Usage: java HTTPTunnel <listenPort> [<max> "+
"[<i2cphost> <i2cpport>]]\n"+
" <listenPort> port to listen for browsers\n"+
" <max> max number of SocketMangers in pool, "+
"use neg. number\n"+
" to use each SocketManager only once "+
"(default: 1)\n"+
" <i2cphost> host to connect to the router "+
"(default: 127.0.0.1)\n"+
" <i2cpport> port to connect to the router "+
"(default: 7654)");
}
}

View File

@@ -0,0 +1,130 @@
package net.i2p.httptunnel;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import net.i2p.util.Log;
/**
* A HTTP request (GET or POST). This will be passed to a hander for
* handling it.
*/
public class Request {
private static final Log _log = new Log(Request.class);
// all strings are forced to be ISO-8859-1 encoding
private String method;
private String url;
private String proto;
private String params;
private String postData;
public Request(InputStream in) throws IOException {
BufferedReader br = new BufferedReader
(new InputStreamReader(in, "ISO-8859-1"));
String line = br.readLine();
if (line == null) { // no data at all
method = null;
_log.error("Connection but no data");
return;
}
int pos = line.indexOf(" ");
if (pos == -1) {
method = line;
url="";
_log.error("Malformed HTTP request: "+line);
} else {
method = line.substring(0,pos);
url=line.substring(pos+1);
}
proto="";
pos = url.indexOf(" ");
if (pos != -1) {
proto=url.substring(pos); // leading space intended
url = url.substring(0,pos);
}
StringBuffer sb = new StringBuffer(512);
while((line=br.readLine()) != null) {
if (line.length() == 0) break;
sb.append(line).append("\r\n");
}
params = sb.toString(); // no leading empty line!
sb = new StringBuffer();
// hack for POST requests, ripped from HttpClient
// this won't work for large POSTDATA
// FIXME: do this better, please.
if (!method.equals("GET")) {
while (br.ready()) { // empty the buffer (POST requests)
int i=br.read();
if (i != -1) {
sb.append((char)i);
}
}
postData = sb.toString();
} else {
postData="";
}
}
public byte[] toByteArray() throws IOException {
if (method == null) return null;
return toISO8859_1String().getBytes("ISO-8859-1");
}
private String toISO8859_1String() throws IOException {
if (method == null) return null;
return method+" "+url+proto+"\r\n"+params+"\r\n"+postData;
}
public String getURL() {
return url;
}
public void setURL(String newURL) {
url=newURL;
}
public String getParam(String name) {
try {
BufferedReader br= new BufferedReader(new StringReader(params));
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith(name)) {
return line.substring(name.length());
}
}
return null;
} catch (IOException ex) {
_log.error("Error getting parameter", ex);
return null;
}
}
public void setParam(String name, String value) {
try {
StringBuffer sb = new StringBuffer(params.length()+value.length());
BufferedReader br= new BufferedReader(new StringReader(params));
String line;
boolean replaced = false;
while((line=br.readLine()) != null) {
if (line.startsWith(name)) {
replaced=true;
if (value == null) continue; // kill param
line = name+value;
}
sb.append(line).append("\r\n");
}
if (!replaced && value != null) {
sb.append(name).append(value).append("\r\n");
}
params=sb.toString();
} catch (IOException ex) {
_log.error("Error getting parameter", ex);
}
}
}

View File

@@ -0,0 +1,111 @@
package net.i2p.httptunnel;
import java.util.*;
import net.i2p.client.streaming.*;
/**
* Produces SocketManagers in a thread and gives them to those who
* need them.
*/
public class SocketManagerProducer extends Thread {
private ArrayList myManagers = new ArrayList();
private HashMap usedManagers = new HashMap();
private int port;
private String host;
private int maxManagers;
private boolean mcDonalds;
public SocketManagerProducer(I2PSocketManager[] initialManagers,
int maxManagers,
boolean mcDonaldsMode,
String host, int port) {
if (maxManagers < 1) {
throw new IllegalArgumentException("maxManagers < 1");
}
this.host=host;
this.port=port;
mcDonalds=mcDonaldsMode;
if (initialManagers != null) {
myManagers.addAll(Arrays.asList(initialManagers));
}
this.maxManagers=maxManagers;
mcDonalds=mcDonaldsMode;
setDaemon(true);
start();
}
/**
* Thread producing new SocketManagers.
*/
public void run() {
while (true) {
synchronized(this) {
// without mcDonalds mode, we most probably need no
// new managers.
while (!mcDonalds && myManagers.size() == maxManagers) {
myWait();
}
}
// produce a new manager, regardless whether it is needed
// or not. Do not synchronized this part, since it can be
// quite time-consuming.
I2PSocketManager newManager =
I2PSocketManagerFactory.createManager(host, port,
new Properties());
// when done, check if it is needed.
synchronized(this) {
while(myManagers.size() == maxManagers) {
myWait();
}
myManagers.add(newManager);
notifyAll();
}
}
}
/**
* Get a manager for connecting to a given destination. Each
* destination will always get the same manager.
*
* @param dest the destination to connect to
* @return the SocketManager to use
*/
public synchronized I2PSocketManager getManager(String dest) {
I2PSocketManager result = (I2PSocketManager) usedManagers.get(dest);
if (result == null) {
result = getManager();
usedManagers.put(dest,result);
}
return result;
}
/**
* Get a "new" SocketManager. Depending on the anonymity settings,
* this can be a completely new one or one randomly selected from
* a pool.
*
* @return the SocketManager to use
*/
public synchronized I2PSocketManager getManager() {
while (myManagers.size() == 0) {
myWait(); // no manager here, so wait until one is produced
}
int which = (int)(Math.random()*myManagers.size());
I2PSocketManager result = (I2PSocketManager) myManagers.get(which);
if (mcDonalds) {
myManagers.remove(which);
notifyAll();
}
return result;
}
public void myWait() {
try {
wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}

View File

@@ -0,0 +1,50 @@
package net.i2p.httptunnel.filter;
import net.i2p.util.Log;
import java.io.*;
import java.util.*;
/**
* Chain multiple filters. Decorator pattern...
*/
public class ChainFilter implements Filter {
private static final Log _log = new Log(ChainFilter.class);
public Collection filters;
public ChainFilter(Collection filters) {
this.filters=filters;
}
public byte[] filter(byte[] toFilter) {
byte[] buf = toFilter;
for (Iterator it = filters.iterator(); it.hasNext();) {
Filter f = (Filter) it.next();
buf = f.filter(buf);
}
return buf;
}
public byte[] finish() {
// this is a bit complicated. Think about it...
try {
byte[] buf = EMPTY;
for (Iterator it = filters.iterator(); it.hasNext();) {
Filter f = (Filter) it.next();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (buf.length != 0) {
baos.write(f.filter(buf));
}
baos.write(f.finish());
buf = baos.toByteArray();
}
return buf;
} catch (IOException ex) {
_log.error("Error chaining filters", ex);
return EMPTY;
}
}
}

View File

@@ -0,0 +1,22 @@
package net.i2p.httptunnel.filter;
/**
* A generic filtering interface.
*/
public interface Filter {
/**
* An empty byte array.
*/
public static final byte[] EMPTY = new byte[0];
/**
* Filter some data. Not all filtered data need to be returned.
*/
public byte[] filter(byte[] toFilter);
/**
* Data stream has finished. Return all of the rest data.
*/
public byte[] finish();
}

View File

@@ -0,0 +1,15 @@
package net.i2p.httptunnel.filter;
/**
* A filter letting everything pass as is.
*/
public class NullFilter implements Filter {
public byte[] filter(byte[] toFilter) {
return toFilter;
}
public byte[] finish() {
return EMPTY;
}
}

View File

@@ -0,0 +1,93 @@
package net.i2p.httptunnel.handler;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.i2p.I2PException;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.data.Destination;
import net.i2p.httptunnel.HTTPListener;
import net.i2p.httptunnel.Request;
import net.i2p.httptunnel.SocketManagerProducer;
import net.i2p.httptunnel.filter.Filter;
import net.i2p.httptunnel.filter.NullFilter;
import net.i2p.util.Log;
/**
* Handler for browsing Eepsites.
*/
public class EepHandler {
private static final Log _log = new Log(EepHandler.class);
protected ErrorHandler errorHandler;
/* package private */ EepHandler(ErrorHandler eh) {
errorHandler=eh;
}
public void handle(Request req, HTTPListener httpl, OutputStream out,
boolean fromProxy, String destination)
throws IOException {
SocketManagerProducer smp = httpl.getSMP();
Destination dest = NamingService.getInstance().lookup(destination);
if (dest == null) {
errorHandler.handle(req, httpl, out,
"Could not lookup host: "+destination);
return;
}
I2PSocketManager sm = smp.getManager(destination);
Filter f = new NullFilter(); //FIXME: use other filter
req.setParam("Host: ", dest.toBase64());
if (!handle(req, f, out, dest, sm)) {
errorHandler.handle(req, httpl, out, "Unable to reach peer");
}
}
public boolean handle(Request req, Filter f, OutputStream out,
Destination dest, I2PSocketManager sm)
throws IOException {
I2PSocket s = null;
boolean written = false;
try {
synchronized(sm) {
s = sm.connect(dest, new I2PSocketOptions());
}
InputStream in = new BufferedInputStream(s.getInputStream());
OutputStream sout = new BufferedOutputStream(s.getOutputStream());
sout.write(req.toByteArray());
sout.flush();
byte[] buffer = new byte[16384], filtered;
int len;
while ((len=in.read(buffer)) != -1) {
if (len != buffer.length) {
byte[] b2 = new byte[len];
System.arraycopy(buffer, 0, b2, 0, len);
filtered=f.filter(b2);
} else {
filtered=f.filter(buffer);
}
written=true;
out.write(filtered);
}
filtered=f.finish();
written=true;
out.write(filtered);
out.flush();
} catch (IOException ex) {
_log.error("Error while handling eepsite request");
return written;
} catch (I2PException ex) {
_log.error("Error while handling eepsite request");
return written;
} finally {
if (s != null) s.close();
}
return true;
}
}

View File

@@ -0,0 +1,36 @@
package net.i2p.httptunnel.handler;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.httptunnel.HTTPListener;
import net.i2p.httptunnel.Request;
import net.i2p.util.Log;
/**
* Handler for general error messages.
*/
public class ErrorHandler {
private static final Log _log = new Log(ErrorHandler.class);
/* package private */ ErrorHandler() {
}
public void handle(Request req, HTTPListener httpl,
OutputStream out, String error) throws IOException {
// FIXME: Make nicer messages for more likely errors.
out.write(("HTTP/1.1 500 Internal Server Error\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n\r\n")
.getBytes("ISO-8859-1"));
out.write(("<html><head><title>"+error+"</title></head><body><h1>"+
error+"</h1>An internal error occurred while "+
"handling a request by HTTPTunnel:<br><b>"+error+
"</b><h2>Complete request:</h2><b>---</b><br><i><pre>\r\n")
.getBytes("ISO-8859-1"));
out.write(req.toByteArray());
out.write(("</pre></i><br><b>---</b></body></html>")
.getBytes("ISO-8859-1"));
out.flush();
}
}

View File

@@ -0,0 +1,49 @@
package net.i2p.httptunnel.handler;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.httptunnel.HTTPListener;
import net.i2p.httptunnel.Request;
import net.i2p.util.Log;
/**
* Handler for requests that do not require any connection to anyone
* (except errors).
*/
public class LocalHandler {
private static final Log _log = new Log(LocalHandler.class);
/* package private */ LocalHandler() {
}
public void handle(Request req, HTTPListener httpl, OutputStream out,
boolean fromProxy) throws IOException {
//FIXME: separate multiple pages, not only a start page
//FIXME: provide some info on this page
out.write(("HTTP/1.1 200 Document following\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n\r\n"+
"<html><head><title>Welcome to I2P HTTPTunnel</title>"+
"</head><body><h1>Welcome to I2P HTTPTunnel</h1>You can "+
"browse Eepsites by adding an eepsite name to the request."+
"</body></html>").getBytes("ISO-8859-1"));
out.flush();
}
public void handleProxyConfWarning(Request req, HTTPListener httpl,
OutputStream out) throws IOException {
//FIXME
throw new IOException("jrandom ate the deprecated method. mooo");
//httpl.handleNotImplemented(out);
}
public void handleHTTPWarning(Request req, HTTPListener httpl,
OutputStream out, boolean fromProxy)
throws IOException {
// FIXME
throw new IOException("jrandom ate the deprecated method. mooo");
//httpl.handleNotImplemented(out);
}
}

View File

@@ -0,0 +1,47 @@
package net.i2p.httptunnel.handler;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Destination;
import net.i2p.httptunnel.HTTPListener;
import net.i2p.httptunnel.Request;
import net.i2p.httptunnel.SocketManagerProducer;
import net.i2p.httptunnel.filter.Filter;
import net.i2p.httptunnel.filter.NullFilter;
import net.i2p.util.Log;
/**
* Handler for proxying "normal" HTTP requests.
*/
public class ProxyHandler extends EepHandler {
private static final Log _log = new Log(ErrorHandler.class);
/* package private */ ProxyHandler(ErrorHandler eh) {
super(eh);
}
public void handle(Request req, HTTPListener httpl, OutputStream out,
boolean fromProxy) throws IOException {
SocketManagerProducer smp = httpl.getSMP();
Destination dest = findProxy();
if (dest == null) {
errorHandler.handle(req, httpl, out,
"Could not find proxy");
return;
}
// one manager for all proxy requests
I2PSocketManager sm = smp.getManager("--proxy--");
Filter f = new NullFilter(); //FIXME: use other filter
if (!handle(req, f, out, dest, sm)) {
errorHandler.handle(req, httpl, out, "Unable to reach peer");
}
}
private Destination findProxy() {
//FIXME!
return NamingService.getInstance().lookup("squid.i2p");
}
}

View File

@@ -0,0 +1,109 @@
package net.i2p.httptunnel.handler;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.httptunnel.HTTPListener;
import net.i2p.httptunnel.Request;
import net.i2p.util.Log;
/**
* Main handler for all requests. Dispatches requests to other handlers.
*/
public class RootHandler {
private static final Log _log = new Log(RootHandler.class);
private RootHandler() {
errorHandler=new ErrorHandler();
localHandler=new LocalHandler();
proxyHandler=new ProxyHandler(errorHandler);
eepHandler=new EepHandler(errorHandler);
}
private ErrorHandler errorHandler;
private ProxyHandler proxyHandler;
private LocalHandler localHandler;
private EepHandler eepHandler;
private static RootHandler instance;
public static synchronized RootHandler getInstance() {
if (instance == null) {
instance = new RootHandler();
}
return instance;
}
public void handle(Request req, HTTPListener httpl,
OutputStream out) throws IOException {
String url=req.getURL();
System.out.println(url);
boolean byProxy = false;
int pos;
if (url.startsWith("http://")) { // access via proxy
byProxy=true;
if (httpl.firstProxyUse()) {
localHandler.handleProxyConfWarning(req,httpl,out);
return;
}
url = url.substring(7);
pos = url.indexOf("/");
String host;
String rest;
if (pos == -1) {
errorHandler.handle(req, httpl, out, "No host end in URL");
return;
} else {
host = url.substring(0,pos);
url = url.substring(pos);
if ("i2p".equals(host) || "i2p.i2p".equals(host)) {
// normal request; go on below...
} else if (host.endsWith(".i2p")) {
// "old" service request, send a redirect...
out.write(("HTTP/1.1 302 Moved\r\nLocation: "+
"http://i2p.i2p/"+host+url+
"\r\n\r\n").getBytes("ISO-8859-1"));
return;
} else {
// this is for proxying to the real web
proxyHandler.handle(req, httpl, out, true);
return;
}
}
}
if (url.equals("/")) { // main page
url="/_/local/index";
} else if (!url.startsWith("/")) {
errorHandler.handle(req, httpl, out,
"No leading slash in URL: "+url);
return;
}
String dest;
url=url.substring(1);
pos = url.indexOf("/");
if (pos == -1) {
dest=url;
url="/";
} else {
dest = url.substring(0,pos);
url=url.substring(pos);
}
req.setURL(url);
if (dest.equals("_")) { // no eepsite
if (url.startsWith("/local/")) { // local request
req.setURL(url.substring(6));
localHandler.handle(req, httpl, out, byProxy);
} else if (url.startsWith("/http/")) { // http warning
localHandler.handleHTTPWarning(req, httpl, out, byProxy);
} else if (url.startsWith("/proxy/")) { // http proxying
req.setURL("http://"+url.substring(7));
proxyHandler.handle(req, httpl, out, byProxy);
} else {
errorHandler.handle(req, httpl, out,
"No local handler for this URL: "+url);
}
} else {
eepHandler.handle(req, httpl, out, byProxy, dest);
}
}
}