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
68 changes: 34 additions & 34 deletions apps/dav/lib/Connector/Sabre/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ public function put($data) {
$view = Filesystem::getView();

if ($needsPartFile) {
$transferId = \rand();
// mark file as partial while uploading (ignored by the scanner)
$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . $transferId . '.part';

if (!$view->isCreatable($partFilePath) && $view->isUpdatable($this->path)) {
$needsPartFile = false;
Expand Down Expand Up @@ -232,42 +233,36 @@ public function put($data) {
fclose($target);
}

if ($result === false) {
$expected = -1;
$lengthHeader = $this->request->getHeader('content-length');
if ($lengthHeader) {
$expected = (int)$lengthHeader;
}
if ($expected !== 0) {
throw new Exception(
$this->l10n->t(
'Error while copying file to target location (copied: %1$s, expected filesize: %2$s)',
[
$this->l10n->n('%n byte', '%n bytes', $count),
$this->l10n->n('%n byte', '%n bytes', $expected),
],
)
);
}
$lengthHeader = $this->request->getHeader('content-length');
$expected = $lengthHeader !== '' ? (int)$lengthHeader : -1;
if ($result === false && $expected >= 0) {
throw new Exception(
$this->l10n->t(
'Error while copying file to target location (copied: %1$s, expected filesize: %2$s)',
[
$this->l10n->n('%n byte', '%n bytes', $count),
$this->l10n->n('%n byte', '%n bytes', $expected),
],
)
);
}

// if content length is sent by client:
// double check if the file was fully received
// compare expected and actual size
$lengthHeader = $this->request->getHeader('content-length');
if ($lengthHeader && $this->request->getMethod() === 'PUT') {
$expected = (int)$lengthHeader;
if ($count !== $expected) {
throw new BadRequest(
$this->l10n->t(
'Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side.',
[
$this->l10n->n('%n byte', '%n bytes', $expected),
$this->l10n->n('%n byte', '%n bytes', $count),
],
)
);
}
if ($expected >= 0
&& $expected !== $count
&& $this->request->getMethod() === 'PUT'
) {
throw new BadRequest(
$this->l10n->t(
'Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side.',
[
$this->l10n->n('%n byte', '%n bytes', $expected),
$this->l10n->n('%n byte', '%n bytes', $count),
],
)
);
}
} catch (\Exception $e) {
if ($e instanceof LockedException) {
Expand Down Expand Up @@ -383,9 +378,14 @@ public function put($data) {
private function getPartFileBasePath($path) {
$partFileInStorage = Server::get(IConfig::class)->getSystemValue('part_file_in_storage', true);
if ($partFileInStorage) {
return $path;
$filename = basename($path);
// hash does not need to be secure but fast and semi unique
$hashedFilename = hash('xxh128', $filename);
return substr($path, 0, strlen($path) - strlen($filename)) . $hashedFilename;
} else {
return md5($path); // will place it in the root of the view with a unique name
// will place the .part file in the users root directory
// therefor we need to make the name (semi) unique - hash does not need to be secure but fast.
return hash('xxh128', $path);
}
}

Expand Down
29 changes: 29 additions & 0 deletions build/integration/dav_features/dav-v2.feature
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ Feature: dav-v2
When User "user0" uploads file "data/textfile.txt" to "/testquota/asdf.txt"
Then the HTTP status code should be "201"

Scenario: Uploading a file with very long filename
Given using new dav path
And As an "admin"
And user "user0" exists
And user "user0" has a quota of "10 MB"
And As an "user0"
When User "user0" uploads file "data/textfile.txt" to "/long-filename-with-250-characters-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.txt"
Then the HTTP status code should be "201"

Scenario: Uploading a file with a too long filename
Given using new dav path
And As an "admin"
And user "user0" exists
And user "user0" has a quota of "10 MB"
And As an "user0"
When User "user0" uploads file "data/textfile.txt" to "/long-filename-with-251-characters-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.txt"
Then the HTTP status code should be "400"

Scenario: Create a search query on image
Given using new dav path
And As an "admin"
Expand All @@ -132,3 +150,14 @@ Feature: dav-v2
Then Favorite search should work
And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1"

Scenario: Create a search query on favorite
Given using new dav path
And As an "admin"
And user "user0" exists
And As an "user0"
When User "user0" uploads file "data/green-square-256.png" to "/fav_image.png"
Then Favorite search should work
And the response should be empty
When user "user0" favorites element "/fav_image.png"
Then Favorite search should work
And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1"
Loading