Ftp.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2006, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * FTP Class
00020  *
00021  * @package             CodeIgniter
00022  * @subpackage  Libraries
00023  * @category    Libraries
00024  * @author              ExpressionEngine Dev Team
00025  * @link                http://codeigniter.com/user_guide/libraries/ftp.html
00026  */ 
00027 class CI_FTP {
00028 
00029         var $hostname   = '';
00030         var $username   = '';
00031         var $password   = '';
00032         var $port               = 21;
00033         var $passive    = TRUE;
00034         var $debug              = FALSE;
00035         var $conn_id    = FALSE;
00036 
00037 
00038         /**
00039          * Constructor - Sets Preferences
00040          *
00041          * The constructor can be passed an array of config values
00042          */     
00043         function CI_FTP($config = array())
00044         {               
00045                 if (count($config) > 0)
00046                 {
00047                         $this->initialize($config);
00048                 }       
00049 
00050                 log_message('debug', "FTP Class Initialized");
00051         }
00052 
00053         // --------------------------------------------------------------------
00054 
00055         /**
00056          * Initialize preferences
00057          *
00058          * @access      public
00059          * @param       array
00060          * @return      void
00061          */     
00062         function initialize($config = array())
00063         {
00064                 foreach ($config as $key => $val)
00065                 {
00066                         if (isset($this->$key))
00067                         {
00068                                 $this->$key = $val;
00069                         }
00070                 }
00071                 
00072                 // Prep the hostname
00073                 $this->hostname = preg_replace('|.+?://|', '', $this->hostname);
00074         }
00075 
00076         // --------------------------------------------------------------------
00077 
00078         /**
00079          * FTP Connect
00080          *
00081          * @access      public
00082          * @param       array    the connection values
00083          * @return      bool
00084          */     
00085         function connect($config = array())
00086         {               
00087                 if (count($config) > 0)
00088                 {
00089                         $this->initialize($config);
00090                 }       
00091         
00092                 if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
00093                 {
00094                         if ($this->debug == TRUE)
00095                         {
00096                                 $this->_error('ftp_unable_to_connect');
00097                         }               
00098                         return FALSE;
00099                 }
00100                 
00101                 if ( ! $this->_login())
00102                 {
00103                         if ($this->debug == TRUE)
00104                         {
00105                                 $this->_error('ftp_unable_to_login');
00106                         }               
00107                         return FALSE;
00108                 }
00109                 
00110                 // Set passive mode if needed
00111                 if ($this->passive == TRUE)
00112                 {
00113                         ftp_pasv($this->conn_id, TRUE);
00114                 }
00115                 
00116                 return TRUE;
00117         }
00118 
00119         // --------------------------------------------------------------------
00120 
00121         /**
00122          * FTP Login
00123          *
00124          * @access      private
00125          * @return      bool
00126          */     
00127         function _login()
00128         {
00129                 return @ftp_login($this->conn_id, $this->username, $this->password);
00130         }
00131 
00132         // --------------------------------------------------------------------
00133 
00134         /**
00135          * Validates the connection ID
00136          *
00137          * @access      private
00138          * @return      bool
00139          */     
00140         function _is_conn()
00141         {
00142                 if ( ! is_resource($this->conn_id))
00143                 {
00144                         if ($this->debug == TRUE)
00145                         {
00146                                 $this->_error('ftp_no_connection');
00147                         }               
00148                         return FALSE;
00149                 }
00150                 return TRUE;
00151         }
00152 
00153         // --------------------------------------------------------------------
00154 
00155 
00156         /**
00157          * Change direcotry
00158          *
00159          * The second parameter lets us momentarily turn off debugging so that
00160          * this function can be used to test for the existance of a folder
00161          * without throwing an error.  There's no FTP equivalent to is_dir()
00162          * so we do it by trying to change to a particular directory.  
00163          * Internally, this paramter is only used by the "mirror" function below.
00164          *
00165          * @access      public
00166          * @param       string
00167          * @param       bool
00168          * @return      bool
00169          */     
00170         function changedir($path = '', $supress_debug = FALSE)
00171         {
00172                 if ($path == '' OR ! $this->_is_conn())
00173                 {
00174                         return FALSE;
00175                 }
00176                 
00177                 $result = @ftp_chdir($this->conn_id, $path);
00178                 
00179                 if ($result === FALSE)
00180                 {
00181                         if ($this->debug == TRUE AND $supress_debug == FALSE)
00182                         {
00183                                 $this->_error('ftp_unable_to_changedir');
00184                         }               
00185                         return FALSE;           
00186                 }
00187                 
00188                 return TRUE;
00189         }
00190         
00191         // --------------------------------------------------------------------
00192 
00193         /**
00194          * Create a directory
00195          *
00196          * @access      public
00197          * @param       string
00198          * @return      bool
00199          */     
00200         function mkdir($path = '', $permissions = NULL)
00201         {
00202                 if ($path == '' OR ! $this->_is_conn())
00203                 {
00204                         return FALSE;
00205                 }
00206         
00207                 $result = @ftp_mkdir($this->conn_id, $path);
00208                 
00209                 if ($result === FALSE)
00210                 {
00211                         if ($this->debug == TRUE)
00212                         {
00213                                 $this->_error('ftp_unable_to_makdir');
00214                         }               
00215                         return FALSE;           
00216                 }
00217 
00218                 // Set file permissions if needed
00219                 if ( ! is_null($permissions))
00220                 {
00221                         $this->chmod($path, (int)$permissions);
00222                 }
00223                 
00224                 return TRUE;
00225         }
00226         
00227         // --------------------------------------------------------------------
00228 
00229         /**
00230          * Upload a file to the server
00231          *
00232          * @access      public
00233          * @param       string
00234          * @param       string
00235          * @param       string
00236          * @return      bool
00237          */     
00238         function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
00239         {
00240                 if ( ! $this->_is_conn())
00241                 {
00242                         return FALSE;
00243                 }
00244 
00245                 if ( ! file_exists($locpath))
00246                 {
00247                         $this->_error('ftp_no_source_file');
00248                         return FALSE;
00249                 }
00250         
00251                 // Set the mode if not specified
00252                 if ($mode == 'auto')
00253                 {
00254                         // Get the file extension so we can set the upload type
00255                         $ext = $this->_getext($locpath);
00256                         $mode = $this->_settype($ext);
00257                 }
00258                 
00259                 $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
00260                 
00261                 $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
00262                 
00263                 if ($result === FALSE)
00264                 {
00265                         if ($this->debug == TRUE)
00266                         {
00267                                 $this->_error('ftp_unable_to_upload');
00268                         }               
00269                         return FALSE;           
00270                 }
00271                 
00272                 // Set file permissions if needed
00273                 if ( ! is_null($permissions))
00274                 {
00275                         $this->chmod($rempath, (int)$permissions);
00276                 }
00277                 
00278                 return TRUE;
00279         }
00280 
00281         // --------------------------------------------------------------------
00282 
00283         /**
00284          * Rename (or move) a file
00285          *
00286          * @access      public
00287          * @param       string
00288          * @param       string
00289          * @param       bool
00290          * @return      bool
00291          */     
00292         function rename($old_file, $new_file, $move = FALSE)
00293         {
00294                 if ( ! $this->_is_conn())
00295                 {
00296                         return FALSE;
00297                 }
00298 
00299                 $result = @ftp_rename($this->conn_id, $old_file, $new_file);
00300                 
00301                 if ($result === FALSE)
00302                 {
00303                         if ($this->debug == TRUE)
00304                         {
00305                                 $msg = ($move == FALSE) ? 'ftp_unable_to_rename' : 'ftp_unable_to_move';
00306                                 
00307                                 $this->_error($msg);
00308                         }               
00309                         return FALSE;           
00310                 }
00311                 
00312                 return TRUE;
00313         }
00314         
00315         // --------------------------------------------------------------------
00316 
00317         /**
00318          * Move a file
00319          *
00320          * @access      public
00321          * @param       string
00322          * @param       string
00323          * @return      bool
00324          */     
00325         function move($old_file, $new_file)
00326         {
00327                 return $this->rename($old_file, $new_file, TRUE);
00328         }
00329 
00330         // --------------------------------------------------------------------
00331 
00332         /**
00333          * Rename (or move) a file
00334          *
00335          * @access      public
00336          * @param       string
00337          * @return      bool
00338          */     
00339         function delete_file($filepath)
00340         {
00341                 if ( ! $this->_is_conn())
00342                 {
00343                         return FALSE;
00344                 }
00345 
00346                 $result = @ftp_delete($this->conn_id, $filepath);
00347                 
00348                 if ($result === FALSE)
00349                 {
00350                         if ($this->debug == TRUE)
00351                         {                               
00352                                 $this->_error('ftp_unable_to_delete');
00353                         }               
00354                         return FALSE;           
00355                 }
00356                 
00357                 return TRUE;
00358         }
00359 
00360         // --------------------------------------------------------------------
00361 
00362         /**
00363          * Delete a folder and recursively delete everything (including sub-folders)
00364          * containted within it.
00365          *
00366          * @access      public
00367          * @param       string
00368          * @return      bool
00369          */     
00370         function delete_dir($filepath)
00371         {
00372                 if ( ! $this->_is_conn())
00373                 {
00374                         return FALSE;
00375                 }
00376 
00377                 // Add a trailing slash to the file path if needed
00378                 $filepath = preg_replace("/(.+?)\/*$/", "\\1/",  $filepath);
00379                 
00380                 $list = $this->list_files($filepath);
00381                 
00382                 if ($list !== FALSE)
00383                 {
00384                         foreach ($list as $item)
00385                         {                       
00386                                 // If we can't delete the item it's probaly a folder so
00387                                 // we'll recursively call delete_dir()
00388                                 if ( ! @ftp_delete($this->conn_id, $item))
00389                                 {
00390                                         $this->delete_dir($item);
00391                                 }
00392                         }
00393                 }
00394         
00395                 $result = @ftp_rmdir($this->conn_id, $filepath);
00396                 
00397                 if ($result === FALSE)
00398                 {
00399                         if ($this->debug == TRUE)
00400                         {                               
00401                                 $this->_error('ftp_unable_to_delete');
00402                         }               
00403                         return FALSE;           
00404                 }
00405                 
00406                 return TRUE;
00407         }
00408 
00409         // --------------------------------------------------------------------
00410 
00411         /**
00412          * Set file permissions
00413          *
00414          * @access      public
00415          * @param       string  the file path
00416          * @param       string  the permissions
00417          * @return      bool
00418          */             
00419         function chmod($path, $perm)
00420         {
00421                 if ( ! $this->_is_conn())
00422                 {
00423                         return FALSE;
00424                 }
00425 
00426                 // Permissions can only be set when running PHP 5
00427                 if ( ! function_exists('ftp_chmod'))
00428                 {
00429                         if ($this->debug == TRUE)
00430                         {
00431                                 $this->_error('ftp_unable_to_chmod');
00432                         }               
00433                         return FALSE;           
00434                 }
00435         
00436                 $result = @ftp_chmod($this->conn_id, $perm, $path);
00437                 
00438                 if ($result === FALSE)
00439                 {
00440                         if ($this->debug == TRUE)
00441                         {
00442                                 $this->_error('ftp_unable_to_chmod');
00443                         }               
00444                         return FALSE;           
00445                 }
00446                 
00447                 return TRUE;
00448         }
00449 
00450         // --------------------------------------------------------------------
00451 
00452         /**
00453          * FTP List files in the specified directory
00454          *
00455          * @access      public
00456          * @return      array
00457          */     
00458         function list_files($path = '.')
00459         {
00460                 if ( ! $this->_is_conn())
00461                 {
00462                         return FALSE;
00463                 }
00464 
00465                 return ftp_nlist($this->conn_id, $path);
00466         }
00467 
00468         // ------------------------------------------------------------------------
00469         
00470         /**
00471          * Read a directory and recreate it remotely
00472          *
00473          * This function recursively reads a folder and everything it contains (including
00474          * sub-folders) and creates a mirror via FTP based on it.  Whatever the directory structure
00475          * of the original file path will be recreated on the server.
00476          *
00477          * @access      public
00478          * @param       string  path to source with trailing slash
00479          * @param       string  path to destination - include the base folder with trailing slash
00480          * @return      bool
00481          */     
00482         function mirror($locpath, $rempath)
00483         {
00484                 if ( ! $this->_is_conn())
00485                 {
00486                         return FALSE;
00487                 }
00488 
00489                 // Open the local file path
00490                 if ($fp = @opendir($locpath))
00491                 {
00492                         // Attempt to open the remote file path.
00493                         if ( ! $this->changedir($rempath, TRUE))
00494                         {
00495                                 // If it doesn't exist we'll attempt to create the direcotory
00496                                 if ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))
00497                                 {
00498                                         return FALSE;
00499                                 }
00500                         }
00501                 
00502                         // Recursively read the local directory
00503                         while (FALSE !== ($file = readdir($fp)))
00504                         {
00505                                 if (@is_dir($locpath.$file) && substr($file, 0, 1) != '.')
00506                                 {                                       
00507                                         $this->mirror($locpath.$file."/", $rempath.$file."/");
00508                                 }
00509                                 elseif (substr($file, 0, 1) != ".")
00510                                 {
00511                                         // Get the file extension so we can se the upload type
00512                                         $ext = $this->_getext($file);
00513                                         $mode = $this->_settype($ext);
00514                                         
00515                                         $this->upload($locpath.$file, $rempath.$file, $mode);
00516                                 }
00517                         }
00518                         return TRUE;
00519                 }
00520                 
00521                 return FALSE;
00522         }
00523 
00524 
00525         // --------------------------------------------------------------------
00526         
00527         /**
00528          * Extract the file extension
00529          *
00530          * @access      private
00531          * @param       string
00532          * @return      string
00533          */     
00534         function _getext($filename)
00535         {
00536                 if (FALSE === strpos($filename, '.'))
00537                 {
00538                         return 'txt';
00539                 }
00540         
00541                 $x = explode('.', $filename);
00542                 return end($x);
00543         }       
00544 
00545 
00546         // --------------------------------------------------------------------
00547         
00548         /**
00549          * Set the upload type
00550          *
00551          * @access      private
00552          * @param       string
00553          * @return      string
00554          */     
00555         function _settype($ext)
00556         {
00557                 $text_types = array(
00558                                                         'txt',
00559                                                         'text',
00560                                                         'php',
00561                                                         'phps',
00562                                                         'php4',
00563                                                         'js',
00564                                                         'css',
00565                                                         'htm',
00566                                                         'html',
00567                                                         'phtml',
00568                                                         'shtml',
00569                                                         'log',
00570                                                         'xml'
00571                                                         );
00572         
00573         
00574                 return (in_array($ext, $text_types)) ? 'ascii' : 'binary';
00575         }
00576 
00577         // ------------------------------------------------------------------------
00578         
00579         /**
00580          * Close the connection
00581          *
00582          * @access      public
00583          * @param       string  path to source
00584          * @param       string  path to destination
00585          * @return      bool
00586          */     
00587         function close()
00588         {
00589                 if ( ! $this->_is_conn())
00590                 {
00591                         return FALSE;
00592                 }
00593 
00594                 @ftp_close($this->conn_id);
00595         }
00596 
00597         // ------------------------------------------------------------------------
00598         
00599         /**
00600          * Display error message
00601          *
00602          * @access      private
00603          * @param       string
00604          * @return      bool
00605          */     
00606         function _error($line)
00607         {
00608                 $CI =& get_instance();
00609                 $CI->lang->load('ftp');
00610                 show_error($CI->lang->line($line));             
00611         }
00612 
00613 
00614 }
00615 // END FTP Class
00616 
00617 /* End of file Ftp.php */
00618 /* Location: ./system/libraries/Ftp.php */