File Coverage

blib/lib/CIPP/Compile/Generator.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             # $Id: Generator.pm,v 1.40 2006/05/19 08:03:37 joern Exp $
2              
3             package CIPP::Compile::Generator;
4              
5             @ISA = qw ( CIPP::Compile::Parser );
6              
7 1     1   5 use strict;
  1         2  
  1         35  
8 1     1   6 use Carp;
  1         2  
  1         55  
9 1     1   6 use Config;
  1         1  
  1         49  
10 1     1   754 use CIPP::Compile::Parser;
  0            
  0            
11             use IO::String;
12             use FileHandle;
13              
14             #---------------------------------------------------------------------
15             # These methods the skeleton of CIPP programs, Includes and Modules,
16             # so they are not directly related to CIPP commands.
17             #---------------------------------------------------------------------
18              
19             sub generate_start_program {
20             croak "generate_start_program not implemented";
21             }
22              
23             sub generate_project_handler {
24             croak "generate_project_handler not implemented";
25             }
26              
27             sub generate_open_exception_handler {
28             my $self = shift; $self->trace_in;
29            
30             $self->write (
31             "# generic exception handler eval\n",
32             "eval {\n\n"
33             );
34            
35             1;
36             }
37              
38             sub generate_open_request {
39             my $self = shift; $self->trace_in;
40            
41             $self->write (
42             '$_cipp_project->new_request ('."\n",
43             ' program_name => "'.$self->get_program_name.'"'."\n",
44             ');'."\n"
45             );
46              
47             1;
48             }
49              
50             sub generate_close_exception_handler {
51             my $self = shift; $self->trace_in;
52            
53             $self->writef (
54             "\n".
55             "}; # end of generic exception handler eval\n\n".
56             '# check for an exception (filters exception)'."\n".
57             'if ( $@ and $@ !~ /_cipp_exit_command/ ) {'."\n".
58             ' $CIPP::request->error ('."\n".
59             ' message => $@,'."\n".
60             ' ) if defined $CIPP::request;'."\n".
61             '}'."\n\n",
62             $self->get_program_name,
63             );
64            
65             1;
66             }
67              
68             sub generate_close_request {
69             my $self = shift; $self->trace_in;
70            
71             $self->write (
72             '$CIPP::request->close if defined $CIPP::request;'."\n"
73             );
74              
75             1;
76             }
77              
78             sub generate_debugging_code {
79             my $self = shift; $self->trace_in;
80            
81             # no debugging code für closed tags, var context and the
82             # expression tag (which is the tag with the empty name).
83             return if $self->context =~ /^var/ or
84             $self->get_current_tag_closed or
85             $self->get_current_tag eq '';
86              
87             $self->write (
88             '# cipp_line_nr='.
89             $self->get_current_tag_line_nr." ".
90             $self->get_current_tag."\n"
91             );
92            
93             1;
94             }
95              
96             sub generate_include_open {
97             my $self = shift; $self->trace_in;
98            
99             my $package = $self->get_program_name;
100             my $i = 0;
101             $package =~ s/\./_/g;
102             $package =~ s/\W/++$i/ge;
103              
104             $package = "main";
105            
106             # An Include is a subroutine
107             $self->writef (
108             'package %s;'."\n\n".
109             'use strict;'."\n".
110             'sub {'."\n",
111             $package
112             );
113              
114             my $interface = $self->get_state->{incinterface};
115              
116             # code for input parameters
117             foreach my $var ( values %{$interface->{input}} ) {
118             my $name = $var;
119             $name =~ s/^(.)//;
120             my $deref = $1;
121            
122             if ( $deref eq '$' ) {
123             $self->write (" my $var = ".'$_[0]->{'.$name.'};'."\n");
124             } else {
125             $self->write (" my $var = $deref\{".'$_[0]->{'.$name.'}};'."\n");
126             }
127             }
128            
129             # code for optional parameters
130             foreach my $var ( values %{$interface->{optional}}) {
131             my $name = $var;
132             $name =~ s/^(.)//;
133             my $deref = $1;
134            
135             if ( $deref eq '$' ) {
136             $self->write (" my $var = ".'$_[0]->{'.$name.'};'."\n");
137             } else {
138             # don't write: my $var = ${$foo} if defined $foo
139             # this produce strange behaviour (at least unter Perl 5.6.0)
140             # The dereferenced memory seems to live outside the
141             # scope of this subroutine.
142             $self->write (" my $var;\n");
143             $self->write (" $var = $deref\{".'$_[0]->{'.$name.'}} if defined $_[0]->{'.$name.'};'."\n");
144             }
145             }
146              
147             # declaration of output parameters
148             if ( keys %{$interface->{output}} ) {
149             my $code;
150             foreach my $var ( values %{$interface->{output}} ) {
151             $code .= "$var,";
152             }
153             $code =~ s/,$//;
154             $self->write (" my ($code);\n");
155             }
156              
157             1;
158             }
159              
160             sub generate_include_close {
161             my $self = shift; $self->trace_in;
162            
163             my $interface = $self->get_state->{incinterface};
164              
165             # return output parameter
166             if ( values %{$interface->{output}} ) {
167             my $code;
168             my $name;
169             foreach my $var ( values %{$interface->{output}} ) {
170             $name = $var;
171             $name =~ s/^(.)//;
172             $code .= "$name => \\$var, ";
173             }
174             $code =~ s/,$//;
175             $self->write (" return { $code};\n");
176             }
177            
178             # close subroutine
179             $self->write (
180             '}'."\n"
181             );
182              
183             1;
184             }
185              
186             sub generate_module_open {
187             my $self = shift; $self->trace_in;
188            
189             $self->write (
190             "use strict;\n",
191             # 'my $_cipp_line_nr;'."\n",
192             );
193            
194             1;
195             }
196              
197             sub generate_module_close {
198             my $self = shift; $self->trace_in;
199              
200             $self->write (
201             '1;'."\n",
202             );
203            
204             1;
205             }
206              
207             #---------------------------------------------------------------------
208             # This method processes all text blocks between tags
209             #---------------------------------------------------------------------
210              
211             sub process_text {
212             my $self = shift; $self->trace_in;
213             my ($text) = @_;
214              
215             $self->debug("GOT TEXT: '$$text'\n");
216              
217             $self->set_last_text_block($$text);
218            
219             my $context = $self->context;
220             my $autoprint = $self->get_state->{autoprint};
221              
222             if ( ($autoprint and $context eq 'html') or $context eq 'force_html' ) {
223             if ( $$text ne '' and $$text =~ /\S/ ) {
224             # print only if the chunk isn't empty or contains
225             # not only whitespace
226             $self->generate_debugging_code;
227              
228             # escape § sign (which is the qouting delimiter)
229             $$text =~ s/§/\\§/g;
230              
231             # truncate whitespace
232             if ( $self->get_trunc_ws ) {
233             $$text =~ s/^\s+//;
234             if ( not $$text =~ s/\s*\n\s*$/\n/ ) {
235             $$text =~ s/\s+$/ /;
236             }
237             }
238              
239             # generate print() command
240             $self->write ("print qq§$$text§;\n");
241             }
242              
243             } elsif ( $autoprint and $context eq 'html_exact' ) {
244             $$text =~ s/§/\\§/g;
245             $self->write ( "print qq§$$text§;\n");
246            
247             } elsif ( $context eq 'perl' ) {
248             $self->write ($$text);
249              
250             } elsif ( $context eq 'var_quote' ) {
251             $$text =~ s/\^/\\^/g;
252             $self->write ($$text);
253              
254             } elsif ( $context eq 'var_noquote' ) {
255             $self->write ($$text);
256             }
257              
258             1;
259             }
260              
261             #---------------------------------------------------------------------
262             # Process method for each CIPP command
263             #---------------------------------------------------------------------
264              
265             sub cmd_perl {
266             my $self = shift; $self->trace_in;
267              
268             my $RC = $self->RC_BLOCK_TAG;
269              
270             if ( $self->get_current_tag_closed ) {
271             $self->pop_context;
272            
273             $self->check_options (
274             mandatory => {},
275             optional => {},
276             ) || return $RC;
277              
278             $self->write (";}\n");
279              
280             return $RC;
281             }
282              
283             $self->check_options (
284             mandatory => {},
285             optional => { 'cond' => 1 },
286             ) || return $RC;
287              
288             my $options = $self->get_current_tag_options;
289              
290             $self->write ("if ($options->{cond}) ") if defined $options->{cond};
291             $self->write ("{");
292              
293             $self->push_context('perl');
294              
295             return $RC;
296             }
297              
298             sub cmd_expression {
299             my $self = shift; $self->trace_in;
300              
301             my $RC = $self->RC_BLOCK_TAG;
302              
303             if ( $self->get_current_tag_closed ) {
304             my $buffer = $self->get_last_text_block;
305             $self->add_tag_message (
306             message => "Expression must not have trailing semicolon"
307             ) if $buffer =~ /;\s*$/;
308              
309             $self->pop_context;
310            
311             $self->check_options (
312             mandatory => {},
313             optional => {},
314             ) || return $RC;
315              
316             $self->write (");\n");
317              
318             return $RC;
319             }
320              
321             $self->check_options (
322             mandatory => {},
323             optional => {},
324             ) || return $RC;
325              
326             $self->write ("print (");
327              
328             $self->push_context('perl');
329              
330             return $RC;
331             }
332              
333             sub cmd_html {
334             my $self = shift; $self->trace_in;
335              
336             my $RC = $self->RC_BLOCK_TAG;
337              
338             if ( $self->get_current_tag_closed ) {
339             $self->pop_context;
340            
341             $self->check_options (
342             mandatory => {},
343             optional => {},
344             );
345              
346             return $RC;
347             }
348              
349             $self->check_options (
350             mandatory => {},
351             optional => {},
352             ) || return $RC;
353              
354             $self->push_context('force_html');
355              
356             return $RC;
357             }
358              
359             sub cmd_if {
360             my $self = shift; $self->trace_in;
361              
362             my $RC = $self->RC_BLOCK_TAG;
363              
364             if ( $self->get_current_tag_closed ) {
365             $self->check_options (
366             mandatory => {},
367             optional => {},
368             ) || return $RC;
369             $self->write ("}\n");
370             return $RC;
371             }
372              
373             $self->check_options (
374             mandatory => { 'cond' => 1 },
375             optional => {},
376             ) || return $RC;
377              
378             my $options = $self->get_current_tag_options;
379              
380             $self->write ("if ($options->{cond}) {\n");
381              
382             return $RC;
383             }
384              
385             sub cmd_while {
386             my $self = shift; $self->trace_in;
387              
388             my $RC = $self->RC_BLOCK_TAG;
389              
390             if ( $self->get_current_tag_closed ) {
391             $self->check_options (
392             mandatory => {},
393             optional => {},
394             ) || return $RC;
395             $self->write ("}\n");
396             return $RC;
397             }
398            
399             $self->check_options (
400             mandatory => { 'cond' => 1 },
401             optional => {},
402             ) || return $RC;
403              
404             my $options = $self->get_current_tag_options;
405              
406             $self->write("while ($options->{cond}) {\n");
407              
408             return $RC;
409             }
410              
411             sub cmd_do {
412             my $self = shift; $self->trace_in;
413              
414             my $RC = $self->RC_BLOCK_TAG;
415              
416             if ( $self->get_current_tag_closed ) {
417             $self->check_options (
418             mandatory => { 'cond' => 1 },
419             optional => {},
420             ) || return $RC;
421            
422             my $options = $self->get_current_tag_options;
423              
424             $self->write ("} while ($options->{cond});\n");
425            
426             return $RC;
427             }
428              
429             $self->check_options (
430             mandatory => {},
431             optional => {},
432             ) || return $RC;
433              
434             $self->write ("do {\n");
435              
436             return $RC;
437             }
438              
439             sub cmd_var {
440             my $self = shift; $self->trace_in;
441              
442             my $RC = $self->RC_BLOCK_TAG;
443              
444             my $tag_data;
445            
446             if ( $tag_data = $self->get_current_tag_closed ) {
447             $self->pop_context;
448              
449             $self->check_options (
450             mandatory => {},
451             optional => {},
452             ) || return $RC;
453              
454             my $quote_char = $tag_data->{quote} ? '^' : '';
455              
456             $self->write($quote_char);
457              
458             if ( $tag_data->{default} ) {
459             my ($open_quote, $close_quote);
460             ($open_quote, $close_quote) = ("qq^","^")
461             if $tag_data->{quote};
462             $self->write(
463             qq{|| $open_quote$tag_data->{default}$close_quote}
464             );
465             }
466              
467             $self->write(";\n");
468             return $RC;
469             }
470              
471             my ($var_quote, $var_default);
472              
473             $self->check_options (
474             mandatory => { 'name' => 1 },
475             optional => { 'default' => 1,
476             'type' => 1,
477             'my' => 1,
478             'noquote' => 1 },
479             ) || return $RC;
480              
481             my $options = $self->get_current_tag_options;
482              
483             my $name = $self->parse_variable_option (
484             option => 'name'
485             ) || return $RC;
486              
487             if ( $name =~ /^[\@\%]/ ) {
488             if ( defined $options->{default} ) {
489             $self->add_tag_message (
490             message => "DEFAULT is invalid for non scalar variables"
491             );
492             return $RC;
493             }
494             $var_quote = 0;
495             } else {
496             $var_quote = 1;
497             }
498              
499             if ( defined ($options->{type}) ) {
500             $options->{type} =~ tr/A-Z/a-z/;
501             if ( $options->{type} eq "num" ) {
502             $self->{var_quote} = 0;
503             } else {
504             $self->add_tag_message (
505             message => "Invalid TYPE."
506             );
507             return $RC;
508             }
509             }
510              
511             $var_quote = 0 if defined $options->{noquote};
512              
513             my $quote_char = $var_quote ? 'qq^' : '';
514             my $quote_end_char = $var_quote ? '^' : '';
515              
516             $self->write("my ") if defined $options->{'my'};
517              
518             if ( defined ($options->{default}) ) {
519             $var_default = $options->{default};
520             }
521              
522             $self->write("$name=".$quote_char);
523              
524             if ( $var_quote ) {
525             $self->push_context('var_quote');
526             } else {
527             $self->push_context('var_noquote');
528             }
529              
530             return $self->RC_BLOCK_TAG (
531             quote => $var_quote,
532             default => $var_default
533             );
534             }
535              
536             sub cmd_else {
537             my $self = shift; $self->trace_in;
538              
539             my $RC = $self->RC_SINGLE_TAG;
540              
541             $self->check_options (
542             mandatory => {},
543             optional => {},
544             ) || return $RC;
545              
546             $self->write ("} else {\n");
547              
548             return $RC;
549             }
550              
551             sub cmd_elsif {
552             my $self = shift; $self->trace_in;
553              
554             my $RC = $self->RC_SINGLE_TAG;
555              
556             $self->check_options (
557             mandatory => { 'cond' => 1 },
558             optional => {},
559             ) || return $RC;
560              
561             my $options = $self->get_current_tag_options;
562              
563             $self->write ("} elsif ($options->{cond}) {\n");
564              
565             return $RC;
566             }
567              
568             sub cmd_try {
569             my $self = shift; $self->trace_in;
570              
571             my $RC = $self->RC_BLOCK_TAG;
572              
573             $self->check_options (
574             mandatory => {},
575             optional => {},
576             ) || return $RC;
577              
578             if ( $self->get_current_tag_closed ) {
579             $self->write (
580             "};\n".
581             "(\$_cipp_exception, \$_cipp_exception_msg)=".
582             "split(\"\\t\",\$\@,2);\n".
583             '$_cipp_exception_msg=$_cipp_exception '.
584             'if $@ and $_cipp_exception_msg eq "";'."\n".
585             'die "_cipp_exit_command" if $_cipp_exception eq "_cipp_exit_command";'."\n"
586             );
587             return $RC;
588             }
589              
590             $self->write (
591             "my (\$_cipp_exception,\$_cipp_exception_msg)=(undef,undef);\n".
592             "eval {\n"
593             );
594              
595             return $RC;
596             }
597              
598             sub cmd_catch {
599             my $self = shift; $self->trace_in;
600              
601             my $RC = $self->RC_BLOCK_TAG;
602              
603             $self->check_options (
604             mandatory => {},
605             optional => { 'throw' => 1,
606             'my' => 1,
607             'excvar' => 1,
608             'msgvar' => 1 },
609             ) || return $RC;
610              
611             if ( $self->get_current_tag_closed ) {
612             $self->write ("}\n");
613             return $RC;
614             }
615              
616             my $options = $self->get_current_tag_options;
617              
618             my $my = '';
619             $my = 'my ' if defined $options->{'my'};
620            
621             my $excvar = $self->parse_variable_option (
622             option => 'excvar', types => [ 'scalar' ]
623             );
624             my $msgvar = $self->parse_variable_option (
625             option => 'msgvar', types => [ 'scalar' ]
626             );
627            
628             $self->write ("$my$excvar = \$_cipp_exception;\n") if $excvar;
629             $self->write ("$my$msgvar = \$_cipp_exception_msg;\n") if $msgvar;
630              
631             if ( defined $options->{throw} ) {
632             $self->write (
633             'if ( $_cipp_exception eq "'.$options->{throw}.'" ) {'."\n"
634             );
635             } else {
636             $self->write (
637             "if ( defined \$_cipp_exception ) {\n"
638             );
639             }
640              
641             return $RC;
642             }
643              
644             sub cmd_log {
645             my $self = shift; $self->trace_in;
646              
647             my $RC = $self->RC_SINGLE_TAG;
648              
649             $self->check_options (
650             mandatory => { 'msg' => 1 },
651             optional => { 'type' => 1, 'filename' => 1, 'throw' => 1 },
652             ) || return $RC;
653              
654             my $options = $self->get_current_tag_options;
655              
656             $options->{type} ||= "APP";
657             $options->{filename} ||= "";
658             $options->{throw} ||= "LOG";
659              
660             $self->writef (
661             '$CIPP::request->log ('."\n".
662             ' type => "%s",'."\n".
663             ' message => "%s",'."\n".
664             ' filename => "%s",'."\n".
665             ' throw => "%s",'."\n".
666             ');'."\n",
667            
668             $options->{type}, $options->{msg},
669             $options->{filename}, $options->{throw}
670             );
671              
672             return $RC;
673             }
674              
675             sub cmd_throw {
676             my $self = shift; $self->trace_in;
677              
678             my $RC = $self->RC_SINGLE_TAG;
679              
680             $self->check_options (
681             mandatory => { 'throw' => 1 },
682             optional => { 'msg' => 1 },
683             ) || return $RC;
684              
685             my $options = $self->get_current_tag_options;
686              
687             if ( defined $options->{msg} ) {
688             $self->write (
689             qq{die "$options->{throw}\t$options->{msg}";\n}
690             );
691             } else {
692             $self->write (
693             qq{die "$options->{throw}\t";\n}
694             );
695             }
696              
697             return $RC;
698             }
699              
700             sub cmd_dump {
701             my $self = shift; $self->trace_in;
702              
703             my $RC = $self->RC_SINGLE_TAG;
704              
705             $self->check_options (
706             mandatory => {},
707             optional => { '*' => 1 },
708             ) || return $RC;
709              
710             my $options_order = $self->get_current_tag_options_order;
711              
712             my $options = $self->get_current_tag_options;
713              
714             my $stderr = delete $options->{stderr};
715             my $log = delete $options->{log};
716              
717             $self->write ("use Data::Dumper;\n");
718              
719             my $dumper_code =
720             "join('',Data::Dumper->Dump ([".
721             join(', ', grep !/^stderr|log$/i, @{$options_order}).
722             "], [qw(".
723             join(' ', grep !/^stderr|log$/i, @{$options_order}).
724             ")]))";
725              
726             if ( $stderr ) {
727             $self->writef (
728             "print STDERR %s;\n",
729             $dumper_code
730             );
731             }
732            
733             if ( $log ) {
734             $self->writef (
735             '$CIPP::request->log(type=>"dump",message=>"\n".%s);'."\n",
736             $dumper_code
737             );
738             }
739              
740             if ( not $stderr and not $log ) {
741             $self->writef (
742             'print "
".%s."
\n";',
743             $dumper_code
744             );
745             }
746              
747             return $RC;
748             }
749              
750             sub cmd_block {
751             my $self = shift; $self->trace_in;
752              
753             my $RC = $self->RC_BLOCK_TAG;
754              
755             $self->check_options (
756             mandatory => {},
757             optional => {},
758             ) || return $RC;
759              
760             if ( $self->get_current_tag_closed ) {
761             $self->write ("}\n");
762             return $RC;
763             }
764              
765             $self->write ("{\n");
766              
767             return $RC;
768             }
769              
770             sub cmd_my {
771             my $self = shift; $self->trace_in;
772              
773             my $RC = $self->RC_SINGLE_TAG;
774              
775             my $options = $self->get_current_tag_options;
776             my $options_case = $self->get_current_tag_options_case;
777             my $options_list = $self->get_current_tag_options_order;
778              
779             if ( not scalar @{$options_list} ) {
780             $self->add_tag_message (
781             message => "No variables given."
782             );
783             return $RC;
784             }
785              
786             # copy all options into the VAR option, so we
787             # can use $self->parse_variable_option_hash
788             delete $options_case->{var};
789             $options->{var} .=
790             ( defined $options->{var} ? ',' : '' ).
791             join (",", map { s/,$//; $_ } values %{$options_case});
792              
793             # now parse the 'var' option
794             my $var = $self->parse_variable_option_hash (
795             option => 'var'
796             );
797            
798             # generate my statement
799             my $varlist = join (",", keys %{$var});
800             $self->write ("my ($varlist);\n");
801              
802             return $RC;
803             }
804              
805             sub cmd_htmlquote {
806             my $self = shift; $self->trace_in;
807              
808             my $RC = $self->RC_SINGLE_TAG;
809              
810             $self->check_options (
811             mandatory => { 'var' => 1 },
812             optional => { 'htmlvar' => 1, 'my' => 1 },
813             ) || return $RC;
814              
815             my $options = $self->get_current_tag_options;
816              
817             my $var = $self->parse_variable_option (
818             option => 'var', types => [ 'scalar' ]
819             ) || return $RC;
820              
821             my $htmlvar;
822             if ( defined $options->{htmlvar} ) {
823             $htmlvar = $self->parse_variable_option (
824             option => 'htmlvar', types => [ 'scalar' ]
825             ) || return $RC;
826             }
827              
828             ($htmlvar = $var) =~ s/^\$(.*)$/\$html_$1/ if not $htmlvar;
829              
830             my $my_cmd = $options->{'my'} ? 'my ' : '';
831            
832             $self->write (
833             "$my_cmd$htmlvar=\$CIPP::request->html_quote($var);\n"
834             );
835              
836             return $RC;
837             }
838              
839             sub cmd_urlencode {
840             my $self = shift; $self->trace_in;
841              
842             my $RC = $self->RC_SINGLE_TAG;
843              
844             $self->check_options (
845             mandatory => { 'var' => 1 },
846             optional => { 'encvar' => 1, 'my' => 1 },
847             ) || return $RC;
848              
849             my $options = $self->get_current_tag_options;
850              
851             my $var = $self->parse_variable_option (
852             option => 'var', types => [ 'scalar' ]
853             ) || return $RC;
854              
855             my $encvar;
856             if ( defined $options->{encvar} ) {
857             $encvar = $self->parse_variable_option (
858             option => 'encvar', types => [ 'scalar' ]
859             ) || return $RC;
860             }
861              
862             ($encvar = $var) =~ s/^\$(.*)$/\$enc_$1/ if not $encvar;
863              
864             my $my_cmd = $options->{'my'} ? 'my ' : '';
865            
866             $self->write (
867             "$my_cmd$encvar=\$CIPP::request->url_encode($var);\n"
868             );
869              
870             return $RC;
871             }
872              
873             sub cmd_foreach {
874             my $self = shift; $self->trace_in;
875              
876             my $RC = $self->RC_BLOCK_TAG;
877              
878             if ( $self->get_current_tag_closed ) {
879             $self->check_options (
880             mandatory => {},
881             optional => {},
882             ) || return $RC;
883             $self->write ("}\n");
884             return $RC;
885             }
886              
887             $self->check_options (
888             mandatory => { 'var' => 1, 'list' => 1 },
889             optional => { 'my' => 1 },
890             ) || return $RC;
891              
892             my $options = $self->get_current_tag_options;
893              
894             my $var = $self->parse_variable_option (
895             option => 'var', types => [ 'scalar' ]
896             ) || return $RC;
897              
898             $self->write ("my $var;\n") if $options->{'my'};
899             $self->write ("foreach $var ($options->{list}) {\n");
900              
901             return $RC;
902             }
903              
904             sub cmd_textarea {
905             my $self = shift; $self->trace_in;
906              
907             my $RC = $self->RC_BLOCK_TAG;
908              
909             if ( $self->get_current_tag_closed ) {
910             $self->pop_context;
911             $self->check_options (
912             mandatory => {},
913             optional => {},
914             ) || return $RC;
915             $self->write ('}); print "\n";'."\n");
916             return $RC;
917             }
918              
919             my $options = $self->get_current_tag_options;
920              
921             my $options_text = '';
922             my ($par, $val);
923             while ( ($par,$val) = each %{$options} ) {
924             $par =~ tr/A-Z/a-z/;
925             $options_text .= qq[ $par="$val"];
926             }
927              
928             $self->write (
929             qq[print qq{},\$CIPP::request->html_quote (qq{]
930             );
931              
932             $self->push_context('var_quote');
933            
934             return $RC;
935             }
936              
937             sub cmd_sub {
938             my $self = shift; $self->trace_in;
939              
940             my $RC = $self->RC_BLOCK_TAG;
941              
942             my $data;
943             if ( $data = $self->get_current_tag_closed ) {
944             $self->check_options (
945             mandatory => {},
946             optional => {},
947             ) || return $RC;
948              
949             my $buffer_sref = $self->close_output_buffer;
950              
951             $self->write ( $buffer_sref );
952             $self->write ("}\n");
953              
954             # now a Perl Syntax check for the subroutine
955             my $var_decl;
956             if ( $data->{import} and @{$data->{import}} ) {
957             $var_decl = 'my (';
958             $var_decl .= "$_, " for @{$data->{import}};
959             $var_decl =~ s/, $//;
960             $var_decl .= ");\n";
961             }
962             $$buffer_sref = "use strict; $var_decl$$buffer_sref";
963              
964             $self->perl_error_check ( perl_code_sref => $buffer_sref );
965            
966             return $RC;
967             }
968              
969             $self->check_options (
970             mandatory => { 'name' => 1 },
971             optional => { 'import' => 1 },
972             ) || return $RC;
973              
974             my $options = $self->get_current_tag_options;
975              
976             my $name = $options->{name};
977             $name = "main::$name" if $name !~ /:/ and
978             not $self->get_state->{module_name};
979              
980             if ( $options->{import} ) {
981             my $import = $self->parse_variable_option_list (
982             option => 'import',
983             );
984             $RC = $self->RC_BLOCK_TAG (
985             import => $import
986             );
987             }
988              
989             $self->write (
990             qq[sub $name {\n]
991             );
992              
993             $self->open_output_buffer;
994            
995             return $RC;
996             }
997              
998             sub cmd_hiddenfields {
999             my $self = shift; $self->trace_in;
1000              
1001             my $RC = $self->RC_SINGLE_TAG;
1002              
1003             $self->check_options (
1004             mandatory => {},
1005             optional => { '*' => 1 },
1006             ) || return $RC;
1007              
1008             my $options = $self->get_current_tag_options;
1009             my $options_case = $self->get_current_tag_options_case;
1010              
1011             my (@val_list, $par, $val);
1012            
1013             # first get variables from PARAMS option
1014             if ( defined $options->{params} ) {
1015             my $params = $self->parse_variable_option_hash (
1016             option => 'params',
1017             types => [ 'scalar', 'array' ]
1018             ) || return $RC;
1019              
1020             foreach $par ( keys %{$params} ) {
1021             $val = $par;
1022             $par =~ s/^[\$\@]//;
1023             push @val_list, "$val\t$par";
1024             }
1025             }
1026              
1027             # now add explicite options
1028             while ( ($par,$val) = each %{$options} ) {
1029             next if $par eq 'params';
1030             push @val_list, "$val\t".$options_case->{$par};
1031             }
1032              
1033             # now we have tab delimited entries in @val_list:
1034             #
1035             # idx 0 assigned parameter:
1036             # if begins with $ : scalar variable
1037             # if begins with @ : array variable
1038             # else: literal string
1039             #
1040             # idx 1 name of the parameter for the hidden field
1041              
1042             # first generate constant hiddenfields for scalar parameters
1043             my $item;
1044             foreach $item (grep /^[^\@]/, @val_list) {
1045             ($val, $par) = split ("\t", $item);
1046             $par=lc($par);
1047             $self->write (
1048             qq[print qq{].
1049             qq[ 1050             qq[\$CIPP::request->html_field_quote(qq{$val}).qq{"\$CIPP::ee>\\n};\n] );
1051             }
1052              
1053             # generate dynamic hiddenfield code for arrays
1054             foreach $item (grep /^\@/, @val_list) {
1055             ($val, $par) = split ("\t", $item);
1056             $par=lc($par);
1057             $self->write (
1058             qq[{my \$cipp_tmp;\nforeach \$cipp_tmp ($val) {\n].
1059             qq[print qq{
1060             qq[value="}.\$CIPP::request->html_field_quote(qq{\$cipp_tmp}).].
1061             qq[qq{"\$CIPP::ee>\\n};\n].
1062             qq[}\n}\n] );
1063             }
1064              
1065             return $RC;
1066             }
1067              
1068             sub cmd_comment {
1069             my $self = shift; $self->trace_in;
1070              
1071             my $RC = $self->RC_BLOCK_TAG;
1072              
1073             if ( $self->get_current_tag_closed ) {
1074             $self->pop_context;
1075             $self->check_options (
1076             mandatory => {},
1077             optional => {},
1078             ) || return $RC;
1079             return $RC;
1080             }
1081              
1082             $self->check_options (
1083             mandatory => {},
1084             optional => {},
1085             ) || return $RC;
1086              
1087             $self->push_context('comment');
1088              
1089             return $RC;
1090             }
1091              
1092             sub cmd_input {
1093             my $self = shift; $self->trace_in;
1094              
1095             my $RC = $self->RC_SINGLE_TAG;
1096              
1097             $self->check_options (
1098             mandatory => {},
1099             optional => { '*' => 1 },
1100             ) || return $RC;
1101              
1102             my $code = qq[print qq{
1103              
1104             my $options = $self->get_current_tag_options;
1105             my $options_case = $self->get_current_tag_options_case;
1106              
1107             my ($par, $val);
1108             while ( ($par,$val) = each %{$options} ) {
1109             if ( $par eq 'value' ) {
1110             # quote the VALUE option
1111             $code .= qq[ value="}.\$CIPP::request->html_quote ].
1112             qq[(qq{$options->{value}}).qq{"];
1113              
1114             } elsif ( $par eq 'src' ) {
1115             # check whether this image exists and is of correct type
1116             # ()
1117             return $RC if not $self->check_object_type (
1118             name => $val,
1119             type => 'cipp-image',
1120             );
1121              
1122             my $object_url = $self->get_object_url ( name => $val );
1123             $code .= qq[ src="$object_url"];
1124              
1125             } elsif ( $par ne 'sticky' ) {
1126             # other parameters are taken as is
1127             $par =~ tr/A-Z/a-z/;
1128             $code .= qq[ $par="$val"];
1129             }
1130             }
1131              
1132             my $sticky_var = $options->{sticky};
1133              
1134             if ( $sticky_var ) {
1135             if ( $options->{type} =~ /^radio$/i and
1136             $options->{name} !~ /\$/ and not $options->{checked} ) {
1137             # sticky feature for type="radio"
1138             if ( $sticky_var == 1 ) {
1139             $sticky_var = '$'.$options->{name};
1140             }
1141             $code .= qq[},($sticky_var eq qq{$options->{value}} ].
1142             qq[? " checked\$CIPP::ee>\\n":"\$CIPP::ee>\\n");\n];
1143              
1144             } elsif ( $options->{type} =~ /^checkbox$/i and
1145             $options->{name} !~ /\$/ and not $options->{checked} ) {
1146             # sticky feature for type="checkbox"
1147             $sticky_var = '@'.$options->{name} if $sticky_var == 1;
1148             $code .= qq[},(grep /^$options->{value}\$/,$sticky_var) ].
1149             qq[? " checked\$CIPP::ee>\\n":"\$CIPP::ee>\\n";\n];
1150             }
1151             } else {
1152             $code .= "\$CIPP::ee>\\n};\n";
1153             }
1154              
1155             $self->write($code);
1156              
1157             return $RC;
1158             }
1159              
1160             sub cmd_savefile { # deprecated. replaced by
1161             my $self = shift; $self->trace_in;
1162              
1163             my $RC = $self->RC_SINGLE_TAG;
1164              
1165             $self->check_options (
1166             mandatory => { 'var' => 1, 'filename' => 1 },
1167             optional => { 'throw' => 1, 'symbolic' => 1 }
1168             ) || return $RC;
1169              
1170             my $options = $self->get_current_tag_options;
1171              
1172             $options->{var} =~ s/^\$//;
1173              
1174             $options->{throw} ||= "savefile";
1175              
1176             my $formvar;
1177             if ( ! defined $options->{symbolic} ) {
1178             $formvar = "'$options->{var}'";
1179             } else {
1180             $formvar = "\$$options->{var}";
1181             }
1182              
1183             my $code = "{\nno strict;\n";
1184             $code .= "my \$_cipp_filehandle = CGI::param($formvar);\n";
1185             $code .= "die '$options->{throw}\tFile upload variable not set.'\n ";
1186             $code .= "if not \$_cipp_filehandle;\n";
1187             $code .= "open (cipp_SAVE_FILE, \"> $options->{filename}\")\n";
1188             $code .= "or die \"$options->{throw}\tCan't open file '$options->{filename}' ".
1189             "for writing\";\n";
1190             $code .= "binmode cipp_SAVE_FILE;\n";
1191             $code .= "binmode \$_cipp_filehandle;\n";
1192             $code .= "my (\$_cipp_filebuf, \$_cipp_read_result);\n";
1193             $code .= "while (\$_cipp_read_result = read \$_cipp_filehandle, ".
1194             "\$_cipp_filebuf, 1024) {\n";
1195             $code .= "print cipp_SAVE_FILE \$_cipp_filebuf ";
1196             $code .= "or die \"$options->{throw}\tError writing to output file.\";\n";
1197             $code .= "}\n";
1198             $code .= "close cipp_SAVE_FILE;\n";
1199             $code .= "(!defined \$_cipp_read_result) and \n";
1200             $code .= "die \"$options->{throw}\tError reading the upload file. ".
1201             "Did you set ENCTYPE=multipart/form-data?\";\n";
1202             $code .= "close \$_cipp_filehandle;\n";
1203             $code .= "}\n";
1204            
1205             $self->write ($code);
1206              
1207             return 1;
1208             }
1209              
1210             sub cmd_fetchupload {
1211             my $self = shift; $self->trace_in;
1212              
1213             my $RC = $self->RC_SINGLE_TAG;
1214              
1215             $self->check_options (
1216             mandatory => { 'var' => 1, 'filename' => 1 },
1217             optional => { 'throw' => 1 }
1218             ) || return $RC;
1219              
1220             my $options = $self->get_current_tag_options;
1221             $options->{throw} ||= "fetchupload";
1222              
1223             my $var = $self->parse_variable_option (
1224             option => 'var',
1225             types => [ 'scalar' ]
1226             ) || return $RC;
1227              
1228             $self->writef (
1229             '$CIPP::request->fetch_upload ('."\n".
1230             ' filename => "%s",'."\n".
1231             ' fh => %s,'."\n".
1232             ' throw => "%s"'."\n".
1233             ');'."\n",
1234            
1235             $options->{filename},
1236             $var,
1237             $options->{throw},
1238             );
1239              
1240             return $RC;
1241             }
1242              
1243             sub cmd_interface {
1244             my $self = shift; $self->trace_in;
1245              
1246             my $RC = $self->RC_SINGLE_TAG;
1247              
1248             if ( defined $self->get_state->{interface_occured} ) {
1249             $self->add_tag_message (
1250             message => 'Multiple instances of '.
1251             ' are forbidden.'
1252             );
1253             return $RC;
1254             }
1255              
1256             if ( $self->get_object_type ne 'cipp' ) {
1257             $self->add_tag_message (
1258             message => "Illegal use of the command. This is not a CIPP program."
1259             );
1260             return $RC;
1261             }
1262              
1263             $self->get_state->{interface_occured} = 1;
1264              
1265             $self->check_options (
1266             mandatory => {},
1267             optional => { 'input' => 1, 'optional' => 1 },
1268             ) || return $RC;
1269              
1270             my $mandatory = $self->parse_variable_option_hash (
1271             option => 'input'
1272             );
1273              
1274             my $optional = $self->parse_variable_option_hash (
1275             option => 'optional'
1276             );
1277              
1278             return $RC if not keys %{$mandatory} and not keys %{$optional};
1279              
1280             $self->write (
1281             "my (".
1282             join (", ", keys %{$mandatory}, keys %{$optional}).
1283             ");\n\n"
1284             );
1285            
1286             $self->write (
1287             '$CIPP::request->read_input_parameter ('."\n".
1288             " mandatory => {\n"
1289             );
1290            
1291             my ($name, $var, @clash);
1292             while ( ($var, $name) = each %{$mandatory} ) {
1293             if ( defined $optional->{$var} ) {
1294             push @clash, $var;
1295             next;
1296             }
1297             $self->write (
1298             " '$name' => \\$var,\n"
1299             );
1300             }
1301            
1302             $self->write (
1303             " },\n".
1304             " optional => {\n"
1305             );
1306              
1307             while ( ($var, $name) = each %{$optional} ) {
1308             $self->write (
1309             " '$name' => \\$var,\n"
1310             );
1311             }
1312             $self->write (
1313             " },\n".
1314             ");\n\n"
1315             );
1316              
1317             $self->add_tag_message (
1318             message => "INPUT/OPTIONAL variable clash: ".
1319             join(', ', @clash)
1320             ) if @clash;
1321              
1322              
1323             return $RC;
1324             }
1325              
1326             sub cmd_use {
1327             my $self = shift; $self->trace_in;
1328              
1329             my $RC = $self->RC_SINGLE_TAG;
1330              
1331             $self->check_options (
1332             mandatory => { 'name' => 1 },
1333             optional => {},
1334             ) || return $RC;
1335              
1336             my $options = $self->get_current_tag_options;
1337              
1338             $self->writef(
1339             'use %s;'."\n",
1340             $options->{name}
1341             );
1342              
1343             $self->add_used_module (
1344             name => $options->{name},
1345             );
1346              
1347             return $RC;
1348             }
1349              
1350             sub cmd_require {
1351             my $self = shift; $self->trace_in;
1352              
1353             my $RC = $self->RC_SINGLE_TAG;
1354              
1355             $self->check_options (
1356             mandatory => { 'name' => 1 },
1357             ) || return $RC;
1358              
1359             my $options = $self->get_current_tag_options;
1360              
1361             $self->write(
1362             qq[{ my \$_cipp_mod = "$options->{name}";\n].
1363             qq[\$_cipp_mod =~ s!::!/!og;\n].
1364             qq[\$_cipp_mod .= ".pm";\n].
1365             qq[require \$_cipp_mod;}\n]
1366             );
1367              
1368             if ( $options->{name} !~ /\$/ ) {
1369             $self->add_used_module (
1370             name => $options->{name},
1371             );
1372             }
1373              
1374             return $RC;
1375             }
1376              
1377             sub cmd_module {
1378             my $self = shift; $self->trace_in;
1379              
1380             my $RC = $self->RC_BLOCK_TAG;
1381              
1382             if ( $self->get_current_tag_closed ) {
1383             $self->check_options (
1384             mandatory => {},
1385             optional => {},
1386             ) || return $RC;
1387             return $RC;
1388             }
1389              
1390             $self->check_options (
1391             mandatory => { 'name' => 1 },
1392             optional => { 'isa' => 1 },
1393             ) || return $RC;
1394              
1395             my $options = $self->get_current_tag_options;
1396              
1397             if ( $self->get_state->{module_name} ) {
1398             $self->add_tag_message (
1399             message => "Mulitiple module declaration: ".
1400             $self->get_state->{module_name}
1401             );
1402             return $RC;
1403             }
1404            
1405             $self->get_state->{module_name} = $options->{name};
1406              
1407             $self->write("package $options->{name};\n\n");
1408              
1409             if ( $options->{isa} ) {
1410             my $isa = $options->{isa};
1411             $isa =~ s/,/ /g;
1412             $self->write (
1413             '@'.$options->{name}."::ISA = qw( $isa );\n"
1414             );
1415             }
1416              
1417             my @isa = split (/\s*,\s*/, $options->{isa});
1418             foreach my $isa ( @isa ) {
1419             $self->write(
1420             qq[\n{ my \$_cipp_mod = "$isa";\n].
1421             qq[\$_cipp_mod =~ s!::!/!og;\n].
1422             qq[\$_cipp_mod .= ".pm";\n].
1423             qq[require \$_cipp_mod;}\n\n]
1424             );
1425             }
1426              
1427             return $RC;
1428             }
1429              
1430             sub cmd_config {
1431             my $self = shift; $self->trace_in;
1432              
1433             my $RC = $self->RC_SINGLE_TAG;
1434              
1435             $self->check_options (
1436             mandatory => { 'name' => 1 },
1437             optional => { 'nocache' => 1, 'runtime' => 1, 'throw' => 1 },
1438             ) || return $RC;
1439              
1440             my $options = $self->get_current_tag_options;
1441              
1442             my $name = $options->{name};
1443            
1444             if ( not $options->{runtime} ) {
1445             return $RC if not $self->check_object_type (
1446             name => $name,
1447             type => 'cipp-config',
1448             );
1449              
1450             $self->add_used_object (
1451             name => $name,
1452             type => 'cipp-config'
1453             );
1454             }
1455              
1456             my $throw = $options->{throw};
1457             $throw ||= 'config';
1458              
1459             my $require;
1460              
1461             $self->writef (
1462             '$CIPP::request->read_config ('."\n".
1463             ' name => "%s",'."\n".
1464             ' throw => "%s"'."\n".
1465             ');'."\n",
1466             $name,
1467             $throw
1468             );
1469              
1470             return $RC;
1471             }
1472              
1473             sub cmd_form {
1474             my $self = shift; $self->trace_in;
1475              
1476             my $RC = $self->RC_BLOCK_TAG;
1477              
1478             if ( $self->get_current_tag_closed ) {
1479             $self->check_options (
1480             mandatory => {},
1481             optional => {},
1482             ) || return $RC;
1483              
1484             $self->write ('print "\n";'."\n");
1485              
1486             return $RC;
1487             }
1488              
1489             $self->check_options (
1490             mandatory => { 'action' => 1 },
1491             optional => { '*' => 1 },
1492             ) || return $RC;
1493              
1494             my $options = $self->get_current_tag_options;
1495              
1496             my $method;
1497             if ( defined $options->{method} ) {
1498             $method = $options->{method};
1499             delete $options->{method};
1500             } else {
1501             $method = "POST";
1502             }
1503              
1504             my $name = $options->{action};
1505             delete $options->{action};
1506              
1507             my $anchor;
1508             if ( $name =~ /#/ ) {
1509             ($name, $anchor) = split ("#", $name, 2);
1510             $anchor = "#$anchor";
1511             }
1512              
1513             return $RC if not $self->check_object_type (
1514             name => $name,
1515             type => 'cipp',
1516             );
1517              
1518             my $object_url = $self->get_object_url ( name => $name );
1519              
1520             my $code = qq[print qq{
1521             qq[method="$method"];
1522              
1523             my ($par, $val);
1524             while ( ($par,$val) = each %{$options} ) {
1525             $par =~ tr/a-z/A-Z/;
1526             $code .= qq[ $par="$val"];
1527             }
1528              
1529             $code .= ">\\n};\n";
1530              
1531             $self->write($code);
1532              
1533             return $RC;
1534             }
1535              
1536             sub cmd_a {
1537             my $self = shift; $self->trace_in;
1538              
1539             my $RC = $self->RC_BLOCK_TAG;
1540              
1541             if ( $self->get_current_tag_closed ) {
1542             $self->pop_context;
1543             $self->check_options (
1544             mandatory => {},
1545             optional => {},
1546             ) || return $RC;
1547              
1548             $self->write ('print qq[\n];'."\n");
1549              
1550             return $RC;
1551             }
1552              
1553             $self->check_options (
1554             mandatory => { 'href' => 1 },
1555             optional => { '*' => 1 },
1556             ) || return $RC;
1557              
1558             my $options = $self->get_current_tag_options;
1559              
1560             my $name = $options->{href};
1561             delete $options->{href};
1562              
1563             my $anchor;
1564             if ( $name =~ /#/ ) {
1565             ($name, $anchor) = split ("#", $name, 2);
1566             }
1567              
1568             return $RC if not $self->object_exists (
1569             name => $name,
1570             add_message_if_not => 1
1571             );
1572              
1573             my $object_url = $self->get_object_url (
1574             name => $name,
1575             add_message_if_has_no => 1
1576             );
1577              
1578             return $RC if not defined $object_url;
1579              
1580             my $code;
1581             if ( defined $anchor ) {
1582             $code = qq[print qq{
1583             } else {
1584             $code = qq[print qq{
1585             }
1586              
1587             my ($par, $val);
1588             while ( ($par,$val) = each %{$options} ) {
1589             $par =~ tr/a-z/A-Z/;
1590             $code .= qq[ $par="$val"];
1591             }
1592              
1593             $code .= ">};\n";
1594              
1595             $self->write($code);
1596              
1597             $self->push_context ('html_exact');
1598              
1599             return $RC;
1600             }
1601              
1602             sub cmd_frame {
1603             my $self = shift; $self->trace_in;
1604              
1605             my $RC = $self->RC_SINGLE_TAG;
1606              
1607             if ( $self->get_current_tag_closed ) {
1608             $self->check_options (
1609             mandatory => {},
1610             optional => {},
1611             ) || return $RC;
1612              
1613             return $RC;
1614             }
1615              
1616             $self->check_options (
1617             mandatory => { 'src' => 1 },
1618             optional => { '*' => 1 },
1619             ) || return $RC;
1620              
1621             my $options = $self->get_current_tag_options;
1622              
1623             my $name = delete $options->{src};
1624              
1625             my $anchor;
1626             if ( $name =~ /#/ ) {
1627             ($name, $anchor) = split ("#", $name, 2);
1628             }
1629              
1630             return $RC if not $self->object_exists (
1631             name => $name,
1632             add_message_if_not => 1
1633             );
1634              
1635             my $object_url = $self->get_object_url (
1636             name => $name,
1637             add_message_if_has_no => 1
1638             );
1639              
1640             return $RC if not defined $object_url;
1641              
1642             my $code;
1643             if ( defined $anchor ) {
1644             $code = qq[print qq{
1645             } else {
1646             $code = qq[print qq{
1647             }
1648              
1649             my ($par, $val);
1650             while ( ($par,$val) = each %{$options} ) {
1651             $par =~ tr/a-z/A-Z/;
1652             $code .= qq[ $par="$val"];
1653             }
1654              
1655             $code .= "\$CIPP::ee>};\n";
1656              
1657             $self->write($code);
1658              
1659             return $RC;
1660             }
1661              
1662             sub cmd_geturl {
1663             my $self = shift; $self->trace_in;
1664              
1665             my $RC = $self->RC_SINGLE_TAG;
1666              
1667             $self->check_options (
1668             mandatory => { 'name' => 1 },
1669             optional => { '*' => 1 },
1670             ) || return $RC;
1671              
1672             my $options = $self->get_current_tag_options;
1673             my $options_case = $self->get_current_tag_options_case;
1674              
1675             # mangle URLVAR and VAR options. URLVAR is depreciated.
1676            
1677             if ( $options->{urlvar} ) {
1678             if ( $options->{var} ) {
1679             $self->add_tag_message (
1680             message => "Using VAR and URLVAR option ".
1681             "is forbidden. URLVAR is ".
1682             "deprecated."
1683             );
1684             return $RC;
1685             }
1686             $options->{var} = $options->{urlvar};
1687             delete $options->{urlvar};
1688             }
1689              
1690             if ( not $options->{var} ) {
1691             $self->add_tag_message (
1692             message => "VAR option missing."
1693             );
1694             return $RC;
1695             }
1696              
1697             my $var = $self->parse_variable_option (
1698             option => 'var',
1699             types => [ 'scalar' ]
1700             );
1701             delete $options->{var};
1702              
1703              
1704             my $name = delete $options->{name};
1705             my $runtime = delete $options->{runtime};
1706             my $throw = delete $options->{throw} || 'geturl';
1707             my $path_info = delete $options->{pathinfo};
1708             my $my_cmd = delete $options->{my};
1709             $my_cmd = $my_cmd ? 'my ' : '';
1710            
1711             return $RC if not $runtime and not $self->object_exists (
1712             name => $name,
1713             add_message_if_not => 1
1714             );
1715              
1716             my $object_url;
1717              
1718             if ( not $runtime ) {
1719             $object_url = $self->get_object_url (
1720             name => $name,
1721             add_message_if_has_no => 1
1722             );
1723             return $RC if not defined $object_url;
1724              
1725             $self->write ("${my_cmd}$var=qq{$object_url}\n");
1726              
1727             } else {
1728             $self->write (
1729             qq{${my_cmd}$var=\$CIPP::request->get_object_url ( name => "$name", throw => "$throw")}
1730             );
1731             }
1732              
1733             # add PATHINFO, if requested
1734             $self->write (qq[.qq{/$path_info}]) if $path_info;
1735              
1736             # now add parameters to the url
1737             my @val_list;
1738             my ($par, $val);
1739              
1740             # get values from PARAMS
1741              
1742             if ( defined $options->{params} ) {
1743             my $params = $self->parse_variable_option_hash (
1744             option => 'params',
1745             types => [ 'scalar', 'array' ]
1746             ) || return $RC;
1747              
1748             foreach $par ( keys %{$params} ) {
1749             $val = $par;
1750             $par =~ s/^[\$\@]//;
1751             push @val_list, "$val\t$par";
1752             }
1753             }
1754              
1755             # now add explicite options
1756             while ( ($par,$val) = each %{$options} ) {
1757             next if $par eq 'params';
1758             push @val_list, "$val\t".$options_case->{$par};
1759             }
1760              
1761             # now we have tab delimited entries in @val_list:
1762             #
1763             # idx 0 assigned parameter:
1764             # if begins with $ : scalar variable
1765             # if begins with @ : array variable
1766             # else: literal string
1767             #
1768             # idx 1 name of the parameter for the hidden field
1769              
1770             if ( @val_list ) {
1771             return $RC if not $runtime and not $self->check_object_type (
1772             name => $name,
1773             type => 'cipp',
1774             message => "Illegal attempt to add parameters ".
1775             "to a non CGI URL."
1776             );
1777              
1778             # process scalar parameters first.
1779             my $delimiter = "?";
1780             my $item;
1781              
1782             foreach $item (grep /^[^\@]/, @val_list) {
1783             ($val, $par) = split ("\t", $item);
1784             $par=lc($par);
1785             $self->write (
1786             qq{.qq{${delimiter}$par=}.}.
1787             qq{\$CIPP::request->url_encode("$val")} );
1788              
1789             $delimiter = $self->get_url_par_delimiter if $delimiter eq '?';
1790             }
1791             $self->write ( ";\n" );
1792              
1793             # now array parameters
1794             foreach $item (grep /^\@/, @val_list) {
1795             ($val, $par) = split ("\t", $item);
1796             $par=lc($par);
1797             $self->write (
1798             qq[{my \$_cipp_tmp;\nforeach \$_cipp_tmp ($val) {\n].
1799             qq[$var.="${delimiter}$par=".].
1800             qq[\$CIPP::request->url_encode(\$_cipp_tmp);\n].
1801             qq[}\n}\n] );
1802              
1803             $delimiter = $self->get_url_par_delimiter if $delimiter eq '?';
1804             }
1805             }
1806              
1807             $self->write (";\n");
1808              
1809             return $RC;
1810             }
1811              
1812             sub cmd_img {
1813             my $self = shift; $self->trace_in;
1814              
1815             my $RC = $self->RC_SINGLE_TAG;
1816              
1817             $self->check_options (
1818             mandatory => { 'src' => 1 },
1819             optional => { '*' => 1 },
1820             ) || return $RC;
1821              
1822             my $options = $self->get_current_tag_options;
1823              
1824             my $name = delete $options->{src};
1825             my $nosize = delete $options->{nosize};
1826              
1827             my $object_url = $self->get_object_url (
1828             name => $name,
1829             add_message_if_has_no => 1
1830             );
1831            
1832             return $RC if not defined $object_url;
1833              
1834             my $code = qq[print qq{
1835              
1836             if ( not defined $nosize and
1837             not defined $options->{width} and
1838             not defined $options->{height} ) {
1839             my $filename = $self->get_object_filename ( name => $name );
1840             last if not $filename;
1841             eval "use Image::Size qw()";
1842             last if $@;
1843             eval {
1844             ($options->{width},
1845             $options->{height})
1846             = Image::Size::imgsize ($filename);
1847             };
1848             }
1849              
1850             my ($par, $val);
1851             while ( ($par,$val) = each %{$options} ) {
1852             $code .= qq[ $par="$val"];
1853             }
1854              
1855             $code .= "\$CIPP::ee>};\n";
1856              
1857             $self->write($code);
1858              
1859             return $RC;
1860             }
1861              
1862             sub cmd_select {
1863             my $self = shift; $self->trace_in;
1864              
1865             my $RC = $self->RC_BLOCK_TAG;
1866              
1867             if ( $self->get_current_tag_closed ) {
1868             $self->get_state->{select_tag_options} = undef;
1869             $self->check_options (
1870             mandatory => {},
1871             optional => {},
1872             ) || return $RC;
1873             $self->write(
1874             qq{print "\\n";}
1875             );
1876             return $RC;
1877             }
1878              
1879             if ( $self->get_state->{select_tag_options} ) {
1880             $self->add_tag_message (
1881             message => "Nesting forbidden."
1882             );
1883             return $RC;
1884             }
1885              
1886             $self->check_options (
1887             mandatory => { 'name' => 1 },
1888             optional => { '*' => 1 },
1889             ) || return $RC;
1890              
1891             my $options = $self->get_current_tag_options;
1892              
1893             $self->get_state->{select_tag_options} = $options;
1894              
1895             my $code = qq[print qq{
1896              
1897             my ($par, $val);
1898             while ( ($par,$val) = each %{$options} ) {
1899             if ( $par ne 'sticky' ) {
1900             $code .= qq[ $par="$val"];
1901             }
1902             }
1903             $code .= ">\\n};\n";
1904              
1905             $self->write($code);
1906              
1907             return $self->RC_BLOCK_TAG (%{$options});
1908             }
1909              
1910             sub cmd_option {
1911             my $self = shift; $self->trace_in;
1912              
1913             my $RC = $self->RC_BLOCK_TAG;
1914              
1915             if ( $self->get_current_tag_closed ) {
1916             $self->check_options (
1917             mandatory => {},
1918             optional => {},
1919             ) || return $RC;
1920             $self->pop_context;
1921             $self->write(
1922             qq[^),"\\n";]
1923             );
1924             return $RC;
1925             }
1926              
1927             my $select_options = $self->get_state->{select_tag_options};
1928              
1929             if ( not $select_options ) {
1930             $self->add_tag_message (
1931             message => "Missing tag."
1932             );
1933             return $RC;
1934             }
1935              
1936             $self->check_options (
1937             mandatory => {},
1938             optional => { '*' => 1 },
1939             ) || return $RC;
1940              
1941             my $options = $self->get_current_tag_options;
1942              
1943             my $code = qq[print qq{
1944              
1945             my ($par, $val);
1946             while ( ($par,$val) = each %{$options} ) {
1947             if ( $par eq 'value' ) {
1948             $code .= qq[ value="}.\$CIPP::request->html_field_quote].
1949             qq[(qq{$options->{value}}).qq{"];
1950             } else {
1951             $par =~ tr/A-Z/a-z/;
1952             if ( $par ne 'sticky' ) {
1953             $code .= qq[ $par="$val"];
1954             }
1955             }
1956             }
1957              
1958             my $sticky_var = $select_options->{sticky} || $options->{sticky};
1959              
1960             if ( $sticky_var ) {
1961             if ( $options->{name} !~ /\$/ and not $options->{selected} and
1962             $select_options->{multiple} ) {
1963             if ( $sticky_var == 1 ) {
1964             $sticky_var = '@'.$select_options->{name};
1965             }
1966             $code .= qq[},(grep /^$options->{value}\$/,$sticky_var) ? " selected>":">",\n];
1967             } elsif ( $options->{name} !~ /\$/ and not $options->{selected} ) {
1968             if ( $sticky_var == 1 ) {
1969             $sticky_var = '$'.$select_options->{name};
1970             }
1971             $code .= qq[},($sticky_var eq qq{$options->{value}}) ? " selected>":">",\n];
1972             }
1973             } else {
1974             $code .= ">},\n";
1975             }
1976              
1977             $self->write($code);
1978             $self->write (
1979             qq[\$CIPP::request->html_quote (qq^]
1980             );
1981              
1982             $self->push_context('var_quote');
1983              
1984             return $RC;
1985             }
1986              
1987             sub cmd_lib {
1988             my $self = shift; $self->trace_in;
1989              
1990             my $RC = $self->RC_SINGLE_TAG;
1991              
1992             $self->check_options (
1993             mandatory => { 'name' => 1 },
1994             optional => {},
1995             ) || return $RC;
1996              
1997             my $options = $self->get_current_tag_options;
1998              
1999             $self->write("use $options->{name};\n");
2000              
2001             return $RC;
2002             }
2003              
2004             sub cmd_getparam {
2005             my $self = shift; $self->trace_in;
2006              
2007             my $RC = $self->RC_SINGLE_TAG;
2008              
2009             $self->check_options (
2010             mandatory => { 'name' => 1 },
2011             optional => { 'my' => 1, 'var' => 1 },
2012             ) || return $RC;
2013              
2014             my $options = $self->get_current_tag_options;
2015              
2016             my $var;
2017             if ( not defined $options->{var} ) {
2018             $var = '$'.$options->{name};
2019             $options->{'my'} = 1;
2020             } else {
2021             $var = $self->parse_variable_option (
2022             option => "var"
2023             );
2024             }
2025              
2026             my $my = $options->{'my'} ? 'my' : '';
2027              
2028             $self->write("$my $var = \$CIPP::request->param(\"$options->{name}\");\n");
2029              
2030             return $RC;
2031             }
2032              
2033             sub cmd_getparamlist {
2034             my $self = shift; $self->trace_in;
2035              
2036             my $RC = $self->RC_SINGLE_TAG;
2037              
2038             $self->check_options (
2039             mandatory => { 'var' => 1 },
2040             optional => { 'my' => 1 },
2041             ) || return $RC;
2042              
2043             my $var = $self->parse_variable_option (
2044             option => "var",
2045             types => [ 'array' ]
2046             ) || return $RC;
2047              
2048             my $options = $self->get_current_tag_options;
2049              
2050             my $my = $options->{'my'} ? 'my' : '';
2051              
2052             $self->write("$my $var = \$CIPP::request->param();\n");
2053              
2054             return $RC;
2055             }
2056              
2057             sub cmd_autoprint {
2058             my $self = shift; $self->trace_in;
2059              
2060             my $RC = $self->RC_SINGLE_TAG;
2061              
2062             $self->check_options (
2063             mandatory => {},
2064             optional => { 'off' => 1, 'on' => 1 },
2065             ) || return $RC;
2066              
2067             my $options = $self->get_current_tag_options;
2068              
2069             if ( $options->{on} and $options->{off} ) {
2070             $self->add_tag_message (
2071             message => 'Illegal combination of ON and OFF.'
2072             );
2073             return $RC;
2074             }
2075              
2076             if ( not $options->{on} and not $options->{off} ) {
2077             $self->add_tag_message (
2078             message => 'Neither ON nor OFF specified.'
2079             );
2080             return $RC;
2081             }
2082              
2083             $self->get_state->{autoprint} = 0 if $options->{off};
2084             $self->get_state->{autoprint} = 1 if $options->{on};
2085            
2086             return $RC;
2087             }
2088              
2089             sub cmd_exit {
2090             my $self = shift; $self->trace_in;
2091              
2092             my $RC = $self->RC_SINGLE_TAG;
2093              
2094             $self->check_options (
2095             mandatory => {},
2096             optional => {},
2097             ) || return $RC;
2098              
2099             $self->write(
2100             "die '_cipp_exit_command';\n"
2101             );
2102              
2103             return $RC;
2104             }
2105              
2106             sub cmd_profile {
2107             my $self = shift; $self->trace_in;
2108              
2109             my $RC = $self->RC_BLOCK_TAG;
2110              
2111             if ( $self->get_current_tag_closed ) {
2112             $self->check_options (
2113             mandatory => {},
2114             optional => {},
2115             ) || return $RC;
2116              
2117             $self->write (
2118             '$CIPP::request->stop_profiling;'."\n"
2119             );
2120              
2121             return $RC;
2122             }
2123              
2124             $self->check_options (
2125             mandatory => {},
2126             optional => {
2127             'deep' => 1, 'name' => 1,
2128             'filename' => 1, 'filter' => 1,
2129             'scaleunit' => 1,
2130             },
2131             ) || return $RC;
2132              
2133             my $options = $self->get_current_tag_options;
2134              
2135             my $deep = $options->{deep} ? 1 : 0;
2136             my $name = $options->{name} || 'unnamed';
2137             my $filename = $options->{filename};
2138            
2139             my $filter = $options->{filter} || 0;
2140             my $scale_unit = $options->{scaleunit} || 0.2;
2141            
2142             $self->write (
2143             '$CIPP::request->start_profiling ('."\n".
2144             " deep => $deep,\n".
2145             " name => qq{$name},\n".
2146             " filename => qq{$filename},\n".
2147             " filter => $filter,\n".
2148             " scale_unit => $scale_unit\n".
2149             ");\n"
2150             );
2151              
2152             return $RC;
2153             }
2154              
2155             sub cmd_profile_old {
2156             my $self = shift; $self->trace_in;
2157              
2158             my $RC = $self->RC_SINGLE_TAG;
2159              
2160             $self->check_options (
2161             mandatory => {},
2162             optional => { 'on' => 1, 'off' => 1, 'deep' => 1 },
2163             ) || return $RC;
2164              
2165             my $options = $self->get_current_tag_options;
2166              
2167             my $deep = '';
2168             if ( $options->{on} ) {
2169             if ( $options->{deep} ) {
2170             $self->get_state->{profile} = "deep";
2171             $deep = " DEEP";
2172             } else {
2173             $self->get_state->{profile} = "on";
2174             }
2175             }
2176            
2177             if ( $options->{off} ) {
2178             $self->get_state->{profile} = undef;
2179             $self->write(
2180             'printf STDERR "PROFILE %5d STOP'.$deep.'\n",$$;'
2181             );
2182             } else {
2183             $self->write(
2184             "require 'Time/HiRes.pm';\n",
2185             'printf STDERR "\nPROFILE %5d START'.$deep.'\n",$$;'
2186             );
2187             }
2188              
2189             return $RC;
2190             }
2191              
2192             sub get_profile_start_code {
2193             my $self = shift; $self->trace_in;
2194            
2195             return 'my ($_cipp_t1, $_cipp_t2);'."\n".
2196             '$_cipp_t1 = Time::HiRes::time();'."\n";
2197             }
2198              
2199             sub get_profile_end_code {
2200             my $self = shift; $self->trace_in;
2201            
2202             my ($what, $detail) = @_;
2203              
2204             $what = "q[$what]";
2205             $detail = "q[$detail]";
2206            
2207             return '$_cipp_t2 = Time::HiRes::time();'."\n".
2208             'printf STDERR "PROFILE %5d %-10s %-40s %2.4f\n", '.
2209             '$$, '.$what.','.$detail.', $_cipp_t2-$_cipp_t1;'."\n";
2210             }
2211              
2212             sub get_dbh_code {
2213             my $self = shift; $self->trace_in;
2214            
2215             my $options = $self->get_current_tag_options;
2216              
2217             if ( $options->{dbh} and $options->{db} ) {
2218             $self->add_tag_message (
2219             message => "Illegal combination of DB and DBH."
2220             );
2221             return;
2222             }
2223              
2224             if ( $options->{dbh} ) {
2225             #-- trivial, if DBH option was set
2226             my $var = $self->parse_variable_option (
2227             option => 'dbh',
2228             types => [ 'scalar' ]
2229             ) || return;
2230             return $var;
2231              
2232             }
2233             elsif ( $options->{db} =~ /\$/ ) {
2234             #-- Obviously a variable database name, then this is
2235             #-- resolved at runtime (need to normalize the name
2236             #-- on-the-fly i.e. remove the PROJECT DOT from the
2237             #-- variable's content).
2238             return '$CIPP::request->dbh(do{my $__db='
2239             . $options->{db}
2240             . ';$__db=~s/^[^.]+\.//;$__db})';
2241            
2242             }
2243             else {
2244             #-- otherwise it's a static new.spirit dotted object name
2245             my $db = $options->{db};
2246             if ( $db ) {
2247             $self->check_object_type (
2248             name => $db,
2249             type => 'cipp-db',
2250             message => "$db is not a database configuration object"
2251             ) || return;
2252              
2253             # we normalize here, because the identifier for
2254             # the default db __default must not be normalized
2255             # by the ->add_used_object method call beyond.
2256             # so we can call it with normalized => 1.
2257             $db =~ s/^[^.]+\.//;
2258             # $db = $self->get_normalized_object_name ( name => $options->{db} );
2259             } else {
2260             $db = "default";
2261             }
2262              
2263             $self->add_used_object (
2264             name => ($db eq 'default' ? '__default' : $db),
2265             type => 'cipp-db',
2266             normalized => 1
2267             );
2268              
2269             return '$CIPP::request->dbh("'.$db.'")';
2270             }
2271             }
2272              
2273             sub cmd_getdbhandle {
2274             my $self = shift; $self->trace_in;
2275              
2276             my $RC = $self->RC_SINGLE_TAG;
2277              
2278             $self->check_options (
2279             mandatory => { 'var' => 1 },
2280             optional => { 'my' => 1, 'db' => 1 },
2281             ) || return $RC;
2282              
2283             my $options = $self->get_current_tag_options;
2284              
2285             my $var = $self->parse_variable_option (
2286             option => 'var',
2287             types => [ 'scalar' ]
2288             ) || return $RC;
2289              
2290             my $dbh_code = $self->get_dbh_code;
2291              
2292             my $my_cmd = $options->{'my'} ? 'my ' : '';
2293              
2294             if ( $self->get_state->{profile} ) {
2295             $self->write ( $self->get_profile_start_code );
2296             }
2297              
2298             $self->write (
2299             qq{${my_cmd}$var = $dbh_code;\n}
2300             );
2301              
2302             if ( $self->get_state->{profile} ) {
2303             $self->write (
2304             $self->get_profile_end_code (
2305             "CONNECT", "Database: ".($options->{db}||'default')
2306             )
2307             );
2308             }
2309              
2310             return $RC;
2311             }
2312              
2313             sub cmd_switchdb {
2314             my $self = shift; $self->trace_in;
2315              
2316             my $RC = $self->RC_BLOCK_TAG;
2317              
2318             if ( $self->get_current_tag_closed ) {
2319             $self->check_options (
2320             mandatory => {},
2321             optional => {},
2322             ) || return $RC;
2323              
2324             $self->writef (
2325             '};'."\n".
2326             '$CIPP::request->unswitch_db;'."\n".
2327             'die $@ if $@;'."\n"
2328             );
2329            
2330             return $RC;
2331             }
2332              
2333             $self->check_options (
2334             optional => { 'dbh' => 1, 'db' => 1 },
2335             ) || return $RC;
2336              
2337             my $options = $self->get_current_tag_options;
2338              
2339             my $dbh_code = $self->get_dbh_code;
2340              
2341             $self->write (
2342             qq[eval {\n].
2343             qq[\$CIPP::request->switch_db ( dbh => $dbh_code );\n]
2344             );
2345              
2346             return $RC;
2347             }
2348              
2349             sub cmd_autocommit {
2350             my $self = shift; $self->trace_in;
2351              
2352             my $RC = $self->RC_SINGLE_TAG;
2353              
2354             $self->check_options (
2355             mandatory => {},
2356             optional => { 'on' => 1, 'off' => 1, 'db' => 1,
2357             'dbh' => 1, 'throw' => 1 },
2358             ) || return $RC;
2359              
2360             my $options = $self->get_current_tag_options;
2361              
2362             my $dbh_code = $self->get_dbh_code;
2363              
2364             if ( not defined $options->{on} and not defined $options->{off} ) {
2365             $self->add_tag_message (
2366             message => "Neither ON nor OFF option set."
2367             );
2368             return $RC;
2369             }
2370              
2371             if ( defined $options->{on} and defined $options->{off} ) {
2372             $self->add_tag_message (
2373             message => "Illegal combination of ON and OFF options."
2374             );
2375             return $RC;
2376             }
2377              
2378             my $status = defined $options->{on} ? 1 : 0;
2379             my $throw = $options->{throw} || 'autocommit';
2380              
2381             $self->writef (
2382             '$CIPP::request->set_throw (qq{%s});'."\n",
2383             $throw
2384             );
2385              
2386             if ( $status ) {
2387             $self->writef (
2388             'die qq{%s\tAutoCommit already on} if %s->{AutoCommit};'."\n",
2389             $throw,
2390             $dbh_code
2391             );
2392             } else {
2393             $self->writef (
2394             'die qq{%s\tAutoCommit already off} if not %s->{AutoCommit};'."\n",
2395             $throw,
2396             $dbh_code
2397             );
2398             }
2399              
2400             $self->write ("$dbh_code\->{AutoCommit} = $status;\n");
2401            
2402              
2403             return $RC;
2404             }
2405              
2406             sub cmd_commit {
2407             my $self = shift; $self->trace_in;
2408              
2409             my $RC = $self->RC_SINGLE_TAG;
2410              
2411             $self->check_options (
2412             mandatory => {},
2413             optional => { 'db' => 1, 'dbh' => 1, 'throw' => 1 },
2414             ) || return $RC;
2415              
2416             my $options = $self->get_current_tag_options;
2417              
2418             my $dbh_code = $self->get_dbh_code;
2419             my $throw = $options->{throw} || 'commit';
2420              
2421             $self->writef (
2422             '$CIPP::request->set_throw (qq{%s});'."\n",
2423             $throw
2424             );
2425              
2426             $self->writef (
2427             'die qq{%s\tCommit used, but AutoCommit is on} if %s->{AutoCommit};'."\n",
2428             $throw,
2429             $dbh_code
2430             );
2431              
2432             $self->write (
2433             "$dbh_code\->commit;\n"
2434             );
2435              
2436             return $RC;
2437             }
2438              
2439             sub cmd_rollback {
2440             my $self = shift; $self->trace_in;
2441              
2442             my $RC = $self->RC_SINGLE_TAG;
2443              
2444             $self->check_options (
2445             mandatory => {},
2446             optional => { 'db' => 1, 'dbh' => 1, 'throw' => 1 },
2447             ) || return $RC;
2448              
2449             my $options = $self->get_current_tag_options;
2450              
2451             my $dbh_code = $self->get_dbh_code;
2452             my $throw = $options->{throw} || 'rollback';
2453              
2454             $self->writef (
2455             '$CIPP::request->set_throw (qq{%s});'."\n",
2456             $throw
2457             );
2458              
2459             $self->writef (
2460             'die qq{%s\tRollback used, but AutoCommit is on} if %s->{AutoCommit};'."\n",
2461             $throw,
2462             $dbh_code
2463             );
2464              
2465             $self->write (
2466             "$dbh_code\->rollback;\n"
2467             );
2468              
2469             return $RC;
2470             }
2471              
2472             sub cmd_dbquote {
2473             my $self = shift; $self->trace_in;
2474              
2475             my $RC = $self->RC_SINGLE_TAG;
2476              
2477             $self->check_options (
2478             mandatory => { 'var' => 1 },
2479             optional => { 'dbvar' => 1, 'dbh' => 1, 'db' => 1, 'my' => 1 },
2480             ) || return $RC;
2481              
2482             my $options = $self->get_current_tag_options;
2483              
2484             my $my_cmd = $options->{'my'} ? 'my ' : '';
2485             my $dbh_code = $self->get_dbh_code;
2486              
2487             my $var = $self->parse_variable_option (
2488             option => 'var',
2489             types => [ 'scalar' ]
2490             ) || return $RC;
2491              
2492             my $dbvar = $self->parse_variable_option (
2493             option => 'dbvar',
2494             types => [ 'scalar' ]
2495             );
2496              
2497             ($dbvar = $var) =~ s/^\$/\$db_/ if not $dbvar;
2498              
2499             $self->writef (
2500             '%s%s = %s->quote(%s);'."\n",
2501             $my_cmd,
2502             $dbvar,
2503             $dbh_code,
2504             $var
2505             );
2506              
2507             return $RC;
2508             }
2509              
2510             sub cmd_sql {
2511             my $self = shift; $self->trace_in;
2512              
2513             my $RC = $self->RC_BLOCK_TAG;
2514              
2515             my $data;
2516             if ( $data = $self->get_current_tag_closed ) {
2517             $self->check_options (
2518             mandatory => {},
2519             optional => {},
2520             ) || return $RC;
2521              
2522             return $RC if $data->{type} eq 'do';
2523            
2524             $self->writef (
2525             " }\n".
2526             ' $_cipp_sth->finish;'."\n".
2527             ' $CIPP::request->sql_select_finished;'."\n".
2528             '}'."\n"
2529             );
2530            
2531             return $RC;
2532             }
2533              
2534             $self->check_options (
2535             mandatory => {
2536             sql => 1
2537             },
2538             optional => {
2539             db => 1, dbh => 1, cond => 1,
2540             var => 1, params => 1, result => 1,
2541             throw => 1, maxrows => 1, winstart => 1,
2542             winsize => 1, my => 1, profile => 1,
2543             }
2544             ) || return $RC;
2545              
2546             my $options = $self->get_current_tag_options;
2547              
2548             if ( defined $options->{winstart} ^ defined $options->{winsize} ) {
2549             $self->add_tag_message (
2550             message => 'WINSTART without WINSIZE or vice versa.'
2551             );
2552             return $RC;
2553             }
2554              
2555             if ( defined $options->{winstart} and defined $options->{maxrows} ) {
2556             $self->add_tag_message (
2557             message => 'Illegal combination of WINSTART and MAXROWS.'
2558             );
2559             return $RC;
2560             }
2561              
2562             my $dbh_code = $self->get_dbh_code;
2563              
2564             my $var_lref = $self->parse_variable_option_list (
2565             option => 'var',
2566             types => [ 'scalar' ]
2567             );
2568              
2569             my $result_var = $self->parse_variable_option (
2570             option => 'result',
2571             types => [ 'scalar' ]
2572             );
2573            
2574             my $sql = $options->{sql};
2575             my $throw = $options->{throw} || "sql";
2576              
2577             my $maxrows = $options->{maxrows};
2578             my $winstart = $options->{winstart};
2579             my $winsize = $options->{winsize};
2580             my $my_cmd = $options->{'my'} ? 'my ' : '';
2581              
2582             $sql =~ s/;\s*$//;
2583             $sql =~ s/^\s+//;
2584             $sql =~ s/\s+$//;
2585              
2586             my $params_code = "";
2587             $params_code = "$options->{params}" if $options->{params};
2588              
2589             my $profile = $options->{profile} || "sql";
2590              
2591             if ( $options->{var} ) {
2592             # we assume a SELECT statement which is fetching data
2593             my $var_list = join(",",@{$var_lref});
2594            
2595             # declare variables, if neccessary
2596             $self->write ( "my ($var_list);\n" ) if $my_cmd;
2597              
2598             # prepare statement
2599             $self->writef (
2600             '{'."\n".
2601             ' my $_cipp_sth = $CIPP::request->sql_select ('."\n".
2602             ' %s, qq{%s}, [%s], qq{%s}, qq{%s}'."\n".
2603             ' );'."\n".
2604             ' $_cipp_sth->execute(%s);'."\n",
2605             $dbh_code,
2606             $sql,
2607             $params_code,
2608             $throw,
2609             $profile
2610             );
2611              
2612             # build list of references for binding fetch data
2613             # (dynamically extend or shrink list if column count
2614             # of the result set doesn't match - for backward
2615             # compatability)
2616             $self->writef (
2617             ' my $_cipp_col_cnt = $_cipp_sth->{NUM_OF_FIELDS};'."\n".
2618             ' my @_cipp_col_refs = \(%s);'."\n".
2619             ' while ( @_cipp_col_refs < $_cipp_col_cnt ) {'."\n".
2620             ' my $_cipp_dummy;'."\n".
2621             ' push @_cipp_col_refs, \$_cipp_dummy;'."\n".
2622             ' }'."\n".
2623             ' splice (@_cipp_col_refs, $_cipp_col_cnt) if @_cipp_col_refs > $_cipp_col_cnt;'."\n",
2624             $var_list
2625             );
2626              
2627             $self->writef (
2628             ' $_cipp_sth->bind_columns (undef, @_cipp_col_refs);'."\n".
2629             ' my $_cipp_maxrows;'."\n",
2630             $throw
2631             );
2632              
2633             # code for MAXROWS/WINSTART/WINSIZE stuff
2634              
2635             my $maxrows_cond;
2636            
2637             if ( defined $maxrows ) {
2638             $self->writef (
2639             ' $_cipp_maxrows = %s;'."\n",
2640             $maxrows
2641             );
2642             $maxrows_cond = '$_cipp_maxrows-- > 0 and';
2643             }
2644              
2645             my $winstart_cmd;
2646              
2647             if ( defined $winstart ) {
2648             $self->writef (
2649             ' $_cipp_maxrows = %s+%s;'."\n".
2650             ' my $_cipp_winstart = %s;'."\n",
2651             $winstart,
2652             $winsize,
2653             $winstart
2654             );
2655             $winstart_cmd = 'next if --$_cipp_winstart > 0;'."\n";
2656             $maxrows_cond = '--$_cipp_maxrows > 0 and';
2657             }
2658              
2659             if ( $options->{cond} ) {
2660             $maxrows_cond .= " ($options->{cond}) and";
2661             }
2662              
2663             # fetch loop
2664              
2665             $self->writef (
2666             ' my $_cipp_utf8 = $CIPP::request->get_utf8;'."\n".
2667             ' SQL: while ( %s $_cipp_sth->fetch ) {'."\n".
2668             ' if ( $_cipp_utf8 ) {'."\n".
2669             ' Encode::_utf8_on($_) for (%s);'."\n".
2670             ' }'."\n",
2671             $maxrows_cond,
2672             $var_list
2673             );
2674              
2675             $self->write ($winstart_cmd) if $winstart_cmd;
2676            
2677             return $self->RC_BLOCK_TAG (
2678             type => 'select',
2679             throw => $throw,
2680             profile => $profile,
2681             );
2682              
2683             } else {
2684             # we assume a do statement without a result set
2685             my $result_code = "";
2686             $result_code = "${my_cmd}$result_var = " if $options->{result};
2687              
2688             $self->writef (
2689             '%s$CIPP::request->sql_do ('."\n".
2690             ' %s, qq{%s}, [%s], qq{%s}, qq{%s}'."\n".
2691             ');'."\n",
2692             $result_code,
2693             $dbh_code,
2694             $sql,
2695             $params_code,
2696             $throw,
2697             $profile
2698             );
2699              
2700             return $self->RC_BLOCK_TAG (
2701             type => 'do',
2702             );
2703             }
2704             }
2705              
2706             sub cmd_incinterface {
2707             my $self = shift; $self->trace_in;
2708             my %par = @_;
2709             my ($tag, $options, $options_case, $closed) =
2710             @par{'tag','options','options_case','closed'};
2711              
2712             my $RC = $self->RC_SINGLE_TAG;
2713              
2714             if ( $self->get_object_type ne 'cipp-inc' ) {
2715             $self->add_tag_message (
2716             message =>
2717             "Illegal use of the ".
2718             "command. This is not a CIPP Include."
2719             );
2720             return $RC;
2721             }
2722              
2723             if ( $self->get_state->{incinterface}->{input} ) {
2724             $self->add_tag_message (
2725             message =>
2726             "Multiple occurence of ."
2727             );
2728             return $RC;
2729             }
2730              
2731             $self->check_options (
2732             optional => {
2733             input => 1,
2734             optional => 1,
2735             output => 1,
2736             noquote => 1,
2737             }
2738             ) or return $RC;
2739              
2740             if ( not defined $options->{input} and
2741             not defined $options->{optional} ) {
2742             $self->get_state->{include_noinput} = 1;
2743             }
2744              
2745             if ( not defined $options->{output} ) {
2746             $self->get_state->{include_nooutput} = 1;
2747             }
2748              
2749             my $input = $self->parse_variable_option_hash (
2750             option => 'input',
2751             name2var => 1,
2752             );
2753             my $optional = $self->parse_variable_option_hash (
2754             option => 'optional',
2755             name2var => 1,
2756             );
2757             my $noquote = $self->parse_variable_option_hash (
2758             option => 'noquote',
2759             name2var => 1,
2760             );
2761             my $output = $self->parse_variable_option_hash (
2762             option => 'output',
2763             name2var => 1,
2764             );
2765              
2766             $self->get_state->{incinterface}->{input} = $input;
2767             $self->get_state->{incinterface}->{optional} = $optional;
2768             $self->get_state->{incinterface}->{noquote} = $noquote;
2769             $self->get_state->{incinterface}->{output} = $output;
2770              
2771             my @unknown;
2772             foreach my $var ( keys %{$noquote} ) {
2773             push @unknown, $var if not defined $input->{$var} and
2774             not defined $optional->{$var};
2775             }
2776             if ( @unknown ) {
2777             $self->add_tag_message (
2778             message => "Unknown NOQUOTE variable(s): ".
2779             join (", ", @unknown)
2780             );
2781             }
2782              
2783             my %double;
2784             foreach my $var ( keys %{$input}, keys %{$optional} ) {
2785             $double{$var} = 1 if defined $input->{$var} and
2786             defined $optional->{$var};
2787             }
2788             if ( %double ) {
2789             $self->add_tag_message (
2790             message => "Illegal INPUT and OPTIONAL declared variable(s): ".
2791             join (", ", sort keys %double)
2792             );
2793             }
2794              
2795             return $RC;
2796             }
2797              
2798             sub cmd_include {
2799             my $self = shift; $self->trace_in;
2800             my %par = @_;
2801             my ($tag, $options, $options_case, $closed) =
2802             @par{'tag','options','options_case','closed'};
2803              
2804             my $RC = $self->RC_SINGLE_TAG;
2805              
2806             $self->check_options (
2807             mandatory => { 'name' => 1 },
2808             optional => { '*' => 1 },
2809             ) || return $RC;
2810              
2811             my $options = $self->get_current_tag_options;
2812              
2813             my $name = delete $options->{name};
2814             my $my = delete $options->{'my'};
2815              
2816             # filter output parameters from $options
2817             my ($var_output, $var);
2818             foreach $var ( keys %{$options} ) {
2819             if ( $var =~ /^[\$\@\%]/ ) {
2820             # output parameters begin with $, @, % an
2821             my $var_name = $options->{$var};
2822             $var_name =~ tr/A-Z/a-z/;
2823             $var_output->{$var_name} = $var;
2824             delete $options->{$var};
2825             }
2826             }
2827              
2828             # memorize that we use this Include
2829             $self->add_used_object (
2830             name => $name,
2831             type => 'cipp-inc'
2832             );
2833              
2834             # check filename of Include
2835             my $filename = $self->get_object_filename ( name => $name );
2836              
2837             if ( not defined $filename ) {
2838             $self->add_tag_message (
2839             message => "Include $name not found."
2840             );
2841             return $RC;
2842             }
2843              
2844             if ( not -r $filename ) {
2845             $self->add_tag_message (
2846             message =>
2847             "Include file '$filename' ($name) ".
2848             "not readable."
2849             );
2850             return $RC;
2851             }
2852              
2853             # first process this Include (cached)
2854             my $include_parser = $self->create_new_parser (
2855             object_type => 'cipp-inc',
2856             program_name => $name,
2857             );
2858              
2859             # check recursive inclusion
2860             my $norm_name = $include_parser->get_norm_name;
2861             # print "

trace=".$self->get_inc_trace." norm_name=$norm_name

\n";
2862              
2863             if ( $self->get_inc_trace =~ /:$norm_name:/ ) {
2864             $self->add_tag_message (
2865             message =>
2866             "Illegal recursive inclusion of ".
2867             "Include '$name' (trace is '".
2868             $self->get_inc_trace."')",
2869             );
2870             return $RC;
2871             }
2872              
2873             $include_parser->process;
2874              
2875             # copy error messages of this Include into $self
2876             foreach my $msg ( @{$include_parser->get_messages} ) {
2877             $self->add_message_object (
2878             object => $msg
2879             );
2880             }
2881              
2882             # check if the actual parameters match the Includes interface
2883             return $RC if not $self->interface_is_correct (
2884             include_parser => $include_parser,
2885             input => $options,
2886             output => $var_output
2887             );
2888              
2889             # now generate Include subroutine call code
2890             my $code = '';
2891             my $interface = $include_parser->read_include_interface_file;
2892              
2893             # get output parameters
2894             my $output = $var_output;
2895             if ( $my ) {
2896             if ( keys %{$output} ) {
2897             $code .= "my (";
2898             foreach my $var_name ( values %{$output} ) {
2899             $code .= "$var_name,";
2900             }
2901             $code =~ s/,$//;
2902             $code .= ");\n";
2903             }
2904             }
2905              
2906             # these three files are neccessary for include processing
2907             my $sub_filename = $self->get_relative_inc_path (
2908             filename => $include_parser->get_prod_filename
2909             );
2910              
2911             # call subroutine
2912             $code .= '$CIPP::request->call_include_subroutine ('."\n";
2913             $code .= "\tfile => '$sub_filename',\n";
2914             $code .= "\tinput => {\n";
2915            
2916             # input parameters
2917             my $input = $options;
2918             my $quote_start;
2919             my $quote_end;
2920             my $val;
2921              
2922             foreach my $name ( keys %{$input} ) {
2923             my $var = $interface->{input}->{$name} ||
2924             $interface->{optional}->{$name};
2925             $var =~ /^(.)/;
2926             my $type = $1;
2927              
2928             if ( $type eq '$' ) {
2929             # scalar parameter
2930             $quote_start = defined $interface->{noquote}->{$name}
2931             ? '' : 'qq{';
2932             $quote_end = defined $interface->{noquote}->{$name}
2933             ? '' : '}';
2934             $val = $input->{$name};
2935             $code .= "\t\t$name => $quote_start$val$quote_end,\n";
2936              
2937             } elsif ( $type eq '@' ) {
2938             # list parameter
2939             $code .= "\t\t$name => [ $input->{$name} ],\n";
2940              
2941             } elsif ( $type eq '%' ) {
2942             # hash parameter
2943             $code .= "\t\t$name => { $input->{$name} },\n";
2944             }
2945             }
2946            
2947             $code .= "\t},\n";
2948            
2949             # tell which output parameters we want
2950             if ( keys %{$output} ) {
2951             $code .= "\toutput => {\n";
2952             my $type;
2953             foreach my $name ( keys %{$output} ) {
2954             my $var = $output->{$name};
2955             $code .= "\t\t\t'$name' => \\$var,\n";
2956             }
2957             $code .= "\t\t},\n";
2958             }
2959            
2960             $code .= ");\n";
2961            
2962             $self->write ( $code );
2963              
2964             return $RC;
2965             }
2966              
2967             sub cmd_httpheader {
2968             my $self = shift; $self->trace_in;
2969             my %par = @_;
2970             my ($tag, $options, $options_case, $closed) =
2971             @par{'tag','options','options_case','closed'};
2972              
2973             my $RC = $self->RC_BLOCK_TAG;
2974              
2975             if ( $self->get_current_tag_closed ) {
2976             $self->pop_context;
2977             $self->writef (
2978             "\n".
2979             " }; # end of generic exception handler eval\n\n".
2980             ' # check for an exception (filters exception)'."\n".
2981             ' if ( $@ and $@ !~ /_cipp_exit_command/ ) {'."\n".
2982             ' $CIPP::request->error ('."\n".
2983             ' message => $@,'."\n".
2984             ' httpheader => "%s"'."\n".
2985             ' );'."\n".
2986             ' die "_cipp_exit_command";'."\n".
2987             ' } elsif ( $@ ) {'."\n".
2988             ' die $@;'."\n".
2989             ' }'."\n\n",
2990             $self->get_program_name
2991             );
2992              
2993             $self->write (
2994             q[ 1;]."\n",
2995             q[};]."\n",
2996             );
2997              
2998             my $buffer_sref = $self->close_output_buffer;
2999              
3000             $self->check_options (
3001             mandatory => {},
3002             optional => {},
3003             ) || return $RC;
3004              
3005             my $http_filename = $self->get_http_filename;
3006              
3007             return $RC if not $http_filename;
3008              
3009             my $fh = FileHandle->new;
3010             if ( open ($fh, ">$http_filename") ) {
3011             print $fh $$buffer_sref;
3012             close $fh;
3013             } else {
3014             $self->add_tag_message (
3015             message => "Can't write '$http_filename'"
3016             );
3017             }
3018            
3019             return $RC;
3020             }
3021              
3022             # We open the output buffer before error checking,
3023             # because the closed_tag code above assumes it.
3024             $self->open_output_buffer;
3025             $self->push_context('perl');
3026              
3027             # now check for errors
3028             $self->check_options (
3029             mandatory => { 'var' => 1 },
3030             optional => { 'my' => 1 },
3031             ) || return $RC;
3032              
3033             my $var = $self->parse_variable_option (
3034             option => 'var', types => [ 'scalar' ]
3035             ) || return $RC;
3036              
3037             # prevent multiple instances
3038             if ( $self->get_state->{http_header_occured} ) {
3039             $self->add_tag_message (
3040             message => "Only one per program allowed.",
3041             );
3042             return $RC;
3043             }
3044            
3045             # only allowed in CGIs and Includes
3046             if ( $self->get_object_type ne 'cipp' and $self->get_object_type ne 'cipp-inc' ) {
3047             $self->add_tag_message (
3048             message => " only allowed inside Programs or Includes",
3049             );
3050             return $RC;
3051             }
3052              
3053             $self->get_state->{http_header_occured} = 1;
3054              
3055             # generate HTTP header code, like an Include subroutine
3056             $self->writef (
3057             q[sub {]."\n".
3058             q[ use strict;]."\n".
3059             q[ shift;]."\n".
3060             # q[ my $_cipp_line_nr;]."\n".
3061             q[ my %s = $CIPP::request->get_http_header;]."\n".
3062             q[ eval {]."\n",
3063             $var
3064             );
3065              
3066             return $RC;
3067             }
3068              
3069             sub cmd_lang {
3070             my $self = shift; $self->trace_in;
3071              
3072             my $RC = $self->RC_BLOCK_TAG;
3073              
3074             if ( $self->get_current_tag_closed ) {
3075             $self->pop_context;
3076             $self->write("^)");
3077             $self->write(";\n") if $self->context eq 'perl';
3078             return $RC;
3079             }
3080              
3081             $self->check_options (
3082             mandatory => {},
3083             optional => {},
3084             ) || return $RC;
3085            
3086             $self->push_context('var_noquote');
3087            
3088             $self->write("CIPP->request->set_locale_messages_lang(qq^");
3089            
3090             return $RC;
3091             }
3092              
3093             sub cmd_l {
3094             my $self = shift; $self->trace_in;
3095              
3096             my $RC = $self->RC_BLOCK_TAG;
3097              
3098             if ( $self->get_current_tag_closed ) {
3099             $self->check_options (
3100             mandatory => {},
3101             optional => {},
3102             ) || return $RC;
3103              
3104             my $buffer_sref = $self->close_output_buffer;
3105             my (undef, $options) = $self->pop_context;
3106             my $context = $self->context;
3107              
3108             ${$buffer_sref} =~ s/^\s+//gm;
3109             ${$buffer_sref} =~ s/\s*$/ /gm;
3110             ${$buffer_sref} =~ s/\s+$//s;
3111             ${$buffer_sref} =~ s/\^/\\^/g;
3112             ${$buffer_sref} =~ s/\s+/ /gs;
3113              
3114             $options ||= {};
3115              
3116             $self->write("print ") if $context ne 'perl' &&
3117             $context !~ /^var/;
3118             $self->write("^.") if $context eq 'var_quote';
3119              
3120             my $domain = $self->get_text_domain;
3121              
3122             if ( $options and keys %{$options} ) {
3123             my $options_hash = "{ ";
3124             while ( my ($k,$v) = each %{$options} ) {
3125             $v =~ s/\^/\\^/g;
3126             $options_hash .= "'$k' => qq^$v^, ";
3127             }
3128             $options_hash .= "}";
3129             $self->writef (
3130             qq[\$CIPP::request->dgettext("$domain",qq^%s^, $options_hash)],
3131             ${$buffer_sref}
3132             );
3133             } else {
3134             $self->writef (
3135             qq[\$CIPP::request->dgettext("$domain",qq^%s^)],
3136             ${$buffer_sref}
3137             );
3138             }
3139              
3140             $self->write(";\n") if $context ne 'perl' &&
3141             $context !~ /^var/;
3142             $self->write(".qq^") if $context eq 'var_quote';
3143              
3144             return $RC;
3145             }
3146              
3147             $self->open_output_buffer;
3148              
3149             my %data;
3150             my $options_case = $self->get_current_tag_options_case;
3151             my $options = $self->get_current_tag_options;
3152              
3153             foreach my $opt ( keys %{$options_case} ) {
3154             $data{$options_case->{$opt}} = $options->{$opt};
3155             }
3156              
3157             $self->push_context('var_noquote', \%data);
3158              
3159             return $RC;
3160              
3161             }
3162              
3163             1;