chunk.php
11 years ago
config.php
11 years ago
download.php
11 years ago
handler.php
11 years ago
helper.php
11 years ago
input.php
11 years ago
nested.php
11 years ago
render.php
11 years ago
session.php
11 years ago
upload.php
11 years ago
helper.php
140 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Helper class which defnes a namespace for some commonly used functions |
| 4 | * |
| 5 | * @author Pavel Kulbakin <p.kulbakin@gmail.com> |
| 6 | */ |
| 7 | class PMXI_Helper { |
| 8 | const GLOB_MARK = 1; |
| 9 | const GLOB_NOSORT = 2; |
| 10 | const GLOB_ONLYDIR = 4; |
| 11 | |
| 12 | const GLOB_NODIR = 256; |
| 13 | const GLOB_PATH = 512; |
| 14 | const GLOB_NODOTS = 1024; |
| 15 | const GLOB_RECURSE = 2048; |
| 16 | |
| 17 | const FNM_PATHNAME = 1; |
| 18 | const FNM_NOESCAPE = 2; |
| 19 | const FNM_PERIOD = 4; |
| 20 | const FNM_CASEFOLD = 16; |
| 21 | |
| 22 | /** |
| 23 | * A safe empowered glob(). |
| 24 | * |
| 25 | * Function glob() is prohibited on some server (probably in safe mode) |
| 26 | * (Message "Warning: glob() has been disabled for security reasons in |
| 27 | * (script) on line (line)") for security reasons as stated on: |
| 28 | * http://seclists.org/fulldisclosure/2005/Sep/0001.html |
| 29 | * |
| 30 | * safe_glob() intends to replace glob() using readdir() & fnmatch() instead. |
| 31 | * Supported flags: self::GLOB_MARK, self::GLOB_NOSORT, self::GLOB_ONLYDIR |
| 32 | * Additional flags: self::GLOB_NODIR, self::GLOB_PATH, self::GLOB_NODOTS, self::GLOB_RECURSE |
| 33 | * (not original glob() flags) |
| 34 | * @author BigueNique AT yahoo DOT ca |
| 35 | * @updates |
| 36 | * - 080324 Added support for additional flags: self::GLOB_NODIR, self::GLOB_PATH, |
| 37 | * self::GLOB_NODOTS, self::GLOB_RECURSE |
| 38 | * - 100607 Recurse is_dir check fixed by Pavel Kulbakin <p.kulbakin@gmail.com> |
| 39 | */ |
| 40 | public static function safe_glob($pattern, $flags=0) { |
| 41 | $split = explode('/', str_replace('\\', '/', $pattern)); |
| 42 | $mask = array_pop($split); |
| 43 | $path = implode('/', $split); |
| 44 | |
| 45 | if (($dir = @opendir($path . '/')) !== false or ($dir = @opendir($path)) !== false) { |
| 46 | $glob = array(); |
| 47 | while(($file = readdir($dir)) !== false) { |
| 48 | // Recurse subdirectories (self::GLOB_RECURSE) |
| 49 | if (($flags & self::GLOB_RECURSE) && is_dir($path . '/' . $file) && ( ! in_array($file, array('.', '..')))) { |
| 50 | $glob = array_merge($glob, self::array_prepend(self::safe_glob($path . '/' . $file . '/' . $mask, $flags), ($flags & self::GLOB_PATH ? '' : $file . '/'))); |
| 51 | } |
| 52 | // Match file mask |
| 53 | if (self::fnmatch($mask, $file, self::FNM_CASEFOLD)) { |
| 54 | if ((( ! ($flags & self::GLOB_ONLYDIR)) || is_dir("$path/$file")) |
| 55 | && (( ! ($flags & self::GLOB_NODIR)) || ( ! is_dir($path . '/' . $file))) |
| 56 | && (( ! ($flags & self::GLOB_NODOTS)) || ( ! in_array($file, array('.', '..')))) |
| 57 | ) { |
| 58 | $glob[] = ($flags & self::GLOB_PATH ? $path . '/' : '') . $file . ($flags & self::GLOB_MARK ? '/' : ''); |
| 59 | } |
| 60 | } |
| 61 | } |
| 62 | closedir($dir); |
| 63 | if ( ! ($flags & self::GLOB_NOSORT)) sort($glob); |
| 64 | return $glob; |
| 65 | } else { |
| 66 | return (strpos($pattern, "*") === false) ? array($pattern) : false; |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Prepends $string to each element of $array |
| 72 | * If $deep is true, will indeed also apply to sub-arrays |
| 73 | * @author BigueNique AT yahoo DOT ca |
| 74 | * @since 080324 |
| 75 | */ |
| 76 | public static function array_prepend($array, $string, $deep=false) { |
| 77 | if(empty($array)||empty($string)) { |
| 78 | return $array; |
| 79 | } |
| 80 | foreach ($array as $key => $element) { |
| 81 | if (is_array($element)) { |
| 82 | if ($deep) { |
| 83 | $array[$key] = self::array_prepend($element,$string,$deep); |
| 84 | } else { |
| 85 | trigger_error(__METHOD__ . ': array element', E_USER_WARNING); |
| 86 | } |
| 87 | } else { |
| 88 | $array[$key] = $string.$element; |
| 89 | } |
| 90 | } |
| 91 | return $array; |
| 92 | |
| 93 | } |
| 94 | |
| 95 | /** |
| 96 | * non-POSIX complient remplacement for the fnmatch |
| 97 | */ |
| 98 | public static function fnmatch($pattern, $string, $flags = 0) { |
| 99 | |
| 100 | $modifiers = null; |
| 101 | $transforms = array( |
| 102 | '\*' => '.*', |
| 103 | '\?' => '.', |
| 104 | '\[\!' => '[^', |
| 105 | '\[' => '[', |
| 106 | '\]' => ']', |
| 107 | '\.' => '\.', |
| 108 | '\\' => '\\\\', |
| 109 | '\-' => '-', |
| 110 | ); |
| 111 | |
| 112 | // Forward slash in string must be in pattern: |
| 113 | if ($flags & self::FNM_PATHNAME) { |
| 114 | $transforms['\*'] = '[^/]*'; |
| 115 | } |
| 116 | |
| 117 | // Back slash should not be escaped: |
| 118 | if ($flags & self::FNM_NOESCAPE) { |
| 119 | unset($transforms['\\']); |
| 120 | } |
| 121 | |
| 122 | // Perform case insensitive match: |
| 123 | if ($flags & self::FNM_CASEFOLD) { |
| 124 | $modifiers .= 'i'; |
| 125 | } |
| 126 | |
| 127 | // Period at start must be the same as pattern: |
| 128 | if ($flags & self::FNM_PERIOD) { |
| 129 | if (strpos($string, '.') === 0 && strpos($pattern, '.') !== 0) return false; |
| 130 | } |
| 131 | |
| 132 | $pattern = '#^' |
| 133 | .strtr(preg_quote($pattern, '#'), $transforms) |
| 134 | .'$#' |
| 135 | .$modifiers; |
| 136 | |
| 137 | return (boolean)preg_match($pattern, $string); |
| 138 | } |
| 139 | } |
| 140 |