Index: locales/fr/plugins.po
===================================================================
--- locales/fr/plugins.po	(revision 3557)
+++ locales/fr/plugins.po	(revision 3594)
@@ -1414,4 +1414,88 @@
 msgstr "Au fur at à mesure des suppressions ou modifications dans vos billets, les tables de la base de données se fragmentent. L'opération d'optimisation permet de compacter celles-ci. Cette opération n'a aucun impact sur l'intégrité de vos données. Il est fortement conseillé d'optimiser la base de données avant tout export de blog."
 
+msgid "UTF8-mb4 check"
+msgstr "Contrôle UTF8-mb4"
+
+msgid "UTF8-mb4 compatibility check"
+msgstr "Contrôle de compatibilité UTF8-mb4"
+
+msgid "Next: %s"
+msgstr "Suivant : %s"
+
+msgid "Next"
+msgstr "Suivant"
+
+msgid "Check end"
+msgstr "Fin du contrôle"
+
+msgid "Some data will not be fully importable in a UTF8-mb4 database. You need to reduce them before."
+msgstr "Certaines données ne seront pas complètement importables dans une base de données au format UTF8-mb4. Vous devrez d'abord les réduire."
+
+msgid "Check various data for compatibility with UTF8-mb4 (full UTF8 encoding storage) before exporting and importing them in a new UTF8-mb4 MySQL database."
+msgstr "Contrôle la compatibilité de certaines données avec le format UTF8-mb4 (encodage complet de l'UTF8) avant un export et un import dans une nouvelle base de données au format UTF8-mb4."
+
+msgid "All post URLs are importable in UTF8-mb4 database"
+msgstr "Toutes les URLs des entrées sont importables dans une base données UTF8-mb4"
+
+msgid "%s post URLs are longer than %d characters:"
+msgstr "%s URLs d'entrée sont plus longues que les %d caractères max :"
+
+msgid "URL Length"
+msgstr "Longueur d'URL"
+
+msgid "All ping URLs are importable in UTF8-mb4 database"
+msgstr "Toutes les URLs de ping sont importables dans une base de données UTF8-mb4"
+
+msgid "%s ping URLs are longer than %d characters:"
+msgstr "%s URLs de ping sont plus longues que les %d caractères max :"
+
+msgid "Ping URL"
+msgstr "URL de ping"
+
+msgid "All meta IDs are importable in UTF8-mb4 database"
+msgstr "Tous les identifiants de métadonnée sont importables dans une base de données UTF8-mb4"
+
+msgid "%s meta IDs are longer than %d characters:"
+msgstr "%s identifiants de métadonnée sont plus longs que les %d caractères max :"
+
+msgid "Meta ID"
+msgstr "Identifiant de métadonnée"
+
+msgid "Type"
+msgstr "Type"
+
+msgid "Length"
+msgstr "Longueur"
+
+msgid "All Category URLs are importable in UTF8-mb4 database"
+msgstr "Toutes les URLs de catégorie sont importables dans une base de données UTF8-mb4"
+
+msgid "%s category URLs are longer than %d characters:"
+msgstr "%s URLs de catégorie sont plus longues que les %d caractères max :"
+
+msgid "All User preferences are importable in UTF8-mb4 database"
+msgstr "Toutes les préférences utilisateur sont importables dans une base de données UTF8-mb4"
+
+msgid "%s User preference IDs are longer than %d characters:"
+msgstr "%s identifiants de préférence utilisateur sont plus longs que les %d caractères max :"
+
+msgid "Preference ID"
+msgstr "Identifiant de préférence utilisateur"
+
+msgid "Workspace"
+msgstr "Espace de travail"
+
+msgid "All Blog settings are importable in UTF8-mb4 database"
+msgstr "Tous les identifiants de réglage de blog sont importables dans une base de données UTF8-mb4"
+
+msgid "%s Blog setting IDs are longer than %d characters:"
+msgstr "%s identifiants de réglage de blog sont plus longs que les %d caractères max :"
+
+msgid "Setting ID"
+msgstr "Identifiant de réglage de blog"
+
+msgid "Namespace"
+msgstr "Espace de noms"
+
 msgid "Download media folder of current blog"
 msgstr "Télécharger la médiathèque du blog courant"
