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 */ 21function getID($param='id',$clean=true){ 22 global $conf; 23 24 $id = $_REQUEST[$param]; 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 $id The pageid to clean 69 * @param boolean $ascii Force ASCII 70 */ 71function cleanID($id,$ascii=false){ 72 global $conf; 73 global $lang; 74 static $sepcharpat = null; 75 76 $sepchar = $conf['sepchar']; 77 if($sepcharpat == null) // build string only once to save clock cycles 78 $sepcharpat = '#\\'.$sepchar.'+#'; 79 80 $id = trim($id); 81 $id = utf8_strtolower($id); 82 83 //alternative namespace seperator 84 $id = strtr($id,';',':'); 85 if($conf['useslash']){ 86 $id = strtr($id,'/',':'); 87 }else{ 88 $id = strtr($id,'/',$sepchar); 89 } 90 91 if($conf['deaccent'] == 2 || $ascii) $id = utf8_romanize($id); 92 if($conf['deaccent'] || $ascii) $id = utf8_deaccent($id,-1); 93 94 //remove specials 95 $id = utf8_stripspecials($id,$sepchar,'\*'); 96 97 if($ascii) $id = utf8_strip($id); 98 99 //clean up 100 $id = preg_replace($sepcharpat,$sepchar,$id); 101 $id = preg_replace('#:+#',':',$id); 102 $id = trim($id,':._-'); 103 $id = preg_replace('#:[:\._\-]+#',':',$id); 104 105 return($id); 106} 107 108/** 109 * Return namespacepart of a wiki ID 110 * 111 * @author Andreas Gohr <andi@splitbrain.org> 112 */ 113function getNS($id){ 114 if(strpos($id,':')!==false){ 115 return substr($id,0,strrpos($id,':')); 116 } 117 return false; 118} 119 120/** 121 * Returns the ID without the namespace 122 * 123 * @author Andreas Gohr <andi@splitbrain.org> 124 */ 125function noNS($id){ 126 return preg_replace('/.*:/','',$id); 127} 128 129/** 130 * returns the full path to the datafile specified by ID and 131 * optional revision 132 * 133 * The filename is URL encoded to protect Unicode chars 134 * 135 * @author Andreas Gohr <andi@splitbrain.org> 136 */ 137function wikiFN($id,$rev=''){ 138 global $conf; 139 $id = cleanID($id); 140 $id = str_replace(':','/',$id); 141 if(empty($rev)){ 142 $fn = $conf['datadir'].'/'.utf8_encodeFN($id).'.txt'; 143 }else{ 144 $fn = $conf['olddir'].'/'.utf8_encodeFN($id).'.'.$rev.'.txt'; 145 if($conf['usegzip'] && !@file_exists($fn)){ 146 //return gzip if enabled and plaintext doesn't exist 147 $fn .= '.gz'; 148 } 149 } 150 return $fn; 151} 152 153/** 154 * returns the full path to the meta file specified by ID and extension 155 * 156 * The filename is URL encoded to protect Unicode chars 157 * 158 * @author Steven Danz <steven-danz@kc.rr.com> 159 */ 160function metaFN($id,$ext){ 161 global $conf; 162 $id = cleanID($id); 163 $id = str_replace(':','/',$id); 164 $fn = $conf['metadir'].'/'.utf8_encodeFN($id).$ext; 165 return $fn; 166} 167 168/** 169 * returns an array of full paths to all metafiles of a given ID 170 * 171 * @author Esther Brunner <esther@kaffeehaus.ch> 172 */ 173function metaFiles($id){ 174 $name = noNS($id); 175 $dir = metaFN(getNS($id),''); 176 $files = array(); 177 178 $dh = @opendir($dir); 179 if(!$dh) return $files; 180 while(($file = readdir($dh)) !== false){ 181 if(strpos($file,$name.'.') === 0 && !is_dir($dir.$file)) 182 $files[] = $dir.$file; 183 } 184 closedir($dh); 185 186 return $files; 187} 188 189/** 190 * returns the full path to the mediafile specified by ID 191 * 192 * The filename is URL encoded to protect Unicode chars 193 * 194 * @author Andreas Gohr <andi@splitbrain.org> 195 */ 196function mediaFN($id){ 197 global $conf; 198 $id = cleanID($id); 199 $id = str_replace(':','/',$id); 200 $fn = $conf['mediadir'].'/'.utf8_encodeFN($id); 201 return $fn; 202} 203 204/** 205 * Returns the full filepath to a localized textfile if local 206 * version isn't found the english one is returned 207 * 208 * @author Andreas Gohr <andi@splitbrain.org> 209 */ 210function localeFN($id){ 211 global $conf; 212 $file = DOKU_INC.'inc/lang/'.$conf['lang'].'/'.$id.'.txt'; 213 if(!@file_exists($file)){ 214 //fall back to english 215 $file = DOKU_INC.'inc/lang/en/'.$id.'.txt'; 216 } 217 return $file; 218} 219 220/** 221 * Returns a full media id 222 * 223 * @author Andreas Gohr <andi@splitbrain.org> 224 */ 225function resolve_mediaid($ns,&$page,&$exists){ 226 global $conf; 227 228 //if links starts with . add current namespace 229 if($page{0} == '.'){ 230 $page = $ns.':'.substr($page,1); 231 } 232 233 //if link contains no namespace. add current namespace (if any) 234 if($ns !== false && strpos($page,':') === false){ 235 $page = $ns.':'.$page; 236 } 237 238 $page = cleanID($page); 239 $file = mediaFN($page); 240 $exists = @file_exists($file); 241} 242 243/** 244 * Returns a full page id 245 * 246 * @author Andreas Gohr <andi@splitbrain.org> 247 */ 248function resolve_pageid($ns,&$page,&$exists){ 249 global $conf; 250 $exists = false; 251 252 //if links starts with . add current namespace 253 if($page{0} == '.'){ 254 $page = $ns.':'.substr($page,1); 255 } 256 257 //if link contains no namespace. add current namespace (if any) 258 if($ns !== false && strpos($page,':') === false){ 259 $page = $ns.':'.$page; 260 } 261 262 //keep hashlink if exists then clean both parts 263 list($page,$hash) = split('#',$page,2); 264 $page = cleanID($page); 265 $hash = cleanID($hash); 266 267 $file = wikiFN($page); 268 269 //check alternative plural/nonplural form 270 if(!@file_exists($file)){ 271 if( $conf['autoplural'] ){ 272 if(substr($page,-1) == 's'){ 273 $try = substr($page,0,-1); 274 }else{ 275 $try = $page.'s'; 276 } 277 if(@file_exists(wikiFN($try))){ 278 $page = $try; 279 $exists = true; 280 } 281 } 282 }else{ 283 $exists = true; 284 } 285 286 //add hash if any 287 if(!empty($hash)) $page .= '#'.$hash; 288} 289 290/** 291 * Returns the name of a cachefile from given data 292 * 293 * The needed directory is created by this function! 294 * 295 * @author Andreas Gohr <andi@splitbrain.org> 296 * 297 * @param string $data This data is used to create a unique md5 name 298 * @param string $ext This is appended to the filename if given 299 * @return string The filename of the cachefile 300 */ 301function getCacheName($data,$ext=''){ 302 global $conf; 303 $md5 = md5($data); 304 $file = $conf['cachedir'].'/'.$md5{0}.'/'.$md5.$ext; 305 io_makeFileDir($file); 306 return $file; 307} 308 309/** 310 * Checks a pageid against $conf['hidepages'] 311 * 312 * @author Andreas Gohr <gohr@cosmocode.de> 313 */ 314function isHiddenPage($id){ 315 global $conf; 316 if(empty($conf['hidepages'])) return false; 317 318 if(preg_match('/'.$conf['hidepages'].'/ui',':'.$id)){ 319 return true; 320 } 321 return false; 322} 323 324/** 325 * Reverse of isHiddenPage 326 * 327 * @author Andreas Gohr <gohr@cosmocode.de> 328 */ 329function isVisiblePage($id){ 330 return !isHiddenPage($id); 331} 332 333//Setup VIM: ex: et ts=2 enc=utf-8 : 334