From 90c892249bc71d72dc5eb706a1ad711ee89f3a10 Mon Sep 17 00:00:00 2001 From: Marc Bradshaw Date: Mon, 18 Sep 2023 01:24:38 +0000 Subject: [PATCH] Option to set more strict quoting of strings --- lib/Mail/AuthenticationResults/Header/Base.pm | 39 +++++++++++++++++- t/05-as_string-styles.t | 40 ++++++++++++++++--- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/lib/Mail/AuthenticationResults/Header/Base.pm b/lib/Mail/AuthenticationResults/Header/Base.pm index 9f52dc2..72a553d 100644 --- a/lib/Mail/AuthenticationResults/Header/Base.pm +++ b/lib/Mail/AuthenticationResults/Header/Base.pm @@ -206,8 +206,10 @@ sub stringify { my ( $self, $value ) = @_; my $string = $value; $string = q{} if ! defined $string; #5.8; + my $strict_quotes = $self->strict_quotes; - if ( $string =~ /[\s\t \(\);=]/ ) { + if ( ( $strict_quotes && $string =~ /[\s\t \(\);=<>@,:\\\/\[\]\?]/ ) + || ( !$strict_quotes && $string =~ /[\s\t \(\);=]/ ) ) { $string = '"' . $string . '"'; } @@ -369,6 +371,41 @@ sub ancestor { return ( $eldest, $depth ); } +=method strict_quotes() + +Return the current value of strict quotes flag for this header or for its +ancestor if not set locally + +If true, we are stricter about which characters result in a quoted string + +=cut + +sub strict_quotes { + my ( $self ) = @_; + + return $self->{ 'strict_quotes' } if defined $self->{ 'strict_quotes' }; + + my ( $eldest, $depth ) = $self->ancestor(); + return 0 if $depth == 0; + return $eldest->strict_quotes; +} + +=method set_strict_quotes( $value ) + +Set the value of strict quotes + +If true, we are stricter about which characters result in a quoted string + +Default false + +=cut + +sub set_strict_quotes { + my ( $self, $value ) = @_; + $self->{ 'strict_quotes' } = $value ? 1 : 0; + return $self; +} + =method as_string_prefix( $header ) Add the prefix to as_string for this object when calledas a child diff --git a/t/05-as_string-styles.t b/t/05-as_string-styles.t index 1d80269..9cc36ff 100644 --- a/t/05-as_string-styles.t +++ b/t/05-as_string-styles.t @@ -17,7 +17,8 @@ my $Input = [ 'x-google-dkim=none (no signatures found)', 'dmarc=fail (p=none,d=none) header.from=marcbradshaw.net', 'dmarc=fail (p=reject,d=reject) header.from=goestheweasel.com', - 'dmarc=none (p=none,d=none) header.from=example.com' + 'dmarc=none (p=none,d=none) header.from=example.com', + 'x-url=http://example.com' ]; my $InputARHeader = join( ";\n", 'test.example.com', @$Input ); @@ -25,7 +26,7 @@ my $InputARHeader = join( ";\n", 'test.example.com', @$Input ); my $Parser = Mail::AuthenticationResults::Parser->new( $InputARHeader ); my $Parsed = $Parser->parsed(); -my $None = 'test.example.com; iprev=fail policy.iprev=123.123.123.123 (NOT FOUND); x-ptr=fail x-ptr-helo=bad.name.google.com x-ptr-lookup=""; spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; dkim=none (no signatures found); x-google-dkim=none (no signatures found); dmarc=fail (p=none,d=none) header.from=marcbradshaw.net; dmarc=fail (p=reject,d=reject) header.from=goestheweasel.com; dmarc=none (p=none,d=none) header.from=example.com'; +my $None = 'test.example.com; iprev=fail policy.iprev=123.123.123.123 (NOT FOUND); x-ptr=fail x-ptr-helo=bad.name.google.com x-ptr-lookup=""; spf=fail smtp.mailfrom=test@goestheweasel.com smtp.helo=bad.name.google.com; dkim=none (no signatures found); x-google-dkim=none (no signatures found); dmarc=fail (p=none,d=none) header.from=marcbradshaw.net; dmarc=fail (p=reject,d=reject) header.from=goestheweasel.com; dmarc=none (p=none,d=none) header.from=example.com; x-url=http://example.com'; my $Entry = 'test.example.com; iprev=fail policy.iprev=123.123.123.123 (NOT FOUND); @@ -35,7 +36,8 @@ my $Entry = 'test.example.com; x-google-dkim=none (no signatures found); dmarc=fail (p=none,d=none) header.from=marcbradshaw.net; dmarc=fail (p=reject,d=reject) header.from=goestheweasel.com; - dmarc=none (p=none,d=none) header.from=example.com'; + dmarc=none (p=none,d=none) header.from=example.com; + x-url=http://example.com'; my $SubEntry = 'test.example.com; iprev=fail @@ -53,7 +55,8 @@ my $SubEntry = 'test.example.com; dmarc=fail (p=reject,d=reject) header.from=goestheweasel.com; dmarc=none (p=none,d=none) - header.from=example.com'; + header.from=example.com; + x-url=http://example.com'; my $Full = 'test.example.com; iprev=fail @@ -77,13 +80,40 @@ my $Full = 'test.example.com; header.from=goestheweasel.com; dmarc=none (p=none,d=none) - header.from=example.com'; + header.from=example.com; + x-url=http://example.com'; +my $FullStrict = 'test.example.com; + iprev=fail + policy.iprev=123.123.123.123 + (NOT FOUND); + x-ptr=fail + x-ptr-helo=bad.name.google.com + x-ptr-lookup=""; + spf=fail + smtp.mailfrom="test@goestheweasel.com" + smtp.helo=bad.name.google.com; + dkim=none + (no signatures found); + x-google-dkim=none + (no signatures found); + dmarc=fail + (p=none,d=none) + header.from=marcbradshaw.net; + dmarc=fail + (p=reject,d=reject) + header.from=goestheweasel.com; + dmarc=none + (p=none,d=none) + header.from=example.com; + x-url="http://example.com"'; is( $Parsed->set_indent_style( 'none' )->as_string(), $None, 'None stringifies correctly' ); is( $Parsed->set_indent_style( 'entry' )->as_string(), $Entry, 'Entry stringifies correctly' ); is( $Parsed->set_indent_style( 'subentry' )->as_string(), $SubEntry, 'SubEntry stringifies correctly' ); is( $Parsed->set_indent_style( 'full' )->as_string(), $Full, 'Full stringifies correctly' ); +is( $Parsed->set_indent_style( 'full' )->set_strict_quotes(1)->as_string(), $FullStrict, 'Full Strict stringifies correctly' ); + dies_ok( sub{ $Parsed->set_indent_style( 'bogus_indent_style' ); }, 'invalid style dies' ); done_testing();