jspwiki-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ajaqu...@apache.org
Subject svn commit: r627255 [25/41] - in /incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src: ./ com/ com/ecyrd/ com/ecyrd/jspwiki/ com/ecyrd/jspwiki/action/ com/ecyrd/jspwiki/attachment/ com/ecyrd/jspwiki/auth/ com/ecyrd/jspwiki/auth/acl/ com/ecyrd/jspwiki...
Date Wed, 13 Feb 2008 05:54:24 GMT
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/LinkParser.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/LinkParser.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/LinkParser.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/LinkParser.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,568 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2006 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package com.ecyrd.jspwiki.parser;
+
+import java.util.*;
+
+import org.apache.log4j.Logger;
+import org.jdom.Attribute;
+
+/**
+ *  Parses JSPWiki-style "augmented" link markup into a Link object
+ *  containing the link text, link reference, and any optional link
+ *  attributes (as JDOM Attributes).
+ *  <p>
+ *  The parser recognizes three link forms:
+ *  </p>
+ *  <ol>
+ *    <li><tt> [Text] </tt></li>
+ *    <li><tt> [Text | Link] </tt></li>
+ *    <li><tt> [Text | Link | attributes] </tt></li>
+ *  </ol>
+ *  <p>
+ *  where the attributes are space-delimited, each in the form of
+ *  </p>
+ *  <pre>
+ *      name1='value1' name2='value2' name3='value3' (etc.) </pre>
+ *  <p>
+ *  If the attribute parsing fails, the parser will still return the
+ *  basic link, writing a warning to the log.
+ *  </p>
+ *
+ *  <h3>Permitted Attributes</h3>
+ *  <p>
+ *  Attributes that aren't declared on <tt>&lt;a&gt;</tt> or those that
+ *  permit scripting in HTML (as this is a security risk) are ignored
+ *  and have no effect on parsing, nor show up in the resulting attribute
+ *  list). The 'href' and 'name' attributes are also ignored as spurious.
+ *  The permitted list is: 'accesskey', 'charset', 'class', 'hreflang',
+ *  'id', 'lang', 'dir', 'rel', 'rev', 'style' , 'tabindex', 'target' ,
+ *  'title', and 'type'. The declared attributes that will be ignored
+ *  are: 'href', 'name', 'shape', 'coords', 'onfocus', 'onblur', or any
+ *  of the other 'on*' event attributes.
+ *  </p>
+ *  <p>
+ *  The permitted attributes and target attribute values are static
+ *  String arrays ({@link #PERMITTED_ATTRIBUTES} and
+ *  {@link #PERMITTED_TARGET_VALUES} resp.) that could be compile-time
+ *  modified (i.e., predeclared).
+ *  </p>
+ *
+ *  <h3>Permitted Values on Target Attribute</h3>
+ *  <p>
+ *  The following target names are reserved in HTML 4 and have special
+ *  meanings. These are the only values permitted by the parser.
+ *  <dl>
+ *    <dt><b>_blank</b></dt>
+ *    <dd> The user agent should load the designated document in a new,
+ *    unnamed window. </dd>
+ *    <dt><b>_self</b></dt>
+ *    <dd> The user agent should load the document in the same frame as
+ *    the element that refers to this target. </dd>
+ *    <dt><b>_parent</b></dt>
+ *    <dd> The user agent should load the document into the immediate
+ *    FRAMESET parent of the current frame. This value is equivalent to
+ *    _self if the current frame has no parent. </dd>
+ *    <dt><b>_top</b></dt>
+ *    <dd> The user agent should load the document into the full,
+ *    original window (thus canceling all other frames). This value is
+ *    equivalent to _self if the current frame has no parent. </dd>
+ *  </dl>
+ *
+ *  <h3>Returned Value</h3>
+ *  <p>
+ *  This returns a <b>Link</b> object, a public inner class with methods:
+ *  <ul>
+ *    <li> <tt>getText()</tt> returns the link text. </li>
+ *    <li> <tt>getReference()</tt> returns the link reference value. </li>
+ *    <li> <tt>attributeCount()</tt> returns the number of declared attributes. </li>
+ *    <li> <tt>getAttributes()</tt> returns an iterator over any validated
+ *        XHTML-compliant attributes, returned as JDOM Attributes.
+ *    </li>
+ *  </ul>
+ *  <p>
+ *  The <tt>attributeCount()</tt> method can be used to circumvent calling
+ *  <tt>getAttributes()</tt>, which will create an empty Iterator rather
+ *  than return a null.
+ *  </p>
+ *
+ *  <h3>Example: Link Form 1</h3>
+ *  <p>
+ *  From an incoming wikitext link of:
+ *  <pre>
+ *     [Acme] </pre>
+ *  returns:
+ *  <pre>
+ *    getText():         "Acme"
+ *    getReference():    "Acme"
+ *    attributeCount():  0
+ *    getAttributes():   an empty Iterator </pre>
+ *
+ *  <h3>Example: Link Form 2</h3>
+ *  <p>
+ *  From an incoming wikitext link of:
+ *  <pre>
+ *     [Acme | http://www.acme.com/] </pre>
+ *  returns:
+ *  <pre>
+ *    getText():         "Acme"
+ *    getReference():    "http://www.acme.com/"
+ *    attributeCount():  0
+ *    getAttributes():   an empty Iterator </pre>
+ *
+ *  <h3>Example: Link Form 3</h3>
+ *  <p>
+ *  From an incoming wikitext link of:
+ *  </p>
+ *  <pre>
+ *    [Acme | http://www.acme.com/ | id='foo' rel='Next'] </pre>
+ *  returns:
+ *  <pre>
+ *    getText():         "Acme"
+ *    getReference():    "http://www.acme.com/"
+ *    attributeCount():  2
+ *    getAttributes():   an Iterator containing:
+ *      JDOM Attribute:  id="foo"
+ *      JDOM Attribute:  rel="Next" </pre>
+ *
+ *
+ *  @author Murray Altheim
+ *  @since  2.5.10
+ */
+public class LinkParser
+{
+    private static Logger log = Logger.getLogger(LinkParser.class);
+
+    /** Permitted attributes on links.  Keep this sorted. */
+    private static final String[] PERMITTED_ATTRIBUTES = new String[] {
+            "accesskey", "charset", "class", "dir", "hreflang", "id", "lang",
+            "rel", "rev", "style", "tabindex", "target", "title", "type" };
+
+    /** Permitted values on the 'target' attribute. */
+    private static final String[] PERMITTED_TARGET_VALUES = new String[] {
+            "_blank", "_self", "_parent", "_top" };
+
+    private static final String EQSQUO = "='";
+    private static final String SQUO   = "'";
+    private static final String EQ     = "=";
+    private static final String TARGET = "target";
+    private static final String DELIMS = " \t\n\r\f=";
+
+    private static final List m_EMPTY = new ArrayList();
+
+    // ............
+
+
+    /**
+     *  Processes incoming link text, separating out the link text, the link
+     *  URI, and then any specified attributes.
+     *
+     * @param  linktext  the wiki link text to be parsed
+     * @return a Link object containing the link text, reference, and any valid Attributes
+     * @throws ParseException if the parameter is null
+     */
+    public Link parse( String linktext ) throws ParseException
+    {
+        if( linktext == null )
+        {
+            throw new ParseException("null value passed to link parser");
+        }
+
+        Link link = null;
+
+        try
+        {
+            // establish link text and link ref
+            int cut1   = linktext.indexOf('|');
+            if( cut1 == -1 )
+            {
+                //  link form 1:  [Acme]
+                return new Link( linktext );
+            }
+
+            int cut2 = cut1+1 < linktext.length()
+                    ? linktext.indexOf('|', cut1+1 )
+                    : -1 ;
+
+            if ( cut2 == -1 )
+            {
+                //  link form 2:  [Acme | http://www.acme.com/]
+                String text = linktext.substring( 0, cut1 ).trim(); // to cut1
+                String ref  = linktext.substring( cut1+1 ).trim();  // cut1 to end
+                return new Link( text, ref );
+            }
+
+            // otherwise:           link form 3:  [Acme | http://www.acme.com/ | id='foo' rel='Next']
+            String text    = linktext.substring( 0, cut1 ).trim();      // to cut1
+            String ref     = linktext.substring( cut1+1, cut2 ).trim(); // cut1 to cut2
+            String attribs = linktext.substring( cut2+1 ).trim();       // cut2 to end
+
+            link = new Link( text, ref );
+
+            // parse attributes
+            if( attribs.indexOf(EQSQUO) != -1 ) // contains "='" that looks like attrib spec
+            {
+                try
+                {
+                    StringTokenizer tok = new StringTokenizer(attribs,DELIMS,true);
+                    while ( tok.hasMoreTokens() )
+                    {
+                        String token = tok.nextToken(DELIMS).trim(); // get attribute name token
+                        while ( isSpace(token) && tok.hasMoreTokens() )
+                        {
+                            token = tok.nextToken(DELIMS).trim(); // eat any WS
+                        }
+
+                        require( tok, EQ ); // eat '=', break after '='
+                        require( tok, SQUO ); // eat opening delim
+                        String value = tok.nextToken(SQUO);  // using existing delim
+                        require( tok, SQUO ); // eat closing delim
+
+                        if( token != null && value != null )
+                        {
+                            if( Arrays.binarySearch( PERMITTED_ATTRIBUTES, token ) >= 0 )
+                            {
+                                if( !token.equals(TARGET) // _blank _self _parent _top
+                                        || Arrays.binarySearch( PERMITTED_TARGET_VALUES, value ) >= 0 )
+                                {
+                                    Attribute a = new Attribute(token,value);
+                                    link.addAttribute(a);
+                                }
+                                else
+                                {
+                                    throw new ParseException("unknown target attribute value='"
+                                                             + value + "' on link");
+                                }
+                            }
+                            else
+                            {
+                                throw new ParseException("unknown attribute name '"
+                                                         + token + "' on link");
+                            }
+                        }
+                        else
+                        {
+                            throw new ParseException("unable to parse link attributes '"
+                                                     + attribs + "'");
+
+                        }
+                    }
+                }
+                catch( ParseException pe )
+                {
+                    log.warn("syntax error parsing link attributes '"+attribs+"': " + pe.getMessage());
+                }
+                catch( NoSuchElementException nse )
+                {
+                    log.warn("expected more tokens while parsing link attributes '" + attribs + "'");
+                }
+            }
+
+        }
+        catch( Exception e )
+        {
+            log.warn( e.getClass().getName() + " thrown by link parser: " + e.getMessage() );
+        }
+
+        return link;
+    }
+
+
+    private String require( StringTokenizer tok, String required )
+            throws ParseException, NoSuchElementException
+    {
+        String s = tok.nextToken(required);
+        if( !s.equals(required) )
+        {
+            throw new ParseException("expected '"+required+"' not '"+s+"'"); // I18N
+        }
+        return s;
+    }
+
+
+    /** 
+     *  Returns true if the String <tt>s</tt> is completely
+     *  composed of whitespace.
+     * 
+     *  @param s The string to check
+     *  @return True, if "s" is all XML whitespace.
+     */
+    public static final boolean isSpace( String s )
+    {
+        for( int i = 0 ; i < s.length() ; i++ )
+        {
+            if( !isSpace( s.charAt(i)) ) return false;
+        }
+        return true;
+    }
+
+
+    /** 
+     *  Returns true if char <tt>c</tt> is a member of
+     *  <tt>S</tt> (space) [XML 1.1 production 3].
+     *  
+     *  @param c Character to check.
+     *  @return True, if the character is an XML space.
+     */
+    public static final boolean isSpace( char c )
+    {
+        return
+           0x20 == c    // SPACE
+        || 0x0A == c    // LF
+        || 0x0D == c    // CR
+        || 0x09 == c    // TAB
+        || 0x85 == c    // NEL
+        || 0x2028 == c; // LS (line separator)
+    }
+
+
+    // .........................................................................
+
+
+    /**
+     *  Inner class serving as a struct containing the parsed
+     *  components of a link.
+     */
+    public static class Link
+    {
+        private String m_text;
+        private String m_ref = null;
+        private int    m_interwikiPoint = -1;
+        private List   m_attribs = null;
+
+        /**
+         *  Create a new Link with text but no reference.
+         *  @param text The link text.
+         *  @throws ParseException If the link text is illegal.
+         */
+        protected Link( String text ) throws ParseException
+        {
+            setText(text);
+        }
+
+        /**
+         *  Create a new link with a given text and hyperlink (reference).
+         *  
+         *  @param text The link text.
+         *  @param ref  The hypertext reference.
+         *  @throws ParseException If the link text or reference are illegal.
+         */
+        protected Link( String text, String ref ) throws ParseException
+        {
+            setText(text);
+            setReference(ref);
+        }
+
+        /**
+         *  Sets the link text.
+         *  
+         *  @param text The link text.
+         *  @throws ParseException If the text is illegal (e.g. null).
+         */
+        protected void setText( String text ) throws ParseException
+        {
+            if( text == null )
+            {
+                throw new ParseException("null link text");
+            }
+            m_text = text;
+        }
+
+        /**
+         *  Returns the link text.
+         *  
+         *  @return Link text.
+         */
+        public String getText()
+        {
+            return m_text;
+        }
+
+        /**
+         *  Sets the hypertext reference.  Typically, this is an URI or an interwiki link,
+         *  or a wikilink.
+         *  
+         *  @param ref The reference.
+         *  @throws ParseException If the reference is illegal.
+         */
+        protected void setReference( String ref ) throws ParseException
+        {
+            if( ref == null )
+            {
+                throw new ParseException("null link reference value");
+            }
+            m_ref = ref;
+        }
+
+        /**
+         *  Returns true, if there is a reference.
+         *  
+         *  @return True, if there's a reference; false otherwise.
+         */
+        public boolean hasReference()
+        {
+            return m_ref != null;
+        }
+
+        /** 
+         *  Returns the link reference, or the link text if null. 
+         *  
+         *  @return A link reference.
+         */
+        public String getReference()
+        {
+            return m_ref != null
+                    ? m_ref
+                    : m_text ;
+        }
+
+        /**
+         *  Returns true, if this Link represents an InterWiki link (of the form wiki:page).
+         * 
+         *  @return True, if this Link represents an InterWiki link.
+         */
+        public boolean isInterwikiLink()
+        {
+            if( !hasReference() ) m_ref = m_text;
+
+            m_interwikiPoint = m_ref.indexOf(':');
+
+            return m_interwikiPoint != -1;
+        }
+
+        /**
+         *  Returns the name of the wiki if this is an interwiki link. 
+         *  <pre>
+         *    Link link = new Link("Foo","Wikipedia:Foobar");
+         *    assert( link.getExternalWikiPage(), "Wikipedia" );
+         *  </pre> 
+         *  
+         *  @return Name of the wiki, or null, if this is not an interwiki link.
+         */
+        public String getExternalWiki()
+        {
+            if( isInterwikiLink() )
+            {
+                return m_ref.substring( 0, m_interwikiPoint );
+            }
+            
+            return null;
+        }
+
+        /** 
+         *  Returns the wikiname part of an interwiki link. Used only with interwiki links.
+         *  <pre>
+         *    Link link = new Link("Foo","Wikipedia:Foobar");
+         *    assert( link.getExternalWikiPage(), "Foobar" );
+         *  </pre> 
+         *  
+         *  @return Wikiname part, or null, if this is not an interwiki link.
+         */
+        public String getExternalWikiPage()
+        {
+            if( isInterwikiLink() )
+            {
+                return m_ref.substring( m_interwikiPoint+1 );
+            }
+            
+            return null;
+        }
+
+        /**
+         *  Returns the number of attributes on this link.
+         *  
+         *  @return The number of attributes.
+         */
+        public int attributeCount()
+        {
+            return m_attribs != null
+                    ? m_attribs.size()
+                    : 0 ;
+        }
+
+        /**
+         *  Adds another attribute to the link.
+         *  
+         *  @param attr A JDOM Attribute.
+         */
+        public void addAttribute( Attribute attr )
+        {
+            if( m_attribs == null )
+            {
+                m_attribs = new ArrayList();
+            }
+            m_attribs.add(attr);
+        }
+
+        /** 
+         *  Returns an Iterator over the list of JDOM Attributes.
+         *  
+         *  @return Iterator over the attributes.
+         */
+        public Iterator getAttributes()
+        {
+            return m_attribs != null
+                    ? m_attribs.iterator()
+                    : m_EMPTY.iterator() ;
+        }
+
+        /** 
+         *  Returns a wikitext string representation of this Link. 
+         *  @return WikiText.
+         */
+        public String toString()
+        {
+            StringBuffer sb = new StringBuffer();
+            sb.append( '[' );
+            sb.append( m_text );
+
+            if( m_ref != null )
+            {
+                sb.append( ' ' );
+                sb.append( '|' );
+                sb.append( ' ' );
+                sb.append( m_ref );
+            }
+
+            if( m_attribs != null )
+            {
+                sb.append( ' ' );
+                sb.append( '|' );
+                Iterator it = getAttributes();
+                while ( it.hasNext() )
+                {
+                    Attribute a = (Attribute)it.next();
+                    sb.append( ' ' );
+                    sb.append( a.getName() );
+                    sb.append( '=' );
+                    sb.append( '\'' );
+                    sb.append( a.getValue() );
+                    sb.append( '\'' );
+                }
+            }
+            sb.append( ']' );
+            return sb.toString();
+        }
+
+    } // end inner class
+
+}
+

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/MarkupParser.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/MarkupParser.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/MarkupParser.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/MarkupParser.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,333 @@
+/*
+  JSPWiki - a JSP-based WikiWiki clone.
+
+  Copyright (C) 2001-2006 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package com.ecyrd.jspwiki.parser;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+import java.util.ArrayList;
+
+
+import com.ecyrd.jspwiki.StringTransmutator;
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+
+/**
+ *   Provides an abstract class for the parser instances.
+ *
+ *   @author Janne Jalkanen
+ *   @since  2.4
+ */
+public abstract class MarkupParser
+{
+    /** Allow this many characters to be pushed back in the stream.  In effect,
+        this limits the size of a single line.  */
+    protected static final int              PUSHBACK_BUFFER_SIZE = 10*1024;
+    protected PushbackReader                m_in;
+    private int              m_pos = -1; // current position in reader stream
+
+    protected WikiEngine     m_engine;
+    protected WikiContext    m_context;
+
+    /** Optionally stores internal wikilinks */
+    protected ArrayList      m_localLinkMutatorChain    = new ArrayList();
+    protected ArrayList      m_externalLinkMutatorChain = new ArrayList();
+    protected ArrayList      m_attachmentLinkMutatorChain = new ArrayList();
+    protected ArrayList      m_headingListenerChain     = new ArrayList();
+    protected ArrayList      m_linkMutators             = new ArrayList();
+
+    protected boolean        m_inlineImages             = true;
+
+    protected boolean        m_parseAccessRules = true;
+    /** If set to "true", allows using raw HTML within Wiki text.  Be warned,
+        this is a VERY dangerous option to set - never turn this on in a publicly
+        allowable Wiki, unless you are absolutely certain of what you're doing. */
+    public static final String     PROP_ALLOWHTML        = "jspwiki.translatorReader.allowHTML";
+    /** If set to "true", enables plugins during parsing */
+    public static final String     PROP_RUNPLUGINS       = "jspwiki.translatorReader.runPlugins";
+
+    /** Lists all punctuation characters allowed in WikiMarkup. These
+        will not be cleaned away. This is for compatibility for older versions
+        of JSPWiki. */
+
+    protected static final String           LEGACY_CHARS_ALLOWED      = "._";
+
+    /** Lists all punctuation characters allowed in page names. */
+    public    static final String           PUNCTUATION_CHARS_ALLOWED = " ()&+,-=._$";
+
+    protected MarkupParser( WikiContext context, Reader in )
+    {
+        m_engine = context.getEngine();
+        m_context = context;
+        setInputReader( in );
+    }
+
+    /**
+     *  Replaces the current input character stream with a new one.
+     *  @param in New source for input.  If null, this method does nothing.
+     *  @return the old stream
+     */
+    public Reader setInputReader( Reader in )
+    {
+        Reader old = m_in;
+
+        if( in != null )
+        {
+            m_in = new PushbackReader( new BufferedReader( in ),
+                                       PUSHBACK_BUFFER_SIZE );
+        }
+
+        return old;
+    }
+
+    /**
+     *  Adds a hook for processing link texts.  This hook is called
+     *  when the link text is written into the output stream, and
+     *  you may use it to modify the text.  It does not affect the
+     *  actual link, only the user-visible text.
+     *
+     *  @param mutator The hook to call.  Null is safe.
+     */
+    public void addLinkTransmutator( StringTransmutator mutator )
+    {
+        if( mutator != null )
+        {
+            m_linkMutators.add( mutator );
+        }
+    }
+
+    /**
+     *  Adds a hook for processing local links.  The engine
+     *  transforms both non-existing and existing page links.
+     *
+     *  @param mutator The hook to call.  Null is safe.
+     */
+    public void addLocalLinkHook( StringTransmutator mutator )
+    {
+        if( mutator != null )
+        {
+            m_localLinkMutatorChain.add( mutator );
+        }
+    }
+
+    /**
+     *  Adds a hook for processing external links.  This includes
+     *  all http:// ftp://, etc. links, including inlined images.
+     *
+     *  @param mutator The hook to call.  Null is safe.
+     */
+    public void addExternalLinkHook( StringTransmutator mutator )
+    {
+        if( mutator != null )
+        {
+            m_externalLinkMutatorChain.add( mutator );
+        }
+    }
+
+    /**
+     *  Adds a hook for processing attachment links.
+     *
+     *  @param mutator The hook to call.  Null is safe.
+     */
+    public void addAttachmentLinkHook( StringTransmutator mutator )
+    {
+        if( mutator != null )
+        {
+            m_attachmentLinkMutatorChain.add( mutator );
+        }
+    }
+
+    public void addHeadingListener( HeadingListener listener )
+    {
+        if( listener != null )
+        {
+            m_headingListenerChain.add( listener );
+        }
+    }
+
+    public void disableAccessRules()
+    {
+        m_parseAccessRules = false;
+    }
+
+    /**
+     *  Use this to turn on or off image inlining.
+     *  @param toggle If true, images are inlined (as per set in jspwiki.properties)
+     *                If false, then images won't be inlined; instead, they will be
+     *                treated as standard hyperlinks.
+     *  @since 2.2.9
+     */
+    public void enableImageInlining( boolean toggle )
+    {
+        m_inlineImages = toggle;
+    }
+
+    /**
+     *  Parses the document.
+     *  @return the parsed document, as a WikiDocument
+     *  @throws IOException
+     */
+    public abstract WikiDocument parse()
+         throws IOException;
+
+    /**
+     *  Return the current position in the reader stream.
+     *  The value will be -1 prior to reading.
+     * @return the reader position as an int.
+     */
+    public int getPosition()
+    {
+        return m_pos;
+    }
+
+    /**
+     * Returns the next token in the stream.  This is the most called method
+     * in the entire parser, so it needs to be lean and mean.
+     *
+     * @return The next token in the stream; or, if the stream is ended, -1.
+     * @throws IOException If something bad happens
+     * @throws NullPointerException If you have not yet created an input document.
+     */
+    protected final int nextToken()
+        throws IOException
+    {
+        // if( m_in == null ) return -1;
+        m_pos++;
+        return m_in.read();
+    }
+
+    /**
+     *  Push back any character to the current input.  Does not
+     *  push back a read EOF, though.
+     */
+    protected void pushBack( int c )
+        throws IOException
+    {
+        if( c != -1 && m_in != null )
+        {
+            m_pos--;
+            m_in.unread( c );
+        }
+    }
+
+    /**
+     *  Cleans a Wiki name.  The functionality of this method was changed in 2.6
+     *  so that the list of allowed characters is much larger.  Use wikifyLink()
+     *  to get the legacy behaviour.
+     *  <P>
+     *  [ This is a link ] -&gt; This is a link
+     *
+     *  @param link Link to be cleared. Null is safe, and causes this to return null.
+     *  @return A cleaned link.
+     *
+     *  @since 2.0
+     */
+    public static String cleanLink( String link )
+    {
+        return cleanLink(link, PUNCTUATION_CHARS_ALLOWED);
+    }
+
+    /**
+     *  Cleans a Wiki name based on a list of characters.  Also, any multiple
+     *  whitespace is collapsed into a single space, and any leading or trailing
+     *  space is removed.
+     *
+     *  @param link Link to be cleared. Null is safe, and causes this to return null.
+     *  @param allowedChars Characters which are allowed in the string.
+     *  @return A cleaned link.
+     *
+     *  @since 2.6
+     */
+    public static String cleanLink( String link, String allowedChars )
+    {
+        if( link == null ) return null;
+
+        link = link.trim();
+        StringBuffer clean = new StringBuffer(link.length());
+
+        //
+        //  Remove non-alphanumeric characters that should not
+        //  be put inside WikiNames.  Note that all valid
+        //  Unicode letters are considered okay for WikiNames.
+        //  It is the problem of the WikiPageProvider to take
+        //  care of actually storing that information.
+        //
+        //  Also capitalize things, if necessary.
+        //
+
+        boolean isWord = true;  // If true, we've just crossed a word boundary
+        boolean wasSpace = false;
+
+        for( int i = 0; i < link.length(); i++ )
+        {
+            char ch = link.charAt(i);
+
+            //
+            //  Cleans away repetitive whitespace and only uses the first one.
+            //
+            if( Character.isWhitespace(ch) )
+            {
+                if( wasSpace )
+                    continue;
+
+                wasSpace = true;
+            }
+            else
+            {
+                wasSpace = false;
+            }
+
+            //
+            //  Check if it is allowed to use this char, and capitalize, if necessary.
+            //
+            if( Character.isLetterOrDigit( ch ) || allowedChars.indexOf(ch) != -1 )
+            {
+                // Is a letter
+
+                if( isWord ) ch = Character.toUpperCase( ch );
+                clean.append( ch );
+                isWord = false;
+            }
+            else
+            {
+                isWord = true;
+            }
+        }
+
+        return clean.toString();
+    }
+
+    /**
+     *  Cleans away extra legacy characters.  This method functions exactly
+     *  like pre-2.6 cleanLink()
+     *  <P>
+     *  [ This is a link ] -&gt; ThisIsALink
+     *
+     *  @param link Link to be cleared. Null is safe, and causes this to return null.
+     *  @return A cleaned link.
+     *  @since 2.6
+     */
+    public static String wikifyLink(String link)
+    {
+        return MarkupParser.cleanLink(link, MarkupParser.LEGACY_CHARS_ALLOWED);
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/ParseException.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/ParseException.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/ParseException.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/ParseException.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,39 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.parser;
+
+import com.ecyrd.jspwiki.WikiException;
+
+/**
+ *  This is an exception which gets thrown whenever the parser cannot
+ *  parse the parsing things.
+ *  
+ *  @author jalkanen
+ */
+public class ParseException extends WikiException
+{
+    private static final long serialVersionUID = 1L;
+
+    public ParseException(String msg)
+    {
+        super(msg);
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/PluginContent.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/PluginContent.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/PluginContent.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/PluginContent.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,194 @@
+/* 
+  JSPWiki - a JSP-based WikiWiki clone.
+
+  Copyright (C) 2001-2006 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package com.ecyrd.jspwiki.parser;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import org.jdom.Text;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.plugin.PluginException;
+import com.ecyrd.jspwiki.plugin.WikiPlugin;
+import com.ecyrd.jspwiki.render.RenderingManager;
+
+/**
+ *  Stores the contents of a plugin in a WikiDocument DOM tree.
+ *  
+ *  @author Janne Jalkanen
+ *  @since  2.4
+ */
+public class PluginContent extends Text
+{
+    private static final String BLANK = "";
+    private static final String CMDLINE = "_cmdline";
+    private static final String ELEMENT_BR = "<br/>";
+    private static final String EMITTABLE_PLUGINS = "Image|FormOpen|FormClose|FormInput|FormTextarea|FormSelect";
+    private static final String LINEBREAK = "\n";
+    private static final String PLUGIN_START = "[{";
+    private static final String PLUGIN_END = "}]";
+    private static final String SPACE = " ";
+
+    private static final long serialVersionUID = 1L;
+
+    private String m_pluginName;
+    private Map    m_params;
+    
+    public PluginContent( String pluginName, Map parameters )
+    {
+        m_pluginName = pluginName;
+        m_params     = parameters;
+    }
+    /**
+     * @since 2.5.7
+     */
+    public String getPluginName()
+    {
+        return m_pluginName;
+    }
+    
+    public Object getParameter( String name )
+    {
+        return m_params.get(name);
+    }
+    
+    public Map getParameters()
+    {
+        return m_params;
+    }
+    
+    public String getValue()
+    {
+        return getText();
+    }
+    
+    public String getText()
+    {
+        String result;
+        
+        WikiDocument doc = (WikiDocument)getDocument();
+
+        if( doc == null )
+        {
+            //
+            // This element has not yet been attached anywhere, so we simply assume there is
+            // no rendering and return the plugin name.  This is required e.g. when the 
+            // paragraphify() checks whether the element is empty or not.  We can't of course
+            // know whether the rendering would result in an empty string or not, but let us
+            // assume it does not.
+            //
+            
+            return getPluginName();
+        }
+               
+        WikiContext context = doc.getContext();
+        
+        Boolean wysiwygVariable = (Boolean)context.getVariable( RenderingManager.WYSIWYG_EDITOR_MODE );
+        boolean wysiwygEditorMode = false;
+        if( wysiwygVariable != null )
+        {
+            wysiwygEditorMode = wysiwygVariable.booleanValue();
+        }
+
+        try
+        {
+            //
+            //  Determine whether we should emit the actual code for this plugin or
+            //  whether we should execute it.  For some plugins we always execute it,
+            //  since they can be edited visually.
+            //
+            // FIXME: The plugin name matching should not be done here, but in a per-editor resource
+            if( wysiwygEditorMode 
+                && !m_pluginName.matches( EMITTABLE_PLUGINS ) )
+            {        
+                result = PLUGIN_START + m_pluginName + SPACE;            
+            
+                // convert newlines to <br> in case the plugin has a body.
+                String cmdLine = ( (String)m_params.get( CMDLINE ) ).replaceAll( LINEBREAK, ELEMENT_BR );
+            
+                result = result + cmdLine + PLUGIN_END;
+            }
+            else
+            {
+                Boolean b = (Boolean)context.getVariable( RenderingManager.VAR_EXECUTE_PLUGINS );
+                if( b != null && !b.booleanValue() ) return BLANK;
+
+                WikiEngine engine = context.getEngine();
+            
+                HashMap parsedParams = new HashMap();
+            
+                //
+                //  Parse any variable instances from the string
+                //
+                for( Iterator i = m_params.entrySet().iterator(); i.hasNext(); )
+                {
+                    Map.Entry e = (Map.Entry) i.next();
+                
+                    Object val = e.getValue();
+                
+                    if( val instanceof String )
+                    {
+                        val = engine.getVariableManager().expandVariables( context, (String)val );
+                    }
+                
+                    parsedParams.put( e.getKey(), val );
+                }
+            
+                result = engine.getPluginManager().execute( context,
+                                                            m_pluginName,
+                                                            parsedParams );
+            }
+        }
+        catch( Exception e )
+        {
+            if( wysiwygEditorMode )
+            {
+                result = "";
+            }
+            else
+            {
+                // log.info("Failed to execute plugin",e);
+                ResourceBundle rb = context.getBundle(WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE);
+                Object[] args = { e.getMessage() };
+                result = JSPWikiMarkupParser.makeError( 
+                                 MessageFormat.format( rb.getString( "plugin.error.insertionfailed" ), args ) ).getText();
+            }
+        }
+        
+        
+        return result;
+    }
+    
+    /**
+     *  Executes the executeParse() method.
+     *  
+     *  @param m_context
+     */
+    public void executeParse(WikiContext m_context)
+        throws PluginException
+    {
+        m_context.getEngine().getPluginManager().executeParse( this, m_context );
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/VariableContent.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/VariableContent.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/VariableContent.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/VariableContent.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,94 @@
+/* 
+  JSPWiki - a JSP-based WikiWiki clone.
+
+  Copyright (C) 2001-2006 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package com.ecyrd.jspwiki.parser;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.jdom.Text;
+
+import com.ecyrd.jspwiki.NoSuchVariableException;
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.render.RenderingManager;
+
+/**
+ *  Stores the contents of a WikiVariable in a WikiDocument DOM tree.
+ *  @author Janne Jalkanen
+ *  @since  2.4
+ */
+public class VariableContent extends Text
+{
+    private static final long serialVersionUID = 1L;
+
+    private String m_varName;
+    
+    public VariableContent( String varName )
+    {
+        m_varName = varName;
+    }
+    
+    /**
+     *   Evaluates the variable and returns the contents.
+     */
+    public String getValue()
+    {
+        String result = "";
+        WikiDocument root = (WikiDocument) getDocument();
+
+        if( root == null )
+        {
+            // See similar note in PluginContent
+            return m_varName;
+        }
+        
+        WikiContext context = root.getContext();
+
+        if( context == null )
+            return "No WikiContext available: INTERNAL ERROR";
+    
+        Boolean wysiwygEditorMode = (Boolean)context.getVariable(RenderingManager.WYSIWYG_EDITOR_MODE);
+        
+        if( wysiwygEditorMode != null && wysiwygEditorMode.booleanValue() )
+        {
+            result = "[" + m_varName + "]";
+        }
+        else
+        {
+            try
+            {
+                result = context.getEngine().getVariableManager().parseAndGetValue( context, m_varName );
+            }
+            catch( NoSuchVariableException e )
+            {
+                result = JSPWikiMarkupParser.makeError("No such variable: "+e.getMessage()).getText(); 
+            }
+        }
+
+        return StringEscapeUtils.escapeXml( result );
+    }
+    
+    public String getText()
+    {
+        return getValue();
+    }
+
+    public String toString()
+    {
+        return "VariableElement[\""+m_varName+"\"]";
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/WikiDocument.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/WikiDocument.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/WikiDocument.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/parser/WikiDocument.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,89 @@
+/* 
+   JSPWiki - a JSP-based WikiWiki clone.
+
+   Copyright (C) 2001-2006 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+package com.ecyrd.jspwiki.parser;
+
+import java.lang.ref.WeakReference;
+
+import org.jdom.Document;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiPage;
+
+/**
+ *  Stores the DOM tree of a rendered WikiPage.  This class
+ *  extends the org.jdom.Document to provide some extra metadata
+ *  specific to JSPWiki.
+ *  <p>
+ *  The document is not stored as metadata in the WikiPage because
+ *  otherwise it could not be cached separately.
+ *  
+ *  @author Janne Jalkanen
+ *  @since  2.4
+ */
+public class WikiDocument extends Document
+{
+    private static final long serialVersionUID = 0L;
+    
+    private WikiPage m_page;
+    private String   m_wikiText;
+
+    private WeakReference m_context;
+    
+    /**
+     *  Creates a new WikiDocument for a specific page.
+     * 
+     *  @param page The page to which this document refers to.
+     */
+    public WikiDocument( WikiPage page )
+    {
+        m_page     = page;
+    }
+    
+    public void setPageData( String data )
+    {
+        m_wikiText = data;
+    }
+    
+    public String getPageData()
+    {
+        return m_wikiText;
+    }
+    
+    public WikiPage getPage()
+    {
+        return m_page;
+    }
+
+    public void setContext( WikiContext ctx )
+    {
+        m_context = new WeakReference( ctx );
+    }
+    
+    /**
+     * Returns the wiki context for this document. This method
+     * may return <code>null</code> if the associated wiki session
+     * had previously been garbage-collected.
+     * @return the wiki context
+     */
+    public WikiContext getContext()
+    {
+        return (WikiContext) m_context.get();
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/.cvsignore
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/.cvsignore?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/.cvsignore (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/.cvsignore Tue Feb 12 21:53:55 2008
@@ -0,0 +1 @@
+PluginResources_en.properties

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/AbstractReferralPlugin.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/AbstractReferralPlugin.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/AbstractReferralPlugin.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/AbstractReferralPlugin.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,311 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.plugin;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.apache.oro.text.GlobCompiler;
+import org.apache.oro.text.regex.*;
+
+import com.ecyrd.jspwiki.*;
+import com.ecyrd.jspwiki.parser.MarkupParser;
+import com.ecyrd.jspwiki.parser.WikiDocument;
+import com.ecyrd.jspwiki.render.RenderingManager;
+
+/**
+ *  This is a base class for all plugins using referral things.
+ *
+ *  <p>Parameters:<br>
+ *  maxwidth: maximum width of generated links<br>
+ *  separator: separator between generated links (wikitext)<br>
+ *  after: output after the link
+ *  before: output before the link
+ *  @author Janne Jalkanen
+ */
+public abstract class AbstractReferralPlugin
+    implements WikiPlugin
+{
+    private static Logger log = Logger.getLogger( AbstractReferralPlugin.class );
+
+    public static final int    ALL_ITEMS       = -1;
+    public static final String PARAM_MAXWIDTH  = "maxwidth";
+    public static final String PARAM_SEPARATOR = "separator";
+    public static final String PARAM_AFTER     = "after";
+    public static final String PARAM_BEFORE    = "before";
+
+    public static final String PARAM_EXCLUDE   = "exclude";
+    public static final String PARAM_INCLUDE   = "include";
+
+    protected           int      m_maxwidth = Integer.MAX_VALUE;
+    protected           String   m_before = ""; // null not blank
+    protected           String   m_separator = ""; // null not blank
+    protected           String   m_after = "\\\\";
+
+    protected           Pattern[]  m_exclude;
+    protected           Pattern[]  m_include;
+
+    protected           WikiEngine m_engine;
+
+    /**
+     *  Used to initialize some things.  All plugins must call this first.
+     *
+     *  @since 1.6.4
+     */
+
+    // FIXME: The compiled pattern strings should really be cached somehow.
+
+    public void initialize( WikiContext context, Map params )
+        throws PluginException
+    {
+        m_engine = context.getEngine();
+        m_maxwidth = TextUtil.parseIntParameter( (String)params.get( PARAM_MAXWIDTH ), Integer.MAX_VALUE );
+        if( m_maxwidth < 0 ) m_maxwidth = 0;
+
+        String s = (String) params.get( PARAM_SEPARATOR );
+
+        if( s != null )
+        {
+            m_separator = s;
+            // pre-2.1.145 there was a separator at the end of the list
+            // if they set the parameters, we use the new format of
+            // before Item1 after separator before Item2 after separator before Item3 after
+            m_after = "";
+        }
+
+        s = (String) params.get( PARAM_BEFORE );
+
+        if( s != null )
+        {
+            m_before = s;
+        }
+
+        s = (String) params.get( PARAM_AFTER );
+
+        if( s != null )
+        {
+            m_after = s;
+        }
+
+        s = (String) params.get( PARAM_EXCLUDE );
+
+        if( s != null )
+        {
+            try
+            {
+                PatternCompiler pc = new GlobCompiler();
+
+                String[] ptrns = StringUtils.split( s, "," );
+
+                m_exclude = new Pattern[ptrns.length];
+
+                for( int i = 0; i < ptrns.length; i++ )
+                {
+                    m_exclude[i] = pc.compile( ptrns[i] );
+                }
+            }
+            catch( MalformedPatternException e )
+            {
+                throw new PluginException("Exclude-parameter has a malformed pattern: "+e.getMessage());
+            }
+        }
+
+        // TODO: Cut-n-paste, refactor
+        s = (String) params.get( PARAM_INCLUDE );
+
+        if( s != null )
+        {
+            try
+            {
+                PatternCompiler pc = new GlobCompiler();
+
+                String[] ptrns = StringUtils.split( s, "," );
+
+                m_include = new Pattern[ptrns.length];
+
+                for( int i = 0; i < ptrns.length; i++ )
+                {
+                    m_include[i] = pc.compile( ptrns[i] );
+                }
+            }
+            catch( MalformedPatternException e )
+            {
+                throw new PluginException("Include-parameter has a malformed pattern: "+e.getMessage());
+            }
+        }
+
+        // log.debug( "Requested maximum width is "+m_maxwidth );
+    }
+
+    protected Collection filterCollection( Collection c )
+    {
+        ArrayList result = new ArrayList();
+
+        PatternMatcher pm = new Perl5Matcher();
+
+        for( Iterator i = c.iterator(); i.hasNext(); )
+        {
+            String pageName = (String) i.next();
+
+            //
+            //  If include parameter exists, then by default we include only those
+            //  pages in it (excluding the ones in the exclude pattern list).
+            //
+            //  include='*' means the same as no include.
+            //
+            boolean includeThis = m_include == null;
+
+            if( m_include != null )
+            {
+                for( int j = 0; j < m_include.length; j++ )
+                {
+                    if( pm.matches( pageName, m_include[j] ) )
+                    {
+                        includeThis = true;
+                        break;
+                    }
+                }
+            }
+
+            if( m_exclude != null )
+            {
+                for( int j = 0; j < m_exclude.length; j++ )
+                {
+                    if( pm.matches( pageName, m_exclude[j] ) )
+                    {
+                        includeThis = false;
+                        break; // The inner loop, continue on the next item
+                    }
+                }
+            }
+
+            if( includeThis )
+            {
+                result.add( pageName );
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     *  Makes WikiText from a Collection.
+     *
+     *  @param links Collection to make into WikiText.
+     *  @param separator Separator string to use.
+     *  @param numItems How many items to show.
+     */
+    protected String wikitizeCollection( Collection links, String separator, int numItems )
+    {
+        if( links == null || links.isEmpty() )
+            return "";
+
+        StringBuffer output = new StringBuffer();
+
+        Iterator it     = links.iterator();
+        int      count  = 0;
+
+        //
+        //  The output will be B Item[1] A S B Item[2] A S B Item[3] A
+        //
+        while( it.hasNext() && ( (count < numItems) || ( numItems == ALL_ITEMS ) ) )
+        {
+            String value = (String)it.next();
+
+            if( count > 0 )
+            {
+                output.append( m_after );
+                output.append( m_separator );
+            }
+
+            output.append( m_before );
+
+            // Make a Wiki markup link. See TranslatorReader.
+            output.append( "[" + m_engine.beautifyTitle(value) + "|" + value + "]" );
+            count++;
+        }
+
+        //
+        //  Output final item - if there have been none, no "after" is printed
+        //
+        if( count > 0 ) output.append( m_after );
+
+        return output.toString();
+    }
+
+    /**
+     *  Makes HTML with common parameters.
+     *
+     *  @since 1.6.4
+     */
+    protected String makeHTML( WikiContext context, String wikitext )
+    {
+        String result = "";
+
+        RenderingManager mgr = m_engine.getRenderingManager();
+
+        try
+        {
+            MarkupParser parser = mgr.getParser(context, wikitext);
+
+            parser.addLinkTransmutator( new CutMutator(m_maxwidth) );
+            parser.enableImageInlining( false );
+
+            WikiDocument doc = parser.parse();
+
+            result = mgr.getHTML( context, doc );
+        }
+        catch( IOException e )
+        {
+            log.error("Failed to convert page data to HTML", e);
+        }
+
+        return result;
+    }
+
+    /**
+     *  A simple class that just cuts a String to a maximum
+     *  length, adding three dots after the cutpoint.
+     */
+    private static class CutMutator implements StringTransmutator
+    {
+        private int m_length;
+
+        public CutMutator( int length )
+        {
+            m_length = length;
+        }
+
+        public String mutate( WikiContext context, String text )
+        {
+            if( text.length() > m_length )
+            {
+                return text.substring( 0, m_length ) + "...";
+            }
+
+            return text;
+        }
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/BugReportHandler.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/BugReportHandler.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/BugReportHandler.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/BugReportHandler.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,244 @@
+/*
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2004 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.plugin;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.security.Principal;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiException;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.filters.RedirectException;
+import com.ecyrd.jspwiki.parser.MarkupParser;
+
+/**
+ *  Provides a handler for bug reports.  Still under construction.
+ *
+ *  <ul>
+ *   <li>"title" = title of the bug.  This is required.  If it is empty (as in "")
+ *       it is a signal to the handler to return quietly.</li>
+ *  </ul>
+ *
+ *  @author Janne Jalkanen
+ */
+public class BugReportHandler
+    implements WikiPlugin
+{
+    private static Logger log = Logger.getLogger( BugReportHandler.class );
+
+    public static final String TITLE          = "title";
+    public static final String DESCRIPTION    = "description";
+    public static final String VERSION        = "version";
+    public static final String MAPPINGS       = "map";
+    public static final String PAGE           = "page";
+
+    public static final String DEFAULT_DATEFORMAT = "dd-MMM-yyyy HH:mm:ss zzz";
+
+    public String execute( WikiContext context, Map params )
+        throws PluginException
+    {
+        String    title;
+        String    description;
+        String    version;
+        String    submitter = null;
+        SimpleDateFormat format = new SimpleDateFormat( DEFAULT_DATEFORMAT );
+        ResourceBundle rb = context.getBundle(WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE);
+
+        title       = (String) params.get( TITLE );
+        description = (String) params.get( DESCRIPTION );
+        version     = (String) params.get( VERSION );
+
+        Principal wup = context.getCurrentUser();
+
+        if( wup != null )
+        {
+            submitter = wup.getName();
+        }
+
+        if( title == null ) throw new PluginException(rb.getString("bugreporthandler.titlerequired"));
+        if( title.length() == 0 ) return "";
+
+        if( description == null ) description = "";
+        if( version == null ) version = "unknown";
+
+        Properties mappings = parseMappings( (String) params.get( MAPPINGS ) );
+
+        //
+        //  Start things
+        //
+
+        try
+        {
+            StringWriter str = new StringWriter();
+            PrintWriter out = new PrintWriter( str );
+
+            Date d = new Date();
+
+            //
+            //  Outputting of basic data
+            //
+            out.println("|"+mappings.getProperty(TITLE,"Title")+"|"+title);
+            out.println("|"+mappings.getProperty("date","Date")+"|"+format.format(d));
+            out.println("|"+mappings.getProperty(VERSION,"Version")+"|"+version);
+            if( submitter != null )
+            {
+                out.println("|"+mappings.getProperty("submitter","Submitter")+
+                            "|"+submitter);
+            }
+
+            //
+            //  Outputting the other parameters added to this.
+            //
+            for( Iterator i = params.entrySet().iterator(); i.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry) i.next();
+
+                if( entry.getKey().equals( TITLE ) ||
+                    entry.getKey().equals( DESCRIPTION ) ||
+                    entry.getKey().equals( VERSION ) ||
+                    entry.getKey().equals( MAPPINGS ) ||
+                    entry.getKey().equals( PAGE ) ||
+                    entry.getKey().toString().startsWith("_") )
+                {
+                    // Ignore this
+                }
+                else
+                {
+                    //
+                    //  If no mapping has been defined, just ignore
+                    //  it.
+                    //
+                    String head = mappings.getProperty( (String)entry.getKey(),
+                                                        (String)entry.getKey() );
+                    if( head.length() > 0 )
+                    {
+                        out.println("|"+head+
+                                    "|"+entry.getValue());
+                    }
+                }
+            }
+
+            out.println();
+            out.println( description );
+
+            out.close();
+
+            //
+            //  Now create a new page for this bug report
+            //
+            String pageName = findNextPage( context, title,
+                                            (String)params.get( PAGE ) );
+
+            WikiPage newPage = new WikiPage( context.getEngine(), pageName );
+            WikiContext newContext = (WikiContext)context.clone();
+            newContext.setPage( newPage );
+
+            context.getEngine().saveText( newContext,
+                                          str.toString() );
+
+            MessageFormat formatter = new MessageFormat("");
+            formatter.applyPattern( rb.getString("bugreporthandler.new") );
+            String[] args = { "<a href=\""+context.getViewURL(pageName)+"\">"+pageName+"</a>" };
+
+            return formatter.format( args );
+        }
+        catch( RedirectException e )
+        {
+            log.info("Saving not allowed, reason: '"+e.getMessage()+"', can't redirect to "+e.getRedirect());
+
+            throw new PluginException("Saving not allowed, reason: "+e.getMessage());
+        }
+        catch( WikiException e )
+        {
+            log.error("Unable to save page!",e);
+
+            return rb.getString("bugreporthandler.unable");
+        }
+    }
+
+    /**
+     *  Finds a free page name for adding the bug report.  Tries to construct a page,
+     *  and if it's found, adds a number to it and tries again.
+     */
+    private synchronized String findNextPage( WikiContext context,
+                                              String title,
+                                              String baseName )
+    {
+        String basicPageName = ((baseName != null)?baseName:"Bug")+MarkupParser.cleanLink(title);
+
+        WikiEngine engine = context.getEngine();
+
+        String pageName = basicPageName;
+        long   lastbug  = 2;
+
+        while( engine.pageExists( pageName ) )
+        {
+            pageName = basicPageName + lastbug++;
+        }
+
+        return pageName;
+    }
+
+    /**
+     *  Just parses a mappings list in the form of "a=b;b=c;c=d".
+     *  <p>
+     *  FIXME: Should probably be in TextUtil or somewhere.
+     */
+    private Properties parseMappings( String mappings )
+    {
+        Properties props = new Properties();
+
+        if( mappings == null ) return props;
+
+        StringTokenizer tok = new StringTokenizer( mappings, ";" );
+
+        while( tok.hasMoreTokens() )
+        {
+            String t = tok.nextToken();
+
+            int colon = t.indexOf("=");
+
+            String key;
+            String value;
+
+            if( colon > 0 )
+            {
+                key = t.substring(0,colon);
+                value = t.substring(colon+1);
+            }
+            else
+            {
+                key = t;
+                value = "";
+            }
+
+            props.setProperty( key, value );
+        }
+
+        return props;
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Counter.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Counter.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Counter.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Counter.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,81 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.plugin;
+
+import com.ecyrd.jspwiki.*;
+import java.util.*;
+
+/**
+ *  Provides a page-specific counter.
+ *  <P>Parameters
+ *  <UL>
+ *    <LI>name - Name of the counter.  Optional.
+ *  </UL>
+ *
+ *  Stores a variable in the WikiContext called "counter", with the name of the
+ *  optionally attached.  For example:<BR>
+ *  If name is "thispage", then the variable name is called "counter-thispage".
+ *
+ *  @since 1.9.30
+ *  @author Janne Jalkanen
+ */
+public class Counter
+    implements WikiPlugin
+{
+    // private static Logger log = Logger.getLogger( Counter.class );
+
+    static final String VARIABLE_NAME = "counter";
+
+    public String execute( WikiContext context, Map params )
+        throws PluginException
+    {
+        //
+        //  First, determine which kind of name we use to store in
+        //  the WikiContext.
+        //
+        String  countername = (String)params.get( "name" );
+
+        if( countername == null ) 
+        {
+            countername = VARIABLE_NAME;
+        }
+        else
+        {
+            countername = VARIABLE_NAME+"-"+countername;
+        }
+
+        //
+        //  Fetch, increment, and store back.
+        //
+        Integer val = (Integer)context.getVariable( countername );
+
+        if( val == null )
+        {
+            val = new Integer( 0 );
+        }
+
+        val = new Integer( val.intValue() + 1 );
+
+        context.setVariable( countername, val );
+
+        return val.toString();
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/CurrentTimePlugin.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/CurrentTimePlugin.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/CurrentTimePlugin.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/CurrentTimePlugin.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,70 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.plugin;
+
+import org.apache.log4j.Logger;
+import com.ecyrd.jspwiki.*;
+import java.util.*;
+import java.text.SimpleDateFormat;
+
+/**
+ *  Just displays the current date and time.
+ *  The time format is exactly like in the java.text.SimpleDateFormat class.
+ *
+ *  @since 1.7.8
+ *  @see java.text.SimpleDateFormat
+ *  @author Janne Jalkanen
+ */
+public class CurrentTimePlugin
+    implements WikiPlugin
+{
+    private static Logger log = Logger.getLogger( CurrentTimePlugin.class );
+
+    public static final String DEFAULT_FORMAT = "HH:mm:ss dd-MMM-yyyy zzzz";
+
+    public String execute( WikiContext context, Map params )
+        throws PluginException
+    {
+        String formatString = (String)params.get("format");
+
+        if( formatString == null )
+        {
+            formatString = DEFAULT_FORMAT;
+        }
+
+        log.debug("Date format string is: "+formatString);
+
+        try
+        {
+            SimpleDateFormat fmt = new SimpleDateFormat( formatString );
+
+            Date d = new Date();  // Now.
+
+            return fmt.format( d );
+        }
+        catch( IllegalArgumentException e )
+        {
+            ResourceBundle rb = context.getBundle(WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE);
+            
+            throw new PluginException( rb.getString("currenttimeplugin.badformat") + e.getMessage() );
+        }
+    }
+
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Denounce.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Denounce.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Denounce.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Denounce.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,210 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2003 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.plugin;
+
+import com.ecyrd.jspwiki.*;
+import org.apache.log4j.Logger;
+import org.apache.oro.text.*;
+import org.apache.oro.text.regex.*;
+
+import java.util.*;
+import java.io.InputStream;
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *  Denounces a link by removing it from any search engine.  The bots are listed
+ *  in com/ecyrd/jspwiki/plugin/denounce.properties.
+ *
+ *  @author Janne Jalkanen
+ *  @since 2.1.40.
+ */
+public class Denounce implements WikiPlugin
+{
+    private static Logger     log = Logger.getLogger(Denounce.class);
+
+    public static final String PARAM_LINK = "link";
+    public static final String PARAM_TEXT = "text";
+
+    public static final String PROPERTYFILE = "com/ecyrd/jspwiki/plugin/denounce.properties";
+    public static final String PROP_AGENTPATTERN   = "denounce.agentpattern.";
+    public static final String PROP_HOSTPATTERN    = "denounce.hostpattern.";
+    public static final String PROP_REFERERPATTERN = "denounce.refererpattern.";
+
+    public static final String PROP_DENOUNCETEXT   = "denounce.denouncetext";
+
+    private static ArrayList c_refererPatterns = new ArrayList();
+    private static ArrayList c_agentPatterns   = new ArrayList();
+    private static ArrayList c_hostPatterns    = new ArrayList();
+
+    private static String    c_denounceText    = "";
+
+    /**
+     *  Prepares the different patterns for later use.  Compiling is
+     *  (probably) expensive, so we do it statically at class load time.
+     */
+    static
+    {
+        try
+        {
+            PatternCompiler compiler = new GlobCompiler();
+            ClassLoader loader = Denounce.class.getClassLoader();
+
+            InputStream in = loader.getResourceAsStream( PROPERTYFILE );
+
+            if( in == null )
+            {
+                throw new IOException("No property file found! (Check the installation, it should be there.)");
+            }
+
+            Properties props = new Properties();
+            props.load( in );
+
+            c_denounceText = props.getProperty( PROP_DENOUNCETEXT, c_denounceText );
+
+            for( Enumeration e = props.propertyNames(); e.hasMoreElements(); )
+            {
+                String name = (String) e.nextElement();
+
+                try 
+                {
+                    if( name.startsWith( PROP_REFERERPATTERN ) )
+                    {
+                        c_refererPatterns.add( compiler.compile( props.getProperty(name) ) );
+                    }
+                    else if( name.startsWith( PROP_AGENTPATTERN ) )
+                    {
+                        c_agentPatterns.add( compiler.compile( props.getProperty(name) ) );
+                    }
+                    else if( name.startsWith( PROP_HOSTPATTERN ) )
+                    {
+                        c_hostPatterns.add( compiler.compile( props.getProperty(name) ) );
+                    }
+                }
+                catch( MalformedPatternException ex )
+                {
+                    log.error( "Malformed URL pattern in "+PROPERTYFILE+": "+props.getProperty(name), ex );
+                }
+            }
+
+            log.debug("Added "+c_refererPatterns.size()+c_agentPatterns.size()+c_hostPatterns.size()+" crawlers to denounce list.");
+        }
+        catch( IOException e )
+        {
+            log.error( "Unable to load URL patterns from "+PROPERTYFILE, e );
+        }
+        catch( Exception e )
+        {
+            log.error( "Unable to initialize Denounce plugin", e );
+        }
+    }
+
+    public String execute( WikiContext context, Map params )
+        throws PluginException
+    {
+        String link = (String) params.get( PARAM_LINK );
+        String text = (String) params.get( PARAM_TEXT );
+        boolean linkAllowed = true;
+
+        if( link == null )
+        {
+            throw new PluginException("Denounce: No parameter "+PARAM_LINK+" defined!");
+        }
+
+        HttpServletRequest request = context.getHttpRequest();
+
+        if( request != null )
+        {
+            linkAllowed = !matchHeaders( request );
+        }
+
+        if( text == null ) text = link;
+
+        if( linkAllowed )
+        {
+            // FIXME: Should really call TranslatorReader
+            return "<a href=\""+link+"\">"+text+"</a>";
+        }
+
+        return c_denounceText;
+    }
+
+    /**
+     *  Returns true, if the path is found among the referers.
+     */
+    private boolean matchPattern( List list, String path )
+    {
+        PatternMatcher matcher = new Perl5Matcher();
+
+        for( Iterator i = list.iterator(); i.hasNext(); )
+        {
+            if( matcher.matches( path, (Pattern)i.next() ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    // FIXME: Should really return immediately when a match is found.
+
+    private boolean matchHeaders( HttpServletRequest request )
+    {
+        //
+        //  User Agent
+        //
+
+        String userAgent = request.getHeader("User-Agent");
+
+        if( userAgent != null && matchPattern( c_agentPatterns, userAgent ) )
+        {
+            log.debug("Matched user agent "+userAgent+" for denounce.");
+            return true;
+        }
+
+        //
+        //  Referrer header
+        //
+
+        String refererPath = request.getHeader("Referer");
+
+        if( refererPath != null && matchPattern( c_refererPatterns, refererPath ) )
+        {
+            log.debug("Matched referer "+refererPath+" for denounce.");
+            return true;
+        }
+
+        //
+        //  Host
+        // 
+
+        String host = request.getRemoteHost();
+
+        if( host != null && matchPattern( c_hostPatterns, host ) )
+        {
+            log.debug("Matched host "+host+" for denounce.");
+            return true;
+        }
+
+        return false;
+    }
+}

Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Groups.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Groups.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Groups.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/plugin/Groups.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,88 @@
+/* 
+    JSPWiki - a JSP-based WikiWiki clone.
+
+    Copyright (C) 2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package com.ecyrd.jspwiki.plugin;
+
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Map;
+
+import net.sourceforge.stripes.action.UrlBinding;
+import net.sourceforge.stripes.util.UrlBuilder;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.action.GroupActionBean;
+import com.ecyrd.jspwiki.auth.PrincipalComparator;
+import com.ecyrd.jspwiki.auth.authorize.GroupManager;
+
+/**
+ *  <p>Prints the groups managed by this wiki, separated by commas.
+ *  The groups are sorted in ascending order, and are hyperlinked
+ *  to the page that displays the group's members.</p>
+ *  @since 2.4.19
+ *  @author Andrew Jaquith
+ */
+public class Groups
+    implements WikiPlugin
+{
+    private static final Comparator COMPARATOR = new PrincipalComparator();
+    
+    public String execute( WikiContext context, Map params )
+        throws PluginException
+    {
+        // Retrieve groups, and sort by name
+        WikiEngine engine = context.getEngine();
+        GroupManager groupMgr = engine.getGroupManager();
+        Principal[] groups = groupMgr.getRoles();
+        Arrays.sort( groups, COMPARATOR );
+
+        StringBuffer s = new StringBuffer();
+        
+        for ( int i = 0; i < groups.length; i++ )
+        {
+            String name = groups[i].getName();
+            
+            // Make Stripes URL
+            String groupUrl = GroupActionBean.class.getAnnotation(UrlBinding.class).value();
+            UrlBuilder urlBuilder = new UrlBuilder(  groupUrl, true );
+            urlBuilder.addParameter("group", name);
+            String url = urlBuilder.toString();
+            
+            // Make re-written URL
+            String rewriteUrl = context.getContext().getResponse().encodeURL( url );
+            
+            // Create hyperlink
+            s.append( "<a href=\"" );
+            s.append( rewriteUrl );
+            s.append( "\">" );
+            s.append( name );
+            s.append( "</a>" );
+            
+            // If not the last one, add a comma and space
+            if ( i < ( groups.length - 1 ) )
+            {
+                s.append( ',' );
+                s.append( ' ' );
+            }
+        }
+        return s.toString();
+    }
+}



Mime
View raw message