PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/external/compat/glob.php

https://bitbucket.org/djl/flyspray-mirror
PHP | 370 lines | 268 code | 19 blank | 83 comment | 64 complexity | 7e9f879d5c6af14465b5bf838449a80d MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, BSD-3-Clause, MPL-2.0-no-copyleft-exception
  1. <?php
  2. // $Id$
  3. if (!defined('GLOB_ERR')) {
  4. define('GLOB_ERR', 1);
  5. }
  6. if (!defined('GLOB_MARK')) {
  7. define('GLOB_MARK', 2);
  8. }
  9. if (!defined('GLOB_NOSORT')) {
  10. define('GLOB_NOSORT', 4);
  11. }
  12. if (!defined('GLOB_NOCHECK')) {
  13. define('GLOB_NOCHECK', 16);
  14. }
  15. if (!defined('GLOB_NOESCAPE')) {
  16. define('GLOB_NOESCAPE', 64);
  17. }
  18. if (!defined('GLOB_BRACE')) {
  19. define('GLOB_BRACE', 1024);
  20. }
  21. if (!defined('GLOB_ONLYDIR')) {
  22. define('GLOB_ONLYDIR', 8192);
  23. }
  24. /**
  25. * Replace glob()
  26. *
  27. * @category PHP
  28. * @package PHP_Compat
  29. * @license LGPL - http://www.gnu.org/licenses/lgpl.html
  30. * @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
  31. * @link http://php.net/glob
  32. * @author Arpad Ray <arpad@php.net>
  33. * @version $Revision: 1.7 $
  34. * @since PHP 4.3.0
  35. * @require PHP 3.0.9 (preg_replace)
  36. */
  37. function php_compat_glob($pattern, $flags = 0)
  38. {
  39. $return_failure = ($flags & GLOB_NOCHECK) ? array($pattern) : false;
  40. // build path to scan files
  41. $path = '.';
  42. $wildcards_open = '*?[';
  43. $wildcards_close = ']';
  44. if ($flags & GLOB_BRACE) {
  45. $wildcards_open .= '{';
  46. $wildcards_close .= '}';
  47. }
  48. $prefix_length = strcspn($pattern, $wildcards_open);
  49. if ($prefix_length) {
  50. if (DIRECTORY_SEPARATOR == '\\') {
  51. $sep = ($flags & GLOB_NOESCAPE) ? '[\\\\/]' : '(?:/|\\\\(?![' . $wildcards_open . $wildcards_close . ']))';
  52. } else {
  53. $sep = '/';
  54. }
  55. if (preg_match('#^(.*)' . $sep . '#', substr($pattern, 0, $prefix_length), $matches)) {
  56. $path = $matches[1];
  57. }
  58. }
  59. $recurse = (strpos($pattern, DIRECTORY_SEPARATOR, $prefix_length) !== false);
  60. // scan files
  61. $files = php_compat_glob_scan_helper($path, $flags, $recurse);
  62. if ($files === false) {
  63. return $return_failure;
  64. }
  65. // build preg pattern
  66. $pattern = php_compat_glob_convert_helper($pattern, $flags);
  67. $convert_patterns = array('/\{([^{}]*)\}/e', '/\[([^\]]*)\]/e');
  68. $convert_replacements = array(
  69. 'php_compat_glob_brace_helper(\'$1\', $flags)',
  70. 'php_compat_glob_charclass_helper(\'$1\', $flags)'
  71. );
  72. while ($flags & GLOB_BRACE) {
  73. $new_pattern = preg_replace($convert_patterns, $convert_replacements, $pattern);
  74. if ($new_pattern == $pattern) {
  75. break;
  76. }
  77. $pattern = $new_pattern;
  78. }
  79. $pattern = '#^' . $pattern . '\z#';
  80. // process files
  81. $results = array();
  82. foreach ($files as $file => $dir) {
  83. if (!preg_match($pattern, $file, $matches)) {
  84. continue;
  85. }
  86. if (($flags & GLOB_ONLYDIR) && !$dir) {
  87. continue;
  88. }
  89. $file = (($flags & GLOB_MARK) && $dir) ? $file . DIRECTORY_SEPARATOR : $file;
  90. if ($flags & GLOB_BRACE) {
  91. // find last matching subpattern
  92. $rank = 0;
  93. for ($i = 1, $matchc = count($matches); $i < $matchc; $i++) {
  94. if (strlen($matches[$i])) {
  95. $rank = $i;
  96. }
  97. }
  98. $file = array($file, $rank);
  99. }
  100. $results[] = $file;
  101. }
  102. if ($flags & GLOB_BRACE) {
  103. usort($results, ($flags & GLOB_NOSORT) ? 'php_compat_glob_brace_nosort_helper' : 'php_compat_glob_brace_sort_helper');
  104. } else if ($flags & GLOB_NOSORT) {
  105. usort($results, 'php_compat_glob_nosort_helper');
  106. } else {
  107. sort($results);
  108. }
  109. // array_values() for php 4 +
  110. $reindex = array();
  111. foreach ($results as $result) {
  112. $reindex[] = ($flags & GLOB_BRACE) ? $result[0] : $result;
  113. }
  114. if (($flags & GLOB_NOCHECK) && !count($reindex)) {
  115. return $return_failure;
  116. }
  117. return $reindex;
  118. }
  119. /**
  120. * Scans a path
  121. *
  122. * @param string $path
  123. * the path to scan
  124. * @param int $flags
  125. * the flags passed to glob()
  126. * @param bool $recurse
  127. * true to scan recursively
  128. * @return mixed
  129. * an array of files in the given path where the key is the path,
  130. * and the value is 1 if the file is a directory, 0 if it isn't.
  131. * Returns false on unrecoverable errors, or all errors when
  132. * GLOB_ERR is on.
  133. */
  134. function php_compat_glob_scan_helper($path, $flags, $recurse = false)
  135. {
  136. if (!is_readable($path)) {
  137. return false;
  138. }
  139. $results = array();
  140. if (is_dir($path)) {
  141. $fp = opendir($path);
  142. if (!$fp) {
  143. return ($flags & GLOB_ERR) ? false : array($path);
  144. }
  145. if ($path != '.') {
  146. $results[$path] = 1;
  147. }
  148. while (($file = readdir($fp)) !== false) {
  149. if ($file[0] == '.' || $file == '..') {
  150. continue;
  151. }
  152. $filepath = ($path == '.') ? $file : $path . DIRECTORY_SEPARATOR . $file;
  153. if (is_dir($filepath)) {
  154. $results[$filepath] = 1;
  155. if (!$recurse) {
  156. continue;
  157. }
  158. $files = php_compat_glob_scan_helper($filepath, $flags);
  159. if ($files === false) {
  160. if ($flags & GLOB_ERR) {
  161. return false;
  162. }
  163. continue;
  164. }
  165. // array_merge for php 4 +
  166. foreach ($files as $rfile => $rdir) {
  167. $results[$rfile] = $rdir;
  168. }
  169. continue;
  170. }
  171. $results[$filepath] = 0;
  172. }
  173. closedir($fp);
  174. } else {
  175. $results[$path] = 0;
  176. }
  177. return $results;
  178. }
  179. /**
  180. * Converts a section of a glob pattern to a PCRE pattern
  181. *
  182. * @param string $input
  183. * the pattern to convert
  184. * @param int $flags
  185. * the flags passed to glob()
  186. * @return string
  187. * the escaped input
  188. */
  189. function php_compat_glob_convert_helper($input, $flags)
  190. {
  191. $opens = array(
  192. '{' => array('}', 0),
  193. '[' => array(']', 0),
  194. '(' => array(')', 0)
  195. );
  196. $ret = '';
  197. for ($i = 0, $len = strlen($input); $i < $len; $i++) {
  198. $skip = false;
  199. $c = $input[$i];
  200. $escaped = ($i && $input[$i - 1] == '\\' && ($flags & GLOB_NOCHECK == false));
  201. // skips characters classes and subpatterns, they are escaped in their respective helpers
  202. foreach ($opens as $k => $v) {
  203. if ($v[1]) {
  204. if ($c == $v[0] && !$escaped) {
  205. --$opens[$k][1];
  206. $ret .= $c;
  207. continue 2;
  208. }
  209. $skip = true;
  210. }
  211. }
  212. if (isset($opens[$c])) {
  213. if (!$escaped) {
  214. ++$opens[$c][1];
  215. }
  216. $ret .= $c;
  217. continue;
  218. }
  219. if ($skip) {
  220. $ret .= $c;
  221. continue;
  222. }
  223. // converts wildcards
  224. switch ($c) {
  225. case '*':
  226. $ret .= $escaped ? '*' : '.*';
  227. continue 2;
  228. case '?':
  229. if ($escaped) {
  230. continue;
  231. }
  232. $ret .= '.';
  233. continue 2;
  234. }
  235. $ret .= preg_quote($c, '#');
  236. }
  237. return $ret;
  238. }
  239. /**
  240. * Converts glob braces
  241. *
  242. * @param string $brace
  243. * the contents of the braces to convert
  244. * @param int $flags
  245. * the flags passed to glob()
  246. * @return string
  247. * a PCRE subpattern of alternatives
  248. */
  249. function php_compat_glob_brace_helper($brace, $flags)
  250. {
  251. $alternatives = explode(',', $brace);
  252. for ($i = count($alternatives); $i--;) {
  253. $alternatives[$i] = php_compat_glob_convert_helper($alternatives[$i], $flags);
  254. }
  255. return '(?:(' . implode(')|(', $alternatives) . '))';
  256. }
  257. /**
  258. * Converts glob character classes
  259. *
  260. * @param string $class
  261. * the contents of the class to convert
  262. * @param int $flags
  263. * the flags passed to glob()
  264. * @return string
  265. * a PCRE character class
  266. */
  267. function php_compat_glob_charclass_helper($class, $flags)
  268. {
  269. if (strpos($class, '-') !== false) {
  270. $class = strtr($class, array('-' => '')) . '-';
  271. }
  272. if (strpos($class, ']') !== false) {
  273. $class = ']' . strtr($class, array(']' => ''));
  274. }
  275. if (strpos($class, '^') !== false) {
  276. $class = '\^' . strtr($class, array('^' => ''));
  277. }
  278. return '[' . strtr($class, array('#' => '\#')) . ']';
  279. }
  280. /**
  281. * Callback sort function for GLOB_NOSORT
  282. *
  283. * Sorts first by the base name, then in reverse by the extension
  284. */
  285. function php_compat_glob_nosort_helper($a, $b)
  286. {
  287. $operands = array(array('full' => $a), array('full' => $b));
  288. foreach ($operands as $k => $v) {
  289. $v['pos'] = strrpos($v['full'], '.');
  290. if ($v['pos'] === false) {
  291. $v['pos'] = strlen($v['full']) - 1;
  292. }
  293. $v['slash'] = strrpos($v['full'], DIRECTORY_SEPARATOR);
  294. if ($v['slash'] === false) {
  295. $v['slash'] = strlen($v['full']) - 1;
  296. }
  297. $operands[$k]['dir'] = substr($v['full'], 0, $v['slash']);
  298. $operands[$k]['base'] = substr($v['full'], $v['slash'], $v['pos'] - $v['slash']);
  299. $operands[$k]['ext'] = substr($v['full'], $v['pos'] + 1);
  300. }
  301. $dir_cmp = strcmp($operands[0]['dir'], $operands[1]['dir']);
  302. if ($dir_cmp == 0) {
  303. $base_cmp = strcmp($operands[0]['base'], $operands[1]['base']);
  304. if ($base_cmp == 0) {
  305. $ext_cmp = strcmp($operands[0]['ext'], $operands[1]['ext']);
  306. return -$ext_cmp;
  307. }
  308. return $base_cmp;
  309. }
  310. return -$dir_cmp;
  311. }
  312. /**
  313. * Callback sort function for GLOB_BRACE
  314. *
  315. * Each argument should be an array where the first element is the
  316. * file path, and the second is its rank. The rank is the number of
  317. * alternatives between this match and the beginning of the brace.
  318. */
  319. function php_compat_glob_brace_sort_helper($a, $b)
  320. {
  321. if ($a[1] == $b[1]) {
  322. return strcmp($a[0], $b[0]);
  323. }
  324. return ($a[1] < $b[1]) ? -1 : 1;
  325. }
  326. /**
  327. * Callback sort function for (GLOB_BRACE | GLOB_NOSORT)
  328. *
  329. * Receives the same arguments php_compat_glob_brace_sort_helper()
  330. */
  331. function php_compat_glob_brace_nosort_helper($a, $b)
  332. {
  333. if ($a[1] == $b[1]) {
  334. $len_a = strlen($a[0]);
  335. $len_b = strlen($b[0]);
  336. if ($len_a == $len_b) {
  337. return -strcmp($a[0], $b[0]);
  338. }
  339. return ($len_a < $len_b) ? -1 : 1;
  340. }
  341. return ($a[1] < $b[1]) ? -1 : 1;
  342. }
  343. if (!function_exists('glob')) {
  344. function glob($pattern, $flags = 0)
  345. {
  346. return php_compat_glob($pattern, $flags);
  347. }
  348. }
  349. ?>