From 68ae0e6edee8d3135b9b6eb2a2324dd1113f17b3 Mon Sep 17 00:00:00 2001 From: icret Date: Thu, 9 Mar 2023 00:38:24 +0800 Subject: [PATCH] fix bugs --- admin/admin.inc.php | 2 +- api/index.php | 37 +- application/FtpClient/FtpClient.php | 968 +++++++++++++++++++++++++ application/FtpClient/FtpException.php | 20 + application/FtpClient/FtpWrapper.php | 116 +++ application/del.php | 38 +- application/function.php | 53 +- application/post_del.php | 2 + application/upload.php | 37 +- config/config.php | 10 +- index.php | 1 - 11 files changed, 1214 insertions(+), 70 deletions(-) create mode 100644 application/FtpClient/FtpClient.php create mode 100644 application/FtpClient/FtpException.php create mode 100644 application/FtpClient/FtpWrapper.php diff --git a/admin/admin.inc.php b/admin/admin.inc.php index f503110..4a7684c 100755 --- a/admin/admin.inc.php +++ b/admin/admin.inc.php @@ -952,7 +952,7 @@ auto_delete(); //定时删除 Manual Telegram Discuss - +

程序依赖
diff --git a/api/index.php b/api/index.php index cac39a8..a023e27 100755 --- a/api/index.php +++ b/api/index.php @@ -194,30 +194,19 @@ if ($handle->uploaded) { /** 后续处理 */ // 使用fastcgi_finish_request操作 - if (function_exists('fastcgi_finish_request')) { // fastcgi_finish_request 模式 - fastcgi_finish_request(); - // 记录同IP上传次数 - @write_ip_upload_count_logs(); - // 上传日志 - @write_upload_logs($pathIMG, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size, $tokenID); - // 鉴黄 - @process_checkImg($processUrl); - // 水印 - @water($handle->file_dst_pathname); - // 压缩 - @process_compress($handle->file_dst_pathname); - } else { // 普通模式 - // 记录同IP上传次数 - @write_ip_upload_count_logs(); - // 上传日志 - @write_upload_logs($pathIMG, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size, $tokenID); - // 鉴黄 - @process_checkImg($processUrl); - // 水印 - @water($handle->file_dst_pathname); - // 压缩 - @process_compress($handle->file_dst_pathname); - } + if (function_exists('fastcgi_finish_request')) fastcgi_finish_request(); + // 同IP上传日志 + @write_ip_upload_count_logs(); + // 日志 + @write_upload_logs($pathIMG, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); + // 鉴黄 + @process_checkImg($processUrl); + // 水印 + @water($handle->file_dst_pathname); + // 压缩 + @process_compress($handle->file_dst_pathname); + // 上传至其他位置 + // @any_upload($pathIMG, APP_ROOT . $pathIMG, 'upload'); unset($handle); } diff --git a/application/FtpClient/FtpClient.php b/application/FtpClient/FtpClient.php new file mode 100644 index 0000000..5a0a83d --- /dev/null +++ b/application/FtpClient/FtpClient.php @@ -0,0 +1,968 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +// namespace FtpClient; + +// use \Countable; + +/** + * The FTP and SSL-FTP client for PHP. + * + * @method bool alloc(int $filesize, string &$result = null) Allocates space for a file to be uploaded + * @method bool append(string $remote_file, string $local_file, int $mode = FTP_BINARY) Append the contents of a file to another file on the FTP server + * @method bool cdup() Changes to the parent directory + * @method bool chdir(string $directory) Changes the current directory on a FTP server + * @method int chmod(int $mode, string $filename) Set permissions on a file via FTP + * @method bool delete(string $path) Deletes a file on the FTP server + * @method bool exec(string $command) Requests execution of a command on the FTP server + * @method bool fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server and saves to an open file + * @method bool fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Uploads from an open file to the FTP server + * @method mixed get_option(int $option) Retrieves various runtime behaviours of the current FTP stream + * @method bool get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server + * @method int mdtm(string $remote_file) Returns the last modified time of the given file + * @method array mlsd(string $remote_dir) Returns a list of files in the given directory + * @method int nb_continue() Continues retrieving/sending a file (non-blocking) + * @method int nb_fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to an open file (non-blocking) + * @method int nb_fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Stores a file from an open file to the FTP server (non-blocking) + * @method int nb_get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to a local file (non-blocking) + * @method int nb_put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Stores a file on the FTP server (non-blocking) + * @method bool pasv(bool $pasv) Turns passive mode on or off + * @method bool put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Uploads a file to the FTP server + * @method string pwd() Returns the current directory name + * @method bool quit() Closes an FTP connection + * @method array raw(string $command) Sends an arbitrary command to an FTP server + * @method bool rename(string $oldname, string $newname) Renames a file or a directory on the FTP server + * @method bool set_option(int $option, mixed $value) Set miscellaneous runtime FTP options + * @method bool site(string $command) Sends a SITE command to the server + * @method int size(string $remote_file) Returns the size of the given file + * @method string systype() Returns the system type identifier of the remote FTP server + * + * @author Nicolas Tallefourtane + */ +class FtpClient implements Countable +{ + /** + * The connection with the server. + * + * @var resource + */ + protected $conn; + + /** + * PHP FTP functions wrapper. + * + * @var FtpWrapper + */ + private $ftp; + + /** + * Constructor. + * + * @param resource|null $connection + * @throws FtpException If FTP extension is not loaded. + */ + public function __construct($connection = null) + { + if (!extension_loaded('ftp')) { + throw new FtpException('FTP extension is not loaded!'); + } + + if ($connection) { + $this->conn = $connection; + } + + $this->setWrapper(new FtpWrapper($this->conn)); + } + + /** + * Close the connection when the object is destroyed. + */ + public function __destruct() + { + if ($this->conn) { + $this->ftp->close(); + } + } + + /** + * Call an internal method or a FTP method handled by the wrapper. + * + * Wrap the FTP PHP functions to call as method of FtpClient object. + * The connection is automaticaly passed to the FTP PHP functions. + * + * @param string $method + * @param array $arguments + * @return mixed + * @throws FtpException When the function is not valid + */ + public function __call($method, array $arguments) + { + return $this->ftp->__call($method, $arguments); + } + + /** + * Overwrites the PHP limit + * + * @param string|null $memory The memory limit, if null is not modified + * @param int $time_limit The max execution time, unlimited by default + * @param bool $ignore_user_abort Ignore user abort, true by default + * @return FtpClient + */ + public function setPhpLimit($memory = null, $time_limit = 0, $ignore_user_abort = true) + { + if (null !== $memory) { + ini_set('memory_limit', $memory); + } + + ignore_user_abort($ignore_user_abort); + set_time_limit($time_limit); + + return $this; + } + + /** + * Get the help information of the remote FTP server. + * + * @return array + */ + public function help() + { + return $this->ftp->raw('help'); + } + + /** + * Open a FTP connection. + * + * @param string $host + * @param bool $ssl + * @param int $port + * @param int $timeout + * + * @return FtpClient + * @throws FtpException If unable to connect + */ + public function connect($host, $ssl = false, $port = 21, $timeout = 90) + { + if ($ssl) { + $this->conn = $this->ftp->ssl_connect($host, $port, $timeout); + } else { + $this->conn = $this->ftp->connect($host, $port, $timeout); + } + + if (!$this->conn) { + throw new FtpException('Unable to connect'); + } + + return $this; + } + + /** + * Closes the current FTP connection. + * + * @return bool + */ + public function close() + { + if ($this->conn) { + $this->ftp->close(); + $this->conn = null; + } + } + + /** + * Get the connection with the server. + * + * @return resource + */ + public function getConnection() + { + return $this->conn; + } + + /** + * Get the wrapper. + * + * @return FtpWrapper + */ + public function getWrapper() + { + return $this->ftp; + } + + /** + * Logs in to an FTP connection. + * + * @param string $username + * @param string $password + * + * @return FtpClient + * @throws FtpException If the login is incorrect + */ + public function login($username = 'anonymous', $password = '') + { + $result = $this->ftp->login($username, $password); + + if ($result === false) { + throw new FtpException('Login incorrect'); + } + + return $this; + } + + /** + * Returns the last modified time of the given file. + * Return -1 on error + * + * @param string $remoteFile + * @param string|null $format + * + * @return int + */ + public function modifiedTime($remoteFile, $format = null) + { + $time = $this->ftp->mdtm($remoteFile); + + if ($time !== -1 && $format !== null) { + return date($format, $time); + } + + return $time; + } + + /** + * Changes to the parent directory. + * + * @throws FtpException + * @return FtpClient + */ + public function up() + { + $result = $this->ftp->cdup(); + + if ($result === false) { + throw new FtpException('Unable to get parent folder'); + } + + return $this; + } + + /** + * Returns a list of files in the given directory. + * + * @param string $directory The directory, by default is "." the current directory + * @param bool $recursive + * @param callable $filter A callable to filter the result, by default is asort() PHP function. + * The result is passed in array argument, + * must take the argument by reference ! + * The callable should proceed with the reference array + * because is the behavior of several PHP sorting + * functions (by reference ensure directly the compatibility + * with all PHP sorting functions). + * + * @return array + * @throws FtpException If unable to list the directory + */ + public function nlist($directory = '.', $recursive = false, $filter = 'sort') + { + if (!$this->isDir($directory)) { + throw new FtpException('"'.$directory.'" is not a directory'); + } + + $files = $this->ftp->nlist($directory); + + if ($files === false) { + throw new FtpException('Unable to list directory'); + } + + $result = array(); + $dir_len = strlen($directory); + + // if it's the current + if (false !== ($kdot = array_search('.', $files))) { + unset($files[$kdot]); + } + + // if it's the parent + if(false !== ($kdot = array_search('..', $files))) { + unset($files[$kdot]); + } + + if (!$recursive) { + $result = $files; + + // working with the reference (behavior of several PHP sorting functions) + $filter($result); + + return $result; + } + + // utils for recursion + $flatten = function (array $arr) use (&$flatten) { + $flat = []; + + foreach ($arr as $k => $v) { + if (is_array($v)) { + $flat = array_merge($flat, $flatten($v)); + } else { + $flat[] = $v; + } + } + + return $flat; + }; + + foreach ($files as $file) { + $file = $directory.'/'.$file; + + // if contains the root path (behavior of the recursivity) + if (0 === strpos($file, $directory, $dir_len)) { + $file = substr($file, $dir_len); + } + + if ($this->isDir($file)) { + $result[] = $file; + $items = $flatten($this->nlist($file, true, $filter)); + + foreach ($items as $item) { + $result[] = $item; + } + + } else { + $result[] = $file; + } + } + + $result = array_unique($result); + $filter($result); + + return $result; + } + + /** + * Creates a directory. + * + * @see FtpClient::rmdir() + * @see FtpClient::remove() + * @see FtpClient::put() + * @see FtpClient::putAll() + * + * @param string $directory The directory + * @param bool $recursive + * @return bool + */ + public function mkdir($directory, $recursive = false) + { + if (!$recursive or $this->isDir($directory)) { + return $this->ftp->mkdir($directory); + } + + $result = false; + $pwd = $this->ftp->pwd(); + $parts = explode('/', $directory); + + foreach ($parts as $part) { + if ($part == '') { + continue; + } + + if (!@$this->ftp->chdir($part)) { + $result = $this->ftp->mkdir($part); + $this->ftp->chdir($part); + } + } + + $this->ftp->chdir($pwd); + + return $result; + } + + /** + * Remove a directory. + * + * @see FtpClient::mkdir() + * @see FtpClient::cleanDir() + * @see FtpClient::remove() + * @see FtpClient::delete() + * @param string $directory + * @param bool $recursive Forces deletion if the directory is not empty + * @return bool + * @throws FtpException If unable to list the directory to remove + */ + public function rmdir($directory, $recursive = true) + { + if ($recursive) { + $files = $this->nlist($directory, false, 'rsort'); + + // remove children + foreach ($files as $file) { + $this->remove($file, true); + } + } + + // remove the directory + return $this->ftp->rmdir($directory); + } + + /** + * Empty directory. + * + * @see FtpClient::remove() + * @see FtpClient::delete() + * @see FtpClient::rmdir() + * + * @param string $directory + * @return bool + */ + public function cleanDir($directory) + { + if (!$files = $this->nlist($directory)) { + return $this->isEmpty($directory); + } + + // remove children + foreach ($files as $file) { + $this->remove($file, true); + } + + return $this->isEmpty($directory); + } + + /** + * Remove a file or a directory. + * + * @see FtpClient::rmdir() + * @see FtpClient::cleanDir() + * @see FtpClient::delete() + * @param string $path The path of the file or directory to remove + * @param bool $recursive Is effective only if $path is a directory, {@see FtpClient::rmdir()} + * @return bool + */ + public function remove($path, $recursive = false) + { + if ($path == '.' || $path == '..') { + return false; + } + + try { + if (@$this->ftp->delete($path) + or ($this->isDir($path) + and $this->rmdir($path, $recursive))) { + return true; + } else { + // in special cases the delete can fail (for example, at Symfony's "r+e.gex[c]a(r)s" directory) + $newPath = preg_replace('/[^A-Za-z0-9\/]/', '', $path); + if ($this->rename($path, $newPath)) { + if (@$this->ftp->delete($newPath) + or ($this->isDir($newPath) + and $this->rmdir($newPath, $recursive))) { + return true; + } + } + } + + return false; + } catch (\Exception $e) { + return false; + } + } + + /** + * Check if a directory exist. + * + * @param string $directory + * @return bool + * @throws FtpException + */ + public function isDir($directory) + { + $pwd = $this->ftp->pwd(); + + if ($pwd === false) { + throw new FtpException('Unable to resolve the current directory'); + } + + if (@$this->ftp->chdir($directory)) { + $this->ftp->chdir($pwd); + return true; + } + + $this->ftp->chdir($pwd); + + return false; + } + + /** + * Check if a directory is empty. + * + * @param string $directory + * @return bool + */ + public function isEmpty($directory) + { + return $this->countItems($directory, null, false) === 0 ? true : false; + } + + /** + * Scan a directory and returns the details of each item. + * + * @see FtpClient::nlist() + * @see FtpClient::rawlist() + * @see FtpClient::parseRawList() + * @see FtpClient::dirSize() + * @param string $directory + * @param bool $recursive + * @return array + */ + public function scanDir($directory = '.', $recursive = false) + { + return $this->parseRawList($this->rawlist($directory, $recursive)); + } + + /** + * Returns the total size of the given directory in bytes. + * + * @param string $directory The directory, by default is the current directory. + * @param bool $recursive true by default + * @return int The size in bytes. + */ + public function dirSize($directory = '.', $recursive = true) + { + $items = $this->scanDir($directory, $recursive); + $size = 0; + + foreach ($items as $item) { + $size += (int) $item['size']; + } + + return $size; + } + + /** + * Count the items (file, directory, link, unknown). + * + * @param string $directory The directory, by default is the current directory. + * @param string|null $type The type of item to count (file, directory, link, unknown) + * @param bool $recursive true by default + * @return int + */ + public function countItems($directory = '.', $type = null, $recursive = true) + { + $items = (null === $type ? $this->nlist($directory, $recursive) + : $this->scanDir($directory, $recursive)); + + $count = 0; + foreach ($items as $item) { + if (null === $type or $item['type'] == $type) { + $count++; + } + } + + return $count; + } + + /** + * Count the items (file, directory, link, unknown). + * This method call `countItems()` with the default arguments. + * + * @see countItems + * @return int + */ + public function count(): int + { + return $this->countItems(); + } + + /** + * Downloads a file from the FTP server into a string + * + * @param string $remote_file + * @param int $mode + * @param int $resumepos + * @return string|null + */ + public function getContent($remote_file, $mode = FTP_BINARY, $resumepos = 0) + { + $handle = fopen('php://temp', 'r+'); + + if ($this->ftp->fget($handle, $remote_file, $mode, $resumepos)) { + rewind($handle); + return stream_get_contents($handle); + } + + return null; + } + + /** + * Uploads a file to the server from a string. + * + * @param string $remote_file + * @param string $content + * @return FtpClient + * @throws FtpException When the transfer fails + */ + public function putFromString($remote_file, $content) + { + $handle = fopen('php://temp', 'w'); + + fwrite($handle, $content); + rewind($handle); + + if ($this->ftp->fput($remote_file, $handle, FTP_BINARY)) { + return $this; + } + + throw new FtpException('Unable to put the file "'.$remote_file.'"'); + } + + /** + * Uploads a file to the server. + * + * @param string $local_file + * @return FtpClient + * @throws FtpException When the transfer fails + */ + public function putFromPath($local_file) + { + $remote_file = basename($local_file); + $handle = fopen($local_file, 'r'); + + if ($this->ftp->fput($remote_file, $handle, FTP_BINARY)) { + rewind($handle); + return $this; + } + + throw new FtpException( + 'Unable to put the remote file from the local file "'.$local_file.'"' + ); + } + + /** + * Upload files. + * + * @param string $source_directory + * @param string $target_directory + * @param int $mode + * @return FtpClient + */ + public function putAll($source_directory, $target_directory, $mode = FTP_BINARY) + { + $d = dir($source_directory); + + // do this for each file in the directory + while ($file = $d->read()) { + + // to prevent an infinite loop + if ($file != "." && $file != "..") { + + // do the following if it is a directory + if (is_dir($source_directory.'/'.$file)) { + if (!$this->isDir($target_directory.'/'.$file)) { + + // create directories that do not yet exist + $this->ftp->mkdir($target_directory.'/'.$file); + } + + // recursive part + $this->putAll( + $source_directory.'/'.$file, $target_directory.'/'.$file, + $mode + ); + } else { + + // put the files + $this->ftp->put( + $target_directory.'/'.$file, $source_directory.'/'.$file, + $mode + ); + } + } + } + + $d->close(); + + return $this; + } + + /** + * Downloads all files from remote FTP directory + * + * @param string $source_directory The remote directory + * @param string $target_directory The local directory + * @param int $mode + * @return FtpClient + */ + public function getAll($source_directory, $target_directory, $mode = FTP_BINARY) + { + if ($source_directory != ".") { + if ($this->ftp->chdir($source_directory) == false) { + throw new FtpException("Unable to change directory: ".$source_directory); + } + + if (!(is_dir($target_directory))) { + mkdir($target_directory); + } + + chdir($target_directory); + } + + $contents = $this->ftp->nlist("."); + + foreach ($contents as $file) { + if ($file == '.' || $file == '..') { + continue; + } + + $this->ftp->get($target_directory."/".$file, $file, $mode); + } + + $this->ftp->chdir(".."); + chdir(".."); + + return $this; + } + + /** + * Returns a detailed list of files in the given directory. + * + * @see FtpClient::nlist() + * @see FtpClient::scanDir() + * @see FtpClient::dirSize() + * @param string $directory The directory, by default is the current directory + * @param bool $recursive + * @return array + * @throws FtpException + */ + public function rawlist($directory = '.', $recursive = false) + { + if (!$this->isDir($directory)) { + throw new FtpException('"'.$directory.'" is not a directory.'); + } + + if (strpos($directory, " ") > 0) { + $ftproot = $this->ftp->pwd(); + $this->ftp->chdir($directory); + $list = $this->ftp->rawlist(""); + $this->ftp->chdir($ftproot); + } else { + $list = $this->ftp->rawlist($directory); + } + + $items = array(); + + if (!$list) { + return $items; + } + + if (false == $recursive) { + foreach ($list as $path => $item) { + $chunks = preg_split("/\s+/", $item); + + // if not "name" + if (!isset($chunks[8]) || strlen($chunks[8]) === 0 || $chunks[8] == '.' || $chunks[8] == '..') { + continue; + } + + $path = $directory.'/'.$chunks[8]; + + if (isset($chunks[9])) { + $nbChunks = count($chunks); + + for ($i = 9; $i < $nbChunks; $i++) { + $path .= ' '.$chunks[$i]; + } + } + + + if (substr($path, 0, 2) == './') { + $path = substr($path, 2); + } + + $items[ $this->rawToType($item).'#'.$path ] = $item; + } + + return $items; + } + + $path = ''; + + foreach ($list as $item) { + $len = strlen($item); + + if (!$len + + // "." + || ($item[$len-1] == '.' && $item[$len-2] == ' ' + + // ".." + or $item[$len-1] == '.' && $item[$len-2] == '.' && $item[$len-3] == ' ') + ) { + + continue; + } + + $chunks = preg_split("/\s+/", $item); + + // if not "name" + if (!isset($chunks[8]) || strlen($chunks[8]) === 0 || $chunks[8] == '.' || $chunks[8] == '..') { + continue; + } + + $path = $directory.'/'.$chunks[8]; + + if (isset($chunks[9])) { + $nbChunks = count($chunks); + + for ($i = 9; $i < $nbChunks; $i++) { + $path .= ' '.$chunks[$i]; + } + } + + if (substr($path, 0, 2) == './') { + $path = substr($path, 2); + } + + $items[$this->rawToType($item).'#'.$path] = $item; + + if ($item[0] == 'd') { + $sublist = $this->rawlist($path, true); + + foreach ($sublist as $subpath => $subitem) { + $items[$subpath] = $subitem; + } + } + } + + return $items; + } + + /** + * Parse raw list. + * + * @see FtpClient::rawlist() + * @see FtpClient::scanDir() + * @see FtpClient::dirSize() + * @param array $rawlist + * @return array + */ + public function parseRawList(array $rawlist) + { + $items = array(); + $path = ''; + + foreach ($rawlist as $key => $child) { + $chunks = preg_split("/\s+/", $child, 9); + + if (isset($chunks[8]) && ($chunks[8] == '.' or $chunks[8] == '..')) { + continue; + } + + if (count($chunks) === 1) { + $len = strlen($chunks[0]); + + if ($len && $chunks[0][$len-1] == ':') { + $path = substr($chunks[0], 0, -1); + } + + continue; + } + + // Prepare for filename that has space + $nameSlices = array_slice($chunks, 8, true); + + $item = [ + 'permissions' => $chunks[0], + 'number' => $chunks[1], + 'owner' => $chunks[2], + 'group' => $chunks[3], + 'size' => $chunks[4], + 'month' => $chunks[5], + 'day' => $chunks[6], + 'time' => $chunks[7], + 'name' => implode(' ', $nameSlices), + 'type' => $this->rawToType($chunks[0]), + ]; + + if ($item['type'] == 'link' && isset($chunks[10])) { + $item['target'] = $chunks[10]; // 9 is "->" + } + + // if the key is not the path, behavior of ftp_rawlist() PHP function + if (is_int($key) || false === strpos($key, $item['name'])) { + array_splice($chunks, 0, 8); + + $key = $item['type'].'#' + .($path ? $path.'/' : '') + .implode(' ', $chunks); + + if ($item['type'] == 'link') { + // get the first part of 'link#the-link.ext -> /path/of/the/source.ext' + $exp = explode(' ->', $key); + $key = rtrim($exp[0]); + } + + $items[$key] = $item; + } else { + // the key is the path, behavior of FtpClient::rawlist() method() + $items[$key] = $item; + } + } + + return $items; + } + + /** + * Convert raw info (drwx---r-x ...) to type (file, directory, link, unknown). + * Only the first char is used for resolving. + * + * @param string $permission Example : drwx---r-x + * + * @return string The file type (file, directory, link, unknown) + * @throws FtpException + */ + public function rawToType($permission) + { + if (!is_string($permission)) { + throw new FtpException('The "$permission" argument must be a string, "' + .gettype($permission).'" given.'); + } + + if (empty($permission[0])) { + return 'unknown'; + } + + switch ($permission[0]) { + case '-': + return 'file'; + + case 'd': + return 'directory'; + + case 'l': + return 'link'; + + default: + return 'unknown'; + } + } + + /** + * Set the wrapper which forward the PHP FTP functions to use in FtpClient instance. + * + * @param FtpWrapper $wrapper + * @return FtpClient + */ + protected function setWrapper(FtpWrapper $wrapper) + { + $this->ftp = $wrapper; + + return $this; + } +} diff --git a/application/FtpClient/FtpException.php b/application/FtpClient/FtpException.php new file mode 100644 index 0000000..d023349 --- /dev/null +++ b/application/FtpClient/FtpException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +// namespace FtpClient; + +/** + * The FtpException class. + * Exception thrown if an error on runtime of the FTP client occurs. + * @inheritDoc + * @author Nicolas Tallefourtane + */ +class FtpException extends \Exception {} diff --git a/application/FtpClient/FtpWrapper.php b/application/FtpClient/FtpWrapper.php new file mode 100644 index 0000000..8b55934 --- /dev/null +++ b/application/FtpClient/FtpWrapper.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +// namespace FtpClient; + +/** + * Wrap the PHP FTP functions + * + * @method bool alloc(int $filesize, string &$result = null) Allocates space for a file to be uploaded + * @method bool cdup() Changes to the parent directory + * @method bool chdir(string $directory) Changes the current directory on a FTP server + * @method int chmod(int $mode, string $filename) Set permissions on a file via FTP + * @method bool close() Closes an FTP connection + * @method bool delete(string $path) Deletes a file on the FTP server + * @method bool exec(string $command) Requests execution of a command on the FTP server + * @method bool fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server and saves to an open file + * @method bool fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Uploads from an open file to the FTP server + * @method mixed get_option(int $option) Retrieves various runtime behaviours of the current FTP stream + * @method bool get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server + * @method bool login(string $username, string $password) Logs in to an FTP connection + * @method int mdtm(string $remote_file) Returns the last modified time of the given file + * @method bool mkdir(string $directory) Creates a directory + * @method array mlsd(string $remote_dir) Returns a list of files in the given directory + * @method int nb_continue() Continues retrieving/sending a file (non-blocking) + * @method int nb_fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to an open file (non-blocking) + * @method int nb_fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Stores a file from an open file to the FTP server (non-blocking) + * @method int nb_get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to a local file (non-blocking) + * @method int nb_put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Stores a file on the FTP server (non-blocking) + * @method array nlist(string $directory) Returns a list of file names in the given directory; remote_dir parameter may also include arguments + * @method bool pasv(bool $pasv) Turns passive mode on or off + * @method bool put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Uploads a file to the FTP server + * @method string pwd() Returns the current directory name + * @method bool quit() Closes an FTP connection + * @method array raw(string $command) Sends an arbitrary command to an FTP server + * @method array rawlist(string $directory, bool $recursive = false) Returns a detailed list of files in the given directory + * @method bool rename(string $oldname, string $newname) Renames a file or a directory on the FTP server + * @method bool rmdir(string $directory) Removes a directory + * @method bool set_option(int $option, mixed $value) Set miscellaneous runtime FTP options + * @method bool site(string $command) Sends a SITE command to the server + * @method int size(string $remote_file) Returns the size of the given file + * @method string systype() Returns the system type identifier of the remote FTP server + * + * @author Nicolas Tallefourtane + */ +class FtpWrapper +{ + /** + * The connection with the server + * + * @var resource + */ + protected $conn; + + /** + * Constructor. + * + * @param resource &$connection The FTP (or SSL-FTP) connection (takes by reference). + */ + public function __construct(&$connection) + { + $this->conn = &$connection; + } + + /** + * Forward the method call to FTP functions + * + * @param string $function + * @param array $arguments + * @return mixed + * @throws FtpException When the function is not valid + */ + public function __call($function, array $arguments) + { + $function = 'ftp_' . $function; + + if (function_exists($function)) { + array_unshift($arguments, $this->conn); + return @call_user_func_array($function, $arguments); + } + + throw new FtpException("{$function} is not a valid FTP function"); + } + + /** + * Opens a FTP connection + * + * @param string $host + * @param int $port + * @param int $timeout + * @return resource + */ + public function connect($host, $port = 21, $timeout = 90) + { + return @ftp_connect($host, $port, $timeout); + } + + /** + * Opens a Secure SSL-FTP connection + * @param string $host + * @param int $port + * @param int $timeout + * @return resource + */ + public function ssl_connect($host, $port = 21, $timeout = 90) + { + return @ftp_ssl_connect($host, $port, $timeout); + } +} diff --git a/application/del.php b/application/del.php index 2f1d4df..3145b0f 100755 --- a/application/del.php +++ b/application/del.php @@ -18,12 +18,12 @@ if (empty($_REQUEST)) { $img = rand_imgurl() . '/public/images/404.png'; if (isset($_GET['url'])) { - $img = $_GET['url']; + $img = strip_tags($_GET['url']); } // 解密删除 if (isset($_GET['hash'])) { - $delHash = $_GET['hash']; + $delHash = strip_tags($_GET['hash']); $delHash = urlHash($delHash, 1); if ($config['image_recycl']) { @@ -51,6 +51,8 @@ if (isset($_GET['hash'])) { // 否则直接删除 getDel($delHash, 'url'); } + // FTP + // any_upload($delHash, null, 'delete'); } // 检查登录后再处理url删除请求 @@ -58,20 +60,24 @@ if (is_who_login('admin')) { // 广场页面删除 if (isset($_GET['url'])) { - getDel($_GET['url'], 'url'); + getDel(strip_tags($_GET['url']), 'url'); + // FTP + // any_upload(parse_url($_GET['url'])['path'], null, 'delete'); } // 从管理页面删除 if (isset($_GET['url_admin_inc'])) { - $del_url = $_GET['url_admin_inc']; + $del_url = strip_tags($_GET['url_admin_inc']); if ($config['hide_path']) { $del_url = $config['domain'] . $config['path'] . parse_url($del_url)['path']; } getDel($del_url, 'url'); + // FTP + // any_upload(parse_url($del_url)['path'], null, 'delete'); } // 回收 if (isset($_GET['recycle_url'])) { - $recycle_url = $_GET['recycle_url']; + $recycle_url = strip_tags($_GET['recycle_url']); $recycle_url = parse_url($recycle_url)['path']; if (file_exists(APP_ROOT . $recycle_url)) { checkImg($recycle_url, 3); @@ -95,18 +101,16 @@ if (is_who_login('admin')) { } } } else { - if (isset($_GET['url'])) { - echo ' - - '; - } + echo ' + + '; } ?>
diff --git a/application/function.php b/application/function.php index d5f7dc4..f476011 100755 --- a/application/function.php +++ b/application/function.php @@ -1696,7 +1696,14 @@ function auto_delete() return false; } -function write_login_log($user, $password, $messege) +/** + * 记录登录日志 + * @param String $user 登录用户 + * @param String $pass 登录密码 + * @param String $msg 登录提示 + */ + +function write_login_log($user, $pass, $msg) { $log_path = APP_ROOT . '/admin/logs/login/'; $log_file = $log_path . date('/Y-m-') . 'logs.php'; @@ -1706,6 +1713,48 @@ function write_login_log($user, $password, $messege) if (!is_file($log_file)) file_put_contents($log_file, '' . PHP_EOL, FILE_APPEND | LOCK_EX); /** 写入日志 */ - $log = '时间: ' . date('Y-m-d H:i:s') . ' IP: ' . real_ip() . ' 账号: ' . $user . ' 密码: ' . $password . ' 消息: ' . $messege; + $log = '时间: ' . date('Y-m-d H:i:s') . ' IP: ' . real_ip() . ' 账号: ' . $user . ' 密码: ' . $pass . ' 消息: ' . $msg; file_put_contents($log_file, $log . PHP_EOL, FILE_APPEND | LOCK_EX); } + +/** + * 其他上传 + * 支持: FTP + * @param String $remoteFile 远程地址 + * @param String $localFile 本地地址 + * @param String $way 使用方式 upload 上传 | delete 删除 + * + */ + +function any_upload($remoteFile = null, $localFile = null, $way = 'upload') +{ + global $config; + + if (!$config['ftp_status']) exit; + + require_once __DIR__ . '/FtpClient/FtpClient.php'; + require_once __DIR__ . '/FtpClient/FtpException.php'; + require_once __DIR__ . '/FtpClient/FtpWrapper.php'; + + $ftp = new FtpClient(); + // FTP 基本信息 + $ftp->connect($config['ftp_host'], $config['ftp_ssl'], $config['ftp_port'], $config['ftp_time']); + // FTP账号密码 + $ftp->login($config['ftp_user'], $config['ftp_pass']); + // FTP主动|被动 + $ftp->pasv($config['ftp_pasv']); + + switch ($way) { + case 'upload': + // 创建文件夹 + $ftp->mkdir(pathinfo($remoteFile, PATHINFO_DIRNAME), 0755, true); + // 上传文件 远端->本地 + $ftp->put($remoteFile, $localFile); + break; + case 'delete': + $ftp->delete($remoteFile); + return true; + break; + } + $ftp->close(); +} diff --git a/application/post_del.php b/application/post_del.php index 5a18a38..e998413 100755 --- a/application/post_del.php +++ b/application/post_del.php @@ -17,6 +17,8 @@ if (isset($_POST['del_url_array'])) { $del_num = count($del_url_array); for ($i = 0; $i < $del_num; $i++) { getDel($del_url_array[$i], 'url'); + // FTP + // any_upload($del_url_array[$i], null, 'delete'); } } diff --git a/application/upload.php b/application/upload.php index 16eb73c..1e19d5b 100755 --- a/application/upload.php +++ b/application/upload.php @@ -217,30 +217,19 @@ if ($handle->uploaded) { /** 后续处理 */ // 使用fastcgi_finish_request操作 - if (function_exists('fastcgi_finish_request')) { // fastcgi_finish_request 模式 - fastcgi_finish_request(); - // 同IP上传日志 - @write_ip_upload_count_logs(); - // 日志 - @write_upload_logs($pathIMG, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); - // 鉴黄 - @process_checkImg($processUrl); - // 水印 - @water($handle->file_dst_pathname); - // 压缩 - @process_compress($handle->file_dst_pathname); - } else { // 普通模式 - // 记录同IP上传次数 - @write_ip_upload_count_logs(); - // 日志 - @write_upload_logs($pathIMG, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); - // 鉴黄 - @process_checkImg($processUrl); - // 水印 - @water($handle->file_dst_pathname); - // 压缩 - @process_compress($handle->file_dst_pathname); - } + if (function_exists('fastcgi_finish_request')) fastcgi_finish_request(); + // 同IP上传日志 + @write_ip_upload_count_logs(); + // 日志 + @write_upload_logs($pathIMG, $handle->file_src_name, $handle->file_dst_pathname, $handle->file_src_size); + // 鉴黄 + @process_checkImg($processUrl); + // 水印 + @water($handle->file_dst_pathname); + // 压缩 + @process_compress($handle->file_dst_pathname); + // 上传至其他位置 + // @any_upload($pathIMG, APP_ROOT . $pathIMG, 'upload'); unset($handle); } diff --git a/config/config.php b/config/config.php index 83e7ff8..c9d274c 100755 --- a/config/config.php +++ b/config/config.php @@ -14,6 +14,14 @@ $config=Array 'imgurl'=>'http://127.0.0.1', 'user'=>'admin', 'password'=>'7676aaafb027c825bd9abab78b234070e702752f625b752e55e55b48e607e358', + 'ftp_status'=>0, + 'ftp_host'=>'', + 'ftp_port'=>21, + 'ftp_user'=>'', + 'ftp_pass'=>'', + 'ftp_pasv'=>1, + 'ftp_ssl'=>false, + 'ftp_time'=>30, 'captcha'=>0, 'mustLogin'=>0, 'apiStatus'=>0, @@ -122,5 +130,5 @@ $config=Array
', 'terms'=>'

服务条款


访问我们网站除主页和本“条款”页面以外的任何页面,即表示您同意这些使用条款和我们的隐私政策。如果您不同意,请不要使用我们的网站。

  1. 您使用我们的网站进行除简单访问/查看之外的任何事情(即上传、下载、评论等),不仅构成您的同意,而且构成您的电子签名,这意味着您受这些条款的合同约束,并且通过我们的隐私政策。
  2. 我们保留在使用过多带宽或以其他方式滥用系统的用户帐户上禁用直接链接的权利。
  3. 请勿上传儿童色情内容或威胁、骚扰、诽谤或鼓励非法行为的材料。不要使用本网站作为内容交付网络。如果你这样做(我们将成为法官),或者如果你做了任何违法的事情,除了我们可能拥有的任何其他合法权利之外,我们将禁止你以及你从中盗链的网站,删除你的所有图片,报告如有必要,您可以向当局报告,并阻止您查看本网站上托管的任何图像。我们是认真的。
  4. 用户必须同意遵守适用于其所在地的所有法律,包括版权和商标法。不允许使用侵犯版权或商标的图片。如果有人对您提出侵权索赔,您将被要求删除受版权保护的文件,直到问题得到解决。如果本网站的参与者之间存在争议,我们没有义务参与其中。
  5. 您可以匿名上传图像,并与您的朋友、家人、在线站点以及社交网络在线共享。
  6. 如果您在我们的网站上看到任何不应该出现的内容,因为它违反了我们的政策或出于任何其他原因,请通过电子邮件联系告知我们
  7. 声明通知中的信息准确无误,否则会受到伪证处罚。为此,请包括以下声明: “我发誓,通知中的信息准确无误,并且我是(版权)所有者或被授权代表专有权的所有者行事,在作伪证的处罚下涉嫌侵权”。

如果发生调查,本网站承诺与任何和所有法律机构合作。

隐私政策


一般:

当您访问本网站或使用本政策中进一步概述的服务(“服务”)时,本网站致力于保护您的隐私。作为使用本网站服务的条件,您同意向本网站提供某些个人信息。该信息包括但不限于: 电子邮件地址和您计算机的唯一 IP 地址(如果有)、财务信息(您的 Paypal 帐户使用的电子邮件地址)和人口统计信息(例如,邮政编码、邮政编码、家乡、性别、购买历史信息和年龄以及不是您计算机独有的 IP 地址)。请注意,我们不会在本网站的任何地方故意收集 13 岁以下儿童的联系信息或财务信息。请定期查看本隐私政策,因为我们可能会不时对其进行更新。本隐私政策的最后修订日期为 2021年10月25日。您每次访问本网站、使用服务或向我们提供信息时,即表示您当时接受本隐私政策中描述的做法。您同意,通过使用本网站,您明确并肯定地同意我们使用和披露您提供的信息,并同意接收电子邮件,如下面的隐私政策所述。

隐私政策变更:

随着新功能添加到网站或我们纳入用户的建议,本政策可能会随着时间的推移进行修订。如果我们打算以与我们收集信息时声明的方式大不相同的方式使用或披露您的个人身份信息,您将可以选择我们是否以这种新方式使用或披露您的信息。我们还将在我们的网站显着位置发布隐私政策已修订的通知,以便您可以随时查看我们收集的信息、我们将如何使用该信息以及在何种条件下我们将向任何人披露这些信息。

如何使用您的信息:

我们使用联系信息(即您的电子邮件地址)来帮助我们有效地执行帐户任务(更改密码、找回丢失的密码)、提供您请求的服务、执行质量保证、销售分析和其他业务分析,并就相关事宜与您联系与您向我们下的任何订单。除非满足任何法律、法规、政府要求或司法命令,否则不会将您的财务信息用于其他用途。当您通过本网站进行购买或在本网站注册时,您将向我们提供一个电子邮件地址,我们或这些服务提供商可能会出于本段所述目的与您联系。

联系您获取优惠和促销信息:

您同意,考虑到我们提供的服务的使用,允许我们使用您的个人信息向您发送营销和促销材料。我们也可能向您发送宣传第三方产品的营销和宣传材料。我们不会出租或出售您的个人信息以供第三方使用。这些材料可能包括但不限于: 向您提供有关如何使用服务的附加信息的时事通讯,以及来自我们或第三方的商品和服务的促销优惠。

人口统计信息的使用:

我们可能会使用您的人口统计信息进行业务分析或根据您的兴趣定制网站和通讯。我们可能会与广告商和其他第三方共享匿名的汇总人口统计信息,以便他们可以针对适当的受众定制广告和通信。在本隐私政策允许我们共享您的联系信息或财务信息的任何时候,我们也可能会同时共享您的人口统计信息。

向政府实体披露:

当我们确定此类披露是遵守法律、与执法部门合作或寻求执法协助或保护我们或网站其他访问者或用户的利益或安全时,我们可能会披露特定的联系信息。服务。此外,如果我们发生合并、收购、合并、剥离或破产,您的联系信息可能会传递给第三方。

Cookie 和其他网站跟踪数据的使用:

Cookies : “cookie”是我们保存在您计算机硬盘上的包含非个人信息的小文件。这些 cookie 有助于让您更快地访问您已经访问过的页面。它们还允许您个性化您的页面,并优化您在我们网站上的体验。我们还使用 cookie 来帮助我们了解有多少人访问了我们的网站、他们访问了我们的哪些网页以及他们在那里停留的时间。此信息可帮助我们确定我们的哪些网络功能非常成功以及哪些网站可能需要改进。您可以通过在浏览器的首选项或选项菜单中指明这一点来禁用计算机上的 cookie。大多数浏览器会自动接受 cookie,但允许您禁用它们。禁用 cookie 可能会阻止您正确使用服务或访问网站。

会话 ID:

“会话 ID”允许我们在多个网页请求中识别特定用户。此会话 ID 会尽可能保存在您的 cookie 文件中。如果 cookie 未启用,或者如果用户的 Internet 浏览器程序不支持 cookie,则我们将在请求的网页中放置会话 ID。这使最终用户不必为每个网页请求不断地重新输入某些信息,例如帐户名和密码。每当用户关闭其 Internet 浏览器时,此会话 ID 就会过期。

网站跟踪、报告:

我们的许多网页还包含特殊的电子图像(称为“单像素 gif”或“gif”),使我们能够仅收集非个人身份的流量统计数据和有关我们网站访问者的其他汇总信息。本站(通过自身或第三方)使用此技术收集和积累匿名数据,帮助我们了解和分析访问我们网站的人的体验,并连同您提供的其他信息,定制您未来的访问并改进我们的网站网站。例如,我们捕获有关所用浏览器类型、操作系统软件(例如 Windows 95 与 98 或 Macintosh)、cookie 偏好(用户是否打开或关闭它们)和搜索引擎关键字(哪些关键字做了什么)的数据。访问者用于访问我们的网站)。我们还记录了访问次数,所采取的路径,以及在我们网站内的站点和页面上花费的时间。请记住,这些信息都不是个人身份信息,我们只将这些信息分发给我们的内部员工以及与我们签署了保密协议的合作伙伴。我们与合作伙伴共享的任何信息都反映了整个网站或 Internet 使用趋势,而不是个别信息。

