<?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;
}
}