line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CGI::AppBuilder; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Perl standard modules |
4
|
1
|
|
|
1
|
|
26033
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
42
|
|
5
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
34
|
|
6
|
1
|
|
|
1
|
|
3606
|
use Getopt::Std; |
|
1
|
|
|
|
|
75
|
|
|
1
|
|
|
|
|
93
|
|
7
|
1
|
|
|
1
|
|
1222
|
use POSIX qw(strftime); |
|
1
|
|
|
|
|
8959
|
|
|
1
|
|
|
|
|
11
|
|
8
|
1
|
|
|
1
|
|
6807
|
use CGI; |
|
1
|
|
|
|
|
34401
|
|
|
1
|
|
|
|
|
9
|
|
9
|
1
|
|
|
1
|
|
1906
|
use CGI::Carp qw(fatalsToBrowser warningsToBrowser); |
|
1
|
|
|
|
|
4308
|
|
|
1
|
|
|
|
|
10
|
|
10
|
1
|
|
|
1
|
|
1862
|
use CGI::Pretty ':standard'; |
|
1
|
|
|
|
|
2442
|
|
|
1
|
|
|
|
|
8
|
|
11
|
1
|
|
|
1
|
|
8169
|
use CGI::AppBuilder::Config qw(:all); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use CGI::AppBuilder::Message qw(:all); |
13
|
|
|
|
|
|
|
use CGI::AppBuilder::Log qw(:all); |
14
|
|
|
|
|
|
|
use CGI::AppBuilder::Form qw(:all); |
15
|
|
|
|
|
|
|
use CGI::AppBuilder::Table qw(:all); |
16
|
|
|
|
|
|
|
use CGI::AppBuilder::Header qw(:all); |
17
|
|
|
|
|
|
|
use CGI::AppBuilder::Frame qw(:all); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
our $VERSION = 0.12; |
20
|
|
|
|
|
|
|
warningsToBrowser(1); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
require Exporter; |
23
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
24
|
|
|
|
|
|
|
our @EXPORT = qw(start_app end_app); |
25
|
|
|
|
|
|
|
our @IMPORT_OK = (@CGI::AppBuilder::Config::EXPORT_OK, |
26
|
|
|
|
|
|
|
@CGI::AppBuilder::Message::EXPORT_OK, |
27
|
|
|
|
|
|
|
@CGI::AppBuilder::Log::EXPORT_OK, |
28
|
|
|
|
|
|
|
@CGI::AppBuilder::Form::EXPORT_OK, |
29
|
|
|
|
|
|
|
@CGI::AppBuilder::Table::EXPORT_OK, |
30
|
|
|
|
|
|
|
@CGI::AppBuilder::Header::EXPORT_OK, |
31
|
|
|
|
|
|
|
@CGI::AppBuilder::Frame::EXPORT_OK |
32
|
|
|
|
|
|
|
); |
33
|
|
|
|
|
|
|
our @EXPORT_OK = (qw(start_app end_app),@IMPORT_OK); |
34
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
35
|
|
|
|
|
|
|
app => [qw(start_app end_app build_html_header)], |
36
|
|
|
|
|
|
|
config => [@CGI::AppBuilder::Config::EXPORT_OK], |
37
|
|
|
|
|
|
|
echo_msg => [@CGI::AppBuilder::Message::EXPORT_OK], |
38
|
|
|
|
|
|
|
log => [@CGI::AppBuilder::Log::EXPORT_OK], |
39
|
|
|
|
|
|
|
form => [@CGI::AppBuilder::Form::EXPORT_OK], |
40
|
|
|
|
|
|
|
table => [@CGI::AppBuilder::Table::EXPORT_OK], |
41
|
|
|
|
|
|
|
header => [@CGI::AppBuilder::Header::EXPORT_OK], |
42
|
|
|
|
|
|
|
frame => [@CGI::AppBuilder::Frame::EXPORT_OK], |
43
|
|
|
|
|
|
|
all => [@EXPORT_OK, @IMPORT_OK] |
44
|
|
|
|
|
|
|
); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 NAME |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
CGI::AppBuilder - CGI Application Builder |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head1 SYNOPSIS |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
use CGI::AppBuilder; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $cg = CGI::AppBuilder->new('ifn', 'my_init.cfg', 'opt', 'vhS:a:'); |
55
|
|
|
|
|
|
|
my $ar = $cg->get_inputs; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head1 DESCRIPTION |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
There are already many application builders out there. Why you need |
60
|
|
|
|
|
|
|
another one? Well, if you are already familiar with CGI::Builder or |
61
|
|
|
|
|
|
|
CGI::Application, this one will provide some useful methods to you to |
62
|
|
|
|
|
|
|
read your configuration file and pre-process your templates. |
63
|
|
|
|
|
|
|
Please read on. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=cut |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head3 new (ifn => 'file.cfg', opt => 'hvS:') |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Input variables: |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$ifn - input/initial file name. |
72
|
|
|
|
|
|
|
$opt - options for Getopt::Std |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Variables used or routines called: |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
None |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
How to use: |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
my $ca = new CGI::AppBuilder; # or |
81
|
|
|
|
|
|
|
my $ca = CGI::AppBuilder->new; # or |
82
|
|
|
|
|
|
|
my $ca = CGI::AppBuilder->new(ifn=>'file.cfg',opt=>'hvS:'); # or |
83
|
|
|
|
|
|
|
my $ca = CGI::AppBuilder->new('ifn', 'file.cfg','opt','hvS:'); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
Return: new empty or initialized CGI::AppBuilder object. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
This method constructs a Perl object and capture any parameters if |
88
|
|
|
|
|
|
|
specified. It creates and defaults the following variables: |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
$self->{ifn} = "" |
91
|
|
|
|
|
|
|
$self->{opt} = 'hvS:'; |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=cut |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub new { |
96
|
|
|
|
|
|
|
my $caller = shift; |
97
|
|
|
|
|
|
|
my $caller_is_obj = ref($caller); |
98
|
|
|
|
|
|
|
my $class = $caller_is_obj || $caller; |
99
|
|
|
|
|
|
|
my $self = bless {}, $class; |
100
|
|
|
|
|
|
|
my %arg = @_; # convert rest of inputs into hash array |
101
|
|
|
|
|
|
|
foreach my $k ( keys %arg ) { |
102
|
|
|
|
|
|
|
if ($caller_is_obj) { |
103
|
|
|
|
|
|
|
$self->{$k} = $caller->{$k}; |
104
|
|
|
|
|
|
|
} else { |
105
|
|
|
|
|
|
|
$self->{$k} = $arg{$k}; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
$self->{ifn} = "" if ! exists $arg{ifn}; |
109
|
|
|
|
|
|
|
$self->{opt} = 'hvS:' if ! exists $arg{opt}; |
110
|
|
|
|
|
|
|
return $self; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head3 start_app ($prg,$arg,$nhh) |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Input variables: |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
$prg - program name |
118
|
|
|
|
|
|
|
$arg - array ref for arguments - %ARGV |
119
|
|
|
|
|
|
|
$nhh - no html header pre-printed |
120
|
|
|
|
|
|
|
1 - no HTML header is set in any circumstance |
121
|
|
|
|
|
|
|
0 - HTML header will be set when it is possible |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
Variables used or routines called: |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
build_html_header - build HTML header array |
126
|
|
|
|
|
|
|
Debug::EchoMessage |
127
|
|
|
|
|
|
|
echo_msg - echo messages |
128
|
|
|
|
|
|
|
start_log - start and write message log |
129
|
|
|
|
|
|
|
CGI::Getopt |
130
|
|
|
|
|
|
|
get_inputs - read input file and/or CGI form inputs |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
How to use: |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
my ($q, $ar, $ar_log) = $self->start_app($0,\@ARGV); |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Return: ($q,$ar,$ar_log) where |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
$q - a CGI object |
140
|
|
|
|
|
|
|
$ar - hash ref containing parameters from input file and/or |
141
|
|
|
|
|
|
|
CGI form inputs and the following elements: |
142
|
|
|
|
|
|
|
ifn - initial file name |
143
|
|
|
|
|
|
|
opt - command input options |
144
|
|
|
|
|
|
|
cfg - configuratoin array |
145
|
|
|
|
|
|
|
html_header - HTML header parameters (hash ref) |
146
|
|
|
|
|
|
|
msg - contain message hash |
147
|
|
|
|
|
|
|
$ar_log - hash ref containing log information |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
This method performs the following tasks: |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
1) initial a CGI object |
152
|
|
|
|
|
|
|
2) read initial file if specified or search for a default file |
153
|
|
|
|
|
|
|
(the same as $prg with .ini extension) and save the file name |
154
|
|
|
|
|
|
|
to $ar->{ifn}. |
155
|
|
|
|
|
|
|
3) define message level |
156
|
|
|
|
|
|
|
4) start HTML header and body using I and I |
157
|
|
|
|
|
|
|
if they are defined. |
158
|
|
|
|
|
|
|
5) parse CGI form inputs and combine them with parameters defined |
159
|
|
|
|
|
|
|
in initial file |
160
|
|
|
|
|
|
|
6) read configuration file ($prg.cfg) if it exists and save the |
161
|
|
|
|
|
|
|
array to $ar->{cfg} |
162
|
|
|
|
|
|
|
7) prepare log record if write log is enabled |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
It checks the parameters read from initial file for page_title, |
165
|
|
|
|
|
|
|
page_style, page_author, page_meta, top_nav, bottom_nav, and js_src. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=cut |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub start_app { |
170
|
|
|
|
|
|
|
my $s = shift; |
171
|
|
|
|
|
|
|
my ($prg, $ar_arg, $nhh) = @_; |
172
|
|
|
|
|
|
|
my $args = ($ar_arg && $ar_arg =~ /ARRAY/)?(join " ", @$ar_arg):''; |
173
|
|
|
|
|
|
|
my $ifn = $prg; $ifn =~ s/\.(\w+)$/\.ini/; |
174
|
|
|
|
|
|
|
my $cfg = $prg; $cfg =~ s/\.(\w+)$/\.cfg/; |
175
|
|
|
|
|
|
|
my $opt = 'a:v:hS:'; |
176
|
|
|
|
|
|
|
my ($q, $ar); |
177
|
|
|
|
|
|
|
# 0. need to decide it is in verbose mode or not |
178
|
|
|
|
|
|
|
my $web_flag = 0; |
179
|
|
|
|
|
|
|
if (exists $ENV{HTTP_HOST} || exists $ENV{QUERY_STRING}) { |
180
|
|
|
|
|
|
|
$q = CGI->new; |
181
|
|
|
|
|
|
|
my $v1 = $q->param('v'); |
182
|
|
|
|
|
|
|
my $v2 = $q->Vars->{v}; |
183
|
|
|
|
|
|
|
if ((defined($v1) && $v1) || (defined($v2) && $v2)) { |
184
|
|
|
|
|
|
|
$web_flag = 1; |
185
|
|
|
|
|
|
|
print $q->header("text/html") if !$nhh; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
# |
189
|
|
|
|
|
|
|
# 1-3,5. Read initial file |
190
|
|
|
|
|
|
|
($q,$ar) = $s->get_inputs($ifn,$opt); |
191
|
|
|
|
|
|
|
$s->echo_msg(" += Starting application..."); |
192
|
|
|
|
|
|
|
$s->echo_msg(" ++ Reading initial file $ifn...") if -f $ifn; |
193
|
|
|
|
|
|
|
$s->echo_msg(" + Initial file - $ifn: not found.") if !-f $ifn; |
194
|
|
|
|
|
|
|
# if user has defined messages in the initial file, we need to |
195
|
|
|
|
|
|
|
# convert it into hash. |
196
|
|
|
|
|
|
|
$ar->{msg} = eval $ar->{msg} if exists $ar->{msg}; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# 4. start HTML header |
199
|
|
|
|
|
|
|
my %ar_hdr = $s->build_html_header($q, $ar); |
200
|
|
|
|
|
|
|
$ar->{html_header} = \%ar_hdr if ! exists $ar->{html_header}; |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# 5. start the HTML page |
203
|
|
|
|
|
|
|
if (!$nhh && ( |
204
|
|
|
|
|
|
|
exists $ENV{HTTP_HOST} || exists $ENV{QUERY_STRING})) { |
205
|
|
|
|
|
|
|
print $q->header("text/html") if ! $web_flag; |
206
|
|
|
|
|
|
|
print $q->start_html(%ar_hdr), "\n"; |
207
|
|
|
|
|
|
|
print $ar->{top_nav} if exists $ar->{top_nav} && $ar->{top_nav}; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# 6. read configuration file |
211
|
|
|
|
|
|
|
if (-f $cfg) { |
212
|
|
|
|
|
|
|
$s->echo_msg(" ++ Reading config file $cfg..."); |
213
|
|
|
|
|
|
|
$ar->{cfg} = $s->read_cfg_file($cfg); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# 7. set log array |
217
|
|
|
|
|
|
|
my ($ds,$log_dir,$log_brf, $log_dtl) = ('/',"","",""); |
218
|
|
|
|
|
|
|
$log_dir = (exists ${$ar}{log_dir})?${$ar}{log_dir}:'.'; |
219
|
|
|
|
|
|
|
my $lgf = $ifn; $lgf =~ s/\.\w+//; $lgf =~ s/.*[\/\\](\w+)$/$1/; |
220
|
|
|
|
|
|
|
my $tmp = strftime "%Y%m%d", localtime time; |
221
|
|
|
|
|
|
|
$log_brf = join $ds, $log_dir, "${lgf}_brief.log"; |
222
|
|
|
|
|
|
|
$log_dtl = join $ds, $log_dir, "${lgf}_${tmp}.log"; |
223
|
|
|
|
|
|
|
my ($lfh_brf,$lfh_dtl,$txt,$ar_log) = ("","","",""); |
224
|
|
|
|
|
|
|
if (exists ${$ar}{write_log} && ${$ar}{write_log}) { |
225
|
|
|
|
|
|
|
$ar_log = $s->start_log($log_dtl,$log_brf,"",$args,2); |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
$s->echo_msg($ar,5); |
228
|
|
|
|
|
|
|
$s->echo_msg($ar_log,5); |
229
|
|
|
|
|
|
|
return ($q,$ar,$ar_log); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=head3 end_app ($q, $ar, $ar_log, $nhh) |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
Input variables: |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
$q - CGI object |
237
|
|
|
|
|
|
|
$ar - array ref for parameters |
238
|
|
|
|
|
|
|
$ar_log - hash ref for log record |
239
|
|
|
|
|
|
|
$nhh - no html header pre-printed |
240
|
|
|
|
|
|
|
1 - no HTML is printed in any circumstance |
241
|
|
|
|
|
|
|
0 - HTML header will be printed when it is possible |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
Variables used or routines called: |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
Debug::EchoMessage |
246
|
|
|
|
|
|
|
echo_msg - echo messages |
247
|
|
|
|
|
|
|
end_log - start and write message log |
248
|
|
|
|
|
|
|
set_param - get a parameter from hash array |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
How to use: |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
my ($q, $ar, $ar_log) = $self->start_app($0,\@ARGV); |
253
|
|
|
|
|
|
|
$self->end_app($q, $ar, $ar_log); |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Return: none |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
This method performs the following tasks: |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
1) ends HTML document |
260
|
|
|
|
|
|
|
2) writes log records to log files |
261
|
|
|
|
|
|
|
3) close database connection if it finds DB handler in {dbh} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=cut |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
sub end_app { |
266
|
|
|
|
|
|
|
my $s = shift; |
267
|
|
|
|
|
|
|
my ($q, $ar, $ar_log, $nhh) = @_; |
268
|
|
|
|
|
|
|
if (exists ${$ar}{write_log} && ${$ar}{write_log}) { |
269
|
|
|
|
|
|
|
$s->end_log($ar_log); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
my $dbh = $s->set_param('dbh', $ar); |
272
|
|
|
|
|
|
|
$dbh->disconnect() if $dbh; |
273
|
|
|
|
|
|
|
if (exists $ENV{HTTP_HOST} || exists $ENV{QUERY_STRING}) { |
274
|
|
|
|
|
|
|
print $ar->{bottom_nav} if exists $ar->{bottom_nav} && !$nhh; |
275
|
|
|
|
|
|
|
print $q->end_html if !$nhh; |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
1; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head1 HISTORY |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=over 4 |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=item * Version 0.10 |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
This version is to extract out the app methods from CGI::Getopt class. |
288
|
|
|
|
|
|
|
It was too much for CGI::Getopt to include the start_app, end_app, |
289
|
|
|
|
|
|
|
build_html_header, and disp_form methods. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
0.11 Rewrote start_app method so that content-type can be changed. |
292
|
|
|
|
|
|
|
0.12 Moved disp_form to CGI::AppBuilder::Form, |
293
|
|
|
|
|
|
|
moved build_html_header to CGI::AppBuilder::Header, and |
294
|
|
|
|
|
|
|
imported all the methods in sub-classes into this class. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=item * Version 0.20 |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=cut |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=head1 SEE ALSO (some of docs that I check often) |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Oracle::Loader, Oracle::Trigger, CGI::Getopt, File::Xcopy, |
303
|
|
|
|
|
|
|
CGI::AppBuilder, CGI::AppBuilder::Message, CGI::AppBuilder::Log, |
304
|
|
|
|
|
|
|
CGI::AppBuilder::Config, etc. |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head1 AUTHOR |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Copyright (c) 2005 Hanming Tu. All rights reserved. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
This package is free software and is provided "as is" without express |
311
|
|
|
|
|
|
|
or implied warranty. It may be used, redistributed and/or modified |
312
|
|
|
|
|
|
|
under the terms of the Perl Artistic License (see |
313
|
|
|
|
|
|
|
http://www.perl.com/perl/misc/Artistic.html) |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=cut |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
|