line
stmt
bran
cond
sub
pod
time
code
1
#####################################
2
package HTML::Merge::Compile;
3
#####################################
4
BEGIN
5
{
6
1
1
1266
eval 'use HTML::Merge::Ext;';
1
1
593
1
2
1
44
7
}
8
# Modules ###########################
9
10
1
1
5
use strict qw(subs vars);
1
3
1
41
11
1
97
use vars qw($open %enders %printers %tokenizers $VERSION $DEBUG
12
1
1
5
$INTERNAL_DB $INTERNAL_DB_TYPE);
1
2
13
1
1
6
use Carp;
1
1
1
130
14
1
1
7
use Config;
1
3
1
41
15
1
1
951
use subs qw(quotemeta);
1
28
1
4
16
17
#####################################
18
$VERSION = '3.54';
19
#####################################
20
# Globals ###########################
21
$open = '\$R';
22
#my @non_flow = qw(VAR SQL ASSIGN SET PSET PGET PIC STATE INDEX CFG);
23
#@non_flow{@non_flow} = @non_flow;
24
25
my @printers = qw(VERSION VAR SQL GET PGET PVAR INDEX PIC STATE CFG INI LOGIN
26
AUTH DECIDE EMPTY DATE DAY MONTH YEAR DATEDIFF LASTDAY ADDDATE
27
USER MERGE TEMPLATE TRANSFER DUMP NAME TAG COOKIE SOURCE
28
DATE2UTC UTC2DATE ENV DATEF EVAL HOUR MINUTE SECOND);
29
@printers{@printers} = @printers;
30
31
#my @stringers = qw(IF SET PSET SETCFG);
32
#@stringers{@stringers} = @stringers;
33
34
my @tokenizers = qw();
35
@tokenizers{@tokenizers} = @tokenizers;
36
37
%enders = qw(END_IF IF END LOOP END_WHILE WHILE);
38
39
$INTERNAL_DB_TYPE='SQLite';
40
41
#####################################
42
# locate the template from the various paths
43
sub GetTemplateFromPath
44
{
45
0
0
0
my ($template) = @_;
46
47
0
my @input = ("$HTML::Merge::Ini::TEMPLATE_PATH/$template",
48
"$HTML::Merge::Ini::MERGE_ABSOLUTE_PATH/public/template/$template");
49
50
# let lets find the input
51
0
foreach (@input)
52
{
53
0
0
if (-f)
54
{
55
0
return $_;
56
}
57
}
58
59
0
return "$HTML::Merge::Ini::TEMPLATE_PATH/$template";
60
}
61
#####################################
62
sub WantPrinter
63
{
64
0
0
0
my ($self, $tag, $dtag, $dline) = @_;
65
66
0
my $ret = $self->WantTag($tag);
67
0
0
return $ret if ($printers{$tag});
68
0
my $line = $self->Line;
69
0
$self->Die("$tag is not an output tag, perhaps you forgot to close a string in tag $dtag from line $dline? Output tags are " . join(", ", keys %printers));
70
}
71
#####################################
72
sub Translate
73
{
74
0
0
0
my ($self, $exp) = @_;
75
0
my $result = "\\\\[=\\.]";
76
0
my $i;
77
my @fetch;
78
0
my $tail;
79
80
0
while ($exp =~ s/^(.*?)([QUELD])//i)
81
{
82
0
my ($before, $token) = ($1, uc($2));
83
0
$result .= quotemeta(quotemeta($before));
84
85
0
0
if ($token eq 'U')
0
0
0
0
86
{
87
0
$result .= '(.*?)';
88
0
$i++;
89
0
push(@fetch, "\$$i");
90
}
91
elsif ($token eq 'L')
92
{
93
0
$result .= '([A-Z])';
94
0
$i++;
95
0
push(@fetch, "\$$i");
96
}
97
elsif ($token eq 'Q')
98
{
99
0
$i++;
100
0
$result .= "\\\\(['\"])(.*?)\\\\\\$i";
101
0
$i++;
102
0
push(@fetch, "\$$i");
103
}
104
elsif ($token eq 'E')
105
{
106
0
$result .= '(?:';
107
0
$tail = ')?' . $tail;
108
}
109
elsif ($token eq 'D')
110
{
111
0
$result .= "\\\\[\\.=]";
112
}
113
else
114
{
115
0
$self->Die("Unknown notator: $token");
116
}
117
}
118
119
0
$result .= quotemeta(quotemeta($exp)) . $tail;
120
0
my $fetch = '(' . join(", ", @fetch) . ')';
121
0
($result, $fetch);
122
}
123
#################################
124
# CGI parsing utility #
125
#################################
126
sub ParseForm
127
{
128
0
0
0
my $toParse = shift;
129
0
my ($name , $value , @pairs , $pair , %FORM);
130
0
@pairs = split(/&/, $toParse);
131
0
foreach $pair (@pairs) {
132
0
($name, $value) = split(/=/, $pair);
133
0
$value =~ tr/+/ /;
134
0
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
0
135
0
$FORM{$name} = $value;
136
#Debug("kak : $name \= $value");
137
}
138
0
return \%FORM;
139
}
140
#####################################
141
sub CgiParse
142
{
143
0
0
0
my $GFORM = &ParseForm($ENV{'QUERY_STRING'});
144
0
my $buffer;
145
0
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
146
0
my $PFORM = &ParseForm($buffer);
147
148
0
my (%FORM , $key);
149
0
foreach $key(keys %$GFORM){
150
0
$FORM{$key} = $GFORM->{$key};
151
}
152
153
0
foreach $key(keys %$PFORM){
154
0
$FORM{$key} = $PFORM->{$key};
155
}
156
0
return \%FORM;
157
}
158
#####################################
159
sub WantTag
160
{
161
0
0
0
my ($self, $tag, $inv) = @_;
162
0
my $candidate = $enders{$tag};
163
0
0
0
if ($candidate && !$inv)
164
{
165
0
$tag = $candidate;
166
0
$inv = 1;
167
}
168
0
0
my $un = $inv ? "Un" : "";
169
0
my $code = UNIVERSAL::can($self, "Do$un$tag");
170
0
0
return $code if $code;
171
0
my $macro = UNIVERSAL::can('HTML::Merge::Ext', "MACRO_$tag");
172
0
0
if ($macro)
173
{
174
0
my $proto = prototype("HTML::Merge::Ext::MACRO_$tag");
175
0
my $text = quotemeta(&$macro);
176
0
0
$proto = " ($proto)" if $proto;
177
178
0
eval <
179
package HTML::Merge::Ext;
180
181
sub API_$tag$proto
182
{
183
Macro("$text", \@_);
184
}
185
EOM
186
}
187
188
0
foreach my $api (qw(API OUT))
189
{
190
0
my $candidate = "RUN${api}_$tag";
191
0
my $code = UNIVERSAL::can('HTML::Merge::Ext', $candidate);
192
0
0
if ($code)
193
{
194
0
my $proto = prototype("HTML::Merge::Ext::$candidate");
195
0
$proto =~ s/;.*$//;
196
0
0
$self->Die("Prototype for $candidate may include only \$ signs")
197
unless ($proto =~ /^\$*$/);
198
0
my $check = "${api}_$tag";
199
0
my $code = UNIVERSAL::can('HTML::Merge::Ext', $check);
200
0
0
unless ($code)
201
{
202
0
my @par;
203
0
my $i = 0;
204
0
foreach (split(//, $proto))
205
{
206
0
push(@par, qq{"\$_[$i]"});
207
0
$i++;
208
}
209
0
my $pass = join(", ", @par);
210
0
my $text = "package HTML::Merge::Ext;
211
sub $check ($proto)
212
{
213
$candidate($pass);
214
}";
215
0
eval $text;
216
0
0
die $@ if $@;
217
0
last;
218
}
219
}
220
}
221
0
0
my @options = !$inv ? qw(API OAPI OUT) : qw(CAPI);
222
0
foreach my $api (@options)
223
{
224
0
my $candidate = "${api}_$tag";
225
0
$code = UNIVERSAL::can('HTML::Merge::Ext', $candidate);
226
0
0
if ($code)
227
{
228
0
my $ref = ref($self);
229
0
my $proto = prototype("HTML::Merge::Ext::$candidate");
230
0
$proto =~ s/;.*$//;
231
0
0
$self->Die("Prototype for $candidate may include only \$ signs")
232
unless ($proto =~ /^\$*$/);
233
0
my $n = length($proto);
234
0
my $shift = join(", ",
235
0
map {"\$param[$_]";} (0 .. $n - 1));
236
0
my $stack;
237
0
my $scope = lc($tag);
238
0
0
if ($api eq 'OAPI')
239
{
240
0
$stack = qq!\$self->Push('$scope', \$engine);!;
241
}
242
0
0
if ($api eq 'CAPI')
243
{
244
0
$stack = qq!\$self->Expect(\$engine, '$scope');!
245
}
246
0
my $desc = UNIVERSAL::can('HTML::Merge::Ext',
247
"DESC_$tag");
248
0
my $expand;
249
0
0
unless ($desc)
250
{
251
0
$expand = 'my @param = @$param;';
252
0
$tokenizers{$tag} = 1;
253
}
254
else
255
{
256
0
0
if ($api eq 'CAPI')
257
{
258
0
$expand = 'my @param;';
259
}
260
else
261
{
262
0
my $txt = &$desc;
263
0
my ($re, $form) = $self->Translate($txt);
264
0
$expand = <
265
unless (\$param =~ /^$re\$/s)
266
{
267
\$self->Syntax;
268
}
269
my \@param = $form;
270
EOM
271
}
272
}
273
0
my $extend = <
274
package $ref;
275
sub Do$un$tag
276
{
277
my (\$self, \$engine, \$param) = \@_;
278
$expand
279
my \$n = \@param;
280
\$self->Die("$n parameters expected for $tag, gotten \$n") unless (\$n == $n);
281
$stack
282
\$HTML::Merge::Ext::ENGINE = \$engine;
283
\$HTML::Merge::Ext::COMPILER = \$self;
284
HTML::Merge::Ext::$candidate($shift);
285
}
286
EOM
287
0
eval $extend;
288
0
0
$self->Die($@) if $@;
289
0
$printers{$tag} = ($api eq 'OUT');
290
0
return $self->WantTag($tag, $inv);
291
}
292
}
293
0
$self->Die("$tag is not a valid Merge tag");
294
}
295
#####################################
296
sub quotemeta {
297
0
0
my $text = CORE::quotemeta(shift);
298
0
$text =~ s/\\ / /g;
299
0
$text =~ s/\\\t/\t/g;
300
0
$text;
301
}
302
#####################################
303
sub Compile {
304
0
0
0
my $self = {'buffer' => '', 'scopes' => []};
305
0
my $class = __PACKAGE__;
306
0
my $in = $HTML::Merge::config;
307
0
$in =~ s|/\w+\.\w+$||;
308
0
$in =~ s|^/*||;
309
0
$in =~ s/[\/\\]/::/g;
310
0
$in =~ tr/A-Za-z0-9_://cd;
311
0
0
if ($in) {
312
0
my $code = <
313
package ${class}::$in;
314
use strict 'vars';
315
use vars qw(\@ISA);
316
\@ISA = qw($class);
317
EOM
318
0
eval $code;
319
0
0
die $@ if $@;
320
0
$class .= "::$in";
321
}
322
0
bless $self, $class;
323
0
$self->{'source'} = shift;
324
0
$self->{'source'} =~ s/\r\n/\n/g;
325
0
$self->{'save'} = $self->{'source'};
326
0
$self->{'name'} = shift;
327
0
$self->{'template'} = $self->{'name'};
328
0
$self->{'template'} =~ s|^$HTML::Merge::Ini::TEMPLATE_PATH/||;
329
0
$self->{'force line'} = shift;
330
0
$self->Main;
331
0
$self->{'buffer'};
332
}
333
#####################################
334
sub Clone {
335
0
0
0
my $self = shift;
336
337
0
return bless {},ref($self);
338
}
339
#####################################
340
sub Clause {
341
0
0
0
my ($self,$text,$in) = @_;
342
343
0
my $new=$self->Clone();
344
0
my $error;
345
my $res;
346
347
0
$new->{'save'} = $new->{'source'} = "$text>";
348
0
eval{
349
0
$res=$new->EatParam($in);
350
};
351
352
0
0
if($@){
353
0
$error=$@;
354
0
$error=~ s/ at .* line .*$//;
355
0
$self->Die($error);
356
}
357
0
$res=~ s/\n+$//s;
358
359
0
return $res;
360
}
361
#####################################
362
sub Line {
363
0
0
0
my $self = shift;
364
0
my $force = $self->{'force line'};
365
0
0
return $force if $force;
366
0
my @lines = split(/\n/, $self->{'save'});
367
0
my $left = substr($self->{'save'}, -length($self->{'source'}));
368
0
my @ll = split(/\n/, $left);
369
0
my $this = @lines - @ll + 1;
370
}
371
#####################################
372
sub Mark {
373
0
0
0
my $self = shift;
374
0
my $name = $self->{'name'};
375
0
my $this = $self->Line;
376
0
0
return unless $name;
377
0
$self->{'buffer'} .= "\$HTML::Merge::context = [\"$name\", \"$this\"];\n";
378
0
$self->{'buffer'} .= "#line $this $name\n";
379
0
return;
380
}
381
#####################################
382
sub Die {
383
0
0
0
my ($self, $error) = @_;
384
0
my $this = $self->Line;
385
0
my $s = (split(/\n/, $self->{'save'}))[$this - 1];
386
0
my $name = $self->{'name'};
387
0
0
if ($error < 0) {
388
0
die "Depcrecated: Die(negative)";
389
}
390
391
0
$name =~ s|^.*/||;
392
0
0
0
Carp::cluck "Error: $error at $name line $this when doing: $s" if $DEBUG
393
|| $ENV{'MERGE_DEBUG'};
394
0
die "Error: $error at $name line $this, when doing: $s";
395
}
396
#####################################
397
sub Main {
398
0
0
0
my $self = shift;
399
0
$self->{'source'} =~ s/<(BODY)/\n<$1/i;
400
0
while ($self->EatOne) {}
401
0
$self->PrePrint($self->{'source'});
402
0
$self->{'source'} = '';
403
0
0
if (@{$self->{'scopes'}}) {
0
404
0
my @scopes = map {join("/", @$_);} @{$self->{'scopes'}};
0
0
405
0
my $stack = join(", ", @scopes);
406
0
$self->Die("Stack not empty: $stack");
407
}
408
}
409
#####################################
410
sub EatOne {
411
0
0
0
my $self = shift;
412
0
0
if ($self->{'source'} =~ s/^(.*?)\<(\/?)$open(\[.+?\]\.)?(\w+)//si) {
413
0
my ($head, $close, $engine, $tag, $param) = ($1, $2, $3, uc($4));
414
0
$engine =~ s/^\[(.*)\]\./$1/;
415
0
0
$engine= $self->Clause($engine,$tag) if($engine=~ /\<$open/);
416
417
0
my $code = $self->WantTag($tag, $close);
418
0
$param = $self->EatParam($tag);
419
0
0
0
$self->Die("Closing tags may not have parameters") if (($close || $enders{$tag}) && ($param && !ref($param) || ref($param) && $#$param >= 0));
0
0
420
0
$self->Mark;
421
0
0
if ($printers{$tag}) {
422
0
$self->PrePrint($head);
423
0
$self->{'buffer'} .= "print (";
424
} else {
425
0
$head =~ s/\s+$//s;
426
0
$self->PrePrint($head);
427
}
428
0
$self->{'buffer'} .= &$code($self, $engine, $param);
429
0
0
if ($printers{$tag}) {
430
0
$self->{'buffer'} .= ");\n";
431
}
432
0
return 1;
433
}
434
0
undef;
435
}
436
#####################################
437
sub Macro {
438
0
0
0
my ($self, $text) = @_;
439
0
my $length = length($self->{'source'});
440
0
my $lennow;
441
442
0
$self->{'source'} = $text . $self->{'source'};
443
0
for (;;) {
444
0
$lennow = length($self->{'source'});
445
0
0
last if ($lennow <= $length);
446
0
my $left = $lennow - $length;
447
0
0
last if $self->{'source'} =~ /^\s{$left}/;
448
449
0
0
$self->EatOne || last;
450
}
451
0
my $remainder = $lennow - $length;
452
0
0
$self->Die("macro did not resolve correctly") if ($remainder < 0);
453
0
$self->PrePrint(substr($self->{'source'}, 0, $remainder));
454
0
substr($self->{'source'}, 0, $remainder) = "";
455
}
456
#####################################
457
sub PrePrint {
458
0
0
0
my ($self, $string) = @_;
459
0
while ($string =~ s/^(.*?)\0(.*?)\0//) {
460
0
my ($b4, $bt) = ($1, $2);
461
462
0
$self->Print($b4);
463
0
$self->{'buffer'} .= qq'print "$bt";';
464
}
465
0
0
$self->Print($string) if $string;
466
}
467
#####################################
468
sub Print {
469
0
0
0
my ($self, $string) = @_;
470
0
my @lines = split(/\n/, $string);
471
0
my $last = pop @lines;
472
0
foreach (@lines) {
473
0
$self->{'buffer'} .= 'print "' . quotemeta($_) . '\n";' . "\n";
474
}
475
0
$self->{'buffer'} .= 'print "' . quotemeta($last) . '";' . "\n";
476
0
0
$self->{'buffer'} .= 'print "\n";' . "\n" if ($string =~ /\n$/);
477
}
478
#####################################
479
sub EatParam {
480
0
0
0
my ($self, $in) = @_;
481
0
my $tokens = $tokenizers{$in};
482
0
my $line = $self->Line;
483
0
my $state = '';
484
0
my $text = '';
485
0
my @tokens;
486
0
for (;;) {
487
0
my $ch;
488
0
0
if ($self->{'source'} =~ s/^(.)//s) {
489
0
$ch = $1;
490
} else {
491
0
$self->Die("Could not close tag $in, probably unbalanced quotes");
492
}
493
0
0
if ($ch eq "\0") {
494
0
0
unless ($self->{'source'} =~ s/^(.*?)\0//) {
495
0
$self->Die("Unclosed null encpasulation. Check your macro");
496
}
497
0
$text .= $1;
498
0
next;
499
}
500
0
0
0
if ($ch eq "'" && $state ne '"') {
501
0
$text .= "\\'";
502
0
0
$state = ($state eq "'" ? '' : "'");
503
0
next;
504
}
505
0
0
0
if ($ch eq '"' && $state ne "'") {
506
0
$text .= "\\\"";
507
0
0
$state = ($state eq '"' ? '' : '"'); #'"
508
0
next;
509
}
510
0
0
if ($ch eq "\\") {
511
0
$self->{'source'} =~ s/^(.)//s;
512
0
$ch = $1;
513
0
$text .= "\\$ch";
514
0
next;
515
}
516
0
0
0
if ($ch eq '>' && !$state) {
517
0
$text =~ s/\s+$//;
518
0
0
return $text unless $tokens;
519
0
0
return [] unless @tokens;
520
0
my $pre = shift @tokens;
521
0
0
$self->Die("Illegal prefix $pre") if $pre;
522
0
push(@tokens, $text);
523
0
return \@tokens;
524
}
525
0
0
0
if ($ch eq '.' && !$state && $tokens) {
0
526
0
push(@tokens, $text);
527
0
$text = '';
528
0
next;
529
}
530
0
0
if ($ch eq "<") {
531
0
0
unless ($self->{'source'} =~ s/^$open//) {
532
0
$text .= "<";
533
0
0
$text .= $self->FindRight if $in eq 'EM';
534
0
next;
535
}
536
0
$self->{'source'} =~ s/(\[.+?\]\.)?(\w+)//;
537
0
my $engine = $1;
538
0
my $tag = uc($2);
539
0
$engine =~ s/^\[(.*)\]\./$1/;
540
0
0
$engine= $self->Clause($engine,$tag) if($engine=~ /\<$open/);
541
0
my $code;
542
0
0
if ($in ne 'EM') {
543
0
$code = $self->WantPrinter($tag, $in, $line);
544
}
545
0
0
my $sub = $self->EatParam($in eq 'EM' ? 'EM' : $tag);
546
0
0
if ($in ne 'EM') {
547
0
$text .= '" . (' . &$code($self, $engine, $sub) . ') . "';
548
}
549
} else {
550
0
$text .= quotemeta($ch);
551
}
552
}
553
}
554
#####################################
555
sub FindRight {
556
0
0
0
my $self = shift;
557
0
my $count = 1;
558
0
my $text;
559
0
while ($self->{'source'} =~ s/^(.*?)([\<\>])//) {
560
0
$text .= "$1$2";
561
0
0
$count += $2 eq '<' ? 1 : -1;
562
0
0
return $text unless $count;
563
}
564
0
return $text;
565
}
566
#####################################
567
sub Expect {
568
0
0
0
my ($self, $engine, @options) = @_;
569
0
my $current = pop @{$self->{'scopes'}};
0
570
0
my @topt = @options;
571
0
my $last = pop @topt;
572
0
0
my $expect = join(", ", @topt) . (@topt ? ' or ' : '') . $last;
573
0
0
$self->Die("Stack underflow - a closing tag without a preceding tag, expecting: $expect. Perhaps you forgot $open in the opening tag?") unless ($current);
574
0
my ($scope, $teng) = @$current;
575
0
0
$self->Die("Expected engine '$engine', got '$teng'") unless ($teng eq $engine);
576
0
foreach (@options) {
577
0
0
return if ($_ eq $scope);
578
}
579
0
$self->Die("Unexpected scope $scope, expecting: $expect. Perhaps you forgot $open in the opening tag?");
580
}
581
#####################################
582
sub Push {
583
0
0
0
my ($self, $scope, $engine) = @_;
584
0
push(@{$self->{'scopes'}}, [$scope, $engine]);
0
585
}
586
#####################################
587
sub DoLOOP {
588
0
0
0
my ($self, $engine, $param) = @_;
589
0
my $limit = undef;
590
0
0
if ($param =~ s/^\\\.LIMIT\\=((?:\\['"])?)(.+)\1$//s) { #'
591
0
$limit = $2;
592
}
593
0
0
$self->Syntax if $param;
594
0
my $text;
595
0
0
unless ($limit) {
596
0
$text = <
597
local (\$_);
598
for (;;) {
599
\$_++;
600
EOM
601
} else {
602
0
$text = <
603
HTML::Merge::Engine::Force("$limit", 'iu');
604
foreach (1 .. "$limit") {
605
EOM
606
}
607
0
$text .= <
608
last unless (\$engines{"$engine"}->HasQuery);
609
last unless (\$engines{"$engine"}->Fetch(1, \$_));
610
local (\$_);
611
EOM
612
0
$self->Push('loop', $engine);
613
0
$text;
614
}
615
#####################################
616
617
*DoEPEAT = \&DoITERATION;
618
*DoUnEPEAT = \&DoUnITERATION;
619
620
#####################################
621
sub DoITERATION {
622
0
0
0
my ($self, $engine, $param) = @_;
623
0
0
unless ($param =~ /^\\\.LIMIT\\=((?:\\['"])?)(.+)\1$/s) { #'
624
0
$self->Syntax;
625
}
626
0
my $limit = $2;
627
0
$self->Push('iteration', $engine);
628
0
<
629
HTML::Merge::Engine::Force("$limit", 'ui');
630
foreach (1 .. "$limit") {
631
EOM
632
}
633
#####################################
634
sub DoUnITERATION {
635
0
0
0
my ($self, $engine, $param) = @_;
636
0
$self->Expect($engine, 'iteration');
637
0
"}\n";
638
}
639
#####################################
640
sub DoBREAK {
641
0
0
0
my ($self, $engine, $param) = @_;
642
0
0
$self->Syntax if ($param);
643
0
"last;";
644
}
645
646
#####################################
647
sub DoCONT {
648
0
0
0
my ($self, $engine, $param) = @_;
649
0
0
$self->Syntax if ($param);
650
0
"next;";
651
}
652
#####################################
653
sub DoUnLOOP {
654
0
0
0
my ($self, $engine, $param) = @_;
655
0
$self->Expect($engine, 'loop');
656
0
"}\n";
657
}
658
#####################################
659
sub DoFETCH {
660
0
0
0
my ($self, $engine, $param) = @_;
661
0
0
$self->Syntax if ($param);
662
0
"\$engines{\"$engine\"}->Fetch(1, 2);";
663
}
664
#####################################
665
666
*DoENVGET = \&DoENV;
667
668
#####################################
669
sub DoENV {
670
0
0
0
my ($self, $engine, $param) = @_;
671
0
0
unless ($param =~ s/^\\\.(.+)$//s) {
672
0
$self->Syntax;
673
}
674
0
return "\$ENV{\"$1\"}";
675
}
676
#####################################
677
sub DoENVSET {
678
0
0
0
my ($self, $engine, $param) = @_;
679
0
0
unless ($param =~ s/^\\\.(.+?)\\=\\(['"])(.*?)\\\2$//s) {
680
0
$self->Syntax;
681
}
682
0
"\$ENV{\"$1\"} = eval(\"$3\");\n";
683
}
684
#####################################
685
sub DoCFG {
686
0
0
0
my ($self, $engine, $param) = @_;
687
0
0
unless ($param =~ s/^\\\.(.+)$//s) {
688
0
$self->Syntax;
689
}
690
0
"\${\"HTML::Merge::Ini::\" . \"$1\"}";
691
}
692
#####################################
693
694
*DoINIGET = *DoINI = *DoCFGGET = \&DoCFG;
695
*DoINISET = \&DoCFGSET;
696
697
#####################################
698
sub DoCFGSET {
699
0
0
0
my ($self, $engine, $param) = @_;
700
0
0
unless ($param =~ s/^\\\.(.+?)\\=\\(['"])(.*)\\\2$//s) {
701
0
$self->Syntax;
702
}
703
0
"\${\"HTML::Merge::Ini::\" . \"$1\"} = eval(\"$3\");\n";
704
}
705
#####################################
706
707
*DoVAL = \&DoVAR;
708
709
#####################################
710
sub DoVAR
711
{
712
0
0
0
my ($self, $engine, $param) = @_;
713
714
0
0
unless ($param =~ s/^\\\.(.+)$//s)
715
{
716
0
$self->Syntax;
717
}
718
719
0
return "\$vars{\"$1\"}";
720
}
721
#####################################
722
sub DoVERSION
723
{
724
0
0
0
my ($self, $engine, $param) = @_;
725
726
0
return $VERSION;
727
}
728
#####################################
729
sub DoSQL
730
{
731
0
0
0
my ($self, $engine, $param) = @_;
732
733
0
0
unless ($param =~ s/^\\\.(.+)$//s)
734
{
735
0
$self->Syntax;
736
}
737
738
0
return "\$engines{\"$engine\"}->Var(\"$1\")";
739
}
740
#####################################
741
sub DoIF
742
{
743
0
0
0
my ($self, $engine, $param) = @_;
744
745
0
0
unless ($param =~ s/^\\[\.=]\\(['"])(.*)\\\1$//s)
746
{
747
0
$self->Syntax;
748
}
749
750
0
my $text = <
751
HTML::Merge::Error::HandleError('INFO', "$2", 'IF');
752
my \$__test = eval("$2");
753
HTML::Merge::Error::HandleError('ERROR', \$@) if (\$@);
754
if (\$__test) {
755
EOM
756
0
$self->Push('if', $engine);
757
0
$text;
758
}
759
#####################################
760
sub DoTIF
761
{
762
0
0
0
my ($self, $engine, $param) = @_;
763
0
0
unless ($param =~ s/^\\[\.=]\\(['"])(.*)\\\1$//s)
764
{
765
0
$self->Syntax;
766
}
767
768
0
my $text = <
769
HTML::Merge::Error::HandleError('INFO', "$2", 'IF');
770
my \$__test = "$2";
771
HTML::Merge::Error::HandleError('ERROR', \$@) if (\$@);
772
if ("$2") {
773
EOM
774
0
$self->Push('if', $engine);
775
0
$text;
776
}
777
#####################################
778
sub DoUnTIF {
779
0
0
0
my ($self, $engine, $param) = @_;
780
0
$self->Expect($engine, 'if', 'else');
781
0
"}\n";
782
}
783
#####################################
784
sub DoELSIF {
785
0
0
0
my ($self, $engine, $param) = @_;
786
0
0
unless ($param =~ s/^\\[\.=]\\(['"])(.*)\\\1$//s) {
787
0
$self->Syntax;
788
}
789
0
$self->Expect($engine, 'if');
790
0
$self->Push('if', $engine);
791
0
my $text = <
792
\$__exit = 0;
793
} elsif (((HTML::Merge::Error::HandleError('INFO', "$2", 'IF'),
794
\$__exit = eval("$2"),
795
\$@ && HTML::Merge::Error::HandleError('ERROR', \$@),
796
\$__exit))[-1]) {
797
EOM
798
0
$text;
799
}
800
801
802
sub DoUnIF {
803
0
0
0
my ($self, $engine, $param) = @_;
804
0
$self->Expect($engine, 'if', 'else');
805
0
"}\n";
806
}
807
808
sub DoELSE {
809
0
0
0
my ($self, $engine, $param) = @_;
810
0
0
$self->Syntax if $param;
811
0
$self->Expect($engine, 'if');
812
0
$self->Push('else', $engine);
813
0
"} else {\n";
814
}
815
816
sub DoWHILE {
817
0
0
0
my ($self, $engine, $param) = @_;
818
0
0
unless ($param =~ s/^\\[\.=]\\(['"])(.*)\\\1$//s) {
819
0
$self->Syntax;
820
}
821
0
my $cond = quotemeta($2);
822
0
my $text = <
823
HTML::Merge::Error::HandleError('INFO', "while $2", 'WHILE');
824
for (;;) {
825
my \$__test = eval("$2");
826
HTML::Merge::Error::HandleError('ERROR', \$@) if (\$@);
827
last unless \$__test;
828
EOM
829
0
$self->Push('while', $engine);
830
0
$text;
831
}
832
833
sub DoUnWHILE {
834
0
0
0
my ($self, $engine, $param) = @_;
835
0
$self->Expect($engine, 'while');
836
0
"}\n";
837
}
838
839
sub DoQ {
840
0
0
0
my ($self, $engine, $param) = @_;
841
0
0
unless ($param =~ s/^\\[=\.]\\(['"])(.*)\\\1$//s) {
842
0
$self->Syntax;
843
}
844
0
"\$engines{\"$engine\"}->Query(\"$2\");\n";
845
}
846
847
sub DoS {
848
0
0
0
my ($self, $engine, $param) = @_;
849
0
0
unless ($param =~ s/^\\[\.=]\\(['"])(.*)\\\1$//s) {
850
0
$self->Syntax;
851
}
852
0
"\$engines{\"$engine\"}->Statement(\"$2\");\n";
853
}
854
855
sub DoEVAL {
856
0
0
0
my ($self, $engine, $param) = @_;
857
0
0
unless ($param =~ s/^\\[\.=]\\(['"])(.*)\\\1$//s) {
858
0
$self->Syntax;
859
}
860
0
"eval(\"$2\")";
861
}
862
#####################################
863
sub DoPERL {
864
0
0
0
my ($self, $engine, $param) = @_;
865
0
my $type;
866
0
0
if ($param =~ s/^\\\.([ABC])$//i) {
867
0
$type = uc($1);
868
}
869
0
0
$self->Syntax if $param;
870
0
my $code = "";
871
0
my $line = $self->Line;
872
0
0
0
if ($type eq 'B' || $type eq 'C') {
873
0
my $flag;
874
0
while ($self->{'source'} =~ s/^(.*?)\<($open(?:\[.+?\]\.)?\w+|\/${open}PERL\>)//is) {
875
0
my $let = quotemeta($1);
876
0
$code .= qq!"$let" . !;
877
0
my $tag = $2;
878
0
0
if ($tag =~ m|^/${open}PERL>$|) {
879
0
$flag = 1;
880
0
last;
881
}
882
0
$tag =~ s/^$open//;
883
0
my $engine = '';
884
0
0
if ($tag =~ s/^\[(.+?)\]\.//) {
885
0
$engine = $1;
886
0
0
$engine= $self->Clause($engine,$tag) if($engine=~ /\<$open/);
887
}
888
0
my $coder = $self->WantPrinter($tag, "PERL", $line);
889
0
my $param = $self->EatParam($tag);
890
0
my $codet = &$coder($self, $engine, $param);
891
0
$code .= "$codet . ";
892
}
893
0
0
$self->Die("End of PERL not found") unless $flag;
894
0
$code .= q!""!;
895
} else {
896
0
0
unless ($self->{'source'} =~ s/^(.*?)\<\/${open}PERL\>//is) {
897
0
$self->Die("End of PERL not found");
898
}
899
0
$code = '"' . quotemeta($1) . '"';
900
}
901
0
my $name = $self->{'name'};
902
0
my $text = <
903
\$__result = $code;
904
HTML::Merge::Error::HandleError('INFO', \$__result, 'PERL');
905
\$__result = eval("\$__result; undef;");
906
HTML::Merge::Error::HandleError('ERROR', \$@) if \$@;
907
EOM
908
0
0
0
if ($type eq 'A' || $type eq 'C') {
909
0
$line = $self->Line;
910
0
$text .= <
911
if (\$__result) {
912
use HTML::Merge::Compile;
913
eval { \$__result = &HTML::Merge::Compile::Compile(\$__result, "$name", $line); };
914
HTML::Merge::Error::HandleError('ERROR', \$@) if \$@;
915
\$__result = eval(\$__result);
916
HTML::Merge::Error::HandleError('ERROR', \$@) if \$@;
917
}
918
EOM
919
}
920
0
$text;
921
}
922
###############################################################
923
sub DoSET
924
{
925
0
0
0
my ($self, $engine, $param) = @_;
926
927
0
0
unless ($param =~ s/^\\\.(.+?)\\=\\(['"])(.*?)\\\2$//s)
928
{
929
0
$self->Syntax;
930
}
931
932
0
return "\$vars{\"$1\"} = eval(\"$3\");\n";
933
}
934
###############################################################
935
sub DoASSIGN
936
{
937
0
0
0
my ($self, $engine, $param) = @_;
938
939
0
0
unless ($param =~ s/^\\\.(.+?)\\=\\(['"])(.*?)\\\2$//s)
940
{
941
0
$self->Syntax;
942
}
943
944
0
return "\$vars{\"$1\"} = \"$3\";\n";
945
}
946
###############################################################
947
948
sub DoPCLEAR {
949
0
0
0
my ($self, $engine, $param) = @_;
950
0
0
$self->Syntax if $param;
951
0
"\$engines{\"$engine\"}->ErasePersistent;\n";
952
}
953
954
sub DoPSET {
955
0
0
0
my ($self, $engine, $param) = @_;
956
0
0
unless ($param =~ s/^\\\.(.+?)\\=\\(['"])(.*?)\\\2$//s) {
957
0
$self->Syntax;
958
}
959
0
"\$engines{\"$engine\"}->SetPersistent(\"$1\", eval(\"$3\"));\n";
960
}
961
962
sub DoPGET {
963
0
0
0
my ($self, $engine, $param) = @_;
964
0
0
unless ($param =~ s/^\\\.(.+)$//s) {
965
0
$self->Syntax;
966
}
967
0
return "\$engines{\"$engine\"}->GetPersistent(\"$1\")";
968
}
969
970
*DoPVAR = \&DoPGET;
971
*DoGET = \&DoVAR;
972
973
sub DoPIMPORT {
974
0
0
0
my ($self, $engine, $param) = @_;
975
0
0
unless ($param =~ s/^\\\.(.+)$//s) {
976
0
$self->Syntax;
977
}
978
0
return "\$hash{\"$1\"} = \$engines{\"$engine\"}->GetPersistent(\"$1\");";
979
}
980
981
sub DoPEXPORT {
982
0
0
0
my ($self, $engine, $param) = @_;
983
0
0
unless ($param =~ s/^\\\.(.+)$//s) {
984
0
$self->Syntax;
985
}
986
0
return "\$engines{\"$engine\"}->SetPersistent(\"$1\", \$hash{\"$1\"});";
987
}
988
989
990
*DoREM = \&DoEM;
991
0
0
0
sub DoEM {}
992
993
sub DoTRACE {
994
0
0
0
my ($self, $engine, $param) = @_;
995
0
0
unless ($param =~ s/^\\\.\\(['"])(.*)\\\1$//s) {
996
0
$self->Syntax;
997
}
998
0
my $line = $2;
999
0
<
1000
HTML::Merge::Error::HandleError('INFO', "$line", 'TRACE');
1001
EOM
1002
}
1003
sub DoDIE {
1004
0
0
0
my ($self, $engine, $param) = @_;
1005
0
0
unless ($param =~ s/^\\\.\\(['"])(.*)\\\1$//s) {
1006
0
$self->Syntax;
1007
}
1008
0
my $line = $2;
1009
0
<
1010
HTML::Merge::Error::HandleError('ERROR', "$line");
1011
EOM
1012
}
1013
#################################################
1014
sub DoINCLUDE
1015
{
1016
0
0
0
my ($self, $engine, $param) = @_;
1017
0
my $inc;
1018
0
my $name = $self->{'name'};
1019
0
my $text;
1020
1021
0
0
unless ($param =~ s/^\\\.\\(['"])(.*)\\\1$//s)
1022
{
1023
0
$self->Syntax;
1024
}
1025
0
$inc = $2;
1026
0
$inc =~ s/\\(.)/$1/g;
1027
1028
##################################################################
1029
# require Cwd;
1030
# my $curr = &Cwd::cwd;
1031
# my @tokens = split(/\//, $self->{'name'});
1032
# pop @tokens;
1033
# my $dir = join("/", @tokens);
1034
# chdir $dir if $dir;
1035
# open(I, $inc) || $self->Die("Can't open $inc at $dir");
1036
# my $text = join("", );
1037
# close(I);
1038
# chdir $curr;
1039
# $self->{'source'} = $text . $self->{'source'};
1040
##################################################################
1041
1042
0
$text = <
1043
my \$__input = HTML::Merge::Compile::GetTemplateFromPath("$inc");
1044
my \$__script = "\$HTML::Merge::Ini::CACHE_PATH/$inc.pli";
1045
my \$__candidate = "\$HTML::Merge::Ini::PRECOMPILED_PATH/$inc.pli";
1046
1047
unless (-e \$__candidate)
1048
{
1049
#HTML::Merge::Error::DoWarn('NO_TEMPLATE','$inc') unless -e \$__input;
1050
HTML::Merge::Error::HandleError('ERROR',
1051
"No template '$inc' found") unless -e \$__input;
1052
1053
my \$__source = (stat(\$__input))[9];
1054
my \$__output = (stat(\$__script))[9];
1055
if (\$__source > \$__output) {
1056
require HTML::Merge::Compile;
1057
HTML::Merge::Compile::safecreate(\$__script)
1058
unless -e \$__script;
1059
eval ' HTML::Merge::Compile::CompileFile(\$__input, \$__script, 1); ';
1060
1061
if(\$@)
1062
{
1063
# erase the pli file
1064
unlink(\$__script);
1065
HTML::Merge::Error::HandleError('ERROR', \$@);
1066
}
1067
}
1068
} else {
1069
\$__script = \$__candidate;
1070
}
1071
HTML::Merge::Error::HandleError('INFO',"$inc",'INCLUDE');
1072
do \$__script;
1073
HTML::Merge::Error::HandleError('ERROR', \$@) if \$@;
1074
EOM
1075
0
$text;
1076
}
1077
#################################################
1078
sub DoWEBINCLUDE {
1079
0
0
0
my ($self, $engine, $param) = @_;
1080
0
0
unless ($param =~ s/^\\\.\\(['"])(.*)\\\1$//s) {
1081
0
$self->Syntax;
1082
}
1083
0
my $url = $2;
1084
0
<
1085
if (\$HTML::Merge::Ini::WEB) {
1086
require LWP;
1087
require HTTP::Request::Common;
1088
import HTTP::Request::Common;
1089
1090
my \$__url = "$url";
1091
\$__url = "http://\$ENV{'SERVER_NAME'}:\$ENV{'SERVER_PORT'}\$__url"
1092
unless (\$__url =~ m|://|);
1093
my \$__ua = new LWP::UserAgent;
1094
my \$__req = GET("$url");
1095
my \$__resp = \$__ua->request(\$__req);
1096
if (\$__resp->is_success) {
1097
print \$__resp->content;
1098
} else {
1099
HTML::Merge::Error::HandleError('ERROR', "Web GET to URL $url returned code " . \$__resp->code);
1100
}
1101
}
1102
EOM
1103
}
1104
1105
sub DoINDEX {
1106
0
0
0
my ($self, $engine, $param) = @_;
1107
0
0
$self->Syntax if $param;
1108
0
"\$engines{\"$engine\"}->Index";
1109
}
1110
1111
*DoRERUN = \&DoERUN;
1112
1113
sub DoERUN {
1114
0
0
0
my ($self, $engine, $param) = @_;
1115
0
0
$self->Syntax if $param;
1116
0
"\$engines{\"$engine\"}->ReRun;";
1117
}
1118
1119
*EQUEST = \&ENUMREQ;
1120
1121
sub DoENUMREQ {
1122
0
0
0
my ($self, $engine, $param) = @_;
1123
0
0
$self->Syntax unless ($param =~ /^\\\.(.+?)\\\=(.+)$/s);
1124
0
my ($iterator, $getter) = ($1, $2);
1125
0
$self->Push('enumreq', $engine);
1126
0
qq!foreach (param()) {
1127
next if (\$_ eq "template");
1128
\$vars{"$iterator"} = \$_;
1129
\$vars{"$getter"} = \$vars{\$_};\n!;
1130
}
1131
1132
sub DoUnENUMREQ {
1133
0
0
0
my ($self, $engine, $param) = @_;
1134
0
$self->Expect($engine, 'enumreq');
1135
0
"}\n";
1136
}
1137
1138
sub DoENUMQUERY {
1139
0
0
0
my ($self, $engine, $param) = @_;
1140
0
0
$self->Syntax unless ($param =~ /^\\\.(.+?)\\\=(.+)$/s);
1141
0
my ($iterator, $getter) = ($1, $2);
1142
0
$self->Push('enumquery', $engine);
1143
0
qq!foreach (\$engines{"$engine"}->Columns) {
1144
\$vars{"$iterator"} = \$_;
1145
\$vars{"$getter"} = \$engines{"$engine"}->Var(\$_);\n!;
1146
}
1147
1148
sub DoUnENUMQUERY {
1149
0
0
0
my ($self, $engine, $param) = @_;
1150
0
$self->Expect($engine, 'enumquery');
1151
0
"}\n";
1152
}
1153
1154
sub DoMULTI {
1155
0
0
0
my ($self, $engine, $param) = @_;
1156
0
0
$self->Syntax unless ($param =~ /^\\\.(.+?)\\\=(.+)$/s);
1157
0
my ($iterator, $getter) = ($1, $2);
1158
0
$self->Push('multi', $engine);
1159
0
qq!foreach (param("$getter")) {
1160
\$vars{"$iterator"} = \$_;!;
1161
}
1162
1163
sub DoUnMULTI {
1164
0
0
0
my ($self, $engine, $param) = @_;
1165
0
$self->Expect($engine, 'multi');
1166
0
"}\n";
1167
}
1168
1169
sub DoGLOB {
1170
0
0
0
my ($self, $engine, $param) = @_;
1171
0
0
unless ($param =~ /^\\\.([DF])\\\.(.+?)\\=\\(['"])(.*)\\\3$/is) {
1172
0
$self->Syntax;
1173
}
1174
0
my ($how, $iterator, $mask) = (uc($1), $2, $4);
1175
0
$self->Push('glob', $engine);
1176
0
0
my $cond = $how eq 'D' ? 'unless' : 'if';
1177
0
qq!\$__x = "$mask";
1178
\$__x .= "/*" if (-d \$__x);
1179
foreach (glob(\$__x)) {
1180
next $cond -d \$_;
1181
s|^.*/||;
1182
\$vars{"$iterator"} = \$_;\n!
1183
}
1184
1185
sub DoUnGLOB {
1186
0
0
0
my ($self, $engine, $param) = @_;
1187
0
$self->Expect($engine, 'glob');
1188
0
"}\n";
1189
}
1190
1191
sub DoFTS {
1192
0
0
0
my ($self, $engine, $param) = @_;
1193
0
0
unless ($param =~ /^\\\.(.+?)\\=\\(['"])(.*)\\\2$/is) {
1194
0
$self->Syntax;
1195
}
1196
0
my ($iterator, $base) = ($1, $3);
1197
0
$self->Push('fts', $engine);
1198
0
<
1199
use File::Find;
1200
\@__files = ();
1201
find(sub {push(\@__files, \$File::Find::name)}, "$base");
1202
foreach (\@__files) {
1203
\$vars{"$iterator"} = \$_;
1204
EOM
1205
}
1206
1207
sub DoUnFTS {
1208
0
0
0
my ($self, $engine, $param) = @_;
1209
0
$self->Expect($engine, 'fts');
1210
0
"}\n";
1211
}
1212
1213
sub DoCOUNT {
1214
0
0
0
my ($self, $engine, $param) = @_;
1215
0
0
$self->Syntax unless ($param =~ /^\\\.(.+?)\\\=(.*?)\\\:(.*?)(\\,.*)?$/s);
1216
0
my ($var, $from, $to, $step) = ($1, $2, $3, $4);
1217
0
0
$step ||= "\\,1";
1218
0
$step =~ s/^\\,//;
1219
1220
0
my $i = "\$vars{\"$var\"}";
1221
0
$self->Push('count', $engine);
1222
0
<
1223
HTML::Merge::Engine::Force("$from", "n");
1224
HTML::Merge::Engine::Force("$to", "n");
1225
HTML::Merge::Engine::Force("$step", "n");
1226
for ($i = "$from"; $i <= "$to"; $i += "$step") {
1227
EOM
1228
}
1229
1230
sub DoUnCOUNT {
1231
0
0
0
my ($self, $engine, $param) = @_;
1232
0
$self->Expect($engine, 'count');
1233
0
"}\n";
1234
}
1235
1236
sub DoPIC {
1237
0
0
0
my ($self, $engine, $param) = @_;
1238
0
my $type;
1239
0
0
unless ($param =~ s/^\\\.([CFRNADX])(.*)$//is) {
1240
0
$self->Syntax;
1241
}
1242
0
($type, $param) = (uc($1), $2);
1243
0
my $code = &UNIVERSAL::can($self, "Picture$type");
1244
0
&$code($self, $param);
1245
}
1246
1247
sub PictureF {
1248
0
0
0
my ($self, $param) = @_;
1249
0
$param =~ s/^\\\((\\?.)\\\)\\\.\\(['"])(.*?)\\\2$/$1\\$2$3\\$2/s;
1250
0
0
unless ($param =~ /^(\\?.)\\(['"])(.*?)\\\2$/s) {
1251
0
$self->Syntax;
1252
}
1253
0
my ($ch, $text) = ($1, $3);
1254
0
<
1255
"" . (\$__s = "$text", \$__s =~ s/\\s/$ch/g, \$__s)[-1]
1256
EOM
1257
}
1258
1259
sub PictureC {
1260
0
0
0
my ($self, $param) = @_;
1261
0
my @ary;
1262
my $flag;
1263
0
$param =~ s/^\\\((.*)\\\)\\\.\\(['"])(.*?)\\\2$/$1\\.\\$2$3\\$2/s;
1264
0
while ($param =~
1265
s/^\s*\\(['"])(.*?)\\\1\s*\\=\s*\\(['"])(.*?)\\\3\s*//s) {
1266
0
push(@ary, [$2, $4]);
1267
0
0
if ($param =~ s/^\\\.//) {
1268
0
$flag = 1;
1269
0
last;
1270
}
1271
0
0
unless ($param =~ s/^\\,//) {
1272
0
$self->Syntax;
1273
}
1274
}
1275
0
0
$self->Die("Syntax error in PIC.C") unless ($flag);
1276
0
0
unless ($param =~ s/^\\(["'])(.*?)\\\1$//s) {
1277
0
$self->Syntax;
1278
}
1279
0
my $text = $2;
1280
0
my $code = <
1281
"" . (\$__s = "$text",
1282
EOM
1283
0
foreach (@ary) {
1284
0
my ($from, $to) = @$_;
1285
0
$code .= <
1286
\$__s =~ s/^$from\$/$to/g,
1287
EOM
1288
}
1289
0
$code . ", \$__s)[-1]";
1290
}
1291
1292
sub PictureR {
1293
0
0
0
my ($self, $param) = @_;
1294
0
my @ary;
1295
my $flag;
1296
0
$param =~ s/^\\\((.*)\\\)\\\.\\(['"])(.*?)\\\2$/$1\\.\\$2$3\\$2/s;
1297
0
while ($param =~
1298
s/^\s*\\(['"])(.*?)\\\1\s*\\=\s*\\(['"])(.*?)\\\3\s*//s) {
1299
0
push(@ary, [$2, $4]);
1300
0
0
if ($param =~ s/^\\\.//) {
1301
0
$flag = 1;
1302
0
last;
1303
}
1304
0
0
unless ($param =~ s/^\\,//) {
1305
0
$self->Syntax;
1306
}
1307
}
1308
0
0
$self->Die("Syntax error in PIC.R") unless ($flag);
1309
0
0
unless ($param =~ s/^\\(["'])(.*?)\\\1$//s) {
1310
0
$self->Syntax;
1311
}
1312
0
my $text = $2;
1313
0
my $code = <
1314
"" . (\$__s = "$text",
1315
EOM
1316
0
foreach (@ary) {
1317
0
my ($from, $to) = @$_;
1318
0
$code .= <
1319
\$__s =~ s/$from/$to/g,
1320
EOM
1321
}
1322
0
$code . ", \$__s)[-1]";
1323
}
1324
1325
sub PictureN {
1326
0
0
0
my ($self, $param) = @_;
1327
0
my %opts;
1328
0
while ($param =~ s/^([ZF])//) {
1329
0
$opts{$1}++;
1330
}
1331
0
0
unless ($param =~ s/^\\\((.*?)\\\)//s) {
1332
0
$self->Syntax;
1333
}
1334
0
my $format = $1;
1335
0
0
unless ($param =~ s/^\\\.\\(["'])(.*?)\\\1$//s) {
1336
0
$self->Syntax;
1337
}
1338
0
my $text = $2;
1339
0
<
1340
"" . (\$__s = "$text" || !"$opts{'Z'}" ? sprintf("%${format}f", "$text") : " ",
1341
"$opts{'F'}" ? (\$__s =~
1342
s!(\\d+)!scalar(reverse join(\$HTML::Merge::Ini::THOUSAND_SEPARATOR || ",", (reverse \$1) =~ /(\\d{1,3})/g))!e) : undef,
1343
\$__s =~ s/\\./\$HTML::Merge::Ini::DECIMAL_SEPARATOR || '.'/e,
1344
\$__s)[-1]
1345
EOM
1346
}
1347
1348
sub PictureA {
1349
0
0
0
my ($self, $param) = @_;
1350
0
my %opts;
1351
0
while ($param =~ s/^([LRCSPWDE])//) {
1352
0
$opts{$1}++;
1353
}
1354
0
foreach (qw(SCP DE)) {
1355
0
my $count;
1356
0
foreach (split(//)) {
1357
0
0
0
$self->Die("Illegal flag combinations")
1358
if ($opts{$_} && $count++);
1359
}
1360
}
1361
0
0
unless ($param =~ s/^\\\((.*?)\\\)//s) {
1362
0
$self->Syntax;
1363
}
1364
0
my $format = $1;
1365
0
0
unless ($param =~ s/^\\\.\\(["'])(.*?)\\\1$//s) {
1366
0
$self->Syntax;
1367
}
1368
0
my $text = $2;
1369
0
<
1370
"" . (\$__s = "$text",
1371
"$opts{'C'}" && \$__s =~ tr/a-z/A-Z/,
1372
"$opts{'S'}" && \$__s =~ tr/A-Z/a-z/,
1373
"$opts{'P'}" && \$__s =~ s/\\b([a-z]\\S+)/ucfirst(lc(\$1))/egi,
1374
"$opts{'L'}" && \$__s =~ s/^\\s+//,
1375
"$opts{'R'}" && \$__s =~ s/\\s+\$//,
1376
"$opts{'W'}" && \$__s =~ s/\\s{2,}/ /g,
1377
"$opts{'E'}" && (\$__s =~ s/([^ _A-Za-z0-9-\\/])/sprintf("%%%02X", ord(\$1))/ge, \$__s =~ s/ /+/g),
1378
"$opts{'D'}" && (\$__s =~ s/\\+/ /g, \$__s =~ s/%(..)/chr(hex(\$1))/ge),
1379
sprintf("%${format}s", \$__s))[-1]
1380
EOM
1381
}
1382
1383
sub PictureD {
1384
0
0
0
my ($self, $param) = @_;
1385
0
0
unless ($param =~ s/^\\\((.*?)\\\)//s) {
1386
0
$self->Syntax;
1387
}
1388
0
my $format = $1;
1389
0
0
unless ($param =~ s/^\\\.\\(["'])(.*?)\\\1$//s) {
1390
0
$self->Syntax;
1391
}
1392
0
my $date = $2;
1393
1394
0
<
1395
(require Time::Local,
1396
("$date") =~ /^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})\$/,
1397
\$__t = Time::Local::timelocal(\$6, \$5, \$4, \$3, \$2 - 1, \$1 - 1900),
1398
HTML::Merge::Engine::time2str("$format", \$__t))[-1]
1399
1400
EOM
1401
}
1402
1403
sub PictureX {
1404
0
0
0
my ($self, $param) = @_;
1405
0
0
unless ($param =~ s/^\\\((.*?)\\\)//s) {
1406
0
$self->Syntax;
1407
}
1408
0
my $times = $1;
1409
0
0
unless ($param =~ s/^\\\.\\(["'])(.*?)\\\1$//s) {
1410
0
$self->Syntax;
1411
}
1412
0
my $text = $2;
1413
0
<
1414
(HTML::Merge::Engine::Force("$times", 'ui'),
1415
"$text" x "$times")[-1]
1416
EOM
1417
}
1418
1419
sub DoINC {
1420
0
0
0
my ($self, $engine, $param) = @_;
1421
0
0
unless ($param =~ /^\\\.(.*?)(\\[+-]\d+)?$/s) {
1422
0
$self->Syntax;
1423
}
1424
0
0
my ($var, $step) = ($1, defined($2) ? $2 : 1);
1425
0
<
1426
HTML::Merge::Engine::Force("$step", "n");
1427
HTML::Merge::Engine::Force(\$vars{"$var"}, "n");
1428
\$vars{"$var"} += "$step";
1429
EOM
1430
}
1431
1432
sub DoSTATE {
1433
0
0
0
my ($self, $engine, $param) = @_;
1434
0
0
$self->Syntax if $param;
1435
0
"\$engines{\"$engine\"}->State";
1436
}
1437
1438
sub DoEMPTY {
1439
0
0
0
my ($self, $engine, $param) = @_;
1440
0
0
$self->Syntax if $param;
1441
0
"\$engines{\"$engine\"}->Empty";
1442
}
1443
1444
sub DoMAIL {
1445
0
0
0
my ($self, $engine, $param) = @_;
1446
0
0
unless ($param =~ /^\\\.\\(['"])(.*?)\\\1\\([\.,])\\(['"])(.*?)\\\4(.*)$/s) {
1447
0
$self->Syntax;
1448
}
1449
0
my $del = quotemeta($3);
1450
0
my ($from, $to, $rem, $subject) = ($2, $5, $6);
1451
0
0
if ($rem) {
1452
0
0
unless ($rem =~ /^\\$del\\(['"])(.*?)\\\1$/s) {
1453
0
$self->Syntax;
1454
}
1455
0
$subject = $2;
1456
}
1457
0
$self->Push('mail', $engine);
1458
0
<
1459
\$__from = "$from";
1460
\$__from =~ s/^.*\<(.*)\>\$/\$1/;
1461
\$__from =~ s/^(.*?)\\s+\(\".*\"\)\$/\$1/;
1462
\$__to = "$to";
1463
\$__to =~ s/^.*\<(.*)\>\$/\$1/;
1464
\$__to =~ s/^(.*?)\\s+\(\".*\"\)\$/\$1/;
1465
use HTML::Merge::Mail;
1466
eval '\$__mail = OpenMail(\$__from, \$__to, \$HTML::Merge::Ini::SMTP_SERVER);';
1467
1468
HTML::Merge::Error::HandleError('WARN', 'Mail failed: \$\@') if \$\@;
1469
\$__prev = select \$__mail;
1470
1471
print "From: $from\\r\\n";
1472
print "To: $to\\r\\n";
1473
print "Subject: $subject\\r\\n";
1474
print "X-Mailer: Merge v. $VERSION (c) http://www.raz.co.il\\r\\n";
1475
print "\\r\\n";
1476
EOM
1477
}
1478
sub DoUnMAIL {
1479
0
0
0
my ($self, $engine, $param) = @_;
1480
0
$self->Expect($engine, 'mail');
1481
0
<
1482
eval ' CloseMail(\$__mail); ';
1483
HTML::Merge::Error::HandleError('WARN', 'Mail failed: \$\@') if \$\@;
1484
select \$__prev;
1485
EOM
1486
}
1487
#####################################
1488
sub DoDB
1489
{
1490
0
0
0
my ($self, $engine, $param) = @_;
1491
1492
0
my ($type, $db, $host);
1493
0
my ($dsn,$dsn1, $user, $pass);
1494
1495
0
$INTERNAL_DB="dbname=$HTML::Merge::Ini::MERGE_ABSOLUTE_PATH/merge.db";
1496
1497
0
0
unless ($param =~ /^\\[\.=]\\(['"])(.*?)\\\1$/s)
1498
{
1499
0
$self->Syntax;
1500
}
1501
1502
0
$dsn = $2;
1503
0
($dsn1, $user, $pass) = split(/\s*\\,\s*/, $dsn);
1504
1505
0
0
unless ($dsn1)
1506
{
1507
0
$self->Die("DSN not specified");
1508
}
1509
1510
0
for($dsn)
1511
{
1512
0
0
if(/^SYSTEM$/)
1513
{
1514
0
0
if($HTML::Merge::Ini::SESSION_DB)
1515
{
1516
0
$type = $HTML::Merge::Ini::DB_TYPE;
1517
0
$db = $HTML::Merge::Ini::SESSION_DB;
1518
0
$host = $HTML::Merge::Ini::DB_HOST;
1519
0
$user = $HTML::Merge::Ini::DB_USER;
1520
0
$pass = $HTML::Merge::Ini::DB_PASSWORD;
1521
}
1522
else
1523
{
1524
0
$type=$INTERNAL_DB_TYPE;
1525
0
$db="$INTERNAL_DB";
1526
}
1527
0
last;
1528
}
1529
0
0
if(/^DEFAULT$/)
1530
{
1531
0
$type = $HTML::Merge::Ini::DB_TYPE;
1532
0
$db = $HTML::Merge::Ini::DB_DATABASE;
1533
0
$host = $HTML::Merge::Ini::DB_HOST;
1534
0
$user = $HTML::Merge::Ini::DB_USER;
1535
0
$pass = $HTML::Merge::Ini::DB_PASSWORD;
1536
0
last;
1537
}
1538
else
1539
{
1540
0
$dsn1 =~ s/^dbi\\://;
1541
0
($type, $db, $host) = split(/\\:/, $dsn1);
1542
0
0
($type, $db) = (undef, $type) unless ($db);
1543
0
last;
1544
}
1545
}
1546
1547
0
<
1548
\$engines{"$engine"}->Preconnect("$type", "$db", "$host", "$user", "$pass");
1549
EOM
1550
}
1551
#####################################
1552
sub DoDISCONNECT {
1553
0
0
0
my ($self, $engine, $param) = @_;
1554
0
0
$self->Syntax if $param;
1555
0
qq!delete \$engines{"$engine"};!;
1556
}
1557
1558
sub DoEXIT {
1559
0
0
0
my ($self, $engine, $param) = @_;
1560
0
0
$self->Die if $param;
1561
0
"die 'STOP_ON_ERROR';\n";
1562
}
1563
1564
sub DoLOGIN {
1565
0
0
0
my ($self, $engine, $param) = @_;
1566
0
0
unless ($param =~ /^\\[\.=]\\(['"])(.*?)\\\1\\\,\\(['"])(.*?)\\\3$/s) {
1567
0
$self->Syntax;
1568
}
1569
0
my ($user, $pass) = ($2, $4);
1570
0
qq!\$engines{"$engine"}->Login("$user", "$pass")!;
1571
}
1572
1573
sub DoCHPASS {
1574
0
0
0
my ($self, $engine, $param) = @_;
1575
0
0
unless ($param =~ /^\\[\.=]\\(['"])(.*?)\\\1$/s) {
1576
0
$self->Syntax;
1577
}
1578
0
qq!\$engines{"$engine"}->ChangePassword("$2");!;
1579
}
1580
1581
sub DoAUTH {
1582
0
0
0
my ($self, $engine, $param) = @_;
1583
0
0
unless ($param =~ /^\\\.\\(['"])(.*?)\\\1$/s) {
1584
0
$self->Syntax;
1585
}
1586
0
qq!\$engines{"$engine"}->HasKey("$2")!;
1587
}
1588
1589
sub DoADDUSER {
1590
0
0
0
my ($self, $engine, $param) = @_;
1591
0
0
unless ($param =~ /^\\[\.=]\\(['"])(.*?)\\\1\\\,\\(['"])(.*?)\\\3$/s) {
1592
0
$self->Syntax;
1593
}
1594
0
my ($user, $pass) = ($2, $4);
1595
0
qq!\$engines{"$engine"}->AddUser("$user", "$pass");!;
1596
}
1597
1598
sub DoDELUSER {
1599
0
0
0
my ($self, $engine, $param) = @_;
1600
0
0
unless ($param =~ /^\\[=\.]\\(['"])(.*?)\\\1$/s) {
1601
0
$self->Syntax;
1602
}
1603
0
my ($user) = ($2);
1604
0
qq!\$engines{"$engine"}->DelUser("$user");!;
1605
}
1606
1607
sub DoJOIN {
1608
0
0
0
my ($self, $engine, $param) = @_;
1609
0
0
unless ($param =~ /^\\[=\.]\\(['"])(.*?)\\\1\\\,\\(['"])(.*?)\\\3$/s) {
1610
0
$self->Syntax;
1611
}
1612
0
my ($user, $group) = ($2, $4);
1613
0
qq!\$engines{"$engine"}->JoinGroup("$user", "$group");!;
1614
}
1615
1616
sub DoPART {
1617
0
0
0
my ($self, $engine, $param) = @_;
1618
0
0
unless ($param =~ /^\\[=\.]\\(['"])(.*?)\\\1\\\,\\(['"])(.*?)\\\3$/s) {
1619
0
$self->Syntax;
1620
}
1621
0
my ($user, $group) = ($2, $4);
1622
0
qq!\$engines{"$engine"}->PartGroup("$user", "$group");!;
1623
}
1624
1625
sub DoGRANT {
1626
0
0
0
my ($self, $engine, $param) = @_;
1627
0
0
unless ($param =~ /^\\[=\.]([UG])\\\.\\(['"])(.*?)\\\2\\\,\\(['"])(.*?)\\\4$/si) {
1628
0
$self->Syntax;
1629
}
1630
0
my ($how, $who, $realm) = (uc($1), $3, $5);
1631
0
0
if ($how eq 'U') {
1632
0
return qq!\$engines{"$engine"}->GrantUser("$who", "$realm");!;
1633
}
1634
0
0
if ($how eq 'G') {
1635
0
return qq!\$engines{"$engine"}->GrantGroup("$who", "$realm");!;
1636
}
1637
}
1638
1639
*DoREVOKE = \&DoEVOKE;
1640
1641
sub DoEVOKE {
1642
0
0
0
my ($self, $engine, $param) = @_;
1643
0
0
unless ($param =~ /^\\[=\.]([UG])\\\.\\(['"])(.*?)\\\2\\\,\\(['"])(.*?)\\\4$/si) {
1644
0
$self->Syntax;
1645
}
1646
0
my ($how, $who, $realm) = (uc($1), $3, $5);
1647
0
0
if ($how eq 'U') {
1648
0
return qq!\$engines{"$engine"}->RevokeUser("$who", "$realm");!;
1649
}
1650
0
0
if ($how eq 'G') {
1651
0
return qq!\$engines{"$engine"}->RevokeGroup("$who", "$realm");!;
1652
}
1653
}
1654
1655
sub DoATTACH {
1656
0
0
0
my ($self, $engine, $param) = @_;
1657
0
0
unless ($param =~ /^\\[=\.]\\(['"])(.*?)\\\1\\\,\\(['"])(.*?)\\\3$/s) {
1658
0
$self->Syntax;
1659
}
1660
0
my ($template, $subsite) = ($2, $4);
1661
0
qq!\$engines{"$engine"}->Attach("$template", "$subsite");!;
1662
}
1663
1664
sub DoDETACH {
1665
0
0
0
my ($self, $engine, $param) = @_;
1666
0
0
unless ($param =~ /^\\[=\.]\\(['"])(.*?)\\\1\\\,\\(['"])(.*?)\\\3$/s) {
1667
0
$self->Syntax;
1668
}
1669
0
my ($template, $subsite) = ($2, $4);
1670
0
qq!\$engines{"$engine"}->Detach("$template", "$subsite");!;
1671
}
1672
1673
1674
*DoREQUIRE = \&DoEQUIRE;
1675
1676
sub DoEQUIRE {
1677
0
0
0
my ($self, $engine, $param) = @_;
1678
0
0
unless ($param =~ /^\\[=\.]\\(['"])(.*?)\\\1\\\,\\(['"])(.*?)\\\3$/s) {
1679
0
$self->Syntax;
1680
}
1681
0
my ($template, $realms) = ($2, $4);
1682
0
qq!\$engines{"$engine"}->Require("$template", "$realms");!;
1683
}
1684
1685
sub DoUSER {
1686
0
0
0
my ($self, $engine, $param) = @_;
1687
0
0
$self->Syntax if $param;
1688
0
qq!\$engines{"$engine"}->GetUser!;
1689
}
1690
1691
sub DoNAME {
1692
0
0
0
my ($self, $engine, $param) = @_;
1693
0
0
$self->Syntax if $param;
1694
0
qq!scalar(\$engines{"$engine"}->GetUserName)!;
1695
}
1696
1697
sub DoTAG {
1698
0
0
0
my ($self, $engine, $param) = @_;
1699
0
0
$self->Syntax if $param;
1700
0
qq!(\$engines{"$engine"}->GetUserName)[1]!;
1701
}
1702
1703
sub DoMERGE {
1704
0
0
0
my ($self, $engine, $param) = @_;
1705
0
0
$self->Syntax if $param;
1706
0
'"$HTML::Merge::Ini::MERGE_PATH/$HTML::Merge::Ini::MERGE_SCRIPT"';
1707
}
1708
1709
sub DoTEMPLATE {
1710
0
0
0
my ($self, $engine, $param) = @_;
1711
0
0
$self->Syntax if $param;
1712
0
qq!\$HTML::Merge::template!;
1713
}
1714
1715
sub DoTRANSFER {
1716
0
0
0
my ($self, $engine, $param) = @_;
1717
0
my $validate;
1718
0
0
unless ($param =~ s/^\\\.(.+)$//s) {
1719
0
$self->Syntax;
1720
}
1721
0
qq!qq/ /!;
1722
}
1723
1724
sub DoSUBMIT {
1725
0
0
0
my ($self, $engine, $param) = @_;
1726
0
my $validate;
1727
0
0
if ($param =~ s/^\\\.\\(["'])(.*)\\\1$//s) {
1728
0
$validate = " onSubmit=\"$2\"";
1729
}
1730
0
0
$self->Syntax if $param;
1731
0
$self->Push('submit', $engine);
1732
0
<
1733
print qq!
1734
!;
1735
EOM
1736
}
1737
1738
sub DoUnSUBMIT {
1739
0
0
0
my ($self, $engine, $param) = @_;
1740
0
$self->Expect($engine, 'submit');
1741
0
qq!print "\\n";!;
1742
}
1743
1744
sub DoDECIDE {
1745
0
0
0
my ($self, $engine, $param) = @_;
1746
0
0
unless ($param =~ /^\\\.\\(['"])(.*?)\\\1\\\?\\(['"])(.*?)\\\3\\\:\\(['"])(.*?)\\\5$/s) {
1747
0
$self->Syntax;
1748
}
1749
0
my ($decision, $true, $false) = ($2, $4, $6);
1750
0
<
1751
(
1752
(eval("$decision") ? "$true" : "$false"),
1753
\$@ && HTML::Merge::Error::HandleError('ERROR', \$@)
1754
)[0]
1755
EOM
1756
}
1757
1758
sub DoDATE {
1759
0
0
0
my ($self, $engine, $param) = @_;
1760
0
my $delta = 0;
1761
0
0
if ($param =~ s/^\\[,\.]((?:\\-)?\d+)$//s) {
1762
0
$delta = $1;
1763
}
1764
0
0
$self->Syntax if $param;
1765
0
<
1766
(HTML::Merge::Engine::Force("$delta", 'i'),
1767
\@__t = localtime(time + "$delta" * 3600 * 24),
1768
sprintf("%04d" . ("%02d" x 5), \$__t[5] + 1900, \$__t[4] + 1,
1769
\@__t[reverse (0 .. 3)]))[-1]
1770
EOM
1771
}
1772
1773
sub DoDAY {
1774
0
0
0
my ($self, $engine, $param) = @_;
1775
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1776
0
$self->Syntax;
1777
}
1778
0
qq{substr("$2", 6, 2) * 1};
1779
}
1780
1781
sub DoMONTH {
1782
0
0
0
my ($self, $engine, $param) = @_;
1783
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1784
0
$self->Syntax;
1785
}
1786
0
qq{substr("$2", 4, 2) * 1};
1787
}
1788
1789
sub DoYEAR {
1790
0
0
0
my ($self, $engine, $param) = @_;
1791
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1792
0
$self->Syntax;
1793
}
1794
0
qq{substr("$2", 0, 4)};
1795
}
1796
1797
sub DoMINUTE {
1798
0
0
0
my ($self, $engine, $param) = @_;
1799
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1800
0
$self->Syntax;
1801
}
1802
0
qq{substr("$2", 10, 2) * 1};
1803
}
1804
1805
sub DoHOUR {
1806
0
0
0
my ($self, $engine, $param) = @_;
1807
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1808
0
$self->Syntax;
1809
}
1810
0
qq{substr("$2", 8, 2) * 1};
1811
}
1812
1813
1814
sub DoSECOND {
1815
0
0
0
my ($self, $engine, $param) = @_;
1816
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1817
0
$self->Syntax;
1818
}
1819
0
qq{substr("$2", 12, 2) * 1};
1820
}
1821
1822
sub DoDATEDIFF {
1823
0
0
0
my ($self, $engine, $param) = @_;
1824
0
0
unless ($param =~ /^\\\.([HSMD])\\\.(\\['"])?(.*)\2\\,(\\['"])?(.*)\4$/s) {
1825
0
$self->Syntax;
1826
}
1827
0
my ($how, $before, $now) = ($1, $3, $5);
1828
0
my %hash = qw(S 1 M 60 H 3600 D 86400);
1829
0
0
my $div = $hash{$how} || 1;
1830
0
<
1831
(require Time::Local,
1832
\$__conv = sub { (shift() =~ /^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})/);
1833
Time::Local::timelocal(\$6, \$5, \$4, \$3, \$2 - 1, \$1 - 1900); },
1834
int((&\$__conv("$now") - &\$__conv("$before")) / $div))[-1]
1835
EOM
1836
}
1837
1838
sub DoDATE2UTC {
1839
0
0
0
my ($self, $engine, $param) = @_;
1840
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1841
0
$self->Syntax;
1842
}
1843
0
<
1844
(require Time::Local,
1845
("$2") =~ /^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})\$/,
1846
Time::Local::timelocal(\$6, \$5, \$4, \$3, \$2 - 1, \$1 - 1900))[-1]
1847
EOM
1848
}
1849
1850
sub DoUTC2DATE {
1851
0
0
0
my ($self, $engine, $param) = @_;
1852
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/) {
1853
0
0
$self->Syntax if $param;
1854
}
1855
0
<
1856
(HTML::Merge::Engine::Force("$2", 'ui'),
1857
\@__t = localtime("$2"),
1858
sprintf("%04d" . ("%02d" x 5), \$__t[5] + 1900, \$__t[4] + 1,
1859
\@__t[reverse (0 .. 3)]))[-1]
1860
EOM
1861
}
1862
1863
sub DoLASTDAY {
1864
0
0
0
my ($self, $engine, $param) = @_;
1865
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1866
0
$self->Syntax;
1867
}
1868
0
<
1869
((\$__y, \$__m, \$__d) = ("$2" =~ /^(\\d{4})(\\d{2})(\\d{2})/),
1870
\$__base = (qw(31 28 31 30 31 30 31 31 30 31 30 31))[\$__m - 1],
1871
\$__leap = (\$__y % 4) ? 0
1872
: ((\$__y % 100) ? 1
1873
: ((\$__y % 400) ? 0 : 1)
1874
),
1875
\$__base + (\$__m == 2 ? \$__leap : 0))[-1]
1876
EOM
1877
}
1878
1879
sub DoADDDATE {
1880
0
0
0
my ($self, $engine, $param) = @_;
1881
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1\\\,\\(['"])(.*)\\\3\\,\\(['"])(.*)\\\5\\,\\(['"])(.*)\\\7$/s) {
1882
0
$self->Syntax;
1883
}
1884
0
my ($date, $d, $m, $y) = ($2, $4, $6, $8);
1885
0
<
1886
(require Time::Local,
1887
("$date") =~ /^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})/,
1888
\$__t = Time::Local::timelocal(\$6, \$5, \$4, \$3, \$2 - 1, \$1 - 1900)
1889
+ 3600 * 24 * "$d",
1890
\@__t = localtime(\$__t),
1891
\$__t[4] += "$m", \$__t[5] += "$y",
1892
\$__t[5] += int(\$__t[4] / 12), \$__t[4] %= 12,
1893
sprintf("%04d" . ("%02d" x 5), \$__t[5] + 1900, \$__t[4] + 1,
1894
\@__t[reverse (0 .. 3)]))[-1]
1895
EOM
1896
}
1897
1898
sub DoDIVERT {
1899
0
0
0
my ($self, $engine, $param) = @_;
1900
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1901
0
$self->Syntax;
1902
}
1903
0
my $fn = $2;
1904
0
$self->Push('divert', $engine);
1905
0
<
1906
push(\@__diverts, select);
1907
use Symbol;
1908
\$__sym = gensym;
1909
open(\$__sym, ">>/tmp/merge-\$\$-$fn.divert") || die \$!;
1910
select \$__sym;
1911
push(\@HTML::Merge::cleanups, eval qq!sub { unlink "/tmp/merge-\$\$-$fn.divert" }!);
1912
EOM
1913
# Value of $fn might contain merge variables, that might change
1914
# until cleanup time. Therefore compile cleanup function
1915
# with the filename as part of the source.
1916
}
1917
1918
sub DoUnDIVERT {
1919
0
0
0
my ($self, $engine, $param) = @_;
1920
0
0
$self->Syntax if $param;
1921
0
$self->Expect($engine, 'divert');
1922
0
<
1923
\$__sym = select;
1924
select pop \@__diverts;
1925
close \$__sym;
1926
EOM
1927
}
1928
1929
sub DoDUMP {
1930
0
0
0
my ($self, $engine, $param) = @_;
1931
0
0
unless ($param =~ /^\\\.\\(['"])(.*)\\\1$/s) {
1932
0
$self->Syntax;
1933
}
1934
0
my $fn = $2;
1935
0
<
1936
(open(DIVERT_DUMP, "/tmp/merge-\$\$-$fn.divert") || die(\$!), join("", ),
1937
close(DIVERT_DUMP))[1]
1938
EOM
1939
}
1940
1941
*DoCGET = *DoCVAR = \&DoCOOKIE;
1942
1943
sub DoCOOKIE {
1944
0
0
0
my ($self, $engine, $param) = @_;
1945
0
0
unless ($param =~ s/^\\\.(.*)$//s) {
1946
0
$self->Syntax;
1947
}
1948
0
"\$engines{\"$engine\"}->GetCookie(\"$1\")";
1949
}
1950
1951
*DoCSET = \&DoCOOKIESET;
1952
1953
sub DoCOOKIESET {
1954
0
0
0
my ($self, $engine, $param) = @_;
1955
0
0
unless ($param =~ s/^\\\.(.*?)\\=\\(['"])(.*?)\\\2((?:\\,.*)?)$//s) {
1956
0
$self->Syntax;
1957
}
1958
0
my $expire = substr($4, 2);
1959
0
"\$engines{\"$engine\"}->SetCookie(\"$1\", eval(\"$3\"), \"$expire\");";
1960
}
1961
1962
sub DoSOURCE {
1963
0
0
0
my ($self, $engine, $param) = @_;
1964
0
my $file = '$HTML::Merge::template';
1965
0
0
if ($param =~ s/^\\\.\\(['"])(.*)\\\1$//s) {
1966
0
$file = $2;
1967
}
1968
0
0
$self->Syntax if $param;
1969
0
$self->Push('source', $engine);
1970
0
qq!'
1971
HTML::Merge::Development::MakeLink('printsource.pl', "template=$file")
1972
. '" TITLE="view source">'!;
1973
}
1974
1975
sub DoUnSOURCE {
1976
0
0
0
my ($self, $engine, $param) = @_;
1977
0
$self->Expect($engine, 'source');
1978
0
qq!""!;
1979
}
1980
1981
sub safecreate {
1982
0
0
0
my @tokens = split(/\//, shift);
1983
0
pop @tokens;
1984
0
my $dir;
1985
0
foreach (@tokens) {
1986
0
$dir .= "/$_";
1987
0
mkdir $dir, 0755;
1988
}
1989
}
1990
#####################################
1991
sub CompileFile
1992
{
1993
0
0
0
my ($file, $out, $sub) = @_;
1994
1995
0
my $tmp;
1996
0
0
open(I, $file) || die "Cannot open $file: $!";
1997
0
my $text = join("", );
1998
0
close(I);
1999
2000
0
0
open(O, ">$out") || die "Can't write $out: $!";
2001
0
my $prev = select O;
2002
2003
0
0
unless ($sub) {
2004
0
print $Config{'startperl'}, "\n";
2005
0
print <<'EOM';
2006
use HTML::Merge::Engine;
2007
use HTML::Merge::Error;
2008
no strict;
2009
sub getvar ($) {
2010
$vars{shift()};
2011
}
2012
sub setvar ($$) {
2013
$vars{$_[0]} = $_[1];
2014
}
2015
sub incvar ($$) {
2016
$vars{$_[0]} += $_[1];
2017
}
2018
sub getfield ($;$) {
2019
my ($field, $engine) = @_;
2020
$engines{$engine}->Var($field);
2021
}
2022
sub merge ($) {
2023
my $code = shift;
2024
require HTML::Merge::Compile;
2025
my $text;
2026
eval { $text = HTML::Merge::Compile::Compile($code, __FILE__); };
2027
HTML::Merge::Error::HandleError('ERROR', $@) if $@;
2028
eval $text;
2029
HTML::Merge::Error::HandleError('ERROR', $@) if $@;
2030
}
2031
sub dbh () {
2032
$engines{""}->{'dbh'};
2033
}
2034
sub register ($) {
2035
push(@HTML::Merge::cleanups, shift);
2036
}
2037
2038
if (tied(%engines)) {
2039
undef %engines;
2040
untie %engines;
2041
}
2042
2043
tie %engines, HTML::Merge::Engine;
2044
use CGI qw/:standard/;
2045
@keys = param();
2046
%vars = ();
2047
foreach (@keys) {
2048
$vars{$_} = param($_);
2049
}
2050
=line
2051
$tmp = HTML::Merge::Compile::CgiParse();
2052
foreach (keys(%$tmp))
2053
{
2054
print "$_\t:\t",$tmp->{$_},"\n";
2055
}
2056
2057
%vars = %$tmp;
2058
=cut
2059
unless ($HTML::Merge::Ini::TEMPLATE_CACHE) {
2060
2061
EOM
2062
0
print "\t\trequire '$HTML::Merge::config';\n\t}\n";
2063
}
2064
2065
0
eval {
2066
0
print &Compile($text, $file);
2067
};
2068
0
my $code = $@;
2069
2070
0
0
unless ($sub) {
2071
0
print <<'EOM';
2072
HTML::Merge::Engine::DumpSuffix;
2073
untie %engines;
2074
2075
1;
2076
EOM
2077
}
2078
2079
0
select $prev;
2080
0
close(O);
2081
0
0
die $code if $code;
2082
0
chmod 0755, $out;
2083
2084
}
2085
2086
sub Syntax {
2087
0
0
0
my $self = shift;
2088
0
&DB::Syntax($self);
2089
}
2090
2091
2092
package DB;
2093
2094
sub Syntax {
2095
0
0
0
my $self = shift;
2096
0
my $step = 0;
2097
0
my $sub;
2098
0
my $pkg = ref($self);
2099
0
for (;;) {
2100
0
$step++;
2101
0
my @c = caller($step);
2102
0
$sub = $c[3];
2103
0
0
0
last if $sub =~ s/^(.*)::Do// && UNIVERSAL::isa($self, $1);
2104
}
2105
0
$self->Die("Syntax error on $sub: $DB::args[2]");
2106
}
2107
2108
2109
package HTML::Merge::Ext;
2110
2111
sub Macro {
2112
0
0
0
my $text = shift;
2113
0
$text =~ s/(?
2114
2115
0
$HTML::Merge::Ext::COMPILER->Macro($text);
2116
0
return "";
2117
}
2118
2119
1;