line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package HTML::Template::Compiled::Parser; |
2
|
36
|
|
|
36
|
|
134
|
use Carp qw(croak carp confess); |
|
36
|
|
|
|
|
40
|
|
|
36
|
|
|
|
|
1931
|
|
3
|
36
|
|
|
36
|
|
126
|
use strict; |
|
36
|
|
|
|
|
42
|
|
|
36
|
|
|
|
|
575
|
|
4
|
36
|
|
|
36
|
|
97
|
use warnings; |
|
36
|
|
|
|
|
41
|
|
|
36
|
|
|
|
|
768
|
|
5
|
36
|
|
|
36
|
|
101
|
use base qw(Exporter); |
|
36
|
|
|
|
|
35
|
|
|
36
|
|
|
|
|
2065
|
|
6
|
36
|
|
|
36
|
|
12224
|
use HTML::Template::Compiled::Token qw(:tagtypes); |
|
36
|
|
|
|
|
58
|
|
|
36
|
|
|
|
|
4024
|
|
7
|
36
|
|
|
36
|
|
173
|
use Scalar::Util; |
|
36
|
|
|
|
|
36
|
|
|
36
|
|
|
|
|
2071
|
|
8
|
|
|
|
|
|
|
our $VERSION = '1.003'; # VERSION |
9
|
|
|
|
|
|
|
my @vars; |
10
|
|
|
|
|
|
|
BEGIN { |
11
|
36
|
|
|
36
|
|
919
|
@vars = qw( |
12
|
|
|
|
|
|
|
$CASE_SENSITIVE_DEFAULT |
13
|
|
|
|
|
|
|
$NEW_CHECK |
14
|
|
|
|
|
|
|
$ENABLE_SUB |
15
|
|
|
|
|
|
|
$DEBUG_DEFAULT |
16
|
|
|
|
|
|
|
$SEARCHPATH |
17
|
|
|
|
|
|
|
%FILESTACK %COMPILE_STACK %PATHS $DEFAULT_ESCAPE $DEFAULT_QUERY |
18
|
|
|
|
|
|
|
$UNTAINT $DEFAULT_TAGSTYLE $MAX_RECURSE |
19
|
|
|
|
|
|
|
); |
20
|
|
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
our @EXPORT_OK = @vars; |
22
|
36
|
|
|
36
|
|
126
|
use vars @vars; |
|
36
|
|
|
|
|
39
|
|
|
36
|
|
|
|
|
4816
|
|
23
|
|
|
|
|
|
|
$MAX_RECURSE = 10; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
$NEW_CHECK = 60 * 10; # 10 minutes default |
26
|
|
|
|
|
|
|
$DEBUG_DEFAULT = 0; |
27
|
|
|
|
|
|
|
$CASE_SENSITIVE_DEFAULT = 1; # set to 0 for H::T compatibility |
28
|
|
|
|
|
|
|
$ENABLE_SUB = 0; |
29
|
|
|
|
|
|
|
$SEARCHPATH = 0; |
30
|
|
|
|
|
|
|
$DEFAULT_ESCAPE = 0; |
31
|
|
|
|
|
|
|
$UNTAINT = 0; |
32
|
|
|
|
|
|
|
$DEFAULT_QUERY = 0; |
33
|
|
|
|
|
|
|
$DEFAULT_TAGSTYLE = [qw(classic comment asp)]; |
34
|
|
|
|
|
|
|
|
35
|
36
|
|
|
36
|
|
129
|
use constant ATTR_TAGSTYLE => 0; |
|
36
|
|
|
|
|
33
|
|
|
36
|
|
|
|
|
1514
|
|
36
|
36
|
|
|
36
|
|
115
|
use constant ATTR_TAGNAMES => 1; |
|
36
|
|
|
|
|
38
|
|
|
36
|
|
|
|
|
1310
|
|
37
|
36
|
|
|
36
|
|
117
|
use constant ATTR_PERL => 2; |
|
36
|
|
|
|
|
38
|
|
|
36
|
|
|
|
|
1267
|
|
38
|
36
|
|
|
36
|
|
116
|
use constant ATTR_EXPRESSION => 3; |
|
36
|
|
|
|
|
38
|
|
|
36
|
|
|
|
|
1302
|
|
39
|
36
|
|
|
36
|
|
123
|
use constant ATTR_CHOMP => 4; |
|
36
|
|
|
|
|
36
|
|
|
36
|
|
|
|
|
1293
|
|
40
|
36
|
|
|
36
|
|
109
|
use constant ATTR_STRICT => 5; |
|
36
|
|
|
|
|
38
|
|
|
36
|
|
|
|
|
1360
|
|
41
|
|
|
|
|
|
|
|
42
|
36
|
|
|
36
|
|
117
|
use constant T_VAR => 'VAR'; |
|
36
|
|
|
|
|
38
|
|
|
36
|
|
|
|
|
1253
|
|
43
|
36
|
|
|
36
|
|
109
|
use constant T_IF => 'IF'; |
|
36
|
|
|
|
|
33
|
|
|
36
|
|
|
|
|
1283
|
|
44
|
36
|
|
|
36
|
|
121
|
use constant T_UNLESS => 'UNLESS'; |
|
36
|
|
|
|
|
36
|
|
|
36
|
|
|
|
|
1269
|
|
45
|
36
|
|
|
36
|
|
104
|
use constant T_ELSIF => 'ELSIF'; |
|
36
|
|
|
|
|
43
|
|
|
36
|
|
|
|
|
1248
|
|
46
|
36
|
|
|
36
|
|
115
|
use constant T_ELSE => 'ELSE'; |
|
36
|
|
|
|
|
40
|
|
|
36
|
|
|
|
|
1197
|
|
47
|
36
|
|
|
36
|
|
106
|
use constant T_IF_DEFINED => 'IF_DEFINED'; |
|
36
|
|
|
|
|
39
|
|
|
36
|
|
|
|
|
1225
|
|
48
|
36
|
|
|
36
|
|
110
|
use constant T_END => '__EOT__'; |
|
36
|
|
|
|
|
30
|
|
|
36
|
|
|
|
|
1145
|
|
49
|
36
|
|
|
36
|
|
111
|
use constant T_WITH => 'WITH'; |
|
36
|
|
|
|
|
34
|
|
|
36
|
|
|
|
|
1222
|
|
50
|
36
|
|
|
36
|
|
112
|
use constant T_SWITCH => 'SWITCH'; |
|
36
|
|
|
|
|
40
|
|
|
36
|
|
|
|
|
1213
|
|
51
|
36
|
|
|
36
|
|
113
|
use constant T_CASE => 'CASE'; |
|
36
|
|
|
|
|
37
|
|
|
36
|
|
|
|
|
1316
|
|
52
|
36
|
|
|
36
|
|
108
|
use constant T_INCLUDE => 'INCLUDE'; |
|
36
|
|
|
|
|
37
|
|
|
36
|
|
|
|
|
1147
|
|
53
|
36
|
|
|
36
|
|
105
|
use constant T_LOOP => 'LOOP'; |
|
36
|
|
|
|
|
32
|
|
|
36
|
|
|
|
|
1197
|
|
54
|
36
|
|
|
36
|
|
112
|
use constant T_WHILE => 'WHILE'; |
|
36
|
|
|
|
|
38
|
|
|
36
|
|
|
|
|
1255
|
|
55
|
36
|
|
|
36
|
|
109
|
use constant T_INCLUDE_VAR => 'INCLUDE_VAR'; |
|
36
|
|
|
|
|
34
|
|
|
36
|
|
|
|
|
1182
|
|
56
|
|
|
|
|
|
|
|
57
|
36
|
|
|
36
|
|
117
|
use constant CHOMP_NONE => 0; |
|
36
|
|
|
|
|
37
|
|
|
36
|
|
|
|
|
1396
|
|
58
|
36
|
|
|
36
|
|
110
|
use constant CHOMP_ONE => 1; |
|
36
|
|
|
|
|
41
|
|
|
36
|
|
|
|
|
1264
|
|
59
|
36
|
|
|
36
|
|
109
|
use constant CHOMP_COLLAPSE => 2; |
|
36
|
|
|
|
|
43
|
|
|
36
|
|
|
|
|
1260
|
|
60
|
36
|
|
|
36
|
|
119
|
use constant CHOMP_GREEDY => 3; |
|
36
|
|
|
|
|
35
|
|
|
36
|
|
|
|
|
88902
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# under construction (sic!) |
63
|
|
|
|
|
|
|
sub new { |
64
|
69
|
|
|
69
|
0
|
95
|
my $class = shift; |
65
|
69
|
|
|
|
|
130
|
my %args = @_; |
66
|
69
|
|
|
|
|
82
|
my $self = []; |
67
|
69
|
|
|
|
|
101
|
bless $self, $class; |
68
|
69
|
|
|
|
|
189
|
$self->init(%args); |
69
|
69
|
|
|
|
|
240
|
$self; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
0
|
0
|
0
|
sub set_tagstyle { $_[0]->[ATTR_TAGSTYLE] = $_[1] } |
73
|
161
|
|
|
161
|
0
|
220
|
sub get_tagstyle { $_[0]->[ATTR_TAGSTYLE] } |
74
|
|
|
|
|
|
|
|
75
|
0
|
|
|
0
|
0
|
0
|
sub set_tagnames { $_[0]->[ATTR_TAGNAMES] = $_[1] } |
76
|
553
|
|
|
553
|
0
|
1736
|
sub get_tagnames { $_[0]->[ATTR_TAGNAMES] } |
77
|
|
|
|
|
|
|
|
78
|
131
|
|
|
131
|
0
|
235
|
sub set_perl { $_[0]->[ATTR_PERL] = $_[1] } |
79
|
4
|
|
|
4
|
0
|
24
|
sub get_perl { $_[0]->[ATTR_PERL] } |
80
|
|
|
|
|
|
|
|
81
|
98
|
|
|
98
|
0
|
203
|
sub set_expressions { $_[0]->[ATTR_EXPRESSION] = $_[1] } |
82
|
409
|
|
|
409
|
0
|
606
|
sub get_expressions { $_[0]->[ATTR_EXPRESSION] } |
83
|
|
|
|
|
|
|
|
84
|
131
|
|
|
131
|
0
|
242
|
sub set_chomp { $_[0]->[ATTR_CHOMP] = $_[1] } |
85
|
1018
|
|
|
1018
|
0
|
1093
|
sub get_chomp { $_[0]->[ATTR_CHOMP] } |
86
|
|
|
|
|
|
|
|
87
|
98
|
|
|
98
|
0
|
179
|
sub set_strict { $_[0]->[ATTR_STRICT] = $_[1] } |
88
|
4
|
|
|
4
|
0
|
10
|
sub get_strict { $_[0]->[ATTR_STRICT] } |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub add_tagnames { |
91
|
4
|
|
|
4
|
0
|
7
|
my ($self, $hash) = @_; |
92
|
4
|
|
|
|
|
6
|
my $open = $hash->{OPENING_TAG()}; |
93
|
4
|
|
|
|
|
4
|
my $close = $hash->{CLOSING_TAG()}; |
94
|
4
|
|
|
|
|
14
|
@{ $_[0]->[ATTR_TAGNAMES]->{OPENING_TAG()} }{keys %$open} = values %$open; |
|
4
|
|
|
|
|
11
|
|
95
|
4
|
|
|
|
|
9
|
@{ $_[0]->[ATTR_TAGNAMES]->{CLOSING_TAG()} }{keys %$close} = values %$close; |
|
4
|
|
|
|
|
11
|
|
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub remove_tags { |
99
|
1
|
|
|
1
|
0
|
2
|
my ($self, @tags) = @_; |
100
|
1
|
|
|
|
|
2
|
my $open = $self->[ATTR_TAGNAMES]->{OPENING_TAG()}; |
101
|
1
|
|
|
|
|
1
|
my $close = $self->[ATTR_TAGNAMES]->{CLOSING_TAG()}; |
102
|
1
|
|
|
|
|
2
|
delete @$open{@tags}; |
103
|
1
|
|
|
|
|
3
|
delete @$close{@tags}; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my $_default_tags = { |
107
|
|
|
|
|
|
|
classic => ['', '', ], |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
comment => ['','',], |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
asp => ['<%' ,'%>', '<%/', '%>', ], |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
php => ['<\?' ,'\?>', '<\?/', '\?>', ], |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
tt => ['\[%' ,'%\]', '\[%/', '%\]' , ], |
116
|
|
|
|
|
|
|
}; |
117
|
|
|
|
|
|
|
sub default_tags { |
118
|
247
|
|
|
247
|
0
|
598
|
return $_default_tags; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
my $default_validation = sub { |
122
|
|
|
|
|
|
|
my ($p, $attr) = @_; |
123
|
|
|
|
|
|
|
my $test = $p->get_expressions; |
124
|
|
|
|
|
|
|
exists $attr->{NAME} or |
125
|
|
|
|
|
|
|
($p->get_expressions and exists $attr->{EXPR}) |
126
|
|
|
|
|
|
|
}; |
127
|
|
|
|
|
|
|
my %allowed_tagnames = ( |
128
|
|
|
|
|
|
|
OPENING_TAG() => { |
129
|
|
|
|
|
|
|
VAR => [$default_validation, qw(NAME ESCAPE DEFAULT EXPR)], |
130
|
|
|
|
|
|
|
# just an alias for VAR |
131
|
|
|
|
|
|
|
'=' => [$default_validation, qw(NAME ESCAPE DEFAULT EXPR)], |
132
|
|
|
|
|
|
|
IF_DEFINED => [$default_validation, qw(NAME EXPR)], |
133
|
|
|
|
|
|
|
IF => [$default_validation, qw(NAME EXPR)], |
134
|
|
|
|
|
|
|
UNLESS => [$default_validation, qw(NAME EXPR)], |
135
|
|
|
|
|
|
|
ELSIF => [$default_validation, qw(NAME EXPR)], |
136
|
|
|
|
|
|
|
ELSE => [undef, qw(NAME)], |
137
|
|
|
|
|
|
|
WITH => [$default_validation, qw(NAME EXPR)], |
138
|
|
|
|
|
|
|
COMMENT => [undef, qw(NAME)], |
139
|
|
|
|
|
|
|
VERBATIM => [undef, qw(NAME)], |
140
|
|
|
|
|
|
|
NOPARSE => [undef, qw(NAME)], |
141
|
|
|
|
|
|
|
LOOP => [$default_validation, qw(NAME ALIAS JOIN BREAK EXPR CONTEXT)], |
142
|
|
|
|
|
|
|
WHILE => [$default_validation, qw(NAME ALIAS BREAK EXPR)], |
143
|
|
|
|
|
|
|
EACH => [$default_validation, qw(NAME BREAK EXPR SORT SORTBY REVERSE CONTEXT)], |
144
|
|
|
|
|
|
|
SWITCH => [$default_validation, qw(NAME EXPR)], |
145
|
|
|
|
|
|
|
CASE => [undef, qw(NAME)], |
146
|
|
|
|
|
|
|
INCLUDE_VAR => [$default_validation, qw(NAME EXPR)], |
147
|
|
|
|
|
|
|
INCLUDE_STRING => [$default_validation, qw(NAME EXPR)], |
148
|
|
|
|
|
|
|
INCLUDE => [$default_validation, qw(NAME)], |
149
|
|
|
|
|
|
|
USE_VARS => [$default_validation, qw(NAME)], |
150
|
|
|
|
|
|
|
SET_VAR => [$default_validation, qw(NAME VALUE EXPR)], |
151
|
|
|
|
|
|
|
WRAPPER => [$default_validation, qw(NAME)], |
152
|
|
|
|
|
|
|
}, |
153
|
|
|
|
|
|
|
CLOSING_TAG() => { |
154
|
|
|
|
|
|
|
IF_DEFINED => [undef, qw(NAME)], |
155
|
|
|
|
|
|
|
IF => [undef, qw(NAME)], |
156
|
|
|
|
|
|
|
UNLESS => [undef, qw(NAME)], |
157
|
|
|
|
|
|
|
ELSIF => [undef, qw(NAME)], |
158
|
|
|
|
|
|
|
WITH => [undef, qw(NAME)], |
159
|
|
|
|
|
|
|
COMMENT => [undef, qw(NAME)], |
160
|
|
|
|
|
|
|
VERBATIM => [undef, qw(NAME)], |
161
|
|
|
|
|
|
|
NOPARSE => [undef, qw(NAME)], |
162
|
|
|
|
|
|
|
LOOP => [undef, qw(NAME)], |
163
|
|
|
|
|
|
|
WHILE => [undef, qw(NAME)], |
164
|
|
|
|
|
|
|
EACH => [undef, qw(NAME)], |
165
|
|
|
|
|
|
|
SWITCH => [undef, qw(NAME)], |
166
|
|
|
|
|
|
|
WRAPPER => [undef, qw(NAME)], |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub init { |
172
|
69
|
|
|
69
|
0
|
98
|
my ( $self, %args ) = @_; |
173
|
69
|
|
50
|
|
|
430
|
my $tagnames = $args{tagnames} || {}; |
174
|
69
|
|
|
|
|
199
|
my $tagstyle = $self->_create_tagstyle( $args{tagstyle} ); |
175
|
69
|
|
|
|
|
293
|
$self->[ATTR_TAGSTYLE] = $tagstyle; |
176
|
69
|
|
|
|
|
91
|
$self->[ATTR_EXPRESSION] = $args{use_expressions}; |
177
|
69
|
|
|
|
|
103
|
$self->[ATTR_CHOMP] = $args{chomp}; |
178
|
69
|
|
|
|
|
144
|
$self->[ATTR_STRICT] = $args{strict}; |
179
|
|
|
|
|
|
|
$self->[ATTR_TAGNAMES] = { |
180
|
|
|
|
|
|
|
OPENING_TAG() => { |
181
|
69
|
|
|
|
|
291
|
%{ $allowed_tagnames{ OPENING_TAG() } }, |
182
|
69
|
50
|
|
|
|
670
|
%{ $tagnames->{ OPENING_TAG() }||{} }, |
183
|
|
|
|
|
|
|
}, |
184
|
|
|
|
|
|
|
CLOSING_TAG() => { |
185
|
69
|
|
|
|
|
203
|
%{ $allowed_tagnames{ CLOSING_TAG() } }, |
186
|
69
|
50
|
|
|
|
71
|
%{ $tagnames->{ CLOSING_TAG() }||{} }, |
|
69
|
|
|
|
|
565
|
|
187
|
|
|
|
|
|
|
}, |
188
|
|
|
|
|
|
|
}; |
189
|
|
|
|
|
|
|
} ## end sub init |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub _create_tagstyle { |
192
|
69
|
|
|
69
|
|
1387
|
my ($self, $tagstyle_def) = @_; |
193
|
69
|
|
100
|
|
|
276
|
$tagstyle_def ||= []; |
194
|
69
|
|
|
|
|
69
|
my $tagstyle; |
195
|
|
|
|
|
|
|
my $named_styles = { |
196
|
|
|
|
|
|
|
map { |
197
|
69
|
|
|
|
|
132
|
($_ => $self->default_tags->{$_}) |
|
207
|
|
|
|
|
273
|
|
198
|
|
|
|
|
|
|
} @$DEFAULT_TAGSTYLE |
199
|
|
|
|
|
|
|
}; |
200
|
69
|
|
|
|
|
165
|
for my $def (@$tagstyle_def) { |
201
|
131
|
50
|
33
|
|
|
339
|
if (ref $def eq 'ARRAY' && @$def == 4) { |
|
|
50
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# we got user defined regexes |
203
|
0
|
|
|
|
|
0
|
push @$tagstyle, $def; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
elsif (!ref $def) { |
206
|
|
|
|
|
|
|
# strings |
207
|
131
|
100
|
|
|
|
336
|
if ($def =~ m/^-(.*)/) { |
|
|
50
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# deactivate style |
209
|
91
|
|
|
|
|
170
|
delete $named_styles->{"$1"}; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
elsif ($def =~ m/^\+?(.*)/) { |
212
|
|
|
|
|
|
|
# activate style |
213
|
40
|
|
|
|
|
64
|
$named_styles->{"$1"} = $self->default_tags->{"$1"}; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
} |
217
|
69
|
|
|
|
|
195
|
push @$tagstyle, values %$named_styles; |
218
|
69
|
|
|
|
|
151
|
return $tagstyle; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub find_start_of_tag { |
222
|
1068
|
|
|
1068
|
0
|
873
|
my ($self, $arg) = @_; |
223
|
1068
|
|
|
|
|
941
|
my $re = $arg->{start_close_re}; |
224
|
1068
|
100
|
|
1
|
|
6018
|
if ($arg->{template} =~ s/^($re)//) { |
|
1
|
|
|
|
|
558
|
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
10
|
|
225
|
519
|
|
|
|
|
433
|
my %open_close_map = %{$arg->{open_close_map}}; |
|
519
|
|
|
|
|
1740
|
|
226
|
|
|
|
|
|
|
# $open contains
|
227
|
519
|
|
|
|
|
982
|
$arg->{open} = $1; |
228
|
519
|
|
|
|
|
676
|
$arg->{token} .= $1; |
229
|
|
|
|
|
|
|
# check which type of tag we got |
230
|
519
|
|
|
|
|
1018
|
TYPES: for my $key (keys %open_close_map) { |
231
|
|
|
|
|
|
|
#print STDERR "try $key '$arg->{open}'\n"; |
232
|
1733
|
100
|
|
|
|
12826
|
if ($arg->{open} =~ m/^$key$/i) { |
233
|
519
|
|
|
|
|
558
|
my $val = $open_close_map{$key}; |
234
|
519
|
|
|
|
|
583
|
$arg->{close_match} = $val->[1]; |
235
|
519
|
|
|
|
|
616
|
$arg->{open_or_close} = $val->[0]; |
236
|
|
|
|
|
|
|
#print STDERR "=== tag type $key, searching for $arg->{close_match}\n"; |
237
|
519
|
|
|
|
|
855
|
last TYPES; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
#print STDERR "got start_close_re\n"; |
241
|
519
|
|
|
|
|
1569
|
return 1; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
else { |
244
|
549
|
|
|
|
|
18418
|
return; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub find_attributes { |
249
|
509
|
|
|
509
|
0
|
515
|
my ($self, $arg) = @_; |
250
|
|
|
|
|
|
|
#warn Data::Dumper->Dump([\%args], ['args']); |
251
|
509
|
|
|
|
|
363
|
my $allowed = [@{ $arg->{allowed_names} }, 'PRE_CHOMP', 'POST_CHOMP']; |
|
509
|
|
|
|
|
1127
|
|
252
|
509
|
|
|
|
|
483
|
my $attr = $arg->{attr}; |
253
|
509
|
|
|
|
|
412
|
my $fname = $arg->{fname}; |
254
|
509
|
|
|
|
|
446
|
my $line = $arg->{line}; |
255
|
|
|
|
|
|
|
|
256
|
509
|
|
|
|
|
807
|
my ($validate_sub, @allowed) = @$allowed; |
257
|
|
|
|
|
|
|
my $allowed_names = [ sort { |
258
|
509
|
|
|
|
|
1003
|
length($b) <=> length($a) |
|
3318
|
|
|
|
|
2981
|
|
259
|
|
|
|
|
|
|
} @allowed ]; |
260
|
509
|
|
|
|
|
906
|
my $re = join '|', @$allowed_names; |
261
|
509
|
|
|
|
|
387
|
ATTR: while (1) { |
262
|
969
|
100
|
|
|
|
3614
|
last if $arg->{template} =~ m/^($arg->{close_match})/; |
263
|
462
|
|
|
|
|
814
|
my ($name, $val, $orig) = $self->find_attribute( $arg, $re ); |
264
|
462
|
50
|
|
|
|
781
|
last unless defined $name; |
265
|
462
|
|
|
|
|
486
|
my $key = uc $name; |
266
|
462
|
50
|
66
|
|
|
904
|
if ($key =~ m/^(?:PRE|POST)_CHOMP\z/ and $val !~ m/^(?:0|1|2|3)\z/) { |
267
|
|
|
|
|
|
|
$self->_error_wrong_tag_syntax( |
268
|
|
|
|
|
|
|
$arg, |
269
|
0
|
|
|
|
|
0
|
$orig.$arg->{template}, '(PRE|POST)_CHOMP=(0|1|2|3)', |
270
|
|
|
|
|
|
|
); |
271
|
|
|
|
|
|
|
} |
272
|
462
|
100
|
|
|
|
723
|
if (exists $attr->{$key}) { |
273
|
|
|
|
|
|
|
$self->_error_wrong_tag_syntax( |
274
|
|
|
|
|
|
|
$arg, |
275
|
2
|
|
|
|
|
7
|
$orig.$arg->{template}, 'duplicate attribute', |
276
|
|
|
|
|
|
|
); |
277
|
|
|
|
|
|
|
} |
278
|
460
|
|
|
|
|
683
|
$attr->{$key} = $val; |
279
|
460
|
|
|
|
|
634
|
$arg->{token} .= $orig; |
280
|
|
|
|
|
|
|
} |
281
|
507
|
100
|
|
|
|
1021
|
my $ok = $validate_sub ? $validate_sub->($self, $attr) : 1; |
282
|
|
|
|
|
|
|
$self->_error_wrong_tag_syntax( |
283
|
|
|
|
|
|
|
$arg, $arg->{template} |
284
|
507
|
100
|
|
|
|
761
|
) unless $ok; |
285
|
505
|
|
|
|
|
1533
|
return $ok; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
{ |
289
|
|
|
|
|
|
|
my $callbacks_found_text; |
290
|
|
|
|
|
|
|
my $encode_tag = sub { |
291
|
|
|
|
|
|
|
my ( $p, $arg ) = @_; |
292
|
|
|
|
|
|
|
$arg->{token} = HTML::Template::Compiled::Utils::escape_html($arg->{token}); |
293
|
|
|
|
|
|
|
$callbacks_found_text->[0]->($p, $arg); |
294
|
|
|
|
|
|
|
$arg->{token} = ""; |
295
|
|
|
|
|
|
|
}; |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
my $ignore_tag = sub { |
298
|
|
|
|
|
|
|
my ( $p, $arg ) = @_; |
299
|
|
|
|
|
|
|
$arg->{token} = ""; |
300
|
|
|
|
|
|
|
}; |
301
|
|
|
|
|
|
|
my $default_callback_text = sub { |
302
|
|
|
|
|
|
|
my ($self, $arg) = @_; |
303
|
|
|
|
|
|
|
$arg->{line} += $arg->{token} =~ tr/\n//; |
304
|
|
|
|
|
|
|
#print STDERR "we found text: '$arg->{token}}'\n"; |
305
|
|
|
|
|
|
|
push @{$arg->{tags}}, |
306
|
|
|
|
|
|
|
HTML::Template::Compiled::Token::Text->new([ |
307
|
|
|
|
|
|
|
$arg->{token}, $arg->{line}, |
308
|
|
|
|
|
|
|
undef, undef, undef, $arg->{fname}, $arg->{level} |
309
|
|
|
|
|
|
|
]); |
310
|
|
|
|
|
|
|
$arg->{token} = ""; |
311
|
|
|
|
|
|
|
}; |
312
|
|
|
|
|
|
|
my $default_callback_tag = sub { |
313
|
|
|
|
|
|
|
my ($self, $arg) = @_; |
314
|
|
|
|
|
|
|
#print STDERR "####found tag $arg->{name}, $arg->{open_or_close}\n"; |
315
|
|
|
|
|
|
|
$arg->{line} += $arg->{token} =~ tr/\n//; |
316
|
|
|
|
|
|
|
my $class = 'HTML::Template::Compiled::Token::' . |
317
|
|
|
|
|
|
|
($arg->{open_or_close} == OPENING_TAG |
318
|
|
|
|
|
|
|
? 'open' |
319
|
|
|
|
|
|
|
: 'close'); |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
my $token = $class->new([ |
322
|
|
|
|
|
|
|
$arg->{token}, $arg->{line}, |
323
|
|
|
|
|
|
|
[$arg->{open}, $arg->{close}], $arg->{name}, |
324
|
|
|
|
|
|
|
{ %{ $arg->{attr} } }, |
325
|
|
|
|
|
|
|
$arg->{fname}, $arg->{level}, |
326
|
|
|
|
|
|
|
]); |
327
|
|
|
|
|
|
|
push @{$arg->{tags}}, $token; |
328
|
|
|
|
|
|
|
if ($token->is_open && |
329
|
|
|
|
|
|
|
exists |
330
|
|
|
|
|
|
|
$self->get_tagnames->{CLOSING_TAG()}->{ $arg->{name} }) { |
331
|
|
|
|
|
|
|
$arg->{level}++ |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
elsif ($token->is_close) { |
334
|
|
|
|
|
|
|
$arg->{level}-- |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
$self->checkstack( $arg ); |
337
|
|
|
|
|
|
|
$arg->{token} = ""; |
338
|
|
|
|
|
|
|
}; |
339
|
|
|
|
|
|
|
$callbacks_found_text = [ $default_callback_text ]; |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub parse { |
342
|
161
|
|
|
161
|
0
|
208
|
my ($self, $fname, $template) = @_; |
343
|
161
|
|
|
|
|
310
|
my $tagnames = $self->get_tagnames; |
344
|
161
|
|
|
|
|
172
|
my %allowed_ident; |
345
|
|
|
|
|
|
|
$allowed_ident{OPENING_TAG()} = "(?i:" . join("|", sort { |
346
|
11659
|
|
|
|
|
8328
|
length $b <=> length $a |
347
|
161
|
|
|
|
|
183
|
} keys %{ $tagnames->{OPENING_TAG()} }) . ")"; |
|
161
|
|
|
|
|
1204
|
|
348
|
|
|
|
|
|
|
$allowed_ident{CLOSING_TAG()} = "(?i:" . join("|", sort { |
349
|
5350
|
|
|
|
|
3804
|
length $b <=> length $a |
350
|
161
|
|
|
|
|
302
|
} keys %{ $tagnames->{CLOSING_TAG()} }) . ")"; |
|
161
|
|
|
|
|
516
|
|
351
|
161
|
|
|
|
|
406
|
my $tagstyle = $self->get_tagstyle; |
352
|
|
|
|
|
|
|
# make (?i:IF_DEFINED|LOOP|IF|=|...) out of the list of identifiers |
353
|
|
|
|
|
|
|
my $start_close_re = '(?i:' . join("|", sort { |
354
|
1099
|
|
|
|
|
1049
|
length($b) <=> length($a) |
355
|
|
|
|
|
|
|
} map { |
356
|
161
|
|
|
|
|
299
|
$_->[0], $_->[2] |
|
424
|
|
|
|
|
752
|
|
357
|
|
|
|
|
|
|
} @$tagstyle) . ")"; |
358
|
|
|
|
|
|
|
my $close_re = '(?i:' . join("|", sort { |
359
|
1098
|
|
|
|
|
992
|
length($b) <=> length($a) |
360
|
|
|
|
|
|
|
} map { |
361
|
161
|
|
|
|
|
279
|
$_->[1], $_->[3] |
|
424
|
|
|
|
|
572
|
|
362
|
|
|
|
|
|
|
} @$tagstyle) . ")"; |
363
|
|
|
|
|
|
|
my %open_close = map { |
364
|
161
|
|
|
|
|
244
|
( |
365
|
424
|
|
|
|
|
1562
|
$_->[0] => [ |
366
|
|
|
|
|
|
|
OPENING_TAG, $_->[1] |
367
|
|
|
|
|
|
|
], |
368
|
|
|
|
|
|
|
$_->[2] => [ |
369
|
|
|
|
|
|
|
CLOSING_TAG, $_->[3] |
370
|
|
|
|
|
|
|
], |
371
|
|
|
|
|
|
|
), |
372
|
|
|
|
|
|
|
} @$tagstyle; |
373
|
|
|
|
|
|
|
|
374
|
161
|
|
|
|
|
214
|
my $comment_info; |
375
|
161
|
|
|
|
|
236
|
my $callback_found_tag = [ $default_callback_tag ]; |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
my $callback = sub { |
378
|
509
|
|
|
509
|
|
472
|
my ( $p, $arg ) = @_; |
379
|
509
|
|
|
|
|
560
|
my $name = $arg->{name}; |
380
|
|
|
|
|
|
|
#print STDERR "callback found tag $name\n"; |
381
|
509
|
100
|
|
|
|
1952
|
if ( $name eq 'COMMENT' ) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
382
|
4
|
100
|
|
|
|
12
|
if ( $arg->{open_or_close} == OPENING_TAG ) { |
|
|
50
|
|
|
|
|
|
383
|
2
|
100
|
|
|
|
7
|
++$comment_info->{$name} == 1 |
384
|
|
|
|
|
|
|
and push @$callbacks_found_text, $ignore_tag; |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
elsif ( $arg->{open_or_close} == CLOSING_TAG ) { |
387
|
2
|
100
|
|
|
|
5
|
--$comment_info->{$name} == 0 |
388
|
|
|
|
|
|
|
and pop @$callbacks_found_text; |
389
|
|
|
|
|
|
|
} |
390
|
4
|
|
|
|
|
9
|
$arg->{token} = ""; |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
elsif ( $comment_info->{COMMENT} ) { |
393
|
2
|
|
|
|
|
7
|
$arg->{token} = ""; |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
elsif ($name eq 'NOPARSE') { |
396
|
4
|
100
|
|
|
|
11
|
if ( $arg->{open_or_close} == OPENING_TAG ) { |
|
|
50
|
|
|
|
|
|
397
|
2
|
100
|
|
|
|
5
|
if (++$comment_info->{$name} == 1) { |
398
|
1
|
|
|
|
|
4
|
$arg->{token} = ""; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
else { |
401
|
1
|
|
|
|
|
3
|
$callbacks_found_text->[0]->(@_); |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
elsif ( $arg->{open_or_close} == CLOSING_TAG ) { |
405
|
2
|
100
|
|
|
|
4
|
if (--$comment_info->{$name} == 0) { |
406
|
1
|
|
|
|
|
4
|
$arg->{token} = ""; |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
else { |
409
|
1
|
|
|
|
|
2
|
$callbacks_found_text->[0]->(@_); |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
elsif ( $comment_info->{NOPARSE} ) { |
414
|
2
|
|
|
|
|
19
|
$callbacks_found_text->[0]->(@_); |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
elsif ($name eq 'VERBATIM') { |
417
|
2
|
100
|
|
|
|
6
|
if ( $arg->{open_or_close} == OPENING_TAG ) { |
|
|
50
|
|
|
|
|
|
418
|
1
|
50
|
|
|
|
3
|
if (++$comment_info->{$name} == 1) { |
419
|
1
|
|
|
|
|
4
|
$arg->{token} = ""; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
else { |
422
|
0
|
|
|
|
|
0
|
$encode_tag->(@_); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
elsif ( $arg->{open_or_close} == CLOSING_TAG ) { |
426
|
1
|
50
|
|
|
|
3
|
if (--$comment_info->{$name} == 0) { |
427
|
1
|
|
|
|
|
3
|
$arg->{token} = ""; |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
else { |
430
|
0
|
|
|
|
|
0
|
$encode_tag->(@_); |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
elsif ( $comment_info->{VERBATIM} ) { |
435
|
1
|
|
|
|
|
4
|
$encode_tag->(@_); |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
else { |
438
|
494
|
|
|
|
|
790
|
$callback_found_tag->[-2]->(@_); |
439
|
|
|
|
|
|
|
} |
440
|
161
|
|
|
|
|
840
|
}; |
441
|
161
|
|
|
|
|
248
|
push @$callback_found_tag, $callback; |
442
|
|
|
|
|
|
|
|
443
|
161
|
|
|
|
|
3905
|
my $arg = { |
444
|
|
|
|
|
|
|
fname => $fname, |
445
|
|
|
|
|
|
|
level => 0, |
446
|
|
|
|
|
|
|
line => 1, |
447
|
|
|
|
|
|
|
name => '', |
448
|
|
|
|
|
|
|
template => $template, |
449
|
|
|
|
|
|
|
token => '', |
450
|
|
|
|
|
|
|
open_or_close => undef, |
451
|
|
|
|
|
|
|
open => undef, |
452
|
|
|
|
|
|
|
open_close_map => \%open_close, |
453
|
|
|
|
|
|
|
start_close_re => qr{$start_close_re}, |
454
|
|
|
|
|
|
|
close_match => qr{close_re}, |
455
|
|
|
|
|
|
|
attr => {}, |
456
|
|
|
|
|
|
|
allowed_names => [], |
457
|
|
|
|
|
|
|
tags => [], |
458
|
|
|
|
|
|
|
close => undef, |
459
|
|
|
|
|
|
|
stack => [T_END], |
460
|
|
|
|
|
|
|
}; |
461
|
161
|
|
|
|
|
499
|
while (length $arg->{template}) { |
462
|
|
|
|
|
|
|
#warn Data::Dumper->Dump([\@tags], ['tags']); |
463
|
|
|
|
|
|
|
#print STDERR "TEXT: $template ($start_close_re)\n"; |
464
|
|
|
|
|
|
|
#print STDERR "TOKEN: '$arg->{token}'\n"; |
465
|
1068
|
|
|
|
|
822
|
my $found_tag = 0; |
466
|
1068
|
|
|
|
|
1129
|
$arg->{attr} = {}; |
467
|
|
|
|
|
|
|
MATCH_TAGS: { |
468
|
1068
|
100
|
|
|
|
1233
|
last MATCH_TAGS unless $self->find_start_of_tag($arg); |
|
1068
|
|
|
|
|
1530
|
|
469
|
|
|
|
|
|
|
# at this point we have a start of a tag. everything |
470
|
|
|
|
|
|
|
# that does not look like correct tag content generates |
471
|
|
|
|
|
|
|
# a die! |
472
|
519
|
|
|
|
|
759
|
my $re = $allowed_ident{$arg->{open_or_close}}; |
473
|
519
|
100
|
|
|
|
17875
|
if ($arg->{template} =~ s/^(($re)\s*)//) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
474
|
513
|
|
|
|
|
1119
|
$arg->{name} = uc $2; |
475
|
513
|
|
|
|
|
662
|
$arg->{token} .= $1; |
476
|
513
|
100
|
|
|
|
961
|
if ($arg->{name} eq '=') { $arg->{name} = 'VAR' } |
|
124
|
|
|
|
|
168
|
|
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
elsif ($comment_info->{NOPARSE}) { |
479
|
1
|
|
|
|
|
3
|
$callbacks_found_text->[0]->($self, $arg); |
480
|
1
|
|
|
|
|
1
|
last MATCH_TAGS; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
elsif ($comment_info->{VERBATIM}) { |
483
|
0
|
|
|
|
|
0
|
$encode_tag->($self, $arg); |
484
|
0
|
|
|
|
|
0
|
last MATCH_TAGS; |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
elsif ($comment_info->{COMMENT}) { |
487
|
1
|
|
|
|
|
2
|
last MATCH_TAGS; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
elsif ($self->get_strict) { |
490
|
|
|
|
|
|
|
$self->_error_wrong_tag_syntax( |
491
|
3
|
|
|
|
|
11
|
$arg, $arg->{template}, "Unknown tag" |
492
|
|
|
|
|
|
|
); |
493
|
0
|
|
|
|
|
0
|
last MATCH_TAGS; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
else { |
496
|
1
|
|
|
|
|
5
|
$arg->{template} =~ s/^(\w+)//; |
497
|
1
|
|
|
|
|
3
|
$arg->{token} .= $1; |
498
|
1
|
|
|
|
|
2
|
$callbacks_found_text->[0]->($self, $arg); |
499
|
1
|
|
|
|
|
1
|
last MATCH_TAGS; |
500
|
|
|
|
|
|
|
} |
501
|
|
|
|
|
|
|
#print STDERR "got ident $arg->{name} ('$arg->{template}')\n"; |
502
|
|
|
|
|
|
|
$arg->{allowed_names} |
503
|
513
|
|
|
|
|
1467
|
= $tagnames->{ $arg->{open_or_close} }->{ $arg->{name} }; |
504
|
513
|
100
|
66
|
|
|
1090
|
if ($arg->{name} eq 'PERL' && $self->get_perl) { |
505
|
4
|
50
|
|
|
|
9
|
last MATCH_TAGS unless $self->find_perlcode($arg); |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
else { |
508
|
509
|
50
|
|
|
|
907
|
last MATCH_TAGS unless $self->find_attributes($arg); |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
|
511
|
509
|
50
|
|
|
|
2286
|
if ($arg->{template} =~ s/^($arg->{close_match})//) { |
512
|
509
|
|
|
|
|
752
|
$arg->{close} = $1; |
513
|
509
|
|
|
|
|
633
|
$arg->{token} .= $1; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
else { |
516
|
0
|
|
|
|
|
0
|
$self->_error_wrong_tag_syntax( $arg, "" ); |
517
|
0
|
|
|
|
|
0
|
last MATCH_TAGS; |
518
|
|
|
|
|
|
|
} |
519
|
509
|
|
|
|
|
771
|
$found_tag = 1; |
520
|
|
|
|
|
|
|
} |
521
|
1061
|
100
|
|
|
|
5807
|
if ($found_tag) { |
|
|
50
|
|
|
|
|
|
522
|
509
|
|
|
|
|
740
|
my $pre_chomp = $self->get_chomp->[0]; |
523
|
509
|
|
|
|
|
493
|
my $attr = $arg->{attr}; |
524
|
509
|
100
|
|
|
|
799
|
$pre_chomp = $attr->{PRE_CHOMP} if exists $attr->{PRE_CHOMP}; |
525
|
509
|
|
|
|
|
626
|
my $post_chomp = $self->get_chomp->[1]; |
526
|
509
|
100
|
|
|
|
763
|
$post_chomp = $attr->{POST_CHOMP} if exists $attr->{POST_CHOMP}; |
527
|
509
|
100
|
100
|
|
|
362
|
if (@{$arg->{tags}} > 0 and $pre_chomp) { |
|
509
|
|
|
|
|
1878
|
|
528
|
3
|
|
|
|
|
11
|
my $text = $arg->{tags}->[-1]->get_text; |
529
|
3
|
50
|
|
|
|
11
|
if ($pre_chomp == CHOMP_ONE) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
530
|
0
|
|
|
|
|
0
|
$text =~ s/ +\z//; |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
elsif ($pre_chomp == CHOMP_COLLAPSE) { |
533
|
0
|
|
|
|
|
0
|
$text =~ s/\s+\z/ /; |
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
elsif ($pre_chomp == CHOMP_GREEDY) { |
536
|
3
|
|
|
|
|
10
|
$text =~ s/\s+\z//; |
537
|
|
|
|
|
|
|
} |
538
|
3
|
|
|
|
|
9
|
$arg->{tags}->[-1]->set_text($text); |
539
|
|
|
|
|
|
|
} |
540
|
509
|
100
|
100
|
|
|
1616
|
if (length $arg->{template} and $post_chomp) { |
541
|
7
|
100
|
|
|
|
18
|
if ($post_chomp == CHOMP_ONE) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
542
|
4
|
|
|
|
|
7
|
$arg->{template} =~ s/^ +//; |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
elsif ($post_chomp == CHOMP_COLLAPSE) { |
545
|
0
|
|
|
|
|
0
|
$arg->{template} =~ s/^\s+/ /; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
elsif ($post_chomp == CHOMP_GREEDY) { |
548
|
3
|
|
|
|
|
7
|
$arg->{template} =~ s/^\s+//; |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
#print STDERR "found tag $arg->{name}\n"; |
552
|
|
|
|
|
|
|
#my $test = $callback_found_tag->[-1]; |
553
|
|
|
|
|
|
|
#print STDERR "(found_tags: @$callback_found_tag) $test\n"; |
554
|
509
|
|
50
|
0
|
|
1192
|
( $callback_found_tag->[-1] || sub { } )->( |
555
|
|
|
|
|
|
|
$self, |
556
|
|
|
|
|
|
|
$arg, |
557
|
|
|
|
|
|
|
); |
558
|
|
|
|
|
|
|
#print STDERR "===== ($open, $line, $ident, $close)\n"; |
559
|
|
|
|
|
|
|
#warn Data::Dumper->Dump([\@tags], ['tags']); |
560
|
|
|
|
|
|
|
} |
561
|
|
|
|
|
|
|
elsif ($arg->{template} =~ s/^(.+?)(?=($start_close_re|\Z))//s) { |
562
|
552
|
|
|
|
|
1077
|
$arg->{token} .= $1; |
563
|
552
|
|
50
|
0
|
|
1321
|
($callbacks_found_text->[-1] || sub {} )->( |
564
|
|
|
|
|
|
|
$self, |
565
|
|
|
|
|
|
|
$arg, |
566
|
|
|
|
|
|
|
); |
567
|
|
|
|
|
|
|
#print "got no tag: '$arg->{token}'\n"; |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
} |
571
|
152
|
|
|
|
|
601
|
Scalar::Util::weaken($callback_found_tag); |
572
|
152
|
|
|
|
|
1554
|
$self->checkstack({ |
573
|
|
|
|
|
|
|
%$arg, name => T_END, open_or_close => CLOSING_TAG |
574
|
|
|
|
|
|
|
} ); |
575
|
151
|
|
|
|
|
452
|
return @{$arg->{tags} }; |
|
151
|
|
|
|
|
2871
|
|
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
36
|
|
|
36
|
|
14206
|
use HTML::Template::Compiled::Exception; |
|
36
|
|
|
|
|
59
|
|
|
36
|
|
|
|
|
27399
|
|
580
|
|
|
|
|
|
|
sub _error_wrong_tag_syntax { |
581
|
8
|
|
|
8
|
|
13
|
my ($self, $arg, $text, $add_info) = @_; |
582
|
8
|
|
|
|
|
21
|
my ($substr) = $text =~ m/^(.{0,10})/s; |
583
|
8
|
|
33
|
|
|
23
|
my $class = ref $self || $self; |
584
|
8
|
|
|
|
|
37
|
my $info = "$class : Syntax error in tag at $arg->{fname} :" |
585
|
|
|
|
|
|
|
. "$arg->{line} near '$arg->{token}$substr...'"; |
586
|
8
|
100
|
|
|
|
22
|
$info .= " $add_info" if defined $add_info; |
587
|
|
|
|
|
|
|
my $ex = HTML::Template::Compiled::Exception->new( |
588
|
|
|
|
|
|
|
text => $info, |
589
|
|
|
|
|
|
|
parser => $self, |
590
|
|
|
|
|
|
|
tokens => $arg->{tags}, |
591
|
8
|
|
|
|
|
47
|
near => $text, |
592
|
|
|
|
|
|
|
); |
593
|
8
|
|
|
|
|
311
|
croak $ex; |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
sub find_perlcode { |
597
|
4
|
|
|
4
|
0
|
4
|
my ($self, $arg) = @_; |
598
|
4
|
|
|
|
|
7
|
my $attr = $arg->{attr}; |
599
|
4
|
50
|
|
|
|
44
|
if ($arg->{template} =~ s{^ (.*?) |
600
|
|
|
|
|
|
|
(?=$arg->{close_match}) |
601
|
|
|
|
|
|
|
}{}xs) { |
602
|
4
|
|
|
|
|
9
|
$attr->{PERL} = "$1"; |
603
|
4
|
|
|
|
|
7
|
$arg->{token} .= $1; |
604
|
4
|
|
|
|
|
10
|
return 1; |
605
|
|
|
|
|
|
|
} |
606
|
0
|
|
|
|
|
0
|
return; |
607
|
|
|
|
|
|
|
} |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
sub find_attribute { |
610
|
462
|
|
|
462
|
0
|
468
|
my ($self, $arg, $re) = @_; |
611
|
462
|
|
|
|
|
359
|
my ($name, $var, $orig); |
612
|
|
|
|
|
|
|
#print STDERR "=====(($arg->{template}))\n"; |
613
|
462
|
100
|
|
|
|
9397
|
if ($arg->{template} =~ s/^(\s*($re)=)//i) { |
614
|
155
|
|
|
|
|
202
|
$name = "$2"; |
615
|
155
|
|
|
|
|
223
|
$orig .= $1; |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
#print STDERR "match '$$text' (?=$until|\\s)\n"; |
618
|
462
|
100
|
|
|
|
4154
|
if ($arg->{template} =~ s{^ (\s* (['"]) (.+?) \2 \s*) }{}x) { |
|
|
50
|
|
|
|
|
|
619
|
|
|
|
|
|
|
#print STDERR qq{matched $2$3$2\n}; |
620
|
113
|
|
|
|
|
161
|
$var = "$3"; |
621
|
113
|
|
|
|
|
166
|
$orig .= $1; |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
elsif ($arg->{template} =~ s{^ (\s* (\S+?) \s*) |
624
|
|
|
|
|
|
|
(?=$arg->{close_match} | \s) }{}x) { |
625
|
|
|
|
|
|
|
#print STDERR qq{matched <$2>\n}; |
626
|
349
|
|
|
|
|
451
|
$var = "$2"; |
627
|
349
|
|
|
|
|
494
|
$orig .= $1; |
628
|
|
|
|
|
|
|
} |
629
|
0
|
|
|
|
|
0
|
else { return } |
630
|
462
|
100
|
|
|
|
845
|
unless (defined $name) { |
631
|
307
|
|
|
|
|
315
|
$name = "NAME"; |
632
|
|
|
|
|
|
|
} |
633
|
462
|
|
|
|
|
1083
|
return ($name, $var, $orig); |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
{ |
637
|
|
|
|
|
|
|
my @map; |
638
|
|
|
|
|
|
|
$map[OPENING_TAG] = { |
639
|
|
|
|
|
|
|
ELSE => [ T_IF, T_UNLESS, T_ELSIF, T_IF_DEFINED ], |
640
|
|
|
|
|
|
|
T_CASE() => [T_SWITCH], |
641
|
|
|
|
|
|
|
}; |
642
|
|
|
|
|
|
|
$map[CLOSING_TAG] = { |
643
|
|
|
|
|
|
|
IF => [ T_IF, T_UNLESS, T_ELSE, T_IF_DEFINED ], |
644
|
|
|
|
|
|
|
T_IF_DEFINED() => [ T_ELSE, T_IF_DEFINED ], |
645
|
|
|
|
|
|
|
UNLESS => [T_UNLESS, T_ELSE, T_IF_DEFINED], |
646
|
|
|
|
|
|
|
ELSIF => [ T_IF, T_UNLESS, T_IF_DEFINED ], |
647
|
|
|
|
|
|
|
LOOP => [T_LOOP], |
648
|
|
|
|
|
|
|
WHILE => [T_WHILE], |
649
|
|
|
|
|
|
|
WITH => [T_WITH], |
650
|
|
|
|
|
|
|
T_SWITCH() => [T_SWITCH], |
651
|
|
|
|
|
|
|
T_END() => [T_END], |
652
|
|
|
|
|
|
|
}; |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub validate_stack { |
655
|
646
|
|
|
646
|
0
|
500
|
my ( $self, $arg ) = @_; |
656
|
646
|
100
|
|
|
|
2242
|
if (defined( my $allowed |
657
|
|
|
|
|
|
|
= $map[$arg->{open_or_close}]->{$arg->{name}})) { |
658
|
254
|
50
|
33
|
|
|
194
|
return 1 if @{ $arg->{stack} } == 0 and @$allowed == 0; |
|
254
|
|
|
|
|
649
|
|
659
|
|
|
|
|
|
|
die "Closing tag 'TMPL_$arg->{name}' does not have opening tag" |
660
|
|
|
|
|
|
|
. "at $arg->{fname} line $arg->{line}\n" |
661
|
254
|
50
|
|
|
|
233
|
unless @{ $arg->{stack} }; |
|
254
|
|
|
|
|
551
|
|
662
|
254
|
100
|
100
|
|
|
888
|
if ( $allowed->[0] eq T_END and $arg->{stack}->[-1] ne T_END ) { |
663
|
|
|
|
|
|
|
# we hit the end of the template but still have an opening tag to close |
664
|
1
|
|
|
|
|
47
|
die "Missing closing tag for '$arg->{stack}->[-1]' at" |
665
|
|
|
|
|
|
|
. "end of $arg->{fname} line $arg->{line}\n"; |
666
|
|
|
|
|
|
|
} |
667
|
253
|
|
|
|
|
404
|
for (@$allowed) { |
668
|
277
|
100
|
|
|
|
719
|
return 1 if $_ eq $arg->{stack}->[-1]; |
669
|
|
|
|
|
|
|
} |
670
|
2
|
|
|
|
|
354
|
croak "'TMPL_$arg->{name}' does not match opening tag ($arg->{stack}->[-1])" |
671
|
|
|
|
|
|
|
. "at $arg->{fname} line $arg->{line}\n"; |
672
|
|
|
|
|
|
|
} |
673
|
|
|
|
|
|
|
} |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
sub checkstack { |
676
|
646
|
|
|
646
|
0
|
591
|
my ( $self, $arg ) = @_; |
677
|
646
|
|
|
|
|
864
|
my $ok = $self->validate_stack($arg ); |
678
|
643
|
100
|
|
|
|
1178
|
if ($arg->{open_or_close} == OPENING_TAG) { |
|
|
50
|
|
|
|
|
|
679
|
391
|
100
|
|
|
|
445
|
if ( |
|
|
100
|
|
|
|
|
|
680
|
2737
|
|
|
|
|
3401
|
grep { $arg->{name} eq $_ } ( |
681
|
|
|
|
|
|
|
T_WITH, T_LOOP, T_WHILE, T_IF, T_UNLESS, T_SWITCH, T_IF_DEFINED |
682
|
|
|
|
|
|
|
) |
683
|
|
|
|
|
|
|
) { |
684
|
92
|
|
|
|
|
78
|
push @{ $arg->{stack} }, $arg->{name}; |
|
92
|
|
|
|
|
169
|
|
685
|
|
|
|
|
|
|
} |
686
|
|
|
|
|
|
|
elsif ($arg->{name} eq T_ELSE) { |
687
|
6
|
|
|
|
|
8
|
pop @{ $arg->{stack} }; |
|
6
|
|
|
|
|
8
|
|
688
|
6
|
|
|
|
|
7
|
push @{ $arg->{stack} }, T_ELSE; |
|
6
|
|
|
|
|
8
|
|
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
elsif ($arg->{open_or_close} == CLOSING_TAG) { |
692
|
252
|
100
|
|
|
|
300
|
if (grep { $arg->{name} eq $_ } ( |
|
1764
|
|
|
|
|
1943
|
|
693
|
|
|
|
|
|
|
T_IF, T_IF_DEFINED, T_UNLESS, T_WITH, T_LOOP, T_WHILE, T_SWITCH |
694
|
|
|
|
|
|
|
)) { |
695
|
89
|
|
|
|
|
83
|
pop @{ $arg->{stack} }; |
|
89
|
|
|
|
|
124
|
|
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
} |
698
|
643
|
|
|
|
|
611
|
return $ok; |
699
|
|
|
|
|
|
|
} |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
} |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
{ |
704
|
|
|
|
|
|
|
my $default_parser = __PACKAGE__->new; |
705
|
98
|
|
|
98
|
0
|
535
|
sub default { return bless [@$default_parser], __PACKAGE__ } |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
1; |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
__END__ |