Já falamos várias vezes sobre Unicode, desde a definição de unicode, funções para manupular unicode, como utilizar unicode em todas camadas do sistema e como representar os símbolos na forma de html entities.
Sabemos que ISO-8859-1 foi uma codificação muito utilizada antes do surgimento do Unicode, mas que a tendência é que tudo seja migrado para Unicode e, no caso do ISO-8859-1, preferencialmente migrado para UTF-8. Porém, aplicações web estão sujeitas a situações das mais adversas, quando se trata de dados enviados pelo usuário. Existem casos em que um usuário consegue colar um texto em que parte dele deveria ser ISO-8859-1 e parte dele deveria ser UTF-8. Isso pode ocorrer ao copiar e colar trechos de aplicações para aplicações em sistemas de "origem duvidosa", que acabam gerando uma bagunça de bytes que, por acaso, acabam sendo enviadas para nossa aplicação.
Para resolver este problema, elaborei uma função parecida com utf8_encode, ou seja, converte os caracteres de ISO-8859-1 para UTF-8, porém, caso a função identifique um caractere UTF-8 no texto, ela o mantem intacto. Portanto, ela é útil para garantir que o texto final seja 100% UTF-8 válido.
Linguagem: PHP
Copyright 2012 Rubens Takiguti Ribeiro
Licença: LGPL 3 ou superior
/** * Função que converte caracteres ISO-8859-1 para UTF-8, mantendo os caracteres UTF-8 intactos. * @param string $texto * @return string */ function sanitizar_utf8($texto) { $saida = ''; $i = 0; $len = strlen($texto); while ($i < $len) { $char = $texto[$i++]; $ord = ord($char); // Primeiro byte 0xxxxxxx: simbolo ascii possui 1 byte if (($ord & 0x80) == 0x00) { // Se e' um caractere de controle if (($ord >= 0 && $ord <= 31) || $ord == 127) { // Incluir se for: tab, retorno de carro ou quebra de linha if ($ord == 9 || $ord == 10 || $ord == 13) { $saida .= $char; } // Simbolo ASCII } else { $saida .= $char; } // Primeiro byte 110xxxxx ou 1110xxxx ou 11110xxx: simbolo possui 2, 3 ou 4 bytes } else { // Determinar quantidade de bytes analisando os bits da esquerda para direita $bytes = 0; for ($b = 7; $b >= 0; $b--) { $bit = $ord & (1 << $b); if ($bit) { $bytes += 1; } else { break; } } switch ($bytes) { case 2: // 110xxxxx 10xxxxxx case 3: // 1110xxxx 10xxxxxx 10xxxxxx case 4: // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx $valido = true; $saida_padrao = $char; $i_inicial = $i; for ($b = 1; $b < $bytes; $b++) { if (!isset($texto[$i])) { $valido = false; break; } $char_extra = $texto[$i++]; $ord_extra = ord($char_extra); if (($ord_extra & 0xC0) == 0x80) { $saida_padrao .= $char_extra; } else { $valido = false; break; } } if ($valido) { $saida .= $saida_padrao; } else { $saida .= ($ord < 0x7F || $ord > 0x9F) ? utf8_encode($char) : ''; $i = $i_inicial; } break; case 1: // 10xxxxxx: ISO-8859-1 default: // 11111xxx: ISO-8859-1 $saida .= ($ord < 0x7F || $ord > 0x9F) ? utf8_encode($char) : ''; break; } } } return $saida; }
13 comentários
Muito bom esse script, eu sempre precisei de algo assim, mas não tinha a espertize para criar, parabéns Rubens, pelo excelente trabalho nesse blog
Cara do céu!! Salvou minha vida! Muito Obrigado!!!
Parabéns fera !
Muito bom.
Isso me livrou um tempo danado.
Amigo, desculpe a ignorância, estou precisando fazer essa conversao mas, onde coloco esse codigo que voce passou?
Mah, se não sabe onde colocar, sugiro que coloque no mesmo arquivo onde irá usar a função (pode ser no início ou no final do arquivo).
No entanto, o ideal é que a função fique em um arquivo separado e você inclua o arquivo usando "include" ou "require".
Rubens, obrigado pela luz... só mais uma coisa... nesse codigo passado tem que editar alguma coisa? rsrrs
Mah, não precisa editar nada. É só incluir a função e usá-la. Se conhece bem a sintaxe de funções em PHP, segue um link útil:
http://www.php.net/manual/pt_BR/functions.user-defined.php
Olá Rubens, primeiramente parabéns pelo artigo, excelente!! Estou tendo problema somente para converter o carácter &, o que será q pode ser ???
Abraço.
Olá, Éric
O caractere "&" é representado da mesma forma tanto no ISO-8859-1 quanto no UTF-8, então seu problema deve ser com entities html.
Dê uma olhada nestes artigos:
http://rubsphp.blogspot.com.br/2011/02/html-entities.html
http://rubsphp.blogspot.com.br/2010/10/unicode.html
Olá Rubens, maravilha !!!
Parabéns, não sei dizer o quanto de tempo que economizei!! Ótimo trabalho.
Poderia me explicar como utilizo essa função? To quebrando cabeça tentando usa-la a dias.
Eu preciso usa-la nessas variáveis:
$title = $this->db->quote($data['title']);
$keywords = $this->db->quote($data['keywords']);
$desc = $this->db->quote($data['desc']);
$pagetext = $this->db->quote($data['page']);
Olá, Anônimo
Para usar a função, basta incluí-la no arquivo e usá-la:
$title = $this->db->quote(sanitizar_utf8($data['title']));
$keywords = $this->db->quote(sanitizar_utf8($data['keywords']));
$desc = $this->db->quote(sanitizar_utf8($data['desc']));
$pagetext = $this->db->quote(sanitizar_utf8($data['page']));
Postar um comentário
Nota: fique a vontade para expressar o que achou deste artigo ou do blog.
Dica: para acompanhar as respostas, acesse com uma conta do Google e marque a opção "Notifique-me".
Atenção: o blogger não permite inclusão de tags nos comentários, por isso, use algum site externo para postar seu código com dúvidas e deixe o link aqui. Exemplo: pastebin.com