xref: /dokuwiki/inc/pageutils.php (revision 81124000ddd28d1b4c8c39847dfe27783342ea75)
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 * and the returned ID will be cleaned. For other params the
18 * cleaning has to be done outside this function
19 *
20 * @author Andreas Gohr <andi@splitbrain.org>
21 */
22function getID($param='id'){
23  global $conf;
24
25  $id = $_REQUEST[$param];
26
27  if($param == 'id') $id = cleanID($id);
28
29  //construct page id from request URI
30  if(empty($id) && $conf['userewrite'] == 2){
31    //get the script URL
32    if($conf['basedir']){
33      $relpath = '';
34      if($param != 'id') {
35        $relpath = 'lib/exe/';
36      }
37      $script = $conf['basedir'].$relpath.basename($_SERVER['SCRIPT_FILENAME']);
38    }elseif($_SERVER['DOCUMENT_ROOT'] && $_SERVER['SCRIPT_FILENAME']){
39      $script = preg_replace ('/^'.preg_quote($_SERVER['DOCUMENT_ROOT'],'/').'/','',
40                              $_SERVER['SCRIPT_FILENAME']);
41      $script = '/'.$script;
42    }else{
43      $script = $_SERVER['SCRIPT_NAME'];
44    }
45
46    //clean script and request (fixes a windows problem)
47    $script  = preg_replace('/\/\/+/','/',$script);
48    $request = preg_replace('/\/\/+/','/',$_SERVER['REQUEST_URI']);
49
50    //remove script URL and Querystring to gain the id
51    if(preg_match('/^'.preg_quote($script,'/').'(.*)/',$request, $match)){
52      $id = preg_replace ('/\?.*/','',$match[1]);
53    }
54    $id = urldecode($id);
55    $id = cleanID($id);
56  }
57  if(empty($id) && $param=='id') $id = cleanID($conf['start']);
58
59  return $id;
60}
61
62/**
63 * Remove unwanted chars from ID
64 *
65 * Cleans a given ID to only use allowed characters. Accented characters are
66 * converted to unaccented ones
67 *
68 * @author Andreas Gohr <andi@splitbrain.org>
69 */
70function cleanID($id){
71  global $conf;
72  global $lang;
73  static $sepcharpat = null;
74
75  $sepchar = $conf['sepchar'];
76  if($sepcharpat == null) // build string only once to save clock cycles
77    $sepcharpat = '#\\'.$sepchar.'+#';
78
79  $id = trim($id);
80  $id = utf8_strtolower($id);
81
82  //alternative namespace seperator
83  $id = strtr($id,';',':');
84  if($conf['useslash']){
85    $id = strtr($id,'/',':');
86  }else{
87    $id = strtr($id,'/',$sepchar);
88  }
89
90  if($conf['deaccent']) $id = utf8_deaccent($id,-1);
91
92  //remove specials
93  $id = utf8_stripspecials($id,$sepchar);
94
95  //clean up
96  $id = preg_replace($sepcharpat,$sepchar,$id);
97  $id = preg_replace('#:+#',':',$id);
98  $id = trim($id,':._-');
99  $id = preg_replace('#:[:\._\-]+#',':',$id);
100
101  return($id);
102}
103
104/**
105 * Return namespacepart of a wiki ID
106 *
107 * @author Andreas Gohr <andi@splitbrain.org>
108 */
109function getNS($id){
110 if(strpos($id,':')!==false){
111   return substr($id,0,strrpos($id,':'));
112 }
113 return false;
114}
115
116/**
117 * Returns the ID without the namespace
118 *
119 * @author Andreas Gohr <andi@splitbrain.org>
120 */
121function noNS($id){
122  return preg_replace('/.*:/','',$id);
123}
124
125/**
126 * returns the full path to the datafile specified by ID and
127 * optional revision
128 *
129 * The filename is URL encoded to protect Unicode chars
130 *
131 * @author Andreas Gohr <andi@splitbrain.org>
132 */
133function wikiFN($id,$rev=''){
134  global $conf;
135  $id = cleanID($id);
136  $id = str_replace(':','/',$id);
137  if(empty($rev)){
138    $fn = $conf['datadir'].'/'.utf8_encodeFN($id).'.txt';
139  }else{
140    $fn = $conf['olddir'].'/'.utf8_encodeFN($id).'.'.$rev.'.txt';
141    if($conf['usegzip'] && !@file_exists($fn)){
142      //return gzip if enabled and plaintext doesn't exist
143      $fn .= '.gz';
144    }
145  }
146  return $fn;
147}
148
149/**
150 * returns the full path to the meta file specified by ID and extension
151 *
152 * The filename is URL encoded to protect Unicode chars
153 *
154 * @author Steven Danz <steven-danz@kc.rr.com>
155 */
156function metaFN($id,$ext){
157  global $conf;
158  $id = cleanID($id);
159  $id = str_replace(':','/',$id);
160  $fn = $conf['metadir'].'/'.utf8_encodeFN($id).$ext;
161  return $fn;
162}
163
164/**
165 * returns an array of full paths to all metafiles of a given ID
166 *
167 * @author Esther Brunner <esther@kaffeehaus.ch>
168 */
169function metaFiles($id){
170   $name   = noNS($id);
171   $dir    = metaFN(getNS($id),'');
172   $files  = array();
173
174   $dh = @opendir($dir);
175   if(!$dh) return $files;
176   while(($file = readdir($dh)) !== false){
177     if(strpos($file,$name.'.') === 0 && !is_dir($dir.$file))
178       $files[] = $dir.$file;
179   }
180   closedir($dh);
181
182   return $files;
183}
184
185/**
186 * returns the full path to the mediafile specified by ID
187 *
188 * The filename is URL encoded to protect Unicode chars
189 *
190 * @author Andreas Gohr <andi@splitbrain.org>
191 */
192function mediaFN($id){
193  global $conf;
194  $id = cleanID($id);
195  $id = str_replace(':','/',$id);
196    $fn = $conf['mediadir'].'/'.utf8_encodeFN($id);
197  return $fn;
198}
199
200/**
201 * Returns the full filepath to a localized textfile if local
202 * version isn't found the english one is returned
203 *
204 * @author Andreas Gohr <andi@splitbrain.org>
205 */
206function localeFN($id){
207  global $conf;
208  $file = DOKU_INC.'inc/lang/'.$conf['lang'].'/'.$id.'.txt';
209  if(!@file_exists($file)){
210    //fall back to english
211    $file = DOKU_INC.'inc/lang/en/'.$id.'.txt';
212  }
213  return $file;
214}
215
216/**
217 * Returns a full media id
218 *
219 * @author Andreas Gohr <andi@splitbrain.org>
220 */
221function resolve_mediaid($ns,&$page,&$exists){
222  global $conf;
223
224  //if links starts with . add current namespace
225  if($page{0} == '.'){
226    $page = $ns.':'.substr($page,1);
227  }
228
229  //if link contains no namespace. add current namespace (if any)
230  if($ns !== false && strpos($page,':') === false){
231    $page = $ns.':'.$page;
232  }
233
234  $page   = cleanID($page);
235  $file   = mediaFN($page);
236  $exists = @file_exists($file);
237}
238
239/**
240 * Returns a full page id
241 *
242 * @author Andreas Gohr <andi@splitbrain.org>
243 */
244function resolve_pageid($ns,&$page,&$exists){
245  global $conf;
246  $exists = false;
247
248  //if links starts with . add current namespace
249  if($page{0} == '.'){
250    $page = $ns.':'.substr($page,1);
251  }
252
253  //if link contains no namespace. add current namespace (if any)
254  if($ns !== false && strpos($page,':') === false){
255    $page = $ns.':'.$page;
256  }
257
258  //keep hashlink if exists then clean both parts
259  list($page,$hash) = split('#',$page,2);
260  $page = cleanID($page);
261  $hash = cleanID($hash);
262
263  $file = wikiFN($page);
264
265  //check alternative plural/nonplural form
266  if(!@file_exists($file)){
267    if( $conf['autoplural'] ){
268      if(substr($page,-1) == 's'){
269        $try = substr($page,0,-1);
270      }else{
271        $try = $page.'s';
272      }
273      if(@file_exists(wikiFN($try))){
274        $page   = $try;
275        $exists = true;
276      }
277    }
278  }else{
279    $exists = true;
280  }
281
282  //add hash if any
283  if(!empty($hash)) $page .= '#'.$hash;
284}
285
286/**
287 * Returns the name of a cachefile from given data
288 *
289 * The needed directory is created by this function!
290 *
291 * @author Andreas Gohr <andi@splitbrain.org>
292 *
293 * @param string $data  This data is used to create a unique md5 name
294 * @param string $ext   This is appended to the filename if given
295 * @return string       The filename of the cachefile
296 */
297function getCacheName($data,$ext=''){
298  global $conf;
299  $md5  = md5($data);
300  $file = $conf['cachedir'].'/'.$md5{0}.'/'.$md5.$ext;
301  io_makeFileDir($file);
302  return $file;
303}
304
305//Setup VIM: ex: et ts=2 enc=utf-8 :
306