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
18 changes: 11 additions & 7 deletions apps/dav/lib/Connector/Sabre/Directory.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
use Sabre\DAV\Exception\BadRequest;
use OC\Files\Mount\MoveableMount;
use Sabre\DAV\IFile;
use OCA\DAV\Upload\FutureFile;

class Directory extends \OCA\DAV\Connector\Sabre\Node
implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget {
Expand Down Expand Up @@ -125,18 +126,21 @@ public function createFile($name, $data = null) {
throw new \Sabre\DAV\Exception\Forbidden();
}

// for chunked upload also updating a existing file is a "createFile"
// because we create all the chunks before re-assemble them to the existing file.
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
$info = false;
if (\OC_FileChunking::isWebdavChunk()) {
// For chunked upload also updating a existing file is a "createFile"
// because we create all the chunks before re-assemble them to the existing file.

// exit if we can't create a new file and we don't updatable existing file
// exit if we can't create a new file and we don't update existing file
$chunkInfo = \OC_FileChunking::decodeName($name);
if (!$this->fileView->isCreatable($this->path) &&
!$this->fileView->isUpdatable($this->path . '/' . $chunkInfo['name'])
) {
throw new \Sabre\DAV\Exception\Forbidden();
}

} else if (FutureFile::isFutureFile()) {
// Future file (chunked upload) requires fileinfo
$info = $this->fileView->getFileInfo($this->path . '/' . $name);
} else {
// For non-chunked upload it is enough to check if we can create a new file
if (!$this->fileView->isCreatable($this->path)) {
Expand All @@ -147,12 +151,12 @@ public function createFile($name, $data = null) {
$this->fileView->verifyPath($this->path, $name);

$path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
// in case the file already exists/overwriting
$info = $this->fileView->getFileInfo($this->path . '/' . $name);

if (!$info) {
// use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
$info = new \OC\Files\FileInfo($path, null, null, [], null);
}

$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
$node->acquireLock(ILockingProvider::LOCK_SHARED);
return $node->put($data);
Expand Down
2 changes: 1 addition & 1 deletion apps/dav/lib/Connector/Sabre/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public function put($data) {
$this->verifyPath();

// chunked handling
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
if (\OC_FileChunking::isWebdavChunk()) {
try {
return $this->createFileChunked($data);
} catch (\Exception $e) {
Expand Down
2 changes: 1 addition & 1 deletion apps/dav/lib/Connector/Sabre/FilesPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ public function handleUpdateProperties($path, PropPatch $propPatch) {
*/
public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
// chunked upload handling
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
if (\OC_FileChunking::isWebdavChunk()) {
list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
$info = \OC_FileChunking::decodeName($name);
if (!empty($info)) {
Expand Down
4 changes: 2 additions & 2 deletions apps/dav/lib/Connector/Sabre/LockPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function initialize(\Sabre\DAV\Server $server) {
public function getLock(RequestInterface $request) {
// we can't listen on 'beforeMethod:PUT' due to order of operations with setting up the tree
// so instead we limit ourselves to the PUT method manually
if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
if ($request->getMethod() !== 'PUT' || \OC_FileChunking::isWebdavChunk()) {
return;
}
try {
Expand All @@ -69,7 +69,7 @@ public function getLock(RequestInterface $request) {
}

public function releaseLock(RequestInterface $request) {
if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) {
if ($request->getMethod() !== 'PUT' || \OC_FileChunking::isWebdavChunk()) {
return;
}
try {
Expand Down
21 changes: 19 additions & 2 deletions apps/dav/lib/Connector/Sabre/ObjectTree.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\File
* @return string path to real file
*/
private function resolveChunkFile($path) {
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
if (\OC_FileChunking::isWebdavChunk()) {
// resolve to real file name to find the proper node
list($dir, $name) = \Sabre\HTTP\URLUtil::splitPath($path);
if ($dir == '/' || $dir == '.') {
Expand All @@ -99,6 +99,22 @@ public function cacheNode(Node $node) {
$this->cache[trim($node->getPath(), '/')] = $node;
}

/**
* This function allows you to check if a node exists.
*
* @param string $path
* @return bool
*/
function nodeExists($path) {
$path = trim($path, '/');
if (isset($this->cache[$path]) && $this->cache[$path] === false){
// Node is not existing, as it was explicitely set in the cache
// Next call to getNodeForPath will create cache instance and unset the cached value
return false;
}
return parent::nodeExists($path);
}

/**
* Returns the INode object for the requested path
*
Expand All @@ -122,7 +138,7 @@ public function getNodeForPath($path) {

$path = trim($path, '/');

if (isset($this->cache[$path])) {
if (isset($this->cache[$path]) && $this->cache[$path] !== false) {
return $this->cache[$path];
}

Expand Down Expand Up @@ -179,6 +195,7 @@ public function getNodeForPath($path) {
}

if (!$info) {
$this->cache[$path] = false;
throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
}

Expand Down
17 changes: 17 additions & 0 deletions apps/dav/lib/Upload/FutureFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ class FutureFile implements \Sabre\DAV\IFile {
/** @var string */
private $name;

static public function getFutureFileName() {
return '.file';
}

static public function isFutureFile() {
$davUploadsTarget = '/dav/uploads';

// Check if pathinfo starts with dav uploads target and basename is future file basename
if (isset($_SERVER['PATH_INFO'])
&& pathinfo($_SERVER['PATH_INFO'], PATHINFO_BASENAME) === FutureFile::getFutureFileName()
&& (strpos($_SERVER['PATH_INFO'], $davUploadsTarget) === 0)) {
return true;
}

return false;
}

/**
* @param Directory $root
* @param string $name
Expand Down
8 changes: 4 additions & 4 deletions apps/dav/lib/Upload/UploadFolder.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,20 @@ function createDirectory($name) {
}

function getChild($name) {
if ($name === '.file') {
return new FutureFile($this->node, '.file');
if ($name === FutureFile::getFutureFileName()) {
return new FutureFile($this->node, FutureFile::getFutureFileName());
}
return $this->node->getChild($name);
}

function getChildren() {
$children = $this->node->getChildren();
$children[] = new FutureFile($this->node, '.file');
$children[] = new FutureFile($this->node, FutureFile::getFutureFileName());
return $children;
}

function childExists($name) {
if ($name === '.file') {
if ($name === FutureFile::getFutureFileName()) {
return true;
}
return $this->node->childExists($name);
Expand Down
7 changes: 7 additions & 0 deletions lib/private/legacy/filechunking.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ class OC_FileChunking {
*/
protected $ttl;

static public function isWebdavChunk() {
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
return true;
}
return false;
}

static public function decodeName($name) {
preg_match('/(?P<name>.*)-chunking-(?P<transferid>\d+)-(?P<chunkcount>\d+)-(?P<index>\d+)/', $name, $matches);
return $matches;
Expand Down