diff --git a/apps/dav/lib/Connector/Sabre/IFrameTransportPlugin.php b/apps/dav/lib/Connector/Sabre/IFrameTransportPlugin.php deleted file mode 100644 index af6e5a62a5..0000000000 --- a/apps/dav/lib/Connector/Sabre/IFrameTransportPlugin.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\DAV\Connector\Sabre; - -use Sabre\DAV\IFile; -use Sabre\HTTP\RequestInterface; -use Sabre\HTTP\ResponseInterface; -use Sabre\DAV\Exception\BadRequest; - -/** - * Plugin to receive Webdav PUT through POST, - * mostly used as a workaround for browsers that - * do not support PUT upload. - */ -class IFrameTransportPlugin extends \Sabre\DAV\ServerPlugin { - - /** - * @var \Sabre\DAV\Server $server - */ - private $server; - - /** - * This initializes the plugin. - * - * @param \Sabre\DAV\Server $server - * @return void - */ - public function initialize(\Sabre\DAV\Server $server) { - $this->server = $server; - $this->server->on('method:POST', [$this, 'handlePost']); - } - - /** - * POST operation - * - * @param RequestInterface $request request object - * @param ResponseInterface $response response object - * @return null|false - */ - public function handlePost(RequestInterface $request, ResponseInterface $response) { - try { - return $this->processUpload($request, $response); - } catch (\Sabre\DAV\Exception $e) { - $response->setStatus($e->getHTTPCode()); - $response->setBody(['message' => $e->getMessage()]); - $this->convertResponse($response); - return false; - } - } - - /** - * Wrap and send response in JSON format - * - * @param ResponseInterface $response response object - */ - private function convertResponse(ResponseInterface $response) { - if (is_resource($response->getBody())) { - throw new BadRequest('Cannot request binary data with iframe transport'); - } - - $responseData = json_encode([ - 'status' => $response->getStatus(), - 'headers' => $response->getHeaders(), - 'data' => $response->getBody(), - ]); - - // IE needs this content type - $response->setHeader('Content-Type', 'text/plain'); - $response->setHeader('Content-Length', strlen($responseData)); - $response->setStatus(200); - $response->setBody($responseData); - } - - /** - * Process upload - * - * @param RequestInterface $request request object - * @param ResponseInterface $response response object - * @return null|false - */ - private function processUpload(RequestInterface $request, ResponseInterface $response) { - $queryParams = $request->getQueryParameters(); - - if (!isset($queryParams['_method'])) { - return null; - } - - $method = $queryParams['_method']; - if ($method !== 'PUT' && $method !== 'POST') { - return null; - } - - $contentType = $request->getHeader('Content-Type'); - list($contentType) = explode(';', $contentType); - if ($contentType !== 'application/x-www-form-urlencoded' - && $contentType !== 'multipart/form-data' - ) { - return null; - } - - if (!isset($_FILES['files'])) { - return null; - } - - // TODO: move this to another plugin ? - if (!\OC::$CLI && !\OC::$server->getRequest()->passesCSRFCheck()) { - throw new BadRequest('Invalid CSRF token'); - } - - if ($_FILES) { - $file = current($_FILES); - } else { - return null; - } - - if ($file['error'][0] !== 0) { - throw new BadRequest('Error during upload, code ' . $file['error'][0]); - } - - if (!\OC::$CLI && !is_uploaded_file($file['tmp_name'][0])) { - return null; - } - - if (count($file['tmp_name']) > 1) { - throw new BadRequest('Only a single file can be uploaded'); - } - - $postData = $request->getPostData(); - if (isset($postData['headers'])) { - $headers = json_decode($postData['headers'], true); - - // copy safe headers into the request - $allowedHeaders = [ - 'If', - 'If-Match', - 'If-None-Match', - 'If-Modified-Since', - 'If-Unmodified-Since', - 'Authorization', - ]; - - foreach ($allowedHeaders as $allowedHeader) { - if (isset($headers[$allowedHeader])) { - $request->setHeader($allowedHeader, $headers[$allowedHeader]); - } - } - } - - // MEGAHACK, because the Sabre File impl reads this property directly - $_SERVER['CONTENT_LENGTH'] = $file['size'][0]; - $request->setHeader('Content-Length', $file['size'][0]); - - $tmpFile = $file['tmp_name'][0]; - $resource = fopen($tmpFile, 'r'); - - $request->setBody($resource); - $request->setMethod($method); - - $this->server->invokeMethod($request, $response, false); - - fclose($resource); - unlink($tmpFile); - - $this->convertResponse($response); - - return false; - } - -} diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php index da541abc19..6d9f9b1bc8 100644 --- a/apps/dav/lib/Connector/Sabre/ServerFactory.php +++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php @@ -114,7 +114,6 @@ class ServerFactory { // FIXME: The following line is a workaround for legacy components relying on being able to send a GET to / $server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin()); $server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger)); - $server->addPlugin(new \OCA\DAV\Connector\Sabre\IFrameTransportPlugin()); $server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin()); // Some WebDAV clients do require Class 2 WebDAV support (locking), since // we do not provide locking we emulate it using a fake locking plugin. diff --git a/apps/dav/tests/unit/Connector/Sabre/IFrameTransportPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/IFrameTransportPluginTest.php deleted file mode 100644 index 485dd1b779..0000000000 --- a/apps/dav/tests/unit/Connector/Sabre/IFrameTransportPluginTest.php +++ /dev/null @@ -1,164 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ -class IFrameTransportPluginTest extends \Test\TestCase { - - /** - * @var \Sabre\DAV\Server - */ - private $server; - - /** - * @var \OCA\DAV\Connector\Sabre\IFrameTransportPlugin - */ - private $plugin; - - public function setUp() { - parent::setUp(); - $this->server = $this->getMockBuilder('\Sabre\DAV\Server') - ->disableOriginalConstructor() - ->getMock(); - - $this->plugin = new \OCA\DAV\Connector\Sabre\IFrameTransportPlugin(); - $this->plugin->initialize($this->server); - } - - public function tearDown() { - $_FILES = null; - unset($_SERVER['CONTENT_LENGTH']); - } - - public function testPutConversion() { - $request = $this->getMock('Sabre\HTTP\RequestInterface'); - $response = $this->getMock('Sabre\HTTP\ResponseInterface'); - - $request->expects($this->once()) - ->method('getQueryParameters') - ->will($this->returnValue(['_method' => 'PUT'])); - - $postData = [ - 'headers' => json_encode([ - 'If-None-Match' => '*', - 'Disallowed-Header' => 'test', - ]), - ]; - - $request->expects($this->once()) - ->method('getPostData') - ->will($this->returnValue($postData)); - - $request->expects($this->once()) - ->method('getHeader') - ->with('Content-Type') - ->will($this->returnValue('multipart/form-data')); - - $tmpFileName = tempnam(sys_get_temp_dir(), 'tmpfile'); - $fh = fopen($tmpFileName, 'w'); - fwrite($fh, 'hello'); - fclose($fh); - - $_FILES = ['files' => [ - 'error' => [0], - 'tmp_name' => [$tmpFileName], - 'size' => [5], - ]]; - - $request->expects($this->any()) - ->method('setHeader') - ->withConsecutive( - ['If-None-Match', '*'], - ['Content-Length', 5] - ); - - $request->expects($this->once()) - ->method('setMethod') - ->with('PUT'); - - $this->server->expects($this->once()) - ->method('invokeMethod') - ->with($request, $response); - - // response data before conversion - $response->expects($this->once()) - ->method('getHeaders') - ->will($this->returnValue(['Test-Response-Header' => [123]])); - - $response->expects($this->any()) - ->method('getBody') - ->will($this->returnValue('test')); - - $response->expects($this->once()) - ->method('getStatus') - ->will($this->returnValue(201)); - - $responseBody = json_encode([ - 'status' => 201, - 'headers' => ['Test-Response-Header' => [123]], - 'data' => 'test', - ]); - - // response data after conversion - $response->expects($this->once()) - ->method('setBody') - ->with($responseBody); - - $response->expects($this->once()) - ->method('setStatus') - ->with(200); - - $response->expects($this->any()) - ->method('setHeader') - ->withConsecutive( - ['Content-Type', 'text/plain'], - ['Content-Length', strlen($responseBody)] - ); - - $this->assertFalse($this->plugin->handlePost($request, $response)); - - $this->assertEquals(5, $_SERVER['CONTENT_LENGTH']); - - $this->assertFalse(file_exists($tmpFileName)); - } - - public function testIgnoreNonPut() { - $request = $this->getMock('Sabre\HTTP\RequestInterface'); - $response = $this->getMock('Sabre\HTTP\ResponseInterface'); - - $request->expects($this->once()) - ->method('getQueryParameters') - ->will($this->returnValue(['_method' => 'PROPFIND'])); - - $this->server->expects($this->never()) - ->method('invokeMethod') - ->with($request, $response); - - $this->assertNull($this->plugin->handlePost($request, $response)); - } - - public function testIgnoreMismatchedContentType() { - $request = $this->getMock('Sabre\HTTP\RequestInterface'); - $response = $this->getMock('Sabre\HTTP\ResponseInterface'); - - $request->expects($this->once()) - ->method('getQueryParameters') - ->will($this->returnValue(['_method' => 'PUT'])); - - $request->expects($this->once()) - ->method('getHeader') - ->with('Content-Type') - ->will($this->returnValue('text/plain')); - - $this->server->expects($this->never()) - ->method('invokeMethod') - ->with($request, $response); - - $this->assertNull($this->plugin->handlePost($request, $response)); - } -}