1 <?php rcs_id('$Id: FileFinder.php,v 1.10 2002-09-12 11:45:33 rurban Exp $');
3 // FIXME: make this work with non-unix (e.g. DOS) filenames.
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, VMS, ...)
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();
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);
47 function slashifyPath ($path) {
48 if ($this->_isOtherPathsep())
49 return strtr($path,$this->_use_path_separator($path),'/');
55 * Try to include file.
57 * If file is found in the path, then the files directory is added
58 * to PHP's include_path (if it's not already there.) Then the
59 * file is include_once()'d.
61 * @param $file string File to include.
62 * @return bool True if file was successfully included.
64 function includeOnce ($file) {
65 if ( ($ret = @include_once($file)) )
68 if (!$this->_is_abs($file)) {
69 if ( ($dir = $this->_search_path($file)) && is_file("$dir/$file")) {
70 $this->_append_to_include_path($dir);
71 return include_once($file);
75 return $this->_not_found($file);
78 function _isOtherPathsep() {
79 return $this->_pathsep != '/';
83 * The system-dependent path-separator character.
84 * UNIX,WindowsNT,MacOSX: /
89 * @return string path_separator.
91 function _get_syspath_separator () {
92 if (!empty($this->_pathsep)) return $this->_pathsep;
93 elseif (isWindowsNT()) return '\\';
94 elseif (isWindows()) return '\\';
95 elseif (isMac()) return ':'; // MacOsX is /
96 // VMS or LispM is really weird, we ignore it.
101 * The path-separator character of the given path.
102 * Windows accepts / also, but gets confused with mixed path_separators,
103 * e.g "C:\Apache\phpwiki/locale/button"
104 * > dir C:\Apache\phpwiki/locale/button =>
105 * Parameterformat nicht korrekt - "locale"
106 * So if there's any \\ in the path, either fix them to / (not in Win95!)
107 * or use \\ for ours.
110 * @return string path_separator.
112 function _use_path_separator ($path) {
114 return (strchr($path,'\\')) ? '\\' : '/';
116 return $this->_get_syspath_separator();
121 * Determine if path is absolute.
124 * @param $path string Path.
125 * @return bool True if path is absolute.
127 function _is_abs($path) {
128 if (ereg('^/', $path)) return true;
129 elseif (isWindows() and (eregi('^[a-z]:[/\\]', $path))) return true;
134 * Report a "file not found" error.
137 * @param $file string Name of missing file.
138 * @return bool false.
140 function _not_found($file) {
141 trigger_error(sprintf(_("%s: file not found"),$file), E_USER_ERROR);
147 * Search our path for a file.
150 * @param $file string File to find.
151 * @return string Directory which contains $file, or false.
153 function _search_path ($file) {
154 foreach ($this->_path as $dir) {
155 // ensure we use the same pathsep
156 if ($this->_pathsep != '/') {
157 $dir = $this->slashifyPath($dir);
158 $file = $this->slashifyPath($file);
159 if (file_exists($dir . $this->_pathsep . $file))
161 } elseif (file_exists("$dir/$file"))
168 * The system-dependent path-separator character. On UNIX systems,
169 * this character is ':'; on Win32 systems it is ';'.
171 * On Mac it cannot be : because this is the seperator there!
174 * @return string path_separator.
176 function _get_ini_separator () {
177 return isWindows() ? ';' : ':';
178 // return preg_match('/^Windows/', php_uname())
182 * Get the value of PHP's include_path.
185 * @return array Include path.
187 function _get_include_path() {
188 $path = ini_get('include_path');
191 return explode($this->_get_ini_separator(), $this->slashifyPath($path));
195 * Add a directory to the end of PHP's include_path.
197 * The directory is appended only if it is not already listed in
201 * @param $dir string Directory to add.
203 function _append_to_include_path ($dir) {
204 $path = $this->_get_include_path();
205 if (!in_array($dir, $path)) {
207 //ini_set('include_path', implode(':', $path));
210 * Some (buggy) PHP's (notable SourceForge's PHP 4.0.6)
211 * sometimes don't seem to heed their include_path.
212 * I.e. sometimes a file is not found even though it seems to
213 * be in the current include_path. A simple
214 * ini_set('include_path', ini_get('include_path')) seems to
215 * be enough to fix the problem
217 * This following line should be in the above if-block, but we
218 * put it here, as it seems to work-around the bug.
220 ini_set('include_path', implode($this->_get_ini_separator(), $this->slashifyPath($path)));
223 // Return all the possible shortened locale specifiers for the given locale.
224 // Most specific first.
225 // de_DE.iso8859-1@euro => de_DE.iso8859-1, de_DE, de
226 // This code might needed somewhere else also.
227 function locale_versions ($lang) {
228 // Try less specific versions of the locale
230 foreach (array('@', '.', '_') as $sep) {
231 if ( ($tail = strchr($lang, $sep)) )
232 $langs[] = substr($lang, 0, -strlen($tail));
238 * Try to figure out the appropriate value for $LANG.
241 *@return string The value of $LANG.
243 function _get_lang() {
244 if (!empty($GLOBALS['LANG']))
245 return $GLOBALS['LANG'];
247 foreach (array('LC_ALL', 'LC_MESSAGES', 'LC_RESPONSES', 'LANG') as $var) {
248 $lang = getenv($var);
258 * A class for finding PEAR code.
260 * This is a subclass of FileFinder which searches a standard list of
261 * directories where PEAR code is likely to be installed.
266 * $pearFinder = new PearFileFinder;
267 * $pearFinder->includeOnce('DB.php');
270 * The above code will look for 'DB.php', if found, the directory in
271 * which it was found will be added to PHP's include_path, and the
272 * file will be included. (If the file is not found, and E_USER_ERROR
281 * @param $path array Where to look for PEAR library code.
282 * A good set of defaults is provided, so you can probably leave
283 * this parameter blank.
285 function PearFileFinder ($path = array()) {
286 $this->FileFinder(array_merge(
288 array('/usr/share/php4',
292 '/usr/local/share/php4',
293 '/usr/local/share/php',
294 '/usr/local/lib/php4',
295 '/usr/local/lib/php',
296 '/System/Library/PHP',
297 '/Apache/pear' // Windows
303 * Find PhpWiki localized files.
305 * This is a subclass of FileFinder which searches PHP's include_path
306 * for files. It looks first for "locale/$LANG/$file", then for
309 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
310 * also search under various less specific variations like
311 * "de_DE.iso8859-1", "de_DE" and "de".
313 class LocalizedFileFinder
319 function LocalizedFileFinder () {
320 $this->_pathsep = $this->_get_syspath_separator();
321 $include_path = $this->_get_include_path();
324 $lang = $this->_get_lang();
325 assert(!empty($lang));
327 if ($locales = $this->locale_versions($lang))
328 foreach ($locales as $lang) {
329 if ($lang == 'C') $lang='en';
330 foreach ($include_path as $dir) {
331 $path[] = $this->slashifyPath($dir) . "/locale/$lang";
334 $this->FileFinder(array_merge($path, $include_path));
339 * Find PhpWiki localized theme buttons.
341 * This is a subclass of FileFinder which searches PHP's include_path
342 * for files. It looks first for "buttons/$LANG/$file", then for
345 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
346 * also search under various less specific variations like
347 * "de_DE.iso8859-1", "de_DE" and "de".
349 class LocalizedButtonFinder
355 function LocalizedButtonFinder () {
357 $this->_pathsep = $this->_get_syspath_separator();
358 $include_path = $this->_get_include_path();
361 $lang = $this->_get_lang();
362 assert(!empty($lang));
363 assert(!empty($Theme));
365 $langs = $this->locale_versions($lang);
367 foreach ($langs as $lang) {
368 if ($lang == 'C') $lang='en';
369 foreach ($include_path as $dir) {
370 $path[] = $Theme->file("buttons/$lang");
374 $this->FileFinder(array_merge($path, $include_path));
379 function isWindows() {
381 if (isset($win)) return $win;
382 //return preg_match('/^Windows/', php_uname());
383 $win = (substr(PHP_OS,0,3) == 'WIN');
387 function isWindows95() {
389 if (isset($win95)) return $win95;
390 $win95 = isWindows() and !isWindowsNT();
394 function isWindowsNT() {
396 if (isset($winnt)) return $winnt;
397 $winnt = preg_match('/^Windows NT/', php_uname());
401 // So far not supported. This has really ugly pathname semantics.
402 // :path is relative, Desktop:path (I think) is absolute. Please fix this someone.
404 return (substr(PHP_OS,0,3) == 'MAC'); // not tested!
407 // probably not needed, same behaviour as on unix.
408 function isCygwin() {
409 return (substr(PHP_OS,0,6) == 'CYGWIN');
416 // c-hanging-comment-ender-p: nil
417 // indent-tabs-mode: nil