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 : &#128169;
+ */
+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",
 		"&amp;",$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 &#128169;
+	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;
 }