Citas de escape en JavaScript

211

Estoy generando valores de una base de datos (en realidad no está abierto a la entrada pública, pero está abierto a la entrada de un usuario de la empresa, lo que significa que no estoy preocupado por XSS ).

Estoy tratando de generar una etiqueta como esta:

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

DESCRIPTION es en realidad un valor de la base de datos que es algo como esto:

Prelim Assess "Mini" Report

He intentado reemplazar "con \", pero no importa lo que intente, Firefox sigue cortando mi llamada de JavaScript después del espacio después de la palabra Evaluar , y está causando todo tipo de problemas.

Debo perder la respuesta obvia, pero por mi vida no puedo entenderlo.

¿A alguien le interesa señalar mi idiotez?

Aquí está la página HTML completa ( eventualmente será una página ASP.NET , pero para resolver esto eliminé todo lo demás excepto el código del problema)

<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;">edit</a>
    </body>
</html>
Matt Dawdy
fuente
3
Es una buena idea hacer que el onclickarchivo adjunto de su evento sea discreto y mover toda la información de su base de datos a una isla de datos. Las cosas estarán más limpias y en realidad obtendrás algún tipo de error de sintaxis cuando tus cadenas se escapen mal.
Justin Johnson el
También puede usar los métodos jquery escape ("string") y unescape ("string")
Abhiram

Respuestas:

212

Debe escapar de la cadena en la que está escribiendo DoEditpara eliminar los caracteres de comillas dobles. Están causando que el onclickatributo HTML se cierre prematuramente.

El uso del carácter de escape JavaScript \no es suficiente en el contexto HTML. Es necesario sustituir el doble cita con la representación XML de entidad adecuada, &quot;.

