From 3fd0b6768bf7f649d77c937e399f578d7add7637 Mon Sep 17 00:00:00 2001 From: andi Date: Fri, 29 Apr 2005 13:49:25 +0200 Subject: comments and cleanup darcs-hash:20050429114925-9977f-ff5b6dcf702b533a2dd64397522da7cd7b97f092.gz --- inc/confutils.php | 4 + inc/format.php | 593 ----------------------------------- inc/format.php.bak | 593 +++++++++++++++++++++++++++++++++++ inc/parser.php | 862 --------------------------------------------------- inc/parser.php.bak | 862 +++++++++++++++++++++++++++++++++++++++++++++++++++ inc/parser/xhtml.php | 329 +++++++------------- inc/parserutils.php | 1 - 7 files changed, 1578 insertions(+), 1666 deletions(-) delete mode 100644 inc/format.php create mode 100644 inc/format.php.bak delete mode 100644 inc/parser.php create mode 100644 inc/parser.php.bak (limited to 'inc') diff --git a/inc/confutils.php b/inc/confutils.php index 4a38eeaac..a0ad322fb 100644 --- a/inc/confutils.php +++ b/inc/confutils.php @@ -98,7 +98,11 @@ function getInterwiki() { /** * Builds a hash from a configfile * + * If $lower is set to true all hash keys are converted to + * lower case. + * * @author Harry Fuecks + * @author Andreas Gohr */ function confToHash($file,$lower=false) { $conf = array(); diff --git a/inc/format.php b/inc/format.php deleted file mode 100644 index 0a20b566c..000000000 --- a/inc/format.php +++ /dev/null @@ -1,593 +0,0 @@ - - * @deprecated part of the XHTML renderer - */ - -trigger_error('deprecated parser.php included'); - - if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); - require_once(DOKU_INC.'conf/dokuwiki.php'); - require_once(DOKU_INC.'inc/common.php'); - - -/** - * Assembles all parts defined by the link formater below - * Returns HTML for the link - * - * @author Andreas Gohr - */ -function format_link_build($link){ - //make sure the url is XHTML compliant (skip mailto) - if(substr($link['url'],0,7) != 'mailto:'){ - $link['url'] = str_replace('&','&',$link['url']); - $link['url'] = str_replace('&amp;','&',$link['url']); - } - //remove double encodings in titles - $link['title'] = str_replace('&amp;','&',$link['title']); - - $ret = ''; - $ret .= $link['pre']; - $ret .= ' with proper special char encoding - * $link['class'] CSS class to set on link - * $link['target'] which target to use (blank) for current window - * $link['style'] Additonal style attribute set with style="" - * $link['title'] Title to set with title="" - * $link['pre'] HTML to prepend to link - * $link['suf'] HTML to append to link - * $link['more'] Additonal HTML to include into the anchortag - * - */ - -/** - * format wiki links - * - * @author Andreas Gohr - */ -function format_link_wiki($link){ - global $conf; - global $ID; //we use this to get the current namespace - //obvious setup - $link['target'] = $conf['target']['wiki']; - $link['style'] = ''; - $link['pre'] = ''; - $link['suf'] = ''; - $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; - - $ns = getNS($ID); - - //if links starts with . add current namespace - if(strpos($link['url'],'.')===0){ - $link['url'] = $ns.':'.substr($link['url'],1); - } - - //if link contains no namespace. add current namespace (if any) - if($ns !== false && strpos($link['url'],':') === false){ - $link['url'] = $ns.':'.$link['url']; - } - - //keep hashlink if exists - list($link['url'],$hash) = split('#',$link['url'],2); - $hash = cleanID($hash); - - $file = wikiFN($link['url']); - $url = cleanID($link['url']); - - //check alternative plural/nonplural form - if(!@file_exists($file) && $conf['autoplural']){ - if(substr($url,-1) == 's'){ - $try = substr($url,0,-1); - }else{ - $try = $url.'s'; - } - $tryfile = wikiFN($try); - if(@file_exists($tryfile)){ - $file = $tryfile; - $url = $try; - } - } - - //set class and name depending on file existence and content - if(@file_exists($file)){ - $link['class']="wikilink1"; - if ($conf['useheading'] && empty($link['name'])) { - $hl = getFirstHeading(io_readFile($file)); - if ($hl) $link['name'] = $hl; - } - }else{ - $link['class']="wikilink2"; - } - - //if no name set yet, use (unclean) link without namespace - if(empty($link['name'])){ - if($conf['useslash']){ - $nssep = '[:;/]'; - }else{ - $nssep = '[:;]'; - } - $link['name'] = preg_replace('!.*'.$nssep.'!','',$link['url']); - } - $link['name'] = htmlspecialchars($link['name']); - - //set title - $link['title'] = $url; - - //construct the full link - $link['url'] = wl($url); - - //add hash if exists - if($hash) $link['url'] .= '#'.$hash; - - return $link; -} - -/** - * format external URLs - * - * @author Andreas Gohr - */ -function format_link_externalurl($link){ - global $conf; - //simple setup - $link['class'] = 'urlextern'; - $link['target'] = $conf['target']['extern']; - $link['pre'] = ''; - $link['suf'] = ''; - $link['style'] = ''; - $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; - $link['url'] = $link['url']; //keep it - $link['title'] = htmlspecialchars($link['url']); - if(!$link['name']) $link['name'] = htmlspecialchars($link['url']); - if($conf['relnofollow']) $link['more'] .= ' rel="nofollow"'; - //thats it :-) - return $link; -} - -/** - * format windows share links - * - * this only works in IE :-( - * - * @author Andreas Gohr - */ -function format_link_windows($link){ - global $conf; - global $lang; - //simple setup - $link['class'] = 'windows'; - $link['target'] = $conf['target']['windows']; - $link['pre'] = ''; - $link['suf'] = ''; - $link['style'] = ''; - //Display error on browsers other than IE - $link['more'] = 'onclick="if(document.all == null){alert(\''.htmlspecialchars($lang['nosmblinks'],ENT_QUOTES).'\');}" onkeypress="if(document.all == null){alert(\''.htmlspecialchars($lang['nosmblinks'],ENT_QUOTES).'\');}"'; - - if(!$link['name']) $link['name'] = htmlspecialchars($link['url']); - $link['title'] = htmlspecialchars($link['url']); - $link['url'] = str_replace('\\','/',$link['url']); - $link['url'] = 'file:///'.$link['url']; - - return $link; -} - -/** - * format email addresses - * - * @author Andreas Gohr - */ -function format_link_email($link){ - global $conf; - //simple setup - $link['class'] = 'mail'; - $link['target'] = ''; - $link['pre'] = ''; - $link['suf'] = ''; - $link['style'] = ''; - $link['more'] = ''; - - $link['name'] = htmlspecialchars($link['name']); - - //shields up - if($conf['mailguard']=='visible'){ - //the mail name gets some visible encoding - $link['url'] = str_replace('@',' [at] ',$link['url']); - $link['url'] = str_replace('.',' [dot] ',$link['url']); - $link['url'] = str_replace('-',' [dash] ',$link['url']); - }elseif($conf['mailguard']=='hex'){ - for ($x=0; $x < strlen($link['url']); $x++) { - $encode .= '&#x' . bin2hex($link['url'][$x]).';'; - } - $link['url'] = $encode; - } - - $link['title'] = $link['url']; - if(!$link['name']) $link['name'] = $link['url']; - $link['url'] = 'mailto:'.$link['url']; - - return $link; -} - -/** - * format interwiki links - * - * @author Andreas Gohr - */ -function format_link_interwiki($link){ - global $conf; - - //obvious ones - $link['class'] = 'interwiki'; - $link['target'] = $conf['target']['interwiki']; - $link['pre'] = ''; - $link['suf'] = ''; - $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; - - //get interwiki short name - list($wiki,$link['url']) = split('>',$link['url'],2); - $wiki = strtolower(trim($wiki)); //always use lowercase - $link['url'] = trim($link['url']); - if(!$link['name']) $link['name'] = $link['url']; - - //encode special chars - $link['name'] = htmlspecialchars($link['name']); - - //set default to google - $url = 'http://www.google.com/search?q='; - $ico = 'google'; - - // Initialize as NULL - for the first fn call - static $iwlinks = NULL; - - // load interwikilinks if needed - if (!$iwlinks) $iwlinks = file('conf/interwiki.conf'); - - //add special case 'this' - $iwlinks[] = 'this '.DOKU_URL.'{NAME}'; - - //go through iwlinks and find URL for wiki - foreach ($iwlinks as $line){ - $line = preg_replace('/#.*/','',$line); //skip comments - $line = trim($line); - list($iw,$iwurl) = preg_split('/\s+/',$line); - if(!$iw or !$iwurl) continue; //skip broken or empty lines - //check for match - if(strtolower($iw) == $wiki){ - $ico = $wiki; - $url = $iwurl; - break; - } - } - - //if ico exists set additonal style - if(@file_exists('interwiki/'.$ico.'.png')){ - $link['style']='background: transparent url('.DOKU_BASE.'interwiki/'.$ico.'.png) 0px 1px no-repeat;'; - }elseif(@file_exists('interwiki/'.$ico.'.gif')){ - $link['style']='background: transparent url('.DOKU_BASE.'interwiki/'.$ico.'.gif) 0px 1px no-repeat;'; - } - - //do we stay at the same server? Use local target - if( strpos($url,DOKU_URL) === 0 ){ - $link['target'] = $conf['target']['wiki']; - } - - //replace placeholder - if(preg_match('#\{(URL|NAME|SCHEME|HOST|PORT|PATH|QUERY)\}#',$url)){ - //use placeholders - $url = str_replace('{URL}',urlencode($link['url']),$url); - $url = str_replace('{NAME}',$link['url'],$url); - $parsed = parse_url($link['url']); - if(!$parsed['port']) $parsed['port'] = 80; - $url = str_replace('{SCHEME}',$parsed['scheme'],$url); - $url = str_replace('{HOST}',$parsed['host'],$url); - $url = str_replace('{PORT}',$parsed['port'],$url); - $url = str_replace('{PATH}',$parsed['path'],$url); - $url = str_replace('{QUERY}',$parsed['query'],$url); - $link['url'] = $url; - }else{ - //default - $link['url'] = $url.urlencode($link['url']); - } - - $link['title'] = htmlspecialchars($link['url']); - - //done :-) - return $link; -} - -/** - * format embedded media - * - * @author Andreas Gohr - */ -function format_link_media($link){ - global $conf; - global $ID; - - $link['class'] = 'media'; - $link['style'] = ''; - $link['pre'] = ''; - $link['suf'] = ''; - $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; - $class = 'media'; - - list($link['name'],$title) = split('\|',$link['name'],2); - $t = htmlspecialchars($title); - - //set alignment from spaces - if(substr($link['name'],0,1)==' ' && substr($link['name'],-1,1)==' '){ - $link['pre'] = "

\n
"; - $link['suf'] = "
\n

"; - }elseif(substr($link['name'],0,1)==' '){ - #$a = ' align="right"'; - $class = 'mediaright'; - }elseif(substr($link['name'],-1,1)==' '){ - #$a = ' align="left"'; - $class = 'medialeft'; - }else{ - $a = ' align="middle"'; - } - $link['name'] = trim($link['name']); - - //split into src and parameters (using the very last questionmark) - $pos = strrpos($link['name'], '?'); - if($pos !== false){ - $src = substr($link['name'],0,$pos); - $param = substr($link['name'],$pos+1); - }else{ - $src = $link['name']; - $param = ''; - } - - //parse width and height - if(preg_match('#(\d+)(x(\d+))?#i',$param,$size)){ - if($size[1]) $w = $size[1]; - if($size[3]) $h = $size[3]; - } - - //namespace mangling for internal images - if(!preg_match('#^https?://#i',$src)){ - $ns = getNS($ID); - //if src starts with . add current namespace - if(strpos($src,'.') === 0){ - $src = $ns.':'.substr($src,1); - } - //if src contains no namespace add current namespace if any - if($ns !== false && strpos($src,':') === false ){ - $src = $ns.':'.$src; - } - } - - //check for nocache/recache param - preg_match('/(nocache|recache)/i',$param,$cachemode); - - //do image caching, resizing and src rewriting - $cache = $src; - $isimg = img_cache($cache,$src,$w,$h,$cachemode[1]); - - //set link to src if none given - if(!$link['url']){ - $link['url'] = $src; - $link['target'] = $conf['target']['media']; - } - - //prepare name - if($isimg){ - $link['name'] = ''.$t.''; - }else{ - if($t){ - $link['name'] = $t; - }else{ - $link['name'] = basename($src); - } - } - - return $link; -} - -/** - * Build an URL list from a RSS feed - * - * Uses magpie - * - * @author Andreas Gohr - */ -function format_rss($url){ - global $lang; - define('MAGPIE_CACHE_ON', false); //we do our own caching - define('MAGPIE_DIR', 'inc/magpie/'); - define('MAGPIE_OUTPUT_ENCODING','UTF-8'); //return all feeds as UTF-8 - require_once(MAGPIE_DIR.'/rss_fetch.inc'); - - //disable warning while fetching - $elvl = error_reporting(E_ERROR); - $rss = fetch_rss($url); - error_reporting($elvl); - - $ret = '

    '; - if($rss){ - foreach ($rss->items as $item ) { - $link = array(); - $link['url'] = $item['link']; - $link['name'] = $item['title']; - $link = format_link_externalurl($link); - $ret .= '
  • '.format_link_build($link).'
  • '; - } - }else{ - $link['url'] = $url; - $link = format_link_externalurl($link); - $ret .= '
  • '; - $ret .= ''.$lang['rssfailed'].''; - $ret .= format_link_build($link); - $ret .= '
  • '; - } - $ret .= '
'; - return $ret; -} - -/** - * Create cache images - * - * @author Andreas Gohr - */ -function img_cache(&$csrc,&$src,&$w,&$h,$cachemode){ - global $conf; - - //container for various paths - $f['full']['web'] = $src; - $f['resz']['web'] = $src; - $f['full']['fs'] = $src; - $f['resz']['fs'] = $src; - - //generate cachename - $md5 = md5($src); - - //check if it is an image - if(preg_match('#\.(jpe?g|gif|png)$#i',$src,$match)){ - $ext = strtolower($match[1]); - $isimg = true; - } - - //check if it is external or a local mediafile - if(preg_match('#^([a-z0-9]+?)://#i',$src)){ - $isurl = true; - }else{ - $src = str_replace(':','/',$src); - $src = utf8_encodeFN($src); - $f['full']['web'] = $conf['mediaweb'].'/'.$src; - $f['resz']['web'] = $conf['mediaweb'].'/'.$src; - $f['full']['fs'] = $conf['mediadir'].'/'.$src; - $f['resz']['fs'] = $conf['mediadir'].'/'.$src; - } - - //download external images if allowed - if($isurl && $isimg && $cachemode != 'nocache'){ - $cache = $conf['mediadir']."/_cache/$md5.$ext"; - if ( ($cachemode == 'recache' && io_download($src,$cache)) || - @file_exists($cache) || io_download($src,$cache)){ - $f['full']['web'] = $conf['mediaweb']."/_cache/$md5.$ext"; - $f['resz']['web'] = $conf['mediaweb']."/_cache/$md5.$ext"; - $f['full']['fs'] = $conf['mediadir']."/_cache/$md5.$ext"; - $f['resz']['fs'] = $conf['mediadir']."/_cache/$md5.$ext"; - $isurl = false; - } - } - - //for local images (cached or media) do resizing - if($isimg && (!$isurl)){ - if($w){ - $info = getImageSize($f['full']['fs']); - //if $h not given calcualte it with correct aspect ratio - if(!$h){ - $h = round(($w * $info[1]) / $info[0]); - } - $cache = $conf['mediadir'].'/_cache/'.$md5.'.'.$w.'x'.$h.'.'.$ext; - //delete outdated cachefile - if(@file_exists($cache) && (filemtime($cache) - */ -function img_resize($ext,$from,$from_w,$from_h,$to,$to_w,$to_h){ - global $conf; - - if($conf['gdlib'] < 1) return false; //no GDlib available or wanted - - // create an image of the given filetype - if ($ext == 'jpg' || $ext == 'jpeg'){ - if(!function_exists("imagecreatefromjpeg")) return false; - $image = @imagecreateFromjpeg($from); - }elseif($ext == 'png') { - if(!function_exists("imagecreatefrompng")) return false; - $image = @imagecreatefrompng($from); - }elseif($ext == 'gif') { - if(!function_exists("imagecreatefromgif")) return false; - $image = @imagecreatefromgif($from); - } - if(!$image) return false; - - if(($conf['gdlib']>1) && function_exists("imagecreatetruecolor")){ - $newimg = @imagecreatetruecolor ($to_w, $to_h); - } - if(!$newimg) $newimg = @imagecreate($to_w, $to_h); - if(!$newimg) return false; - - // create cachedir - io_makeFileDir($to); - - //try resampling first - if(function_exists("imagecopyresampled")){ - if(!@imagecopyresampled($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h)) { - imagecopyresized($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h); - } - }else{ - imagecopyresized($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h); - } - - if ($ext == 'jpg' || $ext == 'jpeg'){ - if(!function_exists("imagejpeg")) return false; - return imagejpeg($newimg, $to, 70); - }elseif($ext == 'png') { - if(!function_exists("imagepng")) return false; - return imagepng($newimg, $to); - }elseif($ext == 'gif') { - if(!function_exists("imagegif")) return false; - return imagegif($newimg, $to); - } - - return false; -} - - -//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/inc/format.php.bak b/inc/format.php.bak new file mode 100644 index 000000000..0a20b566c --- /dev/null +++ b/inc/format.php.bak @@ -0,0 +1,593 @@ + + * @deprecated part of the XHTML renderer + */ + +trigger_error('deprecated parser.php included'); + + if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); + require_once(DOKU_INC.'conf/dokuwiki.php'); + require_once(DOKU_INC.'inc/common.php'); + + +/** + * Assembles all parts defined by the link formater below + * Returns HTML for the link + * + * @author Andreas Gohr + */ +function format_link_build($link){ + //make sure the url is XHTML compliant (skip mailto) + if(substr($link['url'],0,7) != 'mailto:'){ + $link['url'] = str_replace('&','&',$link['url']); + $link['url'] = str_replace('&amp;','&',$link['url']); + } + //remove double encodings in titles + $link['title'] = str_replace('&amp;','&',$link['title']); + + $ret = ''; + $ret .= $link['pre']; + $ret .= '
with proper special char encoding + * $link['class'] CSS class to set on link + * $link['target'] which target to use (blank) for current window + * $link['style'] Additonal style attribute set with style="" + * $link['title'] Title to set with title="" + * $link['pre'] HTML to prepend to link + * $link['suf'] HTML to append to link + * $link['more'] Additonal HTML to include into the anchortag + * + */ + +/** + * format wiki links + * + * @author Andreas Gohr + */ +function format_link_wiki($link){ + global $conf; + global $ID; //we use this to get the current namespace + //obvious setup + $link['target'] = $conf['target']['wiki']; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; + + $ns = getNS($ID); + + //if links starts with . add current namespace + if(strpos($link['url'],'.')===0){ + $link['url'] = $ns.':'.substr($link['url'],1); + } + + //if link contains no namespace. add current namespace (if any) + if($ns !== false && strpos($link['url'],':') === false){ + $link['url'] = $ns.':'.$link['url']; + } + + //keep hashlink if exists + list($link['url'],$hash) = split('#',$link['url'],2); + $hash = cleanID($hash); + + $file = wikiFN($link['url']); + $url = cleanID($link['url']); + + //check alternative plural/nonplural form + if(!@file_exists($file) && $conf['autoplural']){ + if(substr($url,-1) == 's'){ + $try = substr($url,0,-1); + }else{ + $try = $url.'s'; + } + $tryfile = wikiFN($try); + if(@file_exists($tryfile)){ + $file = $tryfile; + $url = $try; + } + } + + //set class and name depending on file existence and content + if(@file_exists($file)){ + $link['class']="wikilink1"; + if ($conf['useheading'] && empty($link['name'])) { + $hl = getFirstHeading(io_readFile($file)); + if ($hl) $link['name'] = $hl; + } + }else{ + $link['class']="wikilink2"; + } + + //if no name set yet, use (unclean) link without namespace + if(empty($link['name'])){ + if($conf['useslash']){ + $nssep = '[:;/]'; + }else{ + $nssep = '[:;]'; + } + $link['name'] = preg_replace('!.*'.$nssep.'!','',$link['url']); + } + $link['name'] = htmlspecialchars($link['name']); + + //set title + $link['title'] = $url; + + //construct the full link + $link['url'] = wl($url); + + //add hash if exists + if($hash) $link['url'] .= '#'.$hash; + + return $link; +} + +/** + * format external URLs + * + * @author Andreas Gohr + */ +function format_link_externalurl($link){ + global $conf; + //simple setup + $link['class'] = 'urlextern'; + $link['target'] = $conf['target']['extern']; + $link['pre'] = ''; + $link['suf'] = ''; + $link['style'] = ''; + $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; + $link['url'] = $link['url']; //keep it + $link['title'] = htmlspecialchars($link['url']); + if(!$link['name']) $link['name'] = htmlspecialchars($link['url']); + if($conf['relnofollow']) $link['more'] .= ' rel="nofollow"'; + //thats it :-) + return $link; +} + +/** + * format windows share links + * + * this only works in IE :-( + * + * @author Andreas Gohr + */ +function format_link_windows($link){ + global $conf; + global $lang; + //simple setup + $link['class'] = 'windows'; + $link['target'] = $conf['target']['windows']; + $link['pre'] = ''; + $link['suf'] = ''; + $link['style'] = ''; + //Display error on browsers other than IE + $link['more'] = 'onclick="if(document.all == null){alert(\''.htmlspecialchars($lang['nosmblinks'],ENT_QUOTES).'\');}" onkeypress="if(document.all == null){alert(\''.htmlspecialchars($lang['nosmblinks'],ENT_QUOTES).'\');}"'; + + if(!$link['name']) $link['name'] = htmlspecialchars($link['url']); + $link['title'] = htmlspecialchars($link['url']); + $link['url'] = str_replace('\\','/',$link['url']); + $link['url'] = 'file:///'.$link['url']; + + return $link; +} + +/** + * format email addresses + * + * @author Andreas Gohr + */ +function format_link_email($link){ + global $conf; + //simple setup + $link['class'] = 'mail'; + $link['target'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['style'] = ''; + $link['more'] = ''; + + $link['name'] = htmlspecialchars($link['name']); + + //shields up + if($conf['mailguard']=='visible'){ + //the mail name gets some visible encoding + $link['url'] = str_replace('@',' [at] ',$link['url']); + $link['url'] = str_replace('.',' [dot] ',$link['url']); + $link['url'] = str_replace('-',' [dash] ',$link['url']); + }elseif($conf['mailguard']=='hex'){ + for ($x=0; $x < strlen($link['url']); $x++) { + $encode .= '&#x' . bin2hex($link['url'][$x]).';'; + } + $link['url'] = $encode; + } + + $link['title'] = $link['url']; + if(!$link['name']) $link['name'] = $link['url']; + $link['url'] = 'mailto:'.$link['url']; + + return $link; +} + +/** + * format interwiki links + * + * @author Andreas Gohr + */ +function format_link_interwiki($link){ + global $conf; + + //obvious ones + $link['class'] = 'interwiki'; + $link['target'] = $conf['target']['interwiki']; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; + + //get interwiki short name + list($wiki,$link['url']) = split('>',$link['url'],2); + $wiki = strtolower(trim($wiki)); //always use lowercase + $link['url'] = trim($link['url']); + if(!$link['name']) $link['name'] = $link['url']; + + //encode special chars + $link['name'] = htmlspecialchars($link['name']); + + //set default to google + $url = 'http://www.google.com/search?q='; + $ico = 'google'; + + // Initialize as NULL - for the first fn call + static $iwlinks = NULL; + + // load interwikilinks if needed + if (!$iwlinks) $iwlinks = file('conf/interwiki.conf'); + + //add special case 'this' + $iwlinks[] = 'this '.DOKU_URL.'{NAME}'; + + //go through iwlinks and find URL for wiki + foreach ($iwlinks as $line){ + $line = preg_replace('/#.*/','',$line); //skip comments + $line = trim($line); + list($iw,$iwurl) = preg_split('/\s+/',$line); + if(!$iw or !$iwurl) continue; //skip broken or empty lines + //check for match + if(strtolower($iw) == $wiki){ + $ico = $wiki; + $url = $iwurl; + break; + } + } + + //if ico exists set additonal style + if(@file_exists('interwiki/'.$ico.'.png')){ + $link['style']='background: transparent url('.DOKU_BASE.'interwiki/'.$ico.'.png) 0px 1px no-repeat;'; + }elseif(@file_exists('interwiki/'.$ico.'.gif')){ + $link['style']='background: transparent url('.DOKU_BASE.'interwiki/'.$ico.'.gif) 0px 1px no-repeat;'; + } + + //do we stay at the same server? Use local target + if( strpos($url,DOKU_URL) === 0 ){ + $link['target'] = $conf['target']['wiki']; + } + + //replace placeholder + if(preg_match('#\{(URL|NAME|SCHEME|HOST|PORT|PATH|QUERY)\}#',$url)){ + //use placeholders + $url = str_replace('{URL}',urlencode($link['url']),$url); + $url = str_replace('{NAME}',$link['url'],$url); + $parsed = parse_url($link['url']); + if(!$parsed['port']) $parsed['port'] = 80; + $url = str_replace('{SCHEME}',$parsed['scheme'],$url); + $url = str_replace('{HOST}',$parsed['host'],$url); + $url = str_replace('{PORT}',$parsed['port'],$url); + $url = str_replace('{PATH}',$parsed['path'],$url); + $url = str_replace('{QUERY}',$parsed['query'],$url); + $link['url'] = $url; + }else{ + //default + $link['url'] = $url.urlencode($link['url']); + } + + $link['title'] = htmlspecialchars($link['url']); + + //done :-) + return $link; +} + +/** + * format embedded media + * + * @author Andreas Gohr + */ +function format_link_media($link){ + global $conf; + global $ID; + + $link['class'] = 'media'; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"'; + $class = 'media'; + + list($link['name'],$title) = split('\|',$link['name'],2); + $t = htmlspecialchars($title); + + //set alignment from spaces + if(substr($link['name'],0,1)==' ' && substr($link['name'],-1,1)==' '){ + $link['pre'] = "

\n
"; + $link['suf'] = "
\n

"; + }elseif(substr($link['name'],0,1)==' '){ + #$a = ' align="right"'; + $class = 'mediaright'; + }elseif(substr($link['name'],-1,1)==' '){ + #$a = ' align="left"'; + $class = 'medialeft'; + }else{ + $a = ' align="middle"'; + } + $link['name'] = trim($link['name']); + + //split into src and parameters (using the very last questionmark) + $pos = strrpos($link['name'], '?'); + if($pos !== false){ + $src = substr($link['name'],0,$pos); + $param = substr($link['name'],$pos+1); + }else{ + $src = $link['name']; + $param = ''; + } + + //parse width and height + if(preg_match('#(\d+)(x(\d+))?#i',$param,$size)){ + if($size[1]) $w = $size[1]; + if($size[3]) $h = $size[3]; + } + + //namespace mangling for internal images + if(!preg_match('#^https?://#i',$src)){ + $ns = getNS($ID); + //if src starts with . add current namespace + if(strpos($src,'.') === 0){ + $src = $ns.':'.substr($src,1); + } + //if src contains no namespace add current namespace if any + if($ns !== false && strpos($src,':') === false ){ + $src = $ns.':'.$src; + } + } + + //check for nocache/recache param + preg_match('/(nocache|recache)/i',$param,$cachemode); + + //do image caching, resizing and src rewriting + $cache = $src; + $isimg = img_cache($cache,$src,$w,$h,$cachemode[1]); + + //set link to src if none given + if(!$link['url']){ + $link['url'] = $src; + $link['target'] = $conf['target']['media']; + } + + //prepare name + if($isimg){ + $link['name'] = ''.$t.''; + }else{ + if($t){ + $link['name'] = $t; + }else{ + $link['name'] = basename($src); + } + } + + return $link; +} + +/** + * Build an URL list from a RSS feed + * + * Uses magpie + * + * @author Andreas Gohr + */ +function format_rss($url){ + global $lang; + define('MAGPIE_CACHE_ON', false); //we do our own caching + define('MAGPIE_DIR', 'inc/magpie/'); + define('MAGPIE_OUTPUT_ENCODING','UTF-8'); //return all feeds as UTF-8 + require_once(MAGPIE_DIR.'/rss_fetch.inc'); + + //disable warning while fetching + $elvl = error_reporting(E_ERROR); + $rss = fetch_rss($url); + error_reporting($elvl); + + $ret = '

    '; + if($rss){ + foreach ($rss->items as $item ) { + $link = array(); + $link['url'] = $item['link']; + $link['name'] = $item['title']; + $link = format_link_externalurl($link); + $ret .= '
  • '.format_link_build($link).'
  • '; + } + }else{ + $link['url'] = $url; + $link = format_link_externalurl($link); + $ret .= '
  • '; + $ret .= ''.$lang['rssfailed'].''; + $ret .= format_link_build($link); + $ret .= '
  • '; + } + $ret .= '
'; + return $ret; +} + +/** + * Create cache images + * + * @author Andreas Gohr + */ +function img_cache(&$csrc,&$src,&$w,&$h,$cachemode){ + global $conf; + + //container for various paths + $f['full']['web'] = $src; + $f['resz']['web'] = $src; + $f['full']['fs'] = $src; + $f['resz']['fs'] = $src; + + //generate cachename + $md5 = md5($src); + + //check if it is an image + if(preg_match('#\.(jpe?g|gif|png)$#i',$src,$match)){ + $ext = strtolower($match[1]); + $isimg = true; + } + + //check if it is external or a local mediafile + if(preg_match('#^([a-z0-9]+?)://#i',$src)){ + $isurl = true; + }else{ + $src = str_replace(':','/',$src); + $src = utf8_encodeFN($src); + $f['full']['web'] = $conf['mediaweb'].'/'.$src; + $f['resz']['web'] = $conf['mediaweb'].'/'.$src; + $f['full']['fs'] = $conf['mediadir'].'/'.$src; + $f['resz']['fs'] = $conf['mediadir'].'/'.$src; + } + + //download external images if allowed + if($isurl && $isimg && $cachemode != 'nocache'){ + $cache = $conf['mediadir']."/_cache/$md5.$ext"; + if ( ($cachemode == 'recache' && io_download($src,$cache)) || + @file_exists($cache) || io_download($src,$cache)){ + $f['full']['web'] = $conf['mediaweb']."/_cache/$md5.$ext"; + $f['resz']['web'] = $conf['mediaweb']."/_cache/$md5.$ext"; + $f['full']['fs'] = $conf['mediadir']."/_cache/$md5.$ext"; + $f['resz']['fs'] = $conf['mediadir']."/_cache/$md5.$ext"; + $isurl = false; + } + } + + //for local images (cached or media) do resizing + if($isimg && (!$isurl)){ + if($w){ + $info = getImageSize($f['full']['fs']); + //if $h not given calcualte it with correct aspect ratio + if(!$h){ + $h = round(($w * $info[1]) / $info[0]); + } + $cache = $conf['mediadir'].'/_cache/'.$md5.'.'.$w.'x'.$h.'.'.$ext; + //delete outdated cachefile + if(@file_exists($cache) && (filemtime($cache) + */ +function img_resize($ext,$from,$from_w,$from_h,$to,$to_w,$to_h){ + global $conf; + + if($conf['gdlib'] < 1) return false; //no GDlib available or wanted + + // create an image of the given filetype + if ($ext == 'jpg' || $ext == 'jpeg'){ + if(!function_exists("imagecreatefromjpeg")) return false; + $image = @imagecreateFromjpeg($from); + }elseif($ext == 'png') { + if(!function_exists("imagecreatefrompng")) return false; + $image = @imagecreatefrompng($from); + }elseif($ext == 'gif') { + if(!function_exists("imagecreatefromgif")) return false; + $image = @imagecreatefromgif($from); + } + if(!$image) return false; + + if(($conf['gdlib']>1) && function_exists("imagecreatetruecolor")){ + $newimg = @imagecreatetruecolor ($to_w, $to_h); + } + if(!$newimg) $newimg = @imagecreate($to_w, $to_h); + if(!$newimg) return false; + + // create cachedir + io_makeFileDir($to); + + //try resampling first + if(function_exists("imagecopyresampled")){ + if(!@imagecopyresampled($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h)) { + imagecopyresized($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h); + } + }else{ + imagecopyresized($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h); + } + + if ($ext == 'jpg' || $ext == 'jpeg'){ + if(!function_exists("imagejpeg")) return false; + return imagejpeg($newimg, $to, 70); + }elseif($ext == 'png') { + if(!function_exists("imagepng")) return false; + return imagepng($newimg, $to); + }elseif($ext == 'gif') { + if(!function_exists("imagegif")) return false; + return imagegif($newimg, $to); + } + + return false; +} + + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/inc/parser.php b/inc/parser.php deleted file mode 100644 index 8f4a188b7..000000000 --- a/inc/parser.php +++ /dev/null @@ -1,862 +0,0 @@ - - * @deprecated replaced by the new parser - */ - -trigger_error('deprecated parser.php included'); - - if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); - include_once(DOKU_INC.'inc/common.php'); - include_once(DOKU_INC.'inc/html.php'); - include_once(DOKU_INC.'inc/format.php'); - require_once(DOKU_INC.'lang/en/lang.php'); - require_once(DOKU_INC.'lang/'.$conf['lang'].'/lang.php'); - -/** - * The main parser function. - * - * Accepts raw data and returns valid xhtml - * - * @author Andreas Gohr - */ -function parse($text){ - global $parser; - global $conf; - $table = array(); - $hltable = array(); - - //preparse - $text = preparse($text,$table,$hltable); - - //padding with a newline - $text = "\n".$text."\n"; - - #for link matching - $urls = '(https?|telnet|gopher|file|wais|ftp|ed2k|irc)'; - $ltrs = '\w'; - $gunk = '/\#~:.?+=&%@!\-'; - $punc = '.:?\-;,'; - $host = $ltrs.$punc; - $any = $ltrs.$gunk.$punc; - - /* first pass */ - - //preformated texts - firstpass($table,$text,"#(.*?)#se","preformat('\\1','nowiki')"); - firstpass($table,$text,"#%%(.*?)%%#se","preformat('\\1','nowiki')"); - firstpass($table,$text,"#(.*?)#se","preformat('\\3','code','\\2')"); - firstpass($table,$text,"#(.*?)#se","preformat('\\1','file')"); - - // html and php includes - firstpass($table,$text,"#(.*?)#se","preformat('\\1','html')"); - firstpass($table,$text,"#(.*?)#se","preformat('\\1','php')"); - - // codeblocks - firstpass($table,$text,"/(\n( {2,}|\t)[^\*\-\n ][^\n]+)(\n( {2,}|\t)[^\n]*)*/se","preformat('\\0','block')","\n"); - - //check if toc is wanted - if(!isset($parser['toc'])){ - if(strpos($text,'~~NOTOC~~')!== false){ - $text = str_replace('~~NOTOC~~','',$text); - $parser['toc'] = false; - }else{ - $parser['toc'] = true; - } - } - - //check if this file may be cached - if(!isset($parser['cache'])){ - if(strpos($text,'~~NOCACHE~~')!=false){ - $text = str_replace('~~NOCACHE~~','',$text); - $parser['cache'] = false; - }else{ - $parser['cache'] = true; - } - } - - //headlines - format_headlines($table,$hltable,$text); - - //links - firstpass($table,$text,"#\[\[([^\]]+?)\]\]#ie","linkformat('\\1')"); - - //media - firstpass($table,$text,"/\{\{([^\}]+)\}\}/se","mediaformat('\\1')"); - - //match full URLs (adapted from Perl cookbook) - firstpass($table,$text,"#(\b)($urls://[$any]+?)([$punc]*[^$any])#ie","linkformat('\\2')",'\1','\4'); - - //short www URLs - firstpass($table,$text,"#(\b)(www\.[$host]+?\.[$host]+?[$any]+?)([$punc]*[^$any])#ie","linkformat('http://\\2|\\2')",'\1','\3'); - - //windows shares - firstpass($table,$text,"#([$gunk$punc\s])(\\\\\\\\[$host]+?\\\\[$any]+?)([$punc]*[^$any])#ie","linkformat('\\2')",'\1','\3'); - - //short ftp URLs - firstpass($table,$text,"#(\b)(ftp\.[$host]+?\.[$host]+?[$any]+?)([$punc]*[^$any])#ie","linkformat('ftp://\\2')",'\1','\3'); - - // email@domain.tld - firstpass($table,$text,"#<([\w0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)>#ie", "linkformat('\\1@\\2')"); - - //CamelCase if wanted - if($conf['camelcase']){ - firstpass($table,$text,"#(\b)([A-Z]+[a-z]+[A-Z][A-Za-z]*)(\b)#se","linkformat('\\2')",'\1','\3'); - } - - $text = htmlspecialchars($text); - - //smileys - smileys($table,$text); - - //acronyms - acronyms($table,$text); - - /* second pass for simple formating */ - $text = simpleformat($text); - - /* third pass - insert the matches from 1st pass */ - reset($table); - while (list($key, $val) = each($table)) { - $text = str_replace($key,$val,$text); - } - - /* remove empty paragraphs */ - $text = preg_replace('"

\n*

"','',$text); - - /* remove padding */ - $text = trim($text); - return $text; -} - -/** - * Line by line preparser - * - * This preparses the text by walking it line by line. This - * is the only place where linenumbers are still available (needed - * for section edit. Some precautions have to be taken to not change - * any noparse block. - * - * @author Andreas Gohr - */ -function preparse($text,&$table,&$hltable){ - $lines = split("\n",$text); - - //prepare a tokens for paragraphs - $po = mkToken(); - $table[$po] = "

"; - $pc = mkToken(); - $table[$pc] = "

"; - - for ($l=0; $l(.*?)#","",$line); - $line = preg_replace("#%%(.*?)%%#","",$line); - $line = preg_replace("#(.*?)#","",$line); - $line = preg_replace("#<(file|html|php)>(.*?)#","",$line); - //check for start of multiline noparse areas - if(preg_match('#^.*?<(nowiki|code|php|html|file)( (\w+))?>#',$line,$matches)){ - list($noparse) = split(" ",$matches[1]); //remove options - $noparse = ''; - continue; - }elseif(preg_match('#^.*?%%#',$line)){ - $noparse = '%%'; - continue; - } - } - - //handle headlines - if(preg_match('/^(\s)*(==+)(.+?)(==+)(\s*)$/',$lines[$l],$matches)){ - //get token - $tk = tokenize_headline($hltable,$matches[2],$matches[3],$l); - //replace line with token - $lines[$l] = $tk; - } - - //handle paragraphs - if(empty($lines[$l])){ - $lines[$l] = "$pc\n$po"; - } - } - - //reassemble full text - $text = join("\n",$lines); - //open first and close last paragraph - $text = "$po\n$text\n$pc"; - - return $text; -} - -/** - * Build TOC lookuptable - * - * This function adds some information about the given headline - * to a lookuptable to be processed later. Returns a unique token - * that idetifies the headline later - * - * @author Andreas Gohr - */ -function tokenize_headline(&$hltable,$pre,$hline,$lno){ - switch (strlen($pre)){ - case 2: - $lvl = 5; - break; - case 3: - $lvl = 4; - break; - case 4: - $lvl = 3; - break; - case 5: - $lvl = 2; - break; - default: - $lvl = 1; - break; - } - $token = mkToken(); - $hltable[] = array( 'name' => htmlspecialchars(trim($hline)), - 'level' => $lvl, - 'line' => $lno, - 'token' => $token ); - return $token; -} - -/** - * Headline formatter - * - * @author Andreas Gohr - */ -function format_headlines(&$table,&$hltable,&$text){ - global $parser; - global $conf; - global $lang; - global $ID; - - // walk the headline table prepared in preparsing - $last = 0; - $cnt = 0; - $hashs = array(); - foreach($hltable as $hl){ - $cnt++; - - //make unique headlinehash - $hash = cleanID($hl['name']); - $i=2; - while(in_array($hash,$hashs)) - $hash = cleanID($hl['name']).$i++; - $hashs[] = $hash; - - // build headline - $headline = "

\n"; //close paragraph - if($cnt - 1) $headline .= ''; //no close on first HL - $headline .= '
'; - $headline .= ''; - $headline .= $hl['name']; - $headline .= ''; - $headline .= '
'; - $headline .= "\n

"; //open new paragraph - - //remember for autoTOC - if($hl['level'] <= $conf['maxtoclevel']){ - $content[] = array('id' => $hash, - 'name' => $hl['name'], - 'level' => $hl['level']); - } - - //add link for section edit for HLs 1, and 3 - if( ($hl['level'] <= $conf['maxseclevel']) && - ($hl['line'] - $last > 1)){ - $secedit = ''; - $headline = $secedit.$headline; - $last = $hl['line']; - } - - //put headline into firstpasstable - $table[$hl['token']] = $headline; - } - - //add link for editing the last section - if($last){ - $secedit = ''; - $token = mktoken(); - $text .= $token; - $table[$token] = $secedit; - } - - //close last div - if ($cnt){ - $token = mktoken(); - $text .= $token; - $table[$token] = '

'; - } - - //prepend toc - if ($parser['toc'] && count($content) > 2){ - $token = mktoken(); - $text = $token.$text; - $table[$token] = html_toc($content); - } -} - -/** - * Formats various link types using the functions from format.php - * - * @author Andreas Gohr - */ -function linkformat($match){ - global $conf; - //unescape - $match = str_replace('\\"','"',$match); - - //prepare variables for the formaters - $link = array(); - list($link['url'],$link['name']) = split('\|',$match,2); - $link['url'] = trim($link['url']); - $link['name'] = trim($link['name']); - $link['class'] = ''; - $link['target'] = ''; - $link['style'] = ''; - $link['pre'] = ''; - $link['suf'] = ''; - $link['more'] = ''; - - //save real name for image check - $realname = $link['name']; - - /* put it into the right formater */ - if(strpos($link['url'],'>')){ - // InterWiki - $link = format_link_interwiki($link); - }elseif(preg_match('#^([a-z0-9]+?)://#i',$link['url'])){ - // external URL - $link = format_link_externalurl($link); - }elseif(preg_match("/^\\\\\\\\([a-z0-9\-_.]+)\\\\(.+)$/",$link['url'])){ - // windows shares - $link = format_link_windows($link); - }elseif(preg_match('#([a-z0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i',$link['url'])){ - // email - $link = format_link_email($link); - }else{ - // wiki link - $link = format_link_wiki($link); - } - - //is realname an image? use media formater - if(preg_match('#^{{.*?\.(gif|png|jpe?g)(\?.*?)?\s*(\|.*?)?}}$#',$realname)){ - $link['name'] = substr($realname,2,-2); - $link = format_link_media($link); - } - - // build the replacement with the variables set by the formaters - return format_link_build($link); -} - -/** - * Simple text formating and typography is done here - * - * @author Andreas Gohr - */ -function simpleformat($text){ - global $conf; - - $text = preg_replace('/__(.+?)__/s','\1',$text); //underline - $text = preg_replace('/\/\/(.+?)\/\//s','\1',$text); //emphasize - $text = preg_replace('/\*\*(.+?)\*\*/s','\1',$text); //bold - $text = preg_replace('/\'\'(.+?)\'\'/s','\1',$text); //code - $text = preg_replace('#<del>(.*?)</del>#is','\1',$text); //deleted - $text = preg_replace('/^\s*----+\s*$/m',"

\n
\n

",$text); //hr - - //sub and superscript - $text = preg_replace('#<su([bp])>(.*?)</su\1>#is','\2',$text); - - //do quoting - $text = preg_replace("/\n((>)[^\n]*?\n)+/se","'\n'.quoteformat('\\0').'\n'",$text); - - // Typography - if($conf['typography']){ - $text = preg_replace('/(?> - $text = preg_replace('/<</i','«',$text); // << - - $text = preg_replace('/<->/i','↔',$text); // <-> - $text = preg_replace('/<-/i','←',$text); // <- - $text = preg_replace('/->/i','→',$text); // -> - - $text = preg_replace('/<=>/i','⇔',$text); // <=> - $text = preg_replace('/<=/i','⇐',$text); // <= - $text = preg_replace('/=>/i','⇒',$text); // => - - $text = preg_replace('/\(c\)/i','©',$text); // copyrigtht - $text = preg_replace('/\(r\)/i','®',$text); // registered - $text = preg_replace('/\(tm\)/i','™',$text); // trademark - } - - //forced linebreaks - $text = preg_replace('#\\\\\\\\(?=\s)#',"
",$text); - - // lists (blocks leftover after blockformat) - $text = preg_replace("/(\n( {2,}|\t)[\*\-][^\n]+)(\n( {2,}|\t)[^\n]*)*/se","\"\\n\".listformat('\\0')",$text); - - // tables - $text = preg_replace("/\n(([\|\^][^\n]*?)+[\|\^] *\n)+/se","\"\\n\".tableformat('\\0')",$text); - - // footnotes - $text = footnotes($text); - - // run custom text replacements - $text = customs($text); - - return $text; -} - -/** - * Footnote formating - * - * @author Andreas Gohr - */ -function footnotes($text){ - $num = 0; - while (preg_match('/\(\((.+?)\)\)/s',$text,$match)){ - $num++; - $fn = $match[1]; - $linkt = ''.$num.')'; - $linkb = ''.$num.')'; - - $text = preg_replace('/ ?\(\((.+?)\)\)/s',$linkt,$text,1); - if($num == 1) $text .= '

'; - $text .= '
'.$linkb.' '.$fn.'
'; - } - - if($num) $text .= '
'; - return $text; -} - -/** - * Replace smileys with their graphic equivalents - * - * @author Andreas Gohr - */ -function smileys(&$table,&$text){ - $smileys = file('conf/smileys.conf'); - foreach($smileys as $smiley){ - $smiley = preg_replace('/#.*$/','',$smiley); //ignore comments - $smiley = trim($smiley); - if(empty($smiley)) continue; - $sm = preg_split('/\s+/',$smiley,2); - $sm[1] = ''.$sm[0].''; - $sm[0] = preg_quote($sm[0],'/'); - firstpass($table,$text,'/(? - */ -function acronyms(&$table,&$text){ - $acronyms = file('conf/acronyms.conf'); - foreach($acronyms as $acro){ - $acro = preg_replace('/#.*$/','',$acro); //ignore comments - $acro = trim($acro); - if(empty($acro)) continue; - list($ac,$desc) = preg_split('/\s+/',$acro,2); - $ac = preg_quote($ac,'/'); - firstpass($table,$text,'/\b('.$ac.')\b/s',"\\1"); - } -} - -/** - * Apply custom text replacements - * - * @author Andreas Gohr - */ -function customs($text){ - $reps = file ('conf/custom.conf'); - foreach($reps as $rep){ - //strip comments only outside a regexp - $rep = preg_replace('/#[^\/]*$/','',$rep); //ignore comments - $rep = trim($rep); - if(empty($rep)) continue; - if(preg_match('#^(/.+/\w*)\s+\'(.*)\'$#',$rep,$matches)){ - $text = preg_replace($matches[1],$matches[2],$text); - } - } - return $text; -} - -/** - * Replace regexp with token - * - * @author Andreas Gohr - */ -function firstpass(&$table,&$text,$regexp,$replace,$lpad='',$rpad=''){ - //extended regexps have to be disabled for inserting the token - //and later reenabled when handling the actual code: - $ext=''; - if(substr($regexp,-1) == 'e'){ - $ext='e'; - $regexp = substr($regexp,0,-1); - } - - while(preg_match($regexp,$text,$matches)){ - $token = mkToken(); - $match = $matches[0]; - $text = preg_replace($regexp,$lpad.$token.$rpad,$text,1); - $table[$token] = preg_replace($regexp.$ext,$replace,$match); - } -} - -/** - * create a random and hopefully unique token - * - * @author Andreas Gohr - */ -function mkToken(){ - return '~'.md5(uniqid(rand(), true)).'~'; -} - -/** - * Do quote blocks - * - * @author Andreas Gohr - */ -function quoteformat($block){ - $block = trim($block); - $lines = split("\n",$block); - - $lvl = 0; - $ret = ""; - foreach ($lines as $line){ - //remove '>' and count them - $cnt = 0; - while(substr($line,0,4) == '>'){ - $line = substr($line,4); - $cnt++; - } - //compare to last level and open or close new divs if needed - if($cnt > $lvl){ - $ret .= "

\n"; - for ($i=0; $i< $cnt - $lvl; $i++){ - $ret .= '
'; - } - $ret .= "\n

"; - }elseif($cnt < $lvl){ - $ret .= "\n

"; - for ($i=0; $i< $lvl - $cnt; $i++){ - $ret .= "
\n"; - } - $ret .= "

\n"; - }elseif(empty($line)){ - $ret .= "

\n

"; - } - //keep rest of line but trim left whitespaces - $ret .= ltrim($line)."\n"; - //remember level - $lvl = $cnt; - } - - //close remaining divs - $ret .= "

\n"; - for ($i=0; $i< $lvl; $i++){ - $ret .= "\n"; - } - $ret .= "

\n"; - - return "$ret"; -} - -/** - * format inline tables - * - * @author Andreas Gohr - * @author Aaron Evans - */ -function tableformat($block) { - $block = trim($block); - $lines = split("\n",$block); - $ret = ""; - //build a row array - $rows = array(); - for($r=0; $r < count($lines); $r++){ - $line = $lines[$r]; - //remove last seperator and trailing whitespace - $line = preg_replace('/[\|\^]\s*$/', '', $line); - $c = -1; //prepare colcounter) - for($chr=0; $chr < strlen($line); $chr++){ - if($line[$chr] == '^'){ - $c++; - $rows[$r][$c]['head'] = true; - $rows[$r][$c]['data'] = ''; - }elseif($line[$chr] == '|'){ - $c++; - $rows[$r][$c]['head'] = false; - $rows[$r][$c]['data'] = ''; - }else{ - $rows[$r][$c]['data'].= $line[$chr]; - } - } - } - - //build table - $ret .= "

\n\n"; - for($r=0; $r < count($rows); $r++){ - $ret .= " \n"; - - for ($c=0; $c < count($rows[$r]); $c++){ - $cspan=1; - $data = $rows[$r][$c]['data']; - $head = $rows[$r][$c]['head']; - - //join cells if next is empty - while($c < count($rows[$r])-1 && $rows[$r][$c+1]['data'] == ''){ - $c++; - $cspan++; - } - if($cspan > 1){ - $cspan = 'colspan="'.$cspan.'"'; - }else{ - $cspan = ''; - } - - //determine alignment from whitespace - if (preg_match('/^\s\s/', $data)) { // right indentation - $td_class = "rightalign"; - if (preg_match('/\s\s$/', $data)) { // both left and right indentation - $td_class = "centeralign"; - } - } else { // left indentation (default) - $td_class = "leftalign"; - } - - $data = trim($data); - if ($head) { - $ret .= " \n"; // set css class for alignment - } else { - $ret .= " \n"; // set css class for alignment - } - } - $ret .= " \n"; - } - $ret .= "
$data $data

\n

"; - - return $ret; -} - -/** - * format lists - * - * @author Andreas Gohr - */ -function listformat($block){ - //remove 1st newline - $block = substr($block,1); - //unescape - $block = str_replace('\\"','"',$block); - -//dbg($block); - - //walk line by line - $ret=''; - $lst=0; - $lvl=0; - $enc=0; - $lines = split("\n",$block); - - //build an item array - $cnt=0; - $items = array(); - foreach ($lines as $line){ - //get intendion level - $lvl = 0; - $lvl += floor(strspn($line,' ')/2); - $lvl += strspn($line,"\t"); - //remove indents - $line = preg_replace('/^[ \t]+/','',$line); - //get type of list - (substr($line,0,1) == '-') ? $type='ol' : $type='ul'; - // remove bullet and following spaces - $line = preg_replace('/^[*\-]\s*/','',$line); - //add item to the list - $items[$cnt]['level'] = $lvl; - $items[$cnt]['type'] = $type; - $items[$cnt]['text'] = $line; - //increase counter - $cnt++; - } - - $level = 0; - $opens = array(); - - foreach ($items as $item){ - if( $item['level'] > $level ){ - //open new list - $ret .= "\n<".$item['type'].">\n"; - array_push($opens,$item['type']); - }elseif( $item['level'] < $level ){ - //close last item - $ret .= "\n"; - for ($i=0; $i<($level - $item['level']); $i++){ - //close higher lists - $ret .= '\n\n"; - } - }elseif($item['type'] != $opens[count($opens)-1]){ - //close last list and open new - $ret .= '\n\n"; - $ret .= "\n<".$item['type'].">\n"; - array_push($opens,$item['type']); - }else{ - //close last item - $ret .= "\n"; - } - - //remember current level and type - $level = $item['level']; - - //print item - $ret .= '

  • '; - $ret .= ''.$item['text'].''; - } - - //close remaining items and lists - while ($open = array_pop($opens)){ - $ret .= "
  • \n"; - $ret .= '\n"; - } - return "

    \n".$ret."\n

    "; -} - -/** - * Handle preformatted blocks - * - * Uses GeSHi for syntax highlighting - * - * @author Andreas Gohr - */ -function preformat($text,$type,$option=''){ - global $conf; - global $lang; - //unescape - $text = str_replace('\\"','"',$text); - - if($type == 'php' && !$conf['phpok']) $type='file'; - if($type == 'html' && !$conf['htmlok']) $type='file'; - - switch ($type){ - case 'php': - ob_start(); - eval($text); - $text = ob_get_contents(); - ob_end_clean(); - break; - case 'html': - break; - case 'nowiki': - $text = htmlspecialchars($text); - break; - case 'file': - $text = htmlspecialchars($text); - $text = "

    \n
    ".$text."
    \n

    "; - break; - case 'code': - if(empty($option)){ - $text = htmlspecialchars($text); - $text = '

    '.$text.'
    '; - }else{ - //strip leading blank line - $text = preg_replace('/^\s*?\n/','',$text); - //use geshi for highlighting - require_once("inc/geshi.php"); - $geshi = new GeSHi($text, strtolower($option), "inc/geshi"); - $geshi->set_encoding($lang['encoding']); - $geshi->enable_classes(); - $geshi->set_header_type(GESHI_HEADER_PRE); - $geshi->set_overall_class('code'); - $geshi->set_link_target($conf['target']['extern']); - $text = $geshi->parse_code(); - } - $text = "

    \n".$text."\n

    "; - break; - case 'block': - $text = substr($text,1); //remove 1st newline - $lines = split("\n",$text); //break into lines - $text = ''; - foreach($lines as $line){ - $text .= substr($line,2)."\n"; //remove indents - } - $text = htmlspecialchars($text); - $text = "

    \n
    ".$text."
    \n

    "; - break; - } - return $text; -} - -/** - * Format embedded media (images) - * - * @author Andreas Gohr - */ -function mediaformat($text){ - global $conf; - - //unescape - $text = str_replace('\\"','"',$text); - - // format RSS - if(substr($text,0,4) == 'rss>'){ - return format_rss(substr($text,4)); - } - - //handle normal media stuff - $link = array(); - $link['name'] = $text; - $link = format_link_media($link); - return format_link_build($link); -} - -/** - * Get first heading, to be used as a page title - * - * @author Jan Decaluwe - */ -function getFirstHeading($text){ - $title = ''; - $lines = split("\n",$text); - foreach($lines as $line){ - if(preg_match('/^\s*==+(.+?)==+\s*$/',$line,$matches)){ - $title = $matches[1]; - break; - } - } - return $title; -} - - -//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/inc/parser.php.bak b/inc/parser.php.bak new file mode 100644 index 000000000..8f4a188b7 --- /dev/null +++ b/inc/parser.php.bak @@ -0,0 +1,862 @@ + + * @deprecated replaced by the new parser + */ + +trigger_error('deprecated parser.php included'); + + if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); + include_once(DOKU_INC.'inc/common.php'); + include_once(DOKU_INC.'inc/html.php'); + include_once(DOKU_INC.'inc/format.php'); + require_once(DOKU_INC.'lang/en/lang.php'); + require_once(DOKU_INC.'lang/'.$conf['lang'].'/lang.php'); + +/** + * The main parser function. + * + * Accepts raw data and returns valid xhtml + * + * @author Andreas Gohr + */ +function parse($text){ + global $parser; + global $conf; + $table = array(); + $hltable = array(); + + //preparse + $text = preparse($text,$table,$hltable); + + //padding with a newline + $text = "\n".$text."\n"; + + #for link matching + $urls = '(https?|telnet|gopher|file|wais|ftp|ed2k|irc)'; + $ltrs = '\w'; + $gunk = '/\#~:.?+=&%@!\-'; + $punc = '.:?\-;,'; + $host = $ltrs.$punc; + $any = $ltrs.$gunk.$punc; + + /* first pass */ + + //preformated texts + firstpass($table,$text,"#(.*?)#se","preformat('\\1','nowiki')"); + firstpass($table,$text,"#%%(.*?)%%#se","preformat('\\1','nowiki')"); + firstpass($table,$text,"#(.*?)#se","preformat('\\3','code','\\2')"); + firstpass($table,$text,"#(.*?)#se","preformat('\\1','file')"); + + // html and php includes + firstpass($table,$text,"#(.*?)#se","preformat('\\1','html')"); + firstpass($table,$text,"#(.*?)#se","preformat('\\1','php')"); + + // codeblocks + firstpass($table,$text,"/(\n( {2,}|\t)[^\*\-\n ][^\n]+)(\n( {2,}|\t)[^\n]*)*/se","preformat('\\0','block')","\n"); + + //check if toc is wanted + if(!isset($parser['toc'])){ + if(strpos($text,'~~NOTOC~~')!== false){ + $text = str_replace('~~NOTOC~~','',$text); + $parser['toc'] = false; + }else{ + $parser['toc'] = true; + } + } + + //check if this file may be cached + if(!isset($parser['cache'])){ + if(strpos($text,'~~NOCACHE~~')!=false){ + $text = str_replace('~~NOCACHE~~','',$text); + $parser['cache'] = false; + }else{ + $parser['cache'] = true; + } + } + + //headlines + format_headlines($table,$hltable,$text); + + //links + firstpass($table,$text,"#\[\[([^\]]+?)\]\]#ie","linkformat('\\1')"); + + //media + firstpass($table,$text,"/\{\{([^\}]+)\}\}/se","mediaformat('\\1')"); + + //match full URLs (adapted from Perl cookbook) + firstpass($table,$text,"#(\b)($urls://[$any]+?)([$punc]*[^$any])#ie","linkformat('\\2')",'\1','\4'); + + //short www URLs + firstpass($table,$text,"#(\b)(www\.[$host]+?\.[$host]+?[$any]+?)([$punc]*[^$any])#ie","linkformat('http://\\2|\\2')",'\1','\3'); + + //windows shares + firstpass($table,$text,"#([$gunk$punc\s])(\\\\\\\\[$host]+?\\\\[$any]+?)([$punc]*[^$any])#ie","linkformat('\\2')",'\1','\3'); + + //short ftp URLs + firstpass($table,$text,"#(\b)(ftp\.[$host]+?\.[$host]+?[$any]+?)([$punc]*[^$any])#ie","linkformat('ftp://\\2')",'\1','\3'); + + // email@domain.tld + firstpass($table,$text,"#<([\w0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)>#ie", "linkformat('\\1@\\2')"); + + //CamelCase if wanted + if($conf['camelcase']){ + firstpass($table,$text,"#(\b)([A-Z]+[a-z]+[A-Z][A-Za-z]*)(\b)#se","linkformat('\\2')",'\1','\3'); + } + + $text = htmlspecialchars($text); + + //smileys + smileys($table,$text); + + //acronyms + acronyms($table,$text); + + /* second pass for simple formating */ + $text = simpleformat($text); + + /* third pass - insert the matches from 1st pass */ + reset($table); + while (list($key, $val) = each($table)) { + $text = str_replace($key,$val,$text); + } + + /* remove empty paragraphs */ + $text = preg_replace('"

    \n*

    "','',$text); + + /* remove padding */ + $text = trim($text); + return $text; +} + +/** + * Line by line preparser + * + * This preparses the text by walking it line by line. This + * is the only place where linenumbers are still available (needed + * for section edit. Some precautions have to be taken to not change + * any noparse block. + * + * @author Andreas Gohr + */ +function preparse($text,&$table,&$hltable){ + $lines = split("\n",$text); + + //prepare a tokens for paragraphs + $po = mkToken(); + $table[$po] = "

    "; + $pc = mkToken(); + $table[$pc] = "

    "; + + for ($l=0; $l(.*?)#","",$line); + $line = preg_replace("#%%(.*?)%%#","",$line); + $line = preg_replace("#(.*?)#","",$line); + $line = preg_replace("#<(file|html|php)>(.*?)#","",$line); + //check for start of multiline noparse areas + if(preg_match('#^.*?<(nowiki|code|php|html|file)( (\w+))?>#',$line,$matches)){ + list($noparse) = split(" ",$matches[1]); //remove options + $noparse = ''; + continue; + }elseif(preg_match('#^.*?%%#',$line)){ + $noparse = '%%'; + continue; + } + } + + //handle headlines + if(preg_match('/^(\s)*(==+)(.+?)(==+)(\s*)$/',$lines[$l],$matches)){ + //get token + $tk = tokenize_headline($hltable,$matches[2],$matches[3],$l); + //replace line with token + $lines[$l] = $tk; + } + + //handle paragraphs + if(empty($lines[$l])){ + $lines[$l] = "$pc\n$po"; + } + } + + //reassemble full text + $text = join("\n",$lines); + //open first and close last paragraph + $text = "$po\n$text\n$pc"; + + return $text; +} + +/** + * Build TOC lookuptable + * + * This function adds some information about the given headline + * to a lookuptable to be processed later. Returns a unique token + * that idetifies the headline later + * + * @author Andreas Gohr + */ +function tokenize_headline(&$hltable,$pre,$hline,$lno){ + switch (strlen($pre)){ + case 2: + $lvl = 5; + break; + case 3: + $lvl = 4; + break; + case 4: + $lvl = 3; + break; + case 5: + $lvl = 2; + break; + default: + $lvl = 1; + break; + } + $token = mkToken(); + $hltable[] = array( 'name' => htmlspecialchars(trim($hline)), + 'level' => $lvl, + 'line' => $lno, + 'token' => $token ); + return $token; +} + +/** + * Headline formatter + * + * @author Andreas Gohr + */ +function format_headlines(&$table,&$hltable,&$text){ + global $parser; + global $conf; + global $lang; + global $ID; + + // walk the headline table prepared in preparsing + $last = 0; + $cnt = 0; + $hashs = array(); + foreach($hltable as $hl){ + $cnt++; + + //make unique headlinehash + $hash = cleanID($hl['name']); + $i=2; + while(in_array($hash,$hashs)) + $hash = cleanID($hl['name']).$i++; + $hashs[] = $hash; + + // build headline + $headline = "

    \n"; //close paragraph + if($cnt - 1) $headline .= ''; //no close on first HL + $headline .= ''; + $headline .= ''; + $headline .= $hl['name']; + $headline .= ''; + $headline .= '
    '; + $headline .= "\n

    "; //open new paragraph + + //remember for autoTOC + if($hl['level'] <= $conf['maxtoclevel']){ + $content[] = array('id' => $hash, + 'name' => $hl['name'], + 'level' => $hl['level']); + } + + //add link for section edit for HLs 1, and 3 + if( ($hl['level'] <= $conf['maxseclevel']) && + ($hl['line'] - $last > 1)){ + $secedit = ''; + $headline = $secedit.$headline; + $last = $hl['line']; + } + + //put headline into firstpasstable + $table[$hl['token']] = $headline; + } + + //add link for editing the last section + if($last){ + $secedit = ''; + $token = mktoken(); + $text .= $token; + $table[$token] = $secedit; + } + + //close last div + if ($cnt){ + $token = mktoken(); + $text .= $token; + $table[$token] = '

    '; + } + + //prepend toc + if ($parser['toc'] && count($content) > 2){ + $token = mktoken(); + $text = $token.$text; + $table[$token] = html_toc($content); + } +} + +/** + * Formats various link types using the functions from format.php + * + * @author Andreas Gohr + */ +function linkformat($match){ + global $conf; + //unescape + $match = str_replace('\\"','"',$match); + + //prepare variables for the formaters + $link = array(); + list($link['url'],$link['name']) = split('\|',$match,2); + $link['url'] = trim($link['url']); + $link['name'] = trim($link['name']); + $link['class'] = ''; + $link['target'] = ''; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = ''; + + //save real name for image check + $realname = $link['name']; + + /* put it into the right formater */ + if(strpos($link['url'],'>')){ + // InterWiki + $link = format_link_interwiki($link); + }elseif(preg_match('#^([a-z0-9]+?)://#i',$link['url'])){ + // external URL + $link = format_link_externalurl($link); + }elseif(preg_match("/^\\\\\\\\([a-z0-9\-_.]+)\\\\(.+)$/",$link['url'])){ + // windows shares + $link = format_link_windows($link); + }elseif(preg_match('#([a-z0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i',$link['url'])){ + // email + $link = format_link_email($link); + }else{ + // wiki link + $link = format_link_wiki($link); + } + + //is realname an image? use media formater + if(preg_match('#^{{.*?\.(gif|png|jpe?g)(\?.*?)?\s*(\|.*?)?}}$#',$realname)){ + $link['name'] = substr($realname,2,-2); + $link = format_link_media($link); + } + + // build the replacement with the variables set by the formaters + return format_link_build($link); +} + +/** + * Simple text formating and typography is done here + * + * @author Andreas Gohr + */ +function simpleformat($text){ + global $conf; + + $text = preg_replace('/__(.+?)__/s','\1',$text); //underline + $text = preg_replace('/\/\/(.+?)\/\//s','\1',$text); //emphasize + $text = preg_replace('/\*\*(.+?)\*\*/s','\1',$text); //bold + $text = preg_replace('/\'\'(.+?)\'\'/s','\1',$text); //code + $text = preg_replace('#<del>(.*?)</del>#is','\1',$text); //deleted + $text = preg_replace('/^\s*----+\s*$/m',"

    \n
    \n

    ",$text); //hr + + //sub and superscript + $text = preg_replace('#<su([bp])>(.*?)</su\1>#is','\2',$text); + + //do quoting + $text = preg_replace("/\n((>)[^\n]*?\n)+/se","'\n'.quoteformat('\\0').'\n'",$text); + + // Typography + if($conf['typography']){ + $text = preg_replace('/(?> + $text = preg_replace('/<</i','«',$text); // << + + $text = preg_replace('/<->/i','↔',$text); // <-> + $text = preg_replace('/<-/i','←',$text); // <- + $text = preg_replace('/->/i','→',$text); // -> + + $text = preg_replace('/<=>/i','⇔',$text); // <=> + $text = preg_replace('/<=/i','⇐',$text); // <= + $text = preg_replace('/=>/i','⇒',$text); // => + + $text = preg_replace('/\(c\)/i','©',$text); // copyrigtht + $text = preg_replace('/\(r\)/i','®',$text); // registered + $text = preg_replace('/\(tm\)/i','™',$text); // trademark + } + + //forced linebreaks + $text = preg_replace('#\\\\\\\\(?=\s)#',"
    ",$text); + + // lists (blocks leftover after blockformat) + $text = preg_replace("/(\n( {2,}|\t)[\*\-][^\n]+)(\n( {2,}|\t)[^\n]*)*/se","\"\\n\".listformat('\\0')",$text); + + // tables + $text = preg_replace("/\n(([\|\^][^\n]*?)+[\|\^] *\n)+/se","\"\\n\".tableformat('\\0')",$text); + + // footnotes + $text = footnotes($text); + + // run custom text replacements + $text = customs($text); + + return $text; +} + +/** + * Footnote formating + * + * @author Andreas Gohr + */ +function footnotes($text){ + $num = 0; + while (preg_match('/\(\((.+?)\)\)/s',$text,$match)){ + $num++; + $fn = $match[1]; + $linkt = ''.$num.')'; + $linkb = ''.$num.')'; + + $text = preg_replace('/ ?\(\((.+?)\)\)/s',$linkt,$text,1); + if($num == 1) $text .= '

    '; + $text .= '
    '.$linkb.' '.$fn.'
    '; + } + + if($num) $text .= '
    '; + return $text; +} + +/** + * Replace smileys with their graphic equivalents + * + * @author Andreas Gohr + */ +function smileys(&$table,&$text){ + $smileys = file('conf/smileys.conf'); + foreach($smileys as $smiley){ + $smiley = preg_replace('/#.*$/','',$smiley); //ignore comments + $smiley = trim($smiley); + if(empty($smiley)) continue; + $sm = preg_split('/\s+/',$smiley,2); + $sm[1] = ''.$sm[0].''; + $sm[0] = preg_quote($sm[0],'/'); + firstpass($table,$text,'/(? + */ +function acronyms(&$table,&$text){ + $acronyms = file('conf/acronyms.conf'); + foreach($acronyms as $acro){ + $acro = preg_replace('/#.*$/','',$acro); //ignore comments + $acro = trim($acro); + if(empty($acro)) continue; + list($ac,$desc) = preg_split('/\s+/',$acro,2); + $ac = preg_quote($ac,'/'); + firstpass($table,$text,'/\b('.$ac.')\b/s',"\\1"); + } +} + +/** + * Apply custom text replacements + * + * @author Andreas Gohr + */ +function customs($text){ + $reps = file ('conf/custom.conf'); + foreach($reps as $rep){ + //strip comments only outside a regexp + $rep = preg_replace('/#[^\/]*$/','',$rep); //ignore comments + $rep = trim($rep); + if(empty($rep)) continue; + if(preg_match('#^(/.+/\w*)\s+\'(.*)\'$#',$rep,$matches)){ + $text = preg_replace($matches[1],$matches[2],$text); + } + } + return $text; +} + +/** + * Replace regexp with token + * + * @author Andreas Gohr + */ +function firstpass(&$table,&$text,$regexp,$replace,$lpad='',$rpad=''){ + //extended regexps have to be disabled for inserting the token + //and later reenabled when handling the actual code: + $ext=''; + if(substr($regexp,-1) == 'e'){ + $ext='e'; + $regexp = substr($regexp,0,-1); + } + + while(preg_match($regexp,$text,$matches)){ + $token = mkToken(); + $match = $matches[0]; + $text = preg_replace($regexp,$lpad.$token.$rpad,$text,1); + $table[$token] = preg_replace($regexp.$ext,$replace,$match); + } +} + +/** + * create a random and hopefully unique token + * + * @author Andreas Gohr + */ +function mkToken(){ + return '~'.md5(uniqid(rand(), true)).'~'; +} + +/** + * Do quote blocks + * + * @author Andreas Gohr + */ +function quoteformat($block){ + $block = trim($block); + $lines = split("\n",$block); + + $lvl = 0; + $ret = ""; + foreach ($lines as $line){ + //remove '>' and count them + $cnt = 0; + while(substr($line,0,4) == '>'){ + $line = substr($line,4); + $cnt++; + } + //compare to last level and open or close new divs if needed + if($cnt > $lvl){ + $ret .= "

    \n"; + for ($i=0; $i< $cnt - $lvl; $i++){ + $ret .= '
    '; + } + $ret .= "\n

    "; + }elseif($cnt < $lvl){ + $ret .= "\n

    "; + for ($i=0; $i< $lvl - $cnt; $i++){ + $ret .= "
    \n"; + } + $ret .= "

    \n"; + }elseif(empty($line)){ + $ret .= "

    \n

    "; + } + //keep rest of line but trim left whitespaces + $ret .= ltrim($line)."\n"; + //remember level + $lvl = $cnt; + } + + //close remaining divs + $ret .= "

    \n"; + for ($i=0; $i< $lvl; $i++){ + $ret .= "\n"; + } + $ret .= "

    \n"; + + return "$ret"; +} + +/** + * format inline tables + * + * @author Andreas Gohr + * @author Aaron Evans + */ +function tableformat($block) { + $block = trim($block); + $lines = split("\n",$block); + $ret = ""; + //build a row array + $rows = array(); + for($r=0; $r < count($lines); $r++){ + $line = $lines[$r]; + //remove last seperator and trailing whitespace + $line = preg_replace('/[\|\^]\s*$/', '', $line); + $c = -1; //prepare colcounter) + for($chr=0; $chr < strlen($line); $chr++){ + if($line[$chr] == '^'){ + $c++; + $rows[$r][$c]['head'] = true; + $rows[$r][$c]['data'] = ''; + }elseif($line[$chr] == '|'){ + $c++; + $rows[$r][$c]['head'] = false; + $rows[$r][$c]['data'] = ''; + }else{ + $rows[$r][$c]['data'].= $line[$chr]; + } + } + } + + //build table + $ret .= "

    \n\n"; + for($r=0; $r < count($rows); $r++){ + $ret .= " \n"; + + for ($c=0; $c < count($rows[$r]); $c++){ + $cspan=1; + $data = $rows[$r][$c]['data']; + $head = $rows[$r][$c]['head']; + + //join cells if next is empty + while($c < count($rows[$r])-1 && $rows[$r][$c+1]['data'] == ''){ + $c++; + $cspan++; + } + if($cspan > 1){ + $cspan = 'colspan="'.$cspan.'"'; + }else{ + $cspan = ''; + } + + //determine alignment from whitespace + if (preg_match('/^\s\s/', $data)) { // right indentation + $td_class = "rightalign"; + if (preg_match('/\s\s$/', $data)) { // both left and right indentation + $td_class = "centeralign"; + } + } else { // left indentation (default) + $td_class = "leftalign"; + } + + $data = trim($data); + if ($head) { + $ret .= " \n"; // set css class for alignment + } else { + $ret .= " \n"; // set css class for alignment + } + } + $ret .= " \n"; + } + $ret .= "
    $data $data

    \n

    "; + + return $ret; +} + +/** + * format lists + * + * @author Andreas Gohr + */ +function listformat($block){ + //remove 1st newline + $block = substr($block,1); + //unescape + $block = str_replace('\\"','"',$block); + +//dbg($block); + + //walk line by line + $ret=''; + $lst=0; + $lvl=0; + $enc=0; + $lines = split("\n",$block); + + //build an item array + $cnt=0; + $items = array(); + foreach ($lines as $line){ + //get intendion level + $lvl = 0; + $lvl += floor(strspn($line,' ')/2); + $lvl += strspn($line,"\t"); + //remove indents + $line = preg_replace('/^[ \t]+/','',$line); + //get type of list + (substr($line,0,1) == '-') ? $type='ol' : $type='ul'; + // remove bullet and following spaces + $line = preg_replace('/^[*\-]\s*/','',$line); + //add item to the list + $items[$cnt]['level'] = $lvl; + $items[$cnt]['type'] = $type; + $items[$cnt]['text'] = $line; + //increase counter + $cnt++; + } + + $level = 0; + $opens = array(); + + foreach ($items as $item){ + if( $item['level'] > $level ){ + //open new list + $ret .= "\n<".$item['type'].">\n"; + array_push($opens,$item['type']); + }elseif( $item['level'] < $level ){ + //close last item + $ret .= "\n"; + for ($i=0; $i<($level - $item['level']); $i++){ + //close higher lists + $ret .= '\n\n"; + } + }elseif($item['type'] != $opens[count($opens)-1]){ + //close last list and open new + $ret .= '\n\n"; + $ret .= "\n<".$item['type'].">\n"; + array_push($opens,$item['type']); + }else{ + //close last item + $ret .= "\n"; + } + + //remember current level and type + $level = $item['level']; + + //print item + $ret .= '

  • '; + $ret .= ''.$item['text'].''; + } + + //close remaining items and lists + while ($open = array_pop($opens)){ + $ret .= "
  • \n"; + $ret .= '\n"; + } + return "

    \n".$ret."\n

    "; +} + +/** + * Handle preformatted blocks + * + * Uses GeSHi for syntax highlighting + * + * @author Andreas Gohr + */ +function preformat($text,$type,$option=''){ + global $conf; + global $lang; + //unescape + $text = str_replace('\\"','"',$text); + + if($type == 'php' && !$conf['phpok']) $type='file'; + if($type == 'html' && !$conf['htmlok']) $type='file'; + + switch ($type){ + case 'php': + ob_start(); + eval($text); + $text = ob_get_contents(); + ob_end_clean(); + break; + case 'html': + break; + case 'nowiki': + $text = htmlspecialchars($text); + break; + case 'file': + $text = htmlspecialchars($text); + $text = "

    \n
    ".$text."
    \n

    "; + break; + case 'code': + if(empty($option)){ + $text = htmlspecialchars($text); + $text = '

    '.$text.'
    '; + }else{ + //strip leading blank line + $text = preg_replace('/^\s*?\n/','',$text); + //use geshi for highlighting + require_once("inc/geshi.php"); + $geshi = new GeSHi($text, strtolower($option), "inc/geshi"); + $geshi->set_encoding($lang['encoding']); + $geshi->enable_classes(); + $geshi->set_header_type(GESHI_HEADER_PRE); + $geshi->set_overall_class('code'); + $geshi->set_link_target($conf['target']['extern']); + $text = $geshi->parse_code(); + } + $text = "

    \n".$text."\n

    "; + break; + case 'block': + $text = substr($text,1); //remove 1st newline + $lines = split("\n",$text); //break into lines + $text = ''; + foreach($lines as $line){ + $text .= substr($line,2)."\n"; //remove indents + } + $text = htmlspecialchars($text); + $text = "

    \n
    ".$text."
    \n

    "; + break; + } + return $text; +} + +/** + * Format embedded media (images) + * + * @author Andreas Gohr + */ +function mediaformat($text){ + global $conf; + + //unescape + $text = str_replace('\\"','"',$text); + + // format RSS + if(substr($text,0,4) == 'rss>'){ + return format_rss(substr($text,4)); + } + + //handle normal media stuff + $link = array(); + $link['name'] = $text; + $link = format_link_media($link); + return format_link_build($link); +} + +/** + * Get first heading, to be used as a page title + * + * @author Jan Decaluwe + */ +function getFirstHeading($text){ + $title = ''; + $lines = split("\n",$text); + foreach($lines as $line){ + if(preg_match('/^\s*==+(.+?)==+\s*$/',$line,$matches)){ + $title = $matches[1]; + break; + } + } + return $title; +} + + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 8f414c2d6..a132d4f4b 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -193,6 +193,15 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= ''; } + /** + * Callback for footnote start syntax + * + * All following content will go to the footnote instead of + * the document. To achive this the previous rendered content + * is moved to $store and $doc is cleared + * + * @author Andreas Gohr + */ function footnote_open() { $id = $this->_newFootnoteId(); $this->doc .= ''.$id.')'; @@ -206,17 +215,15 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= $id.') '.DOKU_LF; } + /** + * Callback for footnote end syntax + * + * All rendered content is moved to the $footnotes array and the old + * content is restored from $store again + * + * @author Andreas Gohr + */ function footnote_close() { - # $contents = ob_get_contents(); - # ob_end_clean(); - # $id = array_pop($this->footnoteIdStack); - - # $contents = '

    '. - # $id.') ' .DOKU_LF .$contents. "\n" . '
    ' . DOKU_LF; - # $this->footnotes[$id] = $contents; - - $this->doc .= '' . DOKU_LF; // put recorded footnote into the stack and restore old content @@ -262,18 +269,27 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } /** - */ + * Execute PHP code if allowed + * + * @author Andreas Gohr + */ function php($text) { global $conf; if($conf['phpok']){ + ob_start; eval($text); + $this->doc .= ob_get_contents(); + ob_end_clean; }else{ $this->file($text); } } /** - */ + * Insert HTML if allowed + * + * @author Andreas Gohr + */ function html($text) { global $conf; if($conf['htmlok']){ @@ -292,7 +308,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } /** - * @TODO Shouldn't this output ? */ function quote_open() { $this->doc .= '
    '.DOKU_LF; @@ -306,7 +322,12 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } /** - */ + * Callback for code text + * + * Uses GeSHi to highlight language syntax + * + * @author Andreas Gohr + */ function code($text, $language = NULL) { global $conf; @@ -402,8 +423,12 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } /** + * Render an internal Wiki Link + * * $search and $returnonly are not for the renderer but are used * elsewhere - no need to implement them in other renderers + * + * @author Andreas Gohr */ function internallink($id, $name = NULL, $search=NULL,$returnonly=false) { global $conf; @@ -548,35 +573,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= $this->_formatLink($link); } - /* - * @deprecated not used!!! - * @TODO Correct the CSS class for files? (not windows) - * @TODO Remove hard coded URL to splitbrain.org - function filelink($link, $title = NULL) { - $this->doc .= '_getLinkTitle($title, $link, $isImage); - - if ( !$isImage ) { - $this->doc .= ' class="windows"'; - } else { - $this->doc .= ' class="media"'; - } - - $this->doc .= ' href="'.$this->_xmlEntities($link).'"'; - - $this->doc .= ' style="background: transparent url(http://wiki.splitbrain.org/images/windows.gif) 0px 1px no-repeat;"'; - - $this->doc .= ' onclick="return svchk()" onkeypress="return svchk()">'; - - $this->doc .= $title; - - $this->doc .= ''; - } - */ - /** - */ + */ function windowssharelink($url, $name = NULL) { global $conf; global $lang; @@ -720,7 +718,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } /** - * Renders an RSS feed using magpie + * Renders an RSS feed using Magpie * * @author Andreas Gohr */ @@ -752,71 +750,6 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= ''; } - /** - * Renders internal and external media - * - * @author Andreas Gohr - * @todo handle center align - * @todo move to bottom - */ - function _media ($src, $title=NULL, $align=NULL, $width=NULL, - $height=NULL, $cache=NULL) { - - $ret = ''; - - list($ext,$mime) = mimetype($src); - if(substr($mime,0,5) == 'image'){ - //add image tag - $ret .= '_xmlEntities($title).'"'; - $ret .= ' alt="'.$this->_xmlEntities($title).'"'; - }else{ - $ret .= ' alt=""'; - } - - if ( !is_null($width) ) - $ret .= ' width="'.$this->_xmlEntities($width).'"'; - - if ( !is_null($height) ) - $ret .= ' height="'.$this->_xmlEntities($height).'"'; - - $ret .= ' />'; - - }elseif($mime == 'application/x-shockwave-flash'){ - //FIXME default to a higher flash version? - - $ret .= '_xmlEntities($width).'"'; - if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; - $ret .= '>'.DOKU_LF; - $ret .= ''.DOKU_LF; - $ret .= ''.DOKU_LF; - $ret .= '_xmlEntities($width).'"'; - if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; - $ret .= ' type="application/x-shockwave-flash"'. - ' pluginspage="http://www.macromedia.com/shockwave/download/index.cgi'. - '?P1_Prod_Version=ShockwaveFlash">'.DOKU_LF; - $ret .= ''.DOKU_LF; - - }elseif(!is_null($title)){ - // well at least we have a title to display - $ret .= $this->_xmlEntities($title); - }else{ - // just show the source - $ret .= $this->_xmlEntities($src); - } - - return $ret; - } - // $numrows not yet implemented function table_open($maxcols = NULL, $numrows = NULL){ $this->doc .= ''.DOKU_LF; @@ -868,8 +801,9 @@ class Doku_Renderer_xhtml extends Doku_Renderer { // Utils /** - * Assembles all parts defined by the link formater below - * Returns HTML for the link + * Build a link + * + * Assembles all parts defined in $link returns HTML for the link * * @author Andreas Gohr */ @@ -913,6 +847,66 @@ class Doku_Renderer_xhtml extends Doku_Renderer { return preg_replace('!.*'.$nssep.'!','',$name); } + + /** + * Renders internal and external media + * + * @author Andreas Gohr + */ + function _media ($src, $title=NULL, $align=NULL, $width=NULL, + $height=NULL, $cache=NULL) { + + $ret = ''; + + list($ext,$mime) = mimetype($src); + if(substr($mime,0,5) == 'image'){ + //add image tag + $ret .= '_xmlEntities($title).'"'; + $ret .= ' alt="'.$this->_xmlEntities($title).'"'; + }else{ + $ret .= ' alt=""'; + } + + if ( !is_null($width) ) + $ret .= ' width="'.$this->_xmlEntities($width).'"'; + + if ( !is_null($height) ) + $ret .= ' height="'.$this->_xmlEntities($height).'"'; + + $ret .= ' />'; + + }elseif($mime == 'application/x-shockwave-flash'){ + $ret .= '_xmlEntities($width).'"'; + if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; + $ret .= '>'.DOKU_LF; + $ret .= ''.DOKU_LF; + $ret .= ''.DOKU_LF; + $ret .= '_xmlEntities($width).'"'; + if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; + $ret .= ' type="application/x-shockwave-flash"'. + ' pluginspage="http://www.macromedia.com/go/getflashplayer">'.DOKU_LF; + $ret .= ''.DOKU_LF; + + }elseif(!is_null($title)){ + // well at least we have a title to display + $ret .= $this->_xmlEntities($title); + }else{ + // just show the source + $ret .= $this->_xmlEntities($src); + } + + return $ret; + } function _newFootnoteId() { static $id = 1; @@ -929,16 +923,25 @@ class Doku_Renderer_xhtml extends Doku_Renderer { /** * Adds code for section editing button + * + * This is just aplaceholder and gets replace by the button if + * section editing is allowed + * + * @author Andreas Gohr */ function _secedit($f, $t){ $this->doc .= ''; } - + + /** + * Construct a title and handle images in titles + * + * @author Harry Fuecks + */ function _getLinkTitle($title, $default, & $isImage, $id=NULL) { global $conf; $isImage = FALSE; - if ( is_null($title) ) { if ($conf['useheading'] && $id) { $heading = p_get_first_heading($id); @@ -947,122 +950,28 @@ class Doku_Renderer_xhtml extends Doku_Renderer { } } return $this->_xmlEntities($default); - } else if ( is_string($title) ) { - return $this->_xmlEntities($title); - } else if ( is_array($title) ) { - $isImage = TRUE; return $this->_imageTitle($title); - } } /** - * @TODO Resolve namespace on internal images + * Returns an HTML code for images used in link titles + * + * @todo Resolve namespace on internal images + * @author Andreas Gohr */ function _imageTitle($img) { - - //FIXME resolve internal links - return $this->_media($img['src'], $img['title'], $img['align'], $img['width'], $img['height'], $img['cache']); - -/* - if ( $img['type'] == 'internalmedia' ) { - - // Resolve here... - if ( strpos($img['src'],':') ) { - $src = explode(':',$img['src']); - $src = $src[1]; - } else { - $src = $img['src']; - } - - $imgStr = '_xmlEntities($img['src']).'"'; - - } - - if ( !is_null($img['title']) ) { - $imgStr .= ' alt="'.$this->_xmlEntities($img['title']).'"'; - } else { - $imgStr .= ' alt=""'; - } - - if ( !is_null($img['align']) ) { - $imgStr .= ' align="'.$img['align'].'"'; - } - - if ( !is_null($img['width']) ) { - $imgStr .= ' width="'.$this->_xmlEntities($img['width']).'"'; - } - - if ( !is_null($img['height']) ) { - $imgStr .= ' height="'.$this->_xmlEntities($img['height']).'"'; - } - - $imgStr .= '/>'; - - return $imgStr; -*/ } } -/** -* Test whether there's an image to display with this interwiki link -*/ -function interwikiImgExists($name) { - - static $exists = array(); - - if ( array_key_exists($name,$exists) ) { - return $exists[$name]; - } - - if( @file_exists( DOKU. 'interwiki/'.$name.'.png') ) { - $exists[$name] = 'png'; - } else if ( @file_exists( DOKU . 'interwiki/'.$name.'.gif') ) { - $exists[$name] = 'gif'; - } else { - $exists[$name] = FALSE; - } - - return $exists[$name]; -} - -/** - * For determining whether to use CSS class "wikilink1" or "wikilink2" - * @todo use configinstead of DOKU_DATA - * @deprecated -> resolve_pagename should be used - */ -function wikiPageExists($name) { -msg("deprecated wikiPageExists called",-1); - static $pages = array(); - - if ( array_key_exists($name,$pages) ) { - return $pages[$name]; - } - - $file = str_replace(':','/',$name).'.txt'; - - if ( @file_exists( DOKU_DATA . $file ) ) { - $pages[$name] = TRUE; - } else { - $pages[$name] = FALSE; - } - - return $pages[$name]; -} - - //Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/inc/parserutils.php b/inc/parserutils.php index 3c7803b16..4f90364aa 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -256,7 +256,6 @@ function p_render($mode,$instructions){ * * @author Jan Decaluwe */ - function p_get_first_heading($id){ $file = wikiFN($id); if (@file_exists($file)) { -- cgit v1.2.3