instead - Cómo reemplazar/escapar los caracteres U+2028 o U+2029 en PHP para detener la ruptura de la API JSONP
jsonp php (2)
Puede reemplazar U+2028
, U+2029
con "/u2028"
, "/u2029"
en el lado de PHP o en el lado de JavaScript, o en ambos, no importa mientras ocurra al menos una vez (es idempotente) .
Puedes usar funciones de reemplazo de cadena ordinarias. No necesitan ser "seguros para múltiples bytes", y puede hacerlo con la misma facilidad en cualquier codificación Unicode (UTF-8, UTF-16, UTF-32 están igualmente bien). PHP no tenía secuencias de escape de Unicode la última vez que verifiqué, lo cual es solo una razón más por la que PHP es una broma, pero puedes usar /x
escape con UTF-8 ...
(En resumen, la razón por la que no hay una función de reemplazo de cadena multibyte es porque sería redundante, sería exactamente lo mismo que una función de reemplazo de cadena no multibyte).
// Javascript
data = data.replace("/u2028", "//u2028").replace("/u2029", "//u2029");
// PHP
$data = str_replace("/xe2/x80/xa8", ''//u2028'', $data);
$data = str_replace("/xe2/x80/xa9", ''//u2029'', $data);
O simplemente no puede hacer nada, ya que PHP escapa de los caracteres no Unicode por defecto en json_encode()
:
// Safe
echo json_encode("/xe2/x80/xa9");
--> "/u2029"
// Correct JSON, but invalid Javascript...
// (Well, technically, JSON root must be array or object)
echo json_encode("/xe2/x80/xa9", JSON_UNESCAPED_UNICODE);
--> "
"
Ok, estoy ejecutando una API JSONP pública en la que los datos se sirven desde mi servidor PHP. Acabo de leer este artículo:
- JSON: el subconjunto de JavaScript que no lo es (por Magnus Holm; mayo de 2011)
(por favor lea para aclaración)
Básicamente, si mis cadenas JSON contienen un carácter U + 2028 (separador de línea Unicode) o un carácter U + 2029 (separador de párrafo Unicode), entonces este JSON es perfectamente válido. Sin embargo, al usar JSONP, el JSON se ejecuta como JavaScript y ninguna cadena en JavaScript puede contener un U + 2028 literal o un U + 2029 ya que romperá el JavaScript. Aparentemente, esto no suele ser un problema siempre que utilice un analizador JSON adecuado, pero en el caso de JSONP, el navegador es el analizador JSON.
Esencialmente, si estos caracteres estuvieran dentro de las cadenas en los datos de JSONP que se envían al cliente, esto generaría un salto de línea o párrafo en la cadena que rompería el JavaScript y detendría su ejecución. Esta es una posibilidad ya que la API está devolviendo algunos datos ingresados por el cliente. Alguien podría potencialmente ingresar un U + 2028 o un U + 2029 en la base de datos, de modo que cuando lo devuelva como JSONP, romperá cualquier implementación usando mi API.
Entonces, mi pregunta es, en PHP, ¿cómo puedo desinfectar / eliminar los datos JSON para eliminar o eliminar los caracteres U + 2028 y U + 2029 antes de enviarlos al cliente?
Actualmente, mi proceso consiste en hacer un json_encode en una matriz de datos y enviar esos datos al cliente. ¿Debo escapar de los datos haciendo un bucle a través de la matriz y filtrarlos, o escapar de toda la cadena codificada JSON a la vez?
La otra cosa es que no estoy seguro de cómo escapar de los caracteres U + 2028 y U + 2029 en PHP de todos modos. ¿Puedo hacer un str_replace? No estoy seguro de si str_replace es multibyte seguro y no hay una función mb_str_replace a menos que use alguna personalizada. Entonces, ¿cómo eliminar / escapar esos caracteres Unicode?
Muchas gracias.
Vale la pena señalar que esto ya no es necesario.
De forma predeterminada, json_encode codifica todos los caracteres que no son ASCII (incluidos U + 2028 y U + 2029), y también escapa de la barra diagonal, aunque no es necesario que la especificación JSON escape. No hace daño escapar de él, y puede ser más seguro en ciertos contextos. Por lo tanto, de forma predeterminada, estos caracteres se escapan de todos modos.
La constante JSON_UNESCAPED_UNICODE
genera Unicode sin escape, que puede guardar bytes. Sin embargo, al igual que el carácter de barra diagonal se escapa porque puede ser peligroso en algunos contextos, también se escapa U + 2028 y U + 2029, porque también son peligrosos en algunos contextos. Este no fue el caso en el momento en que hizo su pregunta: esta función se agregó a PHP más recientemente .
(Estos escapes adicionales se pueden desactivar con JSON_UNESCAPED_SLASHES
y JSON_UNESCAPED_LINE_TERMINATORS
, respectivamente.)