Le jeu de caractères actuellement nommé utf8 utilise un maximum de trois octets par caractère et ne contient que des caractères BMP : Basic Multilingual Plane, c'est-à-dire les 65534 premiers codes (0x0000 à 0xFFFD) du standard UCS (ISO 10646) qui définit le Universal Character Set (UCS).
UCS contient tous les caractères de tous les autres jeux de caractères standards. Il garantit également une compatibilité circulaire, ce qui signifie que les tables de conversions permettent de ne perdre aucune information quand une chaîne de caractères est convertie dans un autre codage, puis reconvertie en sens inverse.
UCS contient les caractères nécessaires pour représenter presque tous les langages connus. En plus des langues utilisant une extension de l'alphabet latin, il inclut : Grec, Cyrillique, Hébreu, Arabe, Arménien, Grégorien, Japonais, Chinois, Hiragana, Katakana, Coréen, Hangul, Devangari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayam, Thai, Lao, Bopomofo, et d'autres encore. Depuis MySQL 5.5.3 sont supporté les extensions Unicode aux caractères BMP : les caractères utf8 composés de quatre octets, c'est-à-dire les codes du standard UCS (ISO 10646) supérieurs à 65534 (> 0xFFFF) et ce support se nomme utf8mb4.
Néanmoins, pour les commandes telles que SHOW, CREATE TABLE or SELECT l'alias utf8mb3 est systématiquement convertit en utf8.
Pour un caractère BMP, utf8 et utf8mb4 fonctionnent de manière identique : même code, même encodage, même longueur (Nombre d'octets), même façon d'enregistrer dans la base de données.
Pour les caractères supplémentaires, par exemple Unicode version 6, utf8 ne peut pas stocker le caractère et générera une erreur car utf8mb4 nécessite quatre octets. Donc, si on veut supporter les caractères uft8 à quatre octets, il est impératif de le déclarer explicitement pour les bases, tables et colonnes le nécessitant.
Si une table avait été précédemment créée pour supporter utf8, par exemple :
CREATE TABLE t1 ( col1 CHAR(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, col2 CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL ) CHARACTER SET utf8;
La requête suivante permettra, sans aucune perte de données, de transcoder la table pour qu'elle accepte les caractères utf8 à quatre octets :(Il est indispensable de préciser le nom des colonnes à transcoder)
ALTER TABLE t1 DEFAULT CHARACTER SET utf8mb4, MODIFY col1 CHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, MODIFY col2 CHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;
Plus simplement, on peut utiliser :
ALTER TABLE t1 CONVERT TO CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci (ou utf8mb4_bin);
Sans être obligé de donner les noms des colonnes ; seules les colonnes nécessitant d'être transcodées le seront automatiquement.
Pour que MySQL accepte les requêtes contenant des données avec des caractères utf8 à quatre octets, il est impératif de la déclarer explicitement, donc d'envoyer la commande :
SET NAMES utf8mb4;
au lieu de
SET NAMES utf8;
avant les requêtes.
Note : À partir de la version 3.5.0 PhpMyAdmin peut supporter les caractères utf8 à quatre octets sans devoir être modifié.
Pour que PhpMyAdmin accepte, lui aussi, les caractères utf8 à quatre octets il faut :
Remplacer :
// Skip charsets for Drizzle if (!PMA_DRIZZLE) { if (! empty($GLOBALS['collation_connection'])) { PMA_DBI_query("SET CHARACTER SET 'utf8';", $link, PMA_DBI_QUERY_STORE); PMA_DBI_query("SET collation_connection = '" . PMA_sqlAddslashes($GLOBALS['collation_connection']) . "';", $link, PMA_DBI_QUERY_STORE); } else { PMA_DBI_query("SET NAMES 'utf8' COLLATE 'utf8_general_ci';", $link, PMA_DBI_QUERY_STORE); } }
par
// Skip charsets for Drizzle - [modif oto] support for utf8mb4 four bytes characters if (!PMA_DRIZZLE) { if (! empty($GLOBALS['collation_connection'])) { PMA_DBI_query("SET CHARACTER SET 'utf8mb4';", $link, PMA_DBI_QUERY_STORE); PMA_DBI_query("SET collation_connection = '" . PMA_sqlAddslashes($GLOBALS['collation_connection']) . "';", $link, PMA_DBI_QUERY_STORE); } else { PMA_DBI_query("SET NAMES 'utf8mb4' COLLATE 'utf8mb4_general_ci';", $link, PMA_DBI_QUERY_STORE); } }
Dans la page d'accueil de PhpMyAdmin, vérifier et changer éventuellement :
//Interclassement pour la connexion MySQL// **utf8mb4_unicode_ci**
Ne pourra fonctionner QUE pour une version MySQL supérieure à 5.5.3
Créer un fichier forum/db_update_oto.php qui contient :
<?php dirname(__FILE__).'/'); include PUN_ROOT.'config.php'; // Load the functions script require PUN_ROOT.'include/functions.php'; // Load DB abstraction layer and try to connect require PUN_ROOT.'include/dblayer/common_db.php'; //TRUNCATE search tables (Vide les tables search) $db->query('TRUNCATE '.$db->prefix.'search_cache') or error('Unable to TRUNCATE search_cache.', __FILE__, __LINE__, $db->error()); $db->query('TRUNCATE '.$db->prefix.'search_matches') or error('Unable to TRUNCATE search_matches.', __FILE__, __LINE__, $db->error()); $db->query('TRUNCATE '.$db->prefix.'search_words') or error('Unable to TRUNCATE search_words.', __FILE__, __LINE__, $db->error()); //Convert tables to utf8mb4 charset (Converti les tables en utf8mb4) $oto_tables = array( 'bans', 'categories', 'censoring', 'forums', 'forum_perms', 'groups', 'online', 'posts', 'ranks', 'reports', 'search_cache', 'search_matches', 'search_words', 'topics', 'users' ); for($oto_i=0;$oto_i < count($oto_tables);$oto_i++) { $oto_collate = 'general_ci'; if($oto_tables[$oto_i] == 'search_words') $oto_collate = 'bin'; $db->query('ALTER TABLE `'.$db->prefix.$oto_tables[$oto_i].'` CONVERT TO CHARSET utf8mb4 COLLATE utf8mb4_'.$oto_collate) or error('Unable to set table charset utf8', __FILE__, __LINE__, $db->error()); } ?>
Dans le fichier forum/include/dblayermysql.php
Remplacer
// Setup the client-server character set (UTF-8) if (!defined('FORUM_NO_SET_NAMES')) $this->set_names('utf8');
par
// Setup the client-server character set (UTF-8) if (!defined('FORUM_NO_SET_NAMES')) $this->set_names('utf8mb4');
Note : Filtrage effectif à partir de FluxBB 1.4.8
Il peut arriver que des caractères utf-8 à quatre octets soient insérés dans les messages par les utilisateurs. Cela va, en fonction de la configuration du verveur :
Pour éviter cela, on peut nettoyer le message et remplacer les caractères utf-8 à quatre octets par le caractère ?
Dans le fichier post.php, juste après :
$now = time();
ajouter :
//modif oto - Replace bad character by '?' including utf8 four bytes
$message = preg_replace('/[x00-x08x10x0Bx0Cx0E-x19x7F]'.
'|[x00-x7F][x80-xBF]+'.
'|([xC0xC1]|[xF0-xFF])[x80-xBF]*'.
'|[xC2-xDF]((?![x80-xBF])|[x80-xBF]{2,})'.
'|[xE0-xEF](([x80-xBF](?![x80-xBF]))|(?![x80-xBF]{2})|[x80-xBF]{3,})/S',
'?', $message );
$message = preg_replace('/xE0[x80-x9F][x80-xBF]'.
'|xED[xA0-xBF][x80-xBF]/S','?', $message );
//En modif oto