get_clone($converter);
return $clone->convert($string, ($page != '') ? $page : $vars['page']);
}
// Converters of inline element
class InlineConverter
{
var $converters; // as array()
var $pattern;
var $pos;
var $result;
function get_clone($obj) {
static $clone_func;
if (! isset($clone_func)) {
if (version_compare(PHP_VERSION, '5.0.0', '<')) {
$clone_func = create_function('$a', 'return $a;');
} else {
$clone_func = create_function('$a', 'return clone $a;');
}
}
return $clone_func($obj);
}
function __clone() {
$converters = array();
foreach ($this->converters as $key=>$converter) {
$converters[$key] = $this->get_clone($converter);
}
$this->converters = $converters;
}
function InlineConverter($converters = NULL, $excludes = NULL)
{
if ($converters === NULL) {
$converters = array(
'plugin', // Inline plugins
'note', // Footnotes
'url', // URLs
'url_interwiki', // URLs (interwiki definition)
'mailto', // mailto: URL schemes
'interwikiname', // InterWikiNames
'autolink', // AutoLinks
'bracketname', // BracketNames
'wikiname', // WikiNames
'autolink_a', // AutoLinks(alphabet)
);
}
if ($excludes !== NULL)
$converters = array_diff($converters, $excludes);
$this->converters = $patterns = array();
$start = 1;
foreach ($converters as $name) {
$classname = 'Link_' . $name;
$converter = new $classname($start);
$pattern = $converter->get_pattern();
if ($pattern === FALSE) continue;
$patterns[] = '(' . "\n" . $pattern . "\n" . ')';
$this->converters[$start] = $converter;
$start += $converter->get_count();
++$start;
}
$this->pattern = join('|', $patterns);
}
function convert($string, $page)
{
$this->page = $page;
$this->result = array();
$string = preg_replace_callback('/' . $this->pattern . '/x',
array(& $this, 'replace'), $string);
$arr = explode("\x08", make_line_rules(htmlspecialchars($string)));
$retval = '';
while (! empty($arr)) {
$retval .= array_shift($arr) . array_shift($this->result);
}
return $retval;
}
function replace($arr)
{
$obj = $this->get_converter($arr);
$this->result[] = ($obj !== NULL && $obj->set($arr, $this->page) !== FALSE) ?
$obj->toString() : make_line_rules(htmlspecialchars($arr[0]));
return "\x08"; // Add a mark into latest processed part
}
function get_objects($string, $page)
{
$matches = $arr = array();
preg_match_all('/' . $this->pattern . '/x', $string, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$obj = $this->get_converter($match);
if ($obj->set($match, $page) !== FALSE) {
$arr[] = $this->get_clone($obj);
if ($obj->body != '')
$arr = array_merge($arr, $this->get_objects($obj->body, $page));
}
}
return $arr;
}
function & get_converter(& $arr)
{
foreach (array_keys($this->converters) as $start) {
if ($arr[$start] == $arr[0])
return $this->converters[$start];
}
return NULL;
}
}
// Base class of inline elements
class Link
{
var $start; // Origin number of parentheses (0 origin)
var $text; // Matched string
var $type;
var $page;
var $name;
var $body;
var $alias;
// Constructor
function Link($start)
{
$this->start = $start;
}
// Return a regex pattern to match
function get_pattern() {}
// Return number of parentheses (except (?:...) )
function get_count() {}
// Set pattern that matches
function set($arr, $page) {}
function toString() {}
// Private: Get needed parts from a matched array()
function splice($arr) {
$count = $this->get_count() + 1;
$arr = array_pad(array_splice($arr, $this->start, $count), $count, '');
$this->text = $arr[0];
return $arr;
}
// Set basic parameters
function setParam($page, $name, $body, $type = '', $alias = '')
{
static $converter = NULL;
$this->page = $page;
$this->name = $name;
$this->body = $body;
$this->type = $type;
if (is_url($alias) && preg_match('/\.(gif|png|jpe?g)$/i', $alias)) {
$alias = htmlspecialchars($alias);
$alias = '';
} else if ($alias != '') {
if ($converter === NULL)
$converter = new InlineConverter(array('plugin'));
$alias = make_line_rules($converter->convert($alias, $page));
// BugTrack/669: A hack removing anchor tags added by AutoLink
$alias = preg_replace('#?a[^>]*>#i', '', $alias);
}
$this->alias = $alias;
return TRUE;
}
}
// Inline plugins
class Link_plugin extends Link
{
var $pattern;
var $plain,$param;
function Link_plugin($start)
{
parent::Link($start);
}
function get_pattern()
{
$this->pattern = <<pattern}
(?:
\{
((?:(?R)|(?!};).)*) # (4) body
\}
)?
;
EOD;
}
function get_count()
{
return 4;
}
function set($arr, $page)
{
list($all, $this->plain, $name, $this->param, $body) = $this->splice($arr);
// Re-get true plugin name and patameters (for PHP 4.1.2)
$matches = array();
if (preg_match('/^' . $this->pattern . '/x', $all, $matches)
&& $matches[1] != $this->plain)
list(, $this->plain, $name, $this->param) = $matches;
return parent::setParam($page, $name, $body, 'plugin');
}
function toString()
{
$body = ($this->body == '') ? '' : make_link($this->body);
$str = FALSE;
// Try to call the plugin
if (exist_plugin_inline($this->name))
$str = do_plugin_inline($this->name, $this->param, $body);
if ($str !== FALSE) {
return $str; // Succeed
} else {
// No such plugin, or Failed
$body = (($body == '') ? '' : '{' . $body . '}') . ';';
return make_line_rules(htmlspecialchars('&' . $this->plain) . $body);
}
}
}
// Footnotes
class Link_note extends Link
{
function Link_note($start)
{
parent::Link($start);
}
function get_pattern()
{
return <<splice($arr);
$id = ++$note_id;
$note = make_link($body);
$page = isset($vars['page']) ? htmlspecialchars($vars['page']) : '';
// Footnote
$foot_explain[$id] = <<