line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
package HTTP::WebTest::Plugin::TagAttTest;
|
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
11399
|
use vars qw($VERSION);
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
70
|
|
5
|
|
|
|
|
|
|
$VERSION = '1.00';
|
6
|
|
|
|
|
|
|
=head1 NAME
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
HTTP::WebTest::Plugin::TagAttTest - Test by tag and attribute existence
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Not Applicable
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
This plugin allows to forbid or require tags and/or attributes in a web page.
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=cut
|
19
|
|
|
|
|
|
|
|
20
|
1
|
|
|
1
|
|
6
|
use strict;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
35
|
|
21
|
1
|
|
|
1
|
|
27
|
use base qw(HTTP::WebTest::Plugin);
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
1608
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
#use HTTP::Status;
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 TEST PARAMETERS
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=for pod_merge copy params
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head2 ignore_case
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Determines if case is important.
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head3 Allowed values
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
C,C
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head3 Default value
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
C
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head2 tag_require
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
A required tag. This is an array of hashs such as C<< require_tag => [{tag=>"script", tag_text=>"spam", attr=>"language",attr_text=>"javascript"}] >>
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
See also the L for a more detailed explaination.
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head3 Allowed values
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
list of hashes
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head3 Default value
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
None (will generate a failed test)
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head2 forbid_tag
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
A forbidden tag. This is an array of hashs such as C<< forbid_tag => [{tag=>"script",attr=>"language",attr_text=>"javascript"}] >>
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
See also the L for a more detailed explaination.
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head3 Allowed values
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
list of hashes
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head3 Default value
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
None (will generate a failed test)
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head1 TAG HASH
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=head2 tag
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
tag to forbid
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head2 attr
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
attribute to forbid
|
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head2 attr_text
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
regular expression or text. If text, will do a substring search.
|
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head2 tag_text
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
regular expression or text. If text, will do a substring search.
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Note that if an element is missing, it will not be considered. So something like
|
95
|
|
|
|
|
|
|
C [{tag=>"title"}]> will assure that a page has a title tag, but the
|
96
|
|
|
|
|
|
|
title tag could be blank.
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=cut
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub param_types {
|
103
|
0
|
|
|
0
|
0
|
|
return q(use_case yesno
|
104
|
|
|
|
|
|
|
tag_forbid list
|
105
|
|
|
|
|
|
|
tag_require list);
|
106
|
|
|
|
|
|
|
}
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub get_tag($ $)
|
109
|
|
|
|
|
|
|
{
|
110
|
0
|
|
|
0
|
0
|
|
my ($page, $tag_name) = @_;
|
111
|
0
|
0
|
|
|
|
|
if (!defined($tag_name))
|
112
|
|
|
|
|
|
|
{
|
113
|
0
|
|
|
|
|
|
return ($page->get_tag) ;
|
114
|
|
|
|
|
|
|
}
|
115
|
|
|
|
|
|
|
else
|
116
|
|
|
|
|
|
|
{
|
117
|
0
|
|
|
|
|
|
my $res = $page->get_tag($tag_name);
|
118
|
0
|
|
|
|
|
|
return ($res);
|
119
|
|
|
|
|
|
|
}
|
120
|
|
|
|
|
|
|
}
|
121
|
|
|
|
|
|
|
sub find_attributes
|
122
|
|
|
|
|
|
|
{
|
123
|
|
|
|
|
|
|
|
124
|
0
|
|
|
0
|
0
|
|
my( $ok, @attrarr, $attr_search, %attrhash, $attr_text_search, $case_re) = @_;
|
125
|
0
|
|
|
|
|
|
for my $attribute (@attrarr)
|
126
|
|
|
|
|
|
|
{
|
127
|
|
|
|
|
|
|
#this isn't as simple as for tags, because we can't get just certain attributes.
|
128
|
|
|
|
|
|
|
#the code can be shortened by combining the two if's, but it was giving me a
|
129
|
|
|
|
|
|
|
#headache figuring out all of the possibilities, so I left it for readability.
|
130
|
|
|
|
|
|
|
#case 6
|
131
|
0
|
0
|
|
|
|
|
if (!defined($attr_search))
|
132
|
|
|
|
|
|
|
{
|
133
|
0
|
|
|
|
|
|
my $attr_content = $attrhash{$attribute};
|
134
|
0
|
0
|
|
|
|
|
$ok = 0 if ($attr_content =~ /$case_re\Q$attr_text_search\E/);
|
135
|
|
|
|
|
|
|
}
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
#case 4
|
138
|
0
|
0
|
0
|
|
|
|
if (!(defined ($attr_text_search)) and ($attribute eq $attr_search))
|
139
|
|
|
|
|
|
|
{
|
140
|
0
|
|
|
|
|
|
$ok = 0;
|
141
|
|
|
|
|
|
|
}
|
142
|
|
|
|
|
|
|
#case 5
|
143
|
|
|
|
|
|
|
else
|
144
|
|
|
|
|
|
|
{
|
145
|
0
|
|
|
|
|
|
my $attr_content = $attrhash{$attribute};
|
146
|
0
|
0
|
|
|
|
|
$ok = 0 if ($attr_content =~ /$case_re\Q$attr_text_search\E/);
|
147
|
|
|
|
|
|
|
}
|
148
|
|
|
|
|
|
|
}
|
149
|
|
|
|
|
|
|
}
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub search_tag
|
152
|
|
|
|
|
|
|
{
|
153
|
0
|
|
|
0
|
0
|
|
my $ok = 1;
|
154
|
0
|
|
|
|
|
|
my ($page,$case_re, %tag_search_struct) = @_;
|
155
|
0
|
|
|
|
|
|
chomp (%tag_search_struct);
|
156
|
0
|
|
|
|
|
|
my $tag_search = $tag_search_struct{"tag"};
|
157
|
0
|
0
|
|
|
|
|
undef $tag_search if ($tag_search eq ''); #an undefined tag causes it to loop through all tags.
|
158
|
0
|
|
|
|
|
|
my $tag_text_search = $tag_search_struct{"tag_text"};
|
159
|
0
|
|
|
|
|
|
my $attr_search = $tag_search_struct{"attr"};
|
160
|
0
|
0
|
|
|
|
|
undef $attr_search if ($attr_search eq '');
|
161
|
0
|
|
|
|
|
|
my $attr_text_search = $tag_search_struct{"attr_text"};
|
162
|
0
|
|
|
|
|
|
my @results=();
|
163
|
|
|
|
|
|
|
|
164
|
0
|
0
|
0
|
|
|
|
return(0, "No values for tag searched") unless (defined ($tag_search) or defined ($attr_search));
|
165
|
|
|
|
|
|
|
#at this point we start looking for tags
|
166
|
|
|
|
|
|
|
#there are 6 main cases
|
167
|
|
|
|
|
|
|
#1, looking for a tag
|
168
|
|
|
|
|
|
|
#2, looking for a specific tag containing some specific text
|
169
|
|
|
|
|
|
|
#3, looking for any tag containing some specific text
|
170
|
|
|
|
|
|
|
#4, looking for an attribute
|
171
|
|
|
|
|
|
|
#5, looking for an attribute containing some specifice text
|
172
|
|
|
|
|
|
|
#6, looking for any attribute containing some specific text
|
173
|
|
|
|
|
|
|
# these can be combined
|
174
|
0
|
|
|
|
|
|
while ( my $tagstruct = get_tag($page,$tag_search) )
|
175
|
|
|
|
|
|
|
{
|
176
|
0
|
|
|
|
|
|
my $tag = $tagstruct->[0];
|
177
|
0
|
0
|
|
|
|
|
next if ($tag =~ m!/!);
|
178
|
0
|
|
|
|
|
|
my %attrhash= %{$tagstruct->[1]};
|
|
0
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
|
my @attrarr = @{$tagstruct->[2]};
|
|
0
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
#the tag exists so we want to see if the contents match
|
181
|
|
|
|
|
|
|
#case 1
|
182
|
0
|
0
|
0
|
|
|
|
$ok = 0 if (defined ($tag_search) and !defined ($tag_text_search)); #if we didn't search a tag, we should continue with the success assumption
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
#case 2 or 3
|
185
|
0
|
0
|
|
|
|
|
if ( defined ($tag_text_search) )
|
186
|
|
|
|
|
|
|
{
|
187
|
0
|
|
|
|
|
|
my $tag_content = $page->get_text;
|
188
|
0
|
0
|
|
|
|
|
$ok = 0 if ($tag_content =~ /$case_re\Q$tag_text_search\E/);
|
189
|
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
#this quits if we hit case 1, 2 or 3 and we aren't looking for cases 4, 5 or 6
|
192
|
0
|
0
|
0
|
|
|
|
last if ( (!defined ($attr_search) && !defined ($attr_text_search)) && !($ok));
|
|
|
|
0
|
|
|
|
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
#look for cases 4, 5, 6
|
195
|
0
|
|
|
|
|
|
$ok = find_attributes( $ok, @attrarr, $attr_search, %attrhash, $attr_text_search, $case_re);
|
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
#if $ok is 0, one of cases 4,5 or 6 must have failed.
|
198
|
0
|
0
|
|
|
|
|
last if ($ok == 0);
|
199
|
|
|
|
|
|
|
}
|
200
|
0
|
|
|
|
|
|
return ($ok, "tag: " . $tag_search . ", tag text: " . $tag_text_search . ", attribute: " . $attr_search . ", attribute text: " . $attr_text_search);
|
201
|
|
|
|
|
|
|
}
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub test_tags
|
204
|
|
|
|
|
|
|
{
|
205
|
0
|
|
|
0
|
0
|
|
my ($self, $tag_type, $content, $case_re) = @_;
|
206
|
1
|
|
|
1
|
|
2054
|
use HTML::TokeParser;
|
|
1
|
|
|
|
|
16232
|
|
|
1
|
|
|
|
|
405
|
|
207
|
0
|
|
|
|
|
|
my $page = HTML::TokeParser->new(\$content);
|
208
|
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
|
my @results;
|
210
|
0
|
|
|
|
|
|
for my $tag_struct (@{$self->test_param( $tag_type, [] )})
|
|
0
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
{
|
212
|
0
|
|
|
|
|
|
my ($ok, $result) = search_tag( $page, $case_re, %{ $tag_struct });
|
|
0
|
|
|
|
|
|
|
213
|
0
|
|
|
|
|
|
push @results, $self->test_result($ok, $result);
|
214
|
|
|
|
|
|
|
}
|
215
|
|
|
|
|
|
|
|
216
|
0
|
|
|
|
|
|
return @results;
|
217
|
|
|
|
|
|
|
}
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub check_response {
|
221
|
0
|
|
|
0
|
0
|
|
my $self = shift;
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# response content
|
224
|
0
|
|
|
|
|
|
my $content = $self->webtest->current_response->content;
|
225
|
0
|
|
|
|
|
|
$self->validate_params(qw(ignore_case
|
226
|
|
|
|
|
|
|
tag_forbid tag_require));
|
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# ignore case or not?
|
229
|
0
|
|
|
|
|
|
my $ignore_case = $self->yesno_test_param('ignore_case');
|
230
|
0
|
0
|
|
|
|
|
my $case_re = $ignore_case ? '(?i)' : '';
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# clean test results
|
233
|
0
|
|
|
|
|
|
my @results = ();
|
234
|
0
|
|
|
|
|
|
my @ret = ();
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# check for forbidden tag and attribute
|
237
|
|
|
|
|
|
|
|
238
|
0
|
|
|
|
|
|
my @forbid = test_tags($self, 'tag_forbid', $content, $case_re );
|
239
|
0
|
0
|
|
|
|
|
push @ret, ['Forbidden tag and attribute', @results] if @forbid;
|
240
|
|
|
|
|
|
|
|
241
|
0
|
|
|
|
|
|
my @require = test_tags( $self,'tag_require', $content, $case_re );
|
242
|
0
|
0
|
|
|
|
|
push @ret, ['Required tag and attribute', @results] if @require;
|
243
|
0
|
|
|
|
|
|
return @ret;
|
244
|
|
|
|
|
|
|
}
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=head1 COPYRIGHT
|
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
Copyright (c) 2003-2004 Edward Fancher. All rights reserved.
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
255
|
|
|
|
|
|
|
it under the same terms as Perl itself.
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=head1 SEE ALSO
|
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
L
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
L
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
L
|
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
L
|
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
L
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=cut
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
1;
|