summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/cases/inc/pageutils_resolve_id.test.php45
-rw-r--r--inc/pageutils.php84
2 files changed, 99 insertions, 30 deletions
diff --git a/_test/cases/inc/pageutils_resolve_id.test.php b/_test/cases/inc/pageutils_resolve_id.test.php
new file mode 100644
index 000000000..64b4033cd
--- /dev/null
+++ b/_test/cases/inc/pageutils_resolve_id.test.php
@@ -0,0 +1,45 @@
+<?php
+require_once DOKU_INC.'inc/utf8.php';
+require_once DOKU_INC.'inc/pageutils.php';
+
+class init_resolve_id_test extends UnitTestCase {
+
+
+ function test1(){
+ // we test multiple cases here
+ // format: $ns, $page, $output
+ $tests = array();
+
+ // relative current in root
+ $tests[] = array('','page','page');
+ $tests[] = array('','.page','page');
+ $tests[] = array('','.:page','page');
+
+ // relative current in namespace
+ $tests[] = array('lev1:lev2','page','lev1:lev2:page');
+ $tests[] = array('lev1:lev2','.page','lev1:lev2:page');
+ $tests[] = array('lev1:lev2','.:page','lev1:lev2:page');
+
+ // relative upper in root
+ $tests[] = array('','..page','page');
+ $tests[] = array('','..:page','page');
+
+ // relative upper in namespace
+ $tests[] = array('lev1:lev2','..page','lev1:page');
+ $tests[] = array('lev1:lev2','..:page','lev1:page');
+ $tests[] = array('lev1:lev2','..:..:page','page');
+ $tests[] = array('lev1:lev2','..:..:..:page','page');
+
+ // strange and broken ones
+ $tests[] = array('lev1:lev2','....:....:page','lev1:lev2:page');
+ $tests[] = array('lev1:lev2','..:..:lev3:page','lev3:page');
+ $tests[] = array('lev1:lev2','..:..:lev3:..:page','page');
+ $tests[] = array('lev1:lev2','..:..:lev3:..:page:....:...','page');
+
+ foreach($tests as $test){
+ $this->assertEqual(resolve_id($test[0],$test[1]),$test[2]);
+ }
+ }
+
+}
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/inc/pageutils.php b/inc/pageutils.php
index 0689ff6fe..6adeb85b2 100644
--- a/inc/pageutils.php
+++ b/inc/pageutils.php
@@ -111,10 +111,11 @@ function cleanID($id,$ascii=false){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function getNS($id){
- if(strpos($id,':')!==false){
- return substr($id,0,strrpos($id,':'));
- }
- return false;
+ $pos = strrpos($id,':');
+ if($pos!==false){
+ return substr($id,0,$pos);
+ }
+ return false;
}
/**
@@ -218,24 +219,57 @@ function localeFN($id){
}
/**
- * Returns a full media id
+ * Resolve relative paths in IDs
*
- * @author Andreas Gohr <andi@splitbrain.org>
+ * Do not call directly use resolve_mediaid or resolve_pageid
+ * instead
+ *
+ * Partyly based on a cleanPath function found at
+ * http://www.php.net/manual/en/function.realpath.php#57016
+ *
+ * @author <bart at mediawave dot nl>
*/
-function resolve_mediaid($ns,&$page,&$exists){
- global $conf;
-
- //if links starts with . add current namespace
- if($page{0} == '.'){
- $page = $ns.':'.substr($page,1);
+function resolve_id($ns,$id){
+ // if the id starts with a dot we need to handle the
+ // relative stuff
+ if($id{0} == '.'){
+ // normalize initial dots without a colon
+ $id = preg_replace('/^(\.+)(?=[^:\.])/','\1:',$id);
+ // prepend the current namespace
+ $id = $ns.':'.$id;
+
+ // cleanup relatives
+ $result = array();
+ $pathA = explode(':', $id);
+ if (!$pathA[0]) $result[] = '';
+ foreach ($pathA AS $key => $dir) {
+ if ($dir == '..') {
+ if (end($result) == '..') {
+ $result[] = '..';
+ } elseif (!array_pop($result)) {
+ $result[] = '..';
+ }
+ } elseif ($dir && $dir != '.') {
+ $result[] = $dir;
+ }
+ }
+ if (!end($pathA)) $result[] = '';
+ $id = implode(':', $result);
+ }elseif($ns !== false && strpos($id,':') === false){
+ //if link contains no namespace. add current namespace (if any)
+ $id = $ns.':'.$id;
}
- //if link contains no namespace. add current namespace (if any)
- if($ns !== false && strpos($page,':') === false){
- $page = $ns.':'.$page;
- }
+ return cleanID($id);
+}
- $page = cleanID($page);
+/**
+ * Returns a full media id
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function resolve_mediaid($ns,&$page,&$exists){
+ $page = resolve_id($ns,$page);
$file = mediaFN($page);
$exists = @file_exists($file);
}
@@ -249,19 +283,9 @@ function resolve_pageid($ns,&$page,&$exists){
global $conf;
$exists = false;
- //if links starts with . add current namespace
- if($page{0} == '.'){
- $page = $ns.':'.substr($page,1);
- }
-
- //if link contains no namespace. add current namespace (if any)
- if($ns !== false && strpos($page,':') === false){
- $page = $ns.':'.$page;
- }
-
//keep hashlink if exists then clean both parts
list($page,$hash) = split('#',$page,2);
- $page = cleanID($page);
+ $page = resolve_id($ns,$page);
$hash = cleanID($hash);
$file = wikiFN($page);
@@ -337,7 +361,7 @@ function isVisiblePage($id){
* @link http://simon.incutio.com/archive/2003/04/23/conditionalGet
*/
function http_conditionalRequest($timestamp){
- // A PHP implementation of conditional get, see
+ // A PHP implementation of conditional get, see
// http://fishbowl.pastiche.org/archives/001132.html
$last_modified = substr(date('r', $timestamp), 0, -5).'GMT';
$etag = '"'.md5($last_modified).'"';
@@ -349,7 +373,7 @@ function http_conditionalRequest($timestamp){
stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) :
false;
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
- stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) :
+ stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) :
false;
if (!$if_modified_since && !$if_none_match) {
return;