| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | 
| 2 |  |  |  |  |  |  | # For documentation for this module, please see the end of this file | 
| 3 |  |  |  |  |  |  | # or try `perldoc Apache::ASP` | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | package Apache::ASP; | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | $VERSION = 2.62; | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | #require DynaLoader; | 
| 10 |  |  |  |  |  |  | #@ISA = qw(DynaLoader); | 
| 11 |  |  |  |  |  |  | #bootstrap Apache::ASP $VERSION; | 
| 12 |  |  |  |  |  |  |  | 
| 13 | 57 |  |  | 57 |  | 5072 | use Digest::MD5 qw(md5_hex); | 
|  | 57 |  |  |  |  | 647 |  | 
|  | 57 |  |  |  |  | 8387 |  | 
| 14 | 57 |  |  | 57 |  | 400 | use Cwd qw(cwd); | 
|  | 57 |  |  |  |  | 162 |  | 
|  | 57 |  |  |  |  | 4884 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | # create multiple entries for this symbols for StatINC | 
| 17 | 52 |  |  | 52 |  | 372 | use Fcntl qw(:flock O_RDWR O_CREAT); | 
|  | 52 |  |  |  |  | 202 |  | 
|  | 52 |  |  |  |  | 10032 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | # load these always, but only load ::State, ::Session, ::Application | 
| 20 |  |  |  |  |  |  | # at runtime in non mod_perl environments since they may not be needed | 
| 21 | 52 |  |  | 52 |  | 39877 | use Apache::ASP::GlobalASA; | 
|  | 52 |  |  |  |  | 266 |  | 
|  | 52 |  |  |  |  | 2979 |  | 
| 22 | 47 |  |  | 47 |  | 65136 | use Apache::ASP::Response; | 
|  | 47 |  |  |  |  | 241 |  | 
|  | 47 |  |  |  |  | 2141 |  | 
| 23 | 47 |  |  | 47 |  | 37683 | use Apache::ASP::Request; | 
|  | 47 |  |  |  |  | 162 |  | 
|  | 47 |  |  |  |  | 1695 |  | 
| 24 | 47 |  |  | 47 |  | 37325 | use Apache::ASP::Server; | 
|  | 47 |  |  |  |  | 127 |  | 
|  | 47 |  |  |  |  | 1674 |  | 
| 25 | 47 |  |  | 47 |  | 33829 | use Apache::ASP::Date; | 
|  | 46 |  |  |  |  | 181 |  | 
|  | 46 |  |  |  |  | 3997 |  | 
| 26 | 46 |  |  | 47 |  | 35876 | use Apache::ASP::Lang::PerlScript; | 
|  | 46 |  |  |  |  | 121 |  | 
|  | 46 |  |  |  |  | 1898 |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 46 |  |  | 47 |  | 5083 | use Carp qw(confess cluck); | 
|  | 46 |  |  |  |  | 93 |  | 
|  | 46 |  |  |  |  | 4116 |  | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 46 |  |  | 46 |  | 258 | use strict; | 
|  | 46 |  |  |  |  | 89 |  | 
|  | 46 |  |  |  |  | 1774 |  | 
| 31 | 46 |  |  | 46 |  | 357 | no strict qw(refs); | 
|  | 46 |  |  |  |  | 93 |  | 
|  | 46 |  |  |  |  | 2312 |  | 
| 32 | 46 |  |  |  |  | 183423 | use vars qw($VERSION | 
| 33 |  |  |  |  |  |  | %NetConfig %LoadedModules %LoadModuleErrors | 
| 34 |  |  |  |  |  |  | %Codes %includes %Includes %CompiledIncludes | 
| 35 |  |  |  |  |  |  | @Objects %Register %XSLT | 
| 36 |  |  |  |  |  |  | $ServerID $ServerPID $SrandPid | 
| 37 |  |  |  |  |  |  | $CompileErrorSize $CacheSize @CompileChecksumKeys | 
| 38 |  |  |  |  |  |  | %ScriptLanguages $ShareDir $INCDir $AbsoluteFileMatch | 
| 39 |  |  |  |  |  |  | $QuickStartTime | 
| 40 |  |  |  |  |  |  | $SessionCookieName | 
| 41 |  |  |  |  |  |  | $LoadModPerl | 
| 42 |  |  |  |  |  |  | $ModPerl2 | 
| 43 | 46 |  |  | 46 |  | 232 | ); | 
|  | 46 |  |  |  |  | 86 |  | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | # other common modules load now, these are optional though, so we do not error upon failure | 
| 46 |  |  |  |  |  |  | # just do this once perl mod_perl parent startup | 
| 47 |  |  |  |  |  |  | unless($LoadModPerl++) { | 
| 48 |  |  |  |  |  |  | my @load_modules = qw( Config lib Time::HiRes ); | 
| 49 |  |  |  |  |  |  | if($ENV{MOD_PERL}) { | 
| 50 |  |  |  |  |  |  | # Only pre-load these if in a mod_perl environment for sharing memory post fork. | 
| 51 |  |  |  |  |  |  | # These will not be loaded then for CGI until absolutely necessary at runtime | 
| 52 |  |  |  |  |  |  | push(@load_modules, qw( | 
| 53 |  |  |  |  |  |  | mod_perl | 
| 54 |  |  |  |  |  |  | MLDBM::Serializer::Data::Dumper Devel::Symdump CGI | 
| 55 |  |  |  |  |  |  | Apache::ASP::StateManager Apache::ASP::Session Apache::ASP::Application | 
| 56 |  |  |  |  |  |  | Apache::ASP::StatINC Apache::ASP::Error | 
| 57 |  |  |  |  |  |  | ) | 
| 58 |  |  |  |  |  |  | ); | 
| 59 |  |  |  |  |  |  | } | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | for my $module ( @load_modules ) { | 
| 62 | 46 |  |  | 46 |  | 461 | eval "use $module ();"; | 
|  | 46 |  |  | 46 |  | 111 |  | 
|  | 46 |  |  | 46 |  | 573 |  | 
|  | 46 |  |  |  |  | 48237 |  | 
|  | 46 |  |  |  |  | 35450 |  | 
|  | 46 |  |  |  |  | 565 |  | 
|  | 46 |  |  |  |  | 51076 |  | 
|  | 46 |  |  |  |  | 137956 |  | 
|  | 46 |  |  |  |  | 844 |  | 
| 63 |  |  |  |  |  |  | } | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | if(exists $ENV{MOD_PERL_API_VERSION}) { | 
| 66 |  |  |  |  |  |  | if($ModPerl2 = ($ENV{MOD_PERL_API_VERSION} >= 2)) { | 
| 67 |  |  |  |  |  |  | if($ModPerl2) { | 
| 68 |  |  |  |  |  |  | eval "use Apache::ASP::ApacheCommon ();"; | 
| 69 |  |  |  |  |  |  | die($@) if $@; | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  | } | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | ## HEADER TOKEN TWEAK | 
| 76 |  |  |  |  |  |  | # This must be called outside the above load module block, so that | 
| 77 |  |  |  |  |  |  | # its gets run whenever this module is loaded | 
| 78 |  |  |  |  |  |  | # This didn't work in 1.27 mod_perl, with DSO enabled, would | 
| 79 |  |  |  |  |  |  | # put the Apache::ASP token in front. | 
| 80 |  |  |  |  |  |  | # eval {     &Apache::add_version_component("Apache::ASP/$VERSION"); }; | 
| 81 |  |  |  |  |  |  | # $Apache::Server::AddPerlVersion = 1; | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | #use integer; # don't use screws up important numeric logic | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | @Objects = ('Application', 'Session', 'Response', 'Server', 'Request'); | 
| 86 | 45 |  |  | 45 | 0 | 953 | map { eval "sub $_ { shift->{$_} }" } @Objects; | 
|  | 0 |  |  | 0 | 0 | 0 |  | 
|  | 0 |  |  | 0 | 0 | 0 |  | 
|  | 0 |  |  | 0 | 0 | 0 |  | 
|  | 23 |  |  | 23 | 0 | 1227 |  | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | # use regexp directly, not sub for speed | 
| 89 |  |  |  |  |  |  | $AbsoluteFileMatch = '^(/|[a-zA-Z]:)'; | 
| 90 |  |  |  |  |  |  | $CacheSize = 1024*1024*10; | 
| 91 |  |  |  |  |  |  | $SessionCookieName = 'session-id'; | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | # ServerID creates a unique identifier for the server | 
| 94 |  |  |  |  |  |  | srand(); | 
| 95 |  |  |  |  |  |  | $ServerID = substr(md5_hex($$.rand().time().(-M('..')||'').(-M('/')||'')), 0, 16); | 
| 96 |  |  |  |  |  |  | $ServerPID  = $$; | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | # DEFAULT VALUES | 
| 99 |  |  |  |  |  |  | $Apache::ASP::CompileErrorSize = 500; | 
| 100 |  |  |  |  |  |  | @CompileChecksumKeys = qw ( Global DynamicIncludes UseStrict XMLSubsMatch XMLSubsPerlArgs XMLSubsStrict GlobalPackage UniquePackages IncludesDir InodeNames PodComments ); | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | %ScriptLanguages = ( | 
| 103 |  |  |  |  |  |  | 'PerlScript' => 1, | 
| 104 |  |  |  |  |  |  | ); | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | &InitPaths(); | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | %Apache::ASP::LoadModuleErrors = | 
| 109 |  |  |  |  |  |  | ( | 
| 110 |  |  |  |  |  |  | 'Filter' => | 
| 111 |  |  |  |  |  |  | "Apache::Filter was not loaded correctly for using SSI filtering.  ". | 
| 112 |  |  |  |  |  |  | "If you don't want to use filtering, make sure you turn the Filter ". | 
| 113 |  |  |  |  |  |  | "config option off whereever it's being used", | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | Clean => undef, | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | CreateObject => | 
| 118 |  |  |  |  |  |  | 'OLE-active objects not supported for this platform, '. | 
| 119 |  |  |  |  |  |  | 'try installing Win32::OLE', | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | Gzip => | 
| 122 |  |  |  |  |  |  | 'Compress::Zlib is needed to make gzip content-encoding work, '. | 
| 123 |  |  |  |  |  |  | 'If you want to use this feature, get yourself the latest '. | 
| 124 |  |  |  |  |  |  | 'Compress::Zlib from CPAN. ', | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | HiRes => undef, | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | FormFill => | 
| 129 |  |  |  |  |  |  | 'HTML::FillInForm is needed to use the FormFill feature '. | 
| 130 |  |  |  |  |  |  | 'for auto filling forms with $Response->Form() data', | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | MailAlert => undef, | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | SendMail => "No mailing support", | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | StateDB => | 
| 137 |  |  |  |  |  |  | 'cannot load StateDB '. | 
| 138 |  |  |  |  |  |  | 'must be a valid perl module with a db tied hash interface '. | 
| 139 |  |  |  |  |  |  | 'such as: SDBM_File (default), or DB_File', | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | StateSerializer => | 
| 142 |  |  |  |  |  |  | 'cannot load StateSerializer '. | 
| 143 |  |  |  |  |  |  | 'must be a valid serializing perl module for use with MLDBM '. | 
| 144 |  |  |  |  |  |  | 'such as Data::Dumper (default), or Storable', | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | StatINC => "You need this module for StatINC, please download it from CPAN", | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | 'Cache' => "You need this module for xml output caching", | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | XSLT => 'Cannot load XML::XSLT.  Try installing the module.', | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | ); | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | sub handler { | 
| 156 | 48 |  |  | 48 | 0 | 210 | my($package, $r) = @_; | 
| 157 | 48 |  |  |  |  | 130 | my $status = 200; | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | # allows it to be called as an object method | 
| 160 | 48 | 100 |  |  |  | 381 | ref $package and $r = $package; | 
| 161 |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | # default to Apache request object if not passed in, for possible DSO fix | 
| 163 |  |  |  |  |  |  | # rarely happens, but just in case | 
| 164 | 48 |  |  |  |  | 103 | my $filename; | 
| 165 | 48 | 50 |  |  |  | 133 | unless($filename = eval { $r->filename }) { | 
|  | 48 |  |  |  |  | 2336 |  | 
| 166 | 0 | 0 |  |  |  | 0 | my $rtest = $ModPerl2 ? Apache2::RequestUtil->request() : Apache->request(); | 
| 167 | 0 | 0 |  |  |  | 0 | if($filename = eval { $rtest->filename }) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 168 | 0 |  |  |  |  | 0 | $r = $rtest; | 
| 169 |  |  |  |  |  |  | } else { | 
| 170 | 0 |  |  |  |  | 0 | return &DSOError($rtest); | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | # better error checking ? | 
| 175 | 48 |  | 33 |  |  | 743 | $filename ||= $r->filename(); | 
| 176 |  |  |  |  |  |  | # using _ is optimized to use last stat() record | 
| 177 | 48 | 50 | 33 |  |  | 2090 | return(404) if (! -e $filename or -d _); | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | # alias $0 to filename, bind to glob for bug workaround | 
| 180 | 48 |  |  |  |  | 187 | local *0 = \$filename; | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | # ASP object creation, a lot goes on in there! | 
| 183 |  |  |  |  |  |  | # method call used for speed optimization, as OO calls are slow | 
| 184 | 48 |  |  |  |  | 292 | my $self = &Apache::ASP::new('Apache::ASP', $r, $filename); | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | # for runtime use/require library loads from global/INCDir | 
| 187 |  |  |  |  |  |  | # do this in the handler section to cover all the execution stages | 
| 188 |  |  |  |  |  |  | # following object set up as possible. | 
| 189 | 48 |  |  |  |  | 692 | local @INC = ($self->{global}, $INCDir, @INC); | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | # Execute if no errors | 
| 192 | 48 | 50 |  |  |  | 1499 | $self->{errs} || &Run($self); | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  | # moved print of object to the end, so we'll pick up all the | 
| 195 |  |  |  |  |  |  | # runtime config directives set while the code is running | 
| 196 |  |  |  |  |  |  |  | 
| 197 | 48 | 100 |  |  |  | 277 | $self->{dbg} && $self->Debug("ASP Done Processing $self", $self ); | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | # error processing | 
| 200 | 48 | 50 |  |  |  | 215 | if($self->{errs}) { | 
| 201 | 0 |  |  |  |  | 0 | require Apache::ASP::Error; | 
| 202 | 0 |  |  |  |  | 0 | $status = $self->ProcessErrors; | 
| 203 |  |  |  |  |  |  | } | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | # XX return code of 302 hangs server on WinNT | 
| 206 |  |  |  |  |  |  | # STATUS hook back to Apache | 
| 207 | 48 |  |  |  |  | 147 | my $response = $self->{Response}; | 
| 208 | 48 | 50 | 66 |  |  | 537 | if($status != 500 and defined $response->{Status} and $response->{Status} != 302) { | 
|  |  |  | 66 |  |  |  |  | 
| 209 |  |  |  |  |  |  | # if still default then set to what has been set by the | 
| 210 |  |  |  |  |  |  | # developer | 
| 211 | 0 |  |  |  |  | 0 | $status = $response->{Status}; | 
| 212 |  |  |  |  |  |  | } | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | # X: we DESTROY in register_cleanup, but if we are filtering, and we | 
| 215 |  |  |  |  |  |  | # handle a virtual request to an asp app, we need to free up the | 
| 216 |  |  |  |  |  |  | # the locked resources now, or the session requests will collide | 
| 217 |  |  |  |  |  |  | # a performance hack would be to share an asp object created between | 
| 218 |  |  |  |  |  |  | # virtual requests, but don't worry about it for now since using SSI | 
| 219 |  |  |  |  |  |  | # is not really performance oriented anyway. | 
| 220 |  |  |  |  |  |  | # | 
| 221 |  |  |  |  |  |  | # If we are not filtering, we let RegisterCleanup get it, since | 
| 222 |  |  |  |  |  |  | # there will be a perceived performance increase on the client side | 
| 223 |  |  |  |  |  |  | # since the connection is terminated before the garabage collection is run. | 
| 224 |  |  |  |  |  |  | # | 
| 225 |  |  |  |  |  |  | # Also need to destroy if we return a 500, as we could be serving an | 
| 226 |  |  |  |  |  |  | # error doc next, before the cleanup phase | 
| 227 |  |  |  |  |  |  |  | 
| 228 | 48 | 50 | 33 |  |  | 1706 | if($self->{filter} || ($status == 500) || ( $r->isa('Apache::ASP::CGI'))) { | 
|  |  |  | 33 |  |  |  |  | 
| 229 | 48 |  |  |  |  | 256 | $self->DESTROY(); | 
| 230 |  |  |  |  |  |  | } | 
| 231 |  |  |  |  |  |  |  | 
| 232 | 48 | 50 |  |  |  | 228 | if($status eq '200') { | 
| 233 | 48 |  |  |  |  | 108 | $status = 0; # OK status code is default unless there was an internal error | 
| 234 |  |  |  |  |  |  | } | 
| 235 |  |  |  |  |  |  |  | 
| 236 | 48 |  |  |  |  | 347 | $status; | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | sub Warn { | 
| 240 | 0 | 0 | 0 | 0 | 0 | 0 | shift if(ref($_[0]) or $_[0] eq 'Apache::ASP'); | 
| 241 | 0 |  |  |  |  | 0 | print STDERR "[ASP WARN] ", @_; | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | sub new { | 
| 245 | 69 |  |  | 69 | 0 | 346 | my($class, $r, $filename) = @_; | 
| 246 | 69 | 50 |  |  |  | 286 | $r || die("need Apache->request() object to Apache::ASP->new(\$r)"); | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | # $StartTime is set by asp-perl early on before modules are loaded | 
| 249 |  |  |  |  |  |  | # for more accurate per time tracking.  Unset, so this init load time does | 
| 250 |  |  |  |  |  |  | # not get used more than once. | 
| 251 | 69 |  |  |  |  | 325 | my $start_time; | 
| 252 | 69 | 100 |  |  |  | 262 | if($QuickStartTime) { | 
| 253 | 1 |  |  |  |  | 3 | $start_time = $QuickStartTime; | 
| 254 | 1 |  |  |  |  | 4 | $QuickStartTime = undef; | 
| 255 |  |  |  |  |  |  | } else { | 
| 256 | 68 |  | 33 |  |  | 155 | $start_time = eval { &Time::HiRes::time(); } || time(); | 
| 257 |  |  |  |  |  |  | } | 
| 258 |  |  |  |  |  |  |  | 
| 259 | 69 |  |  |  |  | 601 | local $SIG{__DIE__} = \&Carp::confess; | 
| 260 |  |  |  |  |  |  | # like cgi, operate in the scripts directory | 
| 261 | 69 |  | 66 |  |  | 855 | $filename ||= $r->filename(); | 
| 262 | 69 |  |  |  |  | 1001 | $filename =~ m|^(.*?[/\\]?)([^/\\]+)$|; | 
| 263 | 69 |  | 100 |  |  | 403 | my $dirname = $1 || '.'; | 
| 264 | 69 |  |  |  |  | 499 | my $basename = $2; | 
| 265 | 69 | 50 |  |  |  | 1729 | chdir($dirname) || die("can't chdir to $dirname: $!"); | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | # temp object just to call config() on, do not bless since we | 
| 268 |  |  |  |  |  |  | # do not want the object to be DESTROY()'d | 
| 269 | 69 |  |  |  |  | 2165 | my $dir_config = $r->dir_config; | 
| 270 | 69 |  |  |  |  | 2427 | my $headers_in = $r->headers_in; | 
| 271 | 69 |  |  |  |  | 855 | my $self = { r => $r, dir_config => $dir_config }; | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | # global is the default for the state dir and also | 
| 274 |  |  |  |  |  |  | # a default lib path for perl, as well as where global.asa | 
| 275 |  |  |  |  |  |  | # can be found | 
| 276 | 69 |  | 100 |  |  | 420 | my $global = &get_dir_config($dir_config, 'Global') || '.'; | 
| 277 | 69 |  |  |  |  | 417 | $global = &AbsPath($global, $dirname); | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | # asp object is handy for passing state around | 
| 280 | 69 | 50 | 100 |  |  | 416 | $self = bless | 
| 281 |  |  |  |  |  |  | { | 
| 282 |  |  |  |  |  |  | 'basename'       => $basename, | 
| 283 |  |  |  |  |  |  | 'cleanup'        => [], | 
| 284 |  |  |  |  |  |  | 'dbg'            => &get_dir_config($dir_config, 'Debug') || 0,  # debug level | 
| 285 |  |  |  |  |  |  | 'destroy'        => 1, | 
| 286 |  |  |  |  |  |  | 'dir_config'     => $dir_config, | 
| 287 |  |  |  |  |  |  | 'headers_in'     => $headers_in, | 
| 288 |  |  |  |  |  |  | filename         => $filename, | 
| 289 |  |  |  |  |  |  | global           => $global, | 
| 290 |  |  |  |  |  |  | global_package   => &get_dir_config($dir_config, 'GlobalPackage'), | 
| 291 |  |  |  |  |  |  | inode_names      => &get_dir_config($dir_config, 'InodeNames'), | 
| 292 |  |  |  |  |  |  | no_cache         => &get_dir_config($dir_config, 'NoCache'), | 
| 293 |  |  |  |  |  |  | 'r'              => $r, # apache request object | 
| 294 |  |  |  |  |  |  | start_time       => $start_time, | 
| 295 |  |  |  |  |  |  | stat_scripts     => &config($self, 'StatScripts', undef, 1), | 
| 296 |  |  |  |  |  |  | stat_inc         => &get_dir_config($dir_config, 'StatINC'), | 
| 297 |  |  |  |  |  |  | stat_inc_match   => &get_dir_config($dir_config, 'StatINCMatch'), | 
| 298 |  |  |  |  |  |  | use_strict       => &get_dir_config($dir_config, 'UseStrict'), | 
| 299 |  |  |  |  |  |  | win32            => ($^O eq 'MSWin32') ? 1 : 0, | 
| 300 |  |  |  |  |  |  | xslt             => &get_dir_config($dir_config, 'XSLT'), | 
| 301 |  |  |  |  |  |  | }, $class; | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | # Only if debug is negative do we kick out all the internal stuff | 
| 304 | 69 | 100 |  |  |  | 2454 | if($self->{dbg}) { | 
| 305 | 9 | 50 |  |  |  | 37 | if($self->{dbg} < 0) { | 
| 306 | 0 |  |  |  |  | 0 | *Debug = *Out; | 
| 307 | 0 |  |  |  |  | 0 | $self->{dbg} = -1 * $self->{dbg}; | 
| 308 |  |  |  |  |  |  | } else { | 
| 309 | 9 |  |  |  |  | 54 | *Debug = *Null; | 
| 310 |  |  |  |  |  |  | } | 
| 311 | 9 |  |  |  |  | 211 | $self->Debug('RUN ASP (v'. $VERSION .") for $self->{filename}"); | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  | } else { | 
| 314 | 60 |  |  |  |  | 377 | *Debug = *Null; | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | # Ken said no need for seed ;), now we just make sure its called post fork | 
| 318 |  |  |  |  |  |  | # Patch from Ime suggested no need for %SrandPid, just srand() again when $$ has changed | 
| 319 | 69 | 100 | 66 |  |  | 712 | unless($SrandPid && $SrandPid == $$) { | 
| 320 | 46 | 100 |  |  |  | 398 | $self->{dbg} && $self->Debug("call srand() post fork"); | 
| 321 | 46 |  |  |  |  | 2499 | srand(); | 
| 322 | 46 |  |  |  |  | 273 | $SrandPid = $$; | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | # filtering support | 
| 326 | 69 |  |  |  |  | 241 | my $filter_config = &get_dir_config($dir_config, 'Filter'); | 
| 327 | 69 | 50 |  |  |  | 286 | if($filter_config) { | 
| 328 | 0 | 0 |  |  |  | 0 | if($self->LoadModules('Filter', 'Apache::Filter')) { | 
| 329 |  |  |  |  |  |  | # new filter_register with Apache::Filter 1.013 | 
| 330 | 0 | 0 |  |  |  | 0 | if($r->can('filter_register')) { | 
| 331 | 0 |  |  |  |  | 0 | $self->{r} = $r = $r->filter_register; | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  |  | 
| 334 | 0 | 0 | 0 |  |  | 0 | if ($r->can('filter_input') && $r->can('get_handlers')) { | 
| 335 | 0 |  |  |  |  | 0 | $self->{filter} = 1; | 
| 336 |  |  |  |  |  |  | #X: do something with the return code, can't now because | 
| 337 |  |  |  |  |  |  | # apache constants aren't working on my win32 | 
| 338 | 0 |  |  |  |  | 0 | my($fh, $rc) = $r->filter_input(); | 
| 339 | 0 |  |  |  |  | 0 | $self->{filehandle} = $fh; | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  | } else { | 
| 342 | 0 | 0 |  |  |  | 0 | if(! $r->can('get_handlers')) { | 
| 343 | 0 |  |  |  |  | 0 | $self->Error("You need at least mod_perl 1.16 to use SSI filtering"); | 
| 344 |  |  |  |  |  |  | } else { | 
| 345 | 0 |  |  |  |  | 0 | $self->Error("Apache::Filter was not loaded correctly for using SSI filtering.  ". | 
| 346 |  |  |  |  |  |  | "If you don't want to use filtering, make sure you turn the Filter ". | 
| 347 |  |  |  |  |  |  | "config option off whereever it's being used"); | 
| 348 |  |  |  |  |  |  | } | 
| 349 |  |  |  |  |  |  | } | 
| 350 |  |  |  |  |  |  | } | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | # gzip content encoding option by ime@iae.nl 28/4/2000 | 
| 353 | 69 |  |  |  |  | 491 | my $compressgzip_config = &get_dir_config($dir_config, 'CompressGzip'); | 
| 354 | 69 | 50 |  |  |  | 330 | if($compressgzip_config) { | 
| 355 | 0 | 0 |  |  |  | 0 | if($self->LoadModule('Gzip','Compress::Zlib')) { | 
| 356 | 0 |  |  |  |  | 0 | $self->{compressgzip} = 1; | 
| 357 |  |  |  |  |  |  | } | 
| 358 |  |  |  |  |  |  | } | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | # must have global directory into which we put the global.asa | 
| 361 |  |  |  |  |  |  | # and possibly state files, optimize out the case of . or .. | 
| 362 | 69 | 100 |  |  |  | 1355 | if($self->{global} !~ /^(\.|\.\.)$/) { | 
| 363 | 28 | 50 |  |  |  | 1140 | -d $self->{global} or | 
| 364 |  |  |  |  |  |  | $self->Error("global path, $self->{global}, is not a directory"); | 
| 365 |  |  |  |  |  |  | } | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  | # includes_dir calculation | 
| 368 | 69 | 100 |  |  |  | 435 | if($filename =~ m,^((/|[a-zA-Z]:).*[/\\])[^/\\]+?$,) { | 
| 369 | 2 |  |  |  |  | 9 | $self->{dirname} = $1; | 
| 370 |  |  |  |  |  |  | } else { | 
| 371 | 67 |  |  |  |  | 293 | $self->{dirname} = '.'; | 
| 372 |  |  |  |  |  |  | } | 
| 373 | 69 |  | 50 |  |  | 700 | $self->{includes_dir} = [ | 
| 374 |  |  |  |  |  |  | $self->{dirname}, | 
| 375 |  |  |  |  |  |  | $self->{global}, | 
| 376 |  |  |  |  |  |  | split(/;/, &config($self, 'IncludesDir') || ''), | 
| 377 |  |  |  |  |  |  | ]; | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | # register cleanup before the state files get set in InitObjects | 
| 380 |  |  |  |  |  |  | # this way DESTROY gets called every time this script is done | 
| 381 |  |  |  |  |  |  | # we must cache $self for lookups later | 
| 382 | 69 |  |  | 67 |  | 908 | &RegisterCleanup($self, sub { $self->DESTROY }); | 
|  | 67 |  |  |  |  | 228 |  | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | #### WAS INIT OBJECTS, REMOVED DECOMP FOR SPEED | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | # GLOBALASA, RESPONSE, REQUEST, SERVER | 
| 387 |  |  |  |  |  |  | # always create these | 
| 388 |  |  |  |  |  |  | # global_asa assigns itself to parent object automatically | 
| 389 | 69 |  |  |  |  | 583 | my $global_asa = &Apache::ASP::GlobalASA::new($self); | 
| 390 | 69 |  |  |  |  | 507 | $self->{Request}   = &Apache::ASP::Request::new($self); | 
| 391 | 69 |  |  |  |  | 894 | $self->{Response}  = &Apache::ASP::Response::new($self); | 
| 392 |  |  |  |  |  |  | # Server::new() is just one line, so execute directly | 
| 393 | 69 |  |  |  |  | 575 | $self->{Server}    = bless {asp => $self}, 'Apache::ASP::Server'; | 
| 394 |  |  |  |  |  |  | #&Apache::ASP::Server::new($self); | 
| 395 |  |  |  |  |  |  |  | 
| 396 |  |  |  |  |  |  | # After GlobalASA Init, init the package that this script will execute in | 
| 397 |  |  |  |  |  |  | # must be here, and not end of new before things like Application_OnStart get run | 
| 398 |  |  |  |  |  |  | # UniquePackages & NoCache configs do not work together, NoCache wins here | 
| 399 | 69 | 100 |  |  |  | 338 | if(&config($self, 'UniquePackages')) { | 
| 400 |  |  |  |  |  |  | # id is not generally useful for the ASP object now, so calculate | 
| 401 |  |  |  |  |  |  | # it here now, only to twist the package object for this script | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | # pass in basename for where to find the file for InodeNames, and the full path | 
| 404 |  |  |  |  |  |  | # for the FileId otherwise | 
| 405 | 1 |  |  |  |  | 7 | my $package = $global_asa->{'package'}.'::'.&FileId($self, $self->{basename}, $self->{filename}); | 
| 406 | 1 |  |  |  |  | 4 | $self->{'package'} = $package; | 
| 407 | 1 |  |  |  |  | 6 | $self->{init_packages} = ['main', $global_asa->{'package'}, $self->{'package'}]; | 
| 408 |  |  |  |  |  |  | } else { | 
| 409 | 68 |  |  |  |  | 222 | $self->{'package'} = $global_asa->{'package'}; | 
| 410 | 68 |  |  |  |  | 401 | $self->{init_packages} = ['main', $global_asa->{'package'}]; | 
| 411 |  |  |  |  |  |  | } | 
| 412 |  |  |  |  |  |  |  | 
| 413 | 69 |  |  |  |  | 359 | $self->{state_dir}   = &config($self, 'StateDir', undef, $self->{global}.'/.state'); | 
| 414 | 69 |  |  |  |  | 255 | $self->{state_dir}   =~ tr///; # untaint | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | # if no state has been config'd, then set up none of the | 
| 417 |  |  |  |  |  |  | # state objects: Application, Internal, Session | 
| 418 | 69 | 100 |  |  |  | 421 | unless(&get_dir_config($dir_config, 'NoState')) { | 
| 419 |  |  |  |  |  |  | # load at runtime for CGI environments, preloaded for mod_perl | 
| 420 | 28 |  |  |  |  | 7799 | require Apache::ASP::StateManager; | 
| 421 | 28 |  |  |  |  | 136 | &InitState($self); | 
| 422 |  |  |  |  |  |  | } | 
| 423 |  |  |  |  |  |  |  | 
| 424 | 69 |  |  |  |  | 644 | $self; | 
| 425 |  |  |  |  |  |  | } | 
| 426 |  |  |  |  |  |  |  | 
| 427 |  |  |  |  |  |  | # called upon every end of connection by RegisterCleanup | 
| 428 |  |  |  |  |  |  | sub DESTROY { | 
| 429 | 135 |  |  | 135 |  | 471 | my $self = shift; | 
| 430 |  |  |  |  |  |  |  | 
| 431 | 135 | 100 |  |  |  | 721 | return unless $self->{destroy}; # still active object | 
| 432 | 68 | 100 |  |  |  | 293 | $self->{dbg} && $self->Debug("destroying ASP object $self"); | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | # do before undef'ing the object references in main | 
| 435 | 68 |  |  |  |  | 139 | for my $code ( @{$self->{cleanup}} ) { | 
|  | 68 |  |  |  |  | 370 |  | 
| 436 | 0 | 0 |  |  |  | 0 | $self->{dbg} && $self->Debug("executing cleanup $code"); | 
| 437 | 0 |  |  |  |  | 0 | eval { &$code() }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 438 | 0 | 0 |  |  |  | 0 | $@ && $self->Error("executing cleanup $code error: $@"); | 
| 439 |  |  |  |  |  |  | } | 
| 440 |  |  |  |  |  |  |  | 
| 441 | 68 |  |  |  |  | 326 | local $^W = 0; # suppress untie while x inner references warnings | 
| 442 | 68 |  |  |  |  | 395 | select(STDOUT); | 
| 443 | 68 | 100 |  |  |  | 741 | untie *RESPONSE if tied *RESPONSE; | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  | # can't move this to Request::DESTROY(), then CGI object compatibility | 
| 446 |  |  |  |  |  |  | # in test ./site/eg/cgi.htm test fails, don't know why, --jc, 12/06/2002 | 
| 447 | 68 | 50 |  |  |  | 288 | untie *STDIN if tied *STDIN; | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  | # in case there is a dummy session here by the | 
| 450 |  |  |  |  |  |  | # end of object execution | 
| 451 | 68 | 100 |  |  |  | 291 | if($self->{Session}) { | 
| 452 | 28 | 50 |  |  |  | 58 | if(eval { $self->{Session}->isa('Apache::ASP::Session') }) { | 
|  | 28 |  |  |  |  | 255 |  | 
| 453 |  |  |  |  |  |  | # only the cleanup master may cleanup groups now, so OK | 
| 454 |  |  |  |  |  |  | # to call just CleanupGroups | 
| 455 | 28 |  |  |  |  | 155 | $self->CleanupGroups(); | 
| 456 |  |  |  |  |  |  | } else { | 
| 457 | 0 |  |  |  |  | 0 | $self->Debug("$self->{Session} is not an Apache::ASP::Session"); | 
| 458 | 0 |  |  |  |  | 0 | eval { $self->{Session}->DESTROY }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 459 | 0 |  |  |  |  | 0 | $self->{Session} = undef; | 
| 460 |  |  |  |  |  |  | } | 
| 461 |  |  |  |  |  |  | } | 
| 462 |  |  |  |  |  |  |  | 
| 463 |  |  |  |  |  |  | # free file handles here.  mod_perl tends to be pretty clingy | 
| 464 |  |  |  |  |  |  | # to memory | 
| 465 | 68 |  |  |  |  | 221 | for('Application', 'Internal', 'Session') { | 
| 466 |  |  |  |  |  |  | # all this stuff in here is very necessary for total cleanup | 
| 467 |  |  |  |  |  |  | # the DESTROY is the most important, as we need to explicitly free | 
| 468 |  |  |  |  |  |  | # state objects, just in case anyone else is keeping references to them | 
| 469 |  |  |  |  |  |  | # But the destroy won't work without first untieing, go figure | 
| 470 | 204 | 100 |  |  |  | 757 | next unless defined $self->{$_}; | 
| 471 | 84 |  |  |  |  | 95 | my $tied = tied %{$self->{$_}}; | 
|  | 84 |  |  |  |  | 189 |  | 
| 472 | 84 | 50 |  |  |  | 199 | next unless $tied; | 
| 473 | 84 |  |  |  |  | 95 | untie %{$self->{$_}}; | 
|  | 84 |  |  |  |  | 352 |  | 
| 474 | 84 |  |  |  |  | 297 | $tied->DESTROY(); # call explicit DESTROY | 
| 475 |  |  |  |  |  |  | } | 
| 476 |  |  |  |  |  |  |  | 
| 477 | 68 | 100 |  |  |  | 579 | if(my $caches = $self->{Caches}) { | 
| 478 |  |  |  |  |  |  | # default cache size to 10M | 
| 479 | 1 |  | 33 |  |  | 3 | $self->{cache_size} = &config($self, 'CacheSize') || $CacheSize; | 
| 480 | 1 | 50 |  |  |  | 12 | if($self->{cache_size} =~ /^([\d\.]+)(M|K|B)?$/) { | 
| 481 | 1 |  |  |  |  | 6 | my($size, $unit) = ($1, $2); | 
| 482 | 1 | 50 |  |  |  | 7 | if($unit eq 'M') { | 
|  |  | 50 |  |  |  |  |  | 
| 483 | 0 |  |  |  |  | 0 | $size *= 1024*1024; | 
| 484 |  |  |  |  |  |  | } elsif($unit eq 'K') { | 
| 485 | 1 |  |  |  |  | 6 | $size *= 1024; | 
| 486 |  |  |  |  |  |  | } | 
| 487 | 1 | 50 |  |  |  | 5 | if($size ne $self->{cache_size}) { | 
| 488 | 1 | 50 |  |  |  | 4 | $self->{dbg} && $self->Debug("converting CacheSize $self->{cache_size} to $size bytes"); | 
| 489 | 1 |  |  |  |  | 2 | $self->{cache_size} = $size; | 
| 490 |  |  |  |  |  |  | } | 
| 491 |  |  |  |  |  |  | } | 
| 492 | 1 |  |  |  |  | 4 | for my $cache (values %$caches) { | 
| 493 | 1 |  |  |  |  | 2 | my $tied = $cache; | 
| 494 | 1 | 50 | 33 |  |  | 11 | if($tied->{writes} && $tied->Size > $self->{cache_size}) { | 
| 495 | 1 | 50 |  |  |  | 157 | $self->{dbg} && $self->Debug("deleting cache $cache, size: ".$tied->Size); | 
| 496 | 1 |  |  |  |  | 7 | $tied->Delete; | 
| 497 |  |  |  |  |  |  | } else { | 
| 498 | 0 | 0 |  |  |  | 0 | $self->{dbg} && $self->Debug("cache $cache OK size, size: ".$tied->Size); | 
| 499 |  |  |  |  |  |  | } | 
| 500 | 1 |  |  |  |  | 2596 | $tied->DESTROY(); | 
| 501 |  |  |  |  |  |  | } | 
| 502 |  |  |  |  |  |  | } | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | #    $self->{'dbg'} && $self->Debug("END ASP DESTROY"); | 
| 505 | 68 | 50 |  |  |  | 655 | $self->{Request} && &Apache::ASP::Request::DESTROY($self->{Request}); | 
| 506 | 68 | 50 |  |  |  | 377 | $self->{Server} && ( %{$self->{Server}} = () ); | 
|  | 68 |  |  |  |  | 235 |  | 
| 507 | 68 | 50 |  |  |  | 323 | $self->{Response} && ( %{$self->{Response}} = () ); | 
|  | 68 |  |  |  |  | 488 |  | 
| 508 | 68 |  |  |  |  | 2244 | %$self = (); | 
| 509 |  |  |  |  |  |  |  | 
| 510 | 68 |  |  |  |  | 280 | 1; | 
| 511 |  |  |  |  |  |  | } | 
| 512 |  |  |  |  |  |  |  | 
| 513 |  |  |  |  |  |  | sub RegisterCleanup { | 
| 514 | 79 |  |  | 79 | 1 | 211 | my $self = shift; | 
| 515 |  |  |  |  |  |  |  | 
| 516 | 79 | 50 |  |  |  | 311 | if($ModPerl2) { | 
| 517 | 0 |  |  |  |  | 0 | $self->{r}->pool->cleanup_register(@_); | 
| 518 |  |  |  |  |  |  | } else { | 
| 519 | 79 |  |  |  |  | 512 | $self->{r}->register_cleanup(@_); | 
| 520 |  |  |  |  |  |  | } | 
| 521 |  |  |  |  |  |  | } | 
| 522 |  |  |  |  |  |  |  | 
| 523 |  |  |  |  |  |  | sub InitPaths { | 
| 524 |  |  |  |  |  |  |  | 
| 525 |  |  |  |  |  |  | # we load this module just to detect where the shared directory really is | 
| 526 | 46 |  |  | 46 |  | 45641 | use Apache::ASP::Share::CORE; | 
|  | 46 |  |  |  |  | 183 |  | 
|  | 46 |  |  |  |  | 1033898 |  | 
| 527 |  |  |  |  |  |  |  | 
| 528 |  |  |  |  |  |  | # major problem with %INC if we cannot get this information | 
| 529 | 46 |  | 50 | 46 | 0 | 319 | my $share_path = $INC{'Apache/ASP/Share/CORE.pm'} | 
| 530 |  |  |  |  |  |  | || die(q(can't find path for $INC{'Apache/ASP/Share/CORE.pm'})); | 
| 531 |  |  |  |  |  |  |  | 
| 532 | 46 |  |  |  |  | 374 | $share_path =~ s/CORE\.pm$//s; | 
| 533 | 46 | 100 |  |  |  | 1951 | unless($share_path =~ /$AbsoluteFileMatch/) { | 
| 534 |  |  |  |  |  |  | # this %ENV manipulation is just to allow cwd() to run in taint check mode | 
| 535 | 2 |  |  |  |  | 318 | local %ENV = %ENV; | 
| 536 | 2 |  |  |  |  | 54 | $ENV{PATH} = '/bin:/usr/bin:/usr/sbin'; | 
| 537 | 2 |  |  |  |  | 35 | delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; | 
| 538 | 2 |  |  |  |  | 10694 | my $currdir = cwd(); | 
| 539 | 2 |  |  |  |  | 399 | $share_path = "$currdir/$share_path"; | 
| 540 |  |  |  |  |  |  | } | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | # not finding the ShareDir creates a hard error, because the Apache/ASP/Share | 
| 543 |  |  |  |  |  |  | # directory will become one of the fundamental underpinings of the project | 
| 544 |  |  |  |  |  |  | # People will need to rely on being able to load shared includes, and not have | 
| 545 |  |  |  |  |  |  | # to discover the lack of loading Share:: at runtime, rather this is a compile | 
| 546 |  |  |  |  |  |  | # time error. | 
| 547 | 46 | 50 |  |  |  | 1903 | -d $share_path || die("Apache::ASP::Share directory not found.  ". | 
| 548 |  |  |  |  |  |  | "Please make sure to install all the modules that make up the Apache::ASP installation." | 
| 549 |  |  |  |  |  |  | ); | 
| 550 | 46 |  |  |  |  | 178 | $ShareDir = $share_path; | 
| 551 |  |  |  |  |  |  |  | 
| 552 |  |  |  |  |  |  | # once we find the $ShareDir, we can truncate the library path | 
| 553 |  |  |  |  |  |  | # and push it onto @INC with use lib... this is to help with loading | 
| 554 |  |  |  |  |  |  | # future Apache::ASP::* modules when the lib path it was found at is | 
| 555 |  |  |  |  |  |  | # relative to some directory.  This was needed to have the "make test" | 
| 556 |  |  |  |  |  |  | # test suite to work which loads libraries from "blib/lib", but Apache::ASP | 
| 557 |  |  |  |  |  |  | # will chdir() into the script directory so that can ruin this | 
| 558 |  |  |  |  |  |  | # library lookup. | 
| 559 |  |  |  |  |  |  | # | 
| 560 | 46 |  |  |  |  | 131 | my $lib_path = $share_path; | 
| 561 | 46 |  |  |  |  | 1094 | $lib_path =~ s/Apache.ASP.Share.?$//s; | 
| 562 | 46 | 50 |  |  |  | 1159 | -d $lib_path || die("\%INC library path $lib_path not found."); | 
| 563 | 46 |  |  |  |  | 247 | $INCDir = $lib_path; | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | # clear taint, for some reason, tr/// or s/^(.*)$/ did not work on perl 5.6.1 | 
| 566 | 46 |  |  |  |  | 356 | $INCDir =~ /^(.*)$/s; | 
| 567 | 46 |  |  |  |  | 232 | $INCDir = $1; | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  | # make sure this gets on @INC at startup, can't hurt | 
| 570 | 46 |  |  | 46 |  | 389 | eval "use lib qw($INCDir);"; | 
|  | 46 |  |  |  |  | 121 |  | 
|  | 46 |  |  |  |  | 450 |  | 
|  | 46 |  |  |  |  | 6933 |  | 
| 571 |  |  |  |  |  |  |  | 
| 572 | 46 |  |  |  |  | 16330 | 1; | 
| 573 |  |  |  |  |  |  | } | 
| 574 |  |  |  |  |  |  |  | 
| 575 |  |  |  |  |  |  | sub FileId { | 
| 576 | 160 |  |  | 160 | 0 | 441 | my($self, $file, $abs_file, $no_compile_checksum) = @_; | 
| 577 | 160 | 50 |  |  |  | 494 | $file || die("no file passed to FileId()"); | 
| 578 | 160 |  |  |  |  | 245 | my $id; | 
| 579 |  |  |  |  |  |  |  | 
| 580 |  |  |  |  |  |  | # calculate compile checksum for file id | 
| 581 | 160 | 100 |  |  |  | 653 | unless($self->{compile_checksum}) { | 
| 582 | 69 |  |  |  |  | 169 | my $r = $self->{r}; | 
| 583 | 759 | 100 |  |  |  | 1554 | my $checksum = md5_hex(join('&-+', | 
| 584 |  |  |  |  |  |  | $VERSION, | 
| 585 | 69 |  |  |  |  | 253 | map { &config($self, $_) || '' } | 
| 586 |  |  |  |  |  |  | @CompileChecksumKeys | 
| 587 |  |  |  |  |  |  | ) | 
| 588 |  |  |  |  |  |  | ); | 
| 589 |  |  |  |  |  |  | #    $self->{dbg} && $self->Debug("compile checksum $checksum"); | 
| 590 | 69 |  |  |  |  | 616 | $self->{compile_checksum} = $checksum; | 
| 591 |  |  |  |  |  |  | } | 
| 592 |  |  |  |  |  |  |  | 
| 593 | 160 | 100 |  |  |  | 534 | my $compile_checksum = $no_compile_checksum ? '' : $self->{compile_checksum}; | 
| 594 |  |  |  |  |  |  |  | 
| 595 | 160 |  |  |  |  | 367 | my @inode_stat = (); | 
| 596 | 160 | 100 |  |  |  | 672 | if($self->{inode_names}) { | 
| 597 | 1 |  |  |  |  | 13 | @inode_stat = stat($file); | 
| 598 |  |  |  |  |  |  | # one or the other device or file ids must be not 0 | 
| 599 | 1 | 0 | 33 |  |  | 5 | unless($inode_stat[0] || $inode_stat[1]) { | 
| 600 | 0 |  |  |  |  | 0 | @inode_stat = (); | 
| 601 |  |  |  |  |  |  | } | 
| 602 |  |  |  |  |  |  | } | 
| 603 |  |  |  |  |  |  |  | 
| 604 | 160 | 100 |  |  |  | 805 | if(@inode_stat) { | 
| 605 | 1 |  |  |  |  | 7 | $id = sprintf("____DEV%X_INODE%X",@inode_stat[0,1]); | 
| 606 | 1 |  |  |  |  | 4 | $id .= 'x'.$compile_checksum; | 
| 607 |  |  |  |  |  |  | } else { | 
| 608 | 159 | 100 |  |  |  | 2786 | if($abs_file) { | 
| 609 | 1 |  |  |  |  | 3 | $file = $abs_file; | 
| 610 |  |  |  |  |  |  | } | 
| 611 | 159 |  |  |  |  | 832 | $file =~ s|/+|/|sg; | 
| 612 | 159 |  |  |  |  | 988 | $file =~ s/[\Wx]/_/sg; | 
| 613 | 159 |  |  |  |  | 357 | my $file_name_length = length($file); | 
| 614 | 159 | 100 |  |  |  | 571 | if($file_name_length >= 35) { | 
| 615 | 9 |  |  |  |  | 30 | $id = substr($file, $file_name_length - 35, 36); | 
| 616 |  |  |  |  |  |  | # only do the hex of the original file to create a unique identifier for the long id | 
| 617 | 9 |  |  |  |  | 84 | $id .= 'x'.&md5_hex($file.$compile_checksum); | 
| 618 |  |  |  |  |  |  | } else { | 
| 619 | 150 |  |  |  |  | 481 | $id = $file.'x'.$compile_checksum; | 
| 620 |  |  |  |  |  |  | } | 
| 621 |  |  |  |  |  |  | } | 
| 622 |  |  |  |  |  |  |  | 
| 623 | 160 |  |  |  |  | 692 | $id = '__ASP_'.$id; | 
| 624 |  |  |  |  |  |  | } | 
| 625 |  |  |  |  |  |  |  | 
| 626 |  |  |  |  |  |  | # defaults to parsing the script's file, or data from a file handle | 
| 627 |  |  |  |  |  |  | # in the case of filtering, but we can also pass in text to parse, | 
| 628 |  |  |  |  |  |  | # which is useful for doing includes separately for compiling | 
| 629 |  |  |  |  |  |  | sub Parse { | 
| 630 | 96 |  |  | 96 | 0 | 251 | my($self, $file) = @_; | 
| 631 | 96 |  |  |  |  | 168 | my $file_exists = 0; | 
| 632 | 96 |  |  |  |  | 273 | my $parse_file = $file; | 
| 633 | 96 |  |  |  |  | 214 | my $r = $self->{r}; | 
| 634 | 96 |  |  |  |  | 152 | my $data; | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | # get script data, from varied data sources; | 
| 637 | 96 | 50 |  |  |  | 334 | $file || die("can't parse without file data"); | 
| 638 |  |  |  |  |  |  |  | 
| 639 | 96 | 100 |  |  |  | 397 | $self->{dbg} && $self->Debug("parse file $file"); | 
| 640 |  |  |  |  |  |  | # file can be a filename, scalar ref, or scalar | 
| 641 | 96 | 100 | 33 |  |  | 1875 | if(ref $file) { | 
|  |  | 50 | 33 |  |  |  |  | 
| 642 | 22 | 50 |  |  |  | 107 | if ($file =~ /SCALAR/) { | 
|  |  | 0 |  |  |  |  |  | 
| 643 | 22 |  |  |  |  | 53 | $data = $$file; | 
| 644 |  |  |  |  |  |  | } elsif ($file =~ /GLOB/) { | 
| 645 | 0 |  |  |  |  | 0 | local $/ = undef; | 
| 646 | 0 |  |  |  |  | 0 | $data = <$file> | 
| 647 |  |  |  |  |  |  | } | 
| 648 |  |  |  |  |  |  | } elsif((length($file) < 1024) && ($file !~ /^GLOB/) && (-e $file)) { | 
| 649 |  |  |  |  |  |  | # filename has length < 1024, should be fine across OS's | 
| 650 | 74 | 100 |  |  |  | 440 | $self->{dbg} && $self->Debug("parsing $file"); | 
| 651 | 74 |  |  |  |  | 125 | $data = ${$self->ReadFile($file)}; | 
|  | 74 |  |  |  |  | 314 |  | 
| 652 | 74 |  |  |  |  | 272 | $file_exists = 1; | 
| 653 | 74 |  |  |  |  | 333 | $self->{parse_file_count}++; | 
| 654 |  |  |  |  |  |  | } else { | 
| 655 | 0 |  |  |  |  | 0 | $data = $file; # raw script, no ref | 
| 656 |  |  |  |  |  |  | } | 
| 657 |  |  |  |  |  |  |  | 
| 658 |  |  |  |  |  |  | # moved parsing config here since not needed for normal | 
| 659 |  |  |  |  |  |  | # eval execution of scripts after compilation | 
| 660 | 96 | 100 |  |  |  | 731 | unless($self->{parse_config}) { | 
| 661 | 50 |  |  |  |  | 146 | $self->{parse_config} = 1; | 
| 662 | 50 |  |  |  |  | 171 | $self->{compile_includes} = &config($self, 'DynamicIncludes'); | 
| 663 | 50 |  |  |  |  | 347 | $self->{pod_comments} = &config($self, 'PodComments', undef, 1); | 
| 664 | 50 |  |  |  |  | 157 | $self->{xml_subs_strict} = &config($self, 'XMLSubsStrict'); | 
| 665 |  |  |  |  |  |  | # default XMLSubsPerlArgs to 1 for now, until 3.0 | 
| 666 | 50 |  |  |  |  | 176 | $self->{xml_subs_perl_args} = &config($self, 'XMLSubsPerlArgs', undef, 1); | 
| 667 |  |  |  |  |  |  |  | 
| 668 |  |  |  |  |  |  | # reduce (pattern) patterns to (?:pattern) to not create $1 side effect | 
| 669 | 50 | 100 |  |  |  | 177 | if($self->{xml_subs_match} = &config($self, 'XMLSubsMatch')) { | 
| 670 | 10 |  |  |  |  | 45 | $self->{xml_subs_match} =~ s/\(\?\:([^\)]*)\)/($1)/isg; | 
| 671 | 10 |  |  |  |  | 36 | $self->{xml_subs_match} =~ s/\(([^\)]*)\)/(?:$1)/isg; | 
| 672 |  |  |  |  |  |  | } | 
| 673 |  |  |  |  |  |  |  | 
| 674 | 50 |  |  |  |  | 188 | my $lang = &config($self, 'ScriptLanguage', undef, 'PerlScript'); | 
| 675 | 50 |  |  |  |  | 182 | my $module = "Apache::ASP::Lang::".$lang; | 
| 676 | 50 | 50 |  |  |  | 300 | unless($ScriptLanguages{$lang}) { | 
| 677 |  |  |  |  |  |  | #	    eval "use $module;"; | 
| 678 | 0 |  |  |  |  | 0 | $self->Error("ScriptLanguage for $lang could not be loaded: $@"); | 
| 679 | 0 |  |  |  |  | 0 | return; | 
| 680 |  |  |  |  |  |  | } | 
| 681 | 50 |  |  |  |  | 110 | eval { | 
| 682 | 50 |  |  |  |  | 799 | my $lang_object = $module->new(ASP => $self); | 
| 683 | 50 |  |  |  |  | 173 | $self->{lang_object} = $lang_object; | 
| 684 | 50 |  |  |  |  | 145 | $self->{lang_module} = $module; | 
| 685 | 50 |  |  |  |  | 127 | $self->{lang_language} = $lang; | 
| 686 | 50 |  |  |  |  | 304 | $self->{lang_comment} = $lang_object->CommentStart; | 
| 687 |  |  |  |  |  |  | }; | 
| 688 | 50 | 50 |  |  |  | 477 | if($@) { | 
| 689 | 0 |  |  |  |  | 0 | $self->Error("ScriptLanguage object for $lang failed init: $@"); | 
| 690 | 0 |  |  |  |  | 0 | return; | 
| 691 |  |  |  |  |  |  | } | 
| 692 |  |  |  |  |  |  | } | 
| 693 |  |  |  |  |  |  |  | 
| 694 | 96 |  |  |  |  | 324 | my $comment = $self->{lang_comment}; | 
| 695 | 96 | 100 |  |  |  | 285 | if(&config($self, 'CgiDoSelf')) { | 
| 696 | 85 |  |  |  |  | 540 | $data =~ s,^(.*?)__END__,,so; | 
| 697 |  |  |  |  |  |  | } | 
| 698 |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  | # do both before and after, so =pods can span includes with =pods | 
| 700 | 96 | 50 |  |  |  | 416 | if($self->{pod_comments}) { | 
| 701 | 96 |  |  |  |  | 383 | &PodComments($self, \$data); | 
| 702 |  |  |  |  |  |  | } | 
| 703 |  |  |  |  |  |  |  | 
| 704 |  |  |  |  |  |  | # if compiling includes, then do now before includes conversion | 
| 705 |  |  |  |  |  |  | # each include will also have its Script_OnParse run on it. | 
| 706 | 96 | 50 | 33 |  |  | 804 | if($self->{compile_includes} && $self->{GlobalASA}{'exists'}) { | 
| 707 | 0 |  |  |  |  | 0 | $self->{Server}{ScriptRef} = \$data; | 
| 708 | 0 |  |  |  |  | 0 | $self->{GlobalASA}->ExecuteEvent('Script_OnParse'); | 
| 709 |  |  |  |  |  |  | } | 
| 710 |  |  |  |  |  |  |  | 
| 711 |  |  |  |  |  |  | # do includes as early as possible !! so included text gets done too | 
| 712 |  |  |  |  |  |  | # this section is for file includes, we do this here instead of ssi | 
| 713 |  |  |  |  |  |  | # so it can be parsed and compiled with the script | 
| 714 | 96 |  |  |  |  | 248 | local %includes; # trap recursive includes with this | 
| 715 |  |  |  |  |  |  |  | 
| 716 |  |  |  |  |  |  | # JUST ONCE | 
| 717 |  |  |  |  |  |  | # there should only be one of these, <%@ LANGUAGE="PerlScript" %>, rip it out | 
| 718 |  |  |  |  |  |  | # we keep white space and substitue text in so the perlscript sync's up with lines | 
| 719 |  |  |  |  |  |  | # only take out the first one | 
| 720 | 96 |  |  |  |  | 233 | $data =~ s/^\#\![^\n]+(\n\s*)/\<\%$1\%\>/s; #X cgi compat ? | 
| 721 | 96 |  |  |  |  | 490 | $data =~ s/^(\s*)\<\%(\s*)\@([^\n]*?)\%\>/$1\<\%$2 ; \%\>/so; | 
| 722 |  |  |  |  |  |  |  | 
| 723 | 96 |  |  |  |  | 188 | my $root_file = $file; | 
| 724 | 96 |  |  |  |  | 163 | my $line1_added = 0; | 
| 725 | 96 |  |  |  |  | 189 | my $munge = $data; | 
| 726 | 96 |  |  |  |  | 177 | $data = ''; | 
| 727 | 96 |  |  |  |  | 154 | my($file_context, $file_line_number, $code_block); | 
| 728 | 96 |  |  |  |  | 549 | while($munge =~ s/^(.*?)\ |