aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/BundleUpload/MultipartContentsParser.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/lib/BundleUpload/MultipartContentsParser.php')
-rw-r--r--apps/dav/lib/BundleUpload/MultipartContentsParser.php497
1 files changed, 0 insertions, 497 deletions
diff --git a/apps/dav/lib/BundleUpload/MultipartContentsParser.php b/apps/dav/lib/BundleUpload/MultipartContentsParser.php
deleted file mode 100644
index 93b24539c49..00000000000
--- a/apps/dav/lib/BundleUpload/MultipartContentsParser.php
+++ /dev/null
@@ -1,497 +0,0 @@
-<?php
-/**
- * @author Piotr Mrowczynski <Piotr.Mrowczynski@owncloud.com>
- * @author Louis Chemineau <louis@chmn.me>
- *
- * @copyright Copyright (c) 2016, ownCloud GmbH.
- * @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 <http://www.gnu.org/licenses/>
- *
- */
-namespace OCA\DAV\BundleUpload;
-
-use Exception;
-use Sabre\HTTP\RequestInterface;
-use Sabre\DAV\Exception\BadRequest;
-
-/**
- * This class is used to parse multipart/related HTTP message according to RFC http://www.rfc-archive.org/getrfc.php?rfc=2387
- * This class requires a message to contain Content-length parameters, which is used in high performance reading of file contents.
- */
-
-class MultipartContentsParser {
- /**
- * @var \Sabre\HTTP\RequestInterface
- */
- // private $request;
-
- /** @var resource */
- private $stream = null;
-
- /** @var string */
- private $boundary = "";
- private $lastBoundary = "";
-
- /**
- * @var Bool
- */
- // private $endDelimiterReached = false;
-
- /**
- * Constructor.
- */
- public function __construct(RequestInterface $request) {
- $this->stream = $request->getBody();
- if (gettype($this->stream) !== 'resource') {
- throw new BadRequest('Wrong body type');
- }
-
- $this->boundary = '--'.$this->getBoundary($request->getHeader('Content-Type'))."\r\n";
- $this->lastBoundary = '--'.$this->getBoundary($request->getHeader('Content-Type'))."--\r\n";
- }
-
- /**
- * Parse the boundary from a Content-Type header
- *
- * @throws \Sabre\DAV\Exception\BadRequest
- */
- private function getBoundary(string $contentType) {
- // Making sure the end node exists
- //TODO: add support for user creation if that is first sync. Currently user has to be created.
- // $this->userFilesHome = $this->request->getPath();
- // $userFilesHomeNode = $this->server->tree->getNodeForPath($this->userFilesHome);
- // if (!($userFilesHomeNode instanceof FilesHome)){
- // throw new Forbidden('URL endpoint has to be instance of \OCA\DAV\Files\FilesHome');
- // }
-
- // $headers = array('Content-Type');
- // foreach ($headers as $header) {
- // $value = $this->request->getHeader($header);
- // if ($value === null) {
- // throw new Forbidden(sprintf('%s header is needed', $header));
- // } elseif (!is_int($value) && empty($value)) {
- // throw new Forbidden(sprintf('%s header must not be empty', $header));
- // }
- // }
-
- // Validate content-type
- // Ex: Content-Type: "multipart/related; boundary=boundary_bf38b9b4b10a303a28ed075624db3978"
- [$mimeType, $boundary] = explode(';', $contentType);
-
- if (trim($mimeType) !== 'multipart/related') {
- throw new BadRequest('Content-Type must be multipart/related');
- }
-
- // Validate boundary
- [$key, $value] = explode('=', $boundary);
- if (trim($key) !== 'boundary') {
- throw new BadRequest('Boundary is invalid');
- }
-
- $value=trim($value);
-
- // Remove potential quotes around boundary value
- if (substr($value, 0, 1) == '"' && substr($value, -1) == '"') {
- $value = substr($value, 1, -1);
- }
-
- return $value;
- }
-
- /**
- * Get a line.
- *
- * If false is return, it's the end of file.
- *
- * @throws \Sabre\DAV\Exception\BadRequest
- */
- // public function gets() {
- // $content = $this->getContent();
- // if (!is_resource($content)) {
- // throw new BadRequest('Unable to get request content');
- // }
-
- // return fgets($content);
- // }
-
- /**
- */
- // public function getCursor() {
- // return ftell($this->getContent());
- // }
-
- /**
- */
- // public function getEndDelimiterReached() {
- // return $this->endDelimiterReached;
- // }
-
- /**
- * Return if end of file.
- */
- public function eof() {
- return feof($this->stream);
- }
-
- /**
- * Seeks to offset of some file contentLength from the current cursor position in the
- * multipartContent.
- *
- * Return true on success and false on failure
- */
- // public function multipartContentSeekToContentLength(int $contentLength) {
- // return (fseek($this->getContent(), $contentLength, SEEK_CUR) === 0 ? true : false);
- // }
-
- /**
- * Get request content.
- *
- * @throws \Sabre\DAV\Exception\BadRequest
- *
- * @return resource
- */
- // public function getContent() {
- // if ($this->stream === null) {
- // // Pass body by reference, so other objects can have global access
- // $content = $this->request->getBody();
-
- // if (!$this->stream) {
- // throw new BadRequest('Unable to get request content');
- // }
-
- // if (gettype($this->stream) !== 'resource') {
- // throw new BadRequest('Wrong body type');
- // }
-
- // $this->stream = $content;
- // }
-
- // return $this->stream;
- // }
-
- // public function getBoundary(string $boundary) {
- // return "\r\n--$boundary\r\n";
- // }
-
- public function checkBoundary(string $boundary, string $line) {
- if ($line !== $boundary) {
- throw new Exception("Invalid boundary, is '$line', should be '$this->boundary'.");
- }
-
- return true;
- }
-
- public function lastBoundary() {
- $content = fread($this->stream, strlen($this->lastBoundary));
- $result = fseek($this->stream, -strlen($this->lastBoundary), SEEK_CUR);
-
- if ($result === -1) {
- throw new Exception("Unknown error while seeking content");
- }
-
- return $content === $this->lastBoundary;
- }
-
- /**
- * Return the next part of the request.
- *
- * @throws Exception
- */
- public function readNextPart(int $length = 0) {
- $this->checkBoundary($this->boundary, fread($this->stream, strlen($this->boundary)));
-
- $headers = $this->readPartHeaders();
-
- if ($length === 0 && isset($headers["content-length"])) {
- $length = $headers["content-length"];
- }
-
- if ($length === 0) {
- throw new Exception("Part cannot be of length 0.");
- }
-
- $content = $this->readPartContent2($length);
-
- return [$headers, $content];
- }
-
- /**
- * Return the next part of the request.
- *
- * @throws Exception
- */
- public function readNextStream() {
- $this->checkBoundary($this->boundary, fread($this->stream, strlen($this->boundary)));
-
- $headers = $this->readPartHeaders();
-
- return [$headers, $this->stream];
- }
-
- /**
- * Return the headers of a part of the request.
- *
- * @throws \Sabre\DAV\Exception\BadRequest
- * @throws Exception
- */
- public function readPartHeaders() {
- $headers = [];
- $blankLineCount = 0;
-
- while($blankLineCount < 1) {
- $line = fgets($this->stream);
-
- if ($line === false) {
- throw new Exception('An error appears while reading headers of a part');
- }
-
- if ($line === "\r\n") {
- break;
- }
-
- try {
- [$key, $value] = explode(':', $line, 2);
- $headers[strtolower(trim($key))] = trim($value);
- } catch (Exception $e) {
- throw new BadRequest('An error appears while parsing headers of a part', $e);
- }
- }
-
- return $headers;
- }
-
- /**
- * Return the content of the current part of the stream.
- *
- * @throws \Sabre\DAV\Exception\BadRequest
- * @throws Exception
- */
- public function readPartContent() {
- $line = '';
- $content = '';
-
- do {
- $content .= $line;
-
- if (feof($this->stream)) {
- throw new BadRequest("Unexpected EOF while reading stream.");
- }
-
- $line = fgets($this->stream);
-
- if ($line === false) {
- throw new Exception("Fail to read part's content.");
- }
- } while ($line !== $this->boundary);
-
- // We need to be before $boundary for the next parsing.
- $result = fseek($this->stream, -strlen($this->boundary), SEEK_CUR);
-
- if ($result === -1) {
- throw new Exception("Fail to seek upstream.");
- }
-
- // Remove the extra new line "\r\n" that is not part of the content
- return substr($content, 0, -2);
- }
-
- public function readPartContent2(int $length) {
- // Read stream until file's $length, EOF or $boundary is reached
- $content = stream_get_line($this->stream, $length);
-
- if ($content === false) {
- throw new Exception("Fail to read part's content.");
- }
-
- if (feof($this->stream)) {
- throw new Exception("Unexpected EOF while reading stream.");
- }
-
- stream_get_contents($this->stream, 2);
-
- return $content;
- }
-
- public function getContentPosition() {
- return ftell($this->stream);
- }
-
- public function getMetadata() {
- fseek($this->stream, 0);
- return $this->readNextPart();
- }
-
- public function getContent(int $pos, int $length) {
- $previousPos = ftell($this->stream);
-
- $content = stream_get_contents($this->stream, $length, $pos);
-
- fseek($this->stream, $previousPos);
-
- return $content;
- }
-
- /**
- * Get a part of request separated by boundary $boundary.
- *
- * If this method returns an exception, it means whole request has to be abandoned,
- * Request part without correct headers might corrupt the message and parsing is impossible
- *
- * @throws \Exception
- */
- // public function getPartHeaders(string $boundary) {
- // $delimiter = '--'.$boundary."\r\n";
- // $endDelimiter = '--'.$boundary.'--';
- // $boundaryCount = 0;
- // $content = '';
- // $headers = null;
-
- // while (!$this->eof()) {
- // $line = $this->gets();
- // if ($line === false) {
- // if ($boundaryCount == 0) {
- // // Empty part, ignore
- // break;
- // }
- // else{
- // throw new \Exception('An error appears while reading and parsing header of content part using fgets');
- // }
- // }
-
- // if ($boundaryCount == 0) {
- // if ($line != $delimiter) {
- // if ($this->getCursor() == strlen($line)) {
- // throw new \Exception('Expected boundary delimiter in content part - this is not a multipart request');
- // }
- // elseif ($line == $endDelimiter || $line == $endDelimiter."\r\n") {
- // $this->endDelimiterReached = true;
- // break;
- // }
- // elseif ($line == "\r\n") {
- // continue;
- // }
- // } else {
- // continue;
- // }
- // // At this point we know, that first line was boundary
- // $boundaryCount++;
- // }
- // elseif ($boundaryCount == 1 && $line == "\r\n"){
- // //header-end according to RFC
- // $content .= $line;
- // $headers = $this->readHeaders($content);
- // break;
- // }
- // elseif ($line == $endDelimiter || $line == $endDelimiter."\r\n") {
- // $this->endDelimiterReached = true;
- // break;
- // }
-
- // $content .= $line;
- // }
-
- // if ($this->eof()){
- // $this->endDelimiterReached = true;
- // }
-
- // return $headers;
- // }
-
- /**
- * Read the contents from the current file pointer to the specified length
- *
- * @throws \Sabre\DAV\Exception\BadRequest
- */
- // public function streamReadToString(int $length) {
- // if ($length<0) {
- // throw new BadRequest('Method streamRead cannot read contents with negative length');
- // }
- // $source = $this->getContent();
- // $bufChunkSize = 8192;
- // $count = $length;
- // $buf = '';
-
- // while ($count!=0) {
- // $bufSize = (($count - $bufChunkSize)<0) ? $count : $bufChunkSize;
- // $buf .= fread($source, $bufSize);
- // $count -= $bufSize;
- // }
-
- // $bytesWritten = strlen($buf);
- // if ($length != $bytesWritten){
- // throw new BadRequest('Method streamRead read '.$bytesWritten.' expected '.$length);
- // }
- // return $buf;
- // }
-
- /**
- * Read the contents from the current file pointer to the specified length and pass
- *
- * @param resource $target
- *
- * @throws \Sabre\DAV\Exception\BadRequest
- */
- // public function streamReadToStream($target, int $length) {
- // if ($length<0) {
- // throw new BadRequest('Method streamRead cannot read contents with negative length');
- // }
- // $source = $this->getContent();
- // $bufChunkSize = 8192;
- // $count = $length;
- // $returnStatus = true;
-
- // while ($count!=0) {
- // $bufSize = (($count - $bufChunkSize)<0) ? $count : $bufChunkSize;
- // $buf = fread($source, $bufSize);
- // $bytesWritten = fwrite($target, $buf);
-
- // // note: strlen is expensive so only use it when necessary,
- // // on the last block
- // if ($bytesWritten === false
- // || ($bytesWritten < $bufSize)
- // ) {
- // // write error, could be disk full ?
- // $returnStatus = false;
- // break;
- // }
- // $count -= $bufSize;
- // }
-
- // return $returnStatus;
- // }
-
-
- /**
- * Get headers from content
- */
- // public function readHeaders($content) {
- // $headers = null;
- // $headerLimitation = strpos($content, "\r\n\r\n");
- // if ($headerLimitation === false) {
- // return null;
- // }
- // $headersContent = substr($content, 0, $headerLimitation);
- // $headersContent = trim($headersContent);
- // foreach (explode("\r\n", $headersContent) as $header) {
- // $parts = explode(':', $header, 2);
- // if (count($parts) != 2) {
- // //has incorrect header, abort
- // return null;
- // }
- // $headers[strtolower(trim($parts[0]))] = trim($parts[1]);
- // }
-
- // return $headers;
- // }
-} \ No newline at end of file