Confidare Weblog

Archive for February, 2009

PHP: Locales + PCRE = ¡Kabum!

por jcataldo el Feb.17, 2009, bajo Informática, Ingeniería de Software, PHP

En principio, es buena la idea de los patrones \w y \W en las expresiones regulares PCRE de PHP. Según la documentación, el patrón \w debe calzar con cualquier carácter de “palabra” (esto es, letras, dígitos y la barra inferior “_”), considerando el locale actual. Cito:

Un caracter de “palabra” es cualquier letra o dígito, o el caracter de subrayado, esto quiere decir, cualquier caracter que pueda ser parte de una “palabra” en Perl. La definición de letras y dígitos es controlada por las tablas de caracteres de PCRE, y puede variar si se están efectuando coincidencias específicas a localidades. Por ejemplo, en la localidad “fr” (Francia), algunos códigos de caracteres mayores a 128 son usados para letras con acentos, y éstas coinciden con \w.

Esta última característica haría que, por ejemplo, la función preg_replace fuera idónea para sanitizar datos ingresados por el usuario; por ejemplo, podríamos reemplazar fácilmente cualquier carácter “extraño” por un espacio mediante un simple:

preg_replace(’/\W/’, ‘ ‘, $q)

La gracia sería que no reemplazara los caracteres acentuados, ni a nuestra querida letra “Ñ”. Según la documentación, todo lo que habría que hacer para lograrlo es asegurarse de que el locale esté ajustado al valor correcto. Sin embargo, miren este caso de prueba:

< ?php
echo setlocale(LC_ALL, ‘es_CL.UTF-8′) . “\n”;
echo preg_replace(’/\W/u’, ‘ ‘, ‘año’) . “\n”;

La salida es:

$ php -f test.php
es_CL.UTF-8
a o

De manera que la “ñ” no es considerada un carácter de “palabra”. ¡Bien, PHP! En devnetwork.net un tipo llegó a probar todo el juego ASCII para finalmente concluir de que el locale es ignorado por las funciones PCRE de PHP.

Ah, por supuesto. ¿Tiene que haber otra manera de lograrlo, no? Claro que no es tan elegante:

preg_replace(’/[^A-Za-z0-9áéíóúÁÉÍÓÚñÑ_]/’, ‘ ‘, $q);

En tardes como ésta puedo llegar a entender a los php-haters.

Actualización: Gracias a Roberto dimos con una mejor alternativa para evitar este “bug”. Mira en los comentarios para más detalles.

2 comentarios más...

Mañoso, mañoso manejo de “culture” en Symfony

por jcataldo el Feb.16, 2009, bajo Informática, Ingeniería de Software, PHP, Symfony

Nada más quería advertir a quienes pasen por aquí que acabo de perder media hora tratando de descubrir por qué el lenguaje del calendario dynarch de la aplicación Symfony en que estoy trabajando volvió a cambiarse de español a inglés, con los consiguientes errores a la hora de almacenar las fechas en la base de datos (por el formato).

Resulta que, por alguna razón (ahí está el misterio), —y a pesar de que mi default_culture está en “es” en el archivo settings.yml— a la hora de incluir los archivos JS del calendario Symfony se encontraba con que la “cultura” del usuario era “en” en lugar de “es”. Después de varios cabezazos y por pura prueba y error, descubrí que el problema residía en la sesión. En la sesión simplemente la cultura había quedado como “en”.

Así que, bastó con borrar las cookies involucradas (gracias a San Web Developer Toolbar) para resolver el problema.

¿Cómo llegó a meterse esa cookie venenosa ahí? Ahora que lo pienso, a la otra aplicación en la que estoy trabajando no le he configurado aún el default_culture, de manera que de ahí debe venir la contaminación. Increíblemente, la reflexión que tuve que hacer para escribir este post me ayudó a encontrar la raíz del problema. ¡Gracias por su ayuda!

1 comentario más...