3 require_once(dirname(__FILE__).'/stdlib.php');
6 * A class for finding files.
8 * This should really provided by pear. We don't want really to mess around
9 * with all the lousy systems. (WindowsNT, Win95, Mac, ...)
10 * But pear has only System and File, which do nothing.
11 * Anyway, in good PHP style we ignore the rest of the world and try to behave
12 * as on unix only. That means we use / as pathsep in all our constants.
16 //var $_pathsep, $_path;
21 * @param $path array A list of directories in which to search for files.
23 function FileFinder ($path = false) {
24 $this->_pathsep = $this->_get_syspath_separator();
25 if (!isset($this->_path) and $path === false)
26 $path = $this->_get_include_path();
33 * @param $file string File to search for.
34 * @return string The filename (including path), if found, otherwise false.
36 function findFile ($file, $missing_okay = false) {
37 if ($this->_is_abs($file)) {
38 if (file_exists($file))
41 elseif ( ($dir = $this->_search_path($file)) ) {
42 return $dir . $this->_use_path_separator($dir) . $file;
44 return $missing_okay ? false : $this->_not_found($file);
48 * Unify used pathsep character.
49 * Accepts array of paths also.
50 * This might not work on Windows95 or FAT volumes. (not tested)
52 function slashifyPath ($path) {
53 return $this->forcePathSlashes($path, $this->_pathsep);
57 * Force using '/' as path seperator.
59 function forcePathSlashes ($path, $sep='/') {
60 if (is_array($path)) {
62 foreach ($path as $dir) { $result[] = $this->forcePathSlashes($dir,$sep); }
65 if (isWindows() or $this->_isOtherPathsep()) {
66 if (isWindows()) $from = "\\";
68 // PHP is stupid enough to use \\ instead of \
70 if (substr($path,0,2) != '\\\\')
71 $path = str_replace('\\\\','\\',$path);
73 $path = '\\\\' . str_replace('\\\\','\\',substr($path,2));
75 return strtr($path, $from, $sep);
82 * Try to include file.
84 * If file is found in the path, then the files directory is added
85 * to PHP's include_path (if it's not already there.) Then the
86 * file is include_once()'d.
88 * @param $file string File to include.
89 * @return bool True if file was successfully included.
91 function includeOnce ($file) {
92 if ( ($ret = @include_once($file)) )
95 if (!$this->_is_abs($file)) {
96 if ( ($dir = $this->_search_path($file)) && is_file($dir . $this->_pathsep . $file)) {
97 $this->_append_to_include_path($dir);
98 return include_once($file);
101 return $this->_not_found($file);
104 function _isOtherPathsep() {
105 return $this->_pathsep != '/';
109 * The system-dependent path-separator character.
110 * UNIX,WindowsNT,MacOSX: /
115 * @return string path_separator.
117 function _get_syspath_separator () {
118 if (!empty($this->_pathsep)) return $this->_pathsep;
119 elseif (isWindowsNT()) return "/"; // we can safely use '/'
120 elseif (isWindows()) return "\\"; // FAT might use '\'
121 // VMS or LispM is really weird, we ignore it.
126 * The path-separator character of the given path.
127 * Windows accepts "/" also, but gets confused with mixed path_separators,
128 * e.g "C:\Apache\phpwiki/locale/button"
129 * > dir "C:\Apache\phpwiki/locale/button" =>
130 * Parameterformat nicht korrekt - "locale"
131 * So if there's any '\' in the path, either fix them to '/' (not in Win95 or FAT?)
132 * or use '\' for ours.
135 * @return string path_separator.
137 function _use_path_separator ($path) {
139 if (empty($path)) return "\\";
140 else return (strchr($path,"\\")) ? "\\" : '/';
142 return $this->_get_syspath_separator();
147 * Determine if path is absolute.
150 * @param $path string Path.
151 * @return bool True if path is absolute.
153 function _is_abs($path) {
154 if (substr($path,0,1) == '/') {
156 } elseif (isWindows() and preg_match("/^[a-z]:/i", $path)
157 and (substr($path,2,1) == "/" or substr($path,2,1) == "\\"))
166 * Strip ending '/' or '\' from path.
169 * @param $path string Path.
170 * @return bool New path (destructive)
172 function _strip_last_pathchar(&$path) {
173 if (substr($path,-1) == '/' or substr($path,-1) == "\\")
174 $path = substr($path,0,-1);
179 * Report a "file not found" error.
182 * @param $file string Name of missing file.
183 * @return bool false.
185 function _not_found($file) {
186 if (function_exists("_"))
187 trigger_error(sprintf(_("%s: file not found"), $file), E_USER_ERROR);
189 trigger_error(sprintf("%s: file not found", $file), E_USER_ERROR);
195 * Search our path for a file.
198 * @param $file string File to find.
199 * @return string Directory which contains $file, or false.
202 function _search_path ($file) {
203 foreach ($this->_path as $dir) {
204 // ensure we use the same pathsep
205 if ($this->_isOtherPathsep()) {
206 $dir = $this->slashifyPath($dir);
207 $file = $this->slashifyPath($file);
208 if (file_exists($dir . $this->_pathsep . $file))
210 } elseif (@file_exists($dir . $this->_pathsep . $file))
217 * The system-dependent path-separator character. On UNIX systems,
218 * this character is ':'; on Win32 systems it is ';'.
220 * On Mac it cannot be : because this is the seperator there!
223 * @return string path_separator.
225 function _get_ini_separator () {
226 return isWindows() ? ';' : ':';
227 // return preg_match('/^Windows/', php_uname())
231 * Get the value of PHP's include_path.
234 * @return array Include path.
236 function _get_include_path() {
237 if (defined("INCLUDE_PATH"))
238 $path = INCLUDE_PATH;
240 $path = @get_cfg_var('include_path'); // FIXME: report warning
241 if (empty($path)) $path = @ini_get('include_path');
245 return explode($this->_get_ini_separator(), $this->slashifyPath($path));
249 * Add a directory to the end of PHP's include_path.
251 * The directory is appended only if it is not already listed in
255 * @param $dir string Directory to add.
257 function _append_to_include_path ($dir) {
258 $dir = $this->slashifyPath($dir);
259 if (!in_array($dir, $this->_path)) {
260 $this->_path[] = $dir;
263 * Some (buggy) PHP's (notable SourceForge's PHP 4.0.6)
264 * sometimes don't seem to heed their include_path.
265 * I.e. sometimes a file is not found even though it seems to
266 * be in the current include_path. A simple
267 * ini_set('include_path', ini_get('include_path')) seems to
268 * be enough to fix the problem
270 * This following line should be in the above if-block, but we
271 * put it here, as it seems to work-around the bug.
273 $GLOBALS['INCLUDE_PATH'] = implode($this->_get_ini_separator(), $this->_path);
274 @ini_set('include_path', $GLOBALS['INCLUDE_PATH']);
278 * Add a directory to the front of PHP's include_path.
280 * The directory is prepended, and removed from the tail if already existing.
283 * @param $dir string Directory to add.
285 function _prepend_to_include_path ($dir) {
286 $dir = $this->slashifyPath($dir);
288 if ($i = array_search($dir, $this->_path) !== false) {
289 array_splice($this->_path, $i, 1);
291 array_unshift($this->_path, $dir);
292 $GLOBALS['INCLUDE_PATH'] = implode($this->_path, $this->_get_ini_separator());
293 @ini_set('include_path', $GLOBALS['INCLUDE_PATH']);
296 // Return all the possible shortened locale specifiers for the given locale.
297 // Most specific first.
298 // de_DE.iso8859-1@euro => de_DE.iso8859-1, de_DE, de
299 // This code might needed somewhere else also.
300 function locale_versions ($lang) {
301 // Try less specific versions of the locale
303 foreach (array('@', '.', '_') as $sep) {
304 if ( ($tail = strchr($lang, $sep)) )
305 $langs[] = substr($lang, 0, -strlen($tail));
311 * Try to figure out the appropriate value for $LANG.
314 *@return string The value of $LANG.
316 function _get_lang() {
317 if (!empty($GLOBALS['LANG']))
318 return $GLOBALS['LANG'];
320 foreach (array('LC_ALL', 'LC_MESSAGES', 'LC_RESPONSES') as $var) {
321 $lang = setlocale(constant($var), 0);
326 foreach (array('LC_ALL', 'LC_MESSAGES', 'LC_RESPONSES', 'LANG') as $var) {
327 $lang = getenv($var);
337 * A class for finding PEAR code.
339 * This is a subclass of FileFinder which searches a standard list of
340 * directories where PEAR code is likely to be installed.
345 * $pearFinder = new PearFileFinder;
346 * $pearFinder->includeOnce('DB.php');
349 * The above code will look for 'DB.php', if found, the directory in
350 * which it was found will be added to PHP's include_path, and the
351 * file will be included. (If the file is not found, and E_USER_ERROR
360 * @param $path array Where to look for PEAR library code.
361 * A good set of defaults is provided, so you can probably leave
362 * this parameter blank.
364 function PearFileFinder ($path = array()) {
365 $this->FileFinder(array_merge(
367 array('/usr/share/php4',
371 '/usr/local/share/php4',
372 '/usr/local/share/php',
373 '/usr/local/lib/php4',
374 '/usr/local/lib/php',
375 '/System/Library/PHP',
376 '/Apache/pear' // Windows
382 * Find PhpWiki localized files.
384 * This is a subclass of FileFinder which searches PHP's include_path
385 * for files. It looks first for "locale/$LANG/$file", then for
388 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
389 * also search under various less specific variations like
390 * "de_DE.iso8859-1", "de_DE" and "de".
392 class LocalizedFileFinder
398 function LocalizedFileFinder () {
399 $this->_pathsep = $this->_get_syspath_separator();
400 $include_path = $this->_get_include_path();
403 $lang = $this->_get_lang();
404 assert(!empty($lang));
406 if ($locales = $this->locale_versions($lang)) {
407 foreach ($locales as $lang) {
408 if ($lang == 'C') $lang = 'en';
409 foreach ($include_path as $dir) {
410 $path[] = $this->slashifyPath($dir . "/locale/$lang");
414 $this->FileFinder(array_merge($path, $include_path));
419 * Find PhpWiki localized theme buttons.
421 * This is a subclass of FileFinder which searches PHP's include_path
422 * for files. It looks first for "buttons/$LANG/$file", then for
425 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
426 * also search under various less specific variations like
427 * "de_DE.iso8859-1", "de_DE" and "de".
429 class LocalizedButtonFinder
435 function LocalizedButtonFinder () {
437 $this->_pathsep = $this->_get_syspath_separator();
438 $include_path = $this->_get_include_path();
441 $lang = $this->_get_lang();
442 assert(!empty($lang));
443 assert(!empty($WikiTheme));
445 if (is_object($WikiTheme)) {
446 $langs = $this->locale_versions($lang);
447 foreach ($langs as $lang) {
448 if ($lang == 'C') $lang = 'en';
449 foreach ($include_path as $dir) {
450 $path[] = $this->slashifyPath($WikiTheme->file("buttons/$lang"));
455 $this->FileFinder(array_merge($path, $include_path));
459 // Search PHP's include_path to find file or directory.
460 function FindFile ($file, $missing_okay = false, $slashify = false)
463 if (!isset($finder)) {
464 $finder = new FileFinder;
465 // remove "/lib" from dirname(__FILE__)
466 $wikidir = preg_replace('/.lib$/','',dirname(__FILE__));
467 // let the system favor its local pear?
468 $finder->_append_to_include_path(dirname(__FILE__)."/pear");
469 $finder->_prepend_to_include_path($wikidir);
470 // Don't override existing INCLUDE_PATH config.
471 if (!defined("INCLUDE_PATH"))
472 define("INCLUDE_PATH", implode($finder->_get_ini_separator(), $finder->_path));
474 $s = $finder->findFile($file, $missing_okay);
476 $s = $finder->slashifyPath($s);
480 // Search PHP's include_path to find file or directory.
481 // Searches for "locale/$LANG/$file", then for "$file".
482 function FindLocalizedFile ($file, $missing_okay = false, $re_init = false)
485 if ($re_init or !isset($finder))
486 $finder = new LocalizedFileFinder;
487 return $finder->findFile($file, $missing_okay);
490 function FindLocalizedButtonFile ($file, $missing_okay = false, $re_init = false)
492 static $buttonfinder;
493 if ($re_init or !isset($buttonfinder))
494 $buttonfinder = new LocalizedButtonFinder;
495 return $buttonfinder->findFile($file, $missing_okay);
499 * Prefixes with PHPWIKI_DIR and slashify.
500 * For example to unify with
501 * require_once dirname(__FILE__).'/lib/file.php'
502 * require_once 'lib/file.php' loading style.
503 * Doesn't expand "~" or symlinks yet. truename would be perfect.
505 * NormalizeLocalFileName("lib/config.php") => /home/user/phpwiki/lib/config.php
507 function NormalizeLocalFileName($file) {
509 if (!isset($finder)) {
510 $finder = new FileFinder;
512 // remove "/lib" from dirname(__FILE__)
513 if ($finder->_is_abs($file))
514 return $finder->slashifyPath($file);
516 if (defined("PHPWIKI_DIR")) $wikidir = PHPWIKI_DIR;
517 else $wikidir = preg_replace('/.lib$/','',dirname(__FILE__));
518 $wikidir = $finder->_strip_last_pathchar($wikidir);
519 $pathsep = $finder->_use_path_separator($wikidir);
520 return $finder->slashifyPath($wikidir . $pathsep . $file);
521 // return PHPWIKI_DIR . "/" . $file;
526 * Prefixes with DATA_PATH and slashify
528 function NormalizeWebFileName($file) {
530 if (!isset($finder)) {
531 $finder = new FileFinder;
533 if (defined("DATA_PATH")) {
534 $wikipath = DATA_PATH;
535 $wikipath = $finder->_strip_last_pathchar($wikipath);
537 return $finder->forcePathSlashes($wikipath);
539 return $finder->forcePathSlashes($wikipath . '/' . $file);
541 return $finder->forcePathSlashes($file);
545 function isWindows() {
547 if (isset($win)) return $win;
548 //return preg_match('/^Windows/', php_uname());
549 $win = (substr(PHP_OS,0,3) == 'WIN');
553 function isWindows95() {
555 if (isset($win95)) return $win95;
556 $win95 = isWindows() and !isWindowsNT();
560 function isWindowsNT() {
562 if (isset($winnt)) return $winnt;
563 // FIXME: Do this using PHP_OS instead of php_uname().
564 // $winnt = (PHP_OS == "WINNT"); // example from http://www.php.net/manual/en/ref.readline.php
565 if (function_usable('php_uname'))
566 $winnt = preg_match('/^Windows NT/', php_uname());
568 $winnt = false; // FIXME: punt.
576 // c-hanging-comment-ender-p: nil
577 // indent-tabs-mode: nil