A general problem exists in libwww when POSTing data to HTTP servers,
Content-Length headers and syswrite() calls use length() function over
payload to determine it's size.  This fails on Utf-8 encoded data,
because length() function returns the count of _characters_, not count
of bytes. It leads to a message truncated.

Solution is to use bytes::length() instead - it returns the size of
string in bytes.

Patch attached.

-- 
Pav Lucistnik <[EMAIL PROTECTED]>
              <[EMAIL PROTECTED]>

Every man is as God made him, ay, and often worse.
  -- Miguel de Cervantes
--- http.pm.orig	Thu Dec  8 11:28:01 2005
+++ http.pm	Thu Jun  8 14:24:21 2006
@@ -182,8 +182,8 @@
     else {
 	# Set (or override) Content-Length header
 	my $clen = $request_headers->header('Content-Length');
-	if (defined($$content_ref) && length($$content_ref)) {
-	    $has_content = length($$content_ref);
+	if (defined($$content_ref) && bytes::length($$content_ref)) {
+	    $has_content = bytes::length($$content_ref);
 	    if (!defined($clen) || $clen ne $has_content) {
 		if (defined $clen) {
 		    warn "Content-Length header value was wrong, fixed";
@@ -207,9 +207,9 @@
 
     if (!$has_content || $write_wait || $has_content > 8*1024) {
 	# XXX need to watch out for write timeouts
-	my $n = $socket->syswrite($req_buf, length($req_buf));
+	my $n = $socket->syswrite($req_buf, bytes::length($req_buf));
 	die $! unless defined($n);
-	die "short write" unless $n == length($req_buf);
+	die "short write" unless $n == bytes::length($req_buf);
 	#LWP::Debug::conns($req_buf);
 	$req_buf = "";
     }
@@ -224,7 +224,7 @@
 	if (ref($content_ref) eq 'CODE') {
 	    my $buf = &$content_ref();
 	    $buf = "" unless defined($buf);
-	    $buf = sprintf "%x%s%s%s", length($buf), $CRLF, $buf, $CRLF
+	    $buf = sprintf "%x%s%s%s", bytes::length($buf), $CRLF, $buf, $CRLF
 		if $chunked;
 	    substr($buf, 0, 0) = $req_buf if $req_buf;
 	    $wbuf = \$buf;
@@ -243,7 +243,7 @@
 	my $fbits = '';
 	vec($fbits, fileno($socket), 1) = 1;
 
-	while ($woffset < length($$wbuf)) {
+	while ($woffset < bytes::length($$wbuf)) {
 
 	    my $time_before;
 	    my $sel_timeout = $timeout;
@@ -267,7 +267,7 @@
 	    if (defined($rbits) && $rbits =~ /[^\0]/) {
 		# readable
 		my $buf = $socket->_rbuf;
-		my $n = $socket->sysread($buf, 1024, length($buf));
+		my $n = $socket->sysread($buf, 1024, bytes::length($buf));
 		unless ($n) {
 		    die "EOF";
 		}
@@ -289,19 +289,19 @@
 		}
 	    }
 	    if (defined($wbits) && $wbits =~ /[^\0]/) {
-		my $n = $socket->syswrite($$wbuf, length($$wbuf), $woffset);
+		my $n = $socket->syswrite($$wbuf, bytes::length($$wbuf), $woffset);
 		unless ($n) {
 		    die "syswrite: $!" unless defined $n;
 		    die "syswrite: no bytes written";
 		}
 		$woffset += $n;
 
-		if (!$eof && $woffset >= length($$wbuf)) {
+		if (!$eof && $woffset >= bytes::length($$wbuf)) {
 		    # need to refill buffer from $content_ref code
 		    my $buf = &$content_ref();
 		    $buf = "" unless defined($buf);
-		    $eof++ unless length($buf);
-		    $buf = sprintf "%x%s%s%s", length($buf), $CRLF, $buf, $CRLF
+		    $eof++ unless bytes::length($buf);
+		    $buf = sprintf "%x%s%s%s", bytes::length($buf), $CRLF, $buf, $CRLF
 			if $chunked;
 		    $wbuf = \$buf;
 		    $woffset = 0;

Reply via email to