File Coverage

blib/lib/LoadHtml.pm
Criterion Covered Total %
statement 22 684 3.2
branch 0 274 0.0
condition 0 89 0.0
subroutine 8 39 20.5
pod 9 29 31.0
total 39 1115 3.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             LoadHtml - Dynamic HTML Generation Library
4              
5             =head1 SYNOPSIS
6              
7             #!/usr/bin/perl
8              
9             use LoadHtml;
10             print "Content-type: text/html", "\n";
11             &loadhtml('mytemplate_file.html',
12             -ascalararg => 'Display this string',
13             -anarrayarg => ['string1', 'string2', 'string3'],
14             -ahasharg => {'key1' => 10, 'key2' => 20, 'key3' => 30},
15             -amatrix => [[1, 2, 3], [4, 5, 6]]
16             );
17              
18             =head1 DESCRIPTION AND EXAMPLES
19              
20             The LoadHtml Home Page
21              
22             LoadHtml - Dynamic HTML Generation Library, by Jim Turner (turnerjw784 att yahoo .dot. com).
23             LoadHtml is a Perl library to enable Perl CGI programs to dynamically generate HTML pages from HTML page templates. LoadHtml includes the following special features:
24              
25             o I) Special, nestable HTML control statements (IF-THEN-ELSE, LOOP, INCLUDE, SELECTLIST, etc.)!
26             o II) HTML templates can be valid stand-alone HTML pages (with default values) for rapid prototyping.
27             o III) Perl code and variables can be optionally embedded or prohibited (for security reasons) on a page-by-page basis.
28             o IV) HTML pages can be generated and later displayed or saved using the "buildhtml" or "dohtml" functions.
29             o V) Easy, dynamic table, select, checkbox and radio-button construct- creation using Perl variables, lists and hashes.
30             o VII) Multiple ways to drive loops of HTML generation (by arrays, hashes, and traditional Perl/C FOR loops, ie. "1 to 100 by 5".
31              
32             LoadHtml is written completely in Perl, a modern, high-performance scripting language. CGI web applications are completely portable across all platforms which support Perl and CGI, including Unix and Windows.
33              
34             Click for System Requirements.
35             I) Overview / User-callable Function List.
36             The following functions are user-callable:
37              
38             &loadhtml($htmlfile,@args)
39             my $htmlstring = &buildhtml($htmlfile,@args)
40             my $htmlstring = &dohtml($htmltemplate_string,@args)
41             &AllowEvals(1|0)
42             &set_poc($poc_name)
43             &SetRegices()
44             &SetListSeperator($separator_string)
45             &SetHtmlHome($htmlhome, $roothtmlhome, $hrefhtmlhome, $hrefcase)
46             &loadhtml_package($package_name)
47              
48             The Perl CGI program calls loadhtml() when it is ready to generate and display an HTML page. The 1st argument is the path and file-name of the html template file to be used to generate the page. The remaining arguments are the data values to be substituted in the html page based on special HTML codes within the template page before the final page is displayed. When loadhtml is called, the template html file is loaded and parsed, all argument/parameter substitutions are made, all dynamic html is generated, and the final html is sent to the browser to be displayed. NOTE: It is the calling program's responisibility to print any needed HTML headers BEFORE calling loadhtml.
49              
50             By default, embedded perl code and variables in HTML templates are not evaluated for security reasons. To enable loadhtml to process these, first call "AllowEvals(1)". To turn back off, call "AllowEvals(0)".
51              
52             Call "set_poc" at the beginning of your CGI script to set a point-of-contact name to be displayed on any error screens generated by LoadHtml.
53              
54             By default, any Perl list arguments passed to loadhtml, where the corresponding html code in the template file is not within a "LOOP" or "SELECTLIST" construct; will print out all values of the list separated by a comma, followed by a space. Call "SetListSeperator" to change this string to something else. Within the "LOOP" and "SELECTLIST" constructs, html is dynamically generated for each element within the resulting list.
55             II) Basic Parameter Substitution:
56             loadhtml is called with the 1st argument being the filename of the HTML template file to load. Each subsequent argument corresponds to a data-value to be added to the HTML via parameter substitution. The simplest parameter substitution is accomplished by placing the argument number preceeded by a colon in the desired location for the corresponding data-value argument in the HTML template file. For example, if an HTML template file named "myhtml.htm" in directory "/usr/htdocs/" looked like the following:
57              
58            
59            
Roses are :1, violets are :2.
60            
61              
62             The following call to loadhtml would supply the proper values:
63              
64             loadhtml('/usr/htdocs/myhtml.htm','red','blue');
65              
66             and would display the following HTML page:
67              
68            
69            
Roses are red, violets are blue.
70            
71              
72             ":1" is replaced by the 1st argument after the file-name, and ":2" with the second one.
73              
74             NOTE: It is now possible and preferrable to call loadhtml with NAMED parameters as follows:
75              
76             The above example using Named Parameters:
77              
78            
79            
Roses are , violets are blue normally.
80            
81              
82             The following call to loadhtml would supply the proper values:
83              
84             loadhtml('/usr/htdocs/myhtml.htm', -roses => 'red', -violets => 'blue');
85              
86             and would display the same results. NOTE: If data is not substituted using named parameters, try enclosing each "-parametername" part in single quotes. Also, the format ":{name}" is used in lieu of ":number" in the HTML whenever a value is to be substituted OUTSIDE of a tag, OR within the 'value=":{name}"' part of a tag. Otherwise (within tags), just use the format ":name".
87              
88             NOTE: In the above example, we show "roses" as a single, unmatched tag. "violets" is shown as a matching tag (note the colon before the closeing >). The text in between ("blue normally") is the default text and is shown if the page is not browsed via LoadHtml.
89              
90             Now, suppose we want the HTML page to function as a stand-alone page without being called by a CGI script, to demo to a customer before writing the script, you could write:
91              
92            
93            
Roses are <:1:>red<:/1>, violets are <:violets:>blue<:/violets>.
94            
95              
96             This would display the same results as the previous example (note the mixing of numbered and named parameters), if the page is loaded stand-alone directly into the browser, but, if called with:
97              
98             loadhtml('/usr/htdocs/myhtml.htm','here', -violets => 'there');
99              
100             would produce the following dynamically-generated page:
101              
102            
103            
Roses are here, violets are there.
104            
105              
106             If no default values are desired, the template file could be written as:
107              
108            
109            
Roses are , violets are .
110            
111              
112             If a different default value is desired, as when the page is loaded via LoadHtml, but without a value for that specific argument, the template file could be written as:
113              
114            
115            
Roses are <:roses=pink:>red<:/roses>, violets are <:violets=violet:>blue<:/violets>.
116            
117              
118             Now if LoadHtml is called as:
119              
120             loadhtml('/usr/htdocs/myhtml.htm', -roses => 'scarlet');
121              
122             The following page would display:
123              
124            
125            
Roses are scarlet, violets are violet.
126            
127            
128             Formatting
129              
130             LoadHtml also supports the "printf" function familiar to C and Perl programmers for formatting parameter as they are displayed. If this is not sufficient, user-defined formatting functions are also supported. For example, to right-justify numeric parameters, one could use the "printf" formatting characters: "-10.2f" as shown below:
131              
132            
The results are 0.00
133              
134             This provides that ":roses" will be displayed using "printf" formatting, with defaults of "0.00".
135              
136             To format currency, one could define a formatting function within the CGI script to place commas every 3 digits, add parenthesis if negative, etc. For example:
137              
138             sub cashit
139             {
140             my ($val) = shift;
141             my ($iter) = shift;
142             my ($lastrow) = shift;
143              
144             $val = sprintf('%.2f',$val);
145             $val =~ s/(\d)(\d\d\d)$/$1,$2/;
146             $val =~ s/(\d)(\d\d\d),/$1,$2,/g;
147             $val = '(' . $val . ')' if ($val =~ s/^\-//);
148             return ("$val");
149             }
150              
151             Then include the following in the HTML template:
152              
153             $0
154              
155             This formats the dollar amount with commas every three digits and adds parenthesis if negative. Two decimal places are also displayed.
156              
157             Sometimes, simple parameter substitution is not sufficient. LoadHtml provides several special control structures to handle more complex dynamic HTML generation.
158              
159             An alternate way of specifying parameters (namely, within HTML tags) is to enclose the parameter name between ":{ and "}". For example:
160              
161             Link to Rose colors
162              
163             would fail since the closing ">" of the parameter would close the tag! To avoid this, specify the parameter as:
164              
165             Link to Rose colors
166              
167             Substituting parameters in places where HTML does not allow special tags:
168              
169             Sometimes it is necessary to embed a parameter substitution where HTML does not permit a special tag, ie a button with a default name. For example, suppose a page should have a form submit button with a default value of "Create Record":
170              
171            
172              
173             Now, if the page is loaded via LoadHTML, it is to be set to ":{arg} Record" if parameter "arg" is specified, otherwise, it is to be set to "Add Record". This can be accomplished with the following code:
174              
175            
176              
177             This hyroglyphics will cause a submit button with the words "Create Record" to be displayed if page is just displayed without LoadHTML, It will be created with the "default" value "Add Record" if loaded by loadhtml() (cgi) but no value for "arg" is passed. If a value is passed to the "arg" parameter, then that value is used, ie. "arg => 'Update'" would yield a button with the displayed value of "Update Record". NOTE the use of ">" instead of ">" since html terminates comments with ">". The way this works is the html enclosed in the ... tag is replaced by what's between the [ ] within the tag. The string "Add" (between the "=" sign and the "[" is the "default" value used in leau of ":{arg}" if no value is passed to that parameter (-arg => 'some value').
178             III) Control Statement Tags:
179              
180             "IF-THEN-ELSE" statement:
181              
182            
183             -body-
184            
185             -body-
186            
187              
188             The "ELSE" part is optional. The "statement_name" is optional, but should always be used if nesting IF statements. Consider the following HTML template file:
189              
190            
191            

Jim's Joke Page!

192            
193            
194            
Roses are , violets are .
195            
196            
Knock Knock, who's there? , who?, , that's who!
197            
198            
199              
200             This example will generate two different joke-lines, depending on the value passed as argument #1.
201              
202             loadhtml('/usr/htdocs/myhtml.htm', -flora => 'FLOWERS', -arg1 => 'red', -arg2 => 'blue');
203              
204             will produce:
205              
206            
207            

Jim's Joke Page!

208            
209            
Roses are red, violets are blue.
210            
211              
212             whereas:
213              
214             loadhtml('/usr/htdocs/myhtml.htm', -flora => 'VEGETABLES', -arg1 => 'Foold', -arg2 => 'Fooled You!');
215              
216             will produce:
217            
218            

Jim's Joke Page!

