📄 translatorreader.java
字号:
/* 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;import java.io.*;import java.util.*;import java.text.*;import org.apache.log4j.Category;import org.apache.oro.text.*;import org.apache.oro.text.regex.*;import com.ecyrd.jspwiki.plugin.PluginManager;import com.ecyrd.jspwiki.plugin.PluginException;import com.ecyrd.jspwiki.attachment.AttachmentManager;import com.ecyrd.jspwiki.attachment.Attachment;import com.ecyrd.jspwiki.providers.ProviderException;/** * Handles conversion from Wiki format into fully featured HTML. * This is where all the magic happens. It is CRITICAL that this * class is tested, or all Wikis might die horribly. * <P> * The output of the HTML has not yet been validated against * the HTML DTD. However, it is very simple. * * @author Janne Jalkanen */public class TranslatorReader extends Reader{ public static final int READ = 0; public static final int EDIT = 1; private static final int EMPTY = 2; // Empty message private static final int LOCAL = 3; private static final int LOCALREF = 4; private static final int IMAGE = 5; private static final int EXTERNAL = 6; private static final int INTERWIKI = 7; private static final int IMAGELINK = 8; private static final int IMAGEWIKILINK = 9; public static final int ATTACHMENT = 10; private static final int ATTACHMENTIMAGE = 11; /** Allow this many characters to be pushed back in the stream. */ private static final int PUSHBACK_BUFFER_SIZE = 8; private PushbackReader m_in; private StringReader m_data = new StringReader(""); private static Category log = Category.getInstance( TranslatorReader.class ); //private boolean m_iscode = false; private boolean m_isbold = false; private boolean m_isitalic = false; private boolean m_isTypedText = false; private boolean m_istable = false; private boolean m_isPre = false; private boolean m_isdefinition = false; private int m_listlevel = 0; private int m_numlistlevel = 0; /** Tag that gets closed at EOL. */ private String m_closeTag = null; private WikiEngine m_engine; private WikiContext m_context; /** Optionally stores internal wikilinks */ private ArrayList m_localLinkMutatorChain = new ArrayList(); private ArrayList m_externalLinkMutatorChain = new ArrayList(); private ArrayList m_attachmentLinkMutatorChain = new ArrayList(); /** Keeps image regexp Patterns */ private ArrayList m_inlineImagePatterns; private PatternMatcher m_inlineMatcher = new Perl5Matcher(); private ArrayList m_linkMutators = new ArrayList(); /** * This property defines the inline image pattern. It's current value * is jspwiki.translatorReader.inlinePattern */ public static final String PROP_INLINEIMAGEPTRN = "jspwiki.translatorReader.inlinePattern"; /** If true, consider CamelCase hyperlinks as well. */ public static final String PROP_CAMELCASELINKS = "jspwiki.translatorReader.camelCaseLinks"; /** If true, all hyperlinks are translated as well, regardless whether they are surrounded by brackets. */ public static final String PROP_PLAINURIS = "jspwiki.translatorReader.plainUris"; /** If true, all outward links (external links) have a small link image appended. */ public static final String PROP_USEOUTLINKIMAGE = "jspwiki.translatorReader.useOutlinkImage"; /** 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 true, then considers CamelCase links as well. */ private boolean m_camelCaseLinks = false; /** If true, consider URIs that have no brackets as well. */ // FIXME: Currently reserved, but not used. private boolean m_plainUris = false; /** If true, all outward links use a small link image. */ private boolean m_useOutlinkImage = true; /** If true, allows raw HTML. */ private boolean m_allowHTML = false; private PatternMatcher m_matcher = new Perl5Matcher(); private PatternCompiler m_compiler = new Perl5Compiler(); private Pattern m_camelCasePtrn; /** * The default inlining pattern. Currently "*.png" */ public static final String DEFAULT_INLINEPATTERN = "*.png"; /** * These characters constitute word separators when trying * to find CamelCase links. */ private static final String WORD_SEPARATORS = ",.|:;+=&"; /** * @param engine The WikiEngine this reader is attached to. Is * used to figure out of a page exits. */ // FIXME: TranslatorReaders should be pooled for better performance. public TranslatorReader( WikiContext context, Reader in ) { PatternCompiler compiler = new GlobCompiler(); ArrayList compiledpatterns = new ArrayList(); m_in = new PushbackReader( new BufferedReader( in ), PUSHBACK_BUFFER_SIZE ); m_engine = context.getEngine(); m_context = context; Collection ptrns = getImagePatterns( m_engine ); // // Make them into Regexp Patterns. Unknown patterns // are ignored. // for( Iterator i = ptrns.iterator(); i.hasNext(); ) { try { compiledpatterns.add( compiler.compile( (String)i.next() ) ); } catch( MalformedPatternException e ) { log.error("Malformed pattern in properties: ", e ); } } m_inlineImagePatterns = compiledpatterns; try { m_camelCasePtrn = m_compiler.compile( "^([[:^alnum:]]*|\\~)([[:upper:]]+[[:lower:]]+[[:upper:]]+[[:alnum:]]*)[[:^alnum:]]*$" ); } catch( MalformedPatternException e ) { log.fatal("Internal error: Someone put in a faulty pattern.",e); throw new InternalWikiException("Faulty camelcasepattern in TranslatorReader"); } // // Set the properties. // Properties props = m_engine.getWikiProperties(); m_camelCaseLinks = TextUtil.getBooleanProperty( props, PROP_CAMELCASELINKS, m_camelCaseLinks ); m_plainUris = TextUtil.getBooleanProperty( props, PROP_PLAINURIS, m_plainUris ); m_useOutlinkImage = TextUtil.getBooleanProperty( props, PROP_USEOUTLINKIMAGE, m_useOutlinkImage ); m_allowHTML = TextUtil.getBooleanProperty( props, PROP_ALLOWHTML, m_allowHTML ); } /** * 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 ); } } /** * Figure out which image suffixes should be inlined. * @return Collection of Strings with patterns. */ protected static Collection getImagePatterns( WikiEngine engine ) { Properties props = engine.getWikiProperties(); ArrayList ptrnlist = new ArrayList(); for( Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { String name = (String) e.nextElement(); if( name.startsWith( PROP_INLINEIMAGEPTRN ) ) { String ptrn = props.getProperty( name ); ptrnlist.add( ptrn ); } } if( ptrnlist.size() == 0 ) { ptrnlist.add( DEFAULT_INLINEPATTERN ); } return ptrnlist; } /** * Returns link name, if it exists; otherwise it returns null. */ private String linkExists( String page ) { return m_engine.getFinalPageName( page ); } /** * Calls a transmutator chain. * * @param list Chain to call * @param text Text that should be passed to the mutate() method * of each of the mutators in the chain. * @return The result of the mutation. */ private String callMutatorChain( Collection list, String text ) { if( list == null || list.size() == 0 ) { return text; } for( Iterator i = list.iterator(); i.hasNext(); ) { StringTransmutator m = (StringTransmutator) i.next(); text = m.mutate( m_context, text ); } return text; } /** * Write a HTMLized link depending on its type. * The link mutator chain is processed. * * @param type Type of the link. * @param link The actual link. * @param text The user-visible text for the link. */ public String makeLink( int type, String link, String text ) { String result; if( text == null ) text = link; // Make sure we make a link name that can be accepted // as a valid URL. String encodedlink = m_engine.encodeName( link ); if( encodedlink.length() == 0 ) { type = EMPTY; } text = callMutatorChain( m_linkMutators, text ); switch(type) { case READ: result = "<A CLASS=\"wikipage\" HREF=\""+m_engine.getViewURL(link)+"\">"+text+"</A>"; break; case EDIT: result = "<U>"+text+"</U><A HREF=\""+m_engine.getEditURL(link)+"\">?</A>"; break; case EMPTY: result = "<U>"+text+"</U>"; break; // // These two are for local references - footnotes and // references to footnotes. // We embed the page name (or whatever WikiContext gives us) // to make sure the links are unique across Wiki. // case LOCALREF: result = "<A CLASS=\"footnoteref\" HREF=\"#ref-"+ m_context.getPage().getName()+"-"+ link+"\">["+text+"]</A>"; break; case LOCAL: result = "<A CLASS=\"footnote\" NAME=\"ref-"+ m_context.getPage().getName()+"-"+ link.substring(1)+"\">["+text+"]</A>"; break; // // With the image, external and interwiki types we need to // make sure nobody can put in Javascript or something else // annoying into the links themselves. We do this by preventing // a haxor from stopping the link name short with quotes in // fillBuffer(). // case IMAGE: result = "<IMG CLASS=\"inline\" SRC=\""+link+"\" ALT=\""+text+"\" />"; break; case IMAGELINK: result = "<A HREF=\""+text+"\"><IMG CLASS=\"inline\" SRC=\""+link+"\" /></A>"; break; case IMAGEWIKILINK: String pagelink = m_engine.getViewURL(text); result = "<A CLASS=\"wikipage\" HREF=\""+pagelink+"\"><IMG CLASS=\"inline\" SRC=\""+link+"\" ALT=\""+text+"\" /></A>"; break; case EXTERNAL: result = "<A CLASS=\"external\" HREF=\""+link+"\">"+text+"</A>"; break; case INTERWIKI: result = "<A CLASS=\"interwiki\" HREF=\""+link+"\">"+text+"</A>"; break; case ATTACHMENT: String attlink = m_engine.getAttachmentURL( link ); result = "<a class=\"attachment\" href=\""+attlink+"\">"+text+"</a>"+ "<a href=\""+m_engine.getBaseURL()+"PageInfo.jsp?page="+encodedlink+ "\"><img src=\"images/attachment_small.png\" border=\"0\" /></a>"; break; default: result = ""; break; } return result; } /** * Cleans a Wiki name. * <P> * [ This is a link ] -> ThisIsALink * * @param link Link to be cleared. Null is safe, and causes this to return null. * @return A cleaned link. * * @since 2.0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -