2005-08-06 19:03:12 +02:00
// wikiCode.java
// -------------------------------------
// part of YACY
//
2006-05-12 16:35:56 +02:00
// (C) 2005, 2006 by Alexander Schier
2006-09-18 00:57:10 +02:00
// Marc Nause, Franz Brausse
2006-05-12 16:35:56 +02:00
//
//
// last change: $LastChangedDate: $ by $LastChangedBy: $
2005-08-06 19:03:12 +02:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Using this software in any meaning (reading, learning, copying, compiling,
// running) means that you agree that the Author(s) is (are) not responsible
// for cost, loss of data or any harm that may be caused directly or indirectly
// by usage of this softare or this documentation. The usage of this software
// is on your own risk. The installation and usage (starting/running) of this
// software may allow other people or application to access your computer and
// any attached devices and is highly dependent on the configuration of the
// software which must be done by the user of the software; the author(s) is
// (are) also not responsible for proper configuration and usage of the
// software, even if provoked by documentation provided together with
// the software.
//
// Any changes to this file according to the GPL as documented in the file
// gpl.txt aside this file in the shipment you received can be done to the
// lines that follows this copyright notice here, but changes must not be
// done inside the copyright notive above. A re-distribution must contain
// the intact and unchanged copyright notice.
// Contributions and changes to the program code must be marked as such.
2005-08-19 03:38:14 +02:00
// Contains contributions from Alexander Schier [AS]
2006-01-17 02:00:38 +01:00
// Franz Brausse [FB] and Marc Nause [MN]
2005-08-19 03:38:14 +02:00
2005-08-06 19:03:12 +02:00
package de.anomic.data ;
import java.io.BufferedReader ;
import java.io.IOException ;
2006-02-22 01:53:14 +01:00
import java.util.ArrayList ;
2005-08-06 19:03:12 +02:00
2007-05-20 15:29:12 +02:00
import de.anomic.data.wiki.abstractWikiParser ;
import de.anomic.data.wiki.wikiParser ;
2005-08-06 19:03:12 +02:00
import de.anomic.plasma.plasmaSwitchboard ;
import de.anomic.server.serverCore ;
2005-12-15 22:58:13 +01:00
import de.anomic.yacy.yacyCore ;
2005-08-06 19:03:12 +02:00
2006-04-17 21:37:09 +02:00
/ * * This class provides methods to handle texts that have been posted in the yacyWiki or other
* parts of YaCy that use this class , like the blog or the profile .
* /
2007-05-20 15:29:12 +02:00
public class wikiCode extends abstractWikiParser implements wikiParser {
2005-08-06 19:03:12 +02:00
private String numListLevel = " " ;
private String ListLevel = " " ;
2005-08-20 14:57:31 +02:00
private String defListLevel = " " ;
2006-04-17 21:37:09 +02:00
private boolean cellprocessing = false ; //needed for prevention of double-execution of replaceHTML
2006-04-11 00:04:52 +02:00
private boolean defList = false ; //needed for definition lists
private boolean escape = false ; //needed for escape
private boolean escaped = false ; //needed for <pre> not getting in the way
private boolean escapeSpan = false ; //needed for escape symbols [= and =] spanning over several lines
2006-04-17 21:37:09 +02:00
private boolean newrowstart = false ; //needed for the first row not to be empty
private boolean nolist = false ; //needed for handling of [= and <pre> in lists
2006-04-11 00:04:52 +02:00
private boolean preformatted = false ; //needed for preformatted text
private boolean preformattedSpan = false ; //needed for <pre> and </pre> spanning over several lines
private boolean replacedHTML = false ; //indicates if method replaceHTML has been used with line already
2006-01-23 14:59:40 +01:00
private boolean replacedCharacters = false ; //indicates if method replaceCharachters has been used with line
2006-05-07 20:15:00 +02:00
private boolean table = false ; //needed for tables, because they reach over several lines
2006-04-11 00:04:52 +02:00
private int preindented = 0 ; //needed for indented <pre>s
private int escindented = 0 ; //needed for indented [=s
private int headlines = 0 ; //number of headlines in page
2006-04-17 21:37:09 +02:00
private ArrayList dirElements = new ArrayList ( ) ; //list of headlines used to create diectory of page
2006-01-16 22:15:06 +01:00
/** Constructor of the class wikiCode */
2005-08-07 19:56:44 +02:00
public wikiCode ( plasmaSwitchboard switchboard ) {
2007-05-20 15:29:12 +02:00
super ( switchboard ) ;
2007-02-03 16:20:12 +01:00
}
2007-05-20 15:29:12 +02:00
protected String transform (
BufferedReader reader ,
int length ,
plasmaSwitchboard switchboard ) throws IOException {
StringBuffer out = new StringBuffer ( length ) ;
String line ;
while ( ( line = reader . readLine ( ) ) ! = null )
out . append ( transformLine ( line , switchboard ) ) . append ( serverCore . crlfString ) ;
return out . insert ( 0 , directory ( ) ) . toString ( ) ;
2007-02-03 16:20:12 +01:00
}
2005-09-05 12:15:59 +02:00
2006-01-22 16:41:49 +01:00
/ * * This method processes tables in the wiki code .
* @param a string that might contain parts of a table
* @return a string with wiki code of parts of table replaced by HTML code for table
* /
2006-03-08 00:58:30 +01:00
//[FB], changes by [MN]
2006-01-23 14:59:40 +01:00
private String processTable ( String result , plasmaSwitchboard switchboard ) {
2006-05-08 00:53:17 +02:00
//some variables that make it easier to change codes for the table
String line = " " ;
String tableStart = " {| " ; // {|
String newLine = " |- " ; // |-
String cellDivider = " || " ; // ||
String tableEnd = " |} " ; // |}
String attribDivider = " | " ; // |
int lenTableStart = tableStart . length ( ) ;
int lenCellDivider = cellDivider . length ( ) ;
int lenTableEnd = tableEnd . length ( ) ;
int lenAttribDivider = attribDivider . length ( ) ;
if ( ( result . startsWith ( tableStart ) ) & & ( ! table ) ) {
2006-01-22 16:41:49 +01:00
table = true ;
newrowstart = true ;
2006-01-23 14:59:40 +01:00
line = " <table " ;
2006-05-08 00:53:17 +02:00
if ( result . trim ( ) . length ( ) > lenTableStart ) {
line + = parseTableProperties ( result . substring ( lenTableStart ) . trim ( ) ) ;
2006-01-22 16:41:49 +01:00
}
line + = " > " ;
2006-01-23 14:59:40 +01:00
result = line ;
}
2006-05-08 00:53:17 +02:00
else if ( result . startsWith ( newLine ) & & ( table ) ) { // new row
2006-01-22 16:41:49 +01:00
if ( ! newrowstart ) {
line + = " \ t</tr> \ n " ;
} else {
newrowstart = false ;
}
line = line + " \ t<tr> " ;
2006-01-23 14:59:40 +01:00
result = line ;
}
2006-05-08 00:53:17 +02:00
else if ( ( result . startsWith ( cellDivider ) ) & & ( table ) ) {
2006-01-22 16:41:49 +01:00
line + = " \ t \ t<td " ;
2006-05-08 00:53:17 +02:00
int cellEnd = ( result . indexOf ( cellDivider , lenCellDivider ) > 0 ) ? ( result . indexOf ( cellDivider , lenCellDivider ) ) : ( result . length ( ) ) ;
int propEnd = result . indexOf ( attribDivider , lenCellDivider ) ;
int occImage = result . indexOf ( " [[Image: " , lenCellDivider ) ;
int occEscape = result . indexOf ( " [= " , lenCellDivider ) ;
2006-02-27 13:33:34 +01:00
//If resultOf("[[Image:") is less than propEnd, that means that there is no
//property for this cell, only an image. Without this, YaCy could get confused
//by a | in [[Image:picture.png|alt-text]] or [[Image:picture.png|alt-text]]
2006-05-08 00:53:17 +02:00
//Same for [= (part of [= =])
if ( ( propEnd > lenCellDivider )
& & ( ( occImage > propEnd ) | | ( occImage < 0 ) )
& & ( ( occEscape > propEnd ) | | ( occEscape < 0 ) )
) {
propEnd = result . indexOf ( attribDivider , lenCellDivider ) + lenAttribDivider ;
2006-02-27 13:33:34 +01:00
}
else {
propEnd = cellEnd ;
}
2006-01-23 14:59:40 +01:00
// both point at same place => new line
if ( propEnd = = cellEnd ) {
2006-05-08 00:53:17 +02:00
propEnd = lenCellDivider ;
2006-09-18 00:57:10 +02:00
}
else {
2006-05-08 00:53:17 +02:00
line + = parseTableProperties ( result . substring ( lenCellDivider , propEnd - lenAttribDivider ) . trim ( ) ) ;
2006-01-22 16:41:49 +01:00
}
2006-09-18 00:57:10 +02:00
// quick&dirty fix for http://www.yacy-forum.de/viewtopic.php?t=2825 [MN]
if ( propEnd > cellEnd ) {
propEnd = lenCellDivider ;
}
2006-01-23 14:59:40 +01:00
table = false ; cellprocessing = true ;
2006-05-08 00:53:17 +02:00
line + = " > " + processTable ( result . substring ( propEnd , cellEnd ) . trim ( ) , switchboard ) + " </td> " ;
2006-01-23 14:59:40 +01:00
table = true ; cellprocessing = false ;
if ( cellEnd < result . length ( ) ) {
line + = " \ n " + processTable ( result . substring ( cellEnd ) , switchboard ) ;
}
result = line ;
}
2006-05-08 00:53:17 +02:00
else if ( result . startsWith ( tableEnd ) & & ( table ) ) { // Table end
2006-01-22 16:41:49 +01:00
table = false ;
2006-05-08 00:53:17 +02:00
line + = " \ t</tr> \ n</table> " + result . substring ( lenTableEnd ) ;
2006-01-23 14:59:40 +01:00
result = line ;
}
return result ;
2006-01-22 16:41:49 +01:00
}
2006-02-22 01:53:14 +01:00
2006-02-24 02:14:38 +01:00
//contributed by [MN]
/ * * This method takes possible table properties and tests if they are valid .
* Valid in this case means if they are a property for the table , tr or td
* tag as stated in the HTML Pocket Reference by Jennifer Niederst ( 1st edition )
* The method is important to avoid XSS attacks on the wiki via table properties .
* @param str A string that may contain several table properties and / or junk .
* @return A string that only contains table properties .
* /
private String parseTableProperties ( String str ) {
str = str . replaceAll ( " " " , " " ) ; //killing all quotationmarks
String [ ] values = str . split ( " [= ] " ) ; //splitting the string at = and blanks
str = " " ; //recycling... ;-)
int numberofvalues = values . length ;
for ( int i = 0 ; i < numberofvalues ; i + + ) {
if ( ( values [ i ] . equals ( " rowspan " ) ) | |
( values [ i ] . equals ( " colspan " ) ) | |
( values [ i ] . equals ( " vspace " ) ) | |
( values [ i ] . equals ( " hspace " ) ) | |
( values [ i ] . equals ( " cellspacing " ) ) | |
( values [ i ] . equals ( " cellpadding " ) ) | |
( values [ i ] . equals ( " border " ) ) ) {
if ( i + 1 < numberofvalues ) {
if ( values [ i + 1 ] . matches ( " \\ d+ " ) ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
}
else if ( ( values [ i ] . equals ( " width " ) ) | | ( values [ i ] . equals ( " height " ) ) ) {
if ( i + 1 < numberofvalues ) {
if ( values [ i + 1 ] . matches ( " \\ d+%{0,1} " ) ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
}
else if ( values [ i ] . equals ( " align " ) ) {
if ( i + 1 < numberofvalues ) {
if ( ( values [ i + 1 ] . equals ( " left " ) ) | |
( values [ i + 1 ] . equals ( " right " ) ) | |
( values [ i + 1 ] . equals ( " center " ) ) ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
}
else if ( values [ i ] . equals ( " valign " ) ) {
if ( i + 1 < numberofvalues ) {
if ( ( values [ i + 1 ] . equals ( " top " ) ) | |
( values [ i + 1 ] . equals ( " middle " ) ) | |
( values [ i + 1 ] . equals ( " bottom " ) ) | |
( values [ i + 1 ] . equals ( " baseline " ) ) ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
}
else if ( values [ i ] . equals ( " bgcolor " ) ) {
if ( i + 1 < numberofvalues ) {
if ( values [ i + 1 ] . matches ( " #{0,1}[0-9a-fA-F]{1,6}|[a-zA-Z]{3,} " ) ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
}
else if ( values [ i ] . equals ( " rules " ) ) {
if ( i + 1 < numberofvalues ) {
if ( ( values [ i + 1 ] . equals ( " none " ) ) | |
( values [ i + 1 ] . equals ( " groups " ) ) | |
( values [ i + 1 ] . equals ( " rows " ) ) | |
( values [ i + 1 ] . equals ( " cols " ) ) | |
( values [ i + 1 ] . equals ( " all " ) ) ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
}
else if ( values [ i ] . equals ( " frame " ) ) {
if ( i + 1 < numberofvalues ) {
if ( ( values [ i + 1 ] . equals ( " void " ) ) | |
( values [ i + 1 ] . equals ( " above " ) ) | |
( values [ i + 1 ] . equals ( " below " ) ) | |
( values [ i + 1 ] . equals ( " hsides " ) ) | |
( values [ i + 1 ] . equals ( " lhs " ) ) | |
( values [ i + 1 ] . equals ( " rhs " ) ) | |
( values [ i + 1 ] . equals ( " vsides " ) ) | |
( values [ i + 1 ] . equals ( " box " ) ) | |
( values [ i + 1 ] . equals ( " border " ) ) ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
}
else if ( values [ i ] . equals ( " summary " ) ) {
if ( i + 1 < numberofvalues ) {
str = str + " " + values [ i ] + " = \" " + values [ i + 1 ] + " \" " ;
i + + ;
}
}
else if ( values [ i ] . equals ( " nowrap " ) ) {
2006-05-07 20:15:00 +02:00
str = str + " nowrap " ;
2006-02-24 02:14:38 +01:00
}
}
return str ;
} //end contrib [MN]
/ * * This method processes ordered lists .
2006-02-22 01:53:14 +01:00
* /
private String orderedList ( String result ) {
2006-04-17 21:37:09 +02:00
if ( ! nolist ) { //lists only get processed if not forbidden (see code for [= and <pre>). [MN]
int p0 = 0 ;
int p1 = 0 ;
//# sorted Lists contributed by [AS]
//## Sublist
if ( result . startsWith ( numListLevel + " # " ) ) { //more #
p0 = result . indexOf ( numListLevel ) ;
p1 = result . length ( ) ;
result = " <ol> " + serverCore . crlfString +
" <li> " +
result . substring ( numListLevel . length ( ) + 1 , p1 ) +
" </li> " ;
numListLevel + = " # " ;
} else if ( numListLevel . length ( ) > 0 & & result . startsWith ( numListLevel ) ) { //equal number of #
p0 = result . indexOf ( numListLevel ) ;
p1 = result . length ( ) ;
result = " <li> " +
result . substring ( numListLevel . length ( ) , p1 ) +
" </li> " ;
} else if ( numListLevel . length ( ) > 0 ) { //less #
int i = numListLevel . length ( ) ;
String tmp = " " ;
while ( ! result . startsWith ( numListLevel . substring ( 0 , i ) ) ) {
tmp + = " </ol> " ;
i - - ;
}
numListLevel = numListLevel . substring ( 0 , i ) ;
p0 = numListLevel . length ( ) ;
p1 = result . length ( ) ;
if ( numListLevel . length ( ) > 0 ) {
result = tmp +
" <li> " +
result . substring ( p0 , p1 ) +
" </li> " ;
} else {
result = tmp + result . substring ( p0 , p1 ) ;
}
2006-02-22 01:53:14 +01:00
}
2006-04-17 21:37:09 +02:00
// end contrib [AS]
2006-02-22 01:53:14 +01:00
}
return result ;
}
2006-04-11 00:04:52 +02:00
/ * * This method processes unordered lists .
* /
//contributed by [AS] put into it's own method by [MN]
private String unorderedList ( String result ) {
2006-04-17 21:37:09 +02:00
if ( ! nolist ) { //lists only get processed if not forbidden (see code for [= and <pre>). [MN]
int p0 = 0 ;
int p1 = 0 ;
//contributed by [AS]
if ( result . startsWith ( ListLevel + " * " ) ) { //more stars
p0 = result . indexOf ( ListLevel ) ;
p1 = result . length ( ) ;
result = " <ul> " + serverCore . crlfString +
2006-04-11 00:04:52 +02:00
" <li> " +
2006-04-17 21:37:09 +02:00
result . substring ( ListLevel . length ( ) + 1 , p1 ) +
2006-04-11 00:04:52 +02:00
" </li> " ;
2006-04-17 21:37:09 +02:00
ListLevel + = " * " ;
} else if ( ListLevel . length ( ) > 0 & & result . startsWith ( ListLevel ) ) { //equal number of stars
p0 = result . indexOf ( ListLevel ) ;
p1 = result . length ( ) ;
result = " <li> " +
result . substring ( ListLevel . length ( ) , p1 ) +
" </li> " ;
} else if ( ListLevel . length ( ) > 0 ) { //less stars
int i = ListLevel . length ( ) ;
String tmp = " " ;
while ( ! result . startsWith ( ListLevel . substring ( 0 , i ) ) ) {
tmp + = " </ul> " ;
i - - ;
}
ListLevel = ListLevel . substring ( 0 , i ) ;
p0 = ListLevel . length ( ) ;
p1 = result . length ( ) ;
if ( ListLevel . length ( ) > 0 ) {
result = tmp +
" <li> " +
result . substring ( p0 , p1 ) +
" </li> " ;
} else {
result = tmp + result . substring ( p0 , p1 ) ;
}
2006-04-11 00:04:52 +02:00
}
2006-04-17 21:37:09 +02:00
//end contrib [AS]
2006-04-11 00:04:52 +02:00
}
return result ;
}
/ * * This method processes definition lists .
* /
//contributed by [MN] based on unordered list code by [AS]
private String definitionList ( String result ) {
2006-04-17 21:37:09 +02:00
if ( ! nolist ) { //lists only get processed if not forbidden (see code for [= and <pre>). [MN]
int p0 = 0 ;
int p1 = 0 ;
if ( result . startsWith ( defListLevel + " ; " ) ) { //more semicolons
String dt = " " ;
String dd = " " ;
p0 = result . indexOf ( defListLevel ) ;
p1 = result . length ( ) ;
String resultCopy = result . substring ( defListLevel . length ( ) + 1 , p1 ) ;
2006-04-11 00:04:52 +02:00
if ( ( p0 = resultCopy . indexOf ( " : " ) ) > 0 ) {
dt = resultCopy . substring ( 0 , p0 ) ;
dd = resultCopy . substring ( p0 + 1 ) ;
2006-04-17 21:37:09 +02:00
result = " <dl> " + " <dt> " + dt + " </dt> " + " <dd> " + dd ;
2006-04-11 00:04:52 +02:00
defList = true ;
}
2006-04-17 21:37:09 +02:00
defListLevel + = " ; " ;
} else if ( defListLevel . length ( ) > 0 & & result . startsWith ( defListLevel ) ) { //equal number of semicolons
String dt = " " ;
String dd = " " ;
p0 = result . indexOf ( defListLevel ) ;
p1 = result . length ( ) ;
String resultCopy = result . substring ( defListLevel . length ( ) , p1 ) ;
if ( ( p0 = resultCopy . indexOf ( " : " ) ) > 0 ) {
dt = resultCopy . substring ( 0 , p0 ) ;
dd = resultCopy . substring ( p0 + 1 ) ;
result = " <dt> " + dt + " </dt> " + " <dd> " + dd ;
defList = true ;
}
} else if ( defListLevel . length ( ) > 0 ) { //less semicolons
String dt = " " ;
String dd = " " ;
int i = defListLevel . length ( ) ;
String tmp = " " ;
while ( ! result . startsWith ( defListLevel . substring ( 0 , i ) ) ) {
tmp + = " </dd></dl> " ;
i - - ;
}
defListLevel = defListLevel . substring ( 0 , i ) ;
p0 = defListLevel . length ( ) ;
p1 = result . length ( ) ;
if ( defListLevel . length ( ) > 0 ) {
String resultCopy = result . substring ( p0 , p1 ) ;
if ( ( p0 = resultCopy . indexOf ( " : " ) ) > 0 ) {
dt = resultCopy . substring ( 0 , p0 ) ;
dd = resultCopy . substring ( p0 + 1 ) ;
result = tmp + " <dt> " + dt + " </dt> " + " <dd> " + dd ;
defList = true ;
}
} else {
result = tmp + result . substring ( p0 , p1 ) ;
}
2006-04-11 00:04:52 +02:00
}
}
return result ;
}
/ * * This method processes links and images .
* /
//contributed by [AS] except where stated otherwise
private String linksAndImages ( String result , plasmaSwitchboard switchboard ) {
// create links
String kl , kv , alt , align ;
int p ;
int p0 = 0 ;
int p1 = 0 ;
// internal links and images
while ( ( p0 = result . indexOf ( " [[ " ) ) > = 0 ) {
p1 = result . indexOf ( " ]] " , p0 + 2 ) ;
if ( p1 < = p0 ) break ;
kl = result . substring ( p0 + 2 , p1 ) ;
// this is the part of the code that's responsible for images
// contributed by [MN]
if ( kl . startsWith ( " Image: " ) ) {
alt = " " ;
align = " " ;
kv = " " ;
kl = kl . substring ( 6 ) ;
// are there any arguments for the image?
2006-05-08 00:53:17 +02:00
if ( ( p = kl . indexOf ( " | " ) ) > 0 ) {
2006-05-08 16:23:22 +02:00
kv = kl . substring ( p + 6 ) ;
2006-04-11 00:04:52 +02:00
kl = kl . substring ( 0 , p ) ;
// if there are 2 arguments, write them into ALIGN and ALT
2006-05-08 00:53:17 +02:00
if ( ( p = kv . indexOf ( " | " ) ) > 0 ) {
2006-04-11 00:04:52 +02:00
align = kv . substring ( 0 , p ) ;
//checking validity of value for align. Only non browser specific
//values get supported. Not supported: absmiddle, baseline, texttop
if ( ( align . equals ( " bottom " ) ) | |
( align . equals ( " center " ) ) | |
( align . equals ( " left " ) ) | |
( align . equals ( " middle " ) ) | |
( align . equals ( " right " ) ) | |
( align . equals ( " top " ) ) )
{
align = " align= \" " + align + " \" " ;
}
else align = " " ;
2006-05-08 16:23:22 +02:00
alt = " alt= \" " + kv . substring ( p + 6 ) + " \" " ;
2006-04-11 00:04:52 +02:00
}
// if there is just one, put it into ALT
else
alt = " alt= \" " + kv + " \" " ;
}
// replace incomplete URLs and make them point to http://peerip:port/...
// with this feature you can access an image in DATA/HTDOCS/share/yacy.gif
// using the wikicode [[Image:share/yacy.gif]]
// or an image DATA/HTDOCS/grafics/kaskelix.jpg with [[Image:grafics/kaskelix.jpg]]
// you are free to use other sub-paths of DATA/HTDOCS
2006-11-24 03:52:38 +01:00
if ( kl . indexOf ( " :// " ) < 1 ) {
2007-04-30 00:05:34 +02:00
kl = " http:// " + yacyCore . seedDB . mySeed . getPublicAddress ( ) . trim ( ) + " / " + kl ;
2006-04-11 00:04:52 +02:00
}
result = result . substring ( 0 , p0 ) + " <img src= \" " + kl + " \" " + align + alt + " > " + result . substring ( p1 + 2 ) ;
}
// end contrib [MN]
// if it's no image, it might be an internal link
else {
2006-05-08 00:53:17 +02:00
if ( ( p = kl . indexOf ( " | " ) ) > 0 ) {
2006-05-08 16:23:22 +02:00
kv = kl . substring ( p + 6 ) ;
2006-04-11 00:04:52 +02:00
kl = kl . substring ( 0 , p ) ;
} else {
kv = kl ;
}
if ( switchboard . wikiDB . read ( kl ) ! = null )
result = result . substring ( 0 , p0 ) + " <a class= \" known \" href= \" Wiki.html?page= " + kl + " \" > " + kv + " </a> " + result . substring ( p1 + 2 ) ;
else
result = result . substring ( 0 , p0 ) + " <a class= \" unknown \" href= \" Wiki.html?page= " + kl + " &edit=Edit \" > " + kv + " </a> " + result . substring ( p1 + 2 ) ;
}
}
// external links
while ( ( p0 = result . indexOf ( " [ " ) ) > = 0 ) {
p1 = result . indexOf ( " ] " , p0 + 1 ) ;
if ( p1 < = p0 ) break ;
kl = result . substring ( p0 + 1 , p1 ) ;
if ( ( p = kl . indexOf ( " " ) ) > 0 ) {
kv = kl . substring ( p + 1 ) ;
kl = kl . substring ( 0 , p ) ;
}
// No text for the link? -> <a href="http://www.url.com/">http://www.url.com/</a>
else {
kv = kl ;
}
// replace incomplete URLs and make them point to http://peerip:port/...
// with this feature you can access a file at DATA/HTDOCS/share/page.html
// using the wikicode [share/page.html]
// or a file DATA/HTDOCS/www/page.html with [www/page.html]
// you are free to use other sub-paths of DATA/HTDOCS
2006-11-24 03:52:38 +01:00
if ( kl . indexOf ( " :// " ) < 1 ) {
2007-04-30 00:05:34 +02:00
kl = " http:// " + yacyCore . seedDB . mySeed . getPublicAddress ( ) . trim ( ) + " / " + kl ;
2006-04-11 00:04:52 +02:00
}
result = result . substring ( 0 , p0 ) + " <a class= \" extern \" href= \" " + kl + " \" > " + kv + " </a> " + result . substring ( p1 + 1 ) ;
}
return result ;
}
2006-04-17 21:37:09 +02:00
/** This method handles the escape tags [= =] */
//contributed by [MN]
private String escapeTag ( String result , plasmaSwitchboard switchboard ) {
int p0 = 0 ;
int p1 = 0 ;
//both [= and =] in the same line
if ( ( ( p0 = result . indexOf ( " [= " ) ) > = 0 ) & & ( ( p1 = result . indexOf ( " =] " ) ) > 0 ) & & ( ! ( preformatted ) ) ) {
if ( p0 < p1 ) {
String escapeText = result . substring ( p0 + 2 , p1 ) ;
2006-09-18 01:42:36 +02:00
escapeText = escapeText . replaceAll ( " !esc! " , " !esc!! " ) ;
2006-04-17 21:37:09 +02:00
result = transformLine ( result . substring ( 0 , p0 ) . replaceAll ( " !esc! " , " !esc!! " ) + " !esc!txt! " + result . substring ( p1 + 2 ) . replaceAll ( " !esc! " , " !esc!! " ) , switchboard ) ;
result = result . replaceAll ( " !esc!txt! " , escapeText ) ;
result = result . replaceAll ( " !esc!! " , " !esc! " ) ;
}
//handles cases like [=[= =]=] [= =] that would cause an exception otherwise
else {
escape = true ;
String temp1 = transformLine ( result . substring ( 0 , p0 - 1 ) . replaceAll ( " !tmp! " , " !tmp!! " ) + " !tmp!txt! " , switchboard ) ;
nolist = true ;
String temp2 = transformLine ( result . substring ( p0 ) , switchboard ) ;
nolist = false ;
result = temp1 . replaceAll ( " !tmp!txt! " , temp2 ) ;
result = result . replaceAll ( " !tmp!! " , " !tmp! " ) ;
escape = false ;
}
}
//start [=
else if ( ( ( p0 = result . indexOf ( " [= " ) ) > = 0 ) & & ( ! escapeSpan ) & & ( ! preformatted ) ) {
escape = true ; //prevent surplus line breaks
escaped = true ; //prevents <pre> being parsed
String bq = " " ; //gets filled with <blockquote>s as needed
String escapeText = result . substring ( p0 + 2 ) ;
2006-09-18 01:42:36 +02:00
escapeText = escapeText . replaceAll ( " !esc! " , " !esc!! " ) ;
2006-04-17 21:37:09 +02:00
//taking care of indented lines
while ( result . substring ( escindented , p0 ) . startsWith ( " : " ) ) {
escindented + + ;
bq = bq + " <blockquote> " ;
}
result = transformLine ( result . substring ( escindented , p0 ) . replaceAll ( " !esc! " , " !esc!! " ) + " !esc!txt! " , switchboard ) ;
result = bq + result . replaceAll ( " !esc!txt! " , escapeText ) ;
2006-09-18 01:42:36 +02:00
result = result . replaceAll ( " !esc!! " , " !esc! " ) ;
2006-04-17 21:37:09 +02:00
escape = false ;
escapeSpan = true ;
}
//end =]
else if ( ( ( p0 = result . indexOf ( " =] " ) ) > = 0 ) & & ( escapeSpan ) & & ( ! preformatted ) ) {
escapeSpan = false ;
2006-09-18 00:57:10 +02:00
String bq = " " ; //gets filled with </blockquote>s as needed
2006-04-17 21:37:09 +02:00
String escapeText = result . substring ( 0 , p0 ) ;
2006-09-18 01:42:36 +02:00
escapeText = escapeText . replaceAll ( " !esc! " , " !esc!! " ) ;
2006-04-17 21:37:09 +02:00
//taking care of indented lines
while ( escindented > 0 ) {
bq = bq + " </blockquote> " ;
escindented - - ;
}
result = transformLine ( " !esc!txt! " + result . substring ( p0 + 2 ) . replaceAll ( " !esc! " , " !esc!! " ) , switchboard ) ;
result = result . replaceAll ( " !esc!txt! " , escapeText ) + bq ;
2006-09-18 01:42:36 +02:00
result = result . replaceAll ( " !esc!! " , " !esc! " ) ;
2006-04-17 21:37:09 +02:00
escaped = false ;
}
//Getting rid of surplus =]
else if ( ( ( p0 = result . indexOf ( " =] " ) ) > = 0 ) & & ( ! escapeSpan ) & & ( ! preformatted ) ) {
while ( ( p0 = result . indexOf ( " =] " ) ) > = 0 ) {
result = result . substring ( 0 , p0 ) + result . substring ( p0 + 2 ) ;
}
result = transformLine ( result , switchboard ) ;
}
return result ;
}
/** This method handles the preformatted tags <pre> </pre> */
//contributed by [MN]
private String preformattedTag ( String result , plasmaSwitchboard switchboard ) {
int p0 = 0 ;
int p1 = 0 ;
//implementation very similar to escape code (see above)
//both <pre> and </pre> in the same line
if ( ( ( p0 = result . indexOf ( " <pre> " ) ) > = 0 ) & & ( ( p1 = result . indexOf ( " </pre> " ) ) > 0 ) & & ( ! ( escaped ) ) ) {
if ( p0 < p1 ) {
String preformattedText = " <pre style= \" border:dotted;border-width:thin \" > " + result . substring ( p0 + 11 , p1 ) + " </pre> " ;
2006-09-18 01:42:36 +02:00
preformattedText = preformattedText . replaceAll ( " !pre! " , " !pre!! " ) ;
2006-04-17 21:37:09 +02:00
result = transformLine ( result . substring ( 0 , p0 ) . replaceAll ( " !pre! " , " !pre!! " ) + " !pre!txt! " + result . substring ( p1 + 12 ) . replaceAll ( " !pre! " , " !pre!! " ) , switchboard ) ;
result = result . replaceAll ( " !pre!txt! " , preformattedText ) ;
result = result . replaceAll ( " !pre!! " , " !pre! " ) ;
}
//handles cases like <pre><pre> </pre></pre> <pre> </pre> that would cause an exception otherwise
else {
preformatted = true ;
String temp1 = transformLine ( result . substring ( 0 , p0 - 1 ) . replaceAll ( " !tmp! " , " !tmp!! " ) + " !tmp!txt! " , switchboard ) ;
nolist = true ;
String temp2 = transformLine ( result . substring ( p0 ) , switchboard ) ;
nolist = false ;
result = temp1 . replaceAll ( " !tmp!txt! " , temp2 ) ;
result = result . replaceAll ( " !tmp!! " , " !tmp! " ) ;
preformatted = false ;
}
}
//start <pre>
else if ( ( ( p0 = result . indexOf ( " <pre> " ) ) > = 0 ) & & ( ! preformattedSpan ) & & ( ! escaped ) ) {
preformatted = true ; //prevent surplus line breaks
String bq = " " ; //gets filled with <blockquote>s as needed
String preformattedText = " <pre style= \" border:dotted;border-width:thin \" > " + result . substring ( p0 + 11 ) ;
2006-09-18 01:42:36 +02:00
preformattedText = preformattedText . replaceAll ( " !pre! " , " !pre!! " ) ;
2006-04-17 21:37:09 +02:00
//taking care of indented lines
while ( result . substring ( preindented , p0 ) . startsWith ( " : " ) ) {
preindented + + ;
bq = bq + " <blockquote> " ;
}
result = transformLine ( result . substring ( preindented , p0 ) . replaceAll ( " !pre! " , " !pre!! " ) + " !pre!txt! " , switchboard ) ;
result = bq + result . replaceAll ( " !pre!txt! " , preformattedText ) ;
result = result . replaceAll ( " !pre!! " , " !pre! " ) ;
preformattedSpan = true ;
}
//end </pre>
else if ( ( ( p0 = result . indexOf ( " </pre> " ) ) > = 0 ) & & ( preformattedSpan ) & & ( ! escaped ) ) {
preformattedSpan = false ;
String bq = " " ; //gets filled with </blockquote>s as needed
String preformattedText = result . substring ( 0 , p0 ) + " </pre> " ;
2006-09-18 01:42:36 +02:00
preformattedText = preformattedText . replaceAll ( " !pre! " , " !pre!! " ) ;
2006-04-17 21:37:09 +02:00
//taking care of indented lines
while ( preindented > 0 ) {
bq = bq + " </blockquote> " ;
preindented - - ;
}
result = transformLine ( " !pre!txt! " + result . substring ( p0 + 12 ) . replaceAll ( " !pre! " , " !pre!! " ) , switchboard ) ;
result = result . replaceAll ( " !pre!txt! " , preformattedText ) + bq ;
2006-09-18 01:42:36 +02:00
result = result . replaceAll ( " !pre!! " , " !pre! " ) ;
2006-04-17 21:37:09 +02:00
preformatted = false ;
}
//Getting rid of surplus </pre>
else if ( ( ( p0 = result . indexOf ( " </pre> " ) ) > = 0 ) & & ( ! preformattedSpan ) & & ( ! escaped ) ) {
while ( ( p0 = result . indexOf ( " </pre> " ) ) > = 0 ) {
result = result . substring ( 0 , p0 ) + result . substring ( p0 + 12 ) ;
}
result = transformLine ( result , switchboard ) ;
}
return result ;
}
2006-02-24 02:14:38 +01:00
/ * * This method creates a directory for a wiki page .
2006-02-22 01:53:14 +01:00
* @return directory of the wiki
* /
//method contributed by [MN]
private String directory ( ) {
String directory = " " ;
String element ;
int s = 0 ;
int level = 1 ;
int level1 = 0 ;
int level2 = 0 ;
int level3 = 0 ;
2006-03-08 00:58:30 +01:00
int doubles = 0 ;
String anchorext = " " ;
2006-02-22 01:53:14 +01:00
if ( ( s = dirElements . size ( ) ) > 2 ) {
for ( int i = 0 ; i < s ; i + + ) {
element = dirElements . get ( i ) . toString ( ) ;
2006-03-08 00:58:30 +01:00
//counting double headlines
doubles = 0 ;
for ( int j = 0 ; j < i ; j + + ) {
2006-03-08 01:38:39 +01:00
if ( dirElements . get ( j ) . toString ( ) . substring ( 1 ) . replaceAll ( " " , " _ " ) . replaceAll ( " [^a-zA-Z0-9_] " , " " ) . equals ( element . substring ( 1 ) . replaceAll ( " " , " _ " ) . replaceAll ( " [^a-zA-Z0-9_] " , " " ) ) ) {
2006-03-08 00:58:30 +01:00
doubles + + ;
}
}
//if there are doubles, create anchorextension
if ( doubles > 0 ) {
anchorext = " _ " + ( doubles + 1 ) ;
}
if ( element . startsWith ( " 3 " ) ) {
2006-02-22 01:53:14 +01:00
if ( level < 3 ) {
level = 3 ;
level3 = 0 ;
}
level3 + + ;
2006-03-08 00:58:30 +01:00
String temp = element . substring ( 1 ) ;
element = level1 + " . " + level2 + " . " + level3 + " " + temp ;
2007-02-04 16:03:13 +01:00
directory = directory + " <a href= \" # " + temp . replaceAll ( " " , " _ " ) . replaceAll ( " [^a-zA-Z0-9_] " , " " ) + anchorext + " \" class= \" WikiTOC \" > " + element + " </a><br /> \ n " ;
2006-02-22 01:53:14 +01:00
}
2006-03-08 00:58:30 +01:00
else if ( element . startsWith ( " 2 " ) ) {
2006-02-22 01:53:14 +01:00
if ( level = = 1 ) {
level2 = 0 ;
level = 2 ;
}
if ( level = = 3 ) {
level = 2 ;
}
level2 + + ;
2006-03-08 00:58:30 +01:00
String temp = element . substring ( 1 ) ;
element = level1 + " . " + level2 + " " + temp ;
2007-02-04 16:03:13 +01:00
directory = directory + " <a href= \" # " + temp . replaceAll ( " " , " _ " ) . replaceAll ( " [^a-zA-Z0-9_] " , " " ) + anchorext + " \" class= \" WikiTOC \" > " + element + " </a><br /> \ n " ;
2006-02-22 01:53:14 +01:00
}
2006-03-08 00:58:30 +01:00
else if ( element . startsWith ( " 1 " ) ) {
2006-02-22 01:53:14 +01:00
if ( level > 1 ) {
level = 1 ;
level2 = 0 ;
level3 = 0 ;
}
level1 + + ;
2006-03-08 00:58:30 +01:00
String temp = element . substring ( 1 ) ;
element = level1 + " . " + temp ;
2007-02-04 16:03:13 +01:00
directory = directory + " <a href= \" # " + temp . replaceAll ( " " , " _ " ) . replaceAll ( " [^a-zA-Z0-9_] " , " " ) + anchorext + " \" class= \" WikiTOC \" > " + element + " </a><br /> \ n " ;
2006-02-22 01:53:14 +01:00
}
2006-03-08 00:58:30 +01:00
anchorext = " " ;
2006-02-22 01:53:14 +01:00
}
directory = " <table><tr><td><div class= \" WikiTOCBox \" > \ n " + directory + " </div></td></tr></table> \ n " ;
}
return directory ;
}
2006-02-24 02:14:38 +01:00
/ * * Replaces two occurences of a substring in a string by a pair of strings if
* that substring occurs twice in the string . This method is not greedy ! You ' ll
* have to run it in a loop if you want to replace all occurences of the substring .
2006-03-08 00:58:30 +01:00
* This method provides special treatment for headlines .
2006-02-21 13:24:44 +01:00
* @param input the string that something is to be replaced in
* @param pat substring to be replaced
* @param repl1 string substring gets replaced by on uneven occurences
* @param repl2 string substring gets replaced by on even occurences
* /
2006-03-08 00:58:30 +01:00
//[MN]
private String pairReplace ( String input , String pat , String repl1 , String repl2 ) {
2006-02-22 01:53:14 +01:00
String direlem = " " ; //string to keep headlines until they get added to List dirElements
2006-02-21 13:24:44 +01:00
int p0 = 0 ;
int p1 = 0 ;
int l = pat . length ( ) ;
2007-02-20 23:07:59 +01:00
//replace pattern if a pair of the pattern can be found in the line
if ( ( ( p0 = input . indexOf ( pat ) ) > = 0 ) & & ( ( p1 = input . indexOf ( pat , p0 + l ) ) > = 0 ) ) {
//extra treatment for headlines
if ( ( pat . equals ( " ==== " ) ) | | ( pat . equals ( " === " ) ) | | ( pat . equals ( " == " ) ) ) {
//add anchor and create headline
direlem = input . substring ( p0 + l , p1 ) ;
//counting double headlines
int doubles = 0 ;
for ( int i = 0 ; i < headlines ; i + + ) {
if ( dirElements . get ( i ) . toString ( ) . substring ( 1 ) . equals ( direlem ) ) {
doubles + + ;
2006-03-08 00:58:30 +01:00
}
2006-02-22 01:53:14 +01:00
}
2007-02-20 23:07:59 +01:00
String anchor = direlem . replaceAll ( " " , " _ " ) . replaceAll ( " [^a-zA-Z0-9_] " , " " ) ; //replace blanks with underscores and delete everything thats not a regular character, a number or _
//if there are doubles, add underscore and number of doubles plus one
if ( doubles > 0 ) {
anchor = anchor + " _ " + ( doubles + 1 ) ;
2006-02-22 01:53:14 +01:00
}
2007-02-20 23:07:59 +01:00
input = input . substring ( 0 , p0 ) + " <a name= \" " + anchor + " \" ></a> " + repl1 +
direlem + repl2 + input . substring ( p1 + l ) ;
//add headlines to list of headlines (so TOC can be created)
if ( pat . equals ( " ==== " ) ) dirElements . add ( " 3 " + direlem ) ;
else if ( pat . equals ( " === " ) ) dirElements . add ( " 2 " + direlem ) ;
else if ( pat . equals ( " == " ) ) dirElements . add ( " 1 " + direlem ) ;
headlines + + ;
}
else {
input = input . substring ( 0 , p0 ) + repl1 +
( direlem = input . substring ( p0 + l , p1 ) ) + repl2 +
input . substring ( p1 + l ) ;
2006-02-21 13:24:44 +01:00
}
2006-02-22 01:53:14 +01:00
}
2007-02-20 23:07:59 +01:00
//recursion if a pair of the pattern can still be found in the line
if ( ( ( p0 = input . indexOf ( pat ) ) > = 0 ) & & ( input . indexOf ( pat , p0 + l ) > = 0 ) ) {
input = pairReplace ( input , pat , repl1 , repl2 ) ;
}
2006-02-21 13:24:44 +01:00
return input ;
}
2006-02-22 01:53:14 +01:00
2006-01-16 22:15:06 +01:00
/ * * Replaces wiki tags with HTML tags .
* @param result a line of text
* @param switchboard
2006-01-23 14:59:40 +01:00
* @return the line of text with HTML tags instead of wiki tags
2006-01-16 22:15:06 +01:00
* /
2005-09-05 12:15:59 +02:00
public String transformLine ( String result , plasmaSwitchboard switchboard ) {
2006-04-17 21:37:09 +02:00
//If HTML has not bee replaced yet (can happen if method gets called in recursion), replace now!
2006-09-18 03:19:54 +02:00
if ( ! replacedHTML | | preformattedSpan ) {
2007-05-20 15:29:12 +02:00
result = htmlTools . replaceXMLEntities ( result ) ;
2006-01-23 14:59:40 +01:00
replacedHTML = true ;
2006-01-18 02:48:34 +01:00
}
2006-04-17 21:37:09 +02:00
//If special characters have not bee replaced yet, replace now!
2006-09-18 03:19:54 +02:00
if ( ! replacedCharacters | | preformattedSpan ) {
2007-05-20 15:29:12 +02:00
result = htmlTools . replaceHTMLEntities ( result ) ;
2006-02-19 19:54:38 +01:00
replacedCharacters = true ;
}
2006-01-16 22:15:06 +01:00
2006-04-17 21:37:09 +02:00
//check if line contains escape symbols([= =]) or if we are in an escape sequence already.
if ( ( result . indexOf ( " [= " ) > = 0 ) | | ( result . indexOf ( " =] " ) > = 0 ) | | ( escapeSpan ) ) {
result = escapeTag ( result , switchboard ) ;
}
2006-09-18 03:19:54 +02:00
2006-04-17 21:37:09 +02:00
//check if line contains preformatted symbols or if we are in a preformatted sequence already.
2006-09-18 03:24:26 +02:00
else if ( ( result . indexOf ( " <pre> " ) > = 0 ) | | ( result . indexOf ( " </pre> " ) > = 0 ) | | ( preformattedSpan ) ) {
2006-04-17 21:37:09 +02:00
result = preformattedTag ( result , switchboard ) ;
}
2006-09-18 03:19:54 +02:00
2006-04-17 21:37:09 +02:00
//transform page as usual
else {
2006-01-16 22:15:06 +01:00
2006-01-23 14:59:40 +01:00
//tables first -> wiki-tags in cells can be treated after that
2006-04-11 00:04:52 +02:00
result = processTable ( result , switchboard ) ;
2006-01-23 14:59:40 +01:00
2005-08-31 16:43:55 +02:00
// format lines
2007-02-04 16:03:13 +01:00
if ( result . startsWith ( " " ) ) result = " <tt> " + result . substring ( 1 ) + " </tt> " ;
if ( result . startsWith ( " ---- " ) ) result = " <hr /> " ;
2006-01-16 22:15:06 +01:00
// citings contributed by [MN]
if ( result . startsWith ( " : " ) ) {
String head = " " ;
String tail = " " ;
while ( result . startsWith ( " : " ) ) {
head = head + " <blockquote> " ;
tail = tail + " </blockquote> " ;
result = result . substring ( 1 ) ;
}
2006-01-22 15:20:38 +01:00
result = head + result + tail ;
}
// end contrib [MN]
2006-01-16 22:15:06 +01:00
2006-01-22 15:20:38 +01:00
// format headers
2006-02-21 13:24:44 +01:00
result = pairReplace ( result , " ==== " , " <h4> " , " </h4> " ) ;
result = pairReplace ( result , " === " , " <h3> " , " </h3> " ) ;
result = pairReplace ( result , " == " , " <h2> " , " </h2> " ) ;
2006-01-16 22:15:06 +01:00
2006-02-21 13:24:44 +01:00
result = pairReplace ( result , " ''''' " , " <b><i> " , " </i></b> " ) ;
result = pairReplace ( result , " ''' " , " <b> " , " </b> " ) ;
result = pairReplace ( result , " '' " , " <i> " , " </i> " ) ;
2006-01-16 22:15:06 +01:00
2006-04-11 00:04:52 +02:00
result = unorderedList ( result ) ;
2006-02-22 01:53:14 +01:00
result = orderedList ( result ) ;
2006-04-11 00:04:52 +02:00
result = definitionList ( result ) ;
2006-01-22 15:20:38 +01:00
2006-04-11 00:04:52 +02:00
result = linksAndImages ( result , switchboard ) ;
2005-08-06 19:03:12 +02:00
2006-01-16 22:15:06 +01:00
}
2006-04-17 21:37:09 +02:00
if ( ! preformatted ) replacedHTML = false ;
2006-01-23 14:59:40 +01:00
replacedCharacters = false ;
if ( ( result . endsWith ( " </li> " ) ) | | ( defList ) | | ( escape ) | | ( preformatted ) | | ( table ) | | ( cellprocessing ) ) return result ;
2007-02-04 16:03:13 +01:00
return result + " <br /> " ;
2005-08-06 19:03:12 +02:00
}
}