1 <?php rcs_id('$Id: FileFinder.php,v 1.12 2003-01-28 21:06:05 zorloc 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') as $var) {
248 $lang = setlocale($var, 0);
253 foreach (array('LC_ALL', 'LC_MESSAGES', 'LC_RESPONSES', 'LANG') as $var) {
254 $lang = getenv($var);
264 * A class for finding PEAR code.
266 * This is a subclass of FileFinder which searches a standard list of
267 * directories where PEAR code is likely to be installed.
272 * $pearFinder = new PearFileFinder;
273 * $pearFinder->includeOnce('DB.php');
276 * The above code will look for 'DB.php', if found, the directory in
277 * which it was found will be added to PHP's include_path, and the
278 * file will be included. (If the file is not found, and E_USER_ERROR
287 * @param $path array Where to look for PEAR library code.
288 * A good set of defaults is provided, so you can probably leave
289 * this parameter blank.
291 function PearFileFinder ($path = array()) {
292 $this->FileFinder(array_merge(
294 array('/usr/share/php4',
298 '/usr/local/share/php4',
299 '/usr/local/share/php',
300 '/usr/local/lib/php4',
301 '/usr/local/lib/php',
302 '/System/Library/PHP',
303 '/Apache/pear' // Windows
309 * Find PhpWiki localized files.
311 * This is a subclass of FileFinder which searches PHP's include_path
312 * for files. It looks first for "locale/$LANG/$file", then for
315 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
316 * also search under various less specific variations like
317 * "de_DE.iso8859-1", "de_DE" and "de".
319 class LocalizedFileFinder
325 function LocalizedFileFinder () {
326 $this->_pathsep = $this->_get_syspath_separator();
327 $include_path = $this->_get_include_path();
330 $lang = $this->_get_lang();
331 assert(!empty($lang));
333 if ($locales = $this->locale_versions($lang))
334 foreach ($locales as $lang) {
335 if ($lang == 'C') $lang='en';
336 foreach ($include_path as $dir) {
337 $path[] = $this->slashifyPath($dir) . "/locale/$lang";
340 $this->FileFinder(array_merge($path, $include_path));
345 * Find PhpWiki localized theme buttons.
347 * This is a subclass of FileFinder which searches PHP's include_path
348 * for files. It looks first for "buttons/$LANG/$file", then for
351 * If $LANG is something like "de_DE.iso8859-1@euro", this class will
352 * also search under various less specific variations like
353 * "de_DE.iso8859-1", "de_DE" and "de".
355 class LocalizedButtonFinder
361 function LocalizedButtonFinder () {
363 $this->_pathsep = $this->_get_syspath_separator();
364 $include_path = $this->_get_include_path();
367 $lang = $this->_get_lang();
368 assert(!empty($lang));
369 assert(!empty($Theme));
371 $langs = $this->locale_versions($lang);
373 foreach ($langs as $lang) {
374 if ($lang == 'C') $lang='en';
375 foreach ($include_path as $dir) {
376 $path[] = $Theme->file("buttons/$lang");
380 $this->FileFinder(array_merge($path, $include_path));
385 function isWindows() {
387 if (isset($win)) return $win;
388 //return preg_match('/^Windows/', php_uname());
389 $win = (substr(PHP_OS,0,3) == 'WIN');
393 function isWindows95() {
395 if (isset($win95)) return $win95;
396 $win95 = isWindows() and !isWindowsNT();
400 function isWindowsNT() {
402 if (isset($winnt)) return $winnt;
403 $winnt = preg_match('/^Windows NT/', php_uname());
407 // So far not supported. This has really ugly pathname semantics.
408 // :path is relative, Desktop:path (I think) is absolute. Please fix this someone.
410 return (substr(PHP_OS,0,3) == 'MAC'); // not tested!
413 // probably not needed, same behaviour as on unix.
414 function isCygwin() {
415 return (substr(PHP_OS,0,6) == 'CYGWIN');
422 // c-hanging-comment-ender-p: nil
423 // indent-tabs-mode: nil