J'ai un hachage Ruby qui contient une chaîne générée par l'utilisateur. Je dois passer ce hash à JavaScript pour qu'il puisse être traité. J'ai essayé d'utiliser JSON, qui fonctionne la plupart du temps, mais casse quand le hachage contient le texte </script>
. Voici le code le plus simple qui casse dans Chrome et FF8:Passez l'objet Ruby en JavaScript en toute sécurité
<%
obj = {
:foo => '</script>'
}
%>
<script type="text/javascript">
var obj = <%= obj.to_json %>; // Results in JS syntax error
</script>
Il en résulte le code HTML suivant:
<script type="text/javascript">
var obj = {"foo":"</script>"};
</script>
J'ai aussi essayé envelopper le JSON entre guillemets (simple et double) il peut être analysé par jQuery.parseJSON()
, mais il en résulte la même erreur de syntaxe:
<%
obj = {
:foo => '</script>'
}
%>
<script type="text/javascript">
var json = '<%= obj.to_json %>'; // Again results in JS syntax error
</script>
il semble que l'erreur de syntaxe est un résultat du navigateur en essayant d'interpréter le </script>
texte à la fin du bloc de script. Ma solution actuelle est d'échapper à la chaîne JSON comme HTML, échapper antislashs reste, écrire à JS comme une chaîne, unescape le code HTML, puis analyser enfin le JSON:
<%
obj = {
:foo => '</script>'
}
json = obj.to_json
escaped_json = CGI.escapeHTML(json)
slashed_escaped_json = escaped_json..gsub(/['"\\\x0]/,'\\\\\0')
%>
<script type="text/javascript">
var json = "<%= slashed_escaped_json %>";
json = $('<div/>').html(json).text(); // unescape HTML
var obj = jQuery.parseJSON(json); // parse JSON safely
console.log(obj);
</script>
Il fonctionne, mais il est laid. Y a-t-il un meilleur moyen? Je ne veux pas supprimer </script>
car j'échappe au contenu des entités HTML avant de le rendre sur la page.
J'ai mis à jour la question par commentaire. J'ai considéré Base64, mais plutôt utilisé l'encodage html dans ma solution laide. Il obtient le même résultat, mais me semble encore mal :( –