2009-04-15 22 views
12

Tengo una aplicación donde los usuarios ingresan texto en formularios.¿Cómo desinfectar la entrada del usuario para una codificación adecuada del contenido antes de guardarlo?

Los datos se guardan en una base de datos MySQL (intercalación: utf8_general_ci) y luego salen como XML (codificación: UTF-8).

El problema es que las personas tienden a cortar y pegar su información de otras fuentes, por ejemplo, documentos de Microsoft Word o archivos PDF, por ejemplo.

Este texto de entrada tiene a menudo personajes que son incorrectos para la codificación de salida, cosas como "comillas inteligentes", que provienen de un documento en Windows-1252 encoding

Esto causa problemas, obviamente, cuando se transforman o de otra manera trabajan en el XML porque los personajes son ilegales

Por lo tanto, la forma de desinfectar la entrada?

Anteriormente, he usado algunos métodos de fuerza bruta, como el "de-moronize" script, que consiste en una larga lista de operaciones de búsqueda y reemplazo.

¿Sigue siendo la mejor manera de hacerlo? ¿Hay alguna otra manera?

¿Puedo simplemente configurar el formulario accept-charset attribute y hacer que el navegador lo haga por mí?

En caso afirmativo, ¿qué navegadores harán eso y es probable que haya algún problema?

Además, ¿cómo es que mi base de datos está aceptando estos caracteres, que son caracteres reservados/de control en UTF-8?

Como se puede ver, sé lo suficiente sobre codificaciones saber que tengo un problema, pero ahora estoy un poco fuera de mi ...

TIA

Respuesta

9

Este texto de entrada tiene a menudo personajes que son incorrectos para la codificación de salida, cosas como "comillas inteligentes", que provienen de un documento en Windows- 1252 de codificación

“comillas inteligentes” (bytes 147 y 148 en CP1252) son perfectamente caracteres Unicode válidos, U + 201C y U + 201D. Su aplicación debe ser capaz de manejarlos sin problemas; si no, estás haciendo algo mal y muy probablemente todos los caracteres que no sean ASCII fallarán.

Independientemente de si los caracteres provienen de alguien que los escribe o alguien que los pega de Word, el navegador debe enviar caracteres codificados en UTF-8 a su aplicación, que debe almacenar los mismos bytes UTF-8 en la base de datos .

Si el navegador no se envía en UTF-8, es posible que no establezca el juego de caracteres de la página HTML que contiene el formulario.Esto se puede hacer mediante el:

Content-Type: text/html;charset=utf-8 

cabecera HTTP y/o el:

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 

elemento en < head>.

¿Puedo simplemente establecer el atributo accept-charset en el formulario y hacer que el navegador lo haga por mí?

No, aceptar-charset es básicamente inútil gracias a IE, que malinterpreta que signifique “intente utilizar este conjunto de caracteres, si el de la página no puede codificar los caracteres que queremos”, en lugar de “utilizar siempre este juego de caracteres ". Esto significa que si usa accept-charset puede terminar con una mezcla de codificaciones enviadas a la vez, sin forma de averiguar cuál es cuál. ¡Bonito!

¿por qué mi base de datos está aceptando estos caracteres, que son caracteres reservados/de control en UTF-8?

En MySQL UTF-8 es solo una recopilación, que se utiliza para comparar y ordenar. Todavía está almacenando los datos como bytes y realmente no le importa si no son secuencias UTF-8 válidas.

Es una buena idea decodificar y verificar las secuencias entrantes UTF-8 en su aplicación de todos modos, porque "secuencias cortas", inválidas en Unicode moderno, pueden ocultar un carácter '<' que aún será reconocido por navegadores antiguos (en menos IE6 pre-SP2, Opera 7).

ETA:

Así, entré en una cadena que contiene el byte 146

No, ha introducido un carácter Unicode U + 201B. El navegador trata con caracteres Unicode, no con bytes, hasta el momento en que debe enviar el formulario serializado al servidor. Es entonces cuando decide cómo convertir los caracteres en bytes, y si la página se maneja como UTF-8, siempre elegirá UTF-8.

(Si no es UTF-8, los navegadores tienden a hacer trampa de una manera que no cumple con los estándares: para todos los caracteres que no caben en la codificación, los codificará referencias de caracteres HTML como '& # 8217; '. Esto es incorrecto porque ahora no se puede distinguir entre un' escapado 'del navegador' & 'y un' & 'real, escrito por el usuario, y es insidiosamente incorrecto porque si luego se hace eco de la referencia como HTML no guardado parece que estás haciendo bien, que de hecho se acaba de hacer un agujero de seguridad grande y viejo.)

entró en la base de datos 146

Realmente, un byte '\ x92', no '\ xC2 \ x92', '\ xE2 \ x80 \ x99' o '& # 146;'?

que salió cuando produje el XML (codificado en UTF-8), 146. No hay quejas de que el navegador

Entonces no salió como una sola 146 bytes. Un navegador se quejará cuando se le presente un '\ x92' desnudo en un archivo XML.(No es un archivo HTML, en el que las secuencias UTF-8 no válidas salen como un glifo de caracteres perdidos.)

Sospecho que está saliendo como una referencia de caracteres '& # 146;' que está bien formada (aunque el carácter U + 0092 es parte del conjunto de control C1, por lo tanto no se representará como algo útil). Si esto es lo que está sucediendo, la página de su formulario no está siendo recogida como UTF-8 después de todo, y usted está sufriendo el problema de presentación automática de escaneo del navegador descrito anteriormente.

+0

OK "los bytes 147 y 148 son caracteres Unicode perfectamente válidos, U + 201C y U + 201D" es la parte que no obtengo. El navegador no puede * saber * la codificación de la prueba pegada. ¿Cómo sabe que son cotizaciones inteligentes CP1252? ¡Seguramente son solo bytes! ¿O es el uso de 147-148 tan inusual que es seguro suponer eso? – AmbroseChapel

+0

El navegador no trata con bytes, se trata de caracteres Unicode. Pega caracteres Unicode U + 201C (et al) en un área de texto; el navegador no sabe ni le importa cómo se almacenaron en la aplicación que los copió (lo que probablemente fue Unicode). – bobince

+0

Podría estar * enviando * bytes 147/148, pero eso sería porque cree que la codificación de la página que contiene el formulario era cp1252 y, por lo tanto, la codificación que su formulario quiere obtener es cp1252. Si no le dice lo contrario, puede usar cp1252 (u otras páginas de códigos del sistema en otros países). – bobince

2

Usted puede tratar el Perl Encode módulo. Admite la conversión entre varios conjuntos de caracteres, incluido UTF-8 de couse. Acabo de comprobar mi instalación de Perl y también admite "cp1252", que es solo otro nombre para Windows-1252 según Wikipedia. Puede comprobar su propia instalación con el siguiente chiste:

perl -MEncode -e 'print map {"$_\n"} Encode->encodings(":all");' 
+0

Saludos. He hecho eso y estoy listo para irme. – AmbroseChapel

1

"¿Puedo simplemente configurar el atributo accept-charset en el formulario y hacer que el navegador lo haga por mí?"

Solo si está preparado para confiar en "el navegador", eso podría ser adecuado en algunas aplicaciones, pero en general se está dejando abierto para hacer travesuras (o cosas peores).

(ver también las advertencias de bobince sobre IE ...)

Iain

Cuestiones relacionadas