#4: Comments posted on photos are now checked against a white-list of allowed HTML tags, and these are filtered out (the inner content is still displayed.)

This commit is contained in:
Andy Heathershaw 2018-09-24 15:55:48 +01:00
parent f56d989d75
commit e00c1631bb
1 changed files with 56 additions and 1 deletions

View File

@ -137,9 +137,12 @@ class PhotoCommentController extends Controller
'comment' => 'required'
]);
$commentText = $this->stripDisallowedHtmlTags($request->get('comment'));
$comment = new PhotoComment();
$comment->photo_id = $photo->id;
$comment->fill($request->only(['name', 'email', 'comment']));
$comment->fill($request->only(['name', 'email']));
$comment->comment = $commentText;
if (!is_null($parentComment))
{
@ -273,4 +276,56 @@ class PhotoCommentController extends Controller
dd($moderators);
}
private function stripDisallowedHtmlTags($commentText)
{
$allowedHtmlTags = explode(',', UserConfig::get('photo_comments_allowed_html'));
$allowedHtmlTagsCleaned = [];
foreach ($allowedHtmlTags as $tag)
{
$allowedHtmlTagsCleaned[] = trim($tag);
}
// Match any starting HTML tags
$regexMatchString = '/<(?!\/)([a-z]+)(?:\s.*)*>/Us';
$htmlTagMatches = [];
preg_match_all($regexMatchString, $commentText, $htmlTagMatches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
for ($index = 0; $index < count($htmlTagMatches); $index++)
{
$htmlTagMatch = $htmlTagMatches[$index];
$htmlTag = $htmlTagMatch[1][0]; // e.g. "p" for <p>
if (in_array($htmlTag, $allowedHtmlTagsCleaned))
{
// This tag is allowed - carry on
continue;
}
/* This tag is not allowed - remove it from the string */
// Find the closing tag
$disallowedStringOffset = $htmlTagMatch[0][1];
$endingTagMatches = [];
preg_match(sprintf('/(<%1$s.*>)(.+)<\/%1$s>/Us', $htmlTag), $commentText, $endingTagMatches, 0, $disallowedStringOffset);
// Replace the matched string with the inner string
$commentText = substr_replace($commentText, $endingTagMatches[2], $disallowedStringOffset, strlen($endingTagMatches[0]));
// Find out what difference in lengths the string are post-replacement (we will have only replaced the tags, not the entire string, so we just use)
// the length of the captured start tag
$differenceAfterReplacement = strlen($endingTagMatches[1]);
// Adjust the offsets for strings after the one we're processing, so the offsets match up with the string correctly
for ($index2 = $index + 1; $index2 < count($htmlTagMatches); $index2++)
{
$htmlTagMatches[$index2][0][1] -= $differenceAfterReplacement;
$htmlTagMatches[$index2][1][1] -= $differenceAfterReplacement;
}
}
return $commentText;
}
}