Apache-ASP

 view release on metacpan or  search on metacpan

ASP.pm  view on Meta::CPAN

    my($package, $r) = @_;
    my $status = 200;
    
    # allows it to be called as an object method
    ref $package and $r = $package;

    # default to Apache request object if not passed in, for possible DSO fix
    # rarely happens, but just in case
    my $filename;
    unless($filename = eval { $r->filename }) {
        my $rtest = $ModPerl2 ? Apache2::RequestUtil->request() : Apache->request();
	if($filename = eval { $rtest->filename }) {
	    $r = $rtest;
	} else {
	    return &DSOError($rtest);
	}
    }

    # better error checking ?
    $filename ||= $r->filename();
    # using _ is optimized to use last stat() record
    return(404) if (! -e $filename or -d _);

    # alias $0 to filename, bind to glob for bug workaround
    local *0 = \$filename;

    # ASP object creation, a lot goes on in there!
    # method call used for speed optimization, as OO calls are slow
    my $self = &Apache::ASP::new('Apache::ASP', $r, $filename);

    # for runtime use/require library loads from global/INCDir
    # do this in the handler section to cover all the execution stages
    # following object set up as possible.
    local @INC = ($self->{global}, $INCDir, @INC);

    # Execute if no errors
    $self->{errs} || &Run($self);
    
    # moved print of object to the end, so we'll pick up all the 
    # runtime config directives set while the code is running

    $self->{dbg} && $self->Debug("ASP Done Processing $self", $self );

    # error processing
    if($self->{errs}) {
	require Apache::ASP::Error;
	$status = $self->ProcessErrors;
    }

    # XX return code of 302 hangs server on WinNT
    # STATUS hook back to Apache
    my $response = $self->{Response};
    if($status != 500 and defined $response->{Status} and $response->{Status} != 302) {
	# if still default then set to what has been set by the 
	# developer
	$status = $response->{Status};
    }

    # X: we DESTROY in register_cleanup, but if we are filtering, and we 
    # handle a virtual request to an asp app, we need to free up the 
    # the locked resources now, or the session requests will collide
    # a performance hack would be to share an asp object created between
    # virtual requests, but don't worry about it for now since using SSI
    # is not really performance oriented anyway.
    # 
    # If we are not filtering, we let RegisterCleanup get it, since
    # there will be a perceived performance increase on the client side
    # since the connection is terminated before the garabage collection is run.
    # 
    # Also need to destroy if we return a 500, as we could be serving an
    # error doc next, before the cleanup phase

    if($self->{filter} || ($status == 500) || ( $r->isa('Apache::ASP::CGI'))) {
	$self->DESTROY();
    }

    if($status eq '200') {
	$status = 0; # OK status code is default unless there was an internal error
    }

    $status;
}

sub Warn {
    shift if(ref($_[0]) or $_[0] eq 'Apache::ASP');
    print STDERR "[ASP WARN] ", @_;
}

