filterhandler.java

来自「一款Java实现的HTTP代理服务器」· Java 代码 · 共 179 行

JAVA
179
字号
package rabbit.handler;import java.io.IOException;import java.io.OutputStream;import java.nio.ByteBuffer;import java.util.ArrayList;import java.util.List;import rabbit.filter.HtmlFilter;import rabbit.filter.HtmlFilterFactory;import rabbit.html.HtmlBlock;import rabbit.html.HtmlParseException;import rabbit.html.HtmlParser;import rabbit.http.HttpHeader;import rabbit.proxy.Connection;import rabbit.proxy.TrafficLoggerHandler;import rabbit.util.Logger;import rabbit.util.SProperties;/** This handler filters out unwanted html features. * * @author <a href="mailto:robo@khelekore.org">Robert Olofsson</a> */public class FilterHandler extends GZipHandler {    private SProperties config = new SProperties ();    private List<HtmlFilterFactory> filterClasses =     new ArrayList<HtmlFilterFactory> ();    private List<HtmlFilter> filters;     private HtmlParser parser;    private HtmlBlock block = null;    // For creating the factory.    public FilterHandler () {	    }    /** Create a new FilterHandler for the given request.     * @param con the Connection handling the request.     * @param request the actual request made.     * @param clientBuffer the client side buffer.     * @param response the actual response.     * @param content the resource.     * @param mayCache May we cache this request?      * @param mayFilter May we filter this request?     * @param size the size of the data beeing handled.     * @param compress if we want this handler to compress or not.     */    public FilterHandler (Connection con, TrafficLoggerHandler tlh, 			  HttpHeader request, ByteBuffer clientBuffer,			  HttpHeader response, ResourceSource content, 			  boolean mayCache, boolean mayFilter, long size, 			  boolean compress, 			  List<HtmlFilterFactory> filterClasses) {	super (con, tlh, request, clientBuffer, response, content, 	       mayCache, mayFilter, size, compress);	if (this.mayFilter) {	    this.filterClasses = filterClasses;	    response.removeHeader ("Content-Length");	    /* Not sure why we would need this, used to be in rabbit/2.x	    if (!con.getChunking ())		con.setKeepalive (false);	    */	    parser = new HtmlParser ();	    filters = initFilters ();	}    }    @Override    public Handler getNewInstance (Connection con, TrafficLoggerHandler tlh,				   HttpHeader header, ByteBuffer buffer, 				   HttpHeader webHeader, 				   ResourceSource content, boolean mayCache, 				   boolean mayFilter, long size) {	return new FilterHandler (con, tlh, header, buffer, webHeader, content,				  mayCache, mayFilter, size, compress, 				  filterClasses);    }        @Override    protected void writeDataToGZipper (byte[] arr) 	throws IOException {		handleArray (arr, gz);    }    @Override    protected void modifyBuffer (ByteBuffer buf) {	if (!mayFilter) {	    super.modifyBuffer (buf);	    return;	}	byte[] arr = new byte[buf.remaining ()];	buf.get (arr);	try {	    handleArray (arr, new Stream2Channel ());	} catch (IOException e) {	    failed (e);	    	}    }    private void handleArray (byte[] arr, OutputStream out) 		throws IOException {	if (block != null) {	    int rs = block.restSize ();	    byte[] buf = new byte[arr.length + rs];	    block.insertRest (buf);	    System.arraycopy (arr, 0, buf, rs, arr.length);	    arr = buf;	}	parser.setText (arr);	HtmlBlock currentBlock = null;	try {	    currentBlock = parser.parse ();	    for (HtmlFilter hf : filters)		hf.filterHtml (currentBlock);	    currentBlock.send (out);	} catch (HtmlParseException e) {	    getLogger ().logInfo ("Bad HTML: " + e.toString ());	    out.write (arr);	    currentBlock = null;	}	if (currentBlock != null && currentBlock.restSize () > 0)	    block = currentBlock;	else 	    block = null;    }    @Override    protected void finishData () throws IOException {	if (block != null) {	    if (gz != null)		block.sendRest (gz);	    else 		block.sendRest (new Stream2Channel ());	}	super.finishData ();    }    /** Initialize the filter we are using.     * @return a List of HtmlFilters.     */    private List<HtmlFilter> initFilters () {	int fsize = filterClasses.size ();	List<HtmlFilter> fl = new ArrayList<HtmlFilter> (fsize);	Class<HtmlFilter> cls = null;		for (int i = 0; i < fsize; i++) {	    HtmlFilterFactory hff = filterClasses.get (i);	    fl.add (hff.newFilter (con, request, response));	}	return fl;    }    /** Setup this class.     * @param prop the properties of this class.     */    @Override public void setup (Logger logger, SProperties prop) {	super.setup (logger, prop);	config = prop;	String fs = config.getProperty ("filters", "");	filterClasses = new ArrayList<HtmlFilterFactory> ();	String[] names = fs.split (",");	for (String classname : names) {	    try {		Class<? extends HtmlFilterFactory> cls = 		    Class.forName (classname).		    asSubclass (HtmlFilterFactory.class);		filterClasses.add (cls.newInstance ());	    } catch (ClassNotFoundException e) {		logger.logWarn ("Could not find filter: '" + classname + "'");	    } catch (InstantiationException e) {		logger.logWarn ("Could not instanciate class: '" + 				classname + "' " + e);	    } catch (IllegalAccessException e) {		logger.logWarn ("Could not get constructor for: '" + 				classname + "' " + e);	    }	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?