/* * FragmentsModel.java * * Created on 04 April 2005, 10:30 */ package org.owasp.webscarab.plugin.fragments; import java.util.ArrayList; import java.util.Collections; import java.util.logging.Logger; import javax.swing.event.EventListenerList; import org.owasp.webscarab.model.AbstractConversationModel; import org.owasp.webscarab.model.ConversationID; import org.owasp.webscarab.model.ConversationModel; import org.owasp.webscarab.model.FrameworkModel; import org.owasp.webscarab.model.HttpUrl; import org.owasp.webscarab.model.StoreException; import org.owasp.webscarab.plugin.AbstractPluginModel; import org.owasp.webscarab.util.Encoding; import EDU.oswego.cs.dl.util.concurrent.Sync; /** * * @author rogan */ public class FragmentsModel extends AbstractPluginModel { private FragmentsStore _store = null; private FrameworkModel _model = null; private FragmentConversationModel _fcm = null; public static String KEY_SCRIPTS = "SCRIPTS"; public static String KEY_COMMENTS = "COMMENTS"; public static String KEY_FILEUPLOAD = "FILEUPLOAD"; public static String KEY_FORMS = "FORMS"; public static String KEY_HIDDENFIELD = "HIDDENFIELD"; public static String KEY_DOMXSS = "DOMXSS"; private Logger _logger = Logger.getLogger(getClass().getName()); private EventListenerList _listenerList = new EventListenerList(); /** Creates a new instance of FragmentsModel */ public FragmentsModel(FrameworkModel model) { _model = model; _fcm = new FragmentConversationModel(model); } public void addFragment(HttpUrl url, ConversationID id, String type, String fragment) { try { _rwl.writeLock().acquire(); String key = Encoding.hashMD5(fragment); int position = _store.putFragment(type, key, fragment); _rwl.readLock().acquire(); _rwl.writeLock().release(); _model.addConversationProperty(id, type, key); _model.addUrlProperty(url, type, key); fireFragmentAdded(url, id, type, key); if (position>-1) fireFragmentAdded(type, key, position); _rwl.readLock().release(); } catch (InterruptedException ie) { _logger.severe("Interrupted! " + ie); } setModified(true); } public String[] getUrlFragmentKeys(HttpUrl url, String type) { if(KEY_COMMENTS.equals(type)|| KEY_DOMXSS.equals(type)|| KEY_FILEUPLOAD.equals(type)|| KEY_FORMS.equals(type)|| KEY_HIDDENFIELD.equals(type) || KEY_SCRIPTS.equals(type)) { return _model.getUrlProperties(url, type); } else { return new String[0]; } } public String[] getConversationFragmentKeys(ConversationID id, String type) { if(KEY_COMMENTS.equals(type)|| KEY_DOMXSS.equals(type)|| KEY_FILEUPLOAD.equals(type)|| KEY_FORMS.equals(type)|| KEY_HIDDENFIELD.equals(type) || KEY_SCRIPTS.equals(type)) { return _model.getConversationProperties(id, type); } else { return new String[0]; } } public int getFragmentTypeCount() { if (_store == null) return 0; return _store.getFragmentTypeCount(); } public String getFragmentType(int index) { return _store.getFragmentType(index); } public int getFragmentCount(String type) { return _store.getFragmentCount(type); } public String getFragmentKeyAt(String type, int position) { return _store.getFragmentKeyAt(type, position); } public int indexOfFragment(String type, String key) { return _store.indexOfFragment(type, key); } public String getFragment(String key) { return _store.getFragment(key); } public void addModelListener(FragmentListener listener) { _listenerList.add(FragmentListener.class, listener); } public void removeModelListener(FragmentListener listener) { _listenerList.remove(FragmentListener.class, listener); } public ConversationModel getConversationModel() { return _fcm; } public void setSelectedFragment(String type, String key) { try { _rwl.writeLock().acquire(); _rwl.readLock().acquire(); _rwl.writeLock().release(); _rwl.readLock().release(); } catch (InterruptedException ie) { _logger.severe("Interrupted! " + ie); } _fcm.setSelectedFragment(type, key); } public void setStore(FragmentsStore store) { _store = store; fireFragmentsChanged(); setModified(false); } public void flush() throws StoreException { if (_store != null && isModified()) { _store.flush(); setModified(false); } } private void fireFragmentsChanged() { // Guaranteed to return a non-null array Object[] listeners = _listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==FragmentListener.class) { try { ((FragmentListener)listeners[i+1]).fragmentsChanged(); } catch (Exception e) { _logger.severe("Unhandled exception: " + e); } } } } private void fireFragmentAdded(String type, String key, int position) { // Guaranteed to return a non-null array Object[] listeners = _listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==FragmentListener.class) { try { ((FragmentListener)listeners[i+1]).fragmentAdded(type, key, position); } catch (Exception e) { _logger.severe("Unhandled exception: " + e); } } } } private void fireFragmentAdded(HttpUrl url, ConversationID id, String type, String key) { // Guaranteed to return a non-null array Object[] listeners = _listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==FragmentListener.class) { try { ((FragmentListener)listeners[i+1]).fragmentAdded(url, id, type, key); } catch (Exception e) { _logger.severe("Unhandled : " + e); } } } } private class FragmentConversationModel extends AbstractConversationModel implements FragmentListener { private String _type = null; private String _key = null; private ArrayList<ConversationID> _conversationList = new ArrayList<ConversationID>(); public FragmentConversationModel(FrameworkModel model) { super(model); } public void setSelectedFragment(String type, String key) { try { _rwl.writeLock().acquire(); _type = type; _key = key; _conversationList.clear(); if (_type != null && _key != null) { ConversationModel cmodel = _model.getConversationModel(); int count = cmodel.getConversationCount(); for (int i=0; i<count; i++) { ConversationID id = cmodel.getConversationAt(i); String[] fragments = getConversationFragmentKeys(id, _type); if (fragments != null) { for (int j=0; j<fragments.length; j++) { if (fragments[j].equals(_key)) { _conversationList.add(id); break; } } } } } _rwl.readLock().acquire(); _rwl.writeLock().release(); fireConversationsChanged(); _rwl.readLock().release(); } catch (InterruptedException ie) { _logger.severe("Interrupted! " + ie); } } public ConversationID getConversationAt(int index) { return _conversationList.get(index); } public int getConversationCount() { return _conversationList.size(); } public int getIndexOfConversation(ConversationID id) { return Collections.binarySearch(_conversationList, id); } public Sync readLock() { return _rwl.readLock(); } public void fragmentAdded(String type, String key, int position) {} public void fragmentAdded(HttpUrl url, ConversationID id, String type, String key) { if (_type != null && _key != null) { if (_type.equals(type) && _key.equals(key)) { int index = getIndexOfConversation(id); if (index < 0) { try { _rwl.writeLock().acquire(); _conversationList.add(-index-1, id); _rwl.readLock().acquire(); _rwl.writeLock().release(); fireConversationAdded(id, -index-1); _rwl.readLock().release(); } catch (InterruptedException ie) { _logger.severe("Interrupted! " + ie); } } } } } public void fragmentsChanged() { try { _rwl.writeLock().acquire(); _key = null; _type = null; _conversationList.clear(); _rwl.readLock().acquire(); _rwl.writeLock().release(); fireConversationsChanged(); _rwl.readLock().release(); } catch (InterruptedException ie) { _logger.severe("Interrupted! " + ie); } } } }