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