Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/files_sharing/appinfo/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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";
OC::$CLASSPATH['OC_Files_Sharing_Util'] = "apps/files_sharing/lib/util.php";
OCP\Util::connectHook('OC_Filesystem', 'setup', 'OC_Filestorage_Shared', 'setup');
OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
Expand Down
36 changes: 28 additions & 8 deletions apps/files_sharing/lib/sharedstorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,14 @@ public function mkdir($path) {
if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) {
return false;
} else if ($source = $this->getSourcePath($path)) {
$parts = explode('/', $source, 4);
$user = $parts[1];
$intPath = '/'.$parts[3];
$storage = OC_Filesystem::getStorage($source);
return $storage->mkdir($this->getInternalPath($source));
if( ($storage->mkdir($this->getInternalPath($source))) ) {
OC_FileCache::put($intPath ,array('user'=>$user), '/'.$user.'/files');
return true;
}
}
return false;
}
Expand Down Expand Up @@ -296,10 +302,15 @@ public function file_put_contents($path, $data) {
'target' => $this->sharedFolder.$path,
'source' => $source,
);
OCP\Util::emitHook('OC_Filestorage_Shared', 'file_put_contents', $info);
OCP\Util::emitHook('OC_Filestorage_Shared', 'file_put_contents', $info);
$parts = explode('/', $source, 4);
$user = $parts[1];
$intPath = '/'.$parts[3];
$storage = OC_Filesystem::getStorage($source);
$result = $storage->file_put_contents($this->getInternalPath($source), $data);
return $result;
if( ( $result = $storage->file_put_contents($this->getInternalPath($source), $data) ) ) {
OC_FileCache::put($intPath ,array('user'=>$user), '/'.$user.'/files');
return $result;
}
}
return false;
}
Expand Down Expand Up @@ -368,17 +379,18 @@ public function copy($path1, $path2) {

public function fopen($path, $mode) {
if ($source = $this->getSourcePath($path)) {
$write = false;
switch ($mode) {
case 'w':
case 'wb':
case 'w+':
case 'wb+': $write = true;
case 'r+':
case 'rb+':
case 'w+':
case 'wb+':
case 'x+':
case 'xb+':
case 'a+':
case 'ab+':
case 'w':
case 'wb':
case 'x':
case 'xb':
case 'a':
Expand All @@ -394,6 +406,14 @@ public function fopen($path, $mode) {
);
OCP\Util::emitHook('OC_Filestorage_Shared', 'fopen', $info);
$storage = OC_Filesystem::getStorage($source);

$parts = explode('/', $source, 4);
$user = $parts[1];
$intPath = '/'.$parts[3];

if ( $write && $storage->touch($this->getInternalPath($source)) ) {
OC_FileCache::put($intPath ,array('user'=>$user), '/'.$user.'/files');
}
return $storage->fopen($this->getInternalPath($source), $mode);
}
return false;
Expand Down
79 changes: 79 additions & 0 deletions apps/files_sharing/lib/util.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/**
* ownCloud
*
* @author Bjoern Schiessle
* @copyright 2012 Bjoern Schiessle schiessle@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/>.
*
*/


class OC_Files_Sharing_Util {

private static $files = array();

/**
* @brief Get the source file path and the permissions granted for a shared file
* @param string Shared target file path
* @return Returns array with the keys path and permissions or false if not found
*/
private static function getFile($target) {
$target = '/'.$target;
$target = rtrim($target, '/');
if (isset(self::$files[$target])) {
return self::$files[$target];
} else {
$pos = strpos($target, '/', 1);
// Get shared folder name
if ($pos !== false) {
$folder = substr($target, 0, $pos);
if (isset(self::$files[$folder])) {
$file = self::$files[$folder];
} else {
$file = OCP\Share::getItemSharedWith('folder', $folder, OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
}
if ($file) {
self::$files[$target]['path'] = $file['path'].substr($target, strlen($folder));
self::$files[$target]['permissions'] = $file['permissions'];
return self::$files[$target];
}
} else {
$file = OCP\Share::getItemSharedWith('file', $target, OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
if ($file) {
self::$files[$target] = $file;
return self::$files[$target];
}
}
OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, OCP\Util::ERROR);
return false;
}
}

/**
* @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
*/
public static function getSourcePath($target) {
$file = self::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'];
}
return false;
}
}
10 changes: 7 additions & 3 deletions lib/connector/sabre/directory.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,20 @@ public function getChild($name, $info = null) {
*/
public function getChildren() {

$source = $this->getFileSource($this->path);
$path = $source['path'];
$user = $source['user'];

$folder_content = OC_Files::getDirectoryContent($this->path);
$paths = array();
foreach($folder_content as $info) {
$paths[] = $this->path.'/'.$info['name'];
$paths[] = $path.'/'.$info['name'];
}
$properties = array_fill_keys($paths, array());
if(count($paths)>0) {
$placeholders = join(',', array_fill(0, count($paths), '?'));
$query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' );
array_unshift($paths, OC_User::getUser()); // prepend userid
array_unshift($paths, $user); // prepend userid
$result = $query->execute( $paths );
while($row = $result->fetchRow()) {
$propertypath = $row['propertypath'];
Expand All @@ -139,7 +143,7 @@ public function getChildren() {
$nodes = array();
foreach($folder_content as $info) {
$node = $this->getChild($info['name'], $info);
$node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
$node->setPropertyCache($properties[$path.'/'.$info['name']]);
$nodes[] = $node;
}
return $nodes;
Expand Down
47 changes: 39 additions & 8 deletions lib/connector/sabre/node.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,16 @@ public function touch($mtime) {
* @return bool|array
*/
public function updateProperties($properties) {
// get source path of shared files
$source = self::getFileSource($this->path);

$existing = $this->getProperties(array());
foreach($properties as $propertyName => $propertyValue) {
// If it was null, we need to delete the property
if (is_null($propertyValue)) {
if(array_key_exists( $propertyName, $existing )) {
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
$query->execute( array( OC_User::getUser(), $this->path, $propertyName ));
$query->execute( array( $source['user'], $source['path'], $propertyName ));
}
}
else {
Expand All @@ -163,10 +166,10 @@ public function updateProperties($properties) {
} 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( $source['user'], $source['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, $source['user'], $source['path'], $propertyName ));
}
}
}
Expand All @@ -188,16 +191,19 @@ public function updateProperties($properties) {
* @return array
*/
public function getProperties($properties) {
if (is_null($this->property_cache)) {

$source = self::getFileSource($this->path);

if (is_null($this->property_cache) || empty($this->property_cache)) {
$query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?' );
$result = $query->execute( array( OC_User::getUser(), $this->path ));
$result = $query->execute( array( $source['user'], $source['path'] ));

$this->property_cache = array();
while( $row = $result->fetchRow()) {
$this->property_cache[$row['propertyname']] = $row['propertyvalue'];
}
}

// if the array was empty, we need to return everything
if(count($properties) == 0) {
return $this->property_cache;
Expand Down Expand Up @@ -234,9 +240,12 @@ static public function getETagPropertyForPath($path) {
if (empty($tag)) {
return null;
}

$source = self::getFileSource($path);

$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 ));
$query->execute( array( $source['user'], $source['path'], self::GETETAG_PROPERTYNAME, $etag ));
return $etag;
}

Expand All @@ -246,6 +255,9 @@ static public function getETagPropertyForPath($path) {
*/
static public function removeETagPropertyForPath($path) {
// remove tags from this and parent paths
$source = self::getFileSource($path);
$path = $source['path'];

$paths = array();
while ($path != '/' && $path != '.' && $path != '' && $path != '\\') {
$paths[] = $path;
Expand All @@ -261,7 +273,26 @@ static public function removeETagPropertyForPath($path) {
.' AND `propertyname` = ?'
.' AND `propertypath` IN ('.$path_placeholders.')'
);
$vals = array( OC_User::getUser(), self::GETETAG_PROPERTYNAME );
$vals = array( $source['user'], self::GETETAG_PROPERTYNAME );
$query->execute(array_merge( $vals, $paths ));

//remove etag for all Shared folders
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
.' WHERE `propertypath` = "/Shared"'
);
$query->execute(array());

}

protected static function getFileSource($path) {
if ( OC_App::isEnabled('files_sharing') && !strncmp($path, '/Shared/', 8)) {
$source = OC_Files_Sharing_Util::getSourcePath(str_replace('/Shared/', '', $path));
$parts = explode('/', $source, 4);
$user = $parts[1];
$path = '/'.$parts[3];
} else {
$user = OC_User::getUser();
}
return(array('user' => $user, 'path' => $path));
}
}
12 changes: 8 additions & 4 deletions lib/filecache.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public static function put($path,$data,$root=false) {

// add parent directory to the file cache if it does not exist yet.
if ($parent == -1 && $fullpath != $root) {
$parentDir = dirname($path);
self::scanFile($parentDir);
$parentDir = dirname(OC_Filesystem::normalizePath($path));
self::scanFile($parentDir, $root);
$parent = self::getParentId($fullpath);
}

Expand All @@ -94,15 +94,19 @@ public static function put($path,$data,$root=false) {
if(!isset($data['versioned'])) {
$data['versioned']=false;
}
if(!isset($data['user'])) {
$data['user']=OC_User::getUser();
}


$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']));
$result=$query->execute(array($parent,basename($fullpath),$fullpath,md5($fullpath),$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$data['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);
}
Expand Down