Dotclear

Ticket #1278 (closed enhancement: fixed)

Opened 14 years ago

Last modified 8 years ago

Problème d'unicode dans l'éditeur de billet en mode wiki

Reported by: dClauzel Owned by: franck
Priority: normal Milestone: 2.13
Component: module:core Version: 2.3
Severity: normal Keywords: unicode, mysql, utf8, utf8mb4
Cc:

Description

La  norme Unicode a récemment évoluée pour intégrer les emoji. Du coup, je me suis dit : « tiens, je vais en mettre dans mes billets, ça va être joli ».

Problème : l'éditeur de billet en mode wiki supprime systématiquement tous ces caractères lors de l'enregistrement du brouillon. C'est regrettable : l'éditeur devrait accepter ces caractères et les conserver à l'enregistrement :(

Naturellement, je travaille avec des polices de caractères qui comportent ces symboles, et je les fais charger au visiteur via les CSS du thème. En créant une page web statique utilisant ces CSS, l'affichage se fait parfaitement.

Procédure pour reproduire

0) créer un nouveau billet

1) s'assurer que l'éditeur est bien en mode wiki

2) insérer un contenu de billet qui comprend des emoji; par exemple : « toto 😊 truc 💩 chose »

3) enregistrer le brouillon

4) constater la disparition des jolis caractères Unicode tout à fait valides.

Notes

Les caractères mentionnés ici sont respectivement :

U+1F60A SMILING FACE WITH SMILING EYES
UTF-8: f0 9f 98 8a  UTF-16BE: d83dde0a  Decimal: 😊
�
Category: So (Symbol, Other)
Bidi: ON (Other Neutrals)

et

U+1F4A9 PILE OF POO
UTF-8: f0 9f 92 a9  UTF-16BE: d83ddca9  Decimal: 💩
�
Category: So (Symbol, Other)
Bidi: ON (Other Neutrals)

Change History

comment:1 Changed 14 years ago by franck

Le phénomène est le même avec l'éditeur XHTML.

comment:2 Changed 14 years ago by franck

Et ce n'a rien à voir avec le mode d'édition puisque le champ notes est traité de la même manière. Je pense qu'il faut plutôt jeter un œil du côté de l'enregistrement en DB.

comment:3 Changed 13 years ago by dClauzel

Des nouvelles sur ce bug ? C'est vraiment casse-pieds quand on veut faire de la rédaction scientifique : l'unicode contient les caractères pour les représentations, mais impossible de les utiliser :(

comment:4 Changed 13 years ago by JcDenis

J'ai testé chez moi avec un peu de mal car je n'y connais rien en Unicode mais ça passe que je l'insert avec le code clavier en wiki ou avec le code HTML ( ex: 😨 ) et rien n'est supprimé ?!

Par contre j'ai lu sur le net que mySQL < 5.5 ne supportait pas ces nouveaux codes, peut-être voir de ce coté.

comment:5 Changed 13 years ago by franck

Je sèche un peu sur ce problème. J'arrive à enregistrer un billet mêlant caractères latin et japonais, mais pas ceux cités ci-dessus.

Quelqu'un a une piste ?

comment:6 Changed 13 years ago by franck

  • Milestone changed from A definir to Wysiwyg editor (multi-syntax)

comment:7 Changed 12 years ago by franck

  • Milestone changed from Wysiwyg editor (multi-syntax) to 2.6

comment:8 Changed 12 years ago by franck

  • Milestone changed from 2.6 to A definir

comment:9 Changed 12 years ago by franck

  • Milestone changed from A definir to 2.7

comment:10 Changed 12 years ago by dClauzel

Marrant, la résolution du bug n'arrête pas d'être repoussée :)

Est-ce qu'on sait à quel niveau est le problème ?

comment:11 Changed 12 years ago by franck

  • Owner changed from xave to team

comment:12 Changed 12 years ago by franck

J'ai fait quelques tests à l'époque sans trouver le coupable et je suis donc bien incapable de dire qui est le fautif.