sub new {
    my($class, $r, $filename) = @_;
    $r || die("need Apache->request() object to Apache::ASP->new(\$r)");

    # $StartTime is set by asp-perl early on before modules are loaded
    # for more accurate per time tracking.  Unset, so this init load time does 
    # not get used more than once.
    my $start_time;
    if($QuickStartTime) {
	$start_time = $QuickStartTime;
	$QuickStartTime = undef;
    } else {
	$start_time = eval { &Time::HiRes::time(); } || time();
    }

    local $SIG{__DIE__} = \&Carp::confess;
    # like cgi, operate in the scripts directory
    $filename ||= $r->filename();
    $filename =~ m|^(.*?[/\\]?)([^/\\]+)$|;
    my $dirname = $1 || '.';
    my $basename = $2;
    chdir($dirname) || die("can't chdir to $dirname: $!");

    # temp object just to call config() on, do not bless since we
    # do not want the object to be DESTROY()'d
    my $dir_config = $r->dir_config;
    my $headers_in = $r->headers_in;
    my $self = { r => $r, dir_config => $dir_config };

    # global is the default for the state dir and also 
    # a default lib path for perl, as well as where global.asa
    # can be found
    my $global = &get_dir_config($dir_config, 'Global') || '.';

ASP.pm  view on Meta::CPAN


Default 20 minutes, when a user's session has been inactive for this
period of time, the Session_OnEnd event is run, if defined, for 
that session, and the contents of that session are destroyed.

  PerlSetVar SessionTimeout 20 

=item SecureSession

default 0.  Sets the secure tag for the session cookie, so that the cookie
will only be transmitted by the browser under https transmissions.

  PerlSetVar SecureSession 1

=item HTTPOnlySession

default 0. Sets HttpOnly flag to session cookie to mitigate XSS attacks.
Supported by most modern browsers, it only allows access to the
session cookie by the server (ie NOT Javascript)

  PerlSetVar HTTPOnlySession 1

=item ParanoidSession

default 0.  When true, stores the user-agent header of the browser 
that creates the session and validates this against the session cookie presented.
If this check fails, the session is killed, with the rationale that 
there is a hacking attempt underway.

This config option was implemented to be a smooth upgrade, as
you can turn it off and on, without disrupting current sessions.  
Sessions must be created with this turned on for the security to take effect.

This config option is to help prevent a brute force cookie search from 
being successful. The number of possible cookies is huge, 2^128, thus making such
a hacking attempt VERY unlikely.  However, on the off chance that such
an attack is successful, the hacker must also present identical
browser headers to authenticate the session, or the session will be
destroyed.  Thus the User-Agent acts as a backup to the real session id.
The IP address of the browser cannot be used, since because of proxies,
IP addresses may change between requests during a session.

There are a few browsers that will not present a User-Agent header.
These browsers are considered to be browsers of type "Unknown", and 
this method works the same way for them.

Most people agree that this level of security is unnecessary, thus
it is titled paranoid :)

  PerlSetVar ParanoidSession 0

=item SessionSerialize

default 0, if true, locks $Session for duration of script, which
serializes requests to the $Session object.  Only one script at
a time may run, per user $Session, with sessions allowed.

Serialized requests to the session object is the Microsoft ASP way, 
but is dangerous in a production environment, where there is risk
of long-running or run-away processes.  If these things happen,
a session may be locked for an indefinite period of time.  A user
STOP button should safely quit the session however.

  PerlSetVar SessionSerialize 0

=item SessionCount

default 0, if true enables the $Application->SessionCount API
which returns how many sessions are currently active in 
the application.  This config was created 
because there is a performance hit associated with this
count tracking, so it is disabled by default.

  PerlSetVar SessionCount 1

=head2 Cookieless Sessions

=item SessionQueryParse

default 0, if true, will automatically parse the $Session
session id into the query string of each local URL found in the 
$Response buffer.  For this setting to work therefore, 
buffering must be enabled.  This parsing will only occur
when a session cookie has not been sent by a browser, so the 
first script of a session enabled site, and scripts viewed by 
web browsers that have cookies disabled will trigger this behavior.

Although this runtime parsing method is computationally 
expensive, this cost should be amortized across most users
that will not need this URL parsing.  This is a lazy programmer's
dream.  For something more efficient, look at the SessionQuery
setting.  For more information about this solution, please 
read the SESSIONS section.

  PerlSetVar SessionQueryParse 0

=item SessionQueryParseMatch

default 0, set to a regexp pattern that matches all URLs that you 
want to have SessionQueryParse parse in session ids.  By default
SessionQueryParse only modifies local URLs, but if you name
your URLs of your site with absolute URLs like http://localhost
then you will need to use this setting.  So to match 
http://localhost URLs, you might set this pattern to 
^http://localhost.  Note that by setting this config,
you are also setting SessionQueryParse.

  PerlSetVar SessionQueryParseMatch ^https?://localhost

=item SessionQuery

default 0, if set, the session id will be initialized from
the $Request->QueryString if not first found as a cookie.
You can use this setting coupled with the 

  $Server->URL($url, \%params) 

API extension to generate local URLs with session ids in their
query strings, for efficient cookieless session support.
Note that if a browser has cookies disabled, every URL
to any page that needs access to $Session will need to

ASP.pm  view on Meta::CPAN

