Como nota, antes de decir algo sobre este problema: por favor considere avanzar hacia MySQLi o PDO con consultas parametrizadas. No solo son una orden o magnitud más seguras, sino que son más fáciles de trabajar y son totalmente compatibles. Las antiguas funciones de mysql_
ahora se consideran al final de la vida útil y pronto quedarán en desuso. (lo siento, perdí el pequeño i
de tu publicación original ... ¡malditas llamadas de procedimiento!)
MySQL opera en cadenas. Las cadenas son dos cosas: una secuencia de bytes y una secuencia de caracteres. La forma en que estas dos secuencias se asignan entre sí se denomina conjunto de caracteres, que se especifica mediante una codificación.
Por ejemplo, ASCII asigna letras, números, símbolos y caracteres de control a los valores de byte 0 a 127. ASCII extendido luego agrega más caracteres para los valores 128 a 255. Otras codificaciones, como la familia UTF (por ejemplo, UTF- 8) utiliza bytes únicos o múltiples para codificar diferentes caracteres. Por ejemplo, los caracteres UTF-16 pueden codificarse como uno o dos puntos de código de 2 bytes (es decir, cada carácter está codificado como 2 o 4 bytes).
La parte interesante sucede cuando se asume un conjunto de caracteres o codificación, pero los datos subyacentes en realidad se codifican de manera diferente. Por ejemplo, el carácter CJK de Asia oriental para "agua" es, que se define en UTF-16 como U + 6C34. Esto codifica a 34 6C
en UTF-16LE. Ahora, si asumimos accidentalmente que los datos que recibimos son ASCII, los descodificaremos como "4l" en lugar del carácter Unicode adecuado.
Ahora, ¿qué pasaría si su aplicación de front-end (en este caso PHP) estuviera configurada para usar ASCII extendido, pero la intercalación de su base de datos se configuró en UTF-8 (por ejemplo, utf8_general_ci), y la máquina de su usuario se configuró para usar Windows CP1251 página de códigos cirílicos? En un mundo ideal, cada sistema reconocería los requisitos de la aplicación de destino y los convertiría adecuadamente. Desafortunadamente este no es un mundo ideal. Los bytes subyacentes que representan los caracteres cirílicos probablemente se confundirán con los caracteres ASCII en su camino hacia la aplicación web de PHP. Entonces, cualquier carácter alto (128-255) puede volver a asignarse a diferentes secuencias de bytes cuando los caracteres ASCII se convierten en UTF-8, o incluso pueden formar caracteres completamente nuevos si se traducen accidentalmente ingenuamente en puntos de código UTF-8. En algunos casos, hay reglas especiales que hacen que ciertos puntos de código secuenciales (por ejemplo, marcas diacríticas) se combinen en caracteres de forma especial.
En resumen: la codificación de caracteres es vudú . Esto es serio "aquí hay dragones" territorio. Si puedes obtener una respuesta sensata de cualquiera que haya escrito antes una biblioteca de cadenas real (normalmente solo garabatean "cthulhu ebcdic fhtagn" en tu cara con un marcador mágico y se alejan misteriosamente), entonces Probablemente te diga algunas cosas realmente repugnantes sobre la abominación que es nuestro lenguaje humano.
¿Por qué esto importa para cosas como mysql_escape_string
? Bueno, digamos que su aplicación PHP está en modo UTF-8, pero su servidor MySQL se está ejecutando en modo ASCII. Su usuario escribe un carácter ∻ ( U + 223B ) y su función de escape dice "bueno, shucks, me parece bien, simplemente preocuparse por las citas y esas cosas ". Su servidor MySQL mira esos bytes subyacentes ... oh, resulta que 22 3B
es una codificación de ";
en ASCII. Whoops!
Esto empeora cuando recuerdas esos trucos de combinación. Puede hacer cosas como aplicar un signo diacrítico a una puntuación, o abofetear esa puntuación en medio de algún texto en árabe, y podría combinarse en un carácter de "forma combinada" con un punto de código totalmente diferente cuando se vuelva a codificar . Esto es importante cuando se utilizan diferentes formatos de codificación modernos, como UTF-8 y UTF-16 juntos.
La función mysql_real_escape_string
intenta salvarnos de este infierno al verificar correctamente la cadena una vez que se ha recodificado en la codificación seleccionada del servidor MySQL de destino. Necesita una referencia a la conexión para recuperar estos metadatos del servidor.
La cosa más misericordiosa del mundo, creo, es la incapacidad de la mente humana para comprender las codificaciones de caracteres. Vivimos en una plácida isla de ignorancia en medio de los mares negros de puntos de código, y no estaba destinado a viajar lejos. Las lenguas, cada una de las cuales se esfuerza en su propia dirección, hasta ahora nos han perjudicado poco; pero algún día la unión de planos disociados de Unicode abrirá tales excentricidades terroríficas del lenguaje, y de nuestra posición aterradora en el mismo, que segregaremos de la revelación o huiremos de la luz a la paz y la seguridad de EBCDIC. >