Merge pull request #673 from owncloud/filesystem

Filecache rewrite
This commit is contained in:
icewind1991 2013-01-30 13:22:33 -08:00
commit 0cde86ac55
123 changed files with 7002 additions and 4374 deletions

View File

@ -12,10 +12,12 @@ $files = isset($_POST["file"]) ? stripslashes($_POST["file"]) : stripslashes($_P
$files = json_decode($files);
$filesWithError = '';
$success = true;
//Now delete
foreach ($files as $file) {
if (!OC_Files::delete($dir, $file)) {
if (($dir === '' && $file === 'Shared') || !\OC\Files\Filesystem::unlink($dir . '/' . $file)) {
$filesWithError .= $file . "\n";
$success = false;
}

View File

@ -32,7 +32,7 @@ if($doBreadcrumb) {
// make filelist
$files = array();
foreach( OC_Files::getdirectorycontent( $dir ) as $i ) {
foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) {
$i["date"] = OCP\Util::formatDate($i["mtime"] );
$files[] = $i;
}

View File

@ -11,15 +11,19 @@ $dir = stripslashes($_POST["dir"]);
$file = stripslashes($_POST["file"]);
$target = stripslashes(rawurldecode($_POST["target"]));
$l=OC_L10N::get('files');
if(OC_Filesystem::file_exists($target . '/' . $file)) {
OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s - File with this name already exists", array($file)) )));
if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) {
OCP\JSON::error(array("data" => array( "message" => "Could not move $file - File with this name already exists" )));
exit;
}
if(OC_Files::move($dir, $file, $target, $file)) {
OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file )));
} else {
OCP\JSON::error(array("data" => array( "message" => $l->t("Could not move %s", array($file)) )));
if ($dir != '' || $file != 'Shared') {
$targetFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file);
$sourceFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file);
if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) {
OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file )));
} else {
OCP\JSON::error(array("data" => array( "message" => "Could not move $file" )));
}
}else{
OCP\JSON::error(array("data" => array( "message" => "Could not move $file" )));
}

View File

