File Coverage

bin/wdrender
Criterion Covered Total %
statement 77 96 80.2
branch 13 26 50.0
condition 4 11 36.3
subroutine 14 14 100.0
pod n/a
total 108 147 73.4


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             #
3             # This file is part of WebDyne.
4             #
5             # This software is copyright (c) 2026 by Andrew Speer .
6             #
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             #
10             # Full license text is available at:
11             #
12             #
13             #
14              
15              
16             #
17             # Compile and/or show compiled version of WebDyne HTML scripts
18             #
19             package main;
20              
21              
22             # Compiler pragma
23             #
24 2     2   11053 use strict qw(vars);
  2         4  
  2         118  
25 2     2   11 use vars qw($VERSION);
  2         4  
  2         129  
26 2     2   11 use warnings;
  2         5  
  2         94  
27              
28              
29             # Use the base module
30             #
31 2     2   1201 use WebDyne::Util;
  2         7  
  2         22  
32              
33              
34             # Other external modules
35             #
36 2     2   2156 use WebDyne;
  2         7  
  2         115  
37 2     2   1121 use WebDyne::Request::Fake;
  2         8  
  2         83  
38 2     2   1625 use Getopt::Long;
  2         25394  
  2         10  
39 2     2   1541 use Pod::Usage;
  2         106830  
  2         265  
40 2     2   17 use IO::File;
  2         3  
  2         252  
41 2     2   40 use File::Spec;
  2         5  
  2         102  
42 2     2   951 use FindBin qw($RealBin $Script);
  2         2550  
  2         258  
43 2     2   990 use URI::Escape;
  2         3781  
  2         138  
44              
45              
46             # Error handling and environment
47             #
48 2     2   13 use Carp;
  2         5  
  2         5774  
49 2         406978 local $SIG{__DIE__}=\&Carp::confess;
50              
51              
52             # Version Info, must be all one line for MakeMaker, CPAN.
53             #
54 2         8 $VERSION='2.075';
55              
56              
57             # Run main
58             #
59 2 50       4 exit ${&main(\@ARGV) || die errdump()};
  2         27  
