| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | ############################################################################### | 
| 2 |  |  |  |  |  |  | #Core.pm | 
| 3 |  |  |  |  |  |  | #Last Change: 2009-01-19 | 
| 4 |  |  |  |  |  |  | #Copyright (c) 2009 Marc-Seabstian "Maluku" Lucksch | 
| 5 |  |  |  |  |  |  | #Version 0.8 | 
| 6 |  |  |  |  |  |  | #################### | 
| 7 |  |  |  |  |  |  | #This file is part of the Dotiac::DTL project. | 
| 8 |  |  |  |  |  |  | #http://search.cpan.org/perldoc?Dotiac::DTL | 
| 9 |  |  |  |  |  |  | # | 
| 10 |  |  |  |  |  |  | #Core.pm is published under the terms of the MIT license, which basically | 
| 11 |  |  |  |  |  |  | #means "Do with it whatever you want". For more information, see the | 
| 12 |  |  |  |  |  |  | #license.txt file that should be enclosed with libsofu distributions. A copy of | 
| 13 |  |  |  |  |  |  | #the license is (at the time of writing) also available at | 
| 14 |  |  |  |  |  |  | #http://www.opensource.org/licenses/mit-license.php . | 
| 15 |  |  |  |  |  |  | ############################################################################### | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | package Dotiac::DTL::Core; | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | our $VERSION = 0.8; | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | package Dotiac::DTL; | 
| 22 |  |  |  |  |  |  | require Dotiac::DTL::Value; | 
| 23 |  |  |  |  |  |  | require Dotiac::DTL::Template; | 
| 24 |  |  |  |  |  |  | require Dotiac::DTL::Filter; | 
| 25 |  |  |  |  |  |  | require Dotiac::DTL::Compiled; | 
| 26 |  |  |  |  |  |  |  | 
| 27 | 12 |  |  | 12 |  | 74 | use strict; | 
|  | 12 |  |  |  |  | 22 |  | 
|  | 12 |  |  |  |  | 460 |  | 
| 28 | 12 |  |  | 12 |  | 70 | use warnings; | 
|  | 12 |  |  |  |  | 24 |  | 
|  | 12 |  |  |  |  | 410 |  | 
| 29 | 12 |  |  | 12 |  | 64 | use Scalar::Util qw/reftype blessed/; | 
|  | 12 |  |  |  |  | 19 |  | 
|  | 12 |  |  |  |  | 1040 |  | 
| 30 | 12 |  |  | 12 |  | 61 | use Carp; | 
|  | 12 |  |  |  |  | 18 |  | 
|  | 12 |  |  |  |  | 37394 |  | 
| 31 |  |  |  |  |  |  | require File::Spec; | 
| 32 |  |  |  |  |  |  | require File::Basename; | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | #These go into the context. | 
| 35 |  |  |  |  |  |  | our $TEMPLATE_STRING_IF_INVALID=""; #If there was no parameter found | 
| 36 |  |  |  |  |  |  | our $ALLOW_METHOD_CALLS=1; | 
| 37 |  |  |  |  |  |  | our $ALLOWED_INCLUDE_ROOTS=0; #Allows the ssi tag | 
| 38 |  |  |  |  |  |  | our $AUTOESCAPING=1; #Default auto escape or not | 
| 39 |  |  |  |  |  |  | our $DATETIME_FORMAT='N j, Y, P'; | 
| 40 |  |  |  |  |  |  | our $DATE_FORMAT='N j, Y'; | 
| 41 |  |  |  |  |  |  | our $TIME_FORMAT='P'; | 
| 42 |  |  |  |  |  |  | our @TEMPLATE_DIRS=(); #Only used by Template(); | 
| 43 |  |  |  |  |  |  | our $Max_Depth=3; | 
| 44 |  |  |  |  |  |  | our $CURRENTDIR=""; | 
| 45 |  |  |  |  |  |  | our $PARSER="Dotiac::DTL::Parser"; | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | #This has to change someday. not global | 
| 48 |  |  |  |  |  |  | our %blocks; #this needs to be global, sadly. | 
| 49 |  |  |  |  |  |  | our %cycle; #Also needs to be global. | 
| 50 |  |  |  |  |  |  | our %globals; #Well we already have other globals, this saves me the init() trough the whole tree/list. | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | our %included; | 
| 54 |  |  |  |  |  |  | our %params; | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | # Template cache, needs to be global | 
| 58 |  |  |  |  |  |  | my %cache; | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | sub new { | 
| 61 | 2 |  |  | 2 | 1 | 41 | my $class=shift; | 
| 62 | 2 |  |  |  |  | 3 | my $data=shift; | 
| 63 | 2 |  |  |  |  | 4 | my $t=""; | 
| 64 | 2 |  |  |  |  | 5 | %params=(); | 
| 65 | 2 | 50 |  |  |  | 11 | if (ref $data eq "SCALAR") { | 
|  |  | 50 |  |  |  |  |  | 
| 66 | 0 |  |  |  |  | 0 | die "Dotiac::DTL::Reduced can only work with compiled templates, use Dotiac::DTL for the full interface"; | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  | elsif (not ref $data) { | 
| 69 | 2 |  |  |  |  | 4 | $t=$data; | 
| 70 | 2 |  |  |  |  | 64 | my @f = File::Basename::fileparse($data); | 
| 71 | 2 |  |  |  |  | 5 | $Dotiac::DTL::currentdir=$f[1]; | 
| 72 | 2 | 100 |  |  |  | 36 | if (-e "$data.pm") { | 
| 73 | 1 | 0 | 33 |  |  | 10 | if ($cache{"$data.pm"} and exists $cache{"$data.pm"}->{changetime} and $cache{"$data.pm"}->{changetime} < (stat("$data.pm"))[9]) { | 
|  |  |  | 33 |  |  |  |  | 
| 74 | 0 |  |  |  |  | 0 | carp "Foo"; | 
| 75 | 0 |  |  |  |  | 0 | delete $cache{"$data.pm"}; | 
| 76 | 0 |  |  |  |  | 0 | delete $INC{"$data.pm"}; | 
| 77 |  |  |  |  |  |  | } | 
| 78 | 1 | 50 |  |  |  | 11 | if (-e $data) { | 
| 79 | 0 | 0 |  |  |  | 0 | if ((stat("$data.pm"))[9] >= (stat("$data"))[9]) { | 
| 80 |  |  |  |  |  |  | eval { | 
| 81 | 0 | 0 |  |  |  | 0 | $cache{"$data.pm"}={ | 
| 82 |  |  |  |  |  |  | template=>Dotiac::DTLCompiled->new("Dotiac::DTL::Compiled::".require "$data.pm"), | 
| 83 |  |  |  |  |  |  | currentdir=>$Dotiac::DTL::currentdir, | 
| 84 |  |  |  |  |  |  | params=>{%Dotiac::DTL::params}, | 
| 85 |  |  |  |  |  |  | parser=>$Dotiac::DTL::PARSER, | 
| 86 |  |  |  |  |  |  | changetime=>(stat("$data.pm"))[9] | 
| 87 |  |  |  |  |  |  | } if not $cache{"$data.pm"};# or (exists $cache{"$data.pm"}->{changetime} and $cache{"$data.pm"}->{changetime} > -M "$data.pm"); #Can't do it, Require won't return the filename a second time, has to be solved differently by manually modifing %INC | 
| 88 | 0 |  |  |  |  | 0 | $t="$data.pm"; | 
| 89 | 0 |  |  |  |  | 0 | 1; | 
| 90 | 0 | 0 |  |  |  | 0 | } or do { | 
| 91 | 0 |  |  |  |  | 0 | croak "Error while getting compiled template $data.pm and can't use $data, because this is Reduced:\n $@\n."; | 
| 92 | 0 |  |  |  |  | 0 | undef $@; | 
| 93 |  |  |  |  |  |  | }; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  | else { | 
| 96 | 0 |  |  |  |  | 0 | carp "$data seem to outdate $data.pm, but Dotiac::DTL::Reduced can only work with compiled templates, use Dotiac::DTL to recompile"; | 
| 97 |  |  |  |  |  |  | eval { | 
| 98 | 0 | 0 |  |  |  | 0 | $cache{"$data.pm"}={ | 
| 99 |  |  |  |  |  |  | template=>Dotiac::DTLCompiled->new("Dotiac::DTL::Compiled::".require "$data.pm"), | 
| 100 |  |  |  |  |  |  | currentdir=>$Dotiac::DTL::currentdir, | 
| 101 |  |  |  |  |  |  | params=>{%Dotiac::DTL::params}, | 
| 102 |  |  |  |  |  |  | parser=>$Dotiac::DTL::PARSER, | 
| 103 |  |  |  |  |  |  | changetime=>(stat("$data.pm"))[9] | 
| 104 |  |  |  |  |  |  | } if not $cache{"$data.pm"};# or (exists $cache{"$data.pm"}->{changetime} and $cache{"$data.pm"}->{changetime} > -M "$data.pm"); | 
| 105 | 0 |  |  |  |  | 0 | $t="$data.pm"; | 
| 106 | 0 |  |  |  |  | 0 | 1; | 
| 107 | 0 | 0 |  |  |  | 0 | } or do { | 
| 108 | 0 |  |  |  |  | 0 | croak "Error while getting compiled template $data.pm and can't use $data, because this is Reduced:\n $@\n."; | 
| 109 | 0 |  |  |  |  | 0 | undef $@; | 
| 110 |  |  |  |  |  |  | }; | 
| 111 |  |  |  |  |  |  | } | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  | else { | 
| 114 |  |  |  |  |  |  | eval { | 
| 115 | 1 | 50 |  |  |  | 708 | $cache{"$data.pm"}={ | 
| 116 |  |  |  |  |  |  | template=>Dotiac::DTL::Compiled->new("Dotiac::DTL::Compiled::".require "$data.pm"), | 
| 117 |  |  |  |  |  |  | currentdir=>$Dotiac::DTL::currentdir, | 
| 118 |  |  |  |  |  |  | params=>{%Dotiac::DTL::params}, | 
| 119 |  |  |  |  |  |  | parser=>$Dotiac::DTL::PARSER, | 
| 120 |  |  |  |  |  |  | changetime=>(stat("$data.pm"))[9] | 
| 121 |  |  |  |  |  |  | } if not $cache{"$data.pm"};# or (exists $cache{"$data.pm"}->{changetime} and $cache{"$data.pm"}->{changetime} > -M "$data.pm"); | 
| 122 | 1 |  |  |  |  | 6 | $t="$data.pm"; | 
| 123 | 1 |  |  |  |  | 5 | 1; | 
| 124 | 1 | 50 |  |  |  | 3 | } or do { | 
| 125 | 0 |  |  |  |  | 0 | croak "Error while getting compiled template $data.pm and $data is gone:\n $@\n."; | 
| 126 | 0 |  |  |  |  | 0 | undef $@; | 
| 127 |  |  |  |  |  |  | }; | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  | } | 
| 130 | 2 | 100 |  |  |  | 8 | unless ($cache{$t})  { | 
| 131 | 1 |  |  |  |  | 227 | croak "Dotiac::DTL::Reduced can only work with compiled templates, use Dotiac::DTL for the full interface"; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  | else { | 
| 135 | 0 |  |  |  |  | 0 | die "Can't work with $data!"; | 
| 136 |  |  |  |  |  |  | } | 
| 137 |  |  |  |  |  |  | #$self->{data}=$data; | 
| 138 | 1 |  |  |  |  | 5 | Dotiac::DTL::Addon::restore(); | 
| 139 | 1 | 50 |  |  |  | 4 | if ($cache{$t}) { | 
| 140 | 1 |  |  |  |  | 13 | return "Dotiac::DTL::Template"->new($cache{$t}->{template},$cache{$t}->{currentdir},$cache{$t}->{parser},$cache{$t}->{params}); | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  | else { | 
| 143 | 0 |  |  |  |  |  | croak "Dotiac::DTL::Reduced can only work with compiled templates, use Dotiac::DTL for the full interface"; | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  | } | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | our $currentdir=""; | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | sub safenew { | 
| 150 | 30 |  |  | 30 | 1 | 13137 | my $class=shift; | 
| 151 | 30 |  |  |  |  | 52 | my $file=shift; | 
| 152 | 30 | 50 | 66 |  |  | 114 | unless ($ALLOWED_INCLUDE_ROOTS and int($ALLOWED_INCLUDE_ROOTS) > 2) { | 
| 153 | 30 |  |  |  |  | 87 | $file=~s/^[\\\/]//g; | 
| 154 | 30 |  |  |  |  | 54 | $file=~s/^\w+\://g; #Windows GRR | 
| 155 | 30 |  |  |  |  | 173 | 1 while $file=~s/^\.\.[\\\/]//g; | 
| 156 |  |  |  |  |  |  | } | 
| 157 | 30 | 100 | 66 |  |  | 639 | unless ( -e $file or -e "$file.pm") { | 
| 158 | 2 |  |  |  |  | 38 | my $rfile=File::Spec->catfile(".",$currentdir,$file); | 
| 159 | 2 | 50 | 33 |  |  | 56 | return Dotiac::DTL->new($rfile) if -e $rfile or -e "$rfile.pm"; | 
| 160 |  |  |  |  |  |  | } | 
| 161 | 28 |  |  |  |  | 47 | my $p=$Dotiac::DTL::PARSER; | 
| 162 | 28 |  |  |  |  | 140 | my $r=Dotiac::DTL->new($file); | 
| 163 | 28 |  |  |  |  | 58 | $Dotiac::DTL::PARSER=$p; | 
| 164 | 28 |  |  |  |  | 79 | return $r; | 
| 165 |  |  |  |  |  |  | } | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | sub compiled { | 
| 168 | 1 |  |  | 1 | 1 | 711 | my $class=shift; | 
| 169 | 1 |  |  |  |  | 3 | my $name=shift; | 
| 170 | 1 |  |  |  |  | 2 | my $f; | 
| 171 | 1 |  |  |  |  | 3 | $Dotiac::DTL::currentdir=$Dotiac::DTL::CURRENTDIR; | 
| 172 | 1 |  |  |  |  | 3 | %params=(); | 
| 173 |  |  |  |  |  |  | eval { | 
| 174 | 1 |  |  |  |  | 7 | $f=Dotiac::DTL::Compiled->new($name); | 
| 175 | 1 |  |  |  |  | 6 | 1; | 
| 176 | 1 | 50 |  |  |  | 3 | } or do { | 
| 177 | 0 |  |  |  |  | 0 | croak "Error while getting compiled template from $name\n $@\n."; | 
| 178 | 0 |  |  |  |  | 0 | undef $@; | 
| 179 |  |  |  |  |  |  | }; | 
| 180 | 1 |  |  |  |  | 2 | undef $@; | 
| 181 | 1 |  |  |  |  | 7 | return "Dotiac::DTL::Template"->new($f,$Dotiac::DTL::CURRENTDIR); | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | sub urlencode { | 
| 187 | 0 |  |  | 0 | 1 | 0 | my $val=shift; | 
| 188 | 0 |  | 0 |  |  | 0 | $val = eval { pack("C*", unpack("U0C*", $val))} || pack("C*", unpack("C*", $val)); | 
| 189 | 0 |  |  |  |  | 0 | $val=~s/([^a-zA-Z0-9_.~-])/uc sprintf("%%%02x",ord($1))/eg; | 
|  | 0 |  |  |  |  | 0 |  | 
| 190 | 0 |  |  |  |  | 0 | return $val; | 
| 191 |  |  |  |  |  |  | } | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | sub escap { #Escape is used too much these days. | 
| 194 | 309 |  |  | 309 | 1 | 538 | my $string=shift; | 
| 195 | 309 |  |  |  |  | 423 | $string=~s/\\n/\n/g; | 
| 196 | 309 |  |  |  |  | 376 | $string=~s/\\t/\t/g; | 
| 197 | 309 |  |  |  |  | 370 | $string=~s/\\r/\r/g; | 
| 198 | 309 |  |  |  |  | 328 | $string=~s/\\b/\b/g; | 
| 199 | 309 |  |  |  |  | 380 | $string=~s/\\f/\f/g; | 
| 200 | 309 |  |  |  |  | 338 | $string=~s/\\x([\dA-Fa-f]{2})/chr(hex($1))/eg; | 
|  | 1 |  |  |  |  | 6 |  | 
| 201 | 309 |  |  |  |  | 344 | $string=~s/\\u([\dA-Fa-f]{4})/chr(hex($1))/eg; | 
|  | 3 |  |  |  |  | 14 |  | 
| 202 | 309 |  |  |  |  | 338 | $string=~s/\\U([\dA-Fa-f]{8})/chr(hex($1))/eg; | 
|  | 0 |  |  |  |  | 0 |  | 
| 203 | 309 |  |  |  |  | 392 | $string=~s/\\(["'{}])/$1/g; | 
| 204 |  |  |  |  |  |  | #$string=~s/\\([^\\])/die/eg; | 
| 205 | 309 |  |  |  |  | 350 | $string=~s/\\\\/\\/g; | 
| 206 |  |  |  |  |  |  | #TODO more pyhton escape seq. | 
| 207 | 309 |  |  |  |  | 618 | $string=~s/([\|\s\,\"\'\`\%\:;=])/sprintf("%%%02X",ord($1))/eg; | 
|  | 151 |  |  |  |  | 609 |  | 
| 208 | 309 |  |  |  |  | 848 | return "`$string`"; | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | sub descap { | 
| 212 | 1204 |  |  | 1204 | 1 | 2442 | my $string=shift; | 
| 213 | 1204 |  |  |  |  | 2258 | $string=~s/%([\da-fA-F]{2})/chr(hex($1))/eg; | 
|  | 502 |  |  |  |  | 1643 |  | 
| 214 | 1204 |  |  |  |  | 4904 | return $string; | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | sub get_variables { | 
| 218 | 412 |  |  | 412 | 1 | 7460 | my $x=shift; | 
| 219 | 412 | 100 | 66 |  |  | 2042 | $x="" if not defined $x or ref $x; | 
| 220 | 412 |  |  |  |  | 2701 | while ($x=~m/[^\"\']*([\"\'])/g) { | 
| 221 | 302 |  |  |  |  | 490 | my $opos=pos($x); | 
| 222 | 302 | 100 |  |  |  | 720 | if ($1 eq '"') { | 
| 223 | 298 |  |  |  |  | 1202 | $x=~m/((?>(?:(?>[^"\\]+)|\\.)*))"/g; | 
| 224 | 298 | 50 |  |  |  | 598 | die "Syntax error in $1..$1 of $x" unless pos($x); | 
| 225 | 298 |  |  |  |  | 529 | my $replace=escap($1); | 
| 226 | 298 |  |  |  |  | 996 | substr($x,$opos-1,pos($x)+1-$opos)=$replace; | 
| 227 | 298 |  |  |  |  | 708 | pos($x)=$opos+length($replace); | 
| 228 |  |  |  |  |  |  | } | 
| 229 |  |  |  |  |  |  | else { | 
| 230 | 4 |  |  |  |  | 24 | $x=~m/((?>(?:(?>[^'\\]+)|\\.)*))'/g; | 
| 231 | 4 | 50 |  |  |  | 14 | die "Syntax error in $1..$1 of $x" unless pos($x); | 
| 232 | 4 |  |  |  |  | 11 | my $replace=escap($1); | 
| 233 | 4 |  |  |  |  | 17 | substr($x,$opos-1,pos($x)+1-$opos)=$replace; | 
| 234 | 4 |  |  |  |  | 50 | pos($x)=$opos+length($replace); | 
| 235 |  |  |  |  |  |  | } | 
| 236 | 302 | 50 |  |  |  | 1742 | die "Syntax error in $1..$1 of $x" unless pos($x); | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  | #warn "var::$x"; | 
| 239 | 412 | 100 |  |  |  | 1054 | if (@_) { | 
| 240 | 71 |  |  |  |  | 104 | my %words; | 
| 241 | 71 |  |  |  |  | 271 | @words{@_}=(1) x scalar @_; | 
| 242 | 71 |  |  |  |  | 101 | my %ret; | 
| 243 | 71 |  |  |  |  | 212 | my $keywords = "(?:^|\\s+)".join ("(?:\\s+|\$)|(?:^|\\s+)",@_)."(?:\\s+|\$)"; | 
| 244 |  |  |  |  |  |  | #print STDERR "@_: $keywords\n"; | 
| 245 | 71 |  |  |  |  | 1562 | my @l = split /($keywords)/,$x; | 
| 246 |  |  |  |  |  |  | #print STDERR join(", ",@l)."\n"; | 
| 247 | 71 |  |  |  |  | 204 | unshift @l,""; | 
| 248 | 71 |  |  |  |  | 231 | while (defined(my $k=shift @l)) { | 
| 249 | 136 |  |  |  |  | 359 | $k=~s/^\s+//g; | 
| 250 | 136 |  |  |  |  | 276 | $k=~s/\s+$//g; | 
| 251 | 136 | 100 |  |  |  | 267 | if (@l) { | 
| 252 | 124 |  |  |  |  | 185 | my $next=$l[0]; | 
| 253 | 124 |  |  |  |  | 268 | $next=~s/^\s+//g; | 
| 254 | 124 |  |  |  |  | 213 | $next=~s/\s+$//g; | 
| 255 | 124 | 100 |  |  |  | 304 | if ($words{$next}) { | 
| 256 | 4 |  |  |  |  | 18 | $ret{$k}=[]; | 
| 257 |  |  |  |  |  |  | } | 
| 258 |  |  |  |  |  |  | else { | 
| 259 | 120 |  |  |  |  | 306 | my @a=split /\s+/,shift(@l); | 
| 260 | 120 |  |  |  |  | 346 | $ret{$k}=[@a]; | 
| 261 | 120 |  |  |  |  | 219 | foreach my $a (@a) { | 
| 262 | 138 |  |  |  |  | 672 | $Dotiac::DTL::params{$a}++; | 
| 263 |  |  |  |  |  |  | } | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  | else { | 
| 267 | 12 |  |  |  |  | 86 | $ret{$k}=[]; | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  | } | 
| 270 | 71 |  |  |  |  | 554 | return %ret; | 
| 271 |  |  |  |  |  |  | } | 
| 272 | 341 |  |  |  |  | 977 | my @a= split /\s+/,$x; | 
| 273 | 341 |  |  |  |  | 642 | foreach my $a (@a) { | 
| 274 | 407 |  |  |  |  | 1331 | $Dotiac::DTL::params{$a}++; | 
| 275 |  |  |  |  |  |  | } | 
| 276 | 341 |  |  |  |  | 1356 | return @a; | 
| 277 |  |  |  |  |  |  | } | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | sub Escape { | 
| 280 | 8 |  |  | 8 | 1 | 17 | my $var=shift; | 
| 281 | 8 | 100 |  |  |  | 47 | return Dotiac::DTL::Value->escape($var)->string() if $_[0]; | 
| 282 | 4 |  |  |  |  | 18 | return $var; | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | sub Conditional { | 
| 286 | 0 |  |  | 0 | 1 | 0 | my $var=shift; | 
| 287 | 0 | 0 |  |  |  | 0 | return "" unless $var; | 
| 288 | 0 | 0 |  |  |  | 0 | return $var unless ref $var; | 
| 289 | 0 | 0 | 0 |  |  | 0 | return $var->count() if Scalar::Util::blessed($var) and $var->can("count"); | 
| 290 | 0 | 0 |  |  |  | 0 | return 1 if Scalar::Util::blessed($var); | 
| 291 | 0 | 0 |  |  |  | 0 | return scalar @{$var} if ref $var eq "ARRAY"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 292 | 0 | 0 |  |  |  | 0 | return scalar keys %{$var} if ref $var eq "HASH"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 293 | 0 |  |  |  |  | 0 | return 1; | 
| 294 |  |  |  |  |  |  | } | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | sub apply_filters { | 
| 297 | 1368 |  |  | 1368 | 1 | 2921 | my $value=shift; | 
| 298 | 1368 |  |  |  |  | 1404 | my $vars=shift; | 
| 299 | 1368 |  |  |  |  | 1551 | my $escape=shift; | 
| 300 |  |  |  |  |  |  | #$escape=0 if $STRING_IS_LITERAL; #TODO | 
| 301 |  |  |  |  |  |  | #$VARIABLE_IS_SAFE=!$escape; | 
| 302 | 1368 | 100 | 66 |  |  | 9272 | unless (Scalar::Util::blessed($value) and $value->isa("Dotiac::DTL::Value")) { | 
| 303 | 12 |  |  |  |  | 55 | $value=Dotiac::DTL::Value->new($value,!$escape); | 
| 304 |  |  |  |  |  |  | } | 
| 305 | 1368 |  |  |  |  | 2810 | foreach my $f (@_) { | 
| 306 | 936 |  |  |  |  | 2553 | my ($filter,$param)=split /:/,$f,2; | 
| 307 | 936 |  |  |  |  | 1458 | $filter=lc $filter; | 
| 308 | 936 |  |  |  |  | 1074 | eval { | 
| 309 | 12 |  |  | 12 |  | 93 | no strict "refs"; #I hate to do this, does anyone know a better one without eval? | 
|  | 12 |  |  |  |  | 26 |  | 
|  | 12 |  |  |  |  | 8005 |  | 
| 310 | 936 | 100 |  |  |  | 4051 | $value="Dotiac::DTL::Filter::$filter"->($value,defined $param?(map {devar_var($_,$vars,0)} split /[,;]/,$param):()); | 
|  | 536 |  |  |  |  | 895 |  | 
| 311 |  |  |  |  |  |  | }; | 
| 312 | 936 | 50 |  |  |  | 2354 | if ($@) { | 
| 313 | 0 |  |  |  |  | 0 | die "Filter '$filter' couldn't be found or an error occoured. The filter has to be in the Dotiac::DTL::Filter namespace\n$@"; | 
| 314 |  |  |  |  |  |  | } | 
| 315 | 936 | 50 | 33 |  |  | 6859 | die "Filter Error: $filter did not return a Dotiac::DTL::Value" unless Scalar::Util::blessed($value) and $value->isa("Dotiac::DTL::Value"); | 
| 316 |  |  |  |  |  |  | } | 
| 317 | 1368 |  |  |  |  | 4976 | return $value; | 
| 318 |  |  |  |  |  |  | } | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | sub devar { | 
| 321 | 393 |  |  | 393 | 1 | 3661 | my $name=shift; | 
| 322 | 393 | 50 |  |  |  | 825 | return "" unless defined $name; | 
| 323 | 393 |  |  |  |  | 1211 | my @data= split/\|/,$name; | 
| 324 | 393 |  |  |  |  | 666 | $name=shift @data; | 
| 325 | 393 |  |  |  |  | 574 | my $param=shift; | 
| 326 | 393 |  |  |  |  | 537 | my $escape=shift; | 
| 327 | 393 |  |  |  |  | 1088 | my $var=devar_var($name,$param,$escape,@_); | 
| 328 | 393 | 100 |  |  |  | 1155 | unless (@data) { | 
| 329 | 365 |  |  |  |  | 1083 | return $var->string(); | 
| 330 |  |  |  |  |  |  | } | 
| 331 | 28 |  |  |  |  | 68 | $var=apply_filters($var,$param,$escape,@data); | 
| 332 | 28 |  |  |  |  | 94 | return $var->string(); | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | } | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | sub devar_nodefault { | 
| 337 | 0 |  |  | 0 | 1 | 0 | my $name=shift; | 
| 338 | 0 | 0 |  |  |  | 0 | return "" unless defined $name; | 
| 339 | 0 |  |  |  |  | 0 | my @data= split/\|/,$name; | 
| 340 | 0 |  |  |  |  | 0 | $name=shift @data; | 
| 341 | 0 |  |  |  |  | 0 | my $param=shift; | 
| 342 | 0 |  |  |  |  | 0 | my $escape=shift; | 
| 343 | 0 |  |  |  |  | 0 | my $var=devar_var($name,$param,$escape,@_); | 
| 344 | 0 | 0 |  |  |  | 0 | unless (@data) { | 
| 345 | 0 |  |  |  |  | 0 | return $var->stringnodefault(); | 
| 346 |  |  |  |  |  |  | } | 
| 347 | 0 |  |  |  |  | 0 | $var=apply_filters($var,$param,$escape,@data); | 
| 348 | 0 |  |  |  |  | 0 | return $var->stringnodefault(); | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | } | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | sub devar_raw { | 
| 353 | 1194 |  |  | 1194 | 1 | 11514 | my $name=shift; | 
| 354 | 1194 | 50 |  |  |  | 2576 | return "" unless defined $name; | 
| 355 | 1194 |  |  |  |  | 3447 | my @data= split/\|/,$name; | 
| 356 | 1194 |  |  |  |  | 1967 | $name=shift @data; | 
| 357 | 1194 |  |  |  |  | 1665 | my $param=shift; | 
| 358 | 1194 |  |  |  |  | 1359 | my $escape=shift; | 
| 359 | 1194 |  |  |  |  | 2529 | my $var=devar_var($name,$param,$escape,@_); | 
| 360 | 1194 | 100 |  |  |  | 3478 | unless (@data) { | 
| 361 | 1170 |  |  |  |  | 4746 | return $var; | 
| 362 |  |  |  |  |  |  | } | 
| 363 | 24 |  |  |  |  | 50 | $var=apply_filters($var,$param,$escape,@data); | 
| 364 | 24 |  |  |  |  | 104 | return $var; | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | } | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | sub devar_content { | 
| 369 | 172 |  |  | 172 | 1 | 1028 | my $name=shift; | 
| 370 | 172 | 50 |  |  |  | 455 | return "" unless defined $name; | 
| 371 | 172 |  |  |  |  | 551 | my @data= split/\|/,$name; | 
| 372 | 172 |  |  |  |  | 289 | $name=shift @data; | 
| 373 | 172 |  |  |  |  | 237 | my $param=shift; | 
| 374 | 172 |  |  |  |  | 215 | my $escape=shift; | 
| 375 | 172 |  |  |  |  | 425 | my $var=devar_var($name,$param,$escape,@_); | 
| 376 | 172 | 100 |  |  |  | 499 | unless (@data) { | 
| 377 | 12 |  |  | 12 |  | 75 | use Carp qw/confess/; | 
|  | 12 |  |  |  |  | 27 |  | 
|  | 12 |  |  |  |  | 2484 |  | 
| 378 | 132 | 50 |  |  |  | 307 | confess unless ref $var; | 
| 379 | 132 |  |  |  |  | 427 | return $var->content(); | 
| 380 |  |  |  |  |  |  | } | 
| 381 | 40 |  |  |  |  | 89 | $var=apply_filters($var,$param,$escape,@data); | 
| 382 | 40 |  |  |  |  | 106 | return $var->content(); | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | } | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | sub devar_repr { | 
| 387 | 16 |  |  | 16 | 1 | 151 | my $name=shift; | 
| 388 | 16 | 50 |  |  |  | 33 | return "" unless defined $name; | 
| 389 | 16 |  |  |  |  | 42 | my @data= split/\|/,$name; | 
| 390 | 16 |  |  |  |  | 24 | $name=shift @data; | 
| 391 | 16 |  |  |  |  | 25 | my $param=shift; | 
| 392 | 16 |  |  |  |  | 18 | my $escape=shift; | 
| 393 | 16 |  |  |  |  | 31 | my $var=devar_var($name,$param,$escape,@_); | 
| 394 | 16 | 50 |  |  |  | 35 | unless (@data) { | 
| 395 | 12 |  |  | 12 |  | 69 | use Carp qw/confess/; | 
|  | 12 |  |  |  |  | 21 |  | 
|  | 12 |  |  |  |  | 1977 |  | 
| 396 | 16 | 50 |  |  |  | 41 | confess unless ref $var; | 
| 397 | 16 |  |  |  |  | 41 | return $var->repr(); | 
| 398 |  |  |  |  |  |  | } | 
| 399 | 0 |  |  |  |  | 0 | $var=apply_filters($var,$param,$escape,@data); | 
| 400 | 0 |  |  |  |  | 0 | return $var->repr(); | 
| 401 |  |  |  |  |  |  |  | 
| 402 |  |  |  |  |  |  | } | 
| 403 |  |  |  |  |  |  |  | 
| 404 |  |  |  |  |  |  | sub devar_var { | 
| 405 | 3359 |  |  | 3359 | 1 | 5436 | my $name=shift; | 
| 406 | 3359 |  |  |  |  | 3810 | my $n=$name; | 
| 407 | 3359 | 50 |  |  |  | 6597 | return Dotiac::DTL::Value->safe(undef) unless defined $name; | 
| 408 | 3359 |  |  |  |  | 4131 | my $param=shift; | 
| 409 | 3359 |  |  |  |  | 5099 | my $f=substr $name,0,1; | 
| 410 | 3359 |  |  |  |  | 4139 | my $l=substr $name,-1,1; | 
| 411 | 3359 |  |  |  |  | 4315 | my $escape=shift; | 
| 412 |  |  |  |  |  |  | #TODO | 
| 413 | 12 |  |  | 12 |  | 82 | use Carp; | 
|  | 12 |  |  |  |  | 39 |  | 
|  | 12 |  |  |  |  | 11993 |  | 
| 414 | 3359 | 50 |  |  |  | 13748 | confess $param unless ref $param; | 
| 415 | 3359 | 50 |  |  |  | 6597 | confess $escape unless defined $escape; | 
| 416 |  |  |  |  |  |  | #confess @_ unless @_; | 
| 417 |  |  |  |  |  |  | #TODO | 
| 418 | 3359 | 50 | 33 |  |  | 22575 | return Dotiac::DTL::Value->safe(substr $name,1,-1) if $f eq "'" and $l eq "'" or $f eq '"' and $l eq '"'; | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 419 | 3359 | 100 | 66 |  |  | 12058 | return Dotiac::DTL::Value->safe(descap(substr $name,1,-1)) if $f eq "`" and $l eq "`"; | 
| 420 | 2274 | 50 | 33 |  |  | 5365 | if ($name eq "block.super" and $param->{"block.super"}) { | 
| 421 | 0 | 0 |  |  |  | 0 | return Dotiac::DTL::Value->safe($param->{"block.super"}->string($param,@_)) if Scalar::Util::blessed($param->{"block.super"}); | 
| 422 | 0 | 0 |  |  |  | 0 | return Dotiac::DTL::Value->safe($param->{"block.super"}->($param,@_)) if ref $param->{"block.super"} eq "CODE"; | 
| 423 |  |  |  |  |  |  | } | 
| 424 | 2274 | 100 |  |  |  | 9176 | return Dotiac::DTL::Value->new($param->{$name},!$escape) if exists $param->{$name}; | 
| 425 | 776 |  |  |  |  | 2250 | my @tree=split/\./,$name; | 
| 426 | 776 |  |  |  |  | 1192 | $name=shift @tree; | 
| 427 | 776 | 100 |  |  |  | 1782 | unless (exists $param->{$name}) { | 
| 428 | 136 | 100 |  |  |  | 575 | return Dotiac::DTL::Value->safe($n) if $n!~/[^\d\-\.\,\e]/; | 
| 429 | 72 | 100 | 66 |  |  | 1198 | if ($cycle{$name} and $cycle{$name}->[1]) { | 
| 430 | 4 | 50 |  |  |  | 12 | return Dotiac::DTL::Value->safe("") if $included{"cycle_$name"}++; | 
| 431 | 4 |  |  |  |  | 25 | my $r=devar_raw($cycle{$name}->[2]->[$cycle{$name}->[0]-1 % $cycle{$name}->[1]],$param,$escape,@_); | 
| 432 | 4 |  |  |  |  | 9 | $included{"cycle_$name"}=0; | 
| 433 | 4 |  |  |  |  | 11 | return $r; | 
| 434 |  |  |  |  |  |  | } | 
| 435 | 68 |  |  |  |  | 315 | return Dotiac::DTL::Value->safe(undef) ; | 
| 436 |  |  |  |  |  |  | } | 
| 437 | 640 |  |  |  |  | 978 | $param=$param->{$name}; | 
| 438 | 640 |  |  |  |  | 1944 | while (defined(my $name = shift @tree)) { | 
| 439 | 684 |  |  |  |  | 1556 | my $r = reftype $param; | 
| 440 | 684 | 50 |  |  |  | 1291 | if ($r) { | 
| 441 | 684 | 100 |  |  |  | 1238 | if ($r eq "HASH") { | 
|  |  | 50 |  |  |  |  |  | 
| 442 | 628 | 100 |  |  |  | 1218 | if (not exists $param->{$name}) { | 
| 443 | 16 | 100 |  |  |  | 72 | return Dotiac::DTL::Value->safe(undef) unless blessed $param; | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  | else { | 
| 446 | 612 |  |  |  |  | 1051 | $param=$param->{$name}; | 
| 447 | 612 |  |  |  |  | 2014 | next; | 
| 448 |  |  |  |  |  |  | } | 
| 449 |  |  |  |  |  |  | } | 
| 450 |  |  |  |  |  |  | elsif ($r eq "ARRAY") { | 
| 451 | 56 | 100 |  |  |  | 133 | if ($name=~m/\D/) { | 
| 452 | 8 | 50 |  |  |  | 35 | return Dotiac::DTL::Value->safe(undef) unless blessed $param; | 
| 453 |  |  |  |  |  |  | } | 
| 454 |  |  |  |  |  |  | else { | 
| 455 | 48 | 50 |  |  |  | 99 | if (not exists $param->[$name]) { | 
| 456 | 0 | 0 |  |  |  | 0 | return Dotiac::DTL::Value->safe(undef) unless blessed $param; | 
| 457 |  |  |  |  |  |  | } | 
| 458 |  |  |  |  |  |  | else { | 
| 459 | 48 |  |  |  |  | 68 | $param=$param->[$name]; | 
| 460 | 48 |  |  |  |  | 431 | next; | 
| 461 |  |  |  |  |  |  | } | 
| 462 |  |  |  |  |  |  | } | 
| 463 |  |  |  |  |  |  | } | 
| 464 |  |  |  |  |  |  | } | 
| 465 | 12 | 50 |  |  |  | 39 | if (blessed $param) { | 
| 466 | 12 | 50 |  |  |  | 26 | return Dotiac::DTL::Value->safe(undef) unless $ALLOW_METHOD_CALLS; | 
| 467 | 12 | 50 |  |  |  | 58 | if ($param->can($name)) { | 
|  |  | 0 |  |  |  |  |  | 
| 468 | 12 |  |  |  |  | 39 | $param=$param->$name(); | 
| 469 | 12 |  |  |  |  | 62 | next; | 
| 470 |  |  |  |  |  |  | } | 
| 471 |  |  |  |  |  |  | elsif ($param->can("__getitem__")) { | 
| 472 | 0 |  |  |  |  | 0 | my $x; | 
| 473 | 0 | 0 |  |  |  | 0 | eval { | 
| 474 | 0 |  |  |  |  | 0 | $x=$param->__getitem__($name); | 
| 475 | 0 |  |  |  |  | 0 | 1; | 
| 476 |  |  |  |  |  |  | } or return Dotiac::DTL::Value->safe(undef); | 
| 477 | 0 | 0 |  |  |  | 0 | if (defined $x) { | 
| 478 | 0 |  |  |  |  | 0 | $param=$x; | 
| 479 | 0 |  |  |  |  | 0 | next; | 
| 480 |  |  |  |  |  |  | } | 
| 481 |  |  |  |  |  |  | } | 
| 482 | 0 |  |  |  |  | 0 | return Dotiac::DTL::Value->safe(undef); | 
| 483 |  |  |  |  |  |  | } | 
| 484 | 0 | 0 |  |  |  | 0 | return Dotiac::DTL::Value->safe($n) if $n!~/[^\d\-\.\,\e]/; | 
| 485 | 0 |  |  |  |  | 0 | return Dotiac::DTL::Value->safe(undef); | 
| 486 |  |  |  |  |  |  | } | 
| 487 | 628 |  |  |  |  | 2185 | return Dotiac::DTL::Value->new($param,!$escape); | 
| 488 |  |  |  |  |  |  | } | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  | sub devar_var_default { | 
| 491 | 0 |  |  | 0 | 1 | 0 | my $var = devar_var(@_); | 
| 492 | 0 |  |  |  |  | 0 | return $var->string(); | 
| 493 |  |  |  |  |  |  | } | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | 1; | 
| 496 |  |  |  |  |  |  | __END__ |