219            
220            
Knock Knock, who's there? Foold, Foold who?, Fooled You!, that's who!
221            
222              
223             NOTE: The "ELSE" portion is not required.
224              
225             If one of the parts is desired for a standalone (no CGI) default, the other can be commented out with HTML comments, for example (NOTE: the "statement_name" is included and is "_STMT1":
226              
227             normal text
228              
229             If invoked as a stand-alone HTML page or if ":condition" is non-null and non-zero, "normal text" will print, otherwise, "special-case text" will print. The HTML comments will be removed automatically for the text, if the corresponding condition evaluates to true.
230              
231             "LOOP" Statement:
232              
233             Another, more powerful construct is the "LOOP". A LOOP repeatedly generates its HTML body for each value in a Perl list. The LOOP construct has the following general format:
234              
235            
236             -body-
237            
238              
239             For example:
240              
241            
242            

Dallas Cowboy's Star Roster

243            

244            
No.NameJersey
245            
246            
:#+1
247            
248            
249            
250              
251             If called with:
252              
253             loadhtml('/usr/htdocs/myhtml.htm',
254             -names => ['Troy Ackman', 'Emmit Smith', 'Michael Irvin'],
255             -numbers => [8,22,88]);
256              
257             would produce:
258              
259            
260            

Dallas Cowboy's Star Roster

261            

262            
NameJersey
263            
1Troy Ackman8
264            
2Emmit Smith22
265            
3Michael Irvin88
266            
267            
268              
269             The values: names, and numbers in the "LOOP" statement refer to those parameters which refer to perl list references instead of scaler values. The ":#" represents a special value -- the iteration number of the loop being processed (starting with zero). We use ":#+1" (":#_LOOPNAME+1) to cause this value to start with one instead of zero). If loops are nested (and thus named, the name can be appended to the ":# variable, ie:
270              
271            
272            
Now in iteration: :#_LOOPNAME+1; next arg1 value=
273            
274              
275             By default, the loop executes with ":#" starting with zero, incrementing by one and continuing through the last value of the 1st list parameter specified. This can be overridden by specifying an increment expression with starting and ending values and optionally, an increment value; -AND/OR- an index-list. For example (start with 10, stop at 100, and increment by 5):
276              
277            
278            
The list value for argument1[:#] is: .
279            
280              
281             This would produce 19 lines of output, the value printed for ":#" would be 10, then 15, 20, ...100. The tenth, 15th, 20th, 25th, ... and 100th elements of the list passed as argument 2 to LoadHtml() would be displayed. If that list contained less than 100 elements, empty strings would print for the missing elements. This is also useful to reverse the order of a list, for example:
282              
283            
284             ...
285            
286            
287              
288            
289              
290             This specifies that the loop should execute argument1 times. Each iteration will correspond to a value of argument2 and argument3 starting with element [1]. argument1 should contain a scaler integer and argument2 and argument3 should be references to arrays with at least "argument1" + 1 elements.
291              
292            
293              
294             This specifies that the loop should execute once for each element of argument2 starting with the 6th one ([5]) and continuing through the last one.
295              
296            
297              
298             This specifies that the loop should execute 4 times using the 2nd, 6th, 3rd, and 8th values of argument1 and argument2.
299              
300            
301              
302             This specifies that the loop should execute once for each element in the array-reference passed to "index-list". Each value of index-list will become the subscript to use for argument1 and argument2 in it's respective iteration.
303              
304             NOTE: If argument1 is a hash-reference instead of an array-reference, then the keys used for argument1 will be based on the relative position within an imaginary array built on the fly as "sort(keys(%{$argument1))". For example if the keys for argument1 (sorted) were "AA", "BB", "CC", and "DD"; and array referenced by index-list contained the values (in this order): (1, 3, 2, 0), then the loop would iterate through the keys in the order of: "BB", then "DD", then "CC", and finally "AA". This allows hashes to be iterated through in an order other than sorted by key!
305              
306             LoadHTML can also emulate Template::Toolkit's ability to reference subcomponents of a reference by name. For example:
307              
308             my @v ;
309             push (@v, {id => 100, name => 'Jack'});
310             push (@v, {id => 101, name => 'Jill'});
311             push (@v, {id => 102, name => 'Jerry'});
312             &loadhtml('template.html', -hashref => \@v);
313              
314             template.html contains:
315              
316            
317            
IdName
318            
319            
320            
321            
322              
323             This would produce:
324              
325            
326            
IdName
327            
100Jack
328            
101Jill
329            
102Jerry
330            
331              
332             NOTE: "id" and "name" are parameters in the LOOP statement that are NOT DEFINED - (no argument is passed to them in the call to "loadhtml()"! This results in the subcomponents of the hashrefs passed to "hashref" (from @v) being used! This is similar to the way Template::Toolkit works and permits easier conversion of templates and scripts from that package. Also NOTE: a HASH could have been used in leau of "@v"!
333              
334             There are four special variables that have meaning within a loop construct:
335              
336             * :# Current increment value. If no increment expression or index list is specified, the loop is driven by the 1st array or hash argument. In that case, the increment value is the zero-based iteration of the loop. This value is always numeric and represents the index subscript of the vectors for the current iteration.
337             * :* Always the current zero-based iteration of the loop (numeric). Normally, this is the same as :#, but if an increment expression or index list is specified before the parameters, then :# is set to each element of the increment expression/index list, whereas :* is ALWAYS 0,1,...
338             * :% Current key value of the 1st (driving) hash (if the 1st argument is a hash-reference). Otherwise, this variable is empty (ie. if the loop is driven by an array).
339             * :^ Always contains the number of iterations (one-based) that the loop will perform.
340              
341             Naming and nesting IF and LOOP constructs.
342              
343             IF and LOOP constructs can be nested with each other. If nested within the same construct, however, they must be named (in order for the parser to match up the proper closing tags). This allows for qualifying the special variables (:#, :*, etc.) to the desired loop. To name an "IF" or "LOOP" constuct, simply append an alphanumeric string to the keyword, for example:
344              
345             ......
346              
347             -or-
348              
349             ...
350              
351             The "IF" is named "2", and the "LOOP" is named "_OUTER".
352              
353             Multi-loop Matrix example:
354              
355             Consider the following code:
356              
357              
358             my $data = $dbh->selectall_arrayref('select name, address, phone from some_database.table');
359             ...
360             &loadhtml('rate_specials.html',
361             -colHeaders => [qw(Name Address Phone)],
362             -matrix => $data,
363             -names => '$matrix->[*][0]', #THIS IS AN EXAMPLE OF A COLUMN "Slice"!
364             );
365              
366             Now consider the following template code:
367              
368              
369            
370            
LinkField Header
371            
372            
373            
374             Field Value
375            
376            
377            
378              
379             This illustrates how simple it is to combine LoadHTML with DBI (the single call to DBI::selectall_arrayref fetches all the data from a database query into a two-dimentional row-major array referenced by $data). This HTML template could handle a variety of queries, since the number of columns (headers) is also driven by a loop. The "ODDEVEN1" IF-statement is optional and simply allows the table rows to have alternating colors for readability. Note the nested loops "_ROWS" (outer) and "_COLS" (inner), both are driven by the two-dimentional array- referencing parameter "matrix". This will produce a table showing a row for each record read by the query and each row will contain all three column values.
380              
381             An extra, but unnecessary level of complexity was added to this example to illustrate another feature - the column "slice". Note that the 1st column header is "Link", and the 1st column of each row is a URL link to "someotherpgm.cgi". The reason for this example is to show access to the entire column of data represented by the field "names". By specifying an additional parameter called "-names" containing the literal value string "$matrix->[*][0]", one can unroll a specific column within a multi-dimentional array in the outter (row) loop. This means that the "names" parameter refers to the 1st ([0]'th) slice of the two-dimentional array referenced by the "matrix" parameter. For each row in the loop, the asterisk is replaced by the increment number, so that in the 1st row "names" refers to $data->[0][0] (The 1st name returned by the query). In the 2nd row, "names" refers to $data->[1][0], etc. This permits the row-major data returned by the query to be handled in a column-major way (allowing the programmer to get at the individual elements of a specified column), which would normally require an inner loop to access.
382              
383             Note also, that is is not limited to 2 dimensions or to array-references. The number of dimensions is not physically limited, but can be any number and combination of array and or hash-references. The trick is that there normally must be a nested loop refering to the same parameter for each dimension to be unrolled (unless a column slice is used). When hash-references are used, they are sorted by key unless an index-list is specified.
384              
385             The above example could have also been acomplished without the slice by using an inner loop (called "NAMES" below) that only referenced the desired (zero-th) element (only iterates once (0..0) unrolling the zeroth column (inner dimension) element of "matrix" for each iteration of the outer ("ROWS") LOOP as follows: (You could replace the "0..0" with the number of the column you wish to use for the slice).
386              
387              
388             /
389            
LinkField Header
390            
391            
392            
393             Field Value
394            
395            
396            
397              
398             "SELECTLIST" Statement:
399              
400             Another compound construct is the "SELECTLIST". It generates an HTML "SELECT" statement using the elements of a Perl list or hash, generating an "OPTION" line for each element in the list or hash. The general format is:
401              
402            
403             [...HTML to display if page invoked standalone...]
404            
405              
406             The NAME and any options other than "VALUE", "DEFAULT", "DEFAULTSEL", "BYKEY", "BYVALUE", and "REVERSE" are added (passed) to the generated SELECT statement. The "list_parameter" (required), by default, becomes the values for the generated "OPTION" lines. If "list_parameter" is a Perl hash, then the keys of the hash become the arguments for the "VALUE=" part of each OPTION line, and the values become the displayed items in the listbox. The values are then character-sorted by key (BYKEY) unless "BYVALUE" is specified. "REVERSE" reversed the order. If "list_parameter" is a list and a second list is supplied via the "VALUE" option, then the second list becomes the "VALUE=" part of each OPTION line and the "list_parameter" list items are displayed. They are displayed in the order they appear in the list(s), unless "REVERSE" is specified. If no "VALUE" option is given and "list_parameter" is a list, then no "VALUE=" option is generated and the values become both the actual values and the displayed values for the listbox. The DEFAULT option, if specified, is a value which is to be the initially highlighted value in the select-list. If the "MULTIPLE" select option is specified, then the "DEFAULT=" value may be either a scalar or a list-reference. Each value in the "DEFAULT" list (if a list reference) is matched against the "VALUE" list and those that match are "SELECTED" by default. If "DEFAULTSEL=" is specified, the default list values are compared with the SELECT values instead the "VALUES" values. Note that the resulting selection-list items are sorted in character-sequence order when the list parameter is a hash To get a true numeric sort, one must left-pad the hash keys with spaces.
407              
408             Example:
409              
410            
411              
412             ...
413              
414             $mydefault = 123;
415             %employeehash = (110 => 'John Smith', 145 => 'Richard Adams', 123 => 'Mike Cox', 132 => 'Eddy Jones');
416             &loadhtml('/usr/htdocs/myhtml.htm', -thisid => $mydefault, -employees => \%employeehash);
417              
418             This would replace the "id" TEXT box field with the following HTML:
419              
420            
421            
422            
423            
424            
425            
426              
427             Checkboxes and radio-buttons:
428              
429             Checkboxes and radio-buttons also require special handling. A default value is specified in the HTML via a parameter. The parameter will be replaced by the word "CHECKED" if it's value matches the value specified for the checkbox or radio-button. for example:
430              
431            
Check here if True!
432              
433             If the value passed to ":ischecked" is "true" in Perl (not zero, empty string, or whitespace), the HTML will be generated with ":ischecked" replaced with the word "CHECKED", otherwise, the ":ischecked" it will be removed. NOTE: If the word "CHECKED" is already in the HTML, it will be removed if the value for ":ischecked" is false, but will remain if no argument is defined for ":ischecked".
434              
435             Give me Meat and Cheese
436             Give me Veggies, please
437              
438             If the argument passed to ":ischecked" is equal 'meat' or 'veggies', then the corresponding radio-button will be marked "CHECKED", otherwise, neither will be checked.
439              
440             "INCLUDE" statement:
441              
442             Additional HTML files can be loaded and processed within an HTML file via the "INCLUDE" statement. All files loaded via the "INCLUDE" statement are also parsed and modified the same way the initial HTML file is. The include file can be specified as either a server file-name or a url. Examples:
443              
444            
445            
446            
447              
448             You can also include a portion of another html template file without including the endire file by using tags
449              
450             For example:
451              
452            
453              
454             This assumes the template file myhtml.htm contains the following block tag:
455              
456            
457             ... stuff to be included ...
458            
459              
460             You can also force different default values for parameters by including them in the include, ie.:
461              
462             -or-
463            
464              
465             Providing default values for form items.
466              
467             LoadHtml provides special ways to assign default values to HTML "INPUT" statements. Consider the following for putting a default value into a TEXT field:
468              
469            
470              
471             This will work, but LoadHtml provides a better way. If done this way and the form is invoked stand-alone, the input box will show a literal ":{default}", which is probably not desired for demos. The preferred way is:
472              
473            
474              
475             This provides a value "standalone-default", if the page is invoked as stand-alone HTML and a value of "somestring", if no argument or "undef" is passed for the corresponding argument. If the "=somestring" string is omitted, the box will show as empty, if no argument is passed for ":{default}". NOTE: If an empty string is passed as an argument, the box will be empty regardless of any default values specified! This option also applies to "HIDDEN" input fields.
476              
477            
478              
479             This permits the default (initially selected) value of the SELECT statement to be specified by the value referenced by argument "default".
480              
481             stand-alone default
482              
483             This works similar to the "" input field described previously.
484             IV). Other Special Tags:
485              
486             Embedding Perl variables:
487              
488             If "AllowEvals(1)" is called before calling "loadhtml", then any embedded Perl variables of the format: ":$scaler or :$array[index] or :$hash{index} or :$package::variable will be replaced by it's value current at the time LoadHtml is called.
489              
490             Embedding Perl code (the "EVAL" Statement):
491              
492             If "AllowEvals(1)" is called before calling "loadhtml", then any Perl code between the tag: "" will be evaluated and any returned results will replace the EVAL tag. Consider the following example:
493              
494            
495             my (@t) = localtime(time);
496             return ($t[3] . '-' . (qw(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC))[$t[4]] . '-' . $t[5] . '.');
497             /EVAL>
498              
499             This tiny Perl program calls Perl's "localtime" function, and returns the current date with the month formated into it's proper three-character abbreviation. The more complicated example below generates a dynamic url link:
500              
501            
502             my ($homepage) = ":0";
503             $homepage =~ s/userpage/pp:4/;
504             if (-e "$homepage")
505             {
506             $homepage = 'http://myhost.domain.com/cgi-bin/loadtext.pl?link='
507             . $homepage . '&args=:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19,:20,:21,:22';
508             return ('
509             }
510             /EVAL>
511              
512             Note that parameter substitutions take place within this code. Also note the use of ">" in lieu of the ">" symbol. This is required to prevent the HTML processor from closing the "
513              
514             Embedding Perl code (the "PERL" Statement):
515              
516             You can also embed the results of a separate Perl script file using the "PERL" tag.
517              
518             The format is:
519              
520             The script must be "eval"-able (last expression's results are returned) by Perl. Also, "-perls => 1" must be passed to SetRegices() and AllowEvals(1) must be called - since THIS IS A SECURITY RISK - if the Perl script is malicious! NOTE: how the "Default String" is enclosed in quotes, since this is fed to Perl's eval() fn also (if the script can't be eval'ed), so must be a valid Perl result also!
521              
522             Of course, one can be even more dangerous, ie: ""!
523              
524             Embedding hash-definitions within HTML pages:
525              
526             Hash tables can now be defined within an HTML page for creating lookup tables, etc. To create a hash table, use the " tag. For example:
527              
528            
529             'any' => 'Any attribute',
530             'di' => 'Direct/Indirect',
531             'dgr' => 'Education (Degree)',
532             'ins' => 'Education (Institution)',
533             'maj' => 'Education (Major)',
534             'exl' => 'Experience (LM)',
535             'ex' => 'Experience (Total)',
536             'flv' => 'Foreign Language',
537             'flw' => 'Foreign Language',
538             'fpt' => 'Full/Part Time',
539             'ou' => 'Organization',
540             'pos' => 'Title',
541             'sg' => 'Salary Grade',
542             'sc' => 'Security Clearance',
543             'sk' => 'Skills and Knowledge',
544             'tr' => 'Training'
545            
546              
547             This defines a lookup table for several codes and gives each a description. The hash can be any valid Perl hash-definition. The hash will be referred to within the HTML by the name "attbdescs". To cause a hash's value to be displayed, use its name in the special tag in the format:
548              
549            
550              
551             For example to display the following tag:
552              
553            
554              
555             would be replaced with "Title". The real use for this is specifying the key dynamically, ie:
556              
557            
558              
559             The result depends on the value of ":1". If the value of ":1" does not match any of the key values, then "-NO SUCH VALUE!-> is displayed.
560              
561             If the template page is also being used stand-alone, the entire hash definition (between "" and ") can be enclosed as a comment ("").
562              
563             Other Tags:
564              
565             (or replace this standalone default text)
566              
567             Generates the point-of-contact's name (whatever value passed to the set_poc() function. The default value is the string "your website administrator". NOTE: "-pocs => 1" must be passed to &SetRegices() first!
568              
569             (or replace this standalone default text)
570              
571             (or replace this standalone default text)
572              
573             Generates today's date (default format is "mm/dd/yy" if DBD::Sprite is installed and the "to_char" function from that library is available, otherwise, the format is: scalar(localtime($mtime).
574              
575             (or replace this standalone default text)
576              
577             (or replace this standalone default text)
578              
579             Generates the last-modified date/time of the template file (default format is "mm/dd/yy" if DBD::Sprite is installed and the "to_char" function from that library is available, otherwise, the format is: scalar(localtime($mtime).
580              
581             V). User-callable Functions (Details):
582              
583             &loadhtml($htmlfile, @args)
584              
585             Main function to read/process a specified template file / url ($htmlfile) and prints out the resulting html page to STDOUT. @args represents a list of values. Each argument value replaces any occurrance of the corresponding parameter number (ie. ":1", ":2", etc.). If the first, third, fifth, etc. are valid Perl "words" starting with a hyphen, then the next argument (ie. the 2nd, fourth, sixth, etc.) represents a value that will replace every occurrance of the parameter with the same name, ie. "-parm => 'value', converts :{parm} or or ... to 'value' everywhere it occurrs. For each parameter that is used in a LOOP or SELECTLIST construct, the value should be an array reference or a hash referehce, rather than a scalar value. If successful, loadhtml returns 1 (true) if fails, ie. could not open the template file, . The special parameter ":0" is replaced with the name of the template file (1st argument).
586              
587             You can also convert programs that use Template::Toolkit by changing:
588              
589             $template_object->process($template_file, $template_hashref);
590              
591             to:
592              
593             &loadhtml($template_file, %{$template_hashref});
594              
595             &loadhtml($htmlfile, @args);
596              
597             is equivalent to:
598              
599             print &buildhtml($htmlfile, @args);
600              
601             my $html = &buildhtml($htmlfile, @args);
602              
603             Same as loadhtml, except returns the generated webpage as a string instead of writing it to STDOUT;
604              
605             print &dohtml($htmlstring, @args);
606              
607             my $html = &dohtml($htmlstring, @args);
608              
609             Same as buildhtml, except processes a input string instead of a template file or url.
610              
611             &AllowEvals(1|0);
612              
613             Toggles whether or not embedded Perl variables and expressions are performed, namely the and constructs and Perl variables in the format: "".
614             Default is 0.
615              
616             &set_poc($str);
617              
618             Sets the string to replace the special "" construct. Default is to ignore this tag. If called without a string or an empty string, the string is set to "your website administrator".
619              
620             &SetRegices(%optionshash);
621              
622             Sets special control options. The currently defined options (with their default values) are: -hashes => 0, -CGIScript => 0, -includes => 1, -embeds => 0, -loops => 1, -numbers => 1, -pocs => 0, -perls => 0)
623              
624             These options allow speeding up processing when turned off (not needed).
625              
626             -hashes: Allows the tag sto be processed if on, otherwise ignored.
627              
628             -CGIScript: Causes s special hidden form variable called "CGIScript" to be added at
629             the bottom of the first form with the value set to "$ENV{SCRIPT_NAME}" if on, otherwise not added.
630              
631             -includes: Allows the tags to be processed if on, otherwise ignored.
632              
633             -embeds: Allows the tags to be processed if on, otherwise ignored.
634              
635             -loops: Allows the tags to be processed if on, otherwise ignored.
636              
637             -numbers: Allows the classic numeric parameter (":1", ":2", etc.) tags to be processed if on, otherwise ignored.
638              
639             -pocs: Allows the tags to be processed if on, otherwise ignored.
640              
641             -perls: Allows the tags to be processed if on, otherwise ignored.
642              
643             &SetListSeperator($separator_string);
644              
645             Sets the separator string to be used if an array-reference is passed to a parameter that appears outside of a loop (where a scalar value is expected) Such values are automatically converted to a string of values ala Perl's "join()" function. The default string is ", ".
646              
647             &SetHtmlHome($htmlhome, $roothtmlhome, $hrefhtmlhome, $hrefcase);
648              
649             This allows certain embedded links within a document to be "converted" for proper handling. Relative links refer to a different path when the document is loaded via CGI/LoadHTML than then they are loaded directly as urls by a browser, for example, the document root usually becomes the directory the CGI script is in. Anyway, this is an attempt to allow valid HTML pages to also be loaded as templates within a CGI script and maintain their links properly.
650              
651             $htmlhome - specifies the URL path to append to relative links in SRC=, HREF=, CL=, HT=, GROUND=, and window.open() arguments.
652              
653             $roothtmlhome specifies the filesystem path to append to relative file names in tags.
654              
655             $hrefhtmlhome - similar to $htmlhome, but only applies to HREF= links, if it is necessary to redirect them to a different path, ie. a cgi-script for pre-processing. If both $hrefhtmlhome and $htmlhome are specified and non-empty, the former will override for HREF= links and the other will applie to the other link types, ie. SRC=, etc.
656              
657             $hrefcase - used to limit the substitutions of $htmlhome and $hrefhtmlhome to specific links. It can be set to 'l' (Lower-case links only), left undefined for all links, or set to anything else for Upper-case links only. For purposes of case, a "Lower-case" link would be "href=", an "Upper-case" link would be "HREF=".
658              
659             &loadhtml_package($package_name);
660              
661             Change the default package LoadHTML uses for embedded Perl variables. Default is main. Best way to set this is to call "loadhtml_package(__PACKAGE__);".
662             VI). Minimum System Requirements:
663              
664             * 1) Any system supporting Perl and CGI.
665             * 2) Perl, v. 5.003 or better.
666             * 3) Perl's "LWP" module (not an absolute requirement, but VERY useful) and required prerequesites: MIME-Base64 (MIME), HTML-Parser (HTML), libnet (Net), MD5, and Data-Dumper (Data). All of these are available for download from CPAN.
667              
668             =head1 METHODS
669              
670             =over 4
671              
672             =item B([package_name])
673              
674             Change the default package LoadHTML uses for embedded Perl variables. Default is I
. Best way to set this is to call "loadhtml_package(__PACKAGE__);".
675              
676             =item B(template_file, @arguments)
677              
678             Main function to read/process a specified template file / url ($htmlfile) and prints out the resulting html page to STDOUT. @args represents a list of values. Each argument value replaces any occurrance of the corresponding parameter number (ie. ":1", ":2", etc.). If the first, third, fifth, etc. are valid Perl "words" starting with a hyphen, then the next argument (ie. the 2nd, fourth, sixth, etc.) represents a value that will replace every occurrance of the parameter with the same name, ie. "-parm => 'value', converts :{parm} or or ... to 'value' everywhere it occurrs. For each parameter that is used in a LOOP or SELECTLIST construct, the value should be an array reference or a hash referehce, rather than a scalar value. If successful, loadhtml returns 1 (true) if fails, ie. could not open the template file, . The special parameter ":0" is replaced with the name of the template file (1st argument).
679              
680             =item $html = B([package_name])
681              
682             Same as loadhtml, except returns the generated webpage as a string instead of writing it to STDOUT;
683              
684             =item $html = B(html_datastring, @arguments)
685              
686             Same as buildhtml, except reads it's template data from a string variable instead of a file.
687              
688             =item B(1|0)
689              
690             Toggles whether or not embedded Perl variables and expressions are performed, namely the and constructs and Perl variables in the format: "".
691             Default is 0.
692              
693             =item B(string)
694              
695             Sets the string to replace the special "" construct. Default is to ignore this tag. If called without a string or an empty string, the string is set to "your website administrator".
696              
697             =item B(separator_string)
698              
699             Sets the separator string to be used if an array-reference is passed to a parameter that appears outside of a loop (where a scalar value is expected) Such values are automatically converted to a string of values ala Perl's "join()" function.
700             Default: I<", ">.
701              
702             =item B(%optionshash)
703              
704             Sets special control options. The currently defined options (with their default values) are: -hashes => 0, -CGIScript => 0, -includes => 1, -embeds => 0, -loops => 1, -numbers => 1, -pocs => 0, -perls => 0)
705             These options allow speeding up processing when turned off (not needed).
706              
707             =over 4
708              
709             B<-hashes>: Allows the tag sto be processed if on, otherwise ignored.
710              
711             B<-CGIScript>: Causes s special hidden form variable called "CGIScript" to be added at
712             the bottom of the first form with the value set to "$ENV{SCRIPT_NAME}" if on, otherwise not added.
713              
714             B<-includes>: Allows the tags to be processed if on, otherwise ignored.
715              
716             B<-embeds>: Allows the tags to be processed if on, otherwise ignored.
717              
718             B<-loops>: Allows the tags to be processed if on, otherwise ignored.
719              
720             B<-numbers>: Allows the classic numeric parameter (":1", ":2", etc.) tags to be processed if on, otherwise ignored.
721              
722             B<-pocs>: Allows the tags to be processed if on, otherwise ignored.
723              
724             B<-perls>: Allows the tags to be processed if on, otherwise ignored.
725              
726             =back
727              
728             =item B(htmlhome, roothtmlhome, hrefhtmlhome, hrefcase)
729              
730             This allows certain embedded links within a document to be "converted" for proper handling. Relative links refer to a different path when the document is loaded via CGI/LoadHTML than then they are loaded directly as urls by a browser, for example, the document root usually becomes the directory the CGI script is in. Anyway, this is an attempt to allow valid HTML pages to also be loaded as templates within a CGI script and maintain their links properly.
731              
732             =over 4
733              
734             B - specifies the URL path to append to relative links in SRC=, HREF=, CL=, HT=, GROUND=, and window.open() arguments.
735              
736             B - specifies the filesystem path to append to relative file names in tags.
737              
738             B - similar to $htmlhome, but only applies to HREF= links, if it is necessary to redirect them to a different path, ie. a cgi-script for pre-processing. If both B and B are specified and non-empty, the former will override for HREF= links and the other will applie to the other link types, ie. SRC=, etc.
739              
740             B - used to limit the substitutions of B and B to specific links. It can be set to 'l' (Lower-case links only), left undefined for all links, or set to anything else for Upper-case links only. For purposes of case, a "Lower-case" link would be "href=", an "Upper-case" link would be "HREF=".
741              
742             =back
743              
744             =back
745              
746             =head1 AUTHOR
747              
748             Jim Turner, C<< >>.
749              
750             =head1 COPYRIGHT
751              
752             Copyright (c) 1996-2018 Jim Turner C<< >>.
753             All rights reserved.
754              
755             This program is free software; you can redistribute
756             it and/or modify it under the same terms as Perl itself.
757              
758             =cut
759              
760             package LoadHtml;
761              
762             #use lib '/home1/people/turnerj';
763              
764 1     1   73407 use strict;
  1         3  
  1         30  
765             #no strict 'refs';
766             #use vars (qw(@ISA @EXPORT $useLWP $err $rtnTime $VERSION));
767 1     1   5 use vars (qw(@ISA @EXPORT $err $VERSION));
  1         2  
  1         4647  
768              
769             our $VERSION = '7.10';
770              
771             require Exporter;
772             #use LWP::Simple;
773             my $useLWP = 0;
774             my $haveTime2fmtstr = 0;
775 1     1   153 eval 'use LWP::Simple; $useLWP = 1;';
  0            
  0            
776             #use Socket;
777              
778             @ISA = qw(Exporter);
779             @EXPORT = qw(loadhtml_package loadhtml buildhtml dohtml modhtml AllowEvals cnvt set_poc
780             SetListSeperator SetRegices SetHtmlHome);
781              
782              
783             local ($_);
784              
785             local $| = 1;
786             my $calling_package = 'main'; #ADDED 20000920 TO ALLOW EVALS IN ASP!
787              
788             my $poc = 'your website administrator';
789             my $listsep = ', ';
790             my $evalsok = 0;
791             my %cfgOps = (
792             hashes => 0,
793             CGIScript => 0,
794             includes => 1,
795             loops => 1,
796             numbers => 1,
797             pocs => 0,
798             perls => 0,
799             embeds => 0,
800             ); #ADDED 20010720.
801             my ($htmlhome, $roothtmlhome, $hrefhtmlhome, $hrefcase);
802              
803             sub SetListSeperator
804             {
805 0     0 1   $listsep = shift;
806             }
807              
808             sub cnvt
809             {
810 0     0 0   my $val = shift;
811 0 0         return ($val eq '26') ? ('%' . $val) : (pack("c",hex($val)));
812             }
813              
814             sub set_poc
815             {
816 0   0 0 1   $poc = shift || 'your website administrator';
817 0           $cfgOps{pocs} = 1;
818             }
819              
820             sub SetRegices
821             {
822 0     0 1   my (%setregices) = @_;
823 0           my ($i, $j);
824              
825 0           foreach $j (qw(hashes CGIScript includes embeds loops numbers pocs perls))
826             {
827 0 0         if ($setregices{"-$j"})
    0          
828             {
829 0           $cfgOps{$j} = 1;
830             }
831             elsif (defined($setregices{"-$j"}))
832             {
833 0           $cfgOps{$j} = 0;
834             }
835             }
836             }
837              
838             sub loadhtml
839             {
840 0     0 1   my %parms = ();
841 0           my $html = '';
842              
843 0           local ($/) = '\x1A';
844              
845 0 0         if (&fetchparms(\$html, \%parms, 1, @_))
846             {
847 0           print &modhtml(\$html, \%parms);
848 0           return 1;
849             }
850             else
851             {
852 0           print $html;
853 0           return undef;
854             }
855             }
856              
857             sub buildhtml
858             {
859 0     0 1   my %parms = ();
860 0           my $html = '';
861              
862 0           local ($/) = '\x1A';
863 0 0         return &fetchparms(\$html, \%parms, 1, @_) ? &modhtml(\$html, \%parms) : $html;
864             }
865              
866             sub dohtml
867             {
868 0     0 1   my %parms = ();
869 0           my $html = '';
870              
871 0 0         return &fetchparms(\$html, \%parms, 0, @_) ? &modhtml(\$html, \%parms) : $html;
872             }
873              
874             sub fetchparms
875             {
876 0     0 0   my $html = shift;
877 0           my $parms = shift;
878 0           my $fromFile = shift;
879 0           my ($parm0) = shift;
880            
881 0           my ($v, $i, $t);
882            
883             # %loopparms = ();
884              
885 0           %{$parms} = ();
  0            
886 0           $$html = '';
887              
888 0           $i = 1;
889 0           $parms->{'0'} = $parm0;
890 0           while (@_)
891             {
892 0           $v = shift;
893 0 0         $parms->{$i++} = (ref($v)) ? $v : "$v";
894 0 0         last unless (@_);
895 0 0         if ($v =~ s/^\-([a-zA-Z]+)/$1/)
896             {
897 0           $t = shift;
898 0 0         if (defined $t) #ADDED 20000523 PREVENT -W WARNING!
899             {
900 0 0         $parms->{$i} = (ref($t)) ? $t : "$t";
901             }
902             else
903             {
904 0           $parms->{$i} = '';
905             }
906 0           $parms->{$v} = $parms->{$i++};
907             }
908             }
909              
910 0 0         unless ($fromFile)
911             {
912 0           $$html = $parm0;
913 0 0         return ($$html) ? 1 : 0;
914             }
915              
916 0 0         if (open(HTMLIN,$parm0))
917             {
918 0           $$html = ();
919 0           close HTMLIN;
920             }
921             else
922             {
923 0 0         $$html = LWP::Simple::get($parm0) if ($useLWP);
924 0 0 0       unless(defined($$html) && $$html =~ /\S/o)
925             {
926 0           $$html = &html_error("Could not load html page: \"$parm0\"!");
927 0           return undef;
928             }
929             }
930 0           return 1;
931             }
932              
933             sub AllowEvals
934             {
935 0     0 1   $evalsok = shift;
936             }
937              
938             sub makaswap
939             {
940 0     0 0   my $parms = shift;
941 0           my $one = shift;
942              
943 0 0 0       return ("\:$one") unless (defined($one) && defined($parms->{$one}));
944 0 0         if (ref($parms->{$one}) =~ /ARRAY/o) #JWT, TEST LISTS!
    0          
945             {
946 0 0         return defined($listsep) ? (join($listsep,@{$parms->{$one}})) : ($#{$parms->{$one}}+1);
  0            
  0            
947             }
948             elsif ($parms->{$one} =~ /(ARRAY|HASH)\(.*\)/o) #FIX BUG.
949             {
950 0           return (''); #JWT, TEST LISTS!
951             }
952             else
953             {
954 0           return ($parms->{$one});
955             }
956             #ACTUALLY, I DON'T THINK THIS IS A BUG, BUT RATHER WAS A PROBLEM
957             #WHEN $#PARMS > $#LOOPPARMS, PARMS WITH VALUE='' IN A LOOP WOULD
958             #NOT GET SUBSTITUTED DUE TO IF-CONDITION 1 ABOVE, BUT WOULD LATER
959             #BE SUBSTITUTED AS SCALERS BY THE GENERAL PARAMETER SUBSTITUTION
960             #REGEX AND THUS GET SET TO "ARRAY(...)". CONDITION-2 ABOVE FIXES THIS.
961             };
962              
963             sub makamath #ADDED 20031028 TO SUPPORT IN-PARM EXPRESSIONS.
964             {
965 0     0 0   my ($one) = shift;
966              
967 0           $_ = eval $one;
968 0           return $_;
969             };
970              
971             sub makaloop
972             {
973 0     0 0   my ($parms, $parmnos, $loopcontent, $looplabel) = @_;
974             #print "---makaloop: args=".join('|',@_)."=\n";
975 0           my $rtn = '';
976 0           my ($lc,$i0,$i,$j,%loopparms);
977 0           my (@forlist); #MOVED UP 20030515. - ORDERED LIST OF ALL HASH KEYS (IFF DRIVING PARAMETER IS A HASHREF).
978 0           $parmnos =~ s/\:(\w+)([\+\-\*]\d+)/eval(&makaswap($parms,$1).$2)/egs; #ALLOW OFFSETS, ie. ":#+1" $parmnos =~ s/\:(\w+)/&makaswap($parms,$1)/egs; #ALLOW ie.
  0            
979 0           $parmnos =~ s/\:(\w+)/&makaswap($parms,$1)/egs; #ALLOW OFFSETS, ie. ":#+1" $parmnos =~ s/\:(\w+)/&makaswap($parms,$1)/egs; #ALLOW ie.
  0            
980 0           $parmnos =~ s/[\:\(\)]//go;
981 0           $parmnos =~ s/\s+\,/\,/go;
982 0           $parmnos =~ s/\,\s+/\,/go;
983 0           my @vectorlist = (); #THE ORDERED LIST OF INDICES TO ITERATE OVER (ALWAYS NUMBERS):
984             # if ($parmnos =~ s/([a-zA-Z]+)\s+([a-zA-Z])/$2/) #CHANGED TO NEXT LN (20070831) TO ALLOW UNDERSCORES IN ITERATOR PARAMETER NAMES.
985 0 0         if ($parmnos =~ s/([a-zA-Z][a-zA-Z_]*)\s+([a-zA-Z])/$2/)
    0          
986             {
987             #print "
-LOADHTML: 1=$1= param=$$parms{$1}=\n"; #JWT:ADDED EVAL 20120309 TO PREVENT FATAL ERROR IF REFERENCE ARRAY MISSING!:
988 0           eval { @vectorlist = @{$parms->{$1}} }; #WE HAVE AN INDEX LIST PARAMETER ()
  0            
  0            
989             #print "
-???- 1st arg=$1= VECTOR=".join('|',@vectorlist)."=\n";
990             }
991             elsif ($parmnos =~ s/(\d+\,\d+)((?:\,\d+)*)\s+([a-zA-Z])/$3/) #WE HAVE A LITERAL INDEX LIST ()
992             {
993 0           eval "\@vectorlist = ($1 $2);";
994             }
995 0           $parmnos =~ s/\s+/\,/go;
996              
997 0           my (@listparms) = split(/\,/o, $parmnos);
998             #1ST IF-CHOICE ADDED 20070807 TO SUPPORT AN INDEX ARRAY OF HASH KEYS W/DRIVING PARAMETER OF TYPE HASHREF:
999 0 0 0       if (ref($parms->{$listparms[0]}) eq 'HASH' && defined($vectorlist[0]) && defined(${$parms->{$listparms[0]}}{$vectorlist[0]}))
  0 0 0        
      0        
1000             {
1001             #print "
-???- 1st is HASH: VECTOR=".join('|',@vectorlist)."=\n";
1002             #INDEX ARRAY CONTAINS HASH-KEYS AND 1ST (DRIVING) VECTOR IS A HASHREF:
1003 0           @forlist = sort keys(%{$parms->{$listparms[0]}});
  0            
1004 0           my @keys = @vectorlist;
1005 0           @vectorlist = ();
1006 0           for (my $i=0;$i<=$#keys;$i++)
1007             {
1008 0           for (my $j=0;$j<=$#forlist;$j++)
1009             {
1010 0 0         if ($keys[$i] eq $forlist[$j])
1011             {
1012 0           push (@vectorlist, $j);
1013 0           last;
1014             }
1015             }
1016             }
1017 0           $i0 = scalar @vectorlist; #NUMBER OF LOOP ITERATIONS TO BE DONE.
1018             }
1019             elsif (defined($vectorlist[0]) && $vectorlist[0] =~ /^\d+$/o)
1020             {
1021             #print "
-???2- VL=".join('|',@vectorlist)."=\n";
1022             #INDEX ARRAY OF JUST NUMBERS:
1023 0 0         if (ref($parms->{$listparms[0]}) eq 'HASH')
1024             {
1025 0           @forlist = sort keys(%{$parms->{$listparms[0]}});
  0            
1026             }
1027 0           $i0 = scalar @vectorlist;
1028             }
1029             else #NO INDEX LIST, SEE IF WE HAVE INCREMENT EXPRESSION (ie. "0..10|2"), ELSE DETERMINE FROM 1ST PARAMETER:
1030             {
1031             #print "
-???3- NO INDEX LIST! vl0=$vectorlist[0]=\n";
1032 0           my ($istart) = 0;
1033 0           my ($iend) = undef;
1034 0           my ($iinc) = 1;
1035 0           my $parmnos0 = $parmnos;
1036 0 0         $istart = $1 if ($parmnos =~ s/([+-]?\d+)\.\./\.\./o);
1037 0 0         $iend = $1 if ($parmnos =~ s/\.\.([+-]?\d+)//o);
1038 0           $parmnos =~ s/\.\.//o; #ADDED 19991203 (FIXES "START.. ").
1039 0 0         $iinc = $1 if ($parmnos =~ s/\|([+-]?\d+)//o);
1040 0           $parmnos =~ s/^\s*\,//o; #ADDED 19991203 (FIXES "START.. ").
1041 0 0         shift @listparms unless ($parmnos eq $parmnos0); #1ST LISTPARM IS THE INCREMENT EXPRESSION, REMOVE IT NOW.
1042 0 0         if (ref($parms->{$listparms[0]}) eq 'HASH')
1043             {
1044 0           @forlist = sort keys(%{$parms->{$listparms[0]}});
  0            
1045 0 0         if ($#vectorlist >= 0) { #THIS IF ADDED 20070914 TO SUPPORT ALTERNATELY SORTED LIST TO DRIVE HASH-DRIVEN LOOPS:
1046 0           my @keys = @vectorlist; #IE.
1047 0           @vectorlist = ();
1048 0           for (my $i=0;$i<=$#keys;$i++)
1049             {
1050 0           for (my $j=0;$j<=$#forlist;$j++)
1051             {
1052 0 0         if ($keys[$i] eq $forlist[$j])
1053             {
1054 0           push (@vectorlist, $forlist[$j]);
1055 0           last;
1056             }
1057             }
1058             }
1059 0           @forlist = @vectorlist;
1060             }
1061 0 0         $iend = $#forlist unless (defined $iend);
1062             #print "
-???- 1ST ARG IS HASH: VL=".join('|',@vectorlist)."= FL=".join('|',@forlist)."=\n";
1063             }
1064             else
1065             {
1066             #no strict 'refs';
1067             #print "
-???- lp=".join('|',@listparms)."= parm0=$parms->{$listparms[0]}=\n";
1068             #print "
-REF=".ref($parms->{$listparms[0]})."=\n";
1069 0 0         unless (defined $iend)
1070             {
1071             $iend = (ref($parms->{$listparms[0]}) eq 'ARRAY'
1072 0 0         ? $#{$parms->{$listparms[0]}} : 0);
  0            
1073             }
1074             #print "
-iend=$iend=\n";
1075             }
1076 0           @vectorlist = ();
1077 0           $i = $istart;
1078 0           $i0 = 0;
1079 0           while (1)
1080             {
1081 0 0         if ($istart <= $iend)
1082             {
1083 0 0 0       last if ($i > $iend || $iinc <= 0);
1084             }
1085             else
1086             {
1087 0 0 0       last if ($i < $iend || $iinc >= 0);
1088             }
1089 0           push (@vectorlist, $i);
1090 0           $i += $iinc;
1091 0           ++$i0;
1092             }
1093             }
1094              
1095 0           my $icnt = 0;
1096 0           foreach $i (@vectorlist)
1097             {
1098 0           $lc = $loopcontent;
1099 0           foreach $j (keys %{$parms})
  0            
1100             {
1101             #if (@{$parms->{$j}}) #PARM IS A LIST, TAKE ITH ELEMENT.
1102 0 0         if (" @listparms " =~ /\s$j\s/)
1103             {
1104             #@parmlist = @{$parms->{$j}};
1105 0 0         if (ref($parms->{$j}) =~ /HASH/io) #ADDED 20020613 TO ALLOW HASHES AS LOOP-DRIVERS!
    0          
    0          
1106             {
1107             #WANT_VALUES: $loopparms{$j} = $parms->{$j}->{(keys(%{$parms->{$j}}))[$i]};
1108             #$loopparms{$j} = (keys(%{$parms->{$j}}))[$i]; #CHGD. TO NEXT 20030515
1109 0           $loopparms{$j} = ${$parms->{$j}}{$forlist[$i]};
  0            
1110             # $lc =~ s/\:\%${looplabel}/$forlist[$i]/eg; #MOVED TO 302l 20070713 ADDED 20031212 TO MAKE :%_loopname HOLD KEY OF 1ST HASH!
1111             }
1112             elsif (ref($parms->{$j}) =~ /ARRAY/io) #TEST ADDED SO FOLLOWING SWITCHES COULD BE ADDED 20070615
1113             {
1114 0           $loopparms{$j} = ${$parms->{$j}}[$i];
  0            
1115             }
1116             elsif ($parms->{$j} =~ /^\$(\w+)/o)
1117             {
1118             #ADDED THIS ELSIF AND NEXT ELSE 20070615 TO
1119             #PLAY NICE W/$dbh->selectall_arrayref()
1120             #SO WE CAN PASS A 2D ROW-BASED MATRIX OF DB DATA
1121             #AND ACCCESS EACH COLUMN AS A NAMED PARAMETER BY
1122             #SPECIFYING: "-fieldname => '$matrix->[*][2]'"
1123             #WHERE "matrix" IS THE DRIVING LOOP PARAMETER NAME
1124             #AND "*" IS REPLACED BY NEXT SUBSCRIPT IN LOOP.
1125             #THIS *AVOIDS* HAVING TO CONVERT ROW-MAJOR ARRAYS
1126             #TO COLUMN-MAJOR AND PASSING EACH COLUMN SLICE!
1127 0           my $one = $1;
1128 0           my $eval = $parms->{$j};
1129             # $eval =~ s/\*/$i/g; #CHGD. TO NEXT 20070831 TO ALLOW RECURSION, IE. '$matrix->[*][*][0]', ETC.
1130 0           $eval =~ s/\*/$i/;
1131 0           my $eval0 = $eval; #ADDED 20070831 TO SAVE FOR POSSIBLE REGRESSION.
1132 0           $eval =~ s/$one/parms\-\>\{$one\}/;
1133 0           $loopparms{$j} = eval $eval;
1134             #print "\n---- j=$j= parm=$parms->{$j}= eval=$eval= lp now=$loopparms{$j}= at=$@=\n";
1135             # $loopparms{$j} = $parms->{$j} if ($@); #CHGD. TO NEXT 20070831 TO ALLOW RECURSION, IE. '$matrix->[*][*][0]', ETC.
1136 0 0         if ($@)
1137             {
1138 0           $eval0 =~ s/(?:\-\>)?\[\d+\]//o; #STRIP OFF HIGH-ORDER DIMENSION SO THAT REFERENCE IS CORRECT W/N THE RECURSIVE CALL TO MAKALOOP!
1139 0           $loopparms{$j} = $eval0;
1140             #print "-!!!- regressing back to lp=$loopparms{$j}=\n";
1141             }
1142             }
1143             else
1144             {
1145 0           $loopparms{$j} = $parms->{$j};
1146             }
1147 0 0         $loopparms{$j} = '' unless(defined($loopparms{$j}));
1148             }
1149             else #PARM IS A SCALER, TAKE IT'S VALUE.
1150             {
1151 0           $loopparms{$j} = $parms->{$j};
1152             }
1153             }
1154             #print "
-???- ll=$looplabel= lc=$lc=\n";
1155             # (:# = CURRENT INDEX NUMBER INTO PARAMETER VECTORS; :* = ZERO-BASED ITERATION#; :% = CURRENT HASH KEY, IFF DRIVEN BY A HASHREF; :^ = NO. OF ITERATIONS TO BE DONE)
1156 0           $lc =~ s#<\!\:\%(${looplabel})([^>]*?)>#&makanop2($parms,$forlist[$i],$2)#egs; #MOVED HERE 20070713 FROM 267l TO MAKE :%_loopname HOLD KEY OF 1ST HASH!
  0            
1157 0           $lc =~ s/\:\%${looplabel}/$forlist[$i]/egs; #MOVED HERE 20070713 FROM 267l TO MAKE :%_loopname HOLD KEY OF 1ST HASH!
  0            
1158 0           $lc =~ s#<\!\:\#(${looplabel})([^>]*?)>#&makanop2($parms,$i,$2)#egs;
  0            
1159 0           $lc =~ s/\:\#${looplabel}([\+\-\*]\d+)/eval("$i$1")/egs; #ALLOW OFFSETS, ie. ":#+1"
  0            
1160 0           $lc =~ s/\:\#${looplabel}/$i/egs;
  0            
1161 0           $lc =~ s#<\!\:\^(${looplabel})([^>]*?)>#&makanop2($parms,$i0,$2)#egs;
  0            
1162 0           $lc =~ s/\:\^${looplabel}([\+\-\*]\d+)/eval("$i0$1")/egs; #CHGD. 20020926 FROM :* TO :^.
  0            
1163 0           $lc =~ s/\:\^${looplabel}/$i0/egs;
  0            
1164 0           $lc =~ s#<\!\:\*(${looplabel})([^>]*?)>#&makanop2($parms,$icnt,$2)#egs;
  0            
1165 0           $lc =~ s/\:\*${looplabel}([\+\-\*]\d+)/eval("$icnt$1")/egs; #ADDED 20020926 TO RETURN INCREMENT NUMBER (1ST = 0);
  0            
1166 0           $lc =~ s/\:\*${looplabel}/$icnt/egs;
  0            
1167             #foreach my $x (sort keys %loopparms) { print "
-loopparm($x)=$loopparms{$x}=\n"; };
1168             #print "
--------------\n";
1169              
1170             #IF-STMT BELOW ADDED 20070830 TO EMULATE Template::Toolkit's ABILITY TO REFERENCE
1171             #SUBCOMPONENTS OF A REFERENCE BY NAME, IE:
1172              
1173             #-arg => {'id' => 'value', 'name' => 'value'}
1174             #...
1175             #
1176 0 0         if (ref($parms->{$listparms[0]}) eq 'HASH')
    0          
1177             {
1178 0           foreach $j (@listparms)
1179             {
1180 0 0         unless (defined $loopparms{$j})
1181             {
1182             #print "
-!!!- will convert $j w/1st parm a HASH! i=$i= j=$j= F=$forlist[$i]= lp0=$listparms[0]= parm=$parms->{$listparms[0]}= val=$parms->{$listparms[0]}{$forlist[$i]}=\n";
1183 0           $lc =~ s#<\!\:$j([^>]*?)\:>.*?<\!\:\/\1>#&makanop1($parms->{$listparms[0]}{$forlist[$i]},$j,$1)#egs;
  0            
1184 0           $lc =~ s#<\!\:$j([^>]*?)>#&makanop1($parms->{$listparms[0]}{$forlist[$i]},$j,$1)#egs;
  0            
1185 0           $lc =~ s/\:\{$j\}/&makaswap($parms->{$listparms[0]}{$forlist[$i]},$j)/egs; #ALLOW ":{word}"!
  0            
1186             }
1187             }
1188             }
1189             elsif (ref($parms->{$listparms[0]}) eq 'ARRAY')
1190             {
1191 0           foreach $j (@listparms)
1192             {
1193 0 0         unless (defined $loopparms{$j})
1194             {
1195             #print "
-!!!- will convert $j w/1st parm an ARRAY! i=$i= j=$j= parm=$parms->{$listparms[0]}= val=$parms->{$listparms[0]}[$i]=\n";
1196 0           $lc =~ s#<\!\:$j([^>]*?)\:>.*?<\!\:\/\1>#&makanop1($parms->{$listparms[0]}[$i],$j,$1)#egs;
  0            
1197 0           $lc =~ s#<\!\:$j([^>]*?)>#&makanop1($parms->{$listparms[0]}[$i],$j,$1)#egs;
  0            
1198 0           $lc =~ s/\:\{$j\}/&makaswap($parms->{$listparms[0]}[$i],$j)/egs; #ALLOW ":{word}"!
  0            
1199             }
1200             }
1201             }
1202 0           $rtn .= &modhtml(\$lc,\%loopparms);
1203 0           ++$icnt;
1204             }
1205              
1206             # $i += $iinc; #NEXT 2 REMOVED 20070809 - DON'T APPEAR TO BE NEEDED.
1207             # ++$i0;
1208 0           return ($rtn);
1209             };
1210              
1211             sub makasel #JWT: REDONE 05/20/1999!
1212             {
1213 0     0 0   my ($parms, $selpart,$opspart,$endpart) = @_;
1214              
1215             local *makaselop = sub
1216             {
1217 0     0     my ($selparm,$padding,$valuparm,$valu,$dispvalu) = @_;
1218 0           $valu =~ s/\:\{?(\w+)\}?/&makaswap($parms,$1)/eg; #ADDED 19991206
  0            
1219 0           $dispvalu =~ s/\:\{?(\w+)\}?/&makaswap($parms,$1)/eg; #ADDED 19991206
  0            
1220 0 0         $valu = $dispvalu unless ($valuparm); #ADDED 05/17/1999
1221 0           my ($res) = "$padding
1222 0 0         if ($valuparm)
1223             {
1224 0           $res .= $valuparm . '"' . $valu . '"';
1225 0 0         $dispvalu = $valu . $dispvalu unless ($dispvalu =~ /\S/o);
1226             }
1227             else
1228             {
1229 0           $valu = $dispvalu;
1230 0           $valu =~ s/\s+$//o;
1231             }
1232 0           $res .= '>' . $dispvalu;
1233 0 0         if (ref($parms->{$selparm}) =~ /ARRAY/o) #JWT, IF SELECTED IS A LIST, CHECK ALL ELEMENTS!
1234             {
1235 0           my ($i);
1236 0           for ($i=0;$i<=$#{$parms->{$selparm}};$i++)
  0            
1237             {
1238 0 0         if ($valu eq ${$parms->{$selparm}}[$i])
  0            
1239             {
1240 0           $res =~ s/\
1241 0           last;
1242             }
1243             }
1244             }
1245             else
1246             {
1247 0 0         $res =~ s/\
1248             }
1249 0           return $res;
1250 0           };
1251              
1252             #my ($rtn) = $selpart; #CHGD TO NEXT LINE 05/17/1999
1253 0           my ($rtn);
1254             #if ($opspart =~ s/\s*\:(\w+)// || $selpart =~ s/\:(\w+)\s*>$//)
1255             #CHANGED 12/18/98 TO PREVENT 1ST OPTION VALUE :# FROM DISAPPEARING! JWT.
1256              
1257 0 0         if ($selpart =~ s/\:(\w+)\s*>$//o)
1258             {
1259 0           $selpart .= '>';
1260 0           my $selparm = $1;
1261 0           my ($opspart2);
1262 0           $opspart =~ s/SELECTED//gio;
1263 0           while ($opspart =~ s/(\s*)]*)?\s*\>([^<]*)//is)
1264             {
1265 0           $opspart2 .= &makaselop($selparm,$1,$2,$4,$5);
1266             }
1267 0           $opspart = $opspart2;
1268             }
1269 0           $rtn = $selpart . $opspart . $endpart;
1270 0           return ($rtn);
1271             };
1272              
1273             sub fetchinclude
1274             {
1275 0     0 0   my $parms = shift;
1276 0           my ($fidurl) = shift;
1277 0           my ($modhtmlflag) = shift;
1278 0           my $tag = shift;
1279 0           my %includeparms; #NEXT 6 ADDED 20030206 TO SUPPORT PARAMETERIZED INCLUDES!
1280 0           while (@_)
1281             {
1282 0           $_ = shift;
1283 0           $_ =~ s/\-//o;
1284 0           $includeparms{$_} = shift;
1285             }
1286              
1287 0           my ($html,$rtn);
1288              
1289             #$fidurl =~ s/\:(\w+)/&makaswap($1)/eg; #JWT 05/19/1999
1290 0           $fidurl =~ s/^\"//o; #JWT 5 NEXT LINES ADDED 1999/08/31.
1291 0           $fidurl =~ s/\"\s*$//o;
1292 0           $fidurl =~ s/\:\{?(\w+)\}?/&makaswap($parms,$1)/eg;
  0            
1293 0 0 0       if (defined($roothtmlhome) && $roothtmlhome =~ /\S/o)
1294             {
1295 0           $fidurl =~ s#^(?!(/|\w+\:))#$roothtmlhome/$1#ig;
1296             }
1297             #$fidurl =~ s/\:\{?(\w+)\}?/&makaswap($parms,$1)/eg; #JWT 20010703: MOVED ABOVE PREV. IF
1298 0 0         if (open(HTMLIN,$fidurl))
1299             {
1300 0           $html = ();
1301 0           close HTMLIN;
1302             }
1303             else
1304             {
1305 0 0         $html = LWP::Simple::get($fidurl) if ($useLWP);
1306 0 0 0       unless(defined($html) && $html =~ /\S/o)
1307             {
1308 0           $rtn = &html_error(">Could not include html page: \"$fidurl\"!");
1309 0           return ($rtn);
1310             }
1311             }
1312 0 0         if ($tag) #ADDED 20060117 TO ALLOW PARTIAL FILE INCLUDES BASED ON TAGS.
1313             {
1314 0 0         $html =~ s/^.*\<\!\-\-\s+BEGIN\s+$tag\s*\-\-\>//is or $html = '';
1315 0           $html =~ s#\<\!\-\-\s+END\s+$tag\s*\-\-\>.*$##is;
1316             }
1317             #$rtn = &modhtml(\$html, %parms); #CHGD. 20010720 TO HANDLE EMBEDS.
1318             #return ($rtn);
1319             #return $modhtmlflag ? &modhtml(\$html, %parms) : $html; #CHD 20030206 TO SUPPORT PARAMETERIZED INCLUDES.
1320 0 0         return $modhtmlflag ? &modhtml(\$html, {%{$parms}, %includeparms}) : $html;
  0            
1321             };
1322              
1323             sub doeval
1324             {
1325 0     0 0   my ($expn) = shift;
1326 0           my ($fid) = shift;
1327 0 0         if ($fid)
1328             {
1329 0           my ($dfltexpn) = $expn;
1330 0           $fid =~ s/^\s+//o;
1331 0           $fid =~ s/^.*\=\s*//o;
1332 0           $fid =~ s/[\"\']//go;
1333 0           $fid =~ s/\s+$//o;
1334 0 0         if (open(HTMLIN,$fid))
1335             {
1336 0           my @expns = ();
1337 0           $expn = join('', @expns);
1338 0           close HTMLIN;
1339             }
1340             else
1341             {
1342 0 0         $expn = LWP::Simple::get($fid) if ($useLWP);
1343 0 0 0       unless (defined($expn) && $expn =~ /\S/o)
1344             {
1345 0           $expn = $dfltexpn;
1346 0 0         return (&html_error("Could not load embedded perl file: \"$fid\"!"))
1347             unless ($dfltexpn =~ /\S/o);
1348             }
1349             }
1350             }
1351 0           $expn =~ s/^\s*\s*$//o;
1353 0 0         return ('') if ($expn =~ /\`/o); #DON'T ALLOW GRAVS!
1354             # return ('') if ($expn =~ /\Wsystem\W/o); #DON'T ALLOW SYSTEM CALLS - THIS NOT GOOD WAY TO DETECT!
1355              
1356 0           $expn =~ s/\>/>/go;
1357 0           $expn =~ s/\</
1358              
1359 0           $expn = 'package htmlpage; ' . $expn;
1360 0           my $x = eval "$expn";
1361 0 0         $x = "Invalid Perl Expression - returned $@" unless (defined $x);
1362 0           return ($x);
1363             };
1364              
1365             sub dovar
1366             {
1367 0     0 0   my $var = shift;
1368 0           my $two = shift;
1369 0           $two =~ s/^=//o;
1370             #$var = substr($var,0,1) . 'main::' . substr($var,1) unless ($var =~ /\:\:/);
1371             #PREV. LINE CHANGED 2 NEXT LINE 20000920 TO ALLOW EVALS IN ASP!
1372             #$var = substr($var,0,1) . $calling_package . '::' . substr($var,1) unless ($var =~ /\:\:/);
1373             #PREV. LINE CHGD. TO NEXT 20031006 TO FIX "${$VAR}...".
1374 0           $var =~ s/\$(\w)/\$$calling_package\:\:$1/g;
1375 0           my $one = eval $var;
1376 0 0         $one = $two unless ($one);
1377 0           return $one;
1378             };
1379              
1380             sub makabutton
1381             {
1382 0     0 0   my ($parms,$pre,$one,$two,$parmno,$four) = @_;
1383 0           my ($rtn) = "$pre$one$two$parmno$four";
1384 0           my ($myvalue);
1385              
1386             local *setbtnval = sub
1387             {
1388 0     0     my ($one,$two,$three) = @_;
1389             #$two =~ s/\:(\w+)/&makaswap($parms,$1)/eg; #CHGD 19990527. JWT.
1390 0           $two =~ s/\:\{?(\w+)\}?/&makaswap($parms,$1)/eg;
  0            
1391 0           $myvalue = "$two";
1392 0           return ($one.$two.$three);
1393 0           };
1394 0 0 0       if ($two =~ /VALUE\s*=\"[^\"]*\"/io || $one =~ /CHECKBOX/io)
1395             {
1396 0           $two =~ s/(VALUE\s*=\")([^\"]*)(\")/&setbtnval($1,$2,$3)/ei;
  0            
1397 0           $rtn = "$pre$one$two$parmno$four";
1398             # $rtn =~ s/CHECKED//i if (defined($myvalue)); #JWT:CHGD. TO NEXT: 19990609!
1399             # $rtn =~ s/CHECKED//io if (defined($parms->{$parmno})); #JWT:CHGD. TO NEXT: 20100830 (v7.05)!
1400 0 0         $rtn =~ s/\bCHECKED\b//io if (defined($parms->{$parmno}));
1401             #if ((defined($myvalue) && $parms->{$parmno} eq $myvalue) || ($one =~ /CHECKBOX/i && $parms->{$parmno} =~ /\S/))
1402 0 0 0       if (ref($parms->{$parmno}) eq 'ARRAY') #NEXT 9 LINES ADDED 20000823
    0 0        
      0        
      0        
      0        
1403             { #TO FIX CHECKBOXES W/SAME NAME
1404 0           foreach my $i (@{$parms->{$parmno}}) #IN LOOPS!
  0            
1405             {
1406 0 0         if ($i eq $myvalue)
1407             {
1408 0           $rtn =~ s/\:$parmno/ CHECKED/;
1409 0           last;
1410             }
1411             }
1412 0           $rtn =~ s/\:$parmno//;
1413             }
1414             #elsif ((defined($parms->{$parmno}) && defined($myvalue) && $parms->{$parmno} eq $myvalue) || ($one =~ /CHECKBOX/i && $parms->{$parmno} =~ /\S/)) #JWT: 19990609! - CHGD. 2 NEXT 20041020!
1415             elsif ((defined($parms->{$parmno}) && defined($myvalue) && $parms->{$parmno} eq $myvalue) || (!defined($myvalue) && $one =~ /CHECKBOX/io && $parms->{$parmno} =~ /\S/o))
1416             { #NOTE: IF NO "VALUE=" IS SPECIFIED, THEN CHECKED UNLESS PARAMETER IS EMPTY/UNDEFINED!!
1417 0           $rtn =~ s/\:$parmno/ CHECKED/;
1418             }
1419             else
1420             {
1421 0           $rtn =~ s/\:$parmno//;
1422             }
1423             #print "
-loadhtml: myvalue=$myvalue= parmno=$parmno= parmval=".$parms->{$parmno}."= rtn=$rtn=\n";
1424             }
1425             else
1426             {
1427 0           $rtn =~ s/\:$parmno//;
1428             }
1429 0           return ($rtn);
1430             };
1431              
1432             sub makatext
1433             {
1434 0     0 0   my $parms = shift;
1435 0           my $one = shift;
1436 0           my $parmno = shift;
1437 0           my $dflt = shift;
1438              
1439 0           my $val;
1440 0           my $rtn = $one;
1441 0 0         if (defined($parms->{$parmno}))
    0          
1442             {
1443 0           $val = $parms->{$parmno};
1444             }
1445             elsif ($dflt =~ /\S/o)
1446             {
1447 0           $dflt =~ s/^\=//o;
1448 0           $dflt =~ s/\"(.*?)\"/$1/;
1449 0           $val = $dflt;
1450             }
1451 0 0         if (defined($val))
1452             {
1453 0 0         if ($rtn =~ /\sVALUE\s*\=/io)
1454             {
1455 0           $rtn =~ s/(\sVALUE\s*=\s*\").*?\"/$1 . $val . '"'/ei;
  0            
1456             }
1457             else
1458             {
1459 0           $rtn = $one . ' VALUE="' . $val . '"';
1460             }
1461             }
1462 0           return ($rtn);
1463             };
1464              
1465             sub makanif
1466             {
1467 0     0 0   my ($parms,$regex,$ifhtml,$nestid) = @_;
1468              
1469 0           my ($x) = '';
1470 0           my ($savesep) = $listsep;
1471              
1472 0           $regex =~ s/\</
1473 0           $regex =~ s/\>/>/gio;
1474 0           $regex =~ s/\&le/<=/gio;
1475 0           $regex =~ s/\&ge/>=/gio;
1476 0           $regex =~ s/\\\%/\%/gio;
1477 0           $listsep = undef;
1478              
1479 0           $regex =~ s/([\'\"])(.*?)\1/
1480 0           my ($q, $body) = ($1, $2);
1481 0 0         $body =~ s!\:\{?(\w+)\}?!defined($parms->{$1}) ? &makaswap($parms,$1) : ''!eg;
  0            
1482 0           $body =~ s!\:!\:\x02!go; #PROTECT AGAINST MULTIPLE SUBSTITUTION!
1483 0           $q.$body.$q;
1484             /eg;
1485              
1486             #$regex =~ s/\:\{?(\w+)\}?/defined($parms->{$1}) ? '"'.&makaswap($parms,$1).'"' : '""'/eg;
1487              
1488             #PREV. LINE REPLACED BY NEXT REGEX 20000309 TO QUOTE DOUBLE-QUOTES IN PARM. VALUE.
1489 0           $regex =~ s/\:\{?(\w+)\}?/
1490 0           my ($one) = $1;
1491 0           my ($res) = '""';
1492 0 0         if (defined($parms->{$one}))
1493             {
1494 0           $res = &makaswap($parms,$1);
1495 0           $res =~ s!\"!\\\"!go;
1496 0           $res = '"'.$res.'"';
1497             }
1498             $res
1499 0           /eg;
1500 0           $regex =~ s/\x02//go; #UNPROTECT!
1501 0 0         $regex =~ s/\:([\$\@\%][\w\:\[\{\]\}\$]+)/&dovar($1)/egs if ($evalsok);
  0            
1502             #$regex =~ s/\:([\$\@\%][\w\:\[\{\]\}\$\-\>]+)/&dovar($1)/egs if ($evalsok);
1503              
1504 0           $regex =~ /^([^`]*)$/o; #MAKE SURE EXPRESSION CONTAINS NO GRAVS!
1505 0           $regex = $1; #20000626 UNTAINT REGEX FOR EVAL!
1506 0           $regex =~ s/([\@\#\$\%])([a-zA-Z_])/\\$1$2/g; #QUOTE ANY SPECIAL PERL CHARS!
1507             #$regex =~ s/\"\"\:\w+\"\"/\"\"/g; #FIX QUOTE BUG -FORCE UNDEFINED PARMS TO RETURN FALSE!
1508 0           $regex = '$x = ' . $regex . ';';
1509 0           eval $regex;
1510 0           $listsep = $savesep;
1511              
1512 0           my ($ifhtml1,$ifhtml2) = split(/<\!ELSE$nestid>\s*/i,$ifhtml);
1513 0 0         if ($x)
1514             {
1515 0 0         if (defined $ifhtml1)
1516             {
1517 0           $ifhtml1 =~ s#^(\s*)<\!\-\-(.*?)\-\->(\s*)$#$1$2$3#s;
1518 0           return ($ifhtml1);
1519             }
1520             else
1521             {
1522 0           return ('');
1523             }
1524             }
1525             else
1526             {
1527 0 0         if (defined $ifhtml2)
1528             {
1529 0           $ifhtml2 =~ s#^(\s*)<\!\-\-(.*?)\-\->(\s*)$#$1$2$3#s;
1530 0           return ($ifhtml2);
1531             }
1532             else
1533             {
1534 0           return ('');
1535             }
1536             }
1537             };
1538              
1539             sub makanop1
1540             {
1541             #
1542             # SUBSTITUTIONS IN COMMENTS TAKE THE ONE OF THE FORMS:
1543             # remove ... OR
1544             #
1545             # where: "#"=Parameter number to substitute.
1546             # "default"=Optional default value to use if parameter
1547             # is empty or omitted.
1548             # "stuff to remove" is removed.
1549             #
1550             # NOTES: ONLY 1 SUCH COMMENT MAY APPEAR PER LINE,
1551             # THE DEFAULT, BEFORE-STUFF AND AFTER-STUFF MUST FIT ON ONE LINE.
1552             # DUE TO HTML LIMITATIONS, ANY ">" BETWEEN THE "[...]" MUST BE
1553             # SPECIFIED AS ">"!
1554             #
1555             # THIS IS VERY USEFUL FOR SUBSTITUTING WHERE HTML WILL NOT ACCEPT
1556             # COMMENTS, EXAMPLE:
1557             #
1558             #
1559             #
1560             #
1561             #
1562             # THIS CAUSES A SUBMIT BUTTON WITH THE WORDS "Create Record" TO
1563             # BE DISPLAYED IF PAGE IS JUST DISPLAYED, "Add Record" if loaded
1564             # by loadhtml() (CGI) but no argument passed. NOTE the use of
1565             # ">" instead of ">" since HTML terminates comments with ">"!!!!
1566             #
1567              
1568 0     0 0   my $parms = shift;
1569 0           my $one = shift;
1570 0           my $two = shift;
1571 0           my ($rtn) = '';
1572 0           my ($picture);
1573 0 0         $picture = $1 if ($two =~ s/\%(.*)\%//o);
1574             #$three = shift;
1575 0           my $three = ''; ##NEXT 3 LINES REP. PREV. LINE 5/14/98 JWT!
1576 0           $two =~ s/^=//o;
1577 0           $two =~ s/([^\[]*)(\[.*\])?/$three = $2; $1/e;
  0            
  0            
1578             #$two =~ s/^=//; #MOVED UP 2 LINES 20050523!
1579             #print "-???- 1=$one= 2=$two= parms=$parms=\n";
1580 0 0 0       return ($two) unless(defined($one) && ref($parms) eq 'HASH' && defined($parms->{$one}) && "\Q$parms->{$one}\E");
      0        
      0        
1581 0 0         if (defined($three) ? ($three =~ s/^\[(.*?)\]/$1/) : 0)
    0          
    0          
1582             {
1583             #$three =~ s/\:(\w+)/(${parms{$1}}||$two)/egx; #JWT 19990611
1584 0 0         $three =~ s/\:(\w+)/(&makaswap($parms,$1)||$two)/egx;
  0            
1585 0           $three =~ s/\>/>/go;
1586 0           $rtn = $three;
1587             }
1588             elsif ($picture) #ALLOW "<:1%10.2f%...> (SPRINTF) FORMATTING!
1589             {
1590 0 0         if ($picture =~ s/^&(.*)/$1/)
1591             {
1592 0           my ($picfn) = $1;
1593 0           $picfn =~ s/\:\{?(\w+)\}?/&makaswap($parms,$1)/eg; #ADDED 20050517 TO ALLOW "%&:{alt_package}::commatize%"
  0            
1594 0 0         $picfn = $calling_package . '::' . $picfn #ADDED 20050517 TO DEFAULT PACKAGE OF commatize TO MAIN RATHER THAN "LoadHtml"!
1595             unless ($picfn =~ /\:\:/o);
1596             # my (@args) = undef; #CHGD. TO NEXT 20070426 TO PREVENT WARNING.
1597 0           my (@args) = ();
1598 0 0         (@args) = split(/\,/o,$1) if ($picfn =~ s/\((.*)\)//o);
1599 1     1   8 no strict 'refs';
  1         1  
  1         381  
1600             # if (defined(@args)) #CHGD. TO NEXT 20070426 TO PREVENT WARNING.
1601 0 0         if (@args)
1602             {
1603 0           for my $j (0..$#args)
1604             {
1605 0           $args[$j] =~ s/\:(\w+)/&makaswap($parms,$1)/egs;
  0            
1606             }
1607             #$rtn = &{$picfn}((${parms{$one}}||$two), @args); #JWT 19990611
1608 0   0       $rtn = &{$picfn}((&makaswap($parms,$one)||$two), @args);
  0            
1609             }
1610             else
1611             {
1612             #$rtn = &{$picfn}(${parms{$one}}||$two); #JWT 19990611
1613 0   0       $rtn = &{$picfn}(&makaswap($parms,$one)||$two);
  0            
1614             }
1615             }
1616             else
1617             {
1618             #$rtn = sprintf("%$picture",(${parms{$one}}||$two)); #JWT 19990611
1619 0   0       $rtn = sprintf("%$picture",(&makaswap($parms,$one)||$two));
1620             }
1621             }
1622             else
1623             {
1624             #$rtn = ${parms{$one}}||$two; #JWT 19990611
1625 0   0       $rtn = &makaswap($parms,$one)||$two;
1626             }
1627 0           return ($rtn);
1628             };
1629              
1630             sub makanop2
1631             {
1632             #
1633             # SUBSTITUTIONS IN COMMENTS TAKE THE ONE OF THE FORMS:
1634             # remove ... OR
1635             #
1636             # ADDED 20070713
1637              
1638 0     0 0   my $parms = shift;
1639 0           my $one = shift;
1640 0           my $two = shift;
1641              
1642 0           my ($rtn) = '';
1643             #print "
-!!!- makanop2($one|$two)\n";
1644 0           my ($picture);
1645 0 0         $picture = $1 if ($two =~ s/\%(.*)\%//o);
1646             #$three = shift;
1647 0           my $three = ''; ##NEXT 3 LINES REP. PREV. LINE 5/14/98 JWT!
1648 0           $two =~ s/^=//o;
1649 0 0         if ($picture) #ALLOW "<:1%10.2f%...> (SPRINTF) FORMATTING!
1650             {
1651 0 0         if ($picture =~ s/^&(.*)/$1/)
1652             {
1653 0           my ($picfn) = $1;
1654 0           $picfn =~ s/\:\{?(\w+)\}?/&makaswap($parms,$1)/eg; #ADDED 20050517 TO ALLOW "%&:{alt_package}::commatize%"
  0            
1655 0 0         $picfn = $calling_package . '::' . $picfn #ADDED 20050517 TO DEFAULT PACKAGE OF commatize TO MAIN RATHER THAN "LoadHtml"!
1656             unless ($picfn =~ /\:\:/o);
1657 0           my (@args) = ();
1658 0 0         (@args) = split(/\,/o,$1) if ($picfn =~ s/\((.*)\)//o);
1659 1     1   7 no strict 'refs';
  1         1  
  1         229  
1660 0 0         if (@args)
1661             {
1662 0           for my $j (0..$#args)
1663             {
1664 0           $args[$j] =~ s/\:(\w+)/&makaswap($parms,$1)/egs;
  0            
1665             }
1666             #$rtn = &{$picfn}((${parms{$one}}||$two), @args); #JWT 19990611
1667 0           $rtn = &{$picfn}($one, @args);
  0            
1668             }
1669             else
1670             {
1671             #$rtn = &{$picfn}(${parms{$one}}||$two); #JWT 19990611
1672 0           $rtn = &{$picfn}($one);
  0            
1673             }
1674             }
1675             else
1676             {
1677             #$rtn = sprintf("%$picture",(${parms{$one}}||$two)); #JWT 19990611
1678 0           $rtn = sprintf("%$picture",$one);
1679             }
1680             }
1681             else
1682             {
1683 0           $rtn = $one;
1684             }
1685 0           return ($rtn);
1686             };
1687              
1688             sub buildahash
1689             {
1690 0     0 0   my ($one,$two) = @_;
1691              
1692 0           $two =~ s/^\s*\s*$//o;
1694 0           $two =~ s/^\s*\(//o;
1695 0           $two =~ s/\)\s*$//o;
1696 1     1   9 no strict 'refs';
  1         2  
  1         83  
1697             #$evalstr = "\%h1_myhash = ($two)";
1698 0           my $evalstr = "\%{\"h1_$one\"} = ($two)";
1699 0           my $x = eval $evalstr;
1700 0           return ('');
1701             };
1702              
1703             sub makahash
1704             {
1705             #
1706             # FORMAT:
1707              
1708 0     0 0   my ($one,$two,$three) = @_;
1709 1     1   5 no strict 'refs';
  1         2  
  1         2898  
1710 0 0         return (${"h1_$one"}{$two}) if (defined(${"h1_$one"}{$two}));
  0            
  0            
1711 0           return $three;
1712             };
1713              
1714             sub makaselect
1715             {
1716             #
1717             # FORMAT: ..stuff to remove...
1718             # ...
1719             # ...
1720             #
1721             # NOTE: "select-options" MAY CONTAIN "default="value"" AND "value"
1722             # MAY ALS0 BE A SCALER PARAMETER. THE LIST PARAMETER MUST BE AT
1723             # THE END JUST BEFORE THE ">" WITH NO SPACE IN BETWEEN!
1724             # THESE COMMENTS AND ANYTHING IN BETWEEN GETS REPLACED BY A SELECT-
1725             # LISTBOX CONTAINING THE ITEMS CONTAINED IN THE LIST REFERENCED BY
1726             # PARAMETER NUMBER "#". (PASS AS "\@list").
1727             # "select_options" MAY ALSO CONTAIN A "value=:#" PARAMETER
1728             # SPECIFYING A SECOND LIST PARAMETER TO BE USED FOR THE ACTUAL
1729             # VALUES. DEFAULTS TO SAME AS DISPLAYED LIST IF OMITTED.
1730             # SPECIFYING A SCALAR OR LIST PARAMETER OR VALUE FOR "DEFAULT[SEL]="
1731             # CAUSES VALUES WHICH MATCH THIS(THESE) VALUES TO BE SET TO SELECTED
1732             # BY DEFAULT WHEN THE LIST IS DISPLAYED. DEFAULT= MATCHES THE
1733             # DEFAULT LIST AGAINST THE VALUES= LIST, DEFAULTSEL= MATCHES THE
1734             # DEFAULT LIST AGAINST THE *DISPLAYED* VALUES LIST (IF DIFFERENT).
1735             # IF USING A HASH, BY DEFAULT IT IS CHARACTER SORTED BY KEY, IF
1736             # "BYVALUE" IS SPECIFIED, IT IS SORTED BY DISPLAYED VALUE. "REVERSE"
1737             # CAUSES THE HASH OR LIST(S) TO BE DISPLAYED IN REVERSE ORDER.
1738             #
1739 0     0 0   my$parms = shift;
1740 0           my ($one) = shift;
1741 0           my ($two) = shift;
1742 0           my ($rtn) = '';
1743 0           my ($dflttype) = 'DEFAULT';
1744 0           my ($dfltval) = '';
1745 0           my (%dfltindex) = ('DEFAULT' => 'value', 'DEFAULTSEL' => 'sel');
1746              
1747             #@value_options = ();
1748             #@sel_options = ();
1749 0           my $options;
1750 0 0         if (ref($parms->{$two}) eq 'HASH')
1751             {
1752             #1ST PART OF NEXT IF ADDED 20031124 TO SUPPORT BOTH VALUE ARRAY AND DESCRIPTION HASH.
1753 0 0         if ($one =~ s/value[s]?=(\")?:(\w+)\1?//i)
    0          
1754             {
1755 0           @{$options->{value}} = @{$parms->{$2}};
  0            
  0            
1756 0           foreach my $i (@{$options->{value}})
  0            
1757             {
1758 0           push (@{$options->{sel}}, ${$parms->{$two}}{$i});
  0            
  0            
1759             }
1760             }
1761             elsif ($one =~ s/BYVALUE//io)
1762             {
1763 0           foreach my $i (sort {$parms->{$two}->{$a} cmp $parms->{$two}->{$b}} (keys(%{$parms->{$two}}))) #JWT: SORT'EM (ALPHA).
  0            
  0            
1764             {
1765 0           push (@{$options->{value}}, $i);
  0            
1766 0           push (@{$options->{sel}}, ${$parms->{$two}}{$i});
  0            
  0            
1767             }
1768             }
1769             else
1770             {
1771 0           $one =~ s/BYKEY//io;
1772 0           foreach my $i (sort(keys(%{$parms->{$two}}))) #JWT: SORT'EM (ALPHA).
  0            
1773             {
1774 0           push (@{$options->{value}}, $i);
  0            
1775 0           push (@{$options->{sel}}, ${$parms->{$two}}{$i});
  0            
  0            
1776             }
1777             }
1778             }
1779             else
1780             {
1781 0           @{$options->{sel}} = @{$parms->{$two}};
  0            
  0            
1782              
1783             #NEXT 9 LINES (IF-OPTION) ADDED 20010410 TO ALLOW "VALUE=:#"!
1784 0 0         if ($one =~ s/value[s]?=(\")?:(\#)([\+\-\*]\d+)?\1?//i)
    0          
    0          
1785             {
1786 0           my ($indx) = $3;
1787 0           $indx =~ s/\+//o;
1788 0           for (my $i=0;$i<=$#{$options->{sel}};$i++)
  0            
1789             {
1790 0           push (@{$options->{value}}, $indx++);
  0            
1791             }
1792             }
1793             elsif ($one =~ s/value[s]?=(\")?:(\w+)\1?//i)
1794             {
1795 0           @{$options->{value}} = @{$parms->{$2}};
  0            
  0            
1796             }
1797             elsif ($one =~ s/value[s]?\s*=\s*(\")?:\#([\+\-\*]\d+)?\1?//i)
1798             {
1799             #JWT(ALLOW "VALUE=:# TO SPECIFY USING NUMERIC ARRAY-INDICES OF
1800             #LIST TO BE USED AS ACTUAL VALUES.
1801 0           for my $i (0..$#{$options->{sel}})
  0            
1802             {
1803 0           push (@{$options->{value}}, eval("$i$2"));
  0            
1804             }
1805             }
1806             else
1807             {
1808 0           @{$options->{value}} = @{$options->{sel}};
  0            
  0            
1809             }
1810             }
1811 0 0         if ($one =~ s/REVERSED?//io)
1812             {
1813 0           @{$options->{sel}} = reverse(@{$options->{sel}});
  0            
  0            
1814 0           @{$options->{value}} = reverse(@{$options->{value}});
  0            
  0            
1815             }
1816              
1817             #$one =~ s/default=\"(.*?)\"//i;
1818             #$one =~ s/default=\"(.*?)\"//i;
1819             #if ($one =~ s/(default|defaultsel)=\"(.*?)\"//i) #20000505: CHGD 2 NEXT 2 LINES 2 MAKE QUOTES OPTIONAL!
1820 0 0 0       if (($one =~ s/(default|defaultsel)\s*=\s*\"(.*?)\"//io)
1821             || ($one =~ s/(default|defaultsel)\s*=\s*(\:?\S+)//io)) #20000505: CHGD 2 NEXT LINE 2 MAKE QUOTES OPTIONAL!
1822             {
1823 0           $dflttype = $1;
1824 0           $dfltval = $2;
1825 0           $dflttype =~ tr/a-z/A-Z/;
1826             #$dfltval =~ s/\:(\w+)/
1827 0           $dfltval =~ s/\:\{?(\w+)\}?/
1828 0 0         if (ref($parms->{$1}) eq 'ARRAY')
1829             {
1830 0           '(?:'.join('|',@{$parms->{$1}}).')'
  0            
1831             }
1832             else
1833             {
1834 0           quotemeta($parms->{$1})
1835             }
1836             /eg;
1837             }
1838             #$one =~ s/\:(\w+)/$parms->{$1}/g;
1839 0           $one =~ s/\:\{?(\w+)\}?/$parms->{$1}/g; #JWT 05/24/1999
1840 0           $rtn = "
1841 0           $one = $dfltval;
1842 0           for (my $i=0;$i<=$#{$options->{sel}};$i++)
  0            
1843             {
1844             #if (${$options->{value}}[$i] =~ /^\Q${one}\E$/)
1845             # if (${($dfltindex{$dflttype}.'_options')}[$i] =~ /^${one}$/)
1846 0 0         if (${$options->{$dfltindex{$dflttype}}}[$i] =~ /^${one}$/)
  0            
1847             {
1848 0           $rtn .= "\n";
  0            
  0            
1849             }
1850             else
1851             {
1852 0           $rtn .= "\n";
  0            
  0            
1853             }
1854             }
1855 0           $rtn .= '';
1856 0           return ($rtn);
1857             };
1858              
1859             sub modhtml
1860             {
1861 0     0 0   my ($html, $parms) = @_;
1862 0           my ($v);
1863              
1864             #NOW FOR THE REAL MAGIC (FROM ANCIENT EGYPTIAN TABLETS)!...
1865              
1866 0 0         if ($cfgOps{loops})
1867             {
1868 0           while ($$html =~ s#<\!LOOP(\S*)\s+(.*?)>\s*(.*?)<\!/LOOP\1>\s*#&makaloop($parms, $2,$3,$1)#eis) {};
  0            
1869             }
1870              
1871 0           $$html =~ s#<\!HASH\s+(\w*?)\s*>(.*?)<\!\/HASH[^>]*>\s*#&buildahash($1,$2)#eigs
1872 0 0         if ($cfgOps{hashes});
1873              
1874             $$html =~ s##\n#i
1875 0 0         if ($cfgOps{CGIScript});
1876              
1877             #$$html =~ s#<\!INCLUDE\s+(.*?)>\s*#&fetchinclude($parms, $1)#eigs #CHGD. TO NEXT 20010720 TO SUPPORT EMBEDS.
1878             $$html =~ s!<\!INCLUDE\s+(.*?)>\s*!
1879 0           my $one = $1;
1880 0           $one =~ s/^\"//o;
1881 0           $one =~ s/\"\s*$//o;
1882 0           my $tag = 0;
1883 0 0         $tag = $1 if ($one =~ s/\:(\w+)//o); #ADDED 20060117 TO ALLOW PARTIAL FILE INCLUDES BASED ON TAGS.
1884 0 0         if ($one =~ s/\((.*)\)\s*$//)
1885             {
1886 0           my $includeparms = $1;
1887 0           $includeparms =~ s/\=/\=\>/go;
1888 0           eval "&fetchinclude($parms, \"$one\", 1, $tag, $includeparms)";
1889             }
1890             else
1891             {
1892 0           &fetchinclude($parms, $one, 1, $tag);
1893             }
1894 0 0         !eigs if ($cfgOps{includes});
1895              
1896 0 0         if ($cfgOps{pocs})
1897             {
1898 0 0         $$html =~ s#<\!POC:>(.*?)<\!/POC>#$poc#ig if ($cfgOps{pocs}); #20000606
1899 0 0         $$html =~ s#<\!POC>#$poc#ig if ($cfgOps{pocs});
1900             }
1901              
1902 0           $$html =~ s#\<\!FILEDATE([^\>]*?)\:\>.*?\<\!\/FILEDATE\>#&filedate($parms,$1,0)#eig; #20020327
  0            
1903 0           $$html =~ s#\<\!FILEDATE([^\>]*)\>#&filedate($parms,$1,0)#eig; #20020327
  0            
1904 0           $$html =~ s#\<\!TODAY([^\>]*?)\:\>.*?\<\!\/TODAY\>#&filedate($parms,$1,1)#eig; #20020327
  0            
1905 0           $$html =~ s#\<\!TODAY([^\>]*)\>#&filedate($parms,$1,1)#eig; #20020327
  0            
1906              
1907 0           while ($$html =~ s#<\!IF(\S*)\s+(.*?)>\s*(.*?)<\!/IF\1>\s*#&makanif($parms, $2,$3,$1)#eigs) {};
  0            
1908              
1909 0           $$html =~ s#<\!\:(\w+)([^>]*?)\:>.*?<\!\:\/\1>#&makanop1($parms,$1,$2)#egs;
  0            
1910 0           $$html =~ s#<\!\:(\w+)([^>]*?)>#&makanop1($parms,$1,$2)#egs;
  0            
1911             #JWT:CHGD. TO NEXT 20100920 TO ALLOW STYLES IN SELECT TAG! $$html =~ s#(]*?\:\w+\s*>)(.*?)(<\/SELECT>)#&makasel($parms, $1,$2,$3)#eigs;
1912 0           $$html =~ s#(]*\>)(.*?)(<\/SELECT>)#&makasel($parms, $1,$2,$3)#eigs;
  0            
1913 0           $$html =~ s#<\!SELECTLIST\s+(.*?)\:(\w+)\s*>(.*?)<\!\/SELECTLIST>\s*#&makaselect($parms, $1,$2,$3)#eigs;
  0            
1914              
1915 0   0       $$html =~ s#(]*?)\:(\w+)(?:\=([\"\']?)([^\3]*)\3|\>)?\s*>.*?(<\/TEXTAREA>)#$1.'>'.($parms->{$2}||$4).$5#eigs;
  0            
1916 0           $$html =~ s/(TYPE\s*=\s*\"?)(CHECKBOX|RADIO)([^>]*?\:)(\w+)(\s*>)/&makabutton($parms,$1,$2,$3,$4,$5)/eigs;
  0            
1917 0           $$html =~ s/(<\s*INPUT[^\<]*?)\:(\w+)(\=.*?)?>/&makatext($parms, $1,$2,$3).'>'/eigs;
  0            
1918 0           $$html =~ s/\:(\d+)/&makaswap($parms,$1)/egs
1919 0 0         if ($cfgOps{numbers}); #STILL ALLOW JUST ":number"!
1920 0           $$html =~ s/\:\{(\w+)\}/&makaswap($parms,$1)/egs; #ALLOW ":{word}"!
  0            
1921 0           $$html =~ s#<\!\%(\w+)\s*\{([^\}]*?)\}([^>]*?)>#&makahash($1,$2,$3)#egs
1922 0 0         if ($cfgOps{hashes});
1923             # $$html =~ s/\:\{(\w+)\}/&makaswap($parms,$1)/egs; #ALLOW ":{word}"! #MOVED ABOVE PREV. LINE 20070428 SO "" WOULD WORK (USED IN "dsm")!
1924              
1925             #NEXT LINE ADDED 20031028 TO ALLOW IN-PARM EXPRESSIONS!
1926 0           $$html =~ s/\:\{([^\}]+)\}/&makamath($1)/egs; #ALLOW STUFF LIKE ":{:{parm1}+:{parm2}+3}"!
  0            
1927 0 0         if ($evalsok)
1928             {
1929 0           $$html =~ s#<\!\:([\$\@\%][\w\:]+\{.*?\})([^>]*?)\:>.*?<\!\:\/\1>#&dovar($1,$2)#egs; #ADDED 20000123 TO HANDLE HASHES W/NON VARIABLE CHARACTERS IN KEYS.
  0            
1930 0           $$html =~ s#<\!\:(\$[\w\:\[\{\]\}\$]+)([^>]*?)\:>.*?<\!\:\/\1>#&dovar($1,$2)#egs;
  0            
1931 0           $$html =~ s#<\!\:([\$\@\%][\w\:]+\{.*?\})([^>]*?)>#&dovar($1,$2)#egs; #ADDED 20000123 TO HANDLE HASHES W/NON VARIABLE CHARACTERS IN KEYS.
  0            
1932 0           $$html =~ s#<\!\:(\$[\w\:\[\{\]\}\$]+)([^>]*?)>#&dovar($1,$2)#egs;
  0            
1933 0           $$html =~ s/\:(\$[\w\:\[\{\]\}\$]+)/&dovar($1)/egs;
  0            
1934 0           $$html =~ s/<\!EVAL\s+(.*?)(?:\/EVAL)?>/&doeval($1)/eigs;
  0            
1935 0 0         $$html =~ s#<\!PERL\s*([^>]*)>\s*(.*?)<\!\/PERL>#&doeval($2,$1)#eigs if ($cfgOps{perls});
  0            
1936             }
1937             else
1938             {
1939 0           $$html =~ s#]*)>(.*?)##igso;
1940             };
1941              
1942             #THE FOLLOWING ALLOWS SETTING ' HREF="relative/link.htm" TO
1943             #A CGI-WRAPPER, IE. ' HREF="http://my/path/cgi-bin/myscript.pl?relative/link.htm".
1944              
1945 0 0         if (defined($hrefhtmlhome))
1946             {
1947             # my $hrefhtmlback = $hrefhtmlhome;
1948             # $hrefhtmlback =~ s#\/[^\/]+$##o;
1949 0 0         if (defined($hrefcase)) #THIS ALLOWS CONTROL OF WHICH "href=" LINKS TO WRAP WITH CGI!
1950             {
1951 0 0         if ($hrefcase eq 'l') #ONLY CONVERT LOWER-CASE "href=" LINKS THIS WAY.
1952             {
1953 0           $$html =~ s# (href)\s*=\s*\"(?!(\#|/|\w+\:))# $1=\"$hrefhtmlhome/$2#g; #ADDED HREF ON 20010719!
1954             }
1955             else #ONLY CONVERT UPPER-CASE "HREF=" LINKS THIS WAY.
1956             {
1957 0           $$html =~ s# (HREF)\s*=\s*\"(?!(\#|/|\w+\:))# $1=\"$hrefhtmlhome/$2#g; #ADDED HREF ON 20010719!
1958             }
1959             }
1960             else #CONVERT ALL "HREF=" LINKS THIS WAY.
1961             {
1962 0           $$html =~ s#( href)\s*=\s*\"(?!(\#|/|\w+\:))# $1=\"$hrefhtmlhome/$2#gi; #ADDED HREF ON 20010719!
1963             #$$html =~ s# (href)\s*=\s*\"(?!(\#|/|\w+\:))# $1=\"$hrefhtmlhome/\x02$2#gi; #ADDED HREF ON 20010719!
1964             }
1965              
1966             #RECURSIVELY CONVERT "my/deep/deeper/../../path" to "my/path".
1967              
1968             }
1969 0 0 0       if (defined($htmlhome) && $htmlhome =~ /\S/o) #JWT 6 NEXT LINES ADDED 1999/08/31.
1970             {
1971 0           $$html =~ s#([\'\"])((?:\.\.\/)+)#$1$htmlhome/$2#ig; #INSERT between '|" and "../[../]*"
1972 0           1 while ($$html =~ s#[^\/]+\/\.\.\/##o); #RECURSIVELY CONVERT "my/deep/deeper/../../path" to "my/path".
1973 0 0         if (defined($hrefcase)) #ADDED 20020117: THIS ALLOWS CONTROL OF WHICH LINKS TO WRAP WITH CGI!
1974             {
1975 0 0         if ($hrefcase eq 'l') #ONLY CONVERT LOWER-CASE "href=" LINKS THIS WAY.
1976             {
1977 0           $$html =~ s#(src|ground|href)\s*=\s*\"(?!(\#|/|\w+\:))#$1=\"$htmlhome/$2#g; #CONVERT RELATIVE LINKS TO ABSOLUTE ONES.
1978 0           $$html =~ s# (cl|ht)\s*=\s*\"(?!(\#|/|\w+\:))# $1=\"$htmlhome/$2#g; #CONVERT RELATIVE SPECIAL JAVASCRIPT LINKS TO ABSOLUTE ONES.
1979 0           $$html =~ s#(\s+window\.open\s*\(\s*\')(?!(\#|/|\w+\:))#$1$htmlhome/$2#g; #ADDED 20050504 TO MAKE CALENDAR.JS WORK!
1980             }
1981             else
1982             {
1983 0           $$html =~ s#(SRC|GROUND|HREF)\s*=\s*\"(?!(\#|/|\w+\:))#$1=\"$htmlhome/$2#g; #CONVERT RELATIVE LINKS TO ABSOLUTE ONES.
1984 0           $$html =~ s# (CL|HT)\s*=\s*\"(?!(\#|/|\w+\:))# $1=\"$htmlhome/$2#g; #CONVERT RELATIVE SPECIAL JAVASCRIPT LINKS TO ABSOLUTE ONES.
1985             }
1986             }
1987             else
1988             {
1989 0           $$html =~ s#(src|ground|href)\s*=\s*\"(?!(\#|/|\w+\:))#$1=\"$htmlhome/$2#ig; #CONVERT RELATIVE LINKS TO ABSOLUTE ONES.
1990 0           $$html =~ s# (cl|ht)\s*=\s*\"(?!(\#|/|\w+\:))# $1=\"$htmlhome/$2#ig; #CONVERT RELATIVE SPECIAL JAVASCRIPT LINKS TO ABSOLUTE ONES.
1991 0           $$html =~ s#(\s+window\.open\s*\(\s*\')(?!(\#|/|\w+\:))#$1$htmlhome/$2#ig; #ADDED 20050504 TO MAKE CALENDAR.JS WORK!
1992             }
1993 0           $$html =~ s#\.\.\/##g; #REMOVE ANY REMAING "../".
1994              
1995             #NOTE: SOME JAVASCRIPT RELATIVE LINK VALUES MAY STILL NEED HAND-CONVERTING
1996             #VIA BUILDHTML, FOLLOWED BY ADDITIONAL APP-SPECIFIC REGICES, ONE EXAMPLE
1997             #WAS THE "JSFPR" SITE, FILLED WITH ASSIGNMENTS OF "'image/file.gif'",
1998             #WHICH WERE CONVERTED USING:
1999             # $html =~ s#([\'\"])images/#$1$main_htmlsubdir/images/#ig;
2000              
2001             }
2002              
2003             #NEXT LINE ADDED 20010720 TO SUPPORT EMBEDS (NON-PARSED INCLUDES).
2004              
2005             # $$html =~ s#<\!EMBED\s+(.*?)>\s*#&fetchinclude($parms, $1, 0)#eigs
2006             # if ($cfgOps{embeds});
2007              
2008             #ABOVE CHANGED TO NEXT REGEX 20060117 TO ALLOW PARTIAL FILE INCLUDES BASED ON TAGS.
2009             $$html =~ s!<\!EMBED\s+(.*?)>\s*!
2010 0           my $one = $1;
2011 0           $one =~ s/^\"//o;
2012 0           $one =~ s/\"\s*$//o;
2013 0           my $tag = 0;
2014 0 0         $tag = $1 if ($one =~ s/\:(\w+)//o);
2015 0           &fetchinclude($parms, $one, 0, $tag);
2016 0 0         !eigs if ($cfgOps{embeds});
2017              
2018 0           return ($$html);
2019             }
2020              
2021             sub html_error
2022             {
2023 0     0 0   my ($mymsg) = shift;
2024            
2025 0           return (<
2026            
2027             CGI Program - Unexpected Error!
2028            
2029            

$mymsg

2030            
2031             Please contact $poc for more information.
2032            
2033             END_HTML
2034             }
2035              
2036             sub SetHtmlHome
2037             {
2038 0     0 1   ($htmlhome, $roothtmlhome, $hrefhtmlhome, $hrefcase) = @_;
2039              
2040             # hrefcase = undef: convert all "href=" to $hrefhtmlhome.
2041             # hrefcase = 'l': convert only "href=" to $hrefhtmlhome.
2042             # hrefcase = '~l': convert only "HREF=" to $hrefhtmlhome.
2043             }
2044              
2045             sub loadhtml_package #ADDED 20000920 TO ALLOW EVALS IN ASP!
2046             {
2047 0   0 0 1   $calling_package = shift || 'main';
2048             }
2049              
2050             sub filedate #ADDED 20020327
2051             {
2052 0     0 0   my $parms = shift;
2053 0           my $fmt = shift;
2054 0           my $usetoday = shift; #ADDED 20030501 TO SUPPORT DISPLAYING CURRENT DATE!
2055              
2056 0           $fmt =~ s/^\=\s*//o;
2057 0           $fmt =~ s/[\"\']//go;
2058 0           $fmt =~ s/\:$//go;
2059 0   0       $fmt ||= 'mm/dd/yy'; #SUPPLY A REASONABLE DEFAULT.
2060 0           my $mtime = time;
2061 0 0         (undef,undef,undef,undef,undef,undef,undef,undef,undef,undef,$mtime)
2062             = stat ($0) unless ($usetoday); #CHGD. TO NEXT:12/30/15:
2063             # = stat ($parms->{'0'}) unless ($usetoday);
2064 0   0       $mtime ||= time;
2065              
2066             #to_char() comes from DBD::Sprite, but is usable as a stand-alone program and is optional.
2067              
2068             #x my @parmsave = @_;
2069             #x @_ = ($mtime, $fmt);
2070              
2071             #x eval "package $calling_package; require 'to_char.pl'";
2072 0 0         eval 'use Date::Time2fmtstr; $haveTime2fmtstr = 1; 1' unless ($haveTime2fmtstr);
2073             #x if ($@)
2074             #x {
2075             #x @_ = @parmsave;
2076             #x return scalar(localtime($mtime));
2077             #x }
2078             #x if (!$rtnTime || $err =~ /^Invalid/o)
2079             #x {
2080             #@_ = (time, 'mm/dd/yy');
2081             #do 'to_char.pl';
2082             #x my $qualified_fn = $calling_package . '::to_char';
2083 1     1   8 no strict 'refs';
  1         2  
  1         77  
2084             #x return &{$qualified_fn}($mtime, $fmt);
2085 0 0 0       return @_ ? scalar(localtime($mtime)) : &time2str($mtime, $fmt) || scalar(localtime($mtime));
2086             #x }
2087             #x @_ = @parmsave;
2088             #x return $rtnTime;
2089             }
2090              
2091             1