Location: PHPKode > projects > Simple Way to Usenet > libs/core/files/file_ssh.class.php
<?php
/**
 *  
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */

class file_ssh extends file_accessor {
	
	private $_CONN;
	private $_SFTP;
	
	private $conf = Array( 	'host' 	=> '127.0.0.1',
							'port' 	=> '22',
							'auth' 	=> 'none'
					);
		
	public function __construct($RRef){
		//TODO add check for ssh2 php extention, raise fatal_error
		parent::__construct($RRef);
		unset($RRef);
		$conf = configs::get('file_repo', $this->RRef, 'conf');
		if ( !isset($conf['basepath']) ){ 
			$this->basepath = '/'; 
		} else {
			$this->basepath = $conf['basepath'];
			unset($conf['basepath']);
		}
		foreach($conf as $opt => &$val){ $this->conf[$opt] = $val; }
		switch($this->conf['auth']){
			case 'password' : 	if ( !isset($this->conf['user']) ){
									errors::raise("Missing 'user' config, required with password auth method", CORE_LOG_ERROR, 'FSSH');
									$this->isconn = FALSE;
								}
								if ( !isset($this->conf['pass']) ){
									errors::raise("Missing 'pass' config, required with password auth method", CORE_LOG_ERROR, 'FSSH');
									$this->isconn = FALSE;
								}
								break;
			case 'publickey':  	if ( !isset($this->conf['user']) ){
									errors::raise("Missing 'user' config, required with password auth method", CORE_LOG_ERROR, 'FSSH');
									$this->isconn = FALSE;
								}
								if ( !isset($this->conf['pubkey']) ){
									errors::raise("Missing 'pubkey' config, required with publickey auth method", CORE_LOG_ERROR, 'FSSH');
									$this->isconn = FALSE;
								} elseif ( FALSE === file_exists($this->conf['pubkey']) ){
									errors::raise("Invalid 'pubkey' config, file could not be found", CORE_LOG_ERROR, 'FSSH');
									$this->isconn = FALSE;
								}
								if ( !isset($this->conf['prvkey']) ){
									errors::raise("Missing 'prvkey' config, required with password auth method", CORE_LOG_ERROR, 'FSSH');
									$this->isconn = FALSE;
								} elseif ( FALSE === file_exists($this->conf['prvkey']) ){
									errors::raise("Invalid 'prvkey' config, file could not be found", CORE_LOG_ERROR, 'FSSH');
									$this->isconn = FALSE;
								}
								break;
		
		} 
		errors::getnew('SSH2 File Repo '.$this->RRef.' constructed', CORE_LOG_INFO, 'FSSH');
	}
	
	public function connect(){ 
		errors::getnew('Connecting to SSH2 File Repo '.$this->RRef, CORE_LOG_INFO, 'FSSH');
		if ( isset($this->isconn) ){ return $this->isconn; }
		$this->_CONN = @ssh2_connect($this->conf['host'], $this->conf['port'], Array(), array('disconnect' => Array(&$this, 'disconnect')) );
		if ( FALSE === $this->_CONN ){
			$this->isconn = FALSE;
			return errors::getnew('Connection to SSH2 File Repo '.$this->RRef.' could not be established', CORE_LOG_ERROR, 'FSSH');
		}
		if ( $this->conf['auth'] !== 'none'){
			$auth_methods = ssh2_auth_none($this->_CONN, $this->conf['user']);
			if ( $auth_methods ==  -1 OR FALSE === in_array($this->conf['auth'], $auth_methods) ){
				$this->isconn = FALSE;
				return errors::getnew('Connection to SSH2 File Repo '.$this->RRef.' failed, auth method not compatible with server, only ('.implode(',',$auth_methods).')', CORE_LOG_ERROR, 'FSSH');
			}
			switch($this->conf['auth']){
				case 'password' :  	$auth = ssh2_auth_password($this->_CONN, $this->conf['user'], $this->conf['pass']); 	
									break;
				case 'publickey':	if ( isset($this->conf['key']) ){								
										$auth = ssh2_auth_pubkey_file($this->_CONN, $this->conf['user'], $this->conf['pubkey'], $this->conf['prvkey'], $this->conf['key']);
									} else {
										$auth = ssh2_auth_pubkey_file($this->_CONN, $this->conf['user'], $this->conf['pubkey'], $this->conf['prvkey']);
									}
									break;
									//TODO case none + case default erraise 
			}			
		} else {
			$auth = TRUE;
		}
		if ( FALSE === $auth ){
			$this->isconn = FALSE;
			return errors::getnew('Connection to SSH2 File Repo '.$this->RRef.' failed, authentification failure', CORE_LOG_ERROR, 'FSSH');
		}
		
		$this->_SFTP = ssh2_sftp($this->_CONN);
		
		if ( FALSE === $this->_SFTP ){
			$this->isconn = FALSE;
			return errors::getnew('ssh2_sftp ressource could not be created !', CORE_LOG_ERROR, 'FSSH');
		} elseif ( FALSE === is_dir("ssh2.sftp://$this->_SFTP$this->basepath") ){
			$this->isconn = FALSE;
			return errors::getnew('Connection to SSH File Repo '.$this->RRef.' failed, could not chdir to remote basepath ('.$this->basepath.')', CORE_LOG_ERROR, 'FSSH');	
		}
		$this->isconn = TRUE;
		$this->curpath = $this->basepath;
		errors::raise('Connected to SSH File Repo "'.$this->RRef.'" ('.$this->conf['host'].':'.$this->conf['port'].$this->basepath.')', CORE_LOG_DEBUG, 'FSSH');
		return TRUE;	
	}
	
