summaryrefslogtreecommitdiffstats
path: root/web/lib/Find.php
diff options
context:
space:
mode:
Diffstat (limited to 'web/lib/Find.php')
-rw-r--r--web/lib/Find.php485
1 files changed, 485 insertions, 0 deletions
diff --git a/web/lib/Find.php b/web/lib/Find.php
new file mode 100644
index 00000000..62fc33ff
--- /dev/null
+++ b/web/lib/Find.php
@@ -0,0 +1,485 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2005 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Author: Sterling Hughes <sterling@php.net> |
+// +----------------------------------------------------------------------+
+//
+// $Id: Find.php,v 1.27 2006/06/30 14:06:16 techtonik Exp $
+//
+
+require_once 'PEAR.php';
+
+define('FILE_FIND_VERSION', '@package_version@');
+
+// to debug uncomment this string
+// define('FILE_FIND_DEBUG', '');
+
+/**
+* Commonly needed functions searching directory trees
+*
+* @access public
+* @version $Id: Find.php,v 1.27 2006/06/30 14:06:16 techtonik Exp $
+* @package File
+* @author Sterling Hughes <sterling@php.net>
+*/
+class File_Find
+{
+ /**
+ * internal dir-list
+ * @var array
+ */
+ var $_dirs = array();
+
+ /**
+ * directory separator
+ * @var string
+ */
+ var $dirsep = "/";
+
+ /**
+ * found files
+ * @var array
+ */
+ var $files = array();
+
+ /**
+ * found dirs
+ * @var array
+ */
+ var $directories = array();
+
+ /**
+ * Search specified directory to find matches for specified pattern
+ *
+ * @param string $pattern a string containing the pattern to search
+ * the directory for.
+ *
+ * @param string $dirpath a string containing the directory path
+ * to search.
+ *
+ * @param string $pattern_type a string containing the type of
+ * pattern matching functions to use (can either be 'php',
+ * 'perl' or 'shell').
+ *
+ * @return array containing all of the files and directories
+ * matching the pattern or null if no matches
+ *
+ * @author Sterling Hughes <sterling@php.net>
+ * @access public
+ * @static
+ */
+ function &glob($pattern, $dirpath, $pattern_type = 'php')
+ {
+ $dh = @opendir($dirpath);
+
+ if (!$dh) {
+ $pe = PEAR::raiseError("Cannot open directory $dirpath");
+ return $pe;
+ }
+
+ $match_function = File_Find::_determineRegex($pattern, $pattern_type);
+ $matches = array();
+
+ // empty string cannot be specified for 'php' and 'perl' pattern
+ if ($pattern || ($pattern_type != 'php' && $pattern_type != 'perl')) {
+ while (false !== ($entry = @readdir($dh))) {
+ if ($match_function($pattern, $entry) &&
+ $entry != '.' && $entry != '..') {
+ $matches[] = $entry;
+ }
+ }
+ }
+
+ @closedir($dh);
+
+ if (0 == count($matches)) {
+ $matches = null;
+ }
+
+ return $matches ;
+ }
+
+ /**
+ * Map the directory tree given by the directory_path parameter.
+ *
+ * @param string $directory contains the directory path that you
+ * want to map.
+ *
+ * @return array a two element array, the first element containing a list
+ * of all the directories, the second element containing a list of all the
+ * files.
+ *
+ * @author Sterling Hughes <sterling@php.net>
+ * @access public
+ */
+ function &maptree($directory)
+ {
+
+ /* if called statically */
+ if (!isset($this) || !is_a($this, "File_Find")) {
+ $obj = &new File_Find();
+ return $obj->maptree($directory);
+ }
+
+ /* clear the results just in case */
+ $this->files = array();
+ $this->directories = array();
+
+ /* strip out trailing slashes */
+ $directory = preg_replace('![\\\\/]+$!', '', $directory);
+
+ $this->_dirs = array($directory);
+
+ while (count($this->_dirs)) {
+ $dir = array_pop($this->_dirs);
+ File_Find::_build($dir, $this->dirsep);
+ array_push($this->directories, $dir);
+ }
+
+ $retval = array($this->directories, $this->files);
+ return $retval;
+
+ }
+
+ /**
+ * Map the directory tree given by the directory parameter.
+ *
+ * @param string $directory contains the directory path that you
+ * want to map.
+ * @param integer $maxrecursion maximun number of folders to recursive
+ * map
+ *
+ * @return array a multidimensional array containing all subdirectories
+ * and their files. For example:
+ *
+ * Array
+ * (
+ * [0] => file_1.php
+ * [1] => file_2.php
+ * [subdirname] => Array
+ * (
+ * [0] => file_1.php
+ * )
+ * )
+ *
+ * @author Mika Tuupola <tuupola@appelsiini.net>
+ * @access public
+ * @static
+ */
+ function &mapTreeMultiple($directory, $maxrecursion = 0, $count = 0)
+ {
+ $retval = array();
+
+ $count++;
+
+ /* strip trailing slashes */
+ $directory = preg_replace('![\\\\/]+$!', '', $directory);
+
+ if (is_readable($directory)) {
+ $dh = opendir($directory);
+ while (false !== ($entry = @readdir($dh))) {
+ if ($entry != '.' && $entry != '..') {
+ array_push($retval, $entry);
+ }
+ }
+ closedir($dh);
+ }
+
+ while (list($key, $val) = each($retval)) {
+ $path = $directory . "/" . $val;
+
+ if (!is_array($val) && is_dir($path)) {
+ unset($retval[$key]);
+ if ($maxrecursion == 0 || $count < $maxrecursion) {
+ $retval[$val] = &File_Find::mapTreeMultiple($path,
+ $maxrecursion, $count);
+ }
+ }
+ }
+
+ return $retval;
+ }
+
+ /**
+ * Search the specified directory tree with the specified pattern. Return
+ * an array containing all matching files (no directories included).
+ *
+ * @param string $pattern the pattern to match every file with.
+ *
+ * @param string $directory the directory tree to search in.
+ *
+ * @param string $type the type of regular expression support to use, either
+ * 'php', 'perl' or 'shell'.
+ *
+ * @param bool $fullpath whether the regex should be matched against the
+ * full path or only against the filename
+ *
+ * @param string $match can be either 'files', 'dirs' or 'both' to specify
+ * the kind of list to return
+ *
+ * @return array a list of files matching the pattern parameter in the the
+ * directory path specified by the directory parameter
+ *
+ * @author Sterling Hughes <sterling@php.net>
+ * @access public
+ * @static
+ */
+ function &search($pattern, $directory, $type = 'php', $fullpath = true, $match = 'files')
+ {
+
+ $matches = array();
+ list ($directories,$files) = File_Find::maptree($directory);
+ switch($match) {
+ case 'directories':
+ $data = $directories;
+ break;
+ case 'both':
+ $data = array_merge($directories, $files);
+ break;
+ case 'files':
+ default:
+ $data = $files;
+ }
+ unset($files, $directories);
+
+ $match_function = File_Find::_determineRegex($pattern, $type);
+
+ reset($data);
+ // check if empty string given (ok for 'shell' method, but bad for others)
+ if ($pattern || ($type != 'php' && $type != 'perl')) {
+ while (list(,$entry) = each($data)) {
+ if ($match_function($pattern,
+ $fullpath ? $entry : basename($entry))) {
+ $matches[] = $entry;
+ }
+ }
+ }
+
+ return $matches;
+ }
+
+ /**
+ * Determine whether or not a variable is a PEAR error
+ *
+ * @param object PEAR_Error $var the variable to test.
+ *
+ * @return boolean returns true if the variable is a PEAR error, otherwise
+ * it returns false.
+ * @access public
+ */
+ function isError(&$var)
+ {
+ return PEAR::isError($var);
+ }
+
+ /**
+ * internal function to build singular directory trees, used by
+ * File_Find::maptree()
+ *
+ * @param string $directory name of the directory to read
+ * @param string $separator directory separator
+ * @return void
+ */
+ function _build($directory, $separator = "/")
+ {
+
+ $dh = @opendir($directory);
+
+ if (!$dh) {
+ $pe = PEAR::raiseError("Cannot open directory");
+ return $pe;
+ }
+
+ while (false !== ($entry = @readdir($dh))) {
+ if ($entry != '.' && $entry != '..') {
+
+ $entry = $directory.$separator.$entry;
+
+ if (is_dir($entry)) {
+ array_push($this->_dirs, $entry);
+ } else {
+ array_push($this->files, $entry);
+ }
+ }
+ }
+
+ @closedir($dh);
+ }
+
+ /**
+ * internal function to determine the type of regular expression to
+ * use, implemented by File_Find::glob() and File_Find::search()
+ *
+ * @param string $type given RegExp type
+ * @return string kind of function ( "eregi", "ereg" or "preg_match") ;
+ *
+ */
+ function _determineRegex($pattern, $type)
+ {
+ if (!strcasecmp($type, 'shell')) {
+ $match_function = 'File_Find_match_shell';
+ } else if (!strcasecmp($type, 'perl')) {
+ $match_function = 'preg_match';
+ } else if (!strcasecmp(substr($pattern, -2), '/i')) {
+ $match_function = 'eregi';
+ } else {
+ $match_function = 'ereg';
+ }
+ return $match_function;
+ }
+
+}
+
+/**
+* Package method to match via 'shell' pattern. Provided in global
+* scope, because it should be called like 'preg_match' and 'eregi'
+* and can be easily copied into other packages
+*
+* @author techtonik <techtonik@php.net>
+* @return mixed bool on success and PEAR_Error on failure
+*/
+function File_Find_match_shell($pattern, $filename)
+{
+ // {{{ convert pattern to positive and negative regexps
+ $positive = $pattern;
+ $negation = substr_count($pattern, "|");
+
+ if ($negation > 1) {
+ PEAR::raiseError("Mask string contains errors!");
+ return FALSE;
+ } elseif ($negation) {
+ list($positive, $negative) = explode("|", $pattern);
+ if (strlen($negative) == 0) {
+ PEAR::raiseError("File-mask string contains errors!");
+ return FALSE;
+ }
+ }
+
+ $positive = _File_Find_match_shell_get_pattern($positive);
+ if ($negation) {
+ $negative = _File_Find_match_shell_get_pattern($negative);
+ }
+ // }}} convert end
+
+
+ if (defined("FILE_FIND_DEBUG")) {
+ print("Method: $type\nPattern: $pattern\n Converted pattern:");
+ print_r($positive);
+ if (isset($negative)) print_r($negative);
+ }
+
+ if (!preg_match($positive, $filename)) {
+ return FALSE;
+ } else {
+ if (isset($negative)
+ && preg_match($negative, $filename)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+}
+
+/**
+* function used by File_Find_match_shell to convert 'shell' mask
+* into pcre regexp. Some of the rules (see testcases for more):
+* escaping all special chars and replacing
+* . with \.
+* * with .*
+* ? with .{1}
+* also adding ^ and $ as the pattern matches whole filename
+*
+* @author techtonik <techtonik@php.net>
+* @return string pcre regexp for preg_match
+*/
+function _File_Find_match_shell_get_pattern($mask) {
+ // get array of several masks (if any) delimited by comma
+ // do not touch commas in char class
+ $premasks = preg_split("|(\[[^\]]+\])|", $mask, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
+ if (defined("FILE_FIND_DEBUG")) {
+ print("\nPremask: ");
+ print_r($premasks);
+ }
+ $pi = 0;
+ foreach($premasks as $pm) {
+ if (!isset($masks[$pi])) $masks[$pi] = "";
+ if ($pm{0} == '[' && $pm{strlen($pm)-1} == ']') {
+ // strip commas from character class
+ $masks[$pi] .= str_replace(",", "", $pm);
+ } else {
+ $tarr = explode(",", $pm);
+ if (sizeof($tarr) == 1) {
+ $masks[$pi] .= $pm;
+ } else {
+ foreach ($tarr as $te) {
+ $masks[$pi++] .= $te;
+ $masks[$pi] = "";
+ }
+ unset($masks[$pi--]);
+ }
+ }
+ }
+
+ // if empty string given return *.* pattern
+ if (strlen($mask) == 0) return "!^.*$!";
+
+ // convert to preg regexp
+ $regexmask = implode("|", $masks);
+ if (defined("FILE_FIND_DEBUG")) {
+ print("regexMask step one(implode): $regexmask");
+ }
+ $regexmask = addcslashes($regexmask, '^$}!{)(\/.+');
+ if (defined("FILE_FIND_DEBUG")) {
+ print("\nregexMask step two(addcslashes): $regexmask");
+ }
+ $regexmask = preg_replace("!(\*|\?)!", ".$1", $regexmask);
+ if (defined("FILE_FIND_DEBUG")) {
+ print("\nregexMask step three(* ? -> .* .?): $regexmask");
+ }
+ // a special case '*.' at the end means that there is no extension
+ $regexmask = preg_replace("!\.\*\\\.(\||$)!", "[^\.]*$1", $regexmask);
+ // it is impossible to have dot at the end of filename
+ $regexmask = preg_replace("!\\\.(\||$)!", "$1", $regexmask);
+ // and .* at the end also means that there could be nothing at all
+ // (i.e. no dot at the end also)
+ $regexmask = preg_replace("!\\\.\.\*(\||$)!", "(\\\\..*)?$1", $regexmask);
+ if (defined("FILE_FIND_DEBUG")) {
+ print("\nregexMask step two and half(*.$ \\..*$ .$ -> [^.]*$ .?.* $): $regexmask");
+ }
+ // if no extension supplied - add .* to match partially from filename start
+ if (strpos($regexmask, "\\.") === FALSE) $regexmask .= ".*";
+
+ // file mask match whole name - adding restrictions
+ $regexmask = preg_replace("!(\|)!", '^'."$1".'$', $regexmask);
+ $regexmask = '^'.$regexmask.'$';
+ if (defined("FILE_FIND_DEBUG")) {
+ print("\nregexMask step three(^ and $ to match whole name): $regexmask");
+ }
+ // wrap regex into ! since all ! are already escaped
+ $regexmask = "!$regexmask!i";
+ if (defined("FILE_FIND_DEBUG")) {
+ print("\nWrapped regex: $regexmask\n");
+ }
+ return $regexmask;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+
+?>