diff --git a/classes/helpers/FrmSpamEntriesHelper.php b/classes/helpers/FrmSpamEntriesHelper.php
index ca3ff7e75a..71f1d9127e 100644
--- a/classes/helpers/FrmSpamEntriesHelper.php
+++ b/classes/helpers/FrmSpamEntriesHelper.php
@@ -673,7 +673,7 @@ public static function escape_value( $value ) {
return array_map( array( self::class, 'escape_value' ), $value );
}
- return is_string( $value ) ? esc_html( $value ) : $value;
+ return is_string( $value ) ? esc_html( str_replace( array( '
', '
', '
' ), "\n", $value ) ) : $value;
}
/**
diff --git a/tests/phpunit/misc/test_FrmSpamOutput.php b/tests/phpunit/misc/test_FrmSpamOutput.php
index 65b215318e..ef729f3a1b 100644
--- a/tests/phpunit/misc/test_FrmSpamOutput.php
+++ b/tests/phpunit/misc/test_FrmSpamOutput.php
@@ -7,6 +7,58 @@
* @covers FrmFieldValue
*/
class test_FrmSpamOutput extends FrmUnitTest {
+ /**
+ * Spam values retain line breaks while other submitted markup remains escaped.
+ */
+ public function test_escape_value_preserves_line_breaks_and_escapes_markup() {
+ $value = array( 'nested' => array( 'First
Second
Third
Fourth
', '', null, 0 ) );
+ $expected = array( 'nested' => array( "First\nSecond\nThird\nFourth<img src=x onerror=alert(1)>", '', null, 0 ) );
+
+ $this->assertSame( $expected, FrmSpamEntriesHelper::escape_value( $value ), 'Breaks should become newlines without allowing other markup or changing non-string values.' );
+ }
+
+ /**
+ * Address formatting remains readable in the entry table after marking an entry as spam.
+ */
+ public function test_spam_address_displays_line_breaks_in_entry_table() {
+ $form = $this->factory->form->create();
+ $field = $this->factory->field->create_and_get(
+ array(
+ 'form_id' => $form,
+ 'type' => 'address',
+ )
+ );
+ $id = $this->factory->entry->create( array( 'form_id' => $form ) );
+ FrmEntryMeta::add_entry_meta(
+ $id,
+ $field->id,
+ '',
+ array(
+ 'line1' => '123 Main St',
+ 'city' => 'Baltimore',
+ 'state' => 'MD',
+ 'zip' => '12345',
+ 'country' => 'United States',
+ )
+ );
+ $normal = FrmEntriesController::show_entry_shortcode( array( 'id' => $id ) );
+ $this->assertTrue( FrmSpamEntriesHelper::mark_as_spam( $id ), 'The entry should be marked as spam.' );
+ $spam = FrmEntriesController::show_entry_shortcode( array( 'id' => $id ) );
+
+ if ( $this->is_pro_active ) {
+ $this->assertSame( $spam, do_shortcode( '[frm-show-entry id="' . $id . '"]' ), 'The Pro shortcode should render the same spam entry table.' );
+ }
+
+ foreach ( array( $normal, $spam ) as $html ) {
+ $this->assertMatchesRegularExpression(
+ '/123 Main St\s*
\s*Baltimore, MD 12345\s*
United States/',
+ $html,
+ 'Both normal and spam entries should display the address on separate lines.'
+ );
+ $this->assertStringNotContainsString( '<br', $html, 'Formatting breaks should not appear as literal tags.' );
+ }
+ }
+
/**
* Referrers keep line breaks without rendering submitted markup for normal or spam entries.
*