views:

47

answers:

1

So I'm sending data to my MySQL database through a HTML form.

When I send a word with special characters like "ñ" or accents "á, é, í.." and when I check the result in the tables those characters are displayed as "ã±".

I tried pretty much everything:

my html form page header has

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

The form accepts UTF-8 with <form accept-charset="UTF-8">

I also added to my action php script:

mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET'utf8'");

Then I tried htmlentities

but all the "ñ" were displayed as &atilde;&

My database, tables, and fields are set in utf8_general_ci, also tried utf8_spanish_ci but nothing changed.

I don't know what else to do, is there anything else I am missing here?

This is the PHP script I'am using:

<?php
// Make a MySQL Connection
$con = mysql_connect("I DELETED THIS");
if (!$con)
{
die('No se pudo conectar a la BD: ' . mysql_error() );
}

mysql_select_db("ldma", $con);

$nombre  = ''; 
$ape1   = ''; 
$ape2   = ''; 
$apodo = ''; 
$errmsg = '';

if ($_POST['enviado']==1)
{
   $nombre   = $_POST['nombre'];
   $ape1   = $_POST['ape1'];
   $ape2 = $_POST['ape2'];
   $apodo = $_POST['apodo'];

   $permitidos = "abcdefghijklmnopqrstuvwxyzÁÉÍÓÚÜüáéíóúñÑABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
   for ($i=0; $i<strlen($nombre); $i++)
   { 
      if (strpos($permitidos, substr($nombre,$i,1))===false)
      {$errmsg = 1; }
         else
         {$errmsg = '';} 


   } 

    /*if (ereg('^[ a-zA-Zñ]+$', $nombre)) 
        {$errmsg = '';
        } 
        else 
        {$errmsg = 1;
        }*/


    if(strlen($nombre) == 0 || strlen($nombre) <= 3) 
    {$errmsg = 1;} 
        else if (strlen($nombre) > 20) 
            {$errmsg = 1;} 

    if(strlen($ape1) == 0 || strlen($ape1) <= 3) 
    {$errmsg = 1;} 
        else if (strlen($ape1) > 15) 
            {$errmsg = 1;} 

    if(strlen($ape2) == 0 || strlen($ape2) <= 3) 
    {$errmsg = 1;} 
        else if (strlen($ape2) > 15) 
            {$errmsg = 1;} 

    if(strlen($apodo) > 15)
    {$errmsg = 1;} 



    if($errmsg == '')
    {

    // Insert a row of information into the table "example"

    $arr = array("nombre", "ape1", "ape2", "apodo"); 
    foreach ($arr as $field)
    {
        $_POST["$field"] = utf8_encode($_POST["$field"]);
        $_POST["$field"] = strtolower($_POST["$field"]);
        $_POST["$field"] = ucwords($_POST["$field"]);
    }

    $sql= "INSERT INTO `ldma`.`maestros` (nombre, ape1, ape2, apodo) 
            VALUES ('$_POST[nombre]', '$_POST[ape1]', '$_POST[ape2]', '$_POST[apodo]')" ;

    if (!mysql_query($sql, $con))
        {
        echo "<center><br /><h2>Al parecer este maestro ya existe, intenta de nuevo.</h2></center> ";
        }
        else {
            echo "<center><br /><h2>Gracias, el maestro ha sido agregado. </h2></center> ";
            }
    }

}

if($errmsg == 1)
    { echo "<center><br/><br/><h2><u>Error: Revisa los datos e intenta de nuevo.</u></h2> </center>
            <center><h2>Recuerda que es recomendable </h2> </center> 
            <center><h2>activar JavaScript en las opciones de tu navegador. </h2></center>";
    }

/*if ($_POST['enviado'] != 1)
    {
    echo 'Error: No se agregaron los datos';
    }*/


mysql_close($con);

?>
+1  A: 

Your error is the usage of non-multibyte-safe string functions:

 $_POST["$field"] = strtolower($_POST["$field"]);
 $_POST["$field"] = ucwords($_POST["$field"]);

Use multi-byte string functions instead.

Apart from that, your form is vulnerable to SQL injection, something that you need to urgently fix.

Pekka
The problem happens with or without that line. (that utf8_encode was added few seconds ago to see if that helps).
Danny
@Danny okay. where do you do the SET NAMES in your script?
Pekka
@Pekka, I deleted the lines with the SET NAMES because didn't help, I'am trying again just to verify it really doesn't help.
Danny
@Danny the set names should do the job.
Pekka
Ok so I added the set names again, but it deletes all the characters after the special "ñ" Eg. "striñg" the result is "stri".
Danny
@Danny what if you disable the `ucwords()` and `strtolower()` for a moment? Any change?
Pekka
Ok, let me try that.
Danny
@Pekka, That works!!! So how can I fix this? I still want to use capital in the first letter of each word.
Danny
@Danny I updated my answer
Pekka
Alright, thanks Pekka, I'm gonna try to fix this and report here if something else happens, thanks :-)
Danny