problema con la ñ y los mb_*

Iniciado por tecasoft, 24 Febrero 2013, 19:43 PM

0 Miembros y 1 Visitante están viendo este tema.

tecasoft

aqui no me funciona el mb_'etc' deberia saltar el "echo" pero me salta "Contiene caracteres no permitidos" e estado googleando y encontrado poca informacion al respecto, podria ser del php.ini en concreto en "mbstring"¿?:


<?php
mb_internal_encoding
("UTF-8");
session_start();

if(!isset(
$_SESSION['usuario1']))
{

$usuario=$_POST['usuario'];
$pass=$_POST['contrasena'];


if (
strlen($usuario)<|| strlen($usuario)>15)
{
      echo  
"El usuario esta entre 8 y 15 caracteres<br>";      
      return 
false;
   }

if (
strlen($pass)<|| strlen($pass)>15)
{
      echo  
"La contraseña esta entre 8 y 15 caracteres<br>";      
      return 
false;
   }

//es mejor hacer una lista blanca con caracteres permitidos que una negra, lo que no este aquí simplemente se ignora
   
$validos "abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789-_@#";
   for (
$i=0$imb_strlen($usuario,'UTF-8'); $i++){
      if (
mb_strpos($validosmb_substr($usuario,$i,1,'UTF-8'),'','UTF-8')===false){
         echo  
" Contiene caracteres no permitidos<br>";
                                    return 
false;  
      }
   }
echo 
$usuario;
}
?>



esto si que funciona:


<?php
$str 
"ABCDEFGHIJKLMNÑOPQRSTUVWXYZabcdefghijklmnñopqrstuvwxyz1234567890";
 
$cad "";
for(
$i=0;$i<12;$i++) {
$cad .= mb_substr($str,rand(0,62),1,'UTF-8');
}
 
echo 
$cad;
?>

http://www.tecasoft.com Un ninja del hacking etico, programacion en html5, css3, javascript, jquery, php, python, c/c++, ensamblador, ingenieria reversa,a auditorias de seguridad, pentesting, exploits

WHK

#1
es porque estas resolviendo el string como si fuera utf8, lo mas probable es que tu archivo php esté escrito en latin-iso y por eso cuando php intenta procesar la letra ñ te da error, algo similar pasa con json_encode().

