Skip to content
Closed
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
15 changes: 7 additions & 8 deletions apps/dav/lib/Connector/Sabre/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ public function __construct(View $view, FileInfo $info, IManager $shareManager =
* @return string|null
*/
public function put($data) {

$contextObject = \OC\StreamHashFilter::getContextObject($data);
try {
$exists = $this->fileView->file_exists($this->path);
if ($this->info && $exists && !$this->info->isUpdateable()) {
Expand Down Expand Up @@ -261,16 +263,13 @@ public function put($data) {
$this->emitPostHooks($exists);
}

$this->refreshInfo();

if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
$checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
$this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
$this->refreshInfo();
} else if ($this->getChecksum() !== null && $this->getChecksum() !== '') {
$this->fileView->putFileInfo($this->path, ['checksum' => '']);
$this->refreshInfo();
} else {
$checksum = hash_final($contextObject->hashContext);
}
$this->fileView->putFileInfo($this->path, ['checksum' => 'md5:' . $checksum]);
$this->refreshInfo();

} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
Expand Down Expand Up @@ -532,7 +531,7 @@ private function createFileChunked($data) {
if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
$checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
$this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
} else if ($info->getChecksum() !== null && $info->getChecksum() !== '') {
} else {
$this->fileView->putFileInfo($this->path, ['checksum' => '']);
}

Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,7 @@
'OC\\Share\\Helper' => $baseDir . '/lib/private/Share/Helper.php',
'OC\\Share\\SearchResultSorter' => $baseDir . '/lib/private/Share/SearchResultSorter.php',
'OC\\Share\\Share' => $baseDir . '/lib/private/Share/Share.php',
'OC\\StreamHashFilter' => $baseDir . '/lib/private/StreamHashFilter.php',
'OC\\Streamer' => $baseDir . '/lib/private/Streamer.php',
'OC\\SubAdmin' => $baseDir . '/lib/private/SubAdmin.php',
'OC\\Support\\CrashReport\\Registry' => $baseDir . '/lib/private/Support/CrashReport/Registry.php',
Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Share\\Helper' => __DIR__ . '/../../..' . '/lib/private/Share/Helper.php',
'OC\\Share\\SearchResultSorter' => __DIR__ . '/../../..' . '/lib/private/Share/SearchResultSorter.php',
'OC\\Share\\Share' => __DIR__ . '/../../..' . '/lib/private/Share/Share.php',
'OC\\StreamHashFilter' => __DIR__ . '/../../..' . '/lib/private/StreamHashFilter.php',
'OC\\Streamer' => __DIR__ . '/../../..' . '/lib/private/Streamer.php',
'OC\\SubAdmin' => __DIR__ . '/../../..' . '/lib/private/SubAdmin.php',
'OC\\Support\\CrashReport\\Registry' => __DIR__ . '/../../..' . '/lib/private/Support/CrashReport/Registry.php',
Expand Down
5 changes: 3 additions & 2 deletions lib/private/Files/Cache/Scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
/** @var CacheEntry $cacheData */
$cacheData = $this->cache->get($file);
}
if (($reuseExisting & self::RECALCULATE_CHECKSUM_IF_EMPTY) && empty($cacheData['checksum'])) {
$data['checksum'] = 'md5:' . $this->storage->hash('md5', $file);
}
if ($cacheData and $reuseExisting and isset($cacheData['fileid'])) {
// prevent empty etag
if (empty($cacheData['etag'])) {
Expand All @@ -216,8 +219,6 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
$fileId = -1;
}
if (!empty($newData)) {
// Reset the checksum if the data has changed
$newData['checksum'] = '';
$data['fileid'] = $this->addToCache($file, $newData, $fileId);
}
if (isset($cacheData['size'])) {
Expand Down
2 changes: 1 addition & 1 deletion lib/private/Files/Utils/Scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public function scan($dir = '', $recursive = \OC\Files\Cache\Scanner::SCAN_RECUR
try {
$propagator = $storage->getPropagator();
$propagator->beginBatch();
$scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
$scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE | \OC\Files\Cache\Scanner::RECALCULATE_CHECKSUM_IF_EMPTY);
$cache = $storage->getCache();
if ($cache instanceof Cache) {
// only re-calculate for the root folder we scanned, anything below that is taken care of by the scanner
Expand Down
14 changes: 12 additions & 2 deletions lib/private/Files/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,12 @@ protected function emit_file_hooks_post($exists, $path) {
* @throws \Exception
*/
public function file_put_contents($path, $data) {
if (is_string($data)) {
$stream = fopen('php://memory','r+');
fwrite($stream, $data);
rewind($stream);
$data = $stream;
}
if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
if (Filesystem::isValidPath($path)
Expand All @@ -660,11 +666,13 @@ public function file_put_contents($path, $data) {

/** @var \OC\Files\Storage\Storage $storage */
list($storage, $internalPath) = $this->resolvePath($path);
$contextObject = \OC\StreamHashFilter::getContextObject($data);
$target = $storage->fopen($internalPath, 'w');
if ($target) {
list (, $result) = \OC_Helper::streamCopy($data, $target);
fclose($target);
fclose($data);
$this->putFileInfo($path, ['checksum' => 'md5:' . hash_final($contextObject->hashContext)]);

$this->writeUpdate($storage, $internalPath);

Expand All @@ -683,8 +691,7 @@ public function file_put_contents($path, $data) {
return false;
}
} else {
$hooks = $this->file_exists($path) ? array('update', 'write') : array('create', 'write');
return $this->basicOperation('file_put_contents', $path, $hooks, $data);
throw new \Exception('$data is neither resource nor string');
}
}

Expand Down Expand Up @@ -1552,6 +1559,9 @@ public function putFileInfo($path, $data) {
*/
list($storage, $internalPath) = Filesystem::resolvePath($path);
if ($storage) {
if ($data['checksum'] == '') {
$data['checksum'] = 'md5' . $storage->hash('md5', $internalPath);
}
$cache = $storage->getCache($path);

if (!$cache->inCache($internalPath)) {
Expand Down
52 changes: 52 additions & 0 deletions lib/private/StreamHashFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* @copyright Copyright (c) 2019, Tomasz Grobelny <[email protected]>
*
* @author Tomasz Grobelny <[email protected]>
*
* @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 OC;

class StreamHashFilter extends \php_user_filter
{
static function getContextObject($stream) {
stream_filter_register('hash.md5', 'OC\\StreamHashFilter');
$obj = new \stdClass();
$md5_filter = stream_filter_append($stream, 'hash.md5', STREAM_FILTER_ALL, $obj);
return $obj;
}

function onCreate () {
$this->params->hashContext = hash_init('md5');
return TRUE;
}

function onClose () {
return TRUE;
}

function filter ($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
hash_update($this->params->hashContext, $bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
1 change: 1 addition & 0 deletions lib/public/Files/Cache/IScanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface IScanner {
const REUSE_NONE = 0;
const REUSE_ETAG = 1;
const REUSE_SIZE = 2;
const RECALCULATE_CHECKSUM_IF_EMPTY = 4;

/**
* scan a single file and store it in the cache
Expand Down