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.61';
14             # ABSTRACT: Expand template text with embedded Perl
15              
16 20     20   207274 use strict;
  20         69  
  20         555  
17 20     20   88 use warnings;
  20         36  
  20         620  
18              
19             require 5.008;
20              
21 20     20   91 use base 'Exporter';
  20         29  
  20         6100  
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   3037 my ($k, %h) = @_;
34              
35 1958         3643 for my $kk ($k, "\u$k", "\U$k", "-$k", "-\u$k", "-\U$k") {
36 10595 100       17393 return $h{$kk} if exists $h{$kk};
37             }
38              
39 1611         3256 return undef;
40             }
41              
42             sub always_prepend {
43 3     3 0 2671 my $pack = shift;
44              
45 3         6 my $old = $GLOBAL_PREPEND{$pack};
46              
47 3         6 $GLOBAL_PREPEND{$pack} = shift;
48              
49 3         8 $old;
50             }
51              
52             {
53             my %LEGAL_TYPE;
54              
55             BEGIN {
56 20     20   86 %LEGAL_TYPE = map { $_ => 1 } qw(FILE FILEHANDLE STRING ARRAY);
  80         27856  
57             }
58              
59             sub new {
60 112     112 1 49043 my ($pack, %a) = @_;
61              
62 112   100     372 my $stype = uc(_param('type', %a) || "FILE");
63 112         264 my $source = _param('source', %a);
64 112         220 my $untaint = _param('untaint', %a);
65 112         217 my $prepend = _param('prepend', %a);
66 112         225 my $alt_delim = _param('delimiters', %a);
67 112         215 my $broken = _param('broken', %a);
68 112         210 my $encoding = _param('encoding', %a);
69              
70 112 100       238 unless (defined $source) {
71 2         11 require Carp;
72 2         303 Carp::croak("Usage: $ {pack}::new(TYPE => ..., SOURCE => ...)");
73             }
74              
75 110 100       229 unless ($LEGAL_TYPE{$stype}) {
76 1         7 require Carp;
77 1         99 Carp::croak("Illegal value `$stype' for TYPE parameter");
78             }
79              
80 109 100       435 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         193 $self->{SOURCE} = $source;
94              
95 109         176 bless $self => $pack;
96 109 100       207 return unless $self->_acquire_data;
97              
98 108         503 $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   278 my $self = shift;
106              
107 216         355 my $type = $self->{TYPE};
108              
109 216 100       426 if ($type eq 'STRING') {
    100          
    100          
    50          
110             # nothing necessary
111             }
112             elsif ($type eq 'FILE') {
113 10         32 my $data = _load_text($self->{SOURCE});
114 10 100       40 unless (defined $data) {
115              
116             # _load_text already set $ERROR
117 1         18 return undef;
118             }
119              
120 9 100 100     40 if ($self->{UNTAINT} && _is_clean($self->{SOURCE})) {
121 1         3 _unconditionally_untaint($data);
122             }
123              
124 9 100       26 if (defined $self->{ENCODING}) {
125 2         18 require Encode;
126 2         15 $data = Encode::decode($self->{ENCODING}, $data, &Encode::FB_CROAK);
127             }
128              
129 9         114 $self->{TYPE} = 'STRING';
130 9         17 $self->{FILENAME} = $self->{SOURCE};
131 9         21 $self->{SOURCE} = $data;
132             }
133             elsif ($type eq 'ARRAY') {
134 5         7 $self->{TYPE} = 'STRING';
135 5         7 $self->{SOURCE} = join '', @{ $self->{SOURCE} };
  5         15  
136             }
137             elsif ($type eq 'FILEHANDLE') {
138 8         13 $self->{TYPE} = 'STRING';
139 8         26 local $/;
140 8         12 my $fh = $self->{SOURCE};
141 8         233 my $data = <$fh>; # Extra assignment avoids bug in Solaris perl5.00[45].
142 8 100       33 if ($self->{UNTAINT}) {
143 1         3 _unconditionally_untaint($data);
144             }
145 8         36 $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         492 $self->{DATA_ACQUIRED} = 1;
155             }
156              
157             sub source {
158 7     7 0 9 my $self = shift;
159              
160 7 50       18 $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 17 my ($self, $newdata, $type) = @_;
167              
168 7         13 $self->{SOURCE} = $newdata;
169 7         8 $self->{DATA_ACQUIRED} = 1;
170 7   50     17 $self->{TYPE} = $type || 'STRING';
171              
172 7         15 1;
173             }
174              
175             sub compile {
176 107     107 1 169 my $self = shift;
177              
178 107 50       232 return 1 if $self->{TYPE} eq 'PREPARSED';
179              
180 107 50       186 return undef unless $self->_acquire_data;
181              
182 107 50       225 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         122 my @tokens;
191 107   100     338 my $delim_pats = shift() || $self->{DELIM};
192              
193 107         177 my ($t_open, $t_close) = ('{', '}');
194 107         122 my $DELIM; # Regex matches a delimiter if $delim_pats
195              
196 107 100       181 if (defined $delim_pats) {
197 21         33 ($t_open, $t_close) = @$delim_pats;
198 21         79 $DELIM = "(?:(?:\Q$t_open\E)|(?:\Q$t_close\E))";
199 21         365 @tokens = split /($DELIM|\n)/, $self->{SOURCE};
200             }
201             else {
202 86         803 @tokens = split /(\\\\(?=\\*[{}])|\\[{}]|[{}\n])/, $self->{SOURCE};
203             }
204              
205 107         175 my $state = 'TEXT';
206 107         132 my $depth = 0;
207 107         137 my $lineno = 1;
208 107         130 my @content;
209 107         136 my $cur_item = '';
210 107         125 my $prog_start;
211              
212 107         220 while (@tokens) {
213 659         807 my $t = shift @tokens;
214              
215 659 100       988 next if $t eq '';
216              
217 571 100 100     1884 if ($t eq $t_open) { # Brace or other opening delimiter
    100 100        
    100          
    100          
    100          
218 127 100       199 if ($depth == 0) {
219 118 100       325 push @content, [ $state, $cur_item, $lineno ] if $cur_item ne '';
220 118         171 $cur_item = '';
221 118         148 $state = 'PROG';
222 118         142 $prog_start = $lineno;
223             }
224             else {
225 9         13 $cur_item .= $t;
226             }
227 127         188 $depth++;
228             }
229             elsif ($t eq $t_close) { # Brace or other closing delimiter
230 137         158 $depth--;
231 137 100       332 if ($depth < 0) {
    100          
232 10         22 $ERROR = "Unmatched close brace at line $lineno";
233 10         42 return undef;
234             }
235             elsif ($depth == 0) {
236 118 50       325 push @content, [ $state, $cur_item, $prog_start ] if $cur_item ne '';
237 118         190 $state = 'TEXT';
238 118         221 $cur_item = '';
239             }
240             else {
241 9         14 $cur_item .= $t;
242             }
243             }
244             elsif (!$delim_pats && $t eq '\\\\') { # precedes \\\..\\\{ or \\\..\\\}
245 6         11 $cur_item .= '\\';
246             }
247             elsif (!$delim_pats && $t =~ /^\\([{}])$/) { # Escaped (literal) brace?
248 6         16 $cur_item .= $1;
249             }
250             elsif ($t eq "\n") { # Newline
251 44         45 $lineno++;
252 44         93 $cur_item .= $t;
253             }
254             else { # Anything else
255 251         530 $cur_item .= $t;
256             }
257             }
258              
259 97 50       252 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       232 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         189 $self->{TYPE} = 'PREPARSED';
271 97         159 $self->{SOURCE} = \@content;
272              
273 97         300 1;
274             }
275              
276             sub prepend_text {
277 116     116 0 162 my $self = shift;
278              
279 116         155 my $t = $self->{PREPEND};
280              
281 116 100       206 unless (defined $t) {
282 112         211 $t = $GLOBAL_PREPEND{ ref $self };
283 112 100       181 unless (defined $t) {
284 10         16 $t = $GLOBAL_PREPEND{'Text::Template'};
285             }
286             }
287              
288 116 50       248 $self->{PREPEND} = $_[1] if $#_ >= 1;
289              
290 116         212 return $t;
291             }
292              
293             sub fill_in {
294 130     130 1 17360 my ($fi_self, %fi_a) = @_;
295              
296 130 100       327 unless ($fi_self->{TYPE} eq 'PREPARSED') {
297 90         174 my $delims = _param('delimiters', %fi_a);
298 90 100       191 my @delim_arg = (defined $delims ? ($delims) : ());
299 90 100       192 $fi_self->compile(@delim_arg)
300             or return undef;
301             }
302              
303 120         271 my $fi_varhash = _param('hash', %fi_a);
304 120         235 my $fi_package = _param('package', %fi_a);
305 120   100     247 my $fi_broken = _param('broken', %fi_a) || $fi_self->{BROKEN} || \&_default_broken;
306 120   100     229 my $fi_broken_arg = _param('broken_arg', %fi_a) || [];
307 120         250 my $fi_safe = _param('safe', %fi_a);
308 120         216 my $fi_ofh = _param('output', %fi_a);
309 120   100     211 my $fi_filename = _param('filename', %fi_a) || $fi_self->{FILENAME} || 'template';
310 120         239 my $fi_strict = _param('strict', %fi_a);
311 120         213 my $fi_prepend = _param('prepend', %fi_a);
312              
313 120         158 my $fi_eval_package;
314 120         180 my $fi_scrub_package = 0;
315              
316 120 100       219 unless (defined $fi_prepend) {
317 116         245 $fi_prepend = $fi_self->prepend_text;
318             }
319              
320 120 100       315 if (defined $fi_safe) {
    100          
    100          
321 12         30 $fi_eval_package = 'main';
322             }
323             elsif (defined $fi_package) {
324 31         50 $fi_eval_package = $fi_package;
325             }
326             elsif (defined $fi_varhash) {
327 21         51 $fi_eval_package = _gensym();
328 21         31 $fi_scrub_package = 1;
329             }
330             else {
331 56         110 $fi_eval_package = caller;
332             }
333              
334 120         166 my @fi_varlist;
335             my $fi_install_package;
336              
337 120 100       252 if (defined $fi_varhash) {
338 31 100       154 if (defined $fi_package) {
    100          
339 9         12 $fi_install_package = $fi_package;
340             }
341             elsif (defined $fi_safe) {
342 1         7 $fi_install_package = $fi_safe->root;
343             }
344             else {
345 21         53 $fi_install_package = $fi_eval_package; # The gensymmed one
346             }
347 31         92 @fi_varlist = _install_hash($fi_varhash => $fi_install_package);
348 31 100       74 if ($fi_strict) {
349 2 50       7 $fi_prepend = "use vars qw(@fi_varlist);$fi_prepend" if @fi_varlist;
350 2         4 $fi_prepend = "use strict;$fi_prepend";
351             }
352             }
353              
354 120 100 100     304 if (defined $fi_package && defined $fi_safe) {
355 20     20   244 no strict 'refs';
  20         43  
  20         1852  
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         2 *{ $fi_safe->root . '::' } = \%{ $fi_package . '::' }; # LOD
  2         7  
  2         3  
360             }
361              
362 120         205 my $fi_r = '';
363 120         139 my $fi_item;
364 120         146 foreach $fi_item (@{ $fi_self->{SOURCE} }) {
  120         234  
365 276         489 my ($fi_type, $fi_text, $fi_lineno) = @$fi_item;
366 276 100       516 if ($fi_type eq 'TEXT') {
    50          
367 139         334 $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   123 no strict;
  20         35  
  20         1218  
375              
376 137         329 my $fi_lcomment = "#line $fi_lineno $fi_filename";
377 137         326 my $fi_progtext = "package $fi_eval_package; $fi_prepend;\n$fi_lcomment\n$fi_text;\n;";
378 137         166 my $fi_res;
379 137         186 my $fi_eval_err = '';
380              
381 137 100       209 if ($fi_safe) {
382 20     20   109 no strict;
  20         36  
  20         487  
383 20     20   109 no warnings;
  20         36  
  20         2072  
384              
385 15         94 $fi_safe->reval(q{undef $OUT});
386 15         6608 $fi_res = $fi_safe->reval($fi_progtext);
387 15         5574 $fi_eval_err = $@;
388 15         41 my $OUT = $fi_safe->reval('$OUT');
389 15 100       5200 $fi_res = $OUT if defined $OUT;
390             }
391             else {
392 20     20   122 no strict;
  20         36  
  20         546  
393 20     20   112 no warnings;
  20         34  
  20         14102  
394              
395 122         137 my $OUT;
396 122     1   8351 $fi_res = eval $fi_progtext;
  1     1   8  
  1     1   2  
  1     1   39  
  1         5  
  1         2  
  1         83  
  1         6  
  1         2  
  1         29  
  1         5  
  1         1  
  1         42  
397 114         1105 $fi_eval_err = $@;
398 114 100       269 $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       254 $fi_res = '' unless defined $fi_res;
405              
406 129 100       256 if ($fi_eval_err) {
407 11         36 $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       64 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         4 return $fi_r; # Undefined means abort processing
421             }
422             }
423             else {
424 118         357 $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       251 _scrubpkg($fi_eval_package) if $fi_scrub_package;
437              
438 111 100       618 defined $fi_ofh ? 1 : $fi_r;
439             }
440              
441             sub append_text_to_output {
442 267     267 0 812 my ($self, %arg) = @_;
443              
444 267 100       507 if (defined $arg{handle}) {
445 2         4 print { $arg{handle} } $arg{text};
  2         24  
446             }
447             else {
448 265         299 ${ $arg{out} } .= $arg{text};
  265         511  
449             }
450              
451 267         648 return;
452             }
453              
454             sub fill_this_in {
455 6     6 1 1006 my ($pack, $text) = splice @_, 0, 2;
456              
457 6 50       21 my $templ = $pack->new(TYPE => 'STRING', SOURCE => $text, @_)
458             or return undef;
459              
460 6 50       19 $templ->compile or return undef;
461              
462 6         24 my $result = $templ->fill_in(@_);
463              
464 6         43 $result;
465             }
466              
467             sub fill_in_string {
468 4     4 1 3465 my $string = shift;
469              
470 4         11 my $package = _param('package', @_);
471              
472 4 100       18 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 1564 my $fn = shift;
479 2 50       12 my $templ = Text::Template->new(TYPE => 'FILE', SOURCE => $fn, @_) or return undef;
480              
481 2 50       5 $templ->compile or return undef;
482              
483 2         6 my $text = $templ->fill_in(@_);
484              
485 2         10 $text;
486             }
487              
488             sub _default_broken {
489 5     5   25 my %a = @_;
490              
491 5         13 my $prog_text = $a{text};
492 5         11 my $err = $a{error};
493 5         9 my $lineno = $a{lineno};
494              
495 5         19 chomp $err;
496              
497             # $err =~ s/\s+at .*//s;
498 5         22 "Program fragment delivered error ``$err''";
499             }
500              
501             sub _load_text {
502 10     10   17 my $fn = shift;
503              
504 10 100       393 open my $fh, '<', $fn or do {
505 1         26 $ERROR = "Couldn't open file $fn: $!";
506 1         7 return undef;
507             };
508              
509 9         45 local $/;
510              
511 9         364 <$fh>;
512             }
513              
514             sub _is_clean {
515 8     8   1901 my $z;
516              
517 8         11 eval { ($z = join('', @_)), eval '#' . substr($z, 0, 0); 1 } # LOD
  8         169  
  5         24  
518             }
519              
520             sub _unconditionally_untaint {
521 4     4   511 for (@_) {
522 4         52 ($_) = /(.*)/s;
523             }
524             }
525              
526             {
527             my $seqno = 0;
528              
529             sub _gensym {
530 21     21   55 __PACKAGE__ . '::GEN' . $seqno++;
531             }
532              
533             sub _scrubpkg {
534 22     22   483 my $s = shift;
535              
536 22         96 $s =~ s/^Text::Template:://;
537              
538 20     20   150 no strict 'refs';
  20         85  
  20         2835  
539              
540 22         74 my $hash = $Text::Template::{ $s . "::" };
541              
542 22         58 foreach my $key (keys %$hash) {
543 39         82 undef $hash->{$key};
544             }
545              
546 22         111 %$hash = ();
547              
548 22         181 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   44 my $hashlist = shift;
557 31         42 my $dest = shift;
558              
559 31 100       112 if (UNIVERSAL::isa($hashlist, 'HASH')) {
560 29         52 $hashlist = [$hashlist];
561             }
562              
563 31         42 my @varlist;
564              
565 31         66 for my $hash (@$hashlist) {
566 34         82 for my $name (keys %$hash) {
567 50         92 my $val = $hash->{$name};
568              
569 20     20   121 no strict 'refs';
  20         45  
  20         560  
570 20     20   104 no warnings 'redefine';
  20         44  
  20         4704  
571              
572 50         76 local *SYM = *{"$ {dest}::$name"};
  50         327  
573              
574 50 100       131 if (!defined $val) {
    100          
575 2         3 delete ${"$ {dest}::"}{$name};
  2         6  
576 2         17 my $match = qr/^.\Q$name\E$/;
577 2         6 @varlist = grep { $_ !~ $match } @varlist;
  1         8  
578             }
579             elsif (ref $val) {
580 10         17 *SYM = $val;
581 10         14 push @varlist, do {
582 10 100       35 if (UNIVERSAL::isa($val, 'ARRAY')) { '@' }
  1 50       3  
583 0         0 elsif (UNIVERSAL::isa($val, 'HASH')) { '%' }
584 9         36 else { '$' }
585             }
586             . $name;
587             }
588             else {
589 38         51 *SYM = \$val;
590 38         104 push @varlist, '$' . $name;
591             }
592             }
593             }
594              
595 31         102 @varlist;
596             }
597              
598 0     0 0 0 sub TTerror { $ERROR }
599              
600             1;
601              
602             __END__