http://www.perlmonks.org?node_id=79420

alfie has asked for the wisdom of the Perl Monks concerning the following question:

Hi!

I think most of you have noticed the current traveling email worm called homepage.HTML.vbs. As a user of a linux-machine I found it very funny to see how often the message popped into my mailbox. On the other hand I was interested in what the source would look like, and found that it does some replacements to a quite long string. So I tried to decode it in perl, and came up with the following solution:

for (my $i = 0; $i < length($foo); $i++) { my $bar = substr($foo, $i, 1); if (ord($bar) == 15) { $bar = chr(10); } elsif (ord($bar) == 16) { $bar = chr(13); } elsif (ord($bar) == 17) { $bar = chr(32); } elsif (ord($bar) == 18) { $bar = chr(9); } else { $bar = chr(ord($bar)-2); } substr($foo, $i, 1) = $bar; } print $foo."\n";
I thought of using tr for that, but it seems to be quite tough to set up that lines.... So, any improvement are welcome - not for helping decoding (that was finished ;) but for improving personal abilities.

Like always, thanks in advance.
--
use signature; signature(" So long\nAlfie");

Replies are listed 'Best First'.
Re: homepage.vbs decode
by jeroenes (Priest) on May 10, 2001 at 19:05 UTC
    With tr it gets simpler:
    tr/\017\020\021\022/\012\015\040\011/; #Gets the subst tr/\023-\200/\021-\176/; #converts ranges
    If you need other ranges, they are easily made.

    Jeroen<br. "We are not alone"(FZ) Oops.. alfie is right. Perl indeed only uses the first occurence of a char in the 'search' string, it is documented in perlop:

    If multiple transliterations are given for a character, only the first one is used: tr/AAA/XYZ/ will transliterate any A to X.
      *beeep* Wrong answer, sorry. You are converting \021 to \036 in the endeffect, and that is not what I'd have expected. Sure, you could change the \040 in the first line to a \042 to fix that but what if there is a character lower than \023 in the original string?

      So, taking this, it seems that the following might be the solution:

      tr/\017\020\021\022\002-\200/\012\015\040\011\000-\176/;
      For with a quick test it seems that tr takes the first occurence of a character and doesn't care if there is another one later. Is that right, is that maybe even documented on it so I can be sure when using it?
      --
      use signature; signature(" So long\nAlfie");