123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 |
- <?php
- /**
- * Part of the Fuel framework.
- *
- * @package Fuel
- * @version 1.5
- * @author Fuel Development Team
- * @license MIT License
- * @copyright 2010 - 2013 Fuel Development Team
- * @link http://fuelphp.com
- */
- namespace Fuel\Core;
- class FtpConnectionException extends \FuelException {}
- class FtpFileAccessException extends \FuelException {}
- /**
- * FTP Class
- *
- * @package Fuel
- * @category Core
- * @author Phil Sturgeon
- * @link http://docs.fuelphp.com/classes/ftp.html
- */
- class Ftp
- {
- public static $initialized = false;
- protected $_hostname = 'localhost';
- protected $_username = '';
- protected $_password = '';
- protected $_port = 21;
- protected $_timeout = 90;
- protected $_passive = true;
- protected $_debug = false;
- protected $_conn_id = false;
- /**
- * Returns a new Ftp object. If you do not define the "file" parameter,
- *
- * $ftp = static::forge('group');
- *
- * @param string|array The name of the config group to use, or a configuration array.
- * @param bool Automatically connect to this server.
- * @return Ftp
- */
- public static function forge($config = 'default', $connect = true)
- {
- $ftp = new static($config);
- // Unless told not to, connect automatically
- $connect === true and $ftp->connect();
- return $ftp;
- }
- /**
- * Sets the initial Ftp filename and local data.
- *
- * @param string|array The name of the config group to use, or a configuration array.
- * @param bool Automatically connect to this server.
- * @return void
- */
- public function __construct($config = 'default')
- {
- \Config::load('ftp', true);
- // If it is a string we're looking at a predefined config group
- if (is_string($config))
- {
- $config_arr = \Config::get('ftp.'.$config);
- // Check that it exists
- if ( ! is_array($config_arr) or $config_arr === array())
- {
- throw new \UnexpectedValueException('You have specified an invalid ftp connection group: '.$config);
- }
- $config = $config_arr;
- }
- // Prep the hostname
- $this->_hostname = preg_replace('|.+?://|', '', $config['hostname']);
- $this->_username = $config['username'];
- $this->_password = $config['password'];
- $this->_timeout = ! empty($config['timeout']) ? (int) $config['timeout'] : 90;
- $this->_port = ! empty($config['port']) ? (int) $config['port'] : 21;
- $this->_passive = (bool) $config['passive'];
- $this->_ssl_mode = (bool) $config['ssl_mode'];
- $this->_debug = (bool) $config['debug'];
- static::$initialized = true;
- }
- // --------------------------------------------------------------------
- /**
- * FTP Connect
- *
- * @access public
- * @param array the connection values
- * @return bool
- */
- public function connect()
- {
- if($this->_ssl_mode === true)
- {
- if( ! function_exists('ftp_ssl_connect'))
- {
- throw new \RuntimeException('ftp_ssl_connect() function is missing.');
- }
- $this->_conn_id = @ftp_ssl_connect($this->_hostname, $this->_port, $this->_timeout);
- }
- else
- {
- $this->_conn_id = @ftp_connect($this->_hostname, $this->_port, $this->_timeout);
- }
- if ($this->_conn_id === false)
- {
- if ($this->_debug == true)
- {
- throw new \FtpConnectionException('Unable to establish a connection');
- }
- return false;
- }
- if ( ! $this->_login())
- {
- if ($this->_debug == true)
- {
- throw new \FtpConnectionException('Unable to login');
- }
- }
- // Set passive mode if needed
- if ($this->_passive == true)
- {
- ftp_pasv($this->_conn_id, true);
- }
- return $this;
- }
- // --------------------------------------------------------------------
- /**
- * FTP Login
- *
- * @return bool
- */
- protected function _login()
- {
- return @ftp_login($this->_conn_id, $this->_username, $this->_password);
- }
- // --------------------------------------------------------------------
- /**
- * Validates the connection ID
- *
- * @return bool
- */
- protected function _is_conn()
- {
- if ( ! is_resource($this->_conn_id))
- {
- if ($this->_debug == true)
- {
- throw new \InvalidArgumentException('Invalid connection');
- }
- return false;
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Change directory
- *
- * The second parameter lets us momentarily turn off debugging so that
- * this function can be used to test for the existence of a folder
- * without throwing an error. There's no FTP equivalent to is_dir()
- * so we do it by trying to change to a particular directory.
- * Internally, this parameter is only used by the "mirror" function below.
- *
- * @access public
- * @param string
- * @param bool
- * @return bool
- */
- public function change_dir($path = '')
- {
- if ($path == '' or ! $this->_is_conn())
- {
- return false;
- }
- $result = @ftp_chdir($this->_conn_id, $path);
- if ($result === false)
- {
- if ($this->_debug == true)
- {
- throw new \FtpFileAccessException('Unable to change the directory');
- }
- return false;
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Create a directory
- *
- * @access public
- * @param string
- * @return bool
- */
- public function mkdir($path, $permissions = null)
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- $result = ftp_mkdir($this->_conn_id, $path);
- if ($result === false)
- {
- if ($this->_debug == true)
- {
- throw new \FtpFileAccessException('Unable to create directory');
- }
- return false;
- }
- // Set file permissions if needed
- if ($permissions !== null)
- {
- $this->chmod($path, (int) $permissions);
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Upload a file to the server
- *
- * @access public
- * @param string
- * @param string
- * @param string
- * @return bool
- */
- public function upload($local_path, $remote_path, $mode = 'auto', $permissions = null)
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- if ( ! file_exists($local_path))
- {
- throw new \FtpFileAccessException('No source file');
- return false;
- }
- // Set the mode if not specified
- if ($mode == 'auto')
- {
- // Get the file extension so we can set the upload type
- $ext = pathinfo($local_path, PATHINFO_EXTENSION);
- $mode = $this->_settype($ext);
- }
- $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
- $result = @ftp_put($this->_conn_id, $remote_path, $local_path, $mode);
- if ($result === false)
- {
- if ($this->_debug == true)
- {
- throw new \FtpFileAccessException('Unable to upload');
- }
- return false;
- }
- // Set file permissions if needed
- if ($permissions !== null)
- {
- $this->chmod($remote_path, (int) $permissions);
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Download a file from a remote server to the local server
- *
- * @access public
- * @param string
- * @param string
- * @param string
- * @return bool
- */
- public function download($remote_path, $local_path, $mode = 'auto')
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- // Set the mode if not specified
- if ($mode == 'auto')
- {
- // Get the file extension so we can set the upload type
- $ext = pathinfo($remote_path, PATHINFO_BASENAME);
- $mode = $this->_settype($ext);
- }
- $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
- $result = @ftp_get($this->_conn_id, $local_path, $remote_path, $mode);
- if ($result === false)
- {
- if ($this->_debug === true)
- {
- throw new \FtpFileAccessException('Unable to download');
- }
- return false;
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Rename (or move) a file
- *
- * @access public
- * @param string
- * @param string
- * @param bool
- * @return bool
- */
- public function rename($old_file, $new_file, $move = false)
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- $result = @ftp_rename($this->_conn_id, $old_file, $new_file);
- if ($result === false)
- {
- if ($this->_debug == true)
- {
- $msg = ($move == false) ? 'Unable to rename' : 'Unable to move';
- throw new \FtpFileAccessException($msg);
- }
- return false;
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Move a file
- *
- * @access public
- * @param string
- * @param string
- * @return bool
- */
- public function move($old_file, $new_file)
- {
- return $this->rename($old_file, $new_file, true);
- }
- // --------------------------------------------------------------------
- /**
- * Rename (or move) a file
- *
- * @access public
- * @param string
- * @return bool
- */
- function delete_file($filepath)
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- $result = @ftp_delete($this->_conn_id, $filepath);
- if ($result === false)
- {
- if ($this->_debug == true)
- {
- throw new \FtpFileAccessException('Unable to delete');
- }
- return false;
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Delete a folder and recursively delete everything (including sub-folders)
- * containted within it.
- *
- * @access public
- * @param string
- * @return bool
- */
- function delete_dir($filepath)
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- // Add a trailing slash to the file path if needed
- $filepath = preg_replace("/(.+?)\/*$/", "\\1/", $filepath);
- $list = $this->list_files($filepath);
- if ($list !== false and count($list) > 0)
- {
- foreach ($list as $item)
- {
- // If we can't delete the item it's probaly a folder so
- // we'll recursively call delete_dir()
- if ( ! @ftp_delete($this->_conn_id, $item))
- {
- $this->delete_dir($item);
- }
- }
- }
- $result = @ftp_rmdir($this->_conn_id, $filepath);
- if ($result === false)
- {
- if ($this->_debug == true)
- {
- throw new \FtpFileAccessException('Unable to delete');
- }
- return false;
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * Set file permissions
- *
- * @access public
- * @param string the file path
- * @param string the permissions
- * @return bool
- */
- public function chmod($path, $perm)
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- // Permissions can only be set when running PHP 5
- if ( ! function_exists('ftp_chmod'))
- {
- if ($this->_debug == true)
- {
- throw new \FtpFileAccessException('CHMOD function does not exist');
- }
- return false;
- }
- $result = @ftp_chmod($this->_conn_id, $perm, $path);
- if ($result === false)
- {
- if ($this->_debug == true)
- {
- throw new \FtpFileAccessException('Unable to CHMOD');
- }
- return false;
- }
- return true;
- }
- // --------------------------------------------------------------------
- /**
- * FTP List files in the specified directory
- *
- * @access public
- * @return array
- */
- public function list_files($path = '.')
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- return ftp_nlist($this->_conn_id, $path);
- }
- // ------------------------------------------------------------------------
- /**
- * Read a directory and recreate it remotely
- *
- * This function recursively reads a folder and everything it contains (including
- * sub-folders) and creates a mirror via FTP based on it. Whatever the directory structure
- * of the original file path will be recreated on the server.
- *
- * @access public
- * @param string path to source with trailing slash
- * @param string path to destination - include the base folder with trailing slash
- * @return bool
- */
- public function mirror($local_path, $remote_path)
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- // Open the local file path
- if ($fp = @opendir($local_path))
- {
- // Attempt to open the remote file path.
- if ( ! $this->change_dir($remote_path, true))
- {
- // If it doesn't exist we'll attempt to create the direcotory
- if ( ! $this->mkdir($remote_path) or ! $this->change_dir($remote_path))
- {
- return false;
- }
- }
- // Recursively read the local directory
- while (false !== ($file = readdir($fp)))
- {
- if (@is_dir($local_path.$file) and substr($file, 0, 1) != '.')
- {
- $this->mirror($local_path.$file."/", $remote_path.$file."/");
- }
- elseif (substr($file, 0, 1) != ".")
- {
- // Get the file extension so we can se the upload type
- $ext = pathinfo($file, PATHINFO_EXTENSION);
- $mode = $this->_settype($ext);
- $this->upload($local_path.$file, $remote_path.$file, $mode);
- }
- }
- return true;
- }
- return false;
- }
- // --------------------------------------------------------------------
- /**
- * Set the upload type
- *
- * @param string
- * @return string
- */
- protected function _settype($ext)
- {
- $text_types = array(
- 'txt',
- 'text',
- 'php',
- 'phps',
- 'php4',
- 'js',
- 'css',
- 'htm',
- 'html',
- 'phtml',
- 'shtml',
- 'log',
- 'xml'
- );
- return in_array($ext, $text_types) ? 'ascii' : 'binary';
- }
- // ------------------------------------------------------------------------
- /**
- * Close the connection
- *
- * @access public
- * @return void
- */
- public function close()
- {
- if ( ! $this->_is_conn())
- {
- return false;
- }
- @ftp_close($this->_conn_id);
- }
- // ------------------------------------------------------------------------
- /**
- * Close the connection when the class is unset
- *
- * @access public
- * @return void
- */
- public function __destruct()
- {
- $this->close();
- }
- }
|