Viewing file: class.sshAccessDriver.php (25.46 KB) -rwxrwxrwx Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/**
* @package info.ajaxplorer.plugins
*
* Copyright 2007-2009 Cyril Russo
* This file is part of AjaXplorer.
* The latest code can be found at http://www.ajaxplorer.info/
*
* This program is published under the LGPL Gnu Lesser General Public License.
* You should have received a copy of the license along with AjaXplorer.
*
* The main conditions are as follow :
* You must conspicuously and appropriately publish on each copy distributed
* an appropriate copyright notice and disclaimer of warranty and keep intact
* all the notices that refer to this License and to the absence of any warranty;
* and give any other recipients of the Program a copy of the GNU Lesser General
* Public License along with the Program.
*
* If you modify your copy or copies of the library or any portion of it, you may
* distribute the resulting library provided you do so under the GNU Lesser
* General Public License. However, programs that link to the library may be
* licensed under terms of your choice, so long as the library itself can be changed.
* Any translation of the GNU Lesser General Public License must be accompanied by the
* GNU Lesser General Public License.
*
* If you copy or distribute the program, you must accompany it with the complete
* corresponding machine-readable source code or with a written offer, valid for at
* least three years, to furnish the complete corresponding machine-readable source code.
*
* Any of the above conditions can be waived if you get permission from the copyright holder.
* AjaXplorer 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.
*
* Description : Access a remote server via SSH protocol.
*/
require_once("class.SSHOperations.php");
class sshAccessDriver extends AbstractAccessDriver
{
/** The SSH operation object
* @var SSHOperation
*/
var $SSHOperation;
/** The remote path (used to make absolute path)
* @var cwd
*/
var $serverCwd;
/** The remote charset (if known)
* @var charset
*/
var $charset;
function sshAccessDriver($driverName, $filePath, $repository, $optOption = NULL){
$repositoryPath = $repository->getOption("PATH");
$accountLimit = strpos($repositoryPath, "@");
if ($accountLimit !== false)
{
$account = substr($repositoryPath, 0, $accountLimit);
$repositoryPath = substr($repositoryPath, $accountLimit+1);
$repository->setOption("PATH", $repositoryPath);
}
// Set the password from a per user specific config
$account = $optOption ? $optOption["account"] : $this->getUserName($repository);
$password = $optOption ? $optOption["password"] : $this->getPassword($repository);
$this->SSHOperation = new SSHOperations($repositoryPath, $account, $password);
parent::AbstractAccessDriver($driverName, $filePath, $repository);
}
function getUserName($repository){
$logUser = AuthService::getLoggedUser();
$wallet = $logUser->getPref("AJXP_WALLET");
return is_array($wallet) ? $wallet[$repository->getUniqueId()]["remote_username"] : "";
}
function getPassword($repository){
$logUser = AuthService::getLoggedUser();
$wallet = $logUser->getPref("AJXP_WALLET");
return is_array($wallet) ? $logUser->decodeUserPassword($wallet[$repository->getUniqueId()]["remote_password"]) : "";
}
function initRepository(){
$path = $this->repository->getOption("PATH");
// We cache this in the session object so it's only done once
global $_SESSION;
if (!isset($_SESSION["cwd"]) || !strlen($_SESSION["cwd"]))
{
$param = $this->SSHOperation->checkConnection();
if (count($param)==0)
{
return new AJXP_Exception("Cannot connect to remote server. Please check repository configuration and install.txt!");
}
$_SESSION["cwd"] = trim($param[0]);
$fullCharset = explode('.', trim($param[1]));
if ($_SESSION["AJXP_CHARSET"] == "") $_SESSION["AJXP_CHARSET"] = array_pop($fullCharset);
}
// If it's set, then cache the result to avoid multiple connection on the remote server
$this->serverCwd = rtrim(trim($_SESSION["cwd"]), '/').'/';
$this->charset = trim($_SESSION["AJXP_CHARSET"]);
}
function switchAction($action, $httpVars, $fileVars){
if(!isSet($this->actions[$action])) return;
$xmlBuffer = "";
foreach($httpVars as $getName=>$getValue){
$$getName = Utils::securePath(SystemTextEncoding::magicDequote($getValue));
}
$selection = new UserSelection();
$selection->initFromHttpVars($httpVars);
if(isSet($dir) && $action != "upload") { $safeDir = $dir; $dir = SystemTextEncoding::fromUTF8($dir); }
if(isSet($dest)) $dest = SystemTextEncoding::fromUTF8($dest);
$mess = ConfService::getMessages();
$recycleBinOption = $this->repository->getOption("RECYCLE_BIN");
// FILTER ACTION FOR DELETE
if($recycleBinOption!="" && $action == "delete" && $dir != "/".$recycleBinOption)
{
$action = "move";
$dest = "/".$recycleBinOption;
$dest_node = "AJAXPLORER_RECYCLE_NODE";
}
// FILTER ACTION FOR RESTORE
if($recycleBinOption!="" && $action == "restore" && $dir == "/".$recycleBinOption)
{
$originalRep = RecycleBinManager::getFileOrigin($selection->getUniqueFile());
if($originalRep != "")
{
$action = "move";
$dest = $originalRep;
}
}
switch($action)
{
//------------------------------------
// DOWNLOAD, IMAGE & MP3 PROXYS
//------------------------------------
case "download";
AJXP_Logger::logAction("Download", array("files"=>$selection));
$zip = false;
if($selection->isUnique()){
if(is_dir($this->getPath()."/".$selection->getUniqueFile())) {
$zip = true;
$dir .= "/".basename($selection->getUniqueFile());
}
}else{
$zip = true;
}
if($zip){
// Make a temp zip and send it as download
$this->downFile($this->makeName($selection->getFiles()), "force-download", "archive.zip");
}else{
$this->downFile($this->makeName($selection->getUniqueFile()), "force-download", $selection->getUniqueFile());
}
exit(0);
break;
case "image_proxy":
$this->downFile($this->makeName($file), "image", $file);
exit(0);
break;
case "mp3_proxy":
$this->downFile($this->makeName($file), "mp3", $file);
exit(0);
break;
//------------------------------------
// ONLINE EDIT
//------------------------------------
case "edit";
if(isset($save) && $save==1)
{
AJXP_Logger::logAction("Online Edition", array("file"=>SystemTextEncoding::fromUTF8($file)));
$code=stripslashes($code);
$code=str_replace("<","<",$code);
$this->SSHOperation->setRemoteContent($this->makeName($file), $code);
echo $mess[115];
}
else
{
$this->sendFile($this->SSHOperation->getRemoteContent($this->makeName($file)), "plain", $file);
}
exit(0);
break;
//------------------------------------
// COPY / MOVE
//------------------------------------
case "copy";
case "move";
if($selection->isEmpty())
{
$errorMessage = $mess[113];
break;
}
$result = "";
if ($action == "move")
$result = $this->SSHOperation->moveFile($this->makeName($selection->getFiles()), $this->makeName($dest));
else
$result = $this->SSHOperation->copyFile($this->makeName($selection->getFiles()), $this->makeName($dest));
{
$mess = ConfService::getMessages();
if(strlen($result))
{
$errorMessage = $mess[114];
}
else
{
foreach($selection->getFiles() as $files)
$logMessage .= $mess[34]." ".SystemTextEncoding::toUTF8(basename($file))." ".$mess[$action=="move" ? 74:73]." ".SystemTextEncoding::toUTF8($dest)."\n";
AJXP_Logger::logAction(($action=="move"?"Move":"Copy"), array("files"=>$selection, "destination"=>$dest));
}
}
$reload_current_node = true;
if(isSet($dest_node)) $reload_dest_node = $dest_node;
$reload_file_list = true;
break;
//------------------------------------
// CHANGE FILE PERMISSION
//------------------------------------
case "chmod";
$messtmp="";
$changedFiles = array();
$value = "0".decoct(octdec(ltrim($chmod_value, "0"))); // On error, the command will fail
$result = $this->SSHOperation->chmodFile($this->makeName($selection->getFiles()), $chmod_value);
{
$mess = ConfService::getMessages();
if(strlen($result))
{
$errorMessage = $mess[114];
}
else
{
$logMessage="Successfully changed permission to ".$chmod_value." for ".count($selection->getFiles())." files or folders";
AJXP_Logger::logAction("Chmod", array("dir"=>$dir, "filesCount"=>count($selection->getFiles())));
$reload_file_list = $dir;
}
}
break;
//------------------------------------
// SUPPRIMER / DELETE
//------------------------------------
case "delete";
if($selection->isEmpty())
{
$errorMessage = $mess[113];
break;
}
$logMessages = array();
$result = $this->SSHOperation->deleteFile($this->makeName($selection->getFiles()));
if(strlen($result))
{
$mess = ConfService::getMessages();
$errorMessage = $mess[120];
}
else
{
$mess = ConfService::getMessages();
foreach($selection->getFiles() as $file)
$logMessages[]="$mess[34] ".SystemTextEncoding::toUTF8($file)." $mess[44].";
$logMessage = join("\n", $logMessages);
}
AJXP_Logger::logAction("Delete", array("files"=>$selection));
$reload_current_node = true;
$reload_file_list = true;
break;
//------------------------------------
// RENOMMER / RENAME
//------------------------------------
case "rename";
$filename_new = $dir."/".$filename_new;
$error = $this->SSHOperation->moveFile($this->makeName($file), $this->makeName($filename_new));
if($error != null) {
$errorMessage = $error;
break;
}
$logMessage= SystemTextEncoding::toUTF8($file)." $mess[41] ".SystemTextEncoding::toUTF8($filename_new);
$reload_current_node = true;
$reload_file_list = basename($filename_new);
AJXP_Logger::logAction("Rename", array("original"=>$file, "new"=>$filename_new));
break;
//------------------------------------
// CREER UN REPERTOIRE / CREATE DIR
//------------------------------------
case "mkdir";
$messtmp="";
$dirname=Utils::processFileName($dirname);
$error = $this->SSHOperation->createRemoteDirectory($this->makeName($dir."/".$dirname));
if(isSet($error)){
$errorMessage = $error; break;
}
$reload_file_list = $dirname;
$messtmp.="$mess[38] ".SystemTextEncoding::toUTF8($dirname)." $mess[39] ";
if($dir=="") {$messtmp.="/";} else {$messtmp.= SystemTextEncoding::toUTF8($dir);}
$logMessage = $messtmp;
$reload_current_node = true;
AJXP_Logger::logAction("Create Dir", array("dir"=>$dir."/".$dirname));
break;
//------------------------------------
// CREER UN FICHIER / CREATE FILE
//------------------------------------
case "mkfile";
$messtmp="";
$filename=Utils::processFileName($filename);
$error = $this->SSHOperation->setRemoteContent($this->makeName($dir."/".$filename), "");
if(isSet($error)){
$errorMessage = $error; break;
}
$messtmp.="$mess[34] ".SystemTextEncoding::toUTF8($filename)." $mess[39] ";
if($dir=="") {$messtmp.="/";} else {$messtmp.=SystemTextEncoding::toUTF8($dir);}
$logMessage = $messtmp;
$reload_file_list = $filename;
AJXP_Logger::logAction("Create File", array("file"=>$dir."/".$filename));
break;
//------------------------------------
// UPLOAD
//------------------------------------
case "upload":
$fancyLoader = false;
if(isSet($fileVars["Filedata"])){
$fancyLoader = true;
if($dir!="") $dir = "/".base64_decode($dir);
}
if($dir!=""){$rep_source="/$dir";}
else $rep_source = "";
$destination = $rep_source;
$logMessage = "";
//$fancyLoader = false;
foreach ($fileVars as $boxName => $boxData)
{
if($boxName != "Filedata" && substr($boxName, 0, 9) != "userfile_") continue;
if($boxName == "Filedata") $fancyLoader = true;
$err = Utils::parseFileDataErrors($boxData, $fancyLoader);
if($err != null)
{
$errorMessage = $err;
break;
}
$userfile_name = $boxData["name"];
$userfile_name=Utils::processFileName($userfile_name);
if (!$this->SSHOperation->uploadFile($boxData["tmp_name"], $this->makeName($destination."/".$userfile_name)))
{
$errorMessage=($fancyLoader?"411 ":"")."$mess[33] ".$userfile_name;
break;
}
$logMessage.="$mess[34] ".SystemTextEncoding::toUTF8($userfile_name)." $mess[35] $dir";
AJXP_Logger::logAction("Upload File", array("file"=>$dir."/".$userfile_name));
}
if($fancyLoader)
{
if(isSet($errorMessage)){
header('HTTP/1.0 '.$errorMessage);
die('Error '.$errorMessage);
}else{
header('HTTP/1.0 200 OK');
die("200 OK");
}
}
else
{
print("<html><script language=\"javascript\">\n");
if(isSet($errorMessage)){
print("\n if(parent.ajaxplorer.actionBar.multi_selector)parent.ajaxplorer.actionBar.multi_selector.submitNext('".str_replace("'", "\'", $errorMessage)."');");
}else{
print("\n if(parent.ajaxplorer.actionBar.multi_selector)parent.ajaxplorer.actionBar.multi_selector.submitNext();");
}
print("</script></html>");
}
exit;
break;
//------------------------------------
// Public URL
//------------------------------------
case "public_url":
$file = SystemTextEncoding::fromUTF8($file);
$url = $this->makePubliclet($file, $password, $expiration);
header("Content-type:text/plain");
echo $url;
exit(1);
break;
//------------------------------------
// XML LISTING
//------------------------------------
case "ls":
if(!isSet($dir) || $dir == "/") $dir = "";
$searchMode = $fileListMode = $completeMode = false;
if(isSet($mode)){
if($mode == "search") $searchMode = true;
else if($mode == "file_list") $fileListMode = true;
else if($mode == "complete") $completeMode = true;
}
$nom_rep = $dir;
AJXP_Exception::errorToXml($nom_rep);
$result = $this->SSHOperation->listFilesIn($nom_rep);
AJXP_XMLWriter::header();
foreach ($result as $file)
{
$attributes = "";
$fileName = SystemTextEncoding::toUTF8($file["name"]);
$icon = Utils::mimetype($fileName, "image", $file["isDir"]==1);
if ($searchMode)
{
if($file["isDir"] == 0) { $attributes = "is_file=\"true\" icon=\"".SystemTextEncoding::toUTF8($icon)."\""; }
} else if ($fileListMode)
{
$atts = array();
$atts[] = "is_file=\"".(1 - $file["isDir"])."\"";
$atts[] = "is_image=\"".Utils::is_image($fileName)."\"";
$atts[] = "mimestring=\"".Utils::mimetype($fileName, "type", $file["isDir"]==1)."\"";
$atts[] = "ajxp_modiftime=\"".$this->dateModif($file["time"])."\"";
$atts[] = "filesize=\"".Utils::roundSize($file["size"])."\"";
$atts[] = "bytesize=\"".$file["size"]."\"";
$atts[] = "filename=\"".str_replace("&", "&", $dir."/".$fileName)."\"";
$atts[] = "icon=\"".($file["isDir"]==1 ? "folder.png" : SystemTextEncoding::toUTF8($icon))."\"";
$attributes = join(" ", $atts);
} else if ($file["isDir"]==1)
{
$link = SERVER_ACCESS."?dir=".$dir."/".$fileName;
$link = urlencode($link);
$folderBaseName = str_replace("&", "&", $fileName);
$folderFullName = "$dir/".$folderBaseName;
$parentFolderName = $dir;
if(!$completeMode){
$icon = CLIENT_RESOURCES_FOLDER."/images/foldericon.png";
$openicon = CLIENT_RESOURCES_FOLDER."/images/openfoldericon.png";
if(eregi("\.zip$",$file["name"])){
$icon = $openicon = CLIENT_RESOURCES_FOLDER."/images/crystal/actions/16/accessories-archiver.png";
}
$attributes = "icon=\"$icon\" openicon=\"$openicon\" filename=\"".$folderFullName."\" src=\"$link\"";
}
}
if (strlen($attributes) > 0)
{
print("<tree text=\"".str_replace("&", "&", SystemTextEncoding::toUTF8($this->SSHOperation->unescapeFileName($file["name"])))."\" $attributes>");
print("</tree>");
}
}
AJXP_XMLWriter::close();
exit(1);
break;
}
if(isset($logMessage) || isset($errorMessage))
{
$xmlBuffer .= AJXP_XMLWriter::sendMessage((isSet($logMessage)?$logMessage:null), (isSet($errorMessage)?$errorMessage:null), false);
}
if(isset($requireAuth))
{
$xmlBuffer .= AJXP_XMLWriter::requireAuth(false);
}
if(isset($reload_current_node) && $reload_current_node == "true")
{
$xmlBuffer .= AJXP_XMLWriter::reloadCurrentNode(false);
}
if(isset($reload_dest_node) && $reload_dest_node != "")
{
$xmlBuffer .= AJXP_XMLWriter::reloadNode($reload_dest_node, false);
}
if(isset($reload_file_list))
{
$xmlBuffer .= AJXP_XMLWriter::reloadFileList($reload_file_list, false);
}
return $xmlBuffer;
}
function getPath(){
return $this->repository->getOption("PATH");
}
function makeName($param)
{
if (is_array($param))
{
$retArray = array();
foreach($param as $item)
{
$retArray[] = $this->serverCwd.SystemTextEncoding::fromUTF8(trim($item, './'));
}
return $retArray;
}
else
{
$param = SystemTextEncoding::fromUTF8(trim($param, './'));
return $this->serverCwd.$param;
}
}
/** The publiclet URL making */
function makePubliclet($filePath, $password, $expire)
{
$data = array("DRIVER"=>"ssh", "OPTIONS"=>array('account'=>$this->getUserName($this->repository), 'password'=>$this->getPassword($this->repository)), "FILE_PATH"=>$filePath, "ACTION"=>"download", "EXPIRE_TIME"=>$expire ? (time() + $expire * 86400) : 0, "PASSWORD"=>$password);
return $this->writePubliclet($data);
}
function zipListing($zipPath, $localPath, &$filteredList){
require_once("server/classes/pclzip.lib.php");
$crtZip = new PclZip($this->getPath()."/".$zipPath);
$liste = $crtZip->listContent();
$files = array();
if($localPath[strlen($localPath)-1] != "/") $localPath.="/";
foreach ($liste as $item){
$stored = $item["stored_filename"];
if($stored[0] != "/") $stored = "/".$stored;
$pathPos = strpos($stored, $localPath);
if($pathPos !== false){
$afterPath = substr($stored, $pathPos+strlen($localPath));
if($afterPath != "" && strpos($afterPath, "/")=== false || strpos($afterPath, "/") == strlen($afterPath)-1){
$item["filename"] = $zipPath.$localPath.$afterPath;
if($item["folder"]){
$filteredList[] = $item;
}else{
$files[] = $item;
}
}
}
}
$filteredList = array_merge($filteredList, $files);
return $crtZip;
}
function initName($dir)
{
$racine = $this->getPath();
$mess = ConfService::getMessages();
if(!isset($dir) || $dir=="" || $dir == "/")
{
$nom_rep=$racine;
}
else
{
$nom_rep="$racine/$dir";
}
if(!file_exists($racine))
{
return new AJXP_Exception(72);
}
if(!is_dir($nom_rep))
{
return new AJXP_Exception(100);
}
return $nom_rep;
}
function sendFile($filePath, $headerType="plain", $fileName, $gzip=true)
{
$size = strlen($filePath);
if($headerType == "plain")
{
header("Content-type:text/plain");
}
else if($headerType == "image")
{
header("Content-Type: ".Utils::getImageMimeType(basename($fileName))."; name=\"".basename($fileName)."\"");
header("Content-Length: ".$size);
header('Cache-Control: public');
}
else if($headerType == "mp3")
{
header("Content-Type: audio/mp3; name=\"".basename($fileName)."\"");
header("Content-Length: ".$size);
}
else
{
header("Content-Type: application/force-download; name=\"".$fileName."\"");
header("Content-Transfer-Encoding: binary");
if($gzip) header("Content-Encoding: gzip");
header("Content-Length: ".$size);
header("Content-Disposition: attachment; filename=\"".$fileName."\"");
header("Expires: 0");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
// For SSL websites there is a bug with IE see article KB 323308
// therefore we must reset the Cache-Control and Pragma Header
if (ConfService::getConf("USE_HTTPS")==1 && preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT']))
{
header("Cache-Control:");
header("Pragma:");
}
if($gzip){
print(gzencode($filePath, 9));
return ;
}
}
print($filePath);
}
function downFile($fileArray, $headerType="plain", $fileName)
{
if($headerType == "plain")
{
header("Content-type:text/plain");
}
else if($headerType == "image")
{
header("Content-Type: ".Utils::getImageMimeType(basename($fileName))."; name=\"".basename($fileName)."\"");
header('Cache-Control: public');
}
else if($headerType == "mp3")
{
header("Content-Type: audio/mp3; name=\"".basename($fileName)."\"");
}
else
{
header("Content-Type: application/force-download; name=\"".$fileName."\"");
header("Content-Transfer-Encoding: binary");
if($gzip) header("Content-Encoding: gzip");
header("Content-Disposition: attachment; filename=\"".$fileName."\"");
header("Expires: 0");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
// For SSL websites there is a bug with IE see article KB 323308
// therefore we must reset the Cache-Control and Pragma Header
if (ConfService::getConf("USE_HTTPS")==1 && preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT']))
{
header("Cache-Control:");
header("Pragma:");
}
}
$this->SSHOperation->downloadRemoteFile($fileArray);
}
function dateModif($time)
{
$tmp = mktime(substr($time, 11, 2), substr($time, 14, 2), 0, substr($time, 5, 2), substr($time, 8, 2), substr($time, 0, 4));
return $tmp;//date("d/m/Y H:i",$tmp);
}
/**
* @return zipfile
*/
function makeZip ($src, $dest, $basedir)
{
set_time_limit(60);
require_once(SERVER_RESOURCES_FOLDER."/pclzip.lib.php");
$filePaths = array();
$totalSize = 0;
foreach ($src as $item){
$filePaths[] = $this->getPath().$item;
}
$archive = new PclZip($dest);
$vList = $archive->create($filePaths, PCLZIP_OPT_REMOVE_PATH, $this->getPath().$basedir, PCLZIP_OPT_NO_COMPRESSION);
if($vList == 0) return false;
}
/**
* @param $selection UserSelection
*/
function convertSelectionToTmpFiles($tmpDir, $selection){
$zipPath = $selection->getZipPath();
$localDir = $selection->getZipLocalPath();
$files = $selection->getFiles();
foreach ($files as $key => $item){// Remove path
$item = substr($item, strlen($zipPath));
if($item[0] == "/") $item = substr($item, 1);
$files[$key] = $item;
}
require_once("server/classes/pclzip.lib.php");
$zip = new PclZip($this->getPath().$zipPath);
$err = $zip->extract(PCLZIP_OPT_BY_NAME, $files,
PCLZIP_OPT_PATH, $this->getPath()."/".$tmpDir);
foreach ($files as $key => $item){// Remove path
$files[$key] = $tmpDir."/".$item;
}
$selection->setFiles($files);
}
}
?>
|