| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # | 
| 2 |  |  |  |  |  |  | #  This file is part of WebDyne. | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | #  This software is Copyright (c) 2017 by Andrew Speer . | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | #  This is free software, licensed under: | 
| 7 |  |  |  |  |  |  | # | 
| 8 |  |  |  |  |  |  | #    The GNU General Public License, Version 2, June 1991 | 
| 9 |  |  |  |  |  |  | # | 
| 10 |  |  |  |  |  |  | #  Full license text is available at: | 
| 11 |  |  |  |  |  |  | # | 
| 12 |  |  |  |  |  |  | # | 
| 13 |  |  |  |  |  |  | # | 
| 14 |  |  |  |  |  |  | package WebDyne; | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | #  Packace init, attempt to load optional Time::HiRes module | 
| 18 |  |  |  |  |  |  | sub BEGIN { | 
| 19 | 2 |  |  | 2 |  | 50276 | local $SIG{__DIE__}; | 
| 20 | 2 |  |  |  |  | 6 | $^W=0; | 
| 21 | 2 | 50 |  | 2 |  | 103 | eval("use Time::HiRes qw(time)") || eval {undef}; | 
|  | 2 |  |  |  |  | 295 |  | 
|  | 2 |  |  |  |  | 632 |  | 
|  | 2 |  |  |  |  | 1965 |  | 
|  | 2 |  |  |  |  | 8 |  | 
| 22 |  |  |  |  |  |  | } | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | #  Pragma | 
| 26 |  |  |  |  |  |  | # | 
| 27 | 2 |  |  | 2 |  | 38 | use strict qw(vars); | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 53 |  | 
| 28 | 2 |  |  | 2 |  | 9 | use vars qw($VERSION %CGI_TAG_WEBDYNE @ISA $AUTOLOAD); | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 115 |  | 
| 29 | 2 |  |  | 2 |  | 10 | use warnings; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 56 |  | 
| 30 | 2 |  |  | 2 |  | 8 | no warnings qw(uninitialized redefine once); | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 129 |  | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | #  WebDyne constants, base modules | 
| 34 |  |  |  |  |  |  | # | 
| 35 | 2 |  |  | 2 |  | 652 | use WebDyne::Constant; | 
|  | 2 |  |  |  |  | 8 |  | 
|  | 2 |  |  |  |  | 561 |  | 
| 36 | 2 |  |  | 2 |  | 12 | use WebDyne::Base; | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 12 |  | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | #  External Modules | 
| 40 |  |  |  |  |  |  | # | 
| 41 | 2 |  |  | 2 |  | 760 | use Storable; | 
|  | 2 |  |  |  |  | 4571 |  | 
|  | 2 |  |  |  |  | 103 |  | 
| 42 | 2 |  |  | 2 |  | 269 | use HTTP::Status qw(is_success is_error is_redirect RC_OK RC_FOUND RC_NOT_FOUND); | 
|  | 2 |  |  |  |  | 3219 |  | 
|  | 2 |  |  |  |  | 149 |  | 
| 43 | 2 |  |  | 2 |  | 10 | use Fcntl; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 364 |  | 
| 44 | 2 |  |  | 2 |  | 556 | use Tie::IxHash; | 
|  | 2 |  |  |  |  | 5571 |  | 
|  | 2 |  |  |  |  | 49 |  | 
| 45 | 2 |  |  | 2 |  | 15 | use Digest::MD5 qw(md5_hex); | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 81 |  | 
| 46 | 2 |  |  | 2 |  | 11 | use File::Spec::Unix; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 38 |  | 
| 47 | 2 |  |  | 2 |  | 8 | use Data::Dumper; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 67 |  | 
| 48 | 2 |  |  | 2 |  | 820 | use overload; | 
|  | 2 |  |  |  |  | 686 |  | 
|  | 2 |  |  |  |  | 11 |  | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | #  Inherit from the Compile module, not loaded until needed though. | 
| 52 |  |  |  |  |  |  | # | 
| 53 |  |  |  |  |  |  | @ISA=qw(WebDyne::Compile); | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | #  Version information | 
| 57 |  |  |  |  |  |  | # | 
| 58 |  |  |  |  |  |  | $VERSION='1.248'; | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | #  Debug load | 
| 62 |  |  |  |  |  |  | # | 
| 63 |  |  |  |  |  |  | 0 && debug("%s loaded, version $VERSION", __PACKAGE__); | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | #  Shortcut error handler, save using ISA; | 
| 67 |  |  |  |  |  |  | # | 
| 68 |  |  |  |  |  |  | require WebDyne::Err; | 
| 69 |  |  |  |  |  |  | *err_html=\&WebDyne::Err::err_html || *err_html; | 
| 70 |  |  |  |  |  |  | *err_eval=\&WebDyne::Err::err_eval || *err_eval; | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | #  Our webdyne "special" tags | 
| 74 |  |  |  |  |  |  | # | 
| 75 |  |  |  |  |  |  | %CGI_TAG_WEBDYNE=map {$_ => 1} ( | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | 'block', | 
| 78 |  |  |  |  |  |  | 'perl', | 
| 79 |  |  |  |  |  |  | 'subst', | 
| 80 |  |  |  |  |  |  | 'dump', | 
| 81 |  |  |  |  |  |  | 'include', | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | ); | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | #  Var to hold package wide hash, for data shared across package | 
| 87 |  |  |  |  |  |  | # | 
| 88 |  |  |  |  |  |  | my %Package; | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | #  Do some class wide initialisation | 
| 92 |  |  |  |  |  |  | # | 
| 93 |  |  |  |  |  |  | &init_class(); | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | #  Eval safe not effective - die if turned on | 
| 97 |  |  |  |  |  |  | # | 
| 98 |  |  |  |  |  |  | if ($WEBDYNE_EVAL_SAFE) {die "WEBDYNE_EVAL_SAFE disabled in this version\n"} | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | #  All done. Positive return | 
| 102 |  |  |  |  |  |  | # | 
| 103 |  |  |  |  |  |  | 1; | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | #================================================================================================== | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | sub handler : method { | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | #  Get self ref/class, request ref | 
| 113 |  |  |  |  |  |  | # | 
| 114 | 10 |  |  | 10 | 0 | 2770 | my ($self, $r, $param_hr)=@_; | 
| 115 | 10 |  |  |  |  | 23 | 0 && debug("handler called with self $self, r $r, MP2 $MP2"); | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | #  Start timer so we can optionally keep stats on how long handler takes to run | 
| 119 |  |  |  |  |  |  | # | 
| 120 | 10 |  |  |  |  | 32 | my $time=time(); | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | #  Work out class and correct self ref | 
| 124 |  |  |  |  |  |  | # | 
| 125 | 10 |  | 33 |  |  | 52 | my $class=ref($self) || do { | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | #  Need new self ref, as self is actually class. Do inline so quicker than -> new | 
| 129 |  |  |  |  |  |  | # | 
| 130 |  |  |  |  |  |  | my %self=( | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | _time => $time, | 
| 133 |  |  |  |  |  |  | _r    => $r, | 
| 134 |  |  |  |  |  |  | %{delete $self->{'_self'}}, | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | ); | 
| 137 |  |  |  |  |  |  | $self=bless \%self, $self; | 
| 138 |  |  |  |  |  |  | ref($self); | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | }; | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | #  Setup error handlers | 
| 145 |  |  |  |  |  |  | # | 
| 146 |  |  |  |  |  |  | local $SIG{'__DIE__'}=sub { | 
| 147 | 0 |  |  | 0 |  | 0 | 0 && debug('in __DIE__ sig handler, caller %s', join(',', (caller(0))[0..3])); | 
| 148 | 0 |  |  |  |  | 0 | return err (@_) | 
| 149 | 10 |  |  |  |  | 75 | }; | 
| 150 |  |  |  |  |  |  | local $SIG{'__WARN__'}=sub { | 
| 151 | 0 |  |  | 0 |  | 0 | 0 && debug('in __WARN__ sig handler, caller %s', join(',', (caller(0))[0..3])); | 
| 152 | 0 |  |  |  |  | 0 | return err (@_) | 
| 153 |  |  |  |  |  |  | } | 
| 154 | 10 | 50 |  |  |  | 31 | if $WEBDYNE_WARNINGS_FATAL; | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | #  Debug | 
| 158 |  |  |  |  |  |  | # | 
| 159 | 10 |  |  |  |  | 15 | 0 && debug( | 
| 160 |  |  |  |  |  |  | "in WebDyne::handler. class $class, self $self, r $r, param_hr %s", | 
| 161 |  |  |  |  |  |  | Dumper($param_hr)); | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | #  Skip all processing if header request only | 
| 165 |  |  |  |  |  |  | # | 
| 166 | 10 | 50 |  |  |  | 36 | if ($r->header_only()) {return &head_request($r)} | 
|  | 0 |  |  |  |  | 0 |  | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | #  Debug | 
| 170 |  |  |  |  |  |  | # | 
| 171 | 10 |  |  |  |  | 16 | 0 && debug( | 
| 172 |  |  |  |  |  |  | "enter handler, r $r, location %s file %s, param %s", | 
| 173 |  |  |  |  |  |  | $r->location(), $r->filename(), Dumper($param_hr)); | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | #  Get full path, mtime of source file, check file exists | 
| 177 |  |  |  |  |  |  | # | 
| 178 | 10 |  | 50 |  |  | 38 | my $srce_pn=$r->filename() || | 
| 179 |  |  |  |  |  |  | return $self->err_html('unable to get request filename'); | 
| 180 | 10 |  | 33 |  |  | 268 | my $srce_mtime=(-f $srce_pn && (stat(_))[9]) || do { | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | #  File not found, we don't want to handle this anymore .. | 
| 183 |  |  |  |  |  |  | # | 
| 184 |  |  |  |  |  |  | 0 && debug("srce_mtime for file '$srce_pn' not found, could not stat !"); | 
| 185 |  |  |  |  |  |  | return &Apache::DECLINED; | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | }; | 
| 188 | 10 |  |  |  |  | 23 | 0 && debug("srce_pn $srce_pn, srce_mtime (real) $srce_mtime"); | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | #  Used to use inode as unique identifier for file in cache, but that | 
| 192 |  |  |  |  |  |  | #  did not take into account the fact that the same file may have diff | 
| 193 |  |  |  |  |  |  | #  Apache locations (and thus WebDyne::Chain) handlers for the same | 
| 194 |  |  |  |  |  |  | #  physical file.  So we now use an md5 hash of handler, location and | 
| 195 |  |  |  |  |  |  | #  file name, but the var name is still "inode"; | 
| 196 |  |  |  |  |  |  | # | 
| 197 |  |  |  |  |  |  | RENDER_BEGIN: | 
| 198 |  |  |  |  |  |  | my $srce_inode=( | 
| 199 | 10 |  | 50 |  |  | 164 | $self->{'_inode'} ||= md5_hex(ref($self), $r->location, $srce_pn) | 
|  |  |  | 33 |  |  |  |  | 
| 200 |  |  |  |  |  |  | || | 
| 201 |  |  |  |  |  |  | return $self->err_html("could not get md5 for file $srce_pn, $!")); | 
| 202 | 10 |  |  |  |  | 19 | 0 && debug("srce_inode $srce_inode"); | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | #  Var to hold pointer to cached metadata area, so we are not constantly | 
| 206 |  |  |  |  |  |  | #  dereferencing $Package{'_cache'}{$srce_inode}; | 
| 207 |  |  |  |  |  |  | # | 
| 208 |  |  |  |  |  |  | my $cache_inode_hr=( | 
| 209 | 10 |  | 50 |  |  | 145 | $Package{'_cache'}{$srce_inode} ||= { | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | data  => undef,    # holds compiled representation of html/psp file | 
| 212 |  |  |  |  |  |  | mtime => undef,    # last modified time of the Storable disk cache file | 
| 213 |  |  |  |  |  |  | nrun  => undef,    # number of times this page run by this mod_perl child | 
| 214 |  |  |  |  |  |  | lrun  => undef,    # last run time of this page by this mod_perl child | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | # Created if needed | 
| 217 |  |  |  |  |  |  | # | 
| 218 |  |  |  |  |  |  | # meta       =>  undef,  # page meta data, held in meta section or supplied by add-on modules | 
| 219 |  |  |  |  |  |  | # eval_cr    =>  undef,  # where anonymous sub's representing eval'd perl code within this page are held | 
| 220 |  |  |  |  |  |  | # perl_init  =>  undef,  # flags that perl code in __PERL__ block has been init'd (run once at page load) | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | }) || return $self->err_html('unable to initialize cache_inode_hr ref'); | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | #  Get "effective" source mtime, as may be a combination of things including | 
| 226 |  |  |  |  |  |  | #  template (eg menu) mtime. Here so can be subclassed by other handler like | 
| 227 |  |  |  |  |  |  | #  menu systems | 
| 228 |  |  |  |  |  |  | # | 
| 229 | 10 |  |  |  |  | 17 | 0 && debug("about to call source_mtime, self $self"); | 
| 230 |  |  |  |  |  |  | $srce_mtime=${ | 
| 231 | 10 |  | 33 |  |  | 18 | $self->source_mtime($srce_mtime) || return $self->err_html()} | 
| 232 |  |  |  |  |  |  | || $srce_mtime; | 
| 233 | 10 |  |  |  |  | 17 | 0 && debug("srce_pn $srce_pn, srce_mtime (computed) $srce_mtime"); | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | #  Need to stat cache file mtime in case another process has updated it (ie via self->cache_compile(1)) call, | 
| 237 |  |  |  |  |  |  | #  which will make our memory cache stale. Would like to not have to do this stat one day, perhaps via shmem | 
| 238 |  |  |  |  |  |  | #  or similar check | 
| 239 |  |  |  |  |  |  | # | 
| 240 |  |  |  |  |  |  | #  Only do if cache directory defined | 
| 241 |  |  |  |  |  |  | # | 
| 242 | 10 |  |  |  |  | 18 | my ($cache_pn, $cache_mtime); | 
| 243 | 10 | 50 |  |  |  | 27 | if ($WEBDYNE_CACHE_DN) { | 
| 244 | 0 |  |  |  |  | 0 | 0 && debug("webdyne_cache_dn $WEBDYNE_CACHE_DN"); | 
| 245 | 0 |  |  |  |  | 0 | $cache_pn=File::Spec->catfile($WEBDYNE_CACHE_DN, $srce_inode); | 
| 246 | 0 |  | 0 |  |  | 0 | $cache_mtime=((-f $cache_pn) && (stat(_))[9]); | 
| 247 |  |  |  |  |  |  | } | 
| 248 |  |  |  |  |  |  | else { | 
| 249 | 10 |  |  |  |  | 21 | 0 && debug('no webdyne_cache_dn'); | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | #  Test if compile/reload needed | 
| 254 |  |  |  |  |  |  | # | 
| 255 | 10 | 50 | 33 |  |  | 94 | if ($WEBDYNE_RELOAD || $self->{'_compile'} || ($cache_inode_hr->{'mtime'} < $srce_mtime) || ($cache_mtime > $cache_inode_hr->{'mtime'})) { | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | #  Debug | 
| 259 |  |  |  |  |  |  | # | 
| 260 |  |  |  |  |  |  | 0 && debug( | 
| 261 |  |  |  |  |  |  | "compile/reload needed _compile %s, cache_inode_hr mtime %s, srce_mtime $srce_mtime, WEBDYNE::RELOAD $WEBDYNE::RELOAD", | 
| 262 | 10 |  |  |  |  | 16 | $self->{'_compile'}, $cache_inode_hr->{'mtime'}); | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | #  use Module::Reload to reload modules | 
| 266 |  |  |  |  |  |  | # | 
| 267 | 10 | 50 |  |  |  | 28 | if ($WEBDYNE_RELOAD) { | 
| 268 | 0 |  |  |  |  | 0 | local $SIG{'__DIE__'}; | 
| 269 | 0 | 0 |  |  |  | 0 | unless ($INC{'Module/Reload.pm'}) { | 
| 270 | 0 |  |  |  |  | 0 | 0 && debug('loading Module::Reload'); | 
| 271 | 0 |  |  |  |  | 0 | eval {require Module::Reload}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 272 | 0 | 0 |  |  |  | 0 | return $self->err_html('unable to load Module::Reload - is it installed ?') if $@; | 
| 273 |  |  |  |  |  |  | } | 
| 274 | 0 |  |  |  |  | 0 | 0 && debug('running Module::Reload->check'); | 
| 275 | 0 |  |  |  |  | 0 | Module::Reload->check(); | 
| 276 |  |  |  |  |  |  | } | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | #  Null out cache_inode to clear any flags | 
| 280 |  |  |  |  |  |  | # | 
| 281 | 10 |  |  |  |  | 17 | foreach my $key (keys %{$cache_inode_hr}) { | 
|  | 10 |  |  |  |  | 69 |  | 
| 282 | 40 |  |  |  |  | 61 | $cache_inode_hr->{$key}=undef; | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | #  Try to clear/reset package name space if possible | 
| 287 |  |  |  |  |  |  | # | 
| 288 |  |  |  |  |  |  | eval { | 
| 289 | 10 |  |  |  |  | 70 | require Symbol; | 
| 290 | 10 |  |  |  |  | 90 | &Symbol::delete_package("WebDyne::${srce_inode}"); | 
| 291 | 10 | 50 |  |  |  | 22 | } || do { | 
| 292 | 10 | 50 |  |  |  | 352 | eval {undef} if $@;    #clear $@ after error above | 
|  | 0 |  |  |  |  | 0 |  | 
| 293 | 10 |  |  |  |  | 20 | my $stash_hr=*{"WebDyne::${srce_inode}::"}{HASH}; | 
|  | 10 |  |  |  |  | 132 |  | 
| 294 | 10 |  |  |  |  | 20 | foreach (keys %{$stash_hr}) { | 
|  | 10 |  |  |  |  | 44 |  | 
| 295 | 0 |  |  |  |  | 0 | undef *{"WebDyne::${srce_inode}::${_}"}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 296 |  |  |  |  |  |  | } | 
| 297 | 10 |  |  |  |  | 19 | %{$stash_hr}=(); | 
|  | 10 |  |  |  |  | 15 |  | 
| 298 | 10 |  |  |  |  | 30 | delete *WebDyne::{'HASH'}->{$srce_inode}; | 
| 299 |  |  |  |  |  |  | }; | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | #  Debug | 
| 303 |  |  |  |  |  |  | # | 
| 304 | 10 |  |  |  |  | 16 | 0 && debug("srce_pn $srce_pn, cache_pn $cache_pn, mtime $cache_mtime"); | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  |  | 
| 307 | 10 |  |  |  |  | 20 | my $container_ar; | 
| 308 | 10 | 50 | 33 |  |  | 75 | if ($self->{'_compile'} || ($cache_mtime < $srce_mtime)) { | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | #  Debug | 
| 312 |  |  |  |  |  |  | # | 
| 313 | 10 |  |  |  |  | 13 | 0 && debug("compiling srce: $srce_pn, dest $cache_pn"); | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | #  Recompile from source | 
| 317 |  |  |  |  |  |  | # | 
| 318 | 10 | 50 | 0 |  |  | 19 | eval {require WebDyne::Compile} | 
|  | 10 |  |  |  |  | 672 |  | 
| 319 |  |  |  |  |  |  | || return $self->err_html( | 
| 320 |  |  |  |  |  |  | errsubst('unable to load WebDyne:Compile, %s', $@ || 'undefined error')); | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | #  Source newer than compiled version, must recompile file | 
| 324 |  |  |  |  |  |  | # | 
| 325 | 10 |  | 50 |  |  | 107 | $container_ar=$self->compile( | 
| 326 |  |  |  |  |  |  | { | 
| 327 |  |  |  |  |  |  |  | 
| 328 |  |  |  |  |  |  | srce => $srce_pn, | 
| 329 |  |  |  |  |  |  | dest => $cache_pn, | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | }) || return $self->err_html(); | 
| 332 |  |  |  |  |  |  |  | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | #  Check for any unhandled errors during compile | 
| 335 |  |  |  |  |  |  | # | 
| 336 | 10 | 50 |  |  |  | 70 | errstr() && return $self->err_html(); | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | #  Update mtime flag, or use current time if we were not able to read | 
| 340 |  |  |  |  |  |  | #  cache file (probably because temp dir was not writable - which would | 
| 341 |  |  |  |  |  |  | #  generated a warning in the logs from the Compile module, so no point | 
| 342 |  |  |  |  |  |  | #  making a fuss about it here anymore. | 
| 343 |  |  |  |  |  |  | # | 
| 344 | 10 | 50 |  |  |  | 23 | $cache_mtime=(stat($cache_pn))[9] if $cache_pn;    # || | 
| 345 |  |  |  |  |  |  | #return $self->err_html("could not stat cache file '$cache_pn'"); | 
| 346 | 10 |  | 33 |  |  | 61 | $cache_inode_hr->{'mtime'}=$cache_mtime || time(); | 
| 347 |  |  |  |  |  |  |  | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | } | 
| 350 |  |  |  |  |  |  | else { | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | #  Debug | 
| 353 |  |  |  |  |  |  | # | 
| 354 | 0 |  |  |  |  | 0 | 0 && debug("loading from disk cache"); | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | #  Load from storeable file | 
| 358 |  |  |  |  |  |  | # | 
| 359 | 0 |  | 0 |  |  | 0 | $container_ar=Storable::lock_retrieve($cache_pn) || | 
| 360 |  |  |  |  |  |  | return $self->err_html("Storable error when retreiveing cached file '$cache_pn', $!"); | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  |  | 
| 363 |  |  |  |  |  |  | #  Update mtime flag | 
| 364 |  |  |  |  |  |  | # | 
| 365 | 0 |  |  |  |  | 0 | $cache_inode_hr->{'mtime'}=$cache_mtime; | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | #  Re-run perl-init for this node. Not done above because handled in compile if needed | 
| 369 |  |  |  |  |  |  | # | 
| 370 | 0 | 0 |  |  |  | 0 | if (my $meta_hr=$container_ar->[0]) { | 
| 371 | 0 | 0 |  |  |  | 0 | if (my $perl_ar=$meta_hr->{'perl'}) { | 
| 372 | 0 |  | 0 |  |  | 0 | my $perl_debug_ar=$meta_hr->{'perl_debug'} || | 
| 373 |  |  |  |  |  |  | return err ('unable to load perl_debug array reference'); | 
| 374 | 0 | 0 |  |  |  | 0 | $self->perl_init($perl_ar, $perl_debug_ar) || return $self->err_html(); | 
| 375 |  |  |  |  |  |  | } | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  | } | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  |  | 
| 380 |  |  |  |  |  |  | #  Done, install into memory cache | 
| 381 |  |  |  |  |  |  | # | 
| 382 | 10 | 50 | 33 |  |  | 71 | if (my $meta_hr=$container_ar->[0] and $cache_inode_hr->{'meta'}) { | 
|  |  | 50 |  |  |  |  |  | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | #  Need to merge meta info | 
| 385 |  |  |  |  |  |  | # | 
| 386 | 0 |  | 0 |  |  | 0 | foreach (keys %{$meta_hr}) {$cache_inode_hr->{'meta'}{$_} ||= $meta_hr->{$_}} | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 387 |  |  |  |  |  |  |  | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  | elsif ($meta_hr) { | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | #  No merge - just use from container | 
| 392 |  |  |  |  |  |  | # | 
| 393 | 10 |  |  |  |  | 29 | $cache_inode_hr->{'meta'}=$meta_hr; | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | } | 
| 396 | 10 |  |  |  |  | 18 | $cache_inode_hr->{'data'}=$container_ar->[1]; | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | #  Corner case. Delete _CGI if WEBDYNE_CGI_EXPAND_PARAM set to force re-read of | 
| 399 |  |  |  |  |  |  | #  CGI params in case was set in  section - which means would not be seen | 
| 400 |  |  |  |  |  |  | #  early enough. Will only happen after first compile, so no major performance | 
| 401 |  |  |  |  |  |  | #  impact on CGI object recreation | 
| 402 |  |  |  |  |  |  | # | 
| 403 |  |  |  |  |  |  | #  Update: Re-init rather than delete or WebDyne::State worn't work | 
| 404 |  |  |  |  |  |  | # | 
| 405 |  |  |  |  |  |  | #delete $self->{'_CGI'} if $WEBDYNE_CGI_PARAM_EXPAND; | 
| 406 | 10 | 50 | 33 |  |  | 38 | if ((my $cgi_or=$self->{'_CGI'}) && $WEBDYNE_CGI_PARAM_EXPAND) { | 
| 407 | 10 |  |  |  |  | 48 | $cgi_or->init(); | 
| 408 |  |  |  |  |  |  | } | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | } | 
| 412 |  |  |  |  |  |  | else { | 
| 413 |  |  |  |  |  |  |  | 
| 414 | 0 |  |  |  |  | 0 | 0 && debug('no compile or disk cache fetch needed - getting from memory cache'); | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | } | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  |  | 
| 419 |  |  |  |  |  |  | #  Separate meta and actual data into separate vars for ease of use | 
| 420 |  |  |  |  |  |  | # | 
| 421 | 10 |  |  |  |  | 2441 | my ($meta_hr, $data_ar)=@{$cache_inode_hr}{qw(meta data)}; | 
|  | 10 |  |  |  |  | 32 |  | 
| 422 | 10 |  |  |  |  | 15 | 0 && debug('meta_hr %s, ', Dumper($meta_hr)); | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  | #  Custom handler ? | 
| 426 |  |  |  |  |  |  | # | 
| 427 | 10 | 50 | 33 |  |  | 68 | if (my $handler_ar=$meta_hr->{'handler'} || $r->dir_config('WebDyneHandler')) { | 
| 428 | 0 | 0 |  |  |  | 0 | my ($handler, $handler_param_hr)=ref($handler_ar) ? @{$handler_ar} : $handler_ar; | 
|  | 0 |  |  |  |  | 0 |  | 
| 429 | 0 | 0 |  |  |  | 0 | if (ref($self) ne $handler) { | 
| 430 | 0 |  |  |  |  | 0 | 0 && debug("passing to custom handler '$handler', param %s", Dumper($handler_param_hr)); | 
| 431 | 0 | 0 |  |  |  | 0 | unless ($Package{'_handler_load'}{$handler}) { | 
| 432 | 0 |  |  |  |  | 0 | 0 && debug("need to load handler '$handler' -  trying"); | 
| 433 | 0 |  |  |  |  | 0 | (my $handler_fn=$handler)=~s/::/\//g; | 
| 434 | 0 |  |  |  |  | 0 | $handler_fn.='.pm'; | 
| 435 | 0 | 0 |  |  |  | 0 | eval {require $handler_fn} || | 
|  | 0 |  |  |  |  | 0 |  | 
| 436 |  |  |  |  |  |  | return $self->err_html("unable to load custom handler '$handler', $@"); | 
| 437 | 0 | 0 |  |  |  | 0 | UNIVERSAL::can($handler, 'handler') || | 
| 438 |  |  |  |  |  |  | return $self->err_html("custom handler '$handler' does not seem to have a 'handler' method to call"); | 
| 439 | 0 |  |  |  |  | 0 | 0 && debug('loaded OK'); | 
| 440 | 0 |  |  |  |  | 0 | $Package{'_handler_load'}{$handler}++; | 
| 441 |  |  |  |  |  |  | } | 
| 442 | 0 |  |  |  |  | 0 | my %handler_param_hr=(%{$param_hr}, %{$handler_param_hr}, meta => $meta_hr); | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 443 | 0 |  |  |  |  | 0 | bless $self, $handler; | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  | #  Force recalc of inode in next handler so recompile done | 
| 446 | 0 |  |  |  |  | 0 | delete $self->{'_inode'}; | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | #  Add meta-data. Something inefficient here, why supplying as handler param and | 
| 449 |  |  |  |  |  |  | #  self attrib ? If don't do it Fake/FastCGI request handler breaks but Apache does | 
| 450 |  |  |  |  |  |  | #  not ? | 
| 451 | 0 |  |  |  |  | 0 | $self->{'_meta_hr'}=$meta_hr; | 
| 452 | 0 |  |  |  |  | 0 | return &{"${handler}::handler"}($self, $r, \%handler_param_hr); | 
|  | 0 |  |  |  |  | 0 |  | 
| 453 |  |  |  |  |  |  | } | 
| 454 |  |  |  |  |  |  | } | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  | #  Contain cache code ? | 
| 458 |  |  |  |  |  |  | # | 
| 459 | 10 | 50 | 33 |  |  | 60 | if ((my $cache=($self->{'_cache'} || $meta_hr->{'cache'})) && !$self->{'_cache_run_fg'}++) { | 
|  |  |  | 33 |  |  |  |  | 
| 460 | 0 |  |  |  |  | 0 | 0 && debug("found cache routine $cache, adding to inode $srce_inode"); | 
| 461 | 0 |  |  |  |  | 0 | my $cache_inode; | 
| 462 | 0 |  |  |  |  | 0 | my $eval_cr=$Package{'_eval_cr'}{'!'}; | 
| 463 | 0 | 0 |  |  |  | 0 | if (ref($cache) eq 'CODE') { | 
| 464 | 0 |  |  |  |  | 0 | my %param=( | 
| 465 |  |  |  |  |  |  | cache_cr   => $cache, | 
| 466 |  |  |  |  |  |  | srce_inode => $srce_inode | 
| 467 |  |  |  |  |  |  | ); | 
| 468 |  |  |  |  |  |  | $cache_inode=${ | 
| 469 | 0 | 0 | 0 |  |  | 0 | $eval_cr->($self, undef, \%param, q[$_[1]->{'cache_cr'}->($_[0], $_[1]->{'srce_inode'})], 0) || | 
|  | 0 |  |  |  |  | 0 |  | 
| 470 |  |  |  |  |  |  | return $self->err_html( | 
| 471 |  |  |  |  |  |  | errsubst( | 
| 472 |  |  |  |  |  |  | 'error in cache code: %s', errstr() || $@ || 'no inode returned' | 
| 473 |  |  |  |  |  |  | )); | 
| 474 |  |  |  |  |  |  | } | 
| 475 |  |  |  |  |  |  | } | 
| 476 |  |  |  |  |  |  | else { | 
| 477 |  |  |  |  |  |  | $cache_inode=${ | 
| 478 | 0 | 0 | 0 |  |  | 0 | $eval_cr->($self, undef, $srce_inode, $cache, 0) || | 
|  | 0 |  |  |  |  | 0 |  | 
| 479 |  |  |  |  |  |  | return $self->err_html( | 
| 480 |  |  |  |  |  |  | errsubst( | 
| 481 |  |  |  |  |  |  | 'error in cache code: %s', errstr() || $@ || 'no inode returned' | 
| 482 |  |  |  |  |  |  | )); | 
| 483 |  |  |  |  |  |  | } | 
| 484 |  |  |  |  |  |  | } | 
| 485 | 0 | 0 |  |  |  | 0 | $cache_inode=$cache_inode ? md5_hex($srce_inode, $cache_inode) : $self->{'_inode'}; | 
| 486 |  |  |  |  |  |  |  | 
| 487 |  |  |  |  |  |  | #  Will probably make inodes with algorithm below some day so we can implement a "maxfiles type limit on | 
| 488 |  |  |  |  |  |  | #  the number of cache files generated. Not today though .. | 
| 489 |  |  |  |  |  |  | # | 
| 490 |  |  |  |  |  |  | #$cache_inode=$cache_inode ? $srce_inode .'_'. md5_hex($cache_inode) : $self->{'_inode'}; | 
| 491 | 0 |  |  |  |  | 0 | 0 && debug("cache inode $cache_inode, compile %s", $self->{'_compile'}); | 
| 492 |  |  |  |  |  |  |  | 
| 493 | 0 | 0 | 0 |  |  | 0 | if (($cache_inode ne $srce_inode) || $self->{'_compile'}) { | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | #  Using a cache file, different inode. | 
| 496 |  |  |  |  |  |  | # | 
| 497 | 0 |  |  |  |  | 0 | 0 && debug("goto RENDER_BEGIN, inode node was $srce_inode, now $cache_inode"); | 
| 498 | 0 |  |  |  |  | 0 | $self->{'_inode'}=$cache_inode; | 
| 499 | 0 |  |  |  |  | 0 | goto RENDER_BEGIN; | 
| 500 |  |  |  |  |  |  |  | 
| 501 |  |  |  |  |  |  | #return &handler($self,$r,$param_hr); #should work instead of goto for pendants | 
| 502 |  |  |  |  |  |  | } | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | } | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  |  | 
| 507 |  |  |  |  |  |  | #  Is it plain HTML which can be/is pre-rendered and stored on disk ? Note to self, leave here - should | 
| 508 |  |  |  |  |  |  | #  run after any cache code is run, as that may change inode. | 
| 509 |  |  |  |  |  |  | # | 
| 510 | 10 |  |  |  |  | 21 | my $html_sr; | 
| 511 | 10 | 100 | 66 |  |  | 68 | if ($self->{'_static'} || ($meta_hr && ($meta_hr->{'html'} || $meta_hr->{'static'}))) { | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 512 |  |  |  |  |  |  |  | 
| 513 |  |  |  |  |  |  | #my $cache_pn=File::Spec->catfile($WEBDYNE_CACHE_DN, $srce_inode); | 
| 514 | 1 | 50 | 33 |  |  | 8 | if ($cache_pn && (-f (my $fn="${cache_pn}.html")) && ((stat(_))[9] >= $srce_mtime) && !$self->{'_compile'}) { | 
|  |  | 50 | 33 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 515 |  |  |  |  |  |  |  | 
| 516 |  |  |  |  |  |  | #  Cache file exists, and is not stale, and user/cache code does not want a recompile. Tell Apache or FCGI | 
| 517 |  |  |  |  |  |  | #  to serve it up directly. | 
| 518 |  |  |  |  |  |  | # | 
| 519 | 0 |  |  |  |  | 0 | 0 && debug("returning pre-rendered file ${cache_pn}.html"); | 
| 520 | 0 | 0 | 0 |  |  | 0 | if ($MP2 || $ENV{'FCGI_ROLE'}) { | 
| 521 |  |  |  |  |  |  |  | 
| 522 |  |  |  |  |  |  | #  Do this way for mod_perl2, FCGI. Note to self need r->output_filter or | 
| 523 |  |  |  |  |  |  | #  Apache 2 seems to add junk characters at end of output | 
| 524 |  |  |  |  |  |  | # | 
| 525 | 0 |  |  |  |  | 0 | my $r_child=$r->lookup_file($fn, $r->output_filters); | 
| 526 | 0 |  |  |  |  | 0 | $r_child->handler('default-handler'); | 
| 527 | 0 |  |  |  |  | 0 | $r_child->content_type($WEBDYNE_CONTENT_TYPE_HTML); | 
| 528 |  |  |  |  |  |  |  | 
| 529 |  |  |  |  |  |  | #  Apache bug ? Need to set content type on r also | 
| 530 | 0 |  |  |  |  | 0 | $r->content_type($WEBDYNE_CONTENT_TYPE_HTML); | 
| 531 | 0 |  |  |  |  | 0 | return $r_child->run(); | 
| 532 |  |  |  |  |  |  |  | 
| 533 |  |  |  |  |  |  | } | 
| 534 |  |  |  |  |  |  | else { | 
| 535 |  |  |  |  |  |  |  | 
| 536 |  |  |  |  |  |  | #  This way for older versions of Apache, other request handlers | 
| 537 |  |  |  |  |  |  | # | 
| 538 | 0 |  |  |  |  | 0 | $r->filename($fn); | 
| 539 | 0 |  |  |  |  | 0 | $r->handler('default-handler'); | 
| 540 | 0 |  |  |  |  | 0 | $r->content_type($WEBDYNE_CONTENT_TYPE_HTML); | 
| 541 | 0 |  |  |  |  | 0 | return &Apache::DECLINED; | 
| 542 |  |  |  |  |  |  | } | 
| 543 |  |  |  |  |  |  | } | 
| 544 |  |  |  |  |  |  | elsif ($cache_pn) { | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | #  Cache file defined, but out of date of non-existant. Register callback handler to write HTML output | 
| 547 |  |  |  |  |  |  | #  after render complete | 
| 548 |  |  |  |  |  |  | # | 
| 549 | 0 |  |  |  |  | 0 | 0 && debug('storing to disk cache html %s', \$data_ar->[0]); | 
| 550 |  |  |  |  |  |  | my $cr=sub { | 
| 551 |  |  |  |  |  |  | &cache_html( | 
| 552 | 0 | 0 | 0 | 0 |  | 0 | "${cache_pn}.html", ($meta_hr->{'static'} || $self->{'_static'}) ? $html_sr : \$data_ar->[0]) | 
| 553 | 0 |  |  |  |  | 0 | }; | 
| 554 | 0 | 0 |  |  |  | 0 | $MP2 ? $r->pool->cleanup_register($cr) : $r->register_cleanup($cr); | 
| 555 |  |  |  |  |  |  | } | 
| 556 |  |  |  |  |  |  | else { | 
| 557 |  |  |  |  |  |  |  | 
| 558 |  |  |  |  |  |  | #  No cache directory, store in memory cache. Each apache process will get a different version, but will | 
| 559 |  |  |  |  |  |  | #  at least still be only compiled once for each version. | 
| 560 |  |  |  |  |  |  | # | 
| 561 | 1 |  |  |  |  | 3 | 0 && debug('storing to memory cache html %s', \$data_ar->[0]); | 
| 562 |  |  |  |  |  |  | my $cr=sub { | 
| 563 |  |  |  |  |  |  | $cache_inode_hr->{'data'}=[ | 
| 564 | 1 | 50 | 33 | 1 |  | 9 | ($meta_hr->{'static'} || $self->{'_static'}) ? ${$html_sr} : $data_ar->[0]] | 
|  | 0 |  |  |  |  | 0 |  | 
| 565 | 1 |  |  |  |  | 7 | }; | 
| 566 | 1 | 50 |  |  |  | 7 | $MP2 ? $r->pool->cleanup_register($cr) : $r->register_cleanup($cr); | 
| 567 |  |  |  |  |  |  | } | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  | } | 
| 570 |  |  |  |  |  |  |  | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | #  Debug | 
| 573 |  |  |  |  |  |  | # | 
| 574 |  |  |  |  |  |  | #0 && debug('about to render'); | 
| 575 |  |  |  |  |  |  |  | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | #  Set default content type to text/html, can be overridden by render code if needed | 
| 578 |  |  |  |  |  |  | # | 
| 579 |  |  |  |  |  |  | #$r->content_type('text/html'); | 
| 580 | 10 |  |  |  |  | 63 | $r->content_type($WEBDYNE_CONTENT_TYPE_HTML); | 
| 581 |  |  |  |  |  |  |  | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | #  Redirect 'print' function to our own routine for later output | 
| 584 |  |  |  |  |  |  | # | 
| 585 | 10 |  | 33 |  |  | 62 | my $select=($self->{'_select'} ||= CORE::select()); | 
| 586 | 10 |  |  |  |  | 22 | 0 && debug("select handle is currently $select, changing to *WEBDYNE"); | 
| 587 | 10 | 50 |  |  |  | 97 | tie(*WEBDYNE, 'WebDyne::TieHandle', $self) || | 
| 588 |  |  |  |  |  |  | return $self->err_html("unable to tie output to 'WebDyne::TieHandle', $!"); | 
| 589 | 10 | 50 |  |  |  | 32 | CORE::select WEBDYNE if $select; | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  |  | 
| 592 |  |  |  |  |  |  | #  Get the actual html. The main event - convert data_ar to html | 
| 593 |  |  |  |  |  |  | # | 
| 594 | 10 |  | 33 |  |  | 82 | $html_sr=$self->render({data => $data_ar, param => $param_hr}) || do { | 
| 595 |  |  |  |  |  |  |  | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | #  Our render routine returned an error. Debug | 
| 598 |  |  |  |  |  |  | # | 
| 599 |  |  |  |  |  |  | RENDER_ERROR: | 
| 600 |  |  |  |  |  |  | 0 && debug("render error $r, select $select"); | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  |  | 
| 603 |  |  |  |  |  |  | #  Return error | 
| 604 |  |  |  |  |  |  | # | 
| 605 |  |  |  |  |  |  | 0 && debug("selecting back to $select for error"); | 
| 606 |  |  |  |  |  |  | CORE::select $select if $select; | 
| 607 |  |  |  |  |  |  | untie *WEBDYNE; | 
| 608 |  |  |  |  |  |  | return $self->err_html(); | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  |  | 
| 611 |  |  |  |  |  |  | }; | 
| 612 |  |  |  |  |  |  |  | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | #  Done with STDOUT redirect | 
| 615 |  |  |  |  |  |  | # | 
| 616 | 10 |  |  |  |  | 20 | 0 && debug("selecting back to $select"); | 
| 617 | 10 | 50 |  |  |  | 64 | CORE::select $select if $select; | 
| 618 | 10 |  |  |  |  | 46 | untie *WEBDYNE; | 
| 619 |  |  |  |  |  |  |  | 
| 620 |  |  |  |  |  |  |  | 
| 621 |  |  |  |  |  |  | #  Check for any unhandled errors during render - render may have returned OK, but | 
| 622 |  |  |  |  |  |  | #  maybe an error occurred along the way that was not passed back .. | 
| 623 |  |  |  |  |  |  | # | 
| 624 | 10 |  |  |  |  | 16 | 0 && debug('errstr after render %s', errstr()); | 
| 625 | 10 | 50 |  |  |  | 32 | errstr() && return $self->err_html(); | 
| 626 | 10 | 50 |  |  |  | 31 | &CGI::cgi_error() && return $self->err_html(&CGI::cgi_error()); | 
| 627 |  |  |  |  |  |  |  | 
| 628 |  |  |  |  |  |  |  | 
| 629 |  |  |  |  |  |  | #  Check for any blocks that user wanted rendered but were | 
| 630 |  |  |  |  |  |  | #  not present anywhere | 
| 631 |  |  |  |  |  |  | # | 
| 632 |  |  |  |  |  |  | #if ($WEBDYNE_DELAYED_BLOCK_RENDER && (my $block_param_hr=delete $self->{'_block_param'})) { | 
| 633 | 10 | 100 |  |  |  | 410 | if (my $block_param_hr=delete $self->{'_block_param'}) { | 
| 634 | 1 |  |  |  |  | 3 | my @block_error; | 
| 635 | 1 |  |  |  |  | 3 | foreach my $block_name (keys %{$block_param_hr}) { | 
|  | 1 |  |  |  |  | 10 |  | 
| 636 | 4 | 50 |  |  |  | 15 | unless (exists $self->{'_block_render'}{$block_name}) { | 
| 637 | 0 |  |  |  |  | 0 | push @block_error, $block_name; | 
| 638 |  |  |  |  |  |  | } | 
| 639 |  |  |  |  |  |  | } | 
| 640 | 1 | 50 |  |  |  | 5 | if (@block_error) { | 
| 641 | 0 |  |  |  |  | 0 | 0 && debug('found un-rendered blocks %s', Dumper(\@block_error)); | 
| 642 |  |  |  |  |  |  | return $self->err_html( | 
| 643 | 0 |  |  |  |  | 0 | err ('unable to locate block(s) %s for render', join(', ', map {"'$_'"} @block_error))) | 
|  | 0 |  |  |  |  | 0 |  | 
| 644 |  |  |  |  |  |  | } | 
| 645 |  |  |  |  |  |  | } | 
| 646 |  |  |  |  |  |  |  | 
| 647 |  |  |  |  |  |  |  | 
| 648 |  |  |  |  |  |  | #  If no error, status must be ok unless otherwise set | 
| 649 |  |  |  |  |  |  | # | 
| 650 | 10 | 50 |  |  |  | 74 | $r->status(RC_OK) unless $r->status(); | 
| 651 | 10 |  |  |  |  | 19 | 0 && debug('r status set, %s', $r->status()); | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  |  | 
| 654 |  |  |  |  |  |  | #  Formulate header, calc length of return. | 
| 655 |  |  |  |  |  |  | # | 
| 656 |  |  |  |  |  |  | #  Modify to remove error checking - WebDyne::FakeRequest does not supply | 
| 657 |  |  |  |  |  |  | #  hash ref, so error generated. No real need to check | 
| 658 |  |  |  |  |  |  | # | 
| 659 | 10 |  |  |  |  | 32 | my $header_out_hr=$r->headers_out();    # || return err(); | 
| 660 |  |  |  |  |  |  | my %header_out=( | 
| 661 |  |  |  |  |  |  |  | 
| 662 | 10 |  |  |  |  | 122 | 'Content-Length' => length ${$html_sr}, | 
| 663 |  |  |  |  |  |  |  | 
| 664 | 10 |  | 33 |  |  | 16 | ($meta_hr->{'no_cache'} || $WEBDYNE_NO_CACHE) && ( | 
| 665 |  |  |  |  |  |  | 'Cache-Control' => 'no-cache', | 
| 666 |  |  |  |  |  |  | 'Pragma'        => 'no-cache', | 
| 667 |  |  |  |  |  |  | 'Expires'       => '-5' | 
| 668 |  |  |  |  |  |  | ) | 
| 669 |  |  |  |  |  |  |  | 
| 670 |  |  |  |  |  |  | ); | 
| 671 | 10 |  |  |  |  | 35 | foreach (keys %header_out) {$header_out_hr->{$_}=$header_out{$_}} | 
|  | 40 |  |  |  |  | 63 |  | 
| 672 |  |  |  |  |  |  |  | 
| 673 |  |  |  |  |  |  |  | 
| 674 |  |  |  |  |  |  | #  Debug | 
| 675 |  |  |  |  |  |  | # | 
| 676 | 10 |  |  |  |  | 15 | 0 && debug('sending header'); | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  |  | 
| 679 |  |  |  |  |  |  | #  Send header | 
| 680 |  |  |  |  |  |  | # | 
| 681 | 10 | 50 |  |  |  | 49 | $r->send_http_header() if !$MP2; | 
| 682 |  |  |  |  |  |  |  | 
| 683 |  |  |  |  |  |  |  | 
| 684 |  |  |  |  |  |  | #  Print. Commented out version only seems to work in Apache 1/mod_perl1 | 
| 685 |  |  |  |  |  |  | # | 
| 686 |  |  |  |  |  |  | #$r->print($html_sr); | 
| 687 | 10 | 50 |  |  |  | 47 | $MP2 ? $r->print(${$html_sr}) : $r->print($html_sr); | 
|  | 0 |  |  |  |  | 0 |  | 
| 688 |  |  |  |  |  |  |  | 
| 689 |  |  |  |  |  |  |  | 
| 690 |  |  |  |  |  |  | #  Work out the form render time, log | 
| 691 |  |  |  |  |  |  | # | 
| 692 | 10 |  |  |  |  | 98 | RENDER_COMPLETE: | 
| 693 |  |  |  |  |  |  | my $time_render=sprintf('%0.4f', time()-$time); | 
| 694 | 10 |  |  |  |  | 16 | 0 && debug("form $srce_pn render time $time_render"); | 
| 695 |  |  |  |  |  |  |  | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | #  Do we need to do house cleaning on cache after this run ? If so | 
| 698 |  |  |  |  |  |  | #  add a perl handler to do it after we finish | 
| 699 |  |  |  |  |  |  | # | 
| 700 | 10 | 50 | 33 |  |  | 62 | if ( | 
|  |  | 50 | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 701 |  |  |  |  |  |  | $WEBDYNE_CACHE_CHECK_FREQ | 
| 702 |  |  |  |  |  |  | && | 
| 703 |  |  |  |  |  |  | ($r eq ($r->main() || $r)) && | 
| 704 |  |  |  |  |  |  | !((my $nrun=++$Package{'_nrun'}) % $WEBDYNE_CACHE_CHECK_FREQ) | 
| 705 |  |  |  |  |  |  | ) { | 
| 706 |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  |  | 
| 708 |  |  |  |  |  |  | #  Debug | 
| 709 |  |  |  |  |  |  | # | 
| 710 | 0 |  |  |  |  | 0 | 0 && debug("run $nrun times, scheduling cache clean"); | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  |  | 
| 713 |  |  |  |  |  |  | #  Yes, we need to clean cache after finished | 
| 714 |  |  |  |  |  |  | # | 
| 715 | 0 |  |  | 0 |  | 0 | my $cr=sub {&cache_clean($Package{'_cache'})}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 716 | 0 | 0 |  |  |  | 0 | $MP2 ? $r->pool->cleanup_register($cr) : $r->register_cleanup($cr); | 
| 717 |  |  |  |  |  |  |  | 
| 718 |  |  |  |  |  |  |  | 
| 719 |  |  |  |  |  |  | #  Used to be sub { $self->cache_clean() }, but for some reason this | 
| 720 |  |  |  |  |  |  | #  made httpd peg at 100% CPU usage after cleanup. Removing $self ref | 
| 721 |  |  |  |  |  |  | #  fixed. | 
| 722 |  |  |  |  |  |  | # | 
| 723 |  |  |  |  |  |  |  | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | } | 
| 726 |  |  |  |  |  |  | elsif ($WEBDYNE_CACHE_CHECK_FREQ) { | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  | #  Only bother to update counters if we are checking cache periodically | 
| 729 |  |  |  |  |  |  | # | 
| 730 |  |  |  |  |  |  |  | 
| 731 |  |  |  |  |  |  |  | 
| 732 |  |  |  |  |  |  | #  Update cache script frequency used, time used indicators, nrun=number | 
| 733 |  |  |  |  |  |  | #  of runs, lrun=last run time | 
| 734 |  |  |  |  |  |  | # | 
| 735 | 10 |  |  |  |  | 20 | $cache_inode_hr->{'nrun'}++; | 
| 736 | 10 |  |  |  |  | 22 | $cache_inode_hr->{'lrun'}=time(); | 
| 737 |  |  |  |  |  |  |  | 
| 738 |  |  |  |  |  |  | } | 
| 739 |  |  |  |  |  |  | else { | 
| 740 |  |  |  |  |  |  |  | 
| 741 |  |  |  |  |  |  |  | 
| 742 |  |  |  |  |  |  | #  Debug | 
| 743 |  |  |  |  |  |  | # | 
| 744 | 0 |  |  |  |  | 0 | 0 && debug("run $nrun times, no cache check needed"); | 
| 745 |  |  |  |  |  |  |  | 
| 746 |  |  |  |  |  |  | } | 
| 747 |  |  |  |  |  |  |  | 
| 748 |  |  |  |  |  |  |  | 
| 749 |  |  |  |  |  |  | #  Debug exit | 
| 750 |  |  |  |  |  |  | # | 
| 751 | 10 |  |  |  |  | 17 | 0 && debug("handler $r exit status %s, leaving with Apache::OK", $r->status);    #, Dumper($self)); | 
| 752 |  |  |  |  |  |  |  | 
| 753 |  |  |  |  |  |  |  | 
| 754 |  |  |  |  |  |  | #  Complete | 
| 755 |  |  |  |  |  |  | # | 
| 756 | 10 |  |  |  |  | 33 | HANDLER_COMPLETE: | 
| 757 |  |  |  |  |  |  | return &Apache::OK; | 
| 758 |  |  |  |  |  |  |  | 
| 759 |  |  |  |  |  |  |  | 
| 760 |  |  |  |  |  |  | } | 
| 761 |  |  |  |  |  |  |  | 
| 762 |  |  |  |  |  |  |  | 
| 763 |  |  |  |  |  |  | sub eval_cr { | 
| 764 |  |  |  |  |  |  |  | 
| 765 |  |  |  |  |  |  |  | 
| 766 |  |  |  |  |  |  | #  Return eval subroutine ref for inode ($_[0]) and eval code ref ($_[1]). Avoid using | 
| 767 |  |  |  |  |  |  | #  var names so not available in eval code | 
| 768 |  |  |  |  |  |  | # | 
| 769 | 43 |  |  | 43 | 0 | 145 | eval("package WebDyne::$_[0]; $WebDyne::WEBDYNE_EVAL_USE_STRICT;\n" . "#line $_[2]\n" . "sub{${$_[1]}\n}"); | 
|  | 43 |  |  | 1 |  | 2578 |  | 
|  | 1 |  |  | 1 |  | 5 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 66 |  | 
|  | 1 |  |  | 1 |  | 9 |  | 
|  | 1 |  |  | 1 |  | 3 |  | 
|  | 1 |  |  | 1 |  | 41 |  | 
|  | 1 |  |  | 1 |  | 6 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 30 |  | 
|  | 1 |  |  | 1 |  | 5 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 29 |  | 
|  | 1 |  |  | 1 |  | 8 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 32 |  | 
|  | 1 |  |  | 1 |  | 13 |  | 
|  | 1 |  |  | 1 |  | 4 |  | 
|  | 1 |  |  | 1 |  | 38 |  | 
|  | 1 |  |  | 1 |  | 6 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 35 |  | 
|  | 1 |  |  | 1 |  | 7 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 32 |  | 
|  | 1 |  |  | 1 |  | 8 |  | 
|  | 1 |  |  | 1 |  | 3 |  | 
|  | 1 |  |  | 1 |  | 45 |  | 
|  | 1 |  |  | 1 |  | 6 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 34 |  | 
|  | 1 |  |  | 1 |  | 9 |  | 
|  | 1 |  |  | 1 |  | 3 |  | 
|  | 1 |  |  | 1 |  | 38 |  | 
|  | 1 |  |  | 1 |  | 8 |  | 
|  | 1 |  |  | 1 |  | 3 |  | 
|  | 1 |  |  | 1 |  | 34 |  | 
|  | 1 |  |  | 1 |  | 8 |  | 
|  | 1 |  |  | 1 |  | 3 |  | 
|  | 1 |  |  | 1 |  | 42 |  | 
|  | 1 |  |  | 1 |  | 5 |  | 
|  | 1 |  |  | 1 |  | 4 |  | 
|  | 1 |  |  | 1 |  | 27 |  | 
|  | 1 |  |  | 1 |  | 7 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  |  |  | 30 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 25 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 27 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 26 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 35 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 24 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 24 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 29 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 26 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 35 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 31 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 26 |  | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 32 |  | 
|  | 1 |  |  |  |  | 10 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 30 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 26 |  | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 27 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 21 |  | 
|  | 1 |  |  |  |  | 13 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 54 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 39 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 32 |  | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 32 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 32 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 33 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 27 |  | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 53 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 36 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 56 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 33 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 32 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 33 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 31 |  | 
| 770 |  |  |  |  |  |  |  | 
| 771 |  |  |  |  |  |  |  | 
| 772 |  |  |  |  |  |  | } | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  |  | 
| 775 |  |  |  |  |  |  | sub perl_init_cr { | 
| 776 |  |  |  |  |  |  |  | 
| 777 | 10 |  |  | 10 | 0 | 70 | eval("package WebDyne::$_[0]; $WebDyne::WEBDYNE_EVAL_USE_STRICT;\n" . "#line $_[2]\n" . "${$_[1]}"); | 
|  | 10 |  |  | 1 |  | 1029 |  | 
|  | 1 |  |  | 1 |  | 10 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 135 |  | 
|  | 1 |  |  | 1 |  | 12 |  | 
|  | 1 |  |  | 1 |  | 5 |  | 
|  | 1 |  |  | 1 |  | 125 |  | 
|  | 1 |  |  | 1 |  | 12 |  | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  |  |  | 99 |  | 
|  | 1 |  |  |  |  | 11 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 61 |  | 
|  | 1 |  |  |  |  | 11 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 52 |  | 
|  | 1 |  |  |  |  | 13 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 140 |  | 
|  | 1 |  |  |  |  | 12 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 45 |  | 
|  | 1 |  |  |  |  | 11 |  | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 81 |  | 
|  | 1 |  |  |  |  | 18 |  | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 320 |  | 
| 778 |  |  |  |  |  |  |  | 
| 779 |  |  |  |  |  |  | } | 
| 780 |  |  |  |  |  |  |  | 
| 781 |  |  |  |  |  |  |  | 
| 782 |  |  |  |  |  |  | sub init_class { | 
| 783 |  |  |  |  |  |  |  | 
| 784 |  |  |  |  |  |  |  | 
| 785 |  |  |  |  |  |  | #  Try to load correct modules depending on Apache ver, taking special care | 
| 786 |  |  |  |  |  |  | #  with constants. This mess will disappear if we only support MP2 | 
| 787 |  |  |  |  |  |  | # | 
| 788 | 4 | 50 |  | 4 | 0 | 19 | if ($MP2) { | 
|  |  | 50 |  |  |  |  |  | 
| 789 |  |  |  |  |  |  |  | 
| 790 | 1 |  |  |  |  | 2 | local $SIG{'__DIE__'}; | 
| 791 |  |  |  |  |  |  | eval { | 
| 792 |  |  |  |  |  |  | #require Apache2; | 
| 793 | 1 |  |  |  |  | 2 | require Apache::Log; | 
| 794 | 1 |  |  |  |  | 5 | require Apache::Response; | 
| 795 | 1 |  |  |  |  | 3 | require Apache::SubRequest; | 
| 796 | 1 |  |  |  |  | 6 | require Apache::Const; Apache::Const->import(-compile => qw(OK DECLINED)); | 
|  | 2 |  |  |  |  | 12 |  | 
| 797 | 1 |  |  |  |  | 3 | require APR::Table; | 
| 798 | 1 | 50 |  |  |  | 7 | } || eval { | 
| 799 | 2 |  |  |  |  | 84 | require Apache2::Log; | 
| 800 | 2 |  |  |  |  | 10 | require Apache2::Response; | 
| 801 | 1 |  |  |  |  | 6 | require Apache2::SubRequest; | 
| 802 | 1 |  |  |  |  | 4 | require Apache2::Const; Apache2::Const->import(-compile => qw(OK DECLINED)); | 
|  | 1 |  |  |  |  | 6 |  | 
| 803 | 1 |  |  |  |  | 3 | require APR::Table; | 
| 804 |  |  |  |  |  |  | }; | 
| 805 | 1 | 0 |  |  |  | 3 | eval {undef} if $@; | 
|  | 3 |  |  |  |  | 15 |  | 
| 806 | 1 | 0 |  |  |  | 4 | unless (UNIVERSAL::can('Apache', 'OK')) { | 
| 807 | 1 | 0 |  |  |  | 2 | if (UNIVERSAL::can('Apache2::Const', 'OK')) { | 
|  |  | 0 |  |  |  |  |  | 
| 808 | 1 |  |  |  |  | 4 | *Apache::OK=\&Apache2::Const::OK; | 
| 809 | 1 |  |  |  |  | 4 | *Apache::DECLINED=\&Apache2::Const::DECLINED; | 
| 810 |  |  |  |  |  |  | } | 
| 811 |  |  |  |  |  |  | elsif (UNIVERSAL::can('Apache::Const', 'OK')) { | 
| 812 | 1 |  |  |  |  | 3 | *Apache::OK=\&Apache::Const::OK; | 
| 813 | 1 |  |  |  |  | 2 | *Apache::DECLINED=\&Apache::Const::DECLINED; | 
| 814 |  |  |  |  |  |  | } | 
| 815 |  |  |  |  |  |  | else { | 
| 816 | 1 |  |  | 2 |  | 3 | *Apache::OK=sub {0} | 
| 817 | 3 | 0 |  |  |  | 8 | unless defined &Apache::OK; | 
| 818 | 1 |  |  | 2 |  | 6 | *Apache::DECLINED=sub {-1} | 
| 819 | 1 | 0 |  |  |  | 5 | unless defined &Apache::DECLINED; | 
| 820 |  |  |  |  |  |  | } | 
| 821 |  |  |  |  |  |  | } | 
| 822 |  |  |  |  |  |  | } | 
| 823 |  |  |  |  |  |  | elsif ($ENV{'MOD_PERL'}) { | 
| 824 |  |  |  |  |  |  |  | 
| 825 | 1 |  |  |  |  | 4 | local $SIG{'__DIE__'}; | 
| 826 |  |  |  |  |  |  | eval { | 
| 827 | 1 |  |  |  |  | 3 | require Apache::Constants; Apache::Constants->import(qw(OK DECLINED)); | 
|  | 1 |  |  |  |  | 6 |  | 
| 828 | 1 |  |  |  |  | 4 | *Apache::OK=\&Apache::Constants::OK; | 
| 829 | 1 |  |  |  |  | 11 | *Apache::DECLINED=\&Apache::Constants::DECLINED; | 
| 830 | 1 | 0 |  |  |  | 2 | } || do { | 
| 831 | 1 |  |  | 1 |  | 10 | *Apache::OK=sub {0} | 
| 832 | 1 |  |  |  |  | 12 | }; | 
| 833 | 1 | 0 |  |  |  | 2 | eval {undef} if $@; | 
|  | 1 |  |  |  |  | 2 |  | 
| 834 |  |  |  |  |  |  | } | 
| 835 |  |  |  |  |  |  | else { | 
| 836 |  |  |  |  |  |  |  | 
| 837 | 5 |  |  | 11 |  | 20 | *Apache::OK=sub       {0}; | 
|  | 11 |  |  |  |  | 230 |  | 
| 838 | 2 |  |  | 1 |  | 8 | *Apache::DECLINED=sub {-1}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 839 |  |  |  |  |  |  |  | 
| 840 |  |  |  |  |  |  | } | 
| 841 |  |  |  |  |  |  |  | 
| 842 |  |  |  |  |  |  |  | 
| 843 |  |  |  |  |  |  | #  If set, delete all old cache files at startup | 
| 844 |  |  |  |  |  |  | # | 
| 845 | 2 | 50 | 33 |  |  | 22 | if ($WEBDYNE_STARTUP_CACHE_FLUSH && (-d $WEBDYNE_CACHE_DN)) { | 
| 846 | 0 |  |  |  |  | 0 | my @file_cn=glob(File::Spec->catfile($WEBDYNE_CACHE_DN, '*')); | 
| 847 | 0 |  |  |  |  | 0 | foreach my $fn (grep {/\w{32}(\.html)?$/} @file_cn) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 848 | 0 |  |  |  |  | 0 | unlink $fn;    #don't error here if problems, user will never see it | 
| 849 |  |  |  |  |  |  | } | 
| 850 |  |  |  |  |  |  | } | 
| 851 |  |  |  |  |  |  |  | 
| 852 |  |  |  |  |  |  |  | 
| 853 |  |  |  |  |  |  | #  Pre-compile some of the CGI functions we will need. Do here rather than in init | 
| 854 |  |  |  |  |  |  | #  so that can be executed at module load, and thus shared in memory between Apache | 
| 855 |  |  |  |  |  |  | #  children. Force run of start_ and end_ functions because CGI seems to lose them | 
| 856 |  |  |  |  |  |  | #  if not called at least once after compilation | 
| 857 |  |  |  |  |  |  | # | 
| 858 | 2 |  |  |  |  | 1213 | require CGI; | 
| 859 |  |  |  |  |  |  |  | 
| 860 |  |  |  |  |  |  | # CGI::->method is needed because perl 5.6.0 will use WebDyne::CGI->method instead of | 
| 861 |  |  |  |  |  |  | # CGI->method. CGI::->method makes it happy | 
| 862 | 2 |  |  |  |  | 45222 | CGI::->import('-no_xhtml', '-no_sticky'); | 
| 863 | 2 |  |  |  |  | 201 | my @cgi_compile=qw(:all area map unescapeHTML form col colgroup spacer nobr Header); | 
| 864 | 2 |  |  |  |  | 15 | CGI::->compile(@cgi_compile); | 
| 865 |  |  |  |  |  |  |  | 
| 866 |  |  |  |  |  |  | #  Broken under CGI 4.28. Use different method | 
| 867 | 2 | 50 |  |  |  | 23 | if (CGI::->can('_tag_func')) { | 
| 868 |  |  |  |  |  |  |  | 
| 869 |  |  |  |  |  |  | #  4.28 | 
| 870 | 2 |  |  |  |  | 7 | foreach my $tag (grep {!/^:/} @cgi_compile) { | 
|  | 20 |  |  |  |  | 35 |  | 
| 871 | 10 |  |  | 1 |  | 27 | *{"CGI::${tag}"}=sub {return &CGI::_tag_func($tag, @_)} | 
|  | 0 |  |  |  |  | 0 |  | 
| 872 | 18 | 100 |  |  |  | 79 | unless CGI::->can($tag); | 
| 873 | 18 |  |  |  |  | 31 | foreach my $start_end (qw(start end)) { | 
| 874 | 36 |  |  |  |  | 69 | my $start_end_function="${start_end}_${tag}"; | 
| 875 | 20 |  |  | 2 |  | 60 | *{"CGI::${start_end_function}"}=sub {return &CGI::_tag_func($start_end_function, @_)} | 
|  | 0 |  |  |  |  | 0 |  | 
| 876 | 36 | 100 |  |  |  | 188 | unless CGI::->can($start_end_function); | 
| 877 |  |  |  |  |  |  | } | 
| 878 |  |  |  |  |  |  | } | 
| 879 |  |  |  |  |  |  | } | 
| 880 |  |  |  |  |  |  | else { | 
| 881 |  |  |  |  |  |  | # Original flavour | 
| 882 | 0 |  |  |  |  | 0 | foreach (grep {!/^:/} @cgi_compile) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 883 | 0 |  |  |  |  | 0 | map {CGI::->$_} ("start_${_}", "end_${_}") | 
|  | 0 |  |  |  |  | 0 |  | 
| 884 |  |  |  |  |  |  | } | 
| 885 |  |  |  |  |  |  | } | 
| 886 |  |  |  |  |  |  |  | 
| 887 |  |  |  |  |  |  |  | 
| 888 |  |  |  |  |  |  | #  Make all errors non-fatal | 
| 889 |  |  |  |  |  |  | # | 
| 890 | 2 |  |  |  |  | 12 | errnofatal(1); | 
| 891 |  |  |  |  |  |  |  | 
| 892 |  |  |  |  |  |  |  | 
| 893 |  |  |  |  |  |  | #  Turn off XHTML in CGI. -no_xhtml should do it above, but this makes sure | 
| 894 |  |  |  |  |  |  | # | 
| 895 | 2 |  |  |  |  | 4 | $CGI::XHTML=0; | 
| 896 | 2 |  |  |  |  | 5 | $CGI::NOSTICKY=1; | 
| 897 |  |  |  |  |  |  |  | 
| 898 |  |  |  |  |  |  |  | 
| 899 |  |  |  |  |  |  | #  CGI good practice | 
| 900 |  |  |  |  |  |  | # | 
| 901 | 2 |  |  |  |  | 3 | $CGI::DISABLE_UPLOADS=$WEBDYNE_CGI_DISABLE_UPLOADS; | 
| 902 | 2 |  |  |  |  | 4 | $CGI::POST_MAX=$WEBDYNE_CGI_POST_MAX; | 
| 903 |  |  |  |  |  |  |  | 
| 904 |  |  |  |  |  |  |  | 
| 905 |  |  |  |  |  |  | #  Apparently not such good practice - but needed. | 
| 906 |  |  |  |  |  |  | #  Update. Now done via local() closer to method. | 
| 907 |  |  |  |  |  |  | # | 
| 908 |  |  |  |  |  |  | #$CGI::LIST_CONTEXT_WARN=0; | 
| 909 |  |  |  |  |  |  |  | 
| 910 |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  | #  Alias request method to just 'r' also | 
| 912 |  |  |  |  |  |  | # | 
| 913 | 2 |  | 33 |  |  | 9 | *WebDyne::r=\&WebDyne::request || *WebDyne::r; | 
| 914 |  |  |  |  |  |  |  | 
| 915 |  |  |  |  |  |  |  | 
| 916 |  |  |  |  |  |  | #  Add comment function to CGI, only called if user has commented out some | 
| 917 |  |  |  |  |  |  | #  HTML that includes a susbst type section, eg | 
| 918 |  |  |  |  |  |  | # | 
| 919 | 2 |  |  | 1 |  | 6 | *{'CGI::~comment'}=sub {""}; | 
|  | 2 |  |  |  |  | 7 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 920 |  |  |  |  |  |  |  | 
| 921 |  |  |  |  |  |  |  | 
| 922 |  |  |  |  |  |  | #  Eval routine for eval'ing perl code in a non-safe way (ie hostile | 
| 923 |  |  |  |  |  |  | #  code could probably easily subvert us, as all operations are | 
| 924 |  |  |  |  |  |  | #  allowed, including redefining our subroutines etc). | 
| 925 |  |  |  |  |  |  | # | 
| 926 |  |  |  |  |  |  | my $eval_cr=sub { | 
| 927 |  |  |  |  |  |  |  | 
| 928 |  |  |  |  |  |  |  | 
| 929 |  |  |  |  |  |  | #  Get self ref | 
| 930 |  |  |  |  |  |  | # | 
| 931 | 43 |  |  | 44 |  | 102 | my ($self, $data_ar, $eval_param_hr, $eval_text, $index, $tag_fg)=@_; | 
| 932 |  |  |  |  |  |  |  | 
| 933 |  |  |  |  |  |  |  | 
| 934 |  |  |  |  |  |  | #  Debug | 
| 935 |  |  |  |  |  |  | # | 
| 936 | 43 |  | 50 |  |  | 99 | my $inode=$self->{'_inode'} || 'ANON';    # Anon used when no inode present, eg wdcompile | 
| 937 | 43 |  |  |  |  | 77 | my $html_line_no=$data_ar->[$WEBDYNE_NODE_LINE_IX]; | 
| 938 |  |  |  |  |  |  |  | 
| 939 |  |  |  |  |  |  |  | 
| 940 |  |  |  |  |  |  | #  Get CGI vars | 
| 941 |  |  |  |  |  |  | # | 
| 942 |  |  |  |  |  |  | my $param_hr=( | 
| 943 | 43 |  | 66 |  |  | 109 | $self->{'_eval_cgi_hr'} ||= do { | 
| 944 |  |  |  |  |  |  |  | 
| 945 | 9 |  | 33 |  |  | 26 | my $cgi_or=$self->{'_CGI'} || $self->CGI(); | 
| 946 | 9 |  |  |  |  | 46 | $cgi_or->Vars(); | 
| 947 |  |  |  |  |  |  |  | 
| 948 |  |  |  |  |  |  | } | 
| 949 |  |  |  |  |  |  | ); | 
| 950 |  |  |  |  |  |  |  | 
| 951 |  |  |  |  |  |  |  | 
| 952 |  |  |  |  |  |  | #  Only eval subroutine if we have not done already, if need to eval store in | 
| 953 |  |  |  |  |  |  | #  cache so only done once. | 
| 954 |  |  |  |  |  |  | # | 
| 955 | 43 |  | 33 |  |  | 437 | my $eval_cr=$Package{'_cache'}{$inode}{'eval_cr'}{$data_ar}{$index} ||= do { | 
| 956 | 43 |  | 66 |  |  | 144 | $Package{'_cache'}{$inode}{'perl_init'}{+undef} ||= $self->perl_init(); | 
| 957 | 2 |  |  | 2 |  | 6287 | no strict; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 47 |  | 
| 958 | 2 |  |  | 2 |  | 9 | no integer; | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 9 |  | 
| 959 | 43 |  |  |  |  | 47 | 0 && debug("calling eval sub: $eval_text"); | 
| 960 | 43 | 50 |  |  |  | 122 | &eval_cr($inode, \$eval_text, $html_line_no) || return | 
| 961 |  |  |  |  |  |  | $self->err_eval("$@", \$eval_text); | 
| 962 |  |  |  |  |  |  | }; | 
| 963 |  |  |  |  |  |  |  | 
| 964 |  |  |  |  |  |  | #0 && debug("eval done, eval_cr $eval_cr"); | 
| 965 |  |  |  |  |  |  |  | 
| 966 |  |  |  |  |  |  |  | 
| 967 |  |  |  |  |  |  | #  Run eval | 
| 968 |  |  |  |  |  |  | # | 
| 969 | 43 |  |  |  |  | 76 | my @eval; | 
| 970 | 43 |  |  |  |  | 60 | eval { | 
| 971 |  |  |  |  |  |  |  | 
| 972 |  |  |  |  |  |  | #  The following line puts all CGI params in %_ during the eval so they are easy to | 
| 973 |  |  |  |  |  |  | #  get to .. | 
| 974 | 43 |  |  |  |  | 104 | local *_=$param_hr; | 
| 975 | 43 |  |  |  |  | 49 | 0 && debug('eval call starting'); | 
| 976 | 43 |  |  |  |  | 788 | @eval=$eval_cr->($self, $eval_param_hr); | 
| 977 | 43 |  |  |  |  | 102 | 0 && debug("eval call complete, $@, %s", Dumper(\@eval)); | 
| 978 |  |  |  |  |  |  |  | 
| 979 |  |  |  |  |  |  | }; | 
| 980 | 43 | 50 | 33 |  |  | 207 | if (!@eval || $@ || !$eval[0]) { | 
|  |  |  | 33 |  |  |  |  | 
| 981 |  |  |  |  |  |  |  | 
| 982 |  |  |  |  |  |  | #  An error occurred - handle it and return. | 
| 983 |  |  |  |  |  |  | # | 
| 984 | 0 | 0 | 0 |  |  | 0 | if (errstr() || $@) { | 
| 985 |  |  |  |  |  |  |  | 
| 986 |  |  |  |  |  |  | #  Eval error or err() called during routine. | 
| 987 |  |  |  |  |  |  | # | 
| 988 | 0 | 0 |  |  |  | 0 | return $self->err_eval($@ ? $@ : undef, \$eval_text); | 
| 989 |  |  |  |  |  |  |  | 
| 990 |  |  |  |  |  |  | } | 
| 991 |  |  |  |  |  |  | else { | 
| 992 |  |  |  |  |  |  |  | 
| 993 |  |  |  |  |  |  | #  Some other problem | 
| 994 |  |  |  |  |  |  | # | 
| 995 | 0 |  |  |  |  | 0 | return err ('code did not return a true value: %s', $eval_text); | 
| 996 |  |  |  |  |  |  |  | 
| 997 |  |  |  |  |  |  | } | 
| 998 |  |  |  |  |  |  |  | 
| 999 |  |  |  |  |  |  | } | 
| 1000 |  |  |  |  |  |  |  | 
| 1001 |  |  |  |  |  |  |  | 
| 1002 |  |  |  |  |  |  | #  Done | 
| 1003 |  |  |  |  |  |  | # | 
| 1004 | 43 |  |  |  |  | 155 | \@eval; | 
| 1005 |  |  |  |  |  |  |  | 
| 1006 | 2 |  |  |  |  | 12 | }; | 
| 1007 |  |  |  |  |  |  |  | 
| 1008 |  |  |  |  |  |  |  | 
| 1009 |  |  |  |  |  |  | #  The code ref for the eval statement if using Safe module | 
| 1010 |  |  |  |  |  |  | # | 
| 1011 |  |  |  |  |  |  | my $eval_safe_cr=sub { | 
| 1012 |  |  |  |  |  |  |  | 
| 1013 |  |  |  |  |  |  |  | 
| 1014 |  |  |  |  |  |  | #  Get self ref | 
| 1015 |  |  |  |  |  |  | # | 
| 1016 | 0 |  |  | 1 |  | 0 | my ($self, $data_ar, $eval_param_hr, $eval_text, $index)=@_; | 
| 1017 |  |  |  |  |  |  |  | 
| 1018 |  |  |  |  |  |  |  | 
| 1019 |  |  |  |  |  |  | #  Inode | 
| 1020 |  |  |  |  |  |  | # | 
| 1021 | 0 |  | 0 |  |  | 0 | my $inode=$self->{'_inode'} || 'ANON';    # Anon used when no inode present, eg wdcompile | 
| 1022 |  |  |  |  |  |  |  | 
| 1023 |  |  |  |  |  |  |  | 
| 1024 |  |  |  |  |  |  | #  Get CGI vars | 
| 1025 |  |  |  |  |  |  | # | 
| 1026 |  |  |  |  |  |  | my $param_hr=( | 
| 1027 | 0 |  | 0 |  |  | 0 | $self->{'_eval_cgi_hr'} ||= do { | 
| 1028 |  |  |  |  |  |  |  | 
| 1029 | 0 |  | 0 |  |  | 0 | my $cgi_or=$self->{'_CGI'} || $self->CGI(); | 
| 1030 | 0 |  |  |  |  | 0 | $cgi_or->Vars(); | 
| 1031 |  |  |  |  |  |  |  | 
| 1032 |  |  |  |  |  |  | } | 
| 1033 |  |  |  |  |  |  | ); | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 |  |  |  |  |  |  | #  Init Safe mode environment space | 
| 1036 |  |  |  |  |  |  | # | 
| 1037 | 0 |  | 0 |  |  | 0 | my $safe_or=$self->{'_eval_safe'} || do { | 
| 1038 |  |  |  |  |  |  | 0 && debug('safe init (eval_init)'); | 
| 1039 |  |  |  |  |  |  | require Safe; | 
| 1040 |  |  |  |  |  |  | require Opcode; | 
| 1041 |  |  |  |  |  |  |  | 
| 1042 |  |  |  |  |  |  | #  Used to use Safe->new($inode), but bug in Safe (actually Opcode) is Safe root namespace too long | 
| 1043 |  |  |  |  |  |  | # | 
| 1044 |  |  |  |  |  |  | Safe->new(); | 
| 1045 |  |  |  |  |  |  | }; | 
| 1046 | 0 |  | 0 |  |  | 0 | $self->{'_eval_safe'} ||= do { | 
| 1047 | 0 |  |  |  |  | 0 | $safe_or->permit_only(@{$WEBDYNE_EVAL_SAFE_OPCODE_AR}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 1048 | 0 |  |  |  |  | 0 | $safe_or; | 
| 1049 |  |  |  |  |  |  | }; | 
| 1050 |  |  |  |  |  |  |  | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 |  |  |  |  |  |  | #  Only eval subroutine if we have not done already, if need to eval store in | 
| 1053 |  |  |  |  |  |  | #  cache so only done once | 
| 1054 |  |  |  |  |  |  | # | 
| 1055 | 0 |  |  |  |  | 0 | local *_=$param_hr; | 
| 1056 | 0 |  |  |  |  | 0 | ${$safe_or->varglob('_self')}=$self; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1057 | 0 |  |  |  |  | 0 | ${$safe_or->varglob('_eval_param_hr')}=$eval_param_hr; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1058 | 0 |  | 0 |  |  | 0 | my $html_sr=$safe_or->reval("sub{$eval_text}->(\$::_self, \$::_eval_param_hr)", $WebDyne::WEBDYNE_EVAL_USE_STRICT) || | 
| 1059 |  |  |  |  |  |  | return errstr() ? err () : err ($@ || 'undefined return from Safe->reval()'); | 
| 1060 |  |  |  |  |  |  |  | 
| 1061 |  |  |  |  |  |  |  | 
| 1062 |  |  |  |  |  |  | #  Run through the same sequence as non-safe routine | 
| 1063 |  |  |  |  |  |  | # | 
| 1064 | 0 | 0 | 0 |  |  | 0 | if (!defined($html_sr) || $@) { | 
| 1065 |  |  |  |  |  |  |  | 
| 1066 |  |  |  |  |  |  |  | 
| 1067 |  |  |  |  |  |  | #  An error occurred - handle it and return. | 
| 1068 |  |  |  |  |  |  | # | 
| 1069 | 0 | 0 | 0 |  |  | 0 | if (errstr() || $@) { | 
| 1070 |  |  |  |  |  |  |  | 
| 1071 |  |  |  |  |  |  | #  Eval error or err() called during routine. | 
| 1072 |  |  |  |  |  |  | # | 
| 1073 | 0 | 0 |  |  |  | 0 | return $self->err_eval($@ ? $@ : undef, \$eval_text); | 
| 1074 |  |  |  |  |  |  |  | 
| 1075 |  |  |  |  |  |  | } | 
| 1076 |  |  |  |  |  |  | else { | 
| 1077 |  |  |  |  |  |  |  | 
| 1078 |  |  |  |  |  |  | #  Some other problem | 
| 1079 |  |  |  |  |  |  | # | 
| 1080 | 0 |  |  |  |  | 0 | return err ('code did not return a true value: %s', $eval_text); | 
| 1081 |  |  |  |  |  |  | } | 
| 1082 |  |  |  |  |  |  |  | 
| 1083 |  |  |  |  |  |  |  | 
| 1084 |  |  |  |  |  |  | } | 
| 1085 |  |  |  |  |  |  |  | 
| 1086 |  |  |  |  |  |  |  | 
| 1087 |  |  |  |  |  |  | #  Array returned ? Convert if so | 
| 1088 |  |  |  |  |  |  | # | 
| 1089 | 0 | 0 |  |  |  | 0 | (ref($html_sr) eq 'ARRAY') && do { | 
| 1090 | 0 | 0 |  |  |  | 0 | $html_sr=\join(undef, map {ref($_) ? ${$_} : $_} @{$html_sr}) | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 1091 |  |  |  |  |  |  | }; | 
| 1092 |  |  |  |  |  |  |  | 
| 1093 |  |  |  |  |  |  |  | 
| 1094 |  |  |  |  |  |  | #  Any 'printed data ? Prepend to output | 
| 1095 |  |  |  |  |  |  | # | 
| 1096 | 0 | 0 |  |  |  | 0 | if (my $print_ar=delete $self->{'_print_ar'}{$data_ar}) { | 
| 1097 | 0 | 0 |  |  |  | 0 | my $print_html=join(undef, grep {$_} map {(ref($_) eq 'SCALAR') ? ${$_} : $_} @{$print_ar}); | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 1098 | 0 | 0 |  |  |  | 0 | $html_sr=ref($html_sr) ? \(${$html_sr} . $print_html) : $html_sr . $print_html; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1099 |  |  |  |  |  |  | } | 
| 1100 |  |  |  |  |  |  |  | 
| 1101 |  |  |  |  |  |  |  | 
| 1102 |  |  |  |  |  |  | #  Make sure we return a ref | 
| 1103 |  |  |  |  |  |  | # | 
| 1104 | 0 | 0 |  |  |  | 0 | return ref($html_sr) ? $html_sr : \$html_sr; | 
| 1105 |  |  |  |  |  |  |  | 
| 1106 |  |  |  |  |  |  |  | 
| 1107 | 2 |  |  |  |  | 9 | }; | 
| 1108 |  |  |  |  |  |  |  | 
| 1109 |  |  |  |  |  |  |  | 
| 1110 |  |  |  |  |  |  | #  Hash eval routine, works similar to the above, but returns a hash ref | 
| 1111 |  |  |  |  |  |  | # | 
| 1112 |  |  |  |  |  |  | my $eval_hash_cr=sub { | 
| 1113 |  |  |  |  |  |  |  | 
| 1114 |  |  |  |  |  |  |  | 
| 1115 |  |  |  |  |  |  | #  Run eval and turn into tied hash | 
| 1116 |  |  |  |  |  |  | # | 
| 1117 | 1 | 50 |  | 2 |  | 7 | tie(my %hr, 'Tie::IxHash', @{$eval_cr->(@_) || return err ()}); | 
|  | 1 |  |  |  |  | 5 |  | 
| 1118 | 1 |  |  |  |  | 51 | return \%hr; | 
| 1119 |  |  |  |  |  |  |  | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 | 2 |  |  |  |  | 6 | }; | 
| 1122 |  |  |  |  |  |  |  | 
| 1123 |  |  |  |  |  |  |  | 
| 1124 |  |  |  |  |  |  | #  Array eval routine, works similar to the above, but returns an array ref | 
| 1125 |  |  |  |  |  |  | # | 
| 1126 |  |  |  |  |  |  | my $eval_array_cr=sub { | 
| 1127 |  |  |  |  |  |  |  | 
| 1128 |  |  |  |  |  |  |  | 
| 1129 |  |  |  |  |  |  | #  Run eval and return default - which is an array ref | 
| 1130 |  |  |  |  |  |  | # | 
| 1131 | 5 |  | 33 | 6 |  | 18 | return $eval_cr->(@_) || err (); | 
| 1132 |  |  |  |  |  |  |  | 
| 1133 | 2 |  |  |  |  | 6 | }; | 
| 1134 |  |  |  |  |  |  |  | 
| 1135 |  |  |  |  |  |  |  | 
| 1136 |  |  |  |  |  |  | #  Code ref eval routine | 
| 1137 |  |  |  |  |  |  | # | 
| 1138 |  |  |  |  |  |  | my $eval_code_cr=sub { | 
| 1139 |  |  |  |  |  |  |  | 
| 1140 | 37 |  |  | 38 |  | 125 | my ($self, $data_ar, $eval_param_hr, $eval_text, $index, $tag_fg)=@_; | 
| 1141 | 37 |  |  |  |  | 48 | 0 && debug("eval code start $eval_text"); | 
| 1142 | 37 |  | 50 |  |  | 89 | my $html_ar=$eval_cr->(@_) || return err (); | 
| 1143 | 37 |  |  |  |  | 51 | 0 && debug("eval code finish %s", Dumper($html_ar)); | 
| 1144 | 37 |  |  |  |  | 50 | my $html_sr=$html_ar->[0]; | 
| 1145 |  |  |  |  |  |  |  | 
| 1146 |  |  |  |  |  |  |  | 
| 1147 |  |  |  |  |  |  | #  If array ref returned and not rendering a tag convert to string. If in tag CGI.pm can | 
| 1148 |  |  |  |  |  |  | #  use array ref so leave alone | 
| 1149 |  |  |  |  |  |  | # | 
| 1150 | 37 | 100 | 100 |  |  | 107 | if ((ref($html_sr) eq 'ARRAY') && !$tag_fg) { | 
| 1151 | 4 |  | 50 |  |  | 9 | $html_sr=\join(undef, map {(ref($_) eq 'SCALAR') ? ${$_} : $_} @{$html_sr}) || | 
| 1152 |  |  |  |  |  |  | return err ('unable to generate scalar from %s', Dumper($html_sr)); | 
| 1153 |  |  |  |  |  |  | } | 
| 1154 |  |  |  |  |  |  |  | 
| 1155 |  |  |  |  |  |  |  | 
| 1156 |  |  |  |  |  |  | #  Any 'printed data ? Prepend to output | 
| 1157 |  |  |  |  |  |  | # | 
| 1158 | 37 | 100 |  |  |  | 99 | if (my $print_ar=delete $self->{'_print_ar'}{$data_ar}) { | 
| 1159 | 3 | 50 |  |  |  | 4 | my $print_html=join(undef, grep {$_} map {(ref($_) eq 'SCALAR') ? ${$_} : $_} @{$print_ar}); | 
|  | 3 |  |  |  |  | 9 |  | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 3 |  |  |  |  | 7 |  | 
| 1160 | 3 | 50 |  |  |  | 6 | $html_sr=ref($html_sr) ? \(${$html_sr} . $print_html) : $html_sr . $print_html; | 
|  | 3 |  |  |  |  | 9 |  | 
| 1161 |  |  |  |  |  |  | } | 
| 1162 |  |  |  |  |  |  |  | 
| 1163 |  |  |  |  |  |  | #  Make sure we return a ref | 
| 1164 |  |  |  |  |  |  | # | 
| 1165 | 37 | 100 |  |  |  | 144 | return ref($html_sr) ? $html_sr : \$html_sr; | 
| 1166 |  |  |  |  |  |  |  | 
| 1167 | 2 |  |  |  |  | 15 | }; | 
| 1168 |  |  |  |  |  |  |  | 
| 1169 |  |  |  |  |  |  |  | 
| 1170 |  |  |  |  |  |  | #  Scalar (${foo}) routine | 
| 1171 |  |  |  |  |  |  | # | 
| 1172 |  |  |  |  |  |  | my $eval_scalar_cr=sub { | 
| 1173 |  |  |  |  |  |  |  | 
| 1174 | 26 |  |  | 27 |  | 63 | my $value=$_[2]->{$_[3]}; | 
| 1175 | 26 | 100 |  |  |  | 59 | unless ($value) { | 
| 1176 | 1 | 0 | 33 |  |  | 4 | if (!exists($_[2]->{$_[3]}) && $WEBDYNE_STRICT_VARS) { | 
| 1177 | 0 |  |  |  |  | 0 | return err ("no '$_[3]' parameter value supplied, parameters are: %s", join(',', map {"'$_'"} keys %{$_[2]})) | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 1178 |  |  |  |  |  |  | } | 
| 1179 |  |  |  |  |  |  | } | 
| 1180 |  |  |  |  |  |  |  | 
| 1181 |  |  |  |  |  |  | #  Get rid of any overloading | 
| 1182 | 26 | 50 | 66 |  |  | 78 | if (ref($value) && overload::Overloaded($value)) {$value="$value"} | 
|  | 0 |  |  |  |  | 0 |  | 
| 1183 | 26 | 100 |  |  |  | 173 | return ref($value) ? $value : \$value | 
| 1184 |  |  |  |  |  |  |  | 
| 1185 | 2 |  |  |  |  | 10 | }; | 
| 1186 |  |  |  |  |  |  |  | 
| 1187 |  |  |  |  |  |  |  | 
| 1188 |  |  |  |  |  |  | #  Init anon text and attr evaluation subroutines, store in class space | 
| 1189 |  |  |  |  |  |  | #  for quick retrieval when needed, save redefining all the time | 
| 1190 |  |  |  |  |  |  | # | 
| 1191 |  |  |  |  |  |  | my %eval_cr=( | 
| 1192 |  |  |  |  |  |  |  | 
| 1193 |  |  |  |  |  |  | '$' => $eval_scalar_cr, | 
| 1194 |  |  |  |  |  |  | '@' => $eval_array_cr, | 
| 1195 |  |  |  |  |  |  | '%' => $eval_hash_cr, | 
| 1196 |  |  |  |  |  |  | '!' => $eval_code_cr, | 
| 1197 | 0 |  |  | 0 |  | 0 | '+' => sub {return \($_[0]->{'_CGI'}->param($_[3]))}, | 
| 1198 | 2 |  |  | 2 |  | 8 | '*' => sub {return \$ENV{$_[3]}}, | 
| 1199 |  |  |  |  |  |  | '^' => sub { | 
| 1200 | 0 |  |  | 0 |  | 0 | my $m=$_[3]; my $r=$_[0]->{'_r'}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1201 | 0 | 0 |  |  |  | 0 | UNIVERSAL::can($r, $m) ? \$r->$m : err ("unknown request method '$m'") | 
| 1202 |  |  |  |  |  |  | } | 
| 1203 |  |  |  |  |  |  |  | 
| 1204 | 2 |  |  |  |  | 23 | ); | 
| 1205 |  |  |  |  |  |  |  | 
| 1206 |  |  |  |  |  |  |  | 
| 1207 |  |  |  |  |  |  | #  Store in class name space | 
| 1208 |  |  |  |  |  |  | # | 
| 1209 | 2 |  |  |  |  | 40 | $Package{'_eval_cr'}=\%eval_cr; | 
| 1210 |  |  |  |  |  |  |  | 
| 1211 |  |  |  |  |  |  | } | 
| 1212 |  |  |  |  |  |  |  | 
| 1213 |  |  |  |  |  |  |  | 
| 1214 |  |  |  |  |  |  | sub cache_clean { | 
| 1215 |  |  |  |  |  |  |  | 
| 1216 |  |  |  |  |  |  |  | 
| 1217 |  |  |  |  |  |  | #  Get cache_hr, only param supplied | 
| 1218 |  |  |  |  |  |  | # | 
| 1219 | 0 |  |  | 0 | 0 | 0 | my $cache_hr=shift(); | 
| 1220 | 0 |  |  |  |  | 0 | 0 && debug('in cache_clean'); | 
| 1221 |  |  |  |  |  |  |  | 
| 1222 |  |  |  |  |  |  |  | 
| 1223 |  |  |  |  |  |  | #  Values we want, either last run time (lrun) or number of times run | 
| 1224 |  |  |  |  |  |  | #  (nrun) | 
| 1225 |  |  |  |  |  |  | # | 
| 1226 | 0 | 0 |  |  |  | 0 | my $clean_method=$WEBDYNE_CACHE_CLEAN_METHOD ? 'nrun' : 'lrun'; | 
| 1227 |  |  |  |  |  |  |  | 
| 1228 |  |  |  |  |  |  |  | 
| 1229 |  |  |  |  |  |  | #  Sort into array of inode values, sorted descending by clean attr | 
| 1230 |  |  |  |  |  |  | # | 
| 1231 | 0 |  |  |  |  | 0 | my @cache=sort {$cache_hr->{$b}{$clean_method} <=> $cache_hr->{$a}{$clean_method}} | 
| 1232 | 0 |  |  |  |  | 0 | keys %{$cache_hr}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1233 | 0 |  |  |  |  | 0 | 0 && debug('cache clean array %s', Dumper(\@cache)); | 
| 1234 |  |  |  |  |  |  |  | 
| 1235 |  |  |  |  |  |  |  | 
| 1236 |  |  |  |  |  |  | #  If > high watermark entries, we need to clean | 
| 1237 |  |  |  |  |  |  | # | 
| 1238 | 0 | 0 |  |  |  | 0 | if (@cache > $WEBDYNE_CACHE_HIGH_WATER) { | 
| 1239 |  |  |  |  |  |  |  | 
| 1240 |  |  |  |  |  |  |  | 
| 1241 |  |  |  |  |  |  | #  Yes, clean | 
| 1242 |  |  |  |  |  |  | # | 
| 1243 | 0 |  |  |  |  | 0 | 0 && debug('cleaning cache'); | 
| 1244 |  |  |  |  |  |  |  | 
| 1245 |  |  |  |  |  |  |  | 
| 1246 |  |  |  |  |  |  | #  Delete excess entries | 
| 1247 |  |  |  |  |  |  | # | 
| 1248 | 0 |  |  |  |  | 0 | my @clean=map {delete $cache_hr->{$_}} @cache[$WEBDYNE_CACHE_LOW_WATER..$#cache]; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1249 |  |  |  |  |  |  |  | 
| 1250 |  |  |  |  |  |  |  | 
| 1251 |  |  |  |  |  |  | #  Debug | 
| 1252 |  |  |  |  |  |  | # | 
| 1253 | 0 |  |  |  |  | 0 | 0 && debug('removed %s entries from cache', scalar @clean); | 
| 1254 |  |  |  |  |  |  |  | 
| 1255 |  |  |  |  |  |  | } | 
| 1256 |  |  |  |  |  |  | else { | 
| 1257 |  |  |  |  |  |  |  | 
| 1258 |  |  |  |  |  |  | #  Nothing to do | 
| 1259 |  |  |  |  |  |  | # | 
| 1260 | 0 |  |  |  |  | 0 | 0 && debug( | 
| 1261 |  |  |  |  |  |  | 'no cleanup needed, cache size %s less than high watermark %s', | 
| 1262 |  |  |  |  |  |  | scalar @cache, $WEBDYNE_CACHE_HIGH_WATER | 
| 1263 |  |  |  |  |  |  | ); | 
| 1264 |  |  |  |  |  |  |  | 
| 1265 |  |  |  |  |  |  | } | 
| 1266 |  |  |  |  |  |  |  | 
| 1267 |  |  |  |  |  |  |  | 
| 1268 |  |  |  |  |  |  | #  Done | 
| 1269 |  |  |  |  |  |  | # | 
| 1270 | 0 |  |  |  |  | 0 | return \undef; | 
| 1271 |  |  |  |  |  |  |  | 
| 1272 |  |  |  |  |  |  | } | 
| 1273 |  |  |  |  |  |  |  | 
| 1274 |  |  |  |  |  |  |  | 
| 1275 |  |  |  |  |  |  | sub head_request { | 
| 1276 |  |  |  |  |  |  |  | 
| 1277 |  |  |  |  |  |  |  | 
| 1278 |  |  |  |  |  |  | #  Head request only | 
| 1279 |  |  |  |  |  |  | # | 
| 1280 | 0 |  |  | 0 | 0 | 0 | my $r=shift(); | 
| 1281 |  |  |  |  |  |  |  | 
| 1282 |  |  |  |  |  |  |  | 
| 1283 |  |  |  |  |  |  | #  Clear any handlers | 
| 1284 |  |  |  |  |  |  | # | 
| 1285 | 0 |  |  |  |  | 0 | $r->set_handlers(PerlHandler => undef); | 
| 1286 |  |  |  |  |  |  |  | 
| 1287 |  |  |  |  |  |  |  | 
| 1288 |  |  |  |  |  |  | #  Send the request | 
| 1289 |  |  |  |  |  |  | # | 
| 1290 | 0 | 0 |  |  |  | 0 | $r->send_http_header() if !$MP2; | 
| 1291 |  |  |  |  |  |  |  | 
| 1292 |  |  |  |  |  |  |  | 
| 1293 |  |  |  |  |  |  | #  Done | 
| 1294 |  |  |  |  |  |  | # | 
| 1295 | 0 |  |  |  |  | 0 | return &Apache::OK; | 
| 1296 |  |  |  |  |  |  |  | 
| 1297 |  |  |  |  |  |  | } | 
| 1298 |  |  |  |  |  |  |  | 
| 1299 |  |  |  |  |  |  |  | 
| 1300 |  |  |  |  |  |  | sub render_reset { | 
| 1301 |  |  |  |  |  |  |  | 
| 1302 | 0 |  |  | 0 | 0 | 0 | my ($self, $data_ar)=@_; | 
| 1303 | 0 | 0 |  |  |  | 0 | $data_ar ? $self->{'_perl'}[0]=$data_ar : delete $self->{'_perl'}; | 
| 1304 |  |  |  |  |  |  |  | 
| 1305 |  |  |  |  |  |  | } | 
| 1306 |  |  |  |  |  |  |  | 
| 1307 |  |  |  |  |  |  |  | 
| 1308 |  |  |  |  |  |  | sub render { | 
| 1309 |  |  |  |  |  |  |  | 
| 1310 |  |  |  |  |  |  |  | 
| 1311 |  |  |  |  |  |  | #  Convert data array structure into HTML | 
| 1312 |  |  |  |  |  |  | # | 
| 1313 | 43 |  |  | 43 | 0 | 79 | my ($self, $param_hr)=@_; | 
| 1314 |  |  |  |  |  |  |  | 
| 1315 |  |  |  |  |  |  |  | 
| 1316 |  |  |  |  |  |  | #  If not supplied param as hash ref assume all vars are params to be subs't when | 
| 1317 |  |  |  |  |  |  | #  rendering this data block | 
| 1318 |  |  |  |  |  |  | # | 
| 1319 | 43 | 100 | 100 |  |  | 146 | ref($param_hr) || ($param_hr={param => {@_[1..$#_]}}) if $param_hr; | 
| 1320 |  |  |  |  |  |  |  | 
| 1321 |  |  |  |  |  |  |  | 
| 1322 |  |  |  |  |  |  | #  Debug | 
| 1323 |  |  |  |  |  |  | # | 
| 1324 | 43 |  |  |  |  | 52 | 0 && debug('in render'); | 
| 1325 |  |  |  |  |  |  |  | 
| 1326 |  |  |  |  |  |  |  | 
| 1327 |  |  |  |  |  |  | #  Get node array ref | 
| 1328 |  |  |  |  |  |  | # | 
| 1329 | 43 |  | 50 |  |  | 140 | my $data_ar=$param_hr->{'data'} || $self->{'_perl'}[0][$WEBDYNE_NODE_CHLD_IX] || | 
| 1330 |  |  |  |  |  |  | return err ('unable to get HTML data array'); | 
| 1331 |  |  |  |  |  |  |  | 
| 1332 |  |  |  |  |  |  | #$self->{'_perl'}[0] ||= $data_ar; | 
| 1333 |  |  |  |  |  |  |  | 
| 1334 |  |  |  |  |  |  |  | 
| 1335 |  |  |  |  |  |  | #  Debug | 
| 1336 |  |  |  |  |  |  | # | 
| 1337 | 43 |  |  |  |  | 48 | 0 && debug("render data_ar $data_ar %s", Dumper($data_ar)); | 
| 1338 |  |  |  |  |  |  |  | 
| 1339 |  |  |  |  |  |  |  | 
| 1340 |  |  |  |  |  |  | #  If block name spec'd register it now | 
| 1341 |  |  |  |  |  |  | # | 
| 1342 | 43 | 50 | 0 |  |  | 70 | $param_hr->{'block'} && ( | 
| 1343 |  |  |  |  |  |  | $self->render_block($param_hr) || return err ()); | 
| 1344 |  |  |  |  |  |  |  | 
| 1345 |  |  |  |  |  |  |  | 
| 1346 |  |  |  |  |  |  | #  Get CGI object | 
| 1347 |  |  |  |  |  |  | # | 
| 1348 | 43 |  | 50 |  |  | 88 | my $cgi_or=$self->{'_CGI'} || $self->CGI() || | 
| 1349 |  |  |  |  |  |  | return err ("unable to get CGI object from self ref"); | 
| 1350 |  |  |  |  |  |  |  | 
| 1351 |  |  |  |  |  |  |  | 
| 1352 |  |  |  |  |  |  | #  Any data params for this render | 
| 1353 |  |  |  |  |  |  | # | 
| 1354 | 43 |  |  |  |  | 57 | my $param_data_hr=$param_hr->{'param'}; | 
| 1355 |  |  |  |  |  |  |  | 
| 1356 |  |  |  |  |  |  |  | 
| 1357 |  |  |  |  |  |  | #  Recursive anon sub to do the render, init and store in class space | 
| 1358 |  |  |  |  |  |  | #  if not already done, saves a small amount of time if doing many | 
| 1359 |  |  |  |  |  |  | #  iterations | 
| 1360 |  |  |  |  |  |  | # | 
| 1361 |  |  |  |  |  |  | my $render_cr=$Package{'_render_cr'} ||= sub { | 
| 1362 |  |  |  |  |  |  |  | 
| 1363 |  |  |  |  |  |  |  | 
| 1364 |  |  |  |  |  |  | #  Get self ref, node array etc | 
| 1365 |  |  |  |  |  |  | # | 
| 1366 | 77 |  |  | 77 |  | 131 | my ($render_cr, $self, $cgi_or, $data_ar, $param_data_hr)=@_; | 
| 1367 |  |  |  |  |  |  |  | 
| 1368 |  |  |  |  |  |  |  | 
| 1369 |  |  |  |  |  |  | #  Get tag | 
| 1370 |  |  |  |  |  |  | # | 
| 1371 |  |  |  |  |  |  | my ($html_tag, $html_line_no)= | 
| 1372 | 77 |  |  |  |  | 96 | @{$data_ar}[$WEBDYNE_NODE_NAME_IX, $WEBDYNE_NODE_LINE_IX]; | 
|  | 77 |  |  |  |  | 156 |  | 
| 1373 | 77 |  |  |  |  | 87 | my $html_chld; | 
| 1374 |  |  |  |  |  |  |  | 
| 1375 |  |  |  |  |  |  |  | 
| 1376 |  |  |  |  |  |  | #  Save current data block away for reference by error handler if something goes | 
| 1377 |  |  |  |  |  |  | #  wrong | 
| 1378 |  |  |  |  |  |  | # | 
| 1379 | 77 |  |  |  |  | 131 | $self->{'_data_ar'}=$data_ar; | 
| 1380 |  |  |  |  |  |  |  | 
| 1381 |  |  |  |  |  |  |  | 
| 1382 |  |  |  |  |  |  | #  Debug | 
| 1383 |  |  |  |  |  |  | # | 
| 1384 | 77 |  |  |  |  | 119 | 0 && debug("render tag $html_tag, line $html_line_no"); | 
| 1385 |  |  |  |  |  |  |  | 
| 1386 |  |  |  |  |  |  |  | 
| 1387 |  |  |  |  |  |  | #  Get attr hash ref | 
| 1388 |  |  |  |  |  |  | # | 
| 1389 | 77 |  |  |  |  | 113 | my $attr_hr=$data_ar->[$WEBDYNE_NODE_ATTR_IX]; | 
| 1390 |  |  |  |  |  |  |  | 
| 1391 |  |  |  |  |  |  |  | 
| 1392 |  |  |  |  |  |  | #  If subst flag present, means we need to process attr values | 
| 1393 |  |  |  |  |  |  | # | 
| 1394 | 77 | 100 |  |  |  | 145 | if ($data_ar->[$WEBDYNE_NODE_SBST_IX]) { | 
| 1395 | 18 |  | 50 |  |  | 52 | $attr_hr=$self->subst_attr($data_ar, $attr_hr, $param_data_hr) || | 
| 1396 |  |  |  |  |  |  | return err (); | 
| 1397 |  |  |  |  |  |  | } | 
| 1398 |  |  |  |  |  |  |  | 
| 1399 |  |  |  |  |  |  |  | 
| 1400 |  |  |  |  |  |  | #  If param present, use for sub-render | 
| 1401 |  |  |  |  |  |  | # | 
| 1402 | 77 | 50 |  |  |  | 154 | $attr_hr->{'param'} && ($param_data_hr=$attr_hr->{'param'}); | 
| 1403 |  |  |  |  |  |  |  | 
| 1404 |  |  |  |  |  |  |  | 
| 1405 |  |  |  |  |  |  | #  Process sub nodes to get child html data, only if not a perl tag or block tag | 
| 1406 |  |  |  |  |  |  | #  though - they will choose when to render sub data. Subst is OK | 
| 1407 |  |  |  |  |  |  | # | 
| 1408 | 77 | 100 | 100 |  |  | 254 | if (!$CGI_TAG_WEBDYNE{$html_tag} || ($html_tag eq 'subst')) { | 
| 1409 |  |  |  |  |  |  |  | 
| 1410 |  |  |  |  |  |  |  | 
| 1411 |  |  |  |  |  |  | #  Not a perl tag, recurse through children and render them, building | 
| 1412 |  |  |  |  |  |  | #  up HTML from inside out | 
| 1413 |  |  |  |  |  |  | # | 
| 1414 | 37 | 100 |  |  |  | 89 | my @data_child_ar=$data_ar->[$WEBDYNE_NODE_CHLD_IX] ? @{$data_ar->[$WEBDYNE_NODE_CHLD_IX]} : undef; | 
|  | 21 |  |  |  |  | 47 |  | 
| 1415 | 37 |  |  |  |  | 67 | foreach my $data_chld_ar (@data_child_ar) { | 
| 1416 |  |  |  |  |  |  |  | 
| 1417 |  |  |  |  |  |  |  | 
| 1418 |  |  |  |  |  |  | #  Debug | 
| 1419 |  |  |  |  |  |  | # | 
| 1420 | 37 |  |  |  |  | 44 | 0 && debug('data_chld_ar %s', Dumper($data_chld_ar)); | 
| 1421 |  |  |  |  |  |  |  | 
| 1422 |  |  |  |  |  |  |  | 
| 1423 |  |  |  |  |  |  | #  Only recurse on children which are are refs, as these are sub nodes. A | 
| 1424 |  |  |  |  |  |  | #  child that is not a ref is merely HTML text | 
| 1425 |  |  |  |  |  |  | # | 
| 1426 | 37 | 100 |  |  |  | 56 | if (ref($data_chld_ar)) { | 
| 1427 |  |  |  |  |  |  |  | 
| 1428 |  |  |  |  |  |  |  | 
| 1429 |  |  |  |  |  |  | #  It is a sub node, render recursively | 
| 1430 |  |  |  |  |  |  | # | 
| 1431 |  |  |  |  |  |  | $html_chld.=${ | 
| 1432 | 2 | 50 |  |  |  | 4 | (   $render_cr->($render_cr, $self, $cgi_or, $data_chld_ar, $param_data_hr) | 
|  | 2 |  |  |  |  | 9 |  | 
| 1433 |  |  |  |  |  |  | || | 
| 1434 |  |  |  |  |  |  | return err ())}; | 
| 1435 |  |  |  |  |  |  |  | 
| 1436 |  |  |  |  |  |  | #$html_chld.="\n"; | 
| 1437 |  |  |  |  |  |  |  | 
| 1438 |  |  |  |  |  |  | } | 
| 1439 |  |  |  |  |  |  | else { | 
| 1440 |  |  |  |  |  |  |  | 
| 1441 |  |  |  |  |  |  |  | 
| 1442 |  |  |  |  |  |  | #  Text node only, add text to child html string | 
| 1443 |  |  |  |  |  |  | # | 
| 1444 | 35 |  |  |  |  | 82 | $html_chld.=$data_chld_ar; | 
| 1445 |  |  |  |  |  |  |  | 
| 1446 |  |  |  |  |  |  | } | 
| 1447 |  |  |  |  |  |  |  | 
| 1448 |  |  |  |  |  |  | } | 
| 1449 |  |  |  |  |  |  |  | 
| 1450 |  |  |  |  |  |  | } | 
| 1451 |  |  |  |  |  |  | else { | 
| 1452 |  |  |  |  |  |  |  | 
| 1453 | 40 |  |  |  |  | 51 | 0 && debug("skip child render, under $html_tag tag"); | 
| 1454 |  |  |  |  |  |  |  | 
| 1455 |  |  |  |  |  |  | } | 
| 1456 |  |  |  |  |  |  |  | 
| 1457 |  |  |  |  |  |  |  | 
| 1458 |  |  |  |  |  |  | #  Debug | 
| 1459 |  |  |  |  |  |  | # | 
| 1460 | 77 |  |  |  |  | 87 | 0 && debug("html_chld $html_chld"); | 
| 1461 |  |  |  |  |  |  |  | 
| 1462 |  |  |  |  |  |  |  | 
| 1463 |  |  |  |  |  |  | #  Render *our* node now, trying to use most efficient/appropriated method depending on a number | 
| 1464 |  |  |  |  |  |  | #  of factors | 
| 1465 |  |  |  |  |  |  | # | 
| 1466 | 77 | 100 |  |  |  | 149 | if ($CGI_TAG_WEBDYNE{$html_tag}) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 1467 |  |  |  |  |  |  |  | 
| 1468 |  |  |  |  |  |  |  | 
| 1469 |  |  |  |  |  |  | #  Debug | 
| 1470 |  |  |  |  |  |  | # | 
| 1471 | 56 |  |  |  |  | 60 | 0 && debug("rendering webdyne tag $html_tag"); | 
| 1472 |  |  |  |  |  |  |  | 
| 1473 |  |  |  |  |  |  |  | 
| 1474 |  |  |  |  |  |  | #  Special WebDyne tag, render using our self ref, not CGI object | 
| 1475 |  |  |  |  |  |  | # | 
| 1476 | 56 |  | 50 |  |  | 175 | my $html_sr=( | 
| 1477 |  |  |  |  |  |  | $self->$html_tag($data_ar, $attr_hr, $param_data_hr, $html_chld) | 
| 1478 |  |  |  |  |  |  | || | 
| 1479 |  |  |  |  |  |  | return err ()); | 
| 1480 |  |  |  |  |  |  |  | 
| 1481 |  |  |  |  |  |  |  | 
| 1482 |  |  |  |  |  |  | #  Debug | 
| 1483 |  |  |  |  |  |  | # | 
| 1484 | 56 |  |  |  |  | 74 | 0 && debug("CGI tag $html_tag render return $html_sr (%s)", Dumper($html_sr)); | 
| 1485 |  |  |  |  |  |  |  | 
| 1486 |  |  |  |  |  |  |  | 
| 1487 |  |  |  |  |  |  | #  Return | 
| 1488 |  |  |  |  |  |  | # | 
| 1489 | 56 |  |  |  |  | 187 | return $html_sr; | 
| 1490 |  |  |  |  |  |  |  | 
| 1491 |  |  |  |  |  |  |  | 
| 1492 |  |  |  |  |  |  | } | 
| 1493 |  |  |  |  |  |  | elsif ($attr_hr) { | 
| 1494 |  |  |  |  |  |  |  | 
| 1495 |  |  |  |  |  |  |  | 
| 1496 |  |  |  |  |  |  | #  Normal CGI tag, with attributes and perhaps child text | 
| 1497 |  |  |  |  |  |  | # | 
| 1498 |  |  |  |  |  |  | return \( | 
| 1499 | 21 |  | 50 |  |  | 40 | $cgi_or->$html_tag(grep {$_} $attr_hr, $html_chld) | 
| 1500 |  |  |  |  |  |  | || | 
| 1501 |  |  |  |  |  |  | return err ( | 
| 1502 |  |  |  |  |  |  | "CGI tag '<$html_tag>' " . | 
| 1503 |  |  |  |  |  |  | 'did not return any text' | 
| 1504 |  |  |  |  |  |  | )); | 
| 1505 |  |  |  |  |  |  |  | 
| 1506 |  |  |  |  |  |  | } | 
| 1507 |  |  |  |  |  |  | elsif ($html_chld) { | 
| 1508 |  |  |  |  |  |  |  | 
| 1509 |  |  |  |  |  |  |  | 
| 1510 |  |  |  |  |  |  | #  Normal CGI tag, no attributes but with child text | 
| 1511 |  |  |  |  |  |  | # | 
| 1512 |  |  |  |  |  |  | return \( | 
| 1513 | 0 |  | 0 |  |  | 0 | $cgi_or->$html_tag($html_chld) | 
| 1514 |  |  |  |  |  |  | || | 
| 1515 |  |  |  |  |  |  | return err ( | 
| 1516 |  |  |  |  |  |  | "CGI tag '<$html_tag>' " . | 
| 1517 |  |  |  |  |  |  | 'did not return any text' | 
| 1518 |  |  |  |  |  |  | )); | 
| 1519 |  |  |  |  |  |  |  | 
| 1520 |  |  |  |  |  |  | } | 
| 1521 |  |  |  |  |  |  | else { | 
| 1522 |  |  |  |  |  |  |  | 
| 1523 |  |  |  |  |  |  |  | 
| 1524 |  |  |  |  |  |  | #  Empty CGI object, eg 
 | 
| 1525 |  |  |  |  |  |  | # | 
| 1526 |  |  |  |  |  |  | return \( | 
| 1527 | 0 |  | 0 |  |  | 0 | $cgi_or->$html_tag() | 
| 1528 |  |  |  |  |  |  | || | 
| 1529 |  |  |  |  |  |  | return err ( | 
| 1530 |  |  |  |  |  |  | "CGI tag '<$html_tag>' " . | 
| 1531 |  |  |  |  |  |  | 'did not return any text' | 
| 1532 |  |  |  |  |  |  | )); | 
| 1533 |  |  |  |  |  |  |  | 
| 1534 |  |  |  |  |  |  | } | 
| 1535 |  |  |  |  |  |  |  | 
| 1536 |  |  |  |  |  |  |  | 
| 1537 | 43 |  | 100 |  |  | 87 | }; | 
| 1538 |  |  |  |  |  |  |  | 
| 1539 |  |  |  |  |  |  |  | 
| 1540 |  |  |  |  |  |  | #  At the top level the array may have completly text nodes, and no children, so | 
| 1541 |  |  |  |  |  |  | #  need to take care to only render children if present. | 
| 1542 |  |  |  |  |  |  | # | 
| 1543 | 43 |  |  |  |  | 56 | my @html; | 
| 1544 | 43 |  |  |  |  | 61 | foreach my $data_ar (@{$data_ar}) { | 
|  | 43 |  |  |  |  | 95 |  | 
| 1545 |  |  |  |  |  |  |  | 
| 1546 |  |  |  |  |  |  |  | 
| 1547 |  |  |  |  |  |  | #  Is this a sub node, or only text (ref means sub-node) | 
| 1548 |  |  |  |  |  |  | # | 
| 1549 | 154 | 100 |  |  |  | 6369 | if (ref($data_ar)) { | 
| 1550 |  |  |  |  |  |  |  | 
| 1551 |  |  |  |  |  |  |  | 
| 1552 |  |  |  |  |  |  | #  Sub node, we call call render routine | 
| 1553 |  |  |  |  |  |  | # | 
| 1554 |  |  |  |  |  |  | push @html, | 
| 1555 | 75 | 50 |  |  |  | 83 | ${$render_cr->($render_cr, $self, $cgi_or, $data_ar, $param_data_hr) || return err ()}; | 
|  | 75 |  |  |  |  | 141 |  | 
| 1556 |  |  |  |  |  |  |  | 
| 1557 |  |  |  |  |  |  |  | 
| 1558 |  |  |  |  |  |  | } | 
| 1559 |  |  |  |  |  |  | else { | 
| 1560 |  |  |  |  |  |  |  | 
| 1561 |  |  |  |  |  |  |  | 
| 1562 |  |  |  |  |  |  | #  Text only, do not render just push onto return array | 
| 1563 |  |  |  |  |  |  | # | 
| 1564 | 79 |  |  |  |  | 142 | push @html, $data_ar; | 
| 1565 |  |  |  |  |  |  |  | 
| 1566 |  |  |  |  |  |  | } | 
| 1567 |  |  |  |  |  |  | } | 
| 1568 |  |  |  |  |  |  |  | 
| 1569 |  |  |  |  |  |  |  | 
| 1570 |  |  |  |  |  |  | #  Return scalar ref of completed HTML string | 
| 1571 |  |  |  |  |  |  | # | 
| 1572 | 43 |  |  |  |  | 1097 | 0 && debug('render exit, html %s', Dumper(\@html)); | 
| 1573 | 43 |  |  |  |  | 462 | return \join(undef, @html); | 
| 1574 |  |  |  |  |  |  |  | 
| 1575 |  |  |  |  |  |  |  | 
| 1576 |  |  |  |  |  |  | } | 
| 1577 |  |  |  |  |  |  |  | 
| 1578 |  |  |  |  |  |  |  | 
| 1579 |  |  |  |  |  |  | sub redirect { | 
| 1580 |  |  |  |  |  |  |  | 
| 1581 |  |  |  |  |  |  |  | 
| 1582 |  |  |  |  |  |  | #  Redirect render to different location | 
| 1583 |  |  |  |  |  |  | # | 
| 1584 | 0 |  |  | 0 | 0 | 0 | my ($self, $param_hr)=@_; | 
| 1585 |  |  |  |  |  |  |  | 
| 1586 |  |  |  |  |  |  |  | 
| 1587 |  |  |  |  |  |  | #  Debug | 
| 1588 |  |  |  |  |  |  | # | 
| 1589 | 0 |  |  |  |  | 0 | 0 && debug('in redirect, param %s', Dumper($param_hr)); | 
| 1590 |  |  |  |  |  |  |  | 
| 1591 |  |  |  |  |  |  |  | 
| 1592 |  |  |  |  |  |  | #  Restore select handler before anything else so all output goes | 
| 1593 |  |  |  |  |  |  | #  to main::STDOUT; | 
| 1594 |  |  |  |  |  |  | # | 
| 1595 | 0 | 0 |  |  |  | 0 | if (my $select=$self->{'_select'}) { | 
| 1596 | 0 |  |  |  |  | 0 | 0 && debug("restoring select handle to $select"); | 
| 1597 | 0 |  |  |  |  | 0 | CORE::select $select; | 
| 1598 |  |  |  |  |  |  | } | 
| 1599 |  |  |  |  |  |  |  | 
| 1600 |  |  |  |  |  |  |  | 
| 1601 |  |  |  |  |  |  | #  If redirecting to a different uri, run its handler | 
| 1602 |  |  |  |  |  |  | # | 
| 1603 | 0 | 0 | 0 |  |  | 0 | if ($param_hr->{'uri'} || $param_hr->{'file'} || $param_hr->{'location'}) { | 
|  |  |  | 0 |  |  |  |  | 
| 1604 |  |  |  |  |  |  |  | 
| 1605 |  |  |  |  |  |  |  | 
| 1606 |  |  |  |  |  |  | #  Get HTML from subrequest | 
| 1607 |  |  |  |  |  |  | # | 
| 1608 | 0 |  | 0 |  |  | 0 | my $status=$self->subrequest($param_hr) || | 
| 1609 |  |  |  |  |  |  | return err (); | 
| 1610 | 0 |  |  |  |  | 0 | 0 && debug("redirect status was $status"); | 
| 1611 |  |  |  |  |  |  |  | 
| 1612 |  |  |  |  |  |  |  | 
| 1613 |  |  |  |  |  |  | #  GOTOs considered harmful - except here ! Speed things up significantly, removes uneeded checks | 
| 1614 |  |  |  |  |  |  | #  for redirects in render code etc. | 
| 1615 |  |  |  |  |  |  | # | 
| 1616 | 0 |  | 0 |  |  | 0 | my $r=$self->r() || return err (); | 
| 1617 | 0 |  |  |  |  | 0 | $r->status($status); | 
| 1618 | 0 | 0 | 0 |  |  | 0 | if (my $errstr=errstr()) { | 
|  |  | 0 | 0 |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 1619 | 0 |  |  |  |  | 0 | 0 && debug("error in subrequest: $errstr"); | 
| 1620 | 0 |  |  |  |  | 0 | return errsubst("error in subrequest: $errstr") | 
| 1621 |  |  |  |  |  |  | } | 
| 1622 |  |  |  |  |  |  | elsif (is_error($status)) { | 
| 1623 | 0 |  |  |  |  | 0 | 0 && debug("sending error response status $status with r $r"); | 
| 1624 | 0 |  |  |  |  | 0 | $r->send_error_response(&Apache::OK) | 
| 1625 |  |  |  |  |  |  | } | 
| 1626 |  |  |  |  |  |  | elsif (($status != &Apache::OK) && !is_success($status) && !is_redirect($status)) { | 
| 1627 | 0 |  |  |  |  | 0 | return err ("unknown status code '$status' returned from subrequest"); | 
| 1628 |  |  |  |  |  |  | } | 
| 1629 |  |  |  |  |  |  | else { | 
| 1630 | 0 |  |  |  |  | 0 | 0 && debug("status $status OK"); | 
| 1631 |  |  |  |  |  |  | } | 
| 1632 | 0 |  |  |  |  | 0 | goto HANDLER_COMPLETE; | 
| 1633 |  |  |  |  |  |  |  | 
| 1634 |  |  |  |  |  |  |  | 
| 1635 |  |  |  |  |  |  | } | 
| 1636 |  |  |  |  |  |  | else { | 
| 1637 |  |  |  |  |  |  |  | 
| 1638 |  |  |  |  |  |  |  | 
| 1639 |  |  |  |  |  |  | #  html/text must be a param | 
| 1640 |  |  |  |  |  |  | # | 
| 1641 | 0 |  | 0 |  |  | 0 | my $html_sr=$param_hr->{'html'} || $param_hr->{'text'} || | 
| 1642 |  |  |  |  |  |  | return err ('no data supplied to redirect method'); | 
| 1643 |  |  |  |  |  |  |  | 
| 1644 |  |  |  |  |  |  |  | 
| 1645 |  |  |  |  |  |  | #  Set content type | 
| 1646 |  |  |  |  |  |  | # | 
| 1647 | 0 |  | 0 |  |  | 0 | my $r=$self->r() || return err (); | 
| 1648 | 0 | 0 |  |  |  | 0 | if ($param_hr->{'html'}) { | 
|  |  | 0 |  |  |  |  |  | 
| 1649 | 0 |  |  |  |  | 0 | $r->content_type($WEBDYNE_CONTENT_TYPE_HTML) | 
| 1650 |  |  |  |  |  |  | } | 
| 1651 |  |  |  |  |  |  | elsif ($param_hr->{'text'}) { | 
| 1652 | 0 |  |  |  |  | 0 | $r->content_type($WEBDYNE_CONTENT_TYPE_PLAIN) | 
| 1653 |  |  |  |  |  |  | } | 
| 1654 |  |  |  |  |  |  |  | 
| 1655 |  |  |  |  |  |  |  | 
| 1656 |  |  |  |  |  |  | #  And length | 
| 1657 |  |  |  |  |  |  | # | 
| 1658 | 0 |  | 0 |  |  | 0 | my $headers_out_hr=$r->headers_out || return err (); | 
| 1659 | 0 | 0 |  |  |  | 0 | $headers_out_hr->{'Content-Length'}=length(ref($html_sr) ? ${$html_sr} : $html_sr); | 
|  | 0 |  |  |  |  | 0 |  | 
| 1660 |  |  |  |  |  |  |  | 
| 1661 |  |  |  |  |  |  |  | 
| 1662 |  |  |  |  |  |  | #  Set status, send header | 
| 1663 |  |  |  |  |  |  | # | 
| 1664 | 0 |  |  |  |  | 0 | $r->status(RC_OK); | 
| 1665 | 0 | 0 |  |  |  | 0 | $r->send_http_header() if !$MP2; | 
| 1666 |  |  |  |  |  |  |  | 
| 1667 |  |  |  |  |  |  |  | 
| 1668 |  |  |  |  |  |  | #  Print directly and shorcut return from render routine with non-harmful GOTO ! Should | 
| 1669 |  |  |  |  |  |  | #  always be SR, but be generous. | 
| 1670 |  |  |  |  |  |  | # | 
| 1671 | 0 | 0 |  |  |  | 0 | $r->print(ref($html_sr) ? ${$html_sr} : $html_sr); | 
|  | 0 |  |  |  |  | 0 |  | 
| 1672 | 0 |  |  |  |  | 0 | goto RENDER_COMPLETE; | 
| 1673 |  |  |  |  |  |  |  | 
| 1674 |  |  |  |  |  |  |  | 
| 1675 |  |  |  |  |  |  | } | 
| 1676 |  |  |  |  |  |  |  | 
| 1677 |  |  |  |  |  |  |  | 
| 1678 |  |  |  |  |  |  | } | 
| 1679 |  |  |  |  |  |  |  | 
| 1680 |  |  |  |  |  |  |  | 
| 1681 |  |  |  |  |  |  | sub subrequest { | 
| 1682 |  |  |  |  |  |  |  | 
| 1683 |  |  |  |  |  |  |  | 
| 1684 |  |  |  |  |  |  | #  Redirect render to different location | 
| 1685 |  |  |  |  |  |  | # | 
| 1686 | 0 |  |  | 0 | 0 | 0 | my ($self, $param_hr)=@_; | 
| 1687 |  |  |  |  |  |  |  | 
| 1688 |  |  |  |  |  |  |  | 
| 1689 |  |  |  |  |  |  | #  Debug | 
| 1690 |  |  |  |  |  |  | # | 
| 1691 | 0 |  |  |  |  | 0 | 0 && debug('in subrequest %s', Dumper($param_hr)); | 
| 1692 |  |  |  |  |  |  |  | 
| 1693 |  |  |  |  |  |  |  | 
| 1694 |  |  |  |  |  |  | #  Get request object, var for subrequest object | 
| 1695 |  |  |  |  |  |  | # | 
| 1696 | 0 | 0 |  |  |  | 0 | my ($r, $cgi_or)=map {$self->$_() || return err ("unable to run '$_' method")} qw(request CGI); | 
|  | 0 |  |  |  |  | 0 |  | 
| 1697 | 0 |  |  |  |  | 0 | my $r_child; | 
| 1698 |  |  |  |  |  |  |  | 
| 1699 |  |  |  |  |  |  |  | 
| 1700 |  |  |  |  |  |  | #  Run taks appropriate for subrequest - location redirects with 302, uri does sinternal redirect, | 
| 1701 |  |  |  |  |  |  | #  and file sends content of file. | 
| 1702 |  |  |  |  |  |  | # | 
| 1703 | 0 | 0 |  |  |  | 0 | if (my $location=$param_hr->{'location'}) { | 
| 1704 |  |  |  |  |  |  |  | 
| 1705 |  |  |  |  |  |  |  | 
| 1706 |  |  |  |  |  |  | #  Does the request handler take care of it ? | 
| 1707 |  |  |  |  |  |  | # | 
| 1708 | 0 | 0 |  |  |  | 0 | if (UNIVERSAL::can($r, 'redirect')) { | 
| 1709 |  |  |  |  |  |  |  | 
| 1710 |  |  |  |  |  |  |  | 
| 1711 |  |  |  |  |  |  | #  Let the request handler take care of it | 
| 1712 |  |  |  |  |  |  | # | 
| 1713 | 0 |  |  |  |  | 0 | 0 && debug('handler does redirect, handing off'); | 
| 1714 | 0 |  |  |  |  | 0 | $r->redirect($location);    # no return value | 
| 1715 | 0 |  |  |  |  | 0 | return RC_FOUND; | 
| 1716 |  |  |  |  |  |  |  | 
| 1717 |  |  |  |  |  |  | } | 
| 1718 |  |  |  |  |  |  | else { | 
| 1719 |  |  |  |  |  |  |  | 
| 1720 |  |  |  |  |  |  |  | 
| 1721 |  |  |  |  |  |  | #  Must do it ourselves | 
| 1722 |  |  |  |  |  |  | # | 
| 1723 | 0 |  |  |  |  | 0 | 0 && debug('doing redirect ourselves'); | 
| 1724 | 0 |  | 0 |  |  | 0 | my $headers_out_hr=$r->headers_out || return err (); | 
| 1725 | 0 |  |  |  |  | 0 | $headers_out_hr->{'Location'}=$location; | 
| 1726 | 0 |  |  |  |  | 0 | $r->status(RC_FOUND); | 
| 1727 | 0 | 0 |  |  |  | 0 | $r->send_http_header if !$MP2; | 
| 1728 | 0 |  |  |  |  | 0 | return RC_FOUND; | 
| 1729 |  |  |  |  |  |  |  | 
| 1730 |  |  |  |  |  |  | } | 
| 1731 |  |  |  |  |  |  | } | 
| 1732 | 0 | 0 |  |  |  | 0 | if (my $uri=$param_hr->{'uri'}) { | 
|  |  | 0 |  |  |  |  |  | 
| 1733 |  |  |  |  |  |  |  | 
| 1734 |  |  |  |  |  |  | #  Handle internally if possible | 
| 1735 |  |  |  |  |  |  | # | 
| 1736 | 0 | 0 |  |  |  | 0 | if (UNIVERSAL::can($r, 'internal_redirect')) { | 
| 1737 |  |  |  |  |  |  |  | 
| 1738 |  |  |  |  |  |  |  | 
| 1739 |  |  |  |  |  |  | #  Let the request handler take care of it | 
| 1740 |  |  |  |  |  |  | # | 
| 1741 | 0 |  |  |  |  | 0 | 0 && debug('handler does internal_redirect, handing off'); | 
| 1742 | 0 |  |  |  |  | 0 | $r->internal_redirect($uri);    # no return value | 
| 1743 | 0 |  |  |  |  | 0 | return $r->status; | 
| 1744 |  |  |  |  |  |  |  | 
| 1745 |  |  |  |  |  |  | } | 
| 1746 |  |  |  |  |  |  | else { | 
| 1747 |  |  |  |  |  |  |  | 
| 1748 |  |  |  |  |  |  | #  Must do it ourselves | 
| 1749 |  |  |  |  |  |  | # | 
| 1750 | 0 |  | 0 |  |  | 0 | $r_child=$r->lookup_uri($uri) || | 
| 1751 |  |  |  |  |  |  | return err ('undefined lookup_uri error'); | 
| 1752 | 0 |  |  |  |  | 0 | 0 && debug('r_child handler %s', $r->handler()); | 
| 1753 | 0 |  |  |  |  | 0 | $r->headers_out($r_child->headers_out()); | 
| 1754 | 0 |  |  |  |  | 0 | $r->uri($uri); | 
| 1755 |  |  |  |  |  |  |  | 
| 1756 |  |  |  |  |  |  | } | 
| 1757 |  |  |  |  |  |  |  | 
| 1758 |  |  |  |  |  |  |  | 
| 1759 |  |  |  |  |  |  | } | 
| 1760 |  |  |  |  |  |  | elsif (my $file=$param_hr->{'file'}) { | 
| 1761 |  |  |  |  |  |  |  | 
| 1762 |  |  |  |  |  |  | #  Get cwd, make request absolute rel to cwd if no dir given. | 
| 1763 |  |  |  |  |  |  | # | 
| 1764 | 0 |  |  |  |  | 0 | my $dn=(File::Spec->splitpath($r->filename()))[1]; | 
| 1765 | 0 |  |  |  |  | 0 | my $file_pn=File::Spec->rel2abs($file, $dn); | 
| 1766 |  |  |  |  |  |  |  | 
| 1767 |  |  |  |  |  |  |  | 
| 1768 |  |  |  |  |  |  | #  Get a new request object | 
| 1769 |  |  |  |  |  |  | # | 
| 1770 | 0 |  | 0 |  |  | 0 | $r_child=$r->lookup_file($file_pn) || | 
| 1771 |  |  |  |  |  |  | return err ('undefined lookup_file error'); | 
| 1772 | 0 |  |  |  |  | 0 | $r->headers_out($r_child->headers_out()); | 
| 1773 |  |  |  |  |  |  |  | 
| 1774 |  |  |  |  |  |  | } | 
| 1775 |  |  |  |  |  |  | else { | 
| 1776 |  |  |  |  |  |  |  | 
| 1777 |  |  |  |  |  |  |  | 
| 1778 |  |  |  |  |  |  | #  Must be one or other | 
| 1779 |  |  |  |  |  |  | # | 
| 1780 | 0 |  |  |  |  | 0 | return err ('must specify file, uri or locations for subrequest'); | 
| 1781 |  |  |  |  |  |  |  | 
| 1782 |  |  |  |  |  |  | } | 
| 1783 |  |  |  |  |  |  |  | 
| 1784 |  |  |  |  |  |  |  | 
| 1785 |  |  |  |  |  |  | #  Save child object, else cleanup handlers will be run when | 
| 1786 |  |  |  |  |  |  | #  we exit and r_child is destroyed, but before r (main) is | 
| 1787 |  |  |  |  |  |  | #  complete. | 
| 1788 |  |  |  |  |  |  | # | 
| 1789 |  |  |  |  |  |  | #  UPDATE no longer needed, leave here as reminder though .. | 
| 1790 |  |  |  |  |  |  | # | 
| 1791 |  |  |  |  |  |  | #push @{$self->{'_r_child'}},$r_child; | 
| 1792 |  |  |  |  |  |  |  | 
| 1793 |  |  |  |  |  |  |  | 
| 1794 |  |  |  |  |  |  | #  Safty check after calling getting r_child - should always be | 
| 1795 |  |  |  |  |  |  | #  OK, but do sanity check. | 
| 1796 |  |  |  |  |  |  | # | 
| 1797 | 0 |  |  |  |  | 0 | my $status=$r_child->status(); | 
| 1798 | 0 |  |  |  |  | 0 | 0 && debug("r_child status return: $status"); | 
| 1799 | 0 | 0 | 0 |  |  | 0 | if (($status && !is_success($status)) || (my $errstr=errstr())) { | 
|  |  |  | 0 |  |  |  |  | 
| 1800 | 0 | 0 |  |  |  | 0 | if ($errstr) { | 
| 1801 |  |  |  |  |  |  | return errsubst( | 
| 1802 |  |  |  |  |  |  | "error in status phase of subrequest to '%s': $errstr", | 
| 1803 | 0 |  | 0 |  |  | 0 | $r_child->uri() || $param_hr->{'file'} | 
| 1804 |  |  |  |  |  |  | ) | 
| 1805 |  |  |  |  |  |  | } | 
| 1806 |  |  |  |  |  |  | else { | 
| 1807 |  |  |  |  |  |  | return err ( | 
| 1808 |  |  |  |  |  |  | "error in status phase of subrequest to '%s', return status was $status", | 
| 1809 | 0 |  | 0 |  |  | 0 | $r_child->uri() || $param_hr->{'file'} | 
| 1810 |  |  |  |  |  |  | ) | 
| 1811 |  |  |  |  |  |  | } | 
| 1812 |  |  |  |  |  |  | } | 
| 1813 |  |  |  |  |  |  |  | 
| 1814 |  |  |  |  |  |  |  | 
| 1815 |  |  |  |  |  |  | #  Debug | 
| 1816 |  |  |  |  |  |  | # | 
| 1817 | 0 |  |  |  |  | 0 | 0 && debug('cgi param %s', Dumper($param_hr->{'param'})); | 
| 1818 |  |  |  |  |  |  |  | 
| 1819 |  |  |  |  |  |  |  | 
| 1820 |  |  |  |  |  |  | #  Set up CGI with any new params | 
| 1821 |  |  |  |  |  |  | # | 
| 1822 | 0 |  |  |  |  | 0 | while (my ($param, $value)=each %{$param_hr->{'param'}}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1823 |  |  |  |  |  |  |  | 
| 1824 |  |  |  |  |  |  |  | 
| 1825 |  |  |  |  |  |  | #  Add to CGI | 
| 1826 |  |  |  |  |  |  | # | 
| 1827 | 0 |  |  |  |  | 0 | $cgi_or->param($param, $value); | 
| 1828 | 0 |  |  |  |  | 0 | 0 && debug("set cgi param $param, value $value"); | 
| 1829 |  |  |  |  |  |  |  | 
| 1830 |  |  |  |  |  |  |  | 
| 1831 |  |  |  |  |  |  | } | 
| 1832 |  |  |  |  |  |  |  | 
| 1833 |  |  |  |  |  |  |  | 
| 1834 |  |  |  |  |  |  | #  Debug | 
| 1835 |  |  |  |  |  |  | # | 
| 1836 | 0 |  |  |  |  | 0 | 0 && debug("about to call child handler with params self $self %s", Dumper($param_hr->{'param'})); | 
| 1837 |  |  |  |  |  |  |  | 
| 1838 |  |  |  |  |  |  |  | 
| 1839 |  |  |  |  |  |  | #  Change of plan - used to check result, but now pass back whatever the child returns - we | 
| 1840 |  |  |  |  |  |  | #  will let Apache handle any errors internally | 
| 1841 |  |  |  |  |  |  | # | 
| 1842 | 0 | 0 |  |  |  | 0 | defined($status=(ref($r_child)=~/^WebDyne::/) ? $r_child->run($self) : $r_child->run()) || | 
|  |  | 0 |  |  |  |  |  | 
| 1843 |  |  |  |  |  |  | return err (); | 
| 1844 | 0 |  |  |  |  | 0 | 0 && debug("r_child run return status $status, rc_child status %s", $r_child->status()); | 
| 1845 | 0 |  | 0 |  |  | 0 | return $status || $r_child->status(); | 
| 1846 |  |  |  |  |  |  |  | 
| 1847 |  |  |  |  |  |  |  | 
| 1848 |  |  |  |  |  |  | } | 
| 1849 |  |  |  |  |  |  |  | 
| 1850 |  |  |  |  |  |  |  | 
| 1851 |  |  |  |  |  |  | sub eof { | 
| 1852 |  |  |  |  |  |  |  | 
| 1853 | 0 |  |  | 0 | 0 | 0 | goto HANDLER_COMPLETE; | 
| 1854 |  |  |  |  |  |  |  | 
| 1855 |  |  |  |  |  |  | } | 
| 1856 |  |  |  |  |  |  |  | 
| 1857 |  |  |  |  |  |  |  | 
| 1858 |  |  |  |  |  |  | sub erase_block { | 
| 1859 |  |  |  |  |  |  |  | 
| 1860 |  |  |  |  |  |  | #  Erase a block section so not rendered if encountered again | 
| 1861 |  |  |  |  |  |  | # | 
| 1862 | 0 |  |  | 0 | 0 | 0 | my ($self, $param_hr)=@_; | 
| 1863 |  |  |  |  |  |  |  | 
| 1864 |  |  |  |  |  |  |  | 
| 1865 |  |  |  |  |  |  | #  Has user only given name as param | 
| 1866 |  |  |  |  |  |  | # | 
| 1867 | 0 | 0 |  |  |  | 0 | ref($param_hr) || ($param_hr={name => $param_hr, param => {@_[2..$#_]}}); | 
| 1868 |  |  |  |  |  |  |  | 
| 1869 |  |  |  |  |  |  |  | 
| 1870 |  |  |  |  |  |  | #  Get block name | 
| 1871 |  |  |  |  |  |  | # | 
| 1872 | 0 |  | 0 |  |  | 0 | my $name=$param_hr->{'name'} || $param_hr->{'block'} || | 
| 1873 |  |  |  |  |  |  | return err ('no block name specified'); | 
| 1874 | 0 |  |  |  |  | 0 | 0 && debug("in erase_block, name $name"); | 
| 1875 | 0 |  |  |  |  | 0 | delete $self->{'_block_param'}{$name}; | 
| 1876 | 0 |  |  |  |  | 0 | delete $self->{'_block_render'}{$name} | 
| 1877 |  |  |  |  |  |  |  | 
| 1878 |  |  |  |  |  |  | } | 
| 1879 |  |  |  |  |  |  |  | 
| 1880 |  |  |  |  |  |  |  | 
| 1881 |  |  |  |  |  |  | sub unrender_block { | 
| 1882 |  |  |  |  |  |  |  | 
| 1883 |  |  |  |  |  |  | #  Synonym for erase_block | 
| 1884 |  |  |  |  |  |  | # | 
| 1885 | 0 |  |  | 0 | 0 | 0 | return shift()->erase_block(@_); | 
| 1886 |  |  |  |  |  |  |  | 
| 1887 |  |  |  |  |  |  | } | 
| 1888 |  |  |  |  |  |  |  | 
| 1889 |  |  |  |  |  |  |  | 
| 1890 |  |  |  |  |  |  | sub render_block { | 
| 1891 |  |  |  |  |  |  |  | 
| 1892 |  |  |  |  |  |  |  | 
| 1893 |  |  |  |  |  |  | #  Render a  section of HTML | 
| 1894 |  |  |  |  |  |  | # | 
| 1895 | 4 |  |  | 4 | 0 | 8 | my ($self, $param_hr)=@_; | 
| 1896 |  |  |  |  |  |  |  | 
| 1897 |  |  |  |  |  |  |  | 
| 1898 |  |  |  |  |  |  | #  Has user only given name as param | 
| 1899 |  |  |  |  |  |  | # | 
| 1900 | 4 | 50 |  |  |  | 24 | ref($param_hr) || ($param_hr={name => $param_hr, param => {@_[2..$#_]}}); | 
| 1901 |  |  |  |  |  |  |  | 
| 1902 |  |  |  |  |  |  |  | 
| 1903 |  |  |  |  |  |  | #  Get block name | 
| 1904 |  |  |  |  |  |  | # | 
| 1905 | 4 |  | 0 |  |  | 12 | my $name=$param_hr->{'name'} || $param_hr->{'block'} || | 
| 1906 |  |  |  |  |  |  | return err ('no block name specified'); | 
| 1907 | 4 |  |  |  |  | 5 | 0 && debug("in render_block, name $name"); | 
| 1908 |  |  |  |  |  |  |  | 
| 1909 |  |  |  |  |  |  |  | 
| 1910 |  |  |  |  |  |  | #  Get current data block | 
| 1911 |  |  |  |  |  |  | # | 
| 1912 |  |  |  |  |  |  | #my $data_ar=$self->{'_perl'}[0] || | 
| 1913 |  |  |  |  |  |  | #return err("unable to get current data node"); | 
| 1914 | 4 |  | 33 |  |  | 9 | my $data_ar=$self->{'_perl'}[0] || do { | 
| 1915 |  |  |  |  |  |  |  | 
| 1916 |  |  |  |  |  |  | #if ($WEBDYNE_DELAYED_BLOCK_RENDER) { | 
| 1917 |  |  |  |  |  |  | push @{$self->{'_block_param'}{$name} ||= []}, $param_hr->{'param'};    # if $WEBDYNE_DELAYED_BLOCK_RENDER; | 
| 1918 |  |  |  |  |  |  | return \undef; | 
| 1919 |  |  |  |  |  |  |  | 
| 1920 |  |  |  |  |  |  | #} | 
| 1921 |  |  |  |  |  |  | #else { | 
| 1922 |  |  |  |  |  |  | #  return err("unable to get current data node") | 
| 1923 |  |  |  |  |  |  | #} | 
| 1924 |  |  |  |  |  |  | }; | 
| 1925 |  |  |  |  |  |  |  | 
| 1926 |  |  |  |  |  |  |  | 
| 1927 |  |  |  |  |  |  | #  Find block name | 
| 1928 |  |  |  |  |  |  | # | 
| 1929 | 4 |  |  |  |  | 5 | my @data_block_ar; | 
| 1930 |  |  |  |  |  |  |  | 
| 1931 |  |  |  |  |  |  |  | 
| 1932 |  |  |  |  |  |  | #  Debug | 
| 1933 |  |  |  |  |  |  | # | 
| 1934 | 4 |  |  |  |  | 4 | 0 && debug("render_block self $self, name $name, data_ar $data_ar, %s", Dumper($data_ar)); | 
| 1935 |  |  |  |  |  |  |  | 
| 1936 |  |  |  |  |  |  |  | 
| 1937 |  |  |  |  |  |  | #  Have we seen this search befor ? | 
| 1938 |  |  |  |  |  |  | # | 
| 1939 | 4 | 50 |  |  |  | 9 | unless (exists($self->{'_block_cache'}{$name})) { | 
| 1940 |  |  |  |  |  |  |  | 
| 1941 |  |  |  |  |  |  |  | 
| 1942 |  |  |  |  |  |  | #  No, search for block | 
| 1943 |  |  |  |  |  |  | # | 
| 1944 | 4 |  |  |  |  | 5 | 0 && debug("searching for node $name in data_ar"); | 
| 1945 |  |  |  |  |  |  |  | 
| 1946 |  |  |  |  |  |  |  | 
| 1947 |  |  |  |  |  |  | #  Do it | 
| 1948 |  |  |  |  |  |  | # | 
| 1949 | 4 |  | 50 |  |  | 17 | my $data_block_all_ar=$self->find_node( | 
| 1950 |  |  |  |  |  |  | { | 
| 1951 |  |  |  |  |  |  |  | 
| 1952 |  |  |  |  |  |  | data_ar => $data_ar, | 
| 1953 |  |  |  |  |  |  | tag     => 'block', | 
| 1954 |  |  |  |  |  |  | all_fg  => 1, | 
| 1955 |  |  |  |  |  |  |  | 
| 1956 |  |  |  |  |  |  | }) || return err (); | 
| 1957 |  |  |  |  |  |  |  | 
| 1958 |  |  |  |  |  |  |  | 
| 1959 |  |  |  |  |  |  | #  Debug | 
| 1960 |  |  |  |  |  |  | # | 
| 1961 | 4 |  |  |  |  | 8 | 0 && debug('find_node returned %s', join('*', @{$data_block_all_ar})); | 
| 1962 |  |  |  |  |  |  |  | 
| 1963 |  |  |  |  |  |  |  | 
| 1964 |  |  |  |  |  |  | #  Go through each block found and svae in block_cache | 
| 1965 |  |  |  |  |  |  | # | 
| 1966 | 4 |  |  |  |  | 5 | foreach my $data_block_ar (@{$data_block_all_ar}) { | 
|  | 4 |  |  |  |  | 7 |  | 
| 1967 |  |  |  |  |  |  |  | 
| 1968 |  |  |  |  |  |  |  | 
| 1969 |  |  |  |  |  |  | #  Get block name | 
| 1970 |  |  |  |  |  |  | # | 
| 1971 | 5 |  |  |  |  | 8 | my $name=$data_block_ar->[$WEBDYNE_NODE_ATTR_IX]->{'name'}; | 
| 1972 | 5 |  |  |  |  | 5 | 0 && debug("looking at block $data_block_ar, name $name"); | 
| 1973 |  |  |  |  |  |  |  | 
| 1974 |  |  |  |  |  |  |  | 
| 1975 |  |  |  |  |  |  | #  Save | 
| 1976 |  |  |  |  |  |  | # | 
| 1977 |  |  |  |  |  |  | #$self->{'_block_cache'}{$name}=$data_block_ar; | 
| 1978 | 5 |  | 100 |  |  | 5 | push @{$self->{'_block_cache'}{$name} ||= []}, $data_block_ar; | 
|  | 5 |  |  |  |  | 20 |  | 
| 1979 |  |  |  |  |  |  |  | 
| 1980 |  |  |  |  |  |  |  | 
| 1981 |  |  |  |  |  |  | } | 
| 1982 |  |  |  |  |  |  |  | 
| 1983 |  |  |  |  |  |  |  | 
| 1984 |  |  |  |  |  |  | #  Done, store | 
| 1985 |  |  |  |  |  |  | # | 
| 1986 | 4 |  |  |  |  | 5 | @data_block_ar=@{$self->{'_block_cache'}{$name}}; | 
|  | 4 |  |  |  |  | 9 |  | 
| 1987 |  |  |  |  |  |  |  | 
| 1988 |  |  |  |  |  |  |  | 
| 1989 |  |  |  |  |  |  | } | 
| 1990 |  |  |  |  |  |  | else { | 
| 1991 |  |  |  |  |  |  |  | 
| 1992 |  |  |  |  |  |  |  | 
| 1993 |  |  |  |  |  |  | #  Yes, set data_block_ar to whatever we saw before, even if it is | 
| 1994 |  |  |  |  |  |  | #  undef | 
| 1995 |  |  |  |  |  |  | # | 
| 1996 | 0 |  |  |  |  | 0 | @data_block_ar=@{$self->{'_block_cache'}{$name}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1997 |  |  |  |  |  |  |  | 
| 1998 |  |  |  |  |  |  |  | 
| 1999 |  |  |  |  |  |  | #  Debug | 
| 2000 |  |  |  |  |  |  | # | 
| 2001 | 0 |  |  |  |  | 0 | 0 && debug("retrieved data_block_ar @data_block_ar for node $name from cache"); | 
| 2002 |  |  |  |  |  |  |  | 
| 2003 |  |  |  |  |  |  |  | 
| 2004 |  |  |  |  |  |  | } | 
| 2005 |  |  |  |  |  |  |  | 
| 2006 |  |  |  |  |  |  |  | 
| 2007 |  |  |  |  |  |  | #  Debug | 
| 2008 |  |  |  |  |  |  | # | 
| 2009 |  |  |  |  |  |  | #0 && debug("set block node to $data_block_ar %s", Dumper($data_block_ar)); | 
| 2010 |  |  |  |  |  |  |  | 
| 2011 |  |  |  |  |  |  |  | 
| 2012 |  |  |  |  |  |  | #  Store params for later block render (outside perl block) if needed | 
| 2013 |  |  |  |  |  |  | # | 
| 2014 | 4 |  | 50 |  |  | 4 | push @{$self->{'_block_param'}{$name} ||= []}, $param_hr->{'param'};    # if $WEBDYNE_DELAYED_BLOCK_RENDER; | 
|  | 4 |  |  |  |  | 15 |  | 
| 2015 |  |  |  |  |  |  |  | 
| 2016 |  |  |  |  |  |  |  | 
| 2017 |  |  |  |  |  |  | #  No data_block_ar ? Could not find block - remove this line if global block | 
| 2018 |  |  |  |  |  |  | #  rendering is desired (ie blocks may lay outside perl code calling render_bloc()) | 
| 2019 |  |  |  |  |  |  | # | 
| 2020 | 4 | 100 |  |  |  | 10 | unless (@data_block_ar) { | 
| 2021 |  |  |  |  |  |  |  | 
| 2022 |  |  |  |  |  |  | #if ($WEBDYNE_DELAYED_BLOCK_RENDER) { | 
| 2023 | 1 |  |  |  |  | 3 | return \undef; | 
| 2024 |  |  |  |  |  |  |  | 
| 2025 |  |  |  |  |  |  | #} | 
| 2026 |  |  |  |  |  |  | #else { | 
| 2027 |  |  |  |  |  |  | #  return err("could not find block '$name' to render") unless $WEBDYNE_DELAYED_BLOCK_RENDER; | 
| 2028 |  |  |  |  |  |  | #} | 
| 2029 |  |  |  |  |  |  | } | 
| 2030 |  |  |  |  |  |  |  | 
| 2031 |  |  |  |  |  |  |  | 
| 2032 |  |  |  |  |  |  | #  Now, was it set to something ? | 
| 2033 |  |  |  |  |  |  | # | 
| 2034 | 3 |  |  |  |  | 3 | my @html_sr; | 
| 2035 | 3 |  |  |  |  | 5 | foreach my $data_block_ar (@data_block_ar) { | 
| 2036 |  |  |  |  |  |  |  | 
| 2037 |  |  |  |  |  |  |  | 
| 2038 |  |  |  |  |  |  | #  Debug | 
| 2039 |  |  |  |  |  |  | # | 
| 2040 | 4 |  |  |  |  | 4 | 0 && debug("rendering block name $name, data $data_ar with param %s", Dumper($param_hr->{'param'})); | 
| 2041 |  |  |  |  |  |  |  | 
| 2042 |  |  |  |  |  |  |  | 
| 2043 |  |  |  |  |  |  | #  Yes, Get HTML for block immedialtly | 
| 2044 |  |  |  |  |  |  | # | 
| 2045 |  |  |  |  |  |  | my $html_sr=$self->render( | 
| 2046 |  |  |  |  |  |  | { | 
| 2047 |  |  |  |  |  |  |  | 
| 2048 |  |  |  |  |  |  | data  => $data_block_ar->[$WEBDYNE_NODE_CHLD_IX], | 
| 2049 | 4 |  | 50 |  |  | 12 | param => $param_hr->{'param'}, | 
| 2050 |  |  |  |  |  |  |  | 
| 2051 |  |  |  |  |  |  | }) || return err (); | 
| 2052 |  |  |  |  |  |  |  | 
| 2053 |  |  |  |  |  |  |  | 
| 2054 |  |  |  |  |  |  | #  Debug | 
| 2055 |  |  |  |  |  |  | # | 
| 2056 | 4 |  |  |  |  | 6 | 0 && debug("block $name rendered HTML $html_sr %s, pushing onto name $name, data_ar $data_block_ar", ${$html_sr}); | 
| 2057 |  |  |  |  |  |  |  | 
| 2058 |  |  |  |  |  |  |  | 
| 2059 |  |  |  |  |  |  | #  Store away for this block | 
| 2060 |  |  |  |  |  |  | # | 
| 2061 | 4 |  | 50 |  |  | 5 | push @{$self->{'_block_render'}{$name}{$data_block_ar} ||= []}, $html_sr; | 
|  | 4 |  |  |  |  | 18 |  | 
| 2062 |  |  |  |  |  |  |  | 
| 2063 |  |  |  |  |  |  |  | 
| 2064 |  |  |  |  |  |  | #  Store | 
| 2065 |  |  |  |  |  |  | # | 
| 2066 | 4 |  |  |  |  | 8 | push @html_sr, $html_sr; | 
| 2067 |  |  |  |  |  |  |  | 
| 2068 |  |  |  |  |  |  |  | 
| 2069 |  |  |  |  |  |  | } | 
| 2070 | 3 | 50 |  |  |  | 9 | if (@html_sr) { | 
| 2071 |  |  |  |  |  |  |  | 
| 2072 |  |  |  |  |  |  |  | 
| 2073 |  |  |  |  |  |  | #  Return scalar or array ref, depending on number of elements | 
| 2074 |  |  |  |  |  |  | # | 
| 2075 |  |  |  |  |  |  | #0 && debug('returning %s', Dumper(\@html_sr)); | 
| 2076 | 3 | 100 |  |  |  | 60 | return $#html_sr ? $html_sr[0] : \@html_sr; | 
| 2077 |  |  |  |  |  |  |  | 
| 2078 |  |  |  |  |  |  | } | 
| 2079 |  |  |  |  |  |  | else { | 
| 2080 |  |  |  |  |  |  |  | 
| 2081 |  |  |  |  |  |  |  | 
| 2082 |  |  |  |  |  |  | #  No, could not find block below us, store param away for later | 
| 2083 |  |  |  |  |  |  | #  render. NOTE now done for all blocks so work both in and out of | 
| 2084 |  |  |  |  |  |  | #   section. Moved this code above | 
| 2085 |  |  |  |  |  |  | # | 
| 2086 |  |  |  |  |  |  | #push @{$self->{'_block_param'}{$name} ||=[]},$param_hr->{'param'}; | 
| 2087 |  |  |  |  |  |  |  | 
| 2088 |  |  |  |  |  |  |  | 
| 2089 |  |  |  |  |  |  | #  Debug | 
| 2090 |  |  |  |  |  |  | # | 
| 2091 | 0 |  |  |  |  | 0 | 0 && debug("block $name not found in tree, storing params for later render"); | 
| 2092 |  |  |  |  |  |  |  | 
| 2093 |  |  |  |  |  |  |  | 
| 2094 |  |  |  |  |  |  | #  Done, return undef at this stage | 
| 2095 |  |  |  |  |  |  | # | 
| 2096 | 0 |  |  |  |  | 0 | return \undef; | 
| 2097 |  |  |  |  |  |  |  | 
| 2098 |  |  |  |  |  |  | } | 
| 2099 |  |  |  |  |  |  |  | 
| 2100 |  |  |  |  |  |  |  | 
| 2101 |  |  |  |  |  |  | } | 
| 2102 |  |  |  |  |  |  |  | 
| 2103 |  |  |  |  |  |  |  | 
| 2104 |  |  |  |  |  |  | sub block { | 
| 2105 |  |  |  |  |  |  |  | 
| 2106 |  |  |  |  |  |  |  | 
| 2107 |  |  |  |  |  |  | #  Called when we encounter a  tag | 
| 2108 |  |  |  |  |  |  | # | 
| 2109 | 11 |  |  | 11 | 0 | 19 | my ($self, $data_ar, $attr_hr, $param_data_hr, $text)=@_; | 
| 2110 | 11 |  |  |  |  | 13 | 0 && debug("in block code, data_ar $data_ar"); | 
| 2111 |  |  |  |  |  |  |  | 
| 2112 |  |  |  |  |  |  |  | 
| 2113 |  |  |  |  |  |  | #  Get block name | 
| 2114 |  |  |  |  |  |  | # | 
| 2115 | 11 |  | 50 |  |  | 25 | my $name=$attr_hr->{'name'} || | 
| 2116 |  |  |  |  |  |  | return err ('no block name specified'); | 
| 2117 | 11 |  |  |  |  | 13 | 0 && debug("in block, looking for name $name, attr given %s", Dumper($attr_hr)); | 
| 2118 |  |  |  |  |  |  |  | 
| 2119 |  |  |  |  |  |  |  | 
| 2120 |  |  |  |  |  |  | #  Only render if registered, do once for every time spec'd | 
| 2121 |  |  |  |  |  |  | # | 
| 2122 | 11 | 100 |  |  |  | 40 | if (exists($self->{'_block_render'}{$name}{$data_ar})) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 2123 |  |  |  |  |  |  |  | 
| 2124 |  |  |  |  |  |  |  | 
| 2125 |  |  |  |  |  |  | #  The block name has been pre-rendered - return it | 
| 2126 |  |  |  |  |  |  | # | 
| 2127 | 4 |  |  |  |  | 6 | 0 && debug("found pre-rendered block $name"); | 
| 2128 |  |  |  |  |  |  |  | 
| 2129 |  |  |  |  |  |  |  | 
| 2130 |  |  |  |  |  |  | #  Var to hold render result | 
| 2131 |  |  |  |  |  |  | # | 
| 2132 | 4 |  |  |  |  | 9 | my $html_ar=delete $self->{'_block_render'}{$name}{$data_ar}; | 
| 2133 |  |  |  |  |  |  |  | 
| 2134 |  |  |  |  |  |  |  | 
| 2135 |  |  |  |  |  |  | #  Return result as a single scalar ref | 
| 2136 |  |  |  |  |  |  | # | 
| 2137 | 4 |  |  |  |  | 9 | return \join(undef, map {${$_}} @{$html_ar}); | 
|  | 4 |  |  |  |  | 6 |  | 
|  | 4 |  |  |  |  | 30 |  | 
|  | 4 |  |  |  |  | 8 |  | 
| 2138 |  |  |  |  |  |  |  | 
| 2139 |  |  |  |  |  |  |  | 
| 2140 |  |  |  |  |  |  | } | 
| 2141 |  |  |  |  |  |  | elsif (exists($self->{'_block_param'}{$name})) { | 
| 2142 |  |  |  |  |  |  |  | 
| 2143 |  |  |  |  |  |  |  | 
| 2144 |  |  |  |  |  |  | #  The block params have been registered, but the block itself was | 
| 2145 |  |  |  |  |  |  | #  not yet rendered. Do it now | 
| 2146 |  |  |  |  |  |  | # | 
| 2147 | 3 |  |  |  |  | 5 | 0 && debug("found block param for $name in register"); | 
| 2148 |  |  |  |  |  |  |  | 
| 2149 |  |  |  |  |  |  |  | 
| 2150 |  |  |  |  |  |  | #  Var to hold render result | 
| 2151 |  |  |  |  |  |  | # | 
| 2152 | 3 |  |  |  |  | 4 | my @html_sr; | 
| 2153 |  |  |  |  |  |  |  | 
| 2154 |  |  |  |  |  |  |  | 
| 2155 |  |  |  |  |  |  | #  Render the block for as many times as it has parameters associated | 
| 2156 |  |  |  |  |  |  | #  with it, eg user may have called ->render_block several times in | 
| 2157 |  |  |  |  |  |  | #  their code | 
| 2158 |  |  |  |  |  |  | # | 
| 2159 | 3 |  |  |  |  | 3 | foreach my $param_data_block_hr (@{$self->{'_block_param'}{$name}}) { | 
|  | 3 |  |  |  |  | 8 |  | 
| 2160 |  |  |  |  |  |  |  | 
| 2161 |  |  |  |  |  |  |  | 
| 2162 |  |  |  |  |  |  | #  If no explicit data hash, use parent hash - not sure how useful | 
| 2163 |  |  |  |  |  |  | #  this really is | 
| 2164 |  |  |  |  |  |  | # | 
| 2165 | 3 |  | 33 |  |  | 7 | $param_data_block_hr ||= $param_data_hr; | 
| 2166 |  |  |  |  |  |  |  | 
| 2167 |  |  |  |  |  |  |  | 
| 2168 |  |  |  |  |  |  | #  Debug | 
| 2169 |  |  |  |  |  |  | # | 
| 2170 | 3 |  |  |  |  | 3 | 0 && debug("about to render block $name, param %s", Dumper($param_data_block_hr)); | 
| 2171 |  |  |  |  |  |  |  | 
| 2172 |  |  |  |  |  |  |  | 
| 2173 |  |  |  |  |  |  | #  Render it | 
| 2174 |  |  |  |  |  |  | # | 
| 2175 | 3 |  | 50 |  |  | 10 | push @html_sr, $self->render( | 
| 2176 |  |  |  |  |  |  | { | 
| 2177 |  |  |  |  |  |  |  | 
| 2178 |  |  |  |  |  |  | data  => $data_ar->[$WEBDYNE_NODE_CHLD_IX], | 
| 2179 |  |  |  |  |  |  | param => $param_data_block_hr | 
| 2180 |  |  |  |  |  |  |  | 
| 2181 |  |  |  |  |  |  | }) || return err (); | 
| 2182 |  |  |  |  |  |  |  | 
| 2183 |  |  |  |  |  |  | } | 
| 2184 |  |  |  |  |  |  |  | 
| 2185 |  |  |  |  |  |  |  | 
| 2186 |  |  |  |  |  |  | #  Return result as a single scalar ref | 
| 2187 |  |  |  |  |  |  | # | 
| 2188 | 3 |  |  |  |  | 6 | return \join(undef, map {${$_}} @html_sr); | 
|  | 3 |  |  |  |  | 3 |  | 
|  | 3 |  |  |  |  | 12 |  | 
| 2189 |  |  |  |  |  |  |  | 
| 2190 |  |  |  |  |  |  | } | 
| 2191 |  |  |  |  |  |  | elsif ($attr_hr->{'display'}) { | 
| 2192 |  |  |  |  |  |  |  | 
| 2193 |  |  |  |  |  |  |  | 
| 2194 |  |  |  |  |  |  | #  User wants block displayed normally | 
| 2195 |  |  |  |  |  |  | # | 
| 2196 | 1 |  | 33 |  |  | 8 | return $self->render( | 
| 2197 |  |  |  |  |  |  | { | 
| 2198 |  |  |  |  |  |  |  | 
| 2199 |  |  |  |  |  |  | data  => $data_ar->[$WEBDYNE_NODE_CHLD_IX], | 
| 2200 |  |  |  |  |  |  | param => $param_data_hr | 
| 2201 |  |  |  |  |  |  |  | 
| 2202 |  |  |  |  |  |  | }) || err (); | 
| 2203 |  |  |  |  |  |  |  | 
| 2204 |  |  |  |  |  |  | } | 
| 2205 |  |  |  |  |  |  | else { | 
| 2206 |  |  |  |  |  |  |  | 
| 2207 |  |  |  |  |  |  |  | 
| 2208 |  |  |  |  |  |  | #  Block name not registered, therefore do not render - return | 
| 2209 |  |  |  |  |  |  | #  blank | 
| 2210 |  |  |  |  |  |  | # | 
| 2211 | 3 |  |  |  |  | 8 | return \undef; | 
| 2212 |  |  |  |  |  |  |  | 
| 2213 |  |  |  |  |  |  | } | 
| 2214 |  |  |  |  |  |  |  | 
| 2215 |  |  |  |  |  |  |  | 
| 2216 |  |  |  |  |  |  | } | 
| 2217 |  |  |  |  |  |  |  | 
| 2218 |  |  |  |  |  |  |  | 
| 2219 |  |  |  |  |  |  | sub perl { | 
| 2220 |  |  |  |  |  |  |  | 
| 2221 |  |  |  |  |  |  |  | 
| 2222 |  |  |  |  |  |  | #  Called when we encounter a  tag | 
| 2223 |  |  |  |  |  |  | # | 
| 2224 | 26 |  |  | 26 | 0 | 53 | my ($self, $data_ar, $attr_hr, $param_data_hr, $text)=@_; | 
| 2225 |  |  |  |  |  |  |  | 
| 2226 |  |  |  |  |  |  | #0 && debug("rendering perl tag in block $data_ar, attr %s"); | 
| 2227 |  |  |  |  |  |  |  | 
| 2228 |  |  |  |  |  |  |  | 
| 2229 |  |  |  |  |  |  | #  If inline, run now | 
| 2230 |  |  |  |  |  |  | # | 
| 2231 | 26 | 100 |  |  |  | 51 | if (my $perl_code=$attr_hr->{'perl'}) { | 
| 2232 |  |  |  |  |  |  |  | 
| 2233 |  |  |  |  |  |  |  | 
| 2234 |  |  |  |  |  |  | #  May be inline code params to supply to this block | 
| 2235 |  |  |  |  |  |  | # | 
| 2236 | 6 |  |  |  |  | 12 | my $perl_param_hr=$attr_hr->{'param'}; | 
| 2237 |  |  |  |  |  |  |  | 
| 2238 |  |  |  |  |  |  |  | 
| 2239 |  |  |  |  |  |  | #  Run the same code as the inline eval (!{! ... !}) would run, | 
| 2240 |  |  |  |  |  |  | #  for consistancy | 
| 2241 |  |  |  |  |  |  | # | 
| 2242 | 6 |  | 33 |  |  | 17 | return $Package{'_eval_cr'}{'!'}->($self, $data_ar, $perl_param_hr, $perl_code) || | 
| 2243 |  |  |  |  |  |  | err (); | 
| 2244 |  |  |  |  |  |  |  | 
| 2245 |  |  |  |  |  |  |  | 
| 2246 |  |  |  |  |  |  | } | 
| 2247 |  |  |  |  |  |  | else { | 
| 2248 |  |  |  |  |  |  |  | 
| 2249 |  |  |  |  |  |  |  | 
| 2250 |  |  |  |  |  |  | #  Not inline, must want to call a handler, get method and caller | 
| 2251 |  |  |  |  |  |  | # | 
| 2252 |  |  |  |  |  |  | #my $function=join('::', grep {$_} @{$attr_hr}{qw(package class method)}) || | 
| 2253 | 20 |  | 50 |  |  | 37 | my $function=join('::', grep {$_} map {exists($attr_hr->{$_}) && $attr_hr->{$_}} qw(package class method)) || | 
| 2254 |  |  |  |  |  |  | return err ('could not determine perl routine to run'); | 
| 2255 |  |  |  |  |  |  |  | 
| 2256 |  |  |  |  |  |  |  | 
| 2257 |  |  |  |  |  |  | #  Try to get the package name as an array, pop the method off | 
| 2258 |  |  |  |  |  |  | # | 
| 2259 | 20 |  |  |  |  | 79 | my @package=split(/\:+/, $function); | 
| 2260 | 20 |  |  |  |  | 33 | my $method=pop @package; | 
| 2261 |  |  |  |  |  |  |  | 
| 2262 |  |  |  |  |  |  |  | 
| 2263 |  |  |  |  |  |  | #  And return package | 
| 2264 |  |  |  |  |  |  | # | 
| 2265 | 20 |  |  |  |  | 42 | my $package=join('::', grep {$_} @package); | 
|  | 0 |  |  |  |  | 0 |  | 
| 2266 |  |  |  |  |  |  |  | 
| 2267 |  |  |  |  |  |  |  | 
| 2268 |  |  |  |  |  |  | #  Debug | 
| 2269 |  |  |  |  |  |  | # | 
| 2270 | 20 |  |  |  |  | 22 | 0 && debug("perl package $package, method $method"); | 
| 2271 |  |  |  |  |  |  |  | 
| 2272 |  |  |  |  |  |  |  | 
| 2273 |  |  |  |  |  |  | #  If no method by now, dud caller | 
| 2274 |  |  |  |  |  |  | # | 
| 2275 | 20 | 50 |  |  |  | 97 | $method || | 
| 2276 |  |  |  |  |  |  | return err ("no package/method in perl block"); | 
| 2277 |  |  |  |  |  |  |  | 
| 2278 |  |  |  |  |  |  |  | 
| 2279 |  |  |  |  |  |  | #  If the require fails, we want to catch it in an eval | 
| 2280 |  |  |  |  |  |  | #  and return a meaningful error message. BTW this is an | 
| 2281 |  |  |  |  |  |  | #  order of magnitued faster than doing eval("require $package"); | 
| 2282 |  |  |  |  |  |  | # | 
| 2283 | 20 | 50 |  |  |  | 38 | 0 && debug("about to require $package") if $package; | 
| 2284 | 20 |  |  |  |  | 38 | my $package_fn=join('/', @package) . '.pm'; | 
| 2285 | 20 | 50 | 33 |  |  | 87 | if ($package && !$INC{$package_fn}) { | 
| 2286 |  |  |  |  |  |  |  | 
| 2287 |  |  |  |  |  |  | #  Add psp file cwd to INC incase package stored in same dir | 
| 2288 |  |  |  |  |  |  | # | 
| 2289 | 0 |  |  |  |  | 0 | local @INC=@INC; | 
| 2290 | 0 |  |  |  |  | 0 | push @INC, $self->cwd(); | 
| 2291 | 0 | 0 | 0 |  |  | 0 | eval {require $package_fn} || | 
|  | 0 |  |  |  |  | 0 |  | 
| 2292 |  |  |  |  |  |  | return errsubst( | 
| 2293 |  |  |  |  |  |  | "error loading package '$package', %s", errstr() || $@ || 'undefined error' | 
| 2294 |  |  |  |  |  |  | ) | 
| 2295 |  |  |  |  |  |  | } | 
| 2296 | 20 |  |  |  |  | 27 | 0 && debug("package $package loaded OK"); | 
| 2297 |  |  |  |  |  |  |  | 
| 2298 |  |  |  |  |  |  |  | 
| 2299 |  |  |  |  |  |  | #  Push data_ar so we can use it if the perl routine calls self->render(). render() | 
| 2300 |  |  |  |  |  |  | #  then has to "know" where it is in the data_ar structure, and can get that info | 
| 2301 |  |  |  |  |  |  | #  here. | 
| 2302 |  |  |  |  |  |  | # | 
| 2303 |  |  |  |  |  |  | #unshift @{$self->{'_perl'}}, $data_ar->[$WEBDYNE_NODE_CHLD_IX]; | 
| 2304 | 20 |  |  |  |  | 26 | unshift @{$self->{'_perl'}}, $data_ar; | 
|  | 20 |  |  |  |  | 58 |  | 
| 2305 |  |  |  |  |  |  |  | 
| 2306 |  |  |  |  |  |  |  | 
| 2307 |  |  |  |  |  |  | #  Run the eval code to get HTML | 
| 2308 |  |  |  |  |  |  | # | 
| 2309 | 20 |  | 33 |  |  | 132 | my $html_sr=$Package{'_eval_cr'}{'!'}->($self, $data_ar, $attr_hr->{'param'}, "&${function}") || do { | 
| 2310 |  |  |  |  |  |  |  | 
| 2311 |  |  |  |  |  |  |  | 
| 2312 |  |  |  |  |  |  | #  Error occurred. Pop data ref off stack and return | 
| 2313 |  |  |  |  |  |  | # | 
| 2314 |  |  |  |  |  |  | shift @{$self->{'_perl'}}; | 
| 2315 |  |  |  |  |  |  | return err (); | 
| 2316 |  |  |  |  |  |  |  | 
| 2317 |  |  |  |  |  |  |  | 
| 2318 |  |  |  |  |  |  | }; | 
| 2319 |  |  |  |  |  |  |  | 
| 2320 |  |  |  |  |  |  |  | 
| 2321 |  |  |  |  |  |  | #  Debug | 
| 2322 |  |  |  |  |  |  | # | 
| 2323 |  |  |  |  |  |  | #0 && debug('perl eval return %s', Dumper($html_sr)); | 
| 2324 |  |  |  |  |  |  |  | 
| 2325 |  |  |  |  |  |  |  | 
| 2326 |  |  |  |  |  |  | #  Modify return value if we were returned an array. COMMENTED OUT - is done in eval | 
| 2327 |  |  |  |  |  |  | # | 
| 2328 |  |  |  |  |  |  | #(ref($html_sr) eq 'ARRAY') && do { | 
| 2329 |  |  |  |  |  |  | #    $html_sr=\ join(undef, map { ref($_) ? ${$_} : $_ } @{$html_sr}) | 
| 2330 |  |  |  |  |  |  | #}; | 
| 2331 |  |  |  |  |  |  |  | 
| 2332 |  |  |  |  |  |  |  | 
| 2333 |  |  |  |  |  |  | #  Unless we have a scalar ref by now, the eval returned the | 
| 2334 |  |  |  |  |  |  | #  wrong type of value. | 
| 2335 |  |  |  |  |  |  | # | 
| 2336 | 20 | 50 |  |  |  | 64 | (ref($html_sr) eq 'SCALAR') || do { | 
| 2337 |  |  |  |  |  |  |  | 
| 2338 |  |  |  |  |  |  |  | 
| 2339 |  |  |  |  |  |  | #  Error occurred. Pop data ref off stack and return | 
| 2340 |  |  |  |  |  |  | # | 
| 2341 | 0 |  |  |  |  | 0 | shift @{$self->{'_perl'}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2342 | 0 |  |  |  |  | 0 | return err ("error in perl method '$method'- code did not return a SCALAR ref value."); | 
| 2343 |  |  |  |  |  |  |  | 
| 2344 |  |  |  |  |  |  | }; | 
| 2345 |  |  |  |  |  |  |  | 
| 2346 |  |  |  |  |  |  |  | 
| 2347 |  |  |  |  |  |  | #  Any printed data ?  COMMENTED OUT - is done in eval | 
| 2348 |  |  |  |  |  |  | # | 
| 2349 |  |  |  |  |  |  | #$self->{'_print_ar'} && do { | 
| 2350 |  |  |  |  |  |  | #    $html_sr=\ join(undef, grep {$_} map { ref($_) ? ${$_} : $_ } @{delete $self->{'_print_ar'}}) }; | 
| 2351 |  |  |  |  |  |  |  | 
| 2352 |  |  |  |  |  |  |  | 
| 2353 |  |  |  |  |  |  | #  Shift perl data_ar ref from stack | 
| 2354 |  |  |  |  |  |  | # | 
| 2355 | 20 |  |  |  |  | 24 | shift @{$self->{'_perl'}}; | 
|  | 20 |  |  |  |  | 35 |  | 
| 2356 |  |  |  |  |  |  |  | 
| 2357 |  |  |  |  |  |  |  | 
| 2358 |  |  |  |  |  |  | #  And return scalar val | 
| 2359 |  |  |  |  |  |  | # | 
| 2360 | 20 |  |  |  |  | 57 | return $html_sr | 
| 2361 |  |  |  |  |  |  |  | 
| 2362 |  |  |  |  |  |  | } | 
| 2363 |  |  |  |  |  |  |  | 
| 2364 |  |  |  |  |  |  | } | 
| 2365 |  |  |  |  |  |  |  | 
| 2366 |  |  |  |  |  |  |  | 
| 2367 |  |  |  |  |  |  | sub perl_init { | 
| 2368 |  |  |  |  |  |  |  | 
| 2369 |  |  |  |  |  |  |  | 
| 2370 |  |  |  |  |  |  | #  Init the perl package space for this inode | 
| 2371 |  |  |  |  |  |  | # | 
| 2372 | 18 |  |  | 18 | 0 | 42 | my ($self, $perl_ar, $perl_debug_ar)=@_; | 
| 2373 | 18 |  | 50 |  |  | 46 | my $inode=$self->{'_inode'} || 'ANON';    #ANON used when run from command line | 
| 2374 |  |  |  |  |  |  |  | 
| 2375 |  |  |  |  |  |  |  | 
| 2376 |  |  |  |  |  |  | #  Prep package space | 
| 2377 |  |  |  |  |  |  | # | 
| 2378 | 18 |  |  |  |  | 21 | 0 && debug("perl_init inode $inode"); | 
| 2379 |  |  |  |  |  |  |  | 
| 2380 |  |  |  |  |  |  | #$Package{'_cache'}{$inode}{'perl_init'}++ && return \undef; | 
| 2381 | 18 |  |  |  |  | 19 | 0 && debug("init perl code $perl_ar, %s", Dumper($perl_ar)); | 
| 2382 | 18 |  |  |  |  | 39 | *{"WebDyne::${inode}::err"}=\&err; | 
|  | 18 |  |  |  |  | 125 |  | 
| 2383 | 18 |  |  | 0 |  | 69 | *{"WebDyne::${inode}::self"}=sub     {$self}; | 
|  | 18 |  |  |  |  | 67 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 2384 | 18 |  |  | 0 |  | 68 | *{"WebDyne::${inode}::AUTOLOAD"}=sub {die("unknown function $AUTOLOAD")}; | 
|  | 18 |  |  |  |  | 105 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 2385 |  |  |  |  |  |  |  | 
| 2386 |  |  |  |  |  |  |  | 
| 2387 |  |  |  |  |  |  | #  Run each piece of perl code | 
| 2388 |  |  |  |  |  |  | # | 
| 2389 | 18 |  |  |  |  | 34 | foreach my $ix (0..$#{$perl_ar}) { | 
|  | 18 |  |  |  |  | 66 |  | 
| 2390 |  |  |  |  |  |  |  | 
| 2391 |  |  |  |  |  |  |  | 
| 2392 |  |  |  |  |  |  | #  Get perl code and debug information | 
| 2393 |  |  |  |  |  |  | # | 
| 2394 | 9 |  |  |  |  | 18 | my $perl_sr=$perl_ar->[$ix]; | 
| 2395 | 9 |  |  |  |  | 13 | my ($perl_line_no, $perl_srce_fn)=@{$perl_debug_ar->[$ix]}; | 
|  | 9 |  |  |  |  | 20 |  | 
| 2396 |  |  |  |  |  |  |  | 
| 2397 |  |  |  |  |  |  |  | 
| 2398 |  |  |  |  |  |  | #  Do not execute twice | 
| 2399 |  |  |  |  |  |  | # | 
| 2400 | 9 | 50 |  |  |  | 56 | $Package{'_cache'}{$inode}{'perl_init'}{$perl_sr}++ && next; | 
| 2401 |  |  |  |  |  |  |  | 
| 2402 |  |  |  |  |  |  |  | 
| 2403 |  |  |  |  |  |  | #  Set inc to include psp dir so can include packages easily | 
| 2404 |  |  |  |  |  |  | # | 
| 2405 | 9 |  |  |  |  | 99 | local @INC=@INC; | 
| 2406 | 9 |  |  |  |  | 42 | push @INC, $self->cwd(); | 
| 2407 |  |  |  |  |  |  |  | 
| 2408 |  |  |  |  |  |  |  | 
| 2409 |  |  |  |  |  |  | #  Wrap in anon CR, eval for syntax | 
| 2410 |  |  |  |  |  |  | # | 
| 2411 | 9 | 50 |  |  |  | 64 | if ($WEBDYNE_EVAL_SAFE) { | 
| 2412 |  |  |  |  |  |  |  | 
| 2413 |  |  |  |  |  |  |  | 
| 2414 |  |  |  |  |  |  | #  Safe mode, vars don't matter so much | 
| 2415 |  |  |  |  |  |  | # | 
| 2416 | 0 |  | 0 |  |  | 0 | my $safe_or=$self->{'_eval_safe'} || do { | 
| 2417 |  |  |  |  |  |  | 0 && debug('safe init (perl_init)'); | 
| 2418 |  |  |  |  |  |  | require Safe; | 
| 2419 |  |  |  |  |  |  | require Opcode; | 
| 2420 |  |  |  |  |  |  |  | 
| 2421 |  |  |  |  |  |  | #Safe->new($self->{'_inode'}); | 
| 2422 |  |  |  |  |  |  | Safe->new(); | 
| 2423 |  |  |  |  |  |  | }; | 
| 2424 | 0 |  | 0 |  |  | 0 | $self->{'_eval_safe'} ||= do { | 
| 2425 | 0 |  |  |  |  | 0 | $safe_or->permit_only(@{$WEBDYNE_EVAL_SAFE_OPCODE_AR}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 2426 | 0 |  |  |  |  | 0 | $safe_or; | 
| 2427 |  |  |  |  |  |  | }; | 
| 2428 | 0 | 0 |  |  |  | 0 | $safe_or->reval(${$perl_sr}, $WebDyne::WEBDYNE_EVAL_USE_STRICT) || do { | 
|  | 0 |  |  |  |  | 0 |  | 
| 2429 |  |  |  |  |  |  |  | 
| 2430 |  |  |  |  |  |  |  | 
| 2431 |  |  |  |  |  |  | #  Nothing was returned  - did an error occur ? | 
| 2432 |  |  |  |  |  |  | # | 
| 2433 | 0 | 0 | 0 |  |  | 0 | if ($@ || errstr()) { | 
| 2434 |  |  |  |  |  |  |  | 
| 2435 |  |  |  |  |  |  | #  An error has occurred. Deregister self subroutine call in package | 
| 2436 |  |  |  |  |  |  | # | 
| 2437 | 0 |  |  |  |  | 0 | undef *{"WebDyne::${inode}::self"}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2438 |  |  |  |  |  |  |  | 
| 2439 |  |  |  |  |  |  |  | 
| 2440 |  |  |  |  |  |  | #  Make up a fake data block with details of error | 
| 2441 |  |  |  |  |  |  | # | 
| 2442 | 0 |  |  |  |  | 0 | my @data; | 
| 2443 | 0 |  |  |  |  | 0 | @data[ | 
| 2444 |  |  |  |  |  |  | $WEBDYNE_NODE_LINE_IX, | 
| 2445 |  |  |  |  |  |  | $WEBDYNE_NODE_LINE_TAG_END_IX, | 
| 2446 |  |  |  |  |  |  | $WEBDYNE_NODE_SRCE_IX, | 
| 2447 |  |  |  |  |  |  | ]=($perl_line_no, $perl_line_no, $perl_srce_fn); | 
| 2448 |  |  |  |  |  |  |  | 
| 2449 |  |  |  |  |  |  |  | 
| 2450 |  |  |  |  |  |  | #  Save away as current data block for reference by error handler | 
| 2451 |  |  |  |  |  |  | # | 
| 2452 | 0 |  |  |  |  | 0 | $self->{'_data_ar'}=\@data; | 
| 2453 |  |  |  |  |  |  |  | 
| 2454 |  |  |  |  |  |  |  | 
| 2455 |  |  |  |  |  |  | #  Throw error | 
| 2456 |  |  |  |  |  |  | # | 
| 2457 | 0 | 0 |  |  |  | 0 | return $self->err_eval($@ ? "error in __PERL__ block: $@" : undef, $perl_sr); | 
| 2458 |  |  |  |  |  |  |  | 
| 2459 |  |  |  |  |  |  | } | 
| 2460 |  |  |  |  |  |  | }; | 
| 2461 |  |  |  |  |  |  |  | 
| 2462 |  |  |  |  |  |  |  | 
| 2463 |  |  |  |  |  |  | } | 
| 2464 |  |  |  |  |  |  | else { | 
| 2465 |  |  |  |  |  |  |  | 
| 2466 |  |  |  |  |  |  |  | 
| 2467 |  |  |  |  |  |  | #  Now init the perl code | 
| 2468 |  |  |  |  |  |  | # | 
| 2469 | 9 |  | 66 |  |  | 70 | my $eval_cr=&perl_init_cr($inode, $perl_sr, $perl_line_no) || do { | 
| 2470 |  |  |  |  |  |  |  | 
| 2471 |  |  |  |  |  |  |  | 
| 2472 |  |  |  |  |  |  | #  Nothing was returned from perl_init - did an error occur ? | 
| 2473 |  |  |  |  |  |  | # | 
| 2474 |  |  |  |  |  |  | if ($@ || errstr()) { | 
| 2475 |  |  |  |  |  |  |  | 
| 2476 |  |  |  |  |  |  |  | 
| 2477 |  |  |  |  |  |  | #  An error has occurred. Deregister self subroutine call in package | 
| 2478 |  |  |  |  |  |  | # | 
| 2479 |  |  |  |  |  |  | undef *{"WebDyne::${inode}::self"}; | 
| 2480 |  |  |  |  |  |  |  | 
| 2481 |  |  |  |  |  |  |  | 
| 2482 |  |  |  |  |  |  | #  Make up a fake data block with details of error | 
| 2483 |  |  |  |  |  |  | # | 
| 2484 |  |  |  |  |  |  | my @data; | 
| 2485 |  |  |  |  |  |  | @data[ | 
| 2486 |  |  |  |  |  |  | $WEBDYNE_NODE_LINE_IX, | 
| 2487 |  |  |  |  |  |  | $WEBDYNE_NODE_LINE_TAG_END_IX, | 
| 2488 |  |  |  |  |  |  | $WEBDYNE_NODE_SRCE_IX, | 
| 2489 |  |  |  |  |  |  | ]=($perl_line_no, $perl_line_no, $perl_srce_fn); | 
| 2490 |  |  |  |  |  |  |  | 
| 2491 |  |  |  |  |  |  |  | 
| 2492 |  |  |  |  |  |  | #  Save away as current data block for reference by error handler | 
| 2493 |  |  |  |  |  |  | # | 
| 2494 |  |  |  |  |  |  | $self->{'_data_ar'}=\@data; | 
| 2495 |  |  |  |  |  |  |  | 
| 2496 |  |  |  |  |  |  |  | 
| 2497 |  |  |  |  |  |  | #  Throw error | 
| 2498 |  |  |  |  |  |  | # | 
| 2499 |  |  |  |  |  |  | return $self->err_eval($@ ? "error in __PERL__ block: $@" : undef, $perl_sr); | 
| 2500 |  |  |  |  |  |  |  | 
| 2501 |  |  |  |  |  |  | } | 
| 2502 |  |  |  |  |  |  | }; | 
| 2503 |  |  |  |  |  |  | } | 
| 2504 |  |  |  |  |  |  |  | 
| 2505 |  |  |  |  |  |  |  | 
| 2506 |  |  |  |  |  |  | } | 
| 2507 |  |  |  |  |  |  |  | 
| 2508 |  |  |  |  |  |  |  | 
| 2509 |  |  |  |  |  |  | #  Done | 
| 2510 |  |  |  |  |  |  | # | 
| 2511 | 18 |  |  |  |  | 34 | undef *{"WebDyne::${inode}::self"}; | 
|  | 18 |  |  |  |  | 136 |  | 
| 2512 | 18 |  |  |  |  | 29 | 0 && debug('perl_init complete'); | 
| 2513 | 18 |  |  |  |  | 90 | \undef; | 
| 2514 |  |  |  |  |  |  |  | 
| 2515 |  |  |  |  |  |  | } | 
| 2516 |  |  |  |  |  |  |  | 
| 2517 |  |  |  |  |  |  |  | 
| 2518 |  |  |  |  |  |  | sub subst { | 
| 2519 |  |  |  |  |  |  |  | 
| 2520 |  |  |  |  |  |  |  | 
| 2521 |  |  |  |  |  |  | #  Called to eval text block, replace params | 
| 2522 |  |  |  |  |  |  | # | 
| 2523 | 16 |  |  | 16 | 0 | 34 | my ($self, $data_ar, $attr_hr, $param_data_hr, $text)=@_; | 
| 2524 |  |  |  |  |  |  |  | 
| 2525 |  |  |  |  |  |  |  | 
| 2526 |  |  |  |  |  |  | #  Debug | 
| 2527 |  |  |  |  |  |  | # | 
| 2528 | 16 |  |  |  |  | 20 | 0 && debug("eval $text %s", Dumper($param_data_hr)); | 
| 2529 |  |  |  |  |  |  |  | 
| 2530 |  |  |  |  |  |  |  | 
| 2531 |  |  |  |  |  |  | #  Get eval code refs for subst | 
| 2532 |  |  |  |  |  |  | # | 
| 2533 | 16 |  | 50 |  |  | 43 | my $eval_cr=$Package{'_eval_cr'} || | 
| 2534 |  |  |  |  |  |  | return err ('unable to get eval code ref table'); | 
| 2535 |  |  |  |  |  |  |  | 
| 2536 |  |  |  |  |  |  |  | 
| 2537 |  |  |  |  |  |  | #  Do we have to replace something in the text, look for pattern. We | 
| 2538 |  |  |  |  |  |  | #  should always find something, as subst tag is only inserted at | 
| 2539 |  |  |  |  |  |  | #  compile time in front of text with one of theses patterns | 
| 2540 |  |  |  |  |  |  | # | 
| 2541 | 16 |  |  |  |  | 20 | my $index; | 
| 2542 |  |  |  |  |  |  | my $cr=sub { | 
| 2543 | 19 |  | 50 | 19 |  | 120 | my $sr=$eval_cr->{$_[0]}($self, $data_ar, $param_data_hr, $_[1], $_[2]) || | 
| 2544 |  |  |  |  |  |  | return err (); | 
| 2545 | 19 | 50 |  |  |  | 53 | (ref($sr) eq 'SCALAR') || | 
| 2546 |  |  |  |  |  |  | return err ("eval of '$_[1]' returned %s ref, should return SCALAR ref", ref($sr)); | 
| 2547 | 19 |  |  |  |  | 85 | $sr; | 
| 2548 | 16 |  |  |  |  | 68 | }; | 
| 2549 | 16 | 50 |  |  |  | 135 | $text=~s/([\$!+*^]){1}{(\1?)(.*?)\2}/${$cr->($1,$3,$index++) || return err()}/ge; | 
|  | 19 |  |  |  |  | 33 |  | 
|  | 19 |  |  |  |  | 50 |  | 
| 2550 |  |  |  |  |  |  |  | 
| 2551 |  |  |  |  |  |  |  | 
| 2552 |  |  |  |  |  |  | #  Done | 
| 2553 |  |  |  |  |  |  | # | 
| 2554 | 16 |  |  |  |  | 90 | return \$text; | 
| 2555 |  |  |  |  |  |  |  | 
| 2556 |  |  |  |  |  |  |  | 
| 2557 |  |  |  |  |  |  | } | 
| 2558 |  |  |  |  |  |  |  | 
| 2559 |  |  |  |  |  |  |  | 
| 2560 |  |  |  |  |  |  | sub subst_attr { | 
| 2561 |  |  |  |  |  |  |  | 
| 2562 |  |  |  |  |  |  |  | 
| 2563 |  |  |  |  |  |  | #  Called to eval tag attributes | 
| 2564 |  |  |  |  |  |  | # | 
| 2565 | 18 |  |  | 18 | 0 | 29 | my ($self, $data_ar, $attr_hr, $param_hr)=@_; | 
| 2566 |  |  |  |  |  |  |  | 
| 2567 |  |  |  |  |  |  |  | 
| 2568 |  |  |  |  |  |  | #  Debug | 
| 2569 |  |  |  |  |  |  | # | 
| 2570 | 18 |  |  |  |  | 20 | 0 && debug('subst_attr %s', Dumper({%{$attr_hr}, perl => undef})); | 
| 2571 |  |  |  |  |  |  |  | 
| 2572 |  |  |  |  |  |  |  | 
| 2573 |  |  |  |  |  |  | #  Get eval code refs for subst | 
| 2574 |  |  |  |  |  |  | # | 
| 2575 | 18 |  | 50 |  |  | 45 | my $eval_cr=$Package{'_eval_cr'} || | 
| 2576 |  |  |  |  |  |  | return err ('unable to get eval code ref table'); | 
| 2577 |  |  |  |  |  |  |  | 
| 2578 |  |  |  |  |  |  |  | 
| 2579 |  |  |  |  |  |  | #  Hash to hold results | 
| 2580 |  |  |  |  |  |  | # | 
| 2581 | 18 |  |  |  |  | 24 | my %attr=%{$attr_hr}; | 
|  | 18 |  |  |  |  | 55 |  | 
| 2582 |  |  |  |  |  |  |  | 
| 2583 |  |  |  |  |  |  |  | 
| 2584 |  |  |  |  |  |  | #  Go through each attribute and value | 
| 2585 |  |  |  |  |  |  | # | 
| 2586 | 18 |  |  |  |  | 27 | my $index; | 
| 2587 | 18 |  |  |  |  | 59 | while (my ($attr_name, $attr_value)=each %attr) { | 
| 2588 |  |  |  |  |  |  |  | 
| 2589 |  |  |  |  |  |  |  | 
| 2590 |  |  |  |  |  |  | #  Skip perl attr, as that is perl code, do not do any regexp on perl code, as we will | 
| 2591 |  |  |  |  |  |  | #  probably botch it. | 
| 2592 |  |  |  |  |  |  | # | 
| 2593 | 27 | 50 |  |  |  | 64 | next if ($attr_name eq 'perl'); | 
| 2594 |  |  |  |  |  |  |  | 
| 2595 |  |  |  |  |  |  |  | 
| 2596 |  |  |  |  |  |  | #  Look for attribute value strings that need substitution. First and second attemps did'nt work as single regexp | 
| 2597 |  |  |  |  |  |  | # | 
| 2598 |  |  |  |  |  |  | #if ($attr_value=~/^\s*([\$@%!+*^]){1}{(\1?)([^{]+)\2}\s*$/so ) { | 
| 2599 |  |  |  |  |  |  | #if ($attr_value=~/^\s*([\$@%!+*^]){1}{(\1?)(.*)\2}\s*$/so ) { | 
| 2600 | 27 | 100 | 100 |  |  | 189 | if ($attr_value=~/^\s*([\@%!+*^]){1}{(\1?)(.*)\2}\s*$/so || $attr_value=~/^\s*(\$){1}{(\1?)([^{]+)\2}\s*$/so) { | 
| 2601 |  |  |  |  |  |  |  | 
| 2602 |  |  |  |  |  |  | #  Straightforward $@%!+^ operator, must be only content of value (can't be mixed | 
| 2603 |  |  |  |  |  |  | #  with string, e.g. | 
| 2604 |  |  |  |  |  |  | # | 
| 2605 | 16 |  |  |  |  | 70 | my ($oper, $eval_text)=($1, $3); | 
| 2606 | 16 |  | 50 |  |  | 64 | my $eval=$eval_cr->{$oper}->($self, $data_ar, $param_hr, $eval_text, $index++, 1) || | 
| 2607 |  |  |  |  |  |  | return err (); | 
| 2608 | 16 | 100 |  |  |  | 83 | $attr{$attr_name}=(ref($eval) eq 'SCALAR') ? ${$eval} : $eval; | 
|  | 5 |  |  |  |  | 27 |  | 
| 2609 |  |  |  |  |  |  |  | 
| 2610 |  |  |  |  |  |  | } | 
| 2611 |  |  |  |  |  |  | else { | 
| 2612 |  |  |  |  |  |  |  | 
| 2613 |  |  |  |  |  |  | #  Trickier - might be interspersed in strings, e.g | 
| 2614 |  |  |  |  |  |  | #  Substitution needed | 
| 2615 |  |  |  |  |  |  | # | 
| 2616 |  |  |  |  |  |  | my $cr=sub { | 
| 2617 | 10 |  | 50 | 10 |  | 23 | my $sr=$eval_cr->{$_[0]}($self, $data_ar, $param_hr, $_[1], $_[2]) || | 
| 2618 |  |  |  |  |  |  | return err (); | 
| 2619 | 10 | 50 |  |  |  | 21 | (ref($sr) eq 'SCALAR') || | 
| 2620 |  |  |  |  |  |  | return err ("eval of '$_[1]' returned %s ref, should return SCALAR ref", ref($sr)); | 
| 2621 | 10 |  |  |  |  | 36 | $sr; | 
| 2622 | 11 |  |  |  |  | 53 | }; | 
| 2623 | 11 | 50 |  |  |  | 42 | $attr_value=~s/([\$!+*^]){1}{(\1?)(.*?)\2}/${$cr->($1,$3,$index++) || return err()}/ge; | 
|  | 10 |  |  |  |  | 14 |  | 
|  | 10 |  |  |  |  | 15 |  | 
| 2624 | 11 |  |  |  |  | 68 | $attr{$attr_name}=$attr_value; | 
| 2625 |  |  |  |  |  |  |  | 
| 2626 |  |  |  |  |  |  | } | 
| 2627 |  |  |  |  |  |  |  | 
| 2628 |  |  |  |  |  |  | } | 
| 2629 |  |  |  |  |  |  |  | 
| 2630 |  |  |  |  |  |  |  | 
| 2631 |  |  |  |  |  |  | #  Debug | 
| 2632 |  |  |  |  |  |  | # | 
| 2633 | 18 |  |  |  |  | 29 | 0 && debug('returning attr hash %s', Dumper({%attr, perl => undef})); | 
| 2634 |  |  |  |  |  |  |  | 
| 2635 |  |  |  |  |  |  |  | 
| 2636 |  |  |  |  |  |  | #  Return new attribute hash | 
| 2637 |  |  |  |  |  |  | # | 
| 2638 | 18 |  |  |  |  | 52 | \%attr; | 
| 2639 |  |  |  |  |  |  |  | 
| 2640 |  |  |  |  |  |  | } | 
| 2641 |  |  |  |  |  |  |  | 
| 2642 |  |  |  |  |  |  |  | 
| 2643 |  |  |  |  |  |  | sub include { | 
| 2644 |  |  |  |  |  |  |  | 
| 2645 |  |  |  |  |  |  |  | 
| 2646 |  |  |  |  |  |  | #  Called to include text/psp block. Can be called from  tag or | 
| 2647 |  |  |  |  |  |  | #  perl code, so need to massage params appropriatly. | 
| 2648 |  |  |  |  |  |  | # | 
| 2649 | 5 |  |  | 5 | 0 | 14 | my $self=shift(); | 
| 2650 | 5 |  |  |  |  | 13 | my ($data_ar, $param_hr, $param_data_hr, $text); | 
| 2651 |  |  |  |  |  |  |  | 
| 2652 |  |  |  |  |  |  |  | 
| 2653 |  |  |  |  |  |  | #  Normally get: | 
| 2654 |  |  |  |  |  |  | # | 
| 2655 |  |  |  |  |  |  | #  my ($self, $data_ar, $attr_hr, $param_data_hr, $text)=@_; | 
| 2656 |  |  |  |  |  |  | # | 
| 2657 |  |  |  |  |  |  | #  from tag, but in this case param_hr subs for attr_hr because | 
| 2658 |  |  |  |  |  |  | #  we use that for code called from perl. Check what called us | 
| 2659 |  |  |  |  |  |  | #  now - if first param (after self) is array ref, called from | 
| 2660 |  |  |  |  |  |  | #  tag | 
| 2661 |  |  |  |  |  |  | # | 
| 2662 | 5 | 100 |  |  |  | 16 | if (ref($_[0]) eq 'ARRAY') { | 
| 2663 |  |  |  |  |  |  |  | 
| 2664 |  |  |  |  |  |  | #  Called from  tag | 
| 2665 |  |  |  |  |  |  | # | 
| 2666 | 3 |  |  |  |  | 9 | ($data_ar, $param_hr, $param_data_hr, $text)=@_; | 
| 2667 |  |  |  |  |  |  | } | 
| 2668 |  |  |  |  |  |  | else { | 
| 2669 |  |  |  |  |  |  |  | 
| 2670 |  |  |  |  |  |  | #  Called from perl code, massage params into hr if not already there | 
| 2671 |  |  |  |  |  |  | # | 
| 2672 | 2 |  |  |  |  | 9 | $param_hr=shift(); | 
| 2673 | 2 | 50 |  |  |  | 10 | ref($param_hr) || ($param_hr={file => $param_hr, param => {@_}}); | 
| 2674 |  |  |  |  |  |  |  | 
| 2675 |  |  |  |  |  |  | } | 
| 2676 |  |  |  |  |  |  |  | 
| 2677 |  |  |  |  |  |  |  | 
| 2678 |  |  |  |  |  |  | #  Debug | 
| 2679 |  |  |  |  |  |  | # | 
| 2680 | 5 |  |  |  |  | 6 | 0 && debug('in include, param %s, %s', Dumper($param_hr, $param_data_hr)); | 
| 2681 |  |  |  |  |  |  |  | 
| 2682 |  |  |  |  |  |  |  | 
| 2683 |  |  |  |  |  |  | #  Get CWD | 
| 2684 |  |  |  |  |  |  | # | 
| 2685 | 5 |  | 50 |  |  | 20 | my $r=$self->r() || return err (); | 
| 2686 | 5 |  | 50 |  |  | 19 | my $dn=(File::Spec->splitpath($r->filename()))[1] || | 
| 2687 |  |  |  |  |  |  | return err ('unable to determine cwd for requested file %s', $r->filename()); | 
| 2688 |  |  |  |  |  |  |  | 
| 2689 |  |  |  |  |  |  |  | 
| 2690 |  |  |  |  |  |  | #  Any param must supply a file name as an attribute | 
| 2691 |  |  |  |  |  |  | # | 
| 2692 | 5 |  | 50 |  |  | 44 | my $fn=$param_hr->{'file'} || | 
| 2693 |  |  |  |  |  |  | return err ('no file name supplied with include tag'); | 
| 2694 | 5 |  |  |  |  | 75 | my $pn=File::Spec->rel2abs($fn, $dn); | 
| 2695 |  |  |  |  |  |  |  | 
| 2696 |  |  |  |  |  |  |  | 
| 2697 |  |  |  |  |  |  | #  Check what user wants to do | 
| 2698 |  |  |  |  |  |  | # | 
| 2699 | 5 | 100 |  |  |  | 21 | if (my $node=(grep {exists $param_hr->{$_}} qw(head body))[0]) { | 
|  | 10 | 100 |  |  |  | 43 |  | 
| 2700 |  |  |  |  |  |  |  | 
| 2701 |  |  |  |  |  |  |  | 
| 2702 |  |  |  |  |  |  | #  They want to include the head or body section of an existing pure HTML | 
| 2703 |  |  |  |  |  |  | #  file. | 
| 2704 |  |  |  |  |  |  | # | 
| 2705 | 2 |  |  |  |  | 4 | 0 && debug('head or body render'); | 
| 2706 | 2 |  |  |  |  | 17 | my %option=( | 
| 2707 |  |  |  |  |  |  |  | 
| 2708 |  |  |  |  |  |  | nofilter => 1, | 
| 2709 |  |  |  |  |  |  | noperl   => 1, | 
| 2710 |  |  |  |  |  |  | stage0   => 1, | 
| 2711 |  |  |  |  |  |  | srce     => $pn, | 
| 2712 |  |  |  |  |  |  |  | 
| 2713 |  |  |  |  |  |  | ); | 
| 2714 |  |  |  |  |  |  |  | 
| 2715 |  |  |  |  |  |  | #  compile spec'd file | 
| 2716 |  |  |  |  |  |  | # | 
| 2717 | 2 |  | 50 |  |  | 13 | my $container_ar=$self->compile(\%option) || | 
| 2718 |  |  |  |  |  |  | return err (); | 
| 2719 | 2 |  |  |  |  | 5 | my $block_data_ar=$container_ar->[1]; | 
| 2720 | 2 |  |  |  |  | 5 | 0 && debug('compiled to data_ar %s', Dumper($block_data_ar)); | 
| 2721 |  |  |  |  |  |  |  | 
| 2722 |  |  |  |  |  |  |  | 
| 2723 |  |  |  |  |  |  | #  Find the head or body tag | 
| 2724 |  |  |  |  |  |  | # | 
| 2725 | 2 |  | 50 |  |  | 9 | my $block_ar=$self->find_node( | 
| 2726 |  |  |  |  |  |  | { | 
| 2727 |  |  |  |  |  |  |  | 
| 2728 |  |  |  |  |  |  | data_ar => $block_data_ar, | 
| 2729 |  |  |  |  |  |  | tag     => $node, | 
| 2730 |  |  |  |  |  |  |  | 
| 2731 |  |  |  |  |  |  | }) || return err (); | 
| 2732 | 2 | 50 |  |  |  | 6 | @{$block_ar} || | 
|  | 2 |  |  |  |  | 7 |  | 
| 2733 |  |  |  |  |  |  | return err ("unable to find block '$node' in include file '$fn'"); | 
| 2734 | 2 |  |  |  |  | 4 | 0 && debug('found block_ar %s', Dumper($block_ar)); | 
| 2735 |  |  |  |  |  |  |  | 
| 2736 |  |  |  |  |  |  |  | 
| 2737 |  |  |  |  |  |  | #  Find_node returns array of blocks that match - we only want first | 
| 2738 |  |  |  |  |  |  | # | 
| 2739 | 2 |  |  |  |  | 5 | $block_ar=$block_ar->[0]; | 
| 2740 |  |  |  |  |  |  |  | 
| 2741 |  |  |  |  |  |  |  | 
| 2742 |  |  |  |  |  |  | #  Need to finish compiling now found | 
| 2743 |  |  |  |  |  |  | # | 
| 2744 | 2 | 50 |  |  |  | 9 | $self->optimise_one($block_ar) || return err (); | 
| 2745 | 2 | 50 |  |  |  | 9 | $self->optimise_two($block_ar) || return err (); | 
| 2746 | 2 |  |  |  |  | 6 | 0 && debug('optimised data now %s', Dumper($block_ar)); | 
| 2747 |  |  |  |  |  |  |  | 
| 2748 |  |  |  |  |  |  |  | 
| 2749 |  |  |  |  |  |  | #  Need to encapsulate into  tag, so alter tag name, attr | 
| 2750 |  |  |  |  |  |  | # | 
| 2751 | 2 |  |  |  |  | 6 | $block_ar->[$WEBDYNE_NODE_NAME_IX]='block'; | 
| 2752 | 2 |  |  |  |  | 11 | $block_ar->[$WEBDYNE_NODE_ATTR_IX]={name => $node, display => 1}; | 
| 2753 |  |  |  |  |  |  |  | 
| 2754 |  |  |  |  |  |  |  | 
| 2755 |  |  |  |  |  |  | #  Incorporate into top level data so we don't have to do this again if | 
| 2756 |  |  |  |  |  |  | #  called from tag | 
| 2757 |  |  |  |  |  |  | # | 
| 2758 | 2 | 50 |  |  |  | 5 | @{$data_ar}=@{$block_ar} if $data_ar; | 
|  | 2 |  |  |  |  | 7 |  | 
|  | 2 |  |  |  |  | 4 |  | 
| 2759 |  |  |  |  |  |  |  | 
| 2760 |  |  |  |  |  |  |  | 
| 2761 |  |  |  |  |  |  | #  Render included block and return | 
| 2762 |  |  |  |  |  |  | # | 
| 2763 | 2 |  | 33 |  |  | 15 | return $self->render({data => $block_ar->[$WEBDYNE_NODE_CHLD_IX], param => $param_hr->{'param'}}) || err (); | 
| 2764 |  |  |  |  |  |  |  | 
| 2765 |  |  |  |  |  |  | } | 
| 2766 |  |  |  |  |  |  | elsif (my $block=$param_hr->{'block'}) { | 
| 2767 |  |  |  |  |  |  |  | 
| 2768 |  |  |  |  |  |  | #  Wants to include a paticular block from a psp library file | 
| 2769 |  |  |  |  |  |  | # | 
| 2770 | 2 |  |  |  |  | 8 | 0 && debug('block render'); | 
| 2771 | 2 |  |  |  |  | 13 | my %option=( | 
| 2772 |  |  |  |  |  |  |  | 
| 2773 |  |  |  |  |  |  | nofilter => 1, | 
| 2774 |  |  |  |  |  |  |  | 
| 2775 |  |  |  |  |  |  | #noperl         =>  1, | 
| 2776 |  |  |  |  |  |  | stage1 => 1, | 
| 2777 |  |  |  |  |  |  | srce   => $pn | 
| 2778 |  |  |  |  |  |  |  | 
| 2779 |  |  |  |  |  |  | ); | 
| 2780 |  |  |  |  |  |  |  | 
| 2781 |  |  |  |  |  |  | #  compile spec'd file | 
| 2782 |  |  |  |  |  |  | # | 
| 2783 | 2 |  | 50 |  |  | 17 | my $container_ar=$self->compile(\%option) || | 
| 2784 |  |  |  |  |  |  | return err (); | 
| 2785 | 2 |  |  |  |  | 5 | my $block_data_ar=$container_ar->[1]; | 
| 2786 | 2 |  |  |  |  | 3 | 0 && debug('block data %s', Dumper($block_data_ar)); | 
| 2787 |  |  |  |  |  |  |  | 
| 2788 |  |  |  |  |  |  |  | 
| 2789 |  |  |  |  |  |  | #  Find the block node with name we want | 
| 2790 |  |  |  |  |  |  | # | 
| 2791 | 2 |  |  |  |  | 3 | 0 && debug("looking for block name $block"); | 
| 2792 | 2 |  | 50 |  |  | 20 | my $block_ar=$self->find_node( | 
| 2793 |  |  |  |  |  |  | { | 
| 2794 |  |  |  |  |  |  |  | 
| 2795 |  |  |  |  |  |  | data_ar => $block_data_ar, | 
| 2796 |  |  |  |  |  |  | tag     => 'block', | 
| 2797 |  |  |  |  |  |  | attr_hr => {name => $block}, | 
| 2798 |  |  |  |  |  |  |  | 
| 2799 |  |  |  |  |  |  | }) || return err (); | 
| 2800 | 2 | 50 |  |  |  | 12 | @{$block_ar} || | 
|  | 2 |  |  |  |  | 10 |  | 
| 2801 |  |  |  |  |  |  | return err ("unable to find block '$block' in include file '$fn'"); | 
| 2802 | 2 |  |  |  |  | 7 | 0 && debug('found block_ar %s', Dumper($block_ar)); | 
| 2803 |  |  |  |  |  |  |  | 
| 2804 |  |  |  |  |  |  |  | 
| 2805 |  |  |  |  |  |  | #  Find_node returns array of blocks that match - we only want first | 
| 2806 |  |  |  |  |  |  | # | 
| 2807 | 2 |  |  |  |  | 5 | $block_ar=$block_ar->[0]; | 
| 2808 |  |  |  |  |  |  |  | 
| 2809 |  |  |  |  |  |  |  | 
| 2810 |  |  |  |  |  |  | #  Set to attr always display | 
| 2811 |  |  |  |  |  |  | # | 
| 2812 | 2 |  |  |  |  | 8 | $block_ar->[$WEBDYNE_NODE_ATTR_IX]{'display'}=1; | 
| 2813 |  |  |  |  |  |  |  | 
| 2814 |  |  |  |  |  |  |  | 
| 2815 |  |  |  |  |  |  | #  Incorporate into top level data so we don't have to do this again if | 
| 2816 |  |  |  |  |  |  | #  called from tag | 
| 2817 |  |  |  |  |  |  | # | 
| 2818 | 2 | 50 |  |  |  | 10 | @{$data_ar}=@{$block_ar} if $data_ar; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 2819 |  |  |  |  |  |  |  | 
| 2820 |  |  |  |  |  |  |  | 
| 2821 |  |  |  |  |  |  | #  We don't want to render  tags, so start at | 
| 2822 |  |  |  |  |  |  | #  child of results [WEBDYNE_NODE_CHLD_IX]. | 
| 2823 |  |  |  |  |  |  | # | 
| 2824 | 2 |  |  |  |  | 4 | 0 && debug('calling render'); | 
| 2825 | 2 |  | 33 |  |  | 22 | return $self->render({data => $block_ar->[$WEBDYNE_NODE_CHLD_IX], param => ($param_hr->{'param'} || $param_data_hr)}) || err (); | 
| 2826 |  |  |  |  |  |  |  | 
| 2827 |  |  |  |  |  |  | } | 
| 2828 |  |  |  |  |  |  | else { | 
| 2829 |  |  |  |  |  |  |  | 
| 2830 |  |  |  |  |  |  |  | 
| 2831 |  |  |  |  |  |  | #  Plain vanilla file include, no mods | 
| 2832 |  |  |  |  |  |  | # | 
| 2833 | 1 |  |  |  |  | 6 | 0 && debug('vanilla file include'); | 
| 2834 | 1 |  | 50 |  |  | 15 | my $fh=IO::File->new($pn, O_RDONLY) || return err ("unable to open file '$fn' for read, $!"); | 
| 2835 | 1 |  |  |  |  | 92 | my @html; | 
| 2836 | 1 |  |  |  |  | 13 | while (<$fh>) { | 
| 2837 | 1 |  |  |  |  | 7 | push @html, $_; | 
| 2838 |  |  |  |  |  |  | } | 
| 2839 | 1 |  |  |  |  | 8 | $fh->close(); | 
| 2840 | 1 |  |  |  |  | 18 | \join(undef, @html); | 
| 2841 |  |  |  |  |  |  |  | 
| 2842 |  |  |  |  |  |  | } | 
| 2843 |  |  |  |  |  |  |  | 
| 2844 |  |  |  |  |  |  | } | 
| 2845 |  |  |  |  |  |  |  | 
| 2846 |  |  |  |  |  |  |  | 
| 2847 |  |  |  |  |  |  | sub find_node { | 
| 2848 |  |  |  |  |  |  |  | 
| 2849 |  |  |  |  |  |  |  | 
| 2850 |  |  |  |  |  |  | #  Find a particular node in the tree | 
| 2851 |  |  |  |  |  |  | # | 
| 2852 | 36 |  |  | 36 | 0 | 89 | my ($self, $param_hr)=@_; | 
| 2853 |  |  |  |  |  |  |  | 
| 2854 |  |  |  |  |  |  |  | 
| 2855 |  |  |  |  |  |  | #  Get max depth we can descend to, zero out in params | 
| 2856 |  |  |  |  |  |  | # | 
| 2857 | 36 |  |  |  |  | 95 | my ($data_ar, $tag, $attr_hr, $depth_max, $prnt_fg, $all_fg)=@{$param_hr}{ | 
| 2858 | 36 |  |  |  |  | 75 | qw(data_ar tag attr_hr depth prnt_fg all_fg) | 
| 2859 |  |  |  |  |  |  | }; | 
| 2860 | 36 |  |  |  |  | 58 | 0 && debug("find_node looking for tag $tag in data_ar $data_ar, %s", Dumper($data_ar)); | 
| 2861 |  |  |  |  |  |  |  | 
| 2862 |  |  |  |  |  |  |  | 
| 2863 |  |  |  |  |  |  | #  Array to hold results, depth | 
| 2864 |  |  |  |  |  |  | # | 
| 2865 | 36 |  |  |  |  | 55 | my ($depth, @node); | 
| 2866 |  |  |  |  |  |  |  | 
| 2867 |  |  |  |  |  |  |  | 
| 2868 |  |  |  |  |  |  | #  Create recursive anon sub | 
| 2869 |  |  |  |  |  |  | # | 
| 2870 |  |  |  |  |  |  | my $find_cr=sub { | 
| 2871 |  |  |  |  |  |  |  | 
| 2872 |  |  |  |  |  |  |  | 
| 2873 |  |  |  |  |  |  | #  Get params | 
| 2874 |  |  |  |  |  |  | # | 
| 2875 | 87 |  |  | 87 |  | 148 | my ($find_cr, $data_ar, $data_prnt_ar)=@_; | 
| 2876 | 87 |  |  |  |  | 87 | 0 && debug("find_cr, data_ar $data_ar, data_prnt_ar $data_prnt_ar"); | 
| 2877 |  |  |  |  |  |  |  | 
| 2878 |  |  |  |  |  |  |  | 
| 2879 |  |  |  |  |  |  | #  Do we match at this level ? | 
| 2880 |  |  |  |  |  |  | # | 
| 2881 | 87 | 100 |  |  |  | 176 | if ((my $data_ar_tag=$data_ar->[$WEBDYNE_NODE_NAME_IX]) eq $tag) { | 
| 2882 |  |  |  |  |  |  |  | 
| 2883 |  |  |  |  |  |  |  | 
| 2884 |  |  |  |  |  |  | #  Match for tag name, now check any attrs | 
| 2885 |  |  |  |  |  |  | # | 
| 2886 | 26 |  |  |  |  | 35 | my $tag_attr_hr=$data_ar->[$WEBDYNE_NODE_ATTR_IX]; | 
| 2887 |  |  |  |  |  |  |  | 
| 2888 |  |  |  |  |  |  |  | 
| 2889 |  |  |  |  |  |  | #  Debug | 
| 2890 |  |  |  |  |  |  | # | 
| 2891 | 26 |  |  |  |  | 25 | 0 && debug("tag '$tag' match, $data_ar_tag, checking attr %s", Dumper($tag_attr_hr)); | 
| 2892 |  |  |  |  |  |  |  | 
| 2893 |  |  |  |  |  |  |  | 
| 2894 |  |  |  |  |  |  | #  Check for match | 
| 2895 |  |  |  |  |  |  | # | 
| 2896 | 26 | 100 |  |  |  | 32 | if ( | 
| 2897 | 12 |  |  |  |  | 35 | (grep {$tag_attr_hr->{$_} eq $attr_hr->{$_}} keys %{$tag_attr_hr}) == | 
|  | 26 |  |  |  |  | 59 |  | 
| 2898 | 26 |  |  |  |  | 57 | (keys %{$attr_hr}) | 
| 2899 |  |  |  |  |  |  | ) { | 
| 2900 |  |  |  |  |  |  |  | 
| 2901 |  |  |  |  |  |  |  | 
| 2902 |  |  |  |  |  |  | #  Match, debug | 
| 2903 |  |  |  |  |  |  | # | 
| 2904 | 25 |  |  |  |  | 32 | 0 && debug("$data_ar_tag attr match, saving"); | 
| 2905 |  |  |  |  |  |  |  | 
| 2906 |  |  |  |  |  |  |  | 
| 2907 |  |  |  |  |  |  | #  Tag name and attribs match, push onto node | 
| 2908 |  |  |  |  |  |  | # | 
| 2909 | 25 | 50 |  |  |  | 53 | push @node, $prnt_fg ? $data_prnt_ar : $data_ar; | 
| 2910 | 25 | 100 |  |  |  | 85 | return $node[0] unless $all_fg; | 
| 2911 |  |  |  |  |  |  |  | 
| 2912 |  |  |  |  |  |  |  | 
| 2913 |  |  |  |  |  |  | } | 
| 2914 |  |  |  |  |  |  |  | 
| 2915 |  |  |  |  |  |  | } | 
| 2916 |  |  |  |  |  |  | else { | 
| 2917 |  |  |  |  |  |  |  | 
| 2918 | 61 |  |  |  |  | 67 | 0 && debug("mismatch on tag $data_ar_tag for tag '$tag'"); | 
| 2919 |  |  |  |  |  |  |  | 
| 2920 |  |  |  |  |  |  | } | 
| 2921 |  |  |  |  |  |  |  | 
| 2922 |  |  |  |  |  |  |  | 
| 2923 |  |  |  |  |  |  | #  Return if out of depth | 
| 2924 |  |  |  |  |  |  | # | 
| 2925 | 69 | 50 | 33 |  |  | 122 | return if ($depth_max && (++$depth > $depth_max)); | 
| 2926 |  |  |  |  |  |  |  | 
| 2927 |  |  |  |  |  |  |  | 
| 2928 |  |  |  |  |  |  | #  Start looking through current node | 
| 2929 |  |  |  |  |  |  | # | 
| 2930 | 69 | 100 |  |  |  | 109 | my @data_child_ar=$data_ar->[$WEBDYNE_NODE_CHLD_IX] ? @{$data_ar->[$WEBDYNE_NODE_CHLD_IX]} : undef; | 
|  | 64 |  |  |  |  | 103 |  | 
| 2931 | 69 |  |  |  |  | 103 | foreach my $data_child_ar (@data_child_ar) { | 
| 2932 |  |  |  |  |  |  |  | 
| 2933 |  |  |  |  |  |  |  | 
| 2934 |  |  |  |  |  |  | #  Only check and/or recurse through children that are child nodes, (ie | 
| 2935 |  |  |  |  |  |  | #  are refs), ignor non-ref (text) nodes | 
| 2936 |  |  |  |  |  |  | # | 
| 2937 | 80 | 100 |  |  |  | 185 | ref($data_child_ar) && do { | 
| 2938 |  |  |  |  |  |  |  | 
| 2939 |  |  |  |  |  |  |  | 
| 2940 |  |  |  |  |  |  | #  We have a ref, recurse look for match | 
| 2941 |  |  |  |  |  |  | # | 
| 2942 | 51 | 100 |  |  |  | 131 | if (my $data_match_ar=$find_cr->($find_cr, $data_child_ar, $data_ar)) { | 
| 2943 |  |  |  |  |  |  |  | 
| 2944 |  |  |  |  |  |  |  | 
| 2945 |  |  |  |  |  |  | #  Found match during recursion, return | 
| 2946 |  |  |  |  |  |  | # | 
| 2947 | 21 | 50 |  |  |  | 52 | return $data_match_ar unless $all_fg; | 
| 2948 |  |  |  |  |  |  |  | 
| 2949 |  |  |  |  |  |  | } | 
| 2950 |  |  |  |  |  |  |  | 
| 2951 |  |  |  |  |  |  | } | 
| 2952 |  |  |  |  |  |  |  | 
| 2953 |  |  |  |  |  |  | } | 
| 2954 |  |  |  |  |  |  |  | 
| 2955 | 36 |  |  |  |  | 185 | }; | 
| 2956 |  |  |  |  |  |  |  | 
| 2957 |  |  |  |  |  |  |  | 
| 2958 |  |  |  |  |  |  | #  Start it running with our top node | 
| 2959 |  |  |  |  |  |  | # | 
| 2960 | 36 |  |  |  |  | 90 | $find_cr->($find_cr, $data_ar); | 
| 2961 |  |  |  |  |  |  |  | 
| 2962 |  |  |  |  |  |  |  | 
| 2963 |  |  |  |  |  |  | #  Debug | 
| 2964 |  |  |  |  |  |  | # | 
| 2965 | 36 |  |  |  |  | 38 | 0 && debug('find complete, return node %s', \@node); | 
| 2966 |  |  |  |  |  |  |  | 
| 2967 |  |  |  |  |  |  |  | 
| 2968 |  |  |  |  |  |  | #  Return results | 
| 2969 |  |  |  |  |  |  | # | 
| 2970 | 36 |  |  |  |  | 308 | return \@node; | 
| 2971 |  |  |  |  |  |  |  | 
| 2972 |  |  |  |  |  |  | } | 
| 2973 |  |  |  |  |  |  |  | 
| 2974 |  |  |  |  |  |  |  | 
| 2975 |  |  |  |  |  |  | sub delete_node { | 
| 2976 |  |  |  |  |  |  |  | 
| 2977 |  |  |  |  |  |  |  | 
| 2978 |  |  |  |  |  |  | #  Delete a particular node from the tree | 
| 2979 |  |  |  |  |  |  | # | 
| 2980 | 0 |  |  | 0 | 0 | 0 | my ($self, $param_hr)=@_; | 
| 2981 |  |  |  |  |  |  |  | 
| 2982 |  |  |  |  |  |  |  | 
| 2983 |  |  |  |  |  |  | #  Get max depth we can descend to, zero out in params | 
| 2984 |  |  |  |  |  |  | # | 
| 2985 | 0 |  |  |  |  | 0 | my ($data_ar, $node_ar)=@{$param_hr}{qw(data_ar node_ar)}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2986 | 0 |  |  |  |  | 0 | 0 && debug("delete node $node_ar starting from data_ar $data_ar"); | 
| 2987 |  |  |  |  |  |  |  | 
| 2988 |  |  |  |  |  |  |  | 
| 2989 |  |  |  |  |  |  | #  Create recursive anon sub | 
| 2990 |  |  |  |  |  |  | # | 
| 2991 |  |  |  |  |  |  | my $find_cr=sub { | 
| 2992 |  |  |  |  |  |  |  | 
| 2993 |  |  |  |  |  |  |  | 
| 2994 |  |  |  |  |  |  | #  Get params | 
| 2995 |  |  |  |  |  |  | # | 
| 2996 | 0 |  |  | 0 |  | 0 | my ($find_cr, $data_ar)=@_; | 
| 2997 |  |  |  |  |  |  |  | 
| 2998 |  |  |  |  |  |  |  | 
| 2999 |  |  |  |  |  |  | #  Iterate through child nodes | 
| 3000 |  |  |  |  |  |  | # | 
| 3001 | 0 |  |  |  |  | 0 | foreach my $data_chld_ix (0..$#{$data_ar->[$WEBDYNE_NODE_CHLD_IX]}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 3002 |  |  |  |  |  |  |  | 
| 3003 | 0 |  | 0 |  |  | 0 | my $data_chld_ar=$data_ar->[$WEBDYNE_NODE_CHLD_IX][$data_chld_ix] || | 
| 3004 |  |  |  |  |  |  | return err ("unable to get chld node from $data_ar"); | 
| 3005 | 0 |  |  |  |  | 0 | 0 && debug("looking at chld node $data_chld_ar"); | 
| 3006 |  |  |  |  |  |  |  | 
| 3007 | 0 | 0 |  |  |  | 0 | if ($data_chld_ar eq $node_ar) { | 
| 3008 |  |  |  |  |  |  |  | 
| 3009 |  |  |  |  |  |  | #  Found node we want to delete. Get rid of it, all done | 
| 3010 |  |  |  |  |  |  | # | 
| 3011 | 0 |  |  |  |  | 0 | 0 && debug("match - splicing at chld $data_chld_ix from array %s", Dumper($data_ar)); | 
| 3012 | 0 |  |  |  |  | 0 | splice(@{$data_ar->[$WEBDYNE_NODE_CHLD_IX]}, $data_chld_ix, 1); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3013 | 0 |  |  |  |  | 0 | return \1; | 
| 3014 |  |  |  |  |  |  |  | 
| 3015 |  |  |  |  |  |  | } | 
| 3016 |  |  |  |  |  |  | else { | 
| 3017 |  |  |  |  |  |  |  | 
| 3018 |  |  |  |  |  |  |  | 
| 3019 |  |  |  |  |  |  | #  Not target node - recurse | 
| 3020 |  |  |  |  |  |  | # | 
| 3021 | 0 |  |  |  |  | 0 | 0 && debug("no match - recursing to chld $data_chld_ar"); | 
| 3022 | 0 | 0 |  |  |  | 0 | ${$find_cr->($find_cr, $data_chld_ar) || return err ()} && | 
|  | 0 | 0 |  |  |  | 0 |  | 
| 3023 |  |  |  |  |  |  | return \1; | 
| 3024 |  |  |  |  |  |  |  | 
| 3025 |  |  |  |  |  |  | } | 
| 3026 |  |  |  |  |  |  | } | 
| 3027 |  |  |  |  |  |  |  | 
| 3028 |  |  |  |  |  |  |  | 
| 3029 |  |  |  |  |  |  | #  All done, but no cigar | 
| 3030 |  |  |  |  |  |  | # | 
| 3031 | 0 |  |  |  |  | 0 | return \undef; | 
| 3032 |  |  |  |  |  |  |  | 
| 3033 | 0 |  |  |  |  | 0 | }; | 
| 3034 |  |  |  |  |  |  |  | 
| 3035 |  |  |  |  |  |  |  | 
| 3036 |  |  |  |  |  |  | #  Start | 
| 3037 |  |  |  |  |  |  | # | 
| 3038 | 0 |  | 0 |  |  | 0 | return $find_cr->($find_cr, $data_ar) || err () | 
| 3039 |  |  |  |  |  |  |  | 
| 3040 |  |  |  |  |  |  | } | 
| 3041 |  |  |  |  |  |  |  | 
| 3042 |  |  |  |  |  |  |  | 
| 3043 |  |  |  |  |  |  | sub CGI { | 
| 3044 |  |  |  |  |  |  |  | 
| 3045 |  |  |  |  |  |  |  | 
| 3046 |  |  |  |  |  |  | #  Accessor method for CGI object | 
| 3047 |  |  |  |  |  |  | # | 
| 3048 | 11 |  | 66 | 11 | 0 | 61 | return shift()->{'_CGI'} ||= do { | 
| 3049 |  |  |  |  |  |  |  | 
| 3050 |  |  |  |  |  |  | #  Debug | 
| 3051 |  |  |  |  |  |  | # | 
| 3052 | 10 |  |  |  |  | 13 | 0 && debug('CGI init'); | 
| 3053 |  |  |  |  |  |  |  | 
| 3054 |  |  |  |  |  |  |  | 
| 3055 |  |  |  |  |  |  | #  Need to turn off XHTML generation - CGI wants to turn it on every time for | 
| 3056 |  |  |  |  |  |  | #  some reason | 
| 3057 |  |  |  |  |  |  | # | 
| 3058 | 10 |  |  |  |  | 21 | $CGI::XHTML=0; | 
| 3059 | 10 |  |  |  |  | 13 | $CGI::NOSTICKY=1; | 
| 3060 |  |  |  |  |  |  |  | 
| 3061 |  |  |  |  |  |  |  | 
| 3062 |  |  |  |  |  |  | #  CGI good practice | 
| 3063 |  |  |  |  |  |  | # | 
| 3064 | 10 |  |  |  |  | 19 | $CGI::DISABLE_UPLOADS=$WEBDYNE_CGI_DISABLE_UPLOADS; | 
| 3065 | 10 |  |  |  |  | 13 | $CGI::POST_MAX=$WEBDYNE_CGI_POST_MAX; | 
| 3066 |  |  |  |  |  |  |  | 
| 3067 |  |  |  |  |  |  |  | 
| 3068 |  |  |  |  |  |  | #  And create it | 
| 3069 |  |  |  |  |  |  | # | 
| 3070 | 10 |  |  |  |  | 112 | my $cgi_or=CGI::->new(); | 
| 3071 |  |  |  |  |  |  |  | 
| 3072 |  |  |  |  |  |  |  | 
| 3073 |  |  |  |  |  |  | #  Set defaults | 
| 3074 |  |  |  |  |  |  | # | 
| 3075 | 10 |  |  |  |  | 2837 | $cgi_or->autoEscape($WEBDYNE_CGI_AUTOESCAPE); | 
| 3076 |  |  |  |  |  |  |  | 
| 3077 |  |  |  |  |  |  |  | 
| 3078 |  |  |  |  |  |  | #  Expand params if we need to | 
| 3079 |  |  |  |  |  |  | # | 
| 3080 | 10 | 50 |  |  |  | 145 | &CGI_param_expand($cgi_or) if $WEBDYNE_CGI_PARAM_EXPAND; | 
| 3081 |  |  |  |  |  |  |  | 
| 3082 |  |  |  |  |  |  |  | 
| 3083 |  |  |  |  |  |  | #  Return new CGI object | 
| 3084 |  |  |  |  |  |  | # | 
| 3085 | 10 |  |  |  |  | 177 | $cgi_or; | 
| 3086 |  |  |  |  |  |  |  | 
| 3087 |  |  |  |  |  |  | }; | 
| 3088 |  |  |  |  |  |  |  | 
| 3089 |  |  |  |  |  |  | } | 
| 3090 |  |  |  |  |  |  |  | 
| 3091 |  |  |  |  |  |  |  | 
| 3092 |  |  |  |  |  |  | sub CGI_param_expand { | 
| 3093 |  |  |  |  |  |  |  | 
| 3094 |  |  |  |  |  |  | #  Expand CGI params if the form "foo;a=b" into "foo=param", "a=b"; | 
| 3095 |  |  |  |  |  |  | # | 
| 3096 | 10 |  | 50 | 10 | 0 | 25 | my $cgi_or=shift() || | 
| 3097 |  |  |  |  |  |  | return err ("unable to get CGI object"); | 
| 3098 | 10 |  |  |  |  | 27 | local ($CGI::LIST_CONTEXT_WARN)=0; | 
| 3099 | 10 |  |  |  |  | 21 | foreach my $param (grep /=/, $cgi_or->param()) { | 
| 3100 | 0 |  |  |  |  | 0 | my (@pairs)=split(/[&;]/, $param); | 
| 3101 | 0 |  |  |  |  | 0 | foreach my $pair (@pairs) { | 
| 3102 | 0 |  |  |  |  | 0 | my ($key, $value)=split('=', $pair, 2); | 
| 3103 | 0 |  | 0 |  |  | 0 | $value ||= $cgi_or->param($param); | 
| 3104 | 0 |  |  |  |  | 0 | $key=&CGI::unescape($key); | 
| 3105 | 0 |  |  |  |  | 0 | $value=&CGI::unescape($value); | 
| 3106 | 0 |  |  |  |  | 0 | $cgi_or->param($key, $value); | 
| 3107 |  |  |  |  |  |  | } | 
| 3108 | 0 |  |  |  |  | 0 | $cgi_or->delete($param); | 
| 3109 |  |  |  |  |  |  | } | 
| 3110 |  |  |  |  |  |  | } | 
| 3111 |  |  |  |  |  |  |  | 
| 3112 |  |  |  |  |  |  |  | 
| 3113 |  |  |  |  |  |  | sub request { | 
| 3114 |  |  |  |  |  |  |  | 
| 3115 |  |  |  |  |  |  |  | 
| 3116 |  |  |  |  |  |  | #  Accessor method for Apache request object | 
| 3117 |  |  |  |  |  |  | # | 
| 3118 | 5 |  |  | 5 | 0 | 8 | my $self=shift(); | 
| 3119 | 5 | 50 |  |  |  | 18 | return @_ ? $self->{'_r'}=shift() : $self->{'_r'}; | 
| 3120 |  |  |  |  |  |  |  | 
| 3121 |  |  |  |  |  |  | } | 
| 3122 |  |  |  |  |  |  |  | 
| 3123 |  |  |  |  |  |  |  | 
| 3124 |  |  |  |  |  |  | sub dump { | 
| 3125 |  |  |  |  |  |  |  | 
| 3126 |  |  |  |  |  |  |  | 
| 3127 |  |  |  |  |  |  | #  Run the dump CGI dump routine. Is here because it produces different output each | 
| 3128 |  |  |  |  |  |  | #  time it is run, and if not a WebDyne tag it would be optimised to static text by | 
| 3129 |  |  |  |  |  |  | #  the compiler | 
| 3130 |  |  |  |  |  |  | # | 
| 3131 | 0 |  |  | 0 | 0 | 0 | my ($self, $data_ar, $attr_hr)=@_; | 
| 3132 | 0 | 0 | 0 |  |  | 0 | return ($WEBDYNE_DUMP_FLAG || $attr_hr->{'force'} || $attr_hr->{'display'}) ? \$self->{'_CGI'}->Dump() : \undef; | 
| 3133 |  |  |  |  |  |  |  | 
| 3134 |  |  |  |  |  |  | } | 
| 3135 |  |  |  |  |  |  |  | 
| 3136 |  |  |  |  |  |  |  | 
| 3137 |  |  |  |  |  |  | sub cwd { | 
| 3138 |  |  |  |  |  |  |  | 
| 3139 |  |  |  |  |  |  | #  Return cwd of current psp file | 
| 3140 |  |  |  |  |  |  | # | 
| 3141 | 9 |  |  | 9 | 0 | 39 | (File::Spec->splitpath(shift()->{'_r'}->filename()))[1]; | 
| 3142 |  |  |  |  |  |  |  | 
| 3143 |  |  |  |  |  |  | } | 
| 3144 |  |  |  |  |  |  |  | 
| 3145 |  |  |  |  |  |  |  | 
| 3146 |  |  |  |  |  |  | sub source_mtime { | 
| 3147 |  |  |  |  |  |  |  | 
| 3148 |  |  |  |  |  |  | #  Get mtime of source file. Is a no-op here so can be subclassed by other handlers. We | 
| 3149 |  |  |  |  |  |  | #  return undef, means engine will use original source mtime | 
| 3150 |  |  |  |  |  |  | # | 
| 3151 | 10 |  |  | 10 | 0 | 66 | \undef; | 
| 3152 |  |  |  |  |  |  |  | 
| 3153 |  |  |  |  |  |  | } | 
| 3154 |  |  |  |  |  |  |  | 
| 3155 |  |  |  |  |  |  |  | 
| 3156 |  |  |  |  |  |  | sub cache_mtime { | 
| 3157 |  |  |  |  |  |  |  | 
| 3158 |  |  |  |  |  |  | #  Mtime accessor - will return mtime of srce inode (default), or mtime of supplied | 
| 3159 |  |  |  |  |  |  | #  inode if given | 
| 3160 |  |  |  |  |  |  | # | 
| 3161 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3162 |  |  |  |  |  |  | my $inode_pn=${ | 
| 3163 | 0 | 0 |  |  |  | 0 | $self->cache_filename(@_) || return err ()}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3164 | 0 | 0 |  |  |  | 0 | \(stat($inode_pn))[9] if $inode_pn; | 
| 3165 |  |  |  |  |  |  |  | 
| 3166 |  |  |  |  |  |  | } | 
| 3167 |  |  |  |  |  |  |  | 
| 3168 |  |  |  |  |  |  |  | 
| 3169 |  |  |  |  |  |  | sub cache_filename { | 
| 3170 |  |  |  |  |  |  |  | 
| 3171 |  |  |  |  |  |  | #  Get cache fq filename given inode or using srce inode if not supplied | 
| 3172 |  |  |  |  |  |  | # | 
| 3173 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3174 | 0 | 0 |  |  |  | 0 | my $inode=@_ ? shift() : $self->{'_inode'}; | 
| 3175 | 0 | 0 |  |  |  | 0 | my $inode_pn=File::Spec->catfile($WEBDYNE_CACHE_DN, $inode) if $WEBDYNE_CACHE_DN; | 
| 3176 | 0 |  |  |  |  | 0 | \$inode_pn; | 
| 3177 |  |  |  |  |  |  |  | 
| 3178 |  |  |  |  |  |  | } | 
| 3179 |  |  |  |  |  |  |  | 
| 3180 |  |  |  |  |  |  |  | 
| 3181 |  |  |  |  |  |  | sub cache_inode { | 
| 3182 |  |  |  |  |  |  |  | 
| 3183 |  |  |  |  |  |  | #  Get cache inode string, or generate new unique inode | 
| 3184 |  |  |  |  |  |  | # | 
| 3185 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3186 | 0 | 0 |  |  |  | 0 | @_ && ($self->{'_inode'}=md5_hex($self->{'_inode'}, $_[0])); | 
| 3187 |  |  |  |  |  |  |  | 
| 3188 |  |  |  |  |  |  | #  See comment in handler section about future inode gen | 
| 3189 |  |  |  |  |  |  | # | 
| 3190 |  |  |  |  |  |  | #@_ && ($self->{'_inode'}.=('_'. md5_hex($_[0]))); | 
| 3191 | 0 |  |  |  |  | 0 | \$self->{'_inode'}; | 
| 3192 |  |  |  |  |  |  |  | 
| 3193 |  |  |  |  |  |  | } | 
| 3194 |  |  |  |  |  |  |  | 
| 3195 |  |  |  |  |  |  |  | 
| 3196 |  |  |  |  |  |  | sub cache_html { | 
| 3197 |  |  |  |  |  |  |  | 
| 3198 |  |  |  |  |  |  | #  Write an inode that is fully HTML out to disk to we dispatch it as a subrequest | 
| 3199 |  |  |  |  |  |  | #  next time. This is a ®ister_cleanup callback | 
| 3200 |  |  |  |  |  |  | # | 
| 3201 | 0 |  |  | 0 | 0 | 0 | my ($cache_pn, $html_sr)=@_; | 
| 3202 | 0 |  |  |  |  | 0 | 0 && debug("cache_html @_"); | 
| 3203 |  |  |  |  |  |  |  | 
| 3204 |  |  |  |  |  |  | #  If there was an error no html_sr will be supplied | 
| 3205 |  |  |  |  |  |  | # | 
| 3206 | 0 | 0 |  |  |  | 0 | if ($html_sr) { | 
| 3207 |  |  |  |  |  |  |  | 
| 3208 |  |  |  |  |  |  | #  No point || return err(), just warn so (maybe) is written to logs, otherwise go for it | 
| 3209 |  |  |  |  |  |  | # | 
| 3210 | 0 |  | 0 |  |  | 0 | my $cache_fh=IO::File->new($cache_pn, O_WRONLY | O_CREAT | O_TRUNC) || | 
| 3211 |  |  |  |  |  |  | return warn("unable to open cache file $cache_pn for write, $!"); | 
| 3212 | 0 |  |  |  |  | 0 | CORE::print $cache_fh ${$html_sr}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3213 | 0 |  |  |  |  | 0 | $cache_fh->close(); | 
| 3214 |  |  |  |  |  |  | } | 
| 3215 | 0 |  |  |  |  | 0 | \undef; | 
| 3216 |  |  |  |  |  |  |  | 
| 3217 |  |  |  |  |  |  | } | 
| 3218 |  |  |  |  |  |  |  | 
| 3219 |  |  |  |  |  |  |  | 
| 3220 |  |  |  |  |  |  | sub cache_compile { | 
| 3221 |  |  |  |  |  |  |  | 
| 3222 |  |  |  |  |  |  | #  Compile flag accessor - if set will force inode recompile, regardless of mtime | 
| 3223 |  |  |  |  |  |  | # | 
| 3224 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3225 | 0 | 0 |  |  |  | 0 | @_ && ($self->{'_compile'}=shift()); | 
| 3226 | 0 |  |  |  |  | 0 | 0 && debug("cache_compile set to %s", $self->{'_compile'}); | 
| 3227 | 0 |  |  |  |  | 0 | \$self->{'_compile'}; | 
| 3228 |  |  |  |  |  |  |  | 
| 3229 |  |  |  |  |  |  | } | 
| 3230 |  |  |  |  |  |  |  | 
| 3231 |  |  |  |  |  |  |  | 
| 3232 |  |  |  |  |  |  | sub filter { | 
| 3233 |  |  |  |  |  |  |  | 
| 3234 |  |  |  |  |  |  |  | 
| 3235 |  |  |  |  |  |  | #  No op | 
| 3236 |  |  |  |  |  |  | # | 
| 3237 | 0 |  |  | 0 | 0 | 0 | my ($self, $data_ar)=@_; | 
| 3238 | 0 |  |  |  |  | 0 | 0 && debug('in filter'); | 
| 3239 | 0 |  |  |  |  | 0 | $data_ar; | 
| 3240 |  |  |  |  |  |  |  | 
| 3241 |  |  |  |  |  |  | } | 
| 3242 |  |  |  |  |  |  |  | 
| 3243 |  |  |  |  |  |  |  | 
| 3244 |  |  |  |  |  |  | sub meta { | 
| 3245 |  |  |  |  |  |  |  | 
| 3246 |  |  |  |  |  |  | #  Return/read/update meta info hash | 
| 3247 |  |  |  |  |  |  | # | 
| 3248 | 0 |  |  | 0 | 0 | 0 | my ($self, @param)=@_; | 
| 3249 | 0 |  |  |  |  | 0 | my $inode=$self->{'_inode'}; | 
| 3250 | 0 |  |  |  |  | 0 | 0 && debug("get meta data for inode $inode"); | 
| 3251 | 0 |  | 0 |  |  | 0 | my $meta_hr=$Package{'_cache'}{$inode}{'meta'} ||= (delete $self->{'_meta_hr'} || {}); | 
|  |  |  | 0 |  |  |  |  | 
| 3252 | 0 |  |  |  |  | 0 | 0 && debug("existing meta $meta_hr %s", Dumper($meta_hr)); | 
| 3253 | 0 | 0 |  |  |  | 0 | if (@param == 2) { | 
|  |  | 0 |  |  |  |  |  | 
| 3254 | 0 |  |  |  |  | 0 | return $meta_hr->{$param[0]}=$param[1]; | 
| 3255 |  |  |  |  |  |  | } | 
| 3256 |  |  |  |  |  |  | elsif (@param) { | 
| 3257 | 0 |  |  |  |  | 0 | return $meta_hr->{$param[0]}; | 
| 3258 |  |  |  |  |  |  | } | 
| 3259 |  |  |  |  |  |  | else { | 
| 3260 | 0 |  |  |  |  | 0 | return $meta_hr; | 
| 3261 |  |  |  |  |  |  | } | 
| 3262 |  |  |  |  |  |  |  | 
| 3263 |  |  |  |  |  |  | } | 
| 3264 |  |  |  |  |  |  |  | 
| 3265 |  |  |  |  |  |  |  | 
| 3266 |  |  |  |  |  |  | sub static { | 
| 3267 |  |  |  |  |  |  |  | 
| 3268 |  |  |  |  |  |  |  | 
| 3269 |  |  |  |  |  |  | #  Set static flag for this instance only. If all instances wanted | 
| 3270 |  |  |  |  |  |  | #  set in meta data. This method used by WebDyne::Static module | 
| 3271 |  |  |  |  |  |  | # | 
| 3272 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3273 | 0 |  |  |  |  | 0 | $self->{'_static'}=1; | 
| 3274 |  |  |  |  |  |  |  | 
| 3275 |  |  |  |  |  |  |  | 
| 3276 |  |  |  |  |  |  | } | 
| 3277 |  |  |  |  |  |  |  | 
| 3278 |  |  |  |  |  |  |  | 
| 3279 |  |  |  |  |  |  | sub cache { | 
| 3280 |  |  |  |  |  |  |  | 
| 3281 |  |  |  |  |  |  | #  Set cache handler for this instance only. If all instances wanted | 
| 3282 |  |  |  |  |  |  | #  set in meta data. This method used by WebDyne::Cache module | 
| 3283 |  |  |  |  |  |  | # | 
| 3284 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3285 | 0 |  | 0 |  |  | 0 | $self->{'_cache'}=shift() || | 
| 3286 |  |  |  |  |  |  | return err ('cache code ref or method name must be supplied'); | 
| 3287 |  |  |  |  |  |  |  | 
| 3288 |  |  |  |  |  |  | } | 
| 3289 |  |  |  |  |  |  |  | 
| 3290 |  |  |  |  |  |  |  | 
| 3291 |  |  |  |  |  |  | sub set_filter { | 
| 3292 |  |  |  |  |  |  |  | 
| 3293 |  |  |  |  |  |  | #  Set cache handler for this instance only. If all instances wanted | 
| 3294 |  |  |  |  |  |  | #  set in meta data. This method used by WebDyne::Cache module | 
| 3295 |  |  |  |  |  |  | # | 
| 3296 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3297 | 0 |  | 0 |  |  | 0 | $self->{'_filter'}=shift() || | 
| 3298 |  |  |  |  |  |  | return err ('filter name must be supplied'); | 
| 3299 |  |  |  |  |  |  |  | 
| 3300 |  |  |  |  |  |  | } | 
| 3301 |  |  |  |  |  |  |  | 
| 3302 |  |  |  |  |  |  |  | 
| 3303 |  |  |  |  |  |  | sub set_handler { | 
| 3304 |  |  |  |  |  |  |  | 
| 3305 |  |  |  |  |  |  |  | 
| 3306 |  |  |  |  |  |  | #  Set/return internal handler. Only good in __PERL__ block, after | 
| 3307 |  |  |  |  |  |  | #  that is too late ! | 
| 3308 |  |  |  |  |  |  | # | 
| 3309 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3310 | 0 |  | 0 |  |  | 0 | my $meta_hr=$self->meta() || return err (); | 
| 3311 | 0 | 0 |  |  |  | 0 | @_ && ($meta_hr->{'handler'}=shift()); | 
| 3312 | 0 |  |  |  |  | 0 | \$meta_hr->{'handler'}; | 
| 3313 |  |  |  |  |  |  |  | 
| 3314 |  |  |  |  |  |  |  | 
| 3315 |  |  |  |  |  |  | } | 
| 3316 |  |  |  |  |  |  |  | 
| 3317 |  |  |  |  |  |  |  | 
| 3318 |  |  |  |  |  |  | sub select { | 
| 3319 |  |  |  |  |  |  |  | 
| 3320 |  |  |  |  |  |  |  | 
| 3321 |  |  |  |  |  |  | #  If we are in select mode where print output is redirected to handler output | 
| 3322 |  |  |  |  |  |  | # | 
| 3323 | 0 |  |  | 0 | 0 | 0 | shift->{'_select'}; | 
| 3324 |  |  |  |  |  |  |  | 
| 3325 |  |  |  |  |  |  | } | 
| 3326 |  |  |  |  |  |  |  | 
| 3327 |  |  |  |  |  |  |  | 
| 3328 |  |  |  |  |  |  | sub inode { | 
| 3329 |  |  |  |  |  |  |  | 
| 3330 |  |  |  |  |  |  |  | 
| 3331 |  |  |  |  |  |  | #  Return inode name | 
| 3332 |  |  |  |  |  |  | # | 
| 3333 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3334 | 0 | 0 |  |  |  | 0 | @_ ? $self->{'_inode'}=shift() : $self->{'_inode'}; | 
| 3335 |  |  |  |  |  |  |  | 
| 3336 |  |  |  |  |  |  | } | 
| 3337 |  |  |  |  |  |  |  | 
| 3338 |  |  |  |  |  |  |  | 
| 3339 |  |  |  |  |  |  | sub data_ar { | 
| 3340 |  |  |  |  |  |  |  | 
| 3341 |  |  |  |  |  |  |  | 
| 3342 |  |  |  |  |  |  | #  Return current data node, assumes we are in a perl block or subst | 
| 3343 |  |  |  |  |  |  | # | 
| 3344 | 0 |  |  | 0 | 0 | 0 | shift()->{'_data_ar'}; | 
| 3345 |  |  |  |  |  |  |  | 
| 3346 |  |  |  |  |  |  | } | 
| 3347 |  |  |  |  |  |  |  | 
| 3348 |  |  |  |  |  |  |  | 
| 3349 |  |  |  |  |  |  | sub data_ar_html_srce_fn { | 
| 3350 |  |  |  |  |  |  |  | 
| 3351 |  |  |  |  |  |  |  | 
| 3352 |  |  |  |  |  |  | #  The file name that this data node was sourced from | 
| 3353 |  |  |  |  |  |  | # | 
| 3354 | 0 |  |  | 0 | 0 | 0 | my ($self, $data_ar)=@_; | 
| 3355 | 0 | 0 | 0 |  |  | 0 | if ($data_ar ||= $self->data_ar()) { | 
| 3356 | 0 |  |  |  |  | 0 | return ${$data_ar->[$WEBDYNE_NODE_SRCE_IX]} | 
|  | 0 |  |  |  |  | 0 |  | 
| 3357 |  |  |  |  |  |  | } | 
| 3358 |  |  |  |  |  |  |  | 
| 3359 |  |  |  |  |  |  | } | 
| 3360 |  |  |  |  |  |  |  | 
| 3361 |  |  |  |  |  |  |  | 
| 3362 |  |  |  |  |  |  | sub data_ar_html_line_no { | 
| 3363 |  |  |  |  |  |  |  | 
| 3364 |  |  |  |  |  |  |  | 
| 3365 |  |  |  |  |  |  | #  The line number (in the original HTML file) this data node was sourced from. Return tag start line in scalar ref, tag start + tag end in array ref | 
| 3366 |  |  |  |  |  |  | # | 
| 3367 | 0 |  |  | 0 | 0 | 0 | my ($self, $data_ar)=@_; | 
| 3368 | 0 | 0 | 0 |  |  | 0 | if ($data_ar ||= $self->data_ar()) { | 
| 3369 | 0 | 0 |  |  |  | 0 | return wantarray ? @{$data_ar}[$WEBDYNE_NODE_LINE_IX, $WEBDYNE_NODE_LINE_TAG_END_IX] : $data_ar->[$WEBDYNE_NODE_LINE_IX]; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3370 |  |  |  |  |  |  | } | 
| 3371 |  |  |  |  |  |  |  | 
| 3372 |  |  |  |  |  |  |  | 
| 3373 |  |  |  |  |  |  | } | 
| 3374 |  |  |  |  |  |  |  | 
| 3375 |  |  |  |  |  |  |  | 
| 3376 |  |  |  |  |  |  | sub print { | 
| 3377 |  |  |  |  |  |  |  | 
| 3378 | 3 |  |  | 3 | 0 | 4 | my $self=shift(); | 
| 3379 | 3 |  |  |  |  | 4 | my $data_ar=$self->{'_data_ar'}; | 
| 3380 | 3 |  | 50 |  |  | 3 | push @{$self->{'_print_ar'}{$data_ar} ||= []}, @_; | 
|  | 3 |  |  |  |  | 22 |  | 
| 3381 | 3 |  |  |  |  | 7 | return \undef; | 
| 3382 |  |  |  |  |  |  |  | 
| 3383 |  |  |  |  |  |  | } | 
| 3384 |  |  |  |  |  |  |  | 
| 3385 |  |  |  |  |  |  |  | 
| 3386 |  |  |  |  |  |  | sub printf { | 
| 3387 |  |  |  |  |  |  |  | 
| 3388 | 0 |  |  | 0 | 0 | 0 | my $self=shift(); | 
| 3389 | 0 |  |  |  |  | 0 | my $data_ar=$self->{'_data_ar'}; | 
| 3390 | 0 |  | 0 |  |  | 0 | push @{$self->{'_print_ar'}{$data_ar} ||= []}, sprintf(shift(), @_); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3391 | 0 |  |  |  |  | 0 | return \undef; | 
| 3392 |  |  |  |  |  |  |  | 
| 3393 |  |  |  |  |  |  | } | 
| 3394 |  |  |  |  |  |  |  | 
| 3395 |  |  |  |  |  |  |  | 
| 3396 |  |  |  |  |  |  | sub DESTROY { | 
| 3397 |  |  |  |  |  |  |  | 
| 3398 |  |  |  |  |  |  |  | 
| 3399 |  |  |  |  |  |  | #  Stops AUTOLOAD chucking wobbly at end of request because no DESTROY method | 
| 3400 |  |  |  |  |  |  | #  found, logs total page cycle time | 
| 3401 |  |  |  |  |  |  | # | 
| 3402 | 10 |  |  | 10 |  | 21 | my $self=shift(); | 
| 3403 |  |  |  |  |  |  |  | 
| 3404 |  |  |  |  |  |  |  | 
| 3405 |  |  |  |  |  |  | #  Call CGI reset_globals if we created a CGI object | 
| 3406 |  |  |  |  |  |  | # | 
| 3407 | 10 | 50 |  |  |  | 49 | $self->{'_CGI'} && (&CGI::_reset_globals); | 
| 3408 |  |  |  |  |  |  |  | 
| 3409 |  |  |  |  |  |  |  | 
| 3410 |  |  |  |  |  |  | #  Work out complete request cylcle time | 
| 3411 |  |  |  |  |  |  | # | 
| 3412 | 10 |  |  |  |  | 677 | 0 && debug("in destroy self $self, param %s", Dumper(\@_)); | 
| 3413 | 10 |  |  |  |  | 87 | my $time_request=sprintf('%0.4f', time()-$self->{'_time'}); | 
| 3414 | 10 |  |  |  |  | 17 | 0 && debug("page request cycle time , $time_request sec"); | 
| 3415 |  |  |  |  |  |  |  | 
| 3416 |  |  |  |  |  |  |  | 
| 3417 |  |  |  |  |  |  | #  Destroy object | 
| 3418 |  |  |  |  |  |  | # | 
| 3419 | 10 |  |  |  |  | 12 | %{$self}=(); | 
|  | 10 |  |  |  |  | 77 |  | 
| 3420 | 10 |  |  |  |  | 119 | undef $self; | 
| 3421 |  |  |  |  |  |  |  | 
| 3422 |  |  |  |  |  |  | } | 
| 3423 |  |  |  |  |  |  |  | 
| 3424 |  |  |  |  |  |  |  | 
| 3425 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 3426 |  |  |  |  |  |  |  | 
| 3427 |  |  |  |  |  |  |  | 
| 3428 |  |  |  |  |  |  | #  Get self ref | 
| 3429 |  |  |  |  |  |  | # | 
| 3430 | 0 |  |  | 0 |  | 0 | my $self=$_[0]; | 
| 3431 | 0 |  |  |  |  | 0 | 0 && debug("AUTOLOAD $self, $AUTOLOAD"); | 
| 3432 |  |  |  |  |  |  |  | 
| 3433 |  |  |  |  |  |  |  | 
| 3434 |  |  |  |  |  |  | #  Get method user was looking for | 
| 3435 |  |  |  |  |  |  | # | 
| 3436 | 0 |  |  |  |  | 0 | my $method=(reverse split(/\:+/, $AUTOLOAD))[0]; | 
| 3437 |  |  |  |  |  |  |  | 
| 3438 |  |  |  |  |  |  |  | 
| 3439 |  |  |  |  |  |  | #  Vars for iterator, call stack | 
| 3440 |  |  |  |  |  |  | # | 
| 3441 | 0 |  |  |  |  | 0 | my $i; my @caller; | 
| 3442 |  |  |  |  |  |  |  | 
| 3443 |  |  |  |  |  |  |  | 
| 3444 |  |  |  |  |  |  | #  Start going backwards through call stack, looking for package that can | 
| 3445 |  |  |  |  |  |  | #  run method, pass control to it if found | 
| 3446 |  |  |  |  |  |  | # | 
| 3447 | 0 |  |  |  |  | 0 | my %caller; | 
| 3448 | 0 |  |  |  |  | 0 | while (my $caller=(caller($i++))[0]) { | 
| 3449 | 0 | 0 |  |  |  | 0 | next if ($caller{$caller}++); | 
| 3450 | 0 |  |  |  |  | 0 | push @caller, $caller; | 
| 3451 | 0 | 0 |  |  |  | 0 | if (my $cr=UNIVERSAL::can($caller, $method)) { | 
| 3452 |  |  |  |  |  |  |  | 
| 3453 |  |  |  |  |  |  | # POLLUTE is virtually useless - no speedup in real life .. | 
| 3454 | 0 | 0 |  |  |  | 0 | if ($WEBDYNE_AUTOLOAD_POLLUTE) { | 
| 3455 | 0 |  |  |  |  | 0 | my $class=ref($self); | 
| 3456 | 0 |  |  |  |  | 0 | *{"${class}::${method}"}=$cr; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3457 |  |  |  |  |  |  | } | 
| 3458 |  |  |  |  |  |  |  | 
| 3459 |  |  |  |  |  |  | #return $cr->($self, @_); | 
| 3460 | 0 |  |  |  |  | 0 | goto &{$cr} | 
|  | 0 |  |  |  |  | 0 |  | 
| 3461 |  |  |  |  |  |  | } | 
| 3462 |  |  |  |  |  |  | } | 
| 3463 |  |  |  |  |  |  |  | 
| 3464 |  |  |  |  |  |  |  | 
| 3465 |  |  |  |  |  |  | #  If we get here, we could not find the method in any caller. Error | 
| 3466 |  |  |  |  |  |  | # | 
| 3467 | 0 |  |  |  |  | 0 | err ("unable to find method '$method' in call stack: %s", join(', ', @caller)); | 
| 3468 | 0 |  |  |  |  | 0 | goto RENDER_ERROR; | 
| 3469 |  |  |  |  |  |  |  | 
| 3470 |  |  |  |  |  |  | } | 
| 3471 |  |  |  |  |  |  |  | 
| 3472 |  |  |  |  |  |  |  | 
| 3473 |  |  |  |  |  |  | #  Package to tie select()ed output handle to so we can override print() command | 
| 3474 |  |  |  |  |  |  | # | 
| 3475 |  |  |  |  |  |  | package WebDyne::TieHandle; | 
| 3476 |  |  |  |  |  |  |  | 
| 3477 |  |  |  |  |  |  |  | 
| 3478 |  |  |  |  |  |  | sub TIEHANDLE { | 
| 3479 |  |  |  |  |  |  |  | 
| 3480 | 10 |  |  | 10 |  | 30 | my ($class, $self)=@_; | 
| 3481 | 10 |  |  |  |  | 48 | bless \$self, $class; | 
| 3482 |  |  |  |  |  |  | } | 
| 3483 |  |  |  |  |  |  |  | 
| 3484 |  |  |  |  |  |  |  | 
| 3485 |  |  |  |  |  |  | sub PRINT { | 
| 3486 |  |  |  |  |  |  |  | 
| 3487 | 3 |  |  | 3 |  | 6 | my $self=shift(); | 
| 3488 | 3 |  |  |  |  | 4 | return ${$self}->print(@_); | 
|  | 3 |  |  |  |  | 11 |  | 
| 3489 |  |  |  |  |  |  |  | 
| 3490 |  |  |  |  |  |  | } | 
| 3491 |  |  |  |  |  |  |  | 
| 3492 |  |  |  |  |  |  |  | 
| 3493 |  |  |  |  |  |  | sub PRINTF { | 
| 3494 |  |  |  |  |  |  |  | 
| 3495 | 0 |  |  | 0 |  | 0 | my $self=shift(); | 
| 3496 | 0 |  |  |  |  | 0 | return ${$self}->printf(@_); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3497 |  |  |  |  |  |  |  | 
| 3498 |  |  |  |  |  |  | } | 
| 3499 |  |  |  |  |  |  |  | 
| 3500 |  |  |  |  |  |  |  | 
| 3501 |  |  |  | 0 |  |  | sub DESTROY { | 
| 3502 |  |  |  |  |  |  | } | 
| 3503 |  |  |  |  |  |  |  | 
| 3504 |  |  |  |  |  |  |  | 
| 3505 |  |  |  | 10 |  |  | sub UNTIE { | 
| 3506 |  |  |  |  |  |  | } | 
| 3507 |  |  |  |  |  |  |  | 
| 3508 |  |  |  |  |  |  |  | 
| 3509 |  |  |  | 0 |  |  | sub AUTOLOAD { | 
| 3510 |  |  |  |  |  |  | } | 
| 3511 |  |  |  |  |  |  |  | 
| 3512 |  |  |  |  |  |  |  | 
| 3513 |  |  |  |  |  |  | __END__ |