Cela dit, si quelqu'un a une ou plusieurs pistes, ça sera le bienvenu car comme j'ai dit plus haut, je sèche.

Cela étant, ce ticket n'est pas une raison suffisante de bloquer une release (la future 2.6). Donc si c'est réglé avant la sortie de la 2.6, on l'intégrera dedans, sinon on verra le moment venu.

comment:13 Changed 12 years ago by franck

Apparemment c'est un problème avec MySQL :

La requête suivante échoue (via phpMyAdmin) :

UPDATE `dc2`.`dc_post` SET `post_content` = 'toto 😊 truc 💩 chose',
`post_content_xhtml` = '<p>toto 😊 truc 💩 chose</p>' WHERE `dc_post`.`post_id` =11064;

comment:15 Changed 12 years ago by franck

Et au passage Wordpress ne fait pas mieux dans ce domaine.

comment:16 Changed 12 years ago by dClauzel

OK, donc c'est bien un problème de MySQL, et pas de DotClear? :P

Sur les nouvelles installations, est-ce qu'utiliser utf8mb4 au lieu d'utf8 pour le backend MySQL résoudrait le problème ?

Last edited 12 years ago by dClauzel (previous) (diff)

comment:17 Changed 12 years ago by franck

Probablement et même pour les installations actuelles, en suivant cette check-list :  http://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4

Par contre on ne va pas l'intégrer pour l'instant dans DC, car l'utf8mb4 n'apparaît qu'à partir de la version 5.5 de MySQL, version qui n'est peut-être pas en vigueur partout.

comment:18 Changed 12 years ago by dClauzel

Pas grave : du moment que la solution est trouvée, c'est ce qui compte. Les gens qui le souhaitent pourront faire la correction à la main (ou avec un patch spécial ?), et les autres auront ça avec une mise à jour ultérieure.

Bravo en tout cas. Bien joué ! ;)

comment:19 Changed 12 years ago by franck

On accepte avec plaisir toutes les propositions de patch, spéciaux ou pas :-)

comment:20 Changed 12 years ago by franck

  • Milestone changed from 2.7 to 2.8

comment:21 Changed 12 years ago by dClauzel

Hihi, encore repoussé :)

Il est bien ce problème, hein ? Je suis très fier de l'avoir signalé : c'est actuellement mon rapport de bug — tous projets confondus — qui a la plus meilleure longévité :D

Courage !

comment:22 Changed 12 years ago by kozlika

C'est surtout qu'on réduit le périmètre de la 2.7, mais évidemment si tu (ou un autre dev) proposes un patch on le mergera of course.

comment:23 follow-up: ↓ 24 Changed 11 years ago by franck

  • Milestone changed from 2.8 to 2.10

comment:24 in reply to: ↑ 23 Changed 11 years ago by dClauzel

Ce problème semble velu. J’aimerais bien aider à la résoudre, malheureusement ce n’est pas dans mon domaine de compétences :(

Aller, on y croit pour la 2.10 ! ;)

comment:25 follow-up: ↓ 29 Changed 11 years ago by franck

Finalement j'ai la réponse précise : MySQL en mode UTF-8, ne gère l'encodage des caractères que jusqu'à 3 octets seulement (et pas 4 comme prévus par UTF-8).

Ce n'est qu'à partir de la version 5.5.3 de MySQL que l'encodage utf8mb4 (utf8mb4_unicode_ci) est géré.

Voir ici pour plus d'infos :  https://mathiasbynens.be/notes/mysql-utf8mb4

comment:26 Changed 11 years ago by dClauzel

Jolie trouvaille, bravo !

C’est possible de convertir les tables de DotClear? depuis utf8_bin vers utf8mb4_unicode_ci ? phpMyAdmin a une interface pour tripatouiller l’encodage, mais je préfère être sûr de la manipulation avant de tout casser.

comment:27 Changed 11 years ago by franck

