[ Index ] |
|
Code source de DokuWiki 2006-11-06 |
1 <?php 2 /** 3 * Utilities for handling pagenames 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 * @todo Combine similar functions like {wiki,media,meta}FN() 8 */ 9 10 /** 11 * Fetch the an ID from request 12 * 13 * Uses either standard $_REQUEST variable or extracts it from 14 * the full request URI when userewrite is set to 2 15 * 16 * For $param='id' $conf['start'] is returned if no id was found. 17 * If the second parameter is true (default) the ID is cleaned. 18 * 19 * @author Andreas Gohr <andi@splitbrain.org> 20 */ 21 function getID($param='id',$clean=true){ 22 global $conf; 23 24 $id = isset($_REQUEST[$param]) ? $_REQUEST[$param] : null; 25 26 //construct page id from request URI 27 if(empty($id) && $conf['userewrite'] == 2){ 28 //get the script URL 29 if($conf['basedir']){ 30 $relpath = ''; 31 if($param != 'id') { 32 $relpath = 'lib/exe/'; 33 } 34 $script = $conf['basedir'].$relpath.basename($_SERVER['SCRIPT_FILENAME']); 35 }elseif($_SERVER['DOCUMENT_ROOT'] && $_SERVER['SCRIPT_FILENAME']){ 36 $script = preg_replace ('/^'.preg_quote($_SERVER['DOCUMENT_ROOT'],'/').'/','', 37 $_SERVER['SCRIPT_FILENAME']); 38 $script = '/'.$script; 39 }else{ 40 $script = $_SERVER['SCRIPT_NAME']; 41 } 42 43 //clean script and request (fixes a windows problem) 44 $script = preg_replace('/\/\/+/','/',$script); 45 $request = preg_replace('/\/\/+/','/',$_SERVER['REQUEST_URI']); 46 47 //remove script URL and Querystring to gain the id 48 if(preg_match('/^'.preg_quote($script,'/').'(.*)/',$request, $match)){ 49 $id = preg_replace ('/\?.*/','',$match[1]); 50 } 51 $id = urldecode($id); 52 //strip leading slashes 53 $id = preg_replace('!^/+!','',$id); 54 } 55 if($clean) $id = cleanID($id); 56 if(empty($id) && $param=='id') $id = $conf['start']; 57 58 return $id; 59 } 60 61 /** 62 * Remove unwanted chars from ID 63 * 64 * Cleans a given ID to only use allowed characters. Accented characters are 65 * converted to unaccented ones 66 * 67 * @author Andreas Gohr <andi@splitbrain.org> 68 * @param string $raw_id The pageid to clean 69 * @param boolean $ascii Force ASCII 70 */ 71 function cleanID($raw_id,$ascii=false){ 72 global $conf; 73 global $lang; 74 static $sepcharpat = null; 75 76 global $cache_cleanid; 77 $cache = & $cache_cleanid; 78 79 // check if it's already in the memory cache 80 if (isset($cache[$raw_id])) { 81 return $cache[$raw_id]; 82 } 83 84 $sepchar = $conf['sepchar']; 85 if($sepcharpat == null) // build string only once to save clock cycles 86 $sepcharpat = '#\\'.$sepchar.'+#'; 87 88 $id = trim($raw_id); 89 $id = utf8_strtolower($id); 90 91 //alternative namespace seperator 92 $id = strtr($id,';',':'); 93 if($conf['useslash']){ 94 $id = strtr($id,'/',':'); 95 }else{ 96 $id = strtr($id,'/',$sepchar); 97 } 98 99 if($conf['deaccent'] == 2 || $ascii) $id = utf8_romanize($id); 100 if($conf['deaccent'] || $ascii) $id = utf8_deaccent($id,-1); 101 102 //remove specials 103 $id = utf8_stripspecials($id,$sepchar,'\*'); 104 105 if($ascii) $id = utf8_strip($id); 106 107 //clean up 108 $id = preg_replace($sepcharpat,$sepchar,$id); 109 $id = preg_replace('#:+#',':',$id); 110 $id = trim($id,':._-'); 111 $id = preg_replace('#:[:\._\-]+#',':',$id); 112 113 $cache[$raw_id] = $id; 114 return($id); 115 } 116 117 /** 118 * Return namespacepart of a wiki ID 119 * 120 * @author Andreas Gohr <andi@splitbrain.org> 121 */ 122 function getNS($id){ 123 $pos = strrpos($id,':'); 124 if($pos!==false){ 125 return substr($id,0,$pos); 126 } 127 return false; 128 } 129 130 /** 131 * Returns the ID without the namespace 132 * 133 * @author Andreas Gohr <andi@splitbrain.org> 134 */ 135 function noNS($id) { 136 $pos = strrpos($id, ':'); 137 if ($pos!==false) { 138 return substr($id, $pos+1); 139 } else { 140 return $id; 141 } 142 } 143 144 /** 145 * returns the full path to the datafile specified by ID and 146 * optional revision 147 * 148 * The filename is URL encoded to protect Unicode chars 149 * 150 * @author Andreas Gohr <andi@splitbrain.org> 151 */ 152 function wikiFN($raw_id,$rev='',$clean=true){ 153 global $conf; 154 155 global $cache_wikifn; 156 $cache = & $cache_wikifn; 157 158 if (isset($cache[$raw_id]) && isset($cache[$raw_id][$rev])) { 159 return $cache[$raw_id][$rev]; 160 } 161 162 $id = $raw_id; 163 164 if ($clean) $id = cleanID($id); 165 $id = str_replace(':','/',$id); 166 if(empty($rev)){ 167 $fn = $conf['datadir'].'/'.utf8_encodeFN($id).'.txt'; 168 }else{ 169 $fn = $conf['olddir'].'/'.utf8_encodeFN($id).'.'.$rev.'.txt'; 170 if($conf['compression']){ 171 //test for extensions here, we want to read both compressions 172 if (@file_exists($fn . '.gz')){ 173 $fn .= '.gz'; 174 }else if(@file_exists($fn . '.bz2')){ 175 $fn .= '.bz2'; 176 }else{ 177 //file doesnt exist yet, so we take the configured extension 178 $fn .= '.' . $conf['compression']; 179 } 180 } 181 } 182 183 if (!isset($cache[$raw_id])) { $cache[$raw_id] = array(); } 184 $cache[$raw_id][$rev] = $fn; 185 return $fn; 186 } 187 188 /** 189 * Returns the full path to the file for locking the page while editing. 190 * 191 * @author Ben Coburn <btcoburn@silicodon.net> 192 */ 193 function wikiLockFN($id) { 194 global $conf; 195 return $conf['lockdir'].'/'.md5(cleanID($id)).'.lock'; 196 } 197 198 199 /** 200 * returns the full path to the meta file specified by ID and extension 201 * 202 * The filename is URL encoded to protect Unicode chars 203 * 204 * @author Steven Danz <steven-danz@kc.rr.com> 205 */ 206 function metaFN($id,$ext){ 207 global $conf; 208 $id = cleanID($id); 209 $id = str_replace(':','/',$id); 210 $fn = $conf['metadir'].'/'.utf8_encodeFN($id).$ext; 211 return $fn; 212 } 213 214 /** 215 * returns an array of full paths to all metafiles of a given ID 216 * 217 * @author Esther Brunner <esther@kaffeehaus.ch> 218 */ 219 function metaFiles($id){ 220 $name = noNS($id); 221 $dir = metaFN(getNS($id),''); 222 $files = array(); 223 224 $dh = @opendir($dir); 225 if(!$dh) return $files; 226 while(($file = readdir($dh)) !== false){ 227 if(strpos($file,$name.'.') === 0 && !is_dir($dir.$file)) 228 $files[] = $dir.$file; 229 } 230 closedir($dh); 231 232 return $files; 233 } 234 235 /** 236 * returns the full path to the mediafile specified by ID 237 * 238 * The filename is URL encoded to protect Unicode chars 239 * 240 * @author Andreas Gohr <andi@splitbrain.org> 241 */ 242 function mediaFN($id){ 243 global $conf; 244 $id = cleanID($id); 245 $id = str_replace(':','/',$id); 246 $fn = $conf['mediadir'].'/'.utf8_encodeFN($id); 247 return $fn; 248 } 249 250 /** 251 * Returns the full filepath to a localized textfile if local 252 * version isn't found the english one is returned 253 * 254 * @author Andreas Gohr <andi@splitbrain.org> 255 */ 256 function localeFN($id){ 257 global $conf; 258 $file = DOKU_INC.'inc/lang/'.$conf['lang'].'/'.$id.'.txt'; 259 if(!@file_exists($file)){ 260 //fall back to english 261 $file = DOKU_INC.'inc/lang/en/'.$id.'.txt'; 262 } 263 return $file; 264 } 265 266 /** 267 * Resolve relative paths in IDs 268 * 269 * Do not call directly use resolve_mediaid or resolve_pageid 270 * instead 271 * 272 * Partyly based on a cleanPath function found at 273 * http://www.php.net/manual/en/function.realpath.php#57016 274 * 275 * @author <bart at mediawave dot nl> 276 */ 277 function resolve_id($ns,$id,$clean=true){ 278 // if the id starts with a dot we need to handle the 279 // relative stuff 280 if($id{0} == '.'){ 281 // normalize initial dots without a colon 282 $id = preg_replace('/^(\.+)(?=[^:\.])/','\1:',$id); 283 // prepend the current namespace 284 $id = $ns.':'.$id; 285 286 // cleanup relatives 287 $result = array(); 288 $pathA = explode(':', $id); 289 if (!$pathA[0]) $result[] = ''; 290 foreach ($pathA AS $key => $dir) { 291 if ($dir == '..') { 292 if (end($result) == '..') { 293 $result[] = '..'; 294 } elseif (!array_pop($result)) { 295 $result[] = '..'; 296 } 297 } elseif ($dir && $dir != '.') { 298 $result[] = $dir; 299 } 300 } 301 if (!end($pathA)) $result[] = ''; 302 $id = implode(':', $result); 303 }elseif($ns !== false && strpos($id,':') === false){ 304 //if link contains no namespace. add current namespace (if any) 305 $id = $ns.':'.$id; 306 } 307 308 if($clean) $id = cleanID($id); 309 return $id; 310 } 311 312 /** 313 * Returns a full media id 314 * 315 * @author Andreas Gohr <andi@splitbrain.org> 316 */ 317 function resolve_mediaid($ns,&$page,&$exists){ 318 $page = resolve_id($ns,$page); 319 $file = mediaFN($page); 320 $exists = @file_exists($file); 321 } 322 323 /** 324 * Returns a full page id 325 * 326 * @author Andreas Gohr <andi@splitbrain.org> 327 */ 328 function resolve_pageid($ns,&$page,&$exists){ 329 global $conf; 330 $exists = false; 331 332 //keep hashlink if exists then clean both parts 333 if (strpos($page,'#')) { 334 list($page,$hash) = split('#',$page,2); 335 } else { 336 $hash = ''; 337 } 338 $hash = cleanID($hash); 339 $page = resolve_id($ns,$page,false); // resolve but don't clean, yet 340 341 // get filename (calls clean itself) 342 $file = wikiFN($page); 343 344 // if ends with colon we have a namespace link 345 if(substr($page,-1) == ':'){ 346 if(@file_exists(wikiFN($page.$conf['start']))){ 347 // start page inside namespace 348 $page = $page.$conf['start']; 349 $exists = true; 350 }elseif(@file_exists(wikiFN($page.noNS(cleanID($page))))){ 351 // page named like the NS inside the NS 352 $page = $page.noNS(cleanID($page)); 353 $exists = true; 354 }elseif(@file_exists(wikiFN($page))){ 355 // page like namespace exists 356 $page = $page; 357 $exists = true; 358 }else{ 359 // fall back to default 360 $page = $page.$conf['start']; 361 } 362 }else{ 363 //check alternative plural/nonplural form 364 if(!@file_exists($file)){ 365 if( $conf['autoplural'] ){ 366 if(substr($page,-1) == 's'){ 367 $try = substr($page,0,-1); 368 }else{ 369 $try = $page.'s'; 370 } 371 if(@file_exists(wikiFN($try))){ 372 $page = $try; 373 $exists = true; 374 } 375 } 376 }else{ 377 $exists = true; 378 } 379 } 380 381 // now make sure we have a clean page 382 $page = cleanID($page); 383 384 //add hash if any 385 if(!empty($hash)) $page .= '#'.$hash; 386 } 387 388 /** 389 * Returns the name of a cachefile from given data 390 * 391 * The needed directory is created by this function! 392 * 393 * @author Andreas Gohr <andi@splitbrain.org> 394 * 395 * @param string $data This data is used to create a unique md5 name 396 * @param string $ext This is appended to the filename if given 397 * @return string The filename of the cachefile 398 */ 399 function getCacheName($data,$ext=''){ 400 global $conf; 401 $md5 = md5($data); 402 $file = $conf['cachedir'].'/'.$md5{0}.'/'.$md5.$ext; 403 io_makeFileDir($file); 404 return $file; 405 } 406 407 /** 408 * Checks a pageid against $conf['hidepages'] 409 * 410 * @author Andreas Gohr <gohr@cosmocode.de> 411 */ 412 function isHiddenPage($id){ 413 global $conf; 414 if(empty($conf['hidepages'])) return false; 415 416 if(preg_match('/'.$conf['hidepages'].'/ui',':'.$id)){ 417 return true; 418 } 419 return false; 420 } 421 422 /** 423 * Reverse of isHiddenPage 424 * 425 * @author Andreas Gohr <gohr@cosmocode.de> 426 */ 427 function isVisiblePage($id){ 428 return !isHiddenPage($id); 429 } 430 431 /** 432 * Checks and sets HTTP headers for conditional HTTP requests 433 * 434 * @author Simon Willison <swillison@gmail.com> 435 * @link http://simon.incutio.com/archive/2003/04/23/conditionalGet 436 * @param timestamp $timestamp lastmodified time of the cache file 437 * @returns void or void with previously header() commands executed 438 */ 439 function http_conditionalRequest($timestamp){ 440 // A PHP implementation of conditional get, see 441 // http://fishbowl.pastiche.org/archives/001132.html 442 $last_modified = substr(date('r', $timestamp), 0, -5).'GMT'; 443 $etag = '"'.md5($last_modified).'"'; 444 // Send the headers 445 header("Last-Modified: $last_modified"); 446 header("ETag: $etag"); 447 // See if the client has provided the required headers 448 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])){ 449 $if_modified_since = stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']); 450 }else{ 451 $if_modified_since = false; 452 } 453 454 if (isset($_SERVER['HTTP_IF_NONE_MATCH'])){ 455 $if_none_match = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']); 456 }else{ 457 $if_none_match = false; 458 } 459 460 if (!$if_modified_since && !$if_none_match){ 461 return; 462 } 463 464 // At least one of the headers is there - check them 465 if ($if_none_match && $if_none_match != $etag) { 466 return; // etag is there but doesn't match 467 } 468 469 if ($if_modified_since && $if_modified_since != $last_modified) { 470 return; // if-modified-since is there but doesn't match 471 } 472 473 // Nothing has changed since their last request - serve a 304 and exit 474 header('HTTP/1.0 304 Not Modified'); 475 exit; 476 } 477 478 //Setup VIM: ex: et ts=2 enc=utf-8 :
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Tue Apr 3 20:47:31 2007 | par Balluche grâce à PHPXref 0.7 |