store data as in: 

    $Session->{count}++;	# increment count by one
    %{$Session} = ();	# clear $Session data

The $Session object state is implemented through MLDBM,
and a user should be aware of the limitations of MLDBM.  
Basically, you can read complex structures, but not write 
them, directly:

  $data = $Session->{complex}{data};     # Read ok.
  $Session->{complex}{data} = $data;     # Write NOT ok.
  $Session->{complex} = {data => $data}; # Write ok, all at once.

Please see MLDBM for more information on this topic.
$Session can also be used for the following methods and properties:

=over

=item $Session->{CodePage}

Not implemented.  May never be until someone needs it.

=item $Session->{LCID}

Not implemented.  May never be until someone needs it.

=item $Session->{SessionID}

SessionID property, returns the id for the current session,
which is exchanged between the client and the server as a cookie.

=item $Session->{Timeout} [= $minutes]

Timeout property, if minutes is being assigned, sets this 
default timeout for the user session, else returns 
the current session timeout.  

If a user session is inactive for the full
timeout, the session is destroyed by the system.
No one can access the session after it times out, and the system
garbage collects it eventually.

=item $Session->Abandon()

The abandon method times out the session immediately.  All Session
data is cleared in the process, just as when any session times out.

=item $Session->Lock()  

API extension. If you are about to use $Session for many consecutive 
reads or writes, you can improve performance by explicitly locking 
$Session, and then unlocking, like:

  $Session->Lock();
  $Session->{count}++;
  $Session->{count}++;
  $Session->{count}++;
  $Session->UnLock();  

This sequence causes $Session to be locked and unlocked only
1 time, instead of the 6 times that it would be locked otherwise,
2 for each increment with one to read and one to write.

Because of flushing issues with SDBM_File and DB_File databases,
each lock actually ties fresh to the database, so the performance
savings here can be considerable.  

Note that if you have SessionSerialize set, $Session is
already locked for each script invocation automatically, as if
you had called $Session->Lock() in Script_OnStart.  Thus you 
do not need to worry about $Session locking for performance.
Please read the section on SessionSerialize for more info.

=item $Session->UnLock()

API Extension. Unlocks the $Session explicitly.  If you do not call this,
$Session will be unlocked automatically at the end of the 
script.

=back

=head2 $Response Object

This object manages the output from the ASP Application and the 
client web browser.  It does not store state information like the 
$Session object but does have a wide array of methods to call.

=over

=item $Response->{BinaryRef}

API extension. This is a perl reference to the buffered output of 
the $Response object, and can be used in the Script_OnFlush
global.asa event to modify the buffered output at runtime
to apply global changes to scripts output without having to 
modify all the scripts.  These changes take place before 
content is flushed to the client web browser.

 sub Script_OnFlush {
   my $ref = $Response->{BinaryRef};
   $$ref =~ s/\s+/ /sg; # to strip extra white space
 }

Check out the ./site/eg/global.asa for an example of its use.

=item $Response->{Buffer}

Default 1, when TRUE sends output from script to client only at
the end of processing the script.  When 0, response is not buffered,
and client is sent output as output is generated by the script.

=item $Response->{CacheControl}

Default "private", when set to public allows proxy servers to 
cache the content.  This setting controls the value set
in the HTTP header Cache-Control

=item $Response->{Charset}

This member when set appends itself to the value of the Content-Type
HTTP header.  If $Response->{Charset} = 'ISO-LATIN-1' is set, the 
corresponding header would look like:

  Content-Type: text/html; charset=ISO-LATIN-1

=item $Response->{Clean} = 0-9;

API extension. Set the Clean level, default 0, on a per script basis.  
Clean of 1-9 compresses text/html output.  Please see
the Clean config option for more information. This setting may
also be useful even if using compression to obfuscate HTML.

=item $Response->{ContentType} = "text/html"

Sets the MIME type for the current response being sent to the client.
Sent as an HTTP header.

ASP.pm  view on Meta::CPAN


For more information, please see the CGI / File Upload section,
as file uploads are implemented via the CGI.pm module.  An
example can be found in the installation 
samples ./site/eg/file_upload.asp

