Merge pull request #2925 from nextcloud/remove-close-wrapper

replace close:// streamwrapper with CallBackWrapper
This commit is contained in:
Roeland Jago Douma 2017-01-10 10:21:10 +01:00 committed by GitHub
commit b847dfcee9
14 changed files with 143 additions and 357 deletions

View File

@ -42,6 +42,7 @@ require_once 'aws-autoloader.php';
use Aws\S3\S3Client; use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception; use Aws\S3\Exception\S3Exception;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\IteratorDirectory; use Icewind\Streams\IteratorDirectory;
use OC\Files\ObjectStore\S3ConnectionTrait; use OC\Files\ObjectStore\S3ConnectionTrait;
@ -366,14 +367,15 @@ class AmazonS3 extends \OC\Files\Storage\Common {
$ext = ''; $ext = '';
} }
$tmpFile = \OCP\Files::tmpFile($ext); $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) { if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r'); $source = $this->fopen($path, 'r');
file_put_contents($tmpFile, $source); file_put_contents($tmpFile, $source);
} }
self::$tmpFiles[$tmpFile] = $path;
return fopen('close://' . $tmpFile, $mode); $handle = fopen($tmpFile, $mode);
return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
$this->writeBack($tmpFile, $path);
});
} }
return false; return false;
} }
@ -514,15 +516,11 @@ class AmazonS3 extends \OC\Files\Storage\Common {
return $this->id; return $this->id;
} }
public function writeBack($tmpFile) { public function writeBack($tmpFile, $path) {
if (!isset(self::$tmpFiles[$tmpFile])) {
return false;
}
try { try {
$this->getConnection()->putObject(array( $this->getConnection()->putObject(array(
'Bucket' => $this->bucket, 'Bucket' => $this->bucket,
'Key' => $this->cleanKey(self::$tmpFiles[$tmpFile]), 'Key' => $this->cleanKey($path),
'SourceFile' => $tmpFile, 'SourceFile' => $tmpFile,
'ContentType' => \OC::$server->getMimeTypeDetector()->detect($tmpFile), 'ContentType' => \OC::$server->getMimeTypeDetector()->detect($tmpFile),
'ContentLength' => filesize($tmpFile) 'ContentLength' => filesize($tmpFile)

View File

@ -31,6 +31,7 @@
namespace OCA\Files_External\Lib\Storage; namespace OCA\Files_External\Lib\Storage;
use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\RequestException;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\IteratorDirectory; use Icewind\Streams\IteratorDirectory;
use Icewind\Streams\RetryWrapper; use Icewind\Streams\RetryWrapper;
use OCP\Files\StorageNotAvailableException; use OCP\Files\StorageNotAvailableException;
@ -45,8 +46,6 @@ class Dropbox extends \OC\Files\Storage\Common {
private $metaData = array(); private $metaData = array();
private $oauth; private $oauth;
private static $tempFiles = array();
public function __construct($params) { public function __construct($params) {
if (isset($params['configured']) && $params['configured'] == 'true' if (isset($params['configured']) && $params['configured'] == 'true'
&& isset($params['app_key']) && isset($params['app_key'])
@ -305,27 +304,26 @@ class Dropbox extends \OC\Files\Storage\Common {
$ext = ''; $ext = '';
} }
$tmpFile = \OCP\Files::tmpFile($ext); $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) { if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r'); $source = $this->fopen($path, 'r');
file_put_contents($tmpFile, $source); file_put_contents($tmpFile, $source);
} }
self::$tempFiles[$tmpFile] = $path; $handle = fopen($tmpFile, $mode);
return fopen('close://'.$tmpFile, $mode); return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
$this->writeBack($tmpFile, $path);
});
} }
return false; return false;
} }
public function writeBack($tmpFile) { public function writeBack($tmpFile, $path) {
if (isset(self::$tempFiles[$tmpFile])) { $handle = fopen($tmpFile, 'r');
$handle = fopen($tmpFile, 'r'); try {
try { $this->dropbox->putFile($path, $handle);
$this->dropbox->putFile(self::$tempFiles[$tmpFile], $handle); unlink($tmpFile);
unlink($tmpFile); $this->deleteMetaData($path);
$this->deleteMetaData(self::$tempFiles[$tmpFile]); } catch (\Exception $exception) {
} catch (\Exception $exception) { \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
}
} }
} }

View File

@ -33,6 +33,7 @@
namespace OCA\Files_External\Lib\Storage; namespace OCA\Files_External\Lib\Storage;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\RetryWrapper; use Icewind\Streams\RetryWrapper;
class FTP extends StreamWrapper{ class FTP extends StreamWrapper{
@ -127,21 +128,20 @@ class FTP extends StreamWrapper{
$ext=''; $ext='';
} }
$tmpFile=\OCP\Files::tmpFile($ext); $tmpFile=\OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) { if ($this->file_exists($path)) {
$this->getFile($path, $tmpFile); $this->getFile($path, $tmpFile);
} }
self::$tempFiles[$tmpFile]=$path; $handle = fopen($tmpFile, $mode);
return fopen('close://'.$tmpFile, $mode); return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
$this->writeBack($tmpFile, $path);
});
} }
return false; return false;
} }
public function writeBack($tmpFile) { public function writeBack($tmpFile, $path) {
if (isset(self::$tempFiles[$tmpFile])) { $this->uploadFile($tmpFile, $path);
$this->uploadFile($tmpFile, self::$tempFiles[$tmpFile]); unlink($tmpFile);
unlink($tmpFile);
}
} }
/** /**

View File

@ -36,6 +36,7 @@
namespace OCA\Files_External\Lib\Storage; namespace OCA\Files_External\Lib\Storage;
use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\RequestException;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\IteratorDirectory; use Icewind\Streams\IteratorDirectory;
use Icewind\Streams\RetryWrapper; use Icewind\Streams\RetryWrapper;
@ -50,8 +51,6 @@ class Google extends \OC\Files\Storage\Common {
private $service; private $service;
private $driveFiles; private $driveFiles;
private static $tempFiles = array();
// Google Doc mimetypes // Google Doc mimetypes
const FOLDER = 'application/vnd.google-apps.folder'; const FOLDER = 'application/vnd.google-apps.folder';
const DOCUMENT = 'application/vnd.google-apps.document'; const DOCUMENT = 'application/vnd.google-apps.document';
@ -495,94 +494,91 @@ class Google extends \OC\Files\Storage\Common {
case 'c': case 'c':
case 'c+': case 'c+':
$tmpFile = \OCP\Files::tmpFile($ext); $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) { if ($this->file_exists($path)) {
$source = $this->fopen($path, 'rb'); $source = $this->fopen($path, 'rb');
file_put_contents($tmpFile, $source); file_put_contents($tmpFile, $source);
} }
self::$tempFiles[$tmpFile] = $path; $handle = fopen($tmpFile, $mode);
return fopen('close://'.$tmpFile, $mode); return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
$this->writeBack($tmpFile, $path);
});
} }
} }
public function writeBack($tmpFile) { public function writeBack($tmpFile, $path) {
if (isset(self::$tempFiles[$tmpFile])) { $parentFolder = $this->getDriveFile(dirname($path));
$path = self::$tempFiles[$tmpFile]; if ($parentFolder) {
$parentFolder = $this->getDriveFile(dirname($path)); $mimetype = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
if ($parentFolder) { $params = array(
$mimetype = \OC::$server->getMimeTypeDetector()->detect($tmpFile); 'mimeType' => $mimetype,
$params = array( 'uploadType' => 'media'
'mimeType' => $mimetype, );
'uploadType' => 'media' $result = false;
);
$result = false;
$chunkSizeBytes = 10 * 1024 * 1024; $chunkSizeBytes = 10 * 1024 * 1024;
$useChunking = false; $useChunking = false;
$size = filesize($tmpFile); $size = filesize($tmpFile);
if ($size > $chunkSizeBytes) { if ($size > $chunkSizeBytes) {
$useChunking = true; $useChunking = true;
} else { } else {
$params['data'] = file_get_contents($tmpFile); $params['data'] = file_get_contents($tmpFile);
} }
if ($this->file_exists($path)) { if ($this->file_exists($path)) {
$file = $this->getDriveFile($path); $file = $this->getDriveFile($path);
$this->client->setDefer($useChunking); $this->client->setDefer($useChunking);
$request = $this->service->files->update($file->getId(), $file, $params); $request = $this->service->files->update($file->getId(), $file, $params);
} else { } else {
$file = new \Google_Service_Drive_DriveFile(); $file = new \Google_Service_Drive_DriveFile();
$file->setTitle(basename($path)); $file->setTitle(basename($path));
$file->setMimeType($mimetype); $file->setMimeType($mimetype);
$parent = new \Google_Service_Drive_ParentReference(); $parent = new \Google_Service_Drive_ParentReference();
$parent->setId($parentFolder->getId()); $parent->setId($parentFolder->getId());
$file->setParents(array($parent)); $file->setParents(array($parent));
$this->client->setDefer($useChunking); $this->client->setDefer($useChunking);
$request = $this->service->files->insert($file, $params); $request = $this->service->files->insert($file, $params);
} }
if ($useChunking) { if ($useChunking) {
// Create a media file upload to represent our upload process. // Create a media file upload to represent our upload process.
$media = new \Google_Http_MediaFileUpload( $media = new \Google_Http_MediaFileUpload(
$this->client, $this->client,
$request, $request,
'text/plain', 'text/plain',
null, null,
true, true,
$chunkSizeBytes $chunkSizeBytes
); );
$media->setFileSize($size); $media->setFileSize($size);
// Upload the various chunks. $status will be false until the process is // Upload the various chunks. $status will be false until the process is
// complete. // complete.
$status = false; $status = false;
$handle = fopen($tmpFile, 'rb'); $handle = fopen($tmpFile, 'rb');
while (!$status && !feof($handle)) { while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes); $chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk); $status = $media->nextChunk($chunk);
} }
// The final value of $status will be the data from the API for the object // The final value of $status will be the data from the API for the object
// that has been uploaded. // that has been uploaded.
$result = false; $result = false;
if ($status !== false) { if ($status !== false) {
$result = $status; $result = $status;
} }
fclose($handle); fclose($handle);
} else { } else {
$result = $request; $result = $request;
} }
// Reset to the client to execute requests immediately in the future. // Reset to the client to execute requests immediately in the future.
$this->client->setDefer(false); $this->client->setDefer(false);
if ($result) { if ($result) {
$this->setDriveFile($path, $result); $this->setDriveFile($path, $result);
}
} }
unlink($tmpFile);
} }
} }

View File

@ -37,6 +37,7 @@ namespace OCA\Files_External\Lib\Storage;
use Guzzle\Http\Url; use Guzzle\Http\Url;
use Guzzle\Http\Exception\ClientErrorResponseException; use Guzzle\Http\Exception\ClientErrorResponseException;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\IteratorDirectory; use Icewind\Streams\IteratorDirectory;
use OpenCloud; use OpenCloud;
use OpenCloud\Common\Exceptions; use OpenCloud\Common\Exceptions;
@ -410,7 +411,6 @@ class Swift extends \OC\Files\Storage\Common {
$ext = ''; $ext = '';
} }
$tmpFile = \OCP\Files::tmpFile($ext); $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
// Fetch existing file if required // Fetch existing file if required
if ($mode[0] !== 'w' && $this->file_exists($path)) { if ($mode[0] !== 'w' && $this->file_exists($path)) {
if ($mode[0] === 'x') { if ($mode[0] === 'x') {
@ -424,9 +424,10 @@ class Swift extends \OC\Files\Storage\Common {
fseek($tmpFile, 0, SEEK_END); fseek($tmpFile, 0, SEEK_END);
} }
} }
self::$tmpFiles[$tmpFile] = $path; $handle = fopen($tmpFile, $mode);
return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
return fopen('close://' . $tmpFile, $mode); $this->writeBack($tmpFile, $path);
});
} }
} }
@ -615,12 +616,9 @@ class Swift extends \OC\Files\Storage\Common {
return $this->container; return $this->container;
} }
public function writeBack($tmpFile) { public function writeBack($tmpFile, $path) {
if (!isset(self::$tmpFiles[$tmpFile])) {
return false;
}
$fileData = fopen($tmpFile, 'r'); $fileData = fopen($tmpFile, 'r');
$this->getContainer()->uploadObject(self::$tmpFiles[$tmpFile], $fileData); $this->getContainer()->uploadObject($path, $fileData);
// invalidate target object to force repopulation on fetch // invalidate target object to force repopulation on fetch
$this->objectCache->remove(self::$tmpFiles[$tmpFile]); $this->objectCache->remove(self::$tmpFiles[$tmpFile]);
unlink($tmpFile); unlink($tmpFile);

View File

@ -669,9 +669,6 @@ class OC {
OC\Log\ErrorHandler::register($debug); OC\Log\ErrorHandler::register($debug);
} }
// register the stream wrappers
stream_wrapper_register('close', 'OC\Files\Stream\Close');
\OC::$server->getEventLogger()->start('init_session', 'Initialize session'); \OC::$server->getEventLogger()->start('init_session', 'Initialize session');
OC_App::loadApps(array('session')); OC_App::loadApps(array('session'));
if (!self::$CLI) { if (!self::$CLI) {

View File

@ -554,7 +554,6 @@ return array(
'OC\\Files\\Storage\\Wrapper\\PermissionsMask' => $baseDir . '/lib/private/Files/Storage/Wrapper/PermissionsMask.php', 'OC\\Files\\Storage\\Wrapper\\PermissionsMask' => $baseDir . '/lib/private/Files/Storage/Wrapper/PermissionsMask.php',
'OC\\Files\\Storage\\Wrapper\\Quota' => $baseDir . '/lib/private/Files/Storage/Wrapper/Quota.php', 'OC\\Files\\Storage\\Wrapper\\Quota' => $baseDir . '/lib/private/Files/Storage/Wrapper/Quota.php',
'OC\\Files\\Storage\\Wrapper\\Wrapper' => $baseDir . '/lib/private/Files/Storage/Wrapper/Wrapper.php', 'OC\\Files\\Storage\\Wrapper\\Wrapper' => $baseDir . '/lib/private/Files/Storage/Wrapper/Wrapper.php',
'OC\\Files\\Stream\\Close' => $baseDir . '/lib/private/Files/Stream/Close.php',
'OC\\Files\\Stream\\Encryption' => $baseDir . '/lib/private/Files/Stream/Encryption.php', 'OC\\Files\\Stream\\Encryption' => $baseDir . '/lib/private/Files/Stream/Encryption.php',
'OC\\Files\\Stream\\Quota' => $baseDir . '/lib/private/Files/Stream/Quota.php', 'OC\\Files\\Stream\\Quota' => $baseDir . '/lib/private/Files/Stream/Quota.php',
'OC\\Files\\Type\\Detection' => $baseDir . '/lib/private/Files/Type/Detection.php', 'OC\\Files\\Type\\Detection' => $baseDir . '/lib/private/Files/Type/Detection.php',

View File

@ -584,7 +584,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Files\\Storage\\Wrapper\\PermissionsMask' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/PermissionsMask.php', 'OC\\Files\\Storage\\Wrapper\\PermissionsMask' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/PermissionsMask.php',
'OC\\Files\\Storage\\Wrapper\\Quota' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/Quota.php', 'OC\\Files\\Storage\\Wrapper\\Quota' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/Quota.php',
'OC\\Files\\Storage\\Wrapper\\Wrapper' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/Wrapper.php', 'OC\\Files\\Storage\\Wrapper\\Wrapper' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Wrapper/Wrapper.php',
'OC\\Files\\Stream\\Close' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/Close.php',
'OC\\Files\\Stream\\Encryption' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/Encryption.php', 'OC\\Files\\Stream\\Encryption' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/Encryption.php',
'OC\\Files\\Stream\\Quota' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/Quota.php', 'OC\\Files\\Stream\\Quota' => __DIR__ . '/../../..' . '/lib/private/Files/Stream/Quota.php',
'OC\\Files\\Type\\Detection' => __DIR__ . '/../../..' . '/lib/private/Files/Type/Detection.php', 'OC\\Files\\Type\\Detection' => __DIR__ . '/../../..' . '/lib/private/Files/Type/Detection.php',

View File

@ -33,6 +33,8 @@
namespace OC\Archive; namespace OC\Archive;
use Icewind\Streams\CallbackWrapper;
class TAR extends Archive { class TAR extends Archive {
const PLAIN = 0; const PLAIN = 0;
const GZIP = 1; const GZIP = 1;
@ -359,22 +361,19 @@ class TAR extends Archive {
if ($mode == 'r' or $mode == 'rb') { if ($mode == 'r' or $mode == 'rb') {
return fopen($tmpFile, $mode); return fopen($tmpFile, $mode);
} else { } else {
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); $handle = fopen($tmpFile, $mode);
self::$tempFiles[$tmpFile] = $path; return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
return fopen('close://' . $tmpFile, $mode); $this->writeBack($tmpFile, $path);
});
} }
} }
private static $tempFiles = array();
/** /**
* write back temporary files * write back temporary files
*/ */
function writeBack($tmpFile) { function writeBack($tmpFile, $path) {
if (isset(self::$tempFiles[$tmpFile])) { $this->addFile($path, $tmpFile);
$this->addFile(self::$tempFiles[$tmpFile], $tmpFile); unlink($tmpFile);
unlink($tmpFile);
}
} }
/** /**

View File

@ -31,6 +31,8 @@
namespace OC\Archive; namespace OC\Archive;
use Icewind\Streams\CallbackWrapper;
class ZIP extends Archive{ class ZIP extends Archive{
/** /**
* @var \ZipArchive zip * @var \ZipArchive zip
@ -198,24 +200,22 @@ class ZIP extends Archive{
$ext=''; $ext='';
} }
$tmpFile=\OCP\Files::tmpFile($ext); $tmpFile=\OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if($this->fileExists($path)) { if($this->fileExists($path)) {
$this->extractFile($path, $tmpFile); $this->extractFile($path, $tmpFile);
} }
self::$tempFiles[$tmpFile]=$path; $handle = fopen($tmpFile, $mode);
return fopen('close://'.$tmpFile, $mode); return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
$this->writeBack($tmpFile, $path);
});
} }
} }
private static $tempFiles=array();
/** /**
* write back temporary files * write back temporary files
*/ */
function writeBack($tmpFile) { function writeBack($tmpFile, $path) {
if(isset(self::$tempFiles[$tmpFile])) { $this->addFile($path, $tmpFile);
$this->addFile(self::$tempFiles[$tmpFile], $tmpFile); unlink($tmpFile);
unlink($tmpFile);
}
} }
/** /**

View File

@ -25,16 +25,12 @@
namespace OC\Files\ObjectStore; namespace OC\Files\ObjectStore;
use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\IteratorDirectory; use Icewind\Streams\IteratorDirectory;
use OC\Files\Cache\CacheEntry; use OC\Files\Cache\CacheEntry;
use OCP\Files\ObjectStore\IObjectStore; use OCP\Files\ObjectStore\IObjectStore;
class ObjectStoreStorage extends \OC\Files\Storage\Common { class ObjectStoreStorage extends \OC\Files\Storage\Common {
/**
* @var array
*/
private static $tmpFiles = array();
/** /**
* @var \OCP\Files\ObjectStore\IObjectStore $objectStore * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
*/ */
@ -291,14 +287,14 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
$ext = ''; $ext = '';
} }
$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext); $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) { if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r'); $source = $this->fopen($path, 'r');
file_put_contents($tmpFile, $source); file_put_contents($tmpFile, $source);
} }
self::$tmpFiles[$tmpFile] = $path; $handle = fopen($tmpFile, $mode);
return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
return fopen('close://' . $tmpFile, $mode); $this->writeBack($tmpFile, $path);
});
} }
return false; return false;
} }
@ -368,12 +364,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
return true; return true;
} }
public function writeBack($tmpFile) { public function writeBack($tmpFile, $path) {
if (!isset(self::$tmpFiles[$tmpFile])) {
return;
}
$path = self::$tmpFiles[$tmpFile];
$stat = $this->stat($path); $stat = $this->stat($path);
if (empty($stat)) { if (empty($stat)) {
// create new file // create new file

View File

@ -36,6 +36,7 @@ namespace OC\Files\Storage;
use Exception; use Exception;
use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Message\ResponseInterface; use GuzzleHttp\Message\ResponseInterface;
use Icewind\Streams\CallbackWrapper;
use OC\Files\Filesystem; use OC\Files\Filesystem;
use OC\Files\Stream\Close; use OC\Files\Stream\Close;
use Icewind\Streams\IteratorDirectory; use Icewind\Streams\IteratorDirectory;
@ -77,8 +78,6 @@ class DAV extends Common {
private $client; private $client;
/** @var ArrayCache */ /** @var ArrayCache */
private $statCache; private $statCache;
/** @var array */
private static $tempFiles = [];
/** @var \OCP\Http\Client\IClientService */ /** @var \OCP\Http\Client\IClientService */
private $httpClientService; private $httpClientService;
@ -409,20 +408,19 @@ class DAV extends Common {
} }
$tmpFile = $tempManager->getTemporaryFile($ext); $tmpFile = $tempManager->getTemporaryFile($ext);
} }
Close::registerCallback($tmpFile, array($this, 'writeBack')); $handle = fopen($tmpFile, $mode);
self::$tempFiles[$tmpFile] = $path; return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
return fopen('close://' . $tmpFile, $mode); $this->writeBack($tmpFile, $path);
});
} }
} }
/** /**
* @param string $tmpFile * @param string $tmpFile
*/ */
public function writeBack($tmpFile) { public function writeBack($tmpFile, $path) {
if (isset(self::$tempFiles[$tmpFile])) { $this->uploadFile($tmpFile, $path);
$this->uploadFile($tmpFile, self::$tempFiles[$tmpFile]); unlink($tmpFile);
unlink($tmpFile);
}
} }
/** {@inheritdoc} */ /** {@inheritdoc} */

