Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
@@ -11,16 +11,20 @@
|
||||
namespace IPS\Ftp;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use RuntimeException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* FTP Class
|
||||
*/
|
||||
class _Exception extends \RuntimeException
|
||||
class Exception extends RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
+69
-63
@@ -11,41 +11,47 @@
|
||||
namespace IPS;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use FTP\Connection;
|
||||
use IPS\Ftp\Exception;
|
||||
use function defined;
|
||||
use function function_exists;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* FTP Class
|
||||
*/
|
||||
class _Ftp
|
||||
class Ftp
|
||||
{
|
||||
/**
|
||||
* @brief Connection resource
|
||||
*/
|
||||
protected $ftp;
|
||||
protected ?Connection $ftp = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $host Hostname
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @param int $port Port
|
||||
* @param bool $secure Use secure SSL-FTP connection?
|
||||
* @param int $timeout Timeout (in seconds)
|
||||
* @param string $host Hostname
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @param int $port Port
|
||||
* @param bool $secure Use secure SSL-FTP connection?
|
||||
* @param int $timeout Timeout (in seconds)
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct( $host, $username, $password, $port=21, $secure=FALSE, $timeout=10 )
|
||||
public function __construct( string $host, string $username, string $password, int $port=21, bool $secure = false, int $timeout=10 )
|
||||
{
|
||||
if ( $secure )
|
||||
{
|
||||
if( !\function_exists('ftp_ssl_connect') )
|
||||
if( !function_exists('ftp_ssl_connect') )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'SSL_NOT_AVAILABLE' );
|
||||
throw new Exception( 'SSL_NOT_AVAILABLE' );
|
||||
}
|
||||
|
||||
$this->ftp = @ftp_ssl_connect( $host, $port, $timeout );
|
||||
@@ -57,11 +63,11 @@ class _Ftp
|
||||
|
||||
if ( $this->ftp === FALSE )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_CONNECT' );
|
||||
throw new Exception( 'COULD_NOT_CONNECT' );
|
||||
}
|
||||
if ( !@ftp_login( $this->ftp, $username, $password ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_LOGIN' );
|
||||
throw new Exception( 'COULD_NOT_LOGIN' );
|
||||
}
|
||||
|
||||
/* Typically if passive mode is required, ftp_nlist will return FALSE instead of an array */
|
||||
@@ -87,15 +93,15 @@ class _Ftp
|
||||
/**
|
||||
* chdir
|
||||
*
|
||||
* @param string $dir Directory
|
||||
* @param string $dir Directory
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function chdir( $dir )
|
||||
public function chdir( string $dir ) : void
|
||||
{
|
||||
if ( !@ftp_chdir( $this->ftp, $dir ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_CHDIR' );
|
||||
throw new Exception( 'COULD_NOT_CHDIR' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,38 +109,38 @@ class _Ftp
|
||||
* cdup
|
||||
*
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function cdup()
|
||||
public function cdup() : void
|
||||
{
|
||||
if ( !@ftp_cdup( $this->ftp ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_CDUP' );
|
||||
throw new Exception( 'COULD_NOT_CDUP' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mkdir
|
||||
*
|
||||
* @param string $dir Directory
|
||||
* @param string $dir Directory
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function mkdir( $dir )
|
||||
public function mkdir( string $dir ) : void
|
||||
{
|
||||
if ( !@ftp_mkdir( $this->ftp, $dir ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_MKDIR' );
|
||||
throw new Exception( 'COULD_NOT_MKDIR' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ls
|
||||
*
|
||||
* @param string $path Argument to pass to ftp_nlist
|
||||
* @param string $path Argument to pass to ftp_nlist
|
||||
* @return array|bool
|
||||
*/
|
||||
public function ls( $path = '.' )
|
||||
public function ls( string $path = '.' ): bool|array
|
||||
{
|
||||
return ftp_nlist( $this->ftp, $path );
|
||||
}
|
||||
@@ -142,11 +148,11 @@ class _Ftp
|
||||
/**
|
||||
* Raw list
|
||||
*
|
||||
* @param string $path Argument to pass to ftp_nlist
|
||||
* @param bool $recursive Whether or not to list recursively
|
||||
* @param string $path Argument to pass to ftp_nlist
|
||||
* @param bool $recursive Whether or not to list recursively
|
||||
* @return array
|
||||
*/
|
||||
public function rawList( $path = '.', $recursive = FALSE )
|
||||
public function rawList( string $path = '.', bool $recursive = false ): array
|
||||
{
|
||||
return ftp_rawlist( $this->ftp, $path, $recursive );
|
||||
}
|
||||
@@ -154,40 +160,40 @@ class _Ftp
|
||||
/**
|
||||
* Upload File
|
||||
*
|
||||
* @param string $filename Filename to use
|
||||
* @param string $file Path to local file
|
||||
* @param string $filename Filename to use
|
||||
* @param string $file Path to local file
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function upload( $filename, $file )
|
||||
public function upload( string $filename, string $file ) : void
|
||||
{
|
||||
if ( !@ftp_put( $this->ftp, $filename, $file, FTP_BINARY ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_UPLOAD' );
|
||||
throw new Exception( 'COULD_NOT_UPLOAD' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download File
|
||||
*
|
||||
* @param string $filename The file to download
|
||||
* @param string|null $target Location to save downloaded file or NULL to return contents
|
||||
* @param bool $returnPath Return the path to the downloaded file instead of the contents
|
||||
* @return string File contents
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @param string $filename The file to download
|
||||
* @param string|null $target Location to save downloaded file or NULL to return contents
|
||||
* @param bool $returnPath Return the path to the downloaded file instead of the contents
|
||||
* @return string|null File contents
|
||||
* @throws Exception
|
||||
*/
|
||||
public function download( $filename, $target=NULL, $returnPath=FALSE )
|
||||
public function download( string $filename, ?string $target=NULL, bool $returnPath = false ): ?string
|
||||
{
|
||||
$temp = FALSE;
|
||||
if ( $target === NULL )
|
||||
{
|
||||
$temp = TRUE;
|
||||
$target = tempnam( \IPS\TEMP_DIRECTORY, 'IPS' );
|
||||
$target = tempnam( TEMP_DIRECTORY, 'IPS' );
|
||||
}
|
||||
|
||||
if ( !@ftp_get( $this->ftp, $target, $filename, FTP_BINARY ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_DOWNLOAD' );
|
||||
throw new Exception( 'COULD_NOT_DOWNLOAD' );
|
||||
}
|
||||
|
||||
/* We use this to avoid out of memory errors - just return path */
|
||||
@@ -209,41 +215,41 @@ class _Ftp
|
||||
/**
|
||||
* CHMOD
|
||||
*
|
||||
* @param string $filename The file to CHMOD
|
||||
* @param int $mode Mode (in octal form)
|
||||
* @return @e void
|
||||
* @param string $filename The file to CHMOD
|
||||
* @param int $mode Mode (in octal form)
|
||||
* @return void
|
||||
* @throws Exception CHMOD_ERROR
|
||||
*/
|
||||
public function chmod( $filename, $mode )
|
||||
public function chmod( string $filename, int $mode ) : void
|
||||
{
|
||||
if( !@ftp_chmod( $this->ftp, $mode, $filename ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'CHMOD_ERROR' );
|
||||
throw new Exception( 'CHMOD_ERROR' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file
|
||||
*
|
||||
* @param string $file Path to file
|
||||
* @param string $file Path to file
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete( $file )
|
||||
public function delete( string $file ) : void
|
||||
{
|
||||
if ( !@ftp_delete( $this->ftp, $file ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_DELETE' );
|
||||
throw new Exception( 'COULD_NOT_DELETE' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file size (if possible)
|
||||
*
|
||||
* @param string $file Path to file
|
||||
* @return float
|
||||
* @param string $file Path to file
|
||||
* @return float|int
|
||||
*/
|
||||
public function size( $file )
|
||||
public function size( string $file ): float|int
|
||||
{
|
||||
$size = @ftp_size( $this->ftp, $file );
|
||||
|
||||
@@ -265,12 +271,12 @@ class _Ftp
|
||||
/**
|
||||
* Delete directory
|
||||
*
|
||||
* @param string $dir Path to directory
|
||||
* @param bool $recursive Recursive? (If FALSE and directory is not empty, operation will fail)
|
||||
* @param string $dir Path to directory
|
||||
* @param bool $recursive Recursive? (If FALSE and directory is not empty, operation will fail)
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rmdir( $dir, $recursive=FALSE )
|
||||
public function rmdir( string $dir, bool $recursive=FALSE ) : void
|
||||
{
|
||||
if ( $recursive )
|
||||
{
|
||||
@@ -282,7 +288,7 @@ class _Ftp
|
||||
{
|
||||
if ( $matches[1] === 'd' )
|
||||
{
|
||||
$this->rmdir( $matches[2], TRUE );
|
||||
$this->rmdir($matches[2], TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -295,7 +301,7 @@ class _Ftp
|
||||
|
||||
if ( !@ftp_rmdir( $this->ftp, $dir ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_DELETE' );
|
||||
throw new Exception( 'COULD_NOT_DELETE' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,21 @@
|
||||
namespace IPS\Ftp;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use InvalidArgumentException;
|
||||
use SplFileInfo;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* FTP file information iterator
|
||||
*/
|
||||
class _FtpSplFileInfo extends \SplFileInfo
|
||||
class FtpSplFileInfo extends SplFileInfo
|
||||
{
|
||||
/**
|
||||
* @brief Type: Unknown
|
||||
@@ -45,26 +50,26 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
/**
|
||||
* @brief Current item type
|
||||
*/
|
||||
protected $type = self::TYPE_DIRECTORY;
|
||||
protected int $type = self::TYPE_DIRECTORY;
|
||||
|
||||
/**
|
||||
* @brief Current directory
|
||||
*/
|
||||
protected $directory = '/';
|
||||
protected mixed $directory = '/';
|
||||
|
||||
/**
|
||||
* @brief Current filename
|
||||
*/
|
||||
protected $filename = '.';
|
||||
protected mixed $filename = '.';
|
||||
|
||||
/**
|
||||
* Constructor: Create a new spl file info object
|
||||
*
|
||||
* @param string $file Filename or directory name
|
||||
* @param string $type The type of item passed
|
||||
* @param int $type The type of item passed
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( $file, $type = self::TYPE_DIRECTORY )
|
||||
public function __construct( string $file, int $type = self::TYPE_DIRECTORY )
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
@@ -81,7 +86,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
$this->directory = $tmp['directory'];
|
||||
}
|
||||
|
||||
return parent::__construct( $this->getPathname() );
|
||||
parent::__construct( $this->getPathname() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +94,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDir()
|
||||
public function isDir(): bool
|
||||
{
|
||||
return ( $this->type === self::TYPE_DIRECTORY );
|
||||
}
|
||||
@@ -99,7 +104,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFile()
|
||||
public function isFile(): bool
|
||||
{
|
||||
return ( $this->type === self::TYPE_FILE );
|
||||
}
|
||||
@@ -107,9 +112,9 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
/**
|
||||
* Return the type
|
||||
*
|
||||
* @return int
|
||||
* @return string|false
|
||||
*/
|
||||
public function getType()
|
||||
public function getType(): string|false
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
@@ -119,7 +124,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPath()
|
||||
public function getPath(): string
|
||||
{
|
||||
return $this->directory;
|
||||
}
|
||||
@@ -129,7 +134,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilename()
|
||||
public function getFilename(): string
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
@@ -139,7 +144,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPathname()
|
||||
public function getPathname(): string
|
||||
{
|
||||
if( $this->isDir() )
|
||||
{
|
||||
@@ -157,7 +162,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
* @param string $file The filename or directory name
|
||||
* @return string
|
||||
*/
|
||||
public function getItemname( $file )
|
||||
public function getItemname( string $file ): string
|
||||
{
|
||||
if( $this->directory === '/' AND $file === '.' )
|
||||
{
|
||||
@@ -173,7 +178,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
* @param mixed $item The item we are parsing, which could be a file or directory (or unknown)
|
||||
* @return int
|
||||
*/
|
||||
public static function getTypeFromRaw( $item )
|
||||
public static function getTypeFromRaw( mixed $item ): int
|
||||
{
|
||||
if( $item === '' )
|
||||
{
|
||||
@@ -199,20 +204,20 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
/**
|
||||
* Parse a raw list item to extract the needed information
|
||||
*
|
||||
* @param string $file The item we are parsing, which could be a file or directory (or unknown)
|
||||
* @param string $file The item we are parsing, which could be a file or directory (or unknown)
|
||||
* @return array ( 'filename' => ..., 'directory' => ... )
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function parseFile( $file = '/' )
|
||||
public static function parseFile( string $file = '/' ): array
|
||||
{
|
||||
if( mb_strpos( $file, '/' ) !== 0 )
|
||||
{
|
||||
throw new \InvalidArgumentException( sprintf( 'File "%s" does not start with a /', $file ) );
|
||||
throw new InvalidArgumentException( sprintf( 'File "%s" does not start with a /', $file ) );
|
||||
}
|
||||
|
||||
if( mb_strlen( $file ) < 2 )
|
||||
{
|
||||
throw new \InvalidArgumentException( sprintf( 'File "%s" must contain at least two characters', $file ) );
|
||||
throw new InvalidArgumentException( sprintf( 'File "%s" must contain at least two characters', $file ) );
|
||||
}
|
||||
|
||||
$pathBreak = mb_strrpos( $file, '/' );
|
||||
@@ -228,7 +233,7 @@ class _FtpSplFileInfo extends \SplFileInfo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->getPathname();
|
||||
}
|
||||
|
||||
@@ -11,46 +11,52 @@
|
||||
namespace IPS\Ftp;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use InvalidArgumentException;
|
||||
use IPS\Ftp;
|
||||
use RecursiveIterator;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive directory FTP iterator
|
||||
*/
|
||||
class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements \RecursiveIterator
|
||||
class RecursiveDirectoryFtpIterator extends FtpSplFileInfo implements RecursiveIterator
|
||||
{
|
||||
/**
|
||||
* @brief Holds an array of iterable objects
|
||||
*/
|
||||
public $contents = NULL;
|
||||
public ?array $contents = NULL;
|
||||
|
||||
/**
|
||||
* @brief The FTP class holding our connection
|
||||
*/
|
||||
protected $ftpObject = NULL;
|
||||
protected ?Ftp $ftpObject = NULL;
|
||||
|
||||
/**
|
||||
* @brief Flag to store whether the iterator has been rewound
|
||||
*/
|
||||
protected $rewound = FALSE;
|
||||
protected bool $rewound = FALSE;
|
||||
|
||||
/**
|
||||
* Constructor: Create a new recursive FTP directory iterator
|
||||
*
|
||||
* @param \IPS\Ftp $ftp The FTP object handle
|
||||
* @param string $file The filename or directory
|
||||
* @param Ftp $ftp The FTP object handle
|
||||
* @param string $file The filename or directory
|
||||
* @param int $type The type of item passed
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct( $ftp, $file, $type = self::TYPE_DIRECTORY )
|
||||
public function __construct( Ftp $ftp, string $file, int $type = self::TYPE_DIRECTORY )
|
||||
{
|
||||
$this->ftpObject = $ftp;
|
||||
|
||||
return parent::__construct( $file, $type );
|
||||
parent::__construct( $file, $type );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,9 +64,9 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function getChildren()
|
||||
public function getChildren(): RecursiveDirectoryFtpIterator|static
|
||||
{
|
||||
return new \IPS\Ftp\RecursiveDirectoryFtpIterator( $this->ftpObject, $this->current()->getPath() );
|
||||
return new RecursiveDirectoryFtpIterator( $this->ftpObject, $this->current()->getPath() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +74,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasChildren()
|
||||
public function hasChildren(): bool
|
||||
{
|
||||
return $this->current()->isDir();
|
||||
}
|
||||
@@ -78,7 +84,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function current()
|
||||
public function current(): mixed
|
||||
{
|
||||
return current( $this->contents );
|
||||
}
|
||||
@@ -88,7 +94,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function key()
|
||||
public function key(): string
|
||||
{
|
||||
return $this->current()->getPathname();
|
||||
}
|
||||
@@ -96,9 +102,9 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
/**
|
||||
* Advance to the next item
|
||||
*
|
||||
* @return mixed
|
||||
* @return void
|
||||
*/
|
||||
public function next()
|
||||
public function next(): void
|
||||
{
|
||||
next( $this->contents );
|
||||
}
|
||||
@@ -108,14 +114,14 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rewind()
|
||||
public function rewind() : void
|
||||
{
|
||||
/* Change to the appropriate directory */
|
||||
$this->ftpObject->chdir( $this->getPath() );
|
||||
|
||||
/* Fetch our names and the raw listing */
|
||||
$names = $this->ftpObject->ls( $this->getFilename() );
|
||||
$types = $this->ftpObject->rawList( $this->getFilename() );
|
||||
$types = $this->ftpObject->rawList($this->getFilename());
|
||||
|
||||
/* Reset our contents array */
|
||||
$this->contents = array();
|
||||
@@ -128,7 +134,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->contents[] = new \IPS\Ftp\RecursiveDirectoryFtpIterator( $this->ftpObject, $this->getItemname( $name ), static::getTypeFromRaw( $types[ $k ] ) );
|
||||
$this->contents[] = new RecursiveDirectoryFtpIterator( $this->ftpObject, $this->getItemname( $name ), static::getTypeFromRaw( $types[ $k ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +143,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
if( !$this->rewound )
|
||||
{
|
||||
@@ -145,7 +151,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
$this->rewound = TRUE;
|
||||
}
|
||||
|
||||
return ( $this->current() instanceof \IPS\Ftp\FtpSplFileInfo );
|
||||
return ( $this->current() instanceof FtpSplFileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +159,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubPath()
|
||||
public function getSubPath(): string
|
||||
{
|
||||
return $this->getPath();
|
||||
}
|
||||
@@ -163,7 +169,7 @@ class _RecursiveDirectoryFtpIterator extends \IPS\Ftp\FtpSplFileInfo implements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubPathname()
|
||||
public function getSubPathname(): string
|
||||
{
|
||||
return $this->getPathname();
|
||||
}
|
||||
|
||||
+72
-65
@@ -11,16 +11,24 @@
|
||||
namespace IPS\Ftp;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use BadMethodCallException;
|
||||
use IPS\Ftp;
|
||||
use function defined;
|
||||
use function extension_loaded;
|
||||
use function in_array;
|
||||
use const IPS\TEMP_DIRECTORY;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* SFTP Class
|
||||
*/
|
||||
class _Sftp extends \IPS\Ftp
|
||||
class Sftp extends Ftp
|
||||
{
|
||||
/**
|
||||
* @brief SSH2 Connection resource
|
||||
@@ -35,58 +43,58 @@ class _Sftp extends \IPS\Ftp
|
||||
/**
|
||||
* @brief Current Directory
|
||||
*/
|
||||
protected $dir;
|
||||
protected string $dir;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $host Hostname
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @param int $port Port
|
||||
* @param string $host Hostname
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @param int $port Port
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws \BadMethodCallException If server does not have ssh
|
||||
* @throws Exception
|
||||
* @throws BadMethodCallException If server does not have ssh
|
||||
*/
|
||||
public function __construct( $host, $username, $password, $port=22 )
|
||||
public function __construct( string $host, string $username, string $password, int $port=22 )
|
||||
{
|
||||
if ( !\extension_loaded( 'ssh2' ) )
|
||||
if ( !extension_loaded( 'ssh2' ) )
|
||||
{
|
||||
throw new \BadMethodCallException;
|
||||
throw new BadMethodCallException;
|
||||
}
|
||||
|
||||
$this->ssh = ssh2_connect( $host, $port );
|
||||
if ( $this->ssh === FALSE )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_CONNECT' );
|
||||
throw new Exception( 'COULD_NOT_CONNECT' );
|
||||
}
|
||||
|
||||
if ( !@ssh2_auth_password( $this->ssh, $username, $password ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_LOGIN' );
|
||||
throw new Exception( 'COULD_NOT_LOGIN' );
|
||||
}
|
||||
|
||||
$this->sftp = @ssh2_sftp( $this->ssh );
|
||||
if ( $this->sftp === FALSE )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_CONNECT' );
|
||||
throw new Exception( 'COULD_NOT_CONNECT' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* chdir
|
||||
*
|
||||
* @param string $dir Directory
|
||||
* @param string $dir Directory
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function chdir( $dir )
|
||||
public function chdir( string $dir ) : void
|
||||
{
|
||||
$dir = mb_substr( $dir, 0, 1 ) === '/' ? $dir : ( $this->dir . $dir );
|
||||
|
||||
if ( $dir and !@ssh2_sftp_stat( $this->sftp, $dir ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_CHDIR' );
|
||||
throw new Exception( 'COULD_NOT_CHDIR' );
|
||||
}
|
||||
|
||||
$this->dir = ssh2_sftp_realpath( $this->sftp, $dir ) . '/';
|
||||
@@ -96,9 +104,9 @@ class _Sftp extends \IPS\Ftp
|
||||
* cdup
|
||||
*
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function cdup()
|
||||
public function cdup() : void
|
||||
{
|
||||
$this->chdir( mb_substr( $this->dir, 0, mb_strrpos( mb_substr( $this->dir, 0, -1 ), '/' ) ) );
|
||||
}
|
||||
@@ -106,31 +114,31 @@ class _Sftp extends \IPS\Ftp
|
||||
/**
|
||||
* mkdir
|
||||
*
|
||||
* @param string $dir Directory
|
||||
* @param string $dir Directory
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function mkdir( $dir )
|
||||
public function mkdir( string $dir ) : void
|
||||
{
|
||||
if ( !@ssh2_sftp_mkdir( $this->sftp, $this->dir . $dir ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_MKDIR' );
|
||||
throw new Exception( 'COULD_NOT_MKDIR' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ls
|
||||
*
|
||||
* @param string $path Path
|
||||
* @param string $path Path
|
||||
* @return array|bool
|
||||
*/
|
||||
public function ls( $path = '' )
|
||||
public function ls( string $path = '' ): bool|array
|
||||
{
|
||||
$return = array();
|
||||
$handle = opendir("ssh2.sftp://{$this->sftp}/{$this->dir}");
|
||||
while( $entry = readdir( $handle ) )
|
||||
{
|
||||
if ( !\in_array( $entry, array( '.', '..' ) ) )
|
||||
if ( !in_array( $entry, array( '.', '..' ) ) )
|
||||
{
|
||||
$return[] = $entry;
|
||||
}
|
||||
@@ -141,17 +149,17 @@ class _Sftp extends \IPS\Ftp
|
||||
/**
|
||||
* Raw list
|
||||
*
|
||||
* @param string $path The path
|
||||
* @param bool $recursive Whether or not to recursively list
|
||||
* @param string $path The path
|
||||
* @param bool $recursive Whether or not to recursively list
|
||||
* @return array
|
||||
*/
|
||||
public function rawList( $path = '.', $recursive = FALSE )
|
||||
public function rawList( string $path = '.', bool $recursive=FALSE ): array
|
||||
{
|
||||
$return = array();
|
||||
$handle = opendir("ssh2.sftp://{$this->sftp}/{$this->dir}");
|
||||
while( $entry = readdir( $handle ) )
|
||||
{
|
||||
if ( !\in_array( $entry, array( '.', '..' ) ) )
|
||||
if ( !in_array( $entry, array( '.', '..' ) ) )
|
||||
{
|
||||
$bits = array();
|
||||
$stats = @ssh2_sftp_stat( $this->sftp, $this->dir . $entry );
|
||||
@@ -192,10 +200,10 @@ class _Sftp extends \IPS\Ftp
|
||||
}
|
||||
|
||||
$bits[] = ( is_dir("ssh2.sftp://{$this->sftp}/{$this->dir}/{$entry}") ? 'd' : '-' ) . $perms;
|
||||
$bits[] = isset( $stats['nlink'] ) ? $stats['nlink'] : 0;
|
||||
$bits[] = isset( $stats['uid'] ) ? $stats['uid'] : 0;
|
||||
$bits[] = isset( $stats['gid'] ) ? $stats['gid'] : 0;
|
||||
$bits[] = isset( $stats['size'] ) ? $stats['size'] : 0;
|
||||
$bits[] = $stats['nlink'] ?? 0;
|
||||
$bits[] = $stats['uid'] ?? 0;
|
||||
$bits[] = $stats['gid'] ?? 0;
|
||||
$bits[] = $stats['size'] ?? 0;
|
||||
$bits[] = isset( $stats['mtime'] ) ? date( 'd M H:i', $stats['mtime'] ) : 0;
|
||||
$bits[] = $entry;
|
||||
|
||||
@@ -208,40 +216,39 @@ class _Sftp extends \IPS\Ftp
|
||||
/**
|
||||
* Upload File
|
||||
*
|
||||
* @param string $filename Filename to use
|
||||
* @param string $file Path to local file
|
||||
* @param string $filename Filename to use
|
||||
* @param string $file Path to local file
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function upload( $filename, $file )
|
||||
public function upload( string $filename, string $file ) : void
|
||||
{
|
||||
if ( !@ssh2_scp_send( $this->ssh, $file, $this->dir . $filename ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_UPLOAD' );
|
||||
throw new Exception( 'COULD_NOT_UPLOAD' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Download File
|
||||
*
|
||||
* @param string $filename The file to download
|
||||
* @param string|null $target Location to save downloaded file or NULL to return contents
|
||||
* @param bool $returnPath Return the path to the downloaded file instead of the contents
|
||||
* @return string File contents
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @param string $filename The file to download
|
||||
* @param string|null $target Location to save downloaded file or NULL to return contents
|
||||
* @param bool $returnPath Return the path to the downloaded file instead of the contents
|
||||
* @return string|null File contents
|
||||
*/
|
||||
public function download( $filename, $target=NULL, $returnPath=FALSE )
|
||||
public function download( string $filename, string $target=NULL, bool $returnPath=FALSE ): ?string
|
||||
{
|
||||
$temp = FALSE;
|
||||
if ( $target === NULL )
|
||||
{
|
||||
$temp = TRUE;
|
||||
$target = tempnam( \IPS\TEMP_DIRECTORY, 'IPS' );
|
||||
$target = tempnam( TEMP_DIRECTORY, 'IPS' );
|
||||
}
|
||||
|
||||
if ( !@ssh2_scp_recv( $this->ssh, $this->dir . $filename, $target ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_DOWNLOAD' );
|
||||
throw new Exception( 'COULD_NOT_DOWNLOAD' );
|
||||
}
|
||||
|
||||
/* We use this to avoid out of memory errors - just return path */
|
||||
@@ -263,25 +270,25 @@ class _Sftp extends \IPS\Ftp
|
||||
/**
|
||||
* Delete file
|
||||
*
|
||||
* @param string $file Path to file
|
||||
* @param string $file Path to file
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete( $file )
|
||||
public function delete( string $file ) : void
|
||||
{
|
||||
if ( !@ssh2_sftp_unlink( $this->sftp, $this->dir . $file ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_DELETE' );
|
||||
throw new Exception( 'COULD_NOT_DELETE' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file size (if possible)
|
||||
*
|
||||
* @param string $file Path to file
|
||||
* @return float
|
||||
* @param string $file Path to file
|
||||
* @return float|int
|
||||
*/
|
||||
public function size( $file )
|
||||
public function size( string $file ): float|int
|
||||
{
|
||||
if( $stats = @ssh2_sftp_stat( $this->sftp, $this->dir . $file ) )
|
||||
{
|
||||
@@ -297,24 +304,24 @@ class _Sftp extends \IPS\Ftp
|
||||
/**
|
||||
* Delete directory
|
||||
*
|
||||
* @param string $dir Path to directory
|
||||
* @param bool $recursive Recursive? (If FALSE and directory is not empty, operation will fail)
|
||||
* @param string $dir Path to directory
|
||||
* @param bool $recursive Recursive? (If FALSE and directory is not empty, operation will fail)
|
||||
* @return void
|
||||
* @throws \IPS\Ftp\Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rmdir( $dir, $recursive=FALSE )
|
||||
public function rmdir( string $dir, bool $recursive=FALSE ) : void
|
||||
{
|
||||
if ( $recursive )
|
||||
{
|
||||
$this->chdir( $dir );
|
||||
foreach ( $this->rawList() as $data )
|
||||
foreach ($this->rawList() as $data )
|
||||
{
|
||||
preg_match( '/^(.).*\s(.*)$/', $data, $matches );
|
||||
if ( $matches[2] !== '.' and $matches[2] !== '..' )
|
||||
{
|
||||
if ( $matches[1] === 'd' )
|
||||
{
|
||||
$this->rmdir( $matches[2], TRUE );
|
||||
$this->rmdir($matches[2], TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -327,7 +334,7 @@ class _Sftp extends \IPS\Ftp
|
||||
|
||||
if ( !@ssh2_sftp_rmdir( $this->sftp, $this->dir . $dir ) )
|
||||
{
|
||||
throw new \IPS\Ftp\Exception( 'COULD_NOT_DELETE' );
|
||||
throw new Exception( 'COULD_NOT_DELETE' );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user