1 package org.plog4u.wiki.filter;
3 import java.io.IOException;
5 import java.text.MessageFormat;
6 import java.util.HashMap;
7 import java.util.HashSet;
10 import org.plog4u.wiki.filter.tags.AbstractTag;
11 import org.plog4u.wiki.filter.tags.CloseTagToken;
12 import org.plog4u.wiki.filter.tags.DivTag;
13 import org.plog4u.wiki.filter.tags.FontTag;
14 import org.plog4u.wiki.filter.tags.OpenTagToken;
15 import org.plog4u.wiki.filter.tags.SpecialTagToken;
16 import org.plog4u.wiki.filter.tags.TableTag;
17 import org.radeox.api.engine.ImageRenderEngine;
18 import org.radeox.api.engine.IncludeRenderEngine;
19 import org.radeox.api.engine.RenderEngine;
20 import org.radeox.api.engine.WikiRenderEngine;
21 import org.radeox.filter.CacheFilter;
22 import org.radeox.filter.FilterSupport;
23 import org.radeox.filter.context.FilterContext;
24 import org.radeox.filter.interwiki.InterWiki;
25 import org.radeox.macro.Macro;
26 import org.radeox.macro.MacroRepository;
27 import org.radeox.macro.parameter.MacroParameter;
28 import org.radeox.util.Encoder;
29 import org.radeox.util.StringBufferWriter;
31 //import org.snipsnap.app.Application;
32 //import org.snipsnap.fUser.Configuration;
33 //import org.snipsnap.app.Application;
36 * Parse the input and transform it for the most used wiki patterns
38 * Parts of the Wiki Syntax are borrowed from Wikipedia.org and SnipSnap.org
40 * @see org.plog4u.wiki.filter.WikipediaParser
42 public class WikipediaFilter extends FilterSupport implements CacheFilter, IWikipediaFilterConstants {
44 public class InvalidInputException extends Exception {
46 public InvalidInputException() {
50 public InvalidInputException(String s) {
57 // public static class ListToken extends Token {
60 // public ListToken(int token, int level) {
65 // public int getLevel() {
70 // public static class OpenTagToken extends Token {
71 // private String fTagName;
72 // private String fOpenTag;
74 // public OpenTagToken(int token, String name, String openTag) {
77 // fOpenTag = openTag;
81 // public String getTagName() {
85 // public String getOpenTag() {
89 // public void setTagName(String name) {
93 // public void setOpenTag(String openTag) {
94 // fOpenTag = openTag;
98 // public static class SpecialTagToken extends OpenTagToken {
99 // public SpecialTagToken(int token, String name, String openTag) {
100 // super(token, name, openTag);
104 // public static class CloseTagToken extends Token {
105 // private String fTagName;
106 // private String fCloseTag;
108 // public CloseTagToken(int token, String name, String closeTag) {
111 // fCloseTag = closeTag;
114 // public String getTagName() {
118 // public String getCloseTag() {
122 // public void setTagName(String name) {
126 // public void setCloseTag(String closeTag) {
127 // fCloseTag = closeTag;
131 final static String HEADER_STRINGS[] = { "=", "==", "===", "====", "=====", "======" };
133 final static int TokenNotFound = -2;
134 final static int TokenIgnore = -1;
135 final static int TokenSTART = 0;
136 final static int TokenEOF = 1;
137 final static int TokenERROR = 2;
138 final static int TokenBOLD = 3;
139 final static int TokenITALIC = 4;
140 final static int TokenSTRIKETHROUGH = 5;
141 final static int TokenSTRONG = 8;
142 final static int TokenEM = 9;
144 final static int TokenCOMMA = 134;
146 final static int TokenDOLLAR_LBRACE = 127;
148 final static int TokenLIST_UL_START = 50;
149 final static int TokenLIST_OL_START = 51;
151 final static int TokenLIST_UL_END = 75;
152 final static int TokenLIST_OL_END = 76;
154 final static int TokenHTML_BR_OPEN = 190;
155 final static int TokenHTML_HR_OPEN = 191;
157 final static int TokenHTML_BOLD_OPEN = 200;
158 final static int TokenHTML_BOLD_CLOSE = 201;
159 final static int TokenHTML_ITALIC_OPEN = 202;
160 final static int TokenHTML_ITALIC_CLOSE = 203;
161 final static int TokenHTML_UNDERLINE_OPEN = 204;
162 final static int TokenHTML_UNDERLINE_CLOSE = 205;
163 final static int TokenHTML_STRIKE_OPEN = 206;
164 final static int TokenHTML_STRIKE_CLOSE = 207;
165 final static int TokenHTML_PARAGRAPH_OPEN = 208;
166 final static int TokenHTML_PARAGRAPH_CLOSE = 209;
167 final static int TokenHTML_PRE_OPEN = 210;
168 final static int TokenHTML_PRE_CLOSE = 211;
169 final static int TokenHTML_BLOCKQUOTE_OPEN = 212;
170 final static int TokenHTML_BLOCKQUOTE_CLOSE = 213;
171 final static int TokenHTML_SUB_OPEN = 216;
172 final static int TokenHTML_SUB_CLOSE = 217;
173 final static int TokenHTML_SUP_OPEN = 218;
174 final static int TokenHTML_SUP_CLOSE = 219;
176 final static int TokenHTML_H1_CLOSE = 221;
178 final static int TokenHTML_H1_OPEN = 220;
179 final static int TokenHTML_H2_CLOSE = 223;
180 final static int TokenHTML_H2_OPEN = 222;
181 final static int TokenHTML_H3_CLOSE = 225;
182 final static int TokenHTML_H3_OPEN = 224;
183 final static int TokenHTML_H4_CLOSE = 227;
184 final static int TokenHTML_H4_OPEN = 226;
185 final static int TokenHTML_H5_CLOSE = 229;
186 final static int TokenHTML_H5_OPEN = 228;
187 final static int TokenHTML_H6_CLOSE = 231;
188 final static int TokenHTML_H6_OPEN = 230;
189 final static int TokenHTML_EM_OPEN = 240;
190 final static int TokenHTML_EM_CLOSE = 241;
193 final static int TokenHTML_STRONG_OPEN = 242;
194 final static int TokenHTML_STRONG_CLOSE = 243;
196 final static int TokenHTML_VAR_OPEN = 245;
197 final static int TokenHTML_VAR_CLOSE = 246;
198 final static int TokenHTML_CODE_OPEN = 247;
199 final static int TokenHTML_CODE_CLOSE = 248;
201 final static int TokenHTML_S_OPEN = 249;
202 final static int TokenHTML_S_CLOSE = 250;
203 final static int TokenHTML_SMALL_OPEN = 251;
204 final static int TokenHTML_SMALL_CLOSE = 252;
206 final static int TokenHTML_MATH_OPEN = 400;
207 final static int TokenHTML_MATH_CLOSE = 401;
209 final static int TokenHTML_TABLE_OPEN = 500;
210 final static int TokenHTML_TABLE_CLOSE = 501;
211 final static int TokenHTML_CAPTION_OPEN = 502;
212 final static int TokenHTML_CAPTION_CLOSE = 503;
213 final static int TokenHTML_TH_OPEN = 504;
214 final static int TokenHTML_TH_CLOSE = 505;
215 final static int TokenHTML_TR_OPEN = 506;
216 final static int TokenHTML_TR_CLOSE = 507;
217 final static int TokenHTML_TD_OPEN = 508;
218 final static int TokenHTML_TD_CLOSE = 509;
220 final static int TokenHTML_FONT_OPEN = 520;
221 final static int TokenHTML_FONT_CLOSE = 521;
222 final static int TokenHTML_CENTER_OPEN = 522;
223 final static int TokenHTML_CENTER_CLOSE = 523;
224 final static int TokenHTML_TT_OPEN = 524;
225 final static int TokenHTML_TT_CLOSE = 525;
226 final static int TokenHTML_DIV_OPEN = 526;
227 final static int TokenHTML_DIV_CLOSE = 527;
229 final static int TokenIdentifier = 138;
230 final static int TokenLBRACKET = 132;
232 final static int TokenLPAREN = 128;
234 final static int TokenPLUGIN_IDENTIFIER = 130;
235 final static int TokenRBRACE = 131;
236 final static int TokenRBRACKET = 133;
237 final static int TokenRPAREN = 129;
239 final static AbstractTag BOLD = new AbstractTag(TokenBOLD);
240 final static AbstractTag ITALIC = new AbstractTag(TokenITALIC);
241 final static AbstractTag STRONG = new AbstractTag(TokenSTRONG);
242 final static AbstractTag EM = new AbstractTag(TokenEM);
244 final static AbstractTag HTML_BR_OPEN = new SpecialTagToken(TokenHTML_BR_OPEN, "br", "<br/>");
245 final static AbstractTag HTML_HR_OPEN = new SpecialTagToken(TokenHTML_HR_OPEN, "hr", "<hr/>");
247 final static AbstractTag HTML_EM_CLOSE = new CloseTagToken(TokenHTML_EM_CLOSE, "em", "</i>");
248 final static AbstractTag HTML_EM_OPEN = new OpenTagToken(TokenHTML_EM_OPEN, "em", "<i>");
249 final static AbstractTag HTML_H1_CLOSE = new CloseTagToken(TokenHTML_H1_CLOSE, "h1", "</h1>");
250 final static AbstractTag HTML_H1_OPEN = new OpenTagToken(TokenHTML_H1_OPEN, "h1", "<h1>");
251 final static AbstractTag HTML_H2_CLOSE = new CloseTagToken(TokenHTML_H2_CLOSE, "h2", "</h2>");
252 final static AbstractTag HTML_H2_OPEN = new OpenTagToken(TokenHTML_H2_OPEN, "h2", "<h2>");
253 final static AbstractTag HTML_H3_CLOSE = new CloseTagToken(TokenHTML_H3_CLOSE, "h3", "</h3>");
254 final static AbstractTag HTML_H3_OPEN = new OpenTagToken(TokenHTML_H3_OPEN, "h3", "<h3>");
255 final static AbstractTag HTML_H4_CLOSE = new CloseTagToken(TokenHTML_H4_CLOSE, "h4", "</h4>");
256 final static AbstractTag HTML_H4_OPEN = new OpenTagToken(TokenHTML_H4_OPEN, "h4", "<h4>");
257 final static AbstractTag HTML_H5_CLOSE = new CloseTagToken(TokenHTML_H5_CLOSE, "h5", "</h5>");
258 final static AbstractTag HTML_H5_OPEN = new OpenTagToken(TokenHTML_H5_OPEN, "h5", "<h5>");
259 final static AbstractTag HTML_H6_CLOSE = new CloseTagToken(TokenHTML_H6_CLOSE, "h6", "</h6>");
260 final static AbstractTag HTML_H6_OPEN = new OpenTagToken(TokenHTML_H6_OPEN, "h6", "<h6>");
261 final static AbstractTag HTML_ITALIC_CLOSE = new CloseTagToken(TokenHTML_ITALIC_CLOSE, "i", "</i>");
262 final static AbstractTag HTML_ITALIC_OPEN = new OpenTagToken(TokenHTML_ITALIC_OPEN, "i", "<i>");
263 final static AbstractTag HTML_BOLD_CLOSE = new CloseTagToken(TokenHTML_BOLD_CLOSE, "b", "</b>");
264 final static AbstractTag HTML_BOLD_OPEN = new OpenTagToken(TokenHTML_BOLD_OPEN, "b", "<b>");
267 final static AbstractTag HTML_PARAGRAPH_CLOSE = new CloseTagToken(TokenHTML_PARAGRAPH_CLOSE, "p", "</p>");
268 final static AbstractTag HTML_PARAGRAPH_OPEN = new OpenTagToken(TokenHTML_PARAGRAPH_OPEN, "p", "<p>");
269 final static AbstractTag HTML_PRE_CLOSE = new CloseTagToken(TokenHTML_PRE_CLOSE, "pre", "</pre>");
270 final static AbstractTag HTML_PRE_OPEN = new OpenTagToken(TokenHTML_PRE_OPEN, "pre", "<pre>");
271 final static AbstractTag HTML_BLOCKQUOTE_CLOSE = new CloseTagToken(TokenHTML_BLOCKQUOTE_CLOSE, "blockquote", "</blockquote>");
272 final static AbstractTag HTML_BLOCKQUOTE_OPEN = new OpenTagToken(TokenHTML_BLOCKQUOTE_OPEN, "blockquote", "<blockquote>");
273 final static AbstractTag HTML_STRIKE_CLOSE = new CloseTagToken(TokenHTML_STRIKE_CLOSE, "strike", "</strike>");
274 final static AbstractTag HTML_STRIKE_OPEN = new OpenTagToken(TokenHTML_STRIKE_OPEN, "strike", "<strike>");
275 final static AbstractTag HTML_STRONG_CLOSE = new CloseTagToken(TokenHTML_STRONG_CLOSE, "strong", "</b>");
276 final static AbstractTag HTML_STRONG_OPEN = new OpenTagToken(TokenHTML_STRONG_OPEN, "strong", "<b>");
277 final static AbstractTag HTML_UNDERLINE_CLOSE = new CloseTagToken(TokenHTML_UNDERLINE_CLOSE, "u", "</u>");
278 final static AbstractTag HTML_UNDERLINE_OPEN = new OpenTagToken(TokenHTML_UNDERLINE_OPEN, "u", "<u>");
279 final static AbstractTag HTML_SUB_CLOSE = new CloseTagToken(TokenHTML_SUB_CLOSE, "sub", "</sub>");
280 final static AbstractTag HTML_SUB_OPEN = new OpenTagToken(TokenHTML_SUB_OPEN, "sub", "<sub>");
281 final static AbstractTag HTML_SUP_CLOSE = new CloseTagToken(TokenHTML_SUP_CLOSE, "sup", "</sup>");
282 final static AbstractTag HTML_SUP_OPEN = new OpenTagToken(TokenHTML_SUP_OPEN, "sup", "<sup>");
284 final static AbstractTag HTML_CENTER_OPEN = new OpenTagToken(TokenHTML_CENTER_OPEN, "center", "<center>");
285 final static AbstractTag HTML_CENTER_CLOSE = new CloseTagToken(TokenHTML_CENTER_CLOSE, "center", "</center>");
286 final static AbstractTag HTML_TT_OPEN = new OpenTagToken(TokenHTML_TT_OPEN, "tt", "<tt>");
287 final static AbstractTag HTML_TT_CLOSE = new CloseTagToken(TokenHTML_TT_CLOSE, "tt", "</tt>");
289 final static AbstractTag HTML_MATH_OPEN = new OpenTagToken(TokenHTML_MATH_OPEN, "math", "<math>");
290 final static AbstractTag HTML_MATH_CLOSE = new CloseTagToken(TokenHTML_MATH_CLOSE, "math", "</math>");
292 final static AbstractTag HTML_TABLE_OPEN = new TableTag(TokenHTML_TABLE_OPEN, "table", "<table>");
293 final static AbstractTag HTML_TABLE_CLOSE = new CloseTagToken(TokenHTML_TABLE_CLOSE, "table", "</table>");
294 final static AbstractTag HTML_CAPTION_OPEN = new OpenTagToken(TokenHTML_CAPTION_OPEN, "caption", "<caption>");
295 final static AbstractTag HTML_CAPTION_CLOSE = new CloseTagToken(TokenHTML_CAPTION_CLOSE, "caption", "</caption>");
296 final static AbstractTag HTML_TH_OPEN = new OpenTagToken(TokenHTML_TH_OPEN, "th", "<th>");
297 final static AbstractTag HTML_TH_CLOSE = new CloseTagToken(TokenHTML_TH_CLOSE, "th", "</th>");
298 final static AbstractTag HTML_TR_OPEN = new OpenTagToken(TokenHTML_TR_OPEN, "tr", "<tr>");
299 final static AbstractTag HTML_TR_CLOSE = new CloseTagToken(TokenHTML_TR_CLOSE, "tr", "</tr>");
300 final static AbstractTag HTML_TD_OPEN = new OpenTagToken(TokenHTML_TD_OPEN, "td", "<td>");
301 final static AbstractTag HTML_TD_CLOSE = new CloseTagToken(TokenHTML_TD_CLOSE, "td", "</td>");
302 final static AbstractTag HTML_FONT_OPEN = new FontTag(TokenHTML_FONT_OPEN, "font", "<font>");
303 final static AbstractTag HTML_FONT_CLOSE = new CloseTagToken(TokenHTML_FONT_CLOSE, "font", "</font>");
304 final static AbstractTag HTML_DIV_OPEN = new DivTag(TokenHTML_DIV_OPEN, "div", "<div>");
305 final static AbstractTag HTML_DIV_CLOSE = new CloseTagToken(TokenHTML_DIV_CLOSE, "div", "</div>");
307 final static AbstractTag LIST_OL_START = new AbstractTag(TokenLIST_OL_START);
308 final static AbstractTag LIST_UL_START = new AbstractTag(TokenLIST_UL_START);
310 final static AbstractTag HTML_VAR_OPEN = new OpenTagToken(TokenHTML_VAR_OPEN, "var", "<var>");
311 final static AbstractTag HTML_VAR_CLOSE = new CloseTagToken(TokenHTML_VAR_CLOSE, "var", "</var>");
312 final static AbstractTag HTML_CODE_OPEN = new OpenTagToken(TokenHTML_CODE_OPEN, "code", "<code>");
313 final static AbstractTag HTML_CODE_CLOSE = new CloseTagToken(TokenHTML_CODE_CLOSE, "code", "</code>");
316 final static AbstractTag HTML_S_OPEN = new OpenTagToken(TokenHTML_S_OPEN, "s", "<s>");
317 final static AbstractTag HTML_S_CLOSE = new CloseTagToken(TokenHTML_S_CLOSE, "s", "</s>");
319 final static AbstractTag HTML_SMALL_OPEN = new OpenTagToken(TokenHTML_SMALL_OPEN, "small", "<small>");
320 final static AbstractTag HTML_SMALL_CLOSE = new CloseTagToken(TokenHTML_SMALL_CLOSE, "small", "</small>");
322 final static HashMap OPEN_TAGS = new HashMap();
323 final static HashMap CLOSE_TAGS = new HashMap();
325 final static HashSet ENTITY_SET = new HashSet();
326 final static HashMap IMAGE_MAP = new HashMap();
328 // private static Log log = LogFactory.getLog(WikipediaFilter.class);
331 for (int i = 0; i < ENTITY_STRINGS.length; i++) {
332 ENTITY_SET.add(ENTITY_STRINGS[i]);
334 for (int i = 0; i < IMAGE_STRINGS.length; i += 2) {
335 IMAGE_MAP.put(IMAGE_STRINGS[i], IMAGE_STRINGS[i + 1]);
337 OPEN_TAGS.put("br", HTML_BR_OPEN);
338 OPEN_TAGS.put("hr", HTML_HR_OPEN);
340 OPEN_TAGS.put("h1", HTML_H1_OPEN);
341 OPEN_TAGS.put("h2", HTML_H2_OPEN);
342 OPEN_TAGS.put("h3", HTML_H3_OPEN);
343 OPEN_TAGS.put("h4", HTML_H4_OPEN);
344 OPEN_TAGS.put("h5", HTML_H5_OPEN);
345 OPEN_TAGS.put("h6", HTML_H6_OPEN);
347 CLOSE_TAGS.put("h1", HTML_H1_CLOSE);
348 CLOSE_TAGS.put("h2", HTML_H2_CLOSE);
349 CLOSE_TAGS.put("h3", HTML_H1_CLOSE);
350 CLOSE_TAGS.put("h4", HTML_H2_CLOSE);
351 CLOSE_TAGS.put("h5", HTML_H1_CLOSE);
352 CLOSE_TAGS.put("h6", HTML_H2_CLOSE);
354 OPEN_TAGS.put("em", HTML_EM_OPEN);
355 CLOSE_TAGS.put("em", HTML_EM_CLOSE);
356 OPEN_TAGS.put("i", HTML_ITALIC_OPEN);
357 CLOSE_TAGS.put("i", HTML_ITALIC_CLOSE);
358 OPEN_TAGS.put("b", HTML_BOLD_OPEN);
359 CLOSE_TAGS.put("b", HTML_BOLD_CLOSE);
360 OPEN_TAGS.put("strong", HTML_STRONG_OPEN);
361 CLOSE_TAGS.put("strong", HTML_STRONG_CLOSE);
362 OPEN_TAGS.put("u", HTML_UNDERLINE_OPEN);
363 CLOSE_TAGS.put("u", HTML_UNDERLINE_CLOSE);
364 OPEN_TAGS.put("p", HTML_PARAGRAPH_OPEN);
365 CLOSE_TAGS.put("p", HTML_PARAGRAPH_CLOSE);
367 OPEN_TAGS.put("pre", HTML_PRE_OPEN);
368 CLOSE_TAGS.put("pre", HTML_PRE_CLOSE);
369 OPEN_TAGS.put("blockquote", HTML_BLOCKQUOTE_OPEN);
370 CLOSE_TAGS.put("blockquote", HTML_BLOCKQUOTE_CLOSE);
372 OPEN_TAGS.put("var", HTML_VAR_OPEN);
373 CLOSE_TAGS.put("var", HTML_VAR_CLOSE);
374 OPEN_TAGS.put("code", HTML_CODE_OPEN);
375 CLOSE_TAGS.put("code", HTML_CODE_CLOSE);
376 OPEN_TAGS.put("s", HTML_S_OPEN);
377 CLOSE_TAGS.put("s", HTML_S_CLOSE);
378 OPEN_TAGS.put("small", HTML_SMALL_OPEN);
379 CLOSE_TAGS.put("small", HTML_SMALL_CLOSE);
380 OPEN_TAGS.put("sub", HTML_SUB_OPEN);
381 CLOSE_TAGS.put("sub", HTML_SUB_CLOSE);
382 OPEN_TAGS.put("sup", HTML_SUP_OPEN);
383 CLOSE_TAGS.put("sup", HTML_SUP_CLOSE);
384 OPEN_TAGS.put("strike", HTML_STRIKE_OPEN);
385 CLOSE_TAGS.put("strike", HTML_STRIKE_CLOSE);
387 OPEN_TAGS.put("math", HTML_MATH_OPEN);
388 CLOSE_TAGS.put("math", HTML_MATH_CLOSE);
390 OPEN_TAGS.put("table", HTML_TABLE_OPEN);
391 CLOSE_TAGS.put("table", HTML_TABLE_CLOSE);
392 OPEN_TAGS.put("th", HTML_TH_OPEN);
393 CLOSE_TAGS.put("th", HTML_TH_CLOSE);
394 OPEN_TAGS.put("tr", HTML_TR_OPEN);
395 CLOSE_TAGS.put("tr", HTML_TR_CLOSE);
396 OPEN_TAGS.put("td", HTML_TD_OPEN);
397 CLOSE_TAGS.put("td", HTML_TD_CLOSE);
398 OPEN_TAGS.put("caption", HTML_CAPTION_OPEN);
399 CLOSE_TAGS.put("caption", HTML_CAPTION_CLOSE);
401 OPEN_TAGS.put("font", HTML_FONT_OPEN);
402 CLOSE_TAGS.put("font", HTML_FONT_CLOSE);
403 OPEN_TAGS.put("center", HTML_CENTER_OPEN);
404 CLOSE_TAGS.put("center", HTML_CENTER_CLOSE);
405 OPEN_TAGS.put("tt", HTML_TT_OPEN);
406 CLOSE_TAGS.put("tt", HTML_TT_CLOSE);
407 OPEN_TAGS.put("div", HTML_DIV_OPEN);
408 CLOSE_TAGS.put("div", HTML_DIV_CLOSE);
412 * Limits the recursive call of this filter to a depth of RECURSION_LIMIT
414 final static int RECURSION_LIMIT = 5;
416 final static AbstractTag START = new AbstractTag(TokenSTART);
418 final static AbstractTag STRIKETHROUGH = new AbstractTag(TokenSTRIKETHROUGH);
421 * Determines if the specified character may be part of a url
423 public final static boolean isUrlIdentifierPart(char ch) {
424 if (Character.isLetterOrDigit(ch)) {
427 final String test = "-_.!~*';/?:@#&=+$,";
428 return test.indexOf(ch) != (-1);
432 * Determines if the specified character may be part of a wiki plugin identifier as other than the first character
434 public final static boolean isWikiPluginIdentifierPart(char ch) {
435 return Character.isLetterOrDigit(ch) || (ch == '_');
439 * Determines if the specified character may be part the first character of a wiki plugin identifier
441 public final static boolean isWikiPluginIdentifierStart(char ch) {
442 return Character.isLetter(ch);
445 public static boolean createStaticImage(String imageTag, StringBuffer buff) {
446 String value = (String) IMAGE_MAP.get(imageTag);
448 buff.append(MessageFormat.format(value, ARGUMENTS));
454 // private MacroRepository macros;
456 public WikipediaFilter() {
460 public String filter(String input, FilterContext context) {
461 return filter(input, context, MacroRepository.getInstance(), 0);
464 public String filter(
466 FilterContext context,
467 MacroRepository macros,
468 int recursionLevel) {
470 if (++recursionLevel > RECURSION_LIMIT) {
471 String error = "<span class=\"error\">Error - recursion limit exceeded.</span>";
475 StringBuffer result = new StringBuffer(input.length() + input.length() / 10);
476 if (input.startsWith("#html")) {
478 int index = input.indexOf('\n');
481 // Configuration fUser = Application.get().getUser();
482 // if (fUser.isAdmin()) {
483 // admins are allowed to insert full html directly
484 String subst = input.substring(index + 1);
490 // instantiate inner Parser class
491 WikipediaParser parser = new WikipediaParser(macros, input, result, context, recursionLevel);
493 return result.toString();
494 // Util.substitute(matcher, p, new Perl5Substitution(s, interps), result, limit);
495 } catch (Exception e) {
496 //log.warn("<span class=\"error\">Exception</span>: " + this + ": " + e);
497 // log.warn("Exception for: " + " " + e);
499 } catch (Error err) {
500 //log.warn("<span class=\"error\">Error</span>: " + this + ": " + err);
501 // log.warn("Error for: ");
502 err.printStackTrace();
504 String error = "<span class=\"error\">Error in Parser.</span>";
508 public static String filterParser(
510 FilterContext context,
511 MacroRepository macros,
512 int recursionLevel) {
514 if (++recursionLevel > RECURSION_LIMIT) {
515 return "<span class=\"error\">Error - recursion limit exceeded.</span>";
518 StringBuffer result = new StringBuffer(input.length() + input.length() / 10);
519 // instantiate inner Parser class
520 WikipediaParser parser = new WikipediaParser(macros, input, result, context, recursionLevel);
522 return result.toString();
523 // Util.substitute(matcher, p, new Perl5Substitution(s, interps), result, limit);
524 } catch (Exception e) {
525 //log.warn("<span class=\"error\">Exception</span>: " + this + ": " + e);
526 // log.warn("Exception for: " + " " + e);
528 } catch (Error err) {
529 //log.warn("<span class=\"error\">Error</span>: " + this + ": " + err);
530 // log.warn("Error for: ");
531 err.printStackTrace();
534 return "<span class=\"error\">Error in Parser.</span>";
537 // private void filterParams(StringBuffer buffer, String name) {
538 // Map param = fContext.getRenderContext().getParameters();
539 // if (param != null) {
540 // if (param.containsKey(name)) {
541 // Object value = param.get(name);
542 // if (value instanceof String[]) {
543 // buffer.append(((String[]) value)[0]);
545 // buffer.append(value);
548 // buffer.append("<");
549 // buffer.append(name);
550 // buffer.append(">");
553 // buffer.append("<");
554 // buffer.append(name);
555 // buffer.append(">");
559 // public String parseParameters(String unsplittedMacroParameters) {
561 // int currEndPos = 0;
562 // int len = unsplittedMacroParameters.length();
563 // StringBuffer buffer = new StringBuffer(len);
565 // while (currPos < len) {
566 // ch = unsplittedMacroParameters.charAt(currPos++);
568 // buffer.append(ch);
570 // if ((currEndPos = unsplittedMacroParameters.indexOf('|', currPos)) >= 1) {
571 // filterParams(buffer, unsplittedMacroParameters.substring(currPos, currEndPos));
572 // currPos = currEndPos + 1;
573 // buffer.append('|');
575 // if (currPos < len) {
576 // filterParams(buffer, unsplittedMacroParameters.substring(currPos, len));
581 // return buffer.toString();
584 // protected Repository getMacroRepository() {
588 // public void setInitialContext(InitialRenderContext context) {
589 // macros = MacroRepository.getInstance();
590 // macros.setInitialContext(context);
593 public static void copyWhite(StringBuffer result, String text) {
594 final int len = text.length();
595 int currentIndex = 0;
596 int lastIndex = currentIndex;
597 while (currentIndex < len) {
598 switch (text.charAt(currentIndex++)) {
599 case '<' : // special html escape character
600 if (lastIndex < (currentIndex - 1)) {
601 result.append(text.substring(lastIndex, currentIndex - 1));
602 lastIndex = currentIndex;
606 result.append("<");
608 case '>' : // special html escape character
609 if (lastIndex < (currentIndex - 1)) {
610 result.append(text.substring(lastIndex, currentIndex - 1));
611 lastIndex = currentIndex;
615 result.append(">");
617 case '&' : // special html escape character
618 if (lastIndex < (currentIndex - 1)) {
619 result.append(text.substring(lastIndex, currentIndex - 1));
620 lastIndex = currentIndex;
624 result.append("&");
626 case '\'' : // special html escape character
627 if (lastIndex < (currentIndex - 1)) {
628 result.append(text.substring(lastIndex, currentIndex - 1));
629 lastIndex = currentIndex;
633 result.append("'");
635 case '\"' : // special html escape character
636 if (lastIndex < (currentIndex - 1)) {
637 result.append(text.substring(lastIndex, currentIndex - 1));
638 lastIndex = currentIndex;
642 result.append(""");
646 if (lastIndex < (currentIndex)) {
647 result.append(text.substring(lastIndex, currentIndex));
651 public static void createMacro(StringBuffer result, String macroCommand, FilterContext context, MacroRepository macros) {
655 String parameterString = null;
656 String macroBodyString = "";
658 int index1 = macroCommand.indexOf('}');
659 if ((index0 = macroCommand.indexOf(':')) >= 0 && (index0 < index1)) {
660 command = macroCommand.substring(1, index0);
661 parameterString = macroCommand.substring(index0 + 1, index1);
663 command = macroCommand.substring(1, index1);
665 Macro macro = (Macro) macros.get(command);
667 String completeMacroSubString;
669 if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
670 endTag = '{' + command + '}';
671 index0 = macroCommand.indexOf(endTag, command.length());
674 macroBodyString = macroCommand.substring(index1 + 1, index0);
677 completeMacroSubString = macroCommand;
679 handleMacro(result, completeMacroSubString, command, parameterString, macroBodyString, context, macros);
683 private static void handleMacro(
685 String completeMacroSubString,
687 String unsplittedMacroParameters,
689 FilterContext context,
690 MacroRepository macros) {
691 if (command != null) {
692 // {$peng} are variables not macros.
693 if (!command.startsWith("$")) {
694 MacroParameter mParams = context.getMacroParameter();
696 if (group3 != null) {
697 mParams.setContent(group3);
698 mParams.setContentStart(0);
699 mParams.setContentEnd(group3.length());
701 if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
702 // mParams.setParams(parseParameters(unsplittedMacroParameters));
703 mParams.setParams(unsplittedMacroParameters);
706 mParams.setEnd(completeMacroSubString.length());
708 // @DANGER: recursive calls may replace macros in included source code
710 if (macros.containsKey(command)) {
712 Macro macro = (Macro) macros.get(command);
713 // recursively filter macros within macros
714 if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
715 mParams.setContent(filterParser(mParams.getContent(), context, macros, 0));
717 StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
718 macro.execute(writer, mParams);
719 StringBuffer buffer = writer.getBuffer();
720 if (macro instanceof IRenderResultMacro) {
721 result.append(filterParser(buffer.toString(), context, macros, 0));
723 result.append(buffer);
726 } else if (command.startsWith("!")) {
727 RenderEngine engine = context.getRenderContext().getRenderEngine();
728 if (engine instanceof IncludeRenderEngine) {
729 String include = ((IncludeRenderEngine) engine).include(command.substring(1));
730 if (null != include) {
731 // Filter paramFilter = new ParamFilter(mParams);
732 // included = paramFilter.filter(included, null);
733 // fResult.append(include);
734 result.append(filterParser(include, context, macros, 0));
736 result.append(command.substring(1) + " not found.");
741 // fResult.append(group0);
742 copyWhite(result, completeMacroSubString);
745 } catch (IllegalArgumentException e) {
746 result.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
750 } catch (Throwable e) {
751 // log.warn("MacroFilter: unable to format macro: " + command, e);
752 result.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
758 result.append(command.substring(1));
762 // fResult.append(group0);
763 copyWhite(result, completeMacroSubString);
767 public static void createExternalLink(StringBuffer result, RenderEngine wikiEngine, String urlString) {
769 // Does our engine know images?
770 if (wikiEngine instanceof ImageRenderEngine) {
771 result.append(((ImageRenderEngine) wikiEngine).getExternalImageLink());
773 result.append("<span class=\"nobr\">");
774 result.append("<a href=\"");
775 result.append(Encoder.escape(urlString));
776 result.append("\">");
777 result.append(Encoder.toEntity(urlString.charAt(0)) + urlString.substring(1));
778 result.append("</a></span>");
781 public static void handleSnipLink(StringBuffer result, RenderEngine wikiEngine, String name) {
783 int index = name.indexOf("http://");
784 // Configuration probably wrote [http://radeox.org] instead of http://radeox.org
786 createExternalLink(result, wikiEngine, name.substring(index));
788 // fResult.append("<div class=\"error\">Do not surround URLs with [...].</div>");
790 // trim the name and unescape it
791 name = Encoder.unescape(name.trim());
792 // Is there an alias like [alias|link] ?
793 int pipeIndex = name.indexOf('|');
795 if (-1 != pipeIndex) {
796 alias = name.substring(0, pipeIndex);
797 name = name.substring(pipeIndex + 1);
800 int hashIndex = name.lastIndexOf('#');
803 if (-1 != hashIndex && hashIndex != name.length() - 1) {
804 hash = name.substring(hashIndex + 1);
805 name = name.substring(0, hashIndex);
808 int colonIndex = name.indexOf(':');
810 if (-1 != colonIndex) {
811 // for now throw away the fType information
812 name = name.substring(colonIndex + 1);
815 int atIndex = name.lastIndexOf('@');
818 String extSpace = name.substring(atIndex + 1);
819 // known extarnal space ?
820 InterWiki interWiki = InterWiki.getInstance();
821 if (interWiki.contains(extSpace)) {
822 name = name.substring(0, atIndex);
823 Writer writer = new StringBufferWriter(result);
825 if (-1 != hashIndex) {
826 interWiki.expand(writer, extSpace, name, hash);
828 interWiki.expand(writer, extSpace, name, "");
830 } catch (IOException e) {
831 // log.debug("InterWiki " + extSpace + " not found.");
834 result.append("[<span class=\"error\">");
836 result.append("?</span>]");
840 if (wikiEngine != null && wikiEngine instanceof WikiRenderEngine) {
841 if (((WikiRenderEngine) wikiEngine).exists(name)) {
843 if (-1 != pipeIndex) {
846 // Do not add hash if an alias was given
847 if (-1 != hashIndex) {
848 ((WikiRenderEngine) wikiEngine).appendLink(result, name, view, hash);
850 ((WikiRenderEngine) wikiEngine).appendLink(result, name, view);
852 } else if (((WikiRenderEngine) wikiEngine).showCreate()) {
853 ((WikiRenderEngine) wikiEngine).appendCreateLink(result, name, name);
854 // links with "create" are not cacheable because
855 // a missing wiki could be created
857 // fContext.getRenderContext().setCacheable(false);
859 // cannot display/create wiki, so just display the text
863 // cannot display/create wiki, so just display the text
871 public static void handleWikipediaLink(StringBuffer result, RenderEngine wikiEngine, String name, String suffix) {
873 int index = name.indexOf("http://");
874 // Configuration probably wrote [http://radeox.org] instead of http://radeox.org
876 // createExternalLink(result, wikiEngine, name.substring(index));
877 String urlString = name.substring(index);
878 // Wikipedia like style:
879 int pipeIndex = urlString.indexOf(' ');
881 if (-1 != pipeIndex) {
882 alias = urlString.substring(pipeIndex + 1);
883 urlString = urlString.substring(0, pipeIndex);
888 if (wikiEngine instanceof ImageRenderEngine) {
889 result.append(((ImageRenderEngine) wikiEngine).getExternalImageLink());
891 result.append("<span class=\"nobr\">");
892 result.append("<a href=\"");
893 result.append(Encoder.escape(urlString));
894 result.append("\">");
895 result.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
896 result.append("</a></span>");
898 if (suffix == null) {
901 // trim the name and unescape it
902 name = Encoder.unescape(name.trim());
904 name = name.replaceAll(":","/");
906 // Is there an alias like [alias|link] ?
907 int pipeIndex = name.indexOf('|');
909 if (-1 != pipeIndex) {
910 alias = name.substring(pipeIndex + 1);
911 name = name.substring(0, pipeIndex);
914 int hashIndex = name.lastIndexOf('#');
917 if (-1 != hashIndex && hashIndex != name.length() - 1) {
918 hash = name.substring(hashIndex + 1);
919 name = name.substring(0, hashIndex);
922 int colonIndex = name.indexOf(':');
924 if (-1 != colonIndex) {
925 // for now throw away the fType information
926 name = name.substring(colonIndex + 1);
929 int atIndex = name.lastIndexOf('@');
932 String extSpace = name.substring(atIndex + 1);
933 // known external space ?
934 InterWiki interWiki = InterWiki.getInstance();
935 if (interWiki.contains(extSpace)) {
936 name = name.substring(0, atIndex);
937 Writer writer = new StringBufferWriter(result);
939 if (-1 != hashIndex) {
940 interWiki.expand(writer, extSpace, name, hash);
942 interWiki.expand(writer, extSpace, name, "");
944 } catch (IOException e) {
945 // log.debug("InterWiki " + extSpace + " not found.");
948 result.append("[<span class=\"error\">");
950 result.append("?</span>]");
954 if (wikiEngine != null && wikiEngine instanceof WikiRenderEngine) {
955 if (((WikiRenderEngine) wikiEngine).exists(name)) {
956 String view = name + suffix;
957 if (-1 != pipeIndex) {
958 view = alias + suffix;
960 // Do not add hash if an alias was given
961 if (-1 != hashIndex) {
962 ((WikiRenderEngine) wikiEngine).appendLink(result, name, view, hash);
964 ((WikiRenderEngine) wikiEngine).appendLink(result, name, view);
966 } else if (((WikiRenderEngine) wikiEngine).showCreate()) {
967 ((WikiRenderEngine) wikiEngine).appendCreateLink(result, name, name + suffix);
968 // links with "create" are not cacheable because
969 // a missing wiki could be created
971 // fContext.getRenderContext().setCacheable(false);
973 // cannot display/create wiki, so just display the text
977 // cannot display/create wiki, so just display the text