diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 9ac7f803a..f5391111b 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -8,6 +8,7 @@ - rfe: Added message to user search operation when user count exceeds 250. (Diona Kidd, Knowmad Technologies) - rfe: Add menuTitle to folder template (perlDreamer Consulting, LLC) + - Added pluggable URL and content handlers. 7.4.19 - fix: Import Package does nothing when re-importing trashed package diff --git a/docs/upgrades/upgrade_7.4.18-7.5.0.pl b/docs/upgrades/upgrade_7.4.18-7.5.0.pl index 66754be1c..18bbeca58 100644 --- a/docs/upgrades/upgrade_7.4.18-7.5.0.pl +++ b/docs/upgrades/upgrade_7.4.18-7.5.0.pl @@ -21,6 +21,7 @@ my $quiet; # this line required my $session = start(); # this line required +addUrlAndContentHandlers($session); addFriendsNetwork($session); addSearchWithContainers($session); addGroupToEditPost($session); @@ -28,6 +29,38 @@ addGroupToEditPost($session); finish($session); # this line required +#------------------------------------------------- +sub addUrlAndContentHandlers { + my $session = shift; + print "\tAdding pluggable URL and content handlers." unless $quiet; + my $config = $session->config; + my @urlHandlers = ( + { "^/extras" => "WebGUI::URL::PassThru" }, + { "^/uploads/dictionaries" => "WebGUI::URL::Unauthorized" }, + { "^/uploads" => "WebGUI::URL::Uploads" }, + { '^/\*give-credit-where-credit-is-due\*$' => "WebGUI::URL::Credits" }, + { '^/abcdefghijklmnopqrstuvwxyz$' => "WebGUI::URL::Snoop" }, + { ".*" => "WebGUI::URL::Content" } + ); + my $passthrus = $config->get("passthruUrls"); + if (defined $passthrus) { + foreach my $url (@{$passthrus}) { + unshift @urlHandlers, { "^".$url => "WebGUI::URL::PassThru" }; + } + } + $config->set("urlHandlers", \@urlHandlers); + $config->set("contentHandlers" , [ + "WebGUI::Content::Prefetch", + "WebGUI::Content::Maintenance", + "WebGUI::Content::Operation", + "WebGUI::Content::Setup", + "WebGUI::Content::Asset", + "WebGUI::Content::NotFound" + ]); + $config->delete("passthruUrls"); + print "DONE!\n" unless $quiet; +} + #------------------------------------------------- sub addSearchWithContainers { my $session = shift; diff --git a/etc/WebGUI.conf.original b/etc/WebGUI.conf.original index 52fdebe6c..0367f5baa 100644 --- a/etc/WebGUI.conf.original +++ b/etc/WebGUI.conf.original @@ -82,12 +82,6 @@ "richEditorsUseAssetUrls" : 1, -# An array of URLs that WebGUI should leave alone for normal -# processing by Apache. Anything that begins with these URLs -# will be entirely ignored by WebGUI - -# "passthruUrls" : ["/icons", "/documentation/pdf", "/my-custom-application", "/server-status", "/perl-status"], - # If you are not running your web server on the standard # port (80) then use this setting to specify that. @@ -450,7 +444,34 @@ # Optional script to run upon successful logout. The script can contain macros # Example: /data/WebGUI/sbin/doLogout.pl --configFile=dev.localhost.localdomain.conf --logoutPage=^PageUrl(); -"runOnLogout" : "" +"runOnLogout" : "", + +# URL handlers are used to associate functionality with a URL via a regular expression. + +"urlHandlers" : [ + { "^/extras" : "WebGUI::URL::PassThru" }, +# { "^/icons" : "WebGUI::URL::PassThru" }, +# { "^/documentation/pdf" : "WebGUI::URL::PassThru" }, +# { "^/my-custom-application$" : "WebGUI::URL::PassThru" }, +# { "^/server-status$" : "WebGUI::URL::PassThru" }, +# { "^/perl-status$" : "WebGUI::URL::PassThru" }, + { "^/uploads/dictionaries" : "WebGUI::URL::Unauthorized" }, + { "^/uploads" : "WebGUI::URL::Uploads" }, + { "^/\*give-credit-where-credit-is-due\*$" : "WebGUI::URL::Credits" }, + { "^/abcdefghijklmnopqrstuvwxyz$" : "WebGUI::URL::Snoop" }, + { ".*" : "WebGUI::URL::Content" } + ], + +# Content handlers are used to produce content from the content URL handler. + +"contentHandlers" : [ + "WebGUI::Content::Prefetch", + "WebGUI::Content::Maintenance", + "WebGUI::Content::Operation", + "WebGUI::Content::Setup", + "WebGUI::Content::Asset", + "WebGUI::Content::NotFound" + ] } diff --git a/lib/WebGUI.pm b/lib/WebGUI.pm index 57e7c73e8..7c9396e32 100644 --- a/lib/WebGUI.pm +++ b/lib/WebGUI.pm @@ -1,6 +1,6 @@ package WebGUI; -use strict qw(vars subs); +use strict;# qw(vars subs); our $VERSION = "7.5.0"; our $STATUS = "beta"; @@ -20,22 +20,10 @@ our $STATUS = "beta"; =cut -use Time::HiRes; -use WebGUI::Affiliate; -use WebGUI::Asset; -use WebGUI::Config; -use WebGUI::Operation; -use WebGUI::Session; -use WebGUI::Utility; -use WebGUI::PassiveProfiling; -use WebGUI::Setup; -use Apache2::Upload; +use Apache2::Const -compile => qw(OK DECLINED); use Apache2::Request; -use Apache2::RequestRec (); -use Apache2::RequestIO (); -use Apache2::Const -compile => qw(OK DECLINED NOT_FOUND DIR_MAGIC_TYPE); use Apache2::ServerUtil (); -use LWP::MediaTypes qw(guess_media_type); +use WebGUI::Config; =head1 NAME @@ -57,38 +45,6 @@ These subroutines are available from this package: #------------------------------------------------------------------- -=head2 getAsset ( session [, assetUrl ] ) - -Returns an asset based upon the requested asset URL, or optionally pass one in. - -=cut - -sub getAsset { - my $session = shift; - my $assetUrl = shift; - my $asset = eval{WebGUI::Asset->newByUrl($session,$assetUrl,$session->form->process("revision"))}; - if ($@) { - $session->errorHandler->warn("Couldn't instantiate asset for url: ".$assetUrl." Root cause: ".$@); - } - return $asset; -} - -#------------------------------------------------------------------- - -=head2 getRequestedAssetUrl ( session [, assetUrl ] ) - -Returns an asset based upon the requested asset URL, or optionally pass one in. - -=cut - -sub getRequestedAssetUrl { - my $session = shift; - my $assetUrl = shift || $session->url->getRequestedUrl; - return $assetUrl; -} - -#------------------------------------------------------------------- - =head2 handler ( requestObject ) Primary http init/response handler for WebGUI. This method decides whether to hand off the request to contentHandler() or uploadsHandler() @@ -100,341 +56,41 @@ The Apache2::RequestRec object passed in by Apache's mod_perl. =cut sub handler { - ## Note: To Apache, the return values of OK, DECLINED, and DONE are all 'success' values. Anything else is an error. OK and DECLINED are pretty much the same thing as far as Apache is concerned. Why use one or the other? To make the code somewhat self-documenting. In this case, DECLINED means 'We aren't going to do anything more with this' - ## OK means 'we handled it' - - my $r = shift; #start with apache request object - my $configFile = shift || $r->dir_config('WebguiConfig'); #either we got a config file, or we'll build it from the request object's settings - my $s = Apache2::ServerUtil->server; #instantiate the server api - my $config = WebGUI::Config->new($s->dir_config('WebguiRoot'), $configFile); #instantiate the config object - $r->push_handlers(PerlFixupHandler => \&fixupHandler) if (defined $config->get("passthruUrls")); #set up the fixup handler if we have passthruUrls - foreach my $url ($config->get("extrasURL"), @{$config->get("passthruUrls")}) { #get list of unhandled urls, return DECLINED if our url is on that list - return Apache2::Const::DECLINED if ($r->uri =~ m/^$url/); - } - my $uploads = $config->get("uploadsURL"); #get uploads directory - $uploads .= "/" unless ($uploads =~ m{/$}); #ad the trailing slash if it's not already present - if ($r->uri =~ m!^$uploads/dictionaries!) { # if the requested url is a personal dictionary, return not found - # Do not allow web-access to personal dictionaries. - $r->push_handlers(PerlAccessHandler => sub { return 401 } ); - } elsif($r->uri =~ m/^$uploads/) { #if the request has uploads in it, return the appropriate handler - $r->push_handlers(PerlAccessHandler => sub { return uploadsHandler($r, $configFile); } ); - } else { #else go to content handler, and set the status to Ok - $r->push_handlers(PerlResponseHandler => sub { return contentHandler($r, $configFile); } ); - $r->push_handlers(PerlTransHandler => sub { return Apache2::Const::OK }); - } - return Apache2::Const::DECLINED; #decline further processing (keep in mind that OK and DECLINED are both success. The difference is mostly for internal documentation. As far as apache in concerned, the two are identical. -} - - -#------------------------------------------------------------------- - -=head2 contentHandler ( requestObject ) - -Creates the WebGUI session, handles exceptional request -headers, handles special states, prints the response headers, -and (usually) prints the output of page(). - -=head3 requestObject - -The Apache2::RequestRec object passed in by Apache's mod_perl. - -=cut - -sub contentHandler { - ### inherit Apache request. - my $r = shift; - my $configFile = shift || $r->dir_config('WebguiConfig'); - ### instantiate the API for this httpd instance. - my $s = Apache2::ServerUtil->server; - ### Open new or existing user session based on user-agent's cookie. - my $request = Apache2::Request->new($r); - my $session = WebGUI::Session->open($s->dir_config('WebguiRoot'),$configFile, $request, $s); - my ($env, $http, $setting, $output, $errorHandler, $config) = $session->quick(qw(env http setting output errorHandler config)); - if ($session->env->get("HTTP_X_MOZ") eq "prefetch") { # browser prefetch is a bad thing - $http->setStatus("403","We don't allow prefetch, because it increases bandwidth, hurts stats, and can break web sites."); - $http->sendHeader; - } - elsif ($setting->get("specialState") eq "upgrading") { - upgrading($session); - } - else { - my $out = processOperations($session); #anything that has op= will have it's thing done here - if ($out ne "") { - # do nothing because we have operation output to display - $out = undef if ($out eq "chunked"); #'chunked' is WebGUI's way of saying 'I took care of it' The output was sent to the browser in pieces as quickly as it could be produced. - } - elsif ($setting->get("specialState") eq "init") { #if specialState is flagged and it's 'init' do initial setup - $out = WebGUI::Setup::setup($session); - } - elsif ($errorHandler->canShowPerformanceIndicators) { #show performance indicators if required - my $t = [Time::HiRes::gettimeofday()]; - $out = page($session); - $t = Time::HiRes::tv_interval($t) ; - if ($out =~ /<\/title>/) { - $out =~ s/<\/title>/ : ${t} seconds<\/title>/i; - } + my $request = shift; #start with apache request object + $request = Apache2::Request->new($request); + my $configFile = shift || $request->dir_config('WebguiConfig'); #either we got a config file, or we'll build it from the request object's settings + my $server = Apache2::ServerUtil->server; #instantiate the server api + my $config = WebGUI::Config->new($server->dir_config('WebguiRoot'), $configFile); #instantiate the config object + my $error = ""; + foreach my $handler (@{$config->get("urlHandlers")}) { + my ($regex) = keys %{$handler}; + if ($request->uri =~ m{$regex}i) { + my $module = $handler->{$regex}; + my $modulePath = $module.".pm"; + $modulePath =~ s{::}{/}g; + eval { require $modulePath }; + if ($@) { + $error .= $@; + } else { - # Kludge. - my $mimeType = $http->getMimeType(); - if ($mimeType eq 'text/css') { - $output->print("\n/* Page generated in $t seconds. */\n"); - } - elsif ($mimeType eq 'text/html') { - $output->print("\nPage generated in $t seconds.\n"); - } - else { - # Don't apply to content when we don't know how - # to modify it semi-safely. - } - } - } - else { - - my $asset = getAsset($session, getRequestedAssetUrl($session)); - - # display from cache if page hasn't been modified. - if ($session->var->get("userId") eq "1" && defined $asset && !$http->ifModifiedSince($asset->getContentLastModified)) { - $http->setStatus("304","Content Not Modified"); - $http->sendHeader; - $session->close; - return Apache2::Const::OK(); - } - - # return the page. - else { - $out = page($session, undef, $asset); - } - } - my $filename = $http->getStreamedFile(); - if ((defined $filename) && ($config->get("enableStreamingUploads") eq "1")) { - my $ct = guess_media_type($filename); - my $oldContentType = $r->content_type($ct); - if ($r->sendfile($filename) ) { - $session->close; - return Apache2::Const::OK(); - } else { - $r->content_type($oldContentType); - } - } - $http->sendHeader(); #http object will only send the header once per request, so if the above sent a header as part of it's operation, this will do nothing. - unless ($http->isRedirect()) { - $output->print($out); - if ($errorHandler->canShowDebug()) { - $output->print($errorHandler->showDebug(),1); - } - } - WebGUI::Affiliate::grabReferral($session); # process affiliate tracking request + my $command = $module."::handler"; + no strict qw(refs); + my $out = &$command($request, $server, $config); + use strict; + return $out; + } + } } - $session->close; - return Apache2::Const::OK; -} - -#------------------------------------------------------------------- - -=head2 fixupHandler ( requestObject ) - -This method is here to allow proper handling of DirectoryIndexes -when someone is using the passthruUrls feature. - -=head3 requestObject - -The Apache2::RequestRec object passed in by Apache's mod_perl. - -=cut - -sub fixupHandler { - my $r = shift; - - if ($r->handler eq 'perl-script' && # Handler is Perl - -d $r->filename && # Filename requested is a directory - $r->is_initial_req) # and this is the initial request - { - $r->handler(Apache2::Const::DIR_MAGIC_TYPE); # Hand off to mod_dir - return Apache2::Const::OK; - } - return Apache2::Const::DECLINED; # just pass it on -} - -#------------------------------------------------------------------- - -=head2 page ( session , [ assetUrl ] ) - -Processes operations (if any), then tries the requested method on the asset corresponding to the requested URL. If that asset fails to be created, it tries the default page. - -=head3 session - -The current WebGUI::Session object. - -=head3 assetUrl - -Optionally pass in a URL to be loaded. - -=cut - -sub page { - my $session = shift; - my $assetUrl = getRequestedAssetUrl($session, shift); - my $asset = shift || getAsset($session, $assetUrl); - my $output = undef; - if (defined $asset) { - my $method = "view"; - if ($session->form->param("func")) { - $method = $session->form->param("func"); - unless ($method =~ /^[A-Za-z0-9]+$/) { - $session->errorHandler->security("to call a non-existent method $method on $assetUrl"); - $method = "view"; - } - } - $output = tryAssetMethod($session,$asset,$method); - $output = tryAssetMethod($session,$asset,"view") unless ($output || ($method eq "view")); - } - if ($output eq "") { - if ($session->var->isAdminOn) { # they're expecting it to be there, so let's help them add it - my $asset = WebGUI::Asset->newByUrl($session, $session->url->getRefererUrl) || WebGUI::Asset->getDefault($session); - $output = $asset->addMissing($assetUrl); - } else { # not in admin mode, so can't create it, so display not found - $session->http->setStatus("404","Page Not Found"); - my $notFound = WebGUI::Asset->getNotFound($session); - if (defined $notFound) { - $output = tryAssetMethod($session,$notFound,'view'); - } else { - $session->errorHandler->error("The notFound page could not be instanciated!"); - $output = "An error was encountered while processing your request."; - } - $output = "An error was encountered while processing your request." if $output eq ''; - } - } - if ($output eq "chunked") { - $output = undef; - } - return $output; + $request->push_handlers(PerlResponseHandler => sub { + print "This server is unable to handle the url '".$request->uri."' that you requested. ".$error; + return Apache2::Const::OK; + } ); + $request->push_handlers(PerlTransHandler => sub { return Apache2::Const::OK }); + return Apache2::Const::DECLINED; } -#------------------------------------------------------------------- -=head2 processOperations ( session ) - -Calls the operation dispatcher using the requested operation. - -=head3 session - -The current WebGUI::Session object. - -=cut - -sub processOperations { - my $session = shift; - my $output = ""; - my $op = $session->form->process("op"); - if ($op) { - $output = WebGUI::Operation::execute($session,$op); - } - return $output; -} - -#------------------------------------------------------------------- - -=head2 tryAssetMethod ( session ) - -Tries an asset method on the requested asset. Tries the "view" method if that method fails. - -=head3 session - -The current WebGUI::Session object. - -=cut - -sub tryAssetMethod { - my $session = shift; - my $asset = shift; - my $method = shift; - my $state = $asset->get("state"); - return if ($state ne "published" && $state ne "archived" && !$session->var->isAdminOn); # can't interact with an asset if it's not published - $session->asset($asset); - my $methodToTry = "www_".$method; - my $output = eval{$asset->$methodToTry()}; - if ($@) { - $session->errorHandler->warn("Couldn't call method ".$method." on asset for url: ".$session->url->getRequestedUrl." Root cause: ".$@); - if ($method ne "view") { - $output = tryAssetMethod($session,$asset,'view'); - } else { - # fatals return chunked - $output = 'chunked'; - } - } - return $output; -} - -#------------------------------------------------------------------- - -=head2 uploadsHandler ( requestObject ) - -Primary http init/response handler for WebGUI. - -=head3 requestObject - -The Apache2::RequestRec object passed in by handler(). - -=cut - -sub uploadsHandler { - my $r = shift; - my $configFile = shift || $r->dir_config('WebguiConfig'); - my $ok = Apache2::Const::OK; - my $notfound = Apache2::Const::NOT_FOUND; - if (-e $r->filename) { - my $path = $r->filename; - $path =~ s/^(\/.*\/).*$/$1/; - if (-e $path.".wgaccess") { - my $fileContents; - open(my $FILE,"<",$path.".wgaccess"); - while (<$FILE>) { - $fileContents .= $_; - } - close($FILE); - my @privs = split("\n",$fileContents); - unless ($privs[1] eq "7" || $privs[1] eq "1") { - my $s = Apache2::ServerUtil->server; - my $request = Apache2::Request->new($r); - my $session = WebGUI::Session->open($s->dir_config('WebguiRoot'),$configFile, $request, $s); - my $hasPrivs = ($session->var->get("userId") eq $privs[0] || $session->user->isInGroup($privs[1]) || $session->user->isInGroup($privs[2])); - $session->close(); - if ($hasPrivs) { - return $ok; - } else { - return 401; - } - } - } - return $ok; - } else { - return $notfound; - } -} - - -#------------------------------------------------------------------- - -=head2 upgrading ( session ) - -Handles a specialState: "upgrading" - -=head3 session - -The current WebGUI::Session object. - -=cut - -sub upgrading { - my $session = shift; - $session->http->sendHeader; - open(my $FILE,"<",$session->config->getWebguiRoot."/docs/maintenance.html"); - while (<$FILE>) { - $session->output->print($_); - } - close($FILE); -} 1; diff --git a/lib/WebGUI/Asset.pm b/lib/WebGUI/Asset.pm index 5ad550a4e..7d29ce9bd 100644 --- a/lib/WebGUI/Asset.pm +++ b/lib/WebGUI/Asset.pm @@ -564,9 +564,6 @@ sub fixUrl { $self->session->config->get("extrasURL"), $self->session->config->get("uploadsURL"), ); - if (defined $self->session->config->get('passthruUrls')) { - push @badUrls, @{ $self->session->config->get('passthruUrls') }; - } foreach my $badUrl (@badUrls) { $badUrl =~ s{ / $ }{}x; # Remove trailing slashes from the end of the URL if ($badUrl =~ /^http/) { @@ -1083,25 +1080,7 @@ A reference to the current session. sub getNotFound { my $class = shift; my $session = shift; - if ($session->url->getRequestedUrl eq "*give-credit-where-credit-is-due*") { - my $content = ""; - open(my $FILE,"<",$session->config->getWebguiRoot."/docs/credits.txt"); - while (<$FILE>) { - $content .= $_; - } - close($FILE); - return WebGUI::Asset->newByPropertyHashRef($session,{ - className=>"WebGUI::Asset::Snippet", - snippet=> '
'.$content.'
' - }); - } elsif ($session->url->getRequestedUrl eq "abcdefghijklmnopqrstuvwxyz") { - return WebGUI::Asset->newByPropertyHashRef($session,{ - className=>"WebGUI::Asset::Snippet", - snippet=>q|
Why would you type in this URL? Really. What were you expecting to see here? You really need to get a life. Are you still here? Seriously, you need to go do something else. I think your boss is calling.
| - }); - } else { - return WebGUI::Asset->newByDynamicClass($session, $session->setting->get("notFoundPage")); - } + return WebGUI::Asset->newByDynamicClass($session, $session->setting->get("notFoundPage")); } diff --git a/lib/WebGUI/Content/Asset.pm b/lib/WebGUI/Content/Asset.pm new file mode 100644 index 000000000..b33d2e458 --- /dev/null +++ b/lib/WebGUI/Content/Asset.pm @@ -0,0 +1,235 @@ +package WebGUI::Content::Asset; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use LWP::MediaTypes qw(guess_media_type); +use Time::HiRes; +use WebGUI::Asset; + +=head1 NAME + +Package WebGUI::Content::MyHandler + +=head1 DESCRIPTION + +A content handler that serves up assets. + +=head1 SYNOPSIS + + use WebGUI::Content::Asset; + my $output = WebGUI::Content::Asset::handler($session); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 getAsset ( session [, assetUrl ] ) + +Returns an asset based upon the requested asset URL, or optionally pass one in. + +=cut + +sub getAsset { + my $session = shift; + my $assetUrl = shift; + my $asset = eval{WebGUI::Asset->newByUrl($session,$assetUrl,$session->form->process("revision"))}; + if ($@) { + $session->errorHandler->warn("Couldn't instantiate asset for url: ".$assetUrl." Root cause: ".$@); + } + return $asset; +} + +#------------------------------------------------------------------- + +=head2 getRequestedAssetUrl ( session [, assetUrl ] ) + +Returns an asset based upon the requested asset URL, or optionally pass one in. + +=cut + +sub getRequestedAssetUrl { + my $session = shift; + my $assetUrl = shift || $session->url->getRequestedUrl; + return $assetUrl; +} + +#------------------------------------------------------------------- + +=head2 handler ( session ) + +The content handler for this package. + +=cut + +sub handler { + my ($session) = @_; + my ($errorHandler, $http, $var, $asset, $request, $config) = $session->quick(qw(errorHandler http var asset request config)); + my $output = ""; + if ($errorHandler->canShowPerformanceIndicators) { #show performance indicators if required + my $t = [Time::HiRes::gettimeofday()]; + $output = page($session); + $t = Time::HiRes::tv_interval($t) ; + if ($output =~ /<\/title>/) { + $output =~ s/<\/title>/ : ${t} seconds<\/title>/i; + } + else { + # Kludge. + my $mimeType = $http->getMimeType(); + if ($mimeType eq 'text/css') { + $session->output->print("\n/* Page generated in $t seconds. */\n"); + } + elsif ($mimeType eq 'text/html') { + $session->output->print("\nPage generated in $t seconds.\n"); + } + else { + # Don't apply to content when we don't know how + # to modify it semi-safely. + } + } + } + else { + + my $asset = getAsset($session, getRequestedAssetUrl($session)); + + # display from cache if page hasn't been modified. + if ($var->get("userId") eq "1" && defined $asset && !$http->ifModifiedSince($asset->getContentLastModified)) { + $http->setStatus("304","Content Not Modified"); + $http->sendHeader; + $session->close; + return Apache2::Const::OK; + } + + # return the page. + else { + $output = page($session, undef, $asset); + } + } + my $filename = $http->getStreamedFile(); + if ((defined $filename) && ($config->get("enableStreamingUploads") eq "1")) { + my $ct = guess_media_type($filename); + my $oldContentType = $request->content_type($ct); + if ($request->sendfile($filename) ) { + $session->close; + return Apache2::Const::OK; + } else { + $request->content_type($oldContentType); + } + } + $http->sendHeader(); #http object will only send the header once per request, so if the above sent a header as part of it's operation, this will do nothing. + unless ($http->isRedirect()) { + $session->output->print($output); + if ($errorHandler->canShowDebug()) { + $session->output->print($errorHandler->showDebug(),1); + } + } + # ... + return $output; +} + +#------------------------------------------------------------------- + +=head2 page ( session , [ assetUrl ] ) + +Processes operations (if any), then tries the requested method on the asset corresponding to the requested URL. If that asset fails to be created, it tries the default page. + +=head3 session + +The current WebGUI::Session object. + +=head3 assetUrl + +Optionally pass in a URL to be loaded. + +=cut + +sub page { + my $session = shift; + my $assetUrl = getRequestedAssetUrl($session, shift); + my $asset = shift || getAsset($session, $assetUrl); + my $output = undef; + if (defined $asset) { + my $method = "view"; + if ($session->form->param("func")) { + $method = $session->form->param("func"); + unless ($method =~ /^[A-Za-z0-9]+$/) { + $session->errorHandler->security("to call a non-existent method $method on $assetUrl"); + $method = "view"; + } + } + $output = tryAssetMethod($session,$asset,$method); + $output = tryAssetMethod($session,$asset,"view") unless ($output || ($method eq "view")); + } + if ($output eq "") { + if ($session->var->isAdminOn) { # they're expecting it to be there, so let's help them add it + my $asset = WebGUI::Asset->newByUrl($session, $session->url->getRefererUrl) || WebGUI::Asset->getDefault($session); + $output = $asset->addMissing($assetUrl); + } else { # not in admin mode, so can't create it, so display not found + $session->http->setStatus("404","Page Not Found"); + my $notFound = WebGUI::Asset->getNotFound($session); + if (defined $notFound) { + $output = tryAssetMethod($session,$notFound,'view'); + } else { + $session->errorHandler->error("The notFound page could not be instanciated!"); + $output = "An error was encountered while processing your request."; + } + $output = "An error was encountered while processing your request." if $output eq ''; + } + } + if ($output eq "chunked") { + $output = undef; + } + return $output; +} + +#------------------------------------------------------------------- + +=head2 tryAssetMethod ( session ) + +Tries an asset method on the requested asset. Tries the "view" method if that method fails. + +=head3 session + +The current WebGUI::Session object. + +=cut + +sub tryAssetMethod { + my $session = shift; + my $asset = shift; + my $method = shift; + my $state = $asset->get("state"); + return if ($state ne "published" && $state ne "archived" && !$session->var->isAdminOn); # can't interact with an asset if it's not published + $session->asset($asset); + my $methodToTry = "www_".$method; + my $output = eval{$asset->$methodToTry()}; + if ($@) { + $session->errorHandler->warn("Couldn't call method ".$method." on asset for url: ".$session->url->getRequestedUrl." Root cause: ".$@); + if ($method ne "view") { + $output = tryAssetMethod($session,$asset,'view'); + } else { + # fatals return chunked + $output = 'chunked'; + } + } + return $output; +} + +1; + diff --git a/lib/WebGUI/Content/Maintenance.pm b/lib/WebGUI/Content/Maintenance.pm new file mode 100644 index 000000000..ff6b720e8 --- /dev/null +++ b/lib/WebGUI/Content/Maintenance.pm @@ -0,0 +1,64 @@ +package WebGUI::Content::Maintenance; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; + + +=head1 NAME + +Package WebGUI::Content::Maintenance; + +=head1 DESCRIPTION + +A content handler that does whatever I tell it to do. + +=head1 SYNOPSIS + + use WebGUI::Content::Maintenance; + my $output = WebGUI::Content::Maintenance::handler($session); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( session ) + +The content handler for this package. + +=cut + +sub handler { + my $session = shift; + if ($session->setting->get("specialState") eq "upgrading") { + $session->http->sendHeader; + my $output = ""; + open(my $FILE,"<",$session->config->getWebguiRoot."/docs/maintenance.html"); + while (<$FILE>) { + $output .= $_; + } + close($FILE); + return $output; + } + return; +} + + +1; + diff --git a/lib/WebGUI/Content/Operation.pm b/lib/WebGUI/Content/Operation.pm new file mode 100644 index 000000000..33be57fed --- /dev/null +++ b/lib/WebGUI/Content/Operation.pm @@ -0,0 +1,58 @@ +package WebGUI::Content::Operation; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use WebGUI::Operation; + +=head1 NAME + +Package WebGUI::Content::Operation + +=head1 DESCRIPTION + +A content handler that handles operations. + +=head1 SYNOPSIS + + use WebGUI::Content::Operation; + my $output = WebGUI::Content::Operation::handler($session); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( session ) + +The content handler for this package. + +=cut + +sub handler { + my ($session) = @_; + my $output = ""; + my $op = $session->form->process("op"); + if ($op) { + $output = WebGUI::Operation::execute($session,$op); + } + return $output; +} + +1; + diff --git a/lib/WebGUI/Content/Prefetch.pm b/lib/WebGUI/Content/Prefetch.pm new file mode 100644 index 000000000..0c344f23c --- /dev/null +++ b/lib/WebGUI/Content/Prefetch.pm @@ -0,0 +1,59 @@ +package WebGUI::Content::Prefetch; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; + + +=head1 NAME + +Package WebGUI::Content::Prefetch + +=head1 DESCRIPTION + +A content handler that prevents prefetching browsers. + +=head1 SYNOPSIS + + use WebGUI::Content::Prefetch; + my $output = WebGUI::Content::Prefetch::handler($session); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( session ) + +The content handler for this package. + +=cut + +sub handler { + my ($session) = @_; + if ($session->env->get("HTTP_X_MOZ") eq "prefetch") { # browser prefetch is a bad thing + my $http = $session->http; + $http->setStatus("403","We don't allow prefetch, because it increases bandwidth, hurts stats, and can break web sites."); + $http->sendHeader; + return "none"; + } + return; +} + +1; + diff --git a/lib/WebGUI/Setup.pm b/lib/WebGUI/Content/Setup.pm similarity index 98% rename from lib/WebGUI/Setup.pm rename to lib/WebGUI/Content/Setup.pm index 4a59a01c8..d1cdc3cb0 100644 --- a/lib/WebGUI/Setup.pm +++ b/lib/WebGUI/Content/Setup.pm @@ -1,4 +1,4 @@ -package WebGUI::Setup; +package WebGUI::Content::Setup; =head1 LEGAL @@ -34,7 +34,7 @@ Initializes a new WebGUI install. =head1 SYNOPSIS use WebGUI::Setup; - WebGUI::Setup::setup(); + WebGUI::Content::Setup::handler(); =head1 SUBROUTINES @@ -99,9 +99,9 @@ sub addPage { #------------------------------------------------------------------- -=head2 setup ( session ) +=head2 handler ( session ) -Handles a specialState: "setup" +Handles a specialState: "init" =head3 session @@ -109,8 +109,11 @@ The current WebGUI::Session object. =cut -sub setup { +sub handler { my $session = shift; + unless ($session->setting->get("specialState") eq "init") { + return; + } $session->http->setCacheControl("none"); my $i18n = WebGUI::International->new($session, "WebGUI"); my ($output,$legend) = ""; @@ -227,7 +230,7 @@ a:visited { color: '.$form->get("visitedLinkColor").'; } #mainBodyContentContainer { padding: 5px; margin-left: 200px; font-family: serif, times new roman; font-size: 12pt; } #pageFooterContainer { text-align: center; background-color: '.$form->get("footerBackgroundColor").'; color: '.$form->get("footerTextColor").'; } #copyrightContainer { font-size: 8pt; } -#pageWidthContainer { width: 80%; margin-left: auto; margin-right: auto; font-family: sans-serif, helvetica, arial; border: 3px solid black; } +#pageWidthContainer { margin-left: 10%; margin-right: 10%; font-family: sans-serif, helvetica, arial; border: 3px solid black; } '; my $css = addAsset($importNode, { title => "my-style.css", @@ -557,6 +560,7 @@ return props[propName]; '; $session->http->setMimeType("text/html"); + $session->http->sendHeader; return $page; } diff --git a/lib/WebGUI/Content/Upgrading.pm b/lib/WebGUI/Content/Upgrading.pm new file mode 100644 index 000000000..63a3f0264 --- /dev/null +++ b/lib/WebGUI/Content/Upgrading.pm @@ -0,0 +1,63 @@ +package WebGUI::Content::Upgrading; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; + + +=head1 NAME + +Package WebGUI::Content::Upgrading + +=head1 DESCRIPTION + +A content handler that displays a maintenance page when in a special upgrade state. + +=head1 SYNOPSIS + + use WebGUI::Content::Upgrading; + my $output = WebGUI::Content::Upgrading::handler($session); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( session ) + +The content handler for this package. + +=cut + +sub handler { + my ($session) = @_; + if ($session->setting->get("specialState") eq "upgrading") { + my $output = ""; + $session->http->sendHeader; + open(my $FILE,"<",$session->config->getWebguiRoot."/docs/maintenance.html"); + while (<$FILE>) { + $session->output->print($_); + } + close($FILE); + return "none"; + } + return; +} + +1; + diff --git a/lib/WebGUI/Content/_content.skeleton b/lib/WebGUI/Content/_content.skeleton new file mode 100644 index 000000000..b3006d8a0 --- /dev/null +++ b/lib/WebGUI/Content/_content.skeleton @@ -0,0 +1,55 @@ +package WebGUI::Content::MyHandler; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; + + +=head1 NAME + +Package WebGUI::Content::MyHandler + +=head1 DESCRIPTION + +A content handler that does whatever I tell it to do. + +=head1 SYNOPSIS + + use WebGUI::Content::MyHandler; + my $output = WebGUI::Content::MyHandler::handler($session); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( session ) + +The content handler for this package. + +=cut + +sub handler { + my ($session) = @_; + my $output = ""; + # ... + return $output; +} + +1; + diff --git a/lib/WebGUI/URL/Content.pm b/lib/WebGUI/URL/Content.pm new file mode 100644 index 000000000..032a0ce83 --- /dev/null +++ b/lib/WebGUI/URL/Content.pm @@ -0,0 +1,82 @@ +package WebGUI::URL::Content; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use Apache2::Const -compile => qw(OK DECLINED); +use WebGUI::Affiliate; +use WebGUI::Session; + +=head1 NAME + +Package WebGUI::URL::Content + +=head1 DESCRIPTION + +A URL handler that does whatever I tell it to do. + +=head1 SYNOPSIS + + use WebGUI::URL::Content; + my $status = WebGUI::URL::Content::handler($r, $s, $config); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( request, server, config ) + +The Apache request handler for this package. + +=cut + +sub handler { + my ($request, $server, $config) = @_; + $request->push_handlers(PerlResponseHandler => sub { + my $session = WebGUI::Session->open($server->dir_config('WebguiRoot'), $config->getFilename, $request, $server); + foreach my $handler (@{$config->get("contentHandlers")}) { + my $handlerPath = $handler.".pm"; + $handlerPath =~ s{::}{/}g; + eval { require $handlerPath }; + if ( $@ ) { + $session->errorHandler->error("Couldn't load content handler $handler."); + } + else { + my $command = $handler."::handler"; + no strict qw(refs); + my $output = &$command($session); + use strict; + if ($output) { + unless ($output eq "none" || $output eq "redirect") { + $session->output->print($output); + } + last; + } + } + } + WebGUI::Affiliate::grabReferral($session); # process affiliate tracking request + $session->close; + return Apache2::Const::OK; + }); + $request->push_handlers(PerlTransHandler => sub { return Apache2::Const::OK }); + return Apache2::Const::DECLINED; +} + +1; + diff --git a/lib/WebGUI/URL/Credits.pm b/lib/WebGUI/URL/Credits.pm new file mode 100644 index 000000000..0c4fb76e2 --- /dev/null +++ b/lib/WebGUI/URL/Credits.pm @@ -0,0 +1,66 @@ +package WebGUI::URL::Credits; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use Apache2::Const -compile => qw(OK DECLINED); +use WebGUI::Session; + +=head1 NAME + +Package WebGUI::URL::Credits + +=head1 DESCRIPTION + +A URL handler that displays the credits file. + +=head1 SYNOPSIS + + use WebGUI::URL::Credits; + my $status = WebGUI::URL::Credits::handler($r, $s, $config); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( request, server, config ) + +The Apache request handler for this package. + +=cut + +sub handler { + my ($request, $server, $config) = @_; + $request->push_handlers(PerlResponseHandler => sub { + my $content = ""; + open(my $FILE, "<", $config->getWebguiRoot."/docs/credits.txt"); + while (my $line = <$FILE>) { + $content .= $line; + } + close($FILE); + print $content; + return Apache2::Const::OK; + } ); + $request->push_handlers(PerlTransHandler => sub { return Apache2::Const::OK }); + return Apache2::Const::DECLINED; +} + + +1; + diff --git a/lib/WebGUI/URL/PassThru.pm b/lib/WebGUI/URL/PassThru.pm new file mode 100644 index 000000000..45d1f9845 --- /dev/null +++ b/lib/WebGUI/URL/PassThru.pm @@ -0,0 +1,59 @@ +package WebGUI::URL::PassThru; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use Apache2::Const -compile => qw(OK DECLINED DIR_MAGIC_TYPE); + + +=head1 NAME + +Package WebGUI::URL::PassThru + +=head1 DESCRIPTION + +A URL handler that just passes the URLs back to Apache. + +=head1 SYNOPSIS + + use WebGUI::URL::PassThru; + my $status = WebGUI::URL::PassThru::handler($r, $s, $config); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( request, server, config ) + +=cut + +sub handler { + my ($request, $server, $config) = @_; + if ($request->handler eq 'perl-script' && # Handler is Perl + -d $request->filename && # Filename requested is a directory + $request->is_initial_req) # and this is the initial request + { + $request->handler(Apache2::Const::DIR_MAGIC_TYPE); # Hand off to mod_dir + return Apache2::Const::OK; + } + return Apache2::Const::DECLINED; +} + +1; + diff --git a/lib/WebGUI/URL/Snoop.pm b/lib/WebGUI/URL/Snoop.pm new file mode 100644 index 000000000..aa06771b9 --- /dev/null +++ b/lib/WebGUI/URL/Snoop.pm @@ -0,0 +1,61 @@ +package WebGUI::URL::Snoop; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use Apache2::Const -compile => qw(OK DECLINED); +use WebGUI::Session; + +=head1 NAME + +Package WebGUI::URL::Snoop + +=head1 DESCRIPTION + +A URL handler that should never be called. + +=head1 SYNOPSIS + + use WebGUI::URL::Snoop; + my $status = WebGUI::URL::Snoop::handler($r, $configFile); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( request, configFile ) + +The Apache request handler for this package. + +=cut + +sub handler { + my ($request, $server, $config) = @_; + $request->content_type("text/html"); + $request->push_handlers(PerlResponseHandler => sub { + print q|Snoopy
Why would you type in this URL? Really. What were you expecting to see here? You really need to get a life. Are you still here? Seriously, you need to go do something else. I think your boss is calling.
|; + return Apache2::Const::OK; + } ); + $request->push_handlers(PerlTransHandler => sub { return Apache2::Const::OK }); + return Apache2::Const::DECLINED; +} + + +1; + diff --git a/lib/WebGUI/URL/Unauthorized.pm b/lib/WebGUI/URL/Unauthorized.pm new file mode 100644 index 000000000..a2196d223 --- /dev/null +++ b/lib/WebGUI/URL/Unauthorized.pm @@ -0,0 +1,54 @@ +package WebGUI::URL::Unauthorized; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use Apache2::Const -compile => qw(AUTH_REQUIRED); + + +=head1 NAME + +Package WebGUI::URL::Unauthorized + +=head1 DESCRIPTION + +A URL handler that deals with requests where the user cannot access what they requested. + +=head1 SYNOPSIS + + use WebGUI::URL::Unauthorized; + my $status = WebGUI::URL::Unauthorized::handler($r, $s, $config); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( request, server, config ) + +The Apache request handler for this package. + +=cut + +sub handler { + my ($request, $server, $config) = @_; + return Apache2::Const::AUTH_REQUIRED; +} + +1; + diff --git a/lib/WebGUI/URL/Uploads.pm b/lib/WebGUI/URL/Uploads.pm new file mode 100644 index 000000000..533adc6c6 --- /dev/null +++ b/lib/WebGUI/URL/Uploads.pm @@ -0,0 +1,85 @@ +package WebGUI::URL::Uploads; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use Apache2::Const -compile => qw(OK DECLINED NOT_FOUND AUTH_REQUIRED); +use WebGUI::Session; + +=head1 NAME + +Package WebGUI::URL::Uploads; + +=head1 DESCRIPTION + +A URL handler that handles privileges for uploaded files. + +=head1 SYNOPSIS + + use WebGUI::URL::Uploads; + my $status = WebGUI::URL::Uploads::handler($r, $s, $config); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( request, server, config ) + +The Apache request handler for this package. + +=cut + +sub handler { + my ($request, $server, $config) = @_; + $request->push_handlers(PerlAccessHandler => sub { + if (-e $request->filename) { + my $path = $request->filename; + $path =~ s/^(\/.*\/).*$/$1/; + if (-e $path.".wgaccess") { + my $fileContents; + open(my $FILE, "<" ,$path.".wgaccess"); + while (my $line = <$FILE>) { + $fileContents .= $line; + } + close($FILE); + my @privs = split("\n", $fileContents); + unless ($privs[1] eq "7" || $privs[1] eq "1") { + my $session = WebGUI::Session->open($server->dir_config('WebguiRoot'), $config->getFilename, $request, $server); + my $hasPrivs = ($session->var->get("userId") eq $privs[0] || $session->user->isInGroup($privs[1]) || $session->user->isInGroup($privs[2])); + $session->close(); + if ($hasPrivs) { + return Apache2::Const::OK; + } + else { + return Apache2::Const::AUTH_REQUIRED; + } + } + } + return Apache2::Const::OK; + } + else { + return Apache2::Const::NOT_FOUND; + } + } ); + return Apache2::Const::DECLINED; +} + + +1; + diff --git a/lib/WebGUI/URL/_url.skeleton b/lib/WebGUI/URL/_url.skeleton new file mode 100644 index 000000000..6c3f6efa4 --- /dev/null +++ b/lib/WebGUI/URL/_url.skeleton @@ -0,0 +1,55 @@ +package WebGUI::URL::MyHandler; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2007 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use Apache2::Const -compile => qw(OK DECLINED NOT_FOUND DIR_MAGIC_TYPE); + + +=head1 NAME + +Package WebGUI::URL::MyHandler + +=head1 DESCRIPTION + +A URL handler that does whatever I tell it to do. + +=head1 SYNOPSIS + + use WebGUI::URL::MyHandler; + my $status = WebGUI::URL::MyHandler::handler($r, $configFile); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 handler ( request, server, config ) + +The Apache request handler for this package. + +=cut + +sub handler { + my ($request, $server, $config) = @_; + # ... + return Apache2::Const::DECLINED; +} + +1; +