in reply to Perl, JavaScript and quoting/escaping

Wow! JS in HTML in JS in HTML in Perl!

(I've broken the lines for readability. It's not quite equivalent with the line breaks, so they should be removed in the final version.)

Start with the inner JavaScript:

this.function.test('')

Add the inner HTML/XHTML:

<tr id="someid"><td> <a href="" onclick=" this.function.test('') "></a> </td></tr>

Add the JavaScript:

this.element.insert(' <tr id="someid"><td> <a href="" onclick=" this.function.test(\'\') "></a> </td></tr> ')

Add the outer HTML/XHTML: (XHTML requires that "<" be encoded. I encoded ">" as well, though it's not required.)

<a href="" onclick=" this.element.insert(' &lt;tr id=&quot;someid&quot;&gt;&lt;td&gt; &lt;a href=&quot;&quot; onclick=&quot; this.function.test(\'\') &quot;&gt;&lt;/a&gt; &lt;/td&gt;&lt;/tr&gt; ') ">

Add the Perl:

print(" <a href=\"\" onclick=\" this.element.insert(' &lt;tr id=&quot;someid&quot;&gt;&lt;td&gt; &lt;a href=&quot;&quot; onclick=&quot; this.function.test(\\'\\') &quot;&gt;&lt;/a&gt; &lt;/td&gt;&lt;/tr&gt; ') \"> ");

For comparison purposes, here's what you had:

print(" <a href=\"\" onclick=\" this.element.insert(' <tr id=\"someid\"><td> <a href=\"\" onclick=\" this.function.test(\'\') \"></a> </td></tr> ') \" ");

Not even close. It's much better to do it programmatically:

use HTML::Entities qw( encode_entities ); sub text_to_ht_attr_val { my $s = @_ ? $_[0] : $_; $s = encode_entities($s); return qq{"$s"}; } sub text_to_js_lit { my $s = @_ ? $_[0] : $_; $s =~ s/\\/\\\\/g; $s =~ s/'/\\'/g; # ... return qq{'$s'}; } my $ht_to_insert = q{<tr id="someid"><td>} . q{<a href="" onclick="this.function.test('')"></a>} . q{</td></tr>}; my $js_onclick = 'this.element.insert(' . text_to_js_lit($ht_to_insert) . ')'; my $ht_dyn_ele = '<a href="" onclick=' . text_to_ht_attr_val($js_onclick) . '>'; print( "$ht_dyn_ele\n" );
<a href="" onclick=" this.element.insert(&#39; &lt;tr id=&quot;someid&quot;&gt;&lt;td&gt; &lt;a href=&quot;&quot; onclick=&quot; this.function.test(\&#39;\&#39;) &quot;&gt;&lt;/a&gt; &lt;/td&gt;&lt;/tr&gt; &#39;) ">

For comparison purposes, here's what I had:

<a href="" onclick=" this.element.insert(' &lt;tr id=&quot;someid&quot;&gt;&lt;td&gt; &lt;a href=&quot;&quot; onclick=&quot; this.function.test(\'\') &quot;&gt;&lt;/a&gt; &lt;/td&gt;&lt;/tr&gt; ') ">

(Note that the single quotes didn't need to be encoded, but encode_entities harmlessly encodes them as "&#39;".)

Replies are listed 'Best First'.
Re^2: Perl, JavaScript and quoting/escaping
by isync (Hermit) on Sep 24, 2008 at 09:45 UTC
    That made it clear! (so the entities approach was the right track..).

    Thanks everyone for contributing!
Re^2: Perl, JavaScript and quoting/escaping
by Anonymous Monk on May 06, 2011 at 02:55 UTC
    This starts it all:
    print '<a href="#" onClick="var xmlHttp = null; xmlHttp = new XMLHttpRequest(); xmlHttp.open( &quot;GET&quot;, &quot;/cgi-bin/bid.js?aid='.( $rBid->{cgi}->param('aid')||-1 ).'&quot; , false ); xmlHttp.send( null ); eval(xmlHttp.responseText); return false;">[Bid]</a> ';

    In the above I'm scared that content from the client is being passed without first being quoted. I should escapeHTML this at the vary least, but this is not enough and whatever function I used needs to be secure enough for the job... Ideally I'd only use something provided by the specific make, model, and version of the processor. Understanding this is a remote web browser I'm willing to make certain concessions... Like using escapeHTML or URL escape functions provided by notable CPAN modules.

    This is where the problem is:
    print $rBid->{session}->header(-type=>'text/javascript'); my $sth = $rBid->{dbh}->prepare( 'INSERT INTO bid VALUES (?, (SELECT bidder_username FROM session WHERE id=?));') or die $rBid->{dbh}->errstr; $sth->execute($rBid->{cgi}->param('aid'), $rBid->{session}->id()||'undef') or print 'alert("Error: '. $rBid->{cgi}->escapeHTML($sth->errstr).'");'."\n"; print 'alert("Bid(s) Placed: '. $rBid->{cgi}->escapeHTML($sth->rows).'");'."\n";
    The escapeHTML above is interpreted by the JS and not the HTML processor, as there is no HTML processor. I could switch to using alert('... but then I'd need to escape '.

      print 'alert("Bid(s) Placed: '. $rBid->{cgi}->escapeHTML($sth->rows).'");'."\n";

      You are generating JavaScript code using something called escapeHTML. Yeah, that's not going to work. Perhaps you should be using the function I posted that generates JavaScript code instead...

        *sigh*

        This does something even if it doesn't produce the best results. I wouldn't be asking for help if I was doing the correct thing.

        This string contains "(s) and it just so happens that escapeHTML changes them to something else. Thus this code will run without errors, even if the output it generates is not correct. With zero escaping the code fails to compile just after the second ".

        As for the part you've taken above to mean something other then "Directly above this line of text" and instead as though top/bottom adjective were used. I think if you re-read it you'll see that I was talking about text/html and text/javascript respectively. Such that my statements about above make sense.

        Ohh yes, my question is "WHERE CAN I FIND A FUNCTION THAT WILL DO WHAT YOU THINK I NEED A FUNCTION TO DO?" So every thing we are arguing about is completely pointless as you understand clearly what I am asking for. I don't know why you replied, but I'm replying mainly to read myself type.

Re^2: Perl, JavaScript and quoting/escaping
by Anonymous Monk on May 06, 2011 at 00:01 UTC
    This is great!  However I have one question.  Is there an alternative to text_to_js_lit packaged as a module?
    
    I'm surprised that (q{\'\'} eq q{\'\'});  wouldn't this be eq q{''}?
    
    In any case the reason I ask is that for testing I'd like to pass perl strings to JS alert().  The problem was at first:
    
    alert("Error: ERROR:  null value in column "bidder_username" violates not-null constraint");  Where I was so lost as to why I couldn't get my string to popup.
    
    Then this:
    alert("Error: ERROR:  null value in column "bidder_username" violates not-null constraint");
    
    Where the result is not readable, this string is displayed as is.
    

      [ Please don't use <pre> here. Start paragraphs with <p>, and wrap computer text (code, input, output, etc) in <c>...</c>. <c>...</c> will even handle escaping "&", "<", ">", "[" and "]" for you. ]

      Is there an alternative to text_to_js_lit packaged as a module?

      package Module; sub text_to_js_lit { my $s = @_ ? $_[0] : $_; $s =~ s/\\/\\\\/g; $s =~ s/'/\\'/g; # ... return qq{'$s'}; } 1;

      I'm surprised that (q{\'\'} eq q{\'\'}); wouldn't this be eq q{''}?

      Say again?

      Where I was so lost as to why I couldn't get my string to popup. [...] Where the result is not readable, this string is displayed as is.

      What? You just said the same piece of code didn't display the message and displayed it as-is.

        Looking for a CPAN module that's hopefully maintained with a bug tracker. For example there are vary good functions for escaping for URL, HTML, many forms of SQL, ect, ect, ect. Where is the one for JavaScript?
        Haha, lol.
        I'm just not used to the markup of this forum and I can't escape properly.

        qq{\&#39;\&#39;} eq q{&#39;&#39;}

        " VS &quote;