diff options
author | Robin McCorkell <robin@mccorkell.me.uk> | 2016-04-13 23:18:07 +0100 |
---|---|---|
committer | Robin McCorkell <robin@mccorkell.me.uk> | 2016-04-14 00:44:28 +0100 |
commit | 4717605d22f5f60e887b5584e8da25b8ef69cdf4 (patch) | |
tree | 8c8ff5df9adaf4701375ef3a8bc76f3e4aa04d0b /apps/files_external/lib/sftp.php | |
parent | 3c0a1d4241c16c13b3fd93406402320284d153d9 (diff) | |
download | nextcloud-server-4717605d22f5f60e887b5584e8da25b8ef69cdf4.tar.gz nextcloud-server-4717605d22f5f60e887b5584e8da25b8ef69cdf4.zip |
Fix storage backend class namespaces and move to subdir
All classes that were previously \OC\Files\Storage\FooBar are now
\OCA\Files_External\Lib\Storage\FooBar
Diffstat (limited to 'apps/files_external/lib/sftp.php')
-rw-r--r-- | apps/files_external/lib/sftp.php | 467 |
1 files changed, 0 insertions, 467 deletions
diff --git a/apps/files_external/lib/sftp.php b/apps/files_external/lib/sftp.php deleted file mode 100644 index a6984f3b4e0..00000000000 --- a/apps/files_external/lib/sftp.php +++ /dev/null @@ -1,467 +0,0 @@ -<?php -/** - * @author Andreas Fischer <bantu@owncloud.com> - * @author Bart Visscher <bartv@thisnet.nl> - * @author hkjolhede <hkjolhede@gmail.com> - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Lennart Rosam <lennart.rosam@medien-systempartner.de> - * @author Lukas Reschke <lukas@owncloud.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <icewind@owncloud.com> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Ross Nicoll <jrn@jrn.me.uk> - * @author SA <stephen@mthosting.net> - * @author Vincent Petry <pvince81@owncloud.com> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ -namespace OC\Files\Storage; -use Icewind\Streams\IteratorDirectory; - -use Icewind\Streams\RetryWrapper; -use phpseclib\Net\SFTP\Stream; - -/** -* Uses phpseclib's Net\SFTP class and the Net\SFTP\Stream stream wrapper to -* provide access to SFTP servers. -*/ -class SFTP extends \OC\Files\Storage\Common { - private $host; - private $user; - private $root; - private $port = 22; - - private $auth; - - /** - * @var SFTP - */ - protected $client; - - /** - * @param string $host protocol://server:port - * @return array [$server, $port] - */ - private function splitHost($host) { - $input = $host; - if (strpos($host, '://') === false) { - // add a protocol to fix parse_url behavior with ipv6 - $host = 'http://' . $host; - } - - $parsed = parse_url($host); - if(is_array($parsed) && isset($parsed['port'])) { - return [$parsed['host'], $parsed['port']]; - } else if (is_array($parsed)) { - return [$parsed['host'], 22]; - } else { - return [$input, 22]; - } - } - - /** - * {@inheritdoc} - */ - public function __construct($params) { - // Register sftp:// - Stream::register(); - - $parsedHost = $this->splitHost($params['host']); - - $this->host = $parsedHost[0]; - $this->port = $parsedHost[1]; - - if (!isset($params['user'])) { - throw new \UnexpectedValueException('no authentication parameters specified'); - } - $this->user = $params['user']; - - if (isset($params['public_key_auth'])) { - $this->auth = $params['public_key_auth']; - } elseif (isset($params['password'])) { - $this->auth = $params['password']; - } else { - throw new \UnexpectedValueException('no authentication parameters specified'); - } - - $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 .= '/'; - } - } - - /** - * Returns the connection. - * - * @return \phpseclib\Net\SFTP connected client instance - * @throws \Exception when the connection failed - */ - public function getConnection() { - if (!is_null($this->client)) { - return $this->client; - } - - $hostKeys = $this->readHostKeys(); - $this->client = new \phpseclib\Net\SFTP($this->host, $this->port); - - // The SSH Host Key MUST be verified before login(). - $currentHostKey = $this->client->getServerPublicHostKey(); - if (array_key_exists($this->host, $hostKeys)) { - if ($hostKeys[$this->host] != $currentHostKey) { - throw new \Exception('Host public key does not match known key'); - } - } else { - $hostKeys[$this->host] = $currentHostKey; - $this->writeHostKeys($hostKeys); - } - - if (!$this->client->login($this->user, $this->auth)) { - throw new \Exception('Login failed'); - } - return $this->client; - } - - /** - * {@inheritdoc} - */ - public function test() { - if ( - !isset($this->host) - || !isset($this->user) - ) { - return false; - } - return $this->getConnection()->nlist() !== false; - } - - /** - * {@inheritdoc} - */ - public function getId(){ - $id = 'sftp::' . $this->user . '@' . $this->host; - if ($this->port !== 22) { - $id .= ':' . $this->port; - } - // note: this will double the root slash, - // we should not change it to keep compatible with - // old storage ids - $id .= '/' . $this->root; - return $id; - } - - /** - * @return string - */ - public function getHost() { - return $this->host; - } - - /** - * @return string - */ - public function getRoot() { - return $this->root; - } - - /** - * @return mixed - */ - public function getUser() { - return $this->user; - } - - /** - * @param string $path - * @return string - */ - private function absPath($path) { - return $this->root . $this->cleanPath($path); - } - - /** - * @return string|false - */ - private function hostKeysPath() { - try { - $storage_view = \OCP\Files::getStorage('files_external'); - if ($storage_view) { - return \OC::$server->getConfig()->getSystemValue('datadirectory') . - $storage_view->getAbsolutePath('') . - 'ssh_hostKeys'; - } - } catch (\Exception $e) { - } - return false; - } - - /** - * @param $keys - * @return bool - */ - protected function writeHostKeys($keys) { - try { - $keyPath = $this->hostKeysPath(); - if ($keyPath && file_exists($keyPath)) { - $fp = fopen($keyPath, 'w'); - foreach ($keys as $host => $key) { - fwrite($fp, $host . '::' . $key . "\n"); - } - fclose($fp); - return true; - } - } catch (\Exception $e) { - } - return false; - } - - /** - * @return array - */ - protected function readHostKeys() { - try { - $keyPath = $this->hostKeysPath(); - if (file_exists($keyPath)) { - $hosts = array(); - $keys = array(); - $lines = file($keyPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - if ($lines) { - foreach ($lines as $line) { - $hostKeyArray = explode("::", $line, 2); - if (count($hostKeyArray) == 2) { - $hosts[] = $hostKeyArray[0]; - $keys[] = $hostKeyArray[1]; - } - } - return array_combine($hosts, $keys); - } - } - } catch (\Exception $e) { - } - return array(); - } - - /** - * {@inheritdoc} - */ - public function mkdir($path) { - try { - return $this->getConnection()->mkdir($this->absPath($path)); - } catch (\Exception $e) { - return false; - } - } - - /** - * {@inheritdoc} - */ - public function rmdir($path) { - try { - $result = $this->getConnection()->delete($this->absPath($path), true); - // workaround: stray stat cache entry when deleting empty folders - // see https://github.com/phpseclib/phpseclib/issues/706 - $this->getConnection()->clearStatCache(); - return $result; - } catch (\Exception $e) { - return false; - } - } - - /** - * {@inheritdoc} - */ - public function opendir($path) { - try { - $list = $this->getConnection()->nlist($this->absPath($path)); - if ($list === false) { - return false; - } - - $id = md5('sftp:' . $path); - $dirStream = array(); - foreach($list as $file) { - if ($file != '.' && $file != '..') { - $dirStream[] = $file; - } - } - return IteratorDirectory::wrap($dirStream); - } catch(\Exception $e) { - return false; - } - } - - /** - * {@inheritdoc} - */ - public function filetype($path) { - try { - $stat = $this->getConnection()->stat($this->absPath($path)); - if ($stat['type'] == NET_SFTP_TYPE_REGULAR) { - return 'file'; - } - - if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) { - return 'dir'; - } - } catch (\Exception $e) { - - } - return false; - } - - /** - * {@inheritdoc} - */ - public function file_exists($path) { - try { - return $this->getConnection()->stat($this->absPath($path)) !== false; - } catch (\Exception $e) { - return false; - } - } - - /** - * {@inheritdoc} - */ - public function unlink($path) { - try { - return $this->getConnection()->delete($this->absPath($path), true); - } catch (\Exception $e) { - return false; - } - } - - /** - * {@inheritdoc} - */ - public function fopen($path, $mode) { - try { - $absPath = $this->absPath($path); - switch($mode) { - case 'r': - case 'rb': - if ( !$this->file_exists($path)) { - return false; - } - case 'w': - case 'wb': - case 'a': - case 'ab': - case 'r+': - case 'w+': - case 'wb+': - case 'a+': - case 'x': - case 'x+': - case 'c': - case 'c+': - $context = stream_context_create(array('sftp' => array('session' => $this->getConnection()))); - $handle = fopen($this->constructUrl($path), $mode, false, $context); - return RetryWrapper::wrap($handle); - } - } catch (\Exception $e) { - } - return false; - } - - /** - * {@inheritdoc} - */ - public function touch($path, $mtime=null) { - try { - if (!is_null($mtime)) { - return false; - } - if (!$this->file_exists($path)) { - $this->getConnection()->put($this->absPath($path), ''); - } else { - return false; - } - } catch (\Exception $e) { - return false; - } - return true; - } - - /** - * @param string $path - * @param string $target - * @throws \Exception - */ - public function getFile($path, $target) { - $this->getConnection()->get($path, $target); - } - - /** - * @param string $path - * @param string $target - * @throws \Exception - */ - public function uploadFile($path, $target) { - $this->getConnection()->put($target, $path, NET_SFTP_LOCAL_FILE); - } - - /** - * {@inheritdoc} - */ - public function rename($source, $target) { - try { - if (!$this->is_dir($target) && $this->file_exists($target)) { - $this->unlink($target); - } - return $this->getConnection()->rename( - $this->absPath($source), - $this->absPath($target) - ); - } catch (\Exception $e) { - return false; - } - } - - /** - * {@inheritdoc} - */ - public function stat($path) { - try { - $stat = $this->getConnection()->stat($this->absPath($path)); - - $mtime = $stat ? $stat['mtime'] : -1; - $size = $stat ? $stat['size'] : 0; - - return array('mtime' => $mtime, 'size' => $size, 'ctime' => -1); - } catch (\Exception $e) { - return false; - } - } - - /** - * @param string $path - * @return string - */ - public function constructUrl($path) { - // Do not pass the password here. We want to use the Net_SFTP object - // supplied via stream context or fail. We only supply username and - // hostname because this might show up in logs (they are not used). - $url = 'sftp://' . urlencode($this->user) . '@' . $this->host . ':' . $this->port . $this->root . $path; - return $url; - } -} |