123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- <?php
- /**
- * Copyright (c) 2012 Henrik Kjölhede <hkjolhede@gmail.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
- namespace OC\Files\Storage;
- set_include_path(get_include_path() . PATH_SEPARATOR .
- \OC_App::getAppPath('files_external') . '/3rdparty/phpseclib/phpseclib');
- require 'Net/SFTP.php';
- class SFTP extends \OC\Files\Storage\Common {
- private $host;
- private $user;
- private $password;
- private $root;
- private $client;
- private static $tempFiles = array();
- public function __construct($params) {
- $this->host = $params['host'];
- $proto = strpos($this->host, '://');
- if ($proto != false) {
- $this->host = substr($this->host, $proto+3);
- }
- $this->user = $params['user'];
- $this->password = $params['password'];
- $this->root = isset($params['root']) ? $this->cleanPath($params['root']) : '/';
- if ($this->root[0] != '/') $this->root = '/' . $this->root;
- if (substr($this->root, -1, 1) != '/') $this->root .= '/';
- $host_keys = $this->read_host_keys();
- $this->client = new \Net_SFTP($this->host);
- if (!$this->client->login($this->user, $this->password)) {
- throw new \Exception('Login failed');
- }
- $current_host_key = $this->client->getServerPublicHostKey();
- if (array_key_exists($this->host, $host_keys)) {
- if ($host_keys[$this->host] != $current_host_key) {
- throw new \Exception('Host public key does not match known key');
- }
- } else {
- $host_keys[$this->host] = $current_host_key;
- $this->write_host_keys($host_keys);
- }
- }
- public function test() {
- if (!isset($params['host']) || !isset($params['user']) || !isset($params['password'])) {
- throw new \Exception("Required parameters not set");
- }
- }
- public function getId(){
- return 'sftp::' . $this->user . '@' . $this->host . '/' . $this->root;
- }
- private function abs_path($path) {
- return $this->root . $this->cleanPath($path);
- }
- private function host_keys_path() {
- try {
- $storage_view = \OCP\Files::getStorage('files_external');
- if ($storage_view) {
- return \OCP\Config::getSystemValue('datadirectory') .
- $storage_view->getAbsolutePath('') .
- 'ssh_host_keys';
- }
- } catch (\Exception $e) {
- }
- return false;
- }
- private function write_host_keys($keys) {
- try {
- $key_path = $this->host_keys_path();
- $fp = fopen($key_path, 'w');
- foreach ($keys as $host => $key) {
- fwrite($fp, $host . '::' . $key . "\n");
- }
- fclose($fp);
- return true;
- } catch (\Exception $e) {
- return false;
- }
- }
- private function read_host_keys() {
- try {
- $key_path = $this->host_keys_path();
- if (file_exists($key_path)) {
- $hosts = array();
- $keys = array();
- $lines = file($key_path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
- if ($lines) {
- foreach ($lines as $line) {
- $host_key_arr = explode("::", $line, 2);
- if (count($host_key_arr) == 2) {
- $hosts[] = $host_key_arr[0];
- $keys[] = $host_key_arr[1];
- }
- }
- return array_combine($hosts, $keys);
- }
- }
- } catch (\Exception $e) {
- }
- return array();
- }
- public function mkdir($path) {
- try {
- return $this->client->mkdir($this->abs_path($path));
- } catch (\Exception $e) {
- return false;
- }
- }
- public function rmdir($path) {
- try {
- return $this->client->delete($this->abs_path($path), true);
- } catch (\Exception $e) {
- return false;
- }
- }
- public function opendir($path) {
- try {
- $list = $this->client->nlist($this->abs_path($path));
- $id = md5('sftp:' . $path);
- $dir_stream = array();
- foreach($list as $file) {
- if ($file != '.' && $file != '..') {
- $dir_stream[] = $file;
- }
- }
- \OC\Files\Stream\Dir::register($id, $dir_stream);
- return opendir('fakedir://' . $id);
- } catch(\Exception $e) {
- return false;
- }
- }
- public function filetype($path) {
- try {
- $stat = $this->client->stat($this->abs_path($path));
- if ($stat['type'] == NET_SFTP_TYPE_REGULAR) return 'file';
- if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) return 'dir';
- } catch (\Exeption $e) {
- }
- return false;
- }
- public function isReadable($path) {
- return true;
- }
- public function isUpdatable($path) {
- return true;
- }
- public function file_exists($path) {
- try {
- return $this->client->stat($this->abs_path($path)) === false ? false : true;
- } catch (\Exception $e) {
- return false;
- }
- }
- public function unlink($path) {
- try {
- return $this->client->delete($this->abs_path($path), true);
- } catch (\Exception $e) {
- return false;
- }
- }
- public function fopen($path, $mode) {
- try {
- $abs_path = $this->abs_path($path);
- switch($mode) {
- case 'r':
- case 'rb':
- if ( !$this->file_exists($path)) return false;
- if (strrpos($path, '.')!==false) {
- $ext=substr($path, strrpos($path, '.'));
- } else {
- $ext='';
- }
- $tmp = \OC_Helper::tmpFile($ext);
- $this->getFile($abs_path, $tmp);
- return fopen($tmp, $mode);
- case 'w':
- case 'wb':
- case 'a':
- case 'ab':
- case 'r+':
- case 'w+':
- case 'wb+':
- case 'a+':
- case 'x':
- case 'x+':
- case 'c':
- case 'c+':
- if (strrpos($path, '.')!==false) {
- $ext=substr($path, strrpos($path, '.'));
- } else {
- $ext='';
- }
- $tmpFile=\OC_Helper::tmpFile($ext);
- \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
- if ($this->file_exists($path)) {
- $this->getFile($abs_path, $tmpFile);
- }
- self::$tempFiles[$tmpFile]=$abs_path;
- return fopen('close://'.$tmpFile, $mode);
- }
- } catch (\Exception $e) {
- }
- return false;
- }
- public function writeBack($tmpFile) {
- if (array_key_exists($tmpFile, self::$tempFiles)) {
- $this->uploadFile($tmpFile, self::$tempFiles[$tmpFile]);
- unlink($tmpFile);
- unset(self::$tempFiles[$tmpFile]);
- }
- }
- public function touch($path, $mtime=null) {
- try {
- if (!is_null($mtime)) return false;
- if (!$this->file_exists($path)) {
- $this->client->put($this->abs_path($path), '');
- } else {
- return false;
- }
- } catch (\Exception $e) {
- return false;
- }
- return true;
- }
- public function getFile($path, $target) {
- $this->client->get($path, $target);
- }
- public function uploadFile($path, $target) {
- $this->client->put($target, $path, NET_SFTP_LOCAL_FILE);
- }
- public function rename($source, $target) {
- try {
- return $this->client->rename($this->abs_path($source), $this->abs_path($target));
- } catch (\Exception $e) {
- return false;
- }
- }
- public function stat($path) {
- try {
- $stat = $this->client->stat($this->abs_path($path));
- $mtime = $stat ? $stat['mtime'] : -1;
- $size = $stat ? $stat['size'] : 0;
- return array('mtime' => $mtime, 'size' => $size, 'ctime' => -1);
- } catch (\Exception $e) {
- return false;
- }
- }
- }
|