Utf-8 and Content-Length header

Pav Lucistnik <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.lwp
Message-ID <[email protected]>
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.diff (text/x-patch, 2.7 KB)
--- 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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.