=item $Request->Params($name)

API extension. If RequestParams CONFIG is set, the $Request->Params 
object is created with combined contents of $Request->QueryString 
and $Request->Form.  This is for developer convenience simlar 
to CGI.pm's param() method.  Just like for $Response->Form, 
one could create a nice alias like:

 # in global.asa
 use vars qw( $Params );
 sub Script_OnStart {
   $Params = $Request->Params;
 }

=item $Request->QueryString($name)

Returns the value of the input of name $name used in a form
with GET method, or passed by appending a query string to the end of
a url as in http://localhost/?data=value.  
If $name is not specified, returns a ref to a hash of all the query 
string data.

=item $Request->ServerVariables($name)

Returns the value of the server variable / environment variable
with name $name.  If $name is not specified, returns a ref to 
a hash of all the server / environment variables data.  The following
would be a common use of this method:

 $env = $Request->ServerVariables();
 # %{$env} here would be equivalent to the cgi %ENV in perl.

=back

=head2 $Application Object

Like the $Session object, you may use the $Application object to 
store data across the entire life of the application.  Every
page in the ASP application always has access to this object.
So if you wanted to keep track of how many visitors there where
to the application during its lifetime, you might have a line
like this:

 $Application->{num_users}++

The Lock and Unlock methods are used to prevent simultaneous 
access to the $Application object.

=over

=item $Application->Lock()

Locks the Application object for the life of the script, or until
UnLock() unlocks it, whichever comes first.  When $Application
is locked, this guarantees that data being read and written to it 
will not suddenly change on you between the reads and the writes.

This and the $Session object both lock automatically upon
every read and every write to ensure data integrity.  This 
lock is useful for concurrent access control purposes.

Be careful to not be too liberal with this, as you can quickly 
create application bottlenecks with its improper use.

=item $Application->UnLock()

Unlocks the $Application object.  If already unlocked, does nothing.

=item $Application->GetSession($sess_id)

This NON-PORTABLE API extension returns a user $Session given
a session id.  This allows one to easily write a session manager if
session ids are stored in $Application during Session_OnStart, with 
full access to these sessions for administrative purposes.  

Be careful not to expose full session ids over the net, as they
could be used by a hacker to impersonate another user.  So when 
creating a session manager, for example, you could create
some other id to reference the SessionID internally, which 
would allow you to control the sessions.  This kind of application
would best be served under a secure web server.

The ./site/eg/global_asa_demo.asp script makes use of this routine 
to display all the data in current user sessions.

=item $Application->SessionCount()

This NON-PORTABLE method returns the current number of active sessions
in the application, and is enabled by the SessionCount configuration setting.
This method is not implemented as part of the original ASP
object model, but is implemented here because it is useful.  In particular,
when accessing databases with license requirements, one can monitor usage
effectively through accessing this value.

=back

=head2 $Server Object

The server object is that object that handles everything the other
objects do not.  The best part of the server object for Win32 users is 
the CreateObject method which allows developers to create instances of
ActiveX components, like the ADO component.

=over

=item $Server->{ScriptTimeout} = $seconds

Not implemented. May never be.  Please see the 
Apache Timeout configuration option, normally in httpd.conf.  

=item $Server->Config($setting)

API extension.  Allows a developer to read the CONFIG
settings, like Global, GlobalPackage, StateDir, etc.
Currently implemented as a wrapper around 

  Apache->dir_config($setting)

May also be invoked as $Server->Config(), which will
return a hash ref of all the PerlSetVar settings. 

=item $Server->CreateObject($program_id)

Allows use of ActiveX objects on Win32.  This routine returns
a reference to an Win32::OLE object upon success, and nothing upon
failure.  It is through this mechanism that a developer can 
utilize ADO.  The equivalent syntax in VBScript is 

