Filename | /usr/local/lib/perl5/site_perl/Mail/SpamAssassin/HTML.pm |
Statements | Executed 3809928 statements in 20.8s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
46554 | 5 | 1 | 3.71s | 4.08s | display_text | Mail::SpamAssassin::HTML::
47000 | 1 | 1 | 3.32s | 12.9s | html_tag | Mail::SpamAssassin::HTML::
29758 | 2 | 1 | 2.11s | 5.62s | html_text | Mail::SpamAssassin::HTML::
32968 | 1 | 1 | 2.05s | 5.03s | text_style | Mail::SpamAssassin::HTML::
16295 | 1 | 1 | 1.65s | 1.65s | close_tag | Mail::SpamAssassin::HTML::
232414 | 25 | 1 | 1.10s | 1.10s | CORE:match (opcode) | Mail::SpamAssassin::HTML::
7824 | 1 | 1 | 881ms | 891ms | close_table_tag | Mail::SpamAssassin::HTML::
24617 | 1 | 1 | 599ms | 683ms | html_tests | Mail::SpamAssassin::HTML::
101857 | 12 | 1 | 552ms | 552ms | CORE:subst (opcode) | Mail::SpamAssassin::HTML::
16898 | 1 | 1 | 537ms | 2.11s | html_whitespace | Mail::SpamAssassin::HTML::
2703 | 2 | 1 | 444ms | 530ms | _remove_dot_segments | Mail::SpamAssassin::HTML::
570 | 3 | 1 | 374ms | 374ms | get_rendered_text | Mail::SpamAssassin::HTML::
12674 | 1 | 1 | 371ms | 1.63s | html_uri | Mail::SpamAssassin::HTML::
4797 | 1 | 1 | 326ms | 369ms | html_font_invisible | Mail::SpamAssassin::HTML::
2705 | 1 | 1 | 276ms | 993ms | target_uri | Mail::SpamAssassin::HTML::
2340 | 3 | 1 | 201ms | 260ms | name_to_rgb | Mail::SpamAssassin::HTML::
5410 | 2 | 1 | 144ms | 188ms | _parse_uri | Mail::SpamAssassin::HTML::
4261 | 2 | 1 | 136ms | 171ms | canon_uri | Mail::SpamAssassin::HTML::
2705 | 3 | 1 | 115ms | 1.21s | push_uri | Mail::SpamAssassin::HTML::
3113 | 20 | 1 | 77.8ms | 77.8ms | put_results | Mail::SpamAssassin::HTML::
190 | 1 | 1 | 62.4ms | 134ms | html_end | Mail::SpamAssassin::HTML::
190 | 1 | 1 | 46.0ms | 20.4s | parse | Mail::SpamAssassin::HTML::
1404 | 1 | 1 | 28.6ms | 28.6ms | CORE:substcont (opcode) | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 13.7ms | 15.9ms | BEGIN@30 | Mail::SpamAssassin::HTML::
190 | 1 | 1 | 8.75ms | 79.2ms | new | Mail::SpamAssassin::HTML::
190 | 1 | 1 | 7.50ms | 12.2ms | html_start | Mail::SpamAssassin::HTML::
413 | 1 | 1 | 5.94ms | 5.94ms | html_comment | Mail::SpamAssassin::HTML::
67 | 1 | 1 | 2.60ms | 2.95ms | html_declaration | Mail::SpamAssassin::HTML::
190 | 1 | 1 | 1.58ms | 1.58ms | get_results | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 40µs | 61µs | BEGIN@23 | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 37µs | 251µs | BEGIN@1080 | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 31µs | 178µs | BEGIN@33 | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 30µs | 195µs | BEGIN@31 | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 25µs | 58µs | BEGIN@24 | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 24µs | 771µs | BEGIN@32 | Mail::SpamAssassin::HTML::
1 | 1 | 1 | 19µs | 104µs | BEGIN@25 | Mail::SpamAssassin::HTML::
0 | 0 | 0 | 0s | 0s | _merge_uri | Mail::SpamAssassin::HTML::
0 | 0 | 0 | 0s | 0s | dec2hex | Mail::SpamAssassin::HTML::
0 | 0 | 0 | 0s | 0s | name_to_rgb_old | Mail::SpamAssassin::HTML::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # <@LICENSE> | ||||
2 | # Licensed to the Apache Software Foundation (ASF) under one or more | ||||
3 | # contributor license agreements. See the NOTICE file distributed with | ||||
4 | # this work for additional information regarding copyright ownership. | ||||
5 | # The ASF licenses this file to you under the Apache License, Version 2.0 | ||||
6 | # (the "License"); you may not use this file except in compliance with | ||||
7 | # the License. You may obtain a copy of the License at: | ||||
8 | # | ||||
9 | # http://www.apache.org/licenses/LICENSE-2.0 | ||||
10 | # | ||||
11 | # Unless required by applicable law or agreed to in writing, software | ||||
12 | # distributed under the License is distributed on an "AS IS" BASIS, | ||||
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
14 | # See the License for the specific language governing permissions and | ||||
15 | # limitations under the License. | ||||
16 | # </@LICENSE> | ||||
17 | |||||
18 | # HTML decoding TODOs | ||||
19 | # - add URIs to list for faster URI testing | ||||
20 | |||||
21 | package Mail::SpamAssassin::HTML; | ||||
22 | |||||
23 | 2 | 71µs | 2 | 81µs | # spent 61µs (40+20) within Mail::SpamAssassin::HTML::BEGIN@23 which was called:
# once (40µs+20µs) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 23 # spent 61µs making 1 call to Mail::SpamAssassin::HTML::BEGIN@23
# spent 20µs making 1 call to strict::import |
24 | 2 | 75µs | 2 | 90µs | # spent 58µs (25+33) within Mail::SpamAssassin::HTML::BEGIN@24 which was called:
# once (25µs+33µs) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 24 # spent 58µs making 1 call to Mail::SpamAssassin::HTML::BEGIN@24
# spent 32µs making 1 call to warnings::import |
25 | 2 | 86µs | 2 | 189µs | # spent 104µs (19+85) within Mail::SpamAssassin::HTML::BEGIN@25 which was called:
# once (19µs+85µs) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 25 # spent 104µs making 1 call to Mail::SpamAssassin::HTML::BEGIN@25
# spent 85µs making 1 call to re::import |
26 | |||||
27 | 1 | 28µs | require 5.008; # need basic Unicode support for HTML::Parser::utf8_mode | ||
28 | # require 5.008008; # Bug 3787; [perl #37950]: Malformed UTF-8 character ... | ||||
29 | |||||
30 | 3 | 375µs | 2 | 15.9ms | # spent 15.9ms (13.7+2.15) within Mail::SpamAssassin::HTML::BEGIN@30 which was called:
# once (13.7ms+2.15ms) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 30 # spent 15.9ms making 1 call to Mail::SpamAssassin::HTML::BEGIN@30
# spent 18µs making 1 call to version::_VERSION |
31 | 2 | 72µs | 2 | 360µs | # spent 195µs (30+165) within Mail::SpamAssassin::HTML::BEGIN@31 which was called:
# once (30µs+165µs) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 31 # spent 195µs making 1 call to Mail::SpamAssassin::HTML::BEGIN@31
# spent 165µs making 1 call to Exporter::import |
32 | 2 | 71µs | 2 | 1.52ms | # spent 771µs (24+747) within Mail::SpamAssassin::HTML::BEGIN@32 which was called:
# once (24µs+747µs) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 32 # spent 771µs making 1 call to Mail::SpamAssassin::HTML::BEGIN@32
# spent 747µs making 1 call to Exporter::import |
33 | 2 | 12.3ms | 2 | 326µs | # spent 178µs (31+148) within Mail::SpamAssassin::HTML::BEGIN@33 which was called:
# once (31µs+148µs) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 33 # spent 178µs making 1 call to Mail::SpamAssassin::HTML::BEGIN@33
# spent 148µs making 1 call to Exporter::import |
34 | |||||
35 | 1 | 22µs | our @ISA = qw(HTML::Parser); | ||
36 | |||||
37 | # elements defined by the HTML 4.01 and XHTML 1.0 DTDs (do not change them!) | ||||
38 | # does not include XML | ||||
39 | 95 | 644µs | my %elements = map {; $_ => 1 } | ||
40 | # strict | ||||
41 | qw( a abbr acronym address area b base bdo big blockquote body br button caption cite code col colgroup dd del dfn div dl dt em fieldset form h1 h2 h3 h4 h5 h6 head hr html i img input ins kbd label legend li link map meta noscript object ol optgroup option p param pre q samp script select small span strong style sub sup table tbody td textarea tfoot th thead title tr tt ul var ), | ||||
42 | # loose | ||||
43 | qw( applet basefont center dir font frame frameset iframe isindex menu noframes s strike u ), | ||||
44 | # non-standard tags | ||||
45 | qw( nobr x-sigsep x-tab ), | ||||
46 | ; | ||||
47 | |||||
48 | # elements that we want to render, but not count as valid | ||||
49 | 6 | 28µs | my %tricks = map {; $_ => 1 } | ||
50 | # non-standard and non-valid tags | ||||
51 | qw( bgsound embed listing plaintext xmp ), | ||||
52 | # other non-standard tags handled in popfile | ||||
53 | # blink ilayer multicol noembed nolayer spacer wbr | ||||
54 | ; | ||||
55 | |||||
56 | # elements that change text style | ||||
57 | 14 | 87µs | my %elements_text_style = map {; $_ => 1 } | ||
58 | qw( body font table tr th td big small basefont marquee span p div ), | ||||
59 | ; | ||||
60 | |||||
61 | # elements that insert whitespace | ||||
62 | 23 | 142µs | my %elements_whitespace = map {; $_ => 1 } | ||
63 | qw( br div li th td dt dd p hr blockquote pre embed listing plaintext xmp title | ||||
64 | h1 h2 h3 h4 h5 h6 ), | ||||
65 | ; | ||||
66 | |||||
67 | # elements that push URIs | ||||
68 | 16 | 109µs | my %elements_uri = map {; $_ => 1 } | ||
69 | qw( body table tr td a area link img frame iframe embed script form base bgsound ), | ||||
70 | ; | ||||
71 | |||||
72 | # style attribute not accepted | ||||
73 | #my %elements_no_style = map {; $_ => 1 } | ||||
74 | # qw( base basefont head html meta param script style title ), | ||||
75 | #; | ||||
76 | |||||
77 | # permitted element attributes | ||||
78 | 1 | 9µs | my %ok_attributes; | ||
79 | 1 | 12µs | $ok_attributes{basefont}{$_} = 1 for qw( color face size ); | ||
80 | 1 | 45µs | $ok_attributes{body}{$_} = 1 for qw( text bgcolor link alink vlink background ); | ||
81 | 1 | 19µs | $ok_attributes{font}{$_} = 1 for qw( color face size ); | ||
82 | 1 | 17µs | $ok_attributes{marquee}{$_} = 1 for qw( bgcolor background ); | ||
83 | 1 | 12µs | $ok_attributes{table}{$_} = 1 for qw( bgcolor ); | ||
84 | 1 | 11µs | $ok_attributes{td}{$_} = 1 for qw( bgcolor ); | ||
85 | 1 | 14µs | $ok_attributes{th}{$_} = 1 for qw( bgcolor ); | ||
86 | 1 | 6µs | $ok_attributes{tr}{$_} = 1 for qw( bgcolor ); | ||
87 | 1 | 14µs | $ok_attributes{span}{$_} = 1 for qw( style ); | ||
88 | 1 | 6µs | $ok_attributes{p}{$_} = 1 for qw( style ); | ||
89 | 1 | 15µs | $ok_attributes{div}{$_} = 1 for qw( style ); | ||
90 | |||||
91 | # spent 79.2ms (8.75+70.5) within Mail::SpamAssassin::HTML::new which was called 190 times, avg 417µs/call:
# 190 times (8.75ms+70.5ms) by Mail::SpamAssassin::Message::Node::rendered at line 635 of Mail/SpamAssassin/Message/Node.pm, avg 417µs/call | ||||
92 | 190 | 544µs | my ($class, $character_semantics_input, $character_semantics_output) = @_; | ||
93 | 190 | 5.88ms | 190 | 70.5ms | my $self = $class->SUPER::new( # spent 70.5ms making 190 calls to HTML::Parser::new, avg 371µs/call |
94 | api_version => 3, | ||||
95 | handlers => [ | ||||
96 | start_document => ["html_start", "self"], | ||||
97 | start => ["html_tag", "self,tagname,attr,'+1'"], | ||||
98 | end_document => ["html_end", "self"], | ||||
99 | end => ["html_tag", "self,tagname,attr,'-1'"], | ||||
100 | text => ["html_text", "self,dtext"], | ||||
101 | comment => ["html_comment", "self,text"], | ||||
102 | declaration => ["html_declaration", "self,text"], | ||||
103 | ], | ||||
104 | marked_sections => 1); | ||||
105 | 190 | 618µs | $self->{SA_character_semantics_input} = $character_semantics_input; | ||
106 | $self->{SA_encode_results} = | ||||
107 | 190 | 580µs | $character_semantics_input && !$character_semantics_output; | ||
108 | 190 | 8.83ms | $self; | ||
109 | } | ||||
110 | |||||
111 | # spent 12.2ms (7.50+4.70) within Mail::SpamAssassin::HTML::html_start which was called 190 times, avg 64µs/call:
# 190 times (7.50ms+4.70ms) by HTML::Parser::parse at line 260, avg 64µs/call | ||||
112 | 190 | 447µs | my ($self) = @_; | ||
113 | |||||
114 | # trigger HTML_MESSAGE | ||||
115 | 190 | 1.69ms | 190 | 4.70ms | $self->put_results(html => 1); # spent 4.70ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 25µs/call |
116 | |||||
117 | # initial display attributes | ||||
118 | 190 | 687µs | $self->{basefont} = 3; | ||
119 | my %default = (tag => "default", | ||||
120 | fgcolor => "#000000", | ||||
121 | bgcolor => "#ffffff", | ||||
122 | 190 | 1.81ms | size => $self->{basefont}); | ||
123 | 380 | 2.82ms | push @{ $self->{text_style} }, \%default; | ||
124 | } | ||||
125 | |||||
126 | # spent 134ms (62.4+72.0) within Mail::SpamAssassin::HTML::html_end which was called 190 times, avg 707µs/call:
# 190 times (62.4ms+72.0ms) by HTML::Parser::eof at line 261, avg 707µs/call | ||||
127 | 190 | 448µs | my ($self) = @_; | ||
128 | |||||
129 | 190 | 1.22ms | delete $self->{text_style}; | ||
130 | |||||
131 | 190 | 365µs | my @uri; | ||
132 | |||||
133 | # add the canonicalized version of each uri to the detail list | ||||
134 | 190 | 823µs | if (defined $self->{uri}) { | ||
135 | 236 | 1.89ms | @uri = keys %{$self->{uri}}; | ||
136 | } | ||||
137 | |||||
138 | # these keep backward compatibility, albeit a little wasteful | ||||
139 | 190 | 1.57ms | 190 | 4.70ms | $self->put_results(uri => \@uri); # spent 4.70ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 25µs/call |
140 | 190 | 1.58ms | 190 | 4.87ms | $self->put_results(anchor => $self->{anchor}); # spent 4.87ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 26µs/call |
141 | |||||
142 | 190 | 1.44ms | 190 | 4.94ms | $self->put_results(uri_detail => $self->{uri}); # spent 4.94ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 26µs/call |
143 | 190 | 1.76ms | 190 | 5.00ms | $self->put_results(uri_truncated => $self->{uri_truncated}); # spent 5.00ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 26µs/call |
144 | |||||
145 | # final results scalars | ||||
146 | 190 | 1.39ms | 190 | 4.34ms | $self->put_results(image_area => $self->{image_area}); # spent 4.34ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 23µs/call |
147 | 190 | 1.41ms | 190 | 3.90ms | $self->put_results(length => $self->{length}); # spent 3.90ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 21µs/call |
148 | 190 | 1.35ms | 190 | 4.88ms | $self->put_results(min_size => $self->{min_size}); # spent 4.88ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 26µs/call |
149 | 190 | 1.39ms | 190 | 3.80ms | $self->put_results(max_size => $self->{max_size}); # spent 3.80ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 20µs/call |
150 | 190 | 1.59ms | if (exists $self->{tags}) { | ||
151 | $self->put_results(closed_extra_ratio => | ||||
152 | 188 | 1.77ms | 188 | 4.93ms | ($self->{closed_extra} / $self->{tags})); # spent 4.93ms making 188 calls to Mail::SpamAssassin::HTML::put_results, avg 26µs/call |
153 | } | ||||
154 | |||||
155 | # final result arrays | ||||
156 | 190 | 1.63ms | 190 | 4.91ms | $self->put_results(comment => $self->{comment}); # spent 4.91ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 26µs/call |
157 | 190 | 1.63ms | 190 | 5.06ms | $self->put_results(script => $self->{script}); # spent 5.06ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 27µs/call |
158 | 190 | 1.55ms | 190 | 4.75ms | $self->put_results(title => $self->{title}); # spent 4.75ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 25µs/call |
159 | |||||
160 | # final result hashes | ||||
161 | 190 | 1.34ms | 190 | 4.75ms | $self->put_results(inside => $self->{inside}); # spent 4.75ms making 190 calls to Mail::SpamAssassin::HTML::put_results, avg 25µs/call |
162 | |||||
163 | # end-of-document result values that don't require looking at the text | ||||
164 | 190 | 525µs | if (exists $self->{backhair}) { | ||
165 | 22 | 132µs | 11 | 300µs | $self->put_results(backhair_count => scalar keys %{ $self->{backhair} }); # spent 300µs making 11 calls to Mail::SpamAssassin::HTML::put_results, avg 27µs/call |
166 | } | ||||
167 | 190 | 919µs | if (exists $self->{elements} && exists $self->{tags}) { | ||
168 | $self->put_results(bad_tag_ratio => | ||||
169 | 188 | 1.75ms | 188 | 5.21ms | ($self->{tags} - $self->{elements}) / $self->{tags}); # spent 5.21ms making 188 calls to Mail::SpamAssassin::HTML::put_results, avg 28µs/call |
170 | } | ||||
171 | 190 | 1.08ms | if (exists $self->{elements_seen} && exists $self->{tags_seen}) { | ||
172 | $self->put_results(non_element_ratio => | ||||
173 | ($self->{tags_seen} - $self->{elements_seen}) / | ||||
174 | 188 | 1.65ms | 188 | 5.15ms | $self->{tags_seen}); # spent 5.15ms making 188 calls to Mail::SpamAssassin::HTML::put_results, avg 27µs/call |
175 | } | ||||
176 | 190 | 1.77ms | if (exists $self->{tags} && exists $self->{obfuscation}) { | ||
177 | $self->put_results(obfuscation_ratio => | ||||
178 | 19 | 154µs | 19 | 500µs | $self->{obfuscation} / $self->{tags}); # spent 500µs making 19 calls to Mail::SpamAssassin::HTML::put_results, avg 26µs/call |
179 | } | ||||
180 | } | ||||
181 | |||||
182 | # spent 77.8ms within Mail::SpamAssassin::HTML::put_results which was called 3113 times, avg 25µs/call:
# 190 times (5.06ms+0s) by Mail::SpamAssassin::HTML::html_end at line 157, avg 27µs/call
# 190 times (5.00ms+0s) by Mail::SpamAssassin::HTML::html_end at line 143, avg 26µs/call
# 190 times (4.94ms+0s) by Mail::SpamAssassin::HTML::html_end at line 142, avg 26µs/call
# 190 times (4.91ms+0s) by Mail::SpamAssassin::HTML::html_end at line 156, avg 26µs/call
# 190 times (4.88ms+0s) by Mail::SpamAssassin::HTML::html_end at line 148, avg 26µs/call
# 190 times (4.87ms+0s) by Mail::SpamAssassin::HTML::html_end at line 140, avg 26µs/call
# 190 times (4.75ms+0s) by Mail::SpamAssassin::HTML::html_end at line 161, avg 25µs/call
# 190 times (4.75ms+0s) by Mail::SpamAssassin::HTML::html_end at line 158, avg 25µs/call
# 190 times (4.70ms+0s) by Mail::SpamAssassin::HTML::html_start at line 115, avg 25µs/call
# 190 times (4.70ms+0s) by Mail::SpamAssassin::HTML::html_end at line 139, avg 25µs/call
# 190 times (4.34ms+0s) by Mail::SpamAssassin::HTML::html_end at line 146, avg 23µs/call
# 190 times (3.90ms+0s) by Mail::SpamAssassin::HTML::html_end at line 147, avg 21µs/call
# 190 times (3.80ms+0s) by Mail::SpamAssassin::HTML::html_end at line 149, avg 20µs/call
# 188 times (5.21ms+0s) by Mail::SpamAssassin::HTML::html_end at line 169, avg 28µs/call
# 188 times (5.15ms+0s) by Mail::SpamAssassin::HTML::html_end at line 174, avg 27µs/call
# 188 times (4.93ms+0s) by Mail::SpamAssassin::HTML::html_end at line 152, avg 26µs/call
# 48 times (1.10ms+0s) by Mail::SpamAssassin::HTML::html_font_invisible at line 555, avg 23µs/call
# 19 times (500µs+0s) by Mail::SpamAssassin::HTML::html_end at line 178, avg 26µs/call
# 11 times (300µs+0s) by Mail::SpamAssassin::HTML::html_end at line 165, avg 27µs/call
# once (33µs+0s) by Mail::SpamAssassin::HTML::html_font_invisible at line 586 | ||||
183 | 3113 | 5.36ms | my $self = shift; | ||
184 | 3113 | 24.8ms | my %results = @_; | ||
185 | |||||
186 | 3113 | 65.5ms | while (my ($k, $v) = each %results) { | ||
187 | 3113 | 11.5ms | $self->{results}{$k} = $v; | ||
188 | } | ||||
189 | } | ||||
190 | |||||
191 | # spent 1.58ms within Mail::SpamAssassin::HTML::get_results which was called 190 times, avg 8µs/call:
# 190 times (1.58ms+0s) by Mail::SpamAssassin::Message::Node::rendered at line 643 of Mail/SpamAssassin/Message/Node.pm, avg 8µs/call | ||||
192 | 190 | 435µs | my ($self) = @_; | ||
193 | |||||
194 | 190 | 1.44ms | return $self->{results}; | ||
195 | } | ||||
196 | |||||
197 | # spent 374ms within Mail::SpamAssassin::HTML::get_rendered_text which was called 570 times, avg 656µs/call:
# 190 times (193ms+0s) by Mail::SpamAssassin::Message::Node::rendered at line 641 of Mail/SpamAssassin/Message/Node.pm, avg 1.01ms/call
# 190 times (171ms+0s) by Mail::SpamAssassin::Message::Node::rendered at line 642 of Mail/SpamAssassin/Message/Node.pm, avg 902µs/call
# 190 times (9.80ms+0s) by Mail::SpamAssassin::Message::Node::rendered at line 640 of Mail/SpamAssassin/Message/Node.pm, avg 52µs/call | ||||
198 | 570 | 1.04ms | my $self = shift; | ||
199 | 570 | 2.43ms | my %options = @_; | ||
200 | |||||
201 | 760 | 22.1ms | return join('', @{ $self->{text} }) unless %options; | ||
202 | |||||
203 | 380 | 690µs | my $mask; | ||
204 | 380 | 4.22ms | while (my ($k, $v) = each %options) { | ||
205 | 380 | 1.16ms | next if !defined $self->{"text_$k"}; | ||
206 | 380 | 1.37ms | if (!defined $mask) { | ||
207 | 380 | 3.72ms | $mask |= $v ? $self->{"text_$k"} : ~ $self->{"text_$k"}; | ||
208 | } | ||||
209 | else { | ||||
210 | $mask &= $v ? $self->{"text_$k"} : ~ $self->{"text_$k"}; | ||||
211 | } | ||||
212 | } | ||||
213 | |||||
214 | 380 | 881µs | my $text = ''; | ||
215 | 380 | 710µs | my $i = 0; | ||
216 | 93868 | 345ms | for (@{ $self->{text} }) { $text .= $_ if vec($mask, $i++, 1); } | ||
217 | 380 | 4.84ms | return $text; | ||
218 | } | ||||
219 | |||||
220 | # spent 20.4s (46.0ms+20.4) within Mail::SpamAssassin::HTML::parse which was called 190 times, avg 107ms/call:
# 190 times (46.0ms+20.4s) by Mail::SpamAssassin::Message::Node::rendered at line 637 of Mail/SpamAssassin/Message/Node.pm, avg 107ms/call | ||||
221 | 190 | 1.01ms | my ($self, $text) = @_; | ||
222 | |||||
223 | 190 | 626µs | $self->{image_area} = 0; | ||
224 | 190 | 541µs | $self->{title_index} = -1; | ||
225 | 190 | 589µs | $self->{max_size} = 3; # start at default size | ||
226 | 190 | 548µs | $self->{min_size} = 3; # start at default size | ||
227 | 190 | 701µs | $self->{closed_html} = 0; | ||
228 | 190 | 536µs | $self->{closed_body} = 0; | ||
229 | 190 | 536µs | $self->{closed_extra} = 0; | ||
230 | 190 | 594µs | $self->{text} = []; # rendered text | ||
231 | 190 | 3.27ms | 190 | 6.73ms | $self->{length} += untaint_var(length($text)); # spent 6.73ms making 190 calls to Mail::SpamAssassin::Util::untaint_var, avg 35µs/call |
232 | |||||
233 | # NOTE: We *only* need to fix the rendering when we verify that it | ||||
234 | # differs from what people see in their MUA. Testing is best done with | ||||
235 | # the most common MUAs and browsers, if you catch my drift. | ||||
236 | |||||
237 | # NOTE: HTML::Parser can cope with: <?xml pis>, <? with space>, so we | ||||
238 | # don't need to fix them here. | ||||
239 | |||||
240 | # # (outdated claim) HTML::Parser converts into a question mark ("?") | ||||
241 | # # for some reason, so convert them to spaces. Confirmed in 3.31, at least. | ||||
242 | # ... Actually it doesn't, it is correctly coverted into Unicode NBSP, | ||||
243 | # nevertheless it does not hurt to treat it as a space. | ||||
244 | 190 | 17.1ms | 190 | 15.2ms | $text =~ s/ / /g; # spent 15.2ms making 190 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 80µs/call |
245 | |||||
246 | # bug 4695: we want "<br/>" to be treated the same as "<br>", and | ||||
247 | # the HTML::Parser API won't do it for us | ||||
248 | 190 | 57.7ms | 1594 | 37.8ms | $text =~ s/<(\w+)\s*\/>/<$1>/gi; # spent 28.6ms making 1404 calls to Mail::SpamAssassin::HTML::CORE:substcont, avg 20µs/call
# spent 9.19ms making 190 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 48µs/call |
249 | |||||
250 | 190 | 4.17ms | 190 | 971µs | if (!$self->UNIVERSAL::can('utf8_mode')) { # spent 971µs making 190 calls to UNIVERSAL::can, avg 5µs/call |
251 | # utf8_mode is cleared by default, only warn if it would need to be set | ||||
252 | warn "message: cannot set utf8_mode, module HTML::Parser is too old\n" | ||||
253 | if !$self->{SA_character_semantics_input}; | ||||
254 | } else { | ||||
255 | 190 | 2.68ms | 190 | 803µs | $self->SUPER::utf8_mode($self->{SA_character_semantics_input} ? 0 : 1); # spent 803µs making 190 calls to HTML::Parser::utf8_mode, avg 4µs/call |
256 | 190 | 3.53ms | 380 | 1.83ms | dbg("message: HTML::Parser utf8_mode %s", # spent 1.31ms making 190 calls to Mail::SpamAssassin::Logger::dbg, avg 7µs/call
# spent 528µs making 190 calls to HTML::Parser::utf8_mode, avg 3µs/call |
257 | $self->SUPER::utf8_mode ? "on (assumed UTF-8 octets)" | ||||
258 | : "off (default, assumed Unicode characters)"); | ||||
259 | } | ||||
260 | 190 | 1.08s | 77471 | 38.6s | $self->SUPER::parse($text); # spent 20.1s making 190 calls to HTML::Parser::parse, avg 106ms/call
# spent 12.9s making 47000 calls to Mail::SpamAssassin::HTML::html_tag, avg 274µs/call
# spent 5.60s making 29611 calls to Mail::SpamAssassin::HTML::html_text, avg 189µs/call
# spent 12.2ms making 190 calls to Mail::SpamAssassin::HTML::html_start, avg 64µs/call
# spent 5.94ms making 413 calls to Mail::SpamAssassin::HTML::html_comment, avg 14µs/call
# spent 2.95ms making 67 calls to Mail::SpamAssassin::HTML::html_declaration, avg 44µs/call |
261 | 190 | 6.10ms | 527 | 319ms | $self->SUPER::eof; # spent 162ms making 190 calls to HTML::Parser::eof, avg 854µs/call
# spent 134ms making 190 calls to Mail::SpamAssassin::HTML::html_end, avg 707µs/call
# spent 22.6ms making 147 calls to Mail::SpamAssassin::HTML::html_text, avg 153µs/call |
262 | |||||
263 | 190 | 1.78ms | return $self->{text}; | ||
264 | } | ||||
265 | |||||
266 | # spent 12.9s (3.32+9.55) within Mail::SpamAssassin::HTML::html_tag which was called 47000 times, avg 274µs/call:
# 47000 times (3.32s+9.55s) by HTML::Parser::parse at line 260, avg 274µs/call | ||||
267 | 47000 | 101ms | my ($self, $tag, $attr, $num) = @_; | ||
268 | 47000 | 89.9ms | utf8::encode($tag) if $self->{SA_encode_results}; | ||
269 | |||||
270 | 47000 | 564ms | 47000 | 96.7ms | my $maybe_namespace = ($tag =~ m@^(?:o|st\d):[\w-]+/?$@); # spent 96.7ms making 47000 calls to Mail::SpamAssassin::HTML::CORE:match, avg 2µs/call |
271 | |||||
272 | 47000 | 176ms | if (exists $elements{$tag} || $maybe_namespace) { | ||
273 | 46985 | 82.1ms | $self->{elements}++; | ||
274 | 46985 | 94.5ms | $self->{elements_seen}++ if !exists $self->{inside}{$tag}; | ||
275 | } | ||||
276 | 47000 | 79.0ms | $self->{tags}++; | ||
277 | 47000 | 86.0ms | $self->{tags_seen}++ if !exists $self->{inside}{$tag}; | ||
278 | 47000 | 130ms | $self->{inside}{$tag} += $num; | ||
279 | 47000 | 90.1ms | if ($self->{inside}{$tag} < 0) { | ||
280 | 34 | 83µs | $self->{inside}{$tag} = 0; | ||
281 | 34 | 69µs | $self->{closed_extra}++; | ||
282 | } | ||||
283 | |||||
284 | 47000 | 95.8ms | return if $maybe_namespace; | ||
285 | |||||
286 | # ignore non-elements | ||||
287 | 45558 | 635ms | if (exists $elements{$tag} || exists $tricks{$tag}) { | ||
288 | 45543 | 306ms | 32968 | 5.03s | $self->text_style($tag, $attr, $num) if exists $elements_text_style{$tag}; # spent 5.03s making 32968 calls to Mail::SpamAssassin::HTML::text_style, avg 153µs/call |
289 | |||||
290 | # bug 5009: things like <p> and </p> both need dealing with | ||||
291 | 45543 | 168ms | 16898 | 2.11s | $self->html_whitespace($tag) if exists $elements_whitespace{$tag}; # spent 2.11s making 16898 calls to Mail::SpamAssassin::HTML::html_whitespace, avg 125µs/call |
292 | |||||
293 | # start tags | ||||
294 | 45543 | 160ms | if ($num == 1) { | ||
295 | 24617 | 109ms | 12674 | 1.63s | $self->html_uri($tag, $attr) if exists $elements_uri{$tag}; # spent 1.63s making 12674 calls to Mail::SpamAssassin::HTML::html_uri, avg 129µs/call |
296 | 24617 | 158ms | 24617 | 683ms | $self->html_tests($tag, $attr, $num); # spent 683ms making 24617 calls to Mail::SpamAssassin::HTML::html_tests, avg 28µs/call |
297 | } | ||||
298 | # end tags | ||||
299 | else { | ||||
300 | 20926 | 37.1ms | $self->{closed_html} = 1 if $tag eq "html"; | ||
301 | 20926 | 35.7ms | $self->{closed_body} = 1 if $tag eq "body"; | ||
302 | } | ||||
303 | } | ||||
304 | } | ||||
305 | |||||
306 | # spent 2.11s (537ms+1.58) within Mail::SpamAssassin::HTML::html_whitespace which was called 16898 times, avg 125µs/call:
# 16898 times (537ms+1.58s) by Mail::SpamAssassin::HTML::html_tag at line 291, avg 125µs/call | ||||
307 | 16898 | 37.4ms | my ($self, $tag) = @_; | ||
308 | |||||
309 | # ordered by frequency of tag groups, note: whitespace is always "visible" | ||||
310 | 16898 | 470ms | 16959 | 60.8ms | if ($tag eq "br" || $tag eq "div") { # spent 60.8ms making 16959 calls to Mail::SpamAssassin::HTML::CORE:match, avg 4µs/call |
311 | 3961 | 25.2ms | 3961 | 361ms | $self->display_text("\n", whitespace => 1); # spent 361ms making 3961 calls to Mail::SpamAssassin::HTML::display_text, avg 91µs/call |
312 | } | ||||
313 | elsif ($tag =~ /^(?:li|t[hd]|d[td]|embed|h\d)$/) { | ||||
314 | 8915 | 55.5ms | 8915 | 777ms | $self->display_text(" ", whitespace => 1); # spent 777ms making 8915 calls to Mail::SpamAssassin::HTML::display_text, avg 87µs/call |
315 | } | ||||
316 | elsif ($tag =~ /^(?:p|hr|blockquote|pre|listing|plaintext|xmp|title)$/) { | ||||
317 | 4022 | 25.4ms | 4022 | 379ms | $self->display_text("\n\n", whitespace => 1); # spent 379ms making 4022 calls to Mail::SpamAssassin::HTML::display_text, avg 94µs/call |
318 | } | ||||
319 | } | ||||
320 | |||||
321 | # puts the uri onto the internal array | ||||
322 | # note: uri may be blank (<a href=""></a> obfuscation, etc.) | ||||
323 | # spent 1.21s (115ms+1.09) within Mail::SpamAssassin::HTML::push_uri which was called 2705 times, avg 446µs/call:
# 1560 times (65.3ms+730ms) by Mail::SpamAssassin::HTML::html_uri at line 362, avg 510µs/call
# 1132 times (49.2ms+357ms) by Mail::SpamAssassin::HTML::html_uri at line 367, avg 359µs/call
# 13 times (549µs+4.51ms) by Mail::SpamAssassin::HTML::html_uri at line 357, avg 389µs/call | ||||
324 | 2705 | 5.76ms | my ($self, $type, $uri) = @_; | ||
325 | |||||
326 | 2705 | 18.7ms | 2705 | 97.9ms | $uri = $self->canon_uri($uri); # spent 97.9ms making 2705 calls to Mail::SpamAssassin::HTML::canon_uri, avg 36µs/call |
327 | 2705 | 5.57ms | utf8::encode($uri) if $self->{SA_encode_results}; | ||
328 | |||||
329 | 2705 | 21.1ms | 2705 | 993ms | my $target = target_uri($self->{base_href} || "", $uri); # spent 993ms making 2705 calls to Mail::SpamAssassin::HTML::target_uri, avg 367µs/call |
330 | |||||
331 | # skip things like <iframe src="" ...> | ||||
332 | 2705 | 69.4ms | $self->{uri}->{$uri}->{types}->{$type} = 1 if $uri ne ''; | ||
333 | } | ||||
334 | |||||
335 | # spent 171ms (136+34.9) within Mail::SpamAssassin::HTML::canon_uri which was called 4261 times, avg 40µs/call:
# 2705 times (71.5ms+26.4ms) by Mail::SpamAssassin::HTML::push_uri at line 326, avg 36µs/call
# 1556 times (64.4ms+8.49ms) by Mail::SpamAssassin::HTML::html_tests at line 654, avg 47µs/call | ||||
336 | 4261 | 8.08ms | my ($self, $uri) = @_; | ||
337 | |||||
338 | # URIs don't have leading/trailing whitespace ... | ||||
339 | 4261 | 39.3ms | 4261 | 12.7ms | $uri =~ s/^\s+//; # spent 12.7ms making 4261 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 3µs/call |
340 | 4261 | 91.4ms | 4261 | 22.2ms | $uri =~ s/\s+$//; # spent 22.2ms making 4261 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 5µs/call |
341 | |||||
342 | # Make sure all the URIs are nice and short | ||||
343 | 4261 | 8.31ms | if (length $uri > MAX_URI_LENGTH) { | ||
344 | $self->{'uri_truncated'} = 1; | ||||
345 | $uri = substr $uri, 0, MAX_URI_LENGTH; | ||||
346 | } | ||||
347 | |||||
348 | 4261 | 58.6ms | return $uri; | ||
349 | } | ||||
350 | |||||
351 | # spent 1.63s (371ms+1.26) within Mail::SpamAssassin::HTML::html_uri which was called 12674 times, avg 129µs/call:
# 12674 times (371ms+1.26s) by Mail::SpamAssassin::HTML::html_tag at line 295, avg 129µs/call | ||||
352 | 12674 | 32.8ms | my ($self, $tag, $attr) = @_; | ||
353 | |||||
354 | # ordered by frequency of tag groups | ||||
355 | 12674 | 355ms | 16543 | 54.9ms | if ($tag =~ /^(?:body|table|tr|td)$/) { # spent 54.9ms making 16543 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
356 | 9939 | 20.3ms | if (defined $attr->{background}) { | ||
357 | 13 | 108µs | 13 | 5.06ms | $self->push_uri($tag, $attr->{background}); # spent 5.06ms making 13 calls to Mail::SpamAssassin::HTML::push_uri, avg 389µs/call |
358 | } | ||||
359 | } | ||||
360 | elsif ($tag =~ /^(?:a|area|link)$/) { | ||||
361 | 1601 | 6.42ms | if (defined $attr->{href}) { | ||
362 | 1560 | 10.7ms | 1560 | 795ms | $self->push_uri($tag, $attr->{href}); # spent 795ms making 1560 calls to Mail::SpamAssassin::HTML::push_uri, avg 510µs/call |
363 | } | ||||
364 | } | ||||
365 | elsif ($tag =~ /^(?:img|frame|iframe|embed|script|bgsound)$/) { | ||||
366 | 1134 | 4.79ms | if (defined $attr->{src}) { | ||
367 | 1132 | 7.42ms | 1132 | 406ms | $self->push_uri($tag, $attr->{src}); # spent 406ms making 1132 calls to Mail::SpamAssassin::HTML::push_uri, avg 359µs/call |
368 | } | ||||
369 | } | ||||
370 | elsif ($tag eq "form") { | ||||
371 | if (defined $attr->{action}) { | ||||
372 | $self->push_uri($tag, $attr->{action}); | ||||
373 | } | ||||
374 | } | ||||
375 | elsif ($tag eq "base") { | ||||
376 | if (my $uri = $attr->{href}) { | ||||
377 | $uri = $self->canon_uri($uri); | ||||
378 | |||||
379 | # use <BASE HREF="URI"> to turn relative links into absolute links | ||||
380 | |||||
381 | # even if it is a base URI, handle like a normal URI as well | ||||
382 | $self->push_uri($tag, $uri); | ||||
383 | |||||
384 | # a base URI will be ignored by browsers unless it is an absolute | ||||
385 | # URI of a standard protocol | ||||
386 | if ($uri =~ m@^(?:https?|ftp):/{0,2}@i) { | ||||
387 | # remove trailing filename, if any; base URIs can have the | ||||
388 | # form of "http://foo.com/index.html" | ||||
389 | $uri =~ s@^([a-z]+:/{0,2}[^/]+/.*?)[^/\.]+\.[^/\.]{2,4}$@$1@i; | ||||
390 | |||||
391 | # Make sure it ends in a slash | ||||
392 | $uri .= "/" unless $uri =~ m@/$@; | ||||
393 | utf8::encode($uri) if $self->{SA_encode_results}; | ||||
394 | $self->{base_href} = $uri; | ||||
395 | } | ||||
396 | } | ||||
397 | } | ||||
398 | } | ||||
399 | |||||
400 | # this might not be quite right, may need to pay attention to table nesting | ||||
401 | # spent 891ms (881+9.88) within Mail::SpamAssassin::HTML::close_table_tag which was called 7824 times, avg 114µs/call:
# 7824 times (881ms+9.88ms) by Mail::SpamAssassin::HTML::text_style at line 455, avg 114µs/call | ||||
402 | 7824 | 15.3ms | my ($self, $tag) = @_; | ||
403 | |||||
404 | # don't close if never opened | ||||
405 | 176215 | 738ms | return unless grep { $_->{tag} eq $tag } @{ $self->{text_style} }; | ||
406 | |||||
407 | 7281 | 11.5ms | my $top; | ||
408 | 14594 | 43.4ms | while (@{ $self->{text_style} } && ($top = $self->{text_style}[-1]->{tag})) { | ||
409 | 7313 | 51.8ms | 3213 | 9.88ms | if (($tag eq "td" && ($top eq "font" || $top eq "td")) || # spent 9.88ms making 3213 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
410 | ($tag eq "tr" && $top =~ /^(?:font|td|tr)$/)) | ||||
411 | { | ||||
412 | 64 | 174µs | pop @{ $self->{text_style} }; | ||
413 | } | ||||
414 | else { | ||||
415 | 7281 | 60.7ms | last; | ||
416 | } | ||||
417 | } | ||||
418 | } | ||||
419 | |||||
420 | # spent 1.65s within Mail::SpamAssassin::HTML::close_tag which was called 16295 times, avg 101µs/call:
# 16295 times (1.65s+0s) by Mail::SpamAssassin::HTML::text_style at line 539, avg 101µs/call | ||||
421 | 16295 | 31.2ms | my ($self, $tag) = @_; | ||
422 | |||||
423 | # don't close if never opened | ||||
424 | 298853 | 1.21s | return if !grep { $_->{tag} eq $tag } @{ $self->{text_style} }; | ||
425 | |||||
426 | # close everything up to and including tag | ||||
427 | 48867 | 285ms | while (my %current = %{ pop @{ $self->{text_style} } }) { | ||
428 | 16308 | 257ms | last if $current{tag} eq $tag; | ||
429 | } | ||||
430 | } | ||||
431 | |||||
432 | # spent 5.03s (2.05+2.98) within Mail::SpamAssassin::HTML::text_style which was called 32968 times, avg 153µs/call:
# 32968 times (2.05s+2.98s) by Mail::SpamAssassin::HTML::html_tag at line 288, avg 153µs/call | ||||
433 | 32968 | 69.7ms | my ($self, $tag, $attr, $num) = @_; | ||
434 | |||||
435 | # treat <th> as <td> | ||||
436 | 32968 | 57.4ms | $tag = "td" if $tag eq "th"; | ||
437 | |||||
438 | # open | ||||
439 | 32968 | 375ms | if ($num == 1) { | ||
440 | # HTML browsers generally only use first <body> for colors, | ||||
441 | # so only push if we haven't seen a body tag yet | ||||
442 | 16515 | 26.9ms | if ($tag eq "body") { | ||
443 | # TODO: skip if we've already seen body | ||||
444 | } | ||||
445 | |||||
446 | # change basefont (only change size) | ||||
447 | 16515 | 26.5ms | if ($tag eq "basefont" && | ||
448 | exists $attr->{size} && $attr->{size} =~ /^\s*(\d+)/) | ||||
449 | { | ||||
450 | $self->{basefont} = $1; | ||||
451 | return; | ||||
452 | } | ||||
453 | |||||
454 | # close elements with optional end tags | ||||
455 | 16515 | 64.7ms | 7824 | 891ms | $self->close_table_tag($tag) if ($tag eq "td" || $tag eq "tr"); # spent 891ms making 7824 calls to Mail::SpamAssassin::HTML::close_table_tag, avg 114µs/call |
456 | |||||
457 | # copy current text state | ||||
458 | 33030 | 269ms | my %new = %{ $self->{text_style}[-1] }; | ||
459 | |||||
460 | # change tag name! | ||||
461 | 16515 | 32.7ms | $new{tag} = $tag; | ||
462 | |||||
463 | # big and small tags | ||||
464 | 16515 | 27.5ms | if ($tag eq "big") { | ||
465 | 13 | 31µs | $new{size} += 1; | ||
466 | 26 | 89µs | push @{ $self->{text_style} }, \%new; | ||
467 | 13 | 98µs | return; | ||
468 | } | ||||
469 | 16502 | 26.9ms | if ($tag eq "small") { | ||
470 | 16 | 39µs | $new{size} -= 1; | ||
471 | 32 | 104µs | push @{ $self->{text_style} }, \%new; | ||
472 | 16 | 115µs | return; | ||
473 | } | ||||
474 | |||||
475 | # tag attributes | ||||
476 | 16486 | 121ms | for my $name (keys %$attr) { | ||
477 | 26315 | 54.7ms | next unless exists $ok_attributes{$tag}{$name}; | ||
478 | 5473 | 23.0ms | if ($name eq "text" || $name eq "color") { | ||
479 | # two different names for text color | ||||
480 | 85 | 722µs | 85 | 8.40ms | $new{fgcolor} = name_to_rgb($attr->{$name}); # spent 8.40ms making 85 calls to Mail::SpamAssassin::HTML::name_to_rgb, avg 99µs/call |
481 | } | ||||
482 | elsif ($name eq "size") { | ||||
483 | 117 | 2.43ms | 198 | 822µs | if ($attr->{size} =~ /^\s*([+-]\d+)/) { # spent 822µs making 198 calls to Mail::SpamAssassin::HTML::CORE:match, avg 4µs/call |
484 | # relative font size | ||||
485 | 36 | 161µs | $new{size} = $self->{basefont} + $1; | ||
486 | } | ||||
487 | elsif ($attr->{size} =~ /^\s*(\d+)/) { | ||||
488 | # absolute font size | ||||
489 | 77 | 292µs | $new{size} = $1; | ||
490 | } | ||||
491 | } | ||||
492 | elsif ($name eq 'style') { | ||||
493 | 4451 | 9.96ms | $new{style} = $attr->{style}; | ||
494 | 4451 | 24.1ms | my @parts = split(/;/, $new{style}); | ||
495 | 4451 | 22.6ms | foreach (@parts) { | ||
496 | 15350 | 517ms | 28464 | 173ms | if (/^\s*(background-)?color:\s*(.+)\s*$/i) { # spent 173ms making 28464 calls to Mail::SpamAssassin::HTML::CORE:match, avg 6µs/call |
497 | 2236 | 5.88ms | my $whcolor = $1 ? 'bgcolor' : 'fgcolor'; | ||
498 | 2236 | 6.50ms | my $value = lc $2; | ||
499 | |||||
500 | 2236 | 25.8ms | 2236 | 6.18ms | if ($value =~ /rgb/) { # spent 6.18ms making 2236 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
501 | 611 | 1.91ms | $value =~ tr/0-9,//cd; | ||
502 | 611 | 2.59ms | my @rgb = split(/,/, $value); | ||
503 | $new{$whcolor} = sprintf("#%02x%02x%02x", | ||||
504 | 2444 | 15.0ms | map { !$_ ? 0 : $_ > 255 ? 255 : $_ } | ||
505 | @rgb[0..2]); | ||||
506 | } | ||||
507 | else { | ||||
508 | 1625 | 13.2ms | 1625 | 181ms | $new{$whcolor} = name_to_rgb($value); # spent 181ms making 1625 calls to Mail::SpamAssassin::HTML::name_to_rgb, avg 111µs/call |
509 | } | ||||
510 | } | ||||
511 | elsif (/^\s*([a-z_-]+)\s*:\s*(\S.*?)\s*$/i) { | ||||
512 | # "display: none", "visibility: hidden", etc. | ||||
513 | 12719 | 84.6ms | $new{'style_'.$1} = $2; | ||
514 | } | ||||
515 | } | ||||
516 | } | ||||
517 | elsif ($name eq "bgcolor") { | ||||
518 | # overwrite with hex value, $new{bgcolor} is set below | ||||
519 | 630 | 5.69ms | 630 | 71.2ms | $attr->{bgcolor} = name_to_rgb($attr->{bgcolor}); # spent 71.2ms making 630 calls to Mail::SpamAssassin::HTML::name_to_rgb, avg 113µs/call |
520 | } | ||||
521 | else { | ||||
522 | # attribute is probably okay | ||||
523 | 190 | 496µs | $new{$name} = $attr->{$name}; | ||
524 | } | ||||
525 | |||||
526 | 5473 | 26.2ms | if ($new{size} > $self->{max_size}) { | ||
527 | 2 | 6µs | $self->{max_size} = $new{size}; | ||
528 | } | ||||
529 | elsif ($new{size} < $self->{min_size}) { | ||||
530 | 33 | 94µs | $self->{min_size} = $new{size}; | ||
531 | } | ||||
532 | } | ||||
533 | 32972 | 114ms | push @{ $self->{text_style} }, \%new; | ||
534 | } | ||||
535 | # explicitly close a tag | ||||
536 | else { | ||||
537 | 16453 | 55.6ms | if ($tag ne "body") { | ||
538 | # don't close body since browsers seem to render text after </body> | ||||
539 | 16295 | 98.8ms | 16295 | 1.65s | $self->close_tag($tag); # spent 1.65s making 16295 calls to Mail::SpamAssassin::HTML::close_tag, avg 101µs/call |
540 | } | ||||
541 | } | ||||
542 | } | ||||
543 | |||||
544 | # spent 369ms (326+43.1) within Mail::SpamAssassin::HTML::html_font_invisible which was called 4797 times, avg 77µs/call:
# 4797 times (326ms+43.1ms) by Mail::SpamAssassin::HTML::html_text at line 746, avg 77µs/call | ||||
545 | 4797 | 10.3ms | my ($self, $text) = @_; | ||
546 | |||||
547 | 4797 | 12.4ms | my $fg = $self->{text_style}[-1]->{fgcolor}; | ||
548 | 4797 | 10.3ms | my $bg = $self->{text_style}[-1]->{bgcolor}; | ||
549 | 4797 | 9.69ms | my $size = $self->{text_style}[-1]->{size}; | ||
550 | 4797 | 9.58ms | my $display = $self->{text_style}[-1]->{style_display}; | ||
551 | 4797 | 9.67ms | my $visibility = $self->{text_style}[-1]->{style_visibility}; | ||
552 | |||||
553 | # invisibility | ||||
554 | 4797 | 91.8ms | 4749 | 25.2ms | if (substr($fg,-6) eq substr($bg,-6)) { # spent 25.2ms making 4749 calls to Mail::SpamAssassin::HTML::CORE:match, avg 5µs/call |
555 | 48 | 310µs | 48 | 1.10ms | $self->put_results(font_low_contrast => 1); # spent 1.10ms making 48 calls to Mail::SpamAssassin::HTML::put_results, avg 23µs/call |
556 | 48 | 379µs | return 1; | ||
557 | # near-invisibility | ||||
558 | } elsif ($fg =~ /^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/) { | ||||
559 | 4748 | 18.7ms | my ($r1, $g1, $b1) = (hex($1), hex($2), hex($3)); | ||
560 | |||||
561 | 4748 | 58.2ms | 4748 | 16.7ms | if ($bg =~ /^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/) { # spent 16.7ms making 4748 calls to Mail::SpamAssassin::HTML::CORE:match, avg 4µs/call |
562 | 4748 | 14.4ms | my ($r2, $g2, $b2) = (hex($1), hex($2), hex($3)); | ||
563 | |||||
564 | 4748 | 9.60ms | my $r = ($r1 - $r2); | ||
565 | 4748 | 8.22ms | my $g = ($g1 - $g2); | ||
566 | 4748 | 8.09ms | my $b = ($b1 - $b2); | ||
567 | |||||
568 | # geometric distance weighted by brightness | ||||
569 | # maximum distance is 191.151823601032 | ||||
570 | 4748 | 19.9ms | my $distance = ((0.2126*$r)**2 + (0.7152*$g)**2 + (0.0722*$b)**2)**0.5; | ||
571 | |||||
572 | # the text is very difficult to read if the distance is under 12, | ||||
573 | # a limit of 14 to 16 might be okay if the usage significantly | ||||
574 | # increases (near-invisible text is at about 0.95% of spam and | ||||
575 | # 1.25% of HTML spam right now), but please test any changes first | ||||
576 | 4748 | 17.2ms | if ($distance < 12) { | ||
577 | $self->put_results(font_low_contrast => 1); | ||||
578 | return 1; | ||||
579 | } | ||||
580 | } | ||||
581 | } | ||||
582 | |||||
583 | |||||
584 | # invalid color | ||||
585 | 4749 | 9.45ms | if ($fg eq 'invalid' or $bg eq 'invalid') { | ||
586 | 1 | 8µs | 1 | 33µs | $self->put_results(font_invalid_color => 1); # spent 33µs making 1 call to Mail::SpamAssassin::HTML::put_results |
587 | 1 | 7µs | return 1; | ||
588 | } | ||||
589 | |||||
590 | # size too small | ||||
591 | 4748 | 8.40ms | if ($size <= 1) { | ||
592 | 40 | 309µs | return 1; | ||
593 | } | ||||
594 | |||||
595 | # <span style="display: none"> | ||||
596 | 4708 | 7.93ms | if ($display && lc $display eq 'none') { | ||
597 | 4 | 32µs | return 1; | ||
598 | } | ||||
599 | |||||
600 | 4704 | 8.03ms | if ($visibility && lc $visibility eq 'hidden') { | ||
601 | 8 | 64µs | return 1; | ||
602 | } | ||||
603 | |||||
604 | 4696 | 87.6ms | return 0; | ||
605 | } | ||||
606 | |||||
607 | # spent 683ms (599+84.1) within Mail::SpamAssassin::HTML::html_tests which was called 24617 times, avg 28µs/call:
# 24617 times (599ms+84.1ms) by Mail::SpamAssassin::HTML::html_tag at line 296, avg 28µs/call | ||||
608 | 24617 | 53.0ms | my ($self, $tag, $attr, $num) = @_; | ||
609 | |||||
610 | 24617 | 43.3ms | if ($tag eq "font" && exists $attr->{face}) { | ||
611 | 175 | 3.09ms | 175 | 1.82ms | if ($attr->{face} !~ /^[a-z ][a-z -]*[a-z](?:,\s*[a-z][a-z -]*[a-z])*$/i) { # spent 1.82ms making 175 calls to Mail::SpamAssassin::HTML::CORE:match, avg 10µs/call |
612 | $self->put_results(font_face_bad => 1); | ||||
613 | } | ||||
614 | } | ||||
615 | 24617 | 45.0ms | if ($tag eq "img" && exists $self->{inside}{a} && $self->{inside}{a} > 0) { | ||
616 | 504 | 1.34ms | my $uri = $self->{anchor_last}; | ||
617 | 504 | 1.08ms | utf8::encode($uri) if $self->{SA_encode_results}; | ||
618 | 504 | 1.91ms | $self->{uri}->{$uri}->{anchor_text}->[-1] .= "<img>\n"; | ||
619 | 504 | 1.41ms | $self->{anchor}->[-1] .= "<img>\n"; | ||
620 | } | ||||
621 | |||||
622 | 24617 | 42.4ms | if ($tag eq "img" && exists $attr->{width} && exists $attr->{height}) { | ||
623 | 776 | 1.54ms | my $width = 0; | ||
624 | 776 | 1.44ms | my $height = 0; | ||
625 | 776 | 1.54ms | my $area = 0; | ||
626 | |||||
627 | # assume 800x600 screen for percentage values | ||||
628 | 776 | 11.2ms | 776 | 4.38ms | if ($attr->{width} =~ /^(\d+)(\%)?$/) { # spent 4.38ms making 776 calls to Mail::SpamAssassin::HTML::CORE:match, avg 6µs/call |
629 | 776 | 1.93ms | $width = $1; | ||
630 | 776 | 1.85ms | $width *= 8 if (defined $2 && $2 eq "%"); | ||
631 | } | ||||
632 | 776 | 19.5ms | 776 | 3.21ms | if ($attr->{height} =~ /^(\d+)(\%)?$/) { # spent 3.21ms making 776 calls to Mail::SpamAssassin::HTML::CORE:match, avg 4µs/call |
633 | 775 | 1.82ms | $height = $1; | ||
634 | 775 | 1.63ms | $height *= 6 if (defined $2 && $2 eq "%"); | ||
635 | } | ||||
636 | # guess size | ||||
637 | 776 | 1.98ms | $width = 200 if $width <= 0; | ||
638 | 776 | 1.52ms | $height = 200 if $height <= 0; | ||
639 | 776 | 3.66ms | if ($width > 0 && $height > 0) { | ||
640 | 776 | 1.36ms | $area = $width * $height; | ||
641 | 776 | 2.07ms | $self->{image_area} += $area; | ||
642 | } | ||||
643 | } | ||||
644 | 24617 | 39.3ms | if ($tag eq "form" && exists $attr->{action}) { | ||
645 | $self->put_results(form_action_mailto => 1) if $attr->{action} =~ /mailto:/i | ||||
646 | } | ||||
647 | 24617 | 45.8ms | if ($tag eq "object" || $tag eq "embed") { | ||
648 | $self->put_results(embeds => 1); | ||||
649 | } | ||||
650 | |||||
651 | # special text delimiters - <a> and <title> | ||||
652 | 24617 | 44.6ms | if ($tag eq "a") { | ||
653 | my $uri = $self->{anchor_last} = | ||||
654 | 1597 | 13.2ms | 1556 | 72.9ms | (exists $attr->{href} ? $self->canon_uri($attr->{href}) : ""); # spent 72.9ms making 1556 calls to Mail::SpamAssassin::HTML::canon_uri, avg 47µs/call |
655 | 1597 | 2.92ms | utf8::encode($uri) if $self->{SA_encode_results}; | ||
656 | 3194 | 16.8ms | push(@{$self->{uri}->{$uri}->{anchor_text}}, ''); | ||
657 | 3194 | 11.0ms | push(@{$self->{anchor}}, ''); | ||
658 | } | ||||
659 | 24617 | 40.8ms | if ($tag eq "title") { | ||
660 | 67 | 173µs | $self->{title_index}++; | ||
661 | 67 | 330µs | $self->{title}->[$self->{title_index}] = ""; | ||
662 | } | ||||
663 | |||||
664 | 24617 | 308ms | 274 | 1.80ms | if ($tag eq "meta" && # spent 1.80ms making 274 calls to Mail::SpamAssassin::HTML::CORE:match, avg 7µs/call |
665 | exists $attr->{'http-equiv'} && | ||||
666 | exists $attr->{content} && | ||||
667 | $attr->{'http-equiv'} =~ /Content-Type/i && | ||||
668 | $attr->{content} =~ /\bcharset\s*=\s*["']?([^"']+)/i) | ||||
669 | { | ||||
670 | 124 | 788µs | $self->{charsets} .= exists $self->{charsets} ? " $1" : $1; | ||
671 | } | ||||
672 | } | ||||
673 | |||||
674 | # spent 4.08s (3.71+366ms) within Mail::SpamAssassin::HTML::display_text which was called 46554 times, avg 88µs/call:
# 29555 times (2.23s+298ms) by Mail::SpamAssassin::HTML::html_text at line 773, avg 86µs/call
# 8915 times (743ms+34.3ms) by Mail::SpamAssassin::HTML::html_whitespace at line 314, avg 87µs/call
# 4022 times (369ms+9.45ms) by Mail::SpamAssassin::HTML::html_whitespace at line 317, avg 94µs/call
# 3961 times (352ms+8.82ms) by Mail::SpamAssassin::HTML::html_whitespace at line 311, avg 91µs/call
# 101 times (19.8ms+15.6ms) by Mail::SpamAssassin::HTML::html_text at line 770, avg 351µs/call | ||||
675 | 46554 | 83.8ms | my $self = shift; | ||
676 | 46554 | 89.4ms | my $text = shift; | ||
677 | 46554 | 111ms | my %display = @_; | ||
678 | |||||
679 | # Unless it's specified to be invisible, then it's not invisible. ;) | ||||
680 | 46554 | 159ms | if (!exists $display{invisible}) { | ||
681 | 46453 | 95.1ms | $display{invisible} = 0; | ||
682 | } | ||||
683 | |||||
684 | 46554 | 175ms | if ($display{whitespace}) { | ||
685 | # trim trailing whitespace from previous element if it was not whitespace | ||||
686 | # and it was not invisible | ||||
687 | 33796 | 195ms | if (@{ $self->{text} } && | ||
688 | (!defined $self->{text_whitespace} || | ||||
689 | 16710 | 31.8ms | !vec($self->{text_whitespace}, $#{$self->{text}}, 1)) && | ||
690 | (!defined $self->{text_invisible} || | ||||
691 | 14301 | 26.6ms | !vec($self->{text_invisible}, $#{$self->{text}}, 1))) | ||
692 | { | ||||
693 | 14238 | 177ms | 14238 | 52.6ms | $self->{text}->[-1] =~ s/ $//; # spent 52.6ms making 14238 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 4µs/call |
694 | } | ||||
695 | } | ||||
696 | else { | ||||
697 | # NBSP: UTF-8: C2 A0, ISO-8859-*: A0 | ||||
698 | 29656 | 546ms | 29656 | 254ms | $text =~ s/[ \t\n\r\f\x0b]+|\xc2\xa0/ /gs; # spent 254ms making 29656 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 9µs/call |
699 | # trim leading whitespace if previous element was whitespace | ||||
700 | # and current element is not invisible | ||||
701 | 59312 | 312ms | if (@{ $self->{text} } && !$display{invisible} && | ||
702 | defined $self->{text_whitespace} && | ||||
703 | 28800 | 52.5ms | vec($self->{text_whitespace}, $#{$self->{text}}, 1)) | ||
704 | { | ||||
705 | 14251 | 214ms | 14251 | 59.9ms | $text =~ s/^ //; # spent 59.9ms making 14251 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 4µs/call |
706 | } | ||||
707 | } | ||||
708 | 93108 | 357ms | push @{ $self->{text} }, $text; | ||
709 | 46554 | 1.10s | while (my ($k, $v) = each %display) { | ||
710 | 63452 | 126ms | my $textvar = "text_".$k; | ||
711 | 63830 | 125ms | if (!exists $self->{$textvar}) { $self->{$textvar} = ''; } | ||
712 | 126904 | 472ms | vec($self->{$textvar}, $#{$self->{text}}, 1) = $v; | ||
713 | } | ||||
714 | } | ||||
715 | |||||
716 | sub html_text { | ||||
717 | 29758 | 62.5ms | my ($self, $text) = @_; | ||
718 | 29758 | 57.7ms | utf8::encode($text) if $self->{SA_encode_results}; | ||
719 | |||||
720 | # text that is not part of body | ||||
721 | 29758 | 55.4ms | if (exists $self->{inside}{script} && $self->{inside}{script} > 0) | ||
722 | { | ||||
723 | 2 | 8µs | push @{ $self->{script} }, $text; | ||
724 | 1 | 7µs | return; | ||
725 | } | ||||
726 | 29757 | 57.1ms | if (exists $self->{inside}{style} && $self->{inside}{style} > 0) { | ||
727 | 101 | 731µs | return; | ||
728 | } | ||||
729 | |||||
730 | # text that is part of body and also stored separately | ||||
731 | 29656 | 63.3ms | if (exists $self->{inside}{a} && $self->{inside}{a} > 0) { | ||
732 | # this doesn't worry about nested anchors | ||||
733 | 1631 | 3.60ms | my $uri = $self->{anchor_last}; | ||
734 | 1631 | 3.08ms | utf8::encode($uri) if $self->{SA_encode_results}; | ||
735 | 1631 | 6.60ms | $self->{uri}->{$uri}->{anchor_text}->[-1] .= $text; | ||
736 | 1631 | 5.77ms | $self->{anchor}->[-1] .= $text; | ||
737 | } | ||||
738 | 29656 | 55.5ms | if (exists $self->{inside}{title} && $self->{inside}{title} > 0) { | ||
739 | 27 | 123µs | $self->{title}->[$self->{title_index}] .= $text; | ||
740 | } | ||||
741 | |||||
742 | 29656 | 51.2ms | my $invisible_for_bayes = 0; | ||
743 | |||||
744 | # NBSP: UTF-8: C2 A0, ISO-8859-*: A0 | ||||
745 | 29656 | 582ms | 29656 | 293ms | if ($text !~ /^(?:[ \t\n\r\f\x0b]|\xc2\xa0)*\z/s) { # spent 293ms making 29656 calls to Mail::SpamAssassin::HTML::CORE:match, avg 10µs/call |
746 | 4797 | 33.1ms | 4797 | 369ms | $invisible_for_bayes = $self->html_font_invisible($text); # spent 369ms making 4797 calls to Mail::SpamAssassin::HTML::html_font_invisible, avg 77µs/call |
747 | } | ||||
748 | |||||
749 | 29656 | 108ms | if (exists $self->{text}->[-1]) { | ||
750 | # ideas discarded since they would be easy to evade: | ||||
751 | # 1. using \w or [A-Za-z] instead of \S or non-punctuation | ||||
752 | # 2. exempting certain tags | ||||
753 | # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables... | ||||
754 | 29491 | 407ms | 33121 | 88.5ms | if ($text =~ /^[^\s\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]/s && # spent 88.5ms making 33121 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
755 | $self->{text}->[-1] =~ /[^\s\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]\z/s) | ||||
756 | { | ||||
757 | 38 | 99µs | $self->{obfuscation}++; | ||
758 | } | ||||
759 | 29491 | 465ms | 29491 | 198ms | if ($self->{text}->[-1] =~ # spent 198ms making 29491 calls to Mail::SpamAssassin::HTML::CORE:match, avg 7µs/call |
760 | /\b([^\s\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]{1,7})\z/s) | ||||
761 | { | ||||
762 | 392 | 1.28ms | my $start = length($1); | ||
763 | 392 | 4.41ms | 392 | 1.31ms | if ($text =~ /^([^\s\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]{1,7})\b/s) { # spent 1.31ms making 392 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
764 | 13 | 112µs | $self->{backhair}->{$start . "_" . length($1)}++; | ||
765 | } | ||||
766 | } | ||||
767 | } | ||||
768 | |||||
769 | 29656 | 407ms | if ($invisible_for_bayes) { | ||
770 | 101 | 700µs | 101 | 35.4ms | $self->display_text($text, invisible => 1); # spent 35.4ms making 101 calls to Mail::SpamAssassin::HTML::display_text, avg 351µs/call |
771 | } | ||||
772 | else { | ||||
773 | 29555 | 188ms | 29555 | 2.53s | $self->display_text($text); # spent 2.53s making 29555 calls to Mail::SpamAssassin::HTML::display_text, avg 86µs/call |
774 | } | ||||
775 | } | ||||
776 | |||||
777 | # note: $text includes <!-- and --> | ||||
778 | # spent 5.94ms within Mail::SpamAssassin::HTML::html_comment which was called 413 times, avg 14µs/call:
# 413 times (5.94ms+0s) by HTML::Parser::parse at line 260, avg 14µs/call | ||||
779 | 413 | 895µs | my ($self, $text) = @_; | ||
780 | 413 | 848µs | utf8::encode($text) if $self->{SA_encode_results}; | ||
781 | |||||
782 | 826 | 5.14ms | push @{ $self->{comment} }, $text; | ||
783 | } | ||||
784 | |||||
785 | # spent 2.95ms (2.60+346µs) within Mail::SpamAssassin::HTML::html_declaration which was called 67 times, avg 44µs/call:
# 67 times (2.60ms+346µs) by HTML::Parser::parse at line 260, avg 44µs/call | ||||
786 | 67 | 314µs | my ($self, $text) = @_; | ||
787 | 67 | 183µs | utf8::encode($text) if $self->{SA_encode_results}; | ||
788 | |||||
789 | 67 | 1.59ms | 67 | 346µs | if ($text =~ /^<!doctype/i) { # spent 346µs making 67 calls to Mail::SpamAssassin::HTML::CORE:match, avg 5µs/call |
790 | 67 | 173µs | my $tag = "!doctype"; | ||
791 | 67 | 340µs | $self->{elements}++; | ||
792 | 67 | 189µs | $self->{tags}++; | ||
793 | 67 | 317µs | $self->{inside}{$tag} = 0; | ||
794 | } | ||||
795 | } | ||||
796 | |||||
797 | ########################################################################### | ||||
798 | |||||
799 | 1 | 101µs | my %html_color = ( | ||
800 | # HTML 4 defined 16 colors | ||||
801 | aqua => 0x00ffff, | ||||
802 | black => 0x000000, | ||||
803 | blue => 0x0000ff, | ||||
804 | fuchsia => 0xff00ff, | ||||
805 | gray => 0x808080, | ||||
806 | green => 0x008000, | ||||
807 | lime => 0x00ff00, | ||||
808 | maroon => 0x800000, | ||||
809 | navy => 0x000080, | ||||
810 | olive => 0x808000, | ||||
811 | purple => 0x800080, | ||||
812 | red => 0xff0000, | ||||
813 | silver => 0xc0c0c0, | ||||
814 | teal => 0x008080, | ||||
815 | white => 0xffffff, | ||||
816 | yellow => 0xffff00, | ||||
817 | # colors specified in CSS3 color module | ||||
818 | aliceblue => 0xf0f8ff, | ||||
819 | antiquewhite => 0xfaebd7, | ||||
820 | aqua => 0x00ffff, | ||||
821 | aquamarine => 0x7fffd4, | ||||
822 | azure => 0xf0ffff, | ||||
823 | beige => 0xf5f5dc, | ||||
824 | bisque => 0xffe4c4, | ||||
825 | black => 0x000000, | ||||
826 | blanchedalmond => 0xffebcd, | ||||
827 | blue => 0x0000ff, | ||||
828 | blueviolet => 0x8a2be2, | ||||
829 | brown => 0xa52a2a, | ||||
830 | burlywood => 0xdeb887, | ||||
831 | cadetblue => 0x5f9ea0, | ||||
832 | chartreuse => 0x7fff00, | ||||
833 | chocolate => 0xd2691e, | ||||
834 | coral => 0xff7f50, | ||||
835 | cornflowerblue => 0x6495ed, | ||||
836 | cornsilk => 0xfff8dc, | ||||
837 | crimson => 0xdc143c, | ||||
838 | cyan => 0x00ffff, | ||||
839 | darkblue => 0x00008b, | ||||
840 | darkcyan => 0x008b8b, | ||||
841 | darkgoldenrod => 0xb8860b, | ||||
842 | darkgray => 0xa9a9a9, | ||||
843 | darkgreen => 0x006400, | ||||
844 | darkgrey => 0xa9a9a9, | ||||
845 | darkkhaki => 0xbdb76b, | ||||
846 | darkmagenta => 0x8b008b, | ||||
847 | darkolivegreen => 0x556b2f, | ||||
848 | darkorange => 0xff8c00, | ||||
849 | darkorchid => 0x9932cc, | ||||
850 | darkred => 0x8b0000, | ||||
851 | darksalmon => 0xe9967a, | ||||
852 | darkseagreen => 0x8fbc8f, | ||||
853 | darkslateblue => 0x483d8b, | ||||
854 | darkslategray => 0x2f4f4f, | ||||
855 | darkslategrey => 0x2f4f4f, | ||||
856 | darkturquoise => 0x00ced1, | ||||
857 | darkviolet => 0x9400d3, | ||||
858 | deeppink => 0xff1493, | ||||
859 | deepskyblue => 0x00bfff, | ||||
860 | dimgray => 0x696969, | ||||
861 | dimgrey => 0x696969, | ||||
862 | dodgerblue => 0x1e90ff, | ||||
863 | firebrick => 0xb22222, | ||||
864 | floralwhite => 0xfffaf0, | ||||
865 | forestgreen => 0x228b22, | ||||
866 | fuchsia => 0xff00ff, | ||||
867 | gainsboro => 0xdcdcdc, | ||||
868 | ghostwhite => 0xf8f8ff, | ||||
869 | gold => 0xffd700, | ||||
870 | goldenrod => 0xdaa520, | ||||
871 | gray => 0x808080, | ||||
872 | green => 0x008000, | ||||
873 | greenyellow => 0xadff2f, | ||||
874 | grey => 0x808080, | ||||
875 | honeydew => 0xf0fff0, | ||||
876 | hotpink => 0xff69b4, | ||||
877 | indianred => 0xcd5c5c, | ||||
878 | indigo => 0x4b0082, | ||||
879 | ivory => 0xfffff0, | ||||
880 | khaki => 0xf0e68c, | ||||
881 | lavender => 0xe6e6fa, | ||||
882 | lavenderblush => 0xfff0f5, | ||||
883 | lawngreen => 0x7cfc00, | ||||
884 | lemonchiffon => 0xfffacd, | ||||
885 | lightblue => 0xadd8e6, | ||||
886 | lightcoral => 0xf08080, | ||||
887 | lightcyan => 0xe0ffff, | ||||
888 | lightgoldenrodyellow => 0xfafad2, | ||||
889 | lightgray => 0xd3d3d3, | ||||
890 | lightgreen => 0x90ee90, | ||||
891 | lightgrey => 0xd3d3d3, | ||||
892 | lightpink => 0xffb6c1, | ||||
893 | lightsalmon => 0xffa07a, | ||||
894 | lightseagreen => 0x20b2aa, | ||||
895 | lightskyblue => 0x87cefa, | ||||
896 | lightslategray => 0x778899, | ||||
897 | lightslategrey => 0x778899, | ||||
898 | lightsteelblue => 0xb0c4de, | ||||
899 | lightyellow => 0xffffe0, | ||||
900 | lime => 0x00ff00, | ||||
901 | limegreen => 0x32cd32, | ||||
902 | linen => 0xfaf0e6, | ||||
903 | magenta => 0xff00ff, | ||||
904 | maroon => 0x800000, | ||||
905 | mediumaquamarine => 0x66cdaa, | ||||
906 | mediumblue => 0x0000cd, | ||||
907 | mediumorchid => 0xba55d3, | ||||
908 | mediumpurple => 0x9370db, | ||||
909 | mediumseagreen => 0x3cb371, | ||||
910 | mediumslateblue => 0x7b68ee, | ||||
911 | mediumspringgreen => 0x00fa9a, | ||||
912 | mediumturquoise => 0x48d1cc, | ||||
913 | mediumvioletred => 0xc71585, | ||||
914 | midnightblue => 0x191970, | ||||
915 | mintcream => 0xf5fffa, | ||||
916 | mistyrose => 0xffe4e1, | ||||
917 | moccasin => 0xffe4b5, | ||||
918 | navajowhite => 0xffdead, | ||||
919 | navy => 0x000080, | ||||
920 | oldlace => 0xfdf5e6, | ||||
921 | olive => 0x808000, | ||||
922 | olivedrab => 0x6b8e23, | ||||
923 | orange => 0xffa500, | ||||
924 | orangered => 0xff4500, | ||||
925 | orchid => 0xda70d6, | ||||
926 | palegoldenrod => 0xeee8aa, | ||||
927 | palegreen => 0x98fb98, | ||||
928 | paleturquoise => 0xafeeee, | ||||
929 | palevioletred => 0xdb7093, | ||||
930 | papayawhip => 0xffefd5, | ||||
931 | peachpuff => 0xffdab9, | ||||
932 | peru => 0xcd853f, | ||||
933 | pink => 0xffc0cb, | ||||
934 | plum => 0xdda0dd, | ||||
935 | powderblue => 0xb0e0e6, | ||||
936 | purple => 0x800080, | ||||
937 | red => 0xff0000, | ||||
938 | rosybrown => 0xbc8f8f, | ||||
939 | royalblue => 0x4169e1, | ||||
940 | saddlebrown => 0x8b4513, | ||||
941 | salmon => 0xfa8072, | ||||
942 | sandybrown => 0xf4a460, | ||||
943 | seagreen => 0x2e8b57, | ||||
944 | seashell => 0xfff5ee, | ||||
945 | sienna => 0xa0522d, | ||||
946 | silver => 0xc0c0c0, | ||||
947 | skyblue => 0x87ceeb, | ||||
948 | slateblue => 0x6a5acd, | ||||
949 | slategray => 0x708090, | ||||
950 | slategrey => 0x708090, | ||||
951 | snow => 0xfffafa, | ||||
952 | springgreen => 0x00ff7f, | ||||
953 | steelblue => 0x4682b4, | ||||
954 | tan => 0xd2b48c, | ||||
955 | teal => 0x008080, | ||||
956 | thistle => 0xd8bfd8, | ||||
957 | tomato => 0xff6347, | ||||
958 | turquoise => 0x40e0d0, | ||||
959 | violet => 0xee82ee, | ||||
960 | wheat => 0xf5deb3, | ||||
961 | white => 0xffffff, | ||||
962 | whitesmoke => 0xf5f5f5, | ||||
963 | yellow => 0xffff00, | ||||
964 | yellowgreen => 0x9acd32, | ||||
965 | ); | ||||
966 | |||||
967 | sub name_to_rgb_old { | ||||
968 | my $color = lc $_[0]; | ||||
969 | |||||
970 | # note: Mozilla strips leading and trailing whitespace at this point, | ||||
971 | # but IE does not | ||||
972 | |||||
973 | # named colors | ||||
974 | my $hex = $html_color{$color}; | ||||
975 | if (defined $hex) { | ||||
976 | return sprintf("#%06x", $hex); | ||||
977 | } | ||||
978 | |||||
979 | # Flex Hex: John Graham-Cumming, http://www.jgc.org/pdf/lisa2004.pdf | ||||
980 | # strip optional # character | ||||
981 | $color =~ s/^#//; | ||||
982 | # pad right-hand-side to a multiple of three | ||||
983 | $color .= "0" x (3 - (length($color) % 3)) if (length($color) % 3); | ||||
984 | # split into triplets | ||||
985 | my $length = length($color) / 3; | ||||
986 | my @colors = ($color =~ /(.{$length})(.{$length})(.{$length})/); | ||||
987 | # truncate each color to a DWORD, take MSB, left pad nibbles | ||||
988 | foreach (@colors) { s/.*(.{8})$/$1/; s/(..).*/$1/; s/^(.)$/0$1/ }; | ||||
989 | # the color | ||||
990 | $color = join("", @colors); | ||||
991 | # replace non-hex characters with 0 | ||||
992 | $color =~ tr/0-9a-f/0/c; | ||||
993 | |||||
994 | return "#" . $color; | ||||
995 | } | ||||
996 | |||||
997 | # spent 260ms (201+59.3) within Mail::SpamAssassin::HTML::name_to_rgb which was called 2340 times, avg 111µs/call:
# 1625 times (144ms+36.6ms) by Mail::SpamAssassin::HTML::text_style at line 508, avg 111µs/call
# 630 times (50.6ms+20.6ms) by Mail::SpamAssassin::HTML::text_style at line 519, avg 113µs/call
# 85 times (6.28ms+2.13ms) by Mail::SpamAssassin::HTML::text_style at line 480, avg 99µs/call | ||||
998 | 2340 | 6.36ms | my $color = lc $_[0]; | ||
999 | 2340 | 4.35ms | my $before = $color; | ||
1000 | |||||
1001 | # strip leading and ending whitespace | ||||
1002 | 2340 | 38.9ms | 2340 | 12.1ms | $color =~ s/^\s*//; # spent 12.1ms making 2340 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 5µs/call |
1003 | 2340 | 41.8ms | 2340 | 13.5ms | $color =~ s/\s*$//; # spent 13.5ms making 2340 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 6µs/call |
1004 | |||||
1005 | # named colors | ||||
1006 | 2340 | 7.43ms | my $hex = $html_color{$color}; | ||
1007 | 2340 | 4.54ms | if (defined $hex) { | ||
1008 | 311 | 14.8ms | return sprintf("#%06x", $hex); | ||
1009 | } | ||||
1010 | |||||
1011 | # IF NOT A NAME, IT SHOULD BE A HEX COLOR, HEX SHORTHAND or rgb values | ||||
1012 | 2029 | 33.0ms | 2029 | 6.51ms | if ($color =~ m/^[#a-f0-9]*$|rgb\([\d%, ]*\)/i) { # spent 6.51ms making 2029 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
1013 | |||||
1014 | #Convert the RGB values to hex values so we can fall through on the programming | ||||
1015 | |||||
1016 | #RGB PERCENTS TO HEX | ||||
1017 | 2023 | 15.5ms | 2023 | 3.47ms | if ($color =~ m/rgb\((\d+)%,\s*(\d+)%,\s*(\d+)%\s*\)/i) { # spent 3.47ms making 2023 calls to Mail::SpamAssassin::HTML::CORE:match, avg 2µs/call |
1018 | $color = "#".dec2hex(int($1/100*255)).dec2hex(int($2/100*255)).dec2hex(int($3/100*255)); | ||||
1019 | } | ||||
1020 | |||||
1021 | #RGB DEC TO HEX | ||||
1022 | 2023 | 15.1ms | 2023 | 3.28ms | if ($color =~ m/rgb\((\d+),\s*(\d+),\s*(\d+)\s*\)/i) { # spent 3.28ms making 2023 calls to Mail::SpamAssassin::HTML::CORE:match, avg 2µs/call |
1023 | $color = "#".dec2hex($1).dec2hex($2).dec2hex($3); | ||||
1024 | } | ||||
1025 | |||||
1026 | #PARSE THE HEX | ||||
1027 | 2023 | 22.7ms | 2023 | 5.88ms | if ($color =~ m/^#/) { # spent 5.88ms making 2023 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
1028 | # strip to hex only | ||||
1029 | 2023 | 27.9ms | 2023 | 14.3ms | $color =~ s/[^a-f0-9]//ig; # spent 14.3ms making 2023 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 7µs/call |
1030 | |||||
1031 | # strip to 6 if greater than 6 | ||||
1032 | 2023 | 4.57ms | if (length($color) > 6) { | ||
1033 | $color=substr($color,0,6); | ||||
1034 | } | ||||
1035 | |||||
1036 | # strip to 3 if length < 6) | ||||
1037 | 2023 | 4.82ms | if (length($color) > 3 && length($color) < 6) { | ||
1038 | $color=substr($color,0,3); | ||||
1039 | } | ||||
1040 | |||||
1041 | # pad right-hand-side to a multiple of three | ||||
1042 | 2023 | 5.20ms | $color .= "0" x (3 - (length($color) % 3)) if (length($color) % 3); | ||
1043 | |||||
1044 | #DUPLICATE SHORTHAND HEX | ||||
1045 | 2023 | 6.71ms | if (length($color) == 3) { | ||
1046 | 66 | 787µs | 66 | 293µs | $color =~ m/(.)(.)(.)/; # spent 293µs making 66 calls to Mail::SpamAssassin::HTML::CORE:match, avg 4µs/call |
1047 | 66 | 666µs | $color = "$1$1$2$2$3$3"; | ||
1048 | } | ||||
1049 | |||||
1050 | } else { | ||||
1051 | return "invalid"; | ||||
1052 | } | ||||
1053 | |||||
1054 | } else { | ||||
1055 | #INVALID | ||||
1056 | |||||
1057 | #??RETURN BLACK SINCE WE DO NOT KNOW HOW THE MUA / BROWSER WILL PARSE | ||||
1058 | #$color = "000000"; | ||||
1059 | |||||
1060 | 6 | 48µs | return "invalid"; | ||
1061 | } | ||||
1062 | |||||
1063 | #print "DEBUG: before/after name_to_rgb new version: $before/$color\n"; | ||||
1064 | |||||
1065 | 2023 | 30.5ms | return "#" . $color; | ||
1066 | } | ||||
1067 | |||||
1068 | sub dec2hex { | ||||
1069 | my ($dec) = @_; | ||||
1070 | my ($pre) = ''; | ||||
1071 | |||||
1072 | if ($dec < 16) { | ||||
1073 | $pre = '0'; | ||||
1074 | } | ||||
1075 | |||||
1076 | return sprintf("$pre%lx", $dec); | ||||
1077 | } | ||||
1078 | |||||
1079 | |||||
1080 | 2 | 1.90ms | 2 | 464µs | # spent 251µs (37+214) within Mail::SpamAssassin::HTML::BEGIN@1080 which was called:
# once (37µs+214µs) by Mail::SpamAssassin::Message::Node::BEGIN@45 at line 1080 # spent 251µs making 1 call to Mail::SpamAssassin::HTML::BEGIN@1080
# spent 214µs making 1 call to constant::import |
1081 | |||||
1082 | # resolving relative URIs as defined in RFC 2396 (steps from section 5.2) | ||||
1083 | # using draft http://www.gbiv.com/protocols/uri/rev-2002/rfc2396bis.html | ||||
1084 | # spent 188ms (144+43.7) within Mail::SpamAssassin::HTML::_parse_uri which was called 5410 times, avg 35µs/call:
# 2705 times (80.1ms+30.2ms) by Mail::SpamAssassin::HTML::target_uri at line 1131, avg 41µs/call
# 2705 times (64.1ms+13.5ms) by Mail::SpamAssassin::HTML::target_uri at line 1132, avg 29µs/call | ||||
1085 | 5410 | 10.0ms | my ($u) = @_; | ||
1086 | 5410 | 8.93ms | my %u; | ||
1087 | 5410 | 107ms | 5410 | 43.7ms | ($u{scheme}, $u{authority}, $u{path}, $u{query}, $u{fragment}) = # spent 43.7ms making 5410 calls to Mail::SpamAssassin::HTML::CORE:match, avg 8µs/call |
1088 | $u =~ m|^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|; | ||||
1089 | 5410 | 99.1ms | return %u; | ||
1090 | } | ||||
1091 | |||||
1092 | sub _remove_dot_segments { | ||||
1093 | 2703 | 5.81ms | my ($input) = @_; | ||
1094 | 2703 | 5.23ms | my $output = ""; | ||
1095 | |||||
1096 | 2703 | 72.5ms | 2703 | 6.20ms | $input =~ s@^(?:\.\.?/)@/@; # spent 6.20ms making 2703 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 2µs/call |
1097 | |||||
1098 | 2703 | 10.1ms | while ($input) { | ||
1099 | 8468 | 391ms | 25404 | 80.0ms | if ($input =~ s@^/\.(?:$|/)@/@) { # spent 80.0ms making 25404 calls to Mail::SpamAssassin::HTML::CORE:subst, avg 3µs/call |
1100 | } | ||||
1101 | elsif ($input =~ s@^/\.\.(?:$|/)@/@) { | ||||
1102 | $output =~ s@/?[^/]*$@@; | ||||
1103 | } | ||||
1104 | elsif ($input =~ s@(/?[^/]*)@@) { | ||||
1105 | 8468 | 29.7ms | $output .= $1; | ||
1106 | } | ||||
1107 | } | ||||
1108 | 2703 | 42.2ms | return $output; | ||
1109 | } | ||||
1110 | |||||
1111 | sub _merge_uri { | ||||
1112 | my ($base_authority, $base_path, $r_path) = @_; | ||||
1113 | |||||
1114 | if (defined $base_authority && !$base_path) { | ||||
1115 | return "/" . $r_path; | ||||
1116 | } | ||||
1117 | else { | ||||
1118 | if ($base_path =~ m|/|) { | ||||
1119 | $base_path =~ s|(?<=/)[^/]*$||; | ||||
1120 | } | ||||
1121 | else { | ||||
1122 | $base_path = ""; | ||||
1123 | } | ||||
1124 | return $base_path . $r_path; | ||||
1125 | } | ||||
1126 | } | ||||
1127 | |||||
1128 | # spent 993ms (276+718) within Mail::SpamAssassin::HTML::target_uri which was called 2705 times, avg 367µs/call:
# 2705 times (276ms+718ms) by Mail::SpamAssassin::HTML::push_uri at line 329, avg 367µs/call | ||||
1129 | 2705 | 5.52ms | my ($base, $r) = @_; | ||
1130 | |||||
1131 | 2705 | 25.0ms | 2705 | 110ms | my %r = _parse_uri($r); # parsed relative URI # spent 110ms making 2705 calls to Mail::SpamAssassin::HTML::_parse_uri, avg 41µs/call |
1132 | 2705 | 22.6ms | 2705 | 77.6ms | my %base = _parse_uri($base); # parsed base URI # spent 77.6ms making 2705 calls to Mail::SpamAssassin::HTML::_parse_uri, avg 29µs/call |
1133 | 2705 | 4.39ms | my %t; # generated temporary URI | ||
1134 | |||||
1135 | 2705 | 6.62ms | if ((not URI_STRICT) and | ||
1136 | (defined $r{scheme} && defined $base{scheme}) and | ||||
1137 | ($r{scheme} eq $base{scheme})) | ||||
1138 | { | ||||
1139 | undef $r{scheme}; | ||||
1140 | } | ||||
1141 | |||||
1142 | 2705 | 9.49ms | if (defined $r{scheme}) { | ||
1143 | 2702 | 7.82ms | $t{scheme} = $r{scheme}; | ||
1144 | 2702 | 7.25ms | $t{authority} = $r{authority}; | ||
1145 | 2702 | 21.6ms | 2702 | 530ms | $t{path} = _remove_dot_segments($r{path}); # spent 530ms making 2702 calls to Mail::SpamAssassin::HTML::_remove_dot_segments, avg 196µs/call |
1146 | 2702 | 9.96ms | $t{query} = $r{query}; | ||
1147 | } | ||||
1148 | else { | ||||
1149 | 3 | 12µs | if (defined $r{authority}) { | ||
1150 | 1 | 3µs | $t{authority} = $r{authority}; | ||
1151 | 1 | 8µs | 1 | 64µs | $t{path} = _remove_dot_segments($r{path}); # spent 64µs making 1 call to Mail::SpamAssassin::HTML::_remove_dot_segments |
1152 | 1 | 3µs | $t{query} = $r{query}; | ||
1153 | } | ||||
1154 | else { | ||||
1155 | 2 | 14µs | if ($r{path} eq "") { | ||
1156 | 2 | 6µs | $t{path} = $base{path}; | ||
1157 | 2 | 8µs | if (defined $r{query}) { | ||
1158 | $t{query} = $r{query}; | ||||
1159 | } | ||||
1160 | else { | ||||
1161 | 2 | 6µs | $t{query} = $base{query}; | ||
1162 | } | ||||
1163 | } | ||||
1164 | else { | ||||
1165 | if ($r{path} =~ m|^/|) { | ||||
1166 | $t{path} = _remove_dot_segments($r{path}); | ||||
1167 | } | ||||
1168 | else { | ||||
1169 | $t{path} = _merge_uri($base{authority}, $base{path}, $r{path}); | ||||
1170 | $t{path} = _remove_dot_segments($t{path}); | ||||
1171 | } | ||||
1172 | $t{query} = $r{query}; | ||||
1173 | } | ||||
1174 | 2 | 6µs | $t{authority} = $base{authority}; | ||
1175 | } | ||||
1176 | 3 | 8µs | $t{scheme} = $base{scheme}; | ||
1177 | } | ||||
1178 | 2705 | 7.71ms | $t{fragment} = $r{fragment}; | ||
1179 | |||||
1180 | # recompose URI | ||||
1181 | 2705 | 5.08ms | my $result = ""; | ||
1182 | 2705 | 9.44ms | if ($t{scheme}) { | ||
1183 | 2702 | 8.44ms | $result .= $t{scheme} . ":"; | ||
1184 | } | ||||
1185 | elsif (defined $t{authority}) { | ||||
1186 | # this block is not part of the RFC | ||||
1187 | # TODO: figure out what MUAs actually do with unschemed URIs | ||||
1188 | # maybe look at URI::Heuristic | ||||
1189 | 1 | 20µs | 2 | 7µs | if ($t{authority} =~ /^www\d*\./i) { # spent 7µs making 2 calls to Mail::SpamAssassin::HTML::CORE:match, avg 3µs/call |
1190 | # some spammers are using unschemed URIs to escape filters | ||||
1191 | $result .= "http:"; | ||||
1192 | } | ||||
1193 | elsif ($t{authority} =~ /^ftp\d*\./i) { | ||||
1194 | $result .= "ftp:"; | ||||
1195 | } | ||||
1196 | } | ||||
1197 | 2705 | 9.20ms | if ($t{authority}) { | ||
1198 | 2654 | 6.93ms | $result .= "//" . $t{authority}; | ||
1199 | } | ||||
1200 | 2705 | 8.74ms | $result .= $t{path}; | ||
1201 | 2705 | 5.61ms | if (defined $t{query}) { | ||
1202 | 328 | 1.54ms | $result .= "?" . $t{query}; | ||
1203 | } | ||||
1204 | 2705 | 4.96ms | if (defined $t{fragment}) { | ||
1205 | 8 | 33µs | $result .= "#" . $t{fragment}; | ||
1206 | } | ||||
1207 | 2705 | 39.3ms | return $result; | ||
1208 | } | ||||
1209 | |||||
1210 | 1 | 140µs | 1; | ||
1211 | __END__ | ||||
# spent 1.10s within Mail::SpamAssassin::HTML::CORE:match which was called 232414 times, avg 5µs/call:
# 47000 times (96.7ms+0s) by Mail::SpamAssassin::HTML::html_tag at line 270, avg 2µs/call
# 33121 times (88.5ms+0s) by Mail::SpamAssassin::HTML::html_text at line 754, avg 3µs/call
# 29656 times (293ms+0s) by Mail::SpamAssassin::HTML::html_text at line 745, avg 10µs/call
# 29491 times (198ms+0s) by Mail::SpamAssassin::HTML::html_text at line 759, avg 7µs/call
# 28464 times (173ms+0s) by Mail::SpamAssassin::HTML::text_style at line 496, avg 6µs/call
# 16959 times (60.8ms+0s) by Mail::SpamAssassin::HTML::html_whitespace at line 310, avg 4µs/call
# 16543 times (54.9ms+0s) by Mail::SpamAssassin::HTML::html_uri at line 355, avg 3µs/call
# 5410 times (43.7ms+0s) by Mail::SpamAssassin::HTML::_parse_uri at line 1087, avg 8µs/call
# 4749 times (25.2ms+0s) by Mail::SpamAssassin::HTML::html_font_invisible at line 554, avg 5µs/call
# 4748 times (16.7ms+0s) by Mail::SpamAssassin::HTML::html_font_invisible at line 561, avg 4µs/call
# 3213 times (9.88ms+0s) by Mail::SpamAssassin::HTML::close_table_tag at line 409, avg 3µs/call
# 2236 times (6.18ms+0s) by Mail::SpamAssassin::HTML::text_style at line 500, avg 3µs/call
# 2029 times (6.51ms+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1012, avg 3µs/call
# 2023 times (5.88ms+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1027, avg 3µs/call
# 2023 times (3.47ms+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1017, avg 2µs/call
# 2023 times (3.28ms+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1022, avg 2µs/call
# 776 times (4.38ms+0s) by Mail::SpamAssassin::HTML::html_tests at line 628, avg 6µs/call
# 776 times (3.21ms+0s) by Mail::SpamAssassin::HTML::html_tests at line 632, avg 4µs/call
# 392 times (1.31ms+0s) by Mail::SpamAssassin::HTML::html_text at line 763, avg 3µs/call
# 274 times (1.80ms+0s) by Mail::SpamAssassin::HTML::html_tests at line 664, avg 7µs/call
# 198 times (822µs+0s) by Mail::SpamAssassin::HTML::text_style at line 483, avg 4µs/call
# 175 times (1.82ms+0s) by Mail::SpamAssassin::HTML::html_tests at line 611, avg 10µs/call
# 67 times (346µs+0s) by Mail::SpamAssassin::HTML::html_declaration at line 789, avg 5µs/call
# 66 times (293µs+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1046, avg 4µs/call
# 2 times (7µs+0s) by Mail::SpamAssassin::HTML::target_uri at line 1189, avg 3µs/call | |||||
# spent 552ms within Mail::SpamAssassin::HTML::CORE:subst which was called 101857 times, avg 5µs/call:
# 29656 times (254ms+0s) by Mail::SpamAssassin::HTML::display_text at line 698, avg 9µs/call
# 25404 times (80.0ms+0s) by Mail::SpamAssassin::HTML::_remove_dot_segments at line 1099, avg 3µs/call
# 14251 times (59.9ms+0s) by Mail::SpamAssassin::HTML::display_text at line 705, avg 4µs/call
# 14238 times (52.6ms+0s) by Mail::SpamAssassin::HTML::display_text at line 693, avg 4µs/call
# 4261 times (22.2ms+0s) by Mail::SpamAssassin::HTML::canon_uri at line 340, avg 5µs/call
# 4261 times (12.7ms+0s) by Mail::SpamAssassin::HTML::canon_uri at line 339, avg 3µs/call
# 2703 times (6.20ms+0s) by Mail::SpamAssassin::HTML::_remove_dot_segments at line 1096, avg 2µs/call
# 2340 times (13.5ms+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1003, avg 6µs/call
# 2340 times (12.1ms+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1002, avg 5µs/call
# 2023 times (14.3ms+0s) by Mail::SpamAssassin::HTML::name_to_rgb at line 1029, avg 7µs/call
# 190 times (15.2ms+0s) by Mail::SpamAssassin::HTML::parse at line 244, avg 80µs/call
# 190 times (9.19ms+0s) by Mail::SpamAssassin::HTML::parse at line 248, avg 48µs/call | |||||
# spent 28.6ms within Mail::SpamAssassin::HTML::CORE:substcont which was called 1404 times, avg 20µs/call:
# 1404 times (28.6ms+0s) by Mail::SpamAssassin::HTML::parse at line 248, avg 20µs/call |