2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-08 01:14:19 +00:00

HttpUtils.pm: second try of chunked changes (Forum #62260)

git-svn-id: https://svn.fhem.de/fhem/trunk@12735 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2016-12-10 13:06:54 +00:00
parent 57c15fbb07
commit 984b02cd9c

View File

@ -405,6 +405,7 @@ HttpUtils_Connect2($)
if($hash->{callback}) { # Nonblocking read
$hash->{FD} = $hash->{conn}->fileno();
$hash->{buf} = "";
delete($hash->{httpdatalen});
$hash->{NAME} = "" if(!defined($hash->{NAME}));
my %timerHash = (hash=>$hash, checkSTS=>$selectTimestamp, msg=>"write to");
$hash->{directReadFn} = sub() {
@ -412,12 +413,12 @@ HttpUtils_Connect2($)
my $len = sysread($hash->{conn},$buf,65536);
$hash->{buf} .= $buf if(defined($len) && $len > 0);
if(!defined($len) || $len <= 0 ||
HttpUtils_DataComplete($hash->{buf})) {
HttpUtils_DataComplete($hash)) {
delete($hash->{FD});
delete($hash->{directReadFn});
delete($selectlist{$hash});
RemoveInternalTimer(\%timerHash);
my ($err, $ret, $redirect) = HttpUtils_ParseAnswer($hash, $hash->{buf});
my ($err, $ret, $redirect) = HttpUtils_ParseAnswer($hash);
$hash->{callback}($hash, $err, $ret) if(!$redirect);
}
};
@ -459,13 +460,52 @@ HttpUtils_Connect2($)
sub
HttpUtils_DataComplete($)
{
my ($ret) = @_;
return 0 if($ret !~ m/^(.*?)\r?\n\r?\n(.*)$/s);
my $hdr = $1;
my $data = $2;
return 0 if($hdr !~ m/Content-Length:\s*(\d+)/si);
return 0 if(length($data) < $1);
return 1;
my ($hash) = @_;
my ($hdr, $data) = ($1, $2);
my $hl = $hash->{httpdatalen};
if(!defined($hl)) {
return 0 if($hash->{buf} !~ m/^(.*?)\r?\n\r?\n(.*)$/s);
my ($hdr, $data) = ($1, $2);
if($hdr =~ m/Transfer-Encoding:\s*chunked/si) {
$hash->{httpheader} = $hdr;
$hash->{httpdata} = "";
$hash->{buf} = $data;
$hash->{httpdatalen} = -1;
} elsif($hdr =~ m/Content-Length:\s*(\d+)/si) {
$hash->{httpdatalen} = $1;
$hash->{httpheader} = $hdr;
$hash->{httpdata} = $data;
$hash->{buf} = "";
} else {
$hash->{httpdatalen} = -2;
}
$hl = $hash->{httpdatalen};
}
return 0 if($hl == -2);
if($hl == -1) { # chunked
while($hash->{buf} =~ m/^[\r\n]*([0-9A-F]+)\r?\n(.*)$/si) {
my ($l, $r) = (hex($1), $2);
if($l == 0) {
$hash->{buf} = "";
return 1;
}
return 0 if(length($r) < $l);
$hash->{httpdata} .= substr($r, 0, $l);
$hash->{buf} = substr($r, $l);
}
return 0;
} else {
$hash->{httpdata} .= $hash->{buf};
$hash->{buf} = "";
return 0 if(length($hash->{httpdata}) < $hash->{httpdatalen});
return 1;
}
}
sub
@ -519,16 +559,16 @@ HttpUtils_DigestHeader($$)
}
sub
HttpUtils_ParseAnswer($$)
HttpUtils_ParseAnswer($)
{
my ($hash, $ret) = @_;
my ($hash) = @_;
if(!$hash->{keepalive}) {
$hash->{conn}->close();
undef $hash->{conn};
}
if(!$ret) {
if(!$hash->{buf} && !$hash->{httpheader}) {
# Server answer: Keep-Alive: timeout=2, max=200
if($hash->{keepalive} && $hash->{hu_filecount}) {
my $bc = $hash->{hu_blocking};
@ -546,11 +586,19 @@ HttpUtils_ParseAnswer($$)
$hash->{hu_filecount} = 0 if(!$hash->{hu_filecount});
$hash->{hu_filecount}++;
$ret=~ s/(.*?)\r?\n\r?\n//s; # Not greedy: separate the header (F:#43482)
return ("", $ret) if(!defined($1));
if(!defined($hash->{httpheader})) { # response without Content-Length
if($hash->{buf} =~ m/^(HTTP.*?)\r?\n\r?\n(.*)$/s) {
$hash->{httpheader} = $1;
$hash->{httpdata} = $2;
} else {
return ("", $hash->{buf});
}
}
my $ret = $hash->{httpdata};
delete $hash->{httpdata};
delete $hash->{httpdatalen};
$hash->{httpheader} = $1;
my @header= split("\r\n", $1);
my @header= split("\r\n", $hash->{httpheader});
my @header0= split(" ", shift @header);
my $code= $header0[1];
@ -583,7 +631,7 @@ HttpUtils_ParseAnswer($$)
}
} elsif($code==401 && defined($hash->{auth})) {
return ("$hash->{displayurl}: wrong authentication", "")
return ("$hash->{displayurl}: wrong authentication", "")
}
@ -608,31 +656,9 @@ HttpUtils_ParseAnswer($$)
}
}
if( $hash->{httpheader} =~ m/^Transfer-Encoding: Chunked/mi ) {
my $data;
my $header;
my ($size, $offset) = (length($ret), 0);
while( $offset < $size ) {
my $next = index($ret, "\r\n", $offset);
last if( $next == -1 );
if( substr($ret,$offset,$next-$offset) =~ m/([\da-f]+)/i ) {
my $len = hex($1);
$offset = $next + 2;
$data .= substr($ret,$offset,$len);
$offset += $len + 2;
next if( $len > 0 );
}
$hash->{httpheader} .= substr($ret,$offset);
}
$ret = $data;
}
# Debug
Log3 $hash, $hash->{loglevel},
"HttpUtils $hash->{displayurl}: Got data, length: ". length($ret);
"HttpUtils $hash->{displayurl}: Got data, length: ". length($ret);
if(!length($ret)) {
Log3 $hash, $hash->{loglevel}, "HttpUtils $hash->{displayurl}: ".
"Zero length data, header follows:";
@ -678,8 +704,10 @@ HttpUtils_BlockingGet($)
my $err = HttpUtils_Connect($hash);
return ($err, undef) if($err);
my ($buf, $ret) = ("", "");
my $buf = "";
$hash->{conn}->timeout($hash->{timeout});
$hash->{buf} = "";
delete($hash->{httpdatalen});
for(;;) {
my ($rout, $rin) = ('', '');
vec($rin, $hash->{conn}->fileno(), 1) = 1;
@ -691,10 +719,10 @@ HttpUtils_BlockingGet($)
my $len = sysread($hash->{conn},$buf,65536);
last if(!defined($len) || $len <= 0);
$ret .= $buf;
last if(HttpUtils_DataComplete($ret));
$hash->{buf} .= $buf;
last if(HttpUtils_DataComplete($hash));
}
return HttpUtils_ParseAnswer($hash, $ret);
return HttpUtils_ParseAnswer($hash);
}
# Deprecated, use GetFileFromURL/GetFileFromURLQuiet