/* * HighlightFilter.java * * Brazil project web application toolkit, * export version: 2.3 * Copyright (c) 2007 Sun Microsystems, Inc. * * Sun Public License Notice * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is included as the file "license.terms", * and also available at http://www.sun.com/ * * The Original Code is from: * Brazil project web application toolkit release 2.3. * The Initial Developer of the Original Code is: suhler. * Portions created by suhler are Copyright (C) Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): suhler. * * Version: 1.2 * Created by suhler on 07/06/21 * Last modified by suhler on 07/06/22 14:16:34 * * Version Histories: * * 1.2 07/06/22-14:16:34 (suhler) * - don't filter when there is no RE * - handle encoding properly * * 1.2 07/06/21-16:21:32 (Codemgr) * SunPro Code Manager data about conflicts, renames, etc... * Name history : 1 0 sunlabs/HighlightFilter.java * * 1.1 07/06/21-16:21:31 (suhler) * date and time created 07/06/21 16:21:31 by suhler * */ package sunlabs.brazil.filter; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.StringTokenizer; import java.util.Hashtable; import java.util.Enumeration; import sunlabs.brazil.server.Request; import sunlabs.brazil.server.Server; import sunlabs.brazil.util.Format; import sunlabs.brazil.util.LexML; import sunlabs.brazil.util.http.HttpInputStream; import sunlabs.brazil.util.http.HttpUtil; import sunlabs.brazil.util.http.MimeHeaders; import sunlabs.brazil.util.regexp.Regexp; import sunlabs.brazil.util.http.HttpRequest; import sunlabs.brazil.handler.HtmlRewriter; /** * Rewrite text between markup (and not in links) based on re sub's. *
* Sample usage: *
* re=test * sub=& ** will cause every occurance of the word "test" in the html content * to be colored red. */ public class HighlightFilter implements Filter { String prefix; // our properties prefix String sub; // the substitution string Regexp re; // the regular expression to match String reString; // the re string String trailer; // text to add at end of all rewritten content boolean noCase; public boolean init(Server server, String prefix) { this.prefix = prefix; reString = null; noCase = (server.props.getProperty(prefix + "noCase") != null); sub = server.props.getProperty(prefix + "sub", ""); trailer = server.props.getProperty(prefix + "trailer"); return true; } /* * be lazy and don't handle content encodings */ public boolean respond(Request request) { String encoding = request.headers.get("accept-encoding"); if (encoding != null) { request.headers.remove("accept-encoding"); } String s = Format.subst(request.props,request.props.getProperty( prefix + "re")); if (s != null && !s.equals(reString)) { reString = s; try { re = new Regexp(reString, noCase); } catch (IllegalArgumentException e) { request.log(Server.LOG_WARNING, prefix, "Invalid regexp"); re=null; } } return false; } public boolean shouldFilter(Request request, MimeHeaders headers) { String type = headers.get("content-type"); String encoding = headers.get("content-encoding"); request.log(Server.LOG_DIAGNOSTIC, request.url + ": " + type); boolean ok = type!=null && type.startsWith("text/html") && encoding==null; return ok; } public byte[] filter(Request request, MimeHeaders headers, byte[] content) { HtmlRewriter hr = null; String encoding = HttpRequest.getEncoding(headers); try { hr = new HtmlRewriter(new String(content, encoding)); } catch (UnsupportedEncodingException e) { request.log(Server.LOG_WARNING, "bad encoding: " + encoding); encoding = null; } if (hr == null) { hr = new HtmlRewriter(new String(content)); } request.log(Server.LOG_DIAGNOSTIC, "filtering: " + request.url); boolean changed=false; boolean skip = false; while (hr.nextToken()) { int type = hr.getType(); if (type == LexML.TAG) { String tag = hr.getTag(); // lower case tag skip = (tag.equals("script") || tag.equals("style") || tag.equals("title")); if (trailer!=null && tag.equals("/body")) { request.log(Server.LOG_DIAGNOSTIC, "adding trailer"); String append = Format.subst(request.props, trailer); hr.append(append); hr.appendToken(); changed = true; } } else if (type==LexML.STRING && !skip && reString!=null && !reString.equals("")) { changed |= process(hr); } } if (changed) { try { return hr.toString().getBytes(encoding); } catch (UnsupportedEncodingException e) { request.log(Server.LOG_WARNING, "bad encoding: " + encoding); return hr.toString().getBytes(); } } else { return content; } } /** * Process literal text for rewriting * hr: current rewrite context */ boolean process(HtmlRewriter hr) { String src = hr.getToken(); String result = re.subAll(src, sub); if (result.equals(src)) { return false; } else { // System.out.println("Map: " + src + " => " + result); hr.append(result); return true; } } }