View File

@ -1,119 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Jörn Friedrich Dreyer <jfd@butonic.de>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
*
* @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\Files\Stream;
/**
* stream wrapper that provides a callback on stream close
*/
class Close {
private static $callBacks = array();
private $path = '';
private $source;
private static $open = array();
public function stream_open($path, $mode, $options, &$opened_path) {
$path = substr($path, strlen('close://'));
$this->path = $path;
$this->source = fopen($path, $mode);
if (is_resource($this->source)) {
$this->meta = stream_get_meta_data($this->source);
}
self::$open[] = $path;
return is_resource($this->source);
}
public function stream_seek($offset, $whence = SEEK_SET) {
return fseek($this->source, $offset, $whence) === 0;
}
public function stream_tell() {
return ftell($this->source);
}
public function stream_read($count) {
return fread($this->source, $count);
}
public function stream_write($data) {
return fwrite($this->source, $data);
}
public function stream_set_option($option, $arg1, $arg2) {
switch ($option) {
case STREAM_OPTION_BLOCKING:
stream_set_blocking($this->source, $arg1);
break;
case STREAM_OPTION_READ_TIMEOUT:
stream_set_timeout($this->source, $arg1, $arg2);
break;
case STREAM_OPTION_WRITE_BUFFER:
stream_set_write_buffer($this->source, $arg1, $arg2);
}
}
public function stream_stat() {
return fstat($this->source);
}
public function stream_lock($mode) {
flock($this->source, $mode);
}
public function stream_flush() {
return fflush($this->source);
}
public function stream_eof() {
return feof($this->source);
}
public function url_stat($path) {
$path = substr($path, strlen('close://'));
if (file_exists($path)) {
return stat($path);
} else {
return false;
}
}
public function stream_close() {
fclose($this->source);
if (isset(self::$callBacks[$this->path])) {
call_user_func(self::$callBacks[$this->path], $this->path);
}
}
public function unlink($path) {
$path = substr($path, strlen('close://'));
return unlink($path);
}
/**
* @param string $path
*/
public static function registerCallback($path, $callback) {
self::$callBacks[$path] = $callback;
}
}

