File Coverage

blib/lib/Text/Template.pm
Criterion Covered Total %
statement 305 316 96.5
branch 124 140 88.5
condition 24 25 96.0
subroutine 37 39 94.8
pod 7 13 53.8
total 497 533 93.2


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             # Text::Template.pm
3             #
4             # Fill in `templates'
5             #
6             # Copyright 2013 M. J. Dominus.
7             # You may copy and distribute this program under the
8             # same terms as Perl itself.
9             # If in doubt, write to mjd-perl-template+@plover.com for a license.
10             #
11              
12             package Text::Template;
13             $Text::Template::VERSION = '1.59';
14             # ABSTRACT: Expand template text with embedded Perl
15              
16 20     20   190468 use strict;
  20         52  
  20         509  
17 20     20   86 use warnings;
  20         28  
  20         581  
18              
19             require 5.008;
20              
21 20     20   83 use base 'Exporter';
  20         31  
  20         5664  
22              
23             our @EXPORT_OK = qw(fill_in_file fill_in_string TTerror);
24             our $ERROR;
25              
26             my %GLOBAL_PREPEND = ('Text::Template' => '');
27              
28             sub Version {
29 0     0 1 0 $Text::Template::VERSION;
30             }
31              
32             sub _param {
33 1958     1958   2976 my ($k, %h) = @_;
34              
35 1958         3732 for my $kk ($k, "\u$k", "\U$k", "-$k", "-\u$k", "-\U$k") {
36 10595 100       27662 return $h{$kk} if exists $h{$kk};
37             }
38              
39 1611         3278 return undef;
40             }
41              
42             sub always_prepend {
43 3     3 0 2355 my $pack = shift;
44              
45 3         6 my $old = $GLOBAL_PREPEND{$pack};
46              
47 3         5 $GLOBAL_PREPEND{$pack} = shift;
48              
49 3         7 $old;
50             }
51              
52             {
53             my %LEGAL_TYPE;
54              
55             BEGIN {
56 20     20   71 %LEGAL_TYPE = map { $_ => 1 } qw(FILE FILEHANDLE STRING ARRAY);
  80         26825  
57             }
58              
59             sub new {
60 112     112 1 66637 my ($pack, %a) = @_;
61              
62 112   100     307 my $stype = uc(_param('type', %a) || "FILE");
63 112         244 my $source = _param('source', %a);
64 112         220 my $untaint = _param('untaint', %a);
65 112         221 my $prepend = _param('prepend', %a);
66 112         188 my $alt_delim = _param('delimiters', %a);
67 112         204 my $broken = _param('broken', %a);
68 112         199 my $encoding = _param('encoding', %a);
69              
70 112 100       210 unless (defined $source) {
71 2         9 require Carp;
72 2         291 Carp::croak("Usage: $ {pack}::new(TYPE => ..., SOURCE => ...)");
73             }
74              
75 110 100       239 unless ($LEGAL_TYPE{$stype}) {
76 1         5 require Carp;
77 1         86 Carp::croak("Illegal value `$stype' for TYPE parameter");
78             }
79              
80 109 100       400 my $self = {
81             TYPE => $stype,
82             PREPEND => $prepend,
83             UNTAINT => $untaint,
84             BROKEN => $broken,
85             ENCODING => $encoding,
86             (defined $alt_delim ? (DELIM => $alt_delim) : ())
87             };
88              
89             # Under 5.005_03, if any of $stype, $prepend, $untaint, or $broken
90             # are tainted, all the others become tainted too as a result of
91             # sharing the expression with them. We install $source separately
92             # to prevent it from acquiring a spurious taint.
93 109         167 $self->{SOURCE} = $source;
94              
95 109         172 bless $self => $pack;
96 109 100       192 return unless $self->_acquire_data;
97              
98 108         389 $self;
99             }
100             }
101              
102             # Convert template objects of various types to type STRING,
103             # in which the template data is embedded in the object itself.
104             sub _acquire_data {
105 216     216   261 my $self = shift;
106              
107 216         313 my $type = $self->{TYPE};
108              
109 216 100       412 if ($type eq 'STRING') {
    100          
    100          
    50          
110             # nothing necessary
111             }
112             elsif ($type eq 'FILE') {
113 10         24 my $data = _load_text($self->{SOURCE});
114 10 100       40 unless (defined $data) {
115              
116             # _load_text already set $ERROR
117 1         13 return undef;
118             }
119              
120 9 100 100     35 if ($self->{UNTAINT} && _is_clean($self->{SOURCE})) {
121 1         3 _unconditionally_untaint($data);
122             }
123              
124 9 100       21 if (defined $self->{ENCODING}) {
125 2         11 require Encode;
126 2         8 $data = Encode::decode($self->{ENCODING}, $data, &Encode::FB_CROAK);
127             }
128              
129 9         99 $self->{TYPE} = 'STRING';
130 9         16 $self->{FILENAME} = $self->{SOURCE};
131 9         17 $self->{SOURCE} = $data;
132             }
133             elsif ($type eq 'ARRAY') {
134 5         11 $self->{TYPE} = 'STRING';
135 5         6 $self->{SOURCE} = join '', @{ $self->{SOURCE} };
  5         16  
136             }
137             elsif ($type eq 'FILEHANDLE') {
138 8         14 $self->{TYPE} = 'STRING';
139 8         24 local $/;
140 8         12 my $fh = $self->{SOURCE};
141 8         182 my $data = <$fh>; # Extra assignment avoids bug in Solaris perl5.00[45].
142 8 100       32 if ($self->{UNTAINT}) {
143 1         3 _unconditionally_untaint($data);
144             }
145 8         33 $self->{SOURCE} = $data;
146             }
147             else {
148             # This should have been caught long ago, so it represents a
149             # drastic `can't-happen' sort of failure
150 0         0 my $pack = ref $self;
151 0         0 die "Can only acquire data for $pack objects of subtype STRING, but this is $type; aborting";
152             }
153              
154 215         477 $self->{DATA_ACQUIRED} = 1;
155             }
156              
157             sub source {
158 7     7 0 8 my $self = shift;
159              
160 7 50       14 $self->_acquire_data unless $self->{DATA_ACQUIRED};
161              
162 7         15 return $self->{SOURCE};
163             }
164              
165             sub set_source_data {
166 7     7 0 14 my ($self, $newdata, $type) = @_;
167              
168 7         11 $self->{SOURCE} = $newdata;
169 7         8 $self->{DATA_ACQUIRED} = 1;
170 7   50     15 $self->{TYPE} = $type || 'STRING';
171              
172 7         11 1;
173             }
174              
175             sub compile {
176 107     107 1 155 my $self = shift;
177              
178 107 50       224 return 1 if $self->{TYPE} eq 'PREPARSED';
179              
180 107 50       162 return undef unless $self->_acquire_data;
181              
182 107 50       222 unless ($self->{TYPE} eq 'STRING') {
183 0         0 my $pack = ref $self;
184              
185             # This should have been caught long ago, so it represents a
186             # drastic `can't-happen' sort of failure
187 0         0 die "Can only compile $pack objects of subtype STRING, but this is $self->{TYPE}; aborting";
188             }
189              
190 107         128 my @tokens;
191 107   100     331 my $delim_pats = shift() || $self->{DELIM};
192              
193 107         167 my ($t_open, $t_close) = ('{', '}');
194 107         121 my $DELIM; # Regex matches a delimiter if $delim_pats
195              
196 107 100       163 if (defined $delim_pats) {
197 21         33 ($t_open, $t_close) = @$delim_pats;
198 21         45 $DELIM = "(?:(?:\Q$t_open\E)|(?:\Q$t_close\E))";
199 21         296 @tokens = split /($DELIM|\n)/, $self->{SOURCE};
200             }
201             else {
202 86         771 @tokens = split /(\\\\(?=\\*[{}])|\\[{}]|[{}\n])/, $self->{SOURCE};
203             }
204              
205 107         170 my $state = 'TEXT';
206 107         124 my $depth = 0;
207 107         129 my $lineno = 1;
208 107         122 my @content;
209 107         141 my $cur_item = '';
210 107         119 my $prog_start;
211              
212 107         207 while (@tokens) {
213 659         809 my $t = shift @tokens;
214              
215 659 100       987 next if $t eq '';
216              
217 571 100 100     1923 if ($t eq $t_open) { # Brace or other opening delimiter
    100 100        
    100          
    100          
    100          
218 127 100       194 if ($depth == 0) {
219 118 100       298 push @content, [ $state, $cur_item, $lineno ] if $cur_item ne '';
220 118         170 $cur_item = '';
221 118         140 $state = 'PROG';
222 118         143 $prog_start = $lineno;
223             }
224             else {
225 9         13 $cur_item .= $t;
226             }
227 127         209 $depth++;
228             }
229             elsif ($t eq $t_close) { # Brace or other closing delimiter
230 137         149 $depth--;
231 137 100       272 if ($depth < 0) {
    100          
232 10         21 $ERROR = "Unmatched close brace at line $lineno";
233 10         41 return undef;
234             }
235             elsif ($depth == 0) {
236 118 50       286 push @content, [ $state, $cur_item, $prog_start ] if $cur_item ne '';
237 118         167 $state = 'TEXT';
238 118         214 $cur_item = '';
239             }
240             else {
241 9         21 $cur_item .= $t;
242             }
243             }
244             elsif (!$delim_pats && $t eq '\\\\') { # precedes \\\..\\\{ or \\\..\\\}
245 6         9 $cur_item .= '\\';
246             }
247             elsif (!$delim_pats && $t =~ /^\\([{}])$/) { # Escaped (literal) brace?
248 6         20 $cur_item .= $1;
249             }
250             elsif ($t eq "\n") { # Newline
251 44         49 $lineno++;
252 44         76 $cur_item .= $t;
253             }
254             else { # Anything else
255 251         585 $cur_item .= $t;
256             }
257             }
258              
259 97 50       208 if ($state eq 'PROG') {
    50          
260 0         0 $ERROR = "End of data inside program text that began at line $prog_start";
261 0         0 return undef;
262             }
263             elsif ($state eq 'TEXT') {
264 97 100       192 push @content, [ $state, $cur_item, $lineno ] if $cur_item ne '';
265             }
266             else {
267 0         0 die "Can't happen error #1";
268             }
269              
270 97         146 $self->{TYPE} = 'PREPARSED';
271 97         170 $self->{SOURCE} = \@content;
272              
273 97         306 1;
274             }
275              
276             sub prepend_text {
277 116     116 0 155 my $self = shift;
278              
279 116         145 my $t = $self->{PREPEND};
280              
281 116 100       179 unless (defined $t) {
282 112         202 $t = $GLOBAL_PREPEND{ ref $self };
283 112 100       184 unless (defined $t) {
284 10         15 $t = $GLOBAL_PREPEND{'Text::Template'};
285             }
286             }
287              
288 116 50       243 $self->{PREPEND} = $_[1] if $#_ >= 1;
289              
290 116         211 return $t;
291             }
292              
293             sub fill_in {
294 130     130 1 25770 my ($fi_self, %fi_a) = @_;
295              
296 130 100       300 unless ($fi_self->{TYPE} eq 'PREPARSED') {
297 90         175 my $delims = _param('delimiters', %fi_a);
298 90 100       185 my @delim_arg = (defined $delims ? ($delims) : ());
299 90 100       175 $fi_self->compile(@delim_arg)
300             or return undef;
301             }
302              
303 120         284 my $fi_varhash = _param('hash', %fi_a);
304 120         228 my $fi_package = _param('package', %fi_a);
305 120   100     308 my $fi_broken = _param('broken', %fi_a) || $fi_self->{BROKEN} || \&_default_broken;
306 120   100     251 my $fi_broken_arg = _param('broken_arg', %fi_a) || [];
307 120         216 my $fi_safe = _param('safe', %fi_a);
308 120         214 my $fi_ofh = _param('output', %fi_a);
309 120   100     229 my $fi_filename = _param('filename', %fi_a) || $fi_self->{FILENAME} || 'template';
310 120         228 my $fi_strict = _param('strict', %fi_a);
311 120         202 my $fi_prepend = _param('prepend', %fi_a);
312              
313 120         149 my $fi_eval_package;
314 120         151 my $fi_scrub_package = 0;
315              
316 120 100       233 unless (defined $fi_prepend) {
317 116         244 $fi_prepend = $fi_self->prepend_text;
318             }
319              
320 120 100       313 if (defined $fi_safe) {
    100          
    100          
321 12         26 $fi_eval_package = 'main';
322             }
323             elsif (defined $fi_package) {
324 31         49 $fi_eval_package = $fi_package;
325             }
326             elsif (defined $fi_varhash) {
327 21         48 $fi_eval_package = _gensym();
328 21         31 $fi_scrub_package = 1;
329             }
330             else {
331 56         99 $fi_eval_package = caller;
332             }
333              
334 120         168 my @fi_varlist;
335             my $fi_install_package;
336              
337 120 100       248 if (defined $fi_varhash) {
338 31 100       66 if (defined $fi_package) {
    100          
339 9         11 $fi_install_package = $fi_package;
340             }
341             elsif (defined $fi_safe) {
342 1         5 $fi_install_package = $fi_safe->root;
343             }
344             else {
345 21         44 $fi_install_package = $fi_eval_package; # The gensymmed one
346             }
347 31         84 @fi_varlist = _install_hash($fi_varhash => $fi_install_package);
348 31 100       80 if ($fi_strict) {
349 2 50       14 $fi_prepend = "use vars qw(@fi_varlist);$fi_prepend" if @fi_varlist;
350 2         6 $fi_prepend = "use strict;$fi_prepend";
351             }
352             }
353              
354 120 100 100     283 if (defined $fi_package && defined $fi_safe) {
355 20     20   146 no strict 'refs';
  20         39  
  20         1769  
356              
357             # Big fat magic here: Fix it so that the user-specified package
358             # is the default one available in the safe compartment.
359 2         3 *{ $fi_safe->root . '::' } = \%{ $fi_package . '::' }; # LOD
  2         6  
  2         5  
360             }
361              
362 120         204 my $fi_r = '';
363 120         141 my $fi_item;
364 120         134 foreach $fi_item (@{ $fi_self->{SOURCE} }) {
  120         255  
365 276         609 my ($fi_type, $fi_text, $fi_lineno) = @$fi_item;
366 276 100       518 if ($fi_type eq 'TEXT') {
    50          
367 139         324 $fi_self->append_text_to_output(
368             text => $fi_text,
369             handle => $fi_ofh,
370             out => \$fi_r,
371             type => $fi_type,);
372             }
373             elsif ($fi_type eq 'PROG') {
374 20     20   110 no strict;
  20         45  
  20         1145  
375              
376 137         257 my $fi_lcomment = "#line $fi_lineno $fi_filename";
377 137         304 my $fi_progtext = "package $fi_eval_package; $fi_prepend;\n$fi_lcomment\n$fi_text;\n;";
378 137         172 my $fi_res;
379 137         164 my $fi_eval_err = '';
380              
381 137 100       236 if ($fi_safe) {
382 20     20   116 no strict;
  20         41  
  20         471  
383 20     20   95 no warnings;
  20         37  
  20         1895  
384              
385 15         61 $fi_safe->reval(q{undef $OUT});
386 15         5969 $fi_res = $fi_safe->reval($fi_progtext);
387 15         5379 $fi_eval_err = $@;
388 15         30 my $OUT = $fi_safe->reval('$OUT');
389 15 100       5242 $fi_res = $OUT if defined $OUT;
390             }
391             else {
392 20     20   112 no strict;
  20         39  
  20         503  
393 20     20   97 no warnings;
  20         36  
  20         13416  
394              
395 122         135 my $OUT;
396 122     1   7958 $fi_res = eval $fi_progtext;
  1     1   6  
  1     1   2  
  1     1   32  
  1         7  
  1         1  
  1         72  
  1         6  
  1         1  
  1         37  
  1         6  
  1         2  
  1         31  
397 114         1068 $fi_eval_err = $@;
398 114 100       291 $fi_res = $OUT if defined $OUT;
399             }
400              
401             # If the value of the filled-in text really was undef,
402             # change it to an explicit empty string to avoid undefined
403             # value warnings later.
404 129 100       251 $fi_res = '' unless defined $fi_res;
405              
406 129 100       221 if ($fi_eval_err) {
407 11         29 $fi_res = $fi_broken->(
408             text => $fi_text,
409             error => $fi_eval_err,
410             lineno => $fi_lineno,
411             arg => $fi_broken_arg,);
412 11 100       56 if (defined $fi_res) {
413 10         42 $fi_self->append_text_to_output(
414             text => $fi_res,
415             handle => $fi_ofh,
416             out => \$fi_r,
417             type => $fi_type,);
418             }
419             else {
420 1         6 return $fi_r; # Undefined means abort processing
421             }
422             }
423             else {
424 118         334 $fi_self->append_text_to_output(
425             text => $fi_res,
426             handle => $fi_ofh,
427             out => \$fi_r,
428             type => $fi_type,);
429             }
430             }
431             else {
432 0         0 die "Can't happen error #2";
433             }
434             }
435              
436 111 100       236 _scrubpkg($fi_eval_package) if $fi_scrub_package;
437              
438 111 100       539 defined $fi_ofh ? 1 : $fi_r;
439             }
440              
441             sub append_text_to_output {
442 267     267 0 796 my ($self, %arg) = @_;
443              
444 267 100       708 if (defined $arg{handle}) {
445 2         2 print { $arg{handle} } $arg{text};
  2         15  
446             }
447             else {
448 265         285 ${ $arg{out} } .= $arg{text};
  265         497  
449             }
450              
451 267         654 return;
452             }
453              
454             sub fill_this_in {
455 6     6 1 2806 my ($pack, $text) = splice @_, 0, 2;
456              
457 6 50       18 my $templ = $pack->new(TYPE => 'STRING', SOURCE => $text, @_)
458             or return undef;
459              
460 6 50       18 $templ->compile or return undef;
461              
462 6         15 my $result = $templ->fill_in(@_);
463              
464 6         46 $result;
465             }
466              
467             sub fill_in_string {
468 4     4 1 3195 my $string = shift;
469              
470 4         11 my $package = _param('package', @_);
471              
472 4 100       16 push @_, 'package' => scalar(caller) unless defined $package;
473              
474 4         14 Text::Template->fill_this_in($string, @_);
475             }
476              
477             sub fill_in_file {
478 2     2 1 1257 my $fn = shift;
479 2 50       11 my $templ = Text::Template->new(TYPE => 'FILE', SOURCE => $fn, @_) or return undef;
480              
481 2 50       4 $templ->compile or return undef;
482              
483 2         5 my $text = $templ->fill_in(@_);
484              
485 2         10 $text;
486             }
487              
488             sub _default_broken {
489 5     5   21 my %a = @_;
490              
491 5         10 my $prog_text = $a{text};
492 5         7 my $err = $a{error};
493 5         8 my $lineno = $a{lineno};
494              
495 5         11 chomp $err;
496              
497             # $err =~ s/\s+at .*//s;
498 5         19 "Program fragment delivered error ``$err''";
499             }
500              
501             sub _load_text {
502 10     10   13 my $fn = shift;
503              
504 10 100       319 open my $fh, '<', $fn or do {
505 1         15 $ERROR = "Couldn't open file $fn: $!";
506 1         5 return undef;
507             };
508              
509 9         43 local $/;
510              
511 9         321 <$fh>;
512             }
513              
514             sub _is_clean {
515 8     8   2129 my $z;
516              
517 8         10 eval { ($z = join('', @_)), eval '#' . substr($z, 0, 0); 1 } # LOD
  8         172  
  5         24  
518             }
519              
520             sub _unconditionally_untaint {
521 4     4   551 for (@_) {
522 4         21 ($_) = /(.*)/s;
523             }
524             }
525              
526             {
527             my $seqno = 0;
528              
529             sub _gensym {
530 21     21   61 __PACKAGE__ . '::GEN' . $seqno++;
531             }
532              
533             sub _scrubpkg {
534 22     22   444 my $s = shift;
535              
536 22         95 $s =~ s/^Text::Template:://;
537              
538 20     20   146 no strict 'refs';
  20         67  
  20         2758  
539              
540 22         71 my $hash = $Text::Template::{ $s . "::" };
541              
542 22         53 foreach my $key (keys %$hash) {
543 39         78 undef $hash->{$key};
544             }
545              
546 22         117 %$hash = ();
547              
548 22         169 delete $Text::Template::{ $s . "::" };
549             }
550             }
551              
552             # Given a hashful of variables (or a list of such hashes)
553             # install the variables into the specified package,
554             # overwriting whatever variables were there before.
555             sub _install_hash {
556 31     31   46 my $hashlist = shift;
557 31         70 my $dest = shift;
558              
559 31 100       115 if (UNIVERSAL::isa($hashlist, 'HASH')) {
560 29         48 $hashlist = [$hashlist];
561             }
562              
563 31         47 my @varlist;
564              
565 31         53 for my $hash (@$hashlist) {
566 34         80 for my $name (keys %$hash) {
567 50         84 my $val = $hash->{$name};
568              
569 20     20   116 no strict 'refs';
  20         50  
  20         554  
570 20     20   100 no warnings 'redefine';
  20         53  
  20         4411  
571              
572 50         62 local *SYM = *{"$ {dest}::$name"};
  50         276  
573              
574 50 100       114 if (!defined $val) {
    100          
575 2         2 delete ${"$ {dest}::"}{$name};
  2         6  
576 2         20 my $match = qr/^.\Q$name\E$/;
577 2         7 @varlist = grep { $_ !~ $match } @varlist;
  1         8  
578             }
579             elsif (ref $val) {
580 10         25 *SYM = $val;
581 10         15 push @varlist, do {
582 10 100       33 if (UNIVERSAL::isa($val, 'ARRAY')) { '@' }
  1 50       3  
583 0         0 elsif (UNIVERSAL::isa($val, 'HASH')) { '%' }
584 9         30 else { '$' }
585             }
586             . $name;
587             }
588             else {
589 38         125 *SYM = \$val;
590 38         95 push @varlist, '$' . $name;
591             }
592             }
593             }
594              
595 31         104 @varlist;
596             }
597              
598 0     0 0 0 sub TTerror { $ERROR }
599              
600             1;
601              
602             __END__