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

As you can tell from the title this is actually more of an HTML question. I have a perl cgi script for a knowledge base that allows folks to add technotes as html. Everything works fine, except html escapes in textareas. For example:

If a user is adding a technote that refers to xml edits, and they want to escape the < by using "&lt;" then the file gets posted and saved fine by my script. But when the user comes back to edit the document again, and I spit it out between the textarea tags - it stays that way in the html source, but in the textarea the &lt; gets traslated to < and when it is saved, the xml tags that were in the technote to be modifed as text are now interpreted as html/xml tags and not text to be displayed in the textarea.

Funny enough the <pre> <code> tags dont help - they aren't interprested as tags, but rather displayed.

Does anyone know a way around this? or are textareas just crappy for editing html? Maybe some type of javascript?

Here is some example code - I've escaped the < and > so that it will show ok in here:

<textarea>&lt;property key="smtpHost"        value=""/&gt;</textarea>

Just drop this in an html doc, and you will see that the escapes will show as <> and not &lt; and &gt; in the textarea

I'll probobly get bashed since the answer has little to do with perl, but I figured if anyone might know, it'd be the Perl Monks

TIA, Jeff

Replies are listed 'Best First'.
Re: HTML Problem getting entities into a textarea
by dws (Chancellor) on Apr 18, 2003 at 20:52 UTC
    When you're emiting the textarea tags, escape the entities in the content. It appears to suffice to escape '&' and '<', though throwing in '>' won't hurt.

    Conceptually, this looks like

    my $escaped = $content; $escaped =~ s/&/&amp;/g; $escaped =~ s/</&lt;/g; $escaped =~ s/>/&gt;/g; print "<textarea>$escaped</textarea>";

      See my above note on this idea. The problem is that I want folks to be able to create a technote (in a textread form) that contains any html tag, and save it exactly as typed, and then have them be able to edit that exact text again later, without some of those tag being interpreted as tags for the page instead of text in the textarea. If I modify the content like that, then a user types in one thing and ends up editing another.

      Then again, if I told folks not to escape, and I escaped for them before saving the file, then that just might work... then any tags would be saves with escapes, and displayed as text and not interpreted. The only problem with this is if you type, say, <pre> </pre> inside a textarea - that doesn't get interpreted, so I would be escaping things that don't need it, but I suppose that might be alright.

      Actually, that get ugly, because, then all of the tags that I am telling people to use to format the text of the technote will now not be tags that format the text when displayed later in a table, they will show as text, unless I unescape all before displaying to the table.

      That get's messy, but it may be the only way...

      Any other ideas?

        The problem is that I want folks to be able to create a technote (in a textread form) that contains any html tag, and save it exactly as typed, and then have them be able to edit that exact text again later, without some of those tag being interpreted as tags for the page instead of text in the textarea.

        From the sound of it, someone is doing some unecessary entity unescaping when the form is submitted. If a user types

        <foo>
        but what ends up saved is
        &lt;foo&gt;
        then there's a problem in your form processing logic.

      And make sure you escape the & before the < and > otherwise you end up with something along the lines of:

      "<" -> "%lt;" -> "&lt;"

Re: HTML Problem getting entities into a textarea
by caedes (Pilgrim) on Apr 18, 2003 at 20:41 UTC
    I believe you'll have to 'double escape' the html escape code for it to show up correctly in the browser's textarea. For example if you wanted '&gt;' to show in the textarea you'd have to write it as '&amp;gt;'. That way when the browser interprets the code it will only replace the '&amp;' with '&' leaving '&gt;' and not '>'.

    Incidentally, in order to print this out correctly I have to triple escape the code. Talk about confusing!

    -caedes

      Thanks, but if you try it like I suggested, you'll see the dilema - here is the problem:

      I want &lt; to show up as-is, since that is what the user typed when the document was created. If I have them double-escape (or really escape the & with &amp;) then when I save the text, and then display it later (on a technote display page that drops the html in a table cell) it will show as &lt; and not as <

      The problem is that most tags inside the textarea tag are NOT interpreted, but the following IS:

      <textarea>&lt;property key="smtpHost"        value=""/&gt;</textarea>

      Basically, I think that this is a bug in the textarea tag for html - any other ideas?

      TIA again, Jeff

        I want &lt; to show up as-is, since that is what the user typed when the document was created.

        If the user literaly typed '&' 'l' 't' ';', then to prevent this from being corrupted when you spit the text back out into a textarea, you're going to need to escape the '&'. This isn't an HTML bug, though it's not the most documented aspect of HTML that you'll find.

Re: HTML Problem getting entities into a textarea
by The Mad Hatter (Priest) on Apr 18, 2003 at 21:20 UTC
    Just escape those characters every time it is sent to the CGI script. If you want &lt; to show up in the textarea, use &amp;lt;. &amp; is the ampresand.
(jeffa) Re: HTML Problem getting entities into a textarea
by jeffa (Bishop) on May 21, 2003 at 02:46 UTC
    Like tye said, use a tool to do this, and a good alternative to CGI.pm is HTML::Template. The <tmpl_var> tag has an option attribute named escape that, when set to html, will solve this problem in a very painless way for the coder. Here is a complete CGI script to demonstrate:
    #!/usr/bin/perl -T use strict; use warnings; use CGI qw(header param); use HTML::Template; my $tmpl = HTML::Template->new(filehandle => \*DATA); $tmpl->param(html => param('html')); print header, $tmpl->output; __DATA__ <html> <head> <title>textarea test</title> </head> <body> <form> <textarea name="html"><tmpl_var name="html" escape="html"></textarea> <input type="submit" /> </form> <hr /> <p><tmpl_var name="html"></p> </body> </html>
    Be sure and view the source and inspect the contents of the textarea element.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: HTML Problem getting entities into a textarea (CGI.pm)
by tye (Sage) on Apr 21, 2003 at 15:43 UTC

    BTW, this is one of the main reasons why I encourage the use of CGI.pm for producing HTML output (not just for interpretting CGI parameters). Just in the code for PerlMonks, quite a large number of bugs can be blamed on not using CGI.pm (I've seen many introduced when code was converted to not use CGI.pm, I've seen many fixed when code was converted to use CGI.pm, and there are at least a few still present that I hope to fix by using CGI.pm).

    Not that CGI.pm's generation of HTML is perfect. Having radio_group() call escapeHTML() on the labels is simply a mistake and I'm not a big fan of what end_form() does. And the most common mistake I see made is people not specifying force=>1 when they should.

    But I suspect that you've only noticed this bug in one place and that you likely have the same bug in several other places. And knowing how to escape a value in some parts of HTML can be rather tricky. But the biggest problem appears to me to be that people simply don't think about having to escape values and just include them unchanged into their HTML and that often works (and sometimes you should not escape things). So I consider generating HTML with CGI.pm to be a good habit (in situations where a better habit isn't being used).

                    - tye