ASP.pm  view on Meta::CPAN

 + Updated docs to note that StateCache config was deprecated
   as of 2.23.  Removed remaining code that referenced the config.

 + Removed references to unused OrderCollections code.

 - Better Cache meta key, lower chance of collision with 
   unrelated data since its using the full MD5 keyspace now

 + Optimized some debugging statements that resulted 
   from recent development.

 + Tie::TextDir .04 and above is supported for StateDB
   and CacheDB settings with MLDBM::Sync .21. This is good for 
   CacheDB where output is larger and there are not many 
   versions to cache, like for XSLTCache, where the site is 
   mostly static.

 + Better RESOURCES section to web site, especially with adding
   some links to past Apache::ASP articles & presentations.

=item $VERSION = 2.25; $DATE="10/11/2001";

 + Improved ./site/apps/search application, for better
   search results at Apache::ASP site.  Also, reengineered
   application better, with more perl code moved to global.asa.
   Make use of MLDBM::Sync::SDBM_File, where search database
   before was engineering around SDBM_File's shortcomings.

 - Fix for SessionSerialize config, which broke in 2.23
   Also, added t/session_serialize.t to test suite to catch
   this problem in the future.

=item $VERSION = 2.23; $DATE="10/11/2001";

 +Make sure a couple other small standard modules get loaded
  upon "PerlModule Apache::ASP", like Time::HiRes, Class::Struct,
  and MLDBM::Serializer::Data::Dumper.  If not available
  these modules won't cause errors, but will promote child httpd
  RAM sharing if they are.

 -XMLSubs args parsing fix so an arg like z-index
  does not error under UseStrict.  This is OK now:

   <my:layer z-index=3 top=0 left=0> HTML </my:layer>

 -Only remove outermost <SCRIPT> tags from global.asa
  for IIS/PerlScript compatibility.  Used to remove
  all <SCRIPT> tags, which hurt when some subs in globa.asa
  would be printing some JavaScript.

 +$Response->{IsClientConnected} now updated correctly 
  before global.asa Script_OnStart.  $Response->IsClientConnect()
  can be used for accurate accounting, while 
  $Response->{IsClientConnected} only gets updated
  after $Response->Flush().  Added test cases to response.t

 +$Server->HTMLEncode(\$data) API extension, now can take
  scalar ref, which can give a 5% improvement in benchmarks
  for data 100K in size.

 -Access to $Application is locked when Application_OnEnd & 
  Application_OnStart is called, creating a critical section
  for use of $Application

 ++MLDBM::Sync used now for core DBM support in Apache::ASP::State.
  This drastically simplifies/stabilizes the code in there
  and will make it easier for future SQL database plugins.

 +New API for accessing ASP object information in non content
  handler phases:

    use Apache::ASP;
    sub My::Auth::handler {
      my $r = shift;
      my $ASP = Apache::ASP->new($r) 
      my $Session = $ASP->Session;
    }

  In the above example, $Session would be the same $Session
  object created later while running the ASP script for this
  same request.  

  Added t/asp_object.t test for this.  Fixed global.asa to only 
  init StateDir when application.asp starts which is the first 
  test script to run.

 -Fixed on Win32 to make Apache::ASP->new($r) able to create
  multiple master ASP objects per request.  Was not reentrant 
  safe before, particularly with state locking for dbms like 
  $Application & $Session.  

 ++Output caching for includes, built on same layer ( extended )
  as XSLTCache, test suite at t/cache.t.  Enabled with special 
  arguments to 

    $Response->Include(\%args, @include_args)
    $Response->TrapInclude(\%args, @include_args)
    $Server->Execute(\%args, @include_args)

  where %args = (
    File => 'file.inc',
    Cache => 1, # to activate cache layer
    Expires => 3600, # to expire in one hour
    LastModified => time() - 600, # to expire if cached before 10 minutes ago
    Key => $Request->Form, # to cache based on checksum of serialized form data,
    Clear => 1, # to not allow fetch from cache this time, will always execute include
  );

  Like the XSLTCache, it uses MLDBM::Sync::SDBM_File
  by default, but can use DB_File or GDBM_File if
  CacheDB is set to these.

  See t/cache.t for API support until this is documented.

 +CacheSize now supports units of M, K, B like 

   CacheSize 10M
   CacheSize 10240K
   CacheSize 10000000B
   CacheSize 10000000



( run in 2.044 seconds using v1.01-cache-2.11-cpan-df04353d9ac )