dev notes
[viewsvn.git] / includes / paths.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # ViewSVN [#]version[#]
5 || # Copyright ©2002-[#]year[#] Iris Studios, Inc.
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * Handles the various methods that are used to navigate
24 * browser paths
25 *
26 * @package ViewSVN
27 */
28
29 /*
30
31 the majority of this stuff should go into the controller.
32 the string creators may need to go into a static class or something. or not. we'll see.
33
34 */
35
36 /**
37 * Path managing class that constructs and parses input
38 * and output for paths. This is essentially a controller
39 * of all current information.
40 *
41 * @package ViewSVN
42 * @version $Id$
43 */
44 class Paths
45 {
46 /**
47 * Path manager type
48 * @var integer
49 */
50 var $type;
51
52 /**
53 * The universal path that is currently being browsed
54 * @var string
55 */
56 var $path;
57
58 /**
59 * Current repository that we're in
60 * @var string
61 */
62 var $repos;
63
64 /**
65 * Current internal path inside the repository
66 * @var string
67 */
68 var $relpath;
69
70 /**
71 * The current revision number
72 * @var integer
73 */
74 var $revnum;
75
76 /**
77 * The current revision as a string argument
78 * @var string
79 */
80 var $revstr;
81
82 /**
83 * Constructor: determine the type of linking to use
84 *
85 * @param integer Path management type
86 */
87 function Paths($type)
88 {
89 global $viewsvn;
90
91 if ($type < 1 OR $type > 2)
92 {
93 $viewsvn->trigger->error($viewsvn->lang->string('Invalid path management type specified in [includes/config.php]'));
94 }
95
96 $this->type = (int)$type;
97
98 $this->path = $this->parse();
99 $this->revnum = $this->revnum;
100 $this->revstr = $this->revstr;
101 }
102
103 /**
104 * Constructs a repository browser link
105 *
106 * @access public
107 *
108 * @param string Base path
109 * @param string Browser path, separated using '/'
110 *
111 * @return string Link path
112 */
113 function out($base, $addpath)
114 {
115 global $viewsvn;
116
117 $url = $this->fetch_arguments($base);
118 $addpath = $this->sanitize($addpath);
119
120 // standard URL type
121 if ($this->type == 1)
122 {
123 return $url[0] . '?path=' . $addpath . ($url[1] ? '&amp;' . $url[1] : '');
124 }
125 // advanced path system
126 else if ($this->type == 2)
127 {
128 return $url[0] . ($addpath{0} != '/' ? '/' : '') . $addpath . ($url[1] ? '?' . $url[1] : '');
129 }
130 }
131
132 /**
133 * Parses an incoming path with the various methods
134 * and returns a universal form
135 *
136 * @access public
137 *
138 * @return string Universal path, separated using '/'
139 */
140 function parse()
141 {
142 global $viewsvn;
143
144 if (defined('PATH_OVERRIDE') AND PATH_OVERRIDE == 1)
145 {
146 return;
147 }
148
149 // standard URL type
150 if ($this->type == 1)
151 {
152 $path = $viewsvn->in['path'];
153 }
154 // advanced path system
155 else if ($this->type == 2)
156 {
157 if (@$_SERVER['PATH_INFO'])
158 {
159 $path = $viewsvn->sanitize($_SERVER['PATH_INFO']);
160 }
161 else
162 {
163 $viewsvn->trigger->error($viewsvn->lang->string('Your server does not support type-2 path management'));
164 }
165 }
166
167 if (!$path)
168 {
169 $viewsvn->trigger->error($viewsvn->lang->string('Invalid path sent'));
170 }
171
172 if (!$viewsvn->repos->verify($this->repos = $this->fetch_repos($path), $this->relpath = $this->fetch_path($path)))
173 {
174 $viewsvn->trigger->error($viewsvn->lang->string('The path specified could not be verified'));
175 }
176
177 return $path;
178 }
179
180 /**
181 * Create path breadcrumb
182 *
183 * @access public
184 *
185 * @param string Universal path
186 * @param bool Add trailing slash
187 *
188 * @return string Breadcrumb HTML
189 */
190 function construct_breadcrumb($path, $doslash = true)
191 {
192 global $viewsvn, $cachev;
193
194 $html = '/ ';
195 $itembit = '/';
196
197 $temp = preg_split('#/#', $path, -1, PREG_SPLIT_NO_EMPTY);
198 $count = count($temp) - 1;
199
200 foreach ($temp AS $val => $item)
201 {
202 $itembit .= $item;
203 $itembit .= (($count != $val OR $cachev->isdir($itembit)) ? '/' : '');
204 $html .= '<a href="' . $viewsvn->path . '/' . $this->out('browse.php' . $this->revstr, $itembit) . '">' . $item . '</a>'. ($count != $val ? ' / ' : '');
205 }
206
207 return $html;
208 }
209
210 /**
211 * Returns the name of the repository from a upath
212 *
213 * @access public
214 *
215 * @param string Universal path
216 *
217 * @return string Repository name
218 */
219 function fetch_repos($path)
220 {
221 $temp = preg_split('#/#', $path, -1, PREG_SPLIT_NO_EMPTY);
222 return $temp[0];
223 }
224
225 /**
226 * Returns the path without the repository from a upath
227 *
228 * @access public
229 *
230 * @param string Universal path
231 * @param bool Preceding slash
232 *
233 * @return string Relative path
234 */
235 function fetch_path($path, $doslash = false)
236 {
237 $temp = preg_split('#/#', $path, -1, PREG_SPLIT_NO_EMPTY);
238 unset($temp[0]);
239 return ($doslash ? '/' : '') . implode('/', $temp);
240 }
241
242 /**
243 * Fetches any URL parameters a link has
244 *
245 * @access public
246 *
247 * @param string Original URL
248 *
249 * @return array Two-element array: base path (no trailing '?'), arguments
250 */
251 function fetch_arguments($url)
252 {
253 $return = array();
254
255 $bits = parse_url($url);
256
257 if (isset($bits['query']))
258 {
259 $return[0] = $bits['path'];
260 $return[1] = $bits['query'];
261 }
262 else
263 {
264 $return[0] = $bits['path'];
265 $return[1] = '';
266 }
267
268 return $return;
269 }
270
271 /**
272 * Determines if the root path has been reached
273 *
274 * @access public
275 *
276 * @param string Universal path
277 *
278 * @return bool Root of path?
279 */
280 function is_root_path($path)
281 {
282 $path = $this->fetch_path($path);
283 $temp = preg_split('#/#', $path, -1, PREG_SPLIT_NO_EMPTY);
284 if (count($temp) > 0)
285 {
286 return false;
287 }
288 else
289 {
290 return true;
291 }
292 }
293
294 /**
295 * Returns the current sanitized revision
296 *
297 * @access public
298 *
299 * @param bool High-low or not
300 * @param mixed High revision (or regular)
301 * @param mixed Low revision
302 *
303 * @return mixed Revision number or HEAD
304 */
305 function fetch_rev_num($highlow = false, $high = null, $low = null)
306 {
307 global $viewsvn;
308
309 if ($highlow)
310 {
311 if (isset($viewsvn->in['high']) AND is_null($high))
312 {
313 $high = $viewsvn->svn->rev($viewsvn->in['high']);
314 }
315 else if (is_null($high))
316 {
317 $high = 'HEAD';
318 }
319
320 if (isset($viewsvn->in['low']) AND is_null($low))
321 {
322 $low = $viewsvn->svn->rev($viewsvn->in['low']);
323 }
324 else if (is_null($low))
325 {
326 $low = 0;
327 }
328
329 if ($low == 'HEAD')
330 {
331 $low = 0;
332 }
333
334 if (is_int($high) AND is_int($low) AND $low > $high)
335 {
336 $temp = $high;
337 $high = $low;
338 $low = $temp;
339 }
340
341 return array('high' => $high, 'low' => $low);
342 }
343 else
344 {
345 if (isset($viewsvn->in['rev']) AND is_null($high))
346 {
347 $rev = $viewsvn->svn->rev($viewsvn->in['rev']);
348 }
349 else if (is_null($high))
350 {
351 $rev = 'HEAD';
352 }
353 else
354 {
355 $rev = $high;
356 }
357
358 return $rev;
359 }
360 }
361
362 /**
363 * Returns a GET string with sanitized revision data
364 *
365 * @access public
366 *
367 * @param bool High-low or not
368 * @param mixed High revision (or regular)
369 * @param mixed Low revision
370 *
371 * @return string Revision GET data
372 */
373 function fetch_rev_str($highlow = false, $high = null, $low = null)
374 {
375 $rev = $this->fetch_rev_num($highlow, $high, $low);
376
377 if ($highlow)
378 {
379 return '?low=' . $rev['low'] . '&amp;high=' . $rev['high'];
380 }
381 else
382 {
383 return '?rev=' . $rev;
384 }
385 }
386
387 /**
388 * Sanitizes a path for passing
389 *
390 * @access private
391 *
392 * @param string Path
393 *
394 * @return string Cleaned string
395 */
396 function sanitize($path)
397 {
398 return preg_replace('#[^a-z0-9\./\-_]*#i', '', $path);
399 }
400 }
401
402 /*=====================================================================*\
403 || ###################################################################
404 || # $HeadURL$
405 || # $Id$
406 || ###################################################################
407 \*=====================================================================*/
408 ?>