in reply to Re: CGI hidden params vs. character encoding
in thread CGI hidden params vs. character encoding

FINALLY FIGURED IT OUT! (...in a manner of speaking)
#!/usr/bin/perl -T -w use strict; use CGI qw(:standard); use Encode; binmode STDOUT, ":utf8"; my $cgi = CGI->new(); print $cgi->header(-charset => 'UTF-8'), $cgi->start_html(-title => "Testing hidden-input character encoding", -encoding => 'UTF-8' ), $cgi->start_form; my $parms = $cgi->Vars; if ( $$parms{submit} ) { my $newtest = decode( 'utf8', $$parms{testtext} ); my $newhid = decode( 'utf8', $$parms{testtext_hid} ); delete $$parms{testtext_hid}; ### THIS IS WHAT FIXES THE PROB +LEM print "<p/> The testtext parameter as received was: ". $newtest, "<p/> The hidden parameter was: ". $newhid, $cgi->hidden( "testtext_hid", $newhid ); } else { my $testtext = "\x{444}\x{443}\x{431}\x{430}\x{440}"; print $cgi->textfield( -name => "testtext", -value => $testtext ), $cgi->hidden( "testtext_hid", $testtext ), $cgi->submit(-name => "submit", -value => "submit" ); } print $cgi->end_form, $cgi->end_html;
I can only guess what might be going on under the covers when CGI sees that it is being given a new value (with the utf8 flag on) that replaces one of the existing parameters already in the "context" of the form (which does not have its utf8 flag on, even though it may already contain valid utf8 data -- it comes from an untrusted source, after all).

In any case, if I remove the existing parameter from the current "context", the assignment proceeds as expected -- no double encoding.

All in all, it smells like a bug in CGI, but I'm sufficiently far enough behind in my coding at this point, that I'm happy enough just to know that there is a way to get the intended behavior. Case closed, as far as I'm concerned.

Replies are listed 'Best First'.
Re^3: CGI hidden params vs. character encoding
by ikegami (Patriarch) on May 28, 2008 at 04:19 UTC

    FINALLY FIGURED IT OUT! (...in a manner of speaking)

    oh, right! Here are two better ways:

    print $cgi->p("The testtext parameter as received was: ". escapeHTML($ +newtest)), $cgi->p("The hidden parameter was: ". escapeHTML($newhid)), $cgi->hidden(-name=>"testtext_hid", -default=>$newhid, -override +=>1);
    $cgi->param('testtext_hid', $newhid); print $cgi->p("The testtext parameter as received was: ". escapeHTML($ +newtest)), $cgi->p("The hidden parameter was: ". escapeHTML($newhid)), $cgi->hidden("testtext_hid");

    Note the -override=>1 in the first snippet, or how the the second snippet sets the parameter instead of setting the default.

    Also note how I did the P elements. <p/> makes no sense. <p/>text<p/>text means <p></p>text<p></p>text but you want <p>text</p><p>text</p>.

    Finally, note how I used escapeHTML to avoid an injection attack and invalid HTML generation.

    All in all, it smells like a bug in CGI

    I agree. Not that you had to use -override, that's clearly documented under the "CREATING FILL-OUT FORMS" header. But how it handles (or rather doesn't handle) encodings other than iso-latin-1.

Re^3: CGI hidden params vs. character encoding
by Anonymous Monk on May 28, 2008 at 02:35 UTC
    Try without Vars(), just using param()