Skip to content

Commit

Permalink
Merge pull request #21237 from owncloud/files-ui-webdav-upload
Browse files Browse the repository at this point in the history
Use Webdav PUT for uploads
  • Loading branch information
Vincent Petry authored Sep 6, 2016
2 parents 746e10b + a89f4f0 commit 3f99035
Show file tree
Hide file tree
Showing 16 changed files with 1,404 additions and 817 deletions.
51 changes: 51 additions & 0 deletions apps/dav/lib/Connector/Sabre/FilesPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
use OCP\Files\StorageNotAvailableException;
use OCP\IConfig;
use OCP\IRequest;
use Sabre\DAV\Exception\BadRequest;
use OCA\DAV\Connector\Sabre\Directory;

class FilesPlugin extends ServerPlugin {

Expand Down Expand Up @@ -155,6 +157,8 @@ public function initialize(\Sabre\DAV\Server $server) {
$this->server = $server;
$this->server->on('propFind', array($this, 'handleGetProperties'));
$this->server->on('propPatch', array($this, 'handleUpdateProperties'));
// RFC5995 to add file to the collection with a suggested name
$this->server->on('method:POST', [$this, 'httpPost']);
$this->server->on('afterBind', array($this, 'sendFileIdHeader'));
$this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
$this->server->on('afterMethod:GET', [$this,'httpGet']);
Expand Down Expand Up @@ -414,4 +418,51 @@ public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
}
}

/**
* POST operation on directories to create a new file
* with suggested name
*
* @param RequestInterface $request request object
* @param ResponseInterface $response response object
* @return null|false
*/
public function httpPost(RequestInterface $request, ResponseInterface $response) {
// TODO: move this to another plugin ?
if (!\OC::$CLI && !\OC::$server->getRequest()->passesCSRFCheck()) {
throw new BadRequest('Invalid CSRF token');
}

list($parentPath, $name) = \Sabre\HTTP\URLUtil::splitPath($request->getPath());

// Making sure the parent node exists and is a directory
$node = $this->tree->getNodeForPath($parentPath);

if ($node instanceof Directory) {
// no Add-Member found
if (empty($name) || $name[0] !== '&') {
// suggested name required
throw new BadRequest('Missing suggested file name');
}

$name = substr($name, 1);

if (empty($name)) {
// suggested name required
throw new BadRequest('Missing suggested file name');
}

// make sure the name is unique
$name = basename(\OC_Helper::buildNotExistingFileNameForView($parentPath, $name, $this->fileView));

$node->createFile($name, $request->getBodyAsStream());

list($parentUrl, ) = \Sabre\HTTP\URLUtil::splitPath($request->getUrl());

$response->setHeader('Content-Location', $parentUrl . '/' . rawurlencode($name));

// created
$response->setStatus(201);
return false;
}
}
}
85 changes: 83 additions & 2 deletions apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public function setUp() {
* @param string $class
* @return \PHPUnit_Framework_MockObject_MockObject
*/
private function createTestNode($class) {
private function createTestNode($class, $path = '/dummypath') {
$node = $this->getMockBuilder($class)
->disableOriginalConstructor()
->getMock();
Expand All @@ -119,7 +119,7 @@ private function createTestNode($class) {

$this->tree->expects($this->any())
->method('getNodeForPath')
->with('/dummypath')
->with($path)
->will($this->returnValue($node));

$node->expects($this->any())
Expand Down Expand Up @@ -550,4 +550,85 @@ public function testDownloadHeaders($isClumsyAgent, $contentDispositionHeader) {

$this->plugin->httpGet($request, $response);
}

public function postCreateFileProvider() {
$baseUrl = 'http://example.com/owncloud/remote.php/webdav/subdir/';
return [
['test.txt', 'some file.txt', 'some file.txt', $baseUrl . 'some%20file.txt'],
['some file.txt', 'some file.txt', 'some file (2).txt', $baseUrl . 'some%20file%20%282%29.txt'],
];
}

/**
* @dataProvider postCreateFileProvider
*/
public function testPostWithAddMember($existingFile, $wantedName, $deduplicatedName, $expectedLocation) {
$request = $this->getMock('Sabre\HTTP\RequestInterface');
$response = $this->getMock('Sabre\HTTP\ResponseInterface');

$request->expects($this->any())
->method('getUrl')
->will($this->returnValue('http://example.com/owncloud/remote.php/webdav/subdir/&' . $wantedName));

$request->expects($this->any())
->method('getPath')
->will($this->returnValue('/subdir/&' . $wantedName));

$request->expects($this->once())
->method('getBodyAsStream')
->will($this->returnValue(fopen('data://text/plain,hello', 'r')));

$this->view->expects($this->any())
->method('file_exists')
->will($this->returnCallback(function($path) use ($existingFile) {
return ($path === '/subdir/' . $existingFile);
}));

$node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory', '/subdir');

$node->expects($this->once())
->method('createFile')
->with($deduplicatedName, $this->isType('resource'));

$response->expects($this->once())
->method('setStatus')
->with(201);
$response->expects($this->once())
->method('setHeader')
->with('Content-Location', $expectedLocation);

$this->assertFalse($this->plugin->httpPost($request, $response));
}

public function testPostOnNonDirectory() {
$request = $this->getMock('Sabre\HTTP\RequestInterface');
$response = $this->getMock('Sabre\HTTP\ResponseInterface');

$request->expects($this->any())
->method('getPath')
->will($this->returnValue('/subdir/test.txt/&abc'));

$this->createTestNode('\OCA\DAV\Connector\Sabre\File', '/subdir/test.txt');

$this->assertNull($this->plugin->httpPost($request, $response));
}

/**
* @expectedException \Sabre\DAV\Exception\BadRequest
*/
public function testPostWithoutAddMember() {
$request = $this->getMock('Sabre\HTTP\RequestInterface');
$response = $this->getMock('Sabre\HTTP\ResponseInterface');

$request->expects($this->any())
->method('getPath')
->will($this->returnValue('/subdir/&'));

$node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory', '/subdir');

$node->expects($this->never())
->method('createFile');

$this->plugin->httpPost($request, $response);
}
}
Loading

0 comments on commit 3f99035

Please sign in to comment.