diff --git a/get_data.lib.php b/get_data.lib.php
index 8d631b4..62c8a4f 100644
--- a/get_data.lib.php
+++ b/get_data.lib.php
@@ -3,6 +3,13 @@ require_once('open_db.lib.php');
require_once(__DIR__ . '/lib/purify.inc.php');
require_once(__DIR__ . '/html.lib.php');
+// The longest story HTML, in bytes. HTML Purifier needs seconds for a few megabytes.
+define('MAX_STORY_BYTES', 65536);
+
+function story_too_long($story) {
+ return strlen((string)$story) > MAX_STORY_BYTES;
+}
+
function display_stories($id = NULL) {
global $db, $is_admin, $editable, $action;
if (is_null($id))
@@ -10,17 +17,20 @@ function display_stories($id = NULL) {
$search = get_search_args();
$page = '';
$nolink = NULL;
+ $posted = FALSE;
if ($action == 'preview') {
global $file_src;
$date = 'Awaiting posting';
$result = get_post_data(TRUE);
$nolink = TRUE;
+ $posted = TRUE;
} else if ($action == 'submit') {
$date = 'Posted '.gmdate("Y-m-d H:i");
if (!$is_admin) {
$result = get_post_data(TRUE);
$nolink = TRUE;
+ $posted = TRUE;
} else {
$result = get_query($id);
}
@@ -90,6 +100,8 @@ date("Y-m-d H:i", strtotime($entry['date'])) . '';
} else {
$page .= '';
}
+ } else if ($posted && story_too_long($entry['story'])) {
+ $page .= '
The story is too long to show.
'."\n"; } else { $page .= purify_story($entry['story'])."\n"; } diff --git a/publish/post.lib.php b/publish/post.lib.php index 4d9b2c9..90aef93 100644 --- a/publish/post.lib.php +++ b/publish/post.lib.php @@ -206,6 +206,10 @@ function validate_data() { $validate['title'] = "You have not submitted a title."; } + if (story_too_long($story)) { + $validate['story'] = 'The story is too long. Please shorten it.'; + } + if ($remove_img && !$story) { $validate['story'] = "You've tried to remove an image without replacing it with text."; } diff --git a/tests/php/Unit/DisplayStoriesTest.php b/tests/php/Unit/DisplayStoriesTest.php index a7c7f62..bfe0f7d 100644 --- a/tests/php/Unit/DisplayStoriesTest.php +++ b/tests/php/Unit/DisplayStoriesTest.php @@ -111,6 +111,15 @@ class DisplayStoriesTest extends TestCase { $this->assertStringNotContainsString('x()', $page); } + // HTML Purifier needs seconds for a few megabytes, so a posted story over the limit is not shown + public function testPreviewDoesNotShowATooLongStory(): void { + $GLOBALS['action'] = 'preview'; + $this->request(array(), array('title' => 'Long', 'author' => 'Me', 'story' => 'x
' . str_repeat('a', 65536))); + $page = display_stories(); + $this->assertStringContainsString('The story is too long to show.
', $page); + $this->assertStringNotContainsString('x', $page); + } + public function testPreviewShowsAPendingImage(): void { $GLOBALS['action'] = 'preview'; $GLOBALS['file_src'] = '/display?pending=">