--- /dev/null
+package org.plog4u.wiki.filter;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.HashSet;
+
+
+import org.plog4u.wiki.filter.tags.AbstractTag;
+import org.plog4u.wiki.filter.tags.CloseTagToken;
+import org.plog4u.wiki.filter.tags.DivTag;
+import org.plog4u.wiki.filter.tags.FontTag;
+import org.plog4u.wiki.filter.tags.OpenTagToken;
+import org.plog4u.wiki.filter.tags.SpecialTagToken;
+import org.plog4u.wiki.filter.tags.TableTag;
+import org.radeox.api.engine.ImageRenderEngine;
+import org.radeox.api.engine.IncludeRenderEngine;
+import org.radeox.api.engine.RenderEngine;
+import org.radeox.api.engine.WikiRenderEngine;
+import org.radeox.filter.CacheFilter;
+import org.radeox.filter.FilterSupport;
+import org.radeox.filter.context.FilterContext;
+import org.radeox.filter.interwiki.InterWiki;
+import org.radeox.macro.Macro;
+import org.radeox.macro.MacroRepository;
+import org.radeox.macro.parameter.MacroParameter;
+import org.radeox.util.Encoder;
+import org.radeox.util.StringBufferWriter;
+
+//import org.snipsnap.app.Application;
+//import org.snipsnap.fUser.Configuration;
+//import org.snipsnap.app.Application;
+
+/**
+ * Parse the input and transform it for the most used wiki patterns
+ *
+ * Parts of the Wiki Syntax are borrowed from Wikipedia.org and SnipSnap.org
+ *
+ * @see org.plog4u.wiki.filter.WikipediaParser
+ */
+public class WikipediaFilter extends FilterSupport implements CacheFilter, IWikipediaFilterConstants {
+
+ public class InvalidInputException extends Exception {
+
+ public InvalidInputException() {
+ super();
+ }
+
+ public InvalidInputException(String s) {
+ super(s);
+ }
+ }
+
+
+
+// public static class ListToken extends Token {
+// int fLevel;
+//
+// public ListToken(int token, int level) {
+// super(token);
+// fLevel = level;
+// }
+//
+// public int getLevel() {
+// return fLevel;
+// }
+// }
+//
+// public static class OpenTagToken extends Token {
+// private String fTagName;
+// private String fOpenTag;
+//
+// public OpenTagToken(int token, String name, String openTag) {
+// super(token);
+// fTagName = name;
+// fOpenTag = openTag;
+//
+// }
+//
+// public String getTagName() {
+// return fTagName;
+// }
+//
+// public String getOpenTag() {
+// return fOpenTag;
+// }
+//
+// public void setTagName(String name) {
+// fTagName = name;
+// }
+//
+// public void setOpenTag(String openTag) {
+// fOpenTag = openTag;
+// }
+// }
+//
+// public static class SpecialTagToken extends OpenTagToken {
+// public SpecialTagToken(int token, String name, String openTag) {
+// super(token, name, openTag);
+// }
+// }
+//
+// public static class CloseTagToken extends Token {
+// private String fTagName;
+// private String fCloseTag;
+//
+// public CloseTagToken(int token, String name, String closeTag) {
+// super(token);
+// fTagName = name;
+// fCloseTag = closeTag;
+// }
+//
+// public String getTagName() {
+// return fTagName;
+// }
+//
+// public String getCloseTag() {
+// return fCloseTag;
+// }
+//
+// public void setTagName(String name) {
+// fTagName = name;
+// }
+//
+// public void setCloseTag(String closeTag) {
+// fCloseTag = closeTag;
+// }
+//
+// }
+ final static String HEADER_STRINGS[] = { "=", "==", "===", "====", "=====", "======" };
+
+ final static int TokenNotFound = -2;
+ final static int TokenIgnore = -1;
+ final static int TokenSTART = 0;
+ final static int TokenEOF = 1;
+ final static int TokenERROR = 2;
+ final static int TokenBOLD = 3;
+ final static int TokenITALIC = 4;
+ final static int TokenSTRIKETHROUGH = 5;
+ final static int TokenSTRONG = 8;
+ final static int TokenEM = 9;
+
+ final static int TokenCOMMA = 134;
+
+ final static int TokenDOLLAR_LBRACE = 127;
+
+ final static int TokenLIST_UL_START = 50;
+ final static int TokenLIST_OL_START = 51;
+
+ final static int TokenLIST_UL_END = 75;
+ final static int TokenLIST_OL_END = 76;
+
+ final static int TokenHTML_BR_OPEN = 190;
+ final static int TokenHTML_HR_OPEN = 191;
+
+ final static int TokenHTML_BOLD_OPEN = 200;
+ final static int TokenHTML_BOLD_CLOSE = 201;
+ final static int TokenHTML_ITALIC_OPEN = 202;
+ final static int TokenHTML_ITALIC_CLOSE = 203;
+ final static int TokenHTML_UNDERLINE_OPEN = 204;
+ final static int TokenHTML_UNDERLINE_CLOSE = 205;
+ final static int TokenHTML_STRIKE_OPEN = 206;
+ final static int TokenHTML_STRIKE_CLOSE = 207;
+ final static int TokenHTML_PARAGRAPH_OPEN = 208;
+ final static int TokenHTML_PARAGRAPH_CLOSE = 209;
+ final static int TokenHTML_PRE_OPEN = 210;
+ final static int TokenHTML_PRE_CLOSE = 211;
+ final static int TokenHTML_BLOCKQUOTE_OPEN = 212;
+ final static int TokenHTML_BLOCKQUOTE_CLOSE = 213;
+ final static int TokenHTML_SUB_OPEN = 216;
+ final static int TokenHTML_SUB_CLOSE = 217;
+ final static int TokenHTML_SUP_OPEN = 218;
+ final static int TokenHTML_SUP_CLOSE = 219;
+
+ final static int TokenHTML_H1_CLOSE = 221;
+
+ final static int TokenHTML_H1_OPEN = 220;
+ final static int TokenHTML_H2_CLOSE = 223;
+ final static int TokenHTML_H2_OPEN = 222;
+ final static int TokenHTML_H3_CLOSE = 225;
+ final static int TokenHTML_H3_OPEN = 224;
+ final static int TokenHTML_H4_CLOSE = 227;
+ final static int TokenHTML_H4_OPEN = 226;
+ final static int TokenHTML_H5_CLOSE = 229;
+ final static int TokenHTML_H5_OPEN = 228;
+ final static int TokenHTML_H6_CLOSE = 231;
+ final static int TokenHTML_H6_OPEN = 230;
+ final static int TokenHTML_EM_OPEN = 240;
+ final static int TokenHTML_EM_CLOSE = 241;
+
+
+ final static int TokenHTML_STRONG_OPEN = 242;
+ final static int TokenHTML_STRONG_CLOSE = 243;
+
+ final static int TokenHTML_VAR_OPEN = 245;
+ final static int TokenHTML_VAR_CLOSE = 246;
+ final static int TokenHTML_CODE_OPEN = 247;
+ final static int TokenHTML_CODE_CLOSE = 248;
+
+ final static int TokenHTML_S_OPEN = 249;
+ final static int TokenHTML_S_CLOSE = 250;
+ final static int TokenHTML_SMALL_OPEN = 251;
+ final static int TokenHTML_SMALL_CLOSE = 252;
+
+ final static int TokenHTML_MATH_OPEN = 400;
+ final static int TokenHTML_MATH_CLOSE = 401;
+
+ final static int TokenHTML_TABLE_OPEN = 500;
+ final static int TokenHTML_TABLE_CLOSE = 501;
+ final static int TokenHTML_CAPTION_OPEN = 502;
+ final static int TokenHTML_CAPTION_CLOSE = 503;
+ final static int TokenHTML_TH_OPEN = 504;
+ final static int TokenHTML_TH_CLOSE = 505;
+ final static int TokenHTML_TR_OPEN = 506;
+ final static int TokenHTML_TR_CLOSE = 507;
+ final static int TokenHTML_TD_OPEN = 508;
+ final static int TokenHTML_TD_CLOSE = 509;
+
+ final static int TokenHTML_FONT_OPEN = 520;
+ final static int TokenHTML_FONT_CLOSE = 521;
+ final static int TokenHTML_CENTER_OPEN = 522;
+ final static int TokenHTML_CENTER_CLOSE = 523;
+ final static int TokenHTML_TT_OPEN = 524;
+ final static int TokenHTML_TT_CLOSE = 525;
+ final static int TokenHTML_DIV_OPEN = 526;
+ final static int TokenHTML_DIV_CLOSE = 527;
+
+ final static int TokenIdentifier = 138;
+ final static int TokenLBRACKET = 132;
+
+ final static int TokenLPAREN = 128;
+
+ final static int TokenPLUGIN_IDENTIFIER = 130;
+ final static int TokenRBRACE = 131;
+ final static int TokenRBRACKET = 133;
+ final static int TokenRPAREN = 129;
+
+ final static AbstractTag BOLD = new AbstractTag(TokenBOLD);
+ final static AbstractTag ITALIC = new AbstractTag(TokenITALIC);
+ final static AbstractTag STRONG = new AbstractTag(TokenSTRONG);
+ final static AbstractTag EM = new AbstractTag(TokenEM);
+
+ final static AbstractTag HTML_BR_OPEN = new SpecialTagToken(TokenHTML_BR_OPEN, "br", "<br/>");
+ final static AbstractTag HTML_HR_OPEN = new SpecialTagToken(TokenHTML_HR_OPEN, "hr", "<hr/>");
+
+ final static AbstractTag HTML_EM_CLOSE = new CloseTagToken(TokenHTML_EM_CLOSE, "em", "</i>");
+ final static AbstractTag HTML_EM_OPEN = new OpenTagToken(TokenHTML_EM_OPEN, "em", "<i>");
+ final static AbstractTag HTML_H1_CLOSE = new CloseTagToken(TokenHTML_H1_CLOSE, "h1", "</h1>");
+ final static AbstractTag HTML_H1_OPEN = new OpenTagToken(TokenHTML_H1_OPEN, "h1", "<h1>");
+ final static AbstractTag HTML_H2_CLOSE = new CloseTagToken(TokenHTML_H2_CLOSE, "h2", "</h2>");
+ final static AbstractTag HTML_H2_OPEN = new OpenTagToken(TokenHTML_H2_OPEN, "h2", "<h2>");
+ final static AbstractTag HTML_H3_CLOSE = new CloseTagToken(TokenHTML_H3_CLOSE, "h3", "</h3>");
+ final static AbstractTag HTML_H3_OPEN = new OpenTagToken(TokenHTML_H3_OPEN, "h3", "<h3>");
+ final static AbstractTag HTML_H4_CLOSE = new CloseTagToken(TokenHTML_H4_CLOSE, "h4", "</h4>");
+ final static AbstractTag HTML_H4_OPEN = new OpenTagToken(TokenHTML_H4_OPEN, "h4", "<h4>");
+ final static AbstractTag HTML_H5_CLOSE = new CloseTagToken(TokenHTML_H5_CLOSE, "h5", "</h5>");
+ final static AbstractTag HTML_H5_OPEN = new OpenTagToken(TokenHTML_H5_OPEN, "h5", "<h5>");
+ final static AbstractTag HTML_H6_CLOSE = new CloseTagToken(TokenHTML_H6_CLOSE, "h6", "</h6>");
+ final static AbstractTag HTML_H6_OPEN = new OpenTagToken(TokenHTML_H6_OPEN, "h6", "<h6>");
+ final static AbstractTag HTML_ITALIC_CLOSE = new CloseTagToken(TokenHTML_ITALIC_CLOSE, "i", "</i>");
+ final static AbstractTag HTML_ITALIC_OPEN = new OpenTagToken(TokenHTML_ITALIC_OPEN, "i", "<i>");
+ final static AbstractTag HTML_BOLD_CLOSE = new CloseTagToken(TokenHTML_BOLD_CLOSE, "b", "</b>");
+ final static AbstractTag HTML_BOLD_OPEN = new OpenTagToken(TokenHTML_BOLD_OPEN, "b", "<b>");
+
+ //
+ final static AbstractTag HTML_PARAGRAPH_CLOSE = new CloseTagToken(TokenHTML_PARAGRAPH_CLOSE, "p", "</p>");
+ final static AbstractTag HTML_PARAGRAPH_OPEN = new OpenTagToken(TokenHTML_PARAGRAPH_OPEN, "p", "<p>");
+ final static AbstractTag HTML_PRE_CLOSE = new CloseTagToken(TokenHTML_PRE_CLOSE, "pre", "</pre>");
+ final static AbstractTag HTML_PRE_OPEN = new OpenTagToken(TokenHTML_PRE_OPEN, "pre", "<pre>");
+ final static AbstractTag HTML_BLOCKQUOTE_CLOSE = new CloseTagToken(TokenHTML_BLOCKQUOTE_CLOSE, "blockquote", "</blockquote>");
+ final static AbstractTag HTML_BLOCKQUOTE_OPEN = new OpenTagToken(TokenHTML_BLOCKQUOTE_OPEN, "blockquote", "<blockquote>");
+ final static AbstractTag HTML_STRIKE_CLOSE = new CloseTagToken(TokenHTML_STRIKE_CLOSE, "strike", "</strike>");
+ final static AbstractTag HTML_STRIKE_OPEN = new OpenTagToken(TokenHTML_STRIKE_OPEN, "strike", "<strike>");
+ final static AbstractTag HTML_STRONG_CLOSE = new CloseTagToken(TokenHTML_STRONG_CLOSE, "strong", "</b>");
+ final static AbstractTag HTML_STRONG_OPEN = new OpenTagToken(TokenHTML_STRONG_OPEN, "strong", "<b>");
+ final static AbstractTag HTML_UNDERLINE_CLOSE = new CloseTagToken(TokenHTML_UNDERLINE_CLOSE, "u", "</u>");
+ final static AbstractTag HTML_UNDERLINE_OPEN = new OpenTagToken(TokenHTML_UNDERLINE_OPEN, "u", "<u>");
+ final static AbstractTag HTML_SUB_CLOSE = new CloseTagToken(TokenHTML_SUB_CLOSE, "sub", "</sub>");
+ final static AbstractTag HTML_SUB_OPEN = new OpenTagToken(TokenHTML_SUB_OPEN, "sub", "<sub>");
+ final static AbstractTag HTML_SUP_CLOSE = new CloseTagToken(TokenHTML_SUP_CLOSE, "sup", "</sup>");
+ final static AbstractTag HTML_SUP_OPEN = new OpenTagToken(TokenHTML_SUP_OPEN, "sup", "<sup>");
+
+ final static AbstractTag HTML_CENTER_OPEN = new OpenTagToken(TokenHTML_CENTER_OPEN, "center", "<center>");
+ final static AbstractTag HTML_CENTER_CLOSE = new CloseTagToken(TokenHTML_CENTER_CLOSE, "center", "</center>");
+ final static AbstractTag HTML_TT_OPEN = new OpenTagToken(TokenHTML_TT_OPEN, "tt", "<tt>");
+ final static AbstractTag HTML_TT_CLOSE = new CloseTagToken(TokenHTML_TT_CLOSE, "tt", "</tt>");
+
+ final static AbstractTag HTML_MATH_OPEN = new OpenTagToken(TokenHTML_MATH_OPEN, "math", "<math>");
+ final static AbstractTag HTML_MATH_CLOSE = new CloseTagToken(TokenHTML_MATH_CLOSE, "math", "</math>");
+
+ final static AbstractTag HTML_TABLE_OPEN = new TableTag(TokenHTML_TABLE_OPEN, "table", "<table>");
+ final static AbstractTag HTML_TABLE_CLOSE = new CloseTagToken(TokenHTML_TABLE_CLOSE, "table", "</table>");
+ final static AbstractTag HTML_CAPTION_OPEN = new OpenTagToken(TokenHTML_CAPTION_OPEN, "caption", "<caption>");
+ final static AbstractTag HTML_CAPTION_CLOSE = new CloseTagToken(TokenHTML_CAPTION_CLOSE, "caption", "</caption>");
+ final static AbstractTag HTML_TH_OPEN = new OpenTagToken(TokenHTML_TH_OPEN, "th", "<th>");
+ final static AbstractTag HTML_TH_CLOSE = new CloseTagToken(TokenHTML_TH_CLOSE, "th", "</th>");
+ final static AbstractTag HTML_TR_OPEN = new OpenTagToken(TokenHTML_TR_OPEN, "tr", "<tr>");
+ final static AbstractTag HTML_TR_CLOSE = new CloseTagToken(TokenHTML_TR_CLOSE, "tr", "</tr>");
+ final static AbstractTag HTML_TD_OPEN = new OpenTagToken(TokenHTML_TD_OPEN, "td", "<td>");
+ final static AbstractTag HTML_TD_CLOSE = new CloseTagToken(TokenHTML_TD_CLOSE, "td", "</td>");
+ final static AbstractTag HTML_FONT_OPEN = new FontTag(TokenHTML_FONT_OPEN, "font", "<font>");
+ final static AbstractTag HTML_FONT_CLOSE = new CloseTagToken(TokenHTML_FONT_CLOSE, "font", "</font>");
+ final static AbstractTag HTML_DIV_OPEN = new DivTag(TokenHTML_DIV_OPEN, "div", "<div>");
+ final static AbstractTag HTML_DIV_CLOSE = new CloseTagToken(TokenHTML_DIV_CLOSE, "div", "</div>");
+
+ final static AbstractTag LIST_OL_START = new AbstractTag(TokenLIST_OL_START);
+ final static AbstractTag LIST_UL_START = new AbstractTag(TokenLIST_UL_START);
+
+ final static AbstractTag HTML_VAR_OPEN = new OpenTagToken(TokenHTML_VAR_OPEN, "var", "<var>");
+ final static AbstractTag HTML_VAR_CLOSE = new CloseTagToken(TokenHTML_VAR_CLOSE, "var", "</var>");
+ final static AbstractTag HTML_CODE_OPEN = new OpenTagToken(TokenHTML_CODE_OPEN, "code", "<code>");
+ final static AbstractTag HTML_CODE_CLOSE = new CloseTagToken(TokenHTML_CODE_CLOSE, "code", "</code>");
+
+ // strikethrough
+ final static AbstractTag HTML_S_OPEN = new OpenTagToken(TokenHTML_S_OPEN, "s", "<s>");
+ final static AbstractTag HTML_S_CLOSE = new CloseTagToken(TokenHTML_S_CLOSE, "s", "</s>");
+ // small
+ final static AbstractTag HTML_SMALL_OPEN = new OpenTagToken(TokenHTML_SMALL_OPEN, "small", "<small>");
+ final static AbstractTag HTML_SMALL_CLOSE = new CloseTagToken(TokenHTML_SMALL_CLOSE, "small", "</small>");
+
+ final static HashMap OPEN_TAGS = new HashMap();
+ final static HashMap CLOSE_TAGS = new HashMap();
+
+ final static HashSet ENTITY_SET = new HashSet();
+ final static HashMap IMAGE_MAP = new HashMap();
+
+// private static Log log = LogFactory.getLog(WikipediaFilter.class);
+
+ {
+ for (int i = 0; i < ENTITY_STRINGS.length; i++) {
+ ENTITY_SET.add(ENTITY_STRINGS[i]);
+ }
+ for (int i = 0; i < IMAGE_STRINGS.length; i += 2) {
+ IMAGE_MAP.put(IMAGE_STRINGS[i], IMAGE_STRINGS[i + 1]);
+ }
+ OPEN_TAGS.put("br", HTML_BR_OPEN);
+ OPEN_TAGS.put("hr", HTML_HR_OPEN);
+
+ OPEN_TAGS.put("h1", HTML_H1_OPEN);
+ OPEN_TAGS.put("h2", HTML_H2_OPEN);
+ OPEN_TAGS.put("h3", HTML_H3_OPEN);
+ OPEN_TAGS.put("h4", HTML_H4_OPEN);
+ OPEN_TAGS.put("h5", HTML_H5_OPEN);
+ OPEN_TAGS.put("h6", HTML_H6_OPEN);
+
+ CLOSE_TAGS.put("h1", HTML_H1_CLOSE);
+ CLOSE_TAGS.put("h2", HTML_H2_CLOSE);
+ CLOSE_TAGS.put("h3", HTML_H1_CLOSE);
+ CLOSE_TAGS.put("h4", HTML_H2_CLOSE);
+ CLOSE_TAGS.put("h5", HTML_H1_CLOSE);
+ CLOSE_TAGS.put("h6", HTML_H2_CLOSE);
+
+ OPEN_TAGS.put("em", HTML_EM_OPEN);
+ CLOSE_TAGS.put("em", HTML_EM_CLOSE);
+ OPEN_TAGS.put("i", HTML_ITALIC_OPEN);
+ CLOSE_TAGS.put("i", HTML_ITALIC_CLOSE);
+ OPEN_TAGS.put("b", HTML_BOLD_OPEN);
+ CLOSE_TAGS.put("b", HTML_BOLD_CLOSE);
+ OPEN_TAGS.put("strong", HTML_STRONG_OPEN);
+ CLOSE_TAGS.put("strong", HTML_STRONG_CLOSE);
+ OPEN_TAGS.put("u", HTML_UNDERLINE_OPEN);
+ CLOSE_TAGS.put("u", HTML_UNDERLINE_CLOSE);
+ OPEN_TAGS.put("p", HTML_PARAGRAPH_OPEN);
+ CLOSE_TAGS.put("p", HTML_PARAGRAPH_CLOSE);
+
+ OPEN_TAGS.put("pre", HTML_PRE_OPEN);
+ CLOSE_TAGS.put("pre", HTML_PRE_CLOSE);
+ OPEN_TAGS.put("blockquote", HTML_BLOCKQUOTE_OPEN);
+ CLOSE_TAGS.put("blockquote", HTML_BLOCKQUOTE_CLOSE);
+
+ OPEN_TAGS.put("var", HTML_VAR_OPEN);
+ CLOSE_TAGS.put("var", HTML_VAR_CLOSE);
+ OPEN_TAGS.put("code", HTML_CODE_OPEN);
+ CLOSE_TAGS.put("code", HTML_CODE_CLOSE);
+ OPEN_TAGS.put("s", HTML_S_OPEN);
+ CLOSE_TAGS.put("s", HTML_S_CLOSE);
+ OPEN_TAGS.put("small", HTML_SMALL_OPEN);
+ CLOSE_TAGS.put("small", HTML_SMALL_CLOSE);
+ OPEN_TAGS.put("sub", HTML_SUB_OPEN);
+ CLOSE_TAGS.put("sub", HTML_SUB_CLOSE);
+ OPEN_TAGS.put("sup", HTML_SUP_OPEN);
+ CLOSE_TAGS.put("sup", HTML_SUP_CLOSE);
+ OPEN_TAGS.put("strike", HTML_STRIKE_OPEN);
+ CLOSE_TAGS.put("strike", HTML_STRIKE_CLOSE);
+
+ OPEN_TAGS.put("math", HTML_MATH_OPEN);
+ CLOSE_TAGS.put("math", HTML_MATH_CLOSE);
+
+ OPEN_TAGS.put("table", HTML_TABLE_OPEN);
+ CLOSE_TAGS.put("table", HTML_TABLE_CLOSE);
+ OPEN_TAGS.put("th", HTML_TH_OPEN);
+ CLOSE_TAGS.put("th", HTML_TH_CLOSE);
+ OPEN_TAGS.put("tr", HTML_TR_OPEN);
+ CLOSE_TAGS.put("tr", HTML_TR_CLOSE);
+ OPEN_TAGS.put("td", HTML_TD_OPEN);
+ CLOSE_TAGS.put("td", HTML_TD_CLOSE);
+ OPEN_TAGS.put("caption", HTML_CAPTION_OPEN);
+ CLOSE_TAGS.put("caption", HTML_CAPTION_CLOSE);
+
+ OPEN_TAGS.put("font", HTML_FONT_OPEN);
+ CLOSE_TAGS.put("font", HTML_FONT_CLOSE);
+ OPEN_TAGS.put("center", HTML_CENTER_OPEN);
+ CLOSE_TAGS.put("center", HTML_CENTER_CLOSE);
+ OPEN_TAGS.put("tt", HTML_TT_OPEN);
+ CLOSE_TAGS.put("tt", HTML_TT_CLOSE);
+ OPEN_TAGS.put("div", HTML_DIV_OPEN);
+ CLOSE_TAGS.put("div", HTML_DIV_CLOSE);
+ }
+
+ /**
+ * Limits the recursive call of this filter to a depth of RECURSION_LIMIT
+ */
+ final static int RECURSION_LIMIT = 5;
+
+ final static AbstractTag START = new AbstractTag(TokenSTART);
+
+ final static AbstractTag STRIKETHROUGH = new AbstractTag(TokenSTRIKETHROUGH);
+
+ /**
+ * Determines if the specified character may be part of a url
+ */
+ public final static boolean isUrlIdentifierPart(char ch) {
+ if (Character.isLetterOrDigit(ch)) {
+ return true;
+ }
+ final String test = "-_.!~*';/?:@#&=+$,";
+ return test.indexOf(ch) != (-1);
+ }
+
+ /**
+ * Determines if the specified character may be part of a wiki plugin identifier as other than the first character
+ */
+ public final static boolean isWikiPluginIdentifierPart(char ch) {
+ return Character.isLetterOrDigit(ch) || (ch == '_');
+ }
+
+ /**
+ * Determines if the specified character may be part the first character of a wiki plugin identifier
+ */
+ public final static boolean isWikiPluginIdentifierStart(char ch) {
+ return Character.isLetter(ch);
+ }
+
+ public static boolean createStaticImage(String imageTag, StringBuffer buff) {
+ String value = (String) IMAGE_MAP.get(imageTag);
+ if (value != null) {
+ buff.append(MessageFormat.format(value, ARGUMENTS));
+ return true;
+ }
+ return false;
+ }
+
+ // private MacroRepository macros;
+
+ public WikipediaFilter() {
+ super();
+ }
+
+ public String filter(String input, FilterContext context) {
+ return filter(input, context, MacroRepository.getInstance(), 0);
+ }
+
+ public String filter(
+ String input,
+ FilterContext context,
+ MacroRepository macros,
+ int recursionLevel) {
+ try {
+ if (++recursionLevel > RECURSION_LIMIT) {
+ String error = "<span class=\"error\">Error - recursion limit exceeded.</span>";
+ return error;
+ }
+
+ StringBuffer result = new StringBuffer(input.length() + input.length() / 10);
+ if (input.startsWith("#html")) {
+ // ignore first line
+ int index = input.indexOf('\n');
+ if (index != (-1)) {
+
+// Configuration fUser = Application.get().getUser();
+// if (fUser.isAdmin()) {
+ // admins are allowed to insert full html directly
+ String subst = input.substring(index + 1);
+ // for page preview:
+ return subst;
+// }
+ }
+ }
+ // instantiate inner Parser class
+ WikipediaParser parser = new WikipediaParser(macros, input, result, context, recursionLevel);
+ parser.parse();
+ return result.toString();
+ // Util.substitute(matcher, p, new Perl5Substitution(s, interps), result, limit);
+ } catch (Exception e) {
+ //log.warn("<span class=\"error\">Exception</span>: " + this + ": " + e);
+// log.warn("Exception for: " + " " + e);
+ e.printStackTrace();
+ } catch (Error err) {
+ //log.warn("<span class=\"error\">Error</span>: " + this + ": " + err);
+// log.warn("Error for: ");
+ err.printStackTrace();
+ }
+ String error = "<span class=\"error\">Error in Parser.</span>";
+ return error;
+ }
+
+ public static String filterParser(
+ String input,
+ FilterContext context,
+ MacroRepository macros,
+ int recursionLevel) {
+ try {
+ if (++recursionLevel > RECURSION_LIMIT) {
+ return "<span class=\"error\">Error - recursion limit exceeded.</span>";
+ }
+
+ StringBuffer result = new StringBuffer(input.length() + input.length() / 10);
+ // instantiate inner Parser class
+ WikipediaParser parser = new WikipediaParser(macros, input, result, context, recursionLevel);
+ parser.parse();
+ return result.toString();
+ // Util.substitute(matcher, p, new Perl5Substitution(s, interps), result, limit);
+ } catch (Exception e) {
+ //log.warn("<span class=\"error\">Exception</span>: " + this + ": " + e);
+// log.warn("Exception for: " + " " + e);
+ e.printStackTrace();
+ } catch (Error err) {
+ //log.warn("<span class=\"error\">Error</span>: " + this + ": " + err);
+// log.warn("Error for: ");
+ err.printStackTrace();
+ }
+
+ return "<span class=\"error\">Error in Parser.</span>";
+ }
+
+ // private void filterParams(StringBuffer buffer, String name) {
+ // Map param = fContext.getRenderContext().getParameters();
+ // if (param != null) {
+ // if (param.containsKey(name)) {
+ // Object value = param.get(name);
+ // if (value instanceof String[]) {
+ // buffer.append(((String[]) value)[0]);
+ // } else {
+ // buffer.append(value);
+ // }
+ // } else {
+ // buffer.append("<");
+ // buffer.append(name);
+ // buffer.append(">");
+ // }
+ // } else {
+ // buffer.append("<");
+ // buffer.append(name);
+ // buffer.append(">");
+ // }
+ // }
+
+ // public String parseParameters(String unsplittedMacroParameters) {
+ // int currPos = 0;
+ // int currEndPos = 0;
+ // int len = unsplittedMacroParameters.length();
+ // StringBuffer buffer = new StringBuffer(len);
+ // char ch;
+ // while (currPos < len) {
+ // ch = unsplittedMacroParameters.charAt(currPos++);
+ // if (ch != '$') {
+ // buffer.append(ch);
+ // } else {
+ // if ((currEndPos = unsplittedMacroParameters.indexOf('|', currPos)) >= 1) {
+ // filterParams(buffer, unsplittedMacroParameters.substring(currPos, currEndPos));
+ // currPos = currEndPos + 1;
+ // buffer.append('|');
+ // } else {
+ // if (currPos < len) {
+ // filterParams(buffer, unsplittedMacroParameters.substring(currPos, len));
+ // }
+ // }
+ // }
+ // }
+ // return buffer.toString();
+ // }
+
+ // protected Repository getMacroRepository() {
+ // return macros;
+ // }
+
+ // public void setInitialContext(InitialRenderContext context) {
+ // macros = MacroRepository.getInstance();
+ // macros.setInitialContext(context);
+ // }
+
+ public static void copyWhite(StringBuffer result, String text) {
+ final int len = text.length();
+ int currentIndex = 0;
+ int lastIndex = currentIndex;
+ while (currentIndex < len) {
+ switch (text.charAt(currentIndex++)) {
+ case '<' : // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ result.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ result.append("<");
+ break;
+ case '>' : // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ result.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ result.append(">");
+ break;
+ case '&' : // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ result.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ result.append("&");
+ break;
+ case '\'' : // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ result.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ result.append("'");
+ break;
+ case '\"' : // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ result.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ result.append(""");
+ break;
+ }
+ }
+ if (lastIndex < (currentIndex)) {
+ result.append(text.substring(lastIndex, currentIndex));
+ }
+ }
+
+ public static void createMacro(StringBuffer result, String macroCommand, FilterContext context, MacroRepository macros) {
+ String command = "";
+ String endTag;
+
+ String parameterString = null;
+ String macroBodyString = "";
+ int index0 = 0;
+ int index1 = macroCommand.indexOf('}');
+ if ((index0 = macroCommand.indexOf(':')) >= 0 && (index0 < index1)) {
+ command = macroCommand.substring(1, index0);
+ parameterString = macroCommand.substring(index0 + 1, index1);
+ } else {
+ command = macroCommand.substring(1, index1);
+ }
+ Macro macro = (Macro) macros.get(command);
+
+ String completeMacroSubString;
+
+ if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
+ endTag = '{' + command + '}';
+ index0 = macroCommand.indexOf(endTag, command.length());
+
+ if (index0 >= 0) {
+ macroBodyString = macroCommand.substring(index1 + 1, index0);
+ }
+ }
+ completeMacroSubString = macroCommand;
+
+ handleMacro(result, completeMacroSubString, command, parameterString, macroBodyString, context, macros);
+
+ }
+
+ private static void handleMacro(
+ StringBuffer result,
+ String completeMacroSubString,
+ String command,
+ String unsplittedMacroParameters,
+ String group3,
+ FilterContext context,
+ MacroRepository macros) {
+ if (command != null) {
+ // {$peng} are variables not macros.
+ if (!command.startsWith("$")) {
+ MacroParameter mParams = context.getMacroParameter();
+
+ if (group3 != null) {
+ mParams.setContent(group3);
+ mParams.setContentStart(0);
+ mParams.setContentEnd(group3.length());
+ }
+ if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
+ // mParams.setParams(parseParameters(unsplittedMacroParameters));
+ mParams.setParams(unsplittedMacroParameters);
+ }
+ mParams.setStart(0);
+ mParams.setEnd(completeMacroSubString.length());
+
+ // @DANGER: recursive calls may replace macros in included source code
+ try {
+ if (macros.containsKey(command)) {
+
+ Macro macro = (Macro) macros.get(command);
+ // recursively filter macros within macros
+ if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
+ mParams.setContent(filterParser(mParams.getContent(), context, macros, 0));
+ }
+ StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
+ macro.execute(writer, mParams);
+ StringBuffer buffer = writer.getBuffer();
+ if (macro instanceof IRenderResultMacro) {
+ result.append(filterParser(buffer.toString(), context, macros, 0));
+ } else {
+ result.append(buffer);
+ }
+
+ } else if (command.startsWith("!")) {
+ RenderEngine engine = context.getRenderContext().getRenderEngine();
+ if (engine instanceof IncludeRenderEngine) {
+ String include = ((IncludeRenderEngine) engine).include(command.substring(1));
+ if (null != include) {
+ // Filter paramFilter = new ParamFilter(mParams);
+ // included = paramFilter.filter(included, null);
+ // fResult.append(include);
+ result.append(filterParser(include, context, macros, 0));
+ } else {
+ result.append(command.substring(1) + " not found.");
+ }
+ }
+ return;
+ } else {
+ // fResult.append(group0);
+ copyWhite(result, completeMacroSubString);
+ return;
+ }
+ } catch (IllegalArgumentException e) {
+ result.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+
+ e.printStackTrace();
+
+ } catch (Throwable e) {
+// log.warn("MacroFilter: unable to format macro: " + command, e);
+ result.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+ e.printStackTrace();
+ return;
+ }
+ } else {
+ result.append("<");
+ result.append(command.substring(1));
+ result.append(">");
+ }
+ } else {
+ // fResult.append(group0);
+ copyWhite(result, completeMacroSubString);
+ }
+ }
+
+ public static void createExternalLink(StringBuffer result, RenderEngine wikiEngine, String urlString) {
+
+ // Does our engine know images?
+ if (wikiEngine instanceof ImageRenderEngine) {
+ result.append(((ImageRenderEngine) wikiEngine).getExternalImageLink());
+ }
+ result.append("<span class=\"nobr\">");
+ result.append("<a href=\"");
+ result.append(Encoder.escape(urlString));
+ result.append("\">");
+ result.append(Encoder.toEntity(urlString.charAt(0)) + urlString.substring(1));
+ result.append("</a></span>");
+ }
+
+ public static void handleSnipLink(StringBuffer result, RenderEngine wikiEngine, String name) {
+ if (name != null) {
+ int index = name.indexOf("http://");
+ // Configuration probably wrote [http://radeox.org] instead of http://radeox.org
+ if (index != -1) {
+ createExternalLink(result, wikiEngine, name.substring(index));
+ // show error
+ // fResult.append("<div class=\"error\">Do not surround URLs with [...].</div>");
+ } else {
+ // trim the name and unescape it
+ name = Encoder.unescape(name.trim());
+ // Is there an alias like [alias|link] ?
+ int pipeIndex = name.indexOf('|');
+ String alias = "";
+ if (-1 != pipeIndex) {
+ alias = name.substring(0, pipeIndex);
+ name = name.substring(pipeIndex + 1);
+ }
+
+ int hashIndex = name.lastIndexOf('#');
+
+ String hash = "";
+ if (-1 != hashIndex && hashIndex != name.length() - 1) {
+ hash = name.substring(hashIndex + 1);
+ name = name.substring(0, hashIndex);
+ }
+
+ int colonIndex = name.indexOf(':');
+ // typed link ?
+ if (-1 != colonIndex) {
+ // for now throw away the fType information
+ name = name.substring(colonIndex + 1);
+ }
+
+ int atIndex = name.lastIndexOf('@');
+ // InterWiki link ?
+ if (-1 != atIndex) {
+ String extSpace = name.substring(atIndex + 1);
+ // known extarnal space ?
+ InterWiki interWiki = InterWiki.getInstance();
+ if (interWiki.contains(extSpace)) {
+ name = name.substring(0, atIndex);
+ Writer writer = new StringBufferWriter(result);
+ try {
+ if (-1 != hashIndex) {
+ interWiki.expand(writer, extSpace, name, hash);
+ } else {
+ interWiki.expand(writer, extSpace, name, "");
+ }
+ } catch (IOException e) {
+// log.debug("InterWiki " + extSpace + " not found.");
+ }
+ } else {
+ result.append("[<span class=\"error\">");
+ result.append(name);
+ result.append("?</span>]");
+ }
+ } else {
+ // internal link
+ if (wikiEngine != null && wikiEngine instanceof WikiRenderEngine) {
+ if (((WikiRenderEngine) wikiEngine).exists(name)) {
+ String view = name;
+ if (-1 != pipeIndex) {
+ view = alias;
+ }
+ // Do not add hash if an alias was given
+ if (-1 != hashIndex) {
+ ((WikiRenderEngine) wikiEngine).appendLink(result, name, view, hash);
+ } else {
+ ((WikiRenderEngine) wikiEngine).appendLink(result, name, view);
+ }
+ } else if (((WikiRenderEngine) wikiEngine).showCreate()) {
+ ((WikiRenderEngine) wikiEngine).appendCreateLink(result, name, name);
+ // links with "create" are not cacheable because
+ // a missing wiki could be created
+ // TODO is this ok?
+ // fContext.getRenderContext().setCacheable(false);
+ } else {
+ // cannot display/create wiki, so just display the text
+ result.append(name);
+ }
+ } else {
+ // cannot display/create wiki, so just display the text
+ result.append(name);
+ }
+ }
+ }
+ }
+ }
+
+ public static void handleWikipediaLink(StringBuffer result, RenderEngine wikiEngine, String name, String suffix) {
+ if (name != null) {
+ int index = name.indexOf("http://");
+ // Configuration probably wrote [http://radeox.org] instead of http://radeox.org
+ if (index != -1) {
+ // createExternalLink(result, wikiEngine, name.substring(index));
+ String urlString = name.substring(index);
+ // Wikipedia like style:
+ int pipeIndex = urlString.indexOf(' ');
+ String alias = "";
+ if (-1 != pipeIndex) {
+ alias = urlString.substring(pipeIndex + 1);
+ urlString = urlString.substring(0, pipeIndex);
+ } else {
+ alias = urlString;
+ }
+
+ if (wikiEngine instanceof ImageRenderEngine) {
+ result.append(((ImageRenderEngine) wikiEngine).getExternalImageLink());
+ }
+ result.append("<span class=\"nobr\">");
+ result.append("<a href=\"");
+ result.append(Encoder.escape(urlString));
+ result.append("\">");
+ result.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
+ result.append("</a></span>");
+ } else {
+ if (suffix == null) {
+ suffix = "";
+ }
+ // trim the name and unescape it
+ name = Encoder.unescape(name.trim());
+
+ name = name.replaceAll(":","/");
+
+ // Is there an alias like [alias|link] ?
+ int pipeIndex = name.indexOf('|');
+ String alias = "";
+ if (-1 != pipeIndex) {
+ alias = name.substring(pipeIndex + 1);
+ name = name.substring(0, pipeIndex);
+ }
+
+ int hashIndex = name.lastIndexOf('#');
+
+ String hash = "";
+ if (-1 != hashIndex && hashIndex != name.length() - 1) {
+ hash = name.substring(hashIndex + 1);
+ name = name.substring(0, hashIndex);
+ }
+
+ int colonIndex = name.indexOf(':');
+ // typed link ?
+ if (-1 != colonIndex) {
+ // for now throw away the fType information
+ name = name.substring(colonIndex + 1);
+ }
+
+ int atIndex = name.lastIndexOf('@');
+ // InterWiki link ?
+ if (-1 != atIndex) {
+ String extSpace = name.substring(atIndex + 1);
+ // known external space ?
+ InterWiki interWiki = InterWiki.getInstance();
+ if (interWiki.contains(extSpace)) {
+ name = name.substring(0, atIndex);
+ Writer writer = new StringBufferWriter(result);
+ try {
+ if (-1 != hashIndex) {
+ interWiki.expand(writer, extSpace, name, hash);
+ } else {
+ interWiki.expand(writer, extSpace, name, "");
+ }
+ } catch (IOException e) {
+// log.debug("InterWiki " + extSpace + " not found.");
+ }
+ } else {
+ result.append("[<span class=\"error\">");
+ result.append(name);
+ result.append("?</span>]");
+ }
+ } else {
+ // internal link
+ if (wikiEngine != null && wikiEngine instanceof WikiRenderEngine) {
+ if (((WikiRenderEngine) wikiEngine).exists(name)) {
+ String view = name + suffix;
+ if (-1 != pipeIndex) {
+ view = alias + suffix;
+ }
+ // Do not add hash if an alias was given
+ if (-1 != hashIndex) {
+ ((WikiRenderEngine) wikiEngine).appendLink(result, name, view, hash);
+ } else {
+ ((WikiRenderEngine) wikiEngine).appendLink(result, name, view);
+ }
+ } else if (((WikiRenderEngine) wikiEngine).showCreate()) {
+ ((WikiRenderEngine) wikiEngine).appendCreateLink(result, name, name + suffix);
+ // links with "create" are not cacheable because
+ // a missing wiki could be created
+ // TODO is this ok?
+ // fContext.getRenderContext().setCacheable(false);
+ } else {
+ // cannot display/create wiki, so just display the text
+ result.append(name);
+ }
+ } else {
+ // cannot display/create wiki, so just display the text
+ result.append(name);
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+package org.plog4u.wiki.filter;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+//import org.apache.commons.logging.Log;
+//import org.apache.commons.logging.LogFactory;
+import org.plog4u.wiki.filter.WikipediaFilter.InvalidInputException;
+import org.plog4u.wiki.filter.tags.AbstractTag;
+import org.plog4u.wiki.filter.tags.CloseTagToken;
+import org.plog4u.wiki.filter.tags.ListToken;
+import org.plog4u.wiki.filter.tags.OpenTagToken;
+import org.plog4u.wiki.filter.tags.SpecialTagToken;
+import org.radeox.api.engine.ImageRenderEngine;
+import org.radeox.api.engine.IncludeRenderEngine;
+import org.radeox.api.engine.RenderEngine;
+import org.radeox.api.engine.WikiRenderEngine;
+import org.radeox.filter.context.FilterContext;
+import org.radeox.filter.interwiki.InterWiki;
+import org.radeox.macro.Macro;
+import org.radeox.macro.MacroRepository;
+import org.radeox.macro.parameter.MacroParameter;
+import org.radeox.util.Encoder;
+import org.radeox.util.StringBufferWriter;
+
+/**
+ * A parser for the WikipediaFilter
+ *
+ * @see org.plog4u.wiki.filter.WikipediaFilter
+ */
+public class WikipediaParser {
+ // private static Log log = LogFactory.getLog(WikipediaFilter.class);
+
+ MacroRepository fMacros;
+
+ private FilterContext fContext;
+
+ private RenderEngine fWikiEngine;
+
+ // TODO check, if this counter is correct in recursions:
+ private int fImageCounter;
+
+ /**
+ * The current snip
+ */
+ // private Snip fSnip;
+ /**
+ * If the snip contains headings for a "table of content" this buffer temporarily contains the start of the snip and the
+ * "table of content"
+ */
+ private StringBuffer fResultBufferHeader = null;
+
+ /**
+ * The buffer for the resulting HTML rendering from the current snip.
+ */
+ private StringBuffer fResultBuffer;
+
+ /**
+ * The wiki syntax string which should be parsed
+ */
+ private char[] fSource;
+
+ /**
+ * The corresponding String for the character source array
+ */
+ private final String fStringSource;
+
+ /**
+ * The current scanned character
+ */
+ private char fCurrentCharacter;
+
+ /**
+ * The current offset in the character source array
+ */
+ private int fCurrentPosition;
+
+ /**
+ * The current recursion level for this parser
+ */
+ private int fRecursionLevel;
+
+ private Stack fTokenStack;
+
+ // private Stack fTableStack;
+
+ private boolean fWhiteStart = false;
+
+ private int fWhiteStartPosition = 0;
+
+ // private TeXParser fTeXParser;
+ // private TeXParser fTeXImageParser;
+ /**
+ *
+ * "table of content"
+ *
+ */
+ private ArrayList fTableOfContent = null;
+
+ // private String fSrcPath;
+ // private String fBinPath;
+
+ public WikipediaParser(MacroRepository macros, String stringSource, StringBuffer result, FilterContext context, int recursionLevel) {
+ fContext = context;
+ fWikiEngine = context.getRenderContext().getRenderEngine();
+
+ // try {
+ // SnipMacroParameter params = (SnipMacroParameter)
+ // fContext.getMacroParameter();
+ // fSnip = params.getSnipRenderContext().getSnip();
+ // } catch (ClassCastException e) {
+ // e.printStackTrace();
+ // }
+ fMacros = macros;
+ fResultBuffer = result;
+ fStringSource = stringSource;
+ setSource(stringSource.toCharArray());
+ fRecursionLevel = recursionLevel;
+ fTokenStack = new Stack();
+ // fTableStack = new Stack();
+ // fTeXParser = new TeXParser("", "m:");
+ // fTeXImageParser = new TeXParser("", "");
+ fImageCounter = 1;
+
+ // fSrcPath = (String) fContext.getRenderContext().get("srcpath");
+ // if (fSrcPath==null) {
+ // fSrcPath = "";
+ // }
+ // fBinPath = (String) fContext.getRenderContext().get("binpath");
+ // if (fBinPath==null) {
+ // fBinPath = "";
+ // }
+ }
+
+ /**
+ * Check until a new-line was found, if there are only whitespace characters before the given endposition.
+ *
+ * @param startPosition
+ * @param endPosition
+ * @return -1 if no whitespace line is found from the end (i.e. endPosition); otherwise the offset directly after where the
+ * new-line was found
+ */
+ private int checkWhitespaces(int startPosition, int endPosition) {
+ char tempChar;
+ while (endPosition >= startPosition) {
+ if ((tempChar = fSource[endPosition--]) == '\n') {
+ return endPosition + 2;
+ }
+ if (tempChar != ' ' && tempChar != '\t' && tempChar != '\r') {
+ return -1;
+ }
+ }
+ if (endPosition < startPosition && endPosition >= 0) {
+ if ((tempChar = fSource[endPosition]) != '\n') {
+ return -1;
+ }
+ } else if (endPosition == (-1) && startPosition == 0) {
+ // special case at the start of a string
+ return 0;
+ }
+ return startPosition;
+ }
+
+ /**
+ * copy the content in the resulting buffer and escape special html characters (< > " & ')
+ */
+ private void copyWhite(boolean whiteStart, final int whiteStartPosition, final int diff) {
+ if (whiteStart) {
+ final int len = fCurrentPosition - diff;
+ int currentIndex = whiteStartPosition;
+ int lastIndex = currentIndex;
+ while (currentIndex < len) {
+ switch (fSource[currentIndex++]) {
+ case '<': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("<");
+ break;
+ case '>': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append(">");
+ break;
+ case '&': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("&");
+ break;
+ case '\'': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("'");
+ break;
+ case '\"': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append(""");
+ break;
+ }
+ }
+ if (lastIndex < (currentIndex)) {
+ fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex);
+ }
+ fWhiteStart = false;
+ }
+ }
+
+ /**
+ * copy the text in the resulting buffer and escape special html characters (< > " & ')
+ */
+ private void copyWhite(String text) {
+ final int len = text.length();
+ int currentIndex = 0;
+ int lastIndex = currentIndex;
+ while (currentIndex < len) {
+ switch (text.charAt(currentIndex++)) {
+ case '<': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ }
+ fResultBuffer.append("<");
+ break;
+ case '>': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append(">");
+ break;
+ case '&': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("&");
+ break;
+ case '\'': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("'");
+ break;
+ case '\"': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append(""");
+ break;
+ }
+ }
+ if (lastIndex < (currentIndex)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex));
+ }
+ }
+
+ /**
+ * Copy the text in the resulting buffer and escape special html characters (< > " & ') Additionally every
+ * newline will be replaced by <br/>
+ */
+ private void copyNowikiNewLine(String text) {
+ final int len = text.length();
+ int currentIndex = 0;
+ int lastIndex = currentIndex;
+ while (currentIndex < len) {
+ switch (text.charAt(currentIndex++)) {
+ case '\n':
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("<br/>");
+ break;
+ case '<': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("<");
+ break;
+ case '>': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append(">");
+ break;
+ // case '&': // special html escape character
+ // if (lastIndex < (currentIndex - 1)) {
+ // fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ // lastIndex = currentIndex;
+ // } else {
+ // lastIndex++;
+ // }
+ // fResultBuffer.append("&");
+ // break;
+ case '\'': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append("'");
+ break;
+ case '\"': // special html escape character
+ if (lastIndex < (currentIndex - 1)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+ lastIndex = currentIndex;
+ } else {
+ lastIndex++;
+ }
+ fResultBuffer.append(""");
+ break;
+ }
+ }
+ if (lastIndex < (currentIndex)) {
+ fResultBuffer.append(text.substring(lastIndex, currentIndex));
+ }
+ }
+
+ /**
+ * Render the HTML token which are defined in the OPEN_TAGS and CLOSE_TAGS map
+ *
+ * @return
+ */
+ public int getHTMLToken() {
+ int currentHtmlPosition = fCurrentPosition;
+ try {
+ char closeCharacter;
+ char nextCharacter;
+ if (getNextChar('/')) {
+ currentHtmlPosition++;
+ // closing tag
+ int r = readUntilCharOrEOL('>');
+ if (r != 1) {
+ return WikipediaFilter.TokenNotFound;
+ }
+ String closeTagString = new String(fSource, currentHtmlPosition, fCurrentPosition - currentHtmlPosition - 1).toLowerCase();
+ // System.out.println(closeTagString);
+ StringTokenizer tagTokenizer = new StringTokenizer(closeTagString);
+ String tokenString;
+ try {
+ tokenString = tagTokenizer.nextToken();
+ CloseTagToken token = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tokenString);
+ if (token == null) {
+ return WikipediaFilter.TokenNotFound;
+ }
+ Object topToken = fTokenStack.peek();
+ if (topToken instanceof OpenTagToken && ((OpenTagToken) topToken).getTagName() == token.getTagName()) {
+ fTokenStack.pop();
+ // if (token.getTagName().equals("table")) {
+ // fTableStack.pop();
+ // }
+ copyWhite(fWhiteStart, fWhiteStartPosition, 3 + tokenString.length());
+ fWhiteStart = false;
+ fResultBuffer.append(token.getCloseTag());
+ return WikipediaFilter.TokenIgnore;
+ }
+ fWhiteStart = false;
+ unexpectedTag(token.getTagName());
+ return WikipediaFilter.TokenIgnore;
+ } catch (NoSuchElementException e) {
+ return WikipediaFilter.TokenNotFound;
+ }
+
+ } else {
+ // opening tag
+ String tokenString;
+ int tagNameStart = fCurrentPosition;
+ int tokenLength = 0;
+ while (Character.isJavaIdentifierStart(fSource[fCurrentPosition++])) {
+ tokenLength++;
+ }
+ try {
+ tokenString = new String(fSource, tagNameStart, fCurrentPosition - tagNameStart - 1); //tagTokenizer.nextToken();
+ OpenTagToken token = (OpenTagToken) WikipediaFilter.OPEN_TAGS.get(tokenString);
+ if (token == null) {
+ return WikipediaFilter.TokenNotFound;
+ }
+ copyWhite(fWhiteStart, fWhiteStartPosition, (fCurrentPosition - tagNameStart) + 1);
+ fWhiteStart = false;
+
+ if (token instanceof SpecialTagToken) {
+ fResultBuffer.append(token.getOpenTag());
+ while (Character.isWhitespace(fSource[fCurrentPosition])) {
+ fCurrentPosition++;
+ }
+ if (fSource[fCurrentPosition] == '/') {
+ fCurrentPosition++;
+ }
+ if (fSource[fCurrentPosition] == '>') {
+ fCurrentPosition++;
+ }
+ } else if (token instanceof OpenTagToken) {
+ fResultBuffer.append("<");
+ fResultBuffer.append(token.getTagName());
+ fTokenStack.push(token);
+ fCurrentPosition = token.scan(fResultBuffer, fSource, fCurrentPosition - 1);
+ fResultBuffer.append(">");
+ }
+
+ // System.out.println(fResultBuffer);
+ return WikipediaFilter.TokenIgnore;
+ } catch (NoSuchElementException e) {
+ return WikipediaFilter.TokenNotFound;
+ }
+ }
+
+ } catch (IndexOutOfBoundsException e) {
+ //
+ }
+ fCurrentPosition = currentHtmlPosition;
+ return WikipediaFilter.TokenNotFound;
+ }
+
+ public final boolean getNextChar(char testedChar) {
+ int temp = fCurrentPosition;
+ try {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter != testedChar) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ return true;
+
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ }
+
+ public final int getNextChar(char testedChar1, char testedChar2) {
+ int temp = fCurrentPosition;
+ try {
+ int result;
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter == testedChar1)
+ result = 0;
+ else if (fCurrentCharacter == testedChar2)
+ result = 1;
+ else {
+ fCurrentPosition = temp;
+ return -1;
+ }
+ return result;
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ return -1;
+ }
+ }
+
+ public final boolean getNextCharAsDigit() {
+ int temp = fCurrentPosition;
+ try {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (!Character.isDigit(fCurrentCharacter)) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ return true;
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ }
+
+ public final boolean getNextCharAsDigit(int radix) {
+
+ int temp = fCurrentPosition;
+ try {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+
+ if (Character.digit(fCurrentCharacter, radix) == -1) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ return true;
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ }
+
+ public final int getNumberOfChar(char testedChar) {
+ int number = 0;
+ try {
+ while ((fCurrentCharacter = fSource[fCurrentPosition++]) == testedChar) {
+ number++;
+ }
+ } catch (IndexOutOfBoundsException e) {
+
+ }
+ fCurrentPosition--;
+ return number;
+ }
+
+ public final char[] getListChars() {
+
+ int startPosition = fCurrentPosition - 1;
+ try {
+ while (true) {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter != '*' && fCurrentCharacter != '#') {
+ break;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ //
+ }
+ fCurrentPosition--;
+ char[] result = new char[fCurrentPosition - startPosition];
+ System.arraycopy(fSource, startPosition, result, 0, fCurrentPosition - startPosition);
+ return result;
+ }
+
+ public boolean getNextCharAsWikiPluginIdentifierPart() {
+ int temp = fCurrentPosition;
+ try {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+
+ if (!WikipediaFilter.isWikiPluginIdentifierPart(fCurrentCharacter)) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ return true;
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ }
+
+ private void stopList() {
+ while (!fTokenStack.isEmpty()) {
+ AbstractTag tok = (AbstractTag) fTokenStack.peek();
+ if (tok.equals(WikipediaFilter.LIST_UL_START)) {
+ fTokenStack.pop();
+ fResultBuffer.append("</li></ul>");
+ } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
+ fTokenStack.pop();
+ fResultBuffer.append("</li></ol>");
+ } else if (tok == WikipediaFilter.BOLD) {
+ fTokenStack.pop();
+ fResultBuffer.append("</b>");
+ } else if (tok == WikipediaFilter.ITALIC) {
+ fTokenStack.pop();
+ fResultBuffer.append("</i>");
+ } else if (tok == WikipediaFilter.STRONG) {
+ fTokenStack.pop();
+ fResultBuffer.append("</strong>");
+ } else if (tok == WikipediaFilter.EM) {
+ fTokenStack.pop();
+ fResultBuffer.append("</em>");
+ } else if (tok == WikipediaFilter.STRIKETHROUGH) {
+ fTokenStack.pop();
+ fResultBuffer.append("</strike>");
+ } else {
+ break;
+ }
+ }
+ }
+
+ protected int getNextToken() throws InvalidInputException {
+ boolean startOfIndent = false;
+ fWhiteStartPosition = 0;
+ fWhiteStart = false;
+ try {
+ while (true) {
+ // fStartPosition = fCurrentPosition;
+ fCurrentCharacter = fSource[fCurrentPosition++];
+
+ // ---------Identify the next token-------------
+ switch (fCurrentCharacter) {
+ case '\n':
+ if (fWhiteStart) {
+ int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 2);
+ if (tempPosition >= 0) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - (++tempPosition));
+ fWhiteStart = false;
+ stopList();
+ fResultBuffer.append("<p/>");
+ // continue;
+ }
+
+ }
+ int fStartPrePosition = fCurrentPosition;
+ boolean preSection = false;
+ try {
+ while (fSource[fCurrentPosition++] == ' ') {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ while (fCurrentCharacter != '\n') {
+ if (!Character.isWhitespace(fCurrentCharacter)) {
+ // preformatted section starts here
+ preSection = true;
+ }
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ }
+ --fCurrentPosition;
+ } catch (IndexOutOfBoundsException e) {
+
+ }
+ if (preSection && fRecursionLevel == 1) {
+ String preString;
+ copyWhite(fWhiteStart, fStartPrePosition, fCurrentPosition - fStartPrePosition);
+ fWhiteStart = true;
+ fResultBuffer.append("<pre>");
+ // copyWhite(fWhiteStart, fStartPrePosition, 1);
+ preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1) + '\n';
+ fResultBuffer.append(WikipediaFilter.filterParser(preString, fContext, fMacros, fRecursionLevel));
+ // preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1)+'\n';
+ // int preIndex = 0;
+ // int lastIndex = 0;
+ // while (preIndex>=0) {
+ // preIndex = preString.indexOf('\n', lastIndex);
+ // if (preIndex>=0) {
+ // fResultBuffer.append(WikipediaFilter.filterParser(preString.substring(lastIndex,preIndex), fContext,
+ // fCachedPage, fMacros, fRecursionLevel));
+ // fResultBuffer.append('\n');
+ // lastIndex = ++preIndex;
+ // }
+ // }
+ fResultBuffer.append("</pre>");
+ fWhiteStart = false;
+ continue;
+ } else {
+ fCurrentPosition = fStartPrePosition;
+ }
+ break;
+ case ':':
+ if (isStartOfLine()) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ fWhiteStart = false;
+
+ int levelHeader = getNumberOfChar(':') + 1;
+ int startHeadPosition = fCurrentPosition;
+ if (readUntilEOL()) {
+ String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
+ for (int i = 0; i < levelHeader; i++) {
+ fResultBuffer.append("<dl><dd>");
+ }
+ fResultBuffer.append(head);
+ for (int i = 0; i < levelHeader; i++) {
+ fResultBuffer.append("</dd></dl>");
+ }
+ continue;
+ }
+
+ continue;
+ }
+ break;
+ case ';':
+ if (isStartOfLine() && getNextChar(' ')) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ fWhiteStart = false;
+
+ int startHeadPosition = fCurrentPosition;
+ if (readUntilEOL()) {
+ // TODO not correct - improve this
+ String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
+ int index = head.indexOf(": ");
+ if (index > 0) {
+ fResultBuffer.append("<dl><dt>");
+ fResultBuffer.append(head.substring(0,index));
+ fResultBuffer.append("</dt><dd>");
+ fResultBuffer.append(head.substring(index+2));
+ fResultBuffer.append("</dd></dl>");
+ } else {
+ fResultBuffer.append("<dl><dt>");
+ fResultBuffer.append(head);
+ fResultBuffer.append("</dt></dl>");
+ }
+ continue;
+ }
+
+ continue;
+ }
+ break;
+ // case '\\': // special characters follow
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ // fWhiteStart = false;
+ // try {
+ // fCurrentCharacter = fSource[fCurrentPosition++];
+ // switch (fCurrentCharacter) {
+ // case '\\': // newline
+ // if ((fCurrentCharacter = fSource[fCurrentPosition++]) == '\\') {
+ // fResultBuffer.append(Encoder
+ // .toEntity(fCurrentCharacter));
+ // break;
+ // } else {
+ // fResultBuffer.append("<br />");
+ // break;
+ // }
+ // default:
+ // fResultBuffer.append(Encoder
+ // .toEntity(fCurrentCharacter));
+ // }
+ // } catch (IndexOutOfBoundsException e) {
+ //
+ // }
+ // continue;
+ // case '$' : // detect tex math
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ // fWhiteStart = false;
+ // startOfIndent = false;
+ // int startMathPosition = fCurrentPosition;
+ // if (getNextChar('$')) {
+ // startMathPosition = fCurrentPosition;
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+ // fWhiteStart = false;
+ // if (readUntilString("$$")) {
+ // String mathContent = new String(fSource, startMathPosition,
+ // fCurrentPosition - startMathPosition - 2);
+ // if (mathContent != null) {
+ // handleTeXMath(mathContent, false);
+ // continue;
+ // }
+ // }
+ // } else {
+ // if (readUntilChar('$')) {
+ // String mathContent = new String(fSource, startMathPosition,
+ // fCurrentPosition - startMathPosition - 1);
+ // if (mathContent != null) {
+ // handleTeXMath(mathContent, true);
+ // continue;
+ // }
+ // }
+ // }
+ // break;
+ case '{':
+ // detect macros
+ copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ fWhiteStart = false;
+ // boolean scanBody = true;
+ int startMacroPosition = fCurrentPosition;
+ if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia
+ // table
+ // syntax
+ continue;
+ } else {
+ if (readUntilChar('}')) {
+ String macroStartTag;
+
+ macroStartTag = new String(fSource, startMacroPosition, fCurrentPosition - startMacroPosition - 1);
+ if (macroStartTag != null) {
+ createMacro(startMacroPosition, macroStartTag);
+ continue;
+ }
+ }
+ }
+ break;
+ case '[':
+ int startLinkPosition = fCurrentPosition;
+ if (getNextChar('[')) { // wikipedia link style
+ startLinkPosition = fCurrentPosition;
+ copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+ fWhiteStart = false;
+ if (readUntilString("]]")) {
+ String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 2);
+ // test for suffix string
+ int temp = fCurrentPosition;
+ StringBuffer suffixBuffer = new StringBuffer();
+ try {
+ while (true) {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (!Character.isLetterOrDigit(fCurrentCharacter)) {
+ fCurrentPosition--;
+ break;
+ }
+ suffixBuffer.append(fCurrentCharacter);
+ }
+ handleWikipediaLink(name, suffixBuffer.toString());
+ continue;
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ }
+
+ handleWikipediaLink(name, "");
+ continue;
+ }
+
+ } else {
+ copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ fWhiteStart = false;
+
+ if (readUntilChar(']')) {
+ String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 1);
+ handleSnipLink(name);
+ continue;
+ }
+ }
+ break;
+ // case '1': // heading filter ?
+ // int temp1Position = checkWhitespaces(fWhiteStartPosition,
+ // fCurrentPosition - 2);
+ // if (temp1Position >= 0) {
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ // fWhiteStart = false;
+ // int simpleHeader = getNextChar(' ', '.');
+ // if (simpleHeader < 0) {
+ // if (getNextChar('1')) {
+ // fCurrentPosition--;
+ // if (getList('1', "<ol>", "</ol>")) {
+ // continue;
+ // }
+ // }
+ // break;
+ // }
+ // if (simpleHeader == 1 && !getNextChar('1')) {
+ // fCurrentPosition--;
+ // if (getList('1', "<ol>", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // }
+ // temp1Position = fCurrentPosition;
+ // if (simpleHeader >= 0 && readUntilChar('\n')) {
+ // String heading = new String(fSource, temp1Position,
+ // fCurrentPosition - temp1Position - 1);
+ // if (heading != null) {
+ // fResultBuffer.append("<h3 class=\"heading-");
+ // if (simpleHeader == 1) {
+ // fResultBuffer.append("1");
+ // } else {
+ // fResultBuffer.append("1-1");
+ // }
+ // fResultBuffer.append("\">");
+ // // System.out.println(heading);
+ // fResultBuffer
+ // .append(WikipediaFilter
+ // .filterParser(
+ // heading,
+ // fContext,
+ // WikipediaFilter.DUMMY_CACHED_PAGE,
+ // fMacros,
+ // fRecursionLevel));
+ // fResultBuffer.append("</h3>");
+ // continue;
+ // }
+ // }
+ // }
+ // break;
+ case '*': // <ul> list
+ case '#': // <ol> list
+ if (isStartOfLine()) {
+ char[] listChars = getListChars();
+ int tempStarPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - listChars.length);
+ if (tempStarPosition >= 0) {
+ appendList(listChars);
+ continue;
+ }
+ }
+ break;
+ // case '#': // <ol> list
+ // if (fCurrentPosition >= 2) {
+ // char beforeChar = fSource[fCurrentPosition - 2];
+ // if (beforeChar == '\n' || beforeChar == '\r') {
+ //
+ // int levelHash = getNumberOfChar('#') + 1;
+ //
+ // int tempHashPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHash);
+ // if (tempHashPosition >= 0) {
+ // copyWhite(fWhiteStart, fWhiteStartPosition, levelHash);
+ // fWhiteStart = false;
+ // AbstractTag tok = (AbstractTag) fTokenStack.peek();
+ // if (tok instanceof ListToken) {
+ // ListToken listToken = (ListToken) tok;
+ // int topLevel = listToken.getLevel();
+ // if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
+ // if (levelHash > topLevel) {
+ // fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
+ // fResultBuffer.append("<ol><li>");
+ // } else if (levelHash < topLevel) {
+ // fTokenStack.pop();
+ // fResultBuffer.append("</li></ol></li><li>");
+ // } else {
+ // fResultBuffer.append("</li><li>");
+ // }
+ // } else {
+ // fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, levelHash));
+ // fResultBuffer.append("<ol><li>");
+ // }
+ // } else {
+ // fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
+ // fResultBuffer.append("\n<ol><li>");
+ // }
+ // continue;
+ // }
+ // }
+ // // }
+ // }
+ // break;
+
+ // case 'i': // <ol> list
+ // if (getList('i', "<ol class=\"roman\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'I': // <ol> list
+ // if (getList('i', "<ol class=\"ROMAN\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'a' : // <ol> list
+ // if (getList('a', "<ol class=\"alpha\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'A' : // <ol> list
+ // if (getList('A', "<ol class=\"ALPHA\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'g' : // <ol> list
+ // if (getList('g', "<ol class=\"greek\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'H' : // <ol> list
+ // if (getList('H', "<ol class=\"HIRAGANA\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'k' : // <ol> list
+ // if (getList('k', "<ol class=\"katakana\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'K' : // <ol> list
+ // if (getList('K', "<ol class=\"KATAKANA\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+ // case 'j' : // <ol> list
+ // if (getList('j', "<ol class=\"HEBREW\">", "</ol>")) {
+ // continue;
+ // }
+ // break;
+
+ case '\'':
+ if (getNextChar('\'')) {
+ if (getNextChar('\'')) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, 3);
+ fWhiteStart = false;
+ return WikipediaFilter.TokenSTRONG;
+ }
+ copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+ fWhiteStart = false;
+ return WikipediaFilter.TokenEM;
+ }
+ break;
+ // case '_':
+ // if (getNextChar('_')) {
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+ // fWhiteStart = false;
+ // return WikipediaFilter.TokenBOLD;
+ // }
+ // break;
+ // case '~':
+ // if (getNextChar('~')) {
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+ // fWhiteStart = false;
+ // return WikipediaFilter.TokenITALIC;
+ // }
+ // break;
+ case '-':
+ int tempCurrPosition = fCurrentPosition;
+ try {
+ if (fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-') {
+ if (fSource[tempCurrPosition] == '\n') {
+ fCurrentPosition = tempCurrPosition;
+ fResultBuffer.append("<hr/>");
+ fWhiteStart = false;
+ continue;
+ } else if (fSource[tempCurrPosition++] == '\r' && fSource[tempCurrPosition++] == '\n') {
+ fCurrentPosition = tempCurrPosition - 1;
+ fResultBuffer.append("<hr/>");
+ fWhiteStart = false;
+ continue;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+
+ }
+
+ // int levelMinus = getNumberOfChar('-') + 1;
+ // if (getNextChar(' ')) {
+ // int tempPosition = checkWhitespaces(
+ // fWhiteStartPosition, fCurrentPosition - 2
+ // - levelMinus);
+ // if (tempPosition >= 0) {
+ // copyWhite(fWhiteStart, fWhiteStartPosition,
+ // 1 + levelMinus);
+ // fWhiteStart = false;
+ // AbstractTag tok = (AbstractTag) fTokenStack.peek();
+ // if (tok instanceof ListToken) {
+ // ListToken listToken = (ListToken) tok;
+ // int topLevel = listToken.getLevel();
+ // if (listToken.getToken() ==
+ // WikipediaFilter.TokenLIST_UL_START) {
+ // if (levelMinus > topLevel) {
+ // fTokenStack
+ // .push(new ListToken(
+ // WikipediaFilter.TokenLIST_UL_START,
+ // topLevel + 1));
+ // fResultBuffer
+ // .append("<ul class=\"minus\"><li>");
+ // } else if (levelMinus < topLevel) {
+ // fTokenStack.pop();
+ // fResultBuffer
+ // .append("</li></ul></li><li>");
+ // } else {
+ // fResultBuffer.append("</li><li>");
+ // }
+ // } else {
+ // fTokenStack
+ // .push(new ListToken(
+ // WikipediaFilter.TokenLIST_UL_START,
+ // levelMinus));
+ // fResultBuffer
+ // .append("<ul class=\"minus\"><li>");
+ // }
+ // } else {
+ // fTokenStack
+ // .push(new ListToken(
+ // WikipediaFilter.TokenLIST_UL_START,
+ // 1));
+ // fResultBuffer
+ // .append("\n<ul class=\"minus\"><li>");
+ // }
+ // continue;
+ // }
+ // }
+ // if (levelMinus == 2) {
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+ // fWhiteStart = false;
+ // return WikipediaFilter.TokenSTRIKETHROUGH;
+ // }
+ break;
+ case 'h': // http(s)://
+ int urlStartPosition = fCurrentPosition;
+ boolean foundUrl = false;
+ int diff = 7;
+ try {
+ String urlString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
+ if (urlString.equals("http")) {
+ fCurrentPosition += 3;
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter == 's') { // optional
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ diff++;
+ }
+
+ if (fCurrentCharacter == ':' && fSource[fCurrentPosition++] == '/' && fSource[fCurrentPosition++] == '/') {
+ copyWhite(fWhiteStart, fWhiteStartPosition, diff);
+ fWhiteStart = false;
+ foundUrl = true;
+ while (WikipediaFilter.isUrlIdentifierPart(fSource[fCurrentPosition++])) {
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ if (!foundUrl) {
+ // rollback work :-)
+ fCurrentPosition = urlStartPosition;
+ }
+ }
+ if (foundUrl) {
+ String urlString = new String(fSource, urlStartPosition - 1, fCurrentPosition - urlStartPosition);
+ fCurrentPosition--;
+ WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, urlString);
+ continue;
+ }
+ break;
+
+ // case '@': // images @xml@ -> /static/rss-small.png
+ // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+ // fWhiteStart = false;
+ // int atStart = fCurrentPosition;
+ // if (readUntilChar('@')) {
+ // String imageTag = new String(fSource, atStart, fCurrentPosition - atStart - 1);
+ // if (imageTag != null) {
+ // if (WikipediaFilter.createStaticImage(imageTag, fResultBuffer)) {
+ // continue;
+ // }
+ // }
+ // }
+ // fCurrentPosition = atStart;
+ // break;
+ case '&':
+ int ampersandStart = fCurrentPosition - 1;
+ if (getNextChar('#')) {
+ try {
+ StringBuffer num = new StringBuffer(5);
+ char ch = fSource[fCurrentPosition++];
+ while (Character.isDigit(ch)) {
+ num.append(ch);
+ ch = fSource[fCurrentPosition++];
+ }
+ if (num.length() > 0 && ch == ';') {
+ Integer i = Integer.valueOf(num.toString());
+ if (i.intValue() < 65536) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, 3 + num.length());
+ fWhiteStart = false;
+ fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
+ continue;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ // ignore exception
+ } catch (NumberFormatException e) {
+ // ignore exception
+ }
+ } else {
+ try {
+ StringBuffer entity = new StringBuffer(10);
+ char ch = fSource[fCurrentPosition++];
+ while (Character.isLetterOrDigit(ch)) {
+ entity.append(ch);
+ ch = fSource[fCurrentPosition++];
+ }
+ if (entity.length() > 0 && ch == ';') {
+ if (WikipediaFilter.ENTITY_SET.contains(entity.toString())) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, 2 + entity.length());
+ fWhiteStart = false;
+ fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
+ continue;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ // ignore exception
+ } catch (NumberFormatException e) {
+ // ignore exception
+ }
+ }
+ break;
+ case '<':
+ int htmlStartPosition = fCurrentPosition;
+ try {
+ switch (fStringSource.charAt(fCurrentPosition)) {
+ case '!': // <!-- html comment -->
+ String htmlCommentString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
+
+ if (htmlCommentString.equals("<!--")) {
+ fCurrentPosition += 3;
+ if (readUntilString("-->")) {
+ String htmlCommentContent = new String(fSource, htmlStartPosition + 3, fCurrentPosition - htmlStartPosition - 6);
+ if (htmlCommentContent != null) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
+ fWhiteStart = false;
+ // insert html comment for visual checks
+ // only:
+ /*
+ * fResultBuffer.append(" <!--"); copyWhite(htmlCommentContent); fResultBuffer.append("--> ");
+ */
+ continue;
+ }
+ }
+ }
+ break;
+ // case 'm' : // math
+ // String mathString =
+ // fStringSource.substring(fCurrentPosition - 1,
+ // fCurrentPosition + 5);
+
+ // if (mathString.equals("<math>")) {
+ // fCurrentPosition += 5;
+ // if (readUntilString("</math>")) {
+ // String mathContent = new String(fSource,
+ // htmlStartPosition + 5, fCurrentPosition -
+ // htmlStartPosition - 12);
+ // if (mathContent != null) {
+ // copyWhite(fWhiteStart, fWhiteStartPosition,
+ // fCurrentPosition - htmlStartPosition + 1);
+ // fWhiteStart = false;
+ // if (startOfIndent) {
+ // startOfIndent = false;
+ // handleTeXMath(mathContent, false);
+ // } else {
+ // handleTeXMath(mathContent, true);
+ // }
+ // continue;
+ // }
+ // }
+ // }
+ // break;
+ case 'n': // nowiki
+ String nowikiString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 7);
+
+ if (nowikiString.equals("<nowiki>")) {
+ fCurrentPosition += 7;
+ if (readUntilString("</nowiki>")) {
+ String nowikiContent = new String(fSource, htmlStartPosition + 7, fCurrentPosition - htmlStartPosition - 16);
+ if (nowikiContent != null) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
+ fWhiteStart = false;
+ copyNowikiNewLine(nowikiContent);
+ continue;
+ }
+ }
+ }
+ break;
+ }
+ } catch (IndexOutOfBoundsException e) {
+
+ }
+ startOfIndent = false;
+ fCurrentPosition = htmlStartPosition;
+ // detect special html tags
+ int htmlToken = getHTMLToken();
+ if (htmlToken == WikipediaFilter.TokenIgnore) {
+ continue;
+ // } else if (htmlToken > TokenIgnore) {
+ // return htmlToken;
+ }
+ fCurrentPosition = htmlStartPosition;
+ break;
+ case '=': // wikipedia header ?
+ if (isStartOfLine()) {
+ int levelHeader = getNumberOfChar('=') + 1;
+ // int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHeader);
+ // if (tempPosition >= 0) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, levelHeader);
+ fWhiteStart = false;
+ int startHeadPosition = fCurrentPosition;
+ // int initialOffset = levelHeader;
+ if (levelHeader > 6) {
+ levelHeader = 6;
+ }
+ levelHeader--;
+ if (readUntilString(WikipediaFilter.HEADER_STRINGS[levelHeader])) {
+ String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition - (1 + levelHeader));
+ levelHeader++;
+ handleHead(head, levelHeader);
+ continue;
+ }
+ // }
+ }
+ break;
+ }
+ if (!fWhiteStart) {
+ fWhiteStart = true;
+ fWhiteStartPosition = fCurrentPosition - 1;
+ }
+
+ startOfIndent = false;
+ }
+ // -----------------end switch while try--------------------
+ } catch (IndexOutOfBoundsException e) {
+ // end of scanner text
+ }
+ copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+
+ return WikipediaFilter.TokenEOF;
+ }
+
+ /**
+ * @return
+ */
+ private boolean isStartOfLine() {
+ boolean isListStart = false;
+ if (fCurrentPosition >= 2) {
+ char beforeChar = fSource[fCurrentPosition - 2];
+ if (beforeChar == '\n' || beforeChar == '\r') {
+ isListStart = true;
+ }
+ }
+ if (fCurrentPosition == 1) {
+ isListStart = true;
+ }
+ return isListStart;
+ }
+
+ /**
+ * @param levelStar
+ * @param listChars
+ * TODO
+ */
+ private void appendList(char[] listChars) {
+ int topLevel = 0;
+ int levelStar = listChars.length;
+ copyWhite(fWhiteStart, fWhiteStartPosition, levelStar);
+ fWhiteStart = false;
+ AbstractTag tok = (AbstractTag) fTokenStack.peek();
+
+ if (tok instanceof ListToken) {
+ ListToken listToken = (ListToken) tok;
+ topLevel = listToken.getLevel();
+
+ if (levelStar > topLevel) {
+ while (levelStar > topLevel) {
+ if (listChars[topLevel] == '*') {
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
+ fResultBuffer.append("<ul><li>");
+ } else {
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
+ fResultBuffer.append("<ol><li>");
+ }
+ }
+ } else if (levelStar < topLevel) {
+ while (levelStar < topLevel) {
+ tok = (AbstractTag) fTokenStack.peek();
+ if (tok instanceof ListToken) {
+ fTokenStack.pop();
+ listToken = (ListToken) tok;
+ if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START) {
+ fResultBuffer.append("</li></ul></li><li>");
+ } else {
+ fResultBuffer.append("</li></ol></li><li>");
+ }
+ topLevel--;
+ } else {
+ break;
+ }
+ }
+ } else {
+ --topLevel;
+ if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START && listChars[topLevel] == '#') {
+ fTokenStack.pop();
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel));
+ fResultBuffer.append("</li></ul><ol><li>");
+ } else if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START && listChars[topLevel] == '*') {
+ fTokenStack.pop();
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, topLevel));
+ fResultBuffer.append("</li></ol><ul><li>");
+ } else {
+ fResultBuffer.append("</li><li>");
+ }
+ }
+ } else {
+ while (levelStar > topLevel) {
+ if (listChars[topLevel] == '*') {
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
+ fResultBuffer.append("\n<ul><li>");
+ } else {
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
+ fResultBuffer.append("\n<ol><li>");
+ }
+ }
+ }
+ }
+
+ private void createMacro(int startMacroPosition, String macroStartTag) {
+ String command = "";
+ String endTag;
+
+ String parameterString = null;
+ String macroBodyString = "";
+ int index0;
+ int index1;
+ if ((index0 = macroStartTag.indexOf(':')) >= 0) {
+ command = macroStartTag.substring(0, index0);
+ parameterString = macroStartTag.substring(index0 + 1, macroStartTag.length());
+ } else {
+ command = macroStartTag;
+ }
+ Macro macro = (Macro) fMacros.get(command);
+
+ String completeMacroSubString;
+
+ if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
+ endTag = '{' + command + '}';
+ index0 = fStringSource.indexOf(endTag, fCurrentPosition);
+
+ if (index0 >= 0) {
+ macroBodyString = fStringSource.substring(fCurrentPosition, index0);
+ completeMacroSubString = new String(fSource, startMacroPosition - 1, index0 + endTag.length() - startMacroPosition + 1);
+ fCurrentPosition = startMacroPosition + completeMacroSubString.length() - 1;
+ } else {
+ completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
+ }
+ } else {
+ completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
+ }
+
+ copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+
+ handleMacro(completeMacroSubString, command, parameterString, macroBodyString);
+ }
+
+ // private void createExternalLink(String urlString) {
+ //
+ // // Does our engine know images?
+ // if (fWikiEngine instanceof ImageRenderEngine) {
+ // fResult.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
+ // }
+ // fResult.append("<span class=\"nobr\">");
+ // fResult.append("<a href=\"");
+ // fResult.append(Encoder.escape(urlString));
+ // fResult.append("\">");
+ // fResult.append(Encoder.toEntity(urlString.charAt(0)) +
+ // urlString.substring(1));
+ // fResult.append("</a></span>");
+ // }
+
+ // private void handleTeXMath(String mathContent, boolean inlineExpression)
+ // {
+ // // TODO clean this up
+ // Map map = Application.get().getParameters();
+ // HttpServletRequest request = (HttpServletRequest) map.get("request");
+ // MathSniffer sniffy = MathSniffer.getBrowserDetection(request);
+ //
+ // if (fCacheStaticBlockActive) {
+ // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition,
+ // fResultBuffer.length()));
+ // fCacheStaticBlockActive = false;
+ // }
+ // // if (inlineExpression) {
+ // // fASMCompiler.compileMath(mathContent, "true");
+ // // } else {
+ // // fASMCompiler.compileMath(mathContent, "false");
+ // // }
+ // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
+ // switch (sniffy.getBrowserId()) {
+ // case MathSniffer.XMLID :
+ // case MathSniffer.MATHPLAYERID :
+ // if (inlineExpression) {
+ // fResultBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
+ // displaystyle=\"true\">");
+ // fTeXParser.initialize(mathContent);
+ // fTeXParser.parse2MML(fResultBuffer);
+ // fResultBuffer.append("</m:mstyle></m:math>");
+ // } else {
+ // fResultBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
+ // displaystyle=\"true\">");
+ // fTeXParser.initialize(mathContent);
+ // fTeXParser.parse2MML(fResultBuffer);
+ // fResultBuffer.append("</m:mstyle></m:math></dd></dl>");
+ // }
+ // break;
+ // case MathSniffer.CSSID :
+ // if (inlineExpression) {
+ // fResultBuffer.append("<m>");
+ // fTeXParser.initialize(mathContent);
+ // fTeXParser.parse2CSS(fResultBuffer, true);
+ // fResultBuffer.append("</m>");
+ // } else {
+ // fResultBuffer.append("<e>");
+ // fTeXParser.initialize(mathContent);
+ // fTeXParser.parse2CSS(fResultBuffer, true);
+ // fResultBuffer.append("</e>");
+ // }
+ // break;
+ // default :
+ // copyWhite(mathContent);
+ // }
+ // } else {
+ // String[] mathStrings = new String[3];
+ // StringBuffer mathBuffer = new StringBuffer();
+ // if (inlineExpression) {
+ // // mathml inline
+ // mathBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
+ // displaystyle=\"true\">");
+ //
+ // fTeXParser.initialize(mathContent);
+ // fTeXParser.parse2MML(mathBuffer);
+ // mathBuffer.append("</m:mstyle></m:math>");
+ // } else {
+ // mathBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
+ // displaystyle=\"true\">");
+ // fTeXParser.initialize(mathContent);
+ // fTeXParser.parse2MML(mathBuffer);
+ // mathBuffer.append("</m:mstyle></m:math></dd></dl>");
+ // }
+ // mathStrings[0] = mathBuffer.toString();
+ // mathBuffer.setLength(0);
+ // // if (inlineExpression) {
+ // // // css inline
+ // // mathBuffer.append("<m>");
+ // // fTeXParser.initialize(mathContent);
+ // // fTeXParser.parse2CSS(mathBuffer, true);
+ // // mathBuffer.append("</m>");
+ // // } else {
+ // // // css block mode
+ // // mathBuffer.append("<e>");
+ // // fTeXParser.initialize(mathContent);
+ // // fTeXParser.parse2CSS(mathBuffer, true);
+ // // mathBuffer.append("</e>");
+ // // }
+ //
+ // String encodedMathContent = Encoder.escape(mathContent);
+ // StringBuffer mathmlBuffer = new StringBuffer();
+ // String shortImageName = "____tex_" + (fImageCounter++);
+ // String longImageName = shortImageName + ".gif";
+ // mathmlBuffer.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
+ // if (inlineExpression) {
+ // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
+ // displaystyle=\"true\">");
+ // fTeXImageParser.initialize(mathContent);
+ // fTeXImageParser.parse2MML(mathmlBuffer);
+ // mathmlBuffer.append("</mstyle></math>");
+ // } else {
+ // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
+ // displaystyle=\"true\">");
+ // fTeXImageParser.initialize(mathContent);
+ // fTeXImageParser.parse2MML(mathmlBuffer);
+ // mathmlBuffer.append("</mstyle></math>");
+ // }
+ //
+ // String snipname = fSnip.getName();
+ // String SnipSnapSpacePath =
+ // Application.get().getConfiguration().getFilePath().getAbsolutePath();
+ // // Remove old image
+ // fSnip.getAttachments().removeAttachment(longImageName + ".gif");
+ //
+ // String directoryName = SnipSnapSpacePath + "/" + snipname;
+ // File directory = new File(directoryName);
+ // if (!directory.exists()) {
+ // directory.mkdirs();
+ // }
+ // String gifFilename = directoryName + "/" + longImageName;
+ // // File file = new File();
+ // // Get the number of bytes in the file
+ // // long length = file.length();
+ // MathMLToGIFConverter conv = new MathMLToGIFConverter();
+ // // String test =
+ // // "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><math
+ // //
+ // mode=\"display\"><mrow><munderover><mo>∫</mo><mn>1</mn><mi>x</mi></munderover><mfrac><mi>dt</mi><mi>t</mi></mfrac></mrow></math>";
+ // try {
+ // File imageFile = conv.convert(mathmlBuffer.toString(), gifFilename);
+ // if (imageFile != null) {
+ // Attachment attachment =
+ // new Attachment(longImageName, "image/gif", imageFile.length(), new
+ // Date(), snipname + "/" + longImageName, true);
+ // // fSnip.getAttachments().addAttachment(longImageName, "image/gif",
+ // imageFile.length(), snipname + "/" + longImageName,
+ // // true);
+ // fSnip.getAttachments().addAttachment(attachment);
+ // StringWriter writer = new StringWriter();
+ //
+ // SnipLink.appendImage(writer, fSnip, shortImageName, encodedMathContent,
+ // "gif", null);
+ //
+ // mathBuffer = writer.getBuffer();
+ // mathStrings[1] = mathBuffer.toString();
+ // } else {
+ // mathStrings[1] = encodedMathContent;
+ // }
+ // } catch (IOException e) {
+ // // TODO Auto-generated catch block
+ // e.printStackTrace();
+ // mathStrings[1] = encodedMathContent;
+ // }
+ // mathBuffer.setLength(0);
+ // WikipediaFilter.copyWhite(mathBuffer, mathContent);
+ // mathStrings[2] = mathBuffer.toString();
+ // fCachedPage.addMath(mathStrings);
+ // }
+ // if (!fCacheStaticBlockActive) {
+ // fCacheStaticBlockActive = true;
+ // fCacheStaticBlockStartPosition = fResultBuffer.length();
+ // }
+ // }
+ private void handleSnipLink(String name) {
+ if (name != null) {
+ int index = name.indexOf("http://");
+ // Configuration probably wrote [http://radeox.org] instead of
+ // http://radeox.org
+ if (index != -1) {
+ // WikipediaFilter.createExternalLink(fResultBuffer,
+ // fWikiEngine, name.substring(index));
+ String urlString = name.substring(index);
+ // Wikipedia like style:
+ int pipeIndex = urlString.indexOf(' ');
+ String alias = "";
+ if (pipeIndex != (-1)) {
+ alias = urlString.substring(pipeIndex + 1);
+ urlString = urlString.substring(0, pipeIndex);
+ } else {
+ alias = urlString;
+ }
+
+ if (fWikiEngine instanceof ImageRenderEngine) {
+ fResultBuffer.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
+ }
+ fResultBuffer.append("<span class=\"nobr\">");
+ fResultBuffer.append("<a href=\"");
+ fResultBuffer.append(Encoder.escape(urlString));
+ fResultBuffer.append("\">");
+ fResultBuffer.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
+ fResultBuffer.append("</a></span>");
+ }
+ // else {
+ // // trim the name and unescape it
+ // name = Encoder.unescape(name.trim());
+ // // Is there an alias like [alias|link] ?
+ // int pipeIndex = name.indexOf('|');
+ // String alias = "";
+ // if (-1 != pipeIndex) {
+ // alias = name.substring(0, pipeIndex);
+ // name = name.substring(pipeIndex + 1);
+ // }
+ //
+ // int hashIndex = name.lastIndexOf('#');
+ //
+ // String hash = "";
+ // if (-1 != hashIndex && hashIndex != name.length() - 1) {
+ // hash = name.substring(hashIndex + 1);
+ // name = name.substring(0, hashIndex);
+ // }
+ //
+ // int colonIndex = name.indexOf(':');
+ // // typed link ?
+ // if (-1 != colonIndex) {
+ // // for now throw away the fType information
+ // name = name.substring(colonIndex + 1);
+ // }
+ //
+ // int atIndex = name.lastIndexOf('@');
+ // // InterWiki link ?
+ // if (-1 != atIndex) {
+ // String extSpace = name.substring(atIndex + 1);
+ // // known extarnal space ?
+ // InterWiki interWiki = InterWiki.getInstance();
+ // if (interWiki.contains(extSpace)) {
+ // name = name.substring(0, atIndex);
+ // Writer writer = new StringBufferWriter(fResultBuffer);
+ // try {
+ // if (-1 != hashIndex) {
+ // interWiki.expand(writer, extSpace, name, hash);
+ // } else {
+ // interWiki.expand(writer, extSpace, name, "");
+ // }
+ // } catch (IOException e) {
+ // log.debug("InterWiki " + extSpace + " not found.");
+ // }
+ // } else {
+ // fResultBuffer.append("[<span class=\"error\">");
+ // fResultBuffer.append(name);
+ // fResultBuffer.append("?</span>]");
+ // }
+ // } else {
+ // // internal link
+ // if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
+ // if (fCacheStaticBlockActive) {
+ // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition, fResultBuffer.length()));
+ // fCacheStaticBlockActive = false;
+ // }
+ // fCachedPage.addSnipLink(name);
+ // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
+ // if (((WikiRenderEngine) fWikiEngine).exists(name)) {
+ // String view = name;
+ // if (-1 != pipeIndex) {
+ // view = alias;
+ // }
+ // // Do not add hash if an alias was given
+ // if (-1 != hashIndex) {
+ // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
+ // } else {
+ // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
+ // }
+ // } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
+ // ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name);
+ // // links with "create" are not cacheable because
+ // // a missing wiki could be created
+ // fContext.getRenderContext().setCacheable(false);
+ // } else {
+ // // cannot display/create wiki, so just display
+ // // the text
+ // fResultBuffer.append(name);
+ // }
+ // }
+ // if (!fCacheStaticBlockActive) {
+ // fCacheStaticBlockActive = true;
+ // fCacheStaticBlockStartPosition = fResultBuffer.length();
+ // }
+ // } else {
+ // // cannot display/create wiki, so just display the text
+ // fResultBuffer.append(name);
+ // }
+ // }
+ // }
+ }
+ }
+
+ private boolean handleWikipediaTable() {
+ // // example
+ //// {| border=1
+ //// |Zelle 1
+ //// |
+ //// {| border=2
+ //// |Zelle A
+ //// |-
+ //// |Zelle B
+ //// |}
+ //// |Zelle 3
+ //// |}
+ int temp = fCurrentPosition;
+ int sequenceStart = 0;
+ char lastChar = ' ';
+ int sequenceLength = 0;
+ int thStartPosition = 0;
+ Stack wpTokenStack = new Stack();
+ try {
+ // add table attributes:
+ fResultBuffer.append("<table ");
+ sequenceStart = fCurrentPosition;
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
+ sequenceLength++;
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ if (sequenceLength > 0) {
+ fResultBuffer.append(fSource, sequenceStart + 1, sequenceLength - 1);
+ }
+ fResultBuffer.append(">");
+ wpTokenStack.push(WikipediaFilter.HTML_TABLE_OPEN);
+
+ fResultBuffer.append("<tr>\n");
+ wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
+ String attributes = null;
+ // parse rest of table
+ while (true) {
+ sequenceStart = fCurrentPosition;
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter == '{' && fSource[fCurrentPosition] == '|') { // nested table
+ handleWikipediaTable();
+ } else if (fCurrentCharacter == '!') {
+ // <th>...</th>
+ reduceTableCellStack(fResultBuffer, wpTokenStack);
+ fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+ sequenceStart = fCurrentPosition;
+ // add header row cells
+ attributes = null;
+ while (true) {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
+ if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
+ reduceTableCellStack(fResultBuffer, wpTokenStack);
+ if (attributes == null) {
+ fResultBuffer.append("<th>");
+ } else {
+ fResultBuffer.append("<th ");
+ fResultBuffer.append(attributes);
+ fResultBuffer.append(">");
+ }
+ wpTokenStack.push(WikipediaFilter.HTML_TH_OPEN);
+ fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+ - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+ fCurrentPosition++;
+ sequenceStart = fCurrentPosition;
+ attributes = null;
+ } else {
+ attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+ sequenceStart = fCurrentPosition;
+ }
+ }
+ if (fCurrentCharacter == '\n') {
+ fCurrentPosition--;
+ break;
+ }
+ }
+ } else if (fCurrentCharacter == '|') {
+ reduceTableCellStack(fResultBuffer, wpTokenStack);
+ fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+
+ sequenceStart = fCurrentPosition;
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ switch (fCurrentCharacter) {
+ case '+': // caption
+ sequenceStart++;
+ reduceTableRowStack(WikipediaFilter.HTML_TABLE_OPEN, fResultBuffer, wpTokenStack);
+ fResultBuffer.append("<caption>\n");
+ wpTokenStack.push(WikipediaFilter.HTML_CAPTION_OPEN);
+ // read until end of line
+ while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition - sequenceStart
+ - 1), fContext, fMacros, fRecursionLevel));
+ break;
+ case '-': // new row
+ sequenceStart++;
+ reduceTableRowStack(WikipediaFilter.HTML_TR_OPEN, fResultBuffer, wpTokenStack);
+
+ // read until end of line
+ while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ // TODO handle row attributes
+ fResultBuffer.append("<tr ");
+ wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
+ fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+ fResultBuffer.append(">\n");
+ // fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+ // - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+ break;
+ case '}': // end of table
+ clearTableStack(fResultBuffer, wpTokenStack);
+ // System.out.println(fResultBuffer.toString());
+ return true;
+ default:
+ // add row cells
+ attributes = null;
+ while (true) {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
+ if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
+ reduceTableCellStack(fResultBuffer, wpTokenStack);
+ if (attributes == null) {
+ fResultBuffer.append("<td>");
+ } else {
+ fResultBuffer.append("<td ");
+ fResultBuffer.append(attributes);
+ fResultBuffer.append(">");
+ }
+ wpTokenStack.push(WikipediaFilter.HTML_TD_OPEN);
+ fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+ - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+ // TODO reduce fTokenStack to <tr> element
+ // if necessary
+ // fResultBuffer.append("</td>");
+ // fTokenStack.pop();
+ fCurrentPosition++;
+ sequenceStart = fCurrentPosition;
+ attributes = null;
+ } else {
+ attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+
+ sequenceStart = fCurrentPosition;
+ }
+ }
+ if (fCurrentCharacter == '\n') {
+ fCurrentPosition--;
+ break;
+ }
+ }
+ }
+ } else if (wpTokenStack.peek() == WikipediaFilter.HTML_TD_OPEN) {
+ // continue a table cell in the next line
+ while (true) {
+ if (fCurrentCharacter == '\n') {
+ char ch0 = fSource[fCurrentPosition];
+ char ch1 = fSource[fCurrentPosition + 1];
+ if (ch0 == '|' || ch0 == '!' || (ch0 == '{' && ch1 == '|')) {
+ fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+ - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+ sequenceStart = fCurrentPosition;
+ attributes = null;
+ break;
+ }
+ }
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ if (sequenceStart + 1 < fCurrentPosition && fSource[sequenceStart + 1] == '}') {
+ // TODO reduce fTokenStack to <tr> element if necessary
+ // fResultBuffer.append("</tr></table>\n");
+ // wpTokenStack.pop(); // tr
+ // wpTokenStack.pop();// table
+ // System.out.println(fResultBuffer.toString());
+ clearTableStack(fResultBuffer, wpTokenStack);
+ return true;
+ }
+ }
+ fCurrentPosition = temp - 1;
+ // System.out.print(fResultBuffer.toString());
+ return false;
+ } // private boolean handleWikipediaTable() {
+
+ private void clearTableStack(StringBuffer buffer, Stack stack) {
+ CloseTagToken closeTag;
+ AbstractTag tag;
+ while (!stack.isEmpty()) {
+ tag = (AbstractTag) stack.pop();
+ closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
+ buffer.append(closeTag.getCloseTag());
+ }
+ }
+
+ private void reduceTableRowStack(AbstractTag stopTag, StringBuffer buffer, Stack stack) {
+ CloseTagToken closeTag;
+ AbstractTag tag;
+ while (!stack.isEmpty()) {
+ tag = (AbstractTag) stack.peek();
+ if (tag == WikipediaFilter.HTML_TABLE_OPEN) {
+ break;
+ }
+ stack.pop();
+ closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
+ buffer.append(closeTag.getCloseTag());
+ if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN) {
+ break;
+ }
+ }
+ }
+
+ private void reduceTableCellStack(StringBuffer buffer, Stack stack) {
+ CloseTagToken closeTag;
+ AbstractTag tag;
+ while (!stack.isEmpty()) {
+ tag = (AbstractTag) stack.peek();
+ if (tag != WikipediaFilter.HTML_TH_OPEN && tag != WikipediaFilter.HTML_TD_OPEN) {
+ break;
+ }
+ stack.pop();
+ closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
+ buffer.append(closeTag.getCloseTag());
+ if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN || tag == WikipediaFilter.HTML_TH_OPEN
+ || tag == WikipediaFilter.HTML_TD_OPEN) {
+ break;
+ }
+ }
+ }
+
+ // // example
+ //// {| border=1
+ //// |Zelle 1
+ //// |
+ //// {| border=2
+ //// |Zelle A
+ //// |-
+ //// |Zelle B
+ //// |}
+ //// |Zelle 3
+ //// |}
+ //
+ // int temp = fCurrentPosition;
+ // // StringBuffer suffixBuffer = new StringBuffer();
+ // Table table = new Table(fContext.getRenderContext());
+ // // char currentChar = ' ';
+ // char lastChar = ' ';
+ // // int startPosition = 0;
+ // // int currentPosition = 0;
+ // StringBuffer buffer = new StringBuffer();
+ // int thStartPosition = 0;
+ //
+ // try { // read first line
+ // fCurrentCharacter = fSource[fCurrentPosition++];
+ // // TODO improve this for different table attributes
+ // while (fCurrentCharacter != '\n' ) {
+ // fCurrentCharacter = fSource[fCurrentPosition++];
+ // // System.out.println(fCurrentCharacter);
+ // }
+ // table.newRow();
+ // lastChar = fCurrentCharacter;
+ // fCurrentCharacter = fSource[fCurrentPosition++];
+ // while (true) {
+ //
+ // switch (fCurrentCharacter) {
+ // // case '{' : // start of nested table ?
+ // // if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia table
+ // end reached
+ // // return true;
+ // // }
+ // // break;
+ // case '!' :
+ // if (lastChar == '\n') {
+ // table.addCell(buffer.toString());
+ // // System.out.println(buffer.toString());
+ // buffer.setLength(0);
+ // thStartPosition = fCurrentPosition;
+ // while (true) {
+ // lastChar = fCurrentCharacter;
+ // fCurrentCharacter = fSource[fCurrentPosition++];
+ // if (fCurrentCharacter == '|') {
+ // break;
+ // }
+ // if (fCurrentCharacter == '\n') {
+ // lastChar = '\n';
+ // fCurrentPosition = thStartPosition;
+ // break;
+ // }
+ // }
+ // } else {
+ // buffer.append(fCurrentCharacter);
+ // }
+ // break;
+ // case '|' :
+ // if (lastChar == '\n') {
+ // if (getNextChar('}')) { // Wikipedia table end reached
+ // table.addCell(buffer.toString());
+ // StringWriter writer = new StringWriter();
+ // try {
+ // table.appendTo(writer);
+ // fResultBuffer.append(writer.getBuffer());
+ // } catch (IOException e1) {
+ // // TODO Auto-generated catch block
+ // e1.printStackTrace();
+ // return false;
+ // }
+ // return true;
+ // } else if (getNextChar('-')) {
+ // table.addCell(buffer.toString());
+ // buffer.setLength(0);
+ // table.newRow();
+ // while (true) {
+ // lastChar = fCurrentCharacter;
+ // fCurrentCharacter = fSource[fCurrentPosition++];
+ // if (fCurrentCharacter == '|' || fCurrentCharacter == '!') {
+ // break;
+ // }
+ // }
+ // // continue;
+ // } else {
+ // if (buffer.length()>0) {
+ // table.addCell(buffer.toString());
+ // buffer.setLength(0);
+ // }
+ // }
+ // } else if (getNextChar('|')) {
+ // table.addCell(buffer.toString());
+ // // System.out.println(buffer.toString());
+ // buffer.setLength(0);
+ // } else {
+ // buffer.append(fCurrentCharacter);
+ // }
+ // break;
+ // default :
+ // buffer.append(fCurrentCharacter);
+ // }
+ // lastChar = fCurrentCharacter;
+ // fCurrentCharacter = fSource[fCurrentPosition++];
+ // }
+ //
+ // } catch (IndexOutOfBoundsException e) {
+ //
+ // }
+ // fCurrentPosition = temp - 1;
+ // return false;
+ // }
+ private void handleWikipediaLink(String linkText, String suffix) {
+ String name = linkText;
+ if (name != null) {
+ int index = name.indexOf("http://");
+ // Configuration probably wrote [http://radeox.org] instead of
+ // http://radeox.org
+ if (index != -1) {
+ WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, name.substring(index));
+ // show error
+ // fResult.append("<div class=\"error\">Do not surround URLs
+ // with [...].</div>");
+ } else {
+ // trim the name and unescape it
+ name = Encoder.unescape(name.trim());
+ // Is there an alias like [alias|link] ?
+ int pipeIndex = name.indexOf('|');
+ String alias = "";
+ if (-1 != pipeIndex) {
+ alias = name.substring(pipeIndex + 1);
+ name = name.substring(0, pipeIndex);
+ }
+
+ int hashIndex = name.lastIndexOf('#');
+
+ String hash = "";
+ if (-1 != hashIndex && hashIndex != name.length() - 1) {
+ hash = name.substring(hashIndex + 1);
+ name = name.substring(0, hashIndex);
+ }
+
+ // int colonIndex = name.indexOf(':');
+ // // typed link ?
+ // if (-1 != colonIndex) {
+ // // for now throw away the fType information
+ // name = name.substring(colonIndex + 1);
+ // }
+
+ int atIndex = name.lastIndexOf('@');
+ // InterWiki link ?
+ if (-1 != atIndex) {
+ String extSpace = name.substring(atIndex + 1);
+ // known extarnal space ?
+ InterWiki interWiki = InterWiki.getInstance();
+ if (interWiki.contains(extSpace)) {
+ name = name.substring(0, atIndex);
+ Writer writer = new StringBufferWriter(fResultBuffer);
+ try {
+ if (-1 != hashIndex) {
+ interWiki.expand(writer, extSpace, name, hash);
+ } else {
+ interWiki.expand(writer, extSpace, name, "");
+ }
+ } catch (IOException e) {
+ // log.debug("InterWiki " + extSpace + " not found.");
+ }
+ } else {
+ fResultBuffer.append("[<span class=\"error\">");
+ fResultBuffer.append(name);
+ fResultBuffer.append("?</span>]");
+ }
+ } else {
+ // internal link
+ if (name.startsWith("Image:") && (fWikiEngine instanceof ImageRenderEngine)) {
+ // server part of rendering images
+ ImageRenderEngine imageEngine = (ImageRenderEngine) fWikiEngine;
+ // fResultBuffer.append("<img src=\"space/1/2004-11-21/5/");
+ fResultBuffer.append("<img src=\"");
+ fResultBuffer.append(FilterUtil.createServerImage(null, name.substring(6), null));
+ fResultBuffer.append("\">");
+ } else if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
+ if (((WikiRenderEngine) fWikiEngine).exists(name)) {
+ String view = name + suffix;
+ if (-1 != pipeIndex) {
+ view = alias + suffix;
+ }
+ if (name.startsWith("Image:")) {
+ fResultBuffer.append("<img src=\"");
+
+ fResultBuffer.append(FilterUtil.createHTMLLink(null, name, null));
+ fResultBuffer.append("\">");
+ } else {
+ // Do not add hash if an alias was given
+ if (-1 != hashIndex) {
+ ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
+ } else {
+ ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
+ }
+ }
+ } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
+ ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name + suffix);
+ // links with "create" are not cacheable because
+ // a missing wiki could be created
+ fContext.getRenderContext().setCacheable(false);
+ } else {
+ // cannot display/create wiki, so just display
+ // the text
+ fResultBuffer.append(name);
+ }
+ } else {
+ // cannot display/create wiki, so just display the text
+ fResultBuffer.append(name);
+ }
+ }
+ }
+ }
+ }
+
+ public String createAnchor(String head) {
+ StringBuffer result = new StringBuffer(head.length() + 1);
+ char ch;
+ result.append('a');
+ // reduce Anchorstring
+ for (int i = 0; i < head.length(); i++) {
+ ch = head.charAt(i);
+ if ('a' <= ch && 'z' >= ch) {
+ result.append(ch);
+ } else if ('A' <= ch && 'Z' >= ch) {
+ result.append(ch);
+ } else if ('0' <= ch && '9' >= ch) {
+ result.append(ch);
+ }
+ // switch (ch) {
+ // case ' ' :
+ // result.append('_');
+ // break;
+ // case '<' : // special html escape character
+ // fResult.append(Encoder.toEntity('<'));
+ // break;
+ // case '>' : // special html escape character
+ // fResult.append(Encoder.toEntity('>'));
+ // break;
+ // case '&' : // special html escape character
+ // fResult.append(Encoder.toEntity('&'));
+ // break;
+ // case '\'' : // special html escape character
+ // fResult.append(Encoder.toEntity('\''));
+ // break;
+ // case '\"' : // special html escape character
+ // fResult.append(Encoder.toEntity('\"'));
+ // break;
+ // default :
+ // result.append(ch);
+ // }
+ }
+ return result.toString();
+ }
+
+ public static StringBuffer appendLink(StringBuffer buffer, String name, String view, String target) {
+ return appendLinkWithRoot(buffer, null, name + "#" + target, view);
+ }
+
+ /**
+ * Create a link with a root and a special view. The name will not be url encoded!
+ */
+ public static StringBuffer appendLinkWithRoot(StringBuffer buffer, String root, String name, String view) {
+ buffer.append("<a href=\"");
+ if (root != null) {
+ buffer.append(root);
+ buffer.append("/");
+ }
+ buffer.append(name);
+ buffer.append("\">");
+ buffer.append(Encoder.escape(view));
+ buffer.append("</a>");
+ return buffer;
+ }
+
+ /**
+ * add an entry to the "table of content" TODO refactor this to a class
+ *
+ * @param toc
+ * @param head
+ * @param anchor
+ * @param headLevel
+ */
+ private void addToTableOfContent(ArrayList toc, String head, String anchor, int headLevel) {
+ int level = 1;
+ if (level == headLevel) {
+ String snipName = "";
+ // if (fSnip != null) {
+ // snipName = fSnip.getName();
+ // }
+
+ StringBuffer link = new StringBuffer(snipName.length() + 40 + head.length() + anchor.length());
+ link.append("<li>");
+ //TODO create link for table of content
+ appendLink(link, snipName, head, anchor);
+ link.append("</li>");
+ toc.add(link.toString());
+ } else {
+ if (toc.size() > 0) {
+ if (toc.get(toc.size() - 1) instanceof ArrayList) {
+ addToTableOfContent((ArrayList) toc.get(toc.size() - 1), head, anchor, --headLevel);
+ return;
+ }
+ }
+ ArrayList list = new ArrayList();
+ toc.add(list);
+ addToTableOfContent(list, head, anchor, --headLevel);
+ }
+ }
+
+ /**
+ * handle head for table of content
+ *
+ * @param head
+ * @param headLevel
+ */
+ private void handleHead(String head, int headLevel) {
+ if (head != null) {
+ String anchor = createAnchor(head.trim());
+
+ if (fTableOfContent == null) {
+ // create new table of content
+ fTableOfContent = new ArrayList();
+ // copy fResult and new initialization:
+
+ fResultBufferHeader = fResultBuffer;
+ fResultBuffer = new StringBuffer(fResultBuffer.capacity());
+ }
+ addToTableOfContent(fTableOfContent, head, anchor, headLevel);
+
+ fResultBuffer.append("<h");
+ fResultBuffer.append(headLevel);
+ fResultBuffer.append("><a name=\"");
+ fResultBuffer.append(anchor);
+ fResultBuffer.append("\">");
+ fResultBuffer.append(head);
+ fResultBuffer.append("</a></h");
+ fResultBuffer.append(headLevel);
+ fResultBuffer.append(">");
+ // if (headLevel <= 2) {
+ // fResultBuffer.append("<hr/>");
+ // }
+ }
+ }
+
+ private boolean getList(char listChar, String openTag, String closeTag) {
+ int currentPosition = fCurrentPosition;
+ int level = getNumberOfChar(listChar) + 1;
+ if (getNextChar('.') && getNextChar(' ')) {
+ int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 3 - level);
+ if (tempPosition >= 0) {
+ copyWhite(fWhiteStart, fWhiteStartPosition, 2 + level);
+ fWhiteStart = false;
+ AbstractTag tok = (AbstractTag) fTokenStack.peek();
+ if (tok instanceof ListToken) {
+ ListToken listToken = (ListToken) tok;
+ int topLevel = listToken.getLevel();
+ if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
+ if (level > topLevel) {
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
+ fResultBuffer.append(openTag + "<li>");
+ } else if (level < topLevel) {
+ fTokenStack.pop();
+ fResultBuffer.append("</li>" + closeTag + "</li><li>");
+ } else {
+ fResultBuffer.append("</li><li>");
+ }
+ } else {
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, level));
+ fResultBuffer.append(openTag + "<li>");
+ }
+ } else {
+ fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
+ fResultBuffer.append("\n" + openTag + "<li>");
+ }
+ return true;
+ }
+ }
+ fCurrentPosition = currentPosition;
+ return false;
+ }
+
+ /**
+ * read until the string is found
+ *
+ * @param name
+ * @return
+ */
+ private final boolean readUntilString(String testedString) {
+ int temp = fCurrentPosition;
+ int index = fStringSource.indexOf(testedString, fCurrentPosition);
+ if (index != (-1)) {
+ fCurrentPosition = index + testedString.length();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * read until character is found
+ *
+ * @param name
+ * @return
+ */
+ private final boolean readUntilChar(char testedChar) {
+ int temp = fCurrentPosition;
+ try {
+ while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
+ }
+ return true;
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ return false;
+ }
+ }
+
+ /**
+ * read until character is found or end-of-line is reached
+ *
+ * @param name
+ * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
+ */
+ private final int readUntilCharOrEOL(char testedChar) {
+ int temp = fCurrentPosition;
+ try {
+ while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
+ // if (fCurrentCharacter == '\n') {
+ // return 0;
+ // }
+ }
+ return 1;
+ } catch (IndexOutOfBoundsException e) {
+ fCurrentPosition = temp;
+ return -1;
+ }
+ }
+
+ /**
+ * read until character is found or end-of-line is reached
+ *
+ * @param name
+ * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
+ */
+ private final boolean readUntilEOL() {
+ int temp = fCurrentPosition;
+ try {
+ while (true) {
+ fCurrentCharacter = fSource[fCurrentPosition++];
+ if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+ return true;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ --fCurrentPosition;
+ return true;
+ }
+ }
+
+ /**
+ * Returns the view of the wiki name that is shown to the fUser. Overwrite to support other views for example transform
+ * "WikiLinking" to "Wiki Linking". Does nothing by default.
+ *
+ * @return view The view of the wiki name
+ */
+ // protected String getWikiView(String name) {
+ // return name;
+ // }
+ private void handleMacro(String completeMacroSubString, String command, String unsplittedMacroParameters, String group3) {
+ if (command != null) {
+ // {$peng} are variables not macros.
+ if (!command.startsWith("$")) {
+ MacroParameter mParams = fContext.getMacroParameter();
+
+ if (group3 != null) {
+ mParams.setContent(group3);
+ mParams.setContentStart(0);
+ mParams.setContentEnd(group3.length());
+ }
+ if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
+ // mParams.setParams(parseParameters(unsplittedMacroParameters));
+ mParams.setParams(unsplittedMacroParameters);
+ }
+ mParams.setStart(0);
+ mParams.setEnd(completeMacroSubString.length());
+
+ // @DANGER: recursive calls may replace macros in included
+ // source code
+ try {
+ if (fMacros.containsKey(command)) {
+ Macro macro = (Macro) fMacros.get(command);
+
+ // recursively filter macros within macros
+ if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
+ mParams.setContent(WikipediaFilter.filterParser(mParams.getContent(), fContext, fMacros, fRecursionLevel));
+ }
+ StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
+ macro.execute(writer, mParams);
+ StringBuffer buffer = writer.getBuffer();
+ if (macro instanceof IRenderResultMacro) {
+ fResultBuffer.append(WikipediaFilter.filterParser(buffer.toString(), fContext, fMacros, fRecursionLevel));
+ } else {
+ fResultBuffer.append(buffer);
+ }
+
+ } else if (command.startsWith("!")) {
+
+ RenderEngine engine = fContext.getRenderContext().getRenderEngine();
+ if (engine instanceof IncludeRenderEngine) {
+ String include = ((IncludeRenderEngine) engine).include(command.substring(1));
+ if (null != include) {
+ // Filter paramFilter = new
+ // ParamFilter(mParams);
+ // included = paramFilter.filter(included,
+ // null);
+ // fResult.append(include);
+
+ fResultBuffer.append(WikipediaFilter.filterParser(include, fContext, fMacros, fRecursionLevel));
+
+ } else {
+ fResultBuffer.append(command.substring(1) + " not found.");
+ }
+ }
+
+ return;
+ } else {
+ // fResult.append(group0);
+ copyWhite(completeMacroSubString);
+ return;
+ }
+ } catch (IllegalArgumentException e) {
+
+ fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+
+ e.printStackTrace();
+
+ } catch (Throwable e) {
+ // log.warn("MacroFilter: unable to format macro: " + command, e);
+ fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+ e.printStackTrace();
+ return;
+ }
+ } else {
+ fResultBuffer.append("<");
+ fResultBuffer.append(command.substring(1));
+ fResultBuffer.append(">");
+ }
+ } else {
+ // fResult.append(group0);
+ copyWhite(completeMacroSubString);
+ }
+ }
+
+ public void parse() {
+ int token = WikipediaFilter.TokenSTART;
+ fTokenStack.add(WikipediaFilter.START);
+ // fListStack.add(START);
+ try {
+ while ((token = getNextToken()) != WikipediaFilter.TokenEOF) {
+ switch (token) {
+ case WikipediaFilter.TokenBOLD:
+ if (fTokenStack.peek() == WikipediaFilter.BOLD) {
+ fTokenStack.pop();
+ fResultBuffer.append("</b>");
+ } else {
+ fTokenStack.push(WikipediaFilter.BOLD);
+ fResultBuffer.append("<b>");
+ }
+ break;
+ case WikipediaFilter.TokenITALIC:
+ if (fTokenStack.peek() == WikipediaFilter.ITALIC) {
+ fTokenStack.pop();
+ fResultBuffer.append("</i>");
+ } else {
+ fTokenStack.push(WikipediaFilter.ITALIC);
+ fResultBuffer.append("<i>");
+ }
+ break;
+ case WikipediaFilter.TokenSTRONG:
+ if (fTokenStack.peek() == WikipediaFilter.STRONG) {
+ fTokenStack.pop();
+ fResultBuffer.append("</strong>");
+ } else {
+ fTokenStack.push(WikipediaFilter.STRONG);
+ fResultBuffer.append("<strong>");
+ }
+ break;
+ case WikipediaFilter.TokenEM:
+ if (fTokenStack.peek() == WikipediaFilter.EM) {
+ fTokenStack.pop();
+ fResultBuffer.append("</em>");
+ } else {
+ fTokenStack.push(WikipediaFilter.EM);
+ fResultBuffer.append("<em>");
+ }
+ break;
+ case WikipediaFilter.TokenSTRIKETHROUGH:
+ if (fTokenStack.peek() == WikipediaFilter.STRIKETHROUGH) {
+ fTokenStack.pop();
+ fResultBuffer.append("</strike>");
+ } else {
+ fTokenStack.push(WikipediaFilter.STRIKETHROUGH);
+ fResultBuffer.append("<strike>");
+ }
+ break;
+ // case TokenLIST_UL_START :
+ // if (fTokenStack.peek().equals(LIST_UL_START)) {
+ // fResult.append("</li>\n<li>");
+ // } else {
+ // fTokenStack.push(LIST_UL_START);
+ // fResult.append("\n<ul class=\"star\">\n<li>");
+ // }
+ // break;
+ // case TokenLIST_UL_END :
+ // fTokenStack.pop();
+ // fResult.append("</li>\n</ul>\n");
+ // break;
+ // case TokenLIST_OL_START :
+ // if (fTokenStack.peek().equals(LIST_OL_START)) {
+ // fResult.append("</li>\n<li>");
+ // } else {
+ // fTokenStack.push(LIST_OL_START);
+ // fResult.append("\n<ol>\n<li>");
+ // }
+ // break;
+ // case TokenLIST_OL_END :
+ // fTokenStack.pop();
+ // fResult.append("</li>\n</ol>\n");
+ // break;
+ }
+ }
+ } catch (InvalidInputException e) {
+ //
+ }
+ // clear rest of stack if necessary (case of error in syntax!?)
+ AbstractTag tok;
+ while ((tok = (AbstractTag) fTokenStack.pop()) != WikipediaFilter.START) {
+ if (tok instanceof OpenTagToken) {
+
+ CloseTagToken closeToken = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tok.getTagName());
+ if (closeToken == null) {
+ // here is something wrong ???
+ fResultBuffer.append("</" + (tok.getTagName()) + ">");
+ } else {
+ fResultBuffer.append(closeToken.getCloseTag());
+ }
+ } else if (tok == WikipediaFilter.BOLD) {
+ fResultBuffer.append("</b>");
+ } else if (tok == WikipediaFilter.ITALIC) {
+ fResultBuffer.append("</i>");
+ } else if (tok == WikipediaFilter.STRONG) {
+ fResultBuffer.append("</strong>");
+ } else if (tok == WikipediaFilter.EM) {
+ fResultBuffer.append("</em>");
+ } else if (tok == WikipediaFilter.STRIKETHROUGH) {
+ fResultBuffer.append("</strike>");
+ } else if (tok.equals(WikipediaFilter.LIST_UL_START)) {
+ fResultBuffer.append("</li>\n</ul>\n");
+ } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
+ fResultBuffer.append("</li>\n</ol>\n");
+ }
+ }
+
+ if (fResultBufferHeader != null) {
+ int tocStart = fResultBufferHeader.length();
+ fResultBufferHeader.append("<table id=\"toc\" border=\"0\"><tr><th>Table of contents</th></tr><tr><td>");
+ fResultBufferHeader.append("<ol>");
+ createToC(fTableOfContent);
+ fResultBufferHeader.append("</ol>");
+ fResultBufferHeader.append("</td></tr></table><hr/>");
+
+ fResultBufferHeader.append(fResultBuffer);
+ fResultBuffer = fResultBufferHeader;
+ fResultBufferHeader = null;
+ fTableOfContent = null;
+ }
+ }
+
+ private void createToC(ArrayList toc) {
+ if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
+ createToC((ArrayList) toc.get(0));
+ return;
+ }
+ for (int i = 0; i < toc.size(); i++) {
+ if (toc.get(i) instanceof ArrayList) {
+ fResultBufferHeader.append("<ol>");
+ createToC((ArrayList) toc.get(i));
+ fResultBufferHeader.append("</ol>");
+ } else {
+ fResultBufferHeader.append(toc.get(i));
+ }
+ }
+ }
+
+ // public int readUntil(String testString) throws InvalidInputException {
+ // startPosition = currentPosition;
+ // int tempPosition;
+ // boolean flag;
+ // try {
+ // while (true) {
+ // currentCharacter = source[currentPosition++];
+ // if (currentCharacter == testString.charAt(0)) {
+ // tempPosition = currentPosition;
+ // flag = true;
+ // for (int i = 1; i < testString.length(); i++) {
+ // currentCharacter = source[currentPosition++];
+ // if (currentCharacter != testString.charAt(i)) {
+ // flag = false;
+ // currentPosition = tempPosition;
+ // break;
+ // }
+ // }
+ // if (flag) {
+ // return TokenBODY;
+ // }
+ // }
+ // }
+ // } catch (IndexOutOfBoundsException e) {
+ // // end of scanner text
+ // }
+ // return TokenEOF;
+ // }
+
+ public int scanIdentifierOrKeyword(boolean isVariable) throws InvalidInputException {
+ while (getNextCharAsWikiPluginIdentifierPart()) {
+ }
+ ;
+ return WikipediaFilter.TokenIdentifier;
+ }
+
+ private final void setSource(char[] source) {
+ //the source-buffer is set to sourceString
+ if (source == null) {
+ this.fSource = new char[0];
+ } else {
+ this.fSource = source;
+ }
+ // this.fEOFPosition = this.fSource.length;
+ // fStartPosition = -1;
+ }
+
+ private void unexpectedTag(String tag) {
+ fResultBuffer.append("<div class=\"error\">Unexpected end for tag: <" + tag + "></div>");
+ }
+
+ /**
+ * @return Returns the context.
+ */
+ public FilterContext getContext() {
+ return fContext;
+ }
+
+ /**
+ * @param context
+ * The context to set.
+ */
+ public void setContext(FilterContext context) {
+ fContext = context;
+ }
+
+ /**
+ * @return Returns the wikiEngine.
+ */
+ public RenderEngine getWikiEngine() {
+ return fWikiEngine;
+ }
+
+ /**
+ * @param wikiEngine
+ * The wikiEngine to set.
+ */
+ public void setWikiEngine(RenderEngine wikiEngine) {
+ fWikiEngine = wikiEngine;
+ }
+}
\ No newline at end of file