60              
61             #===================================================================================================
62              
63             sub main {
64              
65              
66             # Get argv array ref
67             #
68 2     2   6 my $argv_ar=shift();
69              
70              
71             # Defaul options
72             #
73             my %opt=(
74              
75 2   50     26 handler => $ENV{'WebDyneHandler'} || 'WebDyne',
76             error => 'text',
77             header => 0,
78             warn => 0,
79              
80             );
81              
82              
83             # Get command line options
84             #
85 2 50       16 GetOptions(
86             \%opt,
87             'help|?',
88             'handler=s',
89             'status=s',
90             'header!',
91             'warn!',
92             'error=s',
93             'headers_out|header_out=s@',
94             'headers_in|header_in=s@',
95             'outfile=s',
96             'repeat|r|num|n=s',
97             'loop',
98             'get=s@',
99             'delay=i',
100             'man',
101             'version'
102             ) || pod2usage(2);
103 2 50       3096 pod2usage(-verbose => 99, -sections => 'SYNOPSIS|OPTIONS', -exitval => 1) if $opt{'help'};
104 2 50       9 pod2usage(-verbose => 2) if $opt{'man'};
105 2 50       7 $opt{'version'} && do {
106 0         0 print "$Script version: $VERSION\n";
107 0         0 print "WebDyne version: $WebDyne::VERSION ($WebDyne::VERSION_GIT_SHA)\n";
108 0         0 exit 0
109             };
110              
111              
112             # Is dest file set ? If so open
113             #
114 2         4 my $dest_fh;
115 2 50       8 if (my $dest_fn=$opt{'outfile'}) {
116 0   0     0 $dest_fh=IO::File->new($dest_fn, O_CREAT | O_TRUNC | O_WRONLY) ||
117             return err("unable to open file $dest_fn for output, $!");
118 0         0 $opt{'select'}=$dest_fh;
119             }
120              
121              
122             # Get srce file, add to options
123             #
124 2   33     3 my $srce_fn=shift(@{$argv_ar}) ||
125             pod2usage("$Script: no source file specified !");
126 2 50       131 (-f $srce_fn) ||
127             pod2usage("$Script: input file not found !");
128              
129              
130             # Split out header in/out arrays as Request::Fake uses hash to hold them (should be array one day)
131             #
132 2         6 my ($header_out_ar, $header_in_ar)=map {delete $opt{$_}} qw(
  4         13  
133             headers_out
134             headers_in
135             );
136            
137            
138             # Simulate a GET request with parameters if supplied
139             #
140 2 50       9 if (my $query_opt_ar=delete $opt{'get'}) {
141 0         0 my @query_string;
142 0         0 my @query_opt=map { split(/[;&]/) } @{$query_opt_ar};
  0         0  
  0         0  
143 0         0 foreach my $query_opt (@query_opt) {
144 0         0 my ($key, $value)=split(/=/, $query_opt);
145 0         0 push @query_string, join('=', map { uri_escape($_) } ($key, $value));
  0         0  
146             }
147 0         0 my $query_string=join('&', @query_string );
148             ## no critic (Variables::RequireLocalizedPunctuationVars)
149 0         0 $ENV{'QUERY_STRING'}=$query_string;
150 0         0 $ENV{'REQUEST_METHOD'}='GET';
151             ## use critic
152             }
153              
154              
155             # Get new request object
156             #
157 2         4 LOOP: while (1) {
158 2   50     16 for (1..($opt{'repeat'} || 1)) {
159              
160             # Get new request handler
161             #
162 2   50     31 my $r=WebDyne::Request::Fake->new(
163              
164             filename => $srce_fn,
165             %opt
166              
167             #select => $dest_fh,
168             #status => $opt{'status'},
169              
170             ) || return err();
171            
172              
173             # Set headers
174             #
175 2         6 foreach my $header_out (@{$header_out_ar}) {
  2         5  
176 0         0 my ($k, $v)=split(/\s*:\s*/, $header_out);
177 0         0 $r->headers_out($k, $v);
178             }
179 2         4 foreach my $header_in (@{$header_in_ar}) {
  2         4  
180 1         6 my ($k, $v)=split(/\s*:\s*/, $header_in);
181 1         4 $r->headers_in($k, $v);
182             }
183              
184              
185             # Get handler
186             #
187 2         5 my $handler=$opt{'handler'};
188              
189              
190             # Load up whichever handler we are using
191             #
192 2         6 (my $handler_pm = $handler) =~ s{::}{/}g;
193 2         5 $handler_pm.='.pm';
194 2 50       4 eval {require $handler_pm} ||
  2         20  
195             return err("$Script: unable to load handler $handler, $@");
196              
197              
198             # Set text errors only
199             #
200 2 50       9 $WebDyne::Err::WEBDYNE_ERROR_TEXT=1 if ($opt{'error'} eq 'text');
201              
202              
203             # Set header, warning output
204             #
205             #$r->notes('noheader', $opt{'header'} ? 0 : 1);
206             #$r->notes('nowarn', $opt{'warn'} ? 0 : 1);
207              
208              
209             # Run it and display results, or any error generated
210             #
211 2 50       19 defined($handler->handler($r)) || return err();
212 2         9 print $/;
213              
214            
215             # If looking for leak
216             #
217             #my $gladiator_ar=Devel::Gladiator::walk_arena();
218              
219              
220             # Manual cleanup
221             #
222 2         11 $r->DESTROY();
223            
224            
225             # Leak detection
226             #
227             #print("SV: ", scalar @{$gladiator_ar}, "\n") if $opt{'leak'};
228             #@{$gladiator_ar} = ();
229            
230             # Delay (presumably to test caching code)
231             #
232 2 50       10 if (my $delay=$opt{'delay'}) {
233 0         0 sleep $delay
234             }
235              
236             }
237              
238 2 50       9 last LOOP unless $opt{'loop'};
239             }
240              
241              
242             # Done, return success
243             #
244 2           return \0;
245              
246             }
247              
248              
249             __END__