setTables(array( 'xxx' => array( array('id' => 1, 'title' => 'Tom & "Jerry"', 'author' => 'Ann ', 'date' => '2021-01-03 10:00:00', 'story' => "

Wait… a bold\x01 move & more.

"), array('id' => 2, 'title' => 'Picture', 'date' => '2021-01-02 10:00:00', 'story' => '', 'img' => TestCase::png(), 'mime' => 'text/html'), array('id' => 3, 'title' => 'Secret', 'date' => '2021-01-01 10:00:00', 'img' => TestCase::png(), 'mime' => 'image/png', 'hidden' => '1'), array('id' => 4, 'title' => 'Not an image', 'img' => '', 'mime' => 'image/png'), ), 'queue' => array( array('id' => 9, 'title' => 'Waiting', 'img' => TestCase::png(), 'mime' => 'image/png'), ), )); } public function testTheFeedIsValidRss(): void { $feed = $this->get('/feed'); $this->assertSame('application/rss+xml', $this->header($feed, 'Content-Type')); $xml = simplexml_load_string($feed['body']); $this->assertNotFalse($xml, $feed['body']); $items = $xml->channel->item; // The front page, then the visible stories, newest first $this->assertSame(array('Front Page', 'Tom & "Jerry"', 'Picture', 'Not an image'), array_map('strval', iterator_to_array($xml->xpath('/rss/channel/item/title'), FALSE))); $this->assertSame('http://xxx.org.za/article?id=1', (string)$items[1]->link); $this->assertSame('Wait… a bold move & more.', (string)$items[1]->description); $this->assertSame('Ann ', (string)$items[1]->children('http://purl.org/dc/elements/1.1/')->creator); $this->assertSame('Image: Picture', (string)$items[2]->description); $this->assertSame(date('D, d M Y H:i:s O', strtotime('2021-01-03 10:00:00')), (string)$xml->channel->lastBuildDate); } public function testAnImageIsServedWithItsRealType(): void { $image = $this->get('/display?id=2'); $this->assertSame(200, $image['status']); $this->assertSame(TestCase::png(), $image['body']); $this->assertSame('image/png', $this->header($image, 'Content-Type')); $this->assertSame('nosniff', $this->header($image, 'X-Content-Type-Options')); $this->assertSame((string)strlen(TestCase::png()), $this->header($image, 'Content-Length')); } public function testDataThatIsNotAnImageIsNotServed(): void { $image = $this->get('/display?id=4'); $this->assertSame(404, $image['status']); $this->assertStringNotContainsString('script', $image['body']); } public function testAMissingImageIsNotFound(): void { $this->assertSame(404, $this->get('/display?id=99')['status']); $this->assertSame(404, $this->get('/display?id=1')['status']); } public function testHiddenImagesAreForEditorsOnly(): void { $this->assertSame(404, $this->get('/display?id=3')['status']); $this->loginAs(); $this->assertSame(200, $this->get('/display?id=3')['status']); } public function testQueuedImagesNeedPermission(): void { $this->assertSame(401, $this->get('/display?id=9&queue=1')['status']); $this->startSession(array('allow_queue_image' => '8')); $this->assertSame(401, $this->get('/display?id=9&queue=1')['status']); $this->startSession(array('allow_queue_image' => '9')); $this->assertSame(200, $this->get('/display?id=9&queue=1')['status']); $this->loginAs(); $this->assertSame(200, $this->get('/display?id=9&queue=1')['status']); } public function testThePendingUploadIsShownToItsSession(): void { $name = bin2hex(random_bytes(16)); mkdir(self::$state . '/tmp/uploads', 0700); file_put_contents(self::$state . "/tmp/uploads/$name", TestCase::png()); $this->assertSame(404, $this->get('/display?pending=x')['status']); $this->startSession(array('pending_upload' => $name)); $image = $this->get('/display?pending=' . substr($name, 0, 8)); $this->assertSame(200, $image['status']); $this->assertSame(TestCase::png(), $image['body']); $this->assertSame('private, no-store', $this->header($image, 'Cache-Control')); } public function testAPendingUploadMustBeAnImage(): void { $name = bin2hex(random_bytes(16)); mkdir(self::$state . '/tmp/uploads', 0700); file_put_contents(self::$state . "/tmp/uploads/$name", 'This is not an image at all.'); $this->startSession(array('pending_upload' => $name)); $this->assertSame(404, $this->get('/display?pending=x')['status']); } }