[ Index ]

PHP Cross Reference of Limb3

title

Body

[close]

/fs/src/ -> lmbFs.class.php (source)

   1  <?php
   2  /*
   3   * Limb PHP Framework
   4   *
   5   * @link http://limb-project.com 
   6   * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
   7   * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
   8   */
   9  lmb_require('limb/core/src/lmbSys.class.php');
  10  lmb_require('limb/fs/src/exception/lmbFsException.class.php');
  11  
  12  /**

  13   * class lmbFs.

  14   *

  15   * @package fs

  16   * @version $Id$

  17   */
  18  class lmbFs
  19  {
  20    const LOCAL = 1;
  21    const UNIX = 2;
  22    const DOS = 3;
  23    const WIN32_NET_PREFIX = '\\\\';
  24  
  25    static function safeWrite($file, $content, $perm=0664)
  26    {
  27      self :: mkdir(dirname($file));
  28  
  29      $tmp = self :: generateTmpFile('_');
  30      $fh = fopen($tmp, 'w');
  31  
  32      if($fh === false)
  33      {
  34        @unlink($tmp);
  35        throw new lmbFsException('could not open file for writing', array('file' => $file));
  36      }
  37  
  38      //just for safety

  39      @flock($fh, LOCK_EX);
  40      fwrite($fh, $content);
  41      @flock($fh, LOCK_UN);
  42      fclose($fh);
  43  
  44      if(lmbSys :: isWin32() && file_exists($file))
  45        @unlink($file);
  46  
  47      if(!@rename($tmp, $file))
  48      {
  49        @unlink($tmp);
  50        throw new lmbFsException('could not move file', array('src' => $tmp, 'file' => $file));
  51      }
  52  
  53      @chmod($file, $perm);
  54      if(file_exists($tmp))
  55        @unlink($tmp);
  56    }
  57  
  58    static function getTmpDir()
  59    {
  60      if(defined('LIMB_VAR_DIR'))
  61        return LIMB_VAR_DIR;
  62  
  63      if($path = session_save_path())
  64      {
  65        if(($pos = strpos($path, ';')) !== false)
  66          $path = substr($path, $pos+1);
  67        return $path;
  68      }
  69  
  70      if($tmp = getenv('TMP') || $tmp = getenv('TEMP') || $tmp = getenv('TMPDIR'))
  71        return $tmp;
  72  
  73      //gracefull falback?

  74      return '/tmp';
  75    }
  76  
  77    static function generateTmpFile($prefix = 'p')
  78    {
  79      return tempnam(self :: getTmpDir(), $prefix);
  80    }
  81  
  82    /**

  83     * @deprecated

  84     */
  85    static function generateTempFile($prefix = 'p')
  86    {
  87      return self :: generateTmpFile($prefix);
  88    }
  89  
  90    static function dirpath($path)
  91    {
  92      $path = self :: normalizePath($path);
  93  
  94     if(($dir_pos = strrpos($path, self :: separator())) !== false )
  95        return substr($path, 0, $dir_pos);
  96  
  97      return $path;
  98    }
  99  
 100    /**

 101    * Creates the directory $dir with permissions $perm.

 102    * If $parents is true it will create any missing parent directories,

 103    * just like 'mkdir -p'.

 104    */
 105    static function mkdir($dir, $perm=0777, $parents=true)
 106    {
 107      if(is_dir($dir))
 108        return;
 109  
 110      $dir = self :: normalizePath($dir);
 111  
 112      if(!$parents)
 113      {
 114        self :: _doMkdir($dir, $perm);
 115        return;
 116      }
 117  
 118      $separator = self :: separator();
 119      $path_elements = self :: explodePath($dir);
 120  
 121      if(count($path_elements) == 0)
 122        return;
 123  
 124      $index = self :: _getFirstExistingPathIndex($path_elements, $separator);
 125  
 126      if($index === false)
 127      {
 128        throw new lmbFsException('cant find first existent path', array('dir' => $dir));
 129      }
 130  
 131      $offset_path = '';
 132      for($i=0; $i < $index; $i++)
 133      {
 134        $offset_path .= $path_elements[$i] . $separator;
 135      }
 136  
 137      for($i=$index; $i < count($path_elements); $i++)
 138      {
 139        $offset_path .= $path_elements[$i] . $separator;
 140        self :: _doMkdir($offset_path, $perm);
 141      }
 142    }
 143  
 144    protected static function _getFirstExistingPathIndex($path_elements, $separator)
 145    {
 146      for($i=count($path_elements); $i > 0; $i--)
 147      {
 148        $path = implode($separator, $path_elements);
 149  
 150        if(is_dir($path))
 151          return $i;
 152  
 153        array_pop($path_elements);
 154      }
 155  
 156      if(self :: isPathAbsolute($path))
 157        return false;
 158      else
 159        return 0;
 160    }
 161  
 162    /**

 163    * Creates the directory $dir with permission $perm.

 164    */
 165    protected static function _doMkdir($dir, $perm)
 166    {
 167      if(is_dir($dir))
 168        return;
 169  
 170      if(self :: _hasWin32NetPrefix($dir))
 171        return;
 172  
 173      $oldumask = umask(0);
 174      if(!mkdir($dir, $perm))
 175      {
 176        umask($oldumask);
 177        throw new lmbFsException('failed to create directory', array('dir' => $dir));
 178      }
 179  
 180      umask($oldumask);
 181    }
 182  
 183    static function explodePath($path, $fs_type = self :: UNIX)
 184    {
 185      $path = self :: normalizePath($path, $fs_type);
 186      $separator = self :: separator($fs_type);
 187  
 188      $dir_elements = explode($separator, $path);
 189  
 190      if(sizeof($dir_elements) > 1 &&  $dir_elements[sizeof($dir_elements)-1] === '')
 191        array_pop($dir_elements);
 192  
 193      if(self :: _hasWin32NetPrefix($path))
 194      {
 195        array_shift($dir_elements);
 196        array_shift($dir_elements);
 197        $dir_elements[0] = self :: WIN32_NET_PREFIX . $dir_elements[0];
 198      }
 199      return $dir_elements;
 200    }
 201  
 202    static function joinPath($arr, $fs_type = self :: UNIX)
 203    {
 204      return implode(self :: separator($fs_type), $arr);
 205    }
 206  
 207    static function chop($path)
 208    {
 209      if(substr($path, -1) == '/' || substr($path, -1) == '\\')
 210        $path = substr($path, 0, -1);
 211  
 212      return $path;
 213    }
 214  
 215    static function rm($file)
 216    {
 217      if(!file_exists($file))
 218        return false;
 219  
 220      self :: _doRm(self :: normalizePath($file), self :: separator());
 221      clearstatcache();
 222  
 223      return true;
 224    }
 225  
 226    protected static function _doRm($item, $separator)
 227    {
 228      if(!is_dir($item))
 229      {
 230        if(!@unlink($item))
 231          throw new lmbFsException('failed to remove file', array('file' => $item));
 232        return;
 233      }
 234  
 235      if(!$handle = @opendir($item))
 236        throw new lmbFsException('failed to open directory', array('dir' => $item));
 237  
 238      while(($file = readdir($handle)) !== false)
 239      {
 240        if($file == '.' ||  $file == '..')
 241          continue;
 242  
 243        self :: _doRm($item . $separator . $file, $separator);
 244      }
 245  
 246      closedir($handle);
 247  
 248      if(!@rmdir($item))
 249        throw new lmbFsException('failed to remove directory', array('dir' => $item));
 250    }
 251  
 252    static function mv($src, $dest)
 253    {
 254      if(is_dir($src) || is_file($src))
 255      {
 256        if(!@rename($src, $dest))
 257          throw new lmbFsException('failed to move item', array('src' => $src, 'dest' => $dest));
 258  
 259        clearstatcache();
 260      }
 261      else
 262        throw new lmbFsException('source file or directory does not exist', array('src' => $src));
 263    }
 264  
 265    static function cp($src, $dest, $exclude_regex = '', $include_regex = '', $as_child = false, $include_hidden = true)
 266    {
 267      if(!is_dir($src))
 268      {
 269        if(!is_dir($dest))
 270          self :: mkdir(dirname($dest));
 271        else
 272          $dest = $dest . '/' . basename($src);
 273  
 274        if(@copy($src, $dest) === false)
 275          throw new lmbFsException('failed to copy file', array('src' => $src, 'dest' => $dest));
 276        return;
 277      }
 278  
 279      self :: mkdir($dest);
 280  
 281      $src = self :: normalizePath($src);
 282      $dest = self :: normalizePath($dest);
 283      $separator = self :: separator();
 284  
 285      if($as_child)
 286      {
 287        $separator_regex = preg_quote($separator);
 288        if(preg_match( "#^.+{$separator_regex}([^{$separator_regex}]+)$#", $src, $matches))
 289        {
 290          self :: _doMkdir($dest . $separator . $matches[1], 0777);
 291          $dest .= $separator . $matches[1];
 292        }
 293        else
 294          return false;
 295      }
 296      $items = self :: find($src, 'df', $include_regex, $exclude_regex, false, $include_hidden);
 297  
 298      $total_items = $items;
 299      while(count($items) > 0)
 300      {
 301        $current_items = $items;
 302        $items = array();
 303        foreach($current_items as $item)
 304        {
 305          $full_path = $src . $separator . $item;
 306          if(is_file( $full_path))
 307            copy($full_path, $dest . $separator . $item);
 308          elseif(is_dir( $full_path))
 309          {
 310            self :: _doMkdir($dest . $separator . $item, 0777);
 311  
 312            $new_items = self :: find($full_path, 'df', $include_regex, $exclude_regex, $item, $include_hidden);
 313  
 314            $items = array_merge($items, $new_items);
 315            $total_items = array_merge($total_items, $new_items);
 316  
 317           unset($new_items);
 318          }
 319        }
 320      }
 321      if($total_items)
 322        clearstatcache();
 323  
 324      return $total_items;
 325    }
 326  
 327    static function ls($path)
 328    {
 329      if(!is_dir($path))
 330        return array();
 331  
 332      $files = array();
 333      $path = self :: normalizePath($path);
 334      if($handle = opendir($path))
 335      {
 336        while(($file = readdir($handle)) !== false)
 337        {
 338          if($file != '.' &&  $file != '..' )
 339          {
 340            $files[] = $file;
 341          }
 342        }
 343        closedir($handle);
 344      }
 345      return $files;
 346    }
 347  
 348    /**

 349    * Return the separator used between directories and files according to $type.

 350    */
 351    static function separator($type = lmbFs :: UNIX)
 352    {
 353      switch(self :: _concreteSeparatorType($type))
 354      {
 355        case self :: UNIX:
 356          return '/';
 357        case self :: DOS:
 358          return "\\";
 359      }
 360    }
 361  
 362    protected static function _concreteSeparatorType($type)
 363    {
 364      if($type == self :: LOCAL)
 365      {
 366        if(lmbSys :: isWin32())
 367          $type = self :: DOS;
 368        else
 369          $type = lmbFs :: UNIX;
 370      }
 371      return $type;
 372    }
 373  
 374    /**

 375    * Converts any directory separators found in $path, in both unix and dos style, into

 376    * the separator type specified by $to_type and returns it.

 377    */
 378    static function convertSeparators($path, $to_type = self :: UNIX)
 379    {
 380      $separator = self :: separator($to_type);
 381      return preg_replace("#[/\\\\]#", $separator, $path);
 382    }
 383  
 384    /**

 385    * Removes all unneeded directory separators and resolves any "."s and ".."s found in $path.

 386    *

 387    * For instance: "var/../lib/db" becomes "lib/db", while "../site/var" will not be changed.

 388    * Will also convert separators

 389    */
 390    static function normalizePath($path, $to_type = self :: UNIX)
 391    {
 392      $path = self :: convertSeparators($path, $to_type);
 393      $separator = self :: separator($to_type);
 394  
 395      $path = self :: _normalizeSeparators($path, $separator);
 396  
 397      $path_elements= explode($separator, $path);
 398      $newpath_elements= array();
 399  
 400      foreach($path_elements as $path_element)
 401      {
 402        if($path_element == '.')
 403          continue;
 404        if($path_element == '..' &&
 405            count($newpath_elements) > 0)
 406          array_pop($newpath_elements);
 407        else
 408          $newpath_elements[] = $path_element;
 409      }
 410      if(count( $newpath_elements) == 0)
 411        $newpath_elements[] = '.';
 412  
 413      $path = implode($separator, $newpath_elements);
 414      return rtrim($path, '/\\');
 415    }
 416  
 417    static function isPathRelative($path, $fs_type = self :: LOCAL)
 418    {
 419      return !self :: isPathAbsolute($path, $os_type);
 420    }
 421  
 422    static function isPathAbsolute($path, $fs_type = self :: LOCAL)
 423    {
 424      switch(self :: _concreteSeparatorType($fs_type))
 425      {
 426        case self :: UNIX:
 427          return $path{0} == '/';
 428        case self :: DOS:
 429          return $path{0} == '/' ||
 430                 $path{0} == "\\" ||
 431                 preg_match('~^[a-zA-Z]+:~', $path);
 432      }
 433    }
 434  
 435    protected static function _normalizeSeparators($path, $separator)
 436    {
 437      $quoted = preg_quote($separator);
 438      $clean_path = preg_replace( "~$quoted$quoted+~", $separator, $path);
 439  
 440      if(self :: _hasWin32NetPrefix($path))
 441        $clean_path = '\\' . $clean_path;
 442  
 443      return $clean_path;
 444    }
 445  
 446    protected static function _hasWin32NetPrefix($path)//ugly!!!
 447    {
 448      if(lmbSys :: isWin32() &&  strlen($path) > 2)
 449      {
 450        return (substr($path, 0, 2) == self :: WIN32_NET_PREFIX);
 451      }
 452      return false;
 453    }
 454  
 455    static function path($names, $include_end_separator=false, $type = self :: UNIX)
 456    {
 457      $separator = self :: separator($type);
 458      $path = implode($separator, $names);
 459      $path = self :: normalizePath($path, $type);
 460  
 461      $has_end_separator = (strlen($path) > 0 &&  $path[strlen($path) - 1] == $separator);
 462  
 463     if($include_end_separator &&  !$has_end_separator)
 464        $path .= $separator;
 465      elseif (!$include_end_separator &&  $has_end_separator)
 466        $path = substr($path, 0, strlen($path) - 1);
 467  
 468      return $path;
 469    }
 470  
 471    static function find($dir, $types = 'dfl', $include_regex = '', $exclude_regex = '', $add_path = true, $include_hidden = false)
 472    {
 473      $dir = self :: normalizePath($dir);
 474      $dir = self :: chop($dir);
 475  
 476      $items = array();
 477  
 478      $separator = self :: separator();
 479  
 480      if($handle = @opendir($dir))
 481      {
 482        while(($element = readdir($handle)) !== false)
 483        {
 484          if($element == '.' || $element == '..')
 485           continue;
 486          if(!$include_hidden && $element[0] == '.')
 487           continue;
 488          if($include_regex && !preg_match($include_regex, $element, $m))
 489           continue;
 490          if($exclude_regex && preg_match(