Prosélyte has asked for the wisdom of the Perl Monks concerning the following question:

I received some help to write a forum , but i still can't really understand this piece of code who is told to be here to 'Parse'... Especially on the 4th line
foreach $pair (@pairs){ ($name,$value) = split(/=/,$pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $VALUE{$name} = $value;

Edit 2001-06-16 ar0n -- Changed title to a more descriptive one

Replies are listed 'Best First'.
Re: Enlightment for a little french
by tachyon (Chancellor) on Jun 16, 2001 at 04:43 UTC

    This is some decoding script for form input. You should not be doing this yourself. See Use CGI or die; and No excuses about not using CGI.pm

    Anyway here is an explanation:

    # iterate over @pairs array assigning each value to $pair in turn
    # this should start foreach my $pair (@pairs) 
    # see Use strict warnings and diagnostics
    
    foreach $pair (@pairs){
    
    # this splits each pair into $name and $value at the "="
    # the "=" is thrown away
    
          ($name,$value) = split(/=/,$pair);
    
    # this tr(ansliterates) the "+" chars into spaces
    # in HTTP this is how spaces are encoded
    
          $value =~ tr/+/ /;
    
    # this s(ubstitutes) some special encoded characters into their ASCII values
    # In HTTP certain chars have special meaning to the protocol so need
    # to be encoded. These are encoded as their hex equivalent
    # The encoded form is %DD where the DD are two hex digits and
    # the leading % is a flag to let us know the next two chars are 
    # hex digits encoding a ASCII literal. Now to the regex itself.
    # the first part captures the two hex digits after the % into $1
    # the second part converts these to their ASCII equivalents
    # the /eg at the end means "e" evaluate the second part and 
    # "g" do globally ie all ocurrences
    
          $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
          
    
    # this last line generates a associative array (a hash) called %VALUE
    # the key in this hash is $name and the value is $value
    
          $VALUE{$name} = $value;
    

    I recommend you check out Ovid's Web Programming with Perl tutorial for more details. This code will choke on names like "Jack&Jill" or "John Smith" because the decoding is only performed on $value, not $name. These will remain encoded as "Jack%26Jill" and "John+Smith".

    cheers

    tachyon

Re: Enlightment for a little french
by bikeNomad (Priest) on Jun 16, 2001 at 04:28 UTC
    This appears to be decoding urlencoded characters like %20 to their ASCII equivalents. What's happening is:<bl>
  • The two-character hex pairs are being detected and saved by the parentheses in ths s/// command
  • For each two-character hex value, the right side is computed as pack("C",hex($1)) which calls hex() to convert, for instance, "2f" into the number 47. Then pack() is called to take the single number 47 and convert it into the character '/'. This character becomes the value that is substituted for the entire "%2f" in the original string.
  • </bl>

    I wouldn't be surprised, though, to find that the CGI module would do this for you. However, since I don't use it, I can't tell you how.

    update: as others have said, you shouldn't be doing this by hand; use CGI. Also, changed ANSI to ASCII.

      Simply use param() instead of accessing a hash:
      use CGI ':standard'; my $val = param('foo');


      ar0n ]