Foro de elhacker.net

Programación => PHP => Mensaje iniciado por: Alex_bro en 31 Marzo 2015, 22:12 pm



Título: [Resuelto] Caracteres especiales preg_replace
Publicado por: Alex_bro en 31 Marzo 2015, 22:12 pm
Buenas a todos :)

Vereis tengo un problemilla con un filtro que utiliza preg_replace. Hace años inserté como válidos unos caracteres un tanto estraños y como no me acuerdo de por qué lo hice, hoy los he borrado. El caso es que al borrarlos y no pasarlos como válidos, preg_replace devuelve una cadena vacía.

Los caracteres en cuestión son estos:
Citar
ЯяАИМСЗаимсз

Cuando están incluidos dentro de la variable a pasar por preg_replace, devuelve una cadena vacía, en lugar de solo borrarlos y devolver los permitidos, como quiero aquí:
Código
  1. $var = preg_replace("/[^a-zA-Z0-9]/i",'',$var);

Supongo que será alguna forma rara de escribir unas comillas o algo así.

Alguien sabe de que se trata?

Saludos!

Edito:
Buscando mucho por internet, veo que esos caracteres son las vocales acentuadas, que por el formato del archivo se guardarían así en su momento, pero aun no entiendo por qué si se pasan tal cual a la función preg_replace hace que no cumpla con la regla que tiene y devuelve un string vacío. He activado los errores por si decía algo, pero nada.


Título: Re: Caracteres especiales preg_replace
Publicado por: MinusFour en 1 Abril 2015, 14:24 pm
No parece ser error de esa funcion:

http://codepad.viper-7.com/BM5TDw


Título: Re: Caracteres especiales preg_replace
Publicado por: Alex_bro en 2 Abril 2015, 16:29 pm
Amigo gracias por dedicarle tiempo a testearlo y demás.

Tienes razón, el fallo debe estar en otro sitio, ya que como bien muestras la función parece que no tiene problemas. Al principio pensé que seria problema de MySQL por no soportar esos carácteres, y efectivamente lanza un error:
Citar
Warning: #1366 Incorrect string value: '\xD0\xAF\xD1\x8F\xD0\x90...'

Pero luego los guarda como "????????" y no borra lo que le rodea.

Voy a seguir viendo que ocurre por cada función que utiliza esa cadena de entrada y os cuento si veo donde se tropieza.

Muchas gracias de nuevo :)

Edito:
El problema me surge cuando meto en la expresión regular los acentos y demás:
Código:
echo preg_replace('/[^a-zA-Z0-9ñÑáéíóúÁÉÍÓÚ]/i','','TextoЯяАИМСЗаимсзTexto');
Devuelve:
Citar
Texto��Texto

Hay que hacer eso de otra forma?
PD: Siento no poner la etiqueta de PHP al código, si la pongo no se ven los carácteres.


Título: Re: Caracteres especiales preg_replace
Publicado por: MinusFour en 3 Abril 2015, 00:18 am
¿Me imagino que esto es UTF-8 o estamos hablando de Windows 1252?

Esta es mi teoria de lo que pasa cuando agregas caracteres multi-bytes en preg_replace:

Primero, equivalencias hexadecimales. Vocales acentuadas:
Código:
ñ     Ñ     á     é     í     ó     ú     Á     É     Í     Ó     Ú
C3 B1 C3 91 C3 A1 C3 A9 C3 AD C3 B3 C3 BA C3 81 C3 89 C3 8D C3 93 C3 9A

Los otros caracteres:

Código:
Я     я     А     И     М     СЗ    а     и     м     с     з
D1 8F D0 90 D0 98 D0 9C D0 A1 D0 97 D0 B0 D0 B8 D0 BC D1 81 D0 B7

Ahora esencialmente lo que preg_replace debe estar haciendo es remplazar cualquier caracter que no sean de las vocales acentuadas (o las eñies) por nada (''). El problema viene siendo que:

Código:
Á
C3 81
y

Código:
с
D1 81

Nota que los dos comparten un byte. Entonces al hacer la substitucion ese byte se conserva o en otras palabras, el otro byte se remplaza (porque esta substituyendo todos los caracteres en el grupo que no coincidan).

Ocurre lo mismo con á y М:

Código:
C3 A1
D0 A1

Posible solucion:

Código:
echo preg_replace('/[^a-zA-Z0-9ñÑáéíóúÁÉÍÓÚ]/iu','','TextoЯяАИМСЗаимсзTexto');

Antes:
http://codepad.viper-7.com/21Pxvv

Despues:
http://codepad.viper-7.com/g5znmO

Puedes saber mas acerca del modificador 'u' aqui:

http://php.net/manual/en/reference.pcre.pattern.modifiers.php


Título: Re: Caracteres especiales preg_replace
Publicado por: Alex_bro en 3 Abril 2015, 02:08 am
Gracias por explicarlo de forma tan sencilla :D

He añadido el modificador 'u' y ya funciona a la perfección en mi aplicación, pero lo mas importante, es que gracias a ti he entendido lo que ocurría, y ya lo sé para la siguiente. Nunca me he llevado bien con las codificaciones.

Gracias de nuevo por dedicarle tanto tiempo a este tema, te debo una!