|
|
|
|
@ -26,6 +26,7 @@ namespace OCA\Encryption; |
|
|
|
|
use OC\DB\Connection; |
|
|
|
|
use OC\Files\View; |
|
|
|
|
use OCP\IConfig; |
|
|
|
|
use OCP\ILogger; |
|
|
|
|
|
|
|
|
|
class Migration { |
|
|
|
|
|
|
|
|
|
@ -37,17 +38,22 @@ class Migration { |
|
|
|
|
/** @var IConfig */ |
|
|
|
|
private $config; |
|
|
|
|
|
|
|
|
|
/** @var ILogger */ |
|
|
|
|
private $logger; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @param IConfig $config |
|
|
|
|
* @param View $view |
|
|
|
|
* @param Connection $connection |
|
|
|
|
* @param ILogger $logger |
|
|
|
|
*/ |
|
|
|
|
public function __construct(IConfig $config, View $view, Connection $connection) { |
|
|
|
|
public function __construct(IConfig $config, View $view, Connection $connection, ILogger $logger) { |
|
|
|
|
$this->view = $view; |
|
|
|
|
$this->view->getUpdater()->disable(); |
|
|
|
|
$this->connection = $connection; |
|
|
|
|
$this->moduleId = \OCA\Encryption\Crypto\Encryption::ID; |
|
|
|
|
$this->config = $config; |
|
|
|
|
$this->logger = $logger; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function finalCleanUp() { |
|
|
|
|
@ -234,9 +240,10 @@ class Migration { |
|
|
|
|
private function renameUsersPrivateKey($user) { |
|
|
|
|
$oldPrivateKey = $user . '/files_encryption/' . $user . '.privateKey'; |
|
|
|
|
$newPrivateKey = $user . '/files_encryption/' . $this->moduleId . '/' . $user . '.privateKey'; |
|
|
|
|
$this->createPathForKeys(dirname($newPrivateKey)); |
|
|
|
|
|
|
|
|
|
$this->view->rename($oldPrivateKey, $newPrivateKey); |
|
|
|
|
if ($this->view->file_exists($oldPrivateKey)) { |
|
|
|
|
$this->createPathForKeys(dirname($newPrivateKey)); |
|
|
|
|
$this->view->rename($oldPrivateKey, $newPrivateKey); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -247,9 +254,10 @@ class Migration { |
|
|
|
|
private function renameUsersPublicKey($user) { |
|
|
|
|
$oldPublicKey = '/files_encryption/public_keys/' . $user . '.publicKey'; |
|
|
|
|
$newPublicKey = $user . '/files_encryption/' . $this->moduleId . '/' . $user . '.publicKey'; |
|
|
|
|
$this->createPathForKeys(dirname($newPublicKey)); |
|
|
|
|
|
|
|
|
|
$this->view->rename($oldPublicKey, $newPublicKey); |
|
|
|
|
if ($this->view->file_exists($oldPublicKey)) { |
|
|
|
|
$this->createPathForKeys(dirname($newPublicKey)); |
|
|
|
|
$this->view->rename($oldPublicKey, $newPublicKey); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -261,6 +269,11 @@ class Migration { |
|
|
|
|
*/ |
|
|
|
|
private function renameFileKeys($user, $path, $trash = false) { |
|
|
|
|
|
|
|
|
|
if ($this->view->is_dir($user . '/' . $path) === false) { |
|
|
|
|
$this->logger->info('Skip dir /' . $user . '/' . $path . ': does not exist'); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$dh = $this->view->opendir($user . '/' . $path); |
|
|
|
|
|
|
|
|
|
if (is_resource($dh)) { |
|
|
|
|
@ -270,8 +283,15 @@ class Migration { |
|
|
|
|
$this->renameFileKeys($user, $path . '/' . $file, $trash); |
|
|
|
|
} else { |
|
|
|
|
$target = $this->getTargetDir($user, $path, $file, $trash); |
|
|
|
|
$this->createPathForKeys(dirname($target)); |
|
|
|
|
$this->view->rename($user . '/' . $path . '/' . $file, $target); |
|
|
|
|
if ($target) { |
|
|
|
|
$this->createPathForKeys(dirname($target)); |
|
|
|
|
$this->view->rename($user . '/' . $path . '/' . $file, $target); |
|
|
|
|
} else { |
|
|
|
|
$this->logger->warning( |
|
|
|
|
'did not move key "' . $file |
|
|
|
|
. '" could not find the corresponding file in /data/' . $user . '/files.' |
|
|
|
|
. 'Most likely the key was already moved in a previous migration run and is already on the right place.'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -279,23 +299,49 @@ class Migration { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* get system mount points |
|
|
|
|
* wrap static method so that it can be mocked for testing |
|
|
|
|
* |
|
|
|
|
* @return array |
|
|
|
|
*/ |
|
|
|
|
protected function getSystemMountPoints() { |
|
|
|
|
return \OC_Mount_Config::getSystemMountPoints(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* generate target directory |
|
|
|
|
* |
|
|
|
|
* @param string $user |
|
|
|
|
* @param string $filePath |
|
|
|
|
* @param string $keyPath |
|
|
|
|
* @param string $filename |
|
|
|
|
* @param bool $trash |
|
|
|
|
* @return string |
|
|
|
|
*/ |
|
|
|
|
private function getTargetDir($user, $filePath, $filename, $trash) { |
|
|
|
|
private function getTargetDir($user, $keyPath, $filename, $trash) { |
|
|
|
|
if ($trash) { |
|
|
|
|
$targetDir = $user . '/files_encryption/keys/files_trashbin/' . substr($filePath, strlen('/files_trashbin/keys/')) . '/' . $this->moduleId . '/' . $filename; |
|
|
|
|
$filePath = substr($keyPath, strlen('/files_trashbin/keys/')); |
|
|
|
|
$targetDir = $user . '/files_encryption/keys/files_trashbin/' . $filePath . '/' . $this->moduleId . '/' . $filename; |
|
|
|
|
} else { |
|
|
|
|
$targetDir = $user . '/files_encryption/keys/files/' . substr($filePath, strlen('/files_encryption/keys/')) . '/' . $this->moduleId . '/' . $filename; |
|
|
|
|
$filePath = substr($keyPath, strlen('/files_encryption/keys/')); |
|
|
|
|
$targetDir = $user . '/files_encryption/keys/files/' . $filePath . '/' . $this->moduleId . '/' . $filename; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return $targetDir; |
|
|
|
|
if ($user === '') { |
|
|
|
|
// for system wide mounts we need to check if the mount point really exists |
|
|
|
|
$normalized = trim($filePath, '/'); |
|
|
|
|
$systemMountPoints = $this->getSystemMountPoints(); |
|
|
|
|
foreach ($systemMountPoints as $mountPoint) { |
|
|
|
|
if (strpos($normalized, $mountPoint['mountpoint']) === 0) |
|
|
|
|
return $targetDir; |
|
|
|
|
} |
|
|
|
|
} else if ($trash === false && $this->view->file_exists('/' . $user. '/files/' . $filePath)) { |
|
|
|
|
return $targetDir; |
|
|
|
|
} else if ($trash === true && $this->view->file_exists('/' . $user. '/files_trashbin/' . $filePath)) { |
|
|
|
|
return $targetDir; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|