	public function disconnect(){
		unset($this->isconn, $this->curpath);
		if ( @count($this->_HDL) != 0 ){
			errors::raise("Closing ".count($this->_HDL)." Ressources left open.", CORE_LOG_DEBUG, 'FSSH');
			foreach($this->_HDL as &$ref ){ @fclose($ref);@closedir($ref); }
		}
		unset($this->_HDL);
		unset($this->_SFTP);
		unset($this->_CONN);
		errors::raise('Now Disconnected from SSH File Repo "'.$this->RRef.'" ('.$this->conf['host'].':'.$this->conf['port'].$this->basepath.')', CORE_LOG_DEBUG, 'FSSH');
		return TRUE;
	}
	
	public function exists($path){
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		if ( is_file($url) ){ return TRUE; }
		if ( is_dir($url) ){ return TRUE; }		
		return FALSE;
	}
	
	public function isfile($path){ 
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		return is_file($url);
	}
		
	public function isdir($path){ 
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		return is_dir($url);
	}

	public function chdir($path){
		if ( $this->isdir($path) ){
			$rpath = $this->realpath($path); 
			$this->curpath = $rpath;
			return TRUE; 
		}
	}
	
	public function readdir($path){
		if ( ! $this->isdir($path) ){ return FALSE; }
		$ref = __FUNCTION__.md5($path);
		if ( !isset($this->_HDL[$ref]) ){
			$rpath = $this->realpath($path);
			$url = "ssh2.sftp://$this->_SFTP$rpath";
			$this->_HDL[$ref] = opendir($url);
			if ( FALSE === $this->_HDL[$ref] ){ unset($this->_HDL[$ref]);return FALSE; }
		}
		$o = readdir($this->_HDL[$ref]);
		if ( $o == '.' OR $o == '..' ){ return $this->readdir($path); }
		if ( $o === FALSE ){ closedir($this->_HDL[$ref]);unset($this->_HDL[$ref]); }
		return $o;
	}
	
	public function readfile($path){ 
		$rpath = $this->realpath($path);
		$lpath = CORE::tempfile();
		if ( FALSE === ftp_get($this->_CONN, $lpath, $rpath, FTP_BINARY, 0) ){ 
			unlink($lpath);
			return FALSE;
		}
		$o = file_get_contents($lpath);
		unlink($lpath);
		return $o;	
	}
	
	public function getmtime($path){
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		$buff = filemtime($url);
		if ($buff != -1) { return $buff; }
		return FALSE;
	}
	
	public function getctime($path){
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		$buff = filectime($url);
		if ($buff != -1) { return $buff; }
		return FALSE;  
	}
	
	public function getsize($path){ 
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		$buff = filesize($url);
		if ($buff != -1) { return sprintf ("%u", $buff); }
		return FALSE;
	}
	
	public function remove($path, $recur=FALSE){
		if ( $this->isdir($path) ){
			if ( $recur ){
				while( FALSE !== ($child = $this->readdir($path)) ){
					$npath = $path.'/'.$child;
					if ( ! $this->remove($npath, $recur) ){ return FALSE; }
				}
			}
			$rpath = $this->realpath($path);
			$url = "ssh2.sftp://$this->_SFTP$rpath";
			if ( FALSE === rmdir($url) ){ return FALSE; }
			return TRUE;
		}
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		return unlink($url);
	}
	
	public function createdir($path, $recur=FALSE){
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		if ( FALSE === $recur ){ return mkdir($url); }
		//check existance of each path level, create if not present
	}
	
	public function createfile($path, $data=""){ 
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		return file_put_contents($url, $data);	
	}

	public function file_open($path, $mode){
		$rpath = $this->realpath($path);
		$url = "ssh2.sftp://$this->_SFTP$rpath";
		$FH = CORE::hash(NULL, 10).md5($rpath);
		$this->_HDL[$FH] = fopen($url, $mode);
		if ( FALSE === $this->_HDL[$FH] ){
			unset($this->_HDL[$FH]);
			return FALSE;
		}
		return $FH;
	}
	
}

Return current item: Simple Way to Usenet