IP地址:

每次您访问本网站时,我们都会自动收集您的 IP 地址和您来自的网页。为了为您管理和优化站点并诊断我们站点的问题,我们使用您的 IP 地址来帮助识别您的身份并收集有关您的广泛人口统计信息。

来自其他网站的信息:

我们可能会放置指向其他方运营的其他网站的链接,并且可能会不时在我们的促销电子邮件中包含指向第三方网站的信息和链接。其中一些其他网站包含我们的品牌名称和商标以及我们拥有的其他知识产权;其他人没有。当您点击这些链接并访问这些其他网站时,无论它们是否包含我们的品牌名称、商标和其他知识产权,您都需要注意,我们不控制这些其他网站或这些其他网站”商业惯例,并且本隐私政策不适用于这些其他网站。因此,这些其他网站的运营商可能会收集有关您的不同类型的信息,并且可能以不同于我们在网站上收集信息的方式使用和披露该信息。我们鼓励您查看他们的隐私政策,并提醒您我们不对他们的行为负责。

信息存储:

您理解并同意我们在服务器上存储和处理您的信息,并且通过向我们提供任何数据,您同意将此类信息传输到网站服务器。当您从我们帐户中删除文件时,您与该文件之间将不再存在任何链接。删除的文件可能会缓存在我们服务器中以节省带宽,以防其他人请求它们。

