「0/1////5/6/7」のように途中の階層に空文字が含まれるページがあるとします。
上の階層のページから「.////5/6」のように指定しても、 空文字の部分を消去してしまうので「./5/6」と書いたのと同じ動作になってしまいます。
同じように、下の階層(ここでは「0/1////5/6/7」とする)から「../」とした場合も、 「0/1////5/6」ではなく「0/1/5/6」とされてしまいます。
途中の階層に空文字が含まれるページを許さないのなら、is_pagename() の修正、
許すのならlib/make_link.php の修正となるのでしょうが、
ひとまずcvs:lib/make_link.php (v 1.35) を修正すると仮定して、修正案を書きます。
// $Id: make_link.php,v 1.35 2006/09/30 02:10:50 henoheno Exp $ // Copyright (C) // 2003-2005 PukiWiki Developers Team (中略) // Resolve relative / (Unix-like)absolute path of the page function get_fullname($name, $refer) { global $defaultpage; // 'Here' if ($name == '' || $name == './') return $refer; // Absolute path if ($name{0} == '/') { $name = substr($name, 1); return ($name == '') ? $defaultpage : $name; } // Relative path from 'Here' if (substr($name, 0, 2) == './') { - $arrn = preg_split('#/#', $name, -1, PREG_SPLIT_NO_EMPTY); - $arrn[0] = $refer; - return join('/', $arrn); + return $refer . substr($name, 1); } // Relative path from dirname() if (substr($name, 0, 3) == '../') { - $arrn = preg_split('#/#', $name, -1, PREG_SPLIT_NO_EMPTY); - $arrp = preg_split('#/#', $refer, -1, PREG_SPLIT_NO_EMPTY); + if (substr($name, -1) == '/') + $name = substr($name, 0, -1); + $arrn = explode('/', $name); + $arrp = explode('/', $refer); while (! empty($arrn) && $arrn[0] == '..') { array_shift($arrn); array_pop($arrp); } $name = ! empty($arrp) ? join('/', array_merge($arrp, $arrn)) : (! empty($arrn) ? $defaultpage . '/' . join('/', $arrn) : $defaultpage); } return $name; }
上では、「./hoge/」のように、最後が「/」である時のチェックをはずしています。
「./」とだけ書いた時は上のほうで処理してくれるので問題ないですし、
「[[BugTrack2/]]」のように相対表記でない時は、このチェックをしていないのでいいのかなと。
「../」の場合は、上階層のページそのものを指している時に、余分に削られては困るので、最後が「/」かどうかだけをチェックしています。
今いるページを指す$refer は、最後が「/」では無いはずですけど、
何らかの理由でそのようなページが存在した時のために、チェックしたほうがいいような気もします(上では、はずしてしまってます)。
階層を上がった結果が「0/1///」のようになってしまう可能性がありますが、
make_link.php ではこの処理を呼び出した直後に、is_pagename() を実行していますし、
他の場所でもis_page() や、is_file() などを実行している*1ので、特に問題は無いと思います。