You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by aj...@apache.org on 2009/04/20 00:31:37 UTC
svn commit: r766540 [1/2] - in /incubator/jspwiki/trunk:
src/java/org/apache/wiki/content/ src/java/org/apache/wiki/filters/
src/java/org/apache/wiki/tags/ src/java/org/apache/wiki/ui/stripes/
tests/java/org/apache/wiki/ tests/java/org/apache/wiki/acti...
Author: ajaquith
Date: Sun Apr 19 22:31:36 2009
New Revision: 766540
URL: http://svn.apache.org/viewvc?rev=766540&view=rev
Log:
The @SpamProtect annotation and SpamProtect tag are now fully functional. Any JSP that submits to a WikiActionBean whose handler method is annotated with @SpamProtect receives the protection automatically, thanks to SpamInterceptor and collaborating SpamFilter. All that is needed is to add the tag <wiki:SpamProtect /> as a child element to the <form> or <s:form> elements. The same three-way check used in the old Edit.jsp is still done: random "trap" parameter; random "token" parameter; UTF-8 check parameter. To help ActionBean unit test classes run with "protected" handler events, the static method TestEngine.addSpamProtectParams(MockRoundtrip) was created.
Added:
incubator/jspwiki/trunk/src/java/org/apache/wiki/content/MissingParameterException.java
incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamInterceptor.java
- copied, changed from r765589, incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamInterceptor.java
incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamProtect.java
- copied, changed from r765589, incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamProtect.java
incubator/jspwiki/trunk/tests/java/org/apache/wiki/action/TestActionBean.java
incubator/jspwiki/trunk/tests/java/org/apache/wiki/filters/SpamFilterTest.java
incubator/jspwiki/trunk/tests/java/org/apache/wiki/ui/stripes/SpamInterceptorTest.java
Removed:
incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamInterceptor.java
incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamProtect.java
Modified:
incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ContentManager.java
incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java
incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/SpamProtectTag.java
incubator/jspwiki/trunk/tests/java/org/apache/wiki/TestEngine.java
incubator/jspwiki/trunk/tests/java/org/apache/wiki/filters/AllTests.java
Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ContentManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ContentManager.java?rev=766540&r1=766539&r2=766540&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ContentManager.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ContentManager.java Sun Apr 19 22:31:36 2009
@@ -1031,6 +1031,7 @@
}
/** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
@Override
public Outcome execute() throws WikiException
{
@@ -1045,7 +1046,16 @@
}
catch( PageNotFoundException e )
{
- throw new WikiException( e.getMessage(), e );
+ // Doesn't exist? No problem. Time to make one.
+ try
+ {
+ page = engine.getContentManager().addPage( name, ContentManager.JSPWIKI_CONTENT_TYPE );
+ }
+ catch( PageAlreadyExistsException pae )
+ {
+ // This should never happen, but it if does, throw a big honking exception
+ throw new WikiException( "We were just told the page didn't exist. Now it does? Explain that please...", pae );
+ }
}
// Retrieve the page ACL, author, attributes, modified-date, name and new text from the workflow
Added: incubator/jspwiki/trunk/src/java/org/apache/wiki/content/MissingParameterException.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/content/MissingParameterException.java?rev=766540&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/content/MissingParameterException.java (added)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/content/MissingParameterException.java Sun Apr 19 22:31:36 2009
@@ -0,0 +1,23 @@
+package org.apache.wiki.content;
+
+import org.apache.wiki.api.WikiException;
+
+/**
+ * Exception indicating that a required request parameter was not supplied, for example
+ * to SpamFilter.
+ */
+public class MissingParameterException extends WikiException
+{
+ private static final long serialVersionUID = 8665543487480429651L;
+
+ /**
+ * Constructs a new MissingParameterException
+ * @param message the exception message
+ * @param cause the cause of the exception, which may be <code>null</code>
+ */
+ public MissingParameterException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+}
Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java?rev=766540&r1=766539&r2=766540&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamFilter.java Sun Apr 19 22:31:36 2009
@@ -32,21 +32,22 @@
import javax.servlet.jsp.PageContext;
import net.sf.akismet.Akismet;
-import net.sourceforge.stripes.action.RedirectResolution;
-import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.util.CryptoUtil;
+import net.sourceforge.stripes.util.bean.NoSuchPropertyException;
+import net.sourceforge.stripes.util.bean.PropertyExpression;
+import net.sourceforge.stripes.util.bean.PropertyExpressionEvaluation;
import org.apache.commons.jrcs.diff.*;
import org.apache.commons.jrcs.diff.myers.MyersDiff;
import org.apache.commons.lang.time.StopWatch;
import org.apache.wiki.*;
-import org.apache.wiki.action.ViewActionBean;
import org.apache.wiki.action.WikiActionBean;
import org.apache.wiki.action.WikiContextFactory;
import org.apache.wiki.api.ModuleData;
import org.apache.wiki.api.WikiPage;
import org.apache.wiki.attachment.Attachment;
import org.apache.wiki.auth.user.UserProfile;
+import org.apache.wiki.content.MissingParameterException;
import org.apache.wiki.content.PageNotFoundException;
import org.apache.wiki.log.Logger;
import org.apache.wiki.log.LoggerFactory;
@@ -56,196 +57,236 @@
import org.apache.wiki.util.FileUtil;
import org.apache.wiki.util.TextUtil;
-
-
/**
- * This is Herb, the JSPWiki spamfilter that can also do choke modifications.
- *
- * Parameters:
- * <ul>
- * <li>wordlist - Page name where the regexps are found. Use [{SET spamwords='regexp list separated with spaces'}] on
- * that page. Default is "SpamFilterWordList".
- * <li>blacklist - The name of an attachment containing the list of spam patterns, one per line. Default is
- * "SpamFilterWordList/blacklist.txt"</li>
- * <li>errorpage - The page to which the user is redirected. Has a special variable $msg which states the reason. Default is "RejectedMessage".
- * <li>pagechangesinminute - How many page changes are allowed/minute. Default is 5.</li>
- * <li>similarchanges - How many similar page changes are allowed before the host is banned. Default is 2. (since 2.4.72)</li>
- * <li>bantime - How long an IP address stays on the temporary ban list (default is 60 for 60 minutes).</li>
- * <li>maxurls - How many URLs can be added to the page before it is considered spam (default is 5)</li>
- * <li>akismet-apikey - The Akismet API key (see akismet.org)</li>
- * <li>ignoreauthenticated - If set to "true", all authenticated users are ignored and never caught in SpamFilter</li>
- * <li>captcha - Sets the captcha technology to use. Current allowed values are "none" and "asirra".</li>
- * <li>strategy - Sets the filtering strategy to use. If set to "eager", will stop at the first probable
- * match, and won't consider any other tests. This is the default, as it's considerably lighter. If set to "score", will go through all of the tests
- * and calculates a score for the spam, which is then compared to a filter level value.
- * </ul>
- *
- * <p>Please see the default editors/plain.jsp for examples on how the SpamFilter integrates
- * with the editor system.</p>
- *
- * <p>Changes by admin users are ignored in any case.</p>
- *
- * @since 2.1.112
+ * This is Herb, the JSPWiki spamfilter that can also do choke modifications.
+ * Parameters:
+ * <ul>
+ * <li>wordlist - Page name where the regexps are found. Use [{SET
+ * spamwords='regexp list separated with spaces'}] on that page. Default is
+ * "SpamFilterWordList".
+ * <li>blacklist - The name of an attachment containing the list of spam
+ * patterns, one per line. Default is "SpamFilterWordList/blacklist.txt"</li>
+ * <li>errorpage - The page to which the user is redirected. Has a special
+ * variable $msg which states the reason. Default is "RejectedMessage".
+ * <li>pagechangesinminute - How many page changes are allowed/minute. Default
+ * is 5.</li>
+ * <li>similarchanges - How many similar page changes are allowed before the
+ * host is banned. Default is 2. (since 2.4.72)</li>
+ * <li>bantime - How long an IP address stays on the temporary ban list
+ * (default is 60 for 60 minutes).</li>
+ * <li>maxurls - How many URLs can be added to the page before it is considered
+ * spam (default is 5)</li>
+ * <li>akismet-apikey - The Akismet API key (see akismet.org)</li>
+ * <li>ignoreauthenticated - If set to "true", all authenticated users are
+ * ignored and never caught in SpamFilter</li>
+ * <li>captcha - Sets the captcha technology to use. Current allowed values are
+ * "none" and "asirra".</li>
+ * <li>strategy - Sets the filtering strategy to use. If set to "eager", will
+ * stop at the first probable match, and won't consider any other tests. This is
+ * the default, as it's considerably lighter. If set to "score", will go through
+ * all of the tests and calculates a score for the spam, which is then compared
+ * to a filter level value.
+ * </ul>
+ * <p>
+ * Please see the default editors/plain.jsp for examples on how the SpamFilter
+ * integrates with the editor system.
+ * </p>
+ * <p>
+ * Changes by admin users are ignored in any case.
+ * </p>
+ *
+ * @since 2.1.112
*/
@ModuleData( author = "JSPWiki development group" )
-public class SpamFilter
- extends BasicPageFilter
+public class SpamFilter extends BasicPageFilter
{
private static final String ATTR_SPAMFILTER_SCORE = "spamfilter.score";
+
private static final String REASON_REGEXP = "Regexp";
+
private static final String REASON_IP_BANNED_TEMPORARILY = "IPBannedTemporarily";
+
private static final String REASON_BOT_TRAP = "BotTrap";
+
private static final String REASON_AKISMET = "Akismet";
+
private static final String REASON_TOO_MANY_URLS = "TooManyUrls";
+
private static final String REASON_SIMILAR_MODIFICATIONS = "SimilarModifications";
+
private static final String REASON_TOO_MANY_MODIFICATIONS = "TooManyModifications";
+
private static final String REASON_UTF8_TRAP = "UTF8Trap";
private static final String LISTVAR = "spamwords";
-
- /** The filter property name for specifying the page which contains the list of spamwords.
- * Value is <tt>{@value}</tt>. */
- public static final String PROP_WORDLIST = "wordlist";
-
- /** The filter property name for the page to which you are directed if Herb rejects your
- * edit. Value is <tt>{@value}</tt>. */
- public static final String PROP_ERRORPAGE = "errorpage";
-
- /** The filter property name for specifying how many changes is any given IP address
- * allowed to do per minute. Value is <tt>{@value}</tt>.
- */
- public static final String PROP_PAGECHANGES = "pagechangesinminute";
-
- /** The filter property name for specifying how many similar changes are allowed
- * before a host is banned. Value is <tt>{@value}</tt>.
- */
- public static final String PROP_SIMILARCHANGES = "similarchanges";
-
- /** The filter property name for specifying how long a host is banned. Value is <tt>{@value}</tt>.*/
- public static final String PROP_BANTIME = "bantime";
-
- /** The filter property name for the attachment containing the blacklist. Value is <tt>{@value}</tt>.*/
- public static final String PROP_BLACKLIST = "blacklist";
-
- /** The filter property name for specifying how many URLs can any given edit contain.
- * Value is <tt>{@value}</tt> */
- public static final String PROP_MAXURLS = "maxurls";
-
- /** The filter property name for specifying the Akismet API-key. Value is <tt>{@value}</tt>. */
- public static final String PROP_AKISMET_API_KEY = "akismet-apikey";
-
- /** The filter property name for specifying whether authenticated users should be ignored. Value is <tt>{@value}</tt>. */
- public static final String PROP_IGNORE_AUTHENTICATED = "ignoreauthenticated";
-
- /** The filter property name for specifying which captcha technology should be used. Value is <tt>{@value}</tt>. */
- public static final String PROP_CAPTCHA = "captcha";
-
- /** The filter property name for specifying which filter strategy should be used. Value is <tt>{@value}</tt>. */
- public static final String PROP_FILTERSTRATEGY = "strategy";
+
+ /** Request parameter containing the UTF8 check. */
+ public static final String REQ_ENCODING_CHECK = "__wikiEncodingcheck";
+
+ /** Request parameter containing the encoded payload. */
+ public static final String REQ_SPAM_PARAM = "__wikiCheck";
+
+ /**
+ * The filter property name for specifying the page which contains the list
+ * of spamwords. Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_WORDLIST = "wordlist";
+
+ /**
+ * The filter property name for the page to which you are directed if Herb
+ * rejects your edit. Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_ERRORPAGE = "errorpage";
+
+ /**
+ * The filter property name for specifying how many changes is any given IP
+ * address allowed to do per minute. Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_PAGECHANGES = "pagechangesinminute";
+
+ /**
+ * The filter property name for specifying how many similar changes are
+ * allowed before a host is banned. Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_SIMILARCHANGES = "similarchanges";
+
+ /**
+ * The filter property name for specifying how long a host is banned. Value
+ * is <tt>{@value}</tt>.
+ */
+ public static final String PROP_BANTIME = "bantime";
+
+ /**
+ * The filter property name for the attachment containing the blacklist.
+ * Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_BLACKLIST = "blacklist";
+
+ /**
+ * The filter property name for specifying how many URLs can any given edit
+ * contain. Value is <tt>{@value}</tt>
+ */
+ public static final String PROP_MAXURLS = "maxurls";
+
+ /**
+ * The filter property name for specifying the Akismet API-key. Value is
+ * <tt>{@value}</tt>.
+ */
+ public static final String PROP_AKISMET_API_KEY = "akismet-apikey";
+
+ /**
+ * The filter property name for specifying whether authenticated users
+ * should be ignored. Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_IGNORE_AUTHENTICATED = "ignoreauthenticated";
+
+ /**
+ * The filter property name for specifying which captcha technology should
+ * be used. Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_CAPTCHA = "captcha";
+
+ /**
+ * The filter property name for specifying which filter strategy should be
+ * used. Value is <tt>{@value}</tt>.
+ */
+ public static final String PROP_FILTERSTRATEGY = "strategy";
/** The string specifying the "eager" strategy. Value is <tt>{@value}</tt>. */
- public static final String STRATEGY_EAGER = "eager";
-
+ public static final String STRATEGY_EAGER = "eager";
+
/** The string specifying the "score" strategy. Value is <tt>{@value}</tt>. */
- public static final String STRATEGY_SCORE = "score";
+ public static final String STRATEGY_SCORE = "score";
private static final String URL_REGEXP = "(http://|https://|mailto:)([A-Za-z0-9_/\\.\\+\\?\\#\\-\\@=&;]+)";
- private String m_forbiddenWordsPage = "SpamFilterWordList";
- private String m_errorPage = "RejectedMessage";
- private String m_blacklist = "SpamFilterWordList/blacklist.txt";
+ private String m_forbiddenWordsPage = "SpamFilterWordList";
+
+ private String m_errorPage = "RejectedMessage";
+
+ private String m_blacklist = "SpamFilterWordList/blacklist.txt";
private Collection<Pattern> m_spamPatterns = null;
- private Date m_lastRebuild = new Date( 0L );
+ private Date m_lastRebuild = new Date( 0L );
- private static Logger c_spamlog = LoggerFactory.getLogger( "SpamLog" );
- private static Logger log = LoggerFactory.getLogger( SpamFilter.class );
+ private static Logger c_spamlog = LoggerFactory.getLogger( "SpamLog" );
+ private static Logger log = LoggerFactory.getLogger( SpamFilter.class );
- private Vector<Host> m_temporaryBanList = new Vector<Host>();
+ private Vector<Host> m_temporaryBanList = new Vector<Host>();
- private int m_banTime = 60; // minutes
+ private int m_banTime = 60; // minutes
- private Vector<Host> m_lastModifications = new Vector<Host>();
+ private Vector<Host> m_lastModifications = new Vector<Host>();
/**
- * How many times a single IP address can change a page per minute?
+ * How many times a single IP address can change a page per minute?
*/
- private int m_limitSinglePageChanges = 5;
+ private int m_limitSinglePageChanges = 5;
/**
- * How many times can you add the exact same string to a page?
+ * How many times can you add the exact same string to a page?
*/
- private int m_limitSimilarChanges = 2;
+ private int m_limitSimilarChanges = 2;
/**
- * How many URLs can be added at maximum.
+ * How many URLs can be added at maximum.
*/
- private int m_maxUrls = 10;
+ private int m_maxUrls = 10;
+
+ private Pattern m_urlPattern;
- private Pattern m_urlPattern;
- private Akismet m_akismet;
+ private Akismet m_akismet;
- private String m_akismetAPIKey = null;
+ private String m_akismetAPIKey = null;
- private boolean m_useCaptcha = false;
+ private boolean m_useCaptcha = false;
/** The limit at which we consider something to be spam. */
- private int m_scoreLimit = 1;
+ private int m_scoreLimit = 1;
/**
* If set to true, will ignore anyone who is in Authenticated role.
*/
- private boolean m_ignoreAuthenticated = false;
+ private boolean m_ignoreAuthenticated = false;
- private boolean m_stopAtFirstMatch = true;
+ private boolean m_stopAtFirstMatch = true;
- private static String c_hashFieldName;
- private static long c_lastUpdate;
+ private static String c_hashFieldName;
- /** The HASH_DELAY value is a maximum amount of time that an user can keep
- * a session open, because after the value has expired, we will invent a new
- * hash field name. By default this is {@value} hours, which should be ample
- * time for someone.
+ private static long c_lastUpdate;
+
+ /**
+ * The HASH_DELAY value is a maximum amount of time that an user can keep a
+ * session open, because after the value has expired, we will invent a new
+ * hash field name. By default this is {@value} hours, which should be ample
+ * time for someone.
*/
private static final long HASH_DELAY = 24;
-
/**
- * {@inheritDoc}
+ * {@inheritDoc}
*/
@Override
public void initialize( WikiEngine engine, Properties properties )
{
- m_forbiddenWordsPage = properties.getProperty( PROP_WORDLIST,
- m_forbiddenWordsPage );
- m_errorPage = properties.getProperty( PROP_ERRORPAGE,
- m_errorPage );
-
- m_limitSinglePageChanges = TextUtil.getIntegerProperty( properties,
- PROP_PAGECHANGES,
- m_limitSinglePageChanges );
-
- m_limitSimilarChanges = TextUtil.getIntegerProperty( properties,
- PROP_SIMILARCHANGES,
- m_limitSimilarChanges );
-
- m_maxUrls = TextUtil.getIntegerProperty( properties,
- PROP_MAXURLS,
- m_maxUrls );
-
- m_banTime = TextUtil.getIntegerProperty( properties,
- PROP_BANTIME,
- m_banTime );
+ m_forbiddenWordsPage = properties.getProperty( PROP_WORDLIST, m_forbiddenWordsPage );
+ m_errorPage = properties.getProperty( PROP_ERRORPAGE, m_errorPage );
+
+ m_limitSinglePageChanges = TextUtil.getIntegerProperty( properties, PROP_PAGECHANGES, m_limitSinglePageChanges );
+
+ m_limitSimilarChanges = TextUtil.getIntegerProperty( properties, PROP_SIMILARCHANGES, m_limitSimilarChanges );
+
+ m_maxUrls = TextUtil.getIntegerProperty( properties, PROP_MAXURLS, m_maxUrls );
+
+ m_banTime = TextUtil.getIntegerProperty( properties, PROP_BANTIME, m_banTime );
m_blacklist = properties.getProperty( PROP_BLACKLIST, m_blacklist );
- m_ignoreAuthenticated = TextUtil.getBooleanProperty( properties,
- PROP_IGNORE_AUTHENTICATED,
- m_ignoreAuthenticated );
+ m_ignoreAuthenticated = TextUtil.getBooleanProperty( properties, PROP_IGNORE_AUTHENTICATED, m_ignoreAuthenticated );
- m_useCaptcha = properties.getProperty( PROP_CAPTCHA, "" ).equals("asirra");
+ m_useCaptcha = properties.getProperty( PROP_CAPTCHA, "" ).equals( "asirra" );
try
{
@@ -253,27 +294,24 @@
}
catch( PatternSyntaxException e )
{
- log.error("Internal error: Someone put in a faulty pattern.",e);
- throw new InternalWikiException("Faulty pattern.");
+ log.error( "Internal error: Someone put in a faulty pattern.", e );
+ throw new InternalWikiException( "Faulty pattern." );
}
- m_akismetAPIKey = TextUtil.getStringProperty( properties,
- PROP_AKISMET_API_KEY,
- m_akismetAPIKey );
+ m_akismetAPIKey = TextUtil.getStringProperty( properties, PROP_AKISMET_API_KEY, m_akismetAPIKey );
- m_stopAtFirstMatch = TextUtil.getStringProperty( properties,
- PROP_FILTERSTRATEGY,
- STRATEGY_EAGER ).equals(STRATEGY_EAGER);
-
- log.info("# Spam filter initialized. Temporary ban time "+m_banTime+
- " mins, max page changes/minute: "+m_limitSinglePageChanges );
+ m_stopAtFirstMatch = TextUtil.getStringProperty( properties, PROP_FILTERSTRATEGY, STRATEGY_EAGER ).equals( STRATEGY_EAGER );
+ log.info( "# Spam filter initialized. Temporary ban time " + m_banTime + " mins, max page changes/minute: "
+ + m_limitSinglePageChanges );
}
private static final int REJECT = 0;
+
private static final int ACCEPT = 1;
- private static final int NOTE = 2;
+
+ private static final int NOTE = 2;
private static String log( WikiContext ctx, int type, String source, String message )
{
@@ -282,9 +320,10 @@
String uid = getUniqueID();
- String page = ctx.getPage().getName();
+ WikiPage page = ctx.getPage();
+ String pageName = page == null ? "(no page)" : page.getName();
String reason = "UNKNOWN";
- String addr = ctx.getHttpRequest() != null ? ctx.getHttpRequest().getRemoteAddr() : "-";
+ String addr = ctx.getHttpRequest() != null ? ctx.getHttpRequest().getRemoteAddr() : "-";
switch( type )
{
@@ -298,38 +337,36 @@
reason = "NOTE";
break;
default:
- throw new InternalWikiException("Illegal type "+type);
+ throw new InternalWikiException( "Illegal type " + type );
}
- c_spamlog.info( reason+" "+source+" "+uid+" "+addr+" \""+page+"\" "+message );
+ c_spamlog.info( reason + " " + source + " " + uid + " " + addr + " \"" + pageName + "\" " + message );
return uid;
}
/** {@inheritDoc} */
- public String preSave( WikiContext context, String content )
- throws RedirectException
+ public String preSave( WikiContext context, String content ) throws RedirectException
{
cleanBanList();
- refreshBlacklists(context);
+ refreshBlacklists( context );
Change change = getChange( context, content );
- if(!ignoreThisUser(context))
+ if( !ignoreThisUser( context ) )
{
checkBanList( context, change );
checkSinglePageChange( context, content, change );
- checkPatternList(context, content, change);
+ checkPatternList( context, content, change );
}
if( !m_stopAtFirstMatch )
{
- Integer score = (Integer)context.getVariable(ATTR_SPAMFILTER_SCORE);
+ Integer score = (Integer) context.getVariable( ATTR_SPAMFILTER_SCORE );
if( score != null && score.intValue() >= m_scoreLimit )
{
- throw new RedirectException( "Herb says you got too many points",
- getRedirectPage(context) );
+ throw new RedirectException( "Herb says you got too many points", getRedirectPage( context ) );
}
}
@@ -337,27 +374,27 @@
return content;
}
- private void checkStrategy( WikiContext context, String error, String message )
- throws RedirectException
+ private void checkStrategy( WikiContext context, String error, String message ) throws RedirectException
{
if( m_stopAtFirstMatch )
{
- throw new RedirectException( message, getRedirectPage(context) );
+ throw new RedirectException( message, getRedirectPage( context ) );
}
- Integer score = (Integer)context.getVariable( ATTR_SPAMFILTER_SCORE );
+ Integer score = (Integer) context.getVariable( ATTR_SPAMFILTER_SCORE );
if( score != null )
- score = score+1;
+ score = score + 1;
else
score = 1;
context.setVariable( ATTR_SPAMFILTER_SCORE, score );
}
+
/**
- * Parses a list of patterns and returns a Collection of compiled Pattern
- * objects.
- *
+ * Parses a list of patterns and returns a Collection of compiled Pattern
+ * objects.
+ *
* @param source
* @param list
* @return A Collection of the Patterns that were found from the lists.
@@ -370,7 +407,7 @@
{
StringTokenizer tok = new StringTokenizer( list, " \t\n" );
- while( tok.hasMoreTokens() )
+ while ( tok.hasMoreTokens() )
{
String pattern = tok.nextToken();
@@ -380,9 +417,9 @@
}
catch( PatternSyntaxException e )
{
- log.debug( "Malformed spam filter pattern "+pattern );
+ log.debug( "Malformed spam filter pattern " + pattern );
- source.setAttribute("error", "Malformed spam filter pattern "+pattern);
+ source.setAttribute( "error", "Malformed spam filter pattern " + pattern );
}
}
}
@@ -391,11 +428,11 @@
}
/**
- * Takes a MT-Blacklist -formatted blacklist and returns a list of compiled
- * Pattern objects.
- *
- * @param list
- * @return The parsed blacklist patterns.
+ * Takes a MT-Blacklist -formatted blacklist and returns a list of compiled
+ * Pattern objects.
+ *
+ * @param list
+ * @return The parsed blacklist patterns.
*/
private Collection<Pattern> parseBlacklist( String list )
{
@@ -405,21 +442,25 @@
{
try
{
- BufferedReader in = new BufferedReader( new StringReader(list) );
+ BufferedReader in = new BufferedReader( new StringReader( list ) );
String line;
- while( (line = in.readLine()) != null )
+ while ( (line = in.readLine()) != null )
{
line = line.trim();
- if( line.length() == 0 ) continue; // Empty line
- if( line.startsWith("#") ) continue; // It's a comment
+ if( line.length() == 0 )
+ continue; // Empty line
+ if( line.startsWith( "#" ) )
+ continue; // It's a comment
- int ws = line.indexOf(' ');
+ int ws = line.indexOf( ' ' );
- if( ws == -1 ) ws = line.indexOf('\t');
+ if( ws == -1 )
+ ws = line.indexOf( '\t' );
- if( ws != -1 ) line = line.substring(0,ws);
+ if( ws != -1 )
+ line = line.substring( 0, ws );
try
{
@@ -427,13 +468,13 @@
}
catch( PatternSyntaxException e )
{
- log.debug( "Malformed spam filter pattern "+line );
+ log.debug( "Malformed spam filter pattern " + line );
}
}
}
catch( IOException e )
{
- log.info("Could not read patterns; returning what I got",e);
+ log.info( "Could not read patterns; returning what I got", e );
}
}
@@ -441,15 +482,14 @@
}
/**
- * Takes a single page change and performs a load of tests on the content change.
- * An admin can modify anything.
- *
- * @param context
- * @param content
- * @throws RedirectException
+ * Takes a single page change and performs a load of tests on the content
+ * change. An admin can modify anything.
+ *
+ * @param context
+ * @param content
+ * @throws RedirectException
*/
- private synchronized void checkSinglePageChange( WikiContext context, String content, Change change )
- throws RedirectException
+ private synchronized void checkSinglePageChange( WikiContext context, String content, Change change ) throws RedirectException
{
HttpServletRequest req = context.getHttpRequest();
@@ -459,20 +499,20 @@
int hostCounter = 0;
int changeCounter = 0;
- log.debug("Change is "+change.m_change);
+ log.debug( "Change is " + change.m_change );
- long time = System.currentTimeMillis()-60*1000L; // 1 minute
+ long time = System.currentTimeMillis() - 60 * 1000L; // 1 minute
for( Iterator<Host> i = m_lastModifications.iterator(); i.hasNext(); )
{
Host host = i.next();
//
- // Check if this item is invalid
+ // Check if this item is invalid
//
if( host.getAddedTime() < time )
{
- log.debug("Removed host "+host.getAddress()+" from modification queue (expired)");
+ log.debug( "Removed host " + host.getAddress() + " from modification queue (expired)" );
i.remove();
continue;
}
@@ -481,23 +521,23 @@
// Check if this IP address has been seen before
//
- if( host.getAddress().equals(addr) )
+ if( host.getAddress().equals( addr ) )
{
hostCounter++;
}
//
- // Check, if this change has been seen before
+ // Check, if this change has been seen before
//
- if( host.getChange() != null && host.getChange().equals(change) )
+ if( host.getChange() != null && host.getChange().equals( change ) )
{
changeCounter++;
}
}
//
- // Now, let's check against the limits.
+ // Now, let's check against the limits.
//
if( hostCounter >= m_limitSinglePageChanges )
{
@@ -506,8 +546,10 @@
m_temporaryBanList.add( host );
String uid = log( context, REJECT, REASON_TOO_MANY_MODIFICATIONS, change.m_change );
- log.info( "SPAM:TooManyModifications ("+uid+"). Added host "+addr+" to temporary ban list for doing too many modifications/minute" );
- checkStrategy( context, REASON_TOO_MANY_MODIFICATIONS, "Herb says you look like a spammer, and I trust Herb! (Incident code "+uid+")" );
+ log.info( "SPAM:TooManyModifications (" + uid + "). Added host " + addr
+ + " to temporary ban list for doing too many modifications/minute" );
+ checkStrategy( context, REASON_TOO_MANY_MODIFICATIONS,
+ "Herb says you look like a spammer, and I trust Herb! (Incident code " + uid + ")" );
}
if( changeCounter >= m_limitSimilarChanges )
@@ -518,23 +560,25 @@
String uid = log( context, REJECT, REASON_SIMILAR_MODIFICATIONS, change.m_change );
- log.info("SPAM:SimilarModifications ("+uid+"). Added host "+addr+" to temporary ban list for doing too many similar modifications" );
- checkStrategy( context, REASON_SIMILAR_MODIFICATIONS, "Herb says you look like a spammer, and I trust Herb! (Incident code "+uid+")");
+ log.info( "SPAM:SimilarModifications (" + uid + "). Added host " + addr
+ + " to temporary ban list for doing too many similar modifications" );
+ checkStrategy( context, REASON_SIMILAR_MODIFICATIONS,
+ "Herb says you look like a spammer, and I trust Herb! (Incident code " + uid + ")" );
}
//
- // Calculate the number of links in the addition.
+ // Calculate the number of links in the addition.
//
String tstChange = change.toString();
- int urlCounter = 0;
+ int urlCounter = 0;
Matcher matcher = m_urlPattern.matcher( tstChange );
- while( matcher.find() )
+ while ( matcher.find() )
{
MatchResult m = matcher.toMatchResult();
- tstChange = tstChange.substring( m.end(0) );
+ tstChange = tstChange.substring( m.end( 0 ) );
urlCounter++;
}
@@ -547,25 +591,27 @@
String uid = log( context, REJECT, REASON_TOO_MANY_URLS, change.toString() );
- log.info("SPAM:TooManyUrls ("+uid+"). Added host "+addr+" to temporary ban list for adding too many URLs" );
- checkStrategy( context, REASON_TOO_MANY_URLS, "Herb says you look like a spammer, and I trust Herb! (Incident code "+uid+")" );
+ log.info( "SPAM:TooManyUrls (" + uid + "). Added host " + addr + " to temporary ban list for adding too many URLs" );
+ checkStrategy( context, REASON_TOO_MANY_URLS,
+ "Herb says you look like a spammer, and I trust Herb! (Incident code " + uid + ")" );
}
//
- // Check bot trap
+ // Check bot trap
//
checkBotTrap( context, change );
//
- // Check UTF-8 mangling
+ // Check UTF-8 mangling
//
checkUTF8( context, change );
//
- // Do Akismet check. This is good to be the last, because this is the most
- // expensive operation.
+ // Do Akismet check. This is good to be the last, because this is
+ // the most
+ // expensive operation.
//
checkAkismet( context, change );
@@ -574,28 +620,26 @@
}
}
-
/**
- * Checks against the akismet system.
- *
+ * Checks against the akismet system.
+ *
* @param context
* @param change
* @throws RedirectException
*/
- private void checkAkismet( WikiContext context, Change change )
- throws RedirectException
+ private void checkAkismet( WikiContext context, Change change ) throws RedirectException
{
if( m_akismetAPIKey != null )
{
if( m_akismet == null )
{
- log.info("Initializing Akismet spam protection.");
+ log.info( "Initializing Akismet spam protection." );
m_akismet = new Akismet( m_akismetAPIKey, context.getEngine().getBaseURL() );
if( !m_akismet.verifyAPIKey() )
{
- log.error("Akismet API key cannot be verified. Please check your config.");
+ log.error( "Akismet API key cannot be verified. Please check your config." );
m_akismetAPIKey = null;
m_akismet = null;
}
@@ -604,44 +648,36 @@
HttpServletRequest req = context.getHttpRequest();
//
- // Akismet will mark all empty statements as spam, so we'll just
- // ignore them.
+ // Akismet will mark all empty statements as spam, so we'll just
+ // ignore them.
//
if( change.m_adds == 0 && change.m_removals > 0 )
{
return;
}
-
+
if( req != null && m_akismet != null )
{
- log.debug("Calling Akismet to check for spam...");
+ log.debug( "Calling Akismet to check for spam..." );
StopWatch sw = new StopWatch();
sw.start();
- String ipAddress = req.getRemoteAddr();
- String userAgent = req.getHeader("User-Agent");
- String referrer = req.getHeader( "Referer");
- String permalink = context.getViewURL( context.getPage().getName() );
- String commentType = context.getRequestContext().equals(WikiContext.COMMENT) ? "comment" : "edit";
+ String ipAddress = req.getRemoteAddr();
+ String userAgent = req.getHeader( "User-Agent" );
+ String referrer = req.getHeader( "Referer" );
+ String permalink = context.getViewURL( context.getPage().getName() );
+ String commentType = context.getRequestContext().equals( WikiContext.COMMENT ) ? "comment" : "edit";
String commentAuthor = context.getCurrentUser().getName();
String commentAuthorEmail = null;
- String commentAuthorURL = null;
+ String commentAuthorURL = null;
- boolean isSpam = m_akismet.commentCheck( ipAddress,
- userAgent,
- referrer,
- permalink,
- commentType,
- commentAuthor,
- commentAuthorEmail,
- commentAuthorURL,
- change.toString(),
- null );
+ boolean isSpam = m_akismet.commentCheck( ipAddress, userAgent, referrer, permalink, commentType, commentAuthor,
+ commentAuthorEmail, commentAuthorURL, change.toString(), null );
sw.stop();
- log.debug("Akismet request done in: "+sw);
+ log.debug( "Akismet request done in: " + sw );
if( isSpam )
{
@@ -651,19 +687,21 @@
String uid = log( context, REJECT, REASON_AKISMET, change.toString() );
- log.info("SPAM:Akismet ("+uid+"). Akismet thinks this change is spam; added host to temporary ban list.");
+ log.info( "SPAM:Akismet (" + uid + "). Akismet thinks this change is spam; added host to temporary ban list." );
- checkStrategy( context, REASON_AKISMET, "Akismet tells Herb you're a spammer, Herb trusts Akismet, and I trust Herb! (Incident code "+uid+")");
+ checkStrategy( context, REASON_AKISMET,
+ "Akismet tells Herb you're a spammer, Herb trusts Akismet, and I trust Herb! (Incident code "
+ + uid + ")" );
}
}
}
}
/**
- * Returns a static string which can be used to detect spambots which
- * just wildly fill in all the fields.
- *
- * @return A string
+ * Returns a static string which can be used to detect spambots which just
+ * wildly fill in all the fields.
+ *
+ * @return A string
*/
public static String getBotFieldName()
{
@@ -671,11 +709,11 @@
}
/**
- * This checks whether an invisible field is available in the request, and
- * whether it's contents are suspected spam.
- *
- * @param context
- * @param change
+ * This checks whether an invisible field is available in the request, and
+ * whether it's contents are suspected spam.
+ *
+ * @param context
+ * @param change
* @throws RedirectException
*/
private void checkBotTrap( WikiContext context, Change change ) throws RedirectException
@@ -689,9 +727,9 @@
{
String uid = log( context, REJECT, REASON_BOT_TRAP, change.toString() );
- log.info("SPAM:BotTrap ("+uid+"). Wildly behaving bot detected.");
+ log.info( "SPAM:BotTrap (" + uid + "). Wildly behaving bot detected." );
- checkStrategy( context, REASON_BOT_TRAP, "Spamming attempt detected. (Incident code "+uid+")");
+ checkStrategy( context, REASON_BOT_TRAP, "Spamming attempt detected. (Incident code " + uid + ")" );
}
}
@@ -705,19 +743,20 @@
{
String utf8field = request.getParameter( "encodingcheck" );
- if( utf8field != null && !utf8field.equals("\u3041") )
+ if( utf8field != null && !utf8field.equals( "\u3041" ) )
{
String uid = log( context, REJECT, REASON_UTF8_TRAP, change.toString() );
- log.info("SPAM:UTF8Trap ("+uid+"). Wildly posting dumb bot detected.");
+ log.info( "SPAM:UTF8Trap (" + uid + "). Wildly posting dumb bot detected." );
- checkStrategy( context, REASON_UTF8_TRAP, "Spamming attempt detected. (Incident code "+uid+")");
+ checkStrategy( context, REASON_UTF8_TRAP, "Spamming attempt detected. (Incident code " + uid + ")" );
}
}
}
/**
- * Goes through the ban list and cleans away any host which has expired from it.
+ * Goes through the ban list and cleans away any host which has expired from
+ * it.
*/
private synchronized void cleanBanList()
{
@@ -729,21 +768,20 @@
if( host.getReleaseTime() < now )
{
- log.debug("Removed host "+host.getAddress()+" from temporary ban list (expired)");
+ log.debug( "Removed host " + host.getAddress() + " from temporary ban list (expired)" );
i.remove();
}
}
}
/**
- * Checks the ban list if the IP address of the changer is already on it.
- *
- * @param context
- * @throws RedirectException
+ * Checks the ban list if the IP address of the changer is already on it.
+ *
+ * @param context
+ * @throws RedirectException
*/
- private void checkBanList( WikiContext context, Change change )
- throws RedirectException
+ private void checkBanList( WikiContext context, Change change ) throws RedirectException
{
HttpServletRequest req = context.getHttpRequest();
@@ -755,13 +793,15 @@
for( Host host : m_temporaryBanList )
{
- if( host.getAddress().equals(remote) )
+ if( host.getAddress().equals( remote ) )
{
long timeleft = (host.getReleaseTime() - now) / 1000L;
log( context, REJECT, REASON_IP_BANNED_TEMPORARILY, change.m_change );
- checkStrategy( context, REASON_IP_BANNED_TEMPORARILY, "You have been temporarily banned from modifying this wiki. ("+timeleft+" seconds of ban left)");
+ checkStrategy( context, REASON_IP_BANNED_TEMPORARILY,
+ "You have been temporarily banned from modifying this wiki. (" + timeleft
+ + " seconds of ban left)" );
}
}
}
@@ -769,10 +809,10 @@
}
/**
- * If the spam filter notices changes in the black list page, it will refresh
- * them automatically.
- *
- * @param context
+ * If the spam filter notices changes in the black list page, it will
+ * refresh them automatically.
+ *
+ * @param context
*/
private void refreshBlacklists( WikiContext context )
{
@@ -793,11 +833,11 @@
boolean rebuild = false;
//
- // Rebuild, if the page or the attachment has changed since.
+ // Rebuild, if the page or the attachment has changed since.
//
if( source != null )
{
- if( m_spamPatterns == null || m_spamPatterns.isEmpty() || source.getLastModified().after(m_lastRebuild) )
+ if( m_spamPatterns == null || m_spamPatterns.isEmpty() || source.getLastModified().after( m_lastRebuild ) )
{
rebuild = true;
}
@@ -805,38 +845,38 @@
if( att != null )
{
- if( m_spamPatterns == null || m_spamPatterns.isEmpty() || att.getLastModified().after(m_lastRebuild) )
+ if( m_spamPatterns == null || m_spamPatterns.isEmpty() || att.getLastModified().after( m_lastRebuild ) )
{
rebuild = true;
}
}
-
//
- // Do the actual rebuilding. For simplicity's sake, we always rebuild the complete
- // filter list regardless of what changed.
+ // Do the actual rebuilding. For simplicity's sake, we always
+ // rebuild the complete
+ // filter list regardless of what changed.
//
if( rebuild )
{
m_lastRebuild = new Date();
- m_spamPatterns = parseWordList( source,
- (source != null) ? (String)source.getAttribute( LISTVAR ) : null );
+ m_spamPatterns = parseWordList( source, (source != null) ? (String) source.getAttribute( LISTVAR ) : null );
- log.info("Spam filter reloaded - recognizing "+m_spamPatterns.size()+" patterns from page "+m_forbiddenWordsPage);
+ log.info( "Spam filter reloaded - recognizing " + m_spamPatterns.size() + " patterns from page "
+ + m_forbiddenWordsPage );
if( att != null )
{
- InputStream in = context.getEngine().getAttachmentManager().getAttachmentStream(att);
+ InputStream in = context.getEngine().getAttachmentManager().getAttachmentStream( att );
StringWriter out = new StringWriter();
- FileUtil.copyContents( new InputStreamReader(in,"UTF-8"), out );
+ FileUtil.copyContents( new InputStreamReader( in, "UTF-8" ), out );
Collection<Pattern> blackList = parseBlacklist( out.toString() );
- log.info("...recognizing additional "+blackList.size()+" patterns from blacklist "+m_blacklist);
+ log.info( "...recognizing additional " + blackList.size() + " patterns from blacklist " + m_blacklist );
m_spamPatterns.addAll( blackList );
}
@@ -844,28 +884,28 @@
}
catch( IOException ex )
{
- log.info("Unable to read attachment data, continuing...",ex);
+ log.info( "Unable to read attachment data, continuing...", ex );
}
catch( ProviderException ex )
{
- log.info("Failed to read spam filter attachment, continuing...",ex);
+ log.info( "Failed to read spam filter attachment, continuing...", ex );
}
}
/**
- * Does a check against a known pattern list.
- *
- * @param context
- * @param content
- * @param change
- * @throws RedirectException
+ * Does a check against a known pattern list.
+ *
+ * @param context
+ * @param content
+ * @param change
+ * @throws RedirectException
*/
- private void checkPatternList(WikiContext context, String content, Change change) throws RedirectException
+ private void checkPatternList( WikiContext context, String content, Change change ) throws RedirectException
{
//
- // If we have no spam patterns defined, or we're trying to save
- // the page containing the patterns, just return.
+ // If we have no spam patterns defined, or we're trying to save
+ // the page containing the patterns, just return.
//
if( m_spamPatterns == null || context.getPage().getName().equals( m_forbiddenWordsPage ) )
{
@@ -873,42 +913,44 @@
}
String ch = change.toString();
-
+
if( context.getHttpRequest() != null )
ch += context.getHttpRequest().getRemoteAddr();
for( Pattern p : m_spamPatterns )
{
- // log.debug("Attempting to match page contents with "+p.getPattern());
+ // log.debug("Attempting to match page contents with
+ // "+p.getPattern());
Matcher matcher = p.matcher( ch );
- if( matcher.find( ) )
+ if( matcher.find() )
{
//
- // Spam filter has a match.
+ // Spam filter has a match.
//
- String uid = log( context, REJECT, REASON_REGEXP+"("+p.pattern()+")", change.toString());
+ String uid = log( context, REJECT, REASON_REGEXP + "(" + p.pattern() + ")", change.toString() );
- log.info("SPAM:Regexp ("+uid+"). Content matches the spam filter '"+p.pattern()+"'");
+ log.info( "SPAM:Regexp (" + uid + "). Content matches the spam filter '" + p.pattern() + "'" );
- checkStrategy( context, REASON_REGEXP, "Herb says '"+p.pattern()+"' is a bad spam word and I trust Herb! (Incident code "+uid+")");
+ checkStrategy( context, REASON_REGEXP, "Herb says '" + p.pattern()
+ + "' is a bad spam word and I trust Herb! (Incident code " + uid + ")" );
}
}
}
- private void checkPatternList(WikiContext context, String content, String change ) throws RedirectException
+ private void checkPatternList( WikiContext context, String content, String change ) throws RedirectException
{
Change c = new Change();
c.m_change = change;
- checkPatternList(context,content,c);
+ checkPatternList( context, content, c );
}
-
+
/**
- * Creates a simple text string describing the added content.
- *
- * @param context
- * @param newText
- * @return Empty string, if there is no change.
+ * Creates a simple text string describing the added content.
+ *
+ * @param context
+ * @param newText
+ * @return Empty string, if there is no change.
*/
private static Change getChange( WikiContext context, String newText )
{
@@ -918,23 +960,23 @@
// Get current page version
Change ch = new Change();
-
+
try
{
- String oldText = engine.getPureText(page.getName(), WikiProvider.LATEST_VERSION);
+ String oldText = engine.getPureText( page.getName(), WikiProvider.LATEST_VERSION );
- String[] first = Diff.stringToArray(oldText);
- String[] second = Diff.stringToArray(newText);
- Revision rev = Diff.diff(first, second, new MyersDiff());
+ String[] first = Diff.stringToArray( oldText );
+ String[] second = Diff.stringToArray( newText );
+ Revision rev = Diff.diff( first, second, new MyersDiff() );
if( rev == null || rev.size() == 0 )
{
return ch;
}
-
+
for( int i = 0; i < rev.size(); i++ )
{
- Delta d = rev.getDelta(i);
+ Delta d = rev.getDelta( i );
if( d instanceof AddDelta )
{
@@ -952,29 +994,29 @@
}
}
}
- catch (DifferentiationFailedException e)
+ catch( DifferentiationFailedException e )
{
log.error( "Diff failed", e );
}
//
- // Don't forget to include the change note, too
+ // Don't forget to include the change note, too
//
- String changeNote = (String)page.getAttribute(WikiPage.CHANGENOTE);
+ String changeNote = (String) page.getAttribute( WikiPage.CHANGENOTE );
if( changeNote != null )
{
- change.append("\r\n");
- change.append(changeNote);
+ change.append( "\r\n" );
+ change.append( changeNote );
}
//
- // And author as well
+ // And author as well
//
if( page.getAuthor() != null )
{
- change.append("\r\n"+page.getAuthor());
+ change.append( "\r\n" + page.getAuthor() );
}
ch.m_change = change.toString();
@@ -982,12 +1024,12 @@
}
/**
- * Returns true, if this user should be ignored. For example, admin users.
- *
+ * Returns true, if this user should be ignored. For example, admin users.
+ *
* @param context
* @return True, if this users should be ignored.
*/
- private boolean ignoreThisUser(WikiContext context)
+ private boolean ignoreThisUser( WikiContext context )
{
if( context.hasAdminPermissions() )
{
@@ -999,7 +1041,7 @@
return true;
}
- if( context.getVariable("captcha") != null )
+ if( context.getVariable( "captcha" ) != null )
{
return true;
}
@@ -1008,9 +1050,9 @@
}
/**
- * Returns a random string of six uppercase characters.
- *
- * @return A random string
+ * Returns a random string of six uppercase characters.
+ *
+ * @return A random string
*/
private static String getUniqueID()
{
@@ -1019,36 +1061,37 @@
for( int i = 0; i < 6; i++ )
{
- char x = (char)('A'+rand.nextInt(26));
+ char x = (char) ('A' + rand.nextInt( 26 ));
- sb.append(x);
+ sb.append( x );
}
return sb.toString();
}
/**
- * Returns a page to which we shall redirect, based on the current value
- * of the "captcha" parameter.
- *
- * @param ctx WikiContext
- * @return An URL to redirect to
+ * Returns a page to which we shall redirect, based on the current value of
+ * the "captcha" parameter.
+ *
+ * @param ctx WikiContext
+ * @return An URL to redirect to
*/
private String getRedirectPage( WikiContext ctx )
{
if( m_useCaptcha )
- return ctx.getURL( WikiContext.NONE, "Captcha.jsp", "page="+ctx.getEngine().encodeName(ctx.getPage().getName()) );
+ return ctx.getURL( WikiContext.NONE, "Captcha.jsp", "page=" + ctx.getEngine().encodeName( ctx.getPage().getName() ) );
return ctx.getURL( WikiContext.VIEW, m_errorPage );
}
/**
- * Checks whether the UserProfile matches certain checks.
- *
- * @param profile The profile to check
- * @param context The WikiContext
- * @return False, if this userprofile is suspect and should not be allowed to be added.
- * @since 2.6.1
+ * Checks whether the UserProfile matches certain checks.
+ *
+ * @param profile The profile to check
+ * @param context The WikiContext
+ * @return False, if this userprofile is suspect and should not be allowed
+ * to be added.
+ * @since 2.6.1
*/
public boolean isValidUserProfile( WikiContext context, UserProfile profile )
{
@@ -1060,7 +1103,7 @@
}
catch( RedirectException e )
{
- log.info("Detected attempt to create a spammer user account (see above for rejection reason)");
+ log.info( "Detected attempt to create a spammer user account (see above for rejection reason)" );
return false;
}
@@ -1068,14 +1111,14 @@
}
/**
- * This method is used to calculate an unique code when submitting the page
- * to detect edit conflicts. It currently incorporates the last-modified
- * date of the page, and the IP address of the submitter.
- *
- * @param page The WikiPage under edit
- * @param request The HTTP Request
- * @since 2.6
- * @return A hash value for this page and session
+ * This method is used to calculate an unique code when submitting the page
+ * to detect edit conflicts. It currently incorporates the last-modified
+ * date of the page, and the IP address of the submitter.
+ *
+ * @param page The WikiPage under edit
+ * @param request The HTTP Request
+ * @since 2.6
+ * @return A hash value for this page and session
*/
public static final String getSpamHash( WikiPage page, HttpServletRequest request )
{
@@ -1090,13 +1133,13 @@
}
/**
- * Returns the name of the hash field to be used in this request.
- * The value is unique per session, and once the session has expired,
- * you cannot edit anymore.
- *
- * @param request The page request
- * @return The name to be used in the hash field
- * @since 2.6
+ * Returns the name of the hash field to be used in this request. The value
+ * is unique per session, and once the session has expired, you cannot edit
+ * anymore.
+ *
+ * @param request The page request
+ * @return The name to be used in the hash field
+ * @since 2.6
*/
public static final String getHashFieldName( HttpServletRequest request )
@@ -1105,7 +1148,7 @@
if( request.getSession() != null )
{
- hash = (String)request.getSession().getAttribute("_hash");
+ hash = (String) request.getSession().getAttribute( "_hash" );
if( hash == null )
{
@@ -1115,7 +1158,7 @@
}
}
- if( c_hashFieldName == null || c_lastUpdate < (System.currentTimeMillis() - HASH_DELAY*60*60*1000) )
+ if( c_hashFieldName == null || c_lastUpdate < (System.currentTimeMillis() - HASH_DELAY * 60 * 60 * 1000) )
{
c_hashFieldName = getUniqueID().toLowerCase();
@@ -1126,47 +1169,67 @@
}
/**
- * <p>This method checks if the hash value is still valid, i.e. if it exists at all. This
- * can occur in two cases: either this is a spam bot which is not adaptive, or it is
- * someone who has been editing one page for too long, and their session has expired.</p>
- * <p>If the hash is not valid, this method returns a Stripes
- * {@link net.sourceforge.stripes.action.RedirectResolution} that directs
- * users to wiki page "SessionExpired" and logs the incident in the spam log
- * (it may or may not be spam, but it's rather likely that it is).</p>
- * <p>If the hash is valid, this method simply returns <code>null</code>.</p>
- * <p>Other than the differences in the method parameters and return syntax, this
- * method operates in every other respect identically to
- * {@link #checkHash(WikiContext, PageContext)}</p>
- *
- * @param actionBean the WikiActionBean representing the editing activity and page.
- * @return <code>null</code> if hash is okay, or a RedirectResolution if not.
- * @since 3.0
+ * <p>
+ * This method checks if the hash value is still valid, i.e. if it exists at
+ * all. This can occur in two cases: either this is a spam bot which is not
+ * adaptive, or it is someone who has been editing one page for too long,
+ * and their session has expired.
+ * </p>
+ * <p>
+ * If the hash is not valid, this method logs the incident in the spam log
+ * (it may or may not be spam, but it's rather likely that it is) and throws
+ * an exception.
+ * </p>
+ * <p>
+ * If the hash is valid, this method simply returns succeeds silently.
+ * </p>
+ * <p>
+ * Other than the differences in the method parameters and return syntax,
+ * this method operates in every other respect identically to
+ * {@link #checkHash(WikiContext, PageContext)}
+ * </p>
+ *
+ * @param actionBean the WikiActionBean representing the editing activity
+ * and page.
+ * @param beanProperties an array of Strings containing the names of
+ * ActionBean properties that are considered "protected" by the
+ * SpamFilter. Each value represents the name of a bean property.
+ * For example, the value "text" which would be manipulated with
+ * the ActionBean's <code>getText</code> and
+ * <code>setText</code> methods). When spam parameters are
+ * missing, the protected properties' values will be added to the
+ * SpamFilter log for analysis.
+ * @throws MissingParameterException if one or more of the spam-protection
+ * parameters are missing or contain invalid values
+ * @since 3.0
*/
- public static final Resolution validateSpamParams( WikiActionBean actionBean )
+ public static final void validateSpamParams( WikiActionBean actionBean, String[] beanProperties )
+ throws MissingParameterException
{
WikiActionBeanContext context = actionBean.getContext();
- HttpServletRequest request = (HttpServletRequest)context.getRequest();
+ HttpServletRequest request = (HttpServletRequest) context.getRequest();
- // Recover the encrypted parameter and then validate the trap and token fields
+ // Recover the encrypted parameter and then validate the trap and token
+ // fields
boolean spamParamsValid = false;
- String encryptedParam = request.getParameter( SpamInterceptor.REQ_SPAM_PARAM );
- if ( encryptedParam != null )
+ String encryptedParam = request.getParameter( REQ_SPAM_PARAM );
+ if( encryptedParam != null )
{
String payload = CryptoUtil.decrypt( encryptedParam );
- if ( payload != null )
+ if( payload != null )
{
String[] spamParams = payload.split( "\n" );
- if ( spamParams.length != 2 )
+ if( spamParams.length >= 2 )
{
String trapParam = request.getParameter( spamParams[0] );
String tokenParam = request.getParameter( spamParams[1] );
-
+
// Trap parameter should be blank/null
- if ( trapParam == null || trapParam.length() == 0 )
+ if( trapParam == null || trapParam.length() == 0 )
{
-
+
// Token parameter should simply be the session ID
- if ( tokenParam != null && request.getSession().getId().equals( tokenParam ))
+ if( tokenParam != null && request.getSession().getId().equals( tokenParam ) )
{
// If we got here, everything validated ok!
spamParamsValid = true;
@@ -1175,55 +1238,90 @@
}
}
}
-
+
if( !spamParamsValid )
{
- Change change = getChange( context, EditorManager.getEditedText( context.getRequest() ) );
- log( context, REJECT, "MissingHash", change.m_change );
- return new RedirectResolution( ViewActionBean.class, "view" ).addParameter( "name", "SessionExpired");
+ // Collect all of the protected properties and log 'em
+ Map<String, Object> map = getBeanProperties( actionBean, beanProperties );
+ SpamFilter.log( actionBean.getContext(), SpamFilter.REJECT, "MissingHash", map.toString() );
+ throw new MissingParameterException( "Missing SpamProtect parameters! Likely to be a spammer.", null );
}
- return null;
-
}
-
- public static Resolution validateUTF8Param( WikiActionBean actionBean )
+
+ public static void validateUTF8Param( WikiActionBean actionBean ) throws MissingParameterException
{
WikiActionBeanContext context = actionBean.getContext();
HttpServletRequest request = context.getHttpRequest();
- if ( request != null )
+ if( request != null )
{
- String utf8field = request.getParameter( SpamInterceptor.REQ_ENCODING_CHECK );
- if( utf8field != null && utf8field.equals("\u3041") )
+ String utf8field = request.getParameter( REQ_ENCODING_CHECK );
+ if( utf8field != null && utf8field.equals( "\u3041" ) )
{
- return null;
+ return;
+ }
+ }
+ String uid = SpamFilter.log( actionBean.getContext(), SpamFilter.REJECT, SpamFilter.REASON_UTF8_TRAP, request
+ .getRemoteAddr() );
+ log.info( "SPAM:UTF8Trap (" + uid + "). Wildly posting dumb bot detected." );
+ throw new MissingParameterException( "Missing UTF-8 parameter! Likely to be a spammer.", null );
+ }
+
+ /**
+ * Introspects an ActionBean and returns the value for one or more supplied
+ * properties. Any properties not found will be cheerfully ignored.
+ *
+ * @param actionBean the actionBean to inspect
+ * @param beanProperties the bean properties to examine
+ * @return the values if successfully evaluated, or <code>null</code> if
+ * not (or not set)
+ */
+ protected static Map<String, Object> getBeanProperties( WikiActionBean actionBean, String[] beanProperties )
+ {
+ Map<String, Object> map = new HashMap<String, Object>();
+ for( String beanProperty : beanProperties )
+ {
+ try
+ {
+ PropertyExpression propExpression = PropertyExpression.getExpression( beanProperty );
+ PropertyExpressionEvaluation evaluation = new PropertyExpressionEvaluation( propExpression, actionBean );
+ Object value = evaluation.getValue();
+ {
+ if( value != null )
+ {
+ map.put( beanProperty, value );
+ }
+ }
+ }
+ catch( NoSuchPropertyException e )
+ {
+ // Ignore any missing properties
}
}
- String uid = log( context, REJECT, REASON_UTF8_TRAP, request.getRemoteAddr() );
- log.info("SPAM:UTF8Trap ("+uid+"). Wildly posting dumb bot detected.");
- return new RedirectResolution( ViewActionBean.class, "view" ).addParameter( "name", "SessionExpired");
+ return map;
}
/**
- * This method checks if the hash value is still valid, i.e. if it exists at all. This
- * can occur in two cases: either this is a spam bot which is not adaptive, or it is
- * someone who has been editing one page for too long, and their session has expired.
- * <p>
- * This method puts a redirect to the http response field to page "SessionExpired"
- * and logs the incident in the spam log (it may or may not be spam, but it's rather likely
- * that it is).
- *
- * @param context The WikiContext
- * @param pageContext The JSP PageContext.
- * @return True, if hash is okay. False, if hash is not okay, and you need to redirect.
- * @throws IOException If redirection fails
- * @since 2.6
+ * This method checks if the hash value is still valid, i.e. if it exists at
+ * all. This can occur in two cases: either this is a spam bot which is not
+ * adaptive, or it is someone who has been editing one page for too long,
+ * and their session has expired.
+ * <p>
+ * This method puts a redirect to the http response field to page
+ * "SessionExpired" and logs the incident in the spam log (it may or may not
+ * be spam, but it's rather likely that it is).
+ *
+ * @param context The WikiContext
+ * @param pageContext The JSP PageContext.
+ * @return True, if hash is okay. False, if hash is not okay, and you need
+ * to redirect.
+ * @throws IOException If redirection fails
+ * @since 2.6
*/
- public static final boolean checkHash( WikiContext context, PageContext pageContext )
- throws IOException
+ public static final boolean checkHash( WikiContext context, PageContext pageContext ) throws IOException
{
- String hashName = getHashFieldName( (HttpServletRequest)pageContext.getRequest() );
+ String hashName = getHashFieldName( (HttpServletRequest) pageContext.getRequest() );
- if( pageContext.getRequest().getParameter(hashName) == null )
+ if( pageContext.getRequest().getParameter( hashName ) == null )
{
if( pageContext.getAttribute( hashName ) == null )
{
@@ -1231,8 +1329,8 @@
log( context, REJECT, "MissingHash", change.m_change );
- String redirect = context.getURL(WikiContext.VIEW,"SessionExpired");
- ((HttpServletResponse)pageContext.getResponse()).sendRedirect( redirect );
+ String redirect = context.getURL( WikiContext.VIEW, "SessionExpired" );
+ ((HttpServletResponse) pageContext.getResponse()).sendRedirect( redirect );
return false;
}
@@ -1242,37 +1340,41 @@
}
/**
- * This helper method adds all the input fields to your editor that the SpamFilter requires
- * to check for spam. This <i>must</i> be in your editor form if you intend to use
- * the SpamFilter.
- *
- * @param pageContext The PageContext
- * @return A HTML string which contains input fields for the SpamFilter.
+ * This helper method adds all the input fields to your editor that the
+ * SpamFilter requires to check for spam. This <i>must</i> be in your
+ * editor form if you intend to use the SpamFilter.
+ *
+ * @param pageContext The PageContext
+ * @return A HTML string which contains input fields for the SpamFilter.
*/
public static final String insertInputFields( PageContext pageContext )
{
- WikiContext ctx = WikiContextFactory.findContext(pageContext);
+ WikiContext ctx = WikiContextFactory.findContext( pageContext );
WikiEngine engine = ctx.getEngine();
StringBuilder sb = new StringBuilder();
- if (engine.getContentEncoding().equals("UTF-8"))
+ if( engine.getContentEncoding().equals( "UTF-8" ) )
{
- sb.append("<input name='encodingcheck' type='hidden' value='\u3041' />\n");
+ sb.append( "<input name='encodingcheck' type='hidden' value='\u3041' />\n" );
}
return sb.toString();
}
+
/**
- * A local class for storing host information.
- *
- * @since
+ * A local class for storing host information.
+ *
+ * @since
*/
private class Host
{
- private long m_addedTime = System.currentTimeMillis();
- private long m_releaseTime;
- private String m_address;
- private Change m_change;
+ private long m_addedTime = System.currentTimeMillis();
+
+ private long m_releaseTime;
+
+ private String m_address;
+
+ private Change m_change;
public String getAddress()
{
@@ -1297,34 +1399,36 @@
public Host( String ipaddress, Change change )
{
m_address = ipaddress;
- m_change = change;
+ m_change = change;
m_releaseTime = System.currentTimeMillis() + m_banTime * 60 * 1000L;
}
}
-
+
private static class Change
{
public String m_change;
- public int m_adds;
- public int m_removals;
-
+
+ public int m_adds;
+
+ public int m_removals;
+
public String toString()
{
return m_change;
}
-
- public boolean equals(Object o)
+
+ public boolean equals( Object o )
{
if( o instanceof Change )
- return m_change.equals( ((Change)o).m_change);
-
+ return m_change.equals( ((Change) o).m_change );
+
return false;
}
-
+
public int hashCode()
{
- return m_change.hashCode()+17;
+ return m_change.hashCode() + 17;
}
}
}
Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/SpamProtectTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/SpamProtectTag.java?rev=766540&r1=766539&r2=766540&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/SpamProtectTag.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/tags/SpamProtectTag.java Sun Apr 19 22:31:36 2009
@@ -1,6 +1,7 @@
package org.apache.wiki.tags;
import java.io.IOException;
+import java.security.SecureRandom;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
@@ -11,14 +12,14 @@
import net.sourceforge.stripes.util.CryptoUtil;
import org.apache.wiki.filters.SpamFilter;
-import org.apache.wiki.filters.SpamInterceptor;
+import org.apache.wiki.ui.stripes.SpamInterceptor;
/**
* <p>
* Tag that injects hidden {@link SpamFilter}-related parameters into the
* current form, which will be parsed and verified by {@link SpamInterceptor}
* whenever the input is processed by an ActionBean event handler method
- * annotated with the {@link org.apache.wiki.filters.SpamProtect} annotation.
+ * annotated with the {@link org.apache.wiki.ui.stripes.SpamProtect} annotation.
* </p>
* <p>
* This tag will inject the following parameters:
@@ -43,7 +44,7 @@
* to be empty.</li>
* </li>
* <li><b>An an encrypted parameter</b> called
- * {@link SpamInterceptor#REQ_SPAM_PARAM}, whose contents are the names of
+ * {@link SpamFilter#REQ_SPAM_PARAM}, whose contents are the names of
* parameters 2 and 3, separated by a carriage return character. These contents
* are then encrypted.</li>
* </ol>
@@ -82,17 +83,17 @@
out.write( "<input name=\"" + tokenParam + "\" type=\"hidden\" value=\"" + tokenValue + "\" />\n" );
// Inject UTF-8 detector
- out.write( "<input name=\""+ SpamInterceptor.REQ_ENCODING_CHECK + "\" type=\"hidden\" value=\"\u3041\" />\n" );
+ out.write( "<input name=\""+ SpamFilter.REQ_ENCODING_CHECK + "\" type=\"hidden\" value=\"\u3041\" />\n" );
// Add encrypted parameter indicating the names of the trap and token fields
String encryptedParam = CryptoUtil.encrypt( trapParam + "\n" + tokenParam );
- out.write( "<input name=\""+ SpamInterceptor.REQ_SPAM_PARAM+"\" type=\"hidden\" value=\""+encryptedParam+"\" />\n" );
+ out.write( "<input name=\""+ SpamFilter.REQ_SPAM_PARAM+"\" type=\"hidden\" value=\""+encryptedParam+"\" />\n" );
}
private static String getUniqueID()
{
StringBuilder sb = new StringBuilder();
- Random rand = new Random();
+ Random rand = new SecureRandom();
for( int i = 0; i < 6; i++ )
{
Copied: incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamInterceptor.java (from r765589, incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamInterceptor.java)
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamInterceptor.java?p2=incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamInterceptor.java&p1=incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamInterceptor.java&r1=765589&r2=766540&rev=766540&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamInterceptor.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamInterceptor.java Sun Apr 19 22:31:36 2009
@@ -1,12 +1,18 @@
-package org.apache.wiki.filters;
+package org.apache.wiki.ui.stripes;
+import java.lang.reflect.Method;
+
+import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.controller.ExecutionContext;
import net.sourceforge.stripes.controller.Interceptor;
import net.sourceforge.stripes.controller.Intercepts;
import net.sourceforge.stripes.controller.LifecycleStage;
+import org.apache.wiki.action.ViewActionBean;
import org.apache.wiki.action.WikiActionBean;
+import org.apache.wiki.content.MissingParameterException;
+import org.apache.wiki.filters.SpamFilter;
/**
* Stripes Interceptor that ensures that SpamFilter algorithms are applied to
@@ -19,35 +25,52 @@
@Intercepts( { LifecycleStage.HandlerResolution } )
public class SpamInterceptor implements Interceptor
{
- /** Request parameter containing the UTF8 check. */
- public static final String REQ_ENCODING_CHECK = "encodingcheck";
-
- /** Request parameter containing the encoded payload. */
- public static final String REQ_SPAM_PARAM = "____sp____";
-
/**
* Validates spam parameters contained in any requests targeting an
* ActionBean method annotated with the {@link SpamProtect} annotation. This
- * simply delegates to {@link SpamFilter#validateSpamParams(WikiActionBean)}
- * and {@link SpamFilter#validateUTF8Param(WikiActionBean)} in sequence, and
- * returns any Resolutions they generate. If the targeted ActionBean event
- * is not annotated, this method returns <code>null</code>.
+ * simply delegates to
+ * {@link SpamFilter#validateSpamParams(WikiActionBean, String[])} and
+ * {@link SpamFilter#validateUTF8Param(WikiActionBean)} in sequence, and
+ * returns a {@link RedirectResolution} to the WikiPage
+ * <code>SessionExpired</code> if either of these checks fail. If the
+ * targeted ActionBean event is not annotated, this method returns
+ * <code>null</code>.
*/
public Resolution intercept( ExecutionContext context ) throws Exception
{
// Execute all other interceptors first
context.proceed();
- // Validate spam token/trap params
+ // Is the target handler protected by a @SpamProtect annotation?
WikiActionBean actionBean = (WikiActionBean) context.getActionBean();
- Resolution r = SpamFilter.validateSpamParams( actionBean );
+ Method handler = context.getHandler();
+ SpamProtect ann = handler.getAnnotation( SpamProtect.class );
+ if( ann == null )
+ {
+ return null;
+ }
+
+ // Validate spam token/trap params
+ try
+ {
+ SpamFilter.validateSpamParams( actionBean, ann.content() );
+ }
+ catch( MissingParameterException e )
+ {
+ return new RedirectResolution( ViewActionBean.class, "view" ).addParameter( "page", "SessionExpired" );
+ }
// Validate non-Latin1 param
- if( r != null )
+ try
{
- r = SpamFilter.validateUTF8Param( actionBean );
+ SpamFilter.validateUTF8Param( actionBean );
}
- return r;
+ catch( MissingParameterException e )
+ {
+ return new RedirectResolution( ViewActionBean.class, "view" ).addParameter( "page", "SessionExpired" );
+ }
+
+ return null;
}
}
Copied: incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamProtect.java (from r765589, incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamProtect.java)
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamProtect.java?p2=incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamProtect.java&p1=incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamProtect.java&r1=765589&r2=766540&rev=766540&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/filters/SpamProtect.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/ui/stripes/SpamProtect.java Sun Apr 19 22:31:36 2009
@@ -1,24 +1,31 @@
/**
*
*/
-package org.apache.wiki.filters;
+package org.apache.wiki.ui.stripes;
import java.lang.annotation.*;
+import org.apache.wiki.filters.SpamFilter;
+
/**
* Annotation indicating that an event handler method should check that the user
* has submitted a series of expected {@link SpamFilter}-related parameters
- * with the POST or GET. The SpamProtect annotation can be applied to either
- * class or method targets. If the annotation applies to a Stripes event handler
+ * with the POST or GET. The SpamProtect annotation can be applied to
+ * method targets. When annotating Stripes event handler
* method, the {@link SpamInterceptor} will apply spam filtering heuristics to
- * just the annotated event. If the annotation applies to a class, all event
- * handler methods will be filtered by default. Method-level annotations always
- * override class-level annotations.
+ * the annotated event.
*/
@Documented
@Inherited
@Retention( value = RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD, ElementType.TYPE } )
+@Target( { ElementType.METHOD } )
public @interface SpamProtect
{
+ /**
+ * The names of the bean properties containing the content being protected.
+ * This can be used, for example, to extract the protected content from
+ * annotated classes' by introspection. By default, this is a zero-argument
+ * array.
+ */
+ String[] content() default {};
}
Modified: incubator/jspwiki/trunk/tests/java/org/apache/wiki/TestEngine.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/java/org/apache/wiki/TestEngine.java?rev=766540&r1=766539&r2=766540&view=diff
==============================================================================
--- incubator/jspwiki/trunk/tests/java/org/apache/wiki/TestEngine.java (original)
+++ incubator/jspwiki/trunk/tests/java/org/apache/wiki/TestEngine.java Sun Apr 19 22:31:36 2009
@@ -36,6 +36,7 @@
import net.sourceforge.stripes.mock.MockHttpSession;
import net.sourceforge.stripes.mock.MockRoundtrip;
import net.sourceforge.stripes.mock.MockServletContext;
+import net.sourceforge.stripes.util.CryptoUtil;
import org.apache.wiki.action.WikiActionBean;
import org.apache.wiki.api.WikiException;
@@ -48,6 +49,7 @@
import org.apache.wiki.content.PageAlreadyExistsException;
import org.apache.wiki.content.PageNotFoundException;
import org.apache.wiki.content.WikiPath;
+import org.apache.wiki.filters.SpamFilter;
import org.apache.wiki.log.Logger;
import org.apache.wiki.log.LoggerFactory;
import org.apache.wiki.providers.AbstractFileProvider;
@@ -167,6 +169,22 @@
return request;
}
+ /**
+ * For testing purposes: generates and adds sample spam-protect form parameters to a MockRountrip object.
+ * This is done in the same way that {@link SpamProtectTag} does it.
+ */
+ public static void addSpamProtectParams( MockRoundtrip trip )
+ {
+ // Add the trap + token params
+ String paramValue = CryptoUtil.encrypt( "TRAPAA\nTOKENA" );
+ trip.addParameter( "TRAPAA", new String[0] );
+ trip.addParameter( "TOKENA", trip.getRequest().getSession().getId() );
+ trip.addParameter( SpamFilter.REQ_SPAM_PARAM, paramValue );
+
+ // Add the UTF-8 token
+ trip.addParameter( SpamFilter.REQ_ENCODING_CHECK, "\u3041" );
+ }
+
public static void emptyWorkDir()
{
Properties properties = new Properties();
Added: incubator/jspwiki/trunk/tests/java/org/apache/wiki/action/TestActionBean.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/java/org/apache/wiki/action/TestActionBean.java?rev=766540&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/java/org/apache/wiki/action/TestActionBean.java (added)
+++ incubator/jspwiki/trunk/tests/java/org/apache/wiki/action/TestActionBean.java Sun Apr 19 22:31:36 2009
@@ -0,0 +1,51 @@
+package org.apache.wiki.action;
+
+import net.sourceforge.stripes.action.Resolution;
+import net.sourceforge.stripes.validation.Validate;
+
+import org.apache.wiki.action.AbstractPageActionBean;
+import org.apache.wiki.api.WikiPage;
+import org.apache.wiki.ui.stripes.SpamProtect;
+
+/**
+ * Simple test bean with a single event handler method.
+ */
+public class TestActionBean extends AbstractPageActionBean
+{
+ @SpamProtect( content = "text" )
+ public Resolution test()
+ {
+ return null;
+ }
+
+ @Validate( required = false )
+ public void setPage( WikiPage page )
+ {
+ super.setPage( page );
+ }
+
+ private String text = null;
+
+ private String acl = null;
+
+ public String getText()
+ {
+ return text;
+ }
+
+ public void setText( String text )
+ {
+ this.text = text;
+ }
+
+ public String getAcl()
+ {
+ return acl;
+ }
+
+ public void setAcl( String acl )
+ {
+ this.acl = acl;
+ }
+
+}
\ No newline at end of file