Index: plugins/maintenance/_admin.php
===================================================================
--- plugins/maintenance/_admin.php	(revision 3340)
+++ plugins/maintenance/_admin.php	(revision 3594)
@@ -67,4 +67,5 @@
 		->addTask('dcMaintenanceSynchpostsmeta')
 		->addTask('dcMaintenanceLogs')
+		->addTask('dcMaintenanceUtf8mb4')
 		->addTask('dcMaintenanceVacuum')
 		->addTask('dcMaintenanceZipmedia')
Index: plugins/maintenance/_prepend.php
===================================================================
--- plugins/maintenance/_prepend.php	(revision 3324)
+++ plugins/maintenance/_prepend.php	(revision 3594)
@@ -25,4 +25,5 @@
 $__autoload['dcMaintenanceSynchpostsmeta'] = dirname(__FILE__).'/inc/tasks/class.dc.maintenance.synchpostsmeta.php';
 $__autoload['dcMaintenanceLogs'] = dirname(__FILE__).'/inc/tasks/class.dc.maintenance.logs.php';
+$__autoload['dcMaintenanceUtf8mb4'] = dirname(__FILE__).'/inc/tasks/class.dc.maintenance.utf8mb4.php';
 $__autoload['dcMaintenanceVacuum'] = dirname(__FILE__).'/inc/tasks/class.dc.maintenance.vacuum.php';
 $__autoload['dcMaintenanceZipmedia'] = dirname(__FILE__).'/inc/tasks/class.dc.maintenance.zipmedia.php';
