2 /////////////////////////////////////////////////
3 // PukiWiki - Yet another WikiWikiWeb clone.
5 // $Id: make_link.php,v 1.64 2003/11/22 04:50:26 arino Exp $
9 function make_link($string,$page = '')
14 if (!isset($converter))
16 $converter = new InlineConverter();
18 $_converter = $converter; // copy
19 return $_converter->convert($string, ($page != '') ? $page : $vars['page']);
21 //¥¤¥ó¥é¥¤¥óÍ×ÁǤòÃÖ´¹¤¹¤ë
24 var $converters; // as array()
29 function InlineConverter($converters=NULL,$excludes=NULL)
31 if ($converters === NULL)
34 'plugin', // ¥¤¥ó¥é¥¤¥ó¥×¥é¥°¥¤¥ó
37 'url_interwiki', // URL (interwiki definition)
39 'interwikiname', // InterWikiName
40 'autolink', // AutoLink
41 'bracketname', // BracketName
42 'wikiname', // WikiName
43 'autolink_a', // AutoLink(¥¢¥ë¥Õ¥¡¥Ù¥Ã¥È)
46 if ($excludes !== NULL)
48 $converters = array_diff($converters,$excludes);
50 $this->converters = array();
54 foreach ($converters as $name)
56 $classname = "Link_$name";
57 $converter = new $classname($start);
58 $pattern = $converter->get_pattern();
59 if ($pattern === FALSE)
63 $patterns[] = "(\n$pattern\n)";
64 $this->converters[$start] = $converter;
65 $start += $converter->get_count();
68 $this->pattern = join('|',$patterns);
70 function convert($string,$page)
73 $this->result = array();
75 $string = preg_replace_callback("/{$this->pattern}/x",array(&$this,'replace'),$string);
77 $arr = explode("\x08",make_line_rules(htmlspecialchars($string)));
81 $retval .= array_shift($arr).array_shift($this->result);
85 function replace($arr)
87 $obj = $this->get_converter($arr);
89 $this->result[] = ($obj !== NULL and $obj->set($arr,$this->page) !== FALSE) ?
90 $obj->toString() : make_line_rules(htmlspecialchars($arr[0]));
92 return "\x08"; //½èÍýºÑ¤ß¤ÎÉôʬ¤Ë¥Þ¡¼¥¯¤òÆþ¤ì¤ë
94 function get_objects($string,$page)
96 preg_match_all("/{$this->pattern}/x",$string,$matches,PREG_SET_ORDER);
99 foreach ($matches as $match)
101 $obj = $this->get_converter($match);
102 if ($obj->set($match,$page) !== FALSE)
104 $arr[] = $obj; // copy
105 if ($obj->body != '')
107 $arr = array_merge($arr,$this->get_objects($obj->body,$page));
113 function &get_converter(&$arr)
115 foreach (array_keys($this->converters) as $start)
117 if ($arr[$start] == $arr[0])
119 return $this->converters[$start];
125 //¥¤¥ó¥é¥¤¥óÍ×Áǽ¸¹ç¤Î¥Ù¡¼¥¹¥¯¥é¥¹
128 var $start; // ³ç¸Ì¤ÎÀèƬÈÖ¹æ(0¥ª¥ê¥¸¥ó)
129 var $text; // ¥Þ¥Ã¥Á¤·¤¿Ê¸»úÎóÁ´ÂÎ
138 function Link($start)
140 $this->start = $start;
142 // ¥Þ¥Ã¥Á¤Ë»ÈÍѤ¹¤ë¥Ñ¥¿¡¼¥ó¤òÊÖ¤¹
143 function get_pattern()
146 // »ÈÍѤ·¤Æ¤¤¤ë³ç¸Ì¤Î¿ô¤òÊÖ¤¹ ((?:...)¤ò½ü¤¯)
150 // ¥Þ¥Ã¥Á¤·¤¿¥Ñ¥¿¡¼¥ó¤òÀßÄꤹ¤ë
151 function set($arr,$page)
160 // ¥Þ¥Ã¥Á¤·¤¿ÇÛÎ󤫤顢¼«Ê¬¤ËɬÍפÊÉôʬ¤À¤±¤ò¼è¤ê½Ð¤¹
161 function splice($arr)
163 $count = $this->get_count() + 1;
164 $arr = array_pad(array_splice($arr,$this->start,$count),$count,'');
165 $this->text = $arr[0];
168 // ´ðËܥѥé¥á¡¼¥¿¤òÀßÄꤹ¤ë
169 function setParam($page,$name,$body,$type='',$alias='')
171 static $converter = NULL;
177 if ($type != 'InterWikiName' and preg_match('/\.(gif|png|jpe?g)$/i',$alias))
179 $alias = htmlspecialchars($alias);
180 $alias = "<img src=\"$alias\" alt=\"$name\" />";
182 else if ($alias != '')
184 if ($converter === NULL)
186 $converter = new InlineConverter(array('plugin'));
188 $alias = make_line_rules($converter->convert($alias,$page));
190 $this->alias = $alias;
195 // ¥¤¥ó¥é¥¤¥ó¥×¥é¥°¥¤¥ó
196 class Link_plugin extends Link
201 function Link_plugin($start)
203 parent::Link($start);
205 function get_pattern()
207 $this->pattern = <<<EOD
210 (\w+) # (2) plugin name
213 ((?:(?!\)[;{]).)*) # (3) parameter
222 ((?:(?R)|(?!};).)*) # (4) body
232 function set($arr,$page)
234 list($all,$this->plain,$name,$this->param,$body) = $this->splice($arr);
236 // ËÜÍè¤Î¥×¥é¥°¥¤¥ó̾¤ª¤è¤Ó¥Ñ¥é¥á¡¼¥¿¤ò¼èÆÀ¤·¤Ê¤ª¤¹ PHP4.1.2 (?R)Âкö
237 if (preg_match("/^{$this->pattern}/x",$all,$matches)
238 and $matches[1] != $this->plain)
240 list(,$this->plain,$name,$this->param) = $matches;
242 return parent::setParam($page,$name,$body,'plugin');
246 $body = ($this->body == '') ? '' : make_link($this->body);
248 // ¥×¥é¥°¥¤¥ó¸Æ¤Ó½Ð¤·
249 if (exist_plugin_inline($this->name))
251 $str = do_plugin_inline($this->name,$this->param,$body);
252 if ($str !== FALSE) //À®¸ù
258 // ¥×¥é¥°¥¤¥ó¤¬Â¸ºß¤·¤Ê¤¤¤«¡¢ÊÑ´¹¤Ë¼ºÇÔ
259 $body = ($body == '') ? ';' : "\{$body};";
260 return make_line_rules(htmlspecialchars('&'.$this->plain).$body);
264 class Link_note extends Link
266 function Link_note($start)
268 parent::Link($start);
270 function get_pattern()
274 ((?:(?R)|(?!\)\)).)*) # (1) note body
282 function set($arr,$page)
284 global $foot_explain;
287 list(,$body) = $this->splice($arr);
290 $note = make_link($body);
292 $foot_explain[$id] = <<<EOD
293 <a id="notefoot_$id" href="#notetext_$id" class="note_super">*$id</a>
294 <span class="small">$note</span>
297 $name = "<a id=\"notetext_$id\" href=\"#notefoot_$id\" class=\"note_super\">*$id</a>";
299 return parent::setParam($page,$name,$body);
307 class Link_url extends Link
309 function Link_url($start)
311 parent::Link($start);
313 function get_pattern()
315 $s1 = $this->start + 1;
317 (\[\[ # (1) open bracket
318 ((?:(?!\]\]).)+) # (2) alias
322 (?:https?|ftp|news):\/\/[!~*'();\/?:\@&=+\$,%#\w.-]+
324 (?($s1)\]\]) # close bracket
331 function set($arr,$page)
333 list(,,$alias,$name) = $this->splice($arr);
334 return parent::setParam($page,htmlspecialchars($name),'','url',$alias == '' ? $name : $alias);
338 return "<a href=\"{$this->name}\">{$this->alias}</a>";
341 // url (InterWiki definition type)
342 class Link_url_interwiki extends Link
344 function Link_url_interwiki($start)
346 parent::Link($start);
348 function get_pattern()
353 (?:(?:https?|ftp|news):\/\/|\.\.?\/)[!~*'();\/?:\@&=+\$,%#\w.-]*
364 function set($arr,$page)
366 list(,$name,$alias) = $this->splice($arr);
367 return parent::setParam($page,htmlspecialchars($name),'','url',$alias);
371 return "<a href=\"{$this->name}\">{$this->alias}</a>";
375 class Link_mailto extends Link
377 var $is_image,$image;
379 function Link_mailto($start)
381 parent::Link($start);
383 function get_pattern()
385 $s1 = $this->start + 1;
389 ((?:(?!\]\]).)+)(?:>|:) # (1) alias
391 ([\w.-]+@[\w-]+\.[\w.-]+) # (2) mailto
392 (?($s1)\]\]) # close bracket if (1)
399 function set($arr,$page)
401 list(,$alias,$name) = $this->splice($arr);
402 return parent::setParam($page,$name,'','mailto',$alias == '' ? $name : $alias);
406 return "<a href=\"mailto:{$this->name}\">{$this->alias}</a>";
410 class Link_interwikiname extends Link
416 function Link_interwikiname($start)
418 parent::Link($start);
420 function get_pattern()
422 $s2 = $this->start + 2;
423 $s5 = $this->start + 5;
427 ((?:(?!\]\]).)+)> # (1) alias
429 (\[\[)? # (2) open bracket
430 ((?:(?!\s|:|\]\]).)+) # (3) InterWiki
431 (?<! > | >\[\[ ) # not '>' or '>[['
434 (\[\[)? # (5) open bracket
436 (?($s5)\]\]) # close bracket if (5)
438 (?($s2)\]\]) # close bracket if (2)
446 function set($arr,$page)
450 list(,$alias,,$name,$this->param) = $this->splice($arr);
452 if (preg_match('/^([^#]+)(#[A-Za-z][\w-]*)$/',$this->param,$matches))
454 list(,$this->param,$this->anchor) = $matches;
456 $url = get_interwiki_url($name,$this->param);
457 $this->url = ($url === FALSE) ?
458 $script.'?'.rawurlencode('[['.$name.':'.$this->param.']]') :
459 htmlspecialchars($url);
461 return parent::setParam(
463 htmlspecialchars($name.':'.$this->param),
466 $alias == '' ? $name.':'.$this->param : $alias
471 return "<a href=\"{$this->url}{$this->anchor}\" title=\"{$this->name}\">{$this->alias}</a>";
475 class Link_bracketname extends Link
479 function Link_bracketname($start)
481 parent::Link($start);
483 function get_pattern()
485 global $WikiName,$BracketName;
487 $s2 = $this->start + 2;
490 (?:((?:(?!\]\]).)+)>)? # (1) alias
491 (\[\[)? # (2) open bracket
497 (\#(?:[a-zA-Z][\w-]*)?)? # (4) anchor
498 (?($s2)\]\]) # close bracket if (2)
506 function set($arr,$page)
510 list(,$alias,,$name,$this->anchor) = $this->splice($arr);
512 if ($name == '' and $this->anchor == '')
516 if ($name != '' and preg_match("/^$WikiName$/",$name))
518 return parent::setParam($page,$name,'','pagename',$alias);
522 $alias = $name.$this->anchor;
526 if ($this->anchor == '')
533 $name = get_fullname($name,$page);
534 if (!is_pagename($name))
539 return parent::setParam($page,$name,'','pagename',$alias);
543 return make_pagelink(
552 class Link_wikiname extends Link
554 function Link_wikiname($start)
556 parent::Link($start);
558 function get_pattern()
560 global $WikiName,$nowikiname;
562 return $nowikiname ? FALSE : "($WikiName)";
568 function set($arr,$page)
570 list($name) = $this->splice($arr);
571 return parent::setParam($page,$name,'','pagename',$name);
575 return make_pagelink(
584 class Link_autolink extends Link
586 var $forceignorepages = array();
588 var $auto_a; // alphabet only
590 function Link_autolink($start)
594 parent::Link($start);
596 if (!$autolink or !file_exists(CACHE_DIR.'autolink.dat'))
600 @list($auto,$auto_a,$forceignorepages) = file(CACHE_DIR.'autolink.dat');
602 $this->auto_a = $auto_a;
603 $this->forceignorepages = explode("\t",trim($forceignorepages));
605 function get_pattern()
607 return isset($this->auto) ? "({$this->auto})" : FALSE;
613 function set($arr,$page)
617 list($name) = $this->splice($arr);
618 // ̵»ë¥ê¥¹¥È¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ë¡¢¤¢¤ë¤¤¤Ï¸ºß¤·¤Ê¤¤¥Ú¡¼¥¸¤ò¼Î¤Æ¤ë
619 if (in_array($name,$this->forceignorepages) or !is_page($name))
623 return parent::setParam($page,$name,'','pagename',$name);
627 return make_pagelink(
635 class Link_autolink_a extends Link_autolink
637 function Link_autolink_a($start)
639 parent::Link_autolink($start);
641 function get_pattern()
643 return isset($this->auto_a) ? "({$this->auto_a})" : FALSE;
647 // ¥Ú¡¼¥¸Ì¾¤Î¥ê¥ó¥¯¤òºîÀ®
648 function make_pagelink($page,$alias='',$anchor='',$refer='')
650 global $script,$vars,$show_title,$show_passage,$link_compact,$related;
651 global $_symbol_noexists;
653 $s_page = htmlspecialchars(strip_bracket($page));
654 $s_alias = ($alias == '') ? $s_page : $alias;
658 return "<a href=\"$anchor\">$s_alias</a>";
661 $r_page = rawurlencode($page);
662 $r_refer = ($refer == '') ? '' : '&refer='.rawurlencode($refer);
664 if (!array_key_exists($page,$related) and $page != $vars['page'] and is_page($page))
666 $related[$page] = get_filetime($page);
671 $passage = get_pg_passage($page,FALSE);
672 $title = $link_compact ? '' : " title=\"$s_page$passage\"";
673 return "<a href=\"$script?$r_page$anchor\"$title>$s_alias</a>";
677 $retval = "$s_alias<a href=\"$script?cmd=edit&page=$r_page$r_refer\">$_symbol_noexists</a>";
680 $retval = "<span class=\"noexists\">$retval</span>";
686 function get_fullname($name,$refer)
697 $name = substr($name,1);
698 return ($name == '') ? $defaultpage : $name;
706 if (substr($name,0,2) == './')
708 $arrn = preg_split('/\//',$name,-1,PREG_SPLIT_NO_EMPTY);
710 return join('/',$arrn);
713 if (substr($name,0,3) == '../')
715 $arrn = preg_split('/\//',$name,-1,PREG_SPLIT_NO_EMPTY);
716 $arrp = preg_split('/\//',$refer,-1,PREG_SPLIT_NO_EMPTY);
718 while (count($arrn) > 0 and $arrn[0] == '..')
723 $name = count($arrp) ? join('/',array_merge($arrp,$arrn)) :
724 (count($arrn) ? "$defaultpage/".join('/',$arrn) : $defaultpage);
729 // InterWikiName¤òŸ³«
730 function get_interwiki_url($name,$param)
732 global $WikiName,$interwiki;
733 static $interwikinames;
734 static $encode_aliases = array('sjis'=>'SJIS','euc'=>'EUC-JP','utf8'=>'UTF-8');
736 if (!isset($interwikinames))
738 $interwikinames = array();
739 foreach (get_source($interwiki) as $line)
741 if (preg_match('/\[((?:(?:https?|ftp|news):\/\/|\.\.?\/)[!~*\'();\/?:\@&=+\$,%#\w.-]*)\s([^\]]+)\]\s?([^\s]*)/',$line,$matches))
743 $interwikinames[$matches[2]] = array($matches[1],$matches[3]);
747 if (!array_key_exists($name,$interwikinames))
751 list($url,$opt) = $interwikinames[$name];
753 // ʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°
758 if (!preg_match("/$WikiName/",$param))
760 $param = '[['.mb_convert_encoding($param,'SJIS',SOURCE_ENCODING).']]';
762 // $param = htmlspecialchars($param);
767 $param = str_replace('%','_',rawurlencode($param));
770 // ÆâÉôʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤Î¤Þ¤ÞURL¥¨¥ó¥³¡¼¥É
773 $param = rawurlencode($param);
776 // URL¥¨¥ó¥³¡¼¥É¤·¤Ê¤¤
779 // $param = htmlspecialchars($param);
784 if (array_key_exists($opt,$encode_aliases))
786 $opt = $encode_aliases[$opt];
788 // »ØÄꤵ¤ì¤¿Ê¸»ú¥³¡¼¥É¤Ø¥¨¥ó¥³¡¼¥É¤·¤ÆURL¥¨¥ó¥³¡¼¥É
789 $param = rawurlencode(mb_convert_encoding($param,$opt,'auto'));
793 if (strpos($url,'$1') !== FALSE)
795 $url = str_replace('$1',$param,$url);