Para eso tienes varias soluciones:
1: guardar el mismo archivo php en utf-8 y volver a escribir la letra ñ.
2: utilizar utf_encode() así:
if (mb_strpos(utf8_encode($validos), mb_substr(utf8_encode($usuario),$i,1,'UTF-8'),'','UTF-8')===false){

http://php.net/utf8%20encode
Citar
utf8_encode

(PHP 4, PHP 5)

utf8_encode — Codifica una cadena ISO-8859-1 a UTF-8

string utf8_encode ( string $data )

Ésta función codifica la cadena de los data a UTF-8, y devuelve una versión codificada. UTF-8 es una mecanismo estándarusado por Unicode para la codificación de los valores de wide character dentro de una corriete del byte. UTF-8 es transparente para planear caracteres ASCII, es auto-sincronizada (significa que es posible para un programa averiguar donde empiezan los caracteres de la corriente de byte) y puede ser usada con las función de comparación normal para ordenar y otros. PHP codifica los caracteres UTF-8 sobre los cuatro bytes, así:

CitarPeter Albertsson
8 years ago
If you wish to find the byte length of a multi-byte string when you are using mbstring.func_overload 2 and UTF-8 strings, then you can use the following:

mb_strlen($utf8_string, 'latin1');

Te recomiendo la segunda porque si algien ingresa $usuario con acentos o eñes estaras en problemas, lo otro sería procesar todas las cosas en latin iso (como lo hago yo) y usar esas funciones especificas con utf8_encode() para que asi no tengas problemas con las eñes y acentos en los formularios con exploradores no muy estandarizados como internet explorer.

Ahora ojo, porque mb_* es mucho mas lento y utiliza mas memoria y procesador que las funciones normales solo por el hecho de parsear las codificaciones, te recomendaría que utilices funciones normales como strlen y ese tipo de cosas que ya procesan caracteres en su codificación nativa, si el archivo es latin iso entonces procesará caracteres en latin iso:

Citar
koala at example dot com

Just did a little benchmarking (1.000.000 times with lorem ipsum text) on the mbs functions

especially mb_strtolower and mb_strtoupper are really slow (up to 100 times slower compared to normal functions). Other functions are alike-ish, but sometimes up to 5 times slower.

just be cautious when using mb_ functions in high frequented scripts.

# test runs: 1000000
# benchmarking strlen vs. mb_strlen
# normal strlen: 3.6795361042023 ms, average: 3.6795361042023E-6 ms
# mb_strlen: 5.5934538841248 ms, average: 5.5934538841248E-6 ms
ok 1 - mb_strlen is slower than strlen
# mb_strlen is 1.52 slower than strlen
#
#
# benchmarking strpos vs. mb_strpos
# normal strpos: 5.5523281097412 ms, average: 5.5523281097412E-6 ms
# mb_strlen: 31.180974960327 ms, average: 3.1180974960327E-5 ms
ok 2 - mb_strlen is slower than strlen
# mb_strpos is 5.62 slower than strpos
#
#
# benchmarking substr vs. mb_substr
# normal substr: 3.4437320232391 ms, average: 3.4437320232391E-6 ms
# mb_strlen: 3.5374181270599 ms, average: 3.5374181270599E-6 ms
ok 3 - mb_strlen is slower than strlen
# mb_substr is 1.03 slower than substr
#
#
# benchmarking strtolower vs. mb_strtolower
# normal strtolower: 4.446839094162 ms, average: 4.446839094162E-6 ms
# mb_strlen: 193.44901108742 ms, average: 0.00019344901108742 ms
ok 4 - mb_strlen is slower than strlen
# mb_strtolower is 43.5 slower than strtolower
#
#
# benchmarking strtoupper vs. mb_strtoupper
# normal strtoupper: 3.0210740566254 ms, average: 3.0210740566254E-6 ms
# mb_strlen: 340.71775603294 ms, average: 0.00034071775603294 ms
ok 5 - mb_strlen is slower than strlen
# mb_strtoupper is 112.78 slower than strtoupper

Piensalo bien, usala solo en casos de extrema necesidad.

Recuerda establecer la codificación de carácteres en:
el archivo al momento de guardarlo
en el header de php: header('content-type: text/html charset=utf-8');
en el código html dentro de <head> en una meta tag.

Si uno de estos tres no concuerda con los otros dos entonces veras caracteres extraños a cada rato.

Para comparar si un string contiene caracteres invalidos puedes utilizar strpos(), el reemplazo de eregi():
Código (php) [Seleccionar]

<?php
$mystring 
'abc';
$findme   'a';
$pos strpos($mystring$findme);

// Nótese el uso de ===. Puesto que == simple no funcionará como se espera
// porque la posición de 'a' está en el 1° (primer) caracter.
if ($pos === false) {
    echo 
"La cadena '$findme' no fue encontrada en la cadena '$mystring'";
} else {
    echo 
"La cadena '$findme' fue encontrada en la cadena '$mystring'";
    echo 
" y existe en la posición $pos";
}
?>


Saludos.

tecasoft

no me funciona el codigo:

if (mb_strpos(utf8_encode($validos), mb_substr(utf8_encode($usuario),$i,1,'UTF-8'),'','UTF-8')===false){


he puesto esto como has marcado:

<?php
$mystring 
'abcñ';
$findme   'a';
$pos strpos($mystring$findme);
 
// Nótese el uso de ===. Puesto que == simple no funcionará como se espera
// porque la posición de 'a' está en el 1° (primer) caracter.
if ($pos === false) {
    echo 
"La cadena '$findme' no fue encontrada en la cadena '$mystring'";
} else {
    echo 
"La cadena '$findme' fue encontrada en la cadena '$mystring'";
    echo 
" y existe en la posición $pos";
}
?>



y me salta esto:


La cadena 'a' fue encontrada en la cadena 'abcñ' y existe en la posición 0


que errores tengo¿?
http://www.tecasoft.com Un ninja del hacking etico, programacion en html5, css3, javascript, jquery, php, python, c/c++, ensamblador, ingenieria reversa,a auditorias de seguridad, pentesting, exploits

1mpuls0

Verifica tu intercalación :P

utiliza htmlentities($var)

Saludos.
abc

tecasoft

#4
wenas Darhius x tu comentario, pero no respeta los campos $validos, puedo poner cualquier cosa tildes, &, etc, el "%" no me lo coje y eso es buena señal ya que tiene que ser segura la aplicacion, aya va:


<?php
session_start
();

if(!isset(
$_SESSION['usuario1']))
{

$usuario=$_POST['usuario'];
$pass=$_POST['contrasena'];


if (
strlen($usuario)<|| strlen($usuario)>15)
{
      echo  
"El usuario esta entre 8 y 15 caracteres<br>";      
      return 
false;
   }

if (
strlen($pass)<|| strlen($pass)>15)
{
      echo  
"La contraseña esta entre 8 y 15 caracteres<br>";      
      return 
false;
   }



//es mejor hacer una lista blanca con caracteres permitidos que una negra, lo que no este aquí simplemente se ignora
   
$validos "abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789-_@#";
   for (
$i=0$i<strlen($usuario); $i++){
   
if (strpos(htmlentities($validos),substr(htmlentities($usuario),$i,1)) === false){
         echo  
"Contiene caracteres no permitidos<br>";
                                    return 
false;  
      }

   }
echo 
$usuario;
}
?>



veo vulnerabilidades x todos los lados. Que hago con htmlentities¿¿? tienes mas soluciones xk yo no las encuentro x ningun lao¿?
http://www.tecasoft.com Un ninja del hacking etico, programacion en html5, css3, javascript, jquery, php, python, c/c++, ensamblador, ingenieria reversa,a auditorias de seguridad, pentesting, exploits

tecasoft

gracias Darhius x tus consejos lleguemos hasta el final  ;-)


<?php
session_start
();

if(!isset(
$_SESSION['usuario1']))
{

$usuario=$_POST['usuario'];
$pass=$_POST['contrasena'];


if (
strlen($usuario)<|| strlen($usuario)>15)
{
      echo  
"El usuario esta entre 8 y 15 caracteres<br>";      
      return 
false;
   }

if (
strlen($pass)<|| strlen($pass)>15)
{
      echo  
"La contraseña esta entre 8 y 15 caracteres<br>";      
      return 
false;
   }



//es mejor hacer una lista blanca con caracteres permitidos que una negra, lo que no este aquí simplemente se ignora
   
$validos "abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZ0123456789-_@#";
   for (
$i=0$i<strlen($usuario); $i++){
   
if (strpos(utf8_decode($validos),substr($usuario,$i,1)) === false){    
         echo  
"Contiene caracteres no permitidos<br>";
                                    return 
false;  
   
 }
}
echo 
$usuario;
}
?>


SOLUCIONADO SI VEIS ALGUN ERROR COMENTAR GRACIAS
http://www.tecasoft.com Un ninja del hacking etico, programacion en html5, css3, javascript, jquery, php, python, c/c++, ensamblador, ingenieria reversa,a auditorias de seguridad, pentesting, exploits