Apache2-S3
view release on metacpan or search on metacpan
lib/Apache2/S3.pm view on Meta::CPAN
package Apache2::S3;
use strict;
use warnings;
use Apache2::Const -compile => qw(OK DECLINED PROXYREQ_REVERSE);
use Apache2::RequestRec;
use Apache2::Filter;
use Apache2::FilterRec;
use APR::Table;
use APR::String;
use MIME::Base64;
use Digest::SHA1;
use Digest::HMAC;
use URI::Escape;
use HTML::Entities;
use XML::Parser;
use Time::Local;
use POSIX;
use CGI;
our $VERSION = '0.05';
our $ESCAPE = quotemeta " #%<>[\]^`{|}?\\";
use constant TEXT => '0';
sub _signature
{
my ($id, $key, $data) = @_;
return "AWS $id:".MIME::Base64::encode_base64(Digest::HMAC::hmac($data, $key, \&Digest::SHA1::sha1), "");
}
sub handler
{
my $r = shift;
return Apache2::Const::DECLINED
if $r->proxyreq;
return Apache2::Const::DECLINED
unless $r->method eq 'GET' or $r->dir_config('S3ReadWrite');
my $h = $r->headers_in;
my $uri = $r->uri;
my %map = split /\s*(?:,|=>)\s*/, $r->dir_config("S3Map");
# most specific (longest) match first
foreach my $base (sort { length $b <=> length $a } keys %map)
{
$uri =~ s|^($base/*)|| or next;
my $stripped = $1;
my ($bucket, $keyId, $keySecret) = split m|/|, $map{$base};
$keyId ||= $r->dir_config("S3Key");
$keySecret ||= $r->dir_config("S3Secret");
my $is_dir = $uri =~ m,(^|/)$,;
my $path = "/$bucket/".($is_dir ? "" : $uri);
my $args = $r->args || "";
my $sub = $args =~ s/^(acl|logging|torrent)(?:&|$)// ? $1 : "";
local $CGI::USE_PARAM_SEMICOLONS = 0;
$args = CGI->new($r, $args);
if ($is_dir)
{
$args->param('delimiter', $args->param('delimiter') || '/');
$args->param('prefix', $uri) if $uri;
}
my %note = (
'id' => $keyId,
'secret' => $keySecret,
'path' => $path,
'sub' => $sub,
'stripped' => $stripped,
($is_dir ? ('prefix' => $uri) : ()),
(($args->param('raw') or not $is_dir or $sub) ? ('raw' => 1) : ()),
(($args->param('nocache') or $is_dir or $sub) ? ('nocache' => 1) : ()),
);
$r->notes->add(__PACKAGE__."::s3_$_" => $note{$_})
foreach keys %note;
$r->proxyreq(Apache2::Const::PROXYREQ_REVERSE);
$r->uri("http://s3.amazonaws.com$path");
$r->args(($sub ? "$sub&" : "").$args->query_string);
$r->filename("proxy:http://s3.amazonaws.com$path");
$r->handler('proxy-server');
# we delay adding the authorization header to give
# mod_auth* a chance to authenticate the users request
# which would use the same header
$r->set_handlers('PerlFixupHandler' => \&s3_auth_handler);
# we set up an output filter to translate XML responses
# for directory requests into "pretty" HTML
$r->add_output_filter(\&output_filter);
return Apache2::Const::OK;
}
return Apache2::Const::DECLINED;
}
sub s3_auth_handler
{
my $r = shift;
my $h = $r->headers_in;
my ($keyId, $keySecret, $path, $sub) =
map $r->notes->get(__PACKAGE__."::s3_$_"), qw(id secret path sub);
( run in 0.921 second using v1.01-cache-2.11-cpan-6aa56a78535 )