|
|
@@ -161,41 +161,39 @@ class Storage { |
|
|
|
* store a new version of a file. |
|
|
|
*/ |
|
|
|
public static function store($filename) { |
|
|
|
if(\OC::$server->getConfig()->getSystemValue('files_versions', Storage::DEFAULTENABLED)) { |
|
|
|
|
|
|
|
// if the file gets streamed we need to remove the .part extension |
|
|
|
// to get the right target |
|
|
|
$ext = pathinfo($filename, PATHINFO_EXTENSION); |
|
|
|
if ($ext === 'part') { |
|
|
|
$filename = substr($filename, 0, strlen($filename) - 5); |
|
|
|
} |
|
|
|
// if the file gets streamed we need to remove the .part extension |
|
|
|
// to get the right target |
|
|
|
$ext = pathinfo($filename, PATHINFO_EXTENSION); |
|
|
|
if ($ext === 'part') { |
|
|
|
$filename = substr($filename, 0, strlen($filename) - 5); |
|
|
|
} |
|
|
|
|
|
|
|
// we only handle existing files |
|
|
|
if (! Filesystem::file_exists($filename) || Filesystem::is_dir($filename)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// we only handle existing files |
|
|
|
if (! Filesystem::file_exists($filename) || Filesystem::is_dir($filename)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
list($uid, $filename) = self::getUidAndFilename($filename); |
|
|
|
list($uid, $filename) = self::getUidAndFilename($filename); |
|
|
|
|
|
|
|
$files_view = new View('/'.$uid .'/files'); |
|
|
|
$users_view = new View('/'.$uid); |
|
|
|
$files_view = new View('/'.$uid .'/files'); |
|
|
|
$users_view = new View('/'.$uid); |
|
|
|
|
|
|
|
// no use making versions for empty files |
|
|
|
if ($files_view->filesize($filename) === 0) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// no use making versions for empty files |
|
|
|
if ($files_view->filesize($filename) === 0) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// create all parent folders |
|
|
|
self::createMissingDirectories($filename, $users_view); |
|
|
|
// create all parent folders |
|
|
|
self::createMissingDirectories($filename, $users_view); |
|
|
|
|
|
|
|
self::scheduleExpire($uid, $filename); |
|
|
|
self::scheduleExpire($uid, $filename); |
|
|
|
|
|
|
|
// store a new version of a file |
|
|
|
$mtime = $users_view->filemtime('files/' . $filename); |
|
|
|
$users_view->copy('files/' . $filename, 'files_versions/' . $filename . '.v' . $mtime); |
|
|
|
// call getFileInfo to enforce a file cache entry for the new version |
|
|
|
$users_view->getFileInfo('files_versions/' . $filename . '.v' . $mtime); |
|
|
|
} |
|
|
|
// store a new version of a file |
|
|
|
$mtime = $users_view->filemtime('files/' . $filename); |
|
|
|
$users_view->copy('files/' . $filename, 'files_versions/' . $filename . '.v' . $mtime); |
|
|
|
// call getFileInfo to enforce a file cache entry for the new version |
|
|
|
$users_view->getFileInfo('files_versions/' . $filename . '.v' . $mtime); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@@ -320,61 +318,60 @@ class Storage { |
|
|
|
*/ |
|
|
|
public static function rollback($file, $revision) { |
|
|
|
|
|
|
|
if(\OC::$server->getConfig()->getSystemValue('files_versions', Storage::DEFAULTENABLED)) { |
|
|
|
// add expected leading slash |
|
|
|
$file = '/' . ltrim($file, '/'); |
|
|
|
list($uid, $filename) = self::getUidAndFilename($file); |
|
|
|
if ($uid === null || trim($filename, '/') === '') { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// add expected leading slash |
|
|
|
$file = '/' . ltrim($file, '/'); |
|
|
|
list($uid, $filename) = self::getUidAndFilename($file); |
|
|
|
if ($uid === null || trim($filename, '/') === '') { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
$users_view = new View('/'.$uid); |
|
|
|
$files_view = new View('/'. User::getUser().'/files'); |
|
|
|
$users_view = new View('/'.$uid); |
|
|
|
$files_view = new View('/'. User::getUser().'/files'); |
|
|
|
|
|
|
|
$versionCreated = false; |
|
|
|
$versionCreated = false; |
|
|
|
|
|
|
|
$fileInfo = $files_view->getFileInfo($file); |
|
|
|
$fileInfo = $files_view->getFileInfo($file); |
|
|
|
|
|
|
|
// check if user has the permissions to revert a version |
|
|
|
if (!$fileInfo->isUpdateable()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// check if user has the permissions to revert a version |
|
|
|
if (!$fileInfo->isUpdateable()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
//first create a new version |
|
|
|
$version = 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename); |
|
|
|
if (!$users_view->file_exists($version)) { |
|
|
|
$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename)); |
|
|
|
$versionCreated = true; |
|
|
|
} |
|
|
|
//first create a new version |
|
|
|
$version = 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename); |
|
|
|
if (!$users_view->file_exists($version)) { |
|
|
|
$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename)); |
|
|
|
$versionCreated = true; |
|
|
|
} |
|
|
|
|
|
|
|
$fileToRestore = 'files_versions' . $filename . '.v' . $revision; |
|
|
|
|
|
|
|
// Restore encrypted version of the old file for the newly restored file |
|
|
|
// This has to happen manually here since the file is manually copied below |
|
|
|
$oldVersion = $users_view->getFileInfo($fileToRestore)->getEncryptedVersion(); |
|
|
|
$oldFileInfo = $users_view->getFileInfo($fileToRestore); |
|
|
|
$cache = $fileInfo->getStorage()->getCache(); |
|
|
|
$cache->update( |
|
|
|
$fileInfo->getId(), [ |
|
|
|
'encrypted' => $oldVersion, |
|
|
|
'encryptedVersion' => $oldVersion, |
|
|
|
'size' => $oldFileInfo->getSize() |
|
|
|
] |
|
|
|
); |
|
|
|
|
|
|
|
// rollback |
|
|
|
if (self::copyFileContents($users_view, $fileToRestore, 'files' . $filename)) { |
|
|
|
$files_view->touch($file, $revision); |
|
|
|
Storage::scheduleExpire($uid, $file); |
|
|
|
\OC_Hook::emit('\OCP\Versions', 'rollback', array( |
|
|
|
'path' => $filename, |
|
|
|
'revision' => $revision, |
|
|
|
)); |
|
|
|
return true; |
|
|
|
} else if ($versionCreated) { |
|
|
|
self::deleteVersion($users_view, $version); |
|
|
|
} |
|
|
|
$fileToRestore = 'files_versions' . $filename . '.v' . $revision; |
|
|
|
|
|
|
|
// Restore encrypted version of the old file for the newly restored file |
|
|
|
// This has to happen manually here since the file is manually copied below |
|
|
|
$oldVersion = $users_view->getFileInfo($fileToRestore)->getEncryptedVersion(); |
|
|
|
$oldFileInfo = $users_view->getFileInfo($fileToRestore); |
|
|
|
$cache = $fileInfo->getStorage()->getCache(); |
|
|
|
$cache->update( |
|
|
|
$fileInfo->getId(), [ |
|
|
|
'encrypted' => $oldVersion, |
|
|
|
'encryptedVersion' => $oldVersion, |
|
|
|
'size' => $oldFileInfo->getSize() |
|
|
|
] |
|
|
|
); |
|
|
|
|
|
|
|
// rollback |
|
|
|
if (self::copyFileContents($users_view, $fileToRestore, 'files' . $filename)) { |
|
|
|
$files_view->touch($file, $revision); |
|
|
|
Storage::scheduleExpire($uid, $file); |
|
|
|
\OC_Hook::emit('\OCP\Versions', 'rollback', array( |
|
|
|
'path' => $filename, |
|
|
|
'revision' => $revision, |
|
|
|
)); |
|
|
|
return true; |
|
|
|
} else if ($versionCreated) { |
|
|
|
self::deleteVersion($users_view, $version); |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
@@ -698,10 +695,9 @@ class Storage { |
|
|
|
* @return bool|int|null |
|
|
|
*/ |
|
|
|
public static function expire($filename, $uid) { |
|
|
|
$config = \OC::$server->getConfig(); |
|
|
|
$expiration = self::getExpiration(); |
|
|
|
|
|
|
|
if($config->getSystemValue('files_versions', Storage::DEFAULTENABLED) && $expiration->isEnabled()) { |
|
|
|
if ($expiration->isEnabled()) { |
|
|
|
// get available disk space for user |
|
|
|
$user = \OC::$server->getUserManager()->get($uid); |
|
|
|
if (is_null($user)) { |