2024-06-04 01:13:55 -04:00
< ? php declare ( strict_types = 1 );
2016-07-21 11:09:48 -04:00
2020-10-10 06:08:58 -04:00
use PHPUnit\Framework\TestCase ;
2016-08-09 05:54:42 -04:00
use PrivateBin\Data\Filesystem ;
2016-07-21 11:09:48 -04:00
2020-10-10 06:08:58 -04:00
class FilesystemTest extends TestCase
2015-08-15 12:32:31 -04:00
{
private $_model ;
private $_path ;
2017-03-24 16:30:08 -04:00
private $_invalidPath ;
2020-10-10 06:22:20 -04:00
public function setUp () : void
2015-08-15 12:32:31 -04:00
{
/* Setup Routine */
2017-03-24 16:35:50 -04:00
$this -> _path = sys_get_temp_dir () . DIRECTORY_SEPARATOR . 'privatebin_data' ;
2017-03-24 16:30:08 -04:00
$this -> _invalidPath = $this -> _path . DIRECTORY_SEPARATOR . 'bar' ;
2022-10-27 19:01:02 -04:00
$this -> _model = new Filesystem ( array ( 'dir' => $this -> _path ));
2017-03-24 16:30:08 -04:00
if ( ! is_dir ( $this -> _path )) {
mkdir ( $this -> _path );
}
if ( ! is_dir ( $this -> _invalidPath )) {
mkdir ( $this -> _invalidPath );
}
2015-08-15 12:32:31 -04:00
}
2020-10-10 06:22:20 -04:00
public function tearDown () : void
2015-08-15 12:32:31 -04:00
{
/* Tear Down Routine */
2017-03-24 16:30:08 -04:00
chmod ( $this -> _invalidPath , 0700 );
2016-08-09 05:54:42 -04:00
Helper :: rmDir ( $this -> _path );
2015-08-15 12:32:31 -04:00
}
public function testFileBasedDataStoreWorks ()
{
2016-08-09 05:54:42 -04:00
$this -> _model -> delete ( Helper :: getPasteId ());
2015-09-26 06:29:27 -04:00
2015-08-15 12:32:31 -04:00
// storing pastes
2019-05-10 01:55:39 -04:00
$paste = Helper :: getPaste ( 2 , array ( 'expire_date' => 1344803344 ));
2016-08-09 05:54:42 -04:00
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does not yet exist' );
$this -> assertTrue ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'store new paste' );
$this -> assertTrue ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste exists after storing it' );
$this -> assertFalse ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'unable to store the same paste twice' );
2019-05-10 01:55:39 -04:00
$this -> assertEquals ( $paste , $this -> _model -> read ( Helper :: getPasteId ()));
2015-08-15 12:32:31 -04:00
// storing comments
2016-08-09 05:54:42 -04:00
$this -> assertFalse ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment does not yet exist' );
2016-08-11 08:41:52 -04:00
$this -> assertTrue ( $this -> _model -> createComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId (), Helper :: getComment ()), 'store comment' );
2016-08-09 05:54:42 -04:00
$this -> assertTrue ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment exists after storing it' );
2017-03-24 16:30:08 -04:00
$this -> assertFalse ( $this -> _model -> createComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId (), Helper :: getComment ()), 'unable to store the same comment twice' );
2019-05-10 01:55:39 -04:00
$comment = Helper :: getComment ();
$comment [ 'id' ] = Helper :: getCommentId ();
$comment [ 'parentid' ] = Helper :: getPasteId ();
2015-08-15 12:32:31 -04:00
$this -> assertEquals (
2019-05-10 01:55:39 -04:00
array ( $comment [ 'meta' ][ 'created' ] => $comment ),
2016-08-09 05:54:42 -04:00
$this -> _model -> readComments ( Helper :: getPasteId ())
2015-08-15 12:32:31 -04:00
);
// deleting pastes
2016-08-09 05:54:42 -04:00
$this -> _model -> delete ( Helper :: getPasteId ());
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste successfully deleted' );
$this -> assertFalse ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment was deleted with paste' );
$this -> assertFalse ( $this -> _model -> read ( Helper :: getPasteId ()), 'paste can no longer be found' );
2015-08-15 12:32:31 -04:00
}
2015-09-26 06:29:27 -04:00
public function testFileBasedAttachmentStoreWorks ()
{
2016-08-09 05:54:42 -04:00
$this -> _model -> delete ( Helper :: getPasteId ());
2019-05-10 01:55:39 -04:00
$original = $paste = Helper :: getPasteWithAttachment ( 1 , array ( 'expire_date' => 1344803344 ));
2016-10-29 04:24:08 -04:00
$paste [ 'meta' ][ 'attachment' ] = $paste [ 'attachment' ];
2015-09-26 06:29:27 -04:00
$paste [ 'meta' ][ 'attachmentname' ] = $paste [ 'attachmentname' ];
unset ( $paste [ 'attachment' ], $paste [ 'attachmentname' ]);
2016-08-09 05:54:42 -04:00
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does not yet exist' );
$this -> assertTrue ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'store new paste' );
$this -> assertTrue ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste exists after storing it' );
$this -> assertFalse ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'unable to store the same paste twice' );
2019-05-10 01:55:39 -04:00
$this -> assertEquals ( $original , $this -> _model -> read ( Helper :: getPasteId ()));
2015-09-26 06:29:27 -04:00
}
2016-12-25 06:04:47 -05:00
/**
* pastes a - g are expired and should get deleted , x never expires and y - z expire in an hour
*/
2016-07-15 11:02:59 -04:00
public function testPurge ()
{
2016-07-18 08:47:32 -04:00
mkdir ( $this -> _path . DIRECTORY_SEPARATOR . '00' , 0777 , true );
2019-05-10 01:55:39 -04:00
$expired = Helper :: getPaste ( 2 , array ( 'expire_date' => 1344803344 ));
$paste = Helper :: getPaste ( 2 , array ( 'expire_date' => time () + 3600 ));
2016-12-25 06:04:47 -05:00
$keys = array ( 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'x' , 'y' , 'z' );
2016-10-29 04:24:08 -04:00
$ids = array ();
2016-07-26 02:19:35 -04:00
foreach ( $keys as $key ) {
2019-05-10 16:46:39 -04:00
$ids [ $key ] = hash ( 'fnv164' , $key );
2016-07-15 11:02:59 -04:00
$this -> assertFalse ( $this -> _model -> exists ( $ids [ $key ]), " paste $key does not yet exist " );
2016-07-26 02:19:35 -04:00
if ( in_array ( $key , array ( 'x' , 'y' , 'z' ))) {
2016-07-15 11:02:59 -04:00
$this -> assertTrue ( $this -> _model -> create ( $ids [ $key ], $paste ), " store $key paste " );
2016-12-25 06:04:47 -05:00
} elseif ( $key === 'x' ) {
$this -> assertTrue ( $this -> _model -> create ( $ids [ $key ], Helper :: getPaste ()), " store $key paste " );
2016-07-26 02:19:35 -04:00
} else {
2016-07-15 11:02:59 -04:00
$this -> assertTrue ( $this -> _model -> create ( $ids [ $key ], $expired ), " store $key paste " );
}
$this -> assertTrue ( $this -> _model -> exists ( $ids [ $key ]), " paste $key exists after storing it " );
}
$this -> _model -> purge ( 10 );
2016-07-26 02:19:35 -04:00
foreach ( $ids as $key => $id ) {
if ( in_array ( $key , array ( 'x' , 'y' , 'z' ))) {
2016-07-19 02:40:33 -04:00
$this -> assertTrue ( $this -> _model -> exists ( $id ), " paste $key exists after purge " );
$this -> _model -> delete ( $id );
2016-07-26 02:19:35 -04:00
} else {
2016-07-19 02:40:33 -04:00
$this -> assertFalse ( $this -> _model -> exists ( $id ), " paste $key was purged " );
2016-07-15 11:02:59 -04:00
}
}
}
2016-08-11 08:41:52 -04:00
public function testErrorDetection ()
{
$this -> _model -> delete ( Helper :: getPasteId ());
2019-05-10 01:55:39 -04:00
$paste = Helper :: getPaste ( 2 , array ( 'expire' => " Invalid UTF-8 sequence: \xB1 \x31 " ));
2016-08-11 08:41:52 -04:00
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does not yet exist' );
$this -> assertFalse ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'unable to store broken paste' );
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does still not exist' );
2021-06-13 04:44:26 -04:00
$this -> assertFalse ( $this -> _model -> setValue ( 'foo' , 'non existing namespace' ), 'rejects setting value in non existing namespace' );
2016-08-11 08:41:52 -04:00
}
public function testCommentErrorDetection ()
{
$this -> _model -> delete ( Helper :: getPasteId ());
2019-05-10 01:55:39 -04:00
$comment = Helper :: getComment ( 1 , array ( 'nickname' => " Invalid UTF-8 sequence: \xB1 \x31 " ));
2016-08-11 08:41:52 -04:00
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does not yet exist' );
2016-08-11 09:03:48 -04:00
$this -> assertTrue ( $this -> _model -> create ( Helper :: getPasteId (), Helper :: getPaste ()), 'store new paste' );
2016-08-11 08:41:52 -04:00
$this -> assertTrue ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste exists after storing it' );
$this -> assertFalse ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment does not yet exist' );
$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' );
}
2017-10-08 01:46:28 -04:00
public function testOldFilesGetConverted ()
{
// generate 10 (default purge batch size) pastes in the old format
2017-10-08 05:31:41 -04:00
$paste = Helper :: getPaste ();
$comment = Helper :: getComment ();
2017-10-08 01:46:28 -04:00
$commentid = Helper :: getCommentId ();
2017-10-08 05:31:41 -04:00
$ids = array ();
2017-10-08 01:46:28 -04:00
for ( $i = 0 , $max = 10 ; $i < $max ; ++ $i ) {
// PHPs mt_rand only supports 32 bit or up 0x7fffffff on 64 bit systems to be precise :-/
$dataid = str_pad ( dechex ( mt_rand ( 0 , mt_getrandmax ())), 8 , '0' , STR_PAD_LEFT ) .
str_pad ( dechex ( mt_rand ( 0 , mt_getrandmax ())), 8 , '0' , STR_PAD_LEFT );
2017-10-08 05:31:41 -04:00
$storagedir = $this -> _path . DIRECTORY_SEPARATOR . substr ( $dataid , 0 , 2 ) .
2017-10-08 01:46:28 -04:00
DIRECTORY_SEPARATOR . substr ( $dataid , 2 , 2 ) . DIRECTORY_SEPARATOR ;
$ids [ $dataid ] = $storagedir ;
if ( ! is_dir ( $storagedir )) {
mkdir ( $storagedir , 0700 , true );
}
file_put_contents ( $storagedir . $dataid , json_encode ( $paste ));
$storagedir .= $dataid . '.discussion' . DIRECTORY_SEPARATOR ;
if ( ! is_dir ( $storagedir )) {
mkdir ( $storagedir , 0700 , true );
}
file_put_contents ( $storagedir . $dataid . '.' . $commentid . '.' . $dataid , json_encode ( $comment ));
}
// check that all 10 pastes were converted after the purge
$this -> _model -> purge ( 10 );
foreach ( $ids as $dataid => $storagedir ) {
$this -> assertFileExists ( $storagedir . $dataid . '.php' , " paste $dataid exists in new format " );
2020-10-11 04:31:24 -04:00
$this -> assertFileDoesNotExist ( $storagedir . $dataid , " old format paste $dataid got removed " );
2017-10-08 01:46:28 -04:00
$this -> assertTrue ( $this -> _model -> exists ( $dataid ), " paste $dataid exists " );
2019-05-10 01:55:39 -04:00
$this -> assertEquals ( $this -> _model -> read ( $dataid ), $paste , " paste $dataid wasn't modified in the conversion " );
2017-10-08 01:46:28 -04:00
$storagedir .= $dataid . '.discussion' . DIRECTORY_SEPARATOR ;
$this -> assertFileExists ( $storagedir . $dataid . '.' . $commentid . '.' . $dataid . '.php' , " comment of $dataid exists in new format " );
2020-10-11 04:31:24 -04:00
$this -> assertFileDoesNotExist ( $storagedir . $dataid . '.' . $commentid . '.' . $dataid , " old format comment of $dataid got removed " );
2017-10-08 01:46:28 -04:00
$this -> assertTrue ( $this -> _model -> existsComment ( $dataid , $dataid , $commentid ), " comment in paste $dataid exists " );
2019-05-10 01:55:39 -04:00
$comment = $comment ;
$comment [ 'id' ] = $commentid ;
$comment [ 'parentid' ] = $dataid ;
$this -> assertEquals ( $this -> _model -> readComments ( $dataid ), array ( $comment [ 'meta' ][ 'created' ] => $comment ), " comment of $dataid wasn't modified in the conversion " );
2017-10-08 01:46:28 -04:00
}
}
2015-08-15 12:32:31 -04:00
}