]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/FileFinder.php
fixed DB_Session
[SourceForge/phpwiki.git] / lib / FileFinder.php
1 <?php rcs_id('$Id: FileFinder.php,v 1.10 2002-09-12 11:45:33 rurban Exp $');
2
3 // FIXME: make this work with non-unix (e.g. DOS) filenames.
4
5 /**
6  * A class for finding files.
7  * 
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.
13  */
14 class FileFinder
15 {
16     var $_pathsep, $_path;
17
18     /**
19      * Constructor.
20      *
21      * @param $path array A list of directories in which to search for files.
22      */
23     function FileFinder ($path = false) {
24         $this->_pathsep = $this->_get_syspath_separator();
25         if ($path === false)
26             $path = $this->_get_include_path();
27         $this->_path = $path;
28     }
29
30     /**
31      * Find file.
32      *
33      * @param $file string File to search for.
34      * @return string The filename (including path), if found, otherwise false.
35      */
36     function findFile ($file, $missing_okay = false) {
37         if ($this->_is_abs($file)) {
38             if (file_exists($file))
39                 return $file;
40         }
41         elseif ( ($dir = $this->_search_path($file)) ) {
42             return $dir . $this->_use_path_separator($dir) . $file;
43         }
44         return $missing_okay ? false : $this->_not_found($file);
45     }
46
47     function slashifyPath ($path) {
48         if ($this->_isOtherPathsep())
49             return strtr($path,$this->_use_path_separator($path),'/');
50         else 
51             return $path;
52     }
53
54     /**
55      * Try to include file.
56      *
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.
60      *
61      * @param $file string File to include.
62      * @return bool True if file was successfully included.
63      */
64     function includeOnce ($file) {
65         if ( ($ret = @include_once($file)) )
66             return $ret;
67
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);
72             }
73         }
74
75         return $this->_not_found($file);
76     }
77
78     function _isOtherPathsep() {
79         return $this->_pathsep != '/';
80     }
81
82     /**
83      * The system-dependent path-separator character. 
84      * UNIX,WindowsNT,MacOSX: /
85      * Windows95: \
86      * Mac:       :
87      *
88      * @access private
89      * @return string path_separator.
90      */
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.
97         else return '/';
98     }
99
100     /**
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.
108      *
109      * @access private
110      * @return string path_separator.
111      */
112     function _use_path_separator ($path) {
113         if (isWindows95()) {
114             return (strchr($path,'\\')) ? '\\' : '/';
115         } else {
116             return $this->_get_syspath_separator();
117         }
118     }
119
120     /**
121      * Determine if path is absolute.
122      *
123      * @access private
124      * @param $path string Path.
125      * @return bool True if path is absolute. 
126      */
127     function _is_abs($path) {
128         if (ereg('^/', $path)) return true;
129         elseif (isWindows() and (eregi('^[a-z]:[/\\]', $path))) return true;
130         else return false;
131     }
132
133     /**
134      * Report a "file not found" error.
135      *
136      * @access private
137      * @param $file string Name of missing file.
138      * @return bool false.
139      */
140     function _not_found($file) {
141         trigger_error(sprintf(_("%s: file not found"),$file), E_USER_ERROR);
142         return false;
143     }
144
145
146     /**
147      * Search our path for a file.
148      *
149      * @access private
150      * @param $file string File to find.
151      * @return string Directory which contains $file, or false.
152      */
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))
160                     return $dir;
161             } elseif (file_exists("$dir/$file"))
162                 return $dir;
163         }
164         return false;
165     }
166
167     /**
168      * The system-dependent path-separator character. On UNIX systems,
169      * this character is ':'; on Win32 systems it is ';'.
170      * Fixme:
171      * On Mac it cannot be : because this is the seperator there!
172      *
173      * @access private
174      * @return string path_separator.
175      */
176     function _get_ini_separator () {
177         return isWindows() ? ';' : ':';
178         // return preg_match('/^Windows/', php_uname()) 
179     }
180
181     /**
182      * Get the value of PHP's include_path.
183      *
184      * @access private
185      * @return array Include path.
186      */
187     function _get_include_path() {
188         $path = ini_get('include_path');
189         if (empty($path))
190             $path = '.';
191         return explode($this->_get_ini_separator(), $this->slashifyPath($path));
192     }
193
194     /**
195      * Add a directory to the end of PHP's include_path.
196      *
197      * The directory is appended only if it is not already listed in
198      * the include_path.
199      *
200      * @access private
201      * @param $dir string Directory to add.
202      */
203     function _append_to_include_path ($dir) {
204         $path = $this->_get_include_path();
205         if (!in_array($dir, $path)) {
206             $path[] = $dir;
207             //ini_set('include_path', implode(':', $path));
208         }
209         /*
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
216          *
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.
219          */
220         ini_set('include_path', implode($this->_get_ini_separator(), $this->slashifyPath($path)));
221     }
222
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
229         $langs[] = $lang;
230         foreach (array('@', '.', '_') as $sep) {
231             if ( ($tail = strchr($lang, $sep)) )
232                 $langs[] = substr($lang, 0, -strlen($tail));
233         }
234         return $langs;
235     }
236
237     /**
238      * Try to figure out the appropriate value for $LANG.
239      *
240      *@access private
241      *@return string The value of $LANG.
242      */
243     function _get_lang() {
244         if (!empty($GLOBALS['LANG']))
245             return $GLOBALS['LANG'];
246
247         foreach (array('LC_ALL', 'LC_MESSAGES', 'LC_RESPONSES', 'LANG') as $var) {
248             $lang = getenv($var);
249             if (!empty($lang))
250                 return $lang;
251         }
252
253         return "C";
254     }
255 }
256
257 /**
258  * A class for finding PEAR code.
259  *
260  * This is a subclass of FileFinder which searches a standard list of
261  * directories where PEAR code is likely to be installed.
262  *
263  * Example usage:
264  *
265  * <pre>
266  *   $pearFinder = new PearFileFinder;
267  *   $pearFinder->includeOnce('DB.php');
268  * </pre>
269  *
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
273  * will be thrown.)
274  */
275 class PearFileFinder
276     extends FileFinder
277 {
278     /**
279      * Constructor.
280      *
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.
284      */
285     function PearFileFinder ($path = array()) {
286         $this->FileFinder(array_merge(
287                           $path,
288                           array('/usr/share/php4',
289                                 '/usr/share/php',
290                                 '/usr/lib/php4',
291                                 '/usr/lib/php',
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
298                                 )));
299     }
300 }
301
302 /**
303  * Find PhpWiki localized files.
304  *
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
307  * "$file".
308  *
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".
312  */
313 class LocalizedFileFinder
314     extends FileFinder
315 {
316     /**
317      * Constructor.
318      */
319     function LocalizedFileFinder () {
320         $this->_pathsep = $this->_get_syspath_separator();
321         $include_path = $this->_get_include_path();
322         $path = array();
323
324         $lang = $this->_get_lang();
325         assert(!empty($lang));
326
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";
332             }
333           }
334         $this->FileFinder(array_merge($path, $include_path));
335     }
336 }
337
338 /**
339  * Find PhpWiki localized theme buttons.
340  *
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
343  * "$file".
344  *
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".
348  */
349 class LocalizedButtonFinder
350     extends FileFinder
351 {
352     /**
353      * Constructor.
354      */
355     function LocalizedButtonFinder () {
356         global $Theme;
357         $this->_pathsep = $this->_get_syspath_separator();
358         $include_path = $this->_get_include_path();
359         $path = array();
360
361         $lang = $this->_get_lang();
362         assert(!empty($lang));
363         assert(!empty($Theme));
364
365         $langs = $this->locale_versions($lang);
366
367         foreach ($langs as $lang) {
368             if ($lang == 'C') $lang='en';
369             foreach ($include_path as $dir) {
370                 $path[] = $Theme->file("buttons/$lang");
371             }
372         }
373
374         $this->FileFinder(array_merge($path, $include_path));
375     }
376
377 }
378
379 function isWindows() {
380     static $win;
381     if (isset($win)) return $win;
382     //return preg_match('/^Windows/', php_uname());
383     $win = (substr(PHP_OS,0,3) == 'WIN');
384     return $win;
385 }
386
387 function isWindows95() {
388     static $win95;
389     if (isset($win95)) return $win95;
390     $win95 = isWindows() and !isWindowsNT();
391     return $win95;
392 }
393
394 function isWindowsNT() {
395     static $winnt;
396     if (isset($winnt)) return $winnt;
397     $winnt = preg_match('/^Windows NT/', php_uname());
398     return $winnt;
399 }
400
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.
403 function isMac() {
404     return (substr(PHP_OS,0,3) == 'MAC'); // not tested!
405 }
406
407 // probably not needed, same behaviour as on unix.
408 function isCygwin() {
409     return (substr(PHP_OS,0,6) == 'CYGWIN');
410 }
411
412 // Local Variables:
413 // mode: php
414 // tab-width: 8
415 // c-basic-offset: 4
416 // c-hanging-comment-ender-p: nil
417 // indent-tabs-mode: nil
418 // End:
419 ?>