View File

@ -1,68 +0,0 @@
<?php
/**
* ownCloud
*
* @author Robin Appelman
* @copyright 2012 Robin Appelman icewind@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library 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 along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Test;
/**
* Class StreamWrappersTest
*
* @group DB
*/
class StreamWrappersTest extends \Test\TestCase {
private static $trashBinStatus;
public static function setUpBeforeClass() {
self::$trashBinStatus = \OC_App::isEnabled('files_trashbin');
\OC_App::disable('files_trashbin');
}
public static function tearDownAfterClass() {
if (self::$trashBinStatus) {
(new \OC_App())->enable('files_trashbin');
}
}
public function testCloseStream() {
//ensure all basic stream stuff works
$sourceFile = \OC::$SERVERROOT . '/tests/data/lorem.txt';
$tmpFile = \OC::$server->getTempManager()->getTemporaryFile('.txt');
$file = 'close://' . $tmpFile;
$this->assertTrue(file_exists($file));
file_put_contents($file, file_get_contents($sourceFile));
$this->assertEquals(file_get_contents($sourceFile), file_get_contents($file));
unlink($file);
clearstatcache();
$this->assertFalse(file_exists($file));
//test callback
$tmpFile = \OC::$server->getTempManager()->getTemporaryFile('.txt');
$file = 'close://' . $tmpFile;
$actual = false;
$callback = function($path) use (&$actual) { $actual = $path; };
\OC\Files\Stream\Close::registerCallback($tmpFile, $callback);
$fh = fopen($file, 'w');
fwrite($fh, 'asd');
fclose($fh);
$this->assertSame($tmpFile, $actual);
}
}