Possible de convertir la base, oui bien sûr, mais ça ne servira à rien si Dotclear ne se connecte pas avec ce mode (utf8mb4), va falloir adapter côté Clearbricks, pas mal tester, et surtout assurer la rétro-compatibilité avec les versions antérieures de MySQL.

comment:28 Changed 9 years ago by franck

  • Milestone changed from 2.10 to 2.11

comment:29 in reply to: ↑ 25 Changed 9 years ago by JcDenis

Replying to franck:

Finalement j'ai la réponse précise : MySQL en mode UTF-8, ne gère l'encodage des caractères que jusqu'à 3 octets seulement (et pas 4 comme prévus par UTF-8).

Ce n'est qu'à partir de la version 5.5.3 de MySQL que l'encodage utf8mb4 (utf8mb4_unicode_ci) est géré.

Voir ici pour plus d'infos :  https://mathiasbynens.be/notes/mysql-utf8mb4

J'ai regardé un peu cet article assez clair.

La mise à jour d'un base existante est carrément une mission suicide, et pratiquement impossible à faire en automatique par une procédure de mise à jour dans Dotclear... Besoin de lancer des procédures de réparation, d'optimisation, de modifier des longueurs/types de champs, etc...

Par contre pour une nouvelle installation de Dotclear, cela doit pouvoir se faire simplement en créant directement la base en utf8mb4_unicode_ci et en ajoutant un nouveau driver à Clearbricks (une copie des classes mysql/mysqli en y modifiant le jeu de caractère). Le reste des fonctions de Clearbrick ont l'air de supporter le vrai utf8 (sur 4 octets). L'importation d'un vieux blog ne devrait pas non plus poser de problème.

Ce qui me gène le plus est qu'une installation existante a peu de chance de passer à cet encodage...

comment:30 Changed 9 years ago by JcDenis

  • Keywords unicode, mysql, utf8, utf8mb4 added; unicode,wiki removed

comment:31 Changed 9 years ago by franck

  • Milestone changed from 2.11 to 2.12

comment:32 Changed 9 years ago by franck

