working on JsonApi tests

pull/431/head
El RIDO 2019-05-08 22:11:21 +02:00
parent 76dc01b959
commit 59569bf9fc
No known key found for this signature in database
GPG Key ID: 0F5C940A6BD81F92
10 changed files with 128 additions and 134 deletions

View File

@ -199,50 +199,32 @@ class Controller
TrafficLimiter::setConfiguration($this->_conf);
if (!TrafficLimiter::canPass()) {
return $this->_return_message(
1, I18n::_(
'Please wait %d seconds between each post.',
$this->_conf->getKey('limit', 'traffic')
)
);
1, I18n::_(
'Please wait %d seconds between each post.',
$this->_conf->getKey('limit', 'traffic')
)
);
}
$data = $this->_request->getParam('data');
$attachment = $this->_request->getParam('attachment');
$attachmentname = $this->_request->getParam('attachmentname');
// Ensure content is not too big.
$data = $this->_request->getData();
$sizelimit = $this->_conf->getKey('sizelimit');
if (
strlen($data) + strlen($attachment) + strlen($attachmentname) > $sizelimit
) {
if (strlen($data['ct']) > $sizelimit) {
return $this->_return_message(
1,
I18n::_(
'Paste is limited to %s of encrypted data.',
Filter::formatHumanReadableSize($sizelimit)
)
);
}
// Ensure attachment did not get lost due to webserver limits or Suhosin
if (strlen($attachmentname) > 0 && strlen($attachment) == 0) {
return $this->_return_message(1, 'Attachment missing in data received by server. Please check your webserver or suhosin configuration for maximum POST parameter limitations.');
1,
I18n::_(
'Paste is limited to %s of encrypted data.',
Filter::formatHumanReadableSize($sizelimit)
)
);
}
// The user posts a comment.
$pasteid = $this->_request->getParam('pasteid');
$parentid = $this->_request->getParam('parentid');
if (!empty($pasteid) && !empty($parentid)) {
$paste = $this->_model->getPaste($pasteid);
if (!empty($data['pasteid']) && !empty($data['parentid'])) {
$paste = $this->_model->getPaste($data['pasteid']);
if ($paste->exists()) {
try {
$comment = $paste->getComment($parentid);
$nickname = $this->_request->getParam('nickname');
if (!empty($nickname)) {
$comment->setNickname($nickname);
}
$comment = $paste->getComment($data['parentid']);
$comment->setData($data);
$comment->store();
} catch (Exception $e) {
@ -259,34 +241,6 @@ class Controller
$paste = $this->_model->getPaste();
try {
$paste->setData($data);
if (!empty($attachment)) {
$paste->setAttachment($attachment);
if (!empty($attachmentname)) {
$paste->setAttachmentName($attachmentname);
}
}
$expire = $this->_request->getParam('expire');
if (!empty($expire)) {
$paste->setExpiration($expire);
}
$burnafterreading = $this->_request->getParam('burnafterreading');
if (!empty($burnafterreading)) {
$paste->setBurnafterreading($burnafterreading);
}
$opendiscussion = $this->_request->getParam('opendiscussion');
if (!empty($opendiscussion)) {
$paste->setOpendiscussion($opendiscussion);
}
$formatter = $this->_request->getParam('formatter');
if (!empty($formatter)) {
$paste->setFormatter($formatter);
}
$paste->store();
} catch (Exception $e) {
return $this->_return_message(1, $e->getMessage());
@ -307,22 +261,17 @@ class Controller
try {
$paste = $this->_model->getPaste($dataid);
if ($paste->exists()) {
// accessing this property ensures that the paste would be
// accessing this method ensures that the paste would be
// deleted if it has already expired
$burnafterreading = $paste->isBurnafterreading();
$paste->get();
if (
($burnafterreading && $deletetoken == 'burnafterreading') || // either we burn-after it has been read //@TODO: not needed anymore now?
Filter::slowEquals($deletetoken, $paste->getDeleteToken()) // or we manually delete it with this secret token
Filter::slowEquals($deletetoken, $paste->getDeleteToken())
) {
// Paste exists and deletion token (if required) is valid: Delete the paste.
// Paste exists and deletion token is valid: Delete the paste.
$paste->delete();
$this->_status = 'Paste was properly deleted.';
} else {
if (!$burnafterreading && $deletetoken == 'burnafterreading') {
$this->_error = 'Paste is not of burn-after-reading type.';
} else {
$this->_error = 'Wrong deletion token. Paste was not deleted.';
}
$this->_error = 'Wrong deletion token. Paste was not deleted.';
}
} else {
$this->_error = self::GENERIC_ERROR;
@ -355,8 +304,8 @@ class Controller
$paste = $this->_model->getPaste($dataid);
if ($paste->exists()) {
$data = $paste->get();
if (property_exists($data->meta, 'salt')) {
unset($data->meta->salt);
if (array_key_exists('salt', $data['meta'])) {
unset($data['meta']['salt']);
}
$this->_return_message(0, $dataid, (array) $data);
} else {

View File

@ -163,7 +163,7 @@ abstract class AbstractData
/**
* Get next free slot for comment from postdate.
*
* @access public
* @access protected
* @param array $comments
* @param int|string $postdate
* @return int|string
@ -180,4 +180,25 @@ abstract class AbstractData
}
return $postdate;
}
/**
* Upgrade pre-version 1 pastes with attachment to version 1 format.
*
* @access protected
* @static
* @param array $paste
* @return array
*/
protected static function upgradePreV1Format(array $paste)
{
if (array_key_exists('attachment', $paste['meta'])) {
$paste['attachment'] = $paste['meta']['attachment'];
unset($paste['meta']['attachment']);
if (array_key_exists('attachmentname', $paste['meta'])) {
$paste['attachmentname'] = $paste['meta']['attachmentname'];
unset($paste['meta']['attachmentname']);
}
}
return $paste;
}
}

View File

@ -249,12 +249,12 @@ class Database extends AbstractData
list($createdKey) = self::_getVersionedKeys(1);
}
$meta = json_decode($paste['meta'], true);
if (!is_array($meta)) {
$meta = array();
$paste['meta'] = json_decode($paste['meta'], true);
if (!is_array($paste['meta'])) {
$paste['meta'] = array();
}
self::$_cache[$pasteid]['meta'] = $meta;
$paste = self::upgradePreV1Format($paste);
self::$_cache[$pasteid]['meta'] = $paste['meta'];
self::$_cache[$pasteid]['meta'][$createdKey] = (int) $paste['postdate'];
$expire_date = (int) $paste['expiredate'];
if ($expire_date > 0) {
@ -264,17 +264,8 @@ class Database extends AbstractData
return self::$_cache[$pasteid];
}
// support pre v1 attachments
if (array_key_exists('attachment', $meta)) {
self::$_cache[$pasteid]['attachment'] = $meta['attachment'];
unset(self::$_cache[$pasteid]['meta']['attachment']);
if (array_key_exists('attachmentname', $meta)) {
self::$_cache[$pasteid]['attachmentname'] = $meta['attachmentname'];
unset(self::$_cache[$pasteid]['meta']['attachmentname']);
}
}
// support v1 attachments
elseif (array_key_exists('attachment', $paste) && strlen($paste['attachment'])) {
if (array_key_exists('attachment', $paste) && strlen($paste['attachment'])) {
self::$_cache[$pasteid]['attachment'] = $paste['attachment'];
if (array_key_exists('attachmentname', $paste) && strlen($paste['attachmentname'])) {
self::$_cache[$pasteid]['attachmentname'] = $paste['attachmentname'];

View File

@ -71,23 +71,16 @@ class Filesystem extends AbstractData
*
* @access public
* @param string $pasteid
* @return \stdClass|false
* @return array|false
*/
public function read($pasteid)
{
if (!$this->exists($pasteid)) {
return false;
}
$paste = DataStore::get(self::_dataid2path($pasteid) . $pasteid . '.php');
if (property_exists($paste->meta, 'attachment')) {
$paste->attachment = $paste->meta->attachment;
unset($paste->meta->attachment);
if (property_exists($paste->meta, 'attachmentname')) {
$paste->attachmentname = $paste->meta->attachmentname;
unset($paste->meta->attachmentname);
}
}
return $paste;
return self::upgradePreV1Format(
DataStore::get(self::_dataid2path($pasteid) . $pasteid . '.php')
);
}
/**

View File

@ -173,13 +173,31 @@ class Paste extends AbstractModel
*/
public function getDeleteToken()
{
if (!property_exists($this->_data->meta, 'salt')) {
if (!array_key_exists('salt', $this->_data['meta'])) {
$this->get();
}
return hash_hmac(
$this->_conf->getKey('zerobincompatibility') ? 'sha1' : 'sha256',
$this->getId(),
$this->_data->meta->salt
$this->_data['meta']['salt']
);
}
/**
* Check if paste is of burn-after-reading type.
*
* @access public
* @throws Exception
* @return bool
*/
public function isBurnafterreading()
{
if (!array_key_exists('adata', $this->_data) && !array_key_exists('data', $this->_data)) {
$this->get();
}
return (
(array_key_exists('adata', $this->_data) && $this->_data['adata'][3] === 1) ||
(array_key_exists('burnafterreading', $this->_data['meta']) && $this->_data['meta']['burnafterreading'])
);
}
@ -198,7 +216,7 @@ class Paste extends AbstractModel
return (
(array_key_exists('adata', $this->_data) && $this->_data['adata'][2] === 1) ||
(array_key_exists('opendiscussion', $this->_data['meta']) && $this->_data['meta']['opendiscussion'])
);
);
}
/**

View File

@ -62,7 +62,7 @@ class DataStore extends AbstractPersistence
*/
public static function get($filename)
{
return json_decode(substr(file_get_contents($filename), strlen(self::PROTECTION_LINE . PHP_EOL)));
return json_decode(substr(file_get_contents($filename), strlen(self::PROTECTION_LINE . PHP_EOL)), true);
}
/**

View File

@ -126,8 +126,8 @@ class Request
// prepare operation, depending on current parameters
if (
(array_key_exists('data', $this->_params) && !empty($this->_params['data'])) ||
(array_key_exists('attachment', $this->_params) && !empty($this->_params['attachment']))
array_key_exists('ct', $this->_params) &&
!empty($this->_params['ct'])
) {
$this->_operation = 'create';
} elseif (array_key_exists('pasteid', $this->_params) && !empty($this->_params['pasteid'])) {
@ -152,6 +152,33 @@ class Request
return $this->_operation;
}
/**
* Get data of paste or comment
*
* @access public
* @return array
*/
public function getData()
{
$data = array(
'adata' => json_decode($this->getParam('adata', '[]'), true)
);
$required_keys = array('v', 'ct');
$meta = $this->getParam('meta');
if (empty($meta)) {
$required_keys[] = 'pasteid';
$required_keys[] = 'parentid';
} else {
$data['meta'] = json_decode($meta, true);
}
foreach ($required_keys as $key) {
$data[$key] = $this->getParam($key);
}
// forcing a cast to int or float
$data['v'] = $data['v'] + 0;
return $data;
}
/**
* Get a request parameter
*

View File

@ -176,7 +176,8 @@ class Helper
public static function getPastePost()
{
$example = self::getPaste();
$example['meta'] = array('expire' => $example['meta']['expire']);
$example['adata'] = json_encode($example['adata']);
$example['meta'] = json_encode(array('expire' => $example['meta']['expire']));
return $example;
}

View File

@ -6,10 +6,13 @@ class FormatV2Test extends PHPUnit_Framework_TestCase
{
public function testFormatV2ValidatorValidatesCorrectly()
{
$this->assertTrue(FormatV2::isValid(Helper::getPaste()), 'valid format');
$this->assertTrue(FormatV2::isValid(Helper::getComment(), true), 'valid format');
$paste = Helper::getPaste();
$paste['meta'] = array('expire' => $paste['meta']['expire']);
$this->assertTrue(FormatV2::isValid($paste), 'valid format');
$comment = Helper::getComment();
unset($comment['meta']);
$this->assertTrue(FormatV2::isValid($comment, true), 'valid format');
$paste['adata'][0][0] = '$';
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of iv');

View File

@ -48,7 +48,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
$options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0;
Helper::createIniFile(CONF, $options);
$_POST = Helper::getPaste();
$_POST = Helper::getPastePost();
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
@ -62,7 +62,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
$this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
$paste = $this->_model->read($response['id']);
$this->assertEquals(
hash_hmac('sha256', $response['id'], $paste->meta->salt),
hash_hmac('sha256', $response['id'], $paste['meta']['salt']),
$response['deletetoken'],
'outputs valid delete token'
);
@ -76,8 +76,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
$options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0;
Helper::createIniFile(CONF, $options);
$paste = Helper::getPaste();
unset($paste['meta']);
$paste = Helper::getPastePost();
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, http_build_query($paste));
Request::setInputStream($file);
@ -98,7 +97,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
$this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
$paste = $this->_model->read($response['id']);
$this->assertEquals(
hash_hmac('sha256', $response['id'], $paste->meta->salt),
hash_hmac('sha256', $response['id'], $paste['meta']['salt']),
$response['deletetoken'],
'outputs valid delete token'
);
@ -114,7 +113,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
$paste = $this->_model->read(Helper::getPasteId());
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, http_build_query(array(
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste->meta->salt),
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste['meta']['salt']),
)));
Request::setInputStream($file);
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
@ -141,7 +140,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
$paste = $this->_model->read(Helper::getPasteId());
$_POST = array(
'pasteid' => Helper::getPasteId(),
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste->meta->salt),
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste['meta']['salt']),
);
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
@ -159,11 +158,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/
public function testRead()
{
$paste = Helper::getPasteWithAttachment();
$paste['meta']['attachment'] = $paste['attachment'];
$paste['meta']['attachmentname'] = $paste['attachmentname'];
unset($paste['attachment']);
unset($paste['attachmentname']);
$paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste);
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_GET[Helper::getPasteId()] = '';
@ -176,12 +171,8 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
$this->assertEquals(0, $response['status'], 'outputs success status');
$this->assertEquals(Helper::getPasteId(), $response['id'], 'outputs data correctly');
$this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
$this->assertEquals($paste['data'], $response['data'], 'outputs data correctly');
$this->assertEquals($paste['meta']['attachment'], $response['attachment'], 'outputs attachment correctly');
$this->assertEquals($paste['meta']['attachmentname'], $response['attachmentname'], 'outputs attachmentname correctly');
$this->assertEquals($paste['meta']['formatter'], $response['meta']['formatter'], 'outputs format correctly');
$this->assertEquals($paste['meta']['postdate'], $response['meta']['postdate'], 'outputs postdate correctly');
$this->assertEquals($paste['meta']['opendiscussion'], $response['meta']['opendiscussion'], 'outputs opendiscussion correctly');
$this->assertEquals($paste['ct'], $response['ct'], 'outputs data correctly');
$this->assertEquals($paste['meta']['created'], $response['meta']['created'], 'outputs postdate correctly');
$this->assertEquals(0, $response['comment_count'], 'outputs comment_count correctly');
$this->assertEquals(0, $response['comment_offset'], 'outputs comment_offset correctly');
}
@ -191,7 +182,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/
public function testJsonLdPaste()
{
$paste = Helper::getPasteWithAttachment();
$paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'paste';
ob_start();
@ -210,7 +201,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/
public function testJsonLdComment()
{
$paste = Helper::getPasteWithAttachment();
$paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'comment';
ob_start();
@ -229,7 +220,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/
public function testJsonLdPasteMeta()
{
$paste = Helper::getPasteWithAttachment();
$paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'pastemeta';
ob_start();
@ -248,7 +239,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/
public function testJsonLdCommentMeta()
{
$paste = Helper::getPasteWithAttachment();
$paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = 'commentmeta';
ob_start();
@ -267,7 +258,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
*/
public function testJsonLdInvalid()
{
$paste = Helper::getPasteWithAttachment();
$paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste);
$_GET['jsonld'] = CONF;
ob_start();