removing duplicate code, cleanup of temporary test files

This commit is contained in:
El RIDO 2017-03-24 23:42:11 +01:00
parent 6db9dae66b
commit f7853cf439
No known key found for this signature in database
GPG key ID: 0F5C940A6BD81F92
6 changed files with 85 additions and 98 deletions

View file

@ -12,9 +12,8 @@
namespace PrivateBin\Data; namespace PrivateBin\Data;
use Exception;
use PrivateBin\Json;
use PrivateBin\Model\Paste; use PrivateBin\Model\Paste;
use PrivateBin\Persistence\DataStore;
/** /**
* Filesystem * Filesystem
@ -23,15 +22,6 @@ use PrivateBin\Model\Paste;
*/ */
class Filesystem extends AbstractData class Filesystem extends AbstractData
{ {
/**
* directory where data is stored
*
* @access private
* @static
* @var string
*/
private static $_dir = 'data/';
/** /**
* get instance of singleton * get instance of singleton
* *
@ -51,8 +41,7 @@ class Filesystem extends AbstractData
is_array($options) && is_array($options) &&
array_key_exists('dir', $options) array_key_exists('dir', $options)
) { ) {
self::$_dir = $options['dir'] . DIRECTORY_SEPARATOR; DataStore::setPath($options['dir']);
self::_init();
} }
return self::$_instance; return self::$_instance;
} }
@ -63,19 +52,19 @@ class Filesystem extends AbstractData
* @access public * @access public
* @param string $pasteid * @param string $pasteid
* @param array $paste * @param array $paste
* @throws Exception
* @return bool * @return bool
*/ */
public function create($pasteid, $paste) public function create($pasteid, $paste)
{ {
$storagedir = self::_dataid2path($pasteid); $storagedir = self::_dataid2path($pasteid);
if (is_file($storagedir . $pasteid)) { $file = $storagedir . $pasteid;
if (is_file($file)) {
return false; return false;
} }
if (!is_dir($storagedir)) { if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true); mkdir($storagedir, 0700, true);
} }
return (bool) file_put_contents($storagedir . $pasteid, Json::encode($paste)); return DataStore::store($file, $paste);
} }
/** /**
@ -156,20 +145,19 @@ class Filesystem extends AbstractData
* @param string $parentid * @param string $parentid
* @param string $commentid * @param string $commentid
* @param array $comment * @param array $comment
* @throws Exception
* @return bool * @return bool
*/ */
public function createComment($pasteid, $parentid, $commentid, $comment) public function createComment($pasteid, $parentid, $commentid, $comment)
{ {
$storagedir = self::_dataid2discussionpath($pasteid); $storagedir = self::_dataid2discussionpath($pasteid);
$filename = $pasteid . '.' . $commentid . '.' . $parentid; $file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid;
if (is_file($storagedir . $filename)) { if (is_file($file)) {
return false; return false;
} }
if (!is_dir($storagedir)) { if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true); mkdir($storagedir, 0700, true);
} }
return (bool) file_put_contents($storagedir . $filename, Json::encode($comment)); return DataStore::store($file, $comment);
} }
/** /**
@ -238,8 +226,9 @@ class Filesystem extends AbstractData
protected function _getExpiredPastes($batchsize) protected function _getExpiredPastes($batchsize)
{ {
$pastes = array(); $pastes = array();
$mainpath = DataStore::getPath();
$firstLevel = array_filter( $firstLevel = array_filter(
scandir(self::$_dir), scandir($mainpath),
'self::_isFirstLevelDir' 'self::_isFirstLevelDir'
); );
if (count($firstLevel) > 0) { if (count($firstLevel) > 0) {
@ -247,7 +236,7 @@ class Filesystem extends AbstractData
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) { for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) {
$firstKey = array_rand($firstLevel); $firstKey = array_rand($firstLevel);
$secondLevel = array_filter( $secondLevel = array_filter(
scandir(self::$_dir . $firstLevel[$firstKey]), scandir($mainpath . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]),
'self::_isSecondLevelDir' 'self::_isSecondLevelDir'
); );
@ -258,8 +247,9 @@ class Filesystem extends AbstractData
} }
$secondKey = array_rand($secondLevel); $secondKey = array_rand($secondLevel);
$path = self::$_dir . $firstLevel[$firstKey] . $path = $mainpath . DIRECTORY_SEPARATOR .
DIRECTORY_SEPARATOR . $secondLevel[$secondKey]; $firstLevel[$firstKey] . DIRECTORY_SEPARATOR .
$secondLevel[$secondKey];
if (!is_dir($path)) { if (!is_dir($path)) {
continue; continue;
} }
@ -293,34 +283,6 @@ class Filesystem extends AbstractData
return $pastes; return $pastes;
} }
/**
* Initialize data store
*
* @access private
* @static
* @return void
*/
private static function _init()
{
// Create storage directory if it does not exist.
if (!is_dir(self::$_dir)) {
if (!@mkdir(self::$_dir, 0700)) {
throw new Exception('unable to create directory ' . self::$_dir, 10);
}
}
$file = self::$_dir . DIRECTORY_SEPARATOR . '.htaccess';
if (!is_file($file)) {
$writtenBytes = @file_put_contents(
$file,
'Require all denied' . PHP_EOL,
LOCK_EX
);
if ($writtenBytes === false || $writtenBytes < 19) {
throw new Exception('unable to write to file ' . $file, 11);
}
}
}
/** /**
* Convert paste id to storage path. * Convert paste id to storage path.
* *
@ -338,8 +300,10 @@ class Filesystem extends AbstractData
*/ */
private static function _dataid2path($dataid) private static function _dataid2path($dataid)
{ {
return self::$_dir . substr($dataid, 0, 2) . DIRECTORY_SEPARATOR . return DataStore::getPath(
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR; substr($dataid, 0, 2) . DIRECTORY_SEPARATOR .
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR
);
} }
/** /**
@ -369,7 +333,7 @@ class Filesystem extends AbstractData
private static function _isFirstLevelDir($element) private static function _isFirstLevelDir($element)
{ {
return self::_isSecondLevelDir($element) && return self::_isSecondLevelDir($element) &&
is_dir(self::$_dir . DIRECTORY_SEPARATOR . $element); is_dir(DataStore::getPath($element));
} }
/** /**

View file

@ -0,0 +1,48 @@
<?php
/**
* PrivateBin
*
* a zero-knowledge paste bin
*
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1
*/
namespace PrivateBin\Persistence;
use Exception;
use PrivateBin\Configuration;
use PrivateBin\Json;
/**
* DataStore
*
* Handles data storage for Data\Filesystem.
*/
class DataStore extends AbstractPersistence
{
/**
* store the data
*
* @access public
* @static
* @param string $filename
* @param string $data
* @return bool
*/
public static function store($filename, $data)
{
$path = self::getPath();
if (strpos($filename, $path) === 0) {
$filename = substr($filename, strlen($path));
}
try {
self::_store($filename, Json::encode($data));
return true;
} catch (Exception $e) {
return false;
}
}
}

