class ftp_sftp{
//determine,if ssh,to use PHPseclib or PHP's inbuilt ssh_sftp 'libssh'
public $ssh_type = 'PHPseclib';
//set ths path to the directory containing the entire PHPseclib files
public $PHPseclib_path = 'scripts/PHPseclib0.3.0';
//private vars generated by this class
public $host;
public $username;
public $password;
public $connection_type;
public $port_number;
public $connection = false;
//contruct method which will attempt to set the connection details and automatically attempt to establisha connection to the server
public function __construct( $host,$username,$password,$connection_type,$port_number = false ){
//add the webroot to the beginning of the $this->PHPseclib_path (this is bespoke to my own configuration)
$this->PHPseclib_path = WEbroOT_PRIVATE.$this->PHPseclib_path;
//setting the classes vars
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->connection_type = $connection_type;
//set the port number to defaults based on connection type if none passed
if( $port_number === false ){
if( $connection_type == 'ftp' ){
$port_number = 21;
} else {
$port_number = 22;
}
}
$this->port_number = $port_number;
//Now set the server connection into this classes connection var
$this->connection = $this->connect();
}
//tests the details passed and tries to establish a connection,returns false on fail.
function connect(){
br($this->connection_type);
switch( $this->connection_type )
{
case 'ftp':
$connection = ftp_connect($this->host);
$login = ftp_login($connection,$this->username,$this->password);
//if no connection was possible return false and leave $this-connection as false
if(!$connection || !$login){
return false;
} else {
// enabling passive mode
ftp_pasv( $connection,true );
return $connection;
}
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
//inlcude the PHPseclib path in the include array and include the ssh2 class
set_include_path($this->PHPseclib_path );
if(!include('Net/SSH2.PHP')){
echo 'Sorry Failed to load SSH2 class';
br();
}
if(!include('Net/SFTP.PHP')){
echo 'Sorry Failed to load SFTP class';
br();
}
$connection = new Net_SFTP($this->host,$this->port_number);
$login = $connection->login($this->username,$this->password);
break;
case 'libssh2':
$connection = ssh2_connect($this->host,$this->port_number);
$login = ssh2_auth_password($connection,'username','secret');
break;
default:
echo 'No ssh method defined,please define one in: $ftp_sftp->ssh_type';
exit();
break;
}
//if no connection was possible return false and leave $this-connection as false
if (!$connection || !$login) {
return false;
} else {
return $connection;
}
break;
default: echo 'No connection type set cannot choose a method to connect';
break;
}
}
//acces the PHPseclib errors
public function errors(){
if($this->connection_type == 'sftp' && $this->ssh_type == 'PHPseclib'){
print_r($this->connection->getErrors());
} else {
echo 'no error logs available';
}
}
//function used by this class to check certain values are set
public function connection_check(){
if( $this->connection === false){
echo 'Sorry there seems to be a connection problem please try again';
br();
}
if( $this->connection_type === false){
echo 'Sorry there seems to be a no connection type set';
}
if( $this->connection === false || $this->connection_type === false ){
exit();
}
}
//transfers a file to the connected server
public function put($targetLocationToSendTo,$existingLocationToSendFrom){
//check the connection
$this->connection_check();
switch( $this->connection_type )
{
case 'ftp':
//ftp_put the file across
$put = ftp_put( $this->connection,$targetLocationToSendTo,$existingLocationToSendFrom,FTP_BINARY);
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
$put = $this->connection->put( $targetLocationToSendTo,NET_SFTP_LOCAL_FILE );
break;
case 'libssh2':
$put = ssh2_scp_send($this->connection,0755);
break;
}
break;
}
return $put;
}
//list the contents of a remote directory
public function dir_list( $dirToList ){
//check the connection
$this->connection_check();
//run appropriate list
switch( $this->connection_type )
{
case 'ftp':
$list = $this->connection = ftp_nlist($this->connection,$dirToList);
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
$list = $this->connection->nlist( $dirToList );
break;
case 'libssh2':
echo 'Sorry there is no support for nlist with libssh2,however this link has a possible answer: http://randomdrake.com/2012/02/08/listing-and-downloading-files-over-sftp-with-PHP-and-ssh2/';
break;
}
break;
}
return $list;
}
//get the timestamp of the file on another server
public function remote_filemtime( $pathToFile ){
//check the connection
$this->connection_check();
//run appropriate list
switch( $this->connection_type )
{
case 'ftp':
$timeStamp = ftp_mdtm($this->connection,$pathToFile);
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
$statinfo = $this->connection->stat( $pathToFile );
break;
case 'libssh2':
$statinfo = ssh2_sftp_stat($this->connection,$pathToFile);
break;
}
if($statinfo['mtime']){
$timeStamp = $statinfo['mtime'];
} else {
$timeStamp = false;
}
break;
}
return $timeStamp;
}
//make a directory on the Remote Server
public function make_dir( $dirTomake ){
//check the connection
$this->connection_check();
//run appropriate list
switch( $this->connection_type )
{
case 'ftp':
$dir_made = ftp_mkdir($this->connection,$dirTomake);
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
$statinfo = $this->connection->mkdir( $dirTomake );
break;
case 'libssh2':
$statinfo = ssh2_sftp_mkdir($this->connection,$dirTomake,0755);
break;
}
break;
}
return $dir_made;
}
//change directory
public function change_dir( $dirToMoveto ){
//check the connection
$this->connection_check();
//run appropriate list
switch( $this->connection_type )
{
case 'ftp': $chdir = ftp_chdir($this->connection,$dirToMoveto );
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
$chdir = $this->connection->chdir( $dirToMoveto );
break;
case 'libssh2':
echo 'Sorry this feature does exist yet for when using libssh2 with the ftp_sftp class';
exit();
break;
}
break;
}
return $chdir;
}
//curent directory we are looking in
public function pwd(){
//check the connection
$this->connection_check();
//run appropriate list
switch( $this->connection_type )
{
case 'ftp': $pwd = ftp_pwd($this->connection);
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
$pwd = $this->connection->pwd();
break;
case 'libssh2':
echo 'Sorry this feature does exist yet for when using libssh2';
exit();
break;
}
break;
}
return $pwd;
}
//delete file
public function delete_file($filetoDelete){
//check the connection
$this->connection_check();
//run appropriate list
switch( $this->connection_type )
{
case 'ftp': $unlink = ftp_delete($this->connection,$filetoDelete);
break;
case 'sftp':
//decide which ssh type to use
switch( $this->ssh_type ){
case 'PHPseclib':
$unlink = $this->connection->delete( $filetoDelete );
break;
case 'libssh2':
$unlink = ssh2_sftp_unlink($this->connection,$filetoDelete);
break;
}
break;
}
return $unlink;
} }//end of class
使用课程:
$ftp_sftp = new ftp_sftp( '92.21.627.163','ftpuser','yourpassword','','ftp','21' ); echo $ftp_sftp->pwd();
我在使用easyPHP连接我的win7机器上的PHPseclib时遇到了一些麻烦,并开始了Q ..如果有人有任何想法我会非常感激…
Cannot get phpseclib to connect – error 10060
原始代码
switch($connection_type) {
case 'ftp' : // ...
case 'stfp' : // ...
}
变
switch($connection_type) {
case 'ftp' : // ...
case 'stfp' : // ...
case 'file' : // ...
}
请记住,这是针对切换$connection_type的代码中的每个switch语句.想象一下,我们将多少行代码添加到ftp_sftp类中以合并每个附加行为……
事实上,你现在看起来实际上有三种策略,ftp,sftp& SSH.
你想要做的是将代码设置为水平扩展而不是垂直扩展,这样做的方法是通过Strategy design pattern.
基本上你正在做的是在代码中拉出公共接口,然后为FTP和&创建单独的实现. SFTP.有很多不同的方法可以对此进行实际实施,因此请调整您心中的内容!
一个通用的界面
这是任何’ftp类’必须能够做的定义.
interface PHPFtp
{
public function __construct($host,$port_number = false);
public function connect();
public function errors();
public function connection_check();
public function put($targetLocationToSendTo,$existingLocationToSendFrom);
public function dir_list( $dirToList );
public function remote_filemtime( $pathToFile );
public function make_dir( $dirTomake );
public function change_dir( $dirToMoveto );
public function pwd();
public function delete_file($filetoDelete);
}
一个工厂
现在整个代码中都有一个switch语句来检查$connection_type.您可能决定以不同方式处理默认情况.
class PHPFtpFactory
{
public static function create($connection_type)
{
switch($connection_type) {
case 'ftp':
$oFtp = new Ftp();
break;
case 'sftp':
$oFtp = new Sftp();
break;
default:
throw new UnexpectedValueExcpetion(
'No connection type set cannot choose a method to connect');
}
// Potential follow-up construction steps
return $oFtp;
}
}
基类
不是绝对必要,但非常有帮助.此外,我们在这里偷偷摸摸另一个设计模式,称为Template Method.BaseFtp :: pwd是一个模板方法,它控制整个pwd算法,但委托给具体的孩子一部分.
abstract class BaseFtp implements PHPFtp
{
public function pwd()
{
$this->connection_check();
return $this->_pwd();
}
abstract protected function _pwd();
}
具体的FTP实现
现在我们有一个简洁的ftp类,它只进行FTP操作,它对SFTP一无所知.
class Ftp extends BaseFtp
{
protected function _pwd()
{
return ftp_pwd($this->connection);
}
public function connect()
{
$connection = ftp_connect($this->host);
$login = ftp_login($connection,$this->password);
// if no connection was possible return false and leave $this-connection as false
if(!$connection || !$login)
return false;
// enabling passive mode
ftp_pasv( $connection,true );
return $connection;
}
}
具体Sftp类
现在我们有一个独立的Sftp类,但是请注意它就像原始的ftp_sftp类为$connection_type做的那样切换$ssh_type.一旦你掌握了战略模式,并拥有Ftp&完成Sftp类后,您可以返回并在Sftp实现中实现策略模式,这样您就可以拥有2个类PHPseclib&例如,Libssh2.
class Sftp extends BaseFtp
{
protected function _pwd()
{
// decide which ssh type to use
switch($this->ssh_type) {
case 'PHPseclib':
return $this->connection->pwd();
case 'libssh2':
echo 'Sorry this feature does exist yet for when using libssh2';
return false;
}
}
public function connect()
{
// decide which ssh type to use
switch( $this->ssh_type ) {
case 'PHPseclib':
// inlcude the PHPseclib path in the include array
// and include the ssh2 class
set_include_path($this->PHPseclib_path );
if(!include('Net/SSH2.PHP')){
echo 'Sorry Failed to load SSH2 class';
br();
}
if(!include('Net/SFTP.PHP')){
echo 'Sorry Failed to load SFTP class';
br();
}
$connection = new Net_SFTP($this->host,$this->port_number);
$login = $connection->login($this->username,$this->password);
break;
case 'libssh2':
$connection = ssh2_connect($this->host,$this->port_number);
$login = ssh2_auth_password($connection,'secret');
break;
default:
echo 'No ssh method defined,please define one in: $ftp_sftp->ssh_type';
exit();
break;
}
if(!$connection || !$login)
return false;
}
}
使用新代码
随着新系统的到位,它的10X更容易看出是什么,每个类都关注它的特定领域,代码水平增长.那是什么意思?记住上面,当我们考虑在原始范例中添加第三个$connection_type’文件’时?在新的安排中,我们更新了一个switch语句,即工厂中的一个:
class PHPFtpFactory
{
public static function create($connection_type)
{
switch($connection_type) {
case 'ftp':
$oFtp = new Ftp();
break;
case 'sftp':
$oFtp = new Sftp();
break;
case 'file':
$oFtp = new File();
break;
default:
throw new UnexpectedValueExcpetion(
'No connection type set cannot choose a method to connect');
}
// Potential follow-up construction steps
return $oFtp;
}
}
然后你当然添加了新的具体实现
class File extends PHPFtp
{
// ...
}
由于新的File类可以进入它自己的空间,我们不会扩展一个中心类,即原始的ftp_sftp类.
为了使用新系统,你可以在工厂找到一个实例并从那里开始
// get an instance of the Ftp class
$ftp = PHPFtpFactory::create('ftp');
// get an instance of the Sftp class
$sftp = PHPFtpFactory::create('sftp');
这些实例中的任何一个都支持所有PHPFtp函数,因为它们实现了接口!这也使您能够编写多态代码.考虑一个对接口进行类型提示的函数
// This is polymorphic code
function doFtpStuff(PHPFtp $oFtp) {
// As mentioned above $oFtp can be an instance of any class that implements PHPFtp
$oFtp->connect();
$oFtp->pwd();
}