Aaron
fuente
Bien, pero ¿no sería eso? <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;"> edit </a> Lo intenté, y todavía está jodiendo. Esto tiene que ser un simple WTF pero por mi vida, no puedo verlo.
Matt Dawdy
¿Hay alguna función de JavaScript incorporada que pueda escapar de las comillas dobles? Aparte de 'quo "'. Replace ('"', '& quot;') no puedo encontrar nada.
Kevin
44
No es un problema de JavaScript, es un problema de codificación HTML / XML: no puede tener caracteres de comillas dobles dentro de un valor de atributos sin escapar de ellos ... de lo contrario, los navegadores / analizadores piensan que está terminando la declaración del valor del atributo.
Aaron
22
ejemplo de código de reemplazo:'mystring'.replace(/"/g, '&quot;');
Joshua Burns
3
En el comentario anterior hay una cita extra. El código que funciona es 'mystring'.replace (/' / g, '& quot;');
Agustín López
95

&quot; funcionaría en este caso particular, como sugerí antes de mí, debido al contexto HTML.

Sin embargo, si desea que su código JavaScript se escape independientemente para cualquier contexto, puede optar por la codificación nativa de JavaScript:
'se \x27
"convierte en\x22

Entonces su onclick se convertiría en:
DoEdit('Preliminary Assessment \x22Mini\x22');

Esto funcionaría, por ejemplo, también cuando se pasa una cadena de JavaScript como parámetro a otro método de JavaScript ( alert()es un método de prueba fácil para esto).

Me refiero a la pregunta duplicada de desbordamiento de pila, ¿cómo puedo escapar de una cadena dentro del código JavaScript dentro de un controlador onClick? .

tsemer
fuente
2
¡Gracias! La suya es la respuesta más correcta porque es JavaScript nativo independientemente del contexto.
scarver2
2
Esta es la respuesta correcta, aunque en un contexto HTML usando &quot;will, por supuesto, funcionará.
Oliver
Tenga en cuenta que &quot;se requiere en los valores de entrada, es decir, <input value="\x22quoted string\x22">no funcionará.
Thdoan
@ 10basetom, naturalmente, el escape de JavaScript solo funciona en un contexto de JavaScript, como los controladores de eventos ( onclick="..."). El valor de un valueatributo no se procesa dentro de un contexto JavaScript, solo dentro de un contexto HTML.
tsemer
código de reemplazo:'mystring'.replace(/"/g, '\\x22').replace(/'/g, '\\x27')
pollos
33
<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment &quot;Mini&quot;'); return false;">edit</a>
    </body>
</html>

Debería hacer el truco.

Kristian
fuente
24

Amigos, ya existe la unescapefunción en JavaScript que hace el escape para \":

<script type="text/javascript">
    var str="this is \"good\"";
    document.write(unescape(str))
</script>
rohtakdev
fuente
2
Una combinación de "escape" / "unescape" hizo lo que necesitaba. Gracias.
Luis R.
8
escape / unescape están en desuso. aunque encodeURI hace más que solo citas. gotochriswest.com/blog/2011/05/23/escape-unescape-deprecated
chug2k
12

El problema es que HTML no reconoce el carácter de escape. Podría solucionarlo utilizando las comillas simples para el atributo HTML y las comillas dobles para el onclick.

<a href="#" onclick='DoEdit("Preliminary Assessment \"Mini\""); return false;'>edit</a>
dl.
fuente
55
Yikes Me preguntaba por qué naturalmente recurrí al uso 'para el atributo en el pasado. Simplemente nunca profundicé en eso tan profundamente. Gracias.
Matt Dawdy
6

Así es como lo hago, básicamente 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
fuente
2

Si está ensamblando el HTML en Java, puede usar esta buena clase de utilidad de Apache commons-lang para hacer todo el escape correctamente:

org.apache.commons.lang.StringEscapeUtils
Escapes y unescapes Cadenas para Java, Java Script, HTML, XML y SQL.

tomo
fuente
Utilizo org.apache.commons.lang3.StringEscapeUtils.escapeEcmaScript (texto) para construir methodExpression en Java. Gracias.
Harun
1

He hecho una muestra usando jQuery

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

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

Y esto funciona en Internet Explorer y Firefox.

rahul
fuente
55
Por supuesto que sí, porque no lo está poniendo directamente en el atributo. Para usar su método, tendría que crear una matriz de cadenas JS, luego hacer un número arbitrario de $ ("# divxxx") ... asignaciones. Menos que óptimo, pero gracias por la sugerencia.
Matt Dawdy
1

Puede copiar esas dos funciones (enumeradas a continuación) y utilizarlas para escapar / no escapar de todas las comillas y caracteres especiales. No tiene que usar jQuery ni ninguna otra biblioteca para esto.

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
fuente
1

Busque en el siguiente código que escapa a las comillas simples como parte de la cadena ingresada utilizando una expresión regular. Valida si la cadena ingresada por el usuario está separada por comas y, al mismo tiempo, incluso escapa a las comillas simples ingresadas como parte de la cadena.

Para escapar de las comillas simples, solo ingrese una barra invertida seguida de una comilla simple como: \ ' como parte de la cadena. Usé el validador jQuery para este ejemplo, y puedes usarlo según tu conveniencia.

Ejemplos de cadenas válidas:

'Hola'

'Hola Mundo'

'Hola Mundo'

'Hola Mundo',' '

'Es mi mundo', 'No puedo disfrutar esto sin mí', 'Bienvenido, Invitado'

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
fuente
0

Escapar de espacios en blanco también. Me parece que Firefox está asumiendo tres argumentos en lugar de uno. &nbsp;es el personaje espacial que no se rompe. Incluso si no es todo el problema, puede ser una buena idea.

el hámster
fuente
0

Necesita escapar de las comillas con barras diagonales inversas dobles.

Esto falla (producido por json_encode de PHP ):

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

Esto funciona:

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

Puede usar los métodos jQuery escape () y unescape (). Como abajo,

Use escape(str);para escapar de la cadena y recuperarse nuevamente usando unescape(str_esc);.

Abhiram
fuente