package HTTP::ProxyPAC;
use strict;
our $VERSION = '0.01';
use Carp;
use JavaScript;
use Scalar::Util qw(blessed);
use URI;
use HTTP::ProxyPAC::Functions;
use HTTP::ProxyPAC::Result;
our $UserAgent;
sub new {
my($class, $stuff) = @_;
if (blessed($stuff) && $stuff->isa('URI')) {
return $class->init( $class->load_uri($stuff) );
}
elsif (blessed($stuff) && $stuff->isa('IO::Handle')) {
return $class->init( $class->load_fh($stuff) );
}
elsif (ref($stuff) && ref($stuff) eq 'GLOB') {
return $class->init( $class->load_fh($stuff) );
}
elsif (ref($stuff) && ref($stuff) eq 'SCALAR') {
return $class->init( $$stuff );
}
elsif (!ref($stuff)) {
return $class->init( $class->load_file($stuff) );
}
else {
Carp::croak("Unknown reference type to HTTP::ProxyPAC->new: ", ref($stuff));
}
}
sub load_uri {
my($class, $uri) = @_;
$UserAgent ||= do {
require LWP::UserAgent;
LWP::UserAgent->new(agent => __PACKAGE__ . "/" . $VERSION);
};
my $res = $UserAgent->get($uri);
if ($res->content_type ne "application/x-ns-proxy-autoconfig") {
Carp::croak("Content-Type should be application/x-ns-proxy-autoconfig, but ", $res->content_type);
}
return $res->content;
}
sub load_fh {
my($class, $fh) = @_;
read($fh, my($body), -s $fh);
$body;
}
sub load_file {
my($class, $file) = @_;
open my $fh, $file or Carp::croak("$file: $!");
my $body = $class->load_fh($fh);
close $fh;
$body;
}
sub init {
my($class, $code) = @_;
my $runtime = JavaScript::Runtime->new;
my $context = $runtime->create_context();
for my $func (@HTTP::ProxyPAC::Functions::PACFunctions) {
no strict 'refs';
$context->bind_function( name => $func, func => sub { &{"HTTP::ProxyPAC::Functions::$func"}(@_) });
}
$context->eval($code);
bless { context => $context }, $class;
}
sub find_proxy {
my($self, $url) = @_;
Carp::croak("Usage: find_proxy(url)") unless defined $url;
$url = URI->new($url);
my $res = $self->{context}->eval( sprintf("FindProxyForURL('%s', '%s')", $url->as_string, $url->host) );
my @res = HTTP::ProxyPAC::Result->parse($res, $url);
return wantarray ? @res : $res[0];
}
=1= |