Author: fkento
Date: Wed Oct 15 19:19:13 2025
New Revision: 1929159
Log:
Add support for nested anchor tags
Added:
spamassassin/trunk/t/html_nested_anchors.t
Modified:
spamassassin/trunk/MANIFEST
spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm
Modified: spamassassin/trunk/MANIFEST
==============================================================================
--- spamassassin/trunk/MANIFEST Wed Oct 15 14:28:12 2025 (r1929158)
+++ spamassassin/trunk/MANIFEST Wed Oct 15 19:19:13 2025 (r1929159)
@@ -555,6 +555,7 @@ t/header.t
t/header_utf8.t
t/hashbl.t
t/html_colors.t
+t/html_nested_anchors.t
t/html_obfu.t
t/html_utf8.t
t/html_visibility.t
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm Wed Oct 15 14:28:12 2025 (r1929158)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/HTML.pm Wed Oct 15 19:19:13 2025 (r1929159)
@@ -125,6 +125,7 @@ sub new {
$self->{SA_character_semantics_input} = $character_semantics_input;
$self->{SA_encode_results} =
$character_semantics_input && !$character_semantics_output;
+ $self->{anchor_refs} = [];
$self;
}
@@ -343,6 +344,7 @@ sub html_tag {
}
# end tags
else {
+ pop(@{ $self->{anchor_refs} }) if $tag eq "a";
$self->{closed_html} = 1 if $tag eq "html";
$self->{closed_body} = 1 if $tag eq "body";
}
@@ -859,9 +861,7 @@ sub html_tests {
}
}
if ($tag eq "img" && exists $self->{inside}{a} && $self->{inside}{a} > 0) {
- my $uri = $self->{anchor_last};
- utf8::encode($uri) if $self->{SA_encode_results};
- $self->{uri}->{$uri}->{anchor_text}->[-1] .= "<img>\n";
+ $$_ .= "<img>\n" for (@{$self->{anchor_refs}});
$self->{anchor}->[-1] .= "<img>\n";
}
@@ -896,11 +896,13 @@ sub html_tests {
# special text delimiters - <a> and <title>
if ($tag eq "a") {
- my $uri = $self->{anchor_last} =
+ my $uri =
(exists $attr->{href} ? $self->canon_uri($attr->{href}) : "");
utf8::encode($uri) if $self->{SA_encode_results};
push(@{$self->{uri}->{$uri}->{anchor_text}}, '');
push(@{$self->{anchor}}, '');
+ # keep track of nested anchors (max depth 10)
+ push(@{$self->{anchor_refs}}, \($self->{uri}->{$uri}->{anchor_text}->[-1])) if @{$self->{anchor_refs}} < 10;
}
if ($tag eq "title") {
$self->{title_index}++;
@@ -977,10 +979,7 @@ sub html_text {
# text that is part of body and also stored separately
if (exists $self->{inside}{a} && $self->{inside}{a} > 0) {
- # this doesn't worry about nested anchors
- my $uri = $self->{anchor_last};
- utf8::encode($uri) if $self->{SA_encode_results};
- $self->{uri}->{$uri}->{anchor_text}->[-1] .= $text;
+ $$_ .= $text for (@{$self->{anchor_refs}});
$self->{anchor}->[-1] .= $text;
}
if (exists $self->{inside}{title} && $self->{inside}{title} > 0) {
Added: spamassassin/trunk/t/html_nested_anchors.t
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ spamassassin/trunk/t/html_nested_anchors.t Wed Oct 15 19:19:13 2025 (r1929159)
@@ -0,0 +1,45 @@
+#!/usr/bin/perl -T
+use strict;
+use warnings;
+use lib '.'; use lib 't';
+use SATest; sa_t_init("html_nested_anchors");
+use Mail::SpamAssassin::HTML;
+use Test::More;
+
+my @tests = (
+ {
+ html => '<a href="#one">foo<a href="#two">bar</a>baz</a>',
+ uris => {
+ '#one' => {
+ types => { 'a' => 1 },
+ anchor_text => ['foobarbaz'],
+ },
+ '#two' => {
+ types => { 'a' => 1 },
+ anchor_text => ['bar'],
+ }
+ }
+ },
+ {
+ html => '<a href="#one">foo<a href="#one">bar</a>baz</a>',
+ uris => {
+ '#one' => {
+ types => { 'a' => 1 },
+ anchor_text => ['foobarbaz', 'bar'],
+ },
+ }
+ },
+);
+
+plan tests => scalar @tests;
+
+foreach my $test (@tests) {
+ my $html = $test->{html};
+
+ my $html_obj = Mail::SpamAssassin::HTML->new(0, 0);
+ $html_obj->parse($html);
+
+ my $uris = $html_obj->{results}->{uri_detail};
+ is_deeply($uris, $test->{uris}, "URI details match for HTML: $html");
+
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.