@ -63,13 +63,12 @@ if($source) {
$ctx = stream_context_create(null, array('notification' =>'progress'));
$sourceStream=fopen($source, 'rb', false, $ctx);
$target=$dir.'/'.$filename;
$result=OC_Filesystem::file_put_contents($target, $sourceStream);
$result=\OC\Files\Filesystem::file_put_contents($target, $sourceStream);
if($result) {
$target = OC_Filesystem::normalizePath($target);
$meta = OC_FileCache::get($target);
$meta = \OC\Files\Filesystem::getFileInfo($target);
$mime=$meta['mimetype'];
$id = OC_FileCache::getId($target);
$eventSource->send('success', array('mime'=>$mime, 'size'=>OC_Filesystem::filesize($target), 'id' => $id));
$id = $meta['fileid'];
$eventSource->send('success', array('mime'=>$mime, 'size'=>\OC\Files\Filesystem::filesize($target), 'id' => $id));
} else {
$eventSource->send('error', "Error while downloading ".$source. ' to '.$target);
}
@ -77,15 +76,15 @@ if($source) {
exit();
} else {
if($content) {
if(OC_Filesystem::file_put_contents($dir.'/'.$filename, $content)) {
$meta = OC_FileCache::get($dir.'/'.$filename);
$id = OC_FileCache::getId($dir.'/'.$filename);
if(\OC\Files\Filesystem::file_put_contents($dir.'/'.$filename, $content)) {
$meta = \OC\Files\Filesystem::getFileInfo($dir.'/'.$filename);
$id = $meta['fileid'];
OCP\JSON::success(array("data" => array('content'=>$content, 'id' => $id)));
exit();
}
}elseif(OC_Files::newFile($dir, $filename, 'file')) {
$meta = OC_FileCache::get($dir.'/'.$filename);
$id = OC_FileCache::getId($dir.'/'.$filename);
}elseif(\OC\Files\Filesystem::touch($dir . '/' . $filename)) {
$meta = \OC\Files\Filesystem::getFileInfo($dir.'/'.$filename);
$id = $meta['fileid'];
OCP\JSON::success(array("data" => array('content'=>$content, 'id' => $id)));
exit();
}

View File

@ -19,13 +19,14 @@ if(strpos($foldername, '/')!==false) {
exit();
}
if(OC_Files::newFile($dir, stripslashes($foldername), 'dir')) {
if(\OC\Files\Filesystem::mkdir($dir . '/' . stripslashes($foldername))) {
if ( $dir != '/') {
$path = $dir.'/'.$foldername;
} else {
$path = '/'.$foldername;
}
$id = OC_FileCache::getId($path);
$meta = \OC\Files\Filesystem::getFileInfo($path);
$id = $meta['fileid'];
OCP\JSON::success(array("data" => array('id'=>$id)));
exit();
}

View File

@ -15,7 +15,7 @@ $mimetype = isset($_GET['mimetype']) ? $_GET['mimetype'] : '';
// make filelist
$files = array();
foreach( OC_Files::getdirectorycontent( $dir, $mimetype ) as $i ) {
foreach( \OC\Files\Filesystem::getDirectoryContent( $dir, $mimetype ) as $i ) {
$i["date"] = OCP\Util::formatDate($i["mtime"] );
$i['mimetype_icon'] = $i['type'] == 'dir' ? \mimetype_icon('dir'): \mimetype_icon($i['mimetype']);
$files[] = $i;

View File

@ -11,10 +11,14 @@ $dir = stripslashes($_GET["dir"]);
$file = stripslashes($_GET["file"]);
$newname = stripslashes($_GET["newname"]);
// Delete
if( $newname !== '.' and OC_Files::move( $dir, $file, $dir, $newname )) {
OCP\JSON::success(array("data" => array( "dir" => $dir, "file" => $file, "newname" => $newname )));
} else {
$l=OC_L10N::get('files');
OCP\JSON::error(array("data" => array( "message" => $l->t("Unable to rename file") )));
if ( $newname !== '.' and ($dir != '' || $file != 'Shared') and $newname !== '.') {
$targetFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $newname);
$sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file);
if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) {
OCP\JSON::success(array("data" => array( "dir" => $dir, "file" => $file, "newname" => $newname )));
} else {
OCP\JSON::error(array("data" => array( "message" => "Unable to rename file" )));
}
}else{
OCP\JSON::error(array("data" => array( "message" => "Unable to rename file" )));
}

View File

@ -1,44 +1,71 @@
<?php
set_time_limit(0);//scanning can take ages
$force=isset($_GET['force']) and $_GET['force']=='true';
$dir=isset($_GET['dir'])?$_GET['dir']:'';
$checkOnly=isset($_GET['checkonly']) and $_GET['checkonly']=='true';
$eventSource=false;
if(!$checkOnly) {
$eventSource=new OC_EventSource();
}
set_time_limit(0); //scanning can take ages
session_write_close();
//create the file cache if necessary
if($force or !OC_FileCache::inCache('')) {
if(!$checkOnly) {
OCP\DB::beginTransaction();
$force = (isset($_GET['force']) and ($_GET['force'] === 'true'));
$dir = isset($_GET['dir']) ? $_GET['dir'] : '';
if(OC_Cache::isFast()) {
OC_Cache::clear('fileid/'); //make sure the old fileid's don't mess things up
$eventSource = new OC_EventSource();
ScanListener::$eventSource = $eventSource;
ScanListener::$view = \OC\Files\Filesystem::getView();
OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_folder', 'ScanListener', 'folder');
OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_file', 'ScanListener', 'file');
$absolutePath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir);
$mountPoints = \OC\Files\Filesystem::getMountPoints($absolutePath);
$mountPoints[] = \OC\Files\Filesystem::getMountPoint($absolutePath);
$mountPoints = array_reverse($mountPoints); //start with the mount point of $dir
foreach ($mountPoints as $mountPoint) {
$storage = \OC\Files\Filesystem::getStorage($mountPoint);
if ($storage) {
ScanListener::$mountPoints[$storage->getId()] = $mountPoint;
$scanner = $storage->getScanner();
if ($force) {
$scanner->scan('');
} else {
$scanner->backgroundScan();
}
OC_FileCache::scan($dir, $eventSource);
OC_FileCache::clean();
OCP\DB::commit();
$eventSource->send('success', true);
} else {
OCP\JSON::success(array('data'=>array('done'=>true)));
exit;
}
} else {
if($checkOnly) {
OCP\JSON::success(array('data'=>array('done'=>false)));
exit;
}
if(isset($eventSource)) {
$eventSource->send('success', false);
} else {
exit;
}
}
$eventSource->send('done', ScanListener::$fileCount);
$eventSource->close();
class ScanListener {
static public $fileCount = 0;
static public $lastCount = 0;
/**
* @var \OC\Files\View $view
*/
static public $view;
/**
* @var array $mountPoints map storage ids to mountpoints
*/
static public $mountPoints = array();
/**
* @var \OC_EventSource event source to pass events to
*/
static public $eventSource;
static function folder($params) {
$internalPath = $params['path'];
$mountPoint = self::$mountPoints[$params['storage']];
$path = self::$view->getRelativePath($mountPoint . $internalPath);
self::$eventSource->send('folder', $path);
}
static function file() {
self::$fileCount++;
if (self::$fileCount > self::$lastCount + 20) { //send a count update every 20 files
self::$lastCount = self::$fileCount;
self::$eventSource->send('count', self::$fileCount);
}
}
}

View File

@ -0,0 +1,44 @@
<?php
set_time_limit(0); //scanning can take ages
session_write_close();
$user = OC_User::getUser();
$eventSource = new OC_EventSource();
$listener = new UpgradeListener($eventSource);
$legacy = new \OC\Files\Cache\Legacy($user);
if ($legacy->hasItems()) {
OC_Hook::connect('\OC\Files\Cache\Upgrade', 'migrate_path', $listener, 'upgradePath');
OC_DB::beginTransaction();
$upgrade = new \OC\Files\Cache\Upgrade($legacy);
$count = $legacy->getCount();
$eventSource->send('total', $count);
$upgrade->upgradePath('/' . $user . '/files');
OC_DB::commit();
}
\OC\Files\Cache\Upgrade::upgradeDone($user);
$eventSource->send('done', true);
$eventSource->close();
class UpgradeListener {
/**
* @var OC_EventSource $eventSource
*/
private $eventSource;
private $count = 0;
private $lastSend = 0;
public function __construct($eventSource) {
$this->eventSource = $eventSource;
}
public function upgradePath($path) {
$this->count++;
if ($this->count > ($this->lastSend + 5)) {
$this->lastSend = $this->count;
$this->eventSource->send('count', $this->count);
}
}
}

View File

@ -21,13 +21,13 @@ if (!isset($_FILES['files'])) {
foreach ($_FILES['files']['error'] as $error) {
if ($error != 0) {
$errors = array(
UPLOAD_ERR_OK => $l->t('There is no error, the file uploaded with success'),
UPLOAD_ERR_INI_SIZE => $l->t('The uploaded file exceeds the upload_max_filesize directive in php.ini: ')
UPLOAD_ERR_OK => $l->t('There is no error, the file uploaded with success'),
UPLOAD_ERR_INI_SIZE => $l->t('The uploaded file exceeds the upload_max_filesize directive in php.ini: ')
. ini_get('upload_max_filesize'),
UPLOAD_ERR_FORM_SIZE => $l->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified'
UPLOAD_ERR_FORM_SIZE => $l->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified'
. ' in the HTML form'),
UPLOAD_ERR_PARTIAL => $l->t('The uploaded file was only partially uploaded'),
UPLOAD_ERR_NO_FILE => $l->t('No file was uploaded'),
UPLOAD_ERR_PARTIAL => $l->t('The uploaded file was only partially uploaded'),
UPLOAD_ERR_NO_FILE => $l->t('No file was uploaded'),
UPLOAD_ERR_NO_TMP_DIR => $l->t('Missing a temporary folder'),
UPLOAD_ERR_CANT_WRITE => $l->t('Failed to write to disk'),
);
@ -40,12 +40,17 @@ $files = $_FILES['files'];
$dir = $_POST['dir'];
$error = '';
$maxUploadFilesize = OCP\Util::maxUploadFilesize($dir);
$maxHumanFilesize = OCP\Util::humanFileSize($maxUploadFilesize);
$totalSize = 0;
foreach ($files['size'] as $size) {
$totalSize += $size;
}
if ($totalSize > OC_Filesystem::free_space($dir)) {
OCP\JSON::error(array('data' => array_merge(array('message' => $l->t('Not enough storage available')), $storageStats)));
if ($totalSize > \OC\Files\Filesystem::free_space($dir)) {
OCP\JSON::error(array('data' => array('message' => $l->t('Not enough space available'),
'uploadMaxFilesize' => $maxUploadFilesize,
'maxHumanFilesize' => $maxHumanFilesize)));
exit();
}
@ -55,19 +60,19 @@ if (strpos($dir, '..') === false) {
for ($i = 0; $i < $fileCount; $i++) {
$target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]);
// $path needs to be normalized - this failed within drag'n'drop upload to a sub-folder
$target = OC_Filesystem::normalizePath($target);
if (is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i], $target)) {
$meta = OC_FileCache::get($target);
$id = OC_FileCache::getId($target);
$target = \OC\Files\Filesystem::normalizePath($target);
if (is_uploaded_file($files['tmp_name'][$i]) and \OC\Files\Filesystem::fromTmpFile($files['tmp_name'][$i], $target)) {
$meta = \OC\Files\Filesystem::getFileInfo($target);
// updated max file size after upload
$storageStats = \OCA\files\lib\Helper::buildFileStorageStatistics($dir);
$result[] = array_merge(array('status' => 'success',
'mime' => $meta['mimetype'],
'size' => $meta['size'],
'id' => $id,
'name' => basename($target)), $storageStats
$result[] = array('status' => 'success',
'mime' => $meta['mimetype'],
'size' => $meta['size'],
'id' => $meta['fileid'],
'name' => basename($target),
'uploadMaxFilesize' => $maxUploadFilesize,
'maxHumanFilesize' => $maxHumanFilesize
);
}
}

View File

@ -1,5 +1,5 @@
<?php
$l=OC_L10N::get('files');
$l = OC_L10N::get('files');
OCP\App::registerAdmin('files', 'admin');

View File

@ -43,7 +43,7 @@ if ($type != 'oc_chunked') {
die;
}
if (!OC_Filesystem::is_file($file)) {
if (!\OC\Files\Filesystem::is_file($file)) {
OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND);
die;
}
@ -51,7 +51,7 @@ if (!OC_Filesystem::is_file($file)) {
switch($_SERVER['REQUEST_METHOD']) {
case 'PUT':
$input = fopen("php://input", "r");
$org_file = OC_Filesystem::fopen($file, 'rb');
$org_file = \OC\Files\Filesystem::fopen($file, 'rb');
$info = array(
'name' => basename($file),
);

View File

@ -5,7 +5,7 @@
<description>File Management</description>
<licence>AGPL</licence>
<author>Robin Appelman</author>
<require>4.9</require>
<require>4.91</require>
<shipped>true</shipped>
<standalone/>
<default_enable/>

View File

@ -1 +1 @@
1.1.6
1.1.7

View File

@ -132,4 +132,12 @@ table.dragshadow td.filename {
}
table.dragshadow td.size {
padding-right:8px;
}
}
#upgrade {
width: 400px;
position: absolute;
top: 200px;
left: 50%;
text-align: center;
margin-left: -200px;
}

View File

@ -26,7 +26,7 @@ OCP\User::checkLoggedIn();
$filename = $_GET["file"];
if(!OC_Filesystem::file_exists($filename)) {
if(!\OC\Files\Filesystem::file_exists($filename)) {
header("HTTP/1.0 404 Not Found");
$tmpl = new OCP\Template( '', '404', 'guest' );
$tmpl->assign('file', $filename);
@ -34,7 +34,7 @@ if(!OC_Filesystem::file_exists($filename)) {
exit;
}
$ftype=OC_Filesystem::getMimeType( $filename );
$ftype=\OC\Files\Filesystem::getMimeType( $filename );
header('Content-Type:'.$ftype);
if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) {
@ -44,7 +44,7 @@ if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) {
. '; filename="' . rawurlencode( basename($filename) ) . '"' );
}
OCP\Response::disableCaching();
header('Content-Length: '.OC_Filesystem::filesize($filename));
header('Content-Length: '.\OC\Files\Filesystem::filesize($filename));
OC_Util::obEnd();
OC_Filesystem::readfile( $filename );
\OC\Files\Filesystem::readfile( $filename );

View File

@ -29,22 +29,39 @@ OCP\Util::addStyle('files', 'files');
OCP\Util::addscript('files', 'jquery.iframe-transport');
OCP\Util::addscript('files', 'jquery.fileupload');
OCP\Util::addscript('files', 'jquery-visibility');
OCP\Util::addscript('files', 'files');
OCP\Util::addscript('files', 'filelist');
OCP\Util::addscript('files', 'fileactions');
OCP\Util::addscript('files', 'keyboardshortcuts');
OCP\App::setActiveNavigationEntry('files_index');
// Load the files
$dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : '';
// Redirect if directory does not exist
if (!OC_Filesystem::is_dir($dir . '/')) {
if (!\OC\Files\Filesystem::is_dir($dir . '/')) {
header('Location: ' . $_SERVER['SCRIPT_NAME'] . '');
exit();
}
function fileCmp($a, $b) {
if ($a['type'] == 'dir' and $b['type'] != 'dir') {
return -1;
} elseif ($a['type'] != 'dir' and $b['type'] == 'dir') {
return 1;
} else {
return strnatcasecmp($a['name'], $b['name']);
}
}
$files = array();
foreach (OC_Files::getdirectorycontent($dir) as $i) {
$user = OC_User::getUser();
if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache
$content = array();
$needUpgrade = true;
$freeSpace = 0;
} else {
$content = \OC\Files\Filesystem::getDirectoryContent($dir);
$freeSpace = \OC\Files\Filesystem::free_space($dir);
$needUpgrade = false;
}
foreach ($content as $i) {
$i['date'] = OCP\Util::formatDate($i['mtime']);
if ($i['type'] == 'file') {
$fileinfo = pathinfo($i['name']);
@ -55,12 +72,12 @@ foreach (OC_Files::getdirectorycontent($dir) as $i) {
$i['extension'] = '';
}
}
if ($i['directory'] == '/') {
$i['directory'] = '';
}
$i['directory'] = $dir;
$files[] = $i;
}
usort($files, "fileCmp");
// Make breadcrumb
$breadcrumb = array();
$pathtohere = '';
@ -81,34 +98,42 @@ $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '');
$breadcrumbNav->assign('breadcrumb', $breadcrumb, false);
$breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir=', false);
$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir);
$permissions = OCP\PERMISSION_READ;
if (OC_Filesystem::isCreatable($dir . '/')) {
if (\OC\Files\Filesystem::isCreatable($dir . '/')) {
$permissions |= OCP\PERMISSION_CREATE;
}
if (OC_Filesystem::isUpdatable($dir . '/')) {
if (\OC\Files\Filesystem::isUpdatable($dir . '/')) {
$permissions |= OCP\PERMISSION_UPDATE;
}
if (OC_Filesystem::isDeletable($dir . '/')) {
if (\OC\Files\Filesystem::isDeletable($dir . '/')) {
$permissions |= OCP\PERMISSION_DELETE;
}
if (OC_Filesystem::isSharable($dir . '/')) {
if (\OC\Files\Filesystem::isSharable($dir . '/')) {
$permissions |= OCP\PERMISSION_SHARE;
}
// information about storage capacities
$storageInfo=OC_Helper::getStorageInfo();
if ($needUpgrade) {
OCP\Util::addscript('files', 'upgrade');
$tmpl = new OCP\Template('files', 'upgrade', 'user');
$tmpl->printPage();
} else {
// information about storage capacities
$storageInfo=OC_Helper::getStorageInfo();
$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir);
$tmpl = new OCP\Template('files', 'index', 'user');
$tmpl->assign('fileList', $list->fetchPage(), false);
$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false);
$tmpl->assign('dir', OC_Filesystem::normalizePath($dir));
$tmpl->assign('isCreatable', OC_Filesystem::isCreatable($dir . '/'));
$tmpl->assign('permissions', $permissions);
$tmpl->assign('files', $files);
$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
$tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']);
$tmpl->printPage();
OCP\Util::addscript('files', 'fileactions');
OCP\Util::addscript('files', 'files');
OCP\Util::addscript('files', 'keyboardshortcuts');
$tmpl = new OCP\Template('files', 'index', 'user');
$tmpl->assign('fileList', $list->fetchPage(), false);
$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false);
$tmpl->assign('dir', \OC\Files\Filesystem::normalizePath($dir));
$tmpl->assign('isCreatable', \OC\Files\Filesystem::isCreatable($dir . '/'));
$tmpl->assign('permissions', $permissions);
$tmpl->assign('files', $files);
$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
$tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']);
$tmpl->printPage();
}

View File

@ -670,12 +670,8 @@ $(document).ready(function() {
});
});
//check if we need to scan the filesystem
$.get(OC.filePath('files','ajax','scan.php'),{checkonly:'true'}, function(response) {
if(response.data.done){
scanFiles();
}
}, "json");
//do a background scan if needed
scanFiles();
var lastWidth = 0;
var breadcrumbs = [];
@ -774,27 +770,23 @@ $(document).ready(function() {
}
});
function scanFiles(force,dir){
function scanFiles(force, dir){
if(!dir){
dir='';
dir = '';
}
force=!!force; //cast to bool
scanFiles.scanning=true;
$('#scanning-message').show();
$('#fileList').remove();
var scannerEventSource=new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force,dir:dir});
scanFiles.cancel=scannerEventSource.close.bind(scannerEventSource);
scannerEventSource.listen('scanning',function(data){
$('#scan-count').text(t('files', '{count} files scanned', {count: data.count}));
$('#scan-current').text(data.file+'/');
force = !!force; //cast to bool
scanFiles.scanning = true;
var scannerEventSource = new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force,dir:dir});
scanFiles.cancel = scannerEventSource.close.bind(scannerEventSource);
scannerEventSource.listen('count',function(count){
console.log(count + 'files scanned')
});
scannerEventSource.listen('success',function(success){
scannerEventSource.listen('folder',function(path){
console.log('now scanning ' + path)
});
scannerEventSource.listen('done',function(count){
scanFiles.scanning=false;
if(success){
window.location.reload();
}else{
alert(t('files', 'error while scanning'));
}
console.log('done after ' + count + 'files');
});
}
scanFiles.scanning=false;

17
apps/files/js/upgrade.js Normal file
View File

@ -0,0 +1,17 @@
$(document).ready(function () {
var eventSource, total, bar = $('#progressbar');
console.log('start');
bar.progressbar({value: 0});
eventSource = new OC.EventSource(OC.filePath('files', 'ajax', 'upgrade.php'));
eventSource.listen('total', function (count) {
total = count;
console.log(count + ' files needed to be migrated');
});
eventSource.listen('count', function (count) {
bar.progressbar({value: (count / total) * 100});
console.log(count);
});
eventSource.listen('done', function () {
document.location.reload();
});
});

View File

@ -32,7 +32,7 @@ OCP\Util::addscript( "files", "files" );
$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
$files = array();
foreach( OC_Files::getdirectorycontent( $dir ) as $i ) {
foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) {
$i["date"] = date( $CONFIG_DATEFORMAT, $i["mtime"] );
$files[] = $i;
}

View File

@ -13,7 +13,7 @@
$name = str_replace('%2F', '/', $name);
$directory = str_replace('+', '%20', urlencode($file['directory']));
$directory = str_replace('%2F', '/', $directory); ?>
<tr data-id="<?php echo $file['id']; ?>"
<tr data-id="<?php echo $file['fileid']; ?>"
data-file="<?php echo $name;?>"
data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>"
data-mime="<?php echo $file['mimetype']?>"
@ -28,7 +28,7 @@
>
<?php if(!isset($_['readonly']) || !$_['readonly']): ?><input type="checkbox" /><?php endif; ?>
<?php if($file['type'] == 'dir'): ?>
<a class="name" href="<?php $_['baseURL'].$directory.'/'.$name; ?>)" title="">
<a class="name" href="<?php echo $_['baseURL'].$directory.'/'.$name; ?>)" title="">
<?php else: ?>
<a class="name" href="<?php echo $_['downloadURL'].$directory.'/'.$name; ?>" title="">
<?php endif; ?>
@ -61,4 +61,4 @@
</span>
</td>
</tr>
<?php endforeach;
<?php endforeach;

View File

@ -0,0 +1,4 @@
<div id="upgrade">
<?php echo $l->t('Upgrading filesystem cache...');?>
<div id="progressbar" />
</div>

View File

@ -12,8 +12,10 @@ $data = fread($fh, filesize($_FILES['rootcert_import']['tmp_name']));
fclose($fh);
$filename = $_FILES['rootcert_import']['name'];
$view = new \OC_FilesystemView('/'.\OCP\User::getUser().'/files_external/uploads');
if ( ! $view->file_exists('')) $view->mkdir('');
$view = new \OC\Files\View('/'.\OCP\User::getUser().'/files_external/uploads');
if (!$view->file_exists('')){
$view->mkdir('');
}
$isValid = openssl_pkey_get_public($data);

View File

@ -6,14 +6,14 @@
* See the COPYING-README file.
*/
OC::$CLASSPATH['OC_FileStorage_StreamWrapper']='apps/files_external/lib/streamwrapper.php';
OC::$CLASSPATH['OC_Filestorage_FTP']='apps/files_external/lib/ftp.php';
OC::$CLASSPATH['OC_Filestorage_DAV']='apps/files_external/lib/webdav.php';
OC::$CLASSPATH['OC_Filestorage_Google']='apps/files_external/lib/google.php';
OC::$CLASSPATH['OC_Filestorage_SWIFT']='apps/files_external/lib/swift.php';
OC::$CLASSPATH['OC_Filestorage_SMB']='apps/files_external/lib/smb.php';
OC::$CLASSPATH['OC_Filestorage_AmazonS3']='apps/files_external/lib/amazons3.php';
OC::$CLASSPATH['OC_Filestorage_Dropbox']='apps/files_external/lib/dropbox.php';
OC::$CLASSPATH['OC\Files\Storage\StreamWrapper']='apps/files_external/lib/streamwrapper.php';
OC::$CLASSPATH['OC\Files\Storage\FTP']='apps/files_external/lib/ftp.php';
OC::$CLASSPATH['OC\Files\Storage\DAV']='apps/files_external/lib/webdav.php';
OC::$CLASSPATH['OC\Files\Storage\Google']='apps/files_external/lib/google.php';
OC::$CLASSPATH['OC\Files\Storage\SWIFT']='apps/files_external/lib/swift.php';
OC::$CLASSPATH['OC\Files\Storage\SMB']='apps/files_external/lib/smb.php';
OC::$CLASSPATH['OC\Files\Storage\AmazonS3']='apps/files_external/lib/amazons3.php';
OC::$CLASSPATH['OC\Files\Storage\Dropbox']='apps/files_external/lib/dropbox.php';
OC::$CLASSPATH['OC_Mount_Config']='apps/files_external/lib/config.php';
OCP\App::registerAdmin('files_external', 'settings');

View File

@ -5,7 +5,7 @@
<description>Mount external storage sources</description>
<licence>AGPL</licence>
<author>Robin Appelman, Michael Gapczynski</author>
<require>4.9</require>
<require>4.91</require>
<shipped>true</shipped>
<types>
<filesystem/>

View File

@ -1,6 +1,6 @@
$(document).ready(function() {
$('#externalStorage tbody tr.OC_Filestorage_Dropbox').each(function() {
$('#externalStorage tbody tr.\\\\OC\\\\Files\\\\Storage\\\\Dropbox').each(function() {
var configured = $(this).find('[data-parameter="configured"]');
if ($(configured).val() == 'true') {
$(this).find('.configuration input').attr('disabled', 'disabled');
@ -38,7 +38,7 @@ $(document).ready(function() {
$('#externalStorage tbody tr input').live('keyup', function() {
var tr = $(this).parent().parent();
if ($(tr).hasClass('OC_Filestorage_Dropbox') && $(tr).find('[data-parameter="configured"]').val() != 'true') {
if ($(tr).hasClass('\\\\OC\\\\Files\\\\Storage\\\\Dropbox') && $(tr).find('[data-parameter="configured"]').val() != 'true') {
var config = $(tr).find('.configuration');
if ($(tr).find('.mountPoint input').val() != '' && $(config).find('[data-parameter="app_key"]').val() != '' && $(config).find('[data-parameter="app_secret"]').val() != '') {
if ($(tr).find('.dropbox').length == 0) {

View File

@ -1,6 +1,6 @@
$(document).ready(function() {
$('#externalStorage tbody tr.OC_Filestorage_Google').each(function() {
$('#externalStorage tbody tr.\\\\OC\\\\Files\\\\Storage\\\\Google').each(function() {
var configured = $(this).find('[data-parameter="configured"]');
if ($(configured).val() == 'true') {
$(this).find('.configuration')
@ -34,7 +34,8 @@ $(document).ready(function() {
});
$('#externalStorage tbody tr').live('change', function() {
if ($(this).hasClass('OC_Filestorage_Google') && $(this).find('[data-parameter="configured"]').val() != 'true') {
console.log('hello');
if ($(this).hasClass('\\\\OC\\\\Files\\\\Storage\\\\Google') && $(this).find('[data-parameter="configured"]').val() != 'true') {
if ($(this).find('.mountPoint input').val() != '') {
if ($(this).find('.google').length == 0) {
$(this).find('.configuration').append('<a class="button google">'+t('files_external', 'Grant access')+'</a>');
@ -45,7 +46,7 @@ $(document).ready(function() {
$('#externalStorage tbody tr .mountPoint input').live('keyup', function() {
var tr = $(this).parent().parent();
if ($(tr).hasClass('OC_Filestorage_Google') && $(tr).find('[data-parameter="configured"]').val() != 'true' && $(tr).find('.google').length > 0) {
if ($(tr).hasClass('\\\\OC\\\\Files\\\\Storage\\\\Google') && $(tr).find('[data-parameter="configured"]').val() != 'true' && $(tr).find('.google').length > 0) {
if ($(this).val() != '') {
$(tr).find('.google').show();
} else {

View File

@ -100,7 +100,7 @@ $(document).ready(function() {
td.append('<input type="text" data-parameter="'+parameter+'" placeholder="'+placeholder+'" />');
}
});
if (parameters['custom'] && $('#externalStorage tbody tr.'+backendClass).length == 1) {
if (parameters['custom'] && $('#externalStorage tbody tr.'+backendClass.replace(/\\/g, '\\\\')).length == 1) {
OC.addScript('files_external', parameters['custom']);
}
return false;

View File

@ -1,39 +1,43 @@
<?php
/**
* ownCloud
*
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
* ownCloud
*
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OC\Files\Storage;
require_once 'aws-sdk/sdk.class.php';
class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
class AmazonS3 extends \OC\Files\Storage\Common {
private $s3;
private $bucket;
private $objects = array();
private $id;
private static $tempFiles = array();
// TODO options: storage class, encryption server side, encrypt before upload?
public function __construct($params) {
$this->s3 = new AmazonS3(array('key' => $params['key'], 'secret' => $params['secret']));
$this->id = 'amazon::' . $params['key'] . md5($params['secret']);
$this->s3 = new \AmazonS3(array('key' => $params['key'], 'secret' => $params['secret']));
$this->bucket = $params['bucket'];
}
@ -47,7 +51,7 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
return $response;
// This object could be a folder, a '/' must be at the end of the path
} else if (substr($path, -1) != '/') {
$response = $this->s3->get_object_metadata($this->bucket, $path.'/');
$response = $this->s3->get_object_metadata($this->bucket, $path . '/');
if ($response) {
$this->objects[$path] = $response;
return $response;
@ -57,6 +61,10 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
return false;
}
public function getId() {
return $this->id;
}
public function mkdir($path) {
// Folders in Amazon S3 are 0 byte objects with a '/' at the end of the name
if (substr($path, -1) != '/') {
@ -96,8 +104,8 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
foreach ($response->body->CommonPrefixes as $object) {
$files[] = basename($object->Prefix);
}
OC_FakeDirStream::$dirs['amazons3'.$path] = $files;
return opendir('fakedir://amazons3'.$path);
\OC\Files\Stream\Dir::register('amazons3' . $path, $files);
return opendir('fakedir://amazons3' . $path);
}
return false;
}
@ -107,15 +115,10 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
$stat['size'] = $this->s3->get_bucket_filesize($this->bucket);
$stat['atime'] = time();
$stat['mtime'] = $stat['atime'];
$stat['ctime'] = $stat['atime'];
} else {
$object = $this->getObject($path);
if ($object) {
$stat['size'] = $object['Size'];
$stat['atime'] = time();
$stat['mtime'] = strtotime($object['LastModified']);
$stat['ctime'] = $stat['mtime'];
}
} else if ($object = $this->getObject($path)) {
$stat['size'] = $object['Size'];
$stat['atime'] = time();
$stat['mtime'] = strtotime($object['LastModified']);
}
if (isset($stat)) {
return $stat;
@ -166,7 +169,7 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
switch ($mode) {
case 'r':
case 'rb':
$tmpFile = OC_Helper::tmpFile();
$tmpFile = \OC_Helper::tmpFile();
$handle = fopen($tmpFile, 'w');
$response = $this->s3->get_object($this->bucket, $path, array('fileDownload' => $handle));
if ($response->isOK()) {
@ -190,14 +193,14 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
} else {
$ext = '';
}
$tmpFile = OC_Helper::tmpFile($ext);
OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack');
$tmpFile = \OC_Helper::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
file_put_contents($tmpFile, $source);
}
self::$tempFiles[$tmpFile] = $path;
return fopen('close://'.$tmpFile, $mode);
return fopen('close://' . $tmpFile, $mode);
}
return false;
}
@ -206,8 +209,8 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
if (isset(self::$tempFiles[$tmpFile])) {
$handle = fopen($tmpFile, 'r');
$response = $this->s3->create_object($this->bucket,
self::$tempFiles[$tmpFile],
array('fileUpload' => $handle));
self::$tempFiles[$tmpFile],
array('fileUpload' => $handle));
if ($response->isOK()) {
unlink($tmpFile);
}

View File

@ -38,20 +38,20 @@ class OC_Mount_Config {
* @return array
*/
public static function getBackends() {
$backends['OC_Filestorage_Local']=array(
$backends['\OC\Files\Storage\Local']=array(
'backend' => 'Local',
'configuration' => array(
'datadir' => 'Location'));
$backends['OC_Filestorage_AmazonS3']=array(
$backends['\OC\Files\Storage\AmazonS3']=array(
'backend' => 'Amazon S3',
'configuration' => array(
'key' => 'Key',
'secret' => '*Secret',
'bucket' => 'Bucket'));
$backends['OC_Filestorage_Dropbox']=array(
$backends['\OC\Files\Storage\Dropbox']=array(
'backend' => 'Dropbox',
'configuration' => array(
'configured' => '#configured',
@ -61,7 +61,7 @@ class OC_Mount_Config {
'token_secret' => '#token_secret'),
'custom' => 'dropbox');
if(OC_Mount_Config::checkphpftp()) $backends['OC_Filestorage_FTP']=array(
if(OC_Mount_Config::checkphpftp()) $backends['\OC\Files\Storage\FTP']=array(
'backend' => 'FTP',
'configuration' => array(
'host' => 'URL',
@ -70,15 +70,15 @@ class OC_Mount_Config {
'root' => '&Root',
'secure' => '!Secure ftps://'));
$backends['OC_Filestorage_Google']=array(
$backends['\OC\Files\Storage\Google']=array(
'backend' => 'Google Drive',
'configuration' => array(
'configured' => '#configured',
'token' => '#token',
'token_secret' => '#token secret'),
'custom' => 'google');
$backends['OC_Filestorage_SWIFT']=array(
$backends['\OC\Files\Storage\SWIFT']=array(
'backend' => 'OpenStack Swift',
'configuration' => array(
'host' => 'URL',
@ -86,8 +86,8 @@ class OC_Mount_Config {
'token' => '*Token',
'root' => '&Root',
'secure' => '!Secure ftps://'));
if(OC_Mount_Config::checksmbclient()) $backends['OC_Filestorage_SMB']=array(
if(OC_Mount_Config::checksmbclient()) $backends['\OC\Files\Storage\SMB']=array(
'backend' => 'SMB / CIFS',
'configuration' => array(
'host' => 'URL',
@ -95,8 +95,8 @@ class OC_Mount_Config {
'password' => '*Password',
'share' => 'Share',
'root' => '&Root'));
$backends['OC_Filestorage_DAV']=array(
$backends['\OC\Files\Storage\DAV']=array(
'backend' => 'ownCloud / WebDAV',
'configuration' => array(
'host' => 'URL',
@ -120,6 +120,10 @@ class OC_Mount_Config {
if (isset($mountPoints[self::MOUNT_TYPE_GROUP])) {
foreach ($mountPoints[self::MOUNT_TYPE_GROUP] as $group => $mounts) {
foreach ($mounts as $mountPoint => $mount) {
// Update old classes to new namespace
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
}
// Remove '/$user/files/' from mount point
$mountPoint = substr($mountPoint, 13);
// Merge the mount point into the current mount points
@ -139,6 +143,10 @@ class OC_Mount_Config {
if (isset($mountPoints[self::MOUNT_TYPE_USER])) {
foreach ($mountPoints[self::MOUNT_TYPE_USER] as $user => $mounts) {
foreach ($mounts as $mountPoint => $mount) {
// Update old classes to new namespace
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
}
// Remove '/$user/files/' from mount point
$mountPoint = substr($mountPoint, 13);
// Merge the mount point into the current mount points
@ -169,6 +177,10 @@ class OC_Mount_Config {
$personal = array();
if (isset($mountPoints[self::MOUNT_TYPE_USER][$uid])) {
foreach ($mountPoints[self::MOUNT_TYPE_USER][$uid] as $mountPoint => $mount) {
// Update old classes to new namespace
if (strpos($mount['class'], 'OC_Filestorage_') !== false) {
$mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15);
}
// Remove '/uid/files/' from mount point
$personal[substr($mountPoint, strlen($uid) + 8)] = array('class' => $mount['class'],
'backend' => $backends[$mount['class']]['backend'],
@ -178,22 +190,6 @@ class OC_Mount_Config {
return $personal;
}
/**
* Add directory for mount point to the filesystem
* @param OC_Fileview instance $view
* @param string path to mount point
*/
private static function addMountPointDirectory($view, $path) {
$dir = '';
foreach ( explode('/', $path) as $pathPart) {
$dir = $dir.'/'.$pathPart;
if ( !$view->file_exists($dir)) {
$view->mkdir($dir);
}
}
}
/**
* Add a mount point to the filesystem
* @param string Mount point
@ -213,36 +209,11 @@ class OC_Mount_Config {
if ($isPersonal) {
// Verify that the mount point applies for the current user
// Prevent non-admin users from mounting local storage
if ($applicable != OCP\User::getUser() || $class == 'OC_Filestorage_Local') {
if ($applicable != OCP\User::getUser() || $class == '\OC\Files\Storage\Local') {
return false;
}
$view = new OC_FilesystemView('/'.OCP\User::getUser().'/files');
self::addMountPointDirectory($view, ltrim($mountPoint, '/'));
$mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/');
} else {
$view = new OC_FilesystemView('/');
switch ($mountType) {
case 'user':
if ($applicable == "all") {
$users = OCP\User::getUsers();
foreach ( $users as $user ) {
$path = $user.'/files/'.ltrim($mountPoint, '/');
self::addMountPointDirectory($view, $path);
}
} else {
$path = $applicable.'/files/'.ltrim($mountPoint, '/');
self::addMountPointDirectory($view, $path);
}
break;
case 'group' :
$groupMembers = OC_Group::usersInGroups(array($applicable));
foreach ( $groupMembers as $user ) {
$path = $user.'/files/'.ltrim($mountPoint, '/');
self::addMountPointDirectory($view, $path);
}
break;
}
$mountPoint = '/$user/files/'.ltrim($mountPoint, '/');
}
$mount = array($applicable => array($mountPoint => array('class' => $class, 'options' => $classOptions)));

View File

@ -20,12 +20,15 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OC\Files\Storage;
require_once 'Dropbox/autoload.php';
class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
class Dropbox extends \OC\Files\Storage\Common {
private $dropbox;
private $root;
private $id;
private $metaData = array();
private static $tempFiles = array();
@ -37,13 +40,14 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
&& isset($params['token'])
&& isset($params['token_secret'])
) {
$this->id = 'dropbox::'.$params['app_key'] . $params['token']. '/' . $params['root'];
$this->root=isset($params['root'])?$params['root']:'';
$oauth = new Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']);
$oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']);
$oauth->setToken($params['token'], $params['token_secret']);
$this->dropbox = new Dropbox_API($oauth, 'dropbox');
$this->dropbox = new \Dropbox_API($oauth, 'dropbox');
$this->mkdir('');
} else {
throw new Exception('Creating OC_Filestorage_Dropbox storage failed');
throw new \Exception('Creating \OC\Files\Storage\Dropbox storage failed');
}
}
@ -55,8 +59,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
if ($list) {
try {
$response = $this->dropbox->getMetaData($path);
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
if ($response && isset($response['contents'])) {
@ -76,21 +80,25 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
$response = $this->dropbox->getMetaData($path, 'false');
$this->metaData[$path] = $response;
return $response;
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
}
}
}
public function getId(){
return $this->id;
}
public function mkdir($path) {
$path = $this->root.$path;
try {
$this->dropbox->createFolder($path);
return true;
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
}
@ -106,7 +114,7 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
foreach ($contents as $file) {
$files[] = basename($file['path']);
}
OC_FakeDirStream::$dirs['dropbox'.$path] = $files;
\OC\Files\Stream\Dir::register('dropbox'.$path, $files);
return opendir('fakedir://dropbox'.$path);
}
return false;
@ -118,7 +126,6 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
$stat['size'] = $metaData['bytes'];
$stat['atime'] = time();
$stat['mtime'] = (isset($metaData['modified'])) ? strtotime($metaData['modified']) : time();
$stat['ctime'] = $stat['mtime'];
return $stat;
}
return false;
@ -163,8 +170,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
try {
$this->dropbox->delete($path);
return true;
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
}
@ -175,8 +182,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
try {
$this->dropbox->move($path1, $path2);
return true;
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
}
@ -187,8 +194,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
try {
$this->dropbox->copy($path1, $path2);
return true;
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
}
@ -198,13 +205,13 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
switch ($mode) {
case 'r':
case 'rb':
$tmpFile = OC_Helper::tmpFile();
$tmpFile = \OC_Helper::tmpFile();
try {
$data = $this->dropbox->getFile($path);
file_put_contents($tmpFile, $data);
return fopen($tmpFile, 'r');
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
case 'w':
@ -224,8 +231,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
} else {
$ext = '';
}
$tmpFile = OC_Helper::tmpFile($ext);
OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack');
$tmpFile = \OC_Helper::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
file_put_contents($tmpFile, $source);
@ -242,8 +249,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
try {
$this->dropbox->putFile(self::$tempFiles[$tmpFile], $handle);
unlink($tmpFile);
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
}
}
}
@ -264,8 +271,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
try {
$info = $this->dropbox->getAccountInfo();
return $info['quota_info']['quota'] - $info['quota_info']['normal'];
} catch (Exception $exception) {
OCP\Util::writeLog('files_external', $exception->getMessage(), OCP\Util::ERROR);
} catch (\Exception $exception) {
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
return false;
}
}

View File

@ -6,7 +6,9 @@
* See the COPYING-README file.
*/
class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{
namespace OC\Files\Storage;
class FTP extends \OC\Files\Storage\StreamWrapper{
private $password;
private $user;
private $host;
@ -38,9 +40,13 @@ class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{
}
}
public function getId(){
return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root;
}
/**
* construct the ftp url
* @param string path
* @param string $path
* @return string
*/
public function constructUrl($path) {
@ -51,7 +57,8 @@ class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{
$url.='://'.$this->user.':'.$this->password.'@'.$this->host.$this->root.$path;
return $url;
}
public function fopen($path, $mode) {
public function fopen($path,$mode) {
$this->init();
switch($mode) {
case 'r':
case 'rb':
@ -61,7 +68,7 @@ class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{
case 'ab':
//these are supported by the wrapper
$context = stream_context_create(array('ftp' => array('overwrite' => true)));
return fopen($this->constructUrl($path), $mode, false, $context);
return fopen($this->constructUrl($path),$mode, false,$context);
case 'r+':
case 'w+':
case 'wb+':
@ -77,16 +84,18 @@ class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{
$ext='';
}
$tmpFile=OCP\Files::tmpFile($ext);
OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this, 'writeBack');
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$this->getFile($path, $tmpFile);
}
self::$tempFiles[$tmpFile]=$path;
return fopen('close://'.$tmpFile, $mode);
return fopen('close://'.$tmpFile,$mode);
}
return false;
}
public function writeBack($tmpFile) {
$this->init();
if (isset(self::$tempFiles[$tmpFile])) {
$this->uploadFile($tmpFile, self::$tempFiles[$tmpFile]);
unlink($tmpFile);

View File

@ -20,14 +20,17 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OC\Files\Storage;
require_once 'Google/common.inc.php';
class OC_Filestorage_Google extends OC_Filestorage_Common {
class Google extends \OC\Files\Storage\Common {
private $consumer;
private $oauth_token;
private $sig_method;
private $entries;
private $id;
private static $tempFiles = array();
@ -38,12 +41,13 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
) {
$consumer_key = isset($params['consumer_key']) ? $params['consumer_key'] : 'anonymous';
$consumer_secret = isset($params['consumer_secret']) ? $params['consumer_secret'] : 'anonymous';
$this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
$this->oauth_token = new OAuthToken($params['token'], $params['token_secret']);
$this->sig_method = new OAuthSignatureMethod_HMAC_SHA1();
$this->id = 'google::' . $params['token'];
$this->consumer = new \OAuthConsumer($consumer_key, $consumer_secret);
$this->oauth_token = new \OAuthToken($params['token'], $params['token_secret']);
$this->sig_method = new \OAuthSignatureMethod_HMAC_SHA1();
$this->entries = array();
} else {
throw new Exception('Creating OC_Filestorage_Google storage failed');
throw new \Exception('Creating \OC\Files\Storage\Google storage failed');
}
}
@ -68,7 +72,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
$tempStr .= '&' . urlencode($key) . '=' . urlencode($value);
}
$uri = preg_replace('/&/', '?', $tempStr, 1);
$request = OAuthRequest::from_consumer_and_token($this->consumer,
$request = \OAuthRequest::from_consumer_and_token($this->consumer,
$this->oauth_token,
$httpMethod,
$uri,
@ -110,7 +114,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
if ($isDownload) {
$tmpFile = OC_Helper::tmpFile();
$tmpFile = \OC_Helper::tmpFile();
$handle = fopen($tmpFile, 'w');
curl_setopt($curl, CURLOPT_FILE, $handle);
}
@ -139,7 +143,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
private function getFeed($feedUri, $httpMethod, $postData = null) {
$result = $this->sendRequest($feedUri, $httpMethod, $postData);
if ($result) {
$dom = new DOMDocument();
$dom = new \DOMDocument();
$dom->loadXML($result);
return $dom;
}
@ -194,6 +198,9 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
}
}
public function getId(){
return $this->id;
}
public function mkdir($path) {
$collection = dirname($path);
@ -266,7 +273,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
$this->entries[$name] = $entry;
}
}
OC_FakeDirStream::$dirs['google'.$path] = $files;
\OC\Files\Stream\Dir::register('google'.$path, $files);
return opendir('fakedir://google'.$path);
}
@ -287,7 +294,6 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
//$stat['atime'] = strtotime($entry->getElementsByTagNameNS('http://schemas.google.com/g/2005',
// 'lastViewed')->item(0)->nodeValue);
$stat['mtime'] = strtotime($entry->getElementsByTagName('updated')->item(0)->nodeValue);
$stat['ctime'] = strtotime($entry->getElementsByTagName('published')->item(0)->nodeValue);
}
}
if (isset($stat)) {
@ -443,8 +449,8 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
} else {
$ext = '';
}
$tmpFile = OC_Helper::tmpFile($ext);
OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack');
$tmpFile = \OC_Helper::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
file_put_contents($tmpFile, $source);
@ -482,7 +488,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
}
if (isset($uploadUri) && $handle = fopen($path, 'r')) {
$uploadUri .= '?convert=false';
$mimetype = OC_Helper::getMimeType($path);
$mimetype = \OC_Helper::getMimeType($path);
$size = filesize($path);
$headers = array('X-Upload-Content-Type: ' => $mimetype, 'X-Upload-Content-Length: ' => $size);
$postData = '<?xml version="1.0" encoding="UTF-8"?>';
@ -590,4 +596,4 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
}
}
}

View File

@ -6,9 +6,11 @@
* See the COPYING-README file.
*/
namespace OC\Files\Storage;
require_once 'smb4php/smb.php';
class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{
class SMB extends \OC\Files\Storage\StreamWrapper{
private $password;
private $user;
private $host;
@ -30,14 +32,13 @@ class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{
if ( ! $this->share || $this->share[0]!='/') {
$this->share='/'.$this->share;
}
if (substr($this->share, -1, 1)=='/') {
$this->share=substr($this->share, 0, -1);
if(substr($this->share, -1, 1)=='/') {
$this->share = substr($this->share,0,-1);
}
}
//create the root folder if necesary
if ( ! $this->is_dir('')) {
$this->mkdir('');
}
public function getId(){
return 'smb::' . $this->user . '@' . $this->host . '/' . $this->share . '/' . $this->root;
}
public function constructUrl($path) {
@ -65,11 +66,13 @@ class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{
/**
* check if a file or folder has been updated since $time
* @param string $path
* @param int $time
* @return bool
*/
public function hasUpdated($path, $time) {
if ( ! $path and $this->root=='/') {
public function hasUpdated($path,$time) {
$this->init();
if(!$path and $this->root=='/') {
// mtime doesn't work for shares, but giving the nature of the backend,
// doing a full update is still just fast enough
return true;

View File

@ -6,16 +6,33 @@
* See the COPYING-README file.
*/
namespace OC\Files\Storage;
abstract class StreamWrapper extends \OC\Files\Storage\Common{
private $ready = false;
protected function init(){
if($this->ready){
return;
}
$this->ready = true;
//create the root folder if necesary
if(!$this->is_dir('')) {
$this->mkdir('');
}
}
abstract class OC_FileStorage_StreamWrapper extends OC_Filestorage_Common{
abstract public function constructUrl($path);
public function mkdir($path) {
$this->init();
return mkdir($this->constructUrl($path));
}
public function rmdir($path) {
if ($this->file_exists($path)) {
$this->init();
if($this->file_exists($path)) {
$succes = rmdir($this->constructUrl($path));
clearstatcache();
return $succes;
@ -25,10 +42,12 @@ abstract class OC_FileStorage_StreamWrapper extends OC_Filestorage_Common{
}
public function opendir($path) {
$this->init();
return opendir($this->constructUrl($path));
}
public function filetype($path) {
$this->init();
return filetype($this->constructUrl($path));
}
@ -41,46 +60,54 @@ abstract class OC_FileStorage_StreamWrapper extends OC_Filestorage_Common{
}
public function file_exists($path) {
$this->init();
return file_exists($this->constructUrl($path));
}
public function unlink($path) {
$this->init();
$succes = unlink($this->constructUrl($path));
clearstatcache();
return $succes;
}
public function fopen($path, $mode) {
return fopen($this->constructUrl($path), $mode);
public function fopen($path,$mode) {
$this->init();
return fopen($this->constructUrl($path),$mode);
}
public function free_space($path) {
return 0;
}
public function touch($path, $mtime = null) {
if (is_null($mtime)) {
$fh = $this->fopen($path, 'a');
fwrite($fh, '');
public function touch($path,$mtime=null) {
$this->init();
if(is_null($mtime)) {
$fh = $this->fopen($path,'a');
fwrite($fh,'');
fclose($fh);
} else {
return false;//not supported
}
}
public function getFile($path, $target) {
return copy($this->constructUrl($path), $target);
public function getFile($path,$target) {
$this->init();
return copy($this->constructUrl($path),$target);
}
public function uploadFile($path, $target) {
return copy($path, $this->constructUrl($target));
public function uploadFile($path,$target) {
$this->init();
return copy($path,$this->constructUrl($target));
}
public function rename($path1, $path2) {
return rename($this->constructUrl($path1), $this->constructUrl($path2));
public function rename($path1,$path2) {
$this->init();
return rename($this->constructUrl($path1),$this->constructUrl($path2));
}
public function stat($path) {
$this->init();
return stat($this->constructUrl($path));
}

View File

@ -6,24 +6,28 @@
* See the COPYING-README file.
*/
namespace OC\Files\Storage;
require_once 'php-cloudfiles/cloudfiles.php';
class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
class SWIFT extends \OC\Files\Storage\Common{
private $id;
private $host;
private $root;
private $user;
private $token;
private $secure;
private $ready = false;
/**
* @var CF_Authentication auth
* @var \CF_Authentication auth
*/
private $auth;
/**
* @var CF_Connection conn
* @var \CF_Connection conn
*/
private $conn;
/**
* @var CF_Container rootContainer
* @var \CF_Container rootContainer
*/
private $rootContainer;
@ -35,18 +39,18 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* translate directory path to container name
* @param string path
* @param string $path
* @return string
*/
private function getContainerName($path) {
$path=trim(trim($this->root, '/')."/".$path, '/.');
$path=trim(trim($this->root, '/') . "/".$path, '/.');
return str_replace('/', '\\', $path);
}
/**
* get container by path
* @param string path
* @return CF_Container
* @param string $path
* @return \CF_Container
*/
private function getContainer($path) {
if ($path=='' or $path=='/') {
@ -59,15 +63,15 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
$container=$this->conn->get_container($this->getContainerName($path));
$this->containers[$path]=$container;
return $container;
} catch(NoSuchContainerException $e) {
} catch(\NoSuchContainerException $e) {
return null;
}
}
/**
* create container
* @param string path
* @return CF_Container
* @param string $path
* @return \CF_Container
*/
private function createContainer($path) {
if ($path=='' or $path=='/' or $path=='.') {
@ -89,8 +93,8 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* get object by path
* @param string path
* @return CF_Object
* @param string $path
* @return \CF_Object
*/
private function getObject($path) {
if (isset($this->objects[$path])) {
@ -107,7 +111,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
$obj=$container->get_object(basename($path));
$this->objects[$path]=$obj;
return $obj;
} catch(NoSuchObjectException $e) {
} catch(\NoSuchObjectException $e) {
return null;
}
}
@ -132,8 +136,8 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* create object
* @param string path
* @return CF_Object
* @param string $path
* @return \CF_Object
*/
private function createObject($path) {
$container=$this->getContainer(dirname($path));
@ -154,7 +158,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* check if container for path exists
* @param string path
* @param string $path
* @return bool
*/
private function containerExists($path) {
@ -163,15 +167,15 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* get the list of emulated sub containers
* @param CF_Container container
* @param \CF_Container $container
* @return array
*/
private function getSubContainers($container) {
$tmpFile=OCP\Files::tmpFile();
$tmpFile=\OCP\Files::tmpFile();
$obj=$this->getSubContainerFile($container);
try {
$obj->save_to_filename($tmpFile);
} catch(Exception $e) {
} catch(\Exception $e) {
return array();
}
$obj->save_to_filename($tmpFile);
@ -185,15 +189,15 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* add an emulated sub container
* @param CF_Container container
* @param string name
* @param \CF_Container $container
* @param string $name
* @return bool
*/
private function addSubContainer($container, $name) {
if ( ! $name) {
return false;
}
$tmpFile=OCP\Files::tmpFile();
$tmpFile=\OCP\Files::tmpFile();
$obj=$this->getSubContainerFile($container);
try {
$obj->save_to_filename($tmpFile);
@ -201,16 +205,15 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
foreach ($containers as &$sub) {
$sub=trim($sub);
}
if (array_search($name, $containers)!==false) {
if(array_search($name, $containers) !== false) {
unlink($tmpFile);
return false;
} else {
$fh=fopen($tmpFile, 'a');
fwrite($fh, $name."\n");
fwrite($fh,$name . "\n");
}
} catch(Exception $e) {
$containers=array();
file_put_contents($tmpFile, $name."\n");
} catch(\Exception $e) {
file_put_contents($tmpFile, $name . "\n");
}
$obj->load_from_filename($tmpFile);
@ -220,20 +223,20 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* remove an emulated sub container
* @param CF_Container container
* @param string name
* @param \CF_Container $container
* @param string $name
* @return bool
*/
private function removeSubContainer($container, $name) {
if ( ! $name) {
return false;
}
$tmpFile=OCP\Files::tmpFile();
$tmpFile=\OCP\Files::tmpFile();
$obj=$this->getSubContainerFile($container);
try {
$obj->save_to_filename($tmpFile);
$containers=file($tmpFile);
} catch (Exception $e) {
} catch (\Exception $e) {
return false;
}
foreach ($containers as &$sub) {
@ -255,8 +258,8 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* ensure a subcontainer file exists and return it's object
* @param CF_Container container
* @return CF_Object
* @param \CF_Container $container
* @return \CF_Object
*/
private function getSubContainerFile($container) {
try {
@ -283,10 +286,19 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
if ( ! $this->root || $this->root[0]!='/') {
$this->root='/'.$this->root;
}
$this->auth = new CF_Authentication($this->user, $this->token, null, $this->host);
}
private function init(){
if($this->ready){
return;
}
$this->ready = true;
$this->auth = new \CF_Authentication($this->user, $this->token, null, $this->host);
$this->auth->authenticate();
$this->conn = new CF_Connection($this->auth);
$this->conn = new \CF_Connection($this->auth);
if ( ! $this->containerExists('/')) {
$this->rootContainer=$this->createContainer('/');
@ -295,8 +307,13 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
}
public function getId(){
return $this->id;
}
public function mkdir($path) {
$this->init();
if ($this->containerExists($path)) {
return false;
} else {
@ -306,7 +323,8 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function rmdir($path) {
if ( ! $this->containerExists($path)) {
$this->init();
if (!$this->containerExists($path)) {
return false;
} else {
$this->emptyContainer($path);
@ -343,6 +361,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function opendir($path) {
$this->init();
$container=$this->getContainer($path);
$files=$this->getObjects($container);
$i=array_search(self::SUBCONTAINER_FILE, $files);
@ -352,11 +371,12 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
$subContainers=$this->getSubContainers($container);
$files=array_merge($files, $subContainers);
$id=$this->getContainerName($path);
OC_FakeDirStream::$dirs[$id]=$files;
\OC\Files\Stream\Dir::register($id, $files);
return opendir('fakedir://'.$id);
}
public function filetype($path) {
$this->init();
if ($this->containerExists($path)) {
return 'dir';
} else {
@ -373,6 +393,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function file_exists($path) {
$this->init();
if ($this->is_dir($path)) {
return true;
} else {
@ -381,6 +402,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function file_get_contents($path) {
$this->init();
$obj=$this->getObject($path);
if (is_null($obj)) {
return false;
@ -389,6 +411,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function file_put_contents($path, $content) {
$this->init();
$obj=$this->getObject($path);
if (is_null($obj)) {
$container=$this->getContainer(dirname($path));
@ -402,6 +425,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function unlink($path) {
$this->init();
if ($this->containerExists($path)) {
return $this->rmdir($path);
}
@ -415,6 +439,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function fopen($path, $mode) {
$this->init();
switch($mode) {
case 'r':
case 'rb':
@ -440,7 +465,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
case 'c':
case 'c+':
$tmpFile=$this->getTmpFile($path);
OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this, 'writeBack');
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
self::$tempFiles[$tmpFile]=$path;
return fopen('close://'.$tmpFile, $mode);
}
@ -458,6 +483,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function touch($path, $mtime=null) {
$this->init();
$obj=$this->getObject($path);
if (is_null($obj)) {
return false;
@ -472,6 +498,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function rename($path1, $path2) {
$this->init();
$sourceContainer=$this->getContainer(dirname($path1));
$targetContainer=$this->getContainer(dirname($path2));
$result=$sourceContainer->move_object_to(basename($path1), $targetContainer, basename($path2));
@ -484,6 +511,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function copy($path1, $path2) {
$this->init();
$sourceContainer=$this->getContainer(dirname($path1));
$targetContainer=$this->getContainer(dirname($path2));
$result=$sourceContainer->copy_object_to(basename($path1), $targetContainer, basename($path2));
@ -495,6 +523,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
public function stat($path) {
$this->init();
$container=$this->getContainer($path);
if ( ! is_null($container)) {
return array(
@ -523,17 +552,19 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
}
private function getTmpFile($path) {
$this->init();
$obj=$this->getObject($path);
if ( ! is_null($obj)) {
$tmpFile=OCP\Files::tmpFile();
$tmpFile=\OCP\Files::tmpFile();
$obj->save_to_filename($tmpFile);
return $tmpFile;
} else {
return OCP\Files::tmpFile();
return \OCP\Files::tmpFile();
}
}
private function fromTmpFile($tmpFile, $path) {
$this->init();
$obj=$this->getObject($path);
if (is_null($obj)) {
$obj=$this->createObject($path);
@ -544,7 +575,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
/**
* remove custom mtime metadata
* @param CF_Object obj
* @param \CF_Object $obj
*/
private function resetMTime($obj) {
if (isset($obj->metadata['Mtime'])) {

View File

@ -6,14 +6,17 @@
* See the COPYING-README file.
*/
class OC_FileStorage_DAV extends OC_Filestorage_Common{
namespace OC\Files\Storage;
class DAV extends \OC\Files\Storage\Common{
private $password;
private $user;
private $host;
private $secure;
private $root;
private $ready;
/**
* @var Sabre_DAV_Client
* @var \Sabre_DAV_Client
*/
private $client;
@ -43,6 +46,13 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
if (substr($this->root, -1, 1)!='/') {
$this->root.='/';
}
}
private function init(){
if($this->ready){
return;
}
$this->ready = true;
$settings = array(
'baseUri' => $this->createBaseUri(),
@ -50,7 +60,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
'password' => $this->password,
);
$this->client = new Sabre_DAV_Client($settings);
$this->client = new \Sabre_DAV_Client($settings);
$caview = \OCP\Files::getStorage('files_external');
if ($caview) {
@ -63,6 +73,10 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
$this->mkdir('');
}
public function getId(){
return 'webdav::' . $this->user . '@' . $this->host . '/' . $this->root;
}
private function createBaseUri() {
$baseUri='http';
if ($this->secure) {
@ -73,40 +87,46 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
}
public function mkdir($path) {
$this->init();
$path=$this->cleanPath($path);
return $this->simpleResponse('MKCOL', $path, null, 201);
}
public function rmdir($path) {
$this->init();
$path=$this->cleanPath($path);
return $this->simpleResponse('DELETE', $path, null, 204);
}
public function opendir($path) {
$this->init();
$path=$this->cleanPath($path);
try {
$response=$this->client->propfind($path, array(), 1);
$id=md5('webdav'.$this->root.$path);
OC_FakeDirStream::$dirs[$id]=array();
$content = array();
\OC_FakeDirStream::$dirs[$id]=array();
$files=array_keys($response);
array_shift($files);//the first entry is the current directory
foreach ($files as $file) {
$file = urldecode(basename($file));
OC_FakeDirStream::$dirs[$id][]=$file;
$content[]=$file;
}
\OC\Files\Stream\Dir::register($id, $content);
return opendir('fakedir://'.$id);
} catch(Exception $e) {
} catch(\Exception $e) {
return false;
}
}
public function filetype($path) {
$this->init();
$path=$this->cleanPath($path);
try {
$response=$this->client->propfind($path, array('{DAV:}resourcetype'));
$responseType=$response["{DAV:}resourcetype"]->resourceType;
return (count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file';
} catch(Exception $e) {
} catch(\Exception $e) {
error_log($e->getMessage());
\OCP\Util::writeLog("webdav client", \OCP\Util::sanitizeHTML($e->getMessage()), \OCP\Util::ERROR);
return false;
@ -122,20 +142,23 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
}
public function file_exists($path) {
$this->init();
$path=$this->cleanPath($path);
try {
$this->client->propfind($path, array('{DAV:}resourcetype'));
return true;//no 404 exception
} catch(Exception $e) {
} catch(\Exception $e) {
return false;
}
}
public function unlink($path) {
return $this->simpleResponse('DELETE', $path, null, 204);
$this->init();
return $this->simpleResponse('DELETE', $path, null ,204);
}
public function fopen($path, $mode) {
public function fopen($path,$mode) {
$this->init();
$path=$this->cleanPath($path);
switch($mode) {
case 'r':
@ -172,9 +195,9 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
} else {
$ext='';
}
$tmpFile=OCP\Files::tmpFile($ext);
OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this, 'writeBack');
if ($this->file_exists($path)) {
$tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if($this->file_exists($path)) {
$this->getFile($path, $tmpFile);
}
self::$tempFiles[$tmpFile]=$path;
@ -190,6 +213,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
}
public function free_space($path) {
$this->init();
$path=$this->cleanPath($path);
try {
$response=$this->client->propfind($path, array('{DAV:}quota-available-bytes'));
@ -198,12 +222,13 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
} else {
return 0;
}
} catch(Exception $e) {
} catch(\Exception $e) {
return 0;
}
}
public function touch($path, $mtime=null) {
$this->init();
if (is_null($mtime)) {
$mtime=time();
}
@ -211,12 +236,14 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
$this->client->proppatch($path, array('{DAV:}lastmodified' => $mtime));
}
public function getFile($path, $target) {
$source=$this->fopen($path, 'r');
file_put_contents($target, $source);
public function getFile($path,$target) {
$this->init();
$source=$this->fopen($path,'r');
file_put_contents($target,$source);
}
public function uploadFile($path, $target) {
public function uploadFile($path,$target) {
$this->init();
$source=fopen($path, 'r');
$curl = curl_init();
@ -230,47 +257,46 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
curl_close ($curl);
}
public function rename($path1, $path2) {
public function rename($path1,$path2) {
$this->init();
$path1=$this->cleanPath($path1);
$path2=$this->root.$this->cleanPath($path2);
try {
$this->client->request('MOVE', $path1, null, array('Destination'=>$path2));
return true;
} catch(Exception $e) {
echo $e;
echo 'fail';
} catch(\Exception $e) {
return false;
}
}
public function copy($path1, $path2) {
public function copy($path1,$path2) {
$this->init();
$path1=$this->cleanPath($path1);
$path2=$this->root.$this->cleanPath($path2);
try {
$this->client->request('COPY', $path1, null, array('Destination'=>$path2));
return true;
} catch(Exception $e) {
echo $e;
echo 'fail';
} catch(\Exception $e) {
return false;
}
}
public function stat($path) {
$this->init();
$path=$this->cleanPath($path);
try {
$response=$this->client->propfind($path, array('{DAV:}getlastmodified', '{DAV:}getcontentlength'));
return array(
'mtime'=>strtotime($response['{DAV:}getlastmodified']),
'size'=>(int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0,
'ctime'=>-1,
);
} catch(Exception $e) {
} catch(\Exception $e) {
return array();
}
}
public function getMimeType($path) {
$this->init();
$path=$this->cleanPath($path);
try {
$response=$this->client->propfind($path, array('{DAV:}getcontenttype', '{DAV:}resourcetype'));
@ -283,7 +309,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
} else {
return false;
}
} catch(Exception $e) {
} catch(\Exception $e) {
return false;
}
}
@ -296,12 +322,12 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
}
}
private function simpleResponse($method, $path, $body, $expected) {
private function simpleResponse($method,$path,$body,$expected) {
$path=$this->cleanPath($path);
try {
$response=$this->client->request($method, $path, $body);
return $response['statusCode']==$expected;
} catch(Exception $e) {
} catch(\Exception $e) {
return false;
}
}

View File

@ -24,7 +24,7 @@ OCP\Util::addScript('files_external', 'settings');
OCP\Util::addStyle('files_external', 'settings');
$backends = OC_Mount_Config::getBackends();
// Remove local storage
unset($backends['OC_Filestorage_Local']);
unset($backends['\OC\Files\Storage\Local']);
$tmpl = new OCP\Template('files_external', 'settings');
$tmpl->assign('isAdminPage', false, false);
$tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());

View File

@ -20,7 +20,9 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
class Test_Filestorage_AmazonS3 extends Test_FileStorage {
namespace Test\Files\Storage;
class AmazonS3 extends Storage {
private $config;
private $id;
@ -32,12 +34,12 @@ class Test_Filestorage_AmazonS3 extends Test_FileStorage {
$this->markTestSkipped('AmazonS3 backend not configured');
}
$this->config['amazons3']['bucket'] = $id; // Make sure we have a new empty bucket to work in
$this->instance = new OC_Filestorage_AmazonS3($this->config['amazons3']);
$this->instance = new \OC\Files\Storage\AmazonS3($this->config['amazons3']);
}
public function tearDown() {
if ($this->instance) {
$s3 = new AmazonS3(array('key' => $this->config['amazons3']['key'],
$s3 = new \AmazonS3(array('key' => $this->config['amazons3']['key'],
'secret' => $this->config['amazons3']['secret']));
if ($s3->delete_all_objects($this->id)) {
$s3->delete_bucket($this->id);

View File

@ -8,7 +8,7 @@ return array(
'root'=>'/test',
),
'webdav'=>array(
'run'=>false,
'run'=>true,
'host'=>'localhost',
'user'=>'test',
'password'=>'test',
@ -30,7 +30,7 @@ return array(
'root'=>'/',
),
'smb'=>array(
'run'=>false,
'run'=>true,
'user'=>'test',
'password'=>'test',
'host'=>'localhost',

View File

@ -6,7 +6,9 @@
* See the COPYING-README file.
*/
class Test_Filestorage_Dropbox extends Test_FileStorage {
namespace Test\Files\Storage;
class Dropbox extends Storage {
private $config;
public function setUp() {
@ -16,7 +18,7 @@ class Test_Filestorage_Dropbox extends Test_FileStorage {
$this->markTestSkipped('Dropbox backend not configured');
}
$this->config['dropbox']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
$this->instance = new OC_Filestorage_Dropbox($this->config['dropbox']);
$this->instance = new \OC\Files\Storage\Dropbox($this->config['dropbox']);
}
public function tearDown() {

View File

@ -6,7 +6,9 @@
* See the COPYING-README file.
*/
class Test_Filestorage_FTP extends Test_FileStorage {
namespace Test\Files\Storage;
class FTP extends Storage {
private $config;
public function setUp() {
@ -16,12 +18,12 @@ class Test_Filestorage_FTP extends Test_FileStorage {
$this->markTestSkipped('FTP backend not configured');
}
$this->config['ftp']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
$this->instance = new OC_Filestorage_FTP($this->config['ftp']);
$this->instance = new \OC\Files\Storage\FTP($this->config['ftp']);
}
public function tearDown() {
if ($this->instance) {
OCP\Files::rmdirr($this->instance->constructUrl(''));
\OCP\Files::rmdirr($this->instance->constructUrl(''));
}
}

View File

@ -20,8 +20,9 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
class Test_Filestorage_Google extends Test_FileStorage {
namespace Test\Files\Storage;
class Google extends Storage {
private $config;
public function setUp() {
@ -31,7 +32,7 @@ class Test_Filestorage_Google extends Test_FileStorage {
$this->markTestSkipped('Google backend not configured');
}
$this->config['google']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
$this->instance = new OC_Filestorage_Google($this->config['google']);
$this->instance = new \OC\Files\Storage\Google($this->config['google']);
}
public function tearDown() {

View File

@ -6,7 +6,10 @@
* See the COPYING-README file.
*/
class Test_Filestorage_SMB extends Test_FileStorage {
namespace Test\Files\Storage;
class SMB extends Storage {
private $config;
public function setUp() {
@ -16,12 +19,12 @@ class Test_Filestorage_SMB extends Test_FileStorage {
$this->markTestSkipped('Samba backend not configured');
}
$this->config['smb']['root'] .= $id; //make sure we have an new empty folder to work in
$this->instance = new OC_Filestorage_SMB($this->config['smb']);
$this->instance = new \OC\Files\Storage\SMB($this->config['smb']);
}
public function tearDown() {
if ($this->instance) {
OCP\Files::rmdirr($this->instance->constructUrl(''));
\OCP\Files::rmdirr($this->instance->constructUrl(''));
}
}
}

View File

@ -6,7 +6,9 @@
* See the COPYING-README file.
*/
class Test_Filestorage_SWIFT extends Test_FileStorage {
namespace Test\Files\Storage;
class SWIFT extends Storage {
private $config;
public function setUp() {
@ -16,7 +18,7 @@ class Test_Filestorage_SWIFT extends Test_FileStorage {
$this->markTestSkipped('OpenStack SWIFT backend not configured');
}
$this->config['swift']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
$this->instance = new OC_Filestorage_SWIFT($this->config['swift']);
$this->instance = new \OC\Files\Storage\SWIFT($this->config['swift']);
}

View File

@ -6,7 +6,10 @@
* See the COPYING-README file.
*/
class Test_Filestorage_DAV extends Test_FileStorage {
namespace Test\Files\Storage;
class DAV extends Storage {
private $config;
public function setUp() {
@ -16,7 +19,7 @@ class Test_Filestorage_DAV extends Test_FileStorage {
$this->markTestSkipped('WebDAV backend not configured');
}
$this->config['webdav']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
$this->instance = new OC_Filestorage_DAV($this->config['webdav']);
$this->instance = new \OC\Files\Storage\DAV($this->config['webdav']);
}
public function tearDown() {

View File

@ -2,8 +2,11 @@
OC::$CLASSPATH['OC_Share_Backend_File'] = "apps/files_sharing/lib/share/file.php";
OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'apps/files_sharing/lib/share/folder.php';
OC::$CLASSPATH['OC_Filestorage_Shared'] = "apps/files_sharing/lib/sharedstorage.php";
OCP\Util::connectHook('OC_Filesystem', 'setup', 'OC_Filestorage_Shared', 'setup');
OC::$CLASSPATH['OC\Files\Storage\Shared'] = "apps/files_sharing/lib/sharedstorage.php";
OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'apps/files_sharing/lib/cache.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'apps/files_sharing/lib/permissions.php';
OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'apps/files_sharing/lib/watcher.php';
OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
OCP\Util::addScript('files_sharing', 'share');
OCP\Util::addScript('files_sharing', 'share');

View File

@ -5,7 +5,7 @@
<description>File sharing between users</description>
<licence>AGPL</licence>
<author>Michael Gapczynski</author>
<require>4.9</require>
<require>4.91</require>
<shipped>true</shipped>
<default_enable/>
<types>

View File

@ -9,10 +9,12 @@ if (version_compare($installedVersion, '0.3', '<')) {
OC_User::useBackend(new OC_User_Database());
OC_Group::useBackend(new OC_Group_Database());
OC_App::loadApps(array('authentication'));
$rootView = new \OC\Files\View('');
while ($row = $result->fetchRow()) {
$itemSource = OC_FileCache::getId($row['source'], '');
$meta = $rootView->getFileInfo($$row['source']);
$itemSource = $meta['fileid'];
if ($itemSource != -1) {
$file = OC_FileCache::get($row['source'], '');
$file = $meta;
if ($file['mimetype'] == 'httpd/unix-directory') {
$itemType = 'folder';
} else {
@ -68,6 +70,6 @@ if (version_compare($installedVersion, '0.3.3', '<')) {
OC_App::loadApps(array('authentication'));
$users = OC_User::getUsers();
foreach ($users as $user) {
OC_FileCache::delete('Shared', '/'.$user.'/files/');
// OC_FileCache::delete('Shared', '/'.$user.'/files/');
}
}
}

View File

@ -0,0 +1,258 @@
<?php
/**
* ownCloud
*
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OC\Files\Cache;
/**
* Metadata cache for shared files
*
* don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead
*/
class Shared_Cache extends Cache {
private $files = array();
public function __construct($storage) {
}
/**
* @brief Get the source cache of a shared file or folder
* @param string $target Shared target file path
* @return \OC\Files\Cache\Cache
*/
private function getSourceCache($target) {
$source = \OC_Share_Backend_File::getSource($target);
if (isset($source['path'])) {
$source['path'] = '/' . $source['uid_owner'] . '/' . $source['path'];
\OC\Files\Filesystem::initMountPoints($source['uid_owner']);
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source['path']);
if ($storage) {
$this->files[$target] = $internalPath;
$cache = $storage->getCache();
$this->storageId = $storage->getId();
$this->numericId = $cache->getNumericStorageId();
return $cache;
}
}
return false;
}
/**
* get the stored metadata of a file or folder
*
* @param string/int $file
* @return array
*/
public function get($file) {
if ($file == '') {
return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
} else if (is_string($file)) {
if ($cache = $this->getSourceCache($file)) {
return $cache->get($this->files[$file]);
}
} else {
$query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`
FROM `*PREFIX*filecache` WHERE `fileid` = ?');
$result = $query->execute(array($file));
$data = $result->fetchRow();
$data['fileid'] = (int)$data['fileid'];
$data['size'] = (int)$data['size'];
$data['mtime'] = (int)$data['mtime'];
$data['encrypted'] = (bool)$data['encrypted'];
$data['mimetype'] = $this->getMimetype($data['mimetype']);
$data['mimepart'] = $this->getMimetype($data['mimepart']);
return $data;
}
return false;
}
/**
* get the metadata of all files stored in $folder
*
* @param string $folder
* @return array
*/
public function getFolderContents($folder) {
if ($folder == '') {
$files = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS);
foreach ($files as &$file) {
$file['mimetype'] = $this->getMimetype($file['mimetype']);
$file['mimepart'] = $this->getMimetype($file['mimepart']);
}
return $files;
} else {
if ($cache = $this->getSourceCache($folder)) {
return $cache->getFolderContents($this->files[$folder]);
}
}
return false;
}
/**
* store meta data for a file or folder
*
* @param string $file
* @param array $data
*
* @return int file id
*/
public function put($file, array $data) {
if ($cache = $this->getSourceCache($file)) {
return $cache->put($this->files[$file], $data);
}
return false;
}
/**
* get the file id for a file
*
* @param string $file
* @return int
*/
public function getId($file) {
if ($cache = $this->getSourceCache($file)) {
return $cache->getId($this->files[$file]);
}
return -1;
}
/**
* check if a file is available in the cache
*
* @param string $file
* @return bool
*/
public function inCache($file) {
if ($file == '') {
return true;
}
return parent::inCache($file);
}
/**
* remove a file or folder from the cache
*
* @param string $file
*/
public function remove($file) {
if ($cache = $this->getSourceCache($file)) {
$cache->remove($this->files[$file]);
}
}
/**
* Move a file or folder in the cache
*
* @param string $source
* @param string $target
*/
public function move($source, $target) {
if ($cache = $this->getSourceCache($source)) {
$targetPath = \OC_Share_Backend_File::getSourcePath(dirname($target));
if ($targetPath) {
$targetPath .= '/' . basename($target);
$cache->move($this->files[$source], $targetPath);
}
}
}
/**
* remove all entries for files that are stored on the storage from the cache
*/
public function clear() {
// Not a valid action for Shared Cache
}
/**
* @param string $file
*
* @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
*/
public function getStatus($file) {
if ($file == '') {
return self::COMPLETE;
}
if ($cache = $this->getSourceCache($file)) {
return $cache->getStatus($this->files[$file]);
}
return self::NOT_FOUND;
}
/**
* search for files matching $pattern
*
* @param string $pattern
* @return array of file data
*/
public function search($pattern) {
// TODO
}
/**
* search for files by mimetype
*
* @param string $part1
* @param string $part2
* @return array
*/
public function searchByMime($mimetype) {
if (strpos($mimetype, '/')) {
$where = '`mimetype` = ?';
} else {
$where = '`mimepart` = ?';
}
$mimetype = $this->getMimetypeId($mimetype);
$ids = $this->getAll();
$placeholders = join(',', array_fill(0, count($ids), '?'));
$query = \OC_DB::prepare('
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`
FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `fileid` IN (' . $placeholders . ')'
);
$result = $query->execute(array_merge(array($mimetype), $ids));
return $result->fetchAll();
}
/**
* get the size of a folder and set it in the cache
*
* @param string $path
* @return int
*/
public function calculateFolderSize($path) {
if ($cache = $this->getSourceCache($path)) {
return $cache->calculateFolderSize($this->files[$path]);
}
return 0;
}
/**
* get all file ids on the files on the storage
*
* @return int[]
*/
public function getAll() {
return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_ALL);
}
}

View File

@ -0,0 +1,85 @@
<?php
/**
* ownCloud
*
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OC\Files\Cache;
class Shared_Permissions extends Permissions {
/**
* get the permissions for a single file
*
* @param int $fileId
* @param string $user
* @return int (-1 if file no permissions set)
*/
public function get($fileId, $user) {
if ($fileId == -1) {
return \OCP\PERMISSION_READ;
}
$source = \OCP\Share::getItemSharedWithBySource('file', $fileId, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE, null, true);
if ($source) {
return $source['permissions'];
} else {
return -1;
}
}
/**
* set the permissions of a file
*
* @param int $fileId
* @param string $user
* @param int $permissions
*/
public function set($fileId, $user, $permissions) {
// Not a valid action for Shared Permissions
}
/**
* get the permissions of multiply files
*
* @param int[] $fileIds
* @param string $user
* @return int[]
*/
public function getMultiple($fileIds, $user) {
if (count($fileIds) === 0) {
return array();
}
foreach ($fileIds as $fileId) {
$filePermissions[$fileId] = self::get($fileId, $user);
}
return $filePermissions;
}
/**
* remove the permissions for a file
*
* @param int $fileId
* @param string $user
*/
public function remove($fileId, $user) {
// Not a valid action for Shared Permissions
}
public function removeMultiple($fileIds, $user) {
// Not a valid action for Shared Permissions
}
}

View File

@ -22,16 +22,18 @@
class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
const FORMAT_SHARED_STORAGE = 0;
const FORMAT_FILE_APP = 1;
const FORMAT_GET_FOLDER_CONTENTS = 1;
const FORMAT_FILE_APP_ROOT = 2;
const FORMAT_OPENDIR = 3;
const FORMAT_GET_ALL = 4;
private $path;
public function isValidSource($itemSource, $uidOwner) {
$path = OC_FileCache::getPath($itemSource, $uidOwner);
if ($path) {
$this->path = $path;
$query = \OC_DB::prepare('SELECT `name` FROM `*PREFIX*filecache` WHERE `fileid` = ?');
$result = $query->execute(array($itemSource));
if ($row = $result->fetchRow()) {
$this->path = $row['name'];
return true;
}
return false;
@ -70,37 +72,21 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
public function formatItems($items, $format, $parameters = null) {
if ($format == self::FORMAT_SHARED_STORAGE) {
// Only 1 item should come through for this format call
return array('path' => $items[key($items)]['path'], 'permissions' => $items[key($items)]['permissions']);
} else if ($format == self::FORMAT_FILE_APP) {
if (isset($parameters['mimetype_filter']) && $parameters['mimetype_filter']) {
$mimetype_filter = $parameters['mimetype_filter'];
}
return array('path' => $items[key($items)]['path'], 'permissions' => $items[key($items)]['permissions'], 'uid_owner' => $items[key($items)]['uid_owner']);
} else if ($format == self::FORMAT_GET_FOLDER_CONTENTS) {
$files = array();
foreach ($items as $item) {
if (isset($mimetype_filter)
&& strpos($item['mimetype'], $mimetype_filter) !== 0
&& $item['mimetype'] != 'httpd/unix-directory') {
continue;
}
$file = array();
$file['id'] = $item['file_source'];
$file['fileid'] = $item['file_source'];
$file['storage'] = $item['storage'];
$file['path'] = $item['file_target'];
$file['parent'] = $item['file_parent'];
$file['name'] = basename($item['file_target']);
$file['ctime'] = $item['ctime'];
$file['mtime'] = $item['mtime'];
$file['mimetype'] = $item['mimetype'];
$file['mimepart'] = $item['mimepart'];
$file['size'] = $item['size'];
$file['mtime'] = $item['mtime'];
$file['encrypted'] = $item['encrypted'];
$file['versioned'] = $item['versioned'];
$file['directory'] = $parameters['folder'];
$file['type'] = ($item['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file';
$file['permissions'] = $item['permissions'];
if ($file['type'] == 'file') {
// Remove Create permission if type is file
$file['permissions'] &= ~OCP\PERMISSION_CREATE;
}
// NOTE: Temporary fix to allow unsharing of files in root of Shared directory
$file['permissions'] |= OCP\PERMISSION_DELETE;
$files[] = $file;
}
return $files;
@ -111,17 +97,48 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
if ($item['mtime'] > $mtime) {
$mtime = $item['mtime'];
}
$size += $item['size'];
$size += (int)$item['size'];
}
return array(0 => array('id' => -1, 'name' => 'Shared', 'mtime' => $mtime, 'mimetype' => 'httpd/unix-directory', 'size' => $size, 'writable' => false, 'type' => 'dir', 'directory' => '', 'permissions' => OCP\PERMISSION_READ));
return array('fileid' => -1, 'name' => 'Shared', 'mtime' => $mtime, 'mimetype' => 'httpd/unix-directory', 'size' => $size);
} else if ($format == self::FORMAT_OPENDIR) {
$files = array();
foreach ($items as $item) {
$files[] = basename($item['file_target']);
}
return $files;
} else if ($format == self::FORMAT_GET_ALL) {
$ids = array();
foreach ($items as $item) {
$ids[] = $item['file_source'];
}
return $ids;
}
return array();
}
public static function getSource($target) {
if ($target == '') {
return false;
}
$target = '/'.$target;
$target = rtrim($target, '/');
$pos = strpos($target, '/', 1);
// Get shared folder name
if ($pos !== false) {
$folder = substr($target, 0, $pos);
$source = \OCP\Share::getItemSharedWith('folder', $folder, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
if ($source) {
$source['path'] = $source['path'].substr($target, strlen($folder));
return $source;
}
} else {
$source = \OCP\Share::getItemSharedWith('file', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
if ($source) {
return $source;
}
}
\OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, \OCP\Util::ERROR);
return false;
}
}

View File

@ -21,47 +21,26 @@
class OC_Share_Backend_Folder extends OC_Share_Backend_File implements OCP\Share_Backend_Collection {
public function formatItems($items, $format, $parameters = null) {
if ($format == self::FORMAT_SHARED_STORAGE) {
// Only 1 item should come through for this format call
return array('path' => $items[key($items)]['path'], 'permissions' => $items[key($items)]['permissions']);
} else if ($format == self::FORMAT_FILE_APP && isset($parameters['folder'])) {
// Only 1 item should come through for this format call
$folder = $items[key($items)];
if (isset($parameters['mimetype_filter'])) {
$mimetype_filter = $parameters['mimetype_filter'];
} else {
$mimetype_filter = '';
}
$path = $folder['path'].substr($parameters['folder'], 7 + strlen($folder['file_target']));
$files = OC_FileCache::getFolderContent($path, '', $mimetype_filter);
foreach ($files as &$file) {
$file['directory'] = $parameters['folder'];
$file['type'] = ($file['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file';
$file['permissions'] = $folder['permissions'];
if ($file['type'] == 'file') {
// Remove Create permission if type is file
$file['permissions'] &= ~OCP\PERMISSION_CREATE;
}
}
return $files;
}
return array();
}
public function getChildren($itemSource) {
$children = array();
$parents = array($itemSource);
$query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?');
$result = $query->execute(array('httpd/unix-directory'));
if ($row = $result->fetchRow()) {
$mimetype = $row['id'];
} else {
$mimetype = -1;
}
while (!empty($parents)) {
$parents = "'".implode("','", $parents)."'";
$query = OC_DB::prepare('SELECT `id`, `name`, `mimetype` FROM `*PREFIX*fscache` WHERE `parent` IN ('.$parents.')');
$query = OC_DB::prepare('SELECT `fileid`, `name`, `mimetype` FROM `*PREFIX*filecache` WHERE `parent` IN ('.$parents.')');
$result = $query->execute();
$parents = array();
while ($file = $result->fetchRow()) {
$children[] = array('source' => $file['id'], 'file_path' => $file['name']);
$children[] = array('source' => $file['fileid'], 'file_path' => $file['name']);
// If a child folder is found look inside it
if ($file['mimetype'] == 'httpd/unix-directory') {
$parents[] = $file['id'];
if ($file['mimetype'] == $mimetype) {
$parents[] = $file['fileid'];
}
}
}

View File

@ -20,10 +20,12 @@
*
*/
namespace OC\Files\Storage;
/**
* Convert target path to source path and pass the function call to the correct storage provider
*/
class OC_Filestorage_Shared extends OC_Filestorage_Common {
class Shared extends \OC\Files\Storage\Common {
private $sharedFolder;
private $files = array();
@ -32,54 +34,36 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
$this->sharedFolder = $arguments['sharedFolder'];
}
public function getId(){
return 'shared::' . $this->sharedFolder;
}
/**
* @brief Get the source file path and the permissions granted for a shared file
* @brief Get the source file path, permissions, and owner for a shared file
* @param string Shared target file path
* @return Returns array with the keys path and permissions or false if not found
* @return Returns array with the keys path, permissions, and owner or false if not found
*/
private function getFile($target) {
$target = '/'.$target;
$target = rtrim($target, '/');
if (isset($this->files[$target])) {
return $this->files[$target];
} else {
$pos = strpos($target, '/', 1);
// Get shared folder name
if ($pos !== false) {
$folder = substr($target, 0, $pos);
if (isset($this->files[$folder])) {
$file = $this->files[$folder];
} else {
$file = OCP\Share::getItemSharedWith('folder', $folder, OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
}
if ($file) {
$this->files[$target]['path'] = $file['path'].substr($target, strlen($folder));
$this->files[$target]['permissions'] = $file['permissions'];
return $this->files[$target];
}
} else {
$file = OCP\Share::getItemSharedWith('file', $target, OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
if ($file) {
$this->files[$target] = $file;
return $this->files[$target];
}
if (!isset($this->files[$target])) {
$source = \OC_Share_Backend_File::getSource($target);
if ($source) {
$source['path'] = '/'.$source['uid_owner'].'/'.$source['path'];
}
OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, OCP\Util::ERROR);
return false;
$this->files[$target] = $source;
}
return $this->files[$target];
}
/**
* @brief Get the source file path for a shared file
* @param string Shared target file path
* @return Returns source file path or false if not found
* @return string source file path or false if not found
*/
private function getSourcePath($target) {
$file = $this->getFile($target);
if (isset($file['path'])) {
$uid = substr($file['path'], 1, strpos($file['path'], '/', 1) - 1);
OC_Filesystem::mount('OC_Filestorage_Local', array('datadir' => OC_User::getHome($uid)), $uid);
return $file['path'];
$source = $this->getFile($target);
if ($source) {
\OC\Files\Filesystem::initMountPoints($source['uid_owner']);
return $source['path'];
}
return false;
}
@ -87,61 +71,42 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
/**
* @brief Get the permissions granted for a shared file
* @param string Shared target file path
* @return Returns CRUDS permissions granted or false if not found
* @return int CRUDS permissions granted or false if not found
*/
private function getPermissions($target) {
$file = $this->getFile($target);
if (isset($file['permissions'])) {
return $file['permissions'];
public function getPermissions($target) {
$source = $this->getFile($target);
if ($source) {
return $source['permissions'];
}
return false;
}
/**
* @brief Get the internal path to pass to the storage filesystem call
* @param string Source file path
* @return Source file path with mount point stripped out
*/
private function getInternalPath($path) {
$mountPoint = OC_Filesystem::getMountPoint($path);
$internalPath = substr($path, strlen($mountPoint));
return $internalPath;
}
public function getOwner($target) {
$shared_item = OCP\Share::getItemSharedWith('folder', $target, OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
if ($shared_item) {
return $shared_item[0]["uid_owner"];
}
return null;
}
public function mkdir($path) {
if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) {
return false;
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->mkdir($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->mkdir($internalPath);
}
return false;
}
public function rmdir($path) {
if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->rmdir($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->rmdir($internalPath);
}
return false;
}
public function opendir($path) {
if ($path == '' || $path == '/') {
$files = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_Folder::FORMAT_OPENDIR);
OC_FakeDirStream::$dirs['shared'] = $files;
$files = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_Folder::FORMAT_OPENDIR);
\OC\Files\Stream\Dir::register('shared', $files);
return opendir('fakedir://shared');
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->opendir($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->opendir($internalPath);
}
return false;
}
@ -150,16 +115,16 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if ($path == '' || $path == '/') {
return true;
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->is_dir($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->is_dir($internalPath);
}
return false;
}
public function is_file($path) {
if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->is_file($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->is_file($internalPath);
}
return false;
}
@ -168,11 +133,10 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if ($path == '' || $path == '/') {
$stat['size'] = $this->filesize($path);
$stat['mtime'] = $this->filemtime($path);
$stat['ctime'] = $this->filectime($path);
return $stat;
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->stat($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->stat($internalPath);
}
return false;
}
@ -181,8 +145,8 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if ($path == '' || $path == '/') {
return 'dir';
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->filetype($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->filetype($internalPath);
}
return false;
}
@ -191,8 +155,8 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if ($path == '' || $path == '/' || $this->is_dir($path)) {
return 0;
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->filesize($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->filesize($internalPath);
}
return false;
}
@ -201,7 +165,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if ($path == '') {
return false;
}
return ($this->getPermissions($path) & OCP\PERMISSION_CREATE);
return ($this->getPermissions($path) & \OCP\PERMISSION_CREATE);
}
public function isReadable($path) {
@ -212,54 +176,33 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if ($path == '') {
return false;
}
return ($this->getPermissions($path) & OCP\PERMISSION_UPDATE);
return ($this->getPermissions($path) & \OCP\PERMISSION_UPDATE);
}
public function isDeletable($path) {
if ($path == '') {
return true;
}
return ($this->getPermissions($path) & OCP\PERMISSION_DELETE);
return ($this->getPermissions($path) & \OCP\PERMISSION_DELETE);
}
public function isSharable($path) {
if ($path == '') {
return false;
}
return ($this->getPermissions($path) & OCP\PERMISSION_SHARE);
return ($this->getPermissions($path) & \OCP\PERMISSION_SHARE);
}
public function file_exists($path) {
if ($path == '' || $path == '/') {
return true;
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->file_exists($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->file_exists($internalPath);
}
return false;
}
public function filectime($path) {
if ($path == '' || $path == '/') {
$ctime = 0;
if ($dh = $this->opendir($path)) {
while (($filename = readdir($dh)) !== false) {
$tempctime = $this->filectime($filename);
if ($tempctime < $ctime) {
$ctime = $tempctime;
}
}
}
return $ctime;
} else {
$source = $this->getSourcePath($path);
if ($source) {
$storage = OC_Filesystem::getStorage($source);
return $storage->filectime($this->getInternalPath($source));
}
}
}
public function filemtime($path) {
if ($path == '' || $path == '/') {
$mtime = 0;
@ -275,8 +218,8 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
} else {
$source = $this->getSourcePath($path);
if ($source) {
$storage = OC_Filesystem::getStorage($source);
return $storage->filemtime($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->filemtime($internalPath);
}
}
}
@ -288,9 +231,9 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
'target' => $this->sharedFolder.$path,
'source' => $source,
);
OCP\Util::emitHook('OC_Filestorage_Shared', 'file_get_contents', $info);
$storage = OC_Filesystem::getStorage($source);
return $storage->file_get_contents($this->getInternalPath($source));
\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->file_get_contents($internalPath);
}
}
@ -304,9 +247,9 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
'target' => $this->sharedFolder.$path,
'source' => $source,
);
OCP\Util::emitHook('OC_Filestorage_Shared', 'file_put_contents', $info);
$storage = OC_Filesystem::getStorage($source);
$result = $storage->file_put_contents($this->getInternalPath($source), $data);
\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
$result = $storage->file_put_contents($internalPath, $data);
return $result;
}
return false;
@ -316,8 +259,8 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
// Delete the file if DELETE permission is granted
if ($source = $this->getSourcePath($path)) {
if ($this->isDeletable($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->unlink($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->unlink($internalPath);
} else if (dirname($path) == '/' || dirname($path) == '.') {
// Unshare the file from the user if in the root of the Shared folder
if ($this->is_dir($path)) {
@ -325,7 +268,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
} else {
$itemType = 'file';
}
return OCP\Share::unshareFromSelf($itemType, $path);
return \OCP\Share::unshareFromSelf($itemType, $path);
}
}
return false;
@ -340,8 +283,9 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if (dirname($path1) == dirname($path2)) {
// Rename the file if UPDATE permission is granted
if ($this->isUpdatable($path1)) {
$storage = OC_Filesystem::getStorage($oldSource);
return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource));
list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
return $storage->rename($oldInternalPath, $newInternalPath);
}
} else {
// Move the file if DELETE and CREATE permissions are granted
@ -355,8 +299,9 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
return $this->unlink($path1);
}
} else {
$storage = OC_Filesystem::getStorage($oldSource);
return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource));
list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
return $storage->rename($oldInternalPath, $newInternalPath);
}
}
}
@ -369,7 +314,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
if ($this->isCreatable(dirname($path2))) {
$source = $this->fopen($path1, 'r');
$target = $this->fopen($path2, 'w');
return OC_Helper::streamCopy($source, $target);
return \OC_Helper::streamCopy($source, $target);
}
return false;
}
@ -400,9 +345,9 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
'source' => $source,
'mode' => $mode,
);
OCP\Util::emitHook('OC_Filestorage_Shared', 'fopen', $info);
$storage = OC_Filesystem::getStorage($source);
return $storage->fopen($this->getInternalPath($source), $mode);
\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->fopen($internalPath, $mode);
}
return false;
}
@ -412,47 +357,88 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
return 'httpd/unix-directory';
}
if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->getMimeType($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->getMimeType($internalPath);
}
return false;
}
public function free_space($path) {
if ($path == '') {
return -1;
}
$source = $this->getSourcePath($path);
if ($source) {
$storage = OC_Filesystem::getStorage($source);
return $storage->free_space($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->free_space($internalPath);
}
}
public function getLocalFile($path) {
if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->getLocalFile($this->getInternalPath($source));
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->getLocalFile($internalPath);
}
return false;
}
public function touch($path, $mtime = null) {
if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->touch($this->getInternalPath($source), $mtime);
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->touch($internalPath, $mtime);
}
return false;
}
public static function setup($options) {
$user_dir = $options['user_dir'];
OC_Filesystem::mount('OC_Filestorage_Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/');
if (\OCP\Share::getItemsSharedWith('file')) {
$user_dir = $options['user_dir'];
\OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/');
}
}
/**
* check if a file or folder has been updated since $time
* @param int $time
* @return bool
*/
public function hasUpdated($path, $time) {
//TODO
if ($path == '') {
return false;
}
return $this->filemtime($path) > $time;
}
public function getCache($path = '') {
return new \OC\Files\Cache\Shared_Cache($this);
}
public function getScanner($path = '') {
return new \OC\Files\Cache\Scanner($this);
}
public function getPermissionsCache($path = '') {
return new \OC\Files\Cache\Shared_Permissions($this);
}
public function getWatcher($path = '') {
return new \OC\Files\Cache\Shared_Watcher($this);
}
public function getOwner($path) {
if ($path == '') {
return false;
}
$source = $this->getFile($path);
if ($source) {
return $source['uid_owner'];
}
return false;
}
public function getETag($path) {
if ($path == '') {
return parent::getETag($path);
}
if ($source = $this->getSourcePath($path)) {
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
return $storage->getETag($internalPath);
}
return null;
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* ownCloud
*
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OC\Files\Cache;
/**
* check the storage backends for updates and change the cache accordingly
*/
class Shared_Watcher extends Watcher {
/**
* check $path for updates
*
* @param string $path
*/
public function checkUpdate($path) {
if ($path != '') {
parent::checkUpdate($path);
}
}
/**
* remove deleted files in $path from the cache
*
* @param string $path
*/
public function cleanFolder($path) {
if ($path != '') {
parent::cleanFolder($path);
}
}
}

View File

@ -9,9 +9,10 @@ if (isset($_GET['token'])) {
unset($_GET['file']);
$qry = \OC_DB::prepare('SELECT `source` FROM `*PREFIX*sharing` WHERE `target` = ?', 1);
$filepath = $qry->execute(array($_GET['token']))->fetchOne();
if(isset($filepath)) {
$info = OC_FileCache_Cached::get($filepath, '');
if(strtolower($info['mimetype']) == 'httpd/unix-directory') {
if (isset($filepath)) {
$rootView = new \OC\Files\View('');
$info = $rootView->getFileInfo($filepath, '');
if (strtolower($info['mimetype']) == 'httpd/unix-directory') {
$_GET['dir'] = $filepath;
} else {
$_GET['file'] = $filepath;
@ -25,7 +26,7 @@ if (isset($_GET['token'])) {
function getID($path) {
// use the share table from the db to find the item source if the file was reshared because shared files
//are not stored in the file cache.
if (substr(OC_Filesystem::getMountPoint($path), -7, 6) == "Shared") {
if (substr(\OC\Files\Filesystem::getMountPoint($path), -7, 6) == "Shared") {
$path_parts = explode('/', $path, 5);
$user = $path_parts[1];
$intPath = '/'.$path_parts[4];
@ -37,16 +38,19 @@ function getID($path) {
$row = $result->fetchRow();
$fileSource = $row['item_source'];
} else {
$fileSource = OC_Filecache::getId($path, '');
$rootView = new \OC\Files\View('');
$meta = $rootView->getFileInfo($path);
$fileSource = $meta['fileid'];
}
return $fileSource;
}
// Enf of backward compatibility
/**
* lookup file path and owner by fetching it from the fscache
* needed becaus OC_FileCache::getPath($id, $user) already requires the user
* needed because OC_FileCache::getPath($id, $user) already requires the user
* @param int $id
* @return array
*/
@ -86,41 +90,43 @@ if (isset($_GET['t'])) {
OC_Util::setupFS($fileOwner);
}
}
} else if (isset($_GET['file']) || isset($_GET['dir'])) {
OCP\Util::writeLog('share', 'Missing token, trying fallback file/dir links', \OCP\Util::DEBUG);
if (isset($_GET['dir'])) {
$type = 'folder';
$path = $_GET['dir'];
if(strlen($path)>1 and substr($path, -1, 1)==='/') {
$path=substr($path, 0, -1);
} else {
if (isset($_GET['file']) || isset($_GET['dir'])) {
OCP\Util::writeLog('share', 'Missing token, trying fallback file/dir links', \OCP\Util::DEBUG);
if (isset($_GET['dir'])) {
$type = 'folder';
$path = $_GET['dir'];
if (strlen($path) > 1 and substr($path, -1, 1) === '/') {
$path = substr($path, 0, -1);
}
$baseDir = $path;
$dir = $baseDir;
} else {
$type = 'file';
$path = $_GET['file'];
if (strlen($path) > 1 and substr($path, -1, 1) === '/') {
$path = substr($path, 0, -1);
}
}
$baseDir = $path;
$dir = $baseDir;
} else {
$type = 'file';
$path = $_GET['file'];
if(strlen($path)>1 and substr($path, -1, 1)==='/') {
$path=substr($path, 0, -1);
}
}
$shareOwner = substr($path, 1, strpos($path, '/', 1) - 1);
$shareOwner = substr($path, 1, strpos($path, '/', 1) - 1);
if (OCP\User::userExists($shareOwner)) {
OC_Util::setupFS($shareOwner);
$fileSource = getId($path);
if ($fileSource != -1 ) {
$linkItem = OCP\Share::getItemSharedWithByLink($type, $fileSource, $shareOwner);
$pathAndUser['path'] = $path;
$path_parts = explode('/', $path, 5);
$pathAndUser['user'] = $path_parts[1];
$fileOwner = $path_parts[1];
if (OCP\User::userExists($shareOwner)) {
OC_Util::setupFS($shareOwner);
$fileSource = getId($path);
if ($fileSource != -1) {
$linkItem = OCP\Share::getItemSharedWithByLink($type, $fileSource, $shareOwner);
$pathAndUser['path'] = $path;
$path_parts = explode('/', $path, 5);
$pathAndUser['user'] = $path_parts[1];
$fileOwner = $path_parts[1];
}
}
}
}
if ($linkItem) {
if (!isset($linkItem['item_type'])) {
OCP\Util::writeLog('share', 'No item type set for share id: '.$linkItem['id'], \OCP\Util::ERROR);
OCP\Util::writeLog('share', 'No item type set for share id: ' . $linkItem['id'], \OCP\Util::ERROR);
header('HTTP/1.0 404 Not Found');
$tmpl = new OCP\Template('', '404', 'guest');
$tmpl->printPage();
@ -128,11 +134,13 @@ if ($linkItem) {
}
if (isset($linkItem['share_with'])) {
// Authenticate share_with
$url = OCP\Util::linkToPublic('files').'&t='.$token;
$url = OCP\Util::linkToPublic('files') . '&t=' . $token;
if (isset($_GET['file'])) {
$url .= '&file='.urlencode($_GET['file']);
} else if (isset($_GET['dir'])) {
$url .= '&dir='.urlencode($_GET['dir']);
$url .= '&file=' . urlencode($_GET['file']);
} else {
if (isset($_GET['dir'])) {
$url .= '&dir=' . urlencode($_GET['dir']);
}
}
if (isset($_POST['password'])) {
$password = $_POST['password'];
@ -173,13 +181,13 @@ if ($linkItem) {
}
}
}
$basePath = substr($pathAndUser['path'], strlen('/'.$fileOwner.'/files'));
$basePath = substr($pathAndUser['path'], strlen('/' . $fileOwner . '/files'));
$path = $basePath;
if (isset($_GET['path'])) {
$path .= $_GET['path'];
}
if (!$path || !OC_Filesystem::isValidPath($path) || !OC_Filesystem::file_exists($path)) {
OCP\Util::writeLog('share', 'Invalid path '.$path.' for share id '.$linkItem['id'], \OCP\Util::ERROR);
if (!$path || !\OC\Files\Filesystem::isValidPath($path) || !\OC\Files\Filesystem::file_exists($path)) {
OCP\Util::writeLog('share', 'Invalid path ' . $path . ' for share id ' . $linkItem['id'], \OCP\Util::ERROR);
header('HTTP/1.0 404 Not Found');
$tmpl = new OCP\Template('', '404', 'guest');
$tmpl->printPage();
@ -189,13 +197,15 @@ if ($linkItem) {
$file = basename($path);
// Download the file
if (isset($_GET['download'])) {
if (isset($_GET['path']) && $_GET['path'] !== '' ) {
if ( isset($_GET['files']) ) { // download selected files
if (isset($_GET['path']) && $_GET['path'] !== '') {
if (isset($_GET['files'])) { // download selected files
OC_Files::get($path, $_GET['files'], $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
} else if (isset($_GET['path']) && $_GET['path'] != '' ) { // download a file from a shared directory
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
} else { // download the whole shared directory
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
} else {
if (isset($_GET['path']) && $_GET['path'] != '') { // download a file from a shared directory
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
} else { // download the whole shared directory
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
}
}
} else { // download a single shared file
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
@ -210,7 +220,7 @@ if ($linkItem) {
$tmpl->assign('displayName', \OCP\User::getDisplayName($shareOwner));
$tmpl->assign('dir', $dir);
$tmpl->assign('filename', $file);
$tmpl->assign('mimetype', OC_Filesystem::getMimeType($path));
$tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path));
if (isset($_GET['path'])) {
$getPath = $_GET['path'];
} else {
@ -221,7 +231,7 @@ if ($linkItem) {
.(isset($_GET['dir'])?'&dir='.$_GET['dir']:'')
.(isset($_GET['file'])?'&file='.$_GET['file']:'');
// Show file list
if (OC_Filesystem::is_dir($path)) {
if (\OC\Files\Filesystem::is_dir($path)) {
OCP\Util::addStyle('files', 'files');
OCP\Util::addScript('files', 'files');
OCP\Util::addScript('files', 'filelist');
@ -232,9 +242,9 @@ if ($linkItem) {
if ($i['type'] == 'file') {
$fileinfo = pathinfo($i['name']);
$i['basename'] = $fileinfo['filename'];
$i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : '';
$i['extension'] = isset($fileinfo['extension']) ? ('.' . $fileinfo['extension']) : '';
}
$i['directory'] = '/'.substr($i['directory'], $rootLength);
$i['directory'] = '/' . substr($i['directory'], $rootLength);
if ($i['directory'] == '/') {
$i['directory'] = '';
}
@ -251,9 +261,137 @@ if ($linkItem) {
//add subdir breadcrumbs
foreach (explode('/', urldecode($getPath)) as $i) {
if ($i != '') {
$pathtohere .= '/'.$i;
$pathtohere .= '/' . $i;
$breadcrumb[] = array('dir' => $pathtohere, 'name' => $i);
$path = $linkItem['path'];
if (isset($_GET['path'])) {
$path .= $_GET['path'];
$dir .= $_GET['path'];
if (!\OC\Files\Filesystem::file_exists($path)) {
header('HTTP/1.0 404 Not Found');
$tmpl = new OCP\Template('', '404', 'guest');
$tmpl->printPage();
exit();
}
}
$list = new OCP\Template('files', 'part.list', '');
$list->assign('files', $files, false);
$list->assign('publicListView', true);
$list->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path=', false);
$list->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path=', false);
$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '');
$breadcrumbNav->assign('breadcrumb', $breadcrumb, false);
$breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path=', false);
$folder = new OCP\Template('files', 'index', '');
$folder->assign('fileList', $list->fetchPage(), false);
$folder->assign('breadcrumb', $breadcrumbNav->fetchPage(), false);
$folder->assign('isCreatable', false);
$folder->assign('permissions', 0);
$folder->assign('files', $files);
$folder->assign('uploadMaxFilesize', 0);
$folder->assign('uploadMaxHumanFilesize', 0);
$folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
$tmpl->assign('folder', $folder->fetchPage(), false);
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path=' . urlencode($getPath));
} else {
// Show file preview if viewer is available
if ($type == 'file') {
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download');
} else {
OCP\Util::addStyle('files_sharing', 'public');
OCP\Util::addScript('files_sharing', 'public');
OCP\Util::addScript('files', 'fileactions');
$tmpl = new OCP\Template('files_sharing', 'public', 'base');
$tmpl->assign('owner', $uidOwner);
// Show file list
if (\OC\Files\Filesystem::is_dir($path)) {
OCP\Util::addStyle('files', 'files');
OCP\Util::addScript('files', 'files');
OCP\Util::addScript('files', 'filelist');
$files = array();
$rootLength = strlen($baseDir) + 1;
foreach (OC_Files::getDirectoryContent($path) as $i) {
$i['date'] = OCP\Util::formatDate($i['mtime']);
if ($i['type'] == 'file') {
$fileinfo = pathinfo($i['name']);
$i['basename'] = $fileinfo['filename'];
$i['extension'] = isset($fileinfo['extension']) ? ('.' . $fileinfo['extension']) : '';
}
$i['directory'] = '/' . substr('/' . $uidOwner . '/files' . $i['directory'], $rootLength);
if ($i['directory'] == '/') {
$i['directory'] = '';
}
$i['permissions'] = OCP\PERMISSION_READ;
$files[] = $i;
}
// Make breadcrumb
$breadcrumb = array();
$pathtohere = '';
$count = 1;
foreach (explode('/', $dir) as $i) {
if ($i != '') {
if ($i != $baseDir) {
$pathtohere .= '/' . $i;
}
if (strlen($pathtohere) < strlen($_GET['dir'])) {
continue;
}
$breadcrumb[] = array('dir' => str_replace($_GET['dir'], "", $pathtohere, $count), 'name' => $i);
}
}
$list = new OCP\Template('files', 'part.list', '');
$list->assign('files', $files, false);
$list->assign('publicListView', true);
$list->assign('baseURL', OCP\Util::linkToPublic('files') . '&dir=' . urlencode($_GET['dir']) . '&path=', false);
$list->assign('downloadURL', OCP\Util::linkToPublic('files') . '&download&dir=' . urlencode($_GET['dir']) . '&path=', false);
$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '');
$breadcrumbNav->assign('breadcrumb', $breadcrumb, false);
$breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files') . '&dir=' . urlencode($_GET['dir']) . '&path=', false);
$folder = new OCP\Template('files', 'index', '');
$folder->assign('fileList', $list->fetchPage(), false);
$folder->assign('breadcrumb', $breadcrumbNav->fetchPage(), false);
$folder->assign('dir', basename($dir));
$folder->assign('isCreatable', false);
$folder->assign('permissions', 0);
$folder->assign('files', $files);
$folder->assign('uploadMaxFilesize', 0);
$folder->assign('uploadMaxHumanFilesize', 0);
$folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
$tmpl->assign('folder', $folder->fetchPage(), false);
$tmpl->assign('uidOwner', $uidOwner);
$tmpl->assign('dir', basename($dir));
$tmpl->assign('filename', basename($path));
$tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path));
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
if (isset($_GET['path'])) {
$getPath = $_GET['path'];
} else {
$getPath = '';
}
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . '&download&dir=' . urlencode($_GET['dir']) . '&path=' . urlencode($getPath), false);
} else {
// Show file preview if viewer is available
$tmpl->assign('uidOwner', $uidOwner);
$tmpl->assign('dir', dirname($path));
$tmpl->assign('filename', basename($path));
$tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path));
if ($type == 'file') {
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . '&file=' . urlencode($_GET['file']) . '&download', false);
} else {
if (isset($_GET['path'])) {
$getPath = $_GET['path'];
} else {
$getPath = '';
}
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . '&download&dir=' . urlencode($_GET['dir']) . '&path=' . urlencode($getPath), false);
}
}
$tmpl->printPage();
}
}
$tmpl->printPage();
}
$list = new OCP\Template('files', 'part.list', '');
@ -279,21 +417,11 @@ if ($linkItem) {
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files')
.$urlLinkIdentifiers.'&download&path='.urlencode($getPath));
} else {
// Show file preview if viewer is available
if ($type == 'file') {
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files')
.$urlLinkIdentifiers.'&download');
} else {
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files')
.$urlLinkIdentifiers.'&download&path='.urlencode($getPath));
}
OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG);
}
$tmpl->printPage();
}
exit();
} else {
OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG);
}
header('HTTP/1.0 404 Not Found');
$tmpl = new OCP\Template('', '404', 'guest');
$tmpl->printPage();

View File

@ -4,7 +4,7 @@
<name>Versions</name>
<licence>AGPL</licence>
<author>Frank Karlitschek</author>
<require>4.9</require>
<require>4.91</require>
<shipped>true</shipped>
<description>Versioning of files</description>
<types>

View File

@ -21,9 +21,9 @@ class Hooks {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
$versions = new Storage( new \OC_FilesystemView('') );
$versions = new Storage( new \OC\Files\View('') );
$path = $params[\OC_Filesystem::signal_param_path];
$path = $params[\OC\Files\Filesystem::signal_param_path];
if($path<>'') $versions->store( $path );
@ -39,15 +39,15 @@ class Hooks {
* cleanup the versions directory if the actual file gets deleted
*/
public static function remove_hook($params) {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
$versions = new Storage( new \OC_FilesystemView('') );
$path = $params[\OC_Filesystem::signal_param_path];
if($path<>'') $versions->delete( $path );
}
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
$versions = new Storage( new \OC_FilesystemView('') );
$path = $params[\OC\Files\Filesystem::signal_param_path];
if($path<>'') $versions->delete( $path );
}
}
/**
@ -58,15 +58,15 @@ class Hooks {
* of the stored versions along the actual file
*/
public static function rename_hook($params) {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
$versions = new Storage( new \OC_FilesystemView('') );
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
$versions = new Storage( new \OC_FilesystemView('') );
$oldpath = $params['oldpath'];
$newpath = $params['newpath'];
if($oldpath<>'' && $newpath<>'') $versions->rename( $oldpath, $newpath );
$newpath = $params['newpath'];
if($oldpath<>'' && $newpath<>'') $versions->rename( $oldpath, $newpath );
}
}

View File

@ -23,15 +23,15 @@ class Storage {
private static $max_versions_per_interval = array(
1 => array('intervalEndsAfter' => 10, //first 10sec, one version every 2sec
'step' => 2),
2 => array('intervalEndsAfter' => 60, //next minute, one version every 10sec
2 => array('intervalEndsAfter' => 60, //next minute, one version every 10sec
'step' => 10),
3 => array('intervalEndsAfter' => 3600, //next hour, one version every minute
'step' => 60),
4 => array('intervalEndsAfter' => 86400, //next 24h, one version every hour
'step' => 3600),
5 => array('intervalEndsAfter' => 2592000, //next 30days, one version per day
5 => array('intervalEndsAfter' => 2592000, //next 30days, one version per day
'step' => 86400),
6 => array('intervalEndsAfter' => -1, //until the end one version per week
6 => array('intervalEndsAfter' => -1, //until the end one version per week
'step' => 604800),
);
@ -58,8 +58,8 @@ class Storage {
public function store($filename) {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
list($uid, $filename) = self::getUidAndFilename($filename);
$files_view = new \OC_FilesystemView('/'.$uid .'/files');
$users_view = new \OC_FilesystemView('/'.$uid);
$files_view = new \OC\Files\View('/'.\OCP\User::getUser() .'/files');
$users_view = new \OC\Files\View('/'.\OCP\User::getUser());
//check if source file already exist as version to avoid recursions.
// todo does this check work?
@ -86,8 +86,8 @@ class Storage {
// store a new version of a file
$result = $users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename));
if ( ($versionsSize = \OCP\Config::getAppValue('files_versions', 'size')) === null ) {
$versionsSize = self::calculateSize($uid);
if ( ($versionsSize = \OCP\Config::getAppValue('files_versions', 'size')) === null ) {
$versionsSize = self::calculateSize($uid);
}
$versionsSize += $users_view->filesize('files'.$filename);
@ -105,42 +105,42 @@ class Storage {
* Delete versions of a file
*/
public static function delete($filename) {
list($uid, $filename) = self::getUidAndFilename($filename);
list($uid, $filename) = self::getUidAndFilename($filename);
$versions_fileview = new \OC_FilesystemView('/'.$uid .'/files_versions');
$abs_path = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$filename.'.v';
if( ($versions = self::getVersions($filename)) ) {
if ( ($versionsSize = \OCP\Config::getAppValue('files_versions', 'size')) === null ) {
$versionsSize = self::calculateSize($uid);
}
foreach ($versions as $v) {
unlink($abs_path . $v['version']);
$versionsSize -= $v['size'];
}
\OCP\Config::setAppValue('files_versions', 'size', $versionsSize);
$abs_path = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$filename.'.v';
if( ($versions = self::getVersions($filename)) ) {
if ( ($versionsSize = \OCP\Config::getAppValue('files_versions', 'size')) === null ) {
$versionsSize = self::calculateSize($uid);
}
foreach ($versions as $v) {
unlink($abs_path . $v['version']);
$versionsSize -= $v['size'];
}
\OCP\Config::setAppValue('files_versions', 'size', $versionsSize);
}
}
/**
* rename versions of a file
*/
public static function rename($oldpath, $newpath) {
/**
* rename versions of a file
*/
public static function rename($oldpath, $newpath) {
list($uid, $oldpath) = self::getUidAndFilename($oldpath);
list($uidn, $newpath) = self::getUidAndFilename($newpath);
list($uidn, $newpath) = self::getUidAndFilename($newpath);
$versions_view = new \OC_FilesystemView('/'.$uid .'/files_versions');
$files_view = new \OC_FilesystemView('/'.$uid .'/files');
$abs_newpath = \OCP\Config::getSystemValue('datadirectory').$versions_view->getAbsolutePath('').$newpath;
$abs_newpath = \OCP\Config::getSystemValue('datadirectory').$versions_view->getAbsolutePath('').$newpath;
if ( $files_view->is_dir($oldpath) && $versions_view->is_dir($oldpath) ) {
$versions_view->rename($oldpath, $newpath);
} else if ( ($versions = Storage::getVersions($oldpath)) ) {
$info=pathinfo($abs_newpath);
if(!file_exists($info['dirname'])) mkdir($info['dirname'], 0750, true);
$versions = Storage::getVersions($oldpath);
} else if ( ($versions = Storage::getVersions($oldpath)) ) {
$info=pathinfo($abs_newpath);
if(!file_exists($info['dirname'])) mkdir($info['dirname'], 0750, true);
$versions = Storage::getVersions($oldpath);
foreach ($versions as $v) {
$versions_view->rename($oldpath.'.v'.$v['version'], $newpath.'.v'.$v['version']);
}
}
$versions_view->rename($oldpath.'.v'.$v['version'], $newpath.'.v'.$v['version']);
}
}
}
/**
@ -150,7 +150,7 @@ class Storage {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
list($uid, $filename) = self::getUidAndFilename($filename);
$users_view = new \OC_FilesystemView('/'.$uid);
$users_view = new \OC\Files\View('/'.$uid);
$versionCreated = false;
//first create a new version
@ -184,7 +184,7 @@ class Storage {
public static function getVersions( $filename, $count = 0 ) {
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
list($uid, $filename) = self::getUidAndFilename($filename);
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
$versions_fileview = new \OC\Files\View('/' . \OCP\User::getUser() . '/files_versions');
$versionsName = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename);
$versions = array();
@ -202,7 +202,7 @@ class Storage {
$key = $version.'#'.$filename;
$versions[$key]['cur'] = 0;
$versions[$key]['version'] = $version;
$versions[$key]['path'] = $filename;
$versions[$key]['path'] = $filename;
$versions[$key]['size'] = $versions_fileview->filesize($filename.'.v'.$version);
// if file with modified date exists, flag it in array as currently enabled version
@ -236,29 +236,29 @@ class Storage {
}
/**
* @brief get the size of all stored versions from a given user
* @param $uid id from the user
* @return size of vesions
*/
private static function calculateSize($uid) {
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
$versionsRoot = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('');
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($versionsRoot), \RecursiveIteratorIterator::CHILD_FIRST);
/**
* @brief get the size of all stored versions from a given user
* @param $uid id from the user
* @return size of vesions
*/
private static function calculateSize($uid) {
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
$versionsRoot = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('');
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($versionsRoot), \RecursiveIteratorIterator::CHILD_FIRST);
$size = 0;
foreach ($iterator as $path) {
if ( preg_match('/^.+\.v(\d+)$/', $path, $match) ) {
foreach ($iterator as $path) {
if ( preg_match('/^.+\.v(\d+)$/', $path, $match) ) {
$relpath = substr($path, strlen($versionsRoot)-1);
$size += $versions_fileview->filesize($relpath);
}
$size += $versions_fileview->filesize($relpath);
}
}
return $size;
}
return $size;
}
}
/**
@ -267,11 +267,11 @@ class Storage {
* @return array with contains two arrays 'all' which contains all versions sorted by age and 'by_file' which contains all versions sorted by filename
*/
private static function getAllVersions($uid) {
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
$versionsRoot = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('');
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($versionsRoot), \RecursiveIteratorIterator::CHILD_FIRST);
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($versionsRoot), \RecursiveIteratorIterator::CHILD_FIRST);
$versions = array();
@ -280,7 +280,7 @@ class Storage {
$relpath = substr($path, strlen($versionsRoot)-1);
$versions[$match[1].'#'.$relpath] = array('path' => $relpath, 'timestamp' => $match[1]);
}
}
}
ksort($versions);
@ -288,20 +288,20 @@ class Storage {
$result = array();
foreach( $versions as $key => $value ) {
foreach( $versions as $key => $value ) {
$i++;
$size = $versions_fileview->filesize($value['path']);
$filename = substr($value['path'], 0, -strlen($value['timestamp'])-2);
$result['all'][$key]['version'] = $value['timestamp'];
$result['all'][$key]['path'] = $filename;
$result['all'][$key]['path'] = $filename;
$result['all'][$key]['size'] = $size;
$filename = substr($value['path'], 0, -strlen($value['timestamp'])-2);
$result['by_file'][$filename][$key]['version'] = $value['timestamp'];
$result['by_file'][$filename][$key]['path'] = $filename;
$result['by_file'][$filename][$key]['path'] = $filename;
$result['by_file'][$filename][$key]['size'] = $size;
}
return $result;
@ -322,7 +322,7 @@ class Storage {
$quota = \OCP\Util::computerFileSize(\OC_Appconfig::getValue('files', 'default_quota'));
}
if ( $quota == null ) {
$quota = \OC_Filesystem::free_space('/');
$quota = \OC\Files\Filesystem::free_space('/');
}
// make sure that we have the current size of the version history
@ -332,7 +332,7 @@ class Storage {
}
}
// calculate available space for version history
// calculate available space for version history
$rootInfo = \OC_FileCache::get('', '/'. $uid . '/files');
$free = $quota-$rootInfo['size']; // remaining free space for user
if ( $free > 0 ) {
@ -394,7 +394,7 @@ class Storage {
$nextVersion = $prevTimestamp - $step;
if ( Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1 ) {
$nextInterval = -1;
} else {
} else {
$nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
}
$newInterval = true; // we changed the interval -> check same version with new interval

View File

@ -7,7 +7,7 @@
This app is not compatible to the WebDAV user backend.</description>
<licence>AGPL</licence>
<author>Dominik Schmidt and Arthur Schiwon</author>
<require>4.9</require>
<require>4.91</require>
<shipped>true</shipped>
<types>
<authentication/>

View File

@ -7,7 +7,7 @@
This app is not compatible to the LDAP user and group backend.</description>
<licence>AGPL</licence>
<author>Frank Karlitschek</author>
<require>4.9</require>
<require>4.91</require>
<shipped>true</shipped>
<types>
<authentication/>

View File

@ -60,16 +60,96 @@
<table>
<name>*dbprefix*fscache</name>
<name>*dbprefix*storages</name>
<declaration>
<field>
<name>id</name>
<autoincrement>1</autoincrement>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>64</length>
</field>
<field>
<name>numeric_id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<length>4</length>
</field>
<index>
<name>storages_id_index</name>
<unique>true</unique>
<field>
<name>id</name>
<sorting>ascending</sorting>
</field>
</index>
</declaration>
</table>
<table>
<name>*dbprefix*mimetypes</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<length>4</length>
</field>
<field>
<name>mimetype</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>255</length>
</field>
<index>
<name>mimetype_id_index</name>
<unique>true</unique>
<field>
<name>mimetype</name>
<sorting>ascending</sorting>
</field>
</index>
</declaration>
</table>
<table>
<name>*dbprefix*filecache</name>
<declaration>
<field>
<name>fileid</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<length>4</length>
</field>
<field>
<name>storage</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>4</length>
</field>
@ -92,9 +172,9 @@
<field>
<name>parent</name>
<type>integer</type>
<default>0</default>
<default></default>
<notnull>true</notnull>
<length>8</length>
<length>4</length>
</field>
<field>
@ -102,7 +182,122 @@
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>300</length>
<length>250</length>
</field>
<field>
<name>mimetype</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>4</length>
</field>
<field>
<name>mimepart</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>4</length>
</field>
<field>
<name>size</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>4</length>
</field>
<field>
<name>mtime</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>4</length>
</field>
<field>
<name>encrypted</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>4</length>
</field>
<field>
<name>etag</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>40</length>
</field>
<index>
<name>fs_storage_path_hash</name>
<unique>true</unique>
<field>
<name>storage</name>
<sorting>ascending</sorting>
</field>
<field>
<name>path_hash</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>fs_parent_name_hash</name>
<field>
<name>parent</name>
<sorting>ascending</sorting>
</field>
<field>
<name>name</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>fs_storage_mimetype</name>
<field>
<name>storage</name>
<sorting>ascending</sorting>
</field>
<field>
<name>mimetype</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>fs_storage_mimepart</name>
<field>
<name>storage</name>
<sorting>ascending</sorting>
</field>
<field>
<name>mimepart</name>
<sorting>ascending</sorting>
</field>
</index>
</declaration>
</table>
<table>
<name>*dbprefix*permissions</name>
<declaration>
<field>
<name>fileid</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>4</length>
</field>
<field>
@ -114,101 +309,22 @@
</field>
<field>
<name>size</name>
<name>permissions</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>8</length>
</field>
<field>
<name>ctime</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>8</length>
</field>
<field>
<name>mtime</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>8</length>
</field>
<field>
<name>mimetype</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>96</length>
</field>
<field>
<name>mimepart</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>32</length>
</field>
<field>
<name>encrypted</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>1</length>
</field>
<field>
<name>versioned</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>1</length>
</field>
<field>
<name>writable</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<length>1</length>
<length>4</length>
</field>
<index>
<name>fscache_path_hash_index</name>
<name>id_user_index</name>
<unique>true</unique>
<field>
<name>path_hash</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>parent_index</name>
<field>
<name>parent</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>name_index</name>
<field>
<name>name</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>parent_name_index</name>
<field>
<name>parent</name>
<name>fileid</name>
<sorting>ascending</sorting>
</field>
<field>
<name>name</name>
<name>user</name>
<sorting>ascending</sorting>
</field>
</index>

View File

@ -803,16 +803,16 @@ class OC_App{
/**
* @param string $appid
* @return OC_FilesystemView
* @return \OC\Files\View
*/
public static function getStorage($appid) {
if(OC_App::isEnabled($appid)) {//sanity check
if(OC_User::isLoggedIn()) {
$view = new OC_FilesystemView('/'.OC_User::getUser());
$view = new \OC\Files\View('/'.OC_User::getUser());
if(!$view->file_exists($appid)) {
$view->mkdir($appid);
}
return new OC_FilesystemView('/'.OC_User::getUser().'/'.$appid);
return new \OC\Files\View('/'.OC_User::getUser().'/'.$appid);
}else{
OC_Log::write('core', 'Can\'t get app storage, app '.$appid.', user not logged in', OC_Log::ERROR);
return false;

View File

@ -308,7 +308,7 @@ class OC_Archive_TAR extends OC_Archive{
if($mode=='r' or $mode=='rb') {
return fopen($tmpFile, $mode);
}else{
OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this, 'writeBack');
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
self::$tempFiles[$tmpFile]=$path;
return fopen('close://'.$tmpFile, $mode);
}

View File

@ -171,7 +171,7 @@ class OC_Archive_ZIP extends OC_Archive{
$ext='';
}
$tmpFile=OCP\Files::tmpFile($ext);
OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this, 'writeBack');
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if($this->fileExists($path)) {
$this->extractFile($path, $tmpFile);
}

View File

@ -112,6 +112,8 @@ class OC
$path = str_replace('\\', '/', $className) . '.php';
} elseif (strpos($className, 'Test_') === 0) {
$path = 'tests/lib/' . strtolower(str_replace('_', '/', substr($className, 5)) . '.php');
} elseif (strpos($className, 'Test\\') === 0) {
$path = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($className, 5)) . '.php');
} else {
return false;
}
@ -420,10 +422,10 @@ class OC
}
// register the stream wrappers
require_once 'streamwrappers.php';
stream_wrapper_register("fakedir", "OC_FakeDirStream");
stream_wrapper_register('static', 'OC_StaticStreamWrapper');
stream_wrapper_register('close', 'OC_CloseStreamWrapper');
stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
stream_wrapper_register('close', 'OC\Files\Stream\Close');
stream_wrapper_register('oc', 'OC\Files\Stream\OC');
self::checkConfig();
self::checkInstalled();

4
lib/cache/file.php vendored
View File

@ -15,11 +15,11 @@ class OC_Cache_File{
}
if(OC_User::isLoggedIn()) {
$subdir = 'cache';
$view = new OC_FilesystemView('/'.OC_User::getUser());
$view = new \OC\Files\View('/'.OC_User::getUser());
if(!$view->file_exists($subdir)) {
$view->mkdir($subdir);
}
$this->storage = new OC_FilesystemView('/'.OC_User::getUser().'/'.$subdir);
$this->storage = new \OC\Files\View('/'.OC_User::getUser().'/'.$subdir);
return $this->storage;
}else{
OC_Log::write('core', 'Can\'t get cache storage, user not logged in', OC_Log::ERROR);

View File

@ -62,7 +62,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
}
} else {
$newPath = $this->path . '/' . $name;
OC_Filesystem::file_put_contents($newPath, $data);
\OC\Files\Filesystem::file_put_contents($newPath, $data);
return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
}
@ -78,7 +78,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
public function createDirectory($name) {
$newPath = $this->path . '/' . $name;
OC_Filesystem::mkdir($newPath);
\OC\Files\Filesystem::mkdir($newPath);
}
@ -93,7 +93,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
$path = $this->path . '/' . $name;
if (is_null($info)) {
$info = OC_Files::getFileInfo($path);
$info = \OC\Files\Filesystem::getFileInfo($path);
}
if (!$info) {
@ -116,12 +116,13 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
* @return Sabre_DAV_INode[]
*/
public function getChildren() {
$folder_content = OC_Files::getDirectoryContent($this->path);
$folder_content = \OC\Files\Filesystem::getDirectoryContent($this->path);
$paths = array();
foreach($folder_content as $info) {
$paths[] = $this->path.'/'.$info['name'];
$properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = $info['etag'];
}
$properties = array_fill_keys($paths, array());
if(count($paths)>0) {
//
// the number of arguments within IN conditions are limited in most databases
@ -160,7 +161,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
public function childExists($name) {
$path = $this->path . '/' . $name;
return OC_Filesystem::file_exists($path);
return \OC\Files\Filesystem::file_exists($path);
}
@ -173,7 +174,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
if ($this->path != "/Shared") {
foreach($this->getChildren() as $child) $child->delete();
OC_Filesystem::rmdir($this->path);
\OC\Files\Filesystem::rmdir($this->path);
}
}
@ -184,10 +185,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
* @return array
*/
public function getQuotaInfo() {
$rootInfo=OC_FileCache_Cached::get('');
$rootInfo=\OC\Files\Filesystem::getFileInfo('');
return array(
$rootInfo['size'],
OC_Filesystem::free_space()
\OC\Files\Filesystem::free_space()
);
}

View File

@ -45,7 +45,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
*/
public function put($data) {
OC_Filesystem::file_put_contents($this->path, $data);
\OC\Files\Filesystem::file_put_contents($this->path,$data);
return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
}
@ -57,7 +57,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
*/
public function get() {
return OC_Filesystem::fopen($this->path, 'rb');
return \OC\Files\Filesystem::fopen($this->path,'rb');
}
@ -68,7 +68,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
*/
public function delete() {
OC_Filesystem::unlink($this->path);
\OC\Files\Filesystem::unlink($this->path);
}
@ -98,16 +98,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
if (isset($properties[self::GETETAG_PROPERTYNAME])) {
return $properties[self::GETETAG_PROPERTYNAME];
}
return $this->getETagPropertyForPath($this->path);
}
/**
* Creates a ETag for this path.
* @param string $path Path of the file
* @return string|null Returns null if the ETag can not effectively be determined
*/
static protected function createETag($path) {
return OC_Filesystem::hash('md5', $path);
return null;
}
/**
@ -122,7 +113,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
return $this->fileinfo_cache['mimetype'];
}
return OC_Filesystem::getMimeType($this->path);
return \OC\Files\Filesystem::getMimeType($this->path);
}
}

View File

@ -84,12 +84,12 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
$newPath = $parentPath . '/' . $newName;
$oldPath = $this->path;
OC_Filesystem::rename($this->path, $newPath);
\OC\Files\Filesystem::rename($this->path,$newPath);
$this->path = $newPath;
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ? WHERE `userid` = ? AND `propertypath` = ?' );
$query->execute( array( $newPath, OC_User::getUser(), $oldPath ));
$query->execute( array( $newPath,OC_User::getUser(), $oldPath ));
}
@ -104,9 +104,9 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
*/
protected function getFileinfoCache() {
if (!isset($this->fileinfo_cache)) {
if ($fileinfo_cache = OC_FileCache::get($this->path)) {
if ($fileinfo_cache = \OC\Files\Filesystem::getFileInfo($this->path)) {
} else {
$fileinfo_cache = OC_Filesystem::stat($this->path);
$fileinfo_cache = \OC\Files\Filesystem::stat($this->path);
}
$this->fileinfo_cache = $fileinfo_cache;
@ -134,7 +134,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* Even if the modification time is set to a custom value the access time is set to now.
*/
public function touch($mtime) {
OC_Filesystem::touch($this->path, $mtime);
\OC\Files\Filesystem::touch($this->path, $mtime);
}
/**
@ -159,10 +159,10 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
} else {
if(!array_key_exists( $propertyName, $existing )) {
$query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties` (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' );
$query->execute( array( OC_User::getUser(), $this->path, $propertyName, $propertyValue ));
$query->execute( array( OC_User::getUser(), $this->path, $propertyName,$propertyValue ));
} else {
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ? WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
$query->execute( array( $propertyValue, OC_User::getUser(), $this->path, $propertyName ));
$query->execute( array( $propertyValue,OC_User::getUser(), $this->path, $propertyName ));
}
}
}
@ -190,6 +190,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
while( $row = $result->fetchRow()) {
$this->property_cache[$row['propertyname']] = $row['propertyvalue'];
}
$this->property_cache[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path);
}
// if the array was empty, we need to return everything
@ -205,57 +206,16 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
}
/**
* @brief Creates a ETag for this path.
* @param string $path Path of the file
* @return string|null Returns null if the ETag can not effectively be determined
*/
static protected function createETag($path) {
if(self::$ETagFunction) {
$hash = call_user_func(self::$ETagFunction, $path);
return $hash;
}else{
return uniqid('', true);
}
}
/**
* @brief Returns the ETag surrounded by double-quotes for this path.
* Returns the ETag surrounded by double-quotes for this path.
* @param string $path Path of the file
* @return string|null Returns null if the ETag can not effectively be determined
*/
static public function getETagPropertyForPath($path) {
$tag = self::createETag($path);
if (empty($tag)) {
return null;
$data = \OC\Files\Filesystem::getFileInfo($path);
if (isset($data['etag'])) {
return '"'.$data['etag'].'"';
}
$etag = '"'.$tag.'"';
$query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties` (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' );
$query->execute( array( OC_User::getUser(), $path, self::GETETAG_PROPERTYNAME, $etag ));
return $etag;
return null;
}
/**
* @brief Remove the ETag from the cache.
* @param string $path Path of the file
*/
static public function removeETagPropertyForPath($path) {
// remove tags from this and parent paths
$paths = array();
while ($path != '/' && $path != '.' && $path != '' && $path != '\\') {
$paths[] = $path;
$path = dirname($path);
}
if (empty($paths)) {
return;
}
$paths[] = $path;
$path_placeholders = join(',', array_fill(0, count($paths), '?'));
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
.' WHERE `userid` = ?'
.' AND `propertyname` = ?'
.' AND `propertypath` IN ('.$path_placeholders.')'
);
$vals = array( OC_User::getUser(), self::GETETAG_PROPERTYNAME );
$query->execute(array_merge( $vals, $paths ));
}
}

View File

@ -50,7 +50,7 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
$uri='/'.$uri;
}
list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
if ($length > OC_Filesystem::free_space($parentUri)) {
if ($length > \OC\Files\Filesystem::free_space($parentUri)) {
throw new Sabre_DAV_Exception_InsufficientStorage();
}
}

View File

@ -1,539 +0,0 @@
<?php
/**
* @author Robin Appelman
* @copyright 2011 Robin Appelman icewind1991@gmail.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* provide caching for filesystem info in the database
*
* not used by OC_Filesystem for reading filesystem info,
* instead apps should use OC_FileCache::get where possible
*
* It will try to keep the data up to date but changes from outside
* ownCloud can invalidate the cache
*
* Methods that take $path and $root params expect $path to be relative, like
* /admin/files/file.txt, if $root is false
*
*/
class OC_FileCache{
/**
* get the filesystem info from the cache
* @param string path
* @param string root (optional)
* @return array
*
* returns an associative array with the following keys:
* - size
* - mtime
* - ctime
* - mimetype
* - encrypted
* - versioned
*/
public static function get($path, $root=false) {
if(OC_FileCache_Update::hasUpdated($path, $root)) {
if($root===false) {//filesystem hooks are only valid for the default root
OC_Hook::emit('OC_Filesystem', 'post_write', array('path'=>$path));
}else{
OC_FileCache_Update::update($path, $root);
}
}
return OC_FileCache_Cached::get($path, $root);
}
/**
* put filesystem info in the cache
* @param string $path
* @param array data
* @param string root (optional)
* @note $data is an associative array in the same format as returned
* by get
*/
public static function put($path, $data, $root=false) {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
$fullpath=OC_Filesystem::normalizePath($root.'/'.$path);
$parent=self::getParentId($fullpath);
$id=self::getId($fullpath, '');
if(isset(OC_FileCache_Cached::$savedData[$fullpath])) {
$data=array_merge(OC_FileCache_Cached::$savedData[$fullpath], $data);
unset(OC_FileCache_Cached::$savedData[$fullpath]);
}
if($id!=-1) {
self::update($id, $data);
return;
}
// add parent directory to the file cache if it does not exist yet.
if ($parent == -1 && $fullpath != $root) {
$parentDir = dirname($path);
self::scanFile($parentDir);
$parent = self::getParentId($fullpath);
}
if(!isset($data['size']) or !isset($data['mtime'])) {//save incomplete data for the next time we write it
OC_FileCache_Cached::$savedData[$fullpath]=$data;
return;
}
if(!isset($data['encrypted'])) {
$data['encrypted']=false;
}
if(!isset($data['versioned'])) {
$data['versioned']=false;
}
$mimePart=dirname($data['mimetype']);
$data['size']=(int)$data['size'];
$data['ctime']=(int)$data['mtime'];
$data['writable']=(int)$data['writable'];
$data['encrypted']=(int)$data['encrypted'];
$data['versioned']=(int)$data['versioned'];
$user=OC_User::getUser();
$query=OC_DB::prepare('INSERT INTO `*PREFIX*fscache`(`parent`, `name`, `path`, `path_hash`, `size`, `mtime`, `ctime`, `mimetype`, `mimepart`,`user`,`writable`,`encrypted`,`versioned`) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)');
$result=$query->execute(array($parent, basename($fullpath), $fullpath, md5($fullpath), $data['size'], $data['mtime'], $data['ctime'], $data['mimetype'], $mimePart, $user, $data['writable'], $data['encrypted'], $data['versioned']));
if(OC_DB::isError($result)) {
OC_Log::write('files', 'error while writing file('.$fullpath.') to cache', OC_Log::ERROR);
}
if($cache=OC_Cache::getUserCache(true)) {
$cache->remove('fileid/'.$fullpath);//ensure we don't have -1 cached
}
}
/**
* update filesystem info of a file
* @param int $id
* @param array $data
*/
private static function update($id, $data) {
$arguments=array();
$queryParts=array();
foreach(array('size','mtime','ctime','mimetype','encrypted','versioned', 'writable') as $attribute) {
if(isset($data[$attribute])) {
//Convert to int it args are false
if($data[$attribute] === false) {
$arguments[] = 0;
}else{
$arguments[] = $data[$attribute];
}
$queryParts[]='`'.$attribute.'`=?';
}
}
if(isset($data['mimetype'])) {
$arguments[]=dirname($data['mimetype']);
$queryParts[]='`mimepart`=?';
}
$arguments[]=$id;
if(!empty($queryParts)) {
$sql = 'UPDATE `*PREFIX*fscache` SET '.implode(' , ', $queryParts).' WHERE `id`=?';
$query=OC_DB::prepare($sql);
$result=$query->execute($arguments);
if(OC_DB::isError($result)) {
OC_Log::write('files', 'error while updating file('.$id.') in cache', OC_Log::ERROR);
}
}
}
/**
* register a file move in the cache
* @param string oldPath
* @param string newPath
* @param string root (optional)
*/
public static function move($oldPath, $newPath, $root=false) {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
// If replacing an existing file, delete the file
if (self::inCache($newPath, $root)) {
self::delete($newPath, $root);
}
$oldPath=$root.$oldPath;
$newPath=$root.$newPath;
$newParent=self::getParentId($newPath);
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `parent`=? ,`name`=?, `path`=?, `path_hash`=? WHERE `path_hash`=?');
$query->execute(array($newParent, basename($newPath), $newPath, md5($newPath), md5($oldPath)));
if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$oldPath)) {
$cache->set('fileid/'.$newPath, $cache->get('fileid/'.$oldPath));
$cache->remove('fileid/'.$oldPath);
}
$query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `path` LIKE ?');
$oldLength=strlen($oldPath);
$updateQuery=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `path`=?, `path_hash`=? WHERE `path_hash`=?');
while($row= $query->execute(array($oldPath.'/%'))->fetchRow()) {
$old=$row['path'];
$new=$newPath.substr($old, $oldLength);
$updateQuery->execute(array($new, md5($new), md5($old)));
if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$old)) {
$cache->set('fileid/'.$new, $cache->get('fileid/'.$old));
$cache->remove('fileid/'.$old);
}
}
}
/**
* delete info from the cache
* @param string path
* @param string root (optional)
*/
public static function delete($path, $root=false) {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
$query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache` WHERE `path_hash`=?');
$query->execute(array(md5($root.$path)));
//delete everything inside the folder
$query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache` WHERE `path` LIKE ?');
$query->execute(array($root.$path.'/%'));
OC_Cache::remove('fileid/'.$root.$path);
}
/**
* return array of filenames matching the querty
* @param string $query
* @param boolean $returnData
* @param string root (optional)
* @return array of filepaths
*/
public static function search($search, $returnData=false, $root=false) {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
$rootLen=strlen($root);
if(!$returnData) {
$select = '`path`';
}else{
$select = '*';
}
if (OC_Config::getValue('dbtype') === 'oci8') {
$where = 'LOWER(`name`) LIKE LOWER(?) AND `user`=?';
} else {
$where = '`name` LIKE ? AND `user`=?';
}
$query=OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*fscache` WHERE '.$where);
$result=$query->execute(array("%$search%", OC_User::getUser()));
$names=array();
while($row=$result->fetchRow()) {
if(!$returnData) {
$names[]=substr($row['path'], $rootLen);
}else{
$row['path']=substr($row['path'], $rootLen);
$names[]=$row;
}
}
return $names;
}
/**
* get all files and folders in a folder
* @param string path
* @param string root (optional)
* @return array
*
* returns an array of assiciative arrays with the following keys:
* - name
* - size
* - mtime
* - ctime
* - mimetype
* - encrypted
* - versioned
*/
public static function getFolderContent($path, $root=false, $mimetype_filter='') {
if(OC_FileCache_Update::hasUpdated($path, $root, true)) {
OC_FileCache_Update::updateFolder($path, $root);
}
return OC_FileCache_Cached::getFolderContent($path, $root, $mimetype_filter);
}
/**
* check if a file or folder is in the cache
* @param string $path
* @param string root (optional)
* @return bool
*/
public static function inCache($path, $root=false) {
return self::getId($path, $root)!=-1;
}
/**
* get the file id as used in the cache
* @param string path
* @param string root (optional)
* @return int
*/
public static function getId($path, $root=false) {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
$fullPath=$root.$path;
if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$fullPath)) {
return $cache->get('fileid/'.$fullPath);
}
$query=OC_DB::prepare('SELECT `id` FROM `*PREFIX*fscache` WHERE `path_hash`=?');
$result=$query->execute(array(md5($fullPath)));
if(OC_DB::isError($result)) {
OC_Log::write('files', 'error while getting file id of '.$path, OC_Log::ERROR);
return -1;
}
$result=$result->fetchRow();
if(is_array($result)) {
$id=$result['id'];
}else{
$id=-1;
}
if($cache=OC_Cache::getUserCache(true)) {
$cache->set('fileid/'.$fullPath, $id);
}
return $id;
}
/**
* get the file path from the id, relative to the home folder of the user
* @param int id
* @param string user (optional)
* @return string
*/
public static function getPath($id, $user='') {
if(!$user) {
$user=OC_User::getUser();
}
$query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `id`=? AND `user`=?');
$result=$query->execute(array($id, $user));
$row=$result->fetchRow();
$path=$row['path'];
$root='/'.$user.'/files';
if(substr($path, 0, strlen($root))!=$root) {
return false;
}
return substr($path, strlen($root));
}
/**
* get the file id of the parent folder, taking into account '/' has no parent
* @param string $path
* @return int
*/
private static function getParentId($path) {
if($path=='/') {
return -1;
}else{
return self::getId(dirname($path), '');
}
}
/**
* adjust the size of the parent folders
* @param string $path
* @param int $sizeDiff
* @param string root (optinal)
*/
public static function increaseSize($path, $sizeDiff, $root=false) {
if($sizeDiff==0) return;
$item = OC_FileCache_Cached::get($path);
//stop walking up the filetree if we hit a non-folder or reached the root folder
if($path == '/' || $path=='' || $item['mimetype'] !== 'httpd/unix-directory') {
return;
}
$id = $item['id'];
while($id!=-1) {//walk up the filetree increasing the size of all parent folders
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `size`=`size`+? WHERE `id`=?');
$query->execute(array($sizeDiff, $id));
$path=dirname($path);
if($path == '' or $path =='/') {
return;
}
$parent = OC_FileCache_Cached::get($path);
$id = $parent['id'];
//stop walking up the filetree if we hit a non-folder
if($parent['mimetype'] !== 'httpd/unix-directory') {
return;
}
}
}
/**
* recursively scan the filesystem and fill the cache
* @param string $path
* @param OC_EventSource $eventSource (optional)
* @param int $count (optional)
* @param string $root (optional)
*/
public static function scan($path, $eventSource=false,&$count=0, $root=false) {
if($eventSource) {
$eventSource->send('scanning', array('file'=>$path, 'count'=>$count));
}
$lastSend=$count;
// NOTE: Ugly hack to prevent shared files from going into the cache (the source already exists somewhere in the cache)
if (substr($path, 0, 7) == '/Shared') {
return;
}
if($root===false) {
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
self::scanFile($path, $root);
$dh=$view->opendir($path.'/');
$totalSize=0;
if($dh) {
while (($filename = readdir($dh)) !== false) {
if($filename != '.' and $filename != '..') {
$file=$path.'/'.$filename;
if($view->is_dir($file.'/')) {
self::scan($file, $eventSource, $count, $root);
}else{
$totalSize+=self::scanFile($file, $root);
$count++;
if($count>$lastSend+25 and $eventSource) {
$lastSend=$count;
$eventSource->send('scanning', array('file'=>$path, 'count'=>$count));
}
}
}
}
}
OC_FileCache_Update::cleanFolder($path, $root);
self::increaseSize($path, $totalSize, $root);
}
/**
* scan a single file
* @param string path
* @param string root (optional)
* @return int size of the scanned file
*/
public static function scanFile($path, $root=false) {
// NOTE: Ugly hack to prevent shared files from going into the cache (the source already exists somewhere in the cache)
if (substr($path, 0, 7) == '/Shared') {
return;
}
if($root===false) {
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
if(!$view->is_readable($path)) return; //cant read, nothing we can do
clearstatcache();
$mimetype=$view->getMimeType($path);
$stat=$view->stat($path);
if($mimetype=='httpd/unix-directory') {
$stat['size'] = 0;
$writable=$view->is_writable($path.'/');
}else{
$writable=$view->is_writable($path);
}
$stat['mimetype']=$mimetype;
$stat['writable']=$writable;
if($path=='/') {
$path='';
}
self::put($path, $stat, $root);
return $stat['size'];
}
/**
* find files by mimetype
* @param string $part1
* @param string $part2 (optional)
* @param string root (optional)
* @return array of file paths
*
* $part1 and $part2 together form the complete mimetype.
* e.g. searchByMime('text', 'plain')
*
* seccond mimetype part can be ommited
* e.g. searchByMime('audio')
*/
public static function searchByMime($part1, $part2=null, $root=false) {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
$rootLen=strlen($root);
$root .= '%';
$user=OC_User::getUser();
if(!$part2) {
$query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `mimepart`=? AND `user`=? AND `path` LIKE ?');
$result=$query->execute(array($part1, $user, $root));
}else{
$query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `mimetype`=? AND `user`=? AND `path` LIKE ? ');
$result=$query->execute(array($part1.'/'.$part2, $user, $root));
}
$names=array();
while($row=$result->fetchRow()) {
$names[]=substr($row['path'], $rootLen);
}
return $names;
}
/**
* clean old pre-path_hash entries
*/
public static function clean() {
$query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache` WHERE LENGTH(`path_hash`)<30');
$query->execute();
}
/**
* clear filecache entries
* @param string user (optonal)
*/
public static function clear($user='') {
if($user) {
$query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache` WHERE `user`=?');
$query->execute(array($user));
}else{
$query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache`');
$query->execute();
}
}
/**
* trigger an update for the cache by setting the mtimes to 0
* @param string $user (optional)
*/
public static function triggerUpdate($user='') {
if($user) {
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `user`=? AND `mimetype`= ? ');
$query->execute(array($user,'httpd/unix-directory'));
}else{
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 AND `mimetype`= ? ');
$query->execute(array('httpd/unix-directory'));
}
}
}
//watch for changes and try to keep the cache up to date
OC_Hook::connect('OC_Filesystem', 'post_write', 'OC_FileCache_Update', 'fileSystemWatcherWrite');
OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC_FileCache_Update', 'fileSystemWatcherDelete');
OC_Hook::connect('OC_Filesystem', 'post_rename', 'OC_FileCache_Update', 'fileSystemWatcherRename');
OC_Hook::connect('OC_User', 'post_deleteUser', 'OC_FileCache_Update', 'deleteFromUser');

View File

@ -1,81 +0,0 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
/**
* get data from the filecache without checking for updates
*/
class OC_FileCache_Cached{
public static $savedData=array();
public static function get($path, $root=false) {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
$path=$root.$path;
$stmt=OC_DB::prepare('SELECT `id`, `path`,`ctime`,`mtime`,`mimetype`,`size`,`encrypted`,`versioned`,`writable` FROM `*PREFIX*fscache` WHERE `path_hash`=?');
if ( ! OC_DB::isError($stmt) ) {
$result=$stmt->execute(array(md5($path)));
if ( ! OC_DB::isError($result) ) {
$result = $result->fetchRow();
} else {
OC:Log::write('OC_FileCache_Cached', 'could not execute get: '. OC_DB::getErrorMessage($result), OC_Log::ERROR);
$result = false;
}
} else {
OC_Log::write('OC_FileCache_Cached', 'could not prepare get: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR);
$result = false;
}
if(is_array($result)) {
if(isset(self::$savedData[$path])) {
$result=array_merge($result, self::$savedData[$path]);
}
return $result;
}else{
if(isset(self::$savedData[$path])) {
return self::$savedData[$path];
}else{
return array();
}
}
}
/**
* get all files and folders in a folder
* @param string path
* @param string root (optional)
* @return array
*
* returns an array of assiciative arrays with the following keys:
* - path
* - name
* - size
* - mtime
* - ctime
* - mimetype
* - encrypted
* - versioned
*/
public static function getFolderContent($path, $root=false, $mimetype_filter='') {
if($root===false) {
$root=OC_Filesystem::getRoot();
}
$parent=OC_FileCache::getId($path, $root);
if($parent==-1) {
return array();
}
$query=OC_DB::prepare('SELECT `id`,`path`,`name`,`ctime`,`mtime`,`mimetype`,`size`,`encrypted`,`versioned`,`writable` FROM `*PREFIX*fscache` WHERE `parent`=? AND (`mimetype` LIKE ? OR `mimetype` = ?)');
$result=$query->execute(array($parent, $mimetype_filter.'%', 'httpd/unix-directory'))->fetchAll();
if(is_array($result)) {
return $result;
}else{
OC_Log::write('files', 'getFolderContent(): file not found in cache ('.$path.')', OC_Log::DEBUG);
return false;
}
}
}

View File

@ -1,227 +0,0 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
/**
* handles updating the filecache according to outside changes
*/
class OC_FileCache_Update{
/**
* check if a file or folder is updated outside owncloud
* @param string path
* @param string root (optional)
* @param boolean folder
* @return bool
*/
public static function hasUpdated($path, $root=false, $folder=false) {
if($root===false) {
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
if(!$view->file_exists($path)) {
return false;
}
$cachedData=OC_FileCache_Cached::get($path, $root);
if(isset($cachedData['mtime'])) {
$cachedMTime=$cachedData['mtime'];
if($folder) {
return $view->hasUpdated($path.'/', $cachedMTime);
}else{
return $view->hasUpdated($path, $cachedMTime);
}
}else{//file not in cache, so it has to be updated
if(($path=='/' or $path=='') and $root===false) {//dont auto update the home folder, it will be scanned
return false;
}
return true;
}
}
/**
* delete non existing files from the cache
*/
public static function cleanFolder($path, $root=false) {
if($root===false) {
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$cachedContent=OC_FileCache_Cached::getFolderContent($path, $root);
foreach($cachedContent as $fileData) {
$path=$fileData['path'];
$file=$view->getRelativePath($path);
if(!$view->file_exists($file)) {
if($root===false) {//filesystem hooks are only valid for the default root
OC_Hook::emit('OC_Filesystem', 'post_delete', array('path'=>$file));
}else{
self::delete($file, $root);
}
}
}
}
/**
* update the cache according to changes in the folder
* @param string path
* @param string root (optional)
*/
public static function updateFolder($path, $root=false) {
if($root===false) {
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$dh=$view->opendir($path.'/');
if($dh) {//check for changed/new files
while (($filename = readdir($dh)) !== false) {
if($filename != '.' and $filename != '..' and $filename != '') {
$file=$path.'/'.$filename;
$isDir=$view->is_dir($file);
if(self::hasUpdated($file, $root, $isDir)) {
if($isDir) {
self::updateFolder($file, $root);
}elseif($root===false) {//filesystem hooks are only valid for the default root
OC_Hook::emit('OC_Filesystem', 'post_write', array('path'=>$file));
}else{
self::update($file, $root);
}
}
}
}
}
self::cleanFolder($path, $root);
//update the folder last, so we can calculate the size correctly
if($root===false) {//filesystem hooks are only valid for the default root
OC_Hook::emit('OC_Filesystem', 'post_write', array('path'=>$path));
}else{
self::update($path, $root);
}
}
/**
* called when changes are made to files
* @param array $params
* @param string root (optional)
*/
public static function fileSystemWatcherWrite($params) {
$path=$params['path'];
self::update($path);
}
/**
* called when files are deleted
* @param array $params
* @param string root (optional)
*/
public static function fileSystemWatcherDelete($params) {
$path=$params['path'];
self::delete($path);
}
/**
* called when files are deleted
* @param array $params
* @param string root (optional)
*/
public static function fileSystemWatcherRename($params) {
$oldPath=$params['oldpath'];
$newPath=$params['newpath'];
self::rename($oldPath, $newPath);
}
/**
* update the filecache according to changes to the filesystem
* @param string path
* @param string root (optional)
*/
public static function update($path, $root=false) {
if($root===false) {
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$mimetype=$view->getMimeType($path);
$size=0;
$cached=OC_FileCache_Cached::get($path, $root);
$cachedSize=isset($cached['size'])?$cached['size']:0;
if($view->is_dir($path.'/')) {
if(OC_FileCache::inCache($path, $root)) {
$cachedContent=OC_FileCache_Cached::getFolderContent($path, $root);
foreach($cachedContent as $file) {
$size+=$file['size'];
}
$mtime=$view->filemtime($path.'/');
$ctime=$view->filectime($path.'/');
$writable=$view->is_writable($path.'/');
OC_FileCache::put($path, array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype, 'writable'=>$writable));
}else{
$count=0;
OC_FileCache::scan($path, null, $count, $root);
return; //increaseSize is already called inside scan
}
}else{
$size=OC_FileCache::scanFile($path, $root);
}
if($path !== '' and $path !== '/') {
OC_FileCache::increaseSize(dirname($path), $size-$cachedSize, $root);
}
}
/**
* update the filesystem after a delete has been detected
* @param string path
* @param string root (optional)
*/
public static function delete($path, $root=false) {
$cached=OC_FileCache_Cached::get($path, $root);
if(!isset($cached['size'])) {
return;
}
$size=$cached['size'];
OC_FileCache::increaseSize(dirname($path), -$size, $root);
OC_FileCache::delete($path, $root);
}
/**
* update the filesystem after a rename has been detected
* @param string oldPath
* @param string newPath
* @param string root (optional)
*/
public static function rename($oldPath, $newPath, $root=false) {
if(!OC_FileCache::inCache($oldPath, $root)) {
return;
}
if($root===false) {
$view=OC_Filesystem::getView();
}else{
$view=new OC_FilesystemView($root);
}
$cached=OC_FileCache_Cached::get($oldPath, $root);
$oldSize=$cached['size'];
OC_FileCache::increaseSize(dirname($oldPath), -$oldSize, $root);
OC_FileCache::increaseSize(dirname($newPath), $oldSize, $root);
OC_FileCache::move($oldPath, $newPath);
}
/**
* delete files owned by user from the cache
* @param string $parameters$parameters["uid"])
*/
public static function deleteFromUser($parameters) {
OC_FileCache::clear($parameters["uid"]);
}
}

View File

@ -94,49 +94,49 @@ class OC_FileChunking {
}
public function file_assemble($path) {
$absolutePath = OC_Filesystem::normalizePath(OC_Filesystem::getView()->getAbsolutePath($path));
$absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path));
$data = '';
// use file_put_contents as method because that best matches what this function does
if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && OC_Filesystem::isValidPath($path)) {
$path = OC_Filesystem::getView()->getRelativePath($absolutePath);
$exists = OC_Filesystem::file_exists($path);
if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && \OC\Files\Filesystem::isValidPath($path)) {
$path = \OC\Files\Filesystem::getView()->getRelativePath($absolutePath);
$exists = \OC\Files\Filesystem::file_exists($path);
$run = true;
if(!$exists) {
OC_Hook::emit(
OC_Filesystem::CLASSNAME,
OC_Filesystem::signal_create,
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_create,
array(
OC_Filesystem::signal_param_path => $path,
OC_Filesystem::signal_param_run => &$run
\OC\Files\Filesystem::signal_param_path => $path,
\OC\Files\Filesystem::signal_param_run => &$run
)
);
}
OC_Hook::emit(
OC_Filesystem::CLASSNAME,
OC_Filesystem::signal_write,
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_write,
array(
OC_Filesystem::signal_param_path => $path,
OC_Filesystem::signal_param_run => &$run
\OC\Files\Filesystem::signal_param_path => $path,
\OC\Files\Filesystem::signal_param_run => &$run
)
);
if(!$run) {
return false;
}
$target = OC_Filesystem::fopen($path, 'w');
$target = \OC\Files\Filesystem::fopen($path, 'w');
if($target) {
$count = $this->assemble($target);
fclose($target);
if(!$exists) {
OC_Hook::emit(
OC_Filesystem::CLASSNAME,
OC_Filesystem::signal_post_create,
array( OC_Filesystem::signal_param_path => $path)
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_post_create,
array( \OC\Files\Filesystem::signal_param_path => $path)
);
}
OC_Hook::emit(
OC_Filesystem::CLASSNAME,
OC_Filesystem::signal_post_write,
array( OC_Filesystem::signal_param_path => $path)
\OC\Files\Filesystem::CLASSNAME,
\OC\Files\Filesystem::signal_post_write,
array( \OC\Files\Filesystem::signal_param_path => $path)
);
OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
return $count > 0;

View File

@ -36,7 +36,7 @@
* The return value of the post-proxy will be used as the new result of the operation
* The operations that have a post-proxy are:
* file_get_contents, is_file, is_dir, file_exists, stat, is_readable,
* is_writable, fileatime, filemtime, filectime, file_get_contents,
* is_writable, filemtime, filectime, file_get_contents,
* getMimeType, hash, fopen, free_space and search
*/

View File

@ -28,10 +28,10 @@ class OC_FileProxy_FileOperations extends OC_FileProxy{
static $rootView;
public function premkdir($path) {
if(!self::$rootView) {
self::$rootView = new OC_FilesystemView('');
if(!self::$rootView){
self::$rootView = new \OC\Files\View('');
}
return !self::$rootView->file_exists($path);
}
}
}

View File

@ -22,7 +22,7 @@
*/
/**
* user quota managment
* user quota management
*/
class OC_FileProxy_Quota extends OC_FileProxy{
@ -57,23 +57,25 @@ class OC_FileProxy_Quota extends OC_FileProxy{
* @return int
*/
private function getFreeSpace($path) {
$storage=OC_Filesystem::getStorage($path);
$owner=$storage->getOwner($path);
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path);
$owner=$storage->getOwner($internalPath);
if (!$owner) {
return -1;
}
$totalSpace=$this->getQuota($owner);
if($totalSpace==-1) {
return -1;
}
$rootInfo=OC_FileCache::get('', "/".$owner."/files");
// TODO Remove after merge of share_api
if (OC_FileCache::inCache('/Shared', "/".$owner."/files")) {
$sharedInfo=OC_FileCache::get('/Shared', "/".$owner."/files");
} else {
$sharedInfo = null;
}
$view = new \OC\Files\View("/".$owner."/files");
$rootInfo=$view->getFileInfo('/');
$usedSpace=isset($rootInfo['size'])?$rootInfo['size']:0;
$usedSpace=isset($sharedInfo['size'])?$usedSpace-$sharedInfo['size']:$usedSpace;
return $totalSpace-$usedSpace;
}
@ -93,8 +95,8 @@ class OC_FileProxy_Quota extends OC_FileProxy{
}
public function preCopy($path1, $path2) {
if(!self::$rootView) {
self::$rootView = new OC_FilesystemView('');
if(!self::$rootView){
self::$rootView = new \OC\Files\View('');
}
return (self::$rootView->filesize($path1)<$this->getFreeSpace($path2) or $this->getFreeSpace($path2)==-1);
}

View File

@ -1,144 +1,48 @@
<?php
/**
* ownCloud
*
* @author Frank Karlitschek
* @copyright 2012 Frank Karlitschek frank@owncloud.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
* ownCloud
*
* @author Frank Karlitschek
* @copyright 2012 Frank Karlitschek frank@owncloud.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Class for fileserver access
*
*/
class OC_Files {
static $tmpFiles=array();
static $tmpFiles = array();
static public function getFileInfo($path){
return \OC\Files\Filesystem::getFileInfo($path);
}
static public function getDirectoryContent($path){
return \OC\Files\Filesystem::getDirectoryContent($path);
}
/**
* get the filesystem info
* @param string path
* @return array
* return the content of a file or return a zip file containing multiple files
*
* returns an associative array with the following keys:
* - size
* - mtime
* - ctime
* - mimetype
* - encrypted
* - versioned
* @param string $dir
* @param string $file ; separated list of files to download
* @param boolean $only_header ; boolean to only send header of the request
*/
public static function getFileInfo($path) {
$path = OC_Filesystem::normalizePath($path);
if (($path == '/Shared' || substr($path, 0, 8) == '/Shared/') && OC_App::isEnabled('files_sharing')) {
if ($path == '/Shared') {
list($info) = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
} else {
$info = array();
if (OC_Filesystem::file_exists($path)) {
$info['size'] = OC_Filesystem::filesize($path);
$info['mtime'] = OC_Filesystem::filemtime($path);
$info['ctime'] = OC_Filesystem::filectime($path);
$info['mimetype'] = OC_Filesystem::getMimeType($path);
$info['encrypted'] = false;
$info['versioned'] = false;
}
}
} else {
$info = OC_FileCache::get($path);
}
return $info;
}
/**
* get the content of a directory
* @param dir $directory path under datadirectory
*/
public static function getDirectoryContent($directory, $mimetype_filter = '') {
$directory=OC_Filesystem::normalizePath($directory);
if($directory=='/') {
$directory='';
}
$files = array();
if (($directory == '/Shared' || substr($directory, 0, 8) == '/Shared/') && OC_App::isEnabled('files_sharing')) {
if ($directory == '/Shared') {
$files = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP, array('folder' => $directory, 'mimetype_filter' => $mimetype_filter));
} else {
$pos = strpos($directory, '/', 8);
// Get shared folder name
if ($pos !== false) {
$itemTarget = substr($directory, 7, $pos - 7);
} else {
$itemTarget = substr($directory, 7);
}
$files = OCP\Share::getItemSharedWith('folder', $itemTarget, OC_Share_Backend_File::FORMAT_FILE_APP, array('folder' => $directory, 'mimetype_filter' => $mimetype_filter));
}
} else {
$files = OC_FileCache::getFolderContent($directory, false, $mimetype_filter);
foreach ($files as &$file) {
$file['directory'] = $directory;
$file['type'] = ($file['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file';
$permissions = OCP\PERMISSION_READ;
// NOTE: Remove check when new encryption is merged
if (!$file['encrypted']) {
$permissions |= OCP\PERMISSION_SHARE;
}
if ($file['type'] == 'dir' && $file['writable']) {
$permissions |= OCP\PERMISSION_CREATE;
}
if ($file['writable']) {
$permissions |= OCP\PERMISSION_UPDATE | OCP\PERMISSION_DELETE;
}
$file['permissions'] = $permissions;
}
if ($directory == '' && OC_App::isEnabled('files_sharing')) {
// Add 'Shared' folder
$files = array_merge($files, OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP_ROOT));
}
}
usort($files, "fileCmp");//TODO: remove this once ajax is merged
return $files;
}
public static function searchByMime($mimetype_filter) {
$files = array();
$dirs_to_check = array('');
while (!empty($dirs_to_check)) {
// get next subdir to check
$dir = array_pop($dirs_to_check);
$dir_content = self::getDirectoryContent($dir, $mimetype_filter);
foreach($dir_content as $file) {
if ($file['type'] == 'file') {
$files[] = $dir.'/'.$file['name'];
}
else {
$dirs_to_check[] = $dir.'/'.$file['name'];
}
}
}
return $files;
}
/**
* return the content of a file or return a zip file containning multiply files
*
* @param dir $dir
* @param file $file ; seperated list of files to download
* @param boolean $only_header ; boolean to only send header of the request
*/
public static function get($dir, $files, $only_header = false) {
$xsendfile = false;
if (isset($_SERVER['MOD_X_SENDFILE_ENABLED']) ||
@ -149,7 +53,7 @@ class OC_Files {
$files=explode(';', $files);
}
if(is_array($files)) {
if (is_array($files)) {
self::validateZipDownload($dir, $files);
$executionTime = intval(ini_get('max_execution_time'));
set_time_limit(0);
@ -162,19 +66,20 @@ class OC_Files {
if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) {
exit("cannot open <$filename>\n");
}
foreach($files as $file) {
$file=$dir.'/'.$file;
if(OC_Filesystem::is_file($file)) {
$tmpFile=OC_Filesystem::toTmpFile($file);
self::$tmpFiles[]=$tmpFile;
foreach ($files as $file) {
$file = $dir . '/' . $file;
if (\OC\Files\Filesystem::is_file($file)) {
$tmpFile = \OC\Files\Filesystem::toTmpFile($file);
self::$tmpFiles[] = $tmpFile;
$zip->addFile($tmpFile, basename($file));
}elseif(OC_Filesystem::is_dir($file)) {
} elseif (\OC\Files\Filesystem::is_dir($file)) {
self::zipAddDir($file, $zip);
}
}
$zip->close();
$name = basename($dir) . '.zip';
set_time_limit($executionTime);
}elseif(OC_Filesystem::is_dir($dir.'/'.$files)) {
} elseif (\OC\Files\Filesystem::is_dir($dir . '/' . $files)) {
self::validateZipDownload($dir, $files);
$executionTime = intval(ini_get('max_execution_time'));
set_time_limit(0);
@ -187,53 +92,55 @@ class OC_Files {
if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) {
exit("cannot open <$filename>\n");
}
$file=$dir.'/'.$files;
$file = $dir . '/' . $files;
self::zipAddDir($file, $zip);
$zip->close();
$name = $files . '.zip';
set_time_limit($executionTime);
}else{
$zip=false;
$filename=$dir.'/'.$files;
} else {
$zip = false;
$filename = $dir . '/' . $files;
$name = $files;
}
OC_Util::obEnd();
if($zip or OC_Filesystem::is_readable($filename)) {
if ($zip or \OC\Files\Filesystem::isReadable($filename)) {
if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) {
header( 'Content-Disposition: attachment; filename="' . rawurlencode( basename($filename) ) . '"' );
header( 'Content-Disposition: attachment; filename="' . rawurlencode($name) . '"' );
} else {
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode( basename($filename) )
. '; filename="' . rawurlencode( basename($filename) ) . '"' );
header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode($name)
. '; filename="' . rawurlencode($name) . '"' );
}
header('Content-Transfer-Encoding: binary');
OC_Response::disableCaching();
if($zip) {
if ($zip) {
ini_set('zlib.output_compression', 'off');
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($filename));
self::addSendfileHeader($filename);
}else{
header('Content-Type: '.OC_Filesystem::getMimeType($filename));
header("Content-Length: ".OC_Filesystem::filesize($filename));
$storage = OC_Filesystem::getStorage($filename);
if ($storage instanceof OC_Filestorage_Local) {
self::addSendfileHeader(OC_Filesystem::getLocalFile($filename));
header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename));
header("Content-Length: ".\OC\Files\Filesystem::filesize($filename));
list($storage) = \OC\Files\Filesystem::resolvePath($filename);
if ($storage instanceof \OC\File\Storage\Local) {
self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename));
}
}
}elseif($zip or !OC_Filesystem::file_exists($filename)) {
} elseif ($zip or !\OC\Files\Filesystem::file_exists($filename)) {
header("HTTP/1.0 404 Not Found");
$tmpl = new OC_Template( '', '404', 'guest' );
$tmpl->assign('file', $filename);
$tmpl = new OC_Template('', '404', 'guest');
$tmpl->assign('file', $name);
$tmpl->printPage();
}else{
} else {
header("HTTP/1.0 403 Forbidden");
die('403 Forbidden');
}
if($only_header) {
return ;
}
if($zip) {
$handle=fopen($filename, 'r');
if ($zip) {
$handle = fopen($filename, 'r');
if ($handle) {
$chunkSize = 8*1024;// 1 MB chunks
$chunkSize = 8 * 1024; // 1 MB chunks
while (!feof($handle)) {
echo fread($handle, $chunkSize);
flush();
@ -243,10 +150,10 @@ class OC_Files {
unlink($filename);
}
}else{
OC_Filesystem::readfile($filename);
\OC\Files\Filesystem::readfile($filename);
}
foreach(self::$tmpFiles as $tmpFile) {
if(file_exists($tmpFile) and is_file($tmpFile)) {
foreach (self::$tmpFiles as $tmpFile) {
if (file_exists($tmpFile) and is_file($tmpFile)) {
unlink($tmpFile);
}
}
@ -269,97 +176,27 @@ class OC_Files {
foreach($files as $file) {
$filename=$file['name'];
$file=$dir.'/'.$filename;
if(OC_Filesystem::is_file($file)) {
$tmpFile=OC_Filesystem::toTmpFile($file);
if(\OC\Files\Filesystem::is_file($file)) {
$tmpFile=\OC\Files\Filesystem::toTmpFile($file);
OC_Files::$tmpFiles[]=$tmpFile;
$zip->addFile($tmpFile, $internalDir.$filename);
}elseif(OC_Filesystem::is_dir($file)) {
}elseif(\OC\Files\Filesystem::is_dir($file)) {
self::zipAddDir($file, $zip, $internalDir);
}
}
}
/**
* move a file or folder
*
* @param dir $sourceDir
* @param file $source
* @param dir $targetDir
* @param file $target
*/
public static function move($sourceDir, $source, $targetDir, $target) {
if(OC_User::isLoggedIn() && ($sourceDir != '' || $source != 'Shared')) {
$targetFile=self::normalizePath($targetDir.'/'.$target);
$sourceFile=self::normalizePath($sourceDir.'/'.$source);
return OC_Filesystem::rename($sourceFile, $targetFile);
} else {
return false;
}
}
/**
* copy a file or folder
*
* @param dir $sourceDir
* @param file $source
* @param dir $targetDir
* @param file $target
*/
public static function copy($sourceDir, $source, $targetDir, $target) {
if(OC_User::isLoggedIn()) {
$targetFile=$targetDir.'/'.$target;
$sourceFile=$sourceDir.'/'.$source;
return OC_Filesystem::copy($sourceFile, $targetFile);
}
}
/**
* create a new file or folder
*
* @param dir $dir
* @param file $name
* @param type $type
*/
public static function newFile($dir, $name, $type) {
if(OC_User::isLoggedIn()) {
$file=$dir.'/'.$name;
if($type=='dir') {
return OC_Filesystem::mkdir($file);
}elseif($type=='file') {
$fileHandle=OC_Filesystem::fopen($file, 'w');
if($fileHandle) {
fclose($fileHandle);
return true;
}else{
return false;
}
}
}
}
/**
* deletes a file or folder
*
* @param dir $dir
* @param file $name
*/
public static function delete($dir, $file) {
if(OC_User::isLoggedIn() && ($dir!= '' || $file != 'Shared')) {
$file=$dir.'/'.$file;
return OC_Filesystem::unlink($file);
}
}
/**
* checks if the selected files are within the size constraint. If not, outputs an error page.
*
* @param dir $dir
* @param files $files
*/
* checks if the selected files are within the size constraint. If not, outputs an error page.
*
* @param dir $dir
* @param files $files
*/
static function validateZipDownload($dir, $files) {
if(!OC_Config::getValue('allowZipDownload', true)) {
if (!OC_Config::getValue('allowZipDownload', true)) {
$l = OC_L10N::get('lib');
header("HTTP/1.0 409 Conflict");
$tmpl = new OC_Template( '', 'error', 'user' );
$tmpl = new OC_Template('', 'error', 'user');
$errors = array(
array(
'error' => $l->t('ZIP download is turned off.'),
@ -372,19 +209,19 @@ class OC_Files {
}
$zipLimit = OC_Config::getValue('maxZipInputSize', OC_Helper::computerFileSize('800 MB'));
if($zipLimit > 0) {
if ($zipLimit > 0) {
$totalsize = 0;
if(is_array($files)) {
foreach($files as $file) {
$totalsize += OC_Filesystem::filesize($dir.'/'.$file);
if (is_array($files)) {
foreach ($files as $file) {
$totalsize += \OC\Files\Filesystem::filesize($dir . '/' . $file);
}
}else{
$totalsize += OC_Filesystem::filesize($dir.'/'.$files);
} else {
$totalsize += \OC\Files\Filesystem::filesize($dir . '/' . $files);
}
if($totalsize > $zipLimit) {
if ($totalsize > $zipLimit) {
$l = OC_L10N::get('lib');
header("HTTP/1.0 409 Conflict");
$tmpl = new OC_Template( '', 'error', 'user' );
$tmpl = new OC_Template('', 'error', 'user');
$errors = array(
array(
'error' => $l->t('Selected files too large to generate zip file.'),
@ -398,79 +235,32 @@ class OC_Files {
}
}
/**
* try to detect the mime type of a file
*
* @param string path
* @return string guessed mime type
*/
static function getMimeType($path) {
return OC_Filesystem::getMimeType($path);
}
/**
* get a file tree
*
* @param string path
* @return array
*/
static function getTree($path) {
return OC_Filesystem::getTree($path);
}
/**
* pull a file from a remote server
* @param string source
* @param string token
* @param string dir
* @param string file
* @return string guessed mime type
*/
static function pull($source, $token, $dir, $file) {
$tmpfile=tempnam(get_temp_dir(), 'remoteCloudFile');
$fp=fopen($tmpfile, 'w+');
$url=$source.="/files/pull.php?token=$token";
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec($ch);
fclose($fp);
$info=curl_getinfo($ch);
$httpCode=$info['http_code'];
curl_close($ch);
if($httpCode==200 or $httpCode==0) {
OC_Filesystem::fromTmpFile($tmpfile, $dir.'/'.$file);
return true;
}else{
return false;
}
}
/**
* set the maximum upload size limit for apache hosts using .htaccess
*
* @param int size filesisze in bytes
* @return false on failure, size on success
*/
static function setUploadLimit($size) {
//don't allow user to break his config -- upper boundary
if($size > PHP_INT_MAX) {
if ($size > PHP_INT_MAX) {
//max size is always 1 byte lower than computerFileSize returns
if($size > PHP_INT_MAX+1)
if ($size > PHP_INT_MAX + 1)
return false;
$size -=1;
$size -= 1;
} else {
$size=OC_Helper::humanFileSize($size);
$size=substr($size, 0, -1);//strip the B
$size=str_replace(' ', '', $size); //remove the space between the size and the postfix
$size = OC_Helper::humanFileSize($size);
$size = substr($size, 0, -1); //strip the B
$size = str_replace(' ', '', $size); //remove the space between the size and the postfix
}
//don't allow user to break his config -- broken or malicious size input
if(intval($size) == 0) {
if (intval($size) == 0) {
return false;
}
$htaccess = @file_get_contents(OC::$SERVERROOT.'/.htaccess'); //supress errors in case we don't have permissions for
if(!$htaccess) {
$htaccess = @file_get_contents(OC::$SERVERROOT . '/.htaccess'); //supress errors in case we don't have permissions for
if (!$htaccess) {
return false;
}
@ -479,52 +269,26 @@ class OC_Files {
'post_max_size'
);
foreach($phpValueKeys as $key) {
$pattern = '/php_value '.$key.' (\S)*/';
$setting = 'php_value '.$key.' '.$size;
$hasReplaced = 0;
$content = preg_replace($pattern, $setting, $htaccess, 1, $hasReplaced);
if($content !== null) {
foreach ($phpValueKeys as $key) {
$pattern = '/php_value ' . $key . ' (\S)*/';
$setting = 'php_value ' . $key . ' ' . $size;
$hasReplaced = 0;
$content = preg_replace($pattern, $setting, $htaccess, 1, $hasReplaced);
if ($content !== null) {
$htaccess = $content;
}
if($hasReplaced == 0) {
if ($hasReplaced == 0) {
$htaccess .= "\n" . $setting;
}
}
//check for write permissions
if(is_writable(OC::$SERVERROOT.'/.htaccess')) {
file_put_contents(OC::$SERVERROOT.'/.htaccess', $htaccess);
if (is_writable(OC::$SERVERROOT . '/.htaccess')) {
file_put_contents(OC::$SERVERROOT . '/.htaccess', $htaccess);
return OC_Helper::computerFileSize($size);
} else {
OC_Log::write('files', 'Can\'t write upload limit to '.OC::$SERVERROOT.'/.htaccess. Please check the file permissions', OC_Log::WARN);
OC_Log::write('files', 'Can\'t write upload limit to ' . OC::$SERVERROOT . '/.htaccess. Please check the file permissions', OC_Log::WARN);
}
return false;
}
/**
* normalize a path, removing any double, add leading /, etc
* @param string $path
* @return string
*/
static public function normalizePath($path) {
$path='/'.$path;
$old='';
while($old!=$path) {//replace any multiplicity of slashes with a single one
$old=$path;
$path=str_replace('//', '/', $path);
}
return $path;
}
}
function fileCmp($a, $b) {
if($a['type']=='dir' and $b['type']!='dir') {
return -1;
}elseif($a['type']!='dir' and $b['type']=='dir') {
return 1;
}else{
return strnatcasecmp($a['name'], $b['name']);
}
}

521
lib/files/cache/cache.php vendored Normal file
View File

@ -0,0 +1,521 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Cache;
/**
* Metadata cache for the filesystem
*
* don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead
*/
class Cache {
const NOT_FOUND = 0;
const PARTIAL = 1; //only partial data available, file not cached in the database
const SHALLOW = 2; //folder in cache, but not all child files are completely scanned
const COMPLETE = 3;
/**
* @var array partial data for the cache
*/
private $partial = array();
/**
* @var string
*/
private $storageId;
/**
* numeric storage id
*
* @var int $numericId
*/
private $numericId;
private $mimetypeIds = array();
private $mimetypes = array();
/**
* @param \OC\Files\Storage\Storage|string $storage
*/
public function __construct($storage) {
if ($storage instanceof \OC\Files\Storage\Storage) {
$this->storageId = $storage->getId();
} else {
$this->storageId = $storage;
}
$query = \OC_DB::prepare('SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?');
$result = $query->execute(array($this->storageId));
if ($row = $result->fetchRow()) {
$this->numericId = $row['numeric_id'];
} else {
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*storages`(`id`) VALUES(?)');
$query->execute(array($this->storageId));
$this->numericId = \OC_DB::insertid('*PREFIX*filecache');
}
}
public function getNumericStorageId() {
return $this->numericId;
}
/**
* normalize mimetypes
*
* @param string $mime
* @return int
*/
public function getMimetypeId($mime) {
if (!isset($this->mimetypeIds[$mime])) {
$query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?');
$result = $query->execute(array($mime));
if ($row = $result->fetchRow()) {
$this->mimetypeIds[$mime] = $row['id'];
} else {
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)');
$query->execute(array($mime));
$this->mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes');
}
$this->mimetypes[$this->mimetypeIds[$mime]] = $mime;
}
return $this->mimetypeIds[$mime];
}
public function getMimetype($id) {
if (!isset($this->mimetypes[$id])) {
$query = \OC_DB::prepare('SELECT `mimetype` FROM `*PREFIX*mimetypes` WHERE `id` = ?');
$result = $query->execute(array($id));
if ($row = $result->fetchRow()) {
$this->mimetypes[$id] = $row['mimetype'];
} else {
return null;
}
}
return $this->mimetypes[$id];
}
/**
* get the stored metadata of a file or folder
*
* @param string/int $file
* @return array
*/
public function get($file) {
if (is_string($file) or $file == '') {
$where = 'WHERE `storage` = ? AND `path_hash` = ?';
$params = array($this->numericId, md5($file));
} else { //file id
$where = 'WHERE `fileid` = ?';
$params = array($file);
}
$query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
FROM `*PREFIX*filecache` ' . $where);
$result = $query->execute($params);
$data = $result->fetchRow();
//merge partial data
if (!$data and is_string($file)) {
if (isset($this->partial[$file])) {
$data = $this->partial[$file];
}
} else {
//fix types
$data['fileid'] = (int)$data['fileid'];
$data['size'] = (int)$data['size'];
$data['mtime'] = (int)$data['mtime'];
$data['encrypted'] = (bool)$data['encrypted'];
$data['storage'] = $this->storageId;
$data['mimetype'] = $this->getMimetype($data['mimetype']);
$data['mimepart'] = $this->getMimetype($data['mimepart']);
}
return $data;
}
/**
* get the metadata of all files stored in $folder
*
* @param string $folder
* @return array
*/
public function getFolderContents($folder) {
$fileId = $this->getId($folder);
if ($fileId > -1) {
$query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC');
$result = $query->execute(array($fileId));
$files = $result->fetchAll();
foreach ($files as &$file) {
$file['mimetype'] = $this->getMimetype($file['mimetype']);
$file['mimepart'] = $this->getMimetype($file['mimepart']);
}
return $files;
} else {
return array();
}
}
/**
* store meta data for a file or folder
*
* @param string $file
* @param array $data
*
* @return int file id
*/
public function put($file, array $data) {
if (($id = $this->getId($file)) > -1) {
$this->update($id, $data);
return $id;
} else {
if (isset($this->partial[$file])) { //add any saved partial data
$data = array_merge($this->partial[$file], $data);
unset($this->partial[$file]);
}
$requiredFields = array('size', 'mtime', 'mimetype');
foreach ($requiredFields as $field) {
if (!isset($data[$field])) { //data not complete save as partial and return
$this->partial[$file] = $data;
return -1;
}
}
$data['path'] = $file;
$data['parent'] = $this->getParentId($file);
$data['name'] = basename($file);
$data['encrypted'] = isset($data['encrypted']) ? ((int)$data['encrypted']) : 0;
list($queryParts, $params) = $this->buildParts($data);
$queryParts[] = '`storage`';
$params[] = $this->numericId;
$valuesPlaceholder = array_fill(0, count($queryParts), '?');
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ') VALUES(' . implode(', ', $valuesPlaceholder) . ')');
$query->execute($params);
return (int)\OC_DB::insertid('*PREFIX*filecache');
}
}
/**
* update the metadata in the cache
*
* @param int $id
* @param array $data
*/
public function update($id, array $data) {
list($queryParts, $params) = $this->buildParts($data);
$params[] = $id;
$query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? WHERE fileid = ?');
$query->execute($params);
}
/**
* extract query parts and params array from data array
*
* @param array $data
* @return array
*/
function buildParts(array $data) {
$fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag');
$params = array();
$queryParts = array();
foreach ($data as $name => $value) {
if (array_search($name, $fields) !== false) {
if ($name === 'path') {
$params[] = md5($value);
$queryParts[] = '`path_hash`';
} elseif ($name === 'mimetype') {
$params[] = $this->getMimetypeId(substr($value, 0, strpos($value, '/')));
$queryParts[] = '`mimepart`';
$value = $this->getMimetypeId($value);
}
$params[] = $value;
$queryParts[] = '`' . $name . '`';
}
}
return array($queryParts, $params);
}
/**
* get the file id for a file
*
* @param string $file
* @return int
*/
public function getId($file) {
$pathHash = md5($file);
$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?');
$result = $query->execute(array($this->numericId, $pathHash));
if ($row = $result->fetchRow()) {
return $row['fileid'];
} else {
return -1;
}
}
/**
* get the id of the parent folder of a file
*
* @param string $file
* @return int
*/
public function getParentId($file) {
if ($file === '') {
return -1;
} else {
$parent = dirname($file);
if ($parent === '.') {
$parent = '';
}
return $this->getId($parent);
}
}
/**
* check if a file is available in the cache
*
* @param string $file
* @return bool
*/
public function inCache($file) {
return $this->getId($file) != -1;
}
/**
* remove a file or folder from the cache
*
* @param string $file
*/
public function remove($file) {
$entry = $this->get($file);
if ($entry['mimetype'] === 'httpd/unix-directory') {
$children = $this->getFolderContents($file);
foreach ($children as $child) {
$this->remove($child['path']);
}
}
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?');
$query->execute(array($entry['fileid']));
}
/**
* Move a file or folder in the cache
*
* @param string $source
* @param string $target
*/
public function move($source, $target) {
$sourceId = $this->getId($source);
$newParentId = $this->getParentId($target);
//find all child entries
$query = \OC_DB::prepare('SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `path` LIKE ?');
$result = $query->execute(array($source . '/%'));
$childEntries = $result->fetchAll();
$sourceLength = strlen($source);
$query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
foreach ($childEntries as $child) {
$targetPath = $target . substr($child['path'], $sourceLength);
$query->execute(array($targetPath, md5($targetPath), $child['fileid']));
}
$query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ?, `parent` =? WHERE `fileid` = ?');
$query->execute(array($target, md5($target), $newParentId, $sourceId));
}
/**
* remove all entries for files that are stored on the storage from the cache
*/
public function clear() {
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage = ?');
$query->execute(array($this->numericId));
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*storages` WHERE id = ?');
$query->execute(array($this->storageId));
}
/**
* @param string $file
*
* @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
*/
public function getStatus($file) {
$pathHash = md5($file);
$query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?');
$result = $query->execute(array($this->numericId, $pathHash));
if ($row = $result->fetchRow()) {
if ((int)$row['size'] === -1) {
return self::SHALLOW;
} else {
return self::COMPLETE;
}
} else {
if (isset($this->partial[$file])) {
return self::PARTIAL;
} else {
return self::NOT_FOUND;
}
}
}
/**
* search for files matching $pattern
*
* @param string $pattern
* @return array of file data
*/
public function search($pattern) {
$query = \OC_DB::prepare('
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?'
);
$result = $query->execute(array($pattern, $this->numericId));
$files = array();
while ($row = $result->fetchRow()) {
$row['mimetype'] = $this->getMimetype($row['mimetype']);
$row['mimepart'] = $this->getMimetype($row['mimepart']);
$files[] = $row;
}
return $files;
}
/**
* search for files by mimetype
*
* @param string $mimetype
* @return array
*/
public function searchByMime($mimetype) {
if (strpos($mimetype, '/')) {
$where = '`mimetype` = ?';
} else {
$where = '`mimepart` = ?';
}
$query = \OC_DB::prepare('
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`
FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?'
);
$mimetype = $this->getMimetypeId($mimetype);
$result = $query->execute(array($mimetype, $this->numericId));
return $result->fetchAll();
}
/**
* update the folder size and the size of all parent folders
*
* @param $path
*/
public function correctFolderSize($path) {
$this->calculateFolderSize($path);
if ($path !== '') {
$parent = dirname($path);
if ($parent === '.') {
$parent = '';
}
$this->correctFolderSize($parent);
}
}
/**
* get the size of a folder and set it in the cache
*
* @param string $path
* @return int
*/
public function calculateFolderSize($path) {
$id = $this->getId($path);
if ($id === -1) {
return 0;
}
$query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?');
$result = $query->execute(array($id, $this->numericId));
$totalSize = 0;
$hasChilds = 0;
while ($row = $result->fetchRow()) {
$hasChilds = true;
$size = (int)$row['size'];
if ($size === -1) {
$totalSize = -1;
break;
} else {
$totalSize += $size;
}
}
if ($hasChilds) {
$this->update($id, array('size' => $totalSize));
}
return $totalSize;
}
/**
* get all file ids on the files on the storage
*
* @return int[]
*/
public function getAll() {
$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?');
$result = $query->execute(array($this->numericId));
$ids = array();
while ($row = $result->fetchRow()) {
$ids[] = $row['fileid'];
}
return $ids;
}
/**
* find a folder in the cache which has not been fully scanned
*
* If multiply incomplete folders are in the cache, the one with the highest id will be returned,
* use the one with the highest id gives the best result with the background scanner, since that is most
* likely the folder where we stopped scanning previously
*
* @return string|bool the path of the folder or false when no folder matched
*/
public function getIncomplete() {
$query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1');
$query->execute(array($this->numericId));
if ($row = $query->fetchRow()) {
return $row['path'];
} else {
return false;
}
}
/**
* get the storage id of the storage for a file and the internal path of the file
*
* @return array, first element holding the storage id, second the path
*/
static public function getById($id) {
$query = \OC_DB::prepare('SELECT `storage`, `path` FROM `*PREFIX*filecache` WHERE `fileid` = ?');
$result = $query->execute(array($id));
if ($row = $result->fetchRow()) {
$numericId = $row['storage'];
$path = $row['path'];
} else {
return null;
}
$query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?');
$result = $query->execute(array($numericId));
if ($row = $result->fetchRow()) {
return array($row['id'], $path);
} else {
return null;
}
}
}

81
lib/files/cache/legacy.php vendored Normal file
View File

@ -0,0 +1,81 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Cache;
/**
* Provide read only support for the old filecache
*/
class Legacy {
private $user;
private $cacheHasItems = null;
public function __construct($user) {
$this->user = $user;
}
function getCount() {
$query = \OC_DB::prepare('SELECT COUNT(`id`) AS `count` FROM `*PREFIX*fscache` WHERE `user` = ?');
$result = $query->execute(array($this->user));
if ($row = $result->fetchRow()) {
return $row['count'];
} else {
return 0;
}
}
/**
* check if a legacy cache is present and holds items
*
* @return bool
*/
function hasItems() {
if (!is_null($this->cacheHasItems)) {
return $this->cacheHasItems;
}
try {
$query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*fscache` WHERE `user` = ? LIMIT 1');
} catch (\Exception $e) {
$this->cacheHasItems = false;
return false;
}
try {
$result = $query->execute(array($this->user));
} catch (\Exception $e) {
$this->cacheHasItems = false;
return false;
}
$this->cacheHasItems = (bool)$result->fetchRow();
return $this->cacheHasItems;
}
/**
* @param string|int $path
* @return array
*/
function get($path) {
if (is_numeric($path)) {
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `id` = ?');
} else {
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `path` = ?');
}
$result = $query->execute(array($path));
return $result->fetchRow();
}
/**
* @param int $id
* @return array
*/
function getChildren($id) {
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `parent` = ?');
$result = $query->execute(array($id));
return $result->fetchAll();
}
}

102
lib/files/cache/permissions.php vendored Normal file
View File

@ -0,0 +1,102 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Cache;
class Permissions {
/**
* @var string $storageId
*/
private $storageId;
/**
* @param \OC\Files\Storage\Storage|string $storage
*/
public function __construct($storage){
if($storage instanceof \OC\Files\Storage\Storage){
$this->storageId = $storage->getId();
}else{
$this->storageId = $storage;
}
}
/**
* get the permissions for a single file
*
* @param int $fileId
* @param string $user
* @return int (-1 if file no permissions set)
*/
public function get($fileId, $user) {
$query = \OC_DB::prepare('SELECT `permissions` FROM `*PREFIX*permissions` WHERE `user` = ? AND `fileid` = ?');
$result = $query->execute(array($user, $fileId));
if ($row = $result->fetchRow()) {
return $row['permissions'];
} else {
return -1;
}
}
/**
* set the permissions of a file
*
* @param int $fileId
* @param string $user
* @param int $permissions
*/
public function set($fileId, $user, $permissions) {
if (self::get($fileId, $user) !== -1) {
$query = \OC_DB::prepare('UPDATE `*PREFIX*permissions` SET `permissions` = ? WHERE `user` = ? AND `fileid` = ?');
} else {
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*permissions`(`permissions`, `user`, `fileid`) VALUES(?, ?,? )');
}
$query->execute(array($permissions, $user, $fileId));
}
/**
* get the permissions of multiply files
*
* @param int[] $fileIds
* @param string $user
* @return int[]
*/
public function getMultiple($fileIds, $user) {
if (count($fileIds) === 0) {
return array();
}
$params = $fileIds;
$params[] = $user;
$inPart = implode(', ', array_fill(0, count($fileIds), '?'));
$query = \OC_DB::prepare('SELECT `fileid`, `permissions` FROM `*PREFIX*permissions` WHERE `fileid` IN (' . $inPart . ') AND `user` = ?');
$result = $query->execute($params);
$filePermissions = array();
while ($row = $result->fetchRow()) {
$filePermissions[$row['fileid']] = $row['permissions'];
}
return $filePermissions;
}
/**
* remove the permissions for a file
*
* @param int $fileId
* @param string $user
*/
public function remove($fileId, $user) {
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?');
$query->execute(array($fileId, $user));
}
public function removeMultiple($fileIds, $user) {
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?');
foreach($fileIds as $fileId){
$query->execute(array($fileId, $user));
}
}
}

146
lib/files/cache/scanner.php vendored Normal file
View File

@ -0,0 +1,146 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Cache;
class Scanner {
/**
* @var \OC\Files\Storage\Storage $storage
*/
private $storage;
/**
* @var string $storageId
*/
private $storageId;
/**
* @var \OC\Files\Cache\Cache $cache
*/
private $cache;
const SCAN_RECURSIVE = true;
const SCAN_SHALLOW = false;
public function __construct(\OC\Files\Storage\Storage $storage) {
$this->storage = $storage;
$this->storageId = $this->storage->getId();
$this->cache = $storage->getCache();
}
/**
* get all the metadata of a file or folder
* *
*
* @param string $path
* @return array with metadata of the file
*/
public function getData($path) {
$data = array();
if (!$this->storage->isReadable($path)) return null; //cant read, nothing we can do
$data['mimetype'] = $this->storage->getMimeType($path);
$data['mtime'] = $this->storage->filemtime($path);
if ($data['mimetype'] == 'httpd/unix-directory') {
$data['size'] = -1; //unknown
} else {
$data['size'] = $this->storage->filesize($path);
}
$data['etag'] = $this->storage->getETag($path);
return $data;
}
/**
* scan a single file and store it in the cache
*
* @param string $file
* @return array with metadata of the scanned file
*/
public function scanFile($file) {
\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
$data = $this->getData($file);
if ($data) {
if ($file) {
$parent = dirname($file);
if ($parent === '.') {
$parent = '';
}
if (!$this->cache->inCache($parent)) {
$this->scanFile($parent);
}
}
$id = $this->cache->put($file, $data);
}
return $data;
}
/**
* scan all the files in a folder and store them in the cache
*
* @param string $path
* @param SCAN_RECURSIVE/SCAN_SHALLOW $recursive
* @param bool $onlyChilds
* @return int the size of the scanned folder or -1 if the size is unknown at this stage
*/
public function scan($path, $recursive = self::SCAN_RECURSIVE, $onlyChilds = false) {
\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_folder', array('path' => $path, 'storage' => $this->storageId));
$childQueue = array();
if (!$onlyChilds) {
$this->scanFile($path);
}
$size = 0;
if ($dh = $this->storage->opendir($path)) {
\OC_DB::beginTransaction();
while ($file = readdir($dh)) {
if ($file !== '.' and $file !== '..') {
$child = ($path) ? $path . '/' . $file : $file;
$data = $this->scanFile($child);
if ($data) {
if ($data['mimetype'] === 'httpd/unix-directory') {
if ($recursive === self::SCAN_RECURSIVE) {
$childQueue[] = $child;
$data['size'] = 0;
} else {
$data['size'] = -1;
}
} else {
}
if ($data['size'] === -1) {
$size = -1;
} elseif ($size !== -1) {
$size += $data['size'];
}
}
}
}
\OC_DB::commit();
foreach ($childQueue as $child) {
$childSize = $this->scan($child, self::SCAN_RECURSIVE, true);
if ($childSize === -1) {
$size = -1;
} else {
$size += $childSize;
}
}
if ($size !== -1) {
$this->cache->put($path, array('size' => $size));
}
}
return $size;
}
/**
* walk over any folders that are not fully scanned yet and scan them
*/
public function backgroundScan() {
while ($path = $this->cache->getIncomplete()) {
$this->scan($path);
$this->cache->correctFolderSize($path);
}
}
}

105
lib/files/cache/updater.php vendored Normal file
View File

@ -0,0 +1,105 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Cache;
/**
* listen to filesystem hooks and change the cache accordingly
*/
class Updater {
/**
* resolve a path to a storage and internal path
*
* @param string $path
* @return array consisting of the storage and the internal path
*/
static public function resolvePath($path) {
$view = \OC\Files\Filesystem::getView();
return $view->resolvePath($path);
}
static public function writeUpdate($path) {
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = self::resolvePath($path);
if ($storage) {
$cache = $storage->getCache($internalPath);
$scanner = $storage->getScanner($internalPath);
$scanner->scan($internalPath, Scanner::SCAN_SHALLOW);
$cache->correctFolderSize($internalPath);
self::correctFolder($path, $storage->filemtime($internalPath));
}
}
static public function deleteUpdate($path) {
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = self::resolvePath($path);
if ($storage) {
$cache = $storage->getCache($internalPath);
$cache->remove($internalPath);
$cache->correctFolderSize($internalPath);
self::correctFolder($path, time());
}
}
/**
* Update the mtime and ETag of all parent folders
*
* @param string $path
* @param string $time
*/
static public function correctFolder($path, $time) {
if ($path !== '' && $path !== '/') {
$parent = dirname($path);
if ($parent === '.') {
$parent = '';
}
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = self::resolvePath($parent);
if ($storage) {
$cache = $storage->getCache();
$id = $cache->getId($internalPath);
if ($id !== -1) {
$cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath)));
self::correctFolder($parent, $time);
}
}
}
}
/**
* @param array $params
*/
static public function writeHook($params) {
self::writeUpdate($params['path']);
}
/**
* @param array $params
*/
static public function renameHook($params) {
self::deleteUpdate($params['oldpath']);
self::writeUpdate($params['newpath']);
}
/**
* @param array $params
*/
static public function deleteHook($params) {
self::deleteUpdate($params['path']);
}
}

159
lib/files/cache/upgrade.php vendored Normal file
View File

@ -0,0 +1,159 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Cache;
class Upgrade {
/**
* @var Legacy $legacy
*/
private $legacy;
private $numericIds = array();
private $mimeTypeIds = array();
/**
* @param Legacy $legacy
*/
public function __construct($legacy) {
$this->legacy = $legacy;
}
/**
* Preform a shallow upgrade
*
* @param string $path
* @param int $mode
*/
function upgradePath($path, $mode = Scanner::SCAN_RECURSIVE) {
if (!$this->legacy->hasItems()) {
return;
}
\OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path);
if ($row = $this->legacy->get($path)) {
$data = $this->getNewData($row);
$this->insert($data);
$this->upgradeChilds($data['id'], $mode);
}
}
/**
* @param int $id
*/
function upgradeChilds($id, $mode = Scanner::SCAN_RECURSIVE) {
$children = $this->legacy->getChildren($id);
foreach ($children as $child) {
$childData = $this->getNewData($child);
\OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']);
$this->insert($childData);
if ($mode == Scanner::SCAN_RECURSIVE) {
$this->upgradeChilds($child['id']);
}
}
}
/**
* @param array $data the data for the new cache
*/
function insert($data) {
if (!$this->inCache($data['storage'], $data['path_hash'])) {
$insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`
( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` )
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
$insertQuery->execute(array($data['id'], $data['storage'], $data['path'], $data['path_hash'], $data['parent'], $data['name'],
$data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted']));
}
}
/**
* @param string $storage
* @param string $pathHash
* @return bool
*/
function inCache($storage, $pathHash) {
$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?');
$result = $query->execute(array($storage, $pathHash));
return (bool)$result->fetchRow();
}
/**
* get the new data array from the old one
*
* @param array $data the data from the old cache
* @return array
*/
function getNewData($data) {
$newData = $data;
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($data['path']);
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath;
*/
$newData['path_hash'] = md5($internalPath);
$newData['path'] = $internalPath;
$newData['storage'] = $this->getNumericId($storage);
$newData['parent'] = ($internalPath === '') ? -1 : $data['parent'];
$newData['permissions'] = ($data['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ;
$newData['storage_object'] = $storage;
$newData['mimetype'] = $this->getMimetypeId($newData['mimetype'], $storage);
$newData['mimepart'] = $this->getMimetypeId($newData['mimepart'], $storage);
return $newData;
}
/**
* get the numeric storage id
*
* @param \OC\Files\Storage\Storage $storage
* @return int
*/
function getNumericId($storage) {
$storageId = $storage->getId();
if (!isset($this->numericIds[$storageId])) {
$cache = $storage->getCache();
$this->numericIds[$storageId] = $cache->getNumericStorageId();
}
return $this->numericIds[$storageId];
}
/**
* @param string $mimetype
* @param \OC\Files\Storage\Storage $storage
* @return int
*/
function getMimetypeId($mimetype, $storage) {
if (!isset($this->mimeTypeIds[$mimetype])) {
$cache = new Cache($storage);
$this->mimeTypeIds[$mimetype] = $cache->getMimetypeId($mimetype);
}
return $this->mimeTypeIds[$mimetype];
}
/**
* check if a cache upgrade is required for $user
*
* @param string $user
* @return bool
*/
static function needUpgrade($user) {
$cacheVersion = (int)\OCP\Config::getUserValue($user, 'files', 'cache_version', 4);
return $cacheVersion < 5;
}
/**
* mark the filecache as upgrade
*
* @param string $user
*/
static function upgradeDone($user) {
\OCP\Config::setUserValue($user, 'files', 'cache_version', 5);
}
}

72
lib/files/cache/watcher.php vendored Normal file
View File

@ -0,0 +1,72 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Cache;
/**
* check the storage backends for updates and change the cache accordingly
*/
class Watcher {
/**
* @var \OC\Files\Storage\Storage $storage
*/
private $storage;
/**
* @var Cache $cache
*/
private $cache;
/**
* @var Scanner $scanner;
*/
private $scanner;
/**
* @param \OC\Files\Storage\Storage $storage
*/
public function __construct(\OC\Files\Storage\Storage $storage) {
$this->storage = $storage;
$this->cache = $storage->getCache();
$this->scanner = $storage->getScanner();
}
/**
* check $path for updates
*
* @param string $path
*/
public function checkUpdate($path) {
$cachedEntry = $this->cache->get($path);
if ($this->storage->hasUpdated($path, $cachedEntry['mtime'])) {
if ($this->storage->is_dir($path)) {
$this->scanner->scan($path, Scanner::SCAN_SHALLOW);
} else {
$this->scanner->scanFile($path);
}
if ($cachedEntry['mimetype'] === 'httpd/unix-directory') {
$this->cleanFolder($path);
}
$this->cache->correctFolderSize($path);
}
}
/**
* remove deleted files in $path from the cache
*
* @param string $path
*/
public function cleanFolder($path) {
$cachedContent = $this->cache->getFolderContents($path);
foreach ($cachedContent as $entry) {
if (!$this->storage->file_exists($entry['path'])) {
$this->cache->remove($entry['path']);
}
}
}
}

628
lib/files/filesystem.php Normal file
View File

@ -0,0 +1,628 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
/**
* Class for abstraction of filesystem functions
* This class won't call any filesystem functions for itself but but will pass them to the correct OC_Filestorage object
* this class should also handle all the file permission related stuff
*
* Hooks provided:
* read(path)
* write(path, &run)
* post_write(path)
* create(path, &run) (when a file is created, both create and write will be emitted in that order)
* post_create(path)
* delete(path, &run)
* post_delete(path)
* rename(oldpath,newpath, &run)
* post_rename(oldpath,newpath)
* copy(oldpath,newpath, &run) (if the newpath doesn't exists yes, copy, create and write will be emitted in that order)
* post_rename(oldpath,newpath)
*
* the &run parameter can be set to false to prevent the operation from occurring
*/
namespace OC\Files;
class Filesystem {
public static $loaded = false;
/**
* @var \OC\Files\View $defaultInstance
*/
static private $defaultInstance;
/**
* classname which used for hooks handling
* used as signalclass in OC_Hooks::emit()
*/
const CLASSNAME = 'OC_Filesystem';
/**
* signalname emitted before file renaming
*
* @param string $oldpath
* @param string $newpath
*/
const signal_rename = 'rename';
/**
* signal emitted after file renaming
*
* @param string $oldpath
* @param string $newpath
*/
const signal_post_rename = 'post_rename';
/**
* signal emitted before file/dir creation
*
* @param string $path
* @param bool $run changing this flag to false in hook handler will cancel event
*/
const signal_create = 'create';
/**
* signal emitted after file/dir creation
*
* @param string $path
* @param bool $run changing this flag to false in hook handler will cancel event
*/
const signal_post_create = 'post_create';
/**
* signal emits before file/dir copy
*
* @param string $oldpath
* @param string $newpath
* @param bool $run changing this flag to false in hook handler will cancel event
*/
const signal_copy = 'copy';
/**
* signal emits after file/dir copy
*
* @param string $oldpath
* @param string $newpath
*/
const signal_post_copy = 'post_copy';
/**
* signal emits before file/dir save
*
* @param string $path
* @param bool $run changing this flag to false in hook handler will cancel event
*/
const signal_write = 'write';
/**
* signal emits after file/dir save
*
* @param string $path
*/
const signal_post_write = 'post_write';
/**
* signal emits when reading file/dir
*
* @param string $path
*/
const signal_read = 'read';
/**
* signal emits when removing file/dir
*
* @param string $path
*/
const signal_delete = 'delete';
/**
* parameters definitions for signals
*/
const signal_param_path = 'path';
const signal_param_oldpath = 'oldpath';
const signal_param_newpath = 'newpath';
/**
* run - changing this flag to false in hook handler will cancel event
*/
const signal_param_run = 'run';
/**
* get the mountpoint of the storage object for a path
( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account
*
* @param string $path
* @return string
*/
static public function getMountPoint($path) {
$mount = Mount::find($path);
if ($mount) {
return $mount->getMountPoint();
} else {
return '';
}
}
/**
* get a list of all mount points in a directory
*
* @param string $path
* @return string[]
*/
static public function getMountPoints($path) {
$result = array();
$mounts = Mount::findIn($path);
foreach ($mounts as $mount) {
$result[] = $mount->getMountPoint();
}
return $result;
}
/**
* get the storage mounted at $mountPoint
*
* @param string $mountPoint
* @return \OC\Files\Storage\Storage
*/
public static function getStorage($mountPoint) {
$mount = Mount::find($mountPoint);
return $mount->getStorage();
}
/**
* resolve a path to a storage and internal path
*
* @param string $path
* @return array consisting of the storage and the internal path
*/
static public function resolvePath($path) {
$mount = Mount::find($path);
if ($mount) {
return array($mount->getStorage(), $mount->getInternalPath($path));
} else {
return array(null, null);
}
}
static public function init($root) {
if (self::$defaultInstance) {
return false;
}
self::$defaultInstance = new View($root);
//load custom mount config
self::initMountPoints();
self::$loaded = true;
return true;
}
/**
* Initialize system and personal mount points for a user
*
* @param string $user
*/
public static function initMountPoints($user = '') {
if ($user == '') {
$user = \OC_User::getUser();
}
// Load system mount points
if (is_file(\OC::$SERVERROOT . '/config/mount.php')) {
$mountConfig = include 'config/mount.php';
if (isset($mountConfig['global'])) {
foreach ($mountConfig['global'] as $mountPoint => $options) {
self::mount($options['class'], $options['options'], $mountPoint);
}
}
if (isset($mountConfig['group'])) {
foreach ($mountConfig['group'] as $group => $mounts) {
if (\OC_Group::inGroup($user, $group)) {
foreach ($mounts as $mountPoint => $options) {
$mountPoint = self::setUserVars($user, $mountPoint);
foreach ($options as &$option) {
$option = self::setUserVars($user, $option);
}
self::mount($options['class'], $options['options'], $mountPoint);
}
}
}
}
if (isset($mountConfig['user'])) {
foreach ($mountConfig['user'] as $mountUser => $mounts) {
if ($user === 'all' or strtolower($mountUser) === strtolower($user)) {
foreach ($mounts as $mountPoint => $options) {
$mountPoint = self::setUserVars($user, $mountPoint);
foreach ($options as &$option) {
$option = self::setUserVars($user, $option);
}
self::mount($options['class'], $options['options'], $mountPoint);
}
}
}
}
}
// Load personal mount points
$root = \OC_User::getHome($user);
self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user);
if (is_file($root . '/mount.php')) {
$mountConfig = include $root . '/mount.php';
if (isset($mountConfig['user'][$user])) {
foreach ($mountConfig['user'][$user] as $mountPoint => $options) {
self::mount($options['class'], $options['options'], $mountPoint);
}
}
}
}
/**
* fill in the correct values for $user, and $password placeholders
*
* @param string $input
* @param string $input
* @return string
*/
private static function setUserVars($user, $input) {
return str_replace('$user', $user, $input);
}
/**
* get the default filesystem view
*
* @return View
*/
static public function getView() {
return self::$defaultInstance;
}
/**
* tear down the filesystem, removing all storage providers
*/
static public function tearDown() {
self::clearMounts();
}
/**
* @brief get the relative path of the root data directory for the current user
* @return string
*
* Returns path like /admin/files
*/
static public function getRoot() {
return self::$defaultInstance->getRoot();
}
/**
* clear all mounts and storage backends
*/
public static function clearMounts() {
Mount::clear();
}
/**
* mount an \OC\Files\Storage\Storage in our virtual filesystem
*
* @param \OC\Files\Storage\Storage|string $class
* @param array $arguments
* @param string $mountpoint
*/
static public function mount($class, $arguments, $mountpoint) {
new Mount($class, $mountpoint, $arguments);
}
/**
* return the path to a local version of the file
* we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed
*
* @param string $path
* @return string
*/
static public function getLocalFile($path) {
return self::$defaultInstance->getLocalFile($path);
}
/**
* @param string $path
* @return string
*/
static public function getLocalFolder($path) {
return self::$defaultInstance->getLocalFolder($path);
}
/**
* return path to file which reflects one visible in browser
*
* @param string $path
* @return string
*/
static public function getLocalPath($path) {
$datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
$newpath = $path;
if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
$newpath = substr($path, strlen($datadir));
}
return $newpath;
}
/**
* check if the requested path is valid
*
* @param string $path
* @return bool
*/
static public function isValidPath($path) {
$path = self::normalizePath($path);
if (!$path || $path[0] !== '/') {
$path = '/' . $path;
}
if (strstr($path, '/../') || strrchr($path, '/') === '/..') {
return false;
}
return true;
}
/**
* checks if a file is blacklisted for storage in the filesystem
* Listens to write and rename hooks
*
* @param array $data from hook
*/
static public function isBlacklisted($data) {
$blacklist = array('.htaccess');
if (isset($data['path'])) {
$path = $data['path'];
} else if (isset($data['newpath'])) {
$path = $data['newpath'];
}
if (isset($path)) {
$filename = strtolower(basename($path));
if (in_array($filename, $blacklist)) {
$data['run'] = false;
}
}
}
/**
* following functions are equivalent to their php builtin equivalents for arguments/return values.
*/
static public function mkdir($path) {
return self::$defaultInstance->mkdir($path);
}
static public function rmdir($path) {
return self::$defaultInstance->rmdir($path);
}
static public function opendir($path) {
return self::$defaultInstance->opendir($path);
}
static public function readdir($path) {
return self::$defaultInstance->readdir($path);
}
static public function is_dir($path) {
return self::$defaultInstance->is_dir($path);
}
static public function is_file($path) {
return self::$defaultInstance->is_file($path);
}
static public function stat($path) {
return self::$defaultInstance->stat($path);
}
static public function filetype($path) {
return self::$defaultInstance->filetype($path);
}
static public function filesize($path) {
return self::$defaultInstance->filesize($path);
}
static public function readfile($path) {
return self::$defaultInstance->readfile($path);
}
static public function isCreatable($path) {
return self::$defaultInstance->isCreatable($path);
}
static public function isReadable($path) {
return self::$defaultInstance->isReadable($path);
}
static public function isUpdatable($path) {
return self::$defaultInstance->isUpdatable($path);
}
static public function isDeletable($path) {
return self::$defaultInstance->isDeletable($path);
}
static public function isSharable($path) {
return self::$defaultInstance->isSharable($path);
}
static public function file_exists($path) {
return self::$defaultInstance->file_exists($path);
}
static public function filemtime($path) {
return self::$defaultInstance->filemtime($path);
}
static public function touch($path, $mtime = null) {
return self::$defaultInstance->touch($path, $mtime);
}
static public function file_get_contents($path) {
return self::$defaultInstance->file_get_contents($path);
}
static public function file_put_contents($path, $data) {
return self::$defaultInstance->file_put_contents($path, $data);
}
static public function unlink($path) {
return self::$defaultInstance->unlink($path);
}
static public function rename($path1, $path2) {
return self::$defaultInstance->rename($path1, $path2);
}
static public function copy($path1, $path2) {
return self::$defaultInstance->copy($path1, $path2);
}
static public function fopen($path, $mode) {
return self::$defaultInstance->fopen($path, $mode);
}
static public function toTmpFile($path) {
return self::$defaultInstance->toTmpFile($path);
}
static public function fromTmpFile($tmpFile, $path) {
return self::$defaultInstance->fromTmpFile($tmpFile, $path);
}
static public function getMimeType($path) {
return self::$defaultInstance->getMimeType($path);
}
static public function hash($type, $path, $raw = false) {
return self::$defaultInstance->hash($type, $path, $raw);
}
static public function free_space($path = '/') {
return self::$defaultInstance->free_space($path);
}
static public function search($query) {
return self::$defaultInstance->search($query);
}
static public function searchByMime($query) {
return self::$defaultInstance->searchByMime($query);
}
/**
* check if a file or folder has been updated since $time
*
* @param string $path
* @param int $time
* @return bool
*/
static public function hasUpdated($path, $time) {
return self::$defaultInstance->hasUpdated($path, $time);
}
/**
* normalize a path
*
* @param string $path
* @param bool $stripTrailingSlash
* @return string
*/
public static function normalizePath($path, $stripTrailingSlash = true) {
if ($path == '') {
return '/';
}
//no windows style slashes
$path = str_replace('\\', '/', $path);
//add leading slash
if ($path[0] !== '/') {
$path = '/' . $path;
}
//remove duplicate slashes
while (strpos($path, '//') !== false) {
$path = str_replace('//', '/', $path);
}
//remove trailing slash
if ($stripTrailingSlash and strlen($path) > 1 and substr($path, -1, 1) === '/') {
$path = substr($path, 0, -1);
}
//normalize unicode if possible
if (class_exists('Normalizer')) {
$path = \Normalizer::normalize($path);
}
return $path;
}
/**
* get the filesystem info
*
* @param string $path
* @return array
*
* returns an associative array with the following keys:
* - size
* - mtime
* - mimetype
* - encrypted
* - versioned
*/
public static function getFileInfo($path) {
return self::$defaultInstance->getFileInfo($path);
}
/**
* change file metadata
*
* @param string $path
* @param array $data
* @return int
*
* returns the fileid of the updated file
*/
public static function putFileInfo($path, $data) {
return self::$defaultInstance->putFileInfo($path, $data);
}
/**
* get the content of a directory
*
* @param string $directory path under datadirectory
* @return array
*/
public static function getDirectoryContent($directory) {
return self::$defaultInstance->getDirectoryContent($directory);
}
/**
* Get the path of a file by id
*
* Note that the resulting path is not guarantied to be unique for the id, multiple paths can point to the same file
*
* @param int $id
* @return string
*/
public static function getPath($id) {
return self::$defaultInstance->getPath($id);
}
/**
* get the ETag for a file or folder
*
* @param string $path
* @return string
*/
static public function getETag($path) {
return self::$defaultInstance->getETag($path);
}
}
\OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Updater', 'writeHook');
\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Updater', 'deleteHook');
\OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Updater', 'renameHook');
\OC_Util::setupFS();

188
lib/files/mount.php Normal file
View File

@ -0,0 +1,188 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files;
class Mount {
/**
* @var Mount[]
*/
static private $mounts = array();
/**
* @var \OC\Files\Storage\Storage $storage
*/
private $storage = null;
private $class;
private $storageId;
private $arguments = array();
private $mountPoint;
/**
* @param string|\OC\Files\Storage\Storage $storage
* @param string $mountpoint
* @param array $arguments (optional)
*/
public function __construct($storage, $mountpoint, $arguments = null) {
if (is_null($arguments)) {
$arguments = array();
}
$mountpoint = self::formatPath($mountpoint);
if ($storage instanceof \OC\Files\Storage\Storage) {
$this->class = get_class($storage);
$this->storage = $storage;
} else {
// Update old classes to new namespace
if (strpos($storage, 'OC_Filestorage_') !== false) {
$storage = '\OC\Files\Storage\\' . substr($storage, 15);
}
$this->class = $storage;
$this->arguments = $arguments;
}
$this->mountPoint = $mountpoint;
self::$mounts[$this->mountPoint] = $this;
}
/**
* @return string
*/
public function getMountPoint() {
return $this->mountPoint;
}
/**
* @return \OC\Files\Storage\Storage
*/
private function createStorage() {
if (class_exists($this->class)) {
try {
return new $this->class($this->arguments);
} catch (\Exception $exception) {
\OC_Log::write('core', $exception->getMessage(), \OC_Log::ERROR);
return null;
}
} else {
\OC_Log::write('core', 'storage backend ' . $this->class . ' not found', \OC_Log::ERROR);
return null;
}
}
/**
* @return \OC\Files\Storage\Storage
*/
public function getStorage() {
if (is_null($this->storage)) {
$this->storage = $this->createStorage();
}
return $this->storage;
}
/**
* @return string
*/
public function getStorageId() {
if (!$this->storageId) {
if (is_null($this->storage)) {
$this->storage = $this->createStorage();
}
$this->storageId = $this->storage->getId();
}
return $this->storageId;
}
/**
* @param string $path
* @return string
*/
public function getInternalPath($path) {
if ($this->mountPoint === $path or $this->mountPoint . '/' === $path) {
$internalPath = '';
} else {
$internalPath = substr($path, strlen($this->mountPoint));
}
return $internalPath;
}
/**
* @param string $path
* @return string
*/
private static function formatPath($path) {
$path = Filesystem::normalizePath($path);
if (strlen($path) > 1) {
$path .= '/';
}
return $path;
}
/**
* Find the mount for $path
*
* @param $path
* @return Mount
*/
public static function find($path) {
$path = self::formatPath($path);
if (isset(self::$mounts[$path])) {
return self::$mounts[$path];
}
\OC_Hook::emit('OC_Filesystem', 'get_mountpoint', array('path' => $path));
$foundMountPoint = '';
$mountPoints = array_keys(self::$mounts);
foreach ($mountPoints as $mountpoint) {
if (strpos($path, $mountpoint) === 0 and strlen($mountpoint) > strlen($foundMountPoint)) {
$foundMountPoint = $mountpoint;
}
}
if (isset(self::$mounts[$foundMountPoint])) {
return self::$mounts[$foundMountPoint];
} else {
return null;
}
}
/**
* Find all mounts in $path
*
* @param $path
* @return Mount[]
*/
public static function findIn($path) {
$path = self::formatPath($path);
$result = array();
$pathLength = strlen($path);
$mountPoints = array_keys(self::$mounts);
foreach ($mountPoints as $mountPoint) {
if (substr($mountPoint, 0, $pathLength) === $path and strlen($mountPoint) > $pathLength) {
$result[] = self::$mounts[$mountPoint];
}
}
return $result;
}
public static function clear() {
self::$mounts = array();
}
/**
* @param string $id
* @return \OC\Files\Storage\Storage[]
*/
public static function findById($id) {
$result = array();
foreach (self::$mounts as $mount) {
if ($mount->getStorageId() === $id) {
$result[] = $mount;
}
}
return $result;
}
}

View File

@ -1,51 +1,34 @@
<?php
/**
* ownCloud
*
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski GapczynskiM@gmail.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Storage;
/**
* Storage backend class for providing common filesystem operation methods
* which are not storage-backend specific.
*
* OC_Filestorage_Common is never used directly; it is extended by all other
* \OC\Files\Storage\Common is never used directly; it is extended by all other
* storage backends, where its methods may be overridden, and additional
* (backend-specific) methods are defined.
*
* Some OC_Filestorage_Common methods call functions which are first defined
* Some \OC\Files\Storage\Common methods call functions which are first defined
* in classes which extend it, e.g. $this->stat() .
*/
abstract class OC_Filestorage_Common extends OC_Filestorage {
abstract class Common implements \OC\Files\Storage\Storage {
public function __construct($parameters) {}
// abstract public function mkdir($path);
// abstract public function rmdir($path);
// abstract public function opendir($path);
public function is_dir($path) {
return $this->filetype($path)=='dir';
}
public function is_file($path) {
return $this->filetype($path)=='file';
}
// abstract public function stat($path);
// abstract public function filetype($path);
public function filesize($path) {
if($this->is_dir($path)) {
return 0;//by definition
@ -55,29 +38,40 @@ abstract class OC_Filestorage_Common extends OC_Filestorage {
}
}
public function isCreatable($path) {
return $this->isUpdatable($path);
if ($this->is_dir($path) && $this->isUpdatable($path)) {
return true;
}
return false;
}
// abstract public function isReadable($path);
// abstract public function isUpdatable($path);
public function isDeletable($path) {
return $this->isUpdatable($path);
}
public function isSharable($path) {
return $this->isReadable($path);
}
// abstract public function file_exists($path);
public function filectime($path) {
$stat = $this->stat($path);
return $stat['ctime'];
public function getPermissions($path){
$permissions = 0;
if($this->isCreatable($path)){
$permissions |= \OCP\PERMISSION_CREATE;
}
if($this->isReadable($path)){
$permissions |= \OCP\PERMISSION_READ;
}
if($this->isUpdatable($path)){
$permissions |= \OCP\PERMISSION_UPDATE;
}
if($this->isDeletable($path)){
$permissions |= \OCP\PERMISSION_DELETE;
}
if($this->isSharable($path)){
$permissions |= \OCP\PERMISSION_SHARE;
}
return $permissions;
}
public function filemtime($path) {
$stat = $this->stat($path);
return $stat['mtime'];
}
public function fileatime($path) {
$stat = $this->stat($path);
return $stat['atime'];
}
public function file_get_contents($path) {
$handle = $this->fopen($path, "r");
if(!$handle) {
@ -89,94 +83,58 @@ abstract class OC_Filestorage_Common extends OC_Filestorage {
}
return fread($handle, $size);
}
public function file_put_contents($path, $data) {
public function file_put_contents($path,$data) {
$handle = $this->fopen($path, "w");
return fwrite($handle, $data);
}
// abstract public function unlink($path);
public function rename($path1, $path2) {
if($this->copy($path1, $path2)) {
public function rename($path1,$path2) {
if($this->copy($path1,$path2)) {
return $this->unlink($path1);
}else{
return false;
}
}
public function copy($path1, $path2) {
$source=$this->fopen($path1, 'r');
$target=$this->fopen($path2, 'w');
$count=OC_Helper::streamCopy($source, $target);
public function copy($path1,$path2) {
$source=$this->fopen($path1,'r');
$target=$this->fopen($path2,'w');
$count=\OC_Helper::streamCopy($source,$target);
return $count>0;
}
// abstract public function fopen($path, $mode);
/**
* @brief Deletes all files and folders recursively within a directory
* @param $directory The directory whose contents will be deleted
* @param $empty Flag indicating whether directory will be emptied
* @returns true/false
* @param string $directory The directory whose contents will be deleted
* @param bool $empty Flag indicating whether directory will be emptied
* @returns bool
*
* @note By default the directory specified by $directory will be
* deleted together with its contents. To avoid this set $empty to true
*/
public function deleteAll( $directory, $empty = false ) {
// strip leading slash
if( substr( $directory, 0, 1 ) == "/" ) {
$directory = substr( $directory, 1 );
}
// strip trailing slash
if( substr( $directory, -1) == "/" ) {
$directory = substr( $directory, 0, -1 );
}
$directory = trim($directory,'/');
if ( !$this->file_exists( \OCP\USER::getUser() . '/' . $directory ) || !$this->is_dir( \OCP\USER::getUser() . '/' . $directory ) ) {
return false;
} elseif( !$this->is_readable( \OCP\USER::getUser() . '/' . $directory ) ) {
} elseif( !$this->isReadable( \OCP\USER::getUser() . '/' . $directory ) ) {
return false;
} else {
$directoryHandle = $this->opendir( \OCP\USER::getUser() . '/' . $directory );
while ( $contents = readdir( $directoryHandle ) ) {
if ( $contents != '.' && $contents != '..') {
$path = $directory . "/" . $contents;
if ( $this->is_dir( $path ) ) {
deleteAll( $path );
$this->deleteAll( $path );
} else {
$this->unlink( \OCP\USER::getUser() .'/' . $path ); // TODO: make unlink use same system path as is_dir
}
}
}
//$this->closedir( $directoryHandle ); // TODO: implement closedir in OC_FSV
if ( $empty == false ) {
if ( !$this->rmdir( $directory ) ) {
return false;
return false;
}
}
return true;
}
@ -188,73 +146,71 @@ abstract class OC_Filestorage_Common extends OC_Filestorage {
if($this->is_dir($path)) {
return 'httpd/unix-directory';
}
$source=$this->fopen($path, 'r');
$source=$this->fopen($path,'r');
if(!$source) {
return false;
}
$head=fread($source, 8192);//8kb should suffice to determine a mimetype
if($pos=strrpos($path, '.')) {
$extension=substr($path, $pos);
$head=fread($source,8192);//8kb should suffice to determine a mimetype
if($pos=strrpos($path,'.')) {
$extension=substr($path,$pos);
}else{
$extension='';
}
$tmpFile=OC_Helper::tmpFile($extension);
file_put_contents($tmpFile, $head);
$mime=OC_Helper::getMimeType($tmpFile);
$tmpFile=\OC_Helper::tmpFile($extension);
file_put_contents($tmpFile,$head);
$mime=\OC_Helper::getMimeType($tmpFile);
unlink($tmpFile);
return $mime;
}
public function hash($type, $path, $raw = false) {
$tmpFile=$this->getLocalFile();
$hash=hash($type, $tmpFile, $raw);
public function hash($type,$path,$raw = false) {
$tmpFile=$this->getLocalFile($path);
$hash=hash($type,$tmpFile,$raw);
unlink($tmpFile);
return $hash;
}
// abstract public function free_space($path);
public function search($query) {
return $this->searchInDir($query);
}
public function getLocalFile($path) {
return $this->toTmpFile($path);
}
private function toTmpFile($path) {//no longer in the storage api, still usefull here
$source=$this->fopen($path, 'r');
private function toTmpFile($path) {//no longer in the storage api, still useful here
$source=$this->fopen($path,'r');
if(!$source) {
return false;
}
if($pos=strrpos($path, '.')) {
$extension=substr($path, $pos);
if($pos=strrpos($path,'.')) {
$extension=substr($path,$pos);
}else{
$extension='';
}
$tmpFile=OC_Helper::tmpFile($extension);
$target=fopen($tmpFile, 'w');
OC_Helper::streamCopy($source, $target);
$tmpFile=\OC_Helper::tmpFile($extension);
$target=fopen($tmpFile,'w');
\OC_Helper::streamCopy($source,$target);
return $tmpFile;
}
public function getLocalFolder($path) {
$baseDir=OC_Helper::tmpFolder();
$this->addLocalFolder($path, $baseDir);
$baseDir=\OC_Helper::tmpFolder();
$this->addLocalFolder($path,$baseDir);
return $baseDir;
}
private function addLocalFolder($path, $target) {
private function addLocalFolder($path,$target) {
if($dh=$this->opendir($path)) {
while($file=readdir($dh)) {
if($file!=='.' and $file!=='..') {
if($this->is_dir($path.'/'.$file)) {
mkdir($target.'/'.$file);
$this->addLocalFolder($path.'/'.$file, $target.'/'.$file);
$this->addLocalFolder($path.'/'.$file,$target.'/'.$file);
}else{
$tmp=$this->toTmpFile($path.'/'.$file);
rename($tmp, $target.'/'.$file);
rename($tmp,$target.'/'.$file);
}
}
}
}
}
// abstract public function touch($path, $mtime=null);
protected function searchInDir($query, $dir='') {
protected function searchInDir($query,$dir='') {
$files=array();
$dh=$this->opendir($dir);
if($dh) {
@ -264,7 +220,7 @@ abstract class OC_Filestorage_Common extends OC_Filestorage {
$files[]=$dir.'/'.$item;
}
if($this->is_dir($dir.'/'.$item)) {
$files=array_merge($files, $this->searchInDir($query, $dir.'/'.$item));
$files=array_merge($files,$this->searchInDir($query,$dir.'/'.$item));
}
}
}
@ -273,19 +229,52 @@ abstract class OC_Filestorage_Common extends OC_Filestorage {
/**
* check if a file or folder has been updated since $time
* @param string $path
* @param int $time
* @return bool
*/
public function hasUpdated($path, $time) {
public function hasUpdated($path,$time) {
return $this->filemtime($path)>$time;
}
public function getCache($path=''){
return new \OC\Files\Cache\Cache($this);
}
public function getScanner($path=''){
return new \OC\Files\Cache\Scanner($this);
}
public function getPermissionsCache($path=''){
return new \OC\Files\Cache\Permissions($this);
}
public function getWatcher($path=''){
return new \OC\Files\Cache\Watcher($this);
}
/**
* get the owner of a path
* @param $path The path to get the owner
* @param string $path The path to get the owner
* @return string uid or false
*/
public function getOwner($path) {
return OC_User::getUser();
return \OC_User::getUser();
}
/**
* get the ETag for a file or folder
*
* @param string $path
* @return string
*/
public function getETag($path){
$ETagFunction = \OC_Connector_Sabre_Node::$ETagFunction;
if($ETagFunction) {
$hash = call_user_func($ETagFunction, $path);
return $hash;
}else{
return uniqid();
}
}
}

View File

@ -22,20 +22,25 @@
*/
/**
* test implementation for OC_FileStorage_Common with OC_FileStorage_Local
* test implementation for \OC\Files\Storage\Common with \OC\Files\Storage\Local
*/
class OC_Filestorage_CommonTest extends OC_Filestorage_Common{
namespace OC\Files\Storage;
class CommonTest extends \OC\Files\Storage\Common{
/**
* underlying local storage used for missing functions
* @var OC_FileStorage_Local
* @var \OC\Files\Storage\Local
*/
private $storage;
public function __construct($params) {
$this->storage=new OC_Filestorage_Local($params);
$this->storage=new \OC\Files\Storage\Local($params);
}
public function getId(){
return 'test::'.$this->storage->getId();
}
public function mkdir($path) {
return $this->storage->mkdir($path);
}

View File

@ -1,8 +1,17 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Storage;
/**
* for local filestore, we only have to map the paths
*/
class OC_Filestorage_Local extends OC_Filestorage_Common{
class Local extends \OC\Files\Storage\Common{
protected $datadir;
public function __construct($arguments) {
$this->datadir=$arguments['datadir'];
@ -10,6 +19,9 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
$this->datadir.='/';
}
}
public function getId(){
return 'local::'.$this->datadir;
}
public function mkdir($path) {
return @mkdir($this->datadir.$path);
}
@ -20,7 +32,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
return opendir($this->datadir.$path);
}
public function is_dir($path) {
if(substr($path, -1)=='/') {
if(substr($path,-1)=='/') {
$path=substr($path, 0, -1);
}
return is_dir($this->datadir.$path);
@ -68,9 +80,6 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
public function file_exists($path) {
return file_exists($this->datadir.$path);
}
public function filectime($path) {
return filectime($this->datadir.$path);
}
public function filemtime($path) {
return filemtime($this->datadir.$path);
}
@ -100,11 +109,11 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
}
public function rename($path1, $path2) {
if (!$this->isUpdatable($path1)) {
OC_Log::write('core', 'unable to rename, file is not writable : '.$path1, OC_Log::ERROR);
\OC_Log::write('core','unable to rename, file is not writable : '.$path1,\OC_Log::ERROR);
return false;
}
if(! $this->file_exists($path1)) {
OC_Log::write('core', 'unable to rename, file does not exists : '.$path1, OC_Log::ERROR);
\OC_Log::write('core','unable to rename, file does not exists : '.$path1,\OC_Log::ERROR);
return false;
}
@ -143,7 +152,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
public function getMimeType($path) {
if($this->isReadable($path)) {
return OC_Helper::getMimeType($this->datadir.$path);
return \OC_Helper::getMimeType($this->datadir . $path);
}else{
return false;
}

View File

@ -0,0 +1,88 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Storage;
/**
* Provide a common interface to all different storage options
*/
interface Storage{
public function __construct($parameters);
public function getId();
public function mkdir($path);
public function rmdir($path);
public function opendir($path);
public function is_dir($path);
public function is_file($path);
public function stat($path);
public function filetype($path);
public function filesize($path);
public function isCreatable($path);
public function isReadable($path);
public function isUpdatable($path);
public function isDeletable($path);
public function isSharable($path);
public function getPermissions($path);
public function file_exists($path);
public function filemtime($path);
public function file_get_contents($path);
public function file_put_contents($path,$data);
public function unlink($path);
public function rename($path1,$path2);
public function copy($path1,$path2);
public function fopen($path,$mode);
public function getMimeType($path);
public function hash($type,$path,$raw = false);
public function free_space($path);
public function search($query);
public function touch($path, $mtime=null);
public function getLocalFile($path);// get a path to a local version of the file, whether the original file is local or remote
public function getLocalFolder($path);// get a path to a local version of the folder, whether the original file is local or remote
/**
* check if a file or folder has been updated since $time
* @param int $time
* @return bool
*
* hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
* returning true for other changes in the folder is optional
*/
public function hasUpdated($path,$time);
/**
* @param string $path
* @return \OC\Files\Cache\Cache
*/
public function getCache($path='');
/**
* @param string $path
* @return \OC\Files\Cache\Scanner
*/
public function getScanner($path='');
public function getOwner($path);
/**
* @param string $path
* @return \OC\Files\Cache\Permissions
*/
public function getPermissionsCache($path='');
/**
* @param string $path
* @return \OC\Files\Cache\Watcher
*/
public function getWatcher($path='');
/**
* get the ETag for a file or folder
*
* @param string $path
* @return string
*/
public function getETag($path);
}

View File

@ -0,0 +1,26 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Storage;
/**
* local storage backnd in temporary folder for testing purpores
*/
class Temporary extends Local{
public function __construct($arguments) {
$this->datadir=\OC_Helper::tmpFolder();
}
public function cleanUp() {
\OC_Helper::rmdirr($this->datadir);
}
public function __destruct() {
$this->cleanUp();
}
}

100
lib/files/stream/close.php Normal file
View File

@ -0,0 +1,100 @@
<?php
/**
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Stream;
/**
* stream wrapper that provides a callback on stream close
*/
class Close {
private static $callBacks = array();
private $path = '';
private $source;
private static $open = array();
public function stream_open($path, $mode, $options, &$opened_path) {
$path = substr($path, strlen('close://'));
$this->path = $path;
$this->source = fopen($path, $mode);
if (is_resource($this->source)) {
$this->meta = stream_get_meta_data($this->source);
}
self::$open[] = $path;
return is_resource($this->source);
}
public function stream_seek($offset, $whence = SEEK_SET) {
fseek($this->source, $offset, $whence);
}
public function stream_tell() {
return ftell($this->source);
}
public function stream_read($count) {
return fread($this->source, $count);
}
public function stream_write($data) {
return fwrite($this->source, $data);
}
public function stream_set_option($option, $arg1, $arg2) {
switch ($option) {
case STREAM_OPTION_BLOCKING:
stream_set_blocking($this->source, $arg1);
break;
case STREAM_OPTION_READ_TIMEOUT:
stream_set_timeout($this->source, $arg1, $arg2);
break;
case STREAM_OPTION_WRITE_BUFFER:
stream_set_write_buffer($this->source, $arg1, $arg2);
}
}
public function stream_stat() {
return fstat($this->source);
}
public function stream_lock($mode) {
flock($this->source, $mode);
}
public function stream_flush() {
return fflush($this->source);
}
public function stream_eof() {
return feof($this->source);
}
public function url_stat($path) {
$path = substr($path, strlen('close://'));
if (file_exists($path)) {
return stat($path);
} else {
return false;
}
}
public function stream_close() {
fclose($this->source);
if (isset(self::$callBacks[$this->path])) {
call_user_func(self::$callBacks[$this->path], $this->path);
}
}
public function unlink($path) {
$path = substr($path, strlen('close://'));
return unlink($path);
}
public static function registerCallback($path, $callback) {
self::$callBacks[$path] = $callback;
}
}

47
lib/files/stream/dir.php Normal file
View File

@ -0,0 +1,47 @@
<?php
/**
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Stream;
class Dir {
private static $dirs = array();
private $name;
private $index;
public function dir_opendir($path, $options) {
$this->name = substr($path, strlen('fakedir://'));
$this->index = 0;
if (!isset(self::$dirs[$this->name])) {
self::$dirs[$this->name] = array();
}
return true;
}
public function dir_readdir() {
if ($this->index >= count(self::$dirs[$this->name])) {
return false;
}
$filename = self::$dirs[$this->name][$this->index];
$this->index++;
return $filename;
}
public function dir_closedir() {
$this->name = '';
return true;
}
public function dir_rewinddir() {
$this->index = 0;
return true;
}
public static function register($path, $content) {
self::$dirs[$path] = $content;
}
}

129
lib/files/stream/oc.php Normal file
View File

@ -0,0 +1,129 @@
<?php
/**
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Stream;
/**
* a stream wrappers for ownCloud's virtual filesystem
*/
class OC {
/**
* @var \OC\Files\View
*/
static private $rootView;
private $path;
private $dirSource;
private $fileSource;
private $meta;
private function setup(){
if (!self::$rootView) {
self::$rootView = new \OC\Files\View('');
}
}
public function stream_open($path, $mode, $options, &$opened_path) {
$this->setup();
$path = substr($path, strlen('oc://'));
$this->path = $path;
$this->fileSource = self::$rootView->fopen($path, $mode);
if (is_resource($this->fileSource)) {
$this->meta = stream_get_meta_data($this->fileSource);
}
return is_resource($this->fileSource);
}
public function stream_seek($offset, $whence = SEEK_SET) {
fseek($this->fileSource, $offset, $whence);
}
public function stream_tell() {
return ftell($this->fileSource);
}
public function stream_read($count) {
return fread($this->fileSource, $count);
}
public function stream_write($data) {
return fwrite($this->fileSource, $data);
}
public function stream_set_option($option, $arg1, $arg2) {
switch ($option) {
case STREAM_OPTION_BLOCKING:
stream_set_blocking($this->fileSource, $arg1);
break;
case STREAM_OPTION_READ_TIMEOUT:
stream_set_timeout($this->fileSource, $arg1, $arg2);
break;
case STREAM_OPTION_WRITE_BUFFER:
stream_set_write_buffer($this->fileSource, $arg1, $arg2);
}
}
public function stream_stat() {
return fstat($this->fileSource);
}
public function stream_lock($mode) {
flock($this->fileSource, $mode);
}
public function stream_flush() {
return fflush($this->fileSource);
}
public function stream_eof() {
return feof($this->fileSource);
}
public function url_stat($path) {
$this->setup();
$path = substr($path, strlen('oc://'));
if (self::$rootView->file_exists($path)) {
return self::$rootView->stat($path);
} else {
return false;
}
}
public function stream_close() {
fclose($this->fileSource);
}
public function unlink($path) {
$this->setup();
$path = substr($path, strlen('oc://'));
return self::$rootView->unlink($path);
}
public function dir_opendir($path, $options) {
$this->setup();
$path = substr($path, strlen('oc://'));
$this->path = $path;
$this->dirSource = self::$rootView->opendir($path);
if (is_resource($this->dirSource)) {
$this->meta = stream_get_meta_data($this->dirSource);
}
return is_resource($this->dirSource);
}
public function dir_readdir() {
return readdir($this->dirSource);
}
public function dir_closedir() {
closedir($this->dirSource);
}
public function dir_rewinddir() {
rewinddir($this->dirSource);
}
}

View File

@ -1,54 +1,30 @@
<?php
/**
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
class OC_FakeDirStream{
public static $dirs=array();
private $name;
private $index;
namespace OC\Files\Stream;
public function dir_opendir($path, $options) {
$this->name=substr($path, strlen('fakedir://'));
$this->index=0;
if(!isset(self::$dirs[$this->name])) {
self::$dirs[$this->name]=array();
}
return true;
}
public function dir_readdir() {
if($this->index>=count(self::$dirs[$this->name])) {
return false;
}
$filename=self::$dirs[$this->name][$this->index];
$this->index++;
return $filename;
}
public function dir_closedir() {
$this->name='';
return true;
}
public function dir_rewinddir() {
$this->index=0;
return true;
}
}
class OC_StaticStreamWrapper {
class StaticStream {
public $context;
protected static $data = array();
protected $path = '';
protected $path = '';
protected $pointer = 0;
protected $writable = false;
public function stream_close() {}
public function stream_close() {
}
public function stream_eof() {
return $this->pointer >= strlen(self::$data[$this->path]);
}
public function stream_flush() {}
public function stream_flush() {
}
public function stream_open($path, $mode, $options, &$opened_path) {
switch ($mode[0]) {
@ -213,89 +189,3 @@ class OC_StaticStreamWrapper {
return false;
}
}
/**
* stream wrapper that provides a callback on stream close
*/
class OC_CloseStreamWrapper{
public static $callBacks=array();
private $path='';
private $source;
private static $open=array();
public function stream_open($path, $mode, $options, &$opened_path) {
$path=substr($path, strlen('close://'));
$this->path=$path;
$this->source=fopen($path, $mode);
if(is_resource($this->source)) {
$this->meta=stream_get_meta_data($this->source);
}
self::$open[]=$path;
return is_resource($this->source);
}
public function stream_seek($offset, $whence=SEEK_SET) {
fseek($this->source, $offset, $whence);
}
public function stream_tell() {
return ftell($this->source);
}
public function stream_read($count) {
return fread($this->source, $count);
}
public function stream_write($data) {
return fwrite($this->source, $data);
}
public function stream_set_option($option, $arg1, $arg2) {
switch($option) {
case STREAM_OPTION_BLOCKING:
stream_set_blocking($this->source, $arg1);
break;
case STREAM_OPTION_READ_TIMEOUT:
stream_set_timeout($this->source, $arg1, $arg2);
break;
case STREAM_OPTION_WRITE_BUFFER:
stream_set_write_buffer($this->source, $arg1, $arg2);
}
}
public function stream_stat() {
return fstat($this->source);
}
public function stream_lock($mode) {
flock($this->source, $mode);
}
public function stream_flush() {
return fflush($this->source);
}
public function stream_eof() {
return feof($this->source);
}
public function url_stat($path) {
$path=substr($path, strlen('close://'));
if(file_exists($path)) {
return stat($path);
}else{
return false;
}
}
public function stream_close() {
fclose($this->source);
if(isset(self::$callBacks[$this->path])) {
call_user_func(self::$callBacks[$this->path], $this->path);
}
}
public function unlink($path) {
$path=substr($path, strlen('close://'));
return unlink($path);
}
}

958
lib/files/view.php Normal file
View File

@ -0,0 +1,958 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
/**
* Class to provide access to ownCloud filesystem via a "view", and methods for
* working with files within that view (e.g. read, write, delete, etc.). Each
* view is restricted to a set of directories via a virtual root. The default view
* uses the currently logged in user's data directory as root (parts of
* OC_Filesystem are merely a wrapper for OC_FilesystemView).
*
* Apps that need to access files outside of the user data folders (to modify files
* belonging to a user other than the one currently logged in, for example) should
* use this class directly rather than using OC_Filesystem, or making use of PHP's
* built-in file manipulation functions. This will ensure all hooks and proxies
* are triggered correctly.
*
* Filesystem functions are not called directly; they are passed to the correct
* \OC\Files\Storage\Storage object
*/
namespace OC\Files;
class View {
private $fakeRoot = '';
private $internal_path_cache = array();
private $storage_cache = array();
public function __construct($root) {
$this->fakeRoot = $root;
}
public function getAbsolutePath($path = '/') {
if (!$path) {
$path = '/';
}
if ($path[0] !== '/') {
$path = '/' . $path;
}
return $this->fakeRoot . $path;
}
/**
* change the root to a fake root
*
* @param string $fakeRoot
* @return bool
*/
public function chroot($fakeRoot) {
if (!$fakeRoot == '') {
if ($fakeRoot[0] !== '/') {
$fakeRoot = '/' . $fakeRoot;
}
}
$this->fakeRoot = $fakeRoot;
}
/**
* get the fake root
*
* @return string
*/
public function getRoot() {
return $this->fakeRoot;
}
/**
* get path relative to the root of the view
*
* @param string $path
* @return string
*/
public function getRelativePath($path) {
if ($this->fakeRoot == '') {
return $path;
}
if (strpos($path, $this->fakeRoot) !== 0) {
return null;
} else {
$path = substr($path, strlen($this->fakeRoot));
if (strlen($path) === 0) {
return '/';
} else {
return $path;
}
}
}
/**
* get the mountpoint of the storage object for a path
( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account
*
* @param string $path
* @return string
*/
public function getMountPoint($path) {
return Filesystem::getMountPoint($this->getAbsolutePath($path));
}
/**
* resolve a path to a storage and internal path
*
* @param string $path
* @return array consisting of the storage and the internal path
*/
public function resolvePath($path) {
return Filesystem::resolvePath($this->getAbsolutePath($path));
}
/**
* return the path to a local version of the file
* we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed
*
* @param string $path
* @return string
*/
public function getLocalFile($path) {
$parent = substr($path, 0, strrpos($path, '/'));
$path = $this->getAbsolutePath($path);
list($storage, $internalPath) = Filesystem::resolvePath($path);
if (Filesystem::isValidPath($parent) and $storage) {
return $storage->getLocalFile($internalPath);
} else {
return null;
}
}
/**
* @param string $path
* @return string
*/
public function getLocalFolder($path) {
$parent = substr($path, 0, strrpos($path, '/'));
$path = $this->getAbsolutePath($path);
list($storage, $internalPath) = Filesystem::resolvePath($path);
if (Filesystem::isValidPath($parent) and $storage) {
return $storage->getLocalFolder($internalPath);
} else {
return null;
}
}
/**
* the following functions operate with arguments and return values identical
* to those of their PHP built-in equivalents. Mostly they are merely wrappers
* for \OC\Files\Storage\Storage via basicOperation().
*/
public function mkdir($path) {
return $this->basicOperation('mkdir', $path, array('create', 'write'));
}
public function rmdir($path) {
return $this->basicOperation('rmdir', $path, array('delete'));
}
public function opendir($path) {
return $this->basicOperation('opendir', $path, array('read'));
}
public function readdir($handle) {
$fsLocal = new Storage\Local(array('datadir' => '/'));
return $fsLocal->readdir($handle);
}
public function is_dir($path) {
if ($path == '/') {
return true;
}
return $this->basicOperation('is_dir', $path);
}
public function is_file($path) {
if ($path == '/') {
return false;
}
return $this->basicOperation('is_file', $path);
}
public function stat($path) {
return $this->basicOperation('stat', $path);
}
public function filetype($path) {
return $this->basicOperation('filetype', $path);
}
public function filesize($path) {
return $this->basicOperation('filesize', $path);
}
public function readfile($path) {
@ob_end_clean();
$handle = $this->fopen($path, 'rb');
if ($handle) {
$chunkSize = 8192; // 8 MB chunks
while (!feof($handle)) {
echo fread($handle, $chunkSize);
flush();
}
$size = $this->filesize($path);
return $size;
}
return false;
}
public function isCreatable($path) {
return $this->basicOperation('isCreatable', $path);
}
public function isReadable($path) {
return $this->basicOperation('isReadable', $path);
}
public function isUpdatable($path) {
return $this->basicOperation('isUpdatable', $path);
}
public function isDeletable($path) {
return $this->basicOperation('isDeletable', $path);
}
public function isSharable($path) {
return $this->basicOperation('isSharable', $path);
}
public function file_exists($path) {
if ($path == '/') {
return true;
}
return $this->basicOperation('file_exists', $path);
}
public function filemtime($path) {
return $this->basicOperation('filemtime', $path);
}
public function touch($path, $mtime = null) {
if (!is_null($mtime) and !is_numeric($mtime)) {
$mtime = strtotime($mtime);
}
return $this->basicOperation('touch', $path, array('write'), $mtime);
}
public function file_get_contents($path) {
return $this->basicOperation('file_get_contents', $path, array('read'));
}
public function file_put_contents($path, $data) {
if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
if (\OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && Filesystem::isValidPath($path)) {
$path = $this->getRelativePath($absolutePath);
$exists = $this->file_exists($path);
$run = true;
if ($this->fakeRoot == Filesystem::getRoot()) {
if (!$exists) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_create,
array(
Filesystem::signal_param_path => $path,
Filesystem::signal_param_run => &$run
)
);
}
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_write,
array(
Filesystem::signal_param_path => $path,
Filesystem::signal_param_run => &$run
)
);
}
if (!$run) {
return false;
}
$target = $this->fopen($path, 'w');
if ($target) {
$count = \OC_Helper::streamCopy($data, $target);
fclose($target);
fclose($data);
if ($this->fakeRoot == Filesystem::getRoot()) {
if (!$exists) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_create,
array(Filesystem::signal_param_path => $path)
);
}
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_write,
array(Filesystem::signal_param_path => $path)
);
}
\OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
return $count > 0;
} else {
return false;
}
} else {
return false;
}
} else {
return $this->basicOperation('file_put_contents', $path, array('create', 'write'), $data);
}
}
public function unlink($path) {
return $this->basicOperation('unlink', $path, array('delete'));
}
public function deleteAll($directory, $empty = false) {
return $this->basicOperation('deleteAll', $directory, array('delete'), $empty);
}
public function rename($path1, $path2) {
$postFix1 = (substr($path1, -1, 1) === '/') ? '/' : '';
$postFix2 = (substr($path2, -1, 1) === '/') ? '/' : '';
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
if (\OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and Filesystem::isValidPath($path2)) {
$path1 = $this->getRelativePath($absolutePath1);
$path2 = $this->getRelativePath($absolutePath2);
if ($path1 == null or $path2 == null) {
return false;
}
$run = true;
if ($this->fakeRoot == Filesystem::getRoot()) {
\OC_Hook::emit(
Filesystem::CLASSNAME, Filesystem::signal_rename,
array(
Filesystem::signal_param_oldpath => $path1,
Filesystem::signal_param_newpath => $path2,
Filesystem::signal_param_run => &$run
)
);
}
if ($run) {
$mp1 = $this->getMountPoint($path1 . $postFix1);
$mp2 = $this->getMountPoint($path2 . $postFix2);
if ($mp1 == $mp2) {
list($storage, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
if ($storage) {
$result = $storage->rename($internalPath1, $internalPath2);
} else {
$result = false;
}
} else {
$source = $this->fopen($path1 . $postFix1, 'r');
$target = $this->fopen($path2 . $postFix2, 'w');
$count = \OC_Helper::streamCopy($source, $target);
list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
$storage1->unlink($internalPath1);
$result = $count > 0;
}
if ($this->fakeRoot == Filesystem::getRoot()) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_rename,
array(
Filesystem::signal_param_oldpath => $path1,
Filesystem::signal_param_newpath => $path2
)
);
}
return $result;
} else {
return false;
}
} else {
return false;
}
}
public function copy($path1, $path2) {
$postFix1 = (substr($path1, -1, 1) === '/') ? '/' : '';
$postFix2 = (substr($path2, -1, 1) === '/') ? '/' : '';
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
if (\OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and Filesystem::isValidPath($path2)) {
$path1 = $this->getRelativePath($absolutePath1);
$path2 = $this->getRelativePath($absolutePath2);
if ($path1 == null or $path2 == null) {
return false;
}
$run = true;
$exists = $this->file_exists($path2);
if ($this->fakeRoot == Filesystem::getRoot()) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_copy,
array(
Filesystem::signal_param_oldpath => $path1,
Filesystem::signal_param_newpath => $path2,
Filesystem::signal_param_run => &$run
)
);
if ($run and !$exists) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_create,
array(
Filesystem::signal_param_path => $path2,
Filesystem::signal_param_run => &$run
)
);
}
if ($run) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_write,
array(
Filesystem::signal_param_path => $path2,
Filesystem::signal_param_run => &$run
)
);
}
}
if ($run) {
$mp1 = $this->getMountPoint($path1 . $postFix1);
$mp2 = $this->getMountPoint($path2 . $postFix2);
if ($mp1 == $mp2) {
list($storage, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
if ($storage) {
$result = $storage->copy($internalPath1, $internalPath2);
} else {
$result = false;
}
} else {
$source = $this->fopen($path1 . $postFix1, 'r');
$target = $this->fopen($path2 . $postFix2, 'w');
$result = \OC_Helper::streamCopy($source, $target);
}
if ($this->fakeRoot == Filesystem::getRoot()) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_copy,
array(
Filesystem::signal_param_oldpath => $path1,
Filesystem::signal_param_newpath => $path2
)
);
if (!$exists) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_create,
array(Filesystem::signal_param_path => $path2)
);
}
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_post_write,
array(Filesystem::signal_param_path => $path2)
);
}
return $result;
} else {
return false;
}
} else {
return false;
}
}
public function fopen($path, $mode) {
$hooks = array();
switch ($mode) {
case 'r':
case 'rb':
$hooks[] = 'read';
break;
case 'r+':
case 'rb+':
case 'w+':
case 'wb+':
case 'x+':
case 'xb+':
case 'a+':
case 'ab+':
$hooks[] = 'read';
$hooks[] = 'write';
break;
case 'w':
case 'wb':
case 'x':
case 'xb':
case 'a':
case 'ab':
$hooks[] = 'write';
break;
default:
\OC_Log::write('core', 'invalid mode (' . $mode . ') for ' . $path, \OC_Log::ERROR);
}
return $this->basicOperation('fopen', $path, $hooks, $mode);
}
public function toTmpFile($path) {
if (Filesystem::isValidPath($path)) {
$source = $this->fopen($path, 'r');
if ($source) {
$extension = '';
$extOffset = strpos($path, '.');
if ($extOffset !== false) {
$extension = substr($path, strrpos($path, '.'));
}
$tmpFile = \OC_Helper::tmpFile($extension);
file_put_contents($tmpFile, $source);
return $tmpFile;
} else {
return false;
}
} else {
return false;
}
}
public function fromTmpFile($tmpFile, $path) {
if (Filesystem::isValidPath($path)) {
if (!$tmpFile) {
debug_print_backtrace();
}
$source = fopen($tmpFile, 'r');
if ($source) {
$this->file_put_contents($path, $source);
unlink($tmpFile);
return true;
} else {
return false;
}
} else {
return false;
}
}
public function getMimeType($path) {
return $this->basicOperation('getMimeType', $path);
}
public function hash($type, $path, $raw = false) {
$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
if (\OC_FileProxy::runPreProxies('hash', $absolutePath) && Filesystem::isValidPath($path)) {
$path = $this->getRelativePath($absolutePath);
if ($path == null) {
return false;
}
if (Filesystem::$loaded && $this->fakeRoot == Filesystem::getRoot()) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
Filesystem::signal_read,
array(Filesystem::signal_param_path => $path)
);
}
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
if ($storage) {
$result = $storage->hash($type, $internalPath, $raw);
$result = \OC_FileProxy::runPostProxies('hash', $absolutePath, $result);
return $result;
}
}
return null;
}
public function free_space($path = '/') {
return $this->basicOperation('free_space', $path);
}
/**
* @brief abstraction layer for basic filesystem functions: wrapper for \OC\Files\Storage\Storage
* @param string $operation
* @param string $path
* @param array $hooks (optional)
* @param mixed $extraParam (optional)
* @return mixed
*
* This method takes requests for basic filesystem functions (e.g. reading & writing
* files), processes hooks and proxies, sanitises paths, and finally passes them on to
* \OC\Files\Storage\Storage for delegation to a storage backend for execution
*/
private function basicOperation($operation, $path, $hooks = array(), $extraParam = null) {
$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
if (\OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and Filesystem::isValidPath($path)) {
$path = $this->getRelativePath($absolutePath);
if ($path == null) {
return false;
}
$run = $this->runHooks($hooks, $path);
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
if ($run and $storage) {
if (!is_null($extraParam)) {
$result = $storage->$operation($internalPath, $extraParam);
} else {
$result = $storage->$operation($internalPath);
}
$result = \OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result);
if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot()) {
if ($operation != 'fopen') { //no post hooks for fopen, the file stream is still open
$this->runHooks($hooks, $path, true);
}
}
return $result;
}
}
return null;
}
private function runHooks($hooks, $path, $post = false) {
$prefix = ($post) ? 'post_' : '';
$run = true;
if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot()) {
foreach ($hooks as $hook) {
if ($hook != 'read') {
\OC_Hook::emit(
Filesystem::CLASSNAME,
$prefix . $hook,
array(
Filesystem::signal_param_run => &$run,
Filesystem::signal_param_path => $path
)
);
} elseif (!$post) {
\OC_Hook::emit(
Filesystem::CLASSNAME,
$prefix . $hook,
array(
Filesystem::signal_param_path => $path
)
);
}
}
}
return $run;
}
/**
* check if a file or folder has been updated since $time
*
* @param string $path
* @param int $time
* @return bool
*/
public function hasUpdated($path, $time) {
return $this->basicOperation('hasUpdated', $path, array(), $time);
}
/**
* get the filesystem info
*
* @param string $path
* @return array
*
* returns an associative array with the following keys:
* - size
* - mtime
* - mimetype
* - encrypted
* - versioned
*/
public function getFileInfo($path) {
$data = array();
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = Filesystem::resolvePath($path);
if ($storage) {
$cache = $storage->getCache($internalPath);
$permissionsCache = $storage->getPermissionsCache($internalPath);
$user = \OC_User::getUser();
if (!$cache->inCache($internalPath)) {
$scanner = $storage->getScanner($internalPath);
$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
} else {
$watcher = $storage->getWatcher($internalPath);
$watcher->checkUpdate($internalPath);
}
$data = $cache->get($internalPath);
if ($data and $data['fileid']) {
if ($data['mimetype'] === 'httpd/unix-directory') {
//add the sizes of other mountpoints to the folder
$mountPoints = Filesystem::getMountPoints($path);
foreach ($mountPoints as $mountPoint) {
$subStorage = Filesystem::getStorage($mountPoint);
if ($subStorage) {
$subCache = $subStorage->getCache('');
$rootEntry = $subCache->get('');
$data['size'] += $rootEntry['size'];
}
}
}
$permissions = $permissionsCache->get($data['fileid'], $user);
if ($permissions === -1) {
$permissions = $storage->getPermissions($internalPath);
$permissionsCache->set($data['fileid'], $user, $permissions);
}
$data['permissions'] = $permissions;
}
}
return $data;
}
/**
* get the content of a directory
*
* @param string $directory path under datadirectory
* @return array
*/
public function getDirectoryContent($directory, $mimetype_filter = '') {
$result = array();
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $directory);
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = Filesystem::resolvePath($path);
if ($storage) {
$cache = $storage->getCache($internalPath);
$permissionsCache = $storage->getPermissionsCache($internalPath);
$user = \OC_User::getUser();
if ($cache->getStatus($internalPath) < Cache\Cache::COMPLETE) {
$scanner = $storage->getScanner($internalPath);
$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
} else {
$watcher = $storage->getWatcher($internalPath);
$watcher->checkUpdate($internalPath);
}
$files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter
$ids = array();
foreach ($files as $i => $file) {
$files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file';
$ids[] = $file['fileid'];
$permissions = $permissionsCache->get($file['fileid'], $user);
if ($permissions === -1) {
$permissions = $storage->getPermissions($file['path']);
$permissionsCache->set($file['fileid'], $user, $permissions);
}
$files[$i]['permissions'] = $permissions;
}
//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
$mountPoints = Filesystem::getMountPoints($path);
$dirLength = strlen($path);
foreach ($mountPoints as $mountPoint) {
$subStorage = Filesystem::getStorage($mountPoint);
if ($subStorage) {
$subCache = $subStorage->getCache('');
if ($subCache->getStatus('') === Cache\Cache::NOT_FOUND) {
$subScanner = $subStorage->getScanner('');
$subScanner->scanFile('');
}
$rootEntry = $subCache->get('');
if ($rootEntry) {
$relativePath = trim(substr($mountPoint, $dirLength), '/');
if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder
$entryName = substr($relativePath, 0, $pos);
foreach ($files as &$entry) {
if ($entry['name'] === $entryName) {
$entry['size'] += $rootEntry['size'];
}
}
} else { //mountpoint in this folder, add an entry for it
$rootEntry['name'] = $relativePath;
$rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file';
$subPermissionsCache = $subStorage->getPermissionsCache('');
$permissions = $subPermissionsCache->get($rootEntry['fileid'], $user);
if ($permissions === -1) {
$permissions = $subStorage->getPermissions($rootEntry['path']);
$subPermissionsCache->set($rootEntry['fileid'], $user, $permissions);
}
$rootEntry['permissions'] = $permissions;
//remove any existing entry with the same name
foreach ($files as $i => $file) {
if ($file['name'] === $rootEntry['name']) {
unset($files[$i]);
break;
}
}
$files[] = $rootEntry;
}
}
}
}
if ($mimetype_filter) {
foreach ($files as $file) {
if (strpos($mimetype_filter, '/')) {
if ($file['mimetype'] === $mimetype_filter) {
$result[] = $file;
}
} else {
if ($file['mimepart'] === $mimetype_filter) {
$result[] = $file;
}
}
}
} else {
$result = $files;
}
}
return $result;
}
/**
* change file metadata
*
* @param string $path
* @param array $data
* @return int
*
* returns the fileid of the updated file
*/
public function putFileInfo($path, $data) {
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
/**
* @var \OC\Files\Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = Filesystem::resolvePath($path);
if ($storage) {
$cache = $storage->getCache($path);
if (!$cache->inCache($internalPath)) {
$scanner = $storage->getScanner($internalPath);
$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
}
return $cache->put($internalPath, $data);
} else {
return -1;
}
}
/**
* search for files with the name matching $query
*
* @param string $query
* @return array
*/
public function search($query) {
return $this->searchCommon('%' . $query . '%', 'search');
}
/**
* search for files by mimetype
*
* @param string $query
* @return array
*/
public function searchByMime($mimetype) {
return $this->searchCommon($mimetype, 'searchByMime');
}
/**
* @param string $query
* @param string $method
* @return array
*/
private function searchCommon($query, $method) {
$files = array();
$rootLength = strlen($this->fakeRoot);
$mountPoint = Filesystem::getMountPoint($this->fakeRoot);
$storage = Filesystem::getStorage($mountPoint);
if ($storage) {
$cache = $storage->getCache('');
$results = $cache->$method($query);
foreach ($results as $result) {
if (substr($mountPoint . $result['path'], 0, $rootLength) === $this->fakeRoot) {
$result['path'] = substr($mountPoint . $result['path'], $rootLength);
$files[] = $result;
}
}
$mountPoints = Filesystem::getMountPoints($this->fakeRoot);
foreach ($mountPoints as $mountPoint) {
$storage = Filesystem::getStorage($mountPoint);
if ($storage) {
$cache = $storage->getCache('');
$relativeMountPoint = substr($mountPoint, $rootLength);
$results = $cache->$method($query);
foreach ($results as $result) {
$result['path'] = $relativeMountPoint . $result['path'];
$files[] = $result;
}
}
}
}
return $files;
}
/**
* get the ETag for a file or folder
*
* @param string $path
* @return string
*/
public function getETag($path) {
/**
* @var Storage\Storage $storage
* @var string $internalPath
*/
list($storage, $internalPath) = $this->resolvePath($path);
if ($storage) {
return $storage->getETag($internalPath);
} else {
return null;
}
}
/**
* Get the path of a file by id, relative to the view
*
* Note that the resulting path is not guarantied to be unique for the id, multiple paths can point to the same file
*
* @param int $id
* @return string
*/
public function getPath($id) {
list($storage, $internalPath) = Cache\Cache::getById($id);
$mounts = Mount::findById($storage);
foreach ($mounts as $mount) {
/**
* @var \OC\Files\Mount $mount
*/
$fullPath = $mount->getMountPoint() . $internalPath;
if (!is_null($path = $this->getRelativePath($fullPath))) {
return $path;
}
}
return null;
}
}

View File

@ -1,67 +0,0 @@
<?php
/**
* ownCloud
*
* @author Frank Karlitschek
* @copyright 2012 Frank Karlitschek frank@owncloud.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Provide a common interface to all different storage options
*/
abstract class OC_Filestorage{
abstract public function __construct($parameters);
abstract public function mkdir($path);
abstract public function rmdir($path);
abstract public function opendir($path);
abstract public function is_dir($path);
abstract public function is_file($path);
abstract public function stat($path);
abstract public function filetype($path);
abstract public function filesize($path);
abstract public function isCreatable($path);
abstract public function isReadable($path);
abstract public function isUpdatable($path);
abstract public function isDeletable($path);
abstract public function isSharable($path);
abstract public function file_exists($path);
abstract public function filectime($path);
abstract public function filemtime($path);
abstract public function file_get_contents($path);
abstract public function file_put_contents($path, $data);
abstract public function unlink($path);
abstract public function rename($path1, $path2);
abstract public function copy($path1, $path2);
abstract public function fopen($path, $mode);
abstract public function getMimeType($path);
abstract public function hash($type, $path, $raw = false);
abstract public function free_space($path);
abstract public function search($query);
abstract public function touch($path, $mtime=null);
abstract public function getLocalFile($path);// get a path to a local version of the file, whether the original file is local or remote
abstract public function getLocalFolder($path);// get a path to a local version of the folder, whether the original file is local or remote
/**
* check if a file or folder has been updated since $time
* @param int $time
* @return bool
*
* hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
* returning true for other changes in the folder is optional
*/
abstract public function hasUpdated($path, $time);
abstract public function getOwner($path);
}

View File

@ -1,17 +0,0 @@
<?php
/**
* local storage backnd in temporary folder for testing purpores
*/
class OC_Filestorage_Temporary extends OC_Filestorage_Local{
public function __construct($arguments) {
$this->datadir=OC_Helper::tmpFolder();
}
public function cleanUp() {
OC_Helper::rmdirr($this->datadir);
}
public function __destruct() {
$this->cleanUp();
}
}

Some files were not shown because too many files have changed in this diff Show More