package com.limegroup.gnutella.filters; import java.util.Vector; import com.limegroup.gnutella.messages.Message; import com.limegroup.gnutella.settings.FilterSettings; /** * A filter to eliminate Gnutella spam. Subclass to implement custom * filters. Each Gnutella connection has two SpamFilters; the * personal filter (for filtering results and the search monitor) and * a route filter (for deciding what I even consider). (Strategy * pattern.) Note that a packet stopped by the route filter will * never reach the personal filter.<p> * * Because one filter is used per connection, and only one invocation of * the run(..) method is used, filters are <b>not synchronized</b> by * default. The exception is BlackListFilter, which uses the Singleton * pattern and thus must be synchronized. */ public abstract class SpamFilter { /** * Returns a new instance of a SpamFilter subclass based on * the current settings manager. (Factory method) This * filter is intended for deciding which packets I display in * search results. */ public static SpamFilter newPersonalFilter() { Vector /* of SpamFilter */ buf=new Vector(); //1. IP-based techniques. String[] badIPs = FilterSettings.BLACK_LISTED_IP_ADDRESSES.getValue(); if (badIPs.length!=0) { //no need to check getAllowIPs IPFilter bf=IPFilter.instance(); buf.add(bf); } //2. Keyword-based techniques. String[] badWords = FilterSettings.BANNED_WORDS.getValue(); boolean filterAdult = FilterSettings.FILTER_ADULT.getValue(); boolean filterVbs = FilterSettings.FILTER_VBS.getValue(); boolean filterHtml = FilterSettings.FILTER_HTML.getValue(); boolean filterWMVASF = FilterSettings.FILTER_WMV_ASF.getValue(); if (badWords.length!=0 || filterAdult || filterVbs || filterHtml) { KeywordFilter kf=new KeywordFilter(); for (int i=0; i<badWords.length; i++) kf.disallow(badWords[i]); if (filterAdult) kf.disallowAdult(); if (filterVbs) kf.disallowVbs(); if (filterHtml) kf.disallowHtml(); if (filterWMVASF) kf.disallowWMVASF(); buf.add(kf); } //3. Spammy Replies SpamReplyFilter spf=new SpamReplyFilter(); buf.add(spf); //4. Mutable GUID-based filters. MutableGUIDFilter mgf = MutableGUIDFilter.instance(); buf.add(mgf); return compose(buf); } /** * Returns a new instance of a SpamFilter subclass based on * the current settings manager. (Factory method) This * filter is intended for deciding which packets to route. */ public static SpamFilter newRouteFilter() { //Assemble spam filters. Order matters a little bit. Vector /* of SpamFilter */ buf=new Vector(); //1. Eliminate old LimeWire requeries. buf.add(new RequeryFilter()); //1b. Eliminate runaway Qtrax queries. buf.add(new GUIDFilter()); //2. Duplicate-based techniques. if (FilterSettings.FILTER_DUPLICATES.getValue()) buf.add(new DuplicateFilter()); //3. Greedy queries. Yes, this is a route filter issue. if (FilterSettings.FILTER_GREEDY_QUERIES.getValue()) buf.add(new GreedyQueryFilter()); //4. Queries containing hash urns. if (FilterSettings.FILTER_HASH_QUERIES.getValue()) buf.add(new HashFilter()); //4. BearShare high-bit queries. // if (FilterSettings.FILTER_HIGHBIT_QUERIES.getValue()) // buf.add(new BearShareFilter()); return compose(buf); } /** * Returns a composite filter of the given filters. * @param filters a Vector of SpamFilter. */ private static SpamFilter compose(Vector /* of SpamFilter */ filters) { //As a minor optimization, we avoid a few method calls in //special cases. if (filters.size()==0) return new AllowFilter(); else if (filters.size()==1) return (SpamFilter)filters.get(0); else { SpamFilter[] delegates=new SpamFilter[filters.size()]; filters.copyInto(delegates); return new CompositeFilter(delegates); } } /** * Returns true iff this is considered spam and should not be processed. */ public abstract boolean allow(Message m); }