Apache-FilteringProxy
view release on metacpan or search on metacpan
lib/Apache/FilteringProxy.pm view on Meta::CPAN
if ($r->header_only) {
# send headers, but no body. Because we can't know whether this page
# is going to be altered or not, after filtering, we can't tell the
# client whether to accept ranges or not. So strip out accept-ranges
# headers when this is a content type that is supposed to be filtered
if ($Apache::FilteringProxy::filter_types{$r->content_type()}) {
$r->headers_out->unset('Accept-ranges');
}
$r->send_http_header();
return OK;
}
# if we want to filter this type of content and there is content
if ($content_type and $$content_ref and
$Apache::FilteringProxy::filter_types{$content_type})
{
# filter the content
filter_data($r, $content_ref);
# reset the content-length header to make sure we have accurate
# length, which may have changed after filtering
$r->header_out('Content-length', length($$content_ref));
# can't use ranges or xsums if we're messing with content, so remove
$r->headers_out->unset('Accept-ranges');
$r->headers_out->unset('Content-MD5');
}
$r->warn("----- DEBUG HEADER REQUEST-----\n".$r->as_string()."\n-------------------------\n") unless ($Apache::FilteringProxy::logging < 2);
$r->warn("----- DEBUG HEADER TRANSLATED REQUEST -----\n".$request->as_string()."\n-------------------------\n") unless ($Apache::FilteringProxy::logging < 2);
$r->warn("----- DEBUG SOURCE -----\n".$$content_ref."\n-------------------------\n") unless ($Apache::FilteringProxy::logging < 3);
$r->send_http_header();
$r->print ($$content_ref);
$r->rflush;
return OK;
}
# filter_header
#
# Run a given MIME header value through the filter_data subroutine
# and set $r->header_out ($name, $value) to hold the result.
#
sub filter_header {
my $r = shift;
my $name = shift;
my $value = shift || "";
$r->warn("filtering header '$name'='$value'") unless ($Apache::FilteringProxy::logging < 2);
if ($name =~ m/^(location|content-location|content-base|uri|refresh|)$/i) {
# filter redirects so we don't get shot off to a server not proxies
# by us unintentionally and any other data containing domains or URLs
my $val_ref = filter_data($r, \$value);
} elsif ($name =~ m/^content-type$/i) {
# here we are going to see if we need to translate any content-types
# since it is the easiest place to do it
my $content_type = "";
my $charset = "";
if (defined($value)) {
$content_type = $value;
if ($content_type =~ s/(;.*)//) {
$charset = $1;
}
}
$r->warn("determining if content-type '".$content_type."' needs to be translated...") unless ($Apache::FilteringProxy::logging < 1);
if (exists($Apache::FilteringProxy::type_translations{$content_type})) {
$r->warn("content-type '".$content_type."' needs to be translated") unless ($Apache::FilteringProxy::logging < 1);
if (defined($Apache::FilteringProxy::type_translations{$content_type})) {
$r->warn("caught and translated type '".$content_type.$charset."' to '".$Apache::FilteringProxy::type_translations{$content_type}.$charset."'") unless ($Apache::FilteringProxy::logging < 1);
$r->content_type($Apache::FilteringProxy::type_translations{$content_type}.$charset);
$value = $Apache::FilteringProxy::type_translations{$content_type}.$charset;
}
}
} elsif ($name =~ m/^set-cookie$/i) {
# set the domain for this cookie to our local domain so that we can
# intercept all these cookies and filter later
my $s = $r->server;
my $local_hostname = $r->hostname();
$local_hostname =~ m/.*(\.port(\d+))?\.([^.]+)\.$local_servername$/;
my $resource_id = $3;
my $port = $2 || "";
if ($port) {
# include the port in the cookie domain setting
$value =~ s/(^\s*|;\s*)domain\s*=\s*([^\s;]*)(\s*$|\s*;)/$1domain=$2.port$port.$resource_id.$local_servername$3/i;
} else {
$value =~ s/(^\s*|;\s*)domain\s*=\s*([^\s;]*)(\s*$|\s*;)/$1domain=$2.$resource_id.$local_servername$3/i;
}
# filter the cookie data if this resource is configured to allow it
if ($Apache::FilteringProxy::filter_cookie_list{$resource_id}) {
my $val_ref = filter_data ($r, \$value);
} else {
$r->warn("skipping cookie filtering for '$resource_id' cookie") unless ($Apache::FilteringProxy::logging < 2);
}
} else {
# remove headers added by LWP (client-date, client-peer, title,
# proxy-authenticate). Also connection and transfer-encoding
# settings, as apache will handle these on its own.
if ($name =~ m/^(client-(date|peer|warning)|upgrade|proxy-authenticate)$/i) {
$r->warn("removed header '$name'='$value'") unless ($Apache::FilteringProxy::logging < 2);
# tell caller we want to remove this
return undef;
}
}
$r->warn("filtered header '$name'='$value'") unless ($Apache::FilteringProxy::logging < 2);
# this may or may not be used by the caller
return $value;
}
# filter_data
#
# much fun taking data and translating all absolute URLs to the format we need
# to do all sorts of nifty handling later. We translate all URLs that are
# supposed to be caught by our proxy by taking on our subdomain to the domain
# of the URL and add in port information to be processed later.
#
sub filter_data {
my $r = shift;
my $data_ref = shift;
my $s = $r->server;
# check first for empty data
if (not $$data_ref) {
return "";
}
# get the local server information to use for determining what resource
( run in 2.024 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )