Skip to content
Snippets Groups Projects
Commit 10d3e63c authored by Robin Appelman's avatar Robin Appelman
Browse files

add quota streamwrapper that limits the amount of data that can be written to a stream

parent 94560c68
No related branches found
No related tags found
No related merge requests found
......@@ -91,7 +91,7 @@ class OC {
// ensure we can find OC_Config
set_include_path(
OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
get_include_path()
get_include_path()
);
OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
......@@ -160,11 +160,11 @@ class OC {
// set the right include path
set_include_path(
OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
implode($paths, PATH_SEPARATOR) . PATH_SEPARATOR .
get_include_path() . PATH_SEPARATOR .
OC::$SERVERROOT
OC::$SERVERROOT . '/config' . PATH_SEPARATOR .
OC::$THIRDPARTYROOT . '/3rdparty' . PATH_SEPARATOR .
implode($paths, PATH_SEPARATOR) . PATH_SEPARATOR .
get_include_path() . PATH_SEPARATOR .
OC::$SERVERROOT
);
}
......@@ -278,17 +278,17 @@ class OC {
ini_set('session.cookie_httponly', '1;');
// set the cookie path to the ownCloud directory
$cookie_path = OC::$WEBROOT ?: '/';
$cookie_path = OC::$WEBROOT ? : '/';
ini_set('session.cookie_path', $cookie_path);
//set the session object to a dummy session so code relying on the session existing still works
self::$session = new \OC\Session\Memory('');
try{
try {
// set the session name to the instance id - which is unique
self::$session = new \OC\Session\Internal(OC_Util::getInstanceId());
// if session cant be started break with http 500 error
}catch (Exception $e){
} catch (Exception $e) {
OC_Log::write('core', 'Session could not be initialized',
OC_Log::ERROR);
......@@ -352,7 +352,7 @@ class OC {
public static function init() {
// register autoloader
require_once __DIR__ . '/autoloader.php';
self::$loader=new \OC\Autoloader();
self::$loader = new \OC\Autoloader();
self::$loader->registerPrefix('Doctrine\\Common', 'doctrine/common/lib');
self::$loader->registerPrefix('Doctrine\\DBAL', 'doctrine/dbal/lib');
self::$loader->registerPrefix('Symfony\\Component\\Routing', 'symfony/routing');
......@@ -373,7 +373,7 @@ class OC {
ini_set('arg_separator.output', '&');
// try to switch magic quotes off.
if (get_magic_quotes_gpc()==1) {
if (get_magic_quotes_gpc() == 1) {
ini_set('magic_quotes_runtime', 0);
}
......@@ -398,7 +398,8 @@ class OC {
//set http auth headers for apache+php-cgi work around
if (isset($_SERVER['HTTP_AUTHORIZATION'])
&& preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
&& preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)
) {
list($name, $password) = explode(':', base64_decode($matches[1]), 2);
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
......@@ -406,7 +407,8 @@ class OC {
//set http auth headers for apache+php-cgi work around if variable gets renamed by apache
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])
&& preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) {
&& preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)
) {
list($name, $password) = explode(':', base64_decode($matches[1]), 2);
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
......@@ -435,10 +437,11 @@ class OC {
stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir');
stream_wrapper_register('static', 'OC\Files\Stream\StaticStream');
stream_wrapper_register('close', 'OC\Files\Stream\Close');
stream_wrapper_register('quota', 'OC\Files\Stream\Quota');
stream_wrapper_register('oc', 'OC\Files\Stream\OC');
self::initTemplateEngine();
if ( !self::$CLI ) {
if (!self::$CLI) {
self::initSession();
} else {
self::$session = new \OC\Session\Memory('');
......@@ -459,7 +462,7 @@ class OC {
// User and Groups
if (!OC_Config::getValue("installed", false)) {
self::$session->set('user_id','');
self::$session->set('user_id', '');
}
OC_User::useBackend(new OC_User_Database());
......
<?php
/**
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Files\Stream;
/**
* stream wrapper limits the amount of data that can be written to a stream
*
* usage: void \OC\Files\Stream\Quota::register($id, $stream, $limit)
* or: resource \OC\Files\Stream\Quota::wrap($stream, $limit)
*/
class Quota {
private static $streams = array();
/**
* @var resource $source
*/
private $source;
/**
* @var int $limit
*/
private $limit;
/**
* @param string $id
* @param resource $stream
* @param int $limit
*/
public static function register($id, $stream, $limit) {
self::$streams[$id] = array($stream, $limit);
}
/**
* remove all registered streams
*/
public static function clear() {
self::$streams = array();
}
/**
* @param resource $stream
* @param int $limit
* @return resource
*/
static public function wrap($stream, $limit) {
$id = uniqid();
self::register($id, $stream, $limit);
$meta = stream_get_meta_data($stream);
return fopen('quota://' . $id, $meta['mode']);
}
public function stream_open($path, $mode, $options, &$opened_path) {
$id = substr($path, strlen('quota://'));
if (isset(self::$streams[$id])) {
list($this->source, $this->limit) = self::$streams[$id];
return true;
} else {
return false;
}
}
public function stream_seek($offset, $whence = SEEK_SET) {
if ($whence === SEEK_SET) {
$this->limit += $this->stream_tell() - $offset;
} else {
$this->limit -= $offset;
}
fseek($this->source, $offset, $whence);
}
public function stream_tell() {
return ftell($this->source);
}
public function stream_read($count) {
$this->limit -= $count;
return fread($this->source, $count);
}
public function stream_write($data) {
$size = strlen($data);
if ($size > $this->limit) {
$data = substr($data, 0, $this->limit);
$size = $this->limit;
}
$this->limit -= $size;
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 stream_close() {
fclose($this->source);
}
}
<?php
/**
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace Test\Files\Stream;
class Quota extends \PHPUnit_Framework_TestCase {
public function tearDown() {
\OC\Files\Stream\Quota::clear();
}
protected function getStream($mode, $limit) {
$source = fopen('php://temp', $mode);
return \OC\Files\Stream\Quota::wrap($source, $limit);
}
public function testWriteEnoughSpace() {
$stream = $this->getStream('w+', 100);
$this->assertEquals(6, fwrite($stream, 'foobar'));
rewind($stream);
$this->assertEquals('foobar', fread($stream, 100));
}
public function testWriteNotEnoughSpace() {
$stream = $this->getStream('w+', 3);
$this->assertEquals(3, fwrite($stream, 'foobar'));
rewind($stream);
$this->assertEquals('foo', fread($stream, 100));
}
public function testWriteNotEnoughSpaceSecondTime() {
$stream = $this->getStream('w+', 9);
$this->assertEquals(6, fwrite($stream, 'foobar'));
$this->assertEquals(3, fwrite($stream, 'qwerty'));
rewind($stream);
$this->assertEquals('foobarqwe', fread($stream, 100));
}
public function testWriteEnoughSpaceRewind() {
$stream = $this->getStream('w+', 6);
$this->assertEquals(6, fwrite($stream, 'foobar'));
rewind($stream);
$this->assertEquals(3, fwrite($stream, 'qwe'));
rewind($stream);
$this->assertEquals('qwebar', fread($stream, 100));
}
public function testWriteNotEnoughSpaceRead() {
$stream = $this->getStream('w+', 6);
$this->assertEquals(6, fwrite($stream, 'foobar'));
rewind($stream);
$this->assertEquals('foobar', fread($stream, 6));
$this->assertEquals(0, fwrite($stream, 'qwe'));
}
public function testWriteNotEnoughSpaceExistingStream() {
$source = fopen('php://temp', 'w+');
fwrite($source, 'foobar');
$stream = \OC\Files\Stream\Quota::wrap($source, 3);
$this->assertEquals(3, fwrite($stream, 'foobar'));
rewind($stream);
$this->assertEquals('foobarfoo', fread($stream, 100));
}
public function testWriteNotEnoughSpaceExistingStreamRewind() {
$source = fopen('php://temp', 'w+');
fwrite($source, 'foobar');
$stream = \OC\Files\Stream\Quota::wrap($source, 3);
rewind($stream);
$this->assertEquals(6, fwrite($stream, 'qwerty'));
rewind($stream);
$this->assertEquals('qwerty', fread($stream, 100));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment