around the generated
// line. this is useful for making html of headlines and titles. as it is not too
// handy to have inside your
//
function any_wiki_tohtml ( $s, $options = array() )
{
list($tk, $tk_s) = wiki_tokenizer($s, $options);
$block = array(); // lines for current block
$line = array(); // stacked tokens for current line
$line_s = array(); // stacked texts for current line
$html = ''; // generated html
$i = 0;
$toc = false; // is there a toc or not?
do
{
$tok = $tk[$i];
switch ($tok)
{
case 'br':
$line[] = 'html';
$line_s[] = " \n";
break;
case 'html':
list($_html, $block) = _wiki_reduce_line($block, $line, $line_s);
$html .= $_html . _wiki_reduce_block($block);
if (wiki_allow_html())
{
$html .= "\n" . $tk_s[$i] . "\n";
}
else
{
$html .= ' ' . nl2br(strip_tags($tk_s[$i])) . '
';
}
$line = array();
$line_s = array();
$block = array();
break;
case 'code':
list($_html, $block) = _wiki_reduce_line($block, $line, $line_s);
$html .= $_html . _wiki_reduce_block($block);
$html .= "\n\n" . htmlspecialchars($tk_s[$i]) . " \n";
$line = array();
$line_s = array();
$block = array();
break;
case 'p':
case 'end':
list($_html, $block) = _wiki_reduce_line($block, $line, $line_s);
$html .= $_html . "\n" . _wiki_reduce_block($block);
$line = array();
$line_s = array();
$block = array();
break;
case 'newline':
list($_html, $block) = _wiki_reduce_line($block, $line, $line_s);
$html .= $_html;
$line = array();
$line_s = array();
break;
case 'toc':
$html .= '';
$line = array();
$line_s = array();
$toc = true;
break;
case 'comment':
if ($i == 0)
{
// Comment at the start of a line or in a block
$html .= '';
}
else
{
// Comment in a line
list($line, $line_s) = _wiki_shift_reduce($line, $line_s, $tok, $tk_s[$i]);
}
break;
case 'word':
case ' ':
default:
list($line, $line_s) = _wiki_shift_reduce($line, $line_s, $tok, $tk_s[$i]);
break;
}
$i++;
}
while ($tok != 'end');
// Merge 's over more than one line
$html = preg_replace("|
\n|", " \n", $html);
//PH: \-newline to "skip" newlining.
$html = preg_replace("|\\\\ |", "", $html);
if (!empty($options['target']) && $options['target'] == 'line')
{
// Strip the
tags... the user wants a single line.
$html = trim(preg_replace('||', ' ', $html));
}
else if ($toc)
{
$html = _wiki_toc($html);
}
return trim($html);
}
// Function: wiki_allow_html
// Access: EXTERNAL
// Parameters: -
// Returns: false no html allowed
// true html allowed
// Description: Check if the ACL allows html entry
//
function wiki_allow_html ( )
{
$allow = false;
if (isset($GLOBALS['any_acl']))
{
$allow = $GLOBALS['any_acl']->allowHtml();
}
return $allow;
}
// Function: wiki_filter_uri
// Access: EXTERNAL
// Parameters: $uri uri to be checked
// Returns: false when uri not allowed
// uri when allowed
// Description: Check if the ACL allows the given uri
//
function wiki_filter_uri ( $uri )
{
if (isset($GLOBALS['any_acl']))
{
$uri = $GLOBALS['any_acl']->filterUri($uri);
}
return $uri;
}
// Function: wiki_filter_attrs
// Access: EXTERNAL
// Parameters: $uri uri to be checked
// Returns: false when uri not allowed
// uri when allowed
// Description: Check if the ACL allows the given attrs.
// This function has a short whitelist of allowed attributes.
//
function wiki_filter_attrs ( $attr )
{
$as = array();
foreach ($attr as $a => $v)
{
switch ($a)
{
case 'id':
case 'name':
case 'align':
case 'valign':
case 'title':
case 'width':
case 'height':
case 'rel':
case 'alt':
case 'class':
case 'link':
case 'caption':
$as[$a] = $v;
break;
default:
if ( isset($GLOBALS['any_acl'])
&& $GLOBALS['any_acl']->allowHtml())
{
$as[$a] = $v;
}
break;
}
}
return $as;
}
// Function: _wiki_reduce_block
// Access: INTERNAL
// Parameters: $block the tokens in the block
// Returns: html fragment
// Description: Force the complete reduction of a block to html
//
function _wiki_reduce_block ( $block )
{
if (count($block) > 0)
{
list($html, $block) = _wiki_shift_reduce_block($block, array('end'), array(''));
}
else
{
$html = '';
}
return $html;
}
// Function: _wiki_shift_reduce_block
// Access: INTERNAL
// Parameters: $block the tokens in the block
// $line line tokens
// $line_s line strings
// Returns: array(html-fragment, block)
// Description: (Partially) reduces the block after encountering the given line
//
// Checks for:
// - enumerated lists
// - tables
// - blockquote
//
//
// Each block entry is as follows:
//
// ( class, depth, class-parms, line_tokens, line_strings )
//
// Where class is one of:
//
// table, ul, ol, blockquote, dl
//
// Depth is valid for:
//
// ul, ol, blockqoute
//
function _wiki_shift_reduce_block ( $block, $line, $line_s )
{
if (!empty($line))
{
if ($line[0] == '=' && @$line[1] == ' ')
{
$html = _wiki_reduce_block($block);
list($line, $line_s) = _wiki_merge($line, $line_s, 2, false, true);
$html .= "\n
" . $line_s[2] . "
\n";
return array($html, array());
}
}
$block_line = _wiki_block_line($line, $line_s);
if ($block_line[0] == 'p' || $block_line[0] == 'end')
{
$html = _wiki_reduce_block_lines($block);
if ($block_line[0] == 'p')
{
list($line, $line_s) = _wiki_merge($line, $line_s, 0, false, true);
if (!empty($line_s[0]))
{
$html .= "" . $line_s[0] . "
\n";
}
}
$block = array();
}
else
{
$block[] = $block_line;
$html = '';
}
return array($html, $block);
}
// Function: _wiki_reduce_block_lines
// Access: INTERNAL
// Parameters: $block a complete block
// Returns: html
// Description: recursively reduces a block to html
// all line level reductions have been done
// what we get is a block of lines, each preparsed.
//
function _wiki_reduce_block_lines ( &$block )
{
if (empty($block))
{
return '';
}
$len = count($block);
$class = $block[0][0];
$depth = $block[0][1];
// Collect all lines with the same class and depth
$sub_block = array();
$sub_block[] = array_shift($block);
if ($class == 'ol')
{
$alt_class = 'ul';
}
else if ($class == 'ul')
{
$alt_class = 'ol';
}
else
{
$alt_class = false;
}
while ( !empty($block)
&& $block[0][1] >= $depth
&& ( $block[0][0] == $class
|| $block[0][0] == $alt_class))
{
if ($block[0][1] > $depth || $block[0][0] != $class)
{
// this is a nested block of the same kind
// reduce this one separately and remember the html in the previous block line
$html = _wiki_reduce_block_lines($block);
if (!empty($html))
{
$sub_block[count($sub_block)-1][5] = $html;
}
}
else
{
$sub_block[] = array_shift($block);
}
}
// special handling for a table
$td = 0;
if ($class == 'table')
{
foreach ($sub_block as $sub)
{
$td = max($td, $sub[2]);
}
}
// generate the html for the captured block
$html = "<$class>\n";
$nr = 0;
foreach ($sub_block as $sub)
{
$pars = $sub[2];
$line = $sub[3];
$line_s = $sub[4];
$nested = isset($sub[5]) ? $sub[5] : '';
$nr++;
switch ($class)
{
case 'ol':
case 'ul':
list($line, $line_s) = _wiki_merge($line, $line_s, 2, false, true);
$html .= '' . trim($line_s[2]) . $nested . " \n";
break;
case 'table':
// Generate a row
$html .= _wiki_table_row($td, $line, $line_s, $pars);
break;
case 'blockquote':
if ($nr == 1)
{
$html .= '';
}
list($line, $line_s) = _wiki_merge($line, $line_s, 2, false, true);
$html .= $line_s[2] . $nested;
if ($nr != count($sub_block))
{
$html .= ' ';
}
else
{
$html .= "
\n";
}
break;
case 'dl':
// $pars is the offset of the first ' ' of the ' : ' separating the dt from the dd
list($line, $line_s) = _wiki_merge($line, $line_s, $pars+3, false, true);
// the reduced html of the dd
$dd = array_pop($line_s);
array_pop($line);
// op the ' ' ':' ' ';
array_pop($line_s);
array_pop($line);
array_pop($line_s);
array_pop($line);
array_pop($line_s);
array_pop($line);
// Reduce the dt part
list($line, $line_s) = _wiki_merge($line, $line_s, 2, false, true);
$dt = array_pop($line_s);
$html .= " $dt \n $dd \n";
break;
}
}
$html .= "\n\n";
return $html;
}
// Function: _wiki_table_row
// Access: INTERNAL
// Parameters: $table_cols nr of tds
// $line tokens in line
// $line_s text of tokens
// Returns: html for row
// Description: generates the html for a row
//
function _wiki_table_row ( $table_cols, $line, $line_s )
{
$html = "";
$len = count($line);
$td = array();
$start = 1;
$colspan= 1;
// Split the line in tds
for ($i=1;$i<$len;$i++)
{
if ($line[$i] == '||')
{
if ($line[$i-1] == '||' && $i+1 < $len)
{
$colspan++;
$start++;
}
else
{
// A td from $start to $i-1
if ($i - $start > 0)
{
$td[] = array( array_slice($line, $start, $i - $start),
array_slice($line_s, $start, $i - $start),
$colspan);
}
else
{
$td[] = array(false, false, $colspan);
}
$start = $i+1;
$colspan = 1;
}
}
}
// Generate the html per td
foreach ($td as $t)
{
$line = $t[0];
$line_s = $t[1];
if ($t[2] > 1)
{
$colspan = ' colspan="' . $t[2] . '" ';
}
else
{
$colspan = '';
}
if (!empty($line))
{
$end = "";
switch ($line[0])
{
case '>':
$html .= "\n ";
$start = 1;
break;
case '<':
$html .= "\n ";
$start = 1;
break;
case '=':
$html .= "\n ";
$start = 1;
break;
case '~':
$html .= "\n ";
$end = "";
$start = 1;
break;
default:
$html .= "\n ";
$start = 0;
break;
}
list($line, $line_s) = _wiki_merge($line, $line_s, $start, false, true);
$html .= trim($line_s[$start]) . $end;
}
else
{
$html .= "\n ";
}
}
$html .= "\n\n";
return $html;
}
// Function: _wiki_block_line
// Access: INTERNAL
// Parameters: $line line tokens
// $line_s line strings
// Returns: a block line entry
// Description: checks the line to see what kind of block line the line is
//
function _wiki_block_line ( $line, $line_s )
{
$len = count($line);
if ($len >= 2)
{
// : term : definition
if ( $line[0] == ':'
&& $line[1] == ' ')
{
// Try to find (' ', ':' , ' ');
$i = 2;
$offs = false;
while ($i < $len - 2 && $offs === false)
{
if ($line[$i] == ':' && $line[$i-1] == ' ' && $line[$i+1] == ' ')
{
$offs = $i-1;
}
$i++;
}
if ($offs !== false)
{
return array('dl', 0, $offs, $line, $line_s);
}
}
// || td || .. ||
if ($line[0] == '||' && $line[$len-1] == '||')
{
// count the number of cols
$cols = 0;
for ($i = 0; $i<$len; $i++)
{
if ($line[$i] == '||')
{
$cols++;
}
}
return array('table', 0, $cols-1, $line, $line_s);
}
// > block quoted text
if ($line[0] == '>' && $line[1] == ' ')
{
return array('blockquote', strlen($line_s[0]), 0, $line, $line_s);
}
// * unordered list
if ($line[0] == '*' && $line[1] == ' ')
{
return array('ul', 0, 0, $line, $line_s);
}
if ($line[0] == ' ' && $line[1] == '*' && $line[2] == ' ')
{
return array('ul', strlen($line_s[0]), 0, $line, $line_s);
}
// # ordered list
if ($line[0] == '#' && $line[1] == ' ')
{
return array('ol', 0, 0, $line, $line_s);
}
if ($line[0] == ' ' && $line[1] == '#' && $len > 2 && $line[2] == ' ')
{
return array('ol', strlen($line_s[0]), 0, $line, $line_s);
}
}
// Just another part of a paragraph
if ($len > 0 && $line[0] == 'end')
{
return array('end', 0, 0, $line, $line_s);
}
else
{
return array('p', 0, 0, $line, $line_s);
}
}
// Function: _wiki_reduce_line
// Access: INTERNAL
// Parameters: $block the tokens in the block
// $line the line stack
// $line_s line texts
// Returns: html fragment
// modified block
// Description: Reduce the current line and append it to the current block.
// The reduction of a single line checks for:
// - non reduced :// or mailto: urls
// - non reduced wiki words
// - headers
// - blockquote levels
// - enumerated lists
// - table rows
//
function _wiki_reduce_line ( $block, $line, $line_s )
{
// wiki words
list($line, $line_s) = _wiki_replace_wikiwords($line, $line_s);
if (count($line) == 1 && $line[0] == '-' && (strlen($line_s[0]) == 4 || strlen($line_s[0]) == 3))
{
// horiz \n----\n
$html = _wiki_reduce_block($block);
return array($html . "\n \n", array());
}
if (count($line) > 2 && $line[0] == '+' && $line[1] == ' ' && strlen($line_s[0]) <= 6)
{
// \n+++++ headline 1..6
list($line, $line_s) = _wiki_merge($line, $line_s, 2, false, true);
$html = _wiki_reduce_block($block);
$level = strlen($line_s[0]);
$html .= "\n".trim($line_s[2])." \n";
return array($html, array());
}
return _wiki_shift_reduce_block($block, $line, $line_s);
}
// Function: _wiki_shift_reduce
// Access: INTERNAL
// Parameters: $line
// $line_s
// $tok
// $tok_s
// Returns: the new line state
// Description: Shifts the given token on the stack and reduces the stack
// returning a new line state.
//
function _wiki_shift_reduce ( $line, $line_s, $tok, $tok_s )
{
switch ($tok)
{
case "u":
// "__"
$offs = _wiki_offset($line, _wiki_inline_start($tok));
if ($offs !== false)
{
list($line, $line_s) = _wiki_merge($line, $line_s, $offs+1, false, true);
array_pop($line);
$text = array_pop($line_s);
array_pop($line);
array_pop($line_s);
$line[] = 'html';
$line_s[] = _wiki_inline_html($tok, $text);
}
else
{
$line[] = $tok;
$line_s[] = $tok_s;
}
break;
case "em":
case "strong":
case "sup":
case '}}':
// "//" or "**" or "^^" or {{ }}
$offs = _wiki_offset($line, _wiki_inline_start($tok));
if ($offs !== false)
{
list($line, $line_s) = _wiki_merge($line, $line_s, $offs+1, false, true);
array_pop($line);
$text = array_pop($line_s);
array_pop($line);
array_pop($line_s);
$line[] = 'html';
$line_s[] = _wiki_inline_html($tok, $text);
}
else
{
$line[] = $tok;
$line_s[] = $tok_s;
}
break;
case '@@':
// @@---minus+++revision@@
$offs = _wiki_offset($line, '@@');
if ($offs !== false)
{
list($line, $line_s) = _wiki_reduce_revise($line, $line_s, $offs);
}
else
{
$line[] = $tok;
$line_s[] = $tok_s;
}
break;
case '##':
// ##color|text##
$offs = _wiki_offset($line, '##');
if ($offs !== false)
{
list($line, $line_s) = _wiki_reduce_colortext($line, $line_s, $offs);
}
else
{
$line[] = $tok;
$line_s[] = $tok_s;
}
break;
case ']':
// [uri descr]
$offs = _wiki_offset($line, '[');
if ($offs !== false)
{
list($line, $line_s) = _wiki_reduce_link($line, $line_s, $offs);
}
else
{
$line[] = $tok;
$line_s[] = $tok_s;
}
break;
case ']]':
// [[# anchor-name]]
// [[image image-pars]]
// [[image:image-pars]]
$offs = _wiki_offset($line, '[[');
if ($offs !== false && $line[$offs+1] == '#')
{
list($line, $line_s) = _wiki_reduce_anchor($line, $line_s, $offs);
}
else if ($offs !== false && $line[$offs+1] == 'word' && $line_s[$offs+1] == 'image')
{
list($line, $line_s) = _wiki_reduce_image($line, $line_s, $offs);
}
else #MediaWiki-style link
{
list($line, $line_s) = _wiki_reduce_freelink($line, $line_s, $offs);
}
# else
# {
# $line[] = $tok;
# $line_s[] = $tok_s;
# }
break;
case '))':
// ((name|descr))
$offs = _wiki_offset($line, '((');
if ($offs !== false)
{
list($line, $line_s) = _wiki_reduce_freelink($line, $line_s, $offs);
}
else
{
$line[] = $tok;
$line_s[] = $tok_s;
}
break;
case 'comment':
$line[] = 'html';
$line_s[] = '';
break;
default:
$line[] = $tok;
$line_s[] = $tok_s;
break;
}
return array($line, $line_s);
}
// helper for @@--- +++ @@ revision patterns
function _wiki_reduce_revise ( $line, $line_s, $offs )
{
// @@---minus+++revision@@
$len = count($line_s);
$offs = _wiki_offset($line, '@@');
if ( $offs !== false
&& $offs < $len-1
&& ($line_s[$offs+1] == '---' || $line_s[$offs+1] == '+++'))
{
if ($line_s[$offs+1] === '---')
{
$offs_del = $offs+1;
$offs_ins = $offs+2;
// Try to find the '+++'
while ($offs_ins < $len && $line_s[$offs_ins] != '+++')
{
$offs_ins++;
}
}
else
{
$offs_del = false;
$offs_ins = $offs+1;
}
if ($offs_ins < $len)
{
list($line, $line_s) = _wiki_merge($line, $line_s, $offs_ins+1, false, true);
array_pop($line);
$ins = array_pop($line_s);
// Remove the '+++'
array_pop($line);
array_pop($line_s);
}
else
{
$ins = false;
}
if ($offs_del !== false)
{
list($line, $line_s) = _wiki_merge($line, $line_s, $offs_del+1, false, true);
array_pop($line);
$del = array_pop($line_s);
// Remove the '---'
array_pop($line);
array_pop($line_s);
}
else
{
$del = false;
}
// Remove the '@@';
array_pop($line);
array_pop($line_s);
if (!empty($del))
{
$line[] = 'html';
$line_s[] = _wiki_inline_html('del', $del);
}
if (!empty($ins))
{
$line[] = 'html';
$line_s[] = _wiki_inline_html('ins', $ins);
}
}
return array($line, $line_s);
}
// helper for [[# anchor-name]]
function _wiki_reduce_anchor ( $line, $line_s, $offs )
{
// fetch the anchor name
list($line, $line_s) = _wiki_merge($line, $line_s, $offs+2, -1, false, false);
// pop the name
array_pop($line);
$name = array_pop($line_s);
// pop the #
array_pop($line);
array_pop($line_s);
$line[$offs] = 'html';
$line_s[$offs] = ' ';
return array($line, $line_s);
}
// helper for [[image path/to/image image-pars]]
function _wiki_reduce_image ( $line, $line_s, $offs )
{
// fetch the complete text
list($line, $line_s) = _wiki_merge($line, $line_s, $offs+2, -1, false, false);
// pop the image path and parameters
array_pop($line);
$text = trim(array_pop($line_s));
// pop 'image'
array_pop($line);
array_pop($line_s);
//PH: "image:..." syntax
if ($text[0] == ':') {
$text = substr($text,1);
}
// Extract the interesting parts from the image description
$pos = strpos($text, ' ');
if ($pos === false)
{
$src = $text;
$attr = array();
}
else
{
$src = substr($text, 0, $pos);
$attr = _wiki_get_attrs(substr($text, $pos+1));
}
// Remove double quotes around the uri, some people do type them...
if (strlen($src) >= 2 && $src{0} == '"' && $src{strlen($src)-1} == '"')
{
$src = substr($src, 1, -1);
}
// We have to postpone the image generation till 'showtime' because an image
// typically refers to data that is dynamic. So we just pack the image data
// in a special tag and do an expand in smarty.
if ( ( strpos($src, '://') !== false
|| strpos($src, '/') !== false
|| preg_match('/^[a-zA-Z0-9_]+\.[a-z]{3}$/', $src))
&& ( empty($attr['link'])
|| ( strpos($attr['link'], '://') !== false
&& strncasecmp($attr['link'], 'popup:', 6) != 0)))
{
if (!empty($attr['link']))
{
// Remove double quotes around the uri, some people do type them...
$link = $attr['link'];
if (strlen($link) >= 2 && $link{0} == '"' && $link{strlen($link)-1} == '"')
{
$link = substr($link, 1, -1);
}
$pre = '';
$post = ' ';
unset($attr['link']);
}
else
{
$pre = '';
$post = '';
}
$html = $pre . ' $value)
{
$html .= htmlspecialchars($label) . '="' . htmlspecialchars($value) .'" ';
}
$html .= '/>' . $post;
}
else
{
// Pack the attributes so that we can easily expand them again.
$html = '';
}
$line[$offs] = 'html';
$line_s[$offs] = $html;
return array($line, $line_s);
}
// helper for ##color| ## colored text
function _wiki_reduce_colortext ( $line, $line_s, $offs )
{
// Check for the optional description
$space = _wiki_after($line, '|', $offs);
if ($space != false)
{
// Fetch description of link
list($line, $line_s) = _wiki_merge($line, $line_s, $space+1, -1, true);
array_pop($line);
$text = trim(array_pop($line_s));
array_pop($line);
array_pop($line_s);
}
else
{
$text = false;
}
// Merge all tokens for the color
list($line, $line_s) = _wiki_merge($line, $line_s, $offs+1, -1, false);
array_pop($line);
$color = trim(array_pop($line_s));
if ( (strlen($color) == 3 || strlen($color) === 6)
&& preg_match('/^[0-9a-fA-F]+$/', $color))
{
$color = '#' . $color;
}
// pop the opening '##'
array_pop($line);
array_pop($line_s);
// Create the span
if (!empty($text))
{
$line[] = 'html';
$line_s[] = "$text ";
}
return array($line, $line_s);
}
// helper for [uri descr]
function _wiki_reduce_link ( $line, $line_s, $offs )
{
// Keep a copy of line/line_s in case we don't find an uri
$line0 = $line;
$line_s0 = $line_s;
// Check for the optional description
$space = _wiki_after($line, ' ', $offs);
if ($space != false)
{
// Fetch description of link
list($line, $line_s) = _wiki_merge($line, $line_s, $space, -1, false);
array_pop($line);
$descr = trim(array_pop($line_s));
// Try to fetch any optional attributes
list($descr, $attrs) = _wiki_split_descr_attrs($descr);
}
else
{
$descr = false;
$attrs = false;
}
// Merge all tokens for the uri
list($line, $line_s) = _wiki_merge($line, $line_s, $offs+1, -1, false, false);
array_pop($line);
$uri = array_pop($line_s);
// only accept this construct when the uri looks like an uri
$colon = strpos($uri, ':');
$dot = strpos($uri, '.');
$last = strlen($uri) - 1;
if ( strpos($uri, '/') !== false
|| strpos($uri, '#') !== false
|| ($dot !== false && $dot < $last)
|| ($colon > 0 && $colon < $last))
{
// pop the opening '['
array_pop($line);
array_pop($line_s);
// Create the link
if (empty($descr))
{
// Footnote
$html = '' . _wiki_make_link($uri, '*', '', $attrs) .' ';
}
else
{
// Described link
$html = _wiki_make_link($uri, $descr, '', $attrs);
}
$line[] = 'html';
$line_s[] = $html;
}
else
{
// No uri found, do not reduce the found [uri descr] construct
$line = $line0;
$line_s = $line_s0;
$line[] = ']';
$line_s[] = ']';
}
return array($line, $line_s);
}
// helper for ((uri|descr))
function _wiki_reduce_freelink ( $line, $line_s, $offs )
{
// Check for the optional description
$anchor = false;
$pipe = _wiki_after($line, '|', $offs);
if ($pipe != false)
{
$hash = _wiki_after($line, '#', $pipe, true);
if ($hash !== false)
{
list($line, $line_s) = _wiki_merge($line, $line_s, $hash+1, -1, false, false);
array_pop($line);
$anchor = '#' . trim(array_pop($line_s));
array_pop($line);
array_pop($line_s);
}
// Fetch description of link
list($line, $line_s) = _wiki_merge($line, $line_s, $pipe+1, -1, false);
array_pop($line);
$descr = trim(array_pop($line_s));
list($descr, $attrs) = _wiki_split_descr_attrs($descr);
array_pop($line);
array_pop($line_s);
}
else
{
$descr = false;
$attrs = false;
}
// Merge all tokens for the uri (we will need unescaped text for this one)
list($line, $line_s) = _wiki_merge($line, $line_s, $offs+1, -1, false, false);
array_pop($line);
$uri = array_pop($line_s);
// pop the opening '['
array_pop($line);
array_pop($line_s);
// Create the link
$line[] = 'html';
$line_s[] = _wiki_make_link($uri, $descr, $anchor, $attrs);
return array($line, $line_s);
}
// Function: _wiki_offset
// Access: INTERNAL
// Parameters: $stack stack with tokens
// $tok try to find this token
// $start (optional) look below this offset
// Returns: offset in stack
// false when not found
// Description: try to locate the token the stack in the stack,
// starting to search on top
//
function _wiki_offset ( $stack, $tok, $start = false )
{
if ($start === false)
{
$start = count($stack) - 1;
}
else
{
$start--;
}
// Don't scan through tds...
while ( $start >= 0
&& $stack[$start] != $tok
&& ($tok == '||' || $stack[$start] != '||'))
{
$start--;
}
if ($start < 0 || $stack[$start] != $tok)
{
$start = false;
}
return $start;
}
// Function: _wiki_after
// Access: INTERNAL
// Parameters: $line list of tokens
// $tok token to find
// $offs offset to start above
// $space (optional) set to false to disallow whitespace
// Returns: false when not found
// offset otherwise
// Description: find the given token _after_ the given offset
//
function _wiki_after ( $line, $tok, $offset, $space = true )
{
$ct = count($line);
while ( $offset < $ct && $line[$offset] != $tok
&& ($space || $line[$offset] != ' '))
{
$offset ++;
}
if ($offset == $ct || $line[$offset] != $tok)
{
return false;
}
else
{
return $offset;
}
}
// Function: _wiki_merge
// Access: INTERNAL
// Parameters: $stack the token stack
// $stack_s the texts of the stack
// $depth the offset to start the merge
// $count number of tokens to merge (-1 for all)
// $replace do some wikiword on uri replacements
// $escape (optional) set to false to not escape html specialchars
// Returns: modified token stack
// Description: merges the given entries into one textual entry
// literal and word entries will be escaped with htmlspecialchars.
//
function _wiki_merge ( $stack, $stack_s, $offset, $count, $replace, $escape = true )
{
if ($count <= 0)
{
$len = count($stack);
}
else
{
$len = min(count($stack), $offset+$count);
}
$text = '';
for ($i=$offset; $i<$len; $i++)
{
if ($replace && $stack[$i] == 'wiki-word')
{
$text .= _wiki_make_link($stack_s[$i],'');
}
else if ($stack[$i] == 'html')
{
$text .= $stack_s[$i];
}
else if ($stack[$i] == 'literal')
{
$text .= '' . htmlspecialchars($stack_s[$i]) . '';
}
else if ($replace && $stack[$i] == 'url')
{
@list($protocol, $address) = explode('://', $stack_s[$i]);
$text .= '' . htmlspecialchars($address) . " ";
}
else if ($replace && $stack[$i] == 'mailto')
{
// Add a marker to the mailto so that we can rebuild the wiki text
$text .= ''
. substr(htmlspecialchars($stack_s[$i]), 7)
. '';
}
else if ($escape)
{
$text .= htmlspecialchars($stack_s[$i]);
}
else
{
$text .= $stack_s[$i];
}
}
if ($len == count($stack))
{
array_splice($stack, $offset);
array_splice($stack_s, $offset);
}
else
{
array_splice($stack, $offset, $count);
array_splice($stack_s, $offset, $count);
}
if ($escape)
{
$stack[] = 'html';
}
else
{
$stack[] = 'text';
}
$stack_s[] = $text;
return array($stack, $stack_s);
}
// Function: _wiki_make_link
// Access: INTERNAL
// Parameters: $uri url, not escaped
// $descr description, escaped
// $anchor optional anchor ('#anchor')
// $attrs attributes ( attr="value" )
// Returns: complete anchor tag
// Description: creates the anchor tag for the given uri and descr.
// when descr is empty then the anchor tag is generated from the uri.
//
function _wiki_make_link ( $uri, $descr, $anchor = '', $attrs = array() )
{
$uri = trim($uri);
if (!empty($descr))
{
$descr = trim($descr);
}
// Remove double quotes around the uri, some people do type them...
if (strlen($uri) >= 2 && $uri{0} == '"' && $uri{strlen($uri)-1} == '"')
{
$uri = substr($uri, 1, -1);
}
$pre = '';
$post = '';
if (!empty($attrs))
{
$attrs = ' ' . implode(' ', $attrs);
}
else
{
$attrs = '';
}
// 1. Check if the uri is a complete one
if (strncasecmp($uri, 'mailto:', 7) == 0)
{
// Add a marker to the mailto so that we can rebuild the wiki text
$descr = trim($descr);
if (!empty($descr))
{
$descr = ' '.$descr;
}
$text = ''
. htmlspecialchars(substr($uri, 7)) . htmlspecialchars($descr)
. '';
// Bail out!
return $text;
}
else if ( strpos($uri, '/') === false
&& !preg_match('/^[a-zA-Z0-9_\-]+\.[a-zA-Z]{2,4}/', $uri)
&& strncasecmp($uri, 'javascript:', 11) != 0)
{
// assume symbolic name
if (empty($descr))
{
// Bail Out: Make special runtime tag, we will need the title of the thing we are linking to...
$pre = '';
$post = '';
$descr = htmlspecialchars($uri);
}
if (!empty($uri))
{
$uri = "id.php/" . str_replace(' ', '%20', $uri);
}
else if (empty($anchor))
{
$anchor = '#';
}
}
else if ( !empty($uri)
&& strpos($uri, '://') === false
&& strncasecmp($uri, 'javascript:', 11) != 0
&& preg_match('/^[a-z]+(\.[a-z]+)(\.[a-z]+)+(\/.*)?$/', $uri))
{
// Make sure we have a protocol for our link, better for tags
$uri = 'http://' . $uri;
}
// 2. Extract a description when we don't have one
if (empty($descr) && strpos($uri, '://') !== false)
{
list($protocol, $col, $descr) = explode('://', $uri);
}
if (empty($descr))
{
$descr = $uri;
}
if (isset($GLOBALS['any_acl']))
{
$uri = $GLOBALS['any_acl']->filterUri($uri);
}
return $pre . ' ' . $descr . ' ' . $post;
}
// Function: _wiki_inline_start
// Access: INTERNAL
// Parameters: $descr
// Returns: list($descr, $attrs)
// Description: splits any attr="value" attributes from the given description
// returns the descr and the list of attributes
//
function _wiki_split_descr_attrs ( $descr )
{
global $_attrs;
$_attrs = array();
$descr = preg_replace_callback('/\s([a-zA-Z]+)=("|")(.*?)("|")/', '_wiki_collect_attr', ' ' . $descr);
return array(trim($descr), $_attrs);
}
// Helper function to collect all attributes from the descr
function _wiki_collect_attr ( $match )
{
global $_attrs;
global $any_acl;
if ( $match[1] == 'target'
|| $match[1] == 'class'
|| $any_acl->allowHtml())
{
$_attrs[] = $match[1] . '="' . $match[3] . '"';
return '';
}
else
{
return $match[0];
}
}
// Function: _wiki_inline_start
// Access: INTERNAL
// Parameters: $tok
// Returns: start token for $tok
// Description: returns the start token belonging to the inline token $tok
//
function _wiki_inline_start ( $tok )
{
switch ($tok)
{
case '}}':
return '{{';
default:
break;
}
return $tok;
}
// Function: _wiki_inline_html
// Access: INTERNAL
// Parameters: $tok
// $text
// Returns: html for text
// Description: surrounds text with the correct html tags for $tok
//
function _wiki_inline_html ( $tok, $text )
{
switch ($tok)
{
case '}}':
$tag = 'tt';
break;
default:
$tag = $tok;
break;
}
return "<$tag>$text";
}
// Function: _wiki_replace_wikiwords
// Access: INTERNAL
// Parameters: $line
// $line_s
// $offset (optional) start scanning at offset
// $end (optional) stop at offset
// Returns: (line, line_s)
// Description: scans the line for WikiWords, when found then replaces them
// with HTML fragments for freelinks.
//
function _wiki_replace_wikiwords( $line, $line_s, $offset = 0, $end = false )
{
if ($end === false)
{
$end = count($line);
}
for ($i = $offset; $i< $end; $i++)
{
if ($line[$i] == 'wiki-word')
{
$line[$i] = 'html';
$line_s[$i] = _wiki_make_link($line_s[$i], '');
}
}
return array($line, $line_s);
}
// Function: _wiki_get_attrs
// Access: INTERNAL
// Parameters: $text the text containing 'attr="value"' pairs
// Returns: array with attr=>value pairs
// Description: parses the attributes of a tag
//
function _wiki_get_attrs ( $text )
{
$parts = explode('="', trim($text));
$last = count($parts) - 1;
$attrs = array();
$key = false;
foreach ($parts as $i => $val)
{
if ($i == 0)
{
$key = trim($val);
}
else
{
$pos = strrpos($val, '"');
$attrs[$key] = stripslashes(substr($val, 0, $pos));
$key = trim(substr($val, $pos+1));
}
}
return $attrs;
}
// Function: _wiki_toc
// Access: INTERNAL
// Parameters: $html html with a toc marker
// Returns: html with a table of contents
// Description: Inserts a table of contents into the html
//
function _wiki_toc ( $html )
{
global $toc_nr;
global $toc_base;
global $toc;
$pos = strpos($html, '');
if ($pos !== false)
{
$toc_base = abs(crc32(microtime(true).'-'.rand(0,100)));
$toc_nr = 0;
// 1. Find all tags for insertion in the table of contents, no h1 tags are inserted
$html = preg_replace_callback('|()(.*)( )|U', '_wiki_toc_accum', $html);
// 2. Create the table of contents at the place of the toc tag
$s = "\n\n";
foreach ($toc as $entry)
{
list($anchor, $level, $title) = $entry;
$s .= "$title \n";
}
$s .= " \n\n";
$html = str_replace('', $s, $html);
}
return $html;
}
function _wiki_toc_accum ( $ms )
{
global $toc_nr;
global $toc_base;
global $toc;
$toc_nr++;
$anchor = "$toc_base-$toc_nr";
$toc[] = array($anchor, $ms[1]{2}, $ms[2]);
return $ms[1]." ".$ms[2].$ms[3];
}
?>
uri) when input is an array
// uri when input is a single id
// Description: Translates a thing id to an absolute uri.
// Depending on the sharing status and the refering identity
// the uri will direct to either the own or the refered
// identity.
//
function any_thing_uri_abs ( $thg_id, $idn_id = null, $lang = null, $commit = null )
{
return any_thing_uri($thg_id, $idn_id, $lang, $commit, true);
}
// Function: any_thing_uri
// Access: EXTERNAL
// Parameters: $thg_id Id of thing (may be an array)
// $idn_id (optional) Identity reading the uris
// $lang (optional) The target _must_ have this language
// $commit (optional) not used (for now)
// $abs (optional,internal) Force absolute uri
// Returns: array(id => uri) when input is an array
// uri when input is a single id
// Description: Translates a thing id to an uri.
// Depending on the sharing status and the refering identity
// the uri will direct to either the own or the refered
// identity.
//
function any_thing_uri ( $thg_id, $idn_id = null, $lang = null, $commit = null, $abs = false )
{
if ($abs)
{
return 'http://' . $_SERVER['HTTP_HOST'] . "/id/" . urlencode($thg_id);
}
else
{
return 'id/' . urlencode($thg_id);
}
}
// Function: any_uri_abs
// Access: EXTERNAL
// Parameters: $uri
// Returns: uri with hostname etc.
// Description: Prepends (when needed) the given uri with a full domain name.
//
function any_uri_abs ( $uri )
{
if (strpos($uri, '://') === false)
{
$uri = 'http://' . $_SERVER['HTTP_HOST'] . '/' . ltrim($uri, '/');
}
return $uri;
}
// Function: any_symbolic2id
// Access: EXTERNAL
// Parameters: $symbolic Symbolic name to look for
// $options Options for search
// Returns: id of thing with given symbolic id
// false when no id found
// Description: return id of thing with the given symbolic name
// a thing of the internal source prevails above things
// of external sources.
// Optionally the selection is reduced to only the
// own things and/or things of a certain kind.
// When the symbolic id matches the pattern [0-9]+ then
// the symbolic id is assumed to be a real id and the id
// is returned as is.
//
function any_symbolic2id ( $symbolic, $options = array() )
{
return false;
}
// Function: any_attach_label2pred
// Access: EXTERNAL
// Parameters: label label or nr of attachment
// Returns: list(predicate, ord_nr)
// Description: translates a label or nr to the correct predicate/ order nr.
//
// A label can have the format of FIG01, FIG02, ICON or DOC01
// Or just be a number, in that case we assume that the user
// is refering to a figure.
// The first figure is nr 1. Internally we use nr 0 for the
// first figure.
//
function any_attach_label2pred ( $label )
{
if (strcasecmp($label, 'ICON') == 0)
{
$pred = 'ICON';
$nr = 1;
}
else if (strncasecmp($label, 'FIG', 3) == 0)
{
$pred = 'FIGURE';
$nr = @intval(substr($label, 3));
}
else if (strncasecmp($label, 'DOC', 3) == 0)
{
$pred = 'DOCUMENT';
$nr = @intval(substr($label, 3));
}
else
{
// Assume numeric
$pred = 'FIGURE';
$nr = @intval($label);
}
// We need an offset from 0
if ($nr > 0)
{
$nr--;
}
else
{
$nr = 0;
}
return array($pred, $nr);
}
// Function: any_attach_caption_label
// Access: EXTERNAL
// Parameters: thg_id thing id
// pred predicate (figure, icon, document)
// nr order nr of figure etc. (0..n)
// Returns: list(att_id, alt, caption)
// false when not found
// Description: tryes to find the named attachment.
// returns the found attachment id, the alt and the caption text
// does not consider _any_ access rights!
//
// In anyMeta a 'thing' can have many images attached to it.
// This images are 'things' of the kind 'attachment'.
// We identify a particular image by a predicate on the edge
// to the image and by the order nr.
//
// The alt text is typically a short title describing the image.
// The caption text could be longer and is typically shown underneath
// the image.
//
function any_attach_caption_pred ( $thg_id, $label )
{
return false;
}
// Function: any_attach_caption
// Access: EXTERNAL
// Parameters: thg_id thing id
// Returns: list(alt, caption)
// false when not found
// Description: returns the alt and the caption text of the attachment
// does not consider _any_ access rights!
//
// an attachment is an image, mainly used in the context of
// articles etc. see the function any_attach_caption_label()
// above for a short discussion about attachments.
//
function any_attach_caption ( $thg_id )
{
return false;
}
// Function: any_thing_title_short
// Access: EXTERNAL
// Parameters: $thg_id Id of the thing (may be an array, must be real id)
// $usr_id (optional) User reading the titles
// $lang (optional) Preferred language array
// Returns: array(id=>title)
// error string with error message
// Description: Reads the short titles of the given thing(s).
//
// in anyMeta every thing must have a title. it might also have a
// short title. this function returns the short title, and when
// missing it returns the (long) title.
//
function any_thing_title_short ( $thg_id, $usr_id = null, $lang = null )
{
$ts = array();
if (!is_array($thg_id))
{
foreach ($thg_id as $id)
{
$ts[$id] = 'title of ' . htmlspecialchars($id);
}
}
else
{
$ts[$thg_id] = 'title of ' . htmlspecialchars($thg_id);
}
return $ts;
}
// Function: any_text_utf8
// Access: EXTERNAL
// Parameters: $html text to check
// Returns: utf8 version of text
// Description: This checks the input string to be really utf8, replaces non utf8 characters
// with a question mark. This validity check is needed before you want to parse
// the string with any XML parser.
//
function any_text_utf8 ( $html )
{
if (function_exists('iconv'))
{
do
{
$ok = true;
$text = @iconv('UTF-8', 'UTF-8//TRANSLIT', $html);
if (strlen($text) != strlen($html))
{
// Remove the offending character...
$html = $text . '?' . substr($html, strlen($text) + 1);
$ok = false;
}
}
while (!$ok);
}
return $html;
}
// Function: any_encode_mailto
// Access: EXTERNAL
// Parameters: $href mailto link
// $text (optional) description for link
// Returns: for mailto
// Description: This generates the anchor-tag for an mailto url.
// The email address is encoded so that most web-bots won't recognise
// it as an email address.
//
function any_encode_mailto ( $href, $text = '', $encode = 'javascript' )
{
if (substr($href, 0, 7) == 'mailto:')
{
$href = substr($href, 7);
}
if (empty($text))
{
$text = $href;
}
$html = ' '
. htmlspecialchars(str_replace('@',' [at] ',$text), ENT_QUOTES)
. ' ';
if ($encode == 'javascript' )
{
// Double encode the text using javascript
//
$js = '';
for ($x=0; $x < strlen($html); $x++)
{
if (rand(0,5) == 1)
{
$js .= '\'+\'';
}
if (strchr('><\'@', $html[$x]) !== false || rand(0,2) == 1)
{
$js .= '%' . bin2hex($html[$x]);
}
else
{
$js .= $html[$x];
}
}
$html = '';
$js = '';
for ($x=0; $x < strlen($html); $x++)
{
if (strchr('><\'', $html[$x]) !== false || rand(0,2) == 1)
{
$js .= '%' . bin2hex($html[$x]);
}
else
{
$js .= $html[$x];
}
}
$html = '';
}
else
{
// Simple non-javascript version
//
$text_encode = '';
for ($x=0; $x < strlen($href); $x++)
{
$text_encode .= '&#' . ord($href[$x]) . ';';
}
$href = $text_encode;
$text_encode = '';
$text = str_replace('@', ' [at] ', $text);
for ($x=0; $x < strlen($text); $x++)
{
$text_encode .= '&#' . ord($text[$x]) . ';';
}
$text = $text_encode;
$html = "$text ";
}
return $html;
}
// Class: Anymeta_ACL
// Access: EXTERNAL
// Provides: Access control for the anymeta system
//
class Anymeta_ACL
{
function Anymeta_ACL ()
{
}
// Function: Anymeta_ACL::allowHtml
// Access: PUBLIC
// Parameters: -
// Returns: false when user is not allowed to edit html text
// true when user is allowed to edit html text
// Description: Checks if the current user is allowed to edit html.
// This is a very special right, and should be given
// with caution!
//
// This should be a right of an editor, letting normal users
// enter HTML really defies the idea of an wiki, and of the
// security of letting people enter markup text.
//
function allowHtml ()
{
return defined('ALLOWHTML');
}
// Function: Anymeta_ACL::filterUri
// Access: PUBLIC
// Parameters: uri uri to be filtered
// Returns: '' when uri was not allowed
// uri when uri was allowed
// Description: Checks the given uri with the access permissions of the user.
// The user needs text/html permissions for entering javascrpt uris.
//
function filterUri ( $uri )
{
$allow = false;
$uri = trim($uri);
$u = urldecode($uri);
if ( strpos($u, '&#') === false
&& strpos($u, '"') === false
&& strncasecmp($u, 'javascript:', 11) != 0)
{
$allow = true;
}
if (!$allow)
{
// user needs to have the right to edit HTML
$allow = $this->allowHtml();
}
return $allow ? $uri : '';
}
}
$any_acl = new Anymeta_ACL();
?> base width in pixels for images
// height base height in pixels for images
// thg_id the id of the thing the texts belong to
// (needed to find images)
//
function any_wiki_runtime ( $text, $options = array() )
{
global $_wiki_options;
$_wiki_options = $options;
// 1. Filter remainings of and html tags
$text = preg_replace('//', '', $text);
// 2. Grep all image tags and produce tags.
$text = preg_replace_callback('//', '_wiki_runtime_image', $text);
// 3. Handle the runtime replacement of links
$text = preg_replace_callback('/.+?/', '_wiki_runtime_link', $text);
// 4. Handle the runtime replacement of mailto hrefs
$text = preg_replace_callback('/([^ ]+?)( .+?)?/', '_wiki_runtime_mailto', $text);
if (!empty($options['abs_uri']))
{
// 5. Make the id.php/xxxx uris absolute
$text = preg_replace_callback('||', '_wiki_runtime_anchor_abs_uri', $text);
}
return $text;
}
// Function: any_wiki_runtime_image_labels
// Access: EXTERNAL
// Parameters: $text the text to be expanded
// Returns: array with image indices used
// Description: Fetch all image nrs used in the given text.
// Does recognise the 'FIGxx' format for labels.
// Does also handle numerical references correctly
//
function any_wiki_runtime_image_labels ( $text )
{
$image = array();
if (preg_match_all('//', $text, $ms, PREG_PATTERN_ORDER))
{
foreach ($ms[1] as $m)
{
if (strncasecmp($m, 'FIG', 3) == 0)
{
$image[] = @intval(substr($m,3)) - 1;
}
else if (is_numeric($m) && $m < 100)
{
$image[] = intval($m) - 1;
}
}
sort($image);
}
return $image;
}
// Function: _wiki_runtime_link
// Access: INTERNAL
// Parameters: $matches pattern match of the tag
// Returns: tag
// Description: runtime produces the tag with the correct title.
//
function _wiki_runtime_link ( $matches )
{
global $_wiki_options;
$page = $matches[1];
$abs_uri = !empty($_wiki_options['abs_uri']);
$attr = '';
$ct = count($matches);
for ($i=2; $i<$ct; $i+=3)
{
$attr .= ' ' . $matches[$i];
}
@list($page, $anchor) = explode('#', $page);
if (strncasecmp($page, 'uri:', 4) == 0)
{
$page = substr($page, 4);
}
else if ( strpos($page, '://') === false
&& strpos($page, '/' ) === false)
{
// try to translate the given name to an anymeta id
$thg_id = any_symbolic2id($page);
}
if (!empty($thg_id))
{
// It is an anymeta id, use the anymeta routines to generate the link
$text = any_thing_title_short($thg_id);
if (is_array($text))
{
$text = reset($text);
}
if (empty($text))
{
$text = $page;
}
// Fetch the uri, prefered from the pre-fetched uris in the template
if ($abs_uri)
{
$href = any_thing_uri_abs($thg_id);
}
else
{
$href = any_thing_uri($thg_id);
}
// Add the anchor
if (!empty($anchor))
{
$href .= "#$anchor";
}
$html = ' ' . htmlspecialchars($text) . ' ';
}
else if (strpos($page, '://') !== false)
{
$n = strpos($page, '://');
$text = substr($page, $n+3);
$html = "".htmlspecialchars($text)." ";
}
else
{
// the page does not exist, show the page name and
// the "new page" text
$page = htmlspecialchars($page);
$url = 'id.php/'.urlencode($page);
if ($abs_uri)
{
$url = any_uri_abs($url);
}
$html = "$page ";
}
return $html;
}
// Function: _wiki_runtime_anchor_abs_uri
// Access: INTERNAL
// Parameters: $matches pattern of the tag
// Returns: modified tag
// Description: makes the enclose uri absolute
//
function _wiki_runtime_anchor_abs_uri ( $matches )
{
return ' ';
}
// Function: _wiki_runtime_mailto
// Access: INTERNAL
// Parameters: $matches pattern match of the tag
// Returns: tag
// Description: runtime produces the tag with the correct title.
//
function _wiki_runtime_mailto ( $matches )
{
global $_wiki_options;
if (empty($_wiki_options['nojavascript']))
{
$encode = 'javascript';
}
else
{
$encode = 'entities';
}
return any_encode_mailto($matches[1], @trim($matches[2]), $encode);
}
// Function: _wiki_runtime_image
// Access: INTERNAL
// Parameters: $matches pattern match of the tag
// Returns: tag
// Description: runtime produce the tag for the given image description
//
function _wiki_runtime_image ( $matches )
{
global $_wiki_options;
$attr = array();
$src = $matches[1];
$ct = count($matches);
for ($i=2; $i<$ct; $i+=3)
{
$attr[trim($matches[$i+1])] = $matches[$i+2];
}
$base_thg_id = !empty($_wiki_options['thg_id']) ? $_wiki_options['thg_id'] : false;
$base_width = !empty($_wiki_options['width']) ? $_wiki_options['width'] : 400;
$base_height = !empty($_wiki_options['height']) ? $_wiki_options['height'] : 400;
$abs_uri = !empty($_wiki_options['abs_uri']) ? $_wiki_options['abs_uri'] : false;
// Fetch the requested width and height
if (!empty($attr['width']))
{
$width = _wiki_runtime_img_size($attr['width'], $base_width);
}
else
{
$width = round($base_width);
}
if (!empty($attr['height']))
{
$height = _wiki_runtime_img_size($attr['height'], $base_height);
}
else
{
$height = round($base_height);
}
if (substr($src, 0, 1) == '"' && substr($src, -1) == '"')
{
$src = substr($src, 1, -1);
}
$src = trim($src);
// See where we have to fetch the image from
if (!empty($src))
{
if (strpos($src, 'uri:') === 0)
{
// direct uri
$src = substr($src, 4);
$id = false;
}
else if (strpos($src, '://') === false)
{
if (strpos($src, ':') !== false)
{
list($a, $b) = explode(':', $src);
if (empty($b))
{
$thg_id = $a;
$lbl = false;
}
else if (empty($a))
{
$thg_id = $base_thg_id;
$lbl = $b;
}
else
{
$thg_id = $a;
$lbl = $b;
}
}
else
{
$thg_id = $base_thg_id;
$lbl = $src;
}
// Try to translate to a real thg_id
if (!is_numeric($thg_id))
{
if (empty($lbl))
{
$thg_id = any_symbolic2id($thg_id, array('kind'=>'ATTACHMENT'));
}
else
{
$thg_id = any_symbolic2id($thg_id);
}
}
// Fetch the thing id of the attachment
if (!empty($lbl) && !empty($thg_id))
{
list($pred, $nr) = any_attach_label2pred($lbl);
@list($aid, $alt, $caption) = any_attach_caption_pred($thg_id, $pred, $nr);
}
else
{
// Assume the given src is an attachment id
if (!empty($attr['caption']))
{
@list($alt, $caption) = any_attach_caption($thg_id);
}
else
{
$alt = '';
$caption = '';
}
$aid = $thg_id;
$lbl = false;
}
if (empty($caption) && !empty($alt))
{
$caption = $alt;
}
$alt = strip_tags($alt);
}
else
{
$id = false;
$aid = false;
$lbl = false;
$alt = '';
$caption = '';
}
}
else
{
$src = '#'; // Unknown source
$id = false;
$aid = false;
$lbl = false;
}
if (!empty($attr['caption']))
{
if (!empty($caption))
{
$alt = trim($alt);
$caption = trim(str_replace(array('', '
'), array('',' '), $caption));
while (substr($caption, -5) == ' ')
{
$caption = trim(substr($caption, 0, -5));
}
if (!empty($alt) && !empty($intro))
{
$cap = '';
if (!empty($alt))
{
$cap .= '' . any_wiki_runtime($alt, $_wiki_options) .' ';
}
if (!empty($caption))
{
$cap .= any_wiki_runtime($caption, $_wiki_options);
}
$cap .= ' ';
}
else
{
$cap = '';
}
if (strcasecmp($attr['caption'], 'before') == 0)
{
$cap1 = $cap;
$cap2 = '';
}
else
{
$cap1 = '';
$cap2 = $cap;
}
}
else
{
$cap1 = '';
$cap2 = '';
}
unset($attr['caption']);
}
else
{
$cap1 = '';
$cap2 = '';
}
//
// Expand the anchor tag around the image
//
if (array_key_exists('link',$attr))
{
$link = trim($attr['link']);
}
else
{
$link = false;
}
$expand = false;
if (empty($link) && !empty($aid))
{
// Link to the attachment ;-)
$href = 'id/' . $aid;
if ($abs_uri)
{
$href = any_uri_abs($href);
}
}
else if ($link[0] == '#')
{
// Ref to local anchor
$href = $link;
}
else if ( strpos($link, '://') > 0
|| strpos($link, '.php') !== false
|| strpos($link, '.html') !== false
|| strpos($link, '.htm') !== false)
{
// Literal link
$href = $link;
}
else if (strncmp($link, 'javascript:', 12) == 0)
{
$href = $link;
}
else if (strncmp($link, 'popup:', 6) == 0)
{
$popup = substr($link, 6);
if (strlen($popup) == 0)
{
if (is_numeric($thg_id))
{
$label = addslashes($lbl);
$href = "javascript:popup('$thg_id','$label')";
}
else if (!empty($aid) && is_numeric($aid))
{
$href = "javascript:popup('{$aid}')";
$expand = true;
}
}
else
{
// Undefined behaviour for now...
$href = false;
}
}
else
{
// Assume a thing id
if (!empty($abs_uri))
{
$href = any_thing_uri_abs($link);
}
else
{
$href = any_thing_uri($link);
}
}
// Perform any macro expansion (when needed)
if (!empty($href) && $expand)
{
$href = str_replace(array('{$thg_id}', '{$label}', '{$att_id}'),
array($thg_id, $lbl, $aid),
$href);
}
$href = htmlspecialchars($href);
// unset these so they don't show up as attributes
unset($attr['link']);
// Build the image tag
if (!empty($aid) && is_numeric($aid))
{
if (empty($attr['alt']))
{
$attr['alt'] = $alt;
}
if (empty($attr['title']))
{
$attr['title'] = $alt;
}
unset($attr['height']);
unset($attr['width']);
$pars = $attr;
$pars['abs'] = $abs_uri;
$img = any_attach_img_tag($aid, $pars, $width, $height);
}
else
{
if (!array_key_exists('alt', $attr))
{
$attr['alt'] = basename($src);
}
// A normal src, build the tag ourselves
$attr_s = '';
foreach ($attr as $key => $val)
{
$attr_s .= " $key=\"$val\"";
}
$img = " ";
}
if (!empty($href))
{
$html = "$cap1 $img $cap2";
}
else
{
$html = "$cap1$img$cap2";
}
return $html;
}
// Calculate a size, using a base size and a percentage
//
function _wiki_runtime_img_size ( $req, $base )
{
if (substr($req, -2) == 'px')
{
// Absolute size
$ret = substr($req, 0, -2);
}
else if (is_string($req) && is_numeric($base))
{
// Assume percentage of base size
if (substr($req, -1) == '%')
{
$req = substr($req, 0, -1);
}
$ret = ceil(floatval($req) * floatval($base) / 100.0);
}
else
{
// No size
$ret = null;
}
return $ret;
}
?>
Animeband - Home
Welcome to Animeband!
Animeband is based off Angband 2.9.3, an ascii roguelike. However, Animeband started to tangent away from V, and looks quite different. Try it :)
Bug reports can be submitted to Animeband Bugzilla database .
Announcement (2008.04.05):
Animeband v0.6.1a released. This release is just build/compiler adjustments to 0.6.1.
Binary packages are now available: Download Binaries --PhaethonH
Announcement (2008.04.02):
Animeband v0.6.1 released as source tarball: animeband-0.6.1.tar.gz --PhaethonH
Announcement (2008.03.31):
ehuangsan is stepping down as maintainer for Animeband. PhaethonH/phaethon_h (me) will be taking up the mantle in his stead. --PhaethonH