Arfy (sur le forum →  https://forum.dotclear.org/viewtopic.php?pid=339236#p339236) a proposé une idée intéressante qui ne nécessite pas de conversion de base :

$str = 'toto → 😊 truc → 💩 chose';
$enc = mb_convert_encoding($str,'HTML-ENTITIES','UTF-8');
echo '<p> Texte → '.$enc.'</p>';
var_dump($str,$enc);

Fonctionne très bien :

toto → 😊 truc → 💩 chose

string 'toto → 😊 truc → 💩 chose' (length=33)

string 'toto &rarr; &#128522; truc &rarr; &#128169; chose' (length=49)

comment:33 follow-up: ↓ 34 Changed 9 years ago by dClauzel

Ça se passerait comment du coup pour l’exportation des billets (flux rss, archives, etc) ? On pourrait récupérer les emoji ou il faudrait faire un post-traitement à la main ?

comment:34 in reply to: ↑ 33 Changed 9 years ago by franck

Replying to dClauzel:

Ça se passerait comment du coup pour l’exportation des billets (flux rss, archives, etc) ? On pourrait récupérer les emoji ou il faudrait faire un post-traitement à la main ?

Aucune idée pour l'instant, va falloir explorer, tester (beaucoup) et vérifier la portée et les conséquences d'un changement à ce sujet. C'est loin d'être anodin.

comment:36 in reply to: ↑ 35 Changed 9 years ago by dClauzel

Replying to franck:

En attendant mieux →  https://open-time.net/post/2017/03/09/Plugin-utf8mb4-01-pour-Dotclear

Ça fonctionne nickel chez moi : Dotclear v2.11.2 sur Debian avec apache 2.4 + php7.0.16-3 + MariaDB-5+b1 avec connecteur mysqli. La base de données est en interclassement utf8mb4_general_ci, et les tables en innodb utf8_bin

Mes essais :

  • Je charge le greffon; le site web continue de fonctionner (un point positif ;)
  • Je créé une nouvelle page :  https://Damien.Clauzel.eu/pages/essai-emoji-via-greffon-utf8mb4 ; l’affichage est correct.
  • Je vide le cache des templates, tout le blog continue de s’afficher correctement.
  • J’édite un ancien billet pour y glisser des emojis; le billet conserve bien les emojis dans l’éditeur après enregistrement, et les emojis sont bien affichés sur le blog.
  • Je supprime les emoji du billet; le blog affiche bien la nouvelle version sans les emojis.
  • Je revide le cache des templates, tout le blog est OK.

En l’état, pour mon installation je valide.

Un grand bravo, et un splendide merci !

comment:37 Changed 9 years ago by franck

Merci pour les retours de test !

Sinon, pour un "vrai" driver msqlimb4 (que je suis en train d'implémenter dans Clearbricks), ça voudra dire MySQL version 5.7* minimum si on veut conserver les tailles de champs tels que prévus jusqu'à maintenant.

  • 5.7 min pour avoir RAW_FORMAT=Dynamic et innodb_file_format = Barracuda →

 https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix:

innodb_large_prefix is enabled by default in MySQL 5.7. This change coincides with the default value change for innodb_file_format, which is set to Barracuda by default in MySQL 5.7. Together, these default value changes allow larger index key prefixes to be created when using DYNAMIC or COMPRESSED row format. If either option is set to a non-default value, index key prefixes larger than 767 bytes are silently truncated.

innodb_large_prefix is deprecated and will be removed in a future release. innodb_large_prefix was introduced in MySQL 5.5 to disable large index key prefixes for compatibility with earlier versions of InnoDB that do not support large index key prefixes.

Avec la 5.6 on est en mode Compact et format Antelope par défaut et ça coince.

Sinon il faut diminuer les champs qui font 255 caractères de long à 191 max si on veut que ça passe au moment de la création des index. Ça risque de casser, entre autres sur des URLs de billet super long.

comment:38 Changed 9 years ago by franck

  • Milestone changed from 2.12 to 2.13

comment:39 Changed 8 years ago by franck

  • Milestone changed from 2.13 to A definir

comment:40 Changed 8 years ago by franck

  • Milestone A definir deleted

comment:41 Changed 8 years ago by franck

  • Type changed from defect to enhancement

comment:42 Changed 8 years ago by franck

  • Owner changed from team to franck

comment:43 Changed 8 years ago by franck

  • Milestone set to 2.13

comment:44 Changed 8 years ago by franck

Nouveau driver testé (voir les révisions [3564] et [3565]), avec un gros warning : valable uniquement pour de nouvelles bases de données. L'ancien schéma n'est pas compatible et on ne peut convertir les bases sans dégâts.

Les modifications apportées au schéma, quelques champs en varchar(255) passent en varchar(191) :

  • table category, champ cat_url
  • table dc_meta, champ meta_id
  • table dc_ping, champ ping_url
  • table dc_post, champ post_url
  • table dc_pref, champ pref_id
  • table dc_setting, champ setting_id

Soit tous les champs utilisé dans les clés uniques.

La raison est qu'avec un codage sur 4 caractères, la limite étant de 767 octets côté InnoDB pour le stockage, on pouvait spécifier 255 caractères avec un codage sur 3 octets (255,66 exactement) alors que seulement 191 tiennent avec un codage sur 4 caractères (191,75 exactement).

Il va donc falloir réduire la longueur de ces champs à la création.

Last edited 8 years ago by franck (previous) (diff)

comment:45 Changed 8 years ago by franck <carnet.franck.paul@…>

(In [7b171ccd8cee]) Reduce indexed varchar(255) fields to varchar(191) : table category, field cat_url; table dc_meta, field meta_id; table dc_ping, field ping_url; table dc_post, field post_url; table dc_pref, field pref_id; table dc_setting, field setting_id. Addresses #1278

comment:46 Changed 8 years ago by franck

Par conséquent la prochaine 2.13 diminuera la longueur possible pour quelques champs accessibles via l'admin : URL des billets/pages et des catégories essentiellement. Cela dit, 191 caractères pour une URL, on est déjà dans le copieux !

On pourra toujours prévoir une petite fonction côté maintenance pour vérifier s'il y a des URLs qui dépassent et les lister.

comment:47 Changed 8 years ago by philippe

Je vote pour un plugin de maintenance qui vérifie la longueur éventuelle de ces champs, liste les occurrences et invite à les réduire manuellement (sinon ça me paraît trop long à développer pour peu de cas) et permet de convertir ensuite la base. C'est possible ?

comment:48 Changed 8 years ago by franck

La conversion de base je pense qu'on fera l'impasse dessus, c'est trop de code alors qu'on peut en créer une au bon format (UTF8-MB4) et importer dedans les données de l'ancienne. C'est assez simple à faire avec n'importe quel client MySQL qui supporte le mb4.

Quoi qu'il en soit il n'y aura rien d'automatique. Par contre on pourra choisir le driver mysqlmb4 à l'installation, en utilisant une base de données au bon format.

comment:49 Changed 8 years ago by franck

J'ai fait un test avec une (grosse) base de données en UTF8 :

  • Création d'une base encodée utf8mb4 (et collation utf8mb4_general_ci)
  • Export de la structure de l'ancienne base utf8
  • Dans cet export on vire tout ce qui indique UTF8, soit les CHARSET, COLLATION, … (je peux filer un exemple), avec un éditeur de texte
  • Import de la structure dans la nouvelle base afin de créer les tables (qui utiliseront donc l'encodage de la base puisque pas spécifié dans le fichier d'import)
  • Export des données seules de l'ancienne base
  • Import des données dans la nouvelle base

Ensuite direction le inc/config.php pour modifier le nom de la base utilisée et le driver (mysqlimb4) et c'est tout, ça fonctionne.

Last edited 8 years ago by franck (previous) (diff)

comment:50 Changed 8 years ago by philippe

Ouais, ben si c'est juste pour afficher des emojis, dont je peine un peu à saisir l'utilité , j'approuve la manœuvre de conversion que je ne ferai pas. Si c'est possible avec une nouvelle installation, ça me va bien, évidemment :P

comment:51 Changed 8 years ago by franck

Surtout que si c'est juste pour des émojis, j'ai codé un plugin qui fait le job (il est installé chez moi et ne pose aucun problème).

comment:52 Changed 8 years ago by franck

  • Status changed from new to closed
  • Resolution set to fixed

Je clos ce ticket, on verra si quelqu'un se sert du nouveau driver et des retours qui seront éventuellement faits à ce moment.

comment:53 Changed 8 years ago by franck

À noter : la transformation de 255 en 191 caractères de long pour certains index uniques est nécessaire avec MySQL < 5.7, au delà ce n'est plus le cas. Aujourd'hui la version 5.7 n'est pas encore de règle partout, on va donc attendre un peu avant de revenir (éventuellement) aux longueurs initiales.

comment:54 Changed 8 years ago by franck <carnet.franck.paul@…>

(In [d00ce0b58d8a]) Add a maintenance task to check UTF8-mb4 compatibility (for export/import) as some data might not be longer than 191 chars in order to be present in an index. The UTF8-mb4 format will be proposed as database driver for the next 2.13 release and will concern only new installations. Addresses #1278

comment:55 Changed 8 years ago by franck <carnet.franck.paul@…>

(In [bacbc979195e]) Revert back from 191 to 255 chars (as utf8mb4 MySQL is only available with 5.7+ server, assuming large-prefix and barracuda), addresses #1278

comment:56 Changed 8 years ago by franck <carnet.franck.paul@…>

(In [6c9e5333591e]) Revert [3594] revision as utf8mb4 is now only possible with 5.7+ MySQL server (assuming large-prefix and barracuda), addresses #1278

Note: See TracTickets for help on using tickets.

Sites map