Some crappy, half-assed attempt at javadoc stuff; removed (commented out, rather) the fromProxy stuff for *Handler.java. Feel free to put it back in if it's really needed....
(shendaras)
This commit is contained in:
@ -19,6 +19,15 @@ public class HTTPListener extends Thread {
|
|||||||
private String listenHost;
|
private String listenHost;
|
||||||
private SocketManagerProducer smp;
|
private SocketManagerProducer smp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A public constructor. It contstructs things. In this case,
|
||||||
|
* it constructs a nice HTTPListener, for all your listening on
|
||||||
|
* HTTP needs. Yep. That's right.
|
||||||
|
* @param smp A SocketManagerProducer, producing Sockets, no doubt
|
||||||
|
* @param port A port, to connect to.
|
||||||
|
* @param listenHost A host, to connect to.
|
||||||
|
*/
|
||||||
|
|
||||||
public HTTPListener(SocketManagerProducer smp, int port,
|
public HTTPListener(SocketManagerProducer smp, int port,
|
||||||
String listenHost) {
|
String listenHost) {
|
||||||
this.smp = smp;
|
this.smp = smp;
|
||||||
@ -26,6 +35,9 @@ public class HTTPListener extends Thread {
|
|||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Thread#run()
|
||||||
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
InetAddress lh = listenHost == null
|
InetAddress lh = listenHost == null
|
||||||
@ -43,6 +55,10 @@ public class HTTPListener extends Thread {
|
|||||||
|
|
||||||
private boolean proxyUsed=false;
|
private boolean proxyUsed=false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query whether this is the first use of the proxy or not . . .
|
||||||
|
* @return Whether this is the first proxy use, no doubt.
|
||||||
|
*/
|
||||||
public boolean firstProxyUse() {
|
public boolean firstProxyUse() {
|
||||||
// FIXME: check a config option here
|
// FIXME: check a config option here
|
||||||
if (true) return false;
|
if (true) return false;
|
||||||
@ -54,11 +70,19 @@ public class HTTPListener extends Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The SocketManagerProducer being used.
|
||||||
|
*/
|
||||||
public SocketManagerProducer getSMP() {
|
public SocketManagerProducer getSMP() {
|
||||||
return smp;
|
return smp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @deprecated */
|
/**
|
||||||
|
* Outputs with HTTP 1.1 flair that a feature isn't implemented.
|
||||||
|
* @param out The stream the text goes to.
|
||||||
|
* @deprecated
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void handleNotImplemented(OutputStream out) throws IOException {
|
public void handleNotImplemented(OutputStream out) throws IOException {
|
||||||
out.write(("HTTP/1.1 200 Document following\n\n"+
|
out.write(("HTTP/1.1 200 Document following\n\n"+
|
||||||
"<h1>Feature not implemented</h1>").getBytes("ISO-8859-1"));
|
"<h1>Feature not implemented</h1>").getBytes("ISO-8859-1"));
|
||||||
|
@ -21,6 +21,11 @@ public class HTTPSocketHandler extends Thread {
|
|||||||
private HTTPListener httpl;
|
private HTTPListener httpl;
|
||||||
private RootHandler h;
|
private RootHandler h;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A public constructor.
|
||||||
|
* @param httpl An HTTPListener, to listen for HTTP, no doubt
|
||||||
|
* @param s A socket.
|
||||||
|
*/
|
||||||
public HTTPSocketHandler(HTTPListener httpl, Socket s) {
|
public HTTPSocketHandler(HTTPListener httpl, Socket s) {
|
||||||
this.httpl = httpl;
|
this.httpl = httpl;
|
||||||
this.s=s;
|
this.s=s;
|
||||||
@ -28,6 +33,10 @@ public class HTTPSocketHandler extends Thread {
|
|||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Thread#run()
|
||||||
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
OutputStream out = null;
|
OutputStream out = null;
|
||||||
|
@ -69,6 +69,11 @@ public class HTTPTunnel {
|
|||||||
new HTTPListener(smp, listenPort, "127.0.0.1");
|
new HTTPListener(smp, listenPort, "127.0.0.1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The all important main function, allowing HTTPTunnel to be
|
||||||
|
* stand-alone, a program in it's own right, and all that jazz.
|
||||||
|
* @param args A list of String passed to the program
|
||||||
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
String host = "127.0.0.1";
|
String host = "127.0.0.1";
|
||||||
int port = 7654, max = 1;
|
int port = 7654, max = 1;
|
||||||
|
@ -23,6 +23,11 @@ public class Request {
|
|||||||
private String params;
|
private String params;
|
||||||
private String postData;
|
private String postData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A constructor, creating a request from an InputStream
|
||||||
|
* @param in InputStream from which we "read-in" a Request
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public Request(InputStream in) throws IOException {
|
public Request(InputStream in) throws IOException {
|
||||||
BufferedReader br = new BufferedReader
|
BufferedReader br = new BufferedReader
|
||||||
(new InputStreamReader(in, "ISO-8859-1"));
|
(new InputStreamReader(in, "ISO-8859-1"));
|
||||||
@ -70,6 +75,10 @@ public class Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A Request as an array of bytes of a String in ISO-8859-1 format
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public byte[] toByteArray() throws IOException {
|
public byte[] toByteArray() throws IOException {
|
||||||
if (method == null) return null;
|
if (method == null) return null;
|
||||||
return toISO8859_1String().getBytes("ISO-8859-1");
|
return toISO8859_1String().getBytes("ISO-8859-1");
|
||||||
@ -81,14 +90,26 @@ public class Request {
|
|||||||
return method+" "+url+proto+"\r\n"+params+"\r\n"+postData;
|
return method+" "+url+proto+"\r\n"+params+"\r\n"+postData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the URL of the request
|
||||||
|
*/
|
||||||
public String getURL() {
|
public String getURL() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the URL of the Request
|
||||||
|
* @param newURL the new URL
|
||||||
|
*/
|
||||||
public void setURL(String newURL) {
|
public void setURL(String newURL) {
|
||||||
url=newURL;
|
url=newURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of a param.
|
||||||
|
* @param name The name of the param
|
||||||
|
* @return The value of the param, or null
|
||||||
|
*/
|
||||||
public String getParam(String name) {
|
public String getParam(String name) {
|
||||||
try {
|
try {
|
||||||
BufferedReader br= new BufferedReader(new StringReader(params));
|
BufferedReader br= new BufferedReader(new StringReader(params));
|
||||||
@ -105,6 +126,11 @@ public class Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of a param.
|
||||||
|
* @param name the name of the param
|
||||||
|
* @param value the value to be set
|
||||||
|
*/
|
||||||
public void setParam(String name, String value) {
|
public void setParam(String name, String value) {
|
||||||
try {
|
try {
|
||||||
StringBuffer sb = new StringBuffer(params.length()+value.length());
|
StringBuffer sb = new StringBuffer(params.length()+value.length());
|
||||||
|
@ -16,6 +16,14 @@ public class SocketManagerProducer extends Thread {
|
|||||||
private int maxManagers;
|
private int maxManagers;
|
||||||
private boolean mcDonalds;
|
private boolean mcDonalds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public constructor creating a SocketManagerProducer
|
||||||
|
* @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 host which host to listen on
|
||||||
|
* @param port which port to listen on
|
||||||
|
*/
|
||||||
public SocketManagerProducer(I2PSocketManager[] initialManagers,
|
public SocketManagerProducer(I2PSocketManager[] initialManagers,
|
||||||
int maxManagers,
|
int maxManagers,
|
||||||
boolean mcDonaldsMode,
|
boolean mcDonaldsMode,
|
||||||
@ -101,6 +109,9 @@ public class SocketManagerProducer extends Thread {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until InterruptedException
|
||||||
|
*/
|
||||||
public void myWait() {
|
public void myWait() {
|
||||||
try {
|
try {
|
||||||
wait();
|
wait();
|
||||||
|
@ -12,12 +12,19 @@ public class ChainFilter implements Filter {
|
|||||||
|
|
||||||
private static final Log _log = new Log(ChainFilter.class);
|
private static final Log _log = new Log(ChainFilter.class);
|
||||||
|
|
||||||
public Collection filters;
|
private Collection filters; // perhaps protected?
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filters A collection (list) of filters to chain to
|
||||||
|
*/
|
||||||
public ChainFilter(Collection filters) {
|
public ChainFilter(Collection filters) {
|
||||||
this.filters=filters;
|
this.filters=filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.i2p.httptunnel.filter.Filter#filter(byte[])
|
||||||
|
*/
|
||||||
public byte[] filter(byte[] toFilter) {
|
public byte[] filter(byte[] toFilter) {
|
||||||
byte[] buf = toFilter;
|
byte[] buf = toFilter;
|
||||||
for (Iterator it = filters.iterator(); it.hasNext();) {
|
for (Iterator it = filters.iterator(); it.hasNext();) {
|
||||||
@ -27,6 +34,9 @@ public class ChainFilter implements Filter {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.i2p.httptunnel.filter.Filter#finish()
|
||||||
|
*/
|
||||||
public byte[] finish() {
|
public byte[] finish() {
|
||||||
// this is a bit complicated. Think about it...
|
// this is a bit complicated. Think about it...
|
||||||
try {
|
try {
|
||||||
|
@ -12,11 +12,14 @@ public interface Filter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter some data. Not all filtered data need to be returned.
|
* Filter some data. Not all filtered data need to be returned.
|
||||||
|
* @param toFilter the bytes that are to be filtered.
|
||||||
|
* @return the filtered data
|
||||||
*/
|
*/
|
||||||
public byte[] filter(byte[] toFilter);
|
public byte[] filter(byte[] toFilter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data stream has finished. Return all of the rest data.
|
* Data stream has finished. Return all of the rest data.
|
||||||
|
* @return the rest of the data
|
||||||
*/
|
*/
|
||||||
public byte[] finish();
|
public byte[] finish();
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,16 @@ package net.i2p.httptunnel.filter;
|
|||||||
*/
|
*/
|
||||||
public class NullFilter implements Filter {
|
public class NullFilter implements Filter {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.i2p.httptunnel.filter.Filter#filter(byte[])
|
||||||
|
*/
|
||||||
public byte[] filter(byte[] toFilter) {
|
public byte[] filter(byte[] toFilter) {
|
||||||
return toFilter;
|
return toFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see net.i2p.httptunnel.filter.Filter#finish()
|
||||||
|
*/
|
||||||
public byte[] finish() {
|
public byte[] finish() {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,16 @@ public class EepHandler {
|
|||||||
errorHandler=eh;
|
errorHandler=eh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param req the Request
|
||||||
|
* @param httpl an HTTPListener
|
||||||
|
* @param out where to write the results
|
||||||
|
* @param destination destination as a string, (subject to naming
|
||||||
|
* service lookup)
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void handle(Request req, HTTPListener httpl, OutputStream out,
|
public void handle(Request req, HTTPListener httpl, OutputStream out,
|
||||||
boolean fromProxy, String destination)
|
/* boolean fromProxy, */ String destination)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
SocketManagerProducer smp = httpl.getSMP();
|
SocketManagerProducer smp = httpl.getSMP();
|
||||||
Destination dest = NamingService.getInstance().lookup(destination);
|
Destination dest = NamingService.getInstance().lookup(destination);
|
||||||
@ -49,6 +57,15 @@ public class EepHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param req the Request to send out
|
||||||
|
* @param f a Filter to apply to the bytes retrieved from the Destination
|
||||||
|
* @param out where to write the results
|
||||||
|
* @param dest the Destination of the Request
|
||||||
|
* @param sm an I2PSocketManager, to get a socket for the Destination
|
||||||
|
* @return boolean, true if something was written, false otherwise.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public boolean handle(Request req, Filter f, OutputStream out,
|
public boolean handle(Request req, Filter f, OutputStream out,
|
||||||
Destination dest, I2PSocketManager sm)
|
Destination dest, I2PSocketManager sm)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@ -17,6 +17,13 @@ public class ErrorHandler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param req the Request
|
||||||
|
* @param httpl an HTTPListener
|
||||||
|
* @param out where to write the results
|
||||||
|
* @param error the error that happened
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void handle(Request req, HTTPListener httpl,
|
public void handle(Request req, HTTPListener httpl,
|
||||||
OutputStream out, String error) throws IOException {
|
OutputStream out, String error) throws IOException {
|
||||||
// FIXME: Make nicer messages for more likely errors.
|
// FIXME: Make nicer messages for more likely errors.
|
||||||
|
@ -15,11 +15,16 @@ public class LocalHandler {
|
|||||||
private static final Log _log = new Log(LocalHandler.class);
|
private static final Log _log = new Log(LocalHandler.class);
|
||||||
|
|
||||||
/* package private */ LocalHandler() {
|
/* package private */ LocalHandler() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Request req, HTTPListener httpl, OutputStream out,
|
/**
|
||||||
boolean fromProxy) throws IOException {
|
* @param req the Request
|
||||||
|
* @param httpl an HTTPListener
|
||||||
|
* @param out where to write the results
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void handle(Request req, HTTPListener httpl, OutputStream out
|
||||||
|
/*, boolean fromProxy */) throws IOException {
|
||||||
//FIXME: separate multiple pages, not only a start page
|
//FIXME: separate multiple pages, not only a start page
|
||||||
//FIXME: provide some info on this page
|
//FIXME: provide some info on this page
|
||||||
out.write(("HTTP/1.1 200 Document following\r\n"+
|
out.write(("HTTP/1.1 200 Document following\r\n"+
|
||||||
@ -31,6 +36,13 @@ public class LocalHandler {
|
|||||||
out.flush();
|
out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently always throws an IO Exception
|
||||||
|
* @param req the Request
|
||||||
|
* @param httpl an HTTPListener
|
||||||
|
* @param out where to write the results
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void handleProxyConfWarning(Request req, HTTPListener httpl,
|
public void handleProxyConfWarning(Request req, HTTPListener httpl,
|
||||||
OutputStream out) throws IOException {
|
OutputStream out) throws IOException {
|
||||||
//FIXME
|
//FIXME
|
||||||
@ -39,8 +51,15 @@ public class LocalHandler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently always throws an IO Exception
|
||||||
|
* @param req the Request
|
||||||
|
* @param httpl an HTTPListener
|
||||||
|
* @param out where to write the results
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void handleHTTPWarning(Request req, HTTPListener httpl,
|
public void handleHTTPWarning(Request req, HTTPListener httpl,
|
||||||
OutputStream out, boolean fromProxy)
|
OutputStream out /*, boolean fromProxy */)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// FIXME
|
// FIXME
|
||||||
throw new IOException("jrandom ate the deprecated method. mooo");
|
throw new IOException("jrandom ate the deprecated method. mooo");
|
||||||
|
@ -23,8 +23,14 @@ public class ProxyHandler extends EepHandler {
|
|||||||
super(eh);
|
super(eh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Request req, HTTPListener httpl, OutputStream out,
|
/**
|
||||||
boolean fromProxy) throws IOException {
|
* @param req a Request
|
||||||
|
* @param httpl an HTTPListener
|
||||||
|
* @param out where to write the results
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void handle(Request req, HTTPListener httpl, OutputStream out
|
||||||
|
/*, boolean fromProxy */) throws IOException {
|
||||||
SocketManagerProducer smp = httpl.getSMP();
|
SocketManagerProducer smp = httpl.getSMP();
|
||||||
Destination dest = findProxy();
|
Destination dest = findProxy();
|
||||||
if (dest == null) {
|
if (dest == null) {
|
||||||
|
@ -27,6 +27,10 @@ public class RootHandler {
|
|||||||
|
|
||||||
private static RootHandler instance;
|
private static RootHandler instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton stuff . . .
|
||||||
|
* @return the one and only instance, yay!
|
||||||
|
*/
|
||||||
public static synchronized RootHandler getInstance() {
|
public static synchronized RootHandler getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new RootHandler();
|
instance = new RootHandler();
|
||||||
@ -34,14 +38,21 @@ public class RootHandler {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The _ROOT_ handler: it passes its workload off to the other handlers.
|
||||||
|
* @param req a Request
|
||||||
|
* @param httpl an HTTPListener
|
||||||
|
* @param out where to write the results
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void handle(Request req, HTTPListener httpl,
|
public void handle(Request req, HTTPListener httpl,
|
||||||
OutputStream out) throws IOException {
|
OutputStream out) throws IOException {
|
||||||
String url=req.getURL();
|
String url=req.getURL();
|
||||||
System.out.println(url);
|
System.out.println(url);
|
||||||
boolean byProxy = false;
|
/* boolean byProxy = false; */
|
||||||
int pos;
|
int pos;
|
||||||
if (url.startsWith("http://")) { // access via proxy
|
if (url.startsWith("http://")) { // access via proxy
|
||||||
byProxy=true;
|
/* byProxy=true; */
|
||||||
if (httpl.firstProxyUse()) {
|
if (httpl.firstProxyUse()) {
|
||||||
localHandler.handleProxyConfWarning(req,httpl,out);
|
localHandler.handleProxyConfWarning(req,httpl,out);
|
||||||
return;
|
return;
|
||||||
@ -66,7 +77,7 @@ public class RootHandler {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// this is for proxying to the real web
|
// this is for proxying to the real web
|
||||||
proxyHandler.handle(req, httpl, out, true);
|
proxyHandler.handle(req, httpl, out /*, true */);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,18 +103,18 @@ public class RootHandler {
|
|||||||
if (dest.equals("_")) { // no eepsite
|
if (dest.equals("_")) { // no eepsite
|
||||||
if (url.startsWith("/local/")) { // local request
|
if (url.startsWith("/local/")) { // local request
|
||||||
req.setURL(url.substring(6));
|
req.setURL(url.substring(6));
|
||||||
localHandler.handle(req, httpl, out, byProxy);
|
localHandler.handle(req, httpl, out /*, byProxy */);
|
||||||
} else if (url.startsWith("/http/")) { // http warning
|
} else if (url.startsWith("/http/")) { // http warning
|
||||||
localHandler.handleHTTPWarning(req, httpl, out, byProxy);
|
localHandler.handleHTTPWarning(req, httpl, out /*, byProxy */);
|
||||||
} else if (url.startsWith("/proxy/")) { // http proxying
|
} else if (url.startsWith("/proxy/")) { // http proxying
|
||||||
req.setURL("http://"+url.substring(7));
|
req.setURL("http://"+url.substring(7));
|
||||||
proxyHandler.handle(req, httpl, out, byProxy);
|
proxyHandler.handle(req, httpl, out /*, byProxy */);
|
||||||
} else {
|
} else {
|
||||||
errorHandler.handle(req, httpl, out,
|
errorHandler.handle(req, httpl, out,
|
||||||
"No local handler for this URL: "+url);
|
"No local handler for this URL: "+url);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eepHandler.handle(req, httpl, out, byProxy, dest);
|
eepHandler.handle(req, httpl, out, /* byProxy, */ dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ class BufferLogger implements Logging {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass in some random data
|
* Pass in some random data
|
||||||
|
* @param s String containing what we're logging.
|
||||||
*/
|
*/
|
||||||
public void log(String s) {
|
public void log(String s) {
|
||||||
if (_ignore) return;
|
if (_ignore) return;
|
||||||
|
Reference in New Issue
Block a user