|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- <?php if (!defined('DEDEINC')) exit('dedecms');
- /**
- * FTP 操作类
- * 不支持 SFTP 和 SSL FTP 协议, 仅支持标准 FTP 协议.
- * 需要传递一个数组配置
- * 示例:
- * $config['hostname'] = 'ftp.example.com';
- * $config['username'] = 'your-username';
- * $config['password'] = 'your-password';
- * $config['debug'] = TRUE;
- *
- * @version $Id: ftp.class.php 1 2010-07-05 11:43:09Z tianya $
- * @package DedeCMS.Libraries
- * @copyright Copyright (c) 2007 - 2020, DesDev, Inc.
- * @license http://help.dedecms.com/usersguide/license.html
- * @link http://www.dedecms.com
- */
- @set_time_limit(1000);
- class FTP
- {
- var $hostname = '';
- var $username = '';
- var $password = '';
- var $port = 21;
- var $passive = TRUE;
- var $debug = FALSE;
- var $conn_id = FALSE;
-
- function __construct($config = array())
- {
- $this->FTP($config);
- }
-
- /**
- * 析构函数 - 设置参数
- *
- * 构造函数则传递一个配置数组
- */
- function FTP($config = array())
- {
- if (count($config) > 0) {
- $this->initialize($config);
- }
- }
-
- /**
- * 初始化设置
- *
- * @access public
- * @param array
- * @return void
- */
- function initialize($config = array())
- {
- foreach ($config as $key => $val) {
- if (isset($this->$key)) {
- $this->$key = $val;
- }
- }
-
- // 准备主机名
- $this->hostname = preg_replace('|.+?://|', '', $this->hostname);
- }
-
- /**
- * FTP 链接
- *
- * @access public
- * @param array 链接值
- * @return bool
- */
- function connect($config = array())
- {
- if (count($config) > 0) {
- $this->initialize($config);
- }
-
- if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port))) {
- if ($this->debug == TRUE) {
- $this->_error('无法链接');
- }
- return FALSE;
- }
-
- if (!$this->_login()) {
- if ($this->debug == TRUE) {
- $this->_error('无法登录');
- }
- return FALSE;
- }
-
- // 如果需要则设置传输模式
- if ($this->passive == TRUE) {
- ftp_pasv($this->conn_id, TRUE);
- }
-
- return TRUE;
- }
-
- /**
- * FTP 登录
- *
- * @access private
- * @return bool
- */
- function _login()
- {
- return @ftp_login($this->conn_id, $this->username, $this->password);
- }
-
- /**
- * 验证连接ID
- *
- * @access private
- * @return bool
- */
- function _is_conn()
- {
- if (!is_resource($this->conn_id)) {
- if ($this->debug == TRUE) {
- $this->_error('无法链接');
- }
- return FALSE;
- }
- return TRUE;
- }
-
- /**
- * 更改目录
- * 第二个参数可以让我们暂时关闭,以便调试
- * 此功能可用于检测是否存在一个文件夹
- * 抛出一个错误。没有什么的FTP相当于is_dir()
- * 因此,我们试图改变某一特定目录。
- *
- * @access public
- * @param string
- * @param bool
- * @return bool
- */
- function changedir($path = '', $supress_debug = FALSE)
- {
- if ($path == '' or !$this->_is_conn()) {
- return FALSE;
- }
-
- $result = @ftp_chdir($this->conn_id, $path);
-
- if ($result === FALSE) {
- if ($this->debug == TRUE and $supress_debug == FALSE) {
- $this->_error('无法更改目录');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * 创建一个目录
- *
- * @access public
- * @param string
- * @return bool
- */
- function mkdir($path = '', $permissions = NULL)
- {
- if ($path == '' or !$this->_is_conn()) {
- return FALSE;
- }
-
- $result = @ftp_mkdir($this->conn_id, $path);
-
- if ($result === FALSE) {
- if ($this->debug == TRUE) {
- $this->_error('无法创建文件夹');
- }
- return FALSE;
- }
-
- // 如果需要设置权限
- if (!is_null($permissions)) {
- $this->chmod($path, (int)$permissions);
- }
-
- return TRUE;
- }
-
- /**
- * 创建深级目录
- *
- * @access public
- * @param string
- * @return bool
- */
- function rmkdir($path = '', $pathsymbol = '/')
- {
- $pathArray = explode($pathsymbol, $path);
- $pathstr = $pathsymbol;
- foreach ($pathArray as $val) {
- if (!empty($val)) {
- //构建文件夹路径
- $pathstr = $pathstr . $val . $pathsymbol;
- if (!$this->_is_conn()) {
- return FALSE;
- }
- $result = @ftp_chdir($this->conn_id, $pathstr);
- if ($result === FALSE) {
- //如果不存在这个目录则创建
- if (!$this->mkdir($pathstr)) {
- return FALSE;
- }
- }
- }
- }
- return TRUE;
- }
-
- /**
- * 上传一个文件到服务器
- *
- * @access public
- * @param string
- * @param string
- * @param string
- * @return bool
- */
- function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
- {
- if (!$this->_is_conn()) {
- return FALSE;
- }
-
- if (!file_exists($locpath)) {
- $this->_error('不存在源文件');
- return FALSE;
- }
-
- // 未指定则设置模式
- if ($mode == 'auto') {
- // 获取文件扩展名,以便本类上传类型
- $ext = $this->_getext($locpath);
- $mode = $this->_settype($ext);
- }
-
- $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
-
- $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
-
- if ($result === FALSE) {
- if ($this->debug == TRUE) {
- $this->_error('无法上传');
- }
- return FALSE;
- }
-
- // 如果需要设置文件权限
- if (!is_null($permissions)) {
- $this->chmod($rempath, (int)$permissions);
- }
-
- return TRUE;
- }
-
- /**
- * 重命名(或者移动)一个文件
- *
- * @access public
- * @param string
- * @param string
- * @param bool
- * @return bool
- */
- 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) ? '无法重命名' : '无法移动';
-
- $this->_error($msg);
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * 移动一个文件
- *
- * @access public
- * @param string
- * @param string
- * @return bool
- */
- function move($old_file, $new_file)
- {
- return $this->rename($old_file, $new_file, TRUE);
- }
-
- /**
- * 重命名或者移动一个文件
- *
- * @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) {
- $this->_error('无法删除');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * 删除一个文件夹,递归删除一切(包括子文件夹)中内容
- *
- * @access public
- * @param string
- * @return bool
- */
- function delete_dir($filepath)
- {
- if (!$this->_is_conn()) {
- return FALSE;
- }
-
- // 如果需要在尾部加上尾随"/"
- $filepath = preg_replace("/(.+?)\/*$/", "\\1/", $filepath);
-
- $list = $this->list_files($filepath);
-
- if ($list !== FALSE and count($list) > 0) {
- foreach ($list as $item) {
- // 如果我们不能删除该项目,它则可能是一个文件夹
- // 将调用 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) {
- $this->_error('无法删除');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * 设置文件权限
- *
- * @access public
- * @param string 文件地址
- * @param string 权限
- * @return bool
- */
- function chmod($path, $perm)
- {
- if (!$this->_is_conn()) {
- return FALSE;
- }
-
- // 仅PHP5才能运行
- if (!function_exists('ftp_chmod')) {
- if ($this->debug == TRUE) {
- $this->_error('无法更改权限');
- }
- return FALSE;
- }
-
- $result = @ftp_chmod($this->conn_id, $perm, $path);
-
- if ($result === FALSE) {
- if ($this->debug == TRUE) {
- $this->_error('无法更改权限');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * 在指定的目录的FTP文件列表
- *
- * @access public
- * @return array
- */
- function list_files($path = '.')
- {
- if (!$this->_is_conn()) {
- return FALSE;
- }
-
- return ftp_nlist($this->conn_id, $path);
- }
-
- /**
- * 返回指定目录下文件的详细列表
- *
- * @access public
- * @return array
- */
- function list_rawfiles($path = '.', $type = 'dir')
- {
- if (!$this->_is_conn()) {
- return FALSE;
- }
-
- $ftp_rawlist = ftp_rawlist($this->conn_id, $path, TRUE);
- foreach ($ftp_rawlist as $v) {
- $info = array();
- $vinfo = preg_split("/[\s]+/", $v, 9);
- if ($vinfo[0] !== "total") {
- $info['chmod'] = $vinfo[0];
- $info['num'] = $vinfo[1];
- $info['owner'] = $vinfo[2];
- $info['group'] = $vinfo[3];
- $info['size'] = $vinfo[4];
- $info['month'] = $vinfo[5];
- $info['day'] = $vinfo[6];
- $info['time'] = $vinfo[7];
- $info['name'] = $vinfo[8];
- $rawlist[$info['name']] = $info;
- }
- }
-
- $dir = array();
- $file = array();
- foreach ($rawlist as $k => $v) {
- if ($v['chmod'][0] == "d") {
- $dir[$k] = $v;
- } elseif ($v['chmod'][0] == "-") {
- $file[$k] = $v;
- }
- }
-
- return ($type == 'dir') ? $dir : $file;
- }
-
- /**
- * 检索一个本地目录下的所有内容(包括子目录和所有文件),并通过FTP为这个目录创建一份镜像。
- * 源路径下的任何结构都会被创建到服务器上。你必须给出源路径和目标路径
- *
- * @access public
- * @param string 含有尾随"/"的源路径
- * @param string 目标路径 - 含有尾随"/"的文件夹
- * @return bool
- */
- function mirror($locpath, $rempath)
- {
- if (!$this->_is_conn()) {
- return FALSE;
- }
-
- // 打开本地文件路径
- if ($fp = @opendir($locpath)) {
- // 尝试打开远程文件的路径.
- if (!$this->changedir($rempath, TRUE)) {
- // 如果不能打开则创建
- if (!$this->rmkdir($rempath) or !$this->changedir($rempath)) {
- return FALSE;
- }
- }
-
- // 递归读取本地目录
- while (FALSE !== ($file = readdir($fp))) {
- if (@is_dir($locpath . $file) && substr($file, 0, 1) != '.') {
- $this->mirror($locpath . $file . "/", $rempath . $file . "/");
- } elseif (substr($file, 0, 1) != ".") {
- // 获取文件扩展名,以便本类上传类型
- $ext = $this->_getext($file);
- $mode = $this->_settype($ext);
-
- $this->upload($locpath . $file, $rempath . $file, $mode);
- }
- }
- return TRUE;
- }
-
- return FALSE;
- }
-
- /**
- * 取出文件扩展名
- *
- * @access private
- * @param string
- * @return string
- */
- function _getext($filename)
- {
- if (FALSE === strpos($filename, '.')) {
- return 'txt';
- }
-
- $x = explode('.', $filename);
- return end($x);
- }
-
- /**
- * 设置上传类型
- *
- * @access private
- * @param string
- * @return string
- */
- 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';
- }
-
- /**
- * 关闭连接
- *
- * @access public
- * @param string 源路径
- * @param string 目的地路径
- * @return bool
- */
- function close()
- {
- if (!$this->_is_conn()) {
- return FALSE;
- }
-
- @ftp_close($this->conn_id);
- }
-
- /**
- * 显示错误信息
- *
- * @access private
- * @param string
- * @return bool
- */
- function _error($msg)
- {
- $errorTrackFile = dirname(__FILE__) . '/../data/ftp_error_trace.inc';
- $emsg = '';
- $emsg .= "<div><h3>DedeCMS Error Warning!</h3>\r\n";
- $emsg .= "<div><a href='http://bbs.dedecms.com' target='_blank' style='color:red'>Technical Support: http://bbs.dedecms.com</a></div>";
- $emsg .= "<div style='line-helght:160%;font-size:14px;color:green'>\r\n";
- $emsg .= "<div style='color:blue'><br />Error page: <font color='red'>" . $this->GetCurUrl() . "</font></div>\r\n";
- $emsg .= "<div>Error infos: {$msg}</div>\r\n";
- $emsg .= "<br /></div></div>\r\n";
-
- echo $emsg;
-
- $savemsg = 'Page: ' . $this->GetCurUrl() . "\r\nError: " . $msg;
- //保存错误日志
- $fp = @fopen($errorTrackFile, 'a');
- @fwrite($fp, '<' . '?php exit();' . "\r\n/*\r\n{$savemsg}\r\n*/\r\n?" . ">\r\n");
- @fclose($fp);
- }
-
- /**
- * 获得当前的脚本网址
- *
- * @access public
- * @return string
- */
- function GetCurUrl()
- {
- if (!empty($_SERVER["REQUEST_URI"])) {
- $scriptName = $_SERVER["REQUEST_URI"];
- $nowurl = $scriptName;
- } else {
- $scriptName = $_SERVER["PHP_SELF"];
- if (empty($_SERVER["QUERY_STRING"])) {
- $nowurl = $scriptName;
- } else {
- $nowurl = $scriptName . "?" . $_SERVER["QUERY_STRING"];
- }
- }
- return $nowurl;
- }
- }//End Class
|