如何联系我们:

如果您对您提交给我们这个隐私政策或信息有任何疑问,您可以通过邮件方式联系我们

数字千年版权法案


要向我们提交版权侵权通知,您需要发送书面通知,其中包含《数字千年版权法》第 512(c)(3) 条要求和规定的信息。

要撰写适当的 DMCA 通知,请说明以下信息:

  1. 表明自己是您认为受到侵犯的版权作品或专有权的所有者,或代表此类所有者行事的人,并提供物理签名(纸质形式时)或电子签名(电子形式时) )。
  2. 指明您认为受到侵权的受版权保护的作品,或者如果有大量作品受到侵权,请提供作品的代表性清单。
  3. 通过在我们站点上提供包含这些材料的 Web URL,确定侵犯您的版权作品的材料的位置。请不要发送附加的图像、pdf 或其他文件格式的文件,而只能发送包含我们网址的列表。在信函正文中提供所有 URL 是帮助我们快速处理您的请求的最佳方式。
  4. 说明您的联系信息,包括您的姓名、街道地址、电话号码和电子邮件地址。如果您代表版权所有者行事,请同时说明您与版权所有者的关系(例如律师、供应商、代理人)。
  5. 声明您“真诚地相信上述材料的使用未经版权所有者、其代理人或法律授权”。
  6. 声明通知中的信息准确无误,否则会受到伪证处罚。为此,请包括以下声明: “我发誓,通知中的信息准确无误,并且我是(版权)所有者或被授权代表专有权的所有者行事,在作伪证的处罚下涉嫌侵权”。
  7. 请用中文书写,所有电子邮件是任何其他语言都将被忽略。
  8. 要行使您的 DMCA 权利,您必须将适当的 DMCA 通知发送至我们的指定代理至电子邮件。

未能包含上述所有信息可能会导致 DMCA 通知的处理延迟。请注意,根据 DMCA 第 512(f) 条,任何故意歪曲材料或活动侵权的人都可能需要承担责任。

如果我们收到声称侵犯版权的适当通知,它将通过删除或禁止访问声称侵权或成为侵权活动主题的材料迅速做出回应。请注意,我们不一定会向报告者发送有关删除操作的确认。

', - 'update'=>'2023-03-05 10:59:24' + 'update'=>'2023-03-07 00:57:13' ); \ No newline at end of file diff --git a/index.php b/index.php index 4ca3944..2ebcdcf 100755 --- a/index.php +++ b/index.php @@ -130,7 +130,6 @@ mustLogin(); flash_swf_url: '/public/static/zui/lib/uploader/Moxie.xap', // sign multipart_params: { - // 'sign': new Date().format("YYYYMMddhh"), 'sign': new Date().format("YYYYMMddhh"), }, // 预览图尺寸