source: trunk/plugins/MootoolsFileManager/mootools-filemanager/Assets/Connector/Tooling.php @ 1321

Last change on this file since 1321 was 1321, checked in by gogo, 7 years ago

Merge the MootoolsFileManager?-Update branch into the trunk.

File size: 13.3 KB
Line 
1<?php
2/*
3 * Script: Tooling.php
4 *   MooTools FileManager - Backend for the FileManager Script - Support Code
5 *
6 * Authors:
7 *  - Christoph Pojer (http://cpojer.net) (author)
8 *  - James Ehly (http://www.devtrench.com)
9 *  - Fabian Vogelsteller (http://frozeman.de)
10 *  - Ger Hobbelt (http://hebbut.net)
11 *
12 * License:
13 *   MIT-style license.
14 *
15 * Copyright:
16 *   Copyright (c) 2011 [Christoph Pojer](http://cpojer.net)
17 */
18
19
20
21
22if (!function_exists('safe_glob'))
23{
24        /**#@+
25         * Extra GLOB constant for safe_glob()
26         */
27        if (!defined('GLOB_NODIR'))       define('GLOB_NODIR',256);
28        if (!defined('GLOB_PATH'))        define('GLOB_PATH',512);
29        if (!defined('GLOB_NODOTS'))      define('GLOB_NODOTS',1024);
30        if (!defined('GLOB_RECURSE'))     define('GLOB_RECURSE',2048);
31        if (!defined('GLOB_NOHIDDEN'))    define('GLOB_NOHIDDEN',4096);
32        /**#@-*/
33
34
35        /**
36         * A safe empowered glob().
37         *
38         * Function glob() is prohibited on some server (probably in safe mode)
39         * (Message "Warning: glob() has been disabled for security reasons in
40         * (script) on line (line)") for security reasons as stated on:
41         * http://seclists.org/fulldisclosure/2005/Sep/0001.html
42         *
43         * safe_glob() intends to replace glob() using readdir() & fnmatch() instead.
44         * Supported flags: GLOB_MARK, GLOB_NOSORT, GLOB_ONLYDIR
45         * Additional flags: GLOB_NODIR, GLOB_PATH, GLOB_NODOTS, GLOB_RECURSE, GLOB_NOHIDDEN
46         * (not original glob() flags)
47         *
48         * @author BigueNique AT yahoo DOT ca
49         * @updates
50         * - 080324 Added support for additional flags: GLOB_NODIR, GLOB_PATH,
51         *   GLOB_NODOTS, GLOB_RECURSE
52         * - [i_a] Added support for GLOB_NOHIDDEN, split output in directories and files subarrays
53         */
54        function safe_glob($pattern, $flags = 0)
55        {
56                $split = explode('/', strtr($pattern, '\\', '/'));
57                $mask = array_pop($split);
58                $path = implode('/', $split);
59                if (($dir = @opendir($path)) !== false)
60                {
61                        $dirs = array();
62                        $files = array();
63                        while(($file = readdir($dir)) !== false)
64                        {
65                                // HACK/TWEAK: PHP5 and below are completely b0rked when it comes to international filenames   :-(
66                                //             --> do not show such files/directories in the list as they won't be accessible anyway!
67                                //
68                                // The regex charset is limited even within the ASCII range, due to    http://en.wikipedia.org/wiki/Filename#Comparison%5Fof%5Ffile%5Fname%5Flimitations
69                                // Although the filtered characters here are _possible_ on UNIX file systems, they're severely frowned upon.
70                                if (preg_match('/[^ -)+-.0-;=@-\[\]-{}~]/', $file))  // filesystem-illegal characters are not part of the set:   * > < ? / \ |
71                                {
72                                        // simply do NOT list anything that we cannot cope with.
73                                        // That includes clearly inaccessible files (and paths) with non-ASCII characters:
74                                        // PHP5 and below are a real mess when it comes to handling Unicode filesystems
75                                        // (see the php.net site too: readdir / glob / etc. user comments and the official
76                                        // notice that PHP will support filesystem UTF-8/Unicode only when PHP6 is released.
77                                        //
78                                        // Big, fat bummer!
79                                        continue;
80                                }
81                                //$temp = unpack("H*",$file);
82                                //echo 'hexdump of filename = ' . $temp[1] . ' for filename = ' . $file . "<br>\n";
83
84                                $filepath = $path . '/' . $file;
85                                $isdir = is_dir($filepath);
86
87                                // Recurse subdirectories (GLOB_RECURSE); speedup: no need to sort the intermediate results
88                                if (($flags & GLOB_RECURSE) && $isdir && !($file == '.' || $file == '..'))
89                                {
90                                        $subsect = safe_glob($filepath . '/' . $mask, $flags | GLOB_NOSORT);
91                                        if (is_array($subsect))
92                                        {
93                                                if (!($flags & GLOB_PATH))
94                                                {
95                                                        $dirs = array_merge($dirs, array_prepend($subject['dirs'], $file . '/'));
96                                                        $files = array_merge($files, array_prepend($subject['files'], $file . '/'));
97                                                }
98                                        }
99                                }
100                                // Match file mask
101                                if (fnmatch($mask, $file))
102                                {
103                                        if ( ( (!($flags & GLOB_ONLYDIR)) || $isdir )
104                                          && ( (!($flags & GLOB_NODIR)) || !$isdir )
105                                          && ( (!($flags & GLOB_NODOTS)) || !($file == '.' || $file == '..') )
106                                          && ( (!($flags & GLOB_NOHIDDEN)) || ($file[0] != '.' || $file == '..')) )
107                                        {
108                                                if ($isdir)
109                                                {
110                                                        $dirs[] = ($flags & GLOB_PATH ? $path . '/' : '') . $file . (($flags & GLOB_MARK) ? '/' : '');
111                                                }
112                                                else
113                                                {
114                                                        $files[] = ($flags & GLOB_PATH ? $path . '/' : '') . $file;
115                                                }
116                                        }
117                                }
118                        }
119                        closedir($dir);
120                        if (!($flags & GLOB_NOSORT))
121                        {
122                                sort($dirs);
123                                sort($files);
124                        }
125                        return array('dirs' => $dirs, 'files' => $files);
126                }
127                else
128                {
129                        return false;
130                }
131        }
132}
133
134
135
136
137// derived from http://nl.php.net/manual/en/function.http-build-query.php#90438
138if (!function_exists('http_build_query_ex'))
139{
140        if (!defined('PHP_QUERY_RFC1738')) define('PHP_QUERY_RFC1738', 1); // encoding is performed per RFC 1738 and the application/x-www-form-urlencoded media type, which implies that spaces are encoded as plus (+) signs.
141        if (!defined('PHP_QUERY_RFC3986')) define('PHP_QUERY_RFC3986', 2); // encoding is performed according to » RFC 3986, and spaces will be percent encoded (%20).
142
143        function http_build_query_ex($data, $prefix = '', $sep = '', $key = '', $enc_type = PHP_QUERY_RFC1738)
144        {
145                $ret = array();
146                if (!is_array($data) && !is_object($data))
147                {
148                        if ($enc_type == PHP_QUERY_RFC1738)
149                        {
150                                $ret[] = urlencode($data);
151                        }
152                        else
153                        {
154                                $ret[] = rawurlencode($data);
155                        }
156                }
157                else
158                {
159                        if (!empty($prefix))
160                        {
161                                if ($enc_type == PHP_QUERY_RFC1738)
162                                {
163                                        $prefix = urlencode($prefix);
164                                }
165                                else
166                                {
167                                        $prefix = rawurlencode($prefix);
168                                }
169                        }
170                        foreach ($data as $k => $v)
171                        {
172                                if (is_int($k))
173                                {
174                                        $k = $prefix . $k;
175                                }
176                                else if ($enc_type == PHP_QUERY_RFC1738)
177                                {
178                                        $k = urlencode($k);
179                                }
180                                else
181                                {
182                                        $k = rawurlencode($k);
183                                }
184                                if (!empty($key) || $key === 0)
185                                {
186                                        $k = $key . '[' . $k . ']';
187                                }
188                                if (is_array($v) || is_object($v))
189                                {
190                                        $ret[] = http_build_query_ex($v, '', $sep, $k, $enc_type);
191                                }
192                                else
193                                {
194                                        if ($enc_type == PHP_QUERY_RFC1738)
195                                        {
196                                                $v = urlencode($v);
197                                        }
198                                        else
199                                        {
200                                                $v = rawurlencode($v);
201                                        }
202                                        $ret[] = $k . '=' . $v;
203                                }
204                        }
205                }
206                if (empty($sep)) $sep = ini_get('arg_separator.output');
207                return implode($sep, $ret);
208        }
209}
210
211
212
213/**
214 * Determine how the PHP interpreter was invoked: cli/cgi/fastcgi/server,
215 * where 'server' implies PHP is part of a webserver in the form of a 'module' (e.g. mod_php5) or similar.
216 *
217 * This information is used, for example, to decide the correct way to send the 'respose header code':
218 * see send_response_status_header().
219 */
220if (!function_exists('get_interpreter_invocation_mode'))
221{
222        function get_interpreter_invocation_mode()
223        {
224                global $_ENV;
225                global $_SERVER;
226
227                /*
228                 * see
229                 *
230                 * http://nl2.php.net/manual/en/function.php-sapi-name.php
231                 * http://stackoverflow.com/questions/190759/can-php-detect-if-its-run-from-a-cron-job-or-from-the-command-line
232                 */
233                $mode = "server";
234                $name = php_sapi_name();
235                if (preg_match("/fcgi/", $name) == 1)
236                {
237                        $mode = "fastcgi";
238                }
239                else if (preg_match("/cli/", $name) == 1)
240                {
241                        $mode = "cli";
242                }
243                else if (preg_match("/cgi/", $name) == 1)
244                {
245                        $mode = "cgi";
246                }
247
248                /*
249                 * check whether POSIX functions have been compiled/enabled; xampp on Win32/64 doesn't have the buggers! :-(
250                 */
251                if (function_exists('posix_isatty'))
252                {
253                        if (posix_isatty(STDOUT))
254                        {
255                                /* even when seemingly run as cgi/fastcgi, a valid stdout TTY implies an interactive commandline run */
256                                $mode = 'cli';
257                        }
258                }
259
260                if (!empty($_ENV['TERM']) && empty($_SERVER['REMOTE_ADDR']))
261                {
262                        /* even when seemingly run as cgi/fastcgi, a valid stdout TTY implies an interactive commandline run */
263                        $mode = 'cli';
264                }
265
266                return $mode;
267        }
268}
269
270
271
272
273
274
275/**
276 * Return the HTTP response code string for the given response code
277 */
278if (!function_exists('get_response_code_string'))
279{
280        function get_response_code_string($response_code)
281        {
282                $response_code = intval($response_code);
283                switch ($response_code)
284                {
285                case 100:   return "RFC2616 Section 10.1.1: Continue";
286                case 101:   return "RFC2616 Section 10.1.2: Switching Protocols";
287                case 200:   return "RFC2616 Section 10.2.1: OK";
288                case 201:   return "RFC2616 Section 10.2.2: Created";
289                case 202:   return "RFC2616 Section 10.2.3: Accepted";
290                case 203:   return "RFC2616 Section 10.2.4: Non-Authoritative Information";
291                case 204:   return "RFC2616 Section 10.2.5: No Content";
292                case 205:   return "RFC2616 Section 10.2.6: Reset Content";
293                case 206:   return "RFC2616 Section 10.2.7: Partial Content";
294                case 300:   return "RFC2616 Section 10.3.1: Multiple Choices";
295                case 301:   return "RFC2616 Section 10.3.2: Moved Permanently";
296                case 302:   return "RFC2616 Section 10.3.3: Found";
297                case 303:   return "RFC2616 Section 10.3.4: See Other";
298                case 304:   return "RFC2616 Section 10.3.5: Not Modified";
299                case 305:   return "RFC2616 Section 10.3.6: Use Proxy";
300                case 307:   return "RFC2616 Section 10.3.8: Temporary Redirect";
301                case 400:   return "RFC2616 Section 10.4.1: Bad Request";
302                case 401:   return "RFC2616 Section 10.4.2: Unauthorized";
303                case 402:   return "RFC2616 Section 10.4.3: Payment Required";
304                case 403:   return "RFC2616 Section 10.4.4: Forbidden";
305                case 404:   return "RFC2616 Section 10.4.5: Not Found";
306                case 405:   return "RFC2616 Section 10.4.6: Method Not Allowed";
307                case 406:   return "RFC2616 Section 10.4.7: Not Acceptable";
308                case 407:   return "RFC2616 Section 10.4.8: Proxy Authentication Required";
309                case 408:   return "RFC2616 Section 10.4.9: Request Time-out";
310                case 409:   return "RFC2616 Section 10.4.10: Conflict";
311                case 410:   return "RFC2616 Section 10.4.11: Gone";
312                case 411:   return "RFC2616 Section 10.4.12: Length Required";
313                case 412:   return "RFC2616 Section 10.4.13: Precondition Failed";
314                case 413:   return "RFC2616 Section 10.4.14: Request Entity Too Large";
315                case 414:   return "RFC2616 Section 10.4.15: Request-URI Too Large";
316                case 415:   return "RFC2616 Section 10.4.16: Unsupported Media Type";
317                case 416:   return "RFC2616 Section 10.4.17: Requested range not satisfiable";
318                case 417:   return "RFC2616 Section 10.4.18: Expectation Failed";
319                case 500:   return "RFC2616 Section 10.5.1: Internal Server Error";
320                case 501:   return "RFC2616 Section 10.5.2: Not Implemented";
321                case 502:   return "RFC2616 Section 10.5.3: Bad Gateway";
322                case 503:   return "RFC2616 Section 10.5.4: Service Unavailable";
323                case 504:   return "RFC2616 Section 10.5.5: Gateway Time-out";
324                case 505:   return "RFC2616 Section 10.5.6: HTTP Version not supported";
325        /*
326                case 102:   return "Processing";  // http://www.askapache.com/htaccess/apache-status-code-headers-errordocument.html#m0-askapache3
327                case 207:   return "Multi-Status";
328                case 418:   return "I'm a teapot";
329                case 419:   return "unused";
330                case 420:   return "unused";
331                case 421:   return "unused";
332                case 422:   return "Unproccessable entity";
333                case 423:   return "Locked";
334                case 424:   return "Failed Dependency";
335                case 425:   return "Node code";
336                case 426:   return "Upgrade Required";
337                case 506:   return "Variant Also Negotiates";
338                case 507:   return "Insufficient Storage";
339                case 508:   return "unused";
340                case 509:   return "unused";
341                case 510:   return "Not Extended";
342        */
343                default:   return rtrim("Unknown Response Code " . $response_code);
344                }
345        }
346}
347
348
349
350/**
351 * Performs the correct way of transmitting the response status code header: PHP header() must be invoked in different ways
352 * dependent on the way the PHP interpreter has been invoked.
353 *
354 * See also:
355 *
356 *   http://nl2.php.net/manual/en/function.header.php
357 */
358if (!function_exists('send_response_status_header'))
359{
360        function send_response_status_header($response_code)
361        {
362                $mode = get_interpreter_invocation_mode();
363                switch ($mode)
364                {
365                default:
366                case 'fcgi':
367                        header('Status: ' . $response_code, true, $response_code);
368                        break;
369
370                case 'server':
371                        header('HTTP/1.0 ' . $response_code . ' ' . get_response_code_string($response_code), true, $response_code);
372                        break;
373                }
374        }
375}
376
377
378
379
380
381
382/*
383 * http://www.php.net/manual/en/function.image-type-to-extension.php#77354
384 * -->
385 * http://www.php.net/manual/en/function.image-type-to-extension.php#79688
386 */
387if (!function_exists('image_type_to_extension'))
388{
389        function image_type_to_extension($type, $dot = true)
390        {
391                $e = array(1 => 'gif', 'jpeg', 'png', 'swf', 'psd', 'bmp', 'tiff', 'tiff', 'jpc', 'jp2', 'jpf', 'jb2', 'swc', 'aiff', 'wbmp', 'xbm');
392
393                // We are expecting an integer.
394                $t = (int)$type;
395                if (!$t)
396                {
397                        trigger_error('invalid IMAGETYPE_XXX(' . $type . ') passed to image_type_to_extension()', E_USER_NOTICE);
398                        return null;
399                }
400                if (!isset($e[$t]))
401                {
402                        trigger_error('unidentified IMAGETYPE_XXX(' . $type . ') passed to image_type_to_extension()', E_USER_NOTICE);
403                        return null;
404                }
405
406                return ($dot ? '.' : '') . $e[$t];
407        }
408}
409
410
411if (!function_exists('image_type_to_mime_type'))
412{
413        function image_type_to_mime_type($type)
414        {
415                $m = array(1 => 'image/gif', 'image/jpeg', 'image/png',
416                        'application/x-shockwave-flash', 'image/psd', 'image/bmp',
417                        'image/tiff', 'image/tiff', 'application/octet-stream',
418                        'image/jp2', 'application/octet-stream', 'application/octet-stream',
419                        'application/x-shockwave-flash', 'image/iff', 'image/vnd.wap.wbmp', 'image/xbm');
420
421                // We are expecting an integer.
422                $t = (int)$type;
423                if (!$t)
424                {
425                        trigger_error('invalid IMAGETYPE_XXX(' . $type . ') passed to image_type_to_mime_type()', E_USER_NOTICE);
426                        return null;
427                }
428                if (!isset($m[$t]))
429                {
430                        trigger_error('unidentified IMAGETYPE_XXX(' . $type . ') passed to image_type_to_mime_type()', E_USER_NOTICE);
431                        return null;
432                }
433                return $m[$t];
434        }
435}
436
437
438
439
440
441
Note: See TracBrowser for help on using the repository browser.