/* * Search.java * * Created on 19 June 2005, 01:40 */ package org.owasp.webscarab.plugin.search; import bsh.EvalError; import bsh.Interpreter; import bsh.TargetError; import org.owasp.webscarab.model.ConversationID; import org.owasp.webscarab.model.ConversationModel; import org.owasp.webscarab.model.FrameworkModel; import org.owasp.webscarab.model.Preferences; import org.owasp.webscarab.model.Request; import org.owasp.webscarab.model.Response; import org.owasp.webscarab.model.StoreException; import org.owasp.webscarab.plugin.Framework; import org.owasp.webscarab.plugin.FrameworkModelWrapper; import org.owasp.webscarab.plugin.Hook; import org.owasp.webscarab.plugin.Plugin; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author rogan */ public class Search implements Plugin { private Framework _framework; private FrameworkModel _frameworkModel; private FrameworkModelWrapper _wrapper; private Interpreter _interpreter = new Interpreter(); private SearchModel _model; private Thread _runThread; private Logger _logger = Logger.getLogger(getClass().getName()); /** Creates a new instance of Search */ public Search(Framework framework) { _framework = framework; _frameworkModel = _framework.getModel(); _wrapper = new FrameworkModelWrapper(_frameworkModel); _model = new SearchModel(_frameworkModel); loadSearches(); } public SearchModel getModel() { return _model; } private void loadSearches() { String base="Search."; String description; String expression; int i=0; /** * Pre-load some common templates */ _model.addSearch( "Body search", "new String(response.getContent(),\"UTF-8\").toLowerCase().contains(\"<SEARCHWORD>\".toLowerCase())" ); _model.addSearch( "Request search", "new String(request.toString()).toLowerCase().contains(\"<SEARCHWORD>\".toLowerCase())" ); _model.addSearch( "Response search", "new String(response.toString()).toLowerCase().contains(\"<SEARCHWORD>\".toLowerCase())" ); _model.addSearch( "Request parameter search", "request.parameterSearch(\"<SEARCHWORD>\".toLowerCase())" ); do { description=Preferences.getPreference(base+i+".description"); expression=Preferences.getPreference(base+i+".expression"); if (description != null && expression != null) { _model.addSearch(description, expression); } i++; } while (description != null ); } private void saveSearches() { String base = "Search."; String[] searches = _model.getSearches(); for (int i=0; i<searches.length; i++) { String expression = _model.getSearchExpression(searches[i]); Preferences.setPreference(base+i+".description", searches[i]); Preferences.setPreference(base+i+".expression", expression); } Preferences.remove(base+searches.length+".description"); Preferences.remove(base+searches.length+".expression"); } public void addSearch(String description, String expression) { _model.addSearch(description, expression); saveSearches(); } public void removeSearch(String description) { _model.removeSearch(description); ConversationModel cmodel = _frameworkModel.getConversationModel(); int count = cmodel.getConversationCount(); for (int i=0; i<count; i++) { ConversationID id = cmodel.getConversationAt(i); _model.setSearchMatch(id, description, false); } saveSearches(); } public void setFilter(String description) { _model.setFilter(description); } public void reload(String description) { ConversationID id = null; try { String expr = _model.getSearchExpression(description); ConversationModel cmodel = _frameworkModel.getConversationModel(); int count = cmodel.getConversationCount(); for (int i=0; i<count; i++) { id = cmodel.getConversationAt(i); Request request = cmodel.getRequest(id); Response response = cmodel.getResponse(id); String origin = cmodel.getConversationOrigin(id); boolean matches = matches(id, request, response, origin, expr); _model.setSearchMatch(id, description, matches); } } catch (Exception e) { _logger.log(Level.WARNING,"Evaluation error for conversation " + id,e); } } private boolean matches(ConversationID id, Request request, Response response, String origin, String expression) throws EvalError { _interpreter.set("model", _wrapper); _interpreter.set("id", id); _interpreter.set("request", request); _interpreter.set("response", response); _interpreter.set("origin", origin); Object result = _interpreter.eval(expression); if (result != null && result instanceof Boolean) { boolean b = ((Boolean)result).booleanValue(); return b; } else { _logger.info("Got a " + result); return false; } } public void analyse(ConversationID id, Request request, Response response, String origin) { try { _model.readLock().acquire(); synchronized(_interpreter) { String[] searches = _model.getSearches(); for (int i=0; i<searches.length; i++) { try { String expression = _model.getSearchExpression(searches[i]); boolean matches = matches(id, request, response, origin, expression); if (matches) { _model.setSearchMatch(id, searches[i], true); } // no point unsetting if false, could not be set yet } catch (TargetError te) { _logger.warning("Evaluation error for conversation " + id + " : " + te.getMessage()); } } } _model.readLock().release(); } catch (Exception e) { e.printStackTrace(); } } public void flush() throws StoreException { } public String getPluginName() { return "Search"; } public Object getScriptableObject() { return null; } public Hook[] getScriptingHooks() { return new Hook[0]; } public String getStatus() { return _model.getStatus(); } public boolean isBusy() { return _model.isBusy(); } public boolean isModified() { return _model.isModified(); } public boolean isRunning() { return _model.isRunning(); } public void run() { _runThread = Thread.currentThread(); _model.setStopping(false); _model.setRunning(true); _model.setStatus("Idle"); try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException ie) {} _model.setRunning(false); _model.setStatus("Stopped"); } public void setSession(String type, Object store, String session) throws StoreException { } public boolean stop() { _runThread.interrupt(); return true; } }