View file

@ -172,22 +172,24 @@ class Helper
*/ */
public static function rmDir($path) public static function rmDir($path)
{ {
$path .= DIRECTORY_SEPARATOR; if (is_dir($path)) {
$dir = dir($path); $path .= DIRECTORY_SEPARATOR;
while (false !== ($file = $dir->read())) { $dir = dir($path);
if ($file != '.' && $file != '..') { while (false !== ($file = $dir->read())) {
if (is_dir($path . $file)) { if ($file != '.' && $file != '..') {
self::rmDir($path . $file); if (is_dir($path . $file)) {
} elseif (is_file($path . $file)) { self::rmDir($path . $file);
if (!unlink($path . $file)) { } elseif (is_file($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".'); if (!unlink($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".');
}
} }
} }
} }
} $dir->close();
$dir->close(); if (!rmdir($path)) {
if (!rmdir($path)) { throw new Exception('Error deleting directory "' . $path . '".');
throw new Exception('Error deleting directory "' . $path . '".'); }
} }
} }

View file

@ -110,10 +110,6 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
} }
} }
/**
* @expectedException Exception
* @expectedExceptionCode 90
*/
public function testErrorDetection() public function testErrorDetection()
{ {
$this->_model->delete(Helper::getPasteId()); $this->_model->delete(Helper::getPasteId());
@ -123,10 +119,6 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist'); $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist');
} }
/**
* @expectedException Exception
* @expectedExceptionCode 90
*/
public function testCommentErrorDetection() public function testCommentErrorDetection()
{ {
$this->_model->delete(Helper::getPasteId()); $this->_model->delete(Helper::getPasteId());
@ -138,26 +130,4 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
$this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), $comment), 'unable to store broken comment'); $this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), $comment), 'unable to store broken comment');
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does still not exist'); $this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does still not exist');
} }
/**
* @expectedException Exception
* @expectedExceptionCode 10
*/
public function testPermissionShenanigans()
{
// try creating an invalid path
chmod($this->_invalidPath, 0000);
Filesystem::getInstance(array('dir' => $this->_invalidPath . DIRECTORY_SEPARATOR . 'baz'));
}
/**
* @expectedException Exception
* @expectedExceptionCode 11
*/
public function testPathShenanigans()
{
// try setting an invalid path
chmod($this->_invalidPath, 0000);
Filesystem::getInstance(array('dir' => $this->_invalidPath));
}
} }

View file

@ -98,6 +98,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
new PrivateBin; new PrivateBin;
$content = ob_get_contents(); $content = ob_get_contents();
ob_end_clean(); ob_end_clean();
unlink($file);
$response = json_decode($content, true); $response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status'); $this->assertEquals(0, $response['status'], 'outputs status');
$this->assertEquals(Helper::getPasteId(), $response['id'], 'outputted paste ID matches input'); $this->assertEquals(Helper::getPasteId(), $response['id'], 'outputted paste ID matches input');
@ -132,6 +133,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
new PrivateBin; new PrivateBin;
$content = ob_get_contents(); $content = ob_get_contents();
ob_end_clean(); ob_end_clean();
unlink($file);
$response = json_decode($content, true); $response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status'); $this->assertEquals(0, $response['status'], 'outputs status');
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted'); $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');

View file

@ -63,6 +63,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
file_put_contents($file, 'data=foo'); file_put_contents($file, 'data=foo');
Request::setInputStream($file); Request::setInputStream($file);
$request = new Request; $request = new Request;
unlink($file);
$this->assertTrue($request->isJsonApiCall(), 'is JSON Api call'); $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
$this->assertEquals('create', $request->getOperation()); $this->assertEquals('create', $request->getOperation());
$this->assertEquals('foo', $request->getParam('data')); $this->assertEquals('foo', $request->getParam('data'));