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

Hello all, I'm using a mess of perl to output an html page (which isn't all that hard in and of itself), but among the stuff I wanted on the output html were some email addresses...the problem is that i get internal server errors when @ symbols are included in the perl scripting - anyone know a good way for me to trick it into realizing that they're just text to be displayed, just like the rest of the line?

Replies are listed 'Best First'.
Re: @ symbol in html output
by trantor (Chaplain) on Sep 23, 2001 at 11:06 UTC

    Without error logs (can you provide some?) it is dificult to spot the problem, however it's most probably because @ followed by a variable name is interpolated in a double quoted string, or its equivalent, so

    print "My email is foo@bar.com";

    tries to print the array @bar.

    To avoid this, use single quotes, or escape every @ in email addresses putting a backslash before it, like this:

    print "My email is foo\@bar.com"; print 'My email is foo@bar.com';

    Also remember that single quotes prevent interpolation, so if yuo have \n in your string, it won't be interpreted as a newline anymore.

    -- TMTOWTDI

      Good advice. Some more options:

      A here document:

      print <<'END_HTML'; email is officer@dibble.com this is still html <p> <blink>foo</blink> END_HTML
      Or quoting like this:
      print q{ email is officer@dibble.com this is still html <p> <blink>foo</blink> };

      Both of these options will prevent you from being caught out by awkward apostrophes (e.g. you would get in trouble with print 'my brother's email is a@b').

      NB.
      For the here document: if you want interpolation do print <<"END_HTML";. You can use whatever text you like instead of END_HTML.
      For the q{} quoting: if you want interpolation, use qq{}. You can use whatever sort of brackets you like, e.g. q().

      hth, andy.

Re: @ symbol in html output
by tachyon (Chancellor) on Sep 23, 2001 at 17:06 UTC

    Whenever you get 500 internal server errors you can easily ensure you get the actual text of the error in the browser for you to read by adding this code to the top of your script. This makes diagnosis a snap. Actually you can add it anywhere because of the BEGIN block. For more CGI tricks see my CGI Help Guide. It also explains how this works for you.

    You will be getting the 500 error because Perl will be spewing that you need to \ you @ chars in strings. This error comes out before the valid header and thus you get the error

    # ensure all fatals go to browser during debugging and setup # *don't* uncomment these 5 lines on production code for security BEGIN { $|=1; print "Content-type: text/html\n\n"; use CGI::Carp('fatalsToBrowser'); }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      # *don't* uncomment these 5 lines on production code for security
      TIA
      jg
        It wasn't my post, but the reason is simple. The hook in question will make errors go to the browser in a fairly informative fashion. This aids development. But if someone is trying to attack your site, the debugging output will help them break in.

        It is kind of like leaving a note saying where the key is hidden.

        That said, the actual style given there of having lines of code you modify between development and production is not the way you should do it. Instead what you should do is have a very small module that has those lines. Install that module in your development environment. Then in your production environment have a different version of the module that doesn't do anything. That way you don't have to touch your code going from development to production, and nothing will mess up. Otherwise your development process will be constantly complicated by the need to track down things like those lines which have to be edited at the last moment before going live, lines which you could introduce errors on. This will be an ongoing source of work and problems.

        Many here will recognize this as an example of an abstraction layer. Instead of writing in development hooks through your code, you write an abstraction layer for turning on the optional hooks. That abstraction layer will do the right thing for your evironment without your having to change a lot of source code going from one environment to another. The idea of solving problems with abstraction layers rather than scattered checks is a key one in good programming. I talk about it a bit at RE (tilly) 2: Handling cascading defaults (abstraction is great!) among other places.

        They enable extra debugging outfit that's helpful for programmers. Unfortunately, it can be confusing for normal users and may even be exploitable by malicious users. It gives out more information that anyone but the people who have access to the error logs really need to know.
Re: @ symbol in html output
by rob_au (Abbot) on Sep 23, 2001 at 11:01 UTC
    The problems you would be experiencing relate to the interpolation of the address "email@address.com" with the value of the @address. The solution will revolve around either escaping meta characters such as @ with a backslash (\) or printing without interpolation - See quotemeta and perlop for further details.

     

    Ooohhh, Rob no beer function well without!

      I don't think quotemeta is what you want in this case... the '@' and '$' symbols still cause interpolation even inside of the "\Q" usage of quotemeta. You can use the quotemeta() function to escape them, but then you'll also print the backslashes. This happens because the string isn't interpolated recursively. Consider the following:
      #!/usr/bin/perl -wT use strict; ## wrong, causes error # print "\Qblakem@foo1.com\E\n"; ## wrong, prints the backslashes print quotemeta('blakem@foo2.com'),"\n"; ## wrong, still prints backslashes my $escaped = quotemeta('blakem@foo3.com'); print "$escaped\n"; print $escaped, "\n"; ## right my $email = 'blakem@foo4.com'; print "$email\n"; ## right print "blakem\@foo5.com\n"; print 'blakem@foo6.com',"\n"; =output blakem\@foo2\.com blakem\@foo3\.com blakem\@foo3\.com blakem@foo4.com blakem@foo5.com blakem@foo6.com
      From perlop:
      You cannot include a literal $ or @ within a \Q sequence. An unescaped + $ or @ interpolates the corresponding variable, while escaping will cause the literal stri +ng \$ to be inserted. You'll need to write something like m/\Quser\E\@\Qhost/.
      So, either put the backslash in by hand if you are simply printing the string
      print "blakem\@foo.com"; print 'blakem@foo.com';
      or assign it to a scalar and print the scalar
      my $email = 'blakem@foo.com'; print $email;

      -Blake