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)
25 $this->_pathsep = $this->_get_syspath_separator();
26 if (!isset($this->_path) and $path === false)
27 $path = $this->_get_include_path();
34 * @param $file string File to search for.
35 * @return string The filename (including path), if found, otherwise false.
37 function findFile($file, $missing_okay = false)
39 if ($this->_is_abs($file)) {
40 if (file_exists($file))
42 } elseif (($dir = $this->_search_path($file))) {
43 return $dir . $this->_use_path_separator($dir) . $file;
45 return $missing_okay ? false : $this->_not_found($file);
49 * Unify used pathsep character.
50 * Accepts array of paths also.
51 * This might not work on Windows95 or FAT volumes. (not tested)
53 function slashifyPath($path)
55 return $this->forcePathSlashes($path, $this->_pathsep);
59 * Force using '/' as path seperator.
61 function forcePathSlashes($path, $sep = '/')
63 if (is_array($path)) {
65 foreach ($path as $dir) {
66 $result[] = $this->forcePathSlashes($dir, $sep);
70 if (isWindows() or $this->_isOtherPathsep()) {
71 if (isWindows()) $from = "\\";
73 // PHP is stupid enough to use \\ instead of \
75 if (substr($path, 0, 2) != '\\\\')
76 $path = str_replace('\\\\', '\\', $path);
78 $path = '\\\\' . str_replace('\\\\', '\\', substr($path, 2));
80 return strtr($path, $from, $sep);
87 * Try to include file.
89 * If file is found in the path, then the files directory is added
90 * to PHP's include_path (if it's not already there.) Then the
91 * file is include_once()'d.
93 * @param $file string File to include.
94 * @return bool True if file was successfully included.
96 function includeOnce($file)
98 if (($ret = @include_once($file)))
101 if (!$this->_is_abs($file)) {
102 if (($dir = $this->_search_path($file)) && is_file($dir . $this->_pathsep . $file)) {
103 $this->_append_to_include_path($dir);
104 return include_once($file);
107 return $this->_not_found($file);
110 function _isOtherPathsep()
112 return $this->_pathsep != '/';
116 * The system-dependent path-separator character.
117 * UNIX,WindowsNT,MacOSX: /
122 * @return string path_separator.
124 function _get_syspath_separator()
126 if (!empty($this->_pathsep)) return $this->_pathsep;
127 elseif (isWindowsNT()) return "/"; // we can safely use '/'
128 elseif (isWindows()) return "\\"; // FAT might use '\'
129 // VMS or LispM is really weird, we ignore it.
134 * The path-separator character of the given path.
135 * Windows accepts "/" also, but gets confused with mixed path_separators,
136 * e.g "C:\Apache\phpwiki/locale/button"
137 * > dir "C:\Apache\phpwiki/locale/button" =>
138 * Parameterformat nicht korrekt - "locale"
139 * So if there's any '\' in the path, either fix them to '/' (not in Win95 or FAT?)
140 * or use '\' for ours.
143 * @return string path_separator.
145 function _use_path_separator($path)
148 if (empty($path)) return "\\";
149 else return (strchr($path, "\\")) ? "\\" : '/';
151 return $this->_get_syspath_separator();
156 * Determine if path is absolute.
159 * @param $path string Path.
160 * @return bool True if path is absolute.
162 function _is_abs($path)
164 if (substr($path, 0, 1) == '/') {
166 } elseif (isWindows() and preg_match("/^[a-z]:/i", $path)
167 and (substr($path, 2, 1) == "/" or substr($path, 2, 1) == "\\")
176 * Strip ending '/' or '\' from path.
179 * @param $path string Path.
180 * @return bool New path (destructive)
182 function _strip_last_pathchar(&$path)
184 if (substr($path, -1) == '/' or substr($path, -1) == "\\")
185 $path = substr($path, 0, -1);
190 * Report a "file not found" error.
193 * @param $file string Name of missing file.
194 * @return bool false.
196 function _not_found($file)
198 if (function_exists("_"))
199 trigger_error(sprintf(_("%s: file not found"), $file), E_USER_ERROR);
201 trigger_error(sprintf("%s: file not found", $file), E_USER_ERROR);
207 * Search our path for a file.
210 * @param $file string File to find.
211 * @return string Directory which contains $file, or false.
214 function _search_path($file)
216 foreach ($this->_path as $dir) {
217 // ensure we use the same pathsep
218 if ($this->_isOtherPathsep()) {
219 $dir = $this->slashifyPath($dir);
220 $file = $this->slashifyPath($file);
221 if (file_exists($dir . $this->_pathsep . $file))
223 } elseif (@file_exists($dir . $this->_pathsep . $file))
230 * The system-dependent path-separator character. On UNIX systems,
231 * this character is ':'; on Win32 systems it is ';'.
233 * On Mac it cannot be : because this is the seperator there!
236 * @return string path_separator.
238 function _get_ini_separator()
240 return isWindows() ? ';' : ':';
241 // return preg_match('/^Windows/', php_uname())
245 * Get the value of PHP's include_path.
248 * @return array Include path.
250 function _get_include_path()
252 if (defined("INCLUDE_PATH"))
253 $path = INCLUDE_PATH;
255 $path = @get_cfg_var('include_path'); // FIXME: report warning
256 if (empty($path)) $path = @ini_get('include_path');
260 return explode($this->_get_ini_separator(), $this->slashifyPath($path));
264 * Add a directory to the end of PHP's include_path.
266 * The directory is appended only if it is not already listed in
270 * @param $dir string Directory to add.
272 function _append_to_include_path($dir)
274 $dir = $this->slashifyPath($dir);
275 if (!in_array($dir, $this->_path)) {
276 $this->_path[] = $dir;
279 * Some (buggy) PHP's (notable SourceForge's PHP 4.0.6)
280 * sometimes don't seem to heed their include_path.
281 * I.e. sometimes a file is not found even though it seems to
282 * be in the current include_path. A simple
283 * ini_set('include_path', ini_get('include_path')) seems to
284 * be enough to fix the problem
286 * This following line should be in the above if-block, but we
287 * put it here, as it seems to work-around the bug.
289 $GLOBALS['INCLUDE_PATH'] = implode($this->_get_ini_separator(), $this->_path);
290 @ini_set('include_path', $GLOBALS['INCLUDE_PATH']);
294 * Add a directory to the front of PHP's include_path.
296 * The directory is prepended, and removed from the tail if already existing.
299 * @param $dir string Directory to add.
301 function _prepend_to_include_path($dir)
303 $dir = $this->slashifyPath($dir);
305 if ($i = array_search($dir, $this->_path) !== false) {
306 array_splice($this->_path, $i, 1);
308 array_unshift($this->_path, $dir);
309 $GLOBALS['INCLUDE_PATH'] = implode($this->_path, $this->_get_ini_separator());
310 @ini_set('include_path', $GLOBALS['INCLUDE_PATH']);
313 // Return all the possible shortened locale specifiers for the given locale.
314 // Most specific first.
315 // de_DE.iso8859-1@euro => de_DE.iso8859-1, de_DE, de
316 // This code might needed somewhere else also.
317 function locale_versions($lang)
319 // Try less specific versions of the locale
321 foreach (array('@', '.', '_') as $sep) {
322 if (($tail = strchr($lang, $sep)))
323 $langs[] = substr($lang, 0, -strlen($tail));
329 * Try to figure out the appropriate value for $LANG.
332 * @return string The value of $LANG.
336 if (!empty($GLOBALS['LANG']))
337 return $GLOBALS['LANG'];
339 foreach (array('LC_ALL', 'LC_MESSAGES', 'LC_RESPONSES') as $var) {
340 $lang = setlocale(constant($var), 0);
345 foreach (array('LC_ALL', 'LC_MESSAGES', 'LC_RESPONSES', 'LANG') as $var) {
346 $lang = getenv($var);
356 * A class for finding PEAR code.
358 * This is a subclass of FileFinder which searches a standard list of
359 * directories where PEAR code is likely to be installed.
364 * $pearFinder = new PearFileFinder;
365 * $pearFinder->includeOnce('DB.php');
368 * The above code will look for 'DB.php', if found, the directory in
369 * which it was found will be added to PHP's include_path, and the
370 * file will be included. (If the file is not found, and E_USER_ERROR
379 * @param $path array Where to look for PEAR library code.
380 * A good set of defaults is provided, so you can probably leave
381 * this parameter blank.
383 function PearFileFinder($path = array())
385 $this->FileFinder(array_merge(
387 array('/usr/share/php4',
391 '/usr/local/share/php4',
392 '/usr/local/share/php',
393 '/usr/local/lib/php4',
394 '/usr/local/lib/php',
395 '/System/Library/PHP',
396 '/Apache/pear' // Windows
402 * Find PhpWiki localized files.
404 * This is a subclass of FileFinder which searches PHP's include_path
405 * for files. It looks first for "locale/$LANG/$file", then for
408 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
409 * also search under various less specific variations like
410 * "de_DE.iso8859-1", "de_DE" and "de".
412 class LocalizedFileFinder
418 function LocalizedFileFinder()
420 $this->_pathsep = $this->_get_syspath_separator();
421 $include_path = $this->_get_include_path();
424 $lang = $this->_get_lang();
425 assert(!empty($lang));
427 if ($locales = $this->locale_versions($lang)) {
428 foreach ($locales as $lang) {
429 if ($lang == 'C') $lang = 'en';
430 foreach ($include_path as $dir) {
431 $path[] = $this->slashifyPath($dir . "/locale/$lang");
435 $this->FileFinder(array_merge($path, $include_path));
440 * Find PhpWiki localized theme buttons.
442 * This is a subclass of FileFinder which searches PHP's include_path
443 * for files. It looks first for "buttons/$LANG/$file", then for
446 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
447 * also search under various less specific variations like
448 * "de_DE.iso8859-1", "de_DE" and "de".
450 class LocalizedButtonFinder
456 function LocalizedButtonFinder()
459 $this->_pathsep = $this->_get_syspath_separator();
460 $include_path = $this->_get_include_path();
463 $lang = $this->_get_lang();
464 assert(!empty($lang));
465 assert(!empty($WikiTheme));
467 if (is_object($WikiTheme)) {
468 $langs = $this->locale_versions($lang);
469 foreach ($langs as $lang) {
470 if ($lang == 'C') $lang = 'en';
471 foreach ($include_path as $dir) {
472 $path[] = $this->slashifyPath($WikiTheme->file("buttons/$lang"));
477 $this->FileFinder(array_merge($path, $include_path));
481 // Search PHP's include_path to find file or directory.
482 function FindFile($file, $missing_okay = false, $slashify = false)
485 if (!isset($finder)) {
486 $finder = new FileFinder;
487 // remove "/lib" from dirname(__FILE__)
488 $wikidir = preg_replace('/.lib$/', '', dirname(__FILE__));
489 // let the system favor its local pear?
490 $finder->_append_to_include_path(dirname(__FILE__) . "/pear");
491 $finder->_prepend_to_include_path($wikidir);
492 // Don't override existing INCLUDE_PATH config.
493 if (!defined("INCLUDE_PATH"))
494 define("INCLUDE_PATH", implode($finder->_get_ini_separator(), $finder->_path));
496 $s = $finder->findFile($file, $missing_okay);
498 $s = $finder->slashifyPath($s);
502 // Search PHP's include_path to find file or directory.
503 // Searches for "locale/$LANG/$file", then for "$file".
504 function FindLocalizedFile($file, $missing_okay = false, $re_init = false)
507 if ($re_init or !isset($finder))
508 $finder = new LocalizedFileFinder;
509 return $finder->findFile($file, $missing_okay);
512 function FindLocalizedButtonFile($file, $missing_okay = false, $re_init = false)
514 static $buttonfinder;
515 if ($re_init or !isset($buttonfinder))
516 $buttonfinder = new LocalizedButtonFinder;
517 return $buttonfinder->findFile($file, $missing_okay);
521 * Prefixes with PHPWIKI_DIR and slashify.
522 * For example to unify with
523 * require_once dirname(__FILE__).'/lib/file.php'
524 * require_once 'lib/file.php' loading style.
525 * Doesn't expand "~" or symlinks yet. truename would be perfect.
527 * NormalizeLocalFileName("lib/config.php") => /home/user/phpwiki/lib/config.php
529 function NormalizeLocalFileName($file)
532 if (!isset($finder)) {
533 $finder = new FileFinder;
535 // remove "/lib" from dirname(__FILE__)
536 if ($finder->_is_abs($file))
537 return $finder->slashifyPath($file);
539 if (defined("PHPWIKI_DIR")) $wikidir = PHPWIKI_DIR;
540 else $wikidir = preg_replace('/.lib$/', '', dirname(__FILE__));
541 $wikidir = $finder->_strip_last_pathchar($wikidir);
542 $pathsep = $finder->_use_path_separator($wikidir);
543 return $finder->slashifyPath($wikidir . $pathsep . $file);
544 // return PHPWIKI_DIR . "/" . $file;
549 * Prefixes with DATA_PATH and slashify
551 function NormalizeWebFileName($file)
554 if (!isset($finder)) {
555 $finder = new FileFinder;
557 if (defined("DATA_PATH")) {
558 $wikipath = DATA_PATH;
559 $wikipath = $finder->_strip_last_pathchar($wikipath);
561 return $finder->forcePathSlashes($wikipath);
563 return $finder->forcePathSlashes($wikipath . '/' . $file);
565 return $finder->forcePathSlashes($file);
572 if (isset($win)) return $win;
573 //return preg_match('/^Windows/', php_uname());
574 $win = (substr(PHP_OS, 0, 3) == 'WIN');
578 function isWindows95()
581 if (isset($win95)) return $win95;
582 $win95 = isWindows() and !isWindowsNT();
586 function isWindowsNT()
589 if (isset($winnt)) return $winnt;
590 // FIXME: Do this using PHP_OS instead of php_uname().
591 // $winnt = (PHP_OS == "WINNT"); // example from http://www.php.net/manual/en/ref.readline.php
592 if (function_usable('php_uname'))
593 $winnt = preg_match('/^Windows NT/', php_uname());
595 $winnt = false; // FIXME: punt.
603 // c-hanging-comment-ender-p: nil
604 // indent-tabs-mode: nil