in reply to Re: Is there a way to dynamically copy subroutine from one module to another?
in thread Is there a way to dynamically copy subroutine from one module to another?
This doesn't work because Net::HTTPS inherits from Net::SSL and then only Net::SSL inherits from IO::Socket::INET. So, when we exports our connect function to Net::HTTPS it will be called instead of Net::SSL::connect. But Net::SSL::connect has some stuff for creating encription. So creating of the socket will fail.use IO::Socket::Socks::Wrapper ( Net::HTTPS => { ProxyAddr => 'localhost', ProxyPort => 1080, SocksDebug => 1, SocksVersion => 5 } ); use Net::HTTPS; my $s = Net::HTTPS->new(Host => "encrypted.google.com") || die $@; $s->write_request(GET => "/", 'User-Agent' => "Mozilla/5.0"); my($code, $mess, %h) = $s->read_response_headers; while(1) { my $buf; my $n = $s->read_entity_body($buf, 1024); die "read failed: $!" unless defined $n; last unless $n; print $buf; }
package IO::Socket::Socks::Wrapper; use strict; use Socket; use base 'Exporter'; our $VERSION = 0.01; our @EXPORT_OK = 'connect'; sub import { my $pkg = shift; while(my ($module, $cfg) = splice @_, 0, 2) { unless(defined $cfg) { $cfg = $module; $module = undef; } if($module) { # override connect() in the package eval "require $module" or die $@; if($module->isa('IO::Socket::INET')) { *connect = sub(*$) { local(*IO::Socket::INET::connect) = sub(*$) { _connect(@_, $cfg); }; my $self = shift; my $ref = ref($self); no strict 'refs'; foreach my $parent (@{$ref.'::ISA'}) { if($parent->isa('IO::Socket::INET')) { bless $self, $parent; $self->connect(@_); bless $self, $ref; return $self; } } } } else { *connect = sub(*$) { _connect(@_, $cfg); } } $pkg->export($module, 'connect'); } else { # override connect() globally *connect = sub(*$) { _connect(@_, $cfg); }; $pkg->export('CORE::GLOBAL', 'connect'); } } } sub _connect { my ($socket, $name, $cfg) = @_; my $ref = ref($socket); return CORE::connect( $socket, $name ) if (($ref && $socket->isa('IO::Socket::Socks')) || !$cfg); my ($port, $host) = sockaddr_in($name); $host = inet_ntoa($host); # global overriding will not work with `use' pragma require IO::Socket::Socks; IO::Socket::Socks->new_from_socket( $socket, ConnectAddr => $host, ConnectPort => $port, %$cfg ) or return; bless $socket, $ref if $ref && $ref ne 'GLOB'; } 1;
|
|---|