Échapper les citations en JavaScript

211

Je génère des valeurs à partir d'une base de données (elle n'est pas vraiment ouverte à l'entrée publique, mais elle est ouverte à l'entrée par un utilisateur de l'entreprise - ce qui signifie que je ne m'inquiète pas pour XSS ).

J'essaie de sortir une balise comme celle-ci:

<a href="" onclick="DoEdit('DESCRIPTION');">Click Me</a>

DESCRIPTION est en fait une valeur de la base de données qui ressemble à ceci:

Prelim Assess "Mini" Report

J'ai essayé de remplacer "par \", mais peu importe ce que j'essaye, Firefox continue de couper mon appel JavaScript après l'espace après le mot évaluer , et cela provoque toutes sortes de problèmes.

Je dois rejeter la réponse évidente, mais pour la vie de moi, je ne peux pas le comprendre.

Quelqu'un veut-il souligner mon idiotie?

Voici la page HTML entière (ce sera finalement une page ASP.NET , mais pour résoudre ce problème, j'ai retiré tout le reste sauf le code du problème)

<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;">edit</a>
    </body>
</html>
Matt Dawdy
la source
3
C'est une bonne idée de rendre votre onclickpièce jointe d'événement discrète et de déplacer toutes vos informations de base de données dans un îlot de données. Les choses seront plus propres et vous obtiendrez en fait une sorte d'erreur de syntaxe lorsque vos chaînes s'échapperont mal.
Justin Johnson
Vous pouvez également utiliser les méthodes jquery escape ("string") et unescape ("string")
Abhiram

Réponses:

212

Vous devez échapper la chaîne dans laquelle vous écrivez DoEditpour effacer les caractères entre guillemets. Ils provoquent la onclickfermeture prématurée de l'attribut HTML.

L'utilisation du caractère d'échappement JavaScript \, n'est pas suffisante dans le contexte HTML. Vous devez remplacer le guillemet avec la représentation d' une entité XML appropriée, &quot;.

Aaron
la source
D'accord, mais ne serait-ce pas ça? <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;"> modifier </a> J'ai essayé, et ça continue de bousiller. Cela doit être un simple WTF mais pour la vie de moi, je ne peux pas le voir.
Matt Dawdy
Existe-t-il une fonction JavaScript intégrée qui échapperait aux guillemets doubles? A part 'quo "'. Replace ('"', '& quot;') Je ne trouve rien.
kevin
4
Ce n'est pas un problème javascript, c'est un problème d'encodage HTML / XML: vous ne pouvez pas avoir de caractères entre guillemets dans une valeur d'attribut sans les échapper ... sinon les navigateurs / analyseurs pensent que vous terminez la déclaration de valeur d'attribut.
Aaron
22
exemple de code de remplacement:'mystring'.replace(/"/g, '&quot;');
Joshua Burns
3
dans le commentaire précédent, il y a une citation supplémentaire. Le code qui fonctionne est 'mystring'.replace (/' / g, '& quot;');
Agustin Lopez
95

&quot; fonctionnerait dans ce cas particulier, comme suggéré avant moi, en raison du contexte HTML.

Cependant, si vous souhaitez que votre code JavaScript soit échappé indépendamment pour n'importe quel contexte, vous pouvez opter pour le codage JavaScript natif:
'devient \x27
"devient\x22

Votre onclick deviendrait donc:
DoEdit('Preliminary Assessment \x22Mini\x22');

Cela fonctionnerait par exemple également lors du passage d'une chaîne JavaScript en tant que paramètre à une autre méthode JavaScript ( alert()c'est une méthode de test facile pour cela).

Je vous renvoie à la question de débordement de pile en double, comment puis-je échapper une chaîne dans le code JavaScript à l'intérieur d'un gestionnaire onClick? .

tsemer
la source
2
Je vous remercie! Votre réponse est la plus correcte car il s'agit de JavaScript natif quel que soit le contexte.
scarver2
2
C'est la bonne réponse, bien que dans un contexte HTML, l'utilisation fonctionnera &quot;, bien sûr.
Oliver
Notez que cela &quot;est requis dans les valeurs d'entrée, c'est-à-dire <input value="\x22quoted string\x22">qu'il ne fonctionnera pas.
thdoan
@ 10basetom naturellement, l'échappement JavaScript ne fonctionne que dans un contexte JavaScript, comme les gestionnaires d'événements ( onclick="..."). La valeur d'un valueattribut n'est pas traitée dans un contexte JavaScript, uniquement dans un contexte HTML.
tsemer
code de remplacement:'mystring'.replace(/"/g, '\\x22').replace(/'/g, '\\x27')
poulets
33
<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment &quot;Mini&quot;'); return false;">edit</a>
    </body>
</html>

Devrait faire l'affaire.

kristian
la source
24

unescapeMes amis , il y a déjà la fonction en JavaScript qui fait l'échappatoire pour \":

<script type="text/javascript">
    var str="this is \"good\"";
    document.write(unescape(str))
</script>
rohtakdev
la source
2
Une combinaison de «évasion» / «unescape» a fait ce dont j'avais besoin. Merci.
Luis R.
8
escape / unescape sont déconseillés. bien que encodeURI fasse plus que de simples citations. gotochriswest.com/blog/2011/05/23/escape-unescape-deprecated
chug2k
12

Le problème est que HTML ne reconnaît pas le caractère d'échappement. Vous pouvez contourner cela en utilisant les guillemets simples pour l'attribut HTML et les guillemets doubles pour le onclick.

<a href="#" onclick='DoEdit("Preliminary Assessment \"Mini\""); return false;'>edit</a>
dl.
la source
5
Oui. Je me demandais pourquoi j'avais recouru naturellement à utiliser 'pour l'attribut dans le passé. Je n'y ai jamais plongé aussi profondément. Merci.
Matt Dawdy
6

C'est comme ça que je fais, en gros str.replace(/[\""]/g, '\\"').

var display = document.getElementById('output');
var str = 'class="whatever-foo__input" id="node-key"';
display.innerHTML = str.replace(/[\""]/g, '\\"');

//will return class=\"whatever-foo__input\" id=\"node-key\"
<span id="output"></span>

Ronnie Royston
la source
2

Si vous assemblez le HTML en Java, vous pouvez utiliser cette jolie classe d'utilitaires d'Apache commons-lang pour faire tout l'échappement correctement:

org.apache.commons.lang.StringEscapeUtils
Échappe et échappe les chaînes pour Java, Java Script, HTML, XML et SQL.

Je prends
la source
J'utilise org.apache.commons.lang3.StringEscapeUtils.escapeEcmaScript (texte) pour construire methodExpression en Java. Merci.
Harun
1

J'ai fait un exemple en utilisant jQuery

var descr = 'test"inside"outside';
$(function(){
   $("#div1").append('<a href="#" onclick="DoEdit(descr);">Click Me</a>');       
});

function DoEdit(desc)
{
    alert ( desc );
}

Et cela fonctionne dans Internet Explorer et Firefox.

rahul
la source
5
Bien sûr que oui, car vous ne le mettez pas directement dans l'attribut. Pour utiliser votre méthode, je devrais créer un tableau de chaînes JS, puis effectuer un nombre arbitraire d'affectations $ ("# divxxx") .... Moins qu'optimal, mais merci pour la suggestion.
Matt Dawdy
1

Vous pouvez copier ces deux fonctions (répertoriées ci-dessous) et les utiliser pour échapper / échapper toutes les guillemets et les caractères spéciaux. Vous n'avez pas besoin d'utiliser jQuery ou toute autre bibliothèque pour cela.

function escape(s) {
    return ('' + s)
        .replace(/\\/g, '\\\\')
        .replace(/\t/g, '\\t')
        .replace(/\n/g, '\\n')
        .replace(/\u00A0/g, '\\u00A0')
        .replace(/&/g, '\\x26')
        .replace(/'/g, '\\x27')
        .replace(/"/g, '\\x22')
        .replace(/</g, '\\x3C')
        .replace(/>/g, '\\x3E');
}

function unescape(s) {
    s = ('' + s)
       .replace(/\\x3E/g, '>')
       .replace(/\\x3C/g, '<')
       .replace(/\\x22/g, '"')
       .replace(/\\x27/g, "'")
       .replace(/\\x26/g, '&')
       .replace(/\\u00A0/g, '\u00A0')
       .replace(/\\n/g, '\n')
       .replace(/\\t/g, '\t');

    return s.replace(/\\\\/g, '\\');
}
omanosoft
la source
1

Veuillez trouver dans le code ci-dessous qui échappe les guillemets simples dans le cadre de la chaîne entrée en utilisant une expression régulière. Il valide si la chaîne entrée par l'utilisateur est séparée par des virgules et en même temps, elle échappe même aux guillemets simples entrés dans le cadre de la chaîne.

Pour échapper aux guillemets simples, entrez simplement une barre oblique inverse suivie d'une guillemet simple comme: \ ' dans le cadre de la chaîne. J'ai utilisé le validateur jQuery pour cet exemple, et vous pouvez l'utiliser selon votre convenance.

Exemples de chaînes valides:

'Bonjour'

'Bonjour le monde'

'Bonjour le monde'

'Bonjour le monde',' '

"C'est mon monde", "Je ne peux pas profiter de cela sans moi.", "Bienvenue, invité"

HTML:

<tr>
    <td>
        <label class="control-label">
            String Field:
        </label>
        <div class="inner-addon right-addon">
            <input type="text" id="stringField"
                   name="stringField"
                   class="form-control"
                   autocomplete="off"
                   data-rule-required="true"
                   data-msg-required="Cannot be blank."
                   data-rule-commaSeparatedText="true"
                   data-msg-commaSeparatedText="Invalid comma separated value(s).">
        </div>
    </td>

JavaScript:

     /**
 *
 * @param {type} param1
 * @param {type} param2
 * @param {type} param3
 */
jQuery.validator.addMethod('commaSeparatedText', function(value, element) {

    if (value.length === 0) {
        return true;
    }
    var expression = new RegExp("^((')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))(((,)|(,\\s))(')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))*$");
    return expression.test(value);
}, 'Invalid comma separated string values.');
Dinesh Lomte
la source
0

Échappez également aux espaces blancs. Il me semble que Firefox suppose trois arguments au lieu d'un. &nbsp;est le caractère d'espace insécable. Même si ce n'est pas tout le problème, ce peut être une bonne idée.

le Hampster
la source
0

Vous devez échapper aux guillemets avec des doubles barres obliques inverses.

Cela échoue (produit par json_encode de PHP ):

<script>
  var jsonString = '[{"key":"my \"value\" "}]';
  var parsedJson = JSON.parse(jsonString);
</script>

Cela marche:

<script>
  var jsonString = '[{"key":"my \\"value\\" "}]';
  var parsedJson = JSON.parse(jsonString);
</script>
Buffle
la source
0

Vous pouvez utiliser les méthodes jQuery escape () et unescape (). Comme ci-dessous,

Utilisez escape(str);pour échapper à la chaîne et récupérer à nouveau en utilisant unescape(str_esc);.

Abhiram
la source