views:

107

answers:

1

I have the following code:

...
sub setImage {
    my $self=shift;
    my $filename=shift;
    unless(-r $filename) {
        warn "File $filename not found";
        return;
    }
    my $imgn=shift;
    my $operation=&URI::Escape::uri_escape_utf8(
        (shift) ? "Удалить! (Delete)" : "Сохранить! (Store)");
    my $FH=&::File::open($filename, 0, 0);
    my $image;
    # &utf8::downgrade($image);
    sysread($FH, $image, 102400, 0);
    close $FH;
    my $imginfo=eval{&Image::Info::image_info(\$image)};
    if($@ or $imginfo->{"error"}) {
        warn "Invalid image: ".($@ || $imginfo->{"error"});
        return undef;
    }
    my $fields=[
        DIR       => $self->url("fl"),
        OPERATION => $operation,
        FILE_NAME => ".photo$imgn",
        # FILE      => [$filename],
        FILE      => [undef, "image.".$imginfo->{"file_ext"},
            # Content_Type => $imginfo->{"file_media_type"},
            # Content_Type => 'application/octet-stream',
            Content      => $image,
        ],
    ];
    my $response=&ZLR::UA::post(
        &ZLR::UA::absURL("/cgi-bin/file_manager")."",
        $fields,
        Content_Type => "form-data",
    );
    print $response->decoded_content;
}
...

When I try to use function setImage it fails with error HTTP::Message content must be bytes at /usr/lib64/perl5/vendor_perl/5.8.8/HTTP/Request/Common.pm line 91. Worse that I can't reproduce this error without using all of my code and upgrading libwww-perl does nothing. What can cause it?

Versions of libww-perl: dev-perl/libwww-perl-5.836. HTTP::Request and HTTP::Request::Common came from libwww-perl package, versions: 5.827 and 5.824.

Trace:

HTTP::Message content must be bytes at /usr/lib64/perl5/vendor_perl/5.8.8/HTTP/Request/Common.pm line 91
 at Carp::croak(unknown source)
 at HTTP::Message::__ANON__(/usr/lib64/perl5/vendor_perl/5.8.8/HTTP/Message.pm:16)
 at HTTP::Message::_set_content(/usr/lib64/perl5/vendor_perl/5.8.8/HTTP/Message.pm:136)
 at HTTP::Message::content(/usr/lib64/perl5/vendor_perl/5.8.8/HTTP/Message.pm:125)
 at HTTP::Request::Common::POST(/usr/lib64/perl5/vendor_perl/5.8.8/HTTP/Request/Common.pm:91)
 at LWP::UserAgent::post(/usr/lib64/perl5/vendor_perl/5.8.8/LWP/UserAgent.pm:397)
 at ZLR::UA::post(./zlrchecker.pl:71)
 at ZLR::Info::setImage(./zlrchecker.pl:1754)
 at main::main(./zlrchecker.pl:3893)
 at main::(./zlrchecker.pl:4148)
+2  A: 

Use Devel::SimpleTrace and paste the trace. Install the module with cpan. Then run your program with -MDevel::SimpleTrace like perl -MDevel::SimpleTrace ./myapp_run.pl

And paste the version of HTTP::Request:Common, HTTP::Message, and LWP.

My guess is you'll see this in the stack trace:

This seems to be the code likely causing the error:

*_utf8_downgrade = defined(&utf8::downgrade) ?
    sub {
        utf8::downgrade($_[0], 1) or
            Carp::croak("HTTP::Message content must be bytes")
    }
    :
    sub {
    };

The docs in utf8 say this:

Fails if the original UTF-X sequence cannot be represented in the native 8 bit encoding. On failure dies or, if the value of FAIL_OK is true, returns false.

You should be able to make a test case by running utf8::downgrade($http_message_content)

Evan Carroll
ZyX
right, that error is the issue. `HTTP::Message` croaks if you get an error there with its own error (as shown in the code above) -- the second argument (1) means don't die just return failure, then it dies with the message "HTTP::Message content must be bytes" instead.
Evan Carroll
The problem is that if I try the following one-liner everything is OK: `perl -e 'use utf8; use LWP::UserAgent; my $response=LWP::UserAgent->new()->post("http://zhurnal.lib.ru/cgi-bin/file_manager", [DIR => "z/zyx", OPERATION => "Store", FILE_NAME => ".photo1", FILE => ["/home/zyx/a.a/\{smth\}/\{pic\}/speed.jpg"]], Content_Type => "form-data");'`. And if I do the same things in my function it dies.
ZyX
Then your function is doing something goofy. Try hand hacking in a dump of `$_[1]` (or otherwise getting to the $content) at HTTP::Message::_set_content(/usr/lib64/perl5/vendor_perl/5.8.8/HTTP/Message.pm:136). Then try running that output through `utf8::downgrade()`.
Evan Carroll
Commenting out `use encoding 'utf8';` in package main did the trick. Don't remember why I had put it alongside with `use utf8;`.
ZyX
Explanation of the problem: http://stackoverflow.com/questions/492838#493508
daxim