Index: plugins/maintenance/inc/tasks/class.dc.maintenance.utf8mb4.php
===================================================================
--- plugins/maintenance/inc/tasks/class.dc.maintenance.utf8mb4.php	(revision 3594)
+++ plugins/maintenance/inc/tasks/class.dc.maintenance.utf8mb4.php	(revision 3594)
@@ -0,0 +1,256 @@
+<?php
+# -- BEGIN LICENSE BLOCK ---------------------------------------
+#
+# This file is part of Dotclear 2.
+#
+# Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear
+# Licensed under the GPL version 2.0 license.
+# See LICENSE file or
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+#
+# -- END LICENSE BLOCK -----------------------------------------
+if (!defined('DC_RC_PATH')) { return; }
+
+define('UTF8MB4_MAXLEN',191);
+
+class dcMaintenanceUtf8mb4 extends dcMaintenanceTask
+{
+	protected $perm = null;		// super admin only
+	protected $step_task;
+	protected $list;
+
+	protected function init()
+	{
+		$this->name 		= __('UTF8-mb4 check');
+		$this->task 		= __('UTF8-mb4 compatibility check');
+		$this->step			= __('Next: %s');
+		$this->step_task	= __('Next');
+		$this->success 		= __('Check end');
+		$this->error 		= __('Some data will not be fully importable in a UTF8-mb4 database. You need to reduce them before.');
+
+		$this->description = __('Check various data for compatibility with UTF8-mb4 (full UTF8 encoding storage) before exporting and importing them in a new UTF8-mb4 MySQL database.');
+	}
+
+	public function execute()
+	{
+		$this->code = $this->checkUtf8mb4($this->code);
+		return $this->code ?: true;
+	}
+
+	public function task()
+	{
+		return $this->code ? $this->step_task : $this->task;
+	}
+
+	public function step()
+	{
+		return $this->code ? '<p>'.$this->list.'</p>' : null;
+	}
+
+	public function success()
+	{
+		return $this->code ? sprintf($this->step, $this->step_task) : $this->success;
+	}
+
+	public function header()
+	{
+		return sprintf($this->step, $this->step_task);
+	}
+
+	protected function checkUtf8mb4($code=null)
+	{
+		switch ($code) {
+			case null:
+			case 0:
+				# check posts
+				$this->list = __('All post URLs are importable in UTF8-mb4 database');
+
+				$rs = $this->core->con->select(
+					'SELECT post_id, post_type, post_title, post_url, LENGTH(post_url) AS xlen FROM '.$this->core->prefix.'post '.
+					'WHERE LENGTH(post_url) > '.UTF8MB4_MAXLEN.' ORDER BY post_id', true);
+				if (!$rs->isEmpty()) {
+					$this->list =
+						'<p class="step-msg">'.
+						sprintf(__('%s post URLs are longer than %d characters:'),$rs->count(),UTF8MB4_MAXLEN).'</p>'.
+						'<div class="table-outer">'.
+						'<table>'.
+						'<th class="first">'.__('Title').'</th>'.
+						'<th>'.__('URL Length').'</th>';
+					while ($rs->fetch()) {
+						$this->list .=
+							'<tr class="line" id="p'.$rs->post_id.'">'.
+							'<td class="maximal" scope="row"><a href="'.
+								$this->core->getPostAdminURL($rs->post_type,$rs->post_id).'">'.
+								html::escapeHTML($rs->post_title).'</a></td>'.
+							'<td class="nowrap count">'.$rs->xlen.'</td>'.
+							'</tr>';
+					}
+					$this->list .=
+						'</table>'.
+						'</div>';
+				}
+				$code++;
+				break;
+			case 1:
+				# check pings
+				$this->list = __('All ping URLs are importable in UTF8-mb4 database');
+
+				$rs = $this->core->con->select(
+					'SELECT post_id, ping_url, LENGTH(ping_url) AS xlen FROM '.$this->core->prefix.'ping '.
+					'WHERE LENGTH(ping_url) > '.UTF8MB4_MAXLEN.' ORDER BY post_id', true);
+				if (!$rs->isEmpty()) {
+					$this->list =
+						'<p class="step-msg">'.
+						sprintf(__('%s ping URLs are longer than %d characters:'),$rs->count(),UTF8MB4_MAXLEN).'</p>'.
+						'<div class="table-outer">'.
+						'<table>'.
+						'<th class="first">'.__('Ping URL').'</th>'.
+						'<th>'.__('URL Length').'</th>';
+					while ($rs->fetch()) {
+						$this->list .=
+							'<tr class="line" id="p'.$rs->post_id.'">'.
+							'<td class="maximal" scope="row"><a href="'.
+								$this->core->getPostAdminURL('post',$rs->post_id).'#trackbacks">'.
+								html::escapeHTML($rs->ping_url).'</a></td>'.
+							'<td class="nowrap count">'.$rs->xlen.'</td>'.
+							'</tr>';
+					}
+					$this->list .=
+						'</table>'.
+						'</div>';
+				}
+				$code++;
+				break;
+			case 2:
+				# check meta
+				$this->list = __('All meta IDs are importable in UTF8-mb4 database');
+
+				$rs = $this->core->con->select(
+					'SELECT meta_id, meta_type, LENGTH(meta_id) AS xlen FROM '.$this->core->prefix.'meta '.
+					'WHERE LENGTH(meta_id) > '.UTF8MB4_MAXLEN.' ORDER BY meta_id', true);
+				if (!$rs->isEmpty()) {
+					$this->list =
+						'<p class="step-msg">'.
+						sprintf(__('%s meta IDs are longer than %d characters:'),$rs->count(),UTF8MB4_MAXLEN).'</p>'.
+						'<div class="table-outer">'.
+						'<table>'.
+						'<th class="first">'.__('Meta ID').'</th>'.
+						'<th>'.__('Type').'</th>'.
+						'<th>'.__('Length').'</th>';
+					while ($rs->fetch()) {
+						$this->list .=
+							'<tr class="line" id="m-'.$rs->meta_id.'">'.
+							'<td class="maximal" scope="row">'.
+								($rs->meta_type == 'tag' ?
+									'<a href="'.$this->core->adminurl->get('admin.plugin.tags',
+										array('m' => 'tag_posts','tag' => $rs->meta_id)).'">' : '').
+								html::escapeHTML($rs->meta_id).($rs->meta_type == 'tag' ? '</a>' : '').'</td>'.
+							'<td>'.$rs->meta_type.'</td>'.
+							'<td class="nowrap count">'.$rs->xlen.'</td>'.
+							'</tr>';
+					}
+					$this->list .=
+						'</table>'.
+						'</div>';
+				}
+				$code++;
+				break;
+			case 3:
+				# check categories
+				$this->list = __('All Category URLs are importable in UTF8-mb4 database');
+
+				$rs = $this->core->con->select(
+					'SELECT cat_id, cat_title, cat_url, LENGTH(cat_url) AS xlen FROM '.$this->core->prefix.'category '.
+					'WHERE LENGTH(cat_url) > '.UTF8MB4_MAXLEN.' ORDER BY cat_id', true);
+				if (!$rs->isEmpty()) {
+					$this->list =
+						'<p class="step-msg">'.
+						sprintf(__('%s category URLs are longer than %d characters:'),$rs->count(),UTF8MB4_MAXLEN).'</p>'.
+						'<div class="table-outer">'.
+						'<table>'.
+						'<th class="first">'.__('Title').'</th>'.
+						'<th>'.__('URL Length').'</th>';
+					while ($rs->fetch()) {
+						$this->list .=
+							'<tr class="line" id="c-'.$rs->cat_id.'">'.
+							'<td class="maximal" scope="row">'.
+								'<a href="'.$this->core->adminurl->get('admin.category',array('id' => $rs->cat_id)).'">'.
+								html::escapeHTML($rs->cat_title).'</a></td>'.
+							'<td class="nowrap count">'.$rs->xlen.'</td>'.
+							'</tr>';
+					}
+					$this->list .=
+						'</table>'.
+						'</div>';
+				}
+				$code++;
+				break;
+			case 4:
+				# check prefs
+				$this->list = __('All User preferences are importable in UTF8-mb4 database');
+
+				$rs = $this->core->con->select(
+					'SELECT pref_id, pref_ws, LENGTH(pref_id) AS xlen FROM '.$this->core->prefix.'pref '.
+					'WHERE LENGTH(pref_id) > '.UTF8MB4_MAXLEN.' ORDER BY pref_ws,pref_id', true);
+				if (!$rs->isEmpty()) {
+					$this->list =
+						'<p class="step-msg">'.
+						sprintf(__('%s User preference IDs are longer than %d characters:'),$rs->count(),UTF8MB4_MAXLEN).'</p>'.
+						'<div class="table-outer">'.
+						'<table>'.
+						'<th class="first">'.__('Preference ID').'</th>'.
+						'<th>'.__('Workspace').'</th>'.
+						'<th>'.__('Length').'</th>';
+					while ($rs->fetch()) {
+						$this->list .=
+							'<tr class="line" id="p-'.$rs->pref_id.'">'.
+							'<td class="maximal" scope="row">'.html::escapeHTML($rs->pref_id).'</td>'.
+							'<td>'.html::escapeHTML($rs->pref_ws).'</td>'.
+							'<td class="nowrap count">'.$rs->xlen.'</td>'.
+							'</tr>';
+					}
+					$this->list .=
+						'</table>'.
+						'</div>';
+				}
+				$code++;
+				break;
+			case 5:
+				# check settings
+				$this->list = __('All Blog settings are importable in UTF8-mb4 database');
+
+				$rs = $this->core->con->select(
+					'SELECT setting_id, setting_ns, LENGTH(setting_id) AS xlen FROM '.$this->core->prefix.'setting '.
+					'WHERE LENGTH(setting_id) > '.UTF8MB4_MAXLEN.' ORDER BY setting_ns,setting_id', true);
+				if (!$rs->isEmpty()) {
+					$this->list =
+						'<p class="step-msg">'.
+						sprintf(__('%s Blog setting IDs are longer than %d characters:'),$rs->count(),UTF8MB4_MAXLEN).'</p>'.
+						'<div class="table-outer">'.
+						'<table>'.
+						'<th class="first">'.__('Setting ID').'</th>'.
+						'<th>'.__('Namespace').'</th>'.
+						'<th>'.__('Length').'</th>';
+					while ($rs->fetch()) {
+						$this->list .=
+							'<tr class="line" id="s-'.$rs->setting_id.'">'.
+							'<td class="maximal" scope="row">'.html::escapeHTML($rs->setting_id).'</td>'.
+							'<td>'.html::escapeHTML($rs->setting_ns).'</td>'.
+							'<td class="nowrap count">'.$rs->xlen.'</td>'.
+							'</tr>';
+					}
+					$this->list .=
+						'</table>'.
+						'</div>';
+				}
+				$code++;
+				break;
+			default:
+				# Ending check
+				$code = null;
+				break;
+		}
+		return $code;
+	}
+
+}
