diff --git a/ecrire/inc/charsets.php b/ecrire/inc/charsets.php index c07ec39803a707c1ff3d6188bbb1a51bf3415751..d99891a0e30399ca30c7dcd43d0472aa1cec7950 100644 --- a/ecrire/inc/charsets.php +++ b/ecrire/inc/charsets.php @@ -654,6 +654,7 @@ function utf_32_to_unicode($source) { * Caractère utf8 si trouvé, '' sinon **/ function caractere_utf_8($num) { + $num = intval($num); if($num<128) return chr($num); if($num<2048) @@ -661,7 +662,7 @@ function caractere_utf_8($num) { if($num<65536) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128); if($num<1114112) - return chr($num>>18+240).chr((($num>>12)&63)+128).chr(($num>>6)&63+128). chr($num&63+128); + return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr(($num>>6)&63+128). chr($num&63+128); return ''; } @@ -1106,4 +1107,32 @@ if (!isset($GLOBALS['meta']['pcre_u']) ); } + +/** + * Transforme une chaîne utf-8 en utf-8 sans "planes" + * ce qui permet de la donner à MySQL "utf8", qui n'est pas un utf-8 complet + * L'alternative serait d'utiliser utf8mb4 + * + * @param string $x + * La chaîne à transformer + * @return string + * La chaîne avec les caractères utf8 des hauts "planes" échappée + * en unicode : 💩 + */ +function utf8_noplanes($x) { + $regexp_utf8_4bytes = '/( + \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 +)/xS'; + if (preg_match_all($regexp_utf8_4bytes, $x, $z, PREG_PATTERN_ORDER)) { + foreach($z[0] as $k) { + $ku = utf_8_to_unicode($k); + $x = str_replace($k, $ku, $x); + } + } + return $x; +} + + ?> diff --git a/ecrire/inc/modifier.php b/ecrire/inc/modifier.php index 5139b345aa07df0ca76304286dd8854db40249f1..fc3416dbe7ba0f63696f6daebce05f022447ca0f 100644 --- a/ecrire/inc/modifier.php +++ b/ecrire/inc/modifier.php @@ -207,15 +207,25 @@ function objet_modifier_champs($objet, $id_objet, $options, $c=null, $serveur='' // si difference entre les champs, reperer les champs mal enregistres if ($moof != $champs) { $liste = array(); - foreach($moof as $k=>$v) + foreach($moof as $k=>$v) { if ($v !== $champs[$k] - // ne pas alerter si le champ est numerique est que les valeurs sont equivalentes - AND (!is_numeric($v) OR intval($v)!=intval($champs[$k])) - ) { + // ne pas alerter si le champ est numerique est que les valeurs sont equivalentes + AND (!is_numeric($v) OR intval($v)!=intval($champs[$k])) + ) { $liste[] = $k; $conflits[$k]['post'] = $champs[$k]; $conflits[$k]['save'] = $v; + + // cas specifique MySQL+emoji : si l'un est la + // conversion utf8_noplanes de l'autre alors c'est OK + if (defined('_MYSQL_NOPLANES') && _MYSQL_NOPLANES) { + include_spip('inc/charsets'); + if ($v == utf8_noplanes($champs[$k])) { + array_pop($liste); + } + } } + } // si un champ n'a pas ete correctement enregistre, loger et retourner une erreur // c'est un cas exceptionnel if (count($liste)){ diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php index d4b2d2920232f08e8be4db1e738edbf3364ab568..b998a2e58632549ad17e1c7650169461095ab85e 100644 --- a/ecrire/inc/utils.php +++ b/ecrire/inc/utils.php @@ -922,7 +922,7 @@ function queue_sleep_time_to_next_job($force=null) { // http://doc.spip.org/@quote_amp function quote_amp($u) { return preg_replace( - "/&(?![a-z]{0,4}\w{2,3};|#x?[0-9a-f]{2,5};)/i", + "/&(?![a-z]{0,4}\w{2,3};|#x?[0-9a-f]{2,6};)/i", "&",$u); } diff --git a/ecrire/req/mysql.php b/ecrire/req/mysql.php index 321f685cbd82baccabf41b6775ffa70efe3d9a36..efb33c5e3d77c55469bb32b6a2ab9599154ab2c7 100644 --- a/ecrire/req/mysql.php +++ b/ecrire/req/mysql.php @@ -118,8 +118,9 @@ $GLOBALS['spip_mysql_functions_1'] = array( //'iso-8859-6'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'), 'iso-8859-9'=>array('charset'=>'latin5','collation'=>'latin5_turkish_ci'), //'iso-8859-15'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'), -'utf-8'=>array('charset'=>'utf8','collation'=>'utf8_general_ci')) - ); +'utf-8'=>array('charset'=>'utf8','collation'=>'utf8_general_ci') + ) + ); /** @@ -488,6 +489,12 @@ function _mysql_traite_query($query, $db='', $prefixe='') { } $r = preg_replace(_SQL_PREFIXE_TABLE_MYSQL, '\1'.$pref, $query) . $suite; + // en option, remplacer les emoji (que mysql ne sait pas gérer) en 💩 + if (defined('_MYSQL_NOPLANES') && _MYSQL_NOPLANES) { + include_spip('inc/charsets'); + $r = utf8_noplanes($r); + } + #spip_log("_mysql_traite_query: " . substr($r,0, 50) . ".... $db, $prefixe", _LOG_DEBUG); return $r; }