Support Joomla!

Packages

Package: Joomla-Framework

License

Content on this site is copyright © 2005 - 2008 Open Source Matters Inc and can be used in accordance with the Joomla! Electronic Documentation License. Some parts of this website may be subject to other licenses.
Source code for file /joomla/filesystem/folder.php

Documentation is available at folder.php

  1. <?php
  2. /**
  3.  * @version        $Id: folder.php 11675 2009-03-08 20:43:54Z willebil $
  4.  * @package        Joomla.Framework
  5.  * @subpackage    FileSystem
  6.  * @copyright    Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
  7.  * @license        GNU/GPL, see LICENSE.php
  8.  *  Joomla! is free software. This version may have been modified pursuant
  9.  *  to the GNU General Public License, and as distributed it includes or
  10.  *  is derivative of works licensed under the GNU General Public License or
  11.  *  other free or open source software licenses.
  12.  *  See COPYRIGHT.php for copyright notices and details.
  13.  */
  14.  
  15. // Check to ensure this file is within the rest of the framework
  16. defined('JPATH_BASE'or die();
  17.  
  18. jimport('joomla.filesystem.path');
  19.  
  20. /**
  21.  * A Folder handling class
  22.  *
  23.  * @static
  24.  * @package     Joomla.Framework
  25.  * @subpackage    FileSystem
  26.  * @since        1.5
  27.  */
  28. class JFolder
  29. {
  30.     /**
  31.      * Copy a folder.
  32.      *
  33.      * @param    string    The path to the source folder.
  34.      * @param    string    The path to the destination folder.
  35.      * @param    string    An optional base path to prefix to the file names.
  36.      * @param    boolean    Optionally force folder/file overwrites.
  37.      * @return    mixed    JError object on failure or boolean True on success.
  38.      * @since    1.5
  39.      */
  40.     function copy($src$dest$path ''$force false)
  41.     {
  42.         // Initialize variables
  43.         jimport('joomla.client.helper');
  44.         $ftpOptions JClientHelper::getCredentials('ftp');
  45.  
  46.         if ($path{
  47.             $src JPath::clean($path DS $src);
  48.             $dest JPath::clean($path DS $dest);
  49.         }
  50.  
  51.         // Eliminate trailing directory separators, if any
  52.         $src rtrim($srcDS);
  53.         $dest rtrim($destDS);
  54.  
  55.         if (!JFolder::exists($src)) {
  56.             return JError::raiseError(-1JText::_('Cannot find source folder'));
  57.         }
  58.         if (JFolder::exists($dest&& !$force{
  59.             return JError::raiseError(-1JText::_('Folder already exists'));
  60.         }
  61.  
  62.         // Make sure the destination exists
  63.         if (JFolder::create($dest)) {
  64.             return JError::raiseError(-1JText::_('Unable to create target folder'));
  65.         }
  66.  
  67.         if ($ftpOptions['enabled'== 1)
  68.         {
  69.             // Connect the FTP client
  70.             jimport('joomla.client.ftp');
  71.             $ftp &JFTP::getInstance(
  72.                 $ftpOptions['host']$ftpOptions['port']null,
  73.                 $ftpOptions['user']$ftpOptions['pass']
  74.             );
  75.  
  76.             if (!($dh @opendir($src))) {
  77.                 return JError::raiseError(-1JText::_('Unable to open source folder'));
  78.             }
  79.             // Walk through the directory copying files and recursing into folders.
  80.             while (($file readdir($dh)) !== false{
  81.                 $sfid $src DS $file;
  82.                 $dfid $dest DS $file;
  83.                 switch (filetype($sfid)) {
  84.                     case 'dir':
  85.                         if ($file != '.' && $file != '..'{
  86.                             $ret JFolder::copy($sfid$dfidnull$force);
  87.                             if ($ret !== true{
  88.                                 return $ret;
  89.                             }
  90.                         }
  91.                         break;
  92.  
  93.                     case 'file':
  94.                         // Translate path for the FTP account
  95.                         $dfid JPath::clean(str_replace(JPATH_ROOT$ftpOptions['root']$dfid)'/');
  96.                         if ($ftp->store($sfid$dfid)) {
  97.                             return JError::raiseError(-1JText::_('Copy failed'));
  98.                         }
  99.                         break;
  100.                 }
  101.             }
  102.         else {
  103.             if (!($dh @opendir($src))) {
  104.                 return JError::raiseError(-1JText::_('Unable to open source folder'));
  105.             }
  106.             // Walk through the directory copying files and recursing into folders.
  107.             while (($file readdir($dh)) !== false{
  108.                 $sfid $src DS $file;
  109.                 $dfid $dest DS $file;
  110.                 switch (filetype($sfid)) {
  111.                     case 'dir':
  112.                         if ($file != '.' && $file != '..'{
  113.                             $ret JFolder::copy($sfid$dfidnull$force);
  114.                             if ($ret !== true{
  115.                                 return $ret;
  116.                             }
  117.                         }
  118.                         break;
  119.  
  120.                     case 'file':
  121.                         if (!@copy($sfid$dfid)) {
  122.                             return JError::raiseError(-1JText::_('Copy failed'));
  123.                         }
  124.                         break;
  125.                 }
  126.             }
  127.         }
  128.         return true;
  129.     }
  130.  
  131.     /**
  132.      * Create a folder -- and all necessary parent folders.
  133.      *
  134.      * @param string A path to create from the base path.
  135.      * @param int Directory permissions to set for folders created.
  136.      * @return boolean True if successful.
  137.      * @since 1.5
  138.      */
  139.     function create($path ''$mode 0755)
  140.     {
  141.         // Initialize variables
  142.         jimport('joomla.client.helper');
  143.         $ftpOptions JClientHelper::getCredentials('ftp');
  144.         static $nested 0;
  145.  
  146.         // Check to make sure the path valid and clean
  147.                 $path JPath::clean($path);
  148.  
  149.         // Check if parent dir exists
  150.                 $parent dirname($path);
  151.         if (!JFolder::exists($parent)) {
  152.             // Prevent infinite loops!
  153.                         $nested++;
  154.             if (($nested 20|| ($parent == $path)) {
  155.                 JError::raiseWarning(
  156.                     'SOME_ERROR_CODE',
  157.                     'JFolder::create: ' JText::_('Infinite loop detected')
  158.                 );
  159.                 $nested--;
  160.                 return false;
  161.             }
  162.  
  163.             // Create the parent directory
  164.             if (JFolder::create($parent$mode!== true{
  165.                 // JFolder::create throws an error
  166.                 $nested--;
  167.                 return false;
  168.             }
  169.  
  170.             // OK, parent directory has been created
  171.             $nested--;
  172.         }
  173.  
  174.         // Check if dir already exists
  175.                 if (JFolder::exists($path)) {
  176.             return true;
  177.         }
  178.  
  179.         // Check for safe mode
  180.                 if ($ftpOptions['enabled'== 1{
  181.             // Connect the FTP client
  182.                         jimport('joomla.client.ftp');
  183.             $ftp &JFTP::getInstance(
  184.                 $ftpOptions['host']$ftpOptions['port']null,
  185.                 $ftpOptions['user']$ftpOptions['pass']
  186.             );
  187.  
  188.             // Translate path to FTP path
  189.                         $path JPath::clean(str_replace(JPATH_ROOT$ftpOptions['root']$path)'/');
  190.             $ret $ftp->mkdir($path);
  191.             $ftp->chmod($path$mode);
  192.         else {
  193.             // We need to get and explode the open_basedir paths
  194.                         $obd ini_get('open_basedir');
  195.  
  196.             // If open_basedir is set we need to get the open_basedir that the path is in
  197.                         if ($obd != null)
  198.             {
  199.                 if (JPATH_ISWIN{
  200.                     $obdSeparator ";";
  201.                 else {
  202.                     $obdSeparator ":";
  203.                 }
  204.                 // Create the array of open_basedir paths
  205.                                 $obdArray explode($obdSeparator$obd);
  206.                 $inBaseDir false;
  207.                 // Iterate through open_basedir paths looking for a match
  208.                                 foreach ($obdArray as $test{
  209.                     $test JPath::clean($test);
  210.                     if (strpos($path$test=== 0{
  211.                         $obdpath $test;
  212.                         $inBaseDir true;
  213.                         break;
  214.                     }
  215.                 }
  216.                 if ($inBaseDir == false{
  217.                     // Return false for JFolder::create because the path to be created is not in open_basedir
  218.                                         JError::raiseWarning(
  219.                         'SOME_ERROR_CODE',
  220.                         'JFolder::create: ' JText::_('Path not in open_basedir paths')
  221.                     );
  222.                     return false;
  223.                 }
  224.             }
  225.  
  226.             // First set umask
  227.                         $origmask @umask(0);
  228.  
  229.             // Create the path
  230.                         if (!$ret @mkdir($path$mode)) {
  231.                 @umask($origmask);
  232.                 JError::raiseWarning(
  233.                     'SOME_ERROR_CODE',
  234.                     'JFolder::create: ' JText::_('Could not create directory'),
  235.                     'Path: ' $path
  236.                 );
  237.                 return false;
  238.             }
  239.  
  240.             // Reset umask
  241.                         @umask($origmask);
  242.         }
  243.         return $ret;
  244.     }
  245.  
  246.     /**
  247.      * Delete a folder.
  248.      *
  249.      * @param string The path to the folder to delete.
  250.      * @return boolean True on success.
  251.      * @since 1.5
  252.      */
  253.     function delete($path)
  254.     {
  255.         // Sanity check
  256.         if (!$path{
  257.             // Bad programmer! Bad Bad programmer!
  258.             JError::raiseWarning(500'JFolder::delete: ' JText::_('Attempt to delete base directory') );
  259.             return false;
  260.         }
  261.  
  262.         // Initialize variables
  263.         jimport('joomla.client.helper');
  264.         $ftpOptions JClientHelper::getCredentials('ftp');
  265.  
  266.         // Check to make sure the path valid and clean
  267.         $path JPath::clean($path);
  268.  
  269.         // Is this really a folder?
  270.         if (!is_dir($path)) {
  271.             JError::raiseWarning(21'JFolder::delete: ' JText::_('Path is not a folder')'Path: ' $path);
  272.             return false;
  273.         }
  274.  
  275.         // Remove all the files in folder if they exist
  276.         $files JFolder::files($path'.'falsetruearray());
  277.         if (!empty($files)) {
  278.             jimport('joomla.filesystem.file');
  279.             if (JFile::delete($files!== true{
  280.                 // JFile::delete throws an error
  281.                 return false;
  282.             }
  283.         }
  284.  
  285.         // Remove sub-folders of folder
  286.         $folders JFolder::folders($path'.'falsetruearray());
  287.         foreach ($folders as $folder{
  288.             if (is_link($folder)) {
  289.                 // Don't descend into linked directories, just delete the link.
  290.                 jimport('joomla.filesystem.file');
  291.                 if (JFile::delete($folder!== true{
  292.                     // JFile::delete throws an error
  293.                     return false;
  294.                 }
  295.             elseif (JFolder::delete($folder!== true{
  296.                 // JFolder::delete throws an error
  297.                 return false;
  298.             }
  299.         }
  300.  
  301.         if ($ftpOptions['enabled'== 1{
  302.             // Connect the FTP client
  303.             jimport('joomla.client.ftp');
  304.             $ftp &JFTP::getInstance(
  305.                 $ftpOptions['host']$ftpOptions['port']null,
  306.                 $ftpOptions['user']$ftpOptions['pass']
  307.             );
  308.         }
  309.  
  310.         // In case of restricted permissions we zap it one way or the other
  311.         // as long as the owner is either the webserver or the ftp
  312.         if (@rmdir($path)) {
  313.             $ret true;
  314.         elseif ($ftpOptions['enabled'== 1{
  315.             // Translate path and delete
  316.             $path JPath::clean(str_replace(JPATH_ROOT$ftpOptions['root']$path)'/');
  317.             // FTP connector throws an error
  318.             $ret $ftp->delete($path);
  319.         else {
  320.             JError::raiseWarning(
  321.                 'SOME_ERROR_CODE',
  322.                 'JFolder::delete: ' JText::_('Could not delete folder'),
  323.                 'Path: ' $path
  324.             );
  325.             $ret false;
  326.         }
  327.         return $ret;
  328.     }
  329.  
  330.     /**
  331.      * Moves a folder.
  332.      *
  333.      * @param string The path to the source folder.
  334.      * @param string The path to the destination folder.
  335.      * @param string An optional base path to prefix to the file names.
  336.      * @return mixed Error message on false or boolean true on success.
  337.      * @since 1.5
  338.      */
  339.     function move($src$dest$path '')
  340.     {
  341.         // Initialize variables
  342.         jimport('joomla.client.helper');
  343.         $ftpOptions JClientHelper::getCredentials('ftp');
  344.  
  345.         if ($path{
  346.             $src JPath::clean($path DS $src);
  347.             $dest JPath::clean($path DS $dest);
  348.         }
  349.  
  350.         if (!JFolder::exists($src&& !is_writable($src)) {
  351.             return JText::_('Cannot find source folder');
  352.         }
  353.         if (JFolder::exists($dest)) {
  354.             return JText::_('Folder already exists');
  355.         }
  356.  
  357.         if ($ftpOptions['enabled'== 1{
  358.             // Connect the FTP client
  359.             jimport('joomla.client.ftp');
  360.             $ftp &JFTP::getInstance(
  361.                 $ftpOptions['host']$ftpOptions['port']null,
  362.                 $ftpOptions['user']$ftpOptions['pass']
  363.             );
  364.  
  365.             //Translate path for the FTP account
  366.             $src JPath::clean(str_replace(JPATH_ROOT$ftpOptions['root']$src)'/');
  367.             $dest JPath::clean(str_replace(JPATH_ROOT$ftpOptions['root']$dest)'/');
  368.  
  369.             // Use FTP rename to simulate move
  370.             if (!$ftp->rename($src$dest)) {
  371.                 return JText::_('Rename failed');
  372.             }
  373.             $ret true;
  374.         else {
  375.             if (!@rename($src$dest)) {
  376.                 return JText::_('Rename failed');
  377.             }
  378.             $ret true;
  379.         }
  380.         return $ret;
  381.     }
  382.  
  383.     /**
  384.      * Wrapper for the standard file_exists function
  385.      *
  386.      * @param string Folder name relative to installation dir
  387.      * @return boolean True if path is a folder
  388.      * @since 1.5
  389.      */
  390.     function exists($path)
  391.     {
  392.         return is_dir(JPath::clean($path));
  393.     }
  394.  
  395.     /**
  396.      * Utility function to read the files in a folder.
  397.      *
  398.      * @param    string    The path of the folder to read.
  399.      * @param    string    A filter for file names.
  400.      * @param    mixed    True to recursively search into sub-folders, or an
  401.      *  integer to specify the maximum depth.
  402.      * @param    boolean    True to return the full path to the file.
  403.      * @param    array    Array with names of files which should not be shown in
  404.      *  the result.
  405.      * @return    array    Files in the given folder.
  406.      * @since 1.5
  407.      */
  408.     function files($path$filter '.'$recurse false$fullpath false$exclude array('.svn''CVS'))
  409.     {
  410.         // Initialize variables
  411.         $arr array();
  412.  
  413.         // Check to make sure the path valid and clean
  414.         $path JPath::clean($path);
  415.  
  416.         // Is the path a folder?
  417.         if (!is_dir($path)) {
  418.             JError::raiseWarning(21'JFolder::files: ' JText::_('Path is not a folder')'Path: ' $path);
  419.             return false;
  420.         }
  421.  
  422.         // read the source directory
  423.         $handle opendir($path);
  424.         while (($file readdir($handle)) !== false)
  425.         {
  426.             if (($file != '.'&& ($file != '..'&& (!in_array($file$exclude))) {
  427.                 $dir $path DS $file;
  428.                 $isDir is_dir($dir);
  429.                 if ($isDir{
  430.                     if ($recurse{
  431.                         if (is_integer($recurse)) {
  432.                             $arr2 JFolder::files($dir$filter$recurse 1$fullpath);
  433.                         else {
  434.                             $arr2 JFolder::files($dir$filter$recurse$fullpath);
  435.                         }
  436.                         
  437.                         $arr array_merge($arr$arr2);
  438.                     }
  439.                 else {
  440.                     if (preg_match("/$filter/"$file)) {
  441.                         if ($fullpath{
  442.                             $arr[$path DS $file;
  443.                         else {
  444.                             $arr[$file;
  445.                         }
  446.                     }
  447.                 }
  448.             }
  449.         }
  450.         closedir($handle);
  451.  
  452.         asort($arr);
  453.         return $arr;
  454.     }
  455.  
  456.     /**
  457.      * Utility function to read the folders in a folder.
  458.      *
  459.      * @param    string    The path of the folder to read.
  460.      * @param    string    A filter for folder names.
  461.      * @param    mixed    True to recursively search into sub-folders, or an
  462.      *  integer to specify the maximum depth.
  463.      * @param    boolean    True to return the full path to the folders.
  464.      * @param    array    Array with names of folders which should not be shown in
  465.      *  the result.
  466.      * @return    array    Folders in the given folder.
  467.      * @since 1.5
  468.      */
  469.     function folders($path$filter '.'$recurse false$fullpath false$exclude array('.svn''CVS'))
  470.     {
  471.         // Initialize variables
  472.         $arr array();
  473.  
  474.         // Check to make sure the path valid and clean
  475.         $path JPath::clean($path);
  476.  
  477.         // Is the path a folder?
  478.         if (!is_dir($path)) {
  479.             JError::raiseWarning(21'JFolder::folder: ' JText::_('Path is not a folder')'Path: ' $path);
  480.             return false;
  481.         }
  482.  
  483.         // read the source directory
  484.         $handle opendir($path);
  485.         while (($file readdir($handle)) !== false)
  486.         {
  487.             if (($file != '.'&& ($file != '..'&& (!in_array($file$exclude))) {
  488.                 $dir $path DS $file;
  489.                 $isDir is_dir($dir);
  490.                 if ($isDir{
  491.                     // Removes filtered directories
  492.                     if (preg_match("/$filter/"$file)) {
  493.                         if ($fullpath{
  494.                             $arr[$dir;
  495.                         else {
  496.                             $arr[$file;
  497.                         }
  498.                     }
  499.                     if ($recurse{
  500.                         if (is_integer($recurse)) {
  501.                             $arr2 JFolder::folders($dir$filter$recurse 1$fullpath);
  502.                         else {
  503.                             $arr2 JFolder::folders($dir$filter$recurse$fullpath);
  504.                         }
  505.                         
  506.                         $arr array_merge($arr$arr2);
  507.                     }
  508.                 }
  509.             }
  510.         }
  511.         closedir($handle);
  512.  
  513.         asort($arr);
  514.         return $arr;
  515.     }
  516.  
  517.     /**
  518.      * Lists folder in format suitable for tree display.
  519.      *
  520.      * @access    public
  521.      * @param    string    The path of the folder to read.
  522.      * @param    string    A filter for folder names.
  523.      * @param    integer    The maximum number of levels to recursively read,
  524.      *  defaults to three.
  525.      * @param    integer    The current level, optional.
  526.      * @param    integer    Unique identifier of the parent folder, if any.
  527.      * @return    array    Folders in the given folder.
  528.      * @since    1.5
  529.      */
  530.     function listFolderTree($path$filter$maxLevel 3$level 0$parent 0)
  531.     {
  532.         $dirs array ();
  533.         if ($level == 0{
  534.             $GLOBALS['_JFolder_folder_tree_index'0;
  535.         }
  536.         if ($level $maxLevel{
  537.             $folders JFolder::folders($path$filter);
  538.             // first path, index foldernames
  539.             foreach ($folders as $name{
  540.                 $id = ++$GLOBALS['_JFolder_folder_tree_index'];
  541.                 $fullName JPath::clean($path DS $name);
  542.                 $dirs[array(
  543.                     'id' => $id,
  544.                     'parent' => $parent,
  545.                     'name' => $name,
  546.                     'fullname' => $fullName,
  547.                     'relname' => str_replace(JPATH_ROOT''$fullName)
  548.                 );
  549.                 $dirs2 JFolder::listFolderTree($fullName$filter$maxLevel$level 1$id);
  550.                 $dirs array_merge($dirs$dirs2);
  551.             }
  552.         }
  553.         return $dirs;
  554.     }
  555.  
  556.     /**
  557.      * Makes path name safe to use.
  558.      *
  559.      * @access    public
  560.      * @param    string The full path to sanitise.
  561.      * @return    string The sanitised string.
  562.      * @since    1.5
  563.      */
  564.     function makeSafe($path)
  565.     {
  566.         $ds (DS == '\\''\\' DS DS;
  567.         $regex array('#[^A-Za-z0-9:\_\-' $ds ' ]#');
  568.         return preg_replace($regex''$path);
  569.     }
  570.  
  571. }

Documentation generated on Sat, 14 Nov 2009 11:13:09 +0000 by phpDocumentor 1.3.1