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 )