From bf3cd03977d1990c1e23a54a396de468d08f9280 Mon Sep 17 00:00:00 2001 From: Ilia Ross Date: Tue, 14 Jul 2026 00:46:12 +0200 Subject: [PATCH] Fix to manually incorporated Jamie's 70011c1 change --- t/web-lib-funcs-ip.t | 28 ++++++++++++++++++++++++++++ web-lib-funcs.pl | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/t/web-lib-funcs-ip.t b/t/web-lib-funcs-ip.t index e8f982eb6..9316dfa17 100644 --- a/t/web-lib-funcs-ip.t +++ b/t/web-lib-funcs-ip.t @@ -278,6 +278,34 @@ subtest 'callback hash dispatches tracker events' => sub { 'legacy callback code refs remain supported'); }; +subtest 'callback bundle preserves connected IP event' => sub { + no warnings qw(once redefine); + my ($connection_callback, $download_callbacks); + local *main::make_http_connection = sub { + $connection_callback = $_[8]; + return { 'ip' => '93.184.216.34' }; + }; + local *main::complete_http_download = sub { + $download_callbacks = $_[3]; + return 1; + }; + my @events; + my $address_callback = sub { return undef; }; + my $callbacks = { + 'tracker_callback' => sub { push(@events, [ @_ ]); }, + 'address_callback' => $address_callback, + }; + my ($dest, $err); + main::http_download('origin.test', 80, '/', \$dest, \$err, $callbacks, + 0, undef, undef, 0, undef, 1); + is_deeply(\@events, [ [ 7, '93.184.216.34' ] ], + 'tracker callback receives the connected IP event'); + is($connection_callback, $address_callback, + 'connection receives the address callback'); + is($download_callbacks, $callbacks, + 'download receives the complete callback bundle'); +}; + subtest 'redirect destination policy' => sub { no warnings qw(once redefine); my @lines = ( diff --git a/web-lib-funcs.pl b/web-lib-funcs.pl index 7d28dfd66..04ac0cd16 100755 --- a/web-lib-funcs.pl +++ b/web-lib-funcs.pl @@ -3367,6 +3367,23 @@ Downloads data from a HTTP url to a local file or string. The parameters are : =item response_headers - If set returns a hash ref of response HTTP headers. +If the callback function is defined, it will be called at each step of the download process with a mode parameter and +additional args. The mode will be one of : + +=item 1 - Completed reading headers, arg is 1 for a redirect, 0 otherwise + +=item 2 - Received content length, arg is the response size in bytes + +=item 3 - Received data, arg is the bytes returned so far + +=item 4 - Finished receiving data + +=item 5 - Following a redirect, arg is the new URL + +=item 6 - Data was found in cache, arg is the full cached URL + +=item 7 - TCP connection made, arg is the remote IP (if known) + =cut sub http_download { @@ -3446,6 +3463,7 @@ if (!ref($h)) { if ($error) { $$error = $h; return; } else { &error(&html_escape($h)); } } +&$cbfunc(7, $h->{'ip'}) if ($cbfunc); &complete_http_download($h, $dest, $error, $callbacks, $osdn, $host, $port, $headers, $ssl, $nocache, $timeout, $response_headers); if ((!$error || !$$error) && !$nocache) { @@ -4076,6 +4094,8 @@ parameters are : array reference of its resolved IP addresses. It must return an error message to reject the destination, or undef to allow it. +Returns the IP to which the connection was actually made. + =cut sub open_socket { @@ -4093,13 +4113,14 @@ my $address_error = &check_download_address( $host, $address_callback, \@ips); if ($address_error) { my $msg = $address_error; - if ($err) { $$err = $msg; return 0; } + if ($err) { $$err = $msg; return undef; } else { &error($msg); } } # Try each of the resolved IPs my $msg; my $proto = getprotobyname("tcp"); +my $gotip; foreach my $ip (@ips) { $msg = undef; if (&check_ipaddress($ip)) { @@ -4137,11 +4158,12 @@ foreach my $ip (@ips) { next; } } + $gotip = $ip; last; # If we got this far, it worked } if ($msg) { # Last attempt failed - if ($err) { $$err = $msg; return 0; } + if ($err) { $$err = $msg; return undef; } else { &error($msg); } } @@ -4149,7 +4171,7 @@ if ($msg) { my $old = select($fh); $| = 1; select($old); -return 1; +return $gotip; } =head2 download_timeout @@ -9995,9 +10017,10 @@ if ($ssl) { if (!$connected) { # Direct connection my $error; - &open_socket($host, $port, $rv->{'fh'}, \$error, $bindip, - $address_callback); + my $ip = &open_socket($host, $port, $rv->{'fh'}, \$error, $bindip, + $address_callback); return $error if ($error); + $rv->{'ip'} = $ip; } Net::SSLeay::set_fd($rv->{'ssl_con'}, fileno($rv->{'fh'})); eval { @@ -10049,10 +10072,11 @@ else { if (!$connected) { # Connecting directly my $error; - &open_socket($host, $port, $rv->{'fh'}, \$error, $bindip, - $address_callback); + my $ip = &open_socket($host, $port, $rv->{'fh'}, \$error, $bindip, + $address_callback); return $error if ($error); my $fh = $rv->{'fh'}; + $rv->{'ip'} = $ip; my $rtxt = "$method $page HTTP/1.0\r\n".$htxt; print $fh $rtxt; }