<?php
// PukiWiki - Yet another WikiWikiWeb clone.
-// $Id: make_link.php,v 1.11 2005/01/16 13:27:55 henoheno Exp $
+// make_link.php
+// Copyright
+// 2003-2016 PukiWiki Development Team
+// 2001-2002 Originally written by yu-ji
+// License: GPL v2 or (at your option) any later version
//
// Hyperlink-related functions
-// ¥ê¥ó¥¯¤òÉղ乤ë
+// Hyperlink decoration
function make_link($string, $page = '')
{
global $vars;
return $clone->convert($string, ($page != '') ? $page : $vars['page']);
}
-//¥¤¥ó¥é¥¤¥óÍ×ÁǤòÃÖ´¹¤¹¤ë
+// Converters of inline element
class InlineConverter
{
var $converters; // as array()
{
if ($converters === NULL) {
$converters = array(
- 'plugin', // ¥¤¥ó¥é¥¤¥ó¥×¥é¥°¥¤¥ó
- 'note', // Ãí¼á
- 'url', // URL
- 'url_interwiki', // URL (interwiki definition)
- 'mailto', // mailto:
- 'interwikiname', // InterWikiName
- 'autolink', // AutoLink
- 'bracketname', // BracketName
- 'wikiname', // WikiName
- 'autolink_a', // AutoLink(¥¢¥ë¥Õ¥¡¥Ù¥Ã¥È)
+ 'plugin', // Inline plugins
+ 'note', // Footnotes
+ 'url', // URLs
+ 'url_interwiki', // URLs (interwiki definition)
+ 'mailto', // mailto: URL schemes
+ 'interwikiname', // InterWikiNames
+ 'autolink', // AutoLinks
+ 'bracketname', // BracketNames
+ 'wikiname', // WikiNames
+ 'autolink_a', // AutoLinks(alphabet)
);
}
$string = preg_replace_callback('/' . $this->pattern . '/x',
array(& $this, 'replace'), $string);
- $arr = explode("\x08", make_line_rules(htmlspecialchars($string)));
+ $arr = explode("\x08", make_line_rules(htmlsc($string)));
$retval = '';
while (! empty($arr)) {
$retval .= array_shift($arr) . array_shift($this->result);
$obj = $this->get_converter($arr);
$this->result[] = ($obj !== NULL && $obj->set($arr, $this->page) !== FALSE) ?
- $obj->toString() : make_line_rules(htmlspecialchars($arr[0]));
+ $obj->toString() : make_line_rules(htmlsc($arr[0]));
- return "\x08"; //½èÍýºÑ¤ß¤ÎÉôʬ¤Ë¥Þ¡¼¥¯¤òÆþ¤ì¤ë
+ return "\x08"; // Add a mark into latest processed part
}
function get_objects($string, $page)
}
}
-//¥¤¥ó¥é¥¤¥óÍ×Áǽ¸¹ç¤Î¥Ù¡¼¥¹¥¯¥é¥¹
+// Base class of inline elements
class Link
{
- var $start; // ³ç¸Ì¤ÎÀèƬÈÖ¹æ(0¥ª¥ê¥¸¥ó)
- var $text; // ¥Þ¥Ã¥Á¤·¤¿Ê¸»úÎóÁ´ÂÎ
+ var $start; // Origin number of parentheses (0 origin)
+ var $text; // Matched string
var $type;
var $page;
var $body;
var $alias;
- // constructor
+ // Constructor
function Link($start)
{
$this->start = $start;
}
- // ¥Þ¥Ã¥Á¤Ë»ÈÍѤ¹¤ë¥Ñ¥¿¡¼¥ó¤òÊÖ¤¹
+ // Return a regex pattern to match
function get_pattern() {}
- // »ÈÍѤ·¤Æ¤¤¤ë³ç¸Ì¤Î¿ô¤òÊÖ¤¹ ((?:...)¤ò½ü¤¯)
+ // Return number of parentheses (except (?:...) )
function get_count() {}
- // ¥Þ¥Ã¥Á¤·¤¿¥Ñ¥¿¡¼¥ó¤òÀßÄꤹ¤ë
- function set($arr,$page) {}
+ // Set pattern that matches
+ function set($arr, $page) {}
- // ʸ»úÎó¤ËÊÑ´¹¤¹¤ë
function toString() {}
- // Private
- // ¥Þ¥Ã¥Á¤·¤¿ÇÛÎ󤫤顢¼«Ê¬¤ËɬÍפÊÉôʬ¤À¤±¤ò¼è¤ê½Ð¤¹
- function splice($arr) {
+ // Private: Get needed parts from a matched array()
+ function splice($arr)
+ {
$count = $this->get_count() + 1;
$arr = array_pad(array_splice($arr, $this->start, $count), $count, '');
$this->text = $arr[0];
return $arr;
}
- // ´ðËܥѥé¥á¡¼¥¿¤òÀßÄꤹ¤ë
+ // Set basic parameters
function setParam($page, $name, $body, $type = '', $alias = '')
{
static $converter = NULL;
$this->name = $name;
$this->body = $body;
$this->type = $type;
- if (is_url($alias) && preg_match('/\.(gif|png|jpe?g)$/i', $alias)) {
- $alias = htmlspecialchars($alias);
- $alias = '<img src="' . $alias . '" alt="' . $name . '" />';
+ if (! PKWK_DISABLE_INLINE_IMAGE_FROM_URI &&
+ is_url($alias) && preg_match('/\.(gif|png|jpe?g)$/i', $alias)) {
+ $alias = '<img src="' . htmlsc($alias) . '" alt="' . $name . '" />';
} else if ($alias != '') {
if ($converter === NULL)
$converter = new InlineConverter(array('plugin'));
}
}
-// ¥¤¥ó¥é¥¤¥ó¥×¥é¥°¥¤¥ó
+// Inline plugins
class Link_plugin extends Link
{
var $pattern;
{
list($all, $this->plain, $name, $this->param, $body) = $this->splice($arr);
- // ËÜÍè¤Î¥×¥é¥°¥¤¥ó̾¤ª¤è¤Ó¥Ñ¥é¥á¡¼¥¿¤ò¼èÆÀ¤·¤Ê¤ª¤¹ PHP4.1.2 (?R)Âкö
+ // Re-get true plugin name and patameters (for PHP 4.1.2)
$matches = array();
if (preg_match('/^' . $this->pattern . '/x', $all, $matches)
&& $matches[1] != $this->plain)
function toString()
{
$body = ($this->body == '') ? '' : make_link($this->body);
+ $str = FALSE;
- // ¥×¥é¥°¥¤¥ó¸Æ¤Ó½Ð¤·
- if (exist_plugin_inline($this->name)) {
+ // Try to call the plugin
+ if (exist_plugin_inline($this->name))
$str = do_plugin_inline($this->name, $this->param, $body);
- if ($str !== FALSE) //À®¸ù
- return $str;
- }
- // ¥×¥é¥°¥¤¥ó¤¬Â¸ºß¤·¤Ê¤¤¤«¡¢ÊÑ´¹¤Ë¼ºÇÔ
- $body = (($body == '') ? '' : '{' . $body . '}') . ';';
- return make_line_rules(htmlspecialchars('&' . $this->plain) . $body);
+ if ($str !== FALSE) {
+ return $str; // Succeed
+ } else {
+ // No such plugin, or Failed
+ $body = (($body == '') ? '' : '{' . $body . '}') . ';';
+ return make_line_rules(htmlsc('&' . $this->plain) . $body);
+ }
}
}
{
return <<<EOD
\(\(
- ((?:(?R)|(?!\)\)).)*) # (1) note body
+ ((?>(?=\(\()(?R)|(?!\)\)).)*) # (1) note body
\)\)
EOD;
}
function set($arr, $page)
{
- global $foot_explain, $script, $vars;
+ global $foot_explain, $vars;
static $note_id = 0;
list(, $body) = $this->splice($arr);
+ if (PKWK_ALLOW_RELATIVE_FOOTNOTE_ANCHOR) {
+ $script = '';
+ } else {
+ $script = get_script_uri() . '?' . pagename_urlencode($page);
+ }
+
$id = ++$note_id;
$note = make_link($body);
- $page = isset($vars['page']) ? htmlspecialchars($vars['page']) : '';
+ $page = isset($vars['page']) ? rawurlencode($vars['page']) : '';
// Footnote
- $foot_explain[$id] = <<<EOD
-<a id="notefoot_$id" href="$script?$page#notetext_$id" class="note_super">*$id</a>
-<span class="small">$note</span>
-<br />
-EOD;
+ $foot_explain[$id] = '<a id="notefoot_' . $id . '" href="' .
+ $script . '#notetext_' . $id . '" class="note_super">*' .
+ $id . '</a>' . "\n" .
+ '<span class="small">' . $note . '</span><br />';
+
// A hyperlink, content-body to footnote
- $name = '<a id="notetext_' . $id . '" href="' . $script . '?' . $page .
- '#notefoot_' . $id . '" class="note_super" title="' .
- htmlspecialchars(strip_tags($note)) . '">*' . $id . '</a>';
+ if (! is_numeric(PKWK_FOOTNOTE_TITLE_MAX) || PKWK_FOOTNOTE_TITLE_MAX <= 0) {
+ $title = '';
+ } else {
+ $title = strip_tags($note);
+ $count = mb_strlen($title, SOURCE_ENCODING);
+ $title = mb_substr($title, 0, PKWK_FOOTNOTE_TITLE_MAX, SOURCE_ENCODING);
+ $abbr = (mb_strlen($title) < $count) ? '...' : '';
+ $title = ' title="' . $title . $abbr . '"';
+ }
+ $name = '<a id="notetext_' . $id . '" href="' . $script .
+ '#notefoot_' . $id . '" class="note_super"' . $title .
+ '>*' . $id . '</a>';
return parent::setParam($page, $name, $body);
}
}
}
-// url
+// URLs
class Link_url extends Link
{
function Link_url($start)
{
$s1 = $this->start + 1;
return <<<EOD
-(\[\[ # (1) open bracket
- ((?:(?!\]\]).)+) # (2) alias
+((?:\[\[))? # (1) open bracket
+((?($s1) # (2) alias
+((?:(?!\]\]).)+) # (3) alias name
(?:>|:)
-)?
-( # (3) url
+))?
+( # (4) url
(?:(?:https?|ftp|news):\/\/|mailto:)[\w\/\@\$()!?&%#:;.,~'=*+-]+
)
(?($s1)\]\]) # close bracket
function get_count()
{
- return 3;
+ return 4;
}
function set($arr, $page)
{
- list(, , $alias, $name) = $this->splice($arr);
- return parent::setParam($page, htmlspecialchars($name),
+ list(, , , $alias, $name) = $this->splice($arr);
+ return parent::setParam($page, htmlsc($name),
'', 'url', $alias == '' ? $name : $alias);
}
function toString()
{
- return '<a href="' . $this->name . '">' . $this->alias . '</a>';
+ if (FALSE) {
+ $rel = '';
+ } else {
+ $rel = ' rel="nofollow"';
+ }
+ return '<a href="' . $this->name . '"' . $rel . '>' . $this->alias . '</a>';
}
}
-// url (InterWiki definition type)
+// URLs (InterWiki definition on "InterWikiName")
class Link_url_interwiki extends Link
{
function Link_url_interwiki($start)
function set($arr, $page)
{
list(, $name, $alias) = $this->splice($arr);
- return parent::setParam($page, htmlspecialchars($name), '', 'url', $alias);
+ return parent::setParam($page, htmlsc($name), '', 'url', $alias);
}
function toString()
{
- return '<a href="' . $this->name . '">' . $this->alias . '</a>';
+ return '<a href="' . $this->name . '" rel="nofollow">' . $this->alias . '</a>';
}
}
-//mailto:
+// mailto: URL schemes
class Link_mailto extends Link
{
var $is_image, $image;
function toString()
{
- return '<a href="mailto:' . $this->name . '">' . $this->alias . '</a>';
+ return '<a href="mailto:' . $this->name . '" rel="nofollow">' . $this->alias . '</a>';
}
}
-//InterWikiName
+// InterWikiName-rendered URLs
class Link_interwikiname extends Link
{
var $url = '';
$url = get_interwiki_url($name, $this->param);
$this->url = ($url === FALSE) ?
- $script . '?' . rawurlencode('[[' . $name . ':' . $this->param . ']]') :
- htmlspecialchars($url);
+ $script . '?' . pagename_urlencode('[[' . $name . ':' . $this->param . ']]') :
+ htmlsc($url);
return parent::setParam(
$page,
- htmlspecialchars($name . ':' . $this->param),
+ htmlsc($name . ':' . $this->param),
'',
'InterWikiName',
$alias == '' ? $name . ':' . $this->param : $alias
function toString()
{
- return '<a href="' . $this->url . $this->anchor .
- '" title="' . $this->name . '">' . $this->alias . '</a>';
+ return '<a href="' . $this->url . $this->anchor . '" title="' .
+ $this->name . '" rel="nofollow">' . $this->alias . '</a>';
}
}
-// BracketName
+// BracketNames
class Link_bracketname extends Link
{
var $anchor, $refer;
$s2 = $this->start + 2;
return <<<EOD
-\[\[ # open bracket
-(?:((?:(?!\]\]).)+)>)? # (1) alias
-(\[\[)? # (2) open bracket
+\[\[ # Open bracket
+(?:((?:(?!\]\]).)+)>)? # (1) Alias
+(\[\[)? # (2) Open bracket
( # (3) PageName
(?:$WikiName)
|
(?:$BracketName)
)?
-(\#(?:[a-zA-Z][\w-]*)?)? # (4) anchor
-(?($s2)\]\]) # close bracket if (2)
-\]\] # close bracket
+(\#(?:[a-zA-Z][\w-]*)?)? # (4) Anchor
+(?($s2)\]\]) # Close bracket if (2)
+\]\] # Close bracket
EOD;
}
global $WikiName;
list(, $alias, , $name, $this->anchor) = $this->splice($arr);
-
if ($name == '' && $this->anchor == '') return FALSE;
if ($name == '' || ! preg_match('/^' . $WikiName . '$/', $name)) {
-
if ($alias == '') $alias = $name . $this->anchor;
-
if ($name != '') {
$name = get_fullname($name, $page);
if (! is_pagename($name)) return FALSE;
}
}
-// WikiName
+// WikiNames
class Link_wikiname extends Link
{
function Link_wikiname($start)
}
}
-// AutoLink
+// AutoLinks
class Link_autolink extends Link
{
var $forceignorepages = array();
list($name) = $this->splice($arr);
- // ̵»ë¥ê¥¹¥È¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ë¡¢¤¢¤ë¤¤¤Ï¸ºß¤·¤Ê¤¤¥Ú¡¼¥¸¤ò¼Î¤Æ¤ë
+ // Ignore pages listed, or Expire ones not found
if (in_array($name, $this->forceignorepages) || ! is_page($name))
return FALSE;
function toString()
{
- return make_pagelink(
- $this->name,
- $this->alias,
- '',
- $this->page
- );
+ return make_pagelink($this->name, $this->alias, '', $this->page, TRUE);
}
}
}
}
-// ¥Ú¡¼¥¸Ì¾¤Î¥ê¥ó¥¯¤òºîÀ®
-function make_pagelink($page, $alias = '', $anchor = '', $refer = '')
+// Make hyperlink for the page
+function make_pagelink($page, $alias = '', $anchor = '', $refer = '', $isautolink = FALSE)
{
global $script, $vars, $link_compact, $related, $_symbol_noexists;
- $s_page = htmlspecialchars(strip_bracket($page));
+ $s_page = htmlsc(strip_bracket($page));
$s_alias = ($alias == '') ? $s_page : $alias;
if ($page == '') return '<a href="' . $anchor . '">' . $s_alias . '</a>';
- $r_page = rawurlencode($page);
+ $r_page = pagename_urlencode($page);
$r_refer = ($refer == '') ? '' : '&refer=' . rawurlencode($refer);
- if (! isset($related[$page]) && $page != $vars['page'] && is_page($page))
+ if (! isset($related[$page]) && $page !== $vars['page'] && is_page($page))
$related[$page] = get_filetime($page);
- if (is_page($page)) {
- $passage = get_pg_passage($page, FALSE);
- $title = $link_compact ? '' : ' title="' . $s_page . $passage . '"';
- return '<a href="' . $script . '?' . $r_page . $anchor . '"' . $title . '>' .
- $s_alias . '</a>';
+ if ($isautolink || is_page($page)) {
+ // Hyperlink to the page
+ if ($link_compact) {
+ $title = '';
+ } else {
+ $title = ' title="' . $s_page . get_pg_passage($page, FALSE) . '"';
+ }
+
+ // AutoLink marker
+ if ($isautolink) {
+ $al_left = '<!--autolink-->';
+ $al_right = '<!--/autolink-->';
+ } else {
+ $al_left = $al_right = '';
+ }
+
+ return $al_left . '<a ' . 'href="' . $script . '?' . $r_page . $anchor .
+ '"' . $title . '>' . $s_alias . '</a>' . $al_right;
} else {
+ // Dangling link
+ if (PKWK_READONLY) return $s_alias; // No dacorations
+
$retval = $s_alias . '<a href="' .
$script . '?cmd=edit&page=' . $r_page . $r_refer . '">' .
$_symbol_noexists . '</a>';
- if (! $link_compact)
- $retval = '<span class="noexists">' . $retval . '</span>';
- return $retval;
+
+ if ($link_compact) {
+ return $retval;
+ } else {
+ return '<span class="noexists">' . $retval . '</span>';
+ }
}
}
-// Resolve relative/(Unix-like)absolute path of the page
+// Resolve relative / (Unix-like)absolute path of the page
function get_fullname($name, $refer)
{
global $defaultpage;
return $name;
}
-// InterWikiName¤òŸ³«
+// Render an InterWiki into a URL
function get_interwiki_url($name, $param)
{
global $WikiName, $interwiki;
list($url, $opt) = $interwikinames[$name];
- // ʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°
+ // Encoding
switch ($opt) {
- case '':
- case 'std': // ÆâÉôʸ»ú¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¤Î¤Þ¤ÞURL¥¨¥ó¥³¡¼¥É
+ case '': /* FALLTHROUGH */
+ case 'std': // Simply URL-encode the string, whose base encoding is the internal-encoding
$param = rawurlencode($param);
break;
- case 'asis':
- case 'raw':
- // $param = htmlspecialchars($param);
+ case 'asis': /* FALLTHROUGH */
+ case 'raw' : // Truly as-is
break;
case 'yw': // YukiWiki
if (! preg_match('/' . $WikiName . '/', $param))
$param = '[[' . mb_convert_encoding($param, 'SJIS', SOURCE_ENCODING) . ']]';
- // $param = htmlspecialchars($param);
break;
case 'moin': // MoinMoin
break;
default:
- // ¥¨¥¤¥ê¥¢¥¹¤ÎÊÑ´¹
- if (isset($encode_aliases[$opt])) $opt = $encode_aliases[$opt];
- // »ØÄꤵ¤ì¤¿Ê¸»ú¥³¡¼¥É¤Ø¥¨¥ó¥³¡¼¥É¤·¤ÆURL¥¨¥ó¥³¡¼¥É
- $param = rawurlencode(mb_convert_encoding($param, $opt, 'auto'));
+ // Alias conversion of $opt
+ if (isset($encode_aliases[$opt])) $opt = & $encode_aliases[$opt];
+
+ // Encoding conversion into specified encode, and URLencode
+ if (strpos($url, '$1') === FALSE && substr($url, -1) === '?') {
+ // PukiWiki site
+ $param = pagename_urlencode(mb_convert_encoding($param, $opt, SOURCE_ENCODING));
+ } else {
+ $param = rawurlencode(mb_convert_encoding($param, $opt, SOURCE_ENCODING));
+ }
}
- // ¥Ñ¥é¥á¡¼¥¿¤òÃÖ´¹
+ // Replace or Add the parameter
if (strpos($url, '$1') !== FALSE) {
$url = str_replace('$1', $param, $url);
} else {
return $url;
}
-?>