Incompatibilité avec internet explorer (problème d'UTF-8 je suppose)

Eléphanteau du PHP | 29 Messages

10 nov. 2007, 13:42

Bonjour,

Voici la page incriminée : http://www.tokidoki.fr/?mod=dico_kanji& ... 7%E9%81%93

C'est un formulaire de recherche de kanji (caractères chinois utilisés dans la langue japonaise). Il permet d'obtenir des informations, les sens, la prononciation etc.


Le script fonctionne à merveille sur mozilla, firefox, safari, mais sur IE, ça ne passe pas ! Il interprète les caractères japonais comme des points d'interrogation.

Parfois je me demande s'il y a une vraie volonté de standardiser l'UTF-8 par défaut.


Mon script se sépare en deux parties :

Le formulaire
<script src="../js/js_dico_kanji.php?k=<?php echo $_GET['k']; ?>" type="text/javascript"></script>
<img src="http://www.tokidoki.fr/functions/gd_title.php?t=Recherche de Kanji" alt="Titre" class="gd_title" />
<form id="dico_kanji" method="get" action="">
	<p><input type="hidden"name="mod" value="dico_kanji" />
	<input type="text" name="k" id="textfield" value "" class="input_textfield" />
	<input type="submit" class="input_button" value="Rechercher" /></p>
</form>
<div id="result"></div>

Le script ajax
<?php

if (isset($_GET['k']))
{
	include '../admin/mysql.php';
	include '../functions/functions.php';
	$char = str_split(utf8_to_html($_GET['k']), 8);
	$lien = '';
	$affichage = '';
	foreach ($char as $value)
	{
		$sql = "SELECT * FROM `dico_kanji` WHERE `literal` LIKE '".html_to_utf8($value)."'";
		$req = @mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
		if (mysql_affected_rows())
		{
			while ($data = mysql_fetch_array($req))
			{
				$lien .= '<a href="#'.$value.'" class="dico_kanji_right">'. $value .'</a><br />';
				$literal_strip = utf8_to_html_stripped(html_to_utf8($value));
				
				$affichage .= '<p></p><table width="80%" border="1" align="center" cellpadding="10" cellspacing="0" bordercolor="#000000">
					<tr>';
				
				$calligraphie = '/home/tokidoki/www/database/calligraphie/'. $literal_strip .'.jpg';
				if (file_exists($calligraphie))
				{
					$affichage .= '<td width="50%">
							<div align="center">
							<img src="./functions/calli_invert.php?calli='. $literal_strip .'" width="250" height="250" alt="Kanji '. $value .'" /><br />
							<em>Version calligraphiée</em>
							</div>
						</td>';
				}
				
				$affichage .= '<td colspan="2" width="50%">
					<div align="center">
						<span class="kanji_typo" id="'.$value.'">'. $value .'</span><br />
						</span><em>Version typographique</em>
					</div>
				</td>';		
						
				$affichage .= '</tr>
				<tr>
					<td valign="top" width="50%">
						<p><em><strong>Sens de '. $value .' en anglais :</strong></em></p>
						<ul>';
						
						$meanings = explode(", ", $data['meaning_m_lang_en']);
						foreach($meanings as $meaning)
						{
							$affichage .= '<li>'. $meaning .'</li>';
						}
						
						$affichage .= '</ul>
					</td>
					<td colspan="2" valign="top" width="50%">
						<p><strong><em>Radical de '. $value .' :</em></strong></p>';
						//<p>Il est composé de X X X X</p>
						$affichage .= '<p>Ce caractère comporte '. $data['misc_stroke_count'] .' traits.<br />';
						if ($data['misc_grade'])
						{
							if ($data['misc_grade'] == 1) $affichage .= 'Il est enseigné en 1ère année au Japon (CP en France).<br />';
							elseif ($data['misc_grade'] == 2) $affichage .= 'Il est enseigné en 2ème année au Japon (CE1 en France).<br />';
							elseif ($data['misc_grade'] == 3) $affichage .= 'Il est enseigné en 3ème année au Japon (CE2 en France).<br />';
							elseif ($data['misc_grade'] == 4) $affichage .= 'Il est enseigné en 4ème année au Japon (CM1 en France).<br />';
							elseif ($data['misc_grade'] == 5) $affichage .= 'Il est enseigné en 5ème année au Japon (CM2 en France).<br />';
							elseif ($data['misc_grade'] == 6) $affichage .= 'Il est enseigné en 6ème année au Japon (6ème en France).<br />';
							elseif ($data['misc_grade'] == 8) $affichage .= 'Il est enseigné au Collège-Lycée.<br />';
							elseif ($data['misc_grade'] == 9) $affichage .= 'Il est enseigné à l\'université.<br />';
						}
						
						//echo 'Il fait partie des 2500 caractères les plus utilisés dans les journaux (3180ème place).<br />
						$affichage .= '</p>
					</td>
				</tr>
				<tr>';
						if (empty($data['dr_type_sh_kk']) && 
						empty($data['dr_type_nelson_n']) && 
						empty($data['dr_type_nelson_c']) && 
						empty($data['dr_type_heisig']) &&
						empty($data['dr_type_kodansha_compact']) &&
						empty($data['dr_type_kanji_in_context']) &&
						empty($data['dr_type_moro']) &&
						empty($data['dr_type_gakken']) &&
						empty($data['dr_type_oneill_kk']) &&
						empty($data['dr_type_oneill_names']) &&
						empty($data['dr_type_halpern_kkld']) &&
						empty($data['dr_type_halpern_njecd']) &&
						empty($data['dr_type_busy_people']) &&
						empty($data['dr_type_sakade']) &&
						empty($data['dr_type_henshall3']) &&
						empty($data['dr_type_tutt_cards']) &&
						empty($data['dr_type_crowley']))
						{
							$affichage .= '<td valign="top" colspan="2">';
						}
						else
						{ 
							$affichage .= '<td valign="top" width="50%">';
						}
						if ($data['r_type_ja_kun'])
						{
							$readings = explode(", ", $data['r_type_ja_kun']);
							$affichage .= '<p><em><strong>Prononciation japonaise (kun-yomi) :</strong></em></p>
							<ul>';
							foreach ($readings as $reading) $affichage .= '<li><acronym title="'. kana2romaji($reading) .'">'. $reading .'</acronym></li>';
							$affichage .= '</ul>';
						}
						
						if ($data['r_type_ja_on'])
						{
							$readings = explode(", ", $data['r_type_ja_on']);
							$affichage .= '<p><em><strong>Prononciation chinoise (on-yomi) :</strong></em></p>
							<ul>';
							foreach ($readings as $reading) $affichage .= '<li><acronym title="'. kana2romaji($reading) .'">'. $reading .'</acronym></li>';
							$affichage .= '</ul>';
						}
						if ($data['reading_nanori'])
						{
							$readings = explode(", ", $data['reading_nanori']);
							$affichage .= '<p><em><strong>Prononciation dans un nom propre (nanori-yomi) :</strong></em></p>
							<ul>';
							foreach ($readings as $reading) $affichage .= '<li><acronym title="'. kana2romaji($reading) .'">'. $reading .'</acronym></li>';
							$affichage .= '</ul>';
						}
						
						if (empty($data['q_type_skip']) && 
						empty($data['q_type_sh_desc']) && 
						empty($data['q_type_four_corner']) && 
						empty($data['q_type_deroo'])) {}
						else
						{
							$affichage .= '<p><em><strong>Classifications :</strong></em></p>
							<ul>';
								if ($data['q_type_skip']) $affichage .= '<li>Code SKIP : '. $data['q_type_skip'] .'</li>';
								if ($data['q_type_sh_desc']) $affichage .= '<li>The Kanji Dictionary : '. $data['q_type_sh_desc'] .'</li>';
								if ($data['q_type_four_corner']) $affichage .= '<li>Four Corner Code : '. $data['q_type_four_corner'] .'</li>';
								if ($data['q_type_deroo']) $affichage .= '<li>2001 Kanji : '. $data['q_type_deroo'] .'</li>';
							$affichage .= '</ul>';
						}
						
						$affichage .= '<p><strong><em>Information d\'encoding :</em></strong></p>
						<ul>';
							if ($data['cp_type_jis208']) $affichage .= '<li>JIS-208 : '. $data['cp_type_jis208'] .'</li>';
							elseif ($data['cp_type_jis212']) $affichage .= '<li>JIS-212 : '. $data['cp_type_jis212'] .'</li>';
							elseif ($data['cp_type_jis213']) $affichage .= '<li>JIS-213 : '. $data['cp_type_jis213'] .'</li>';
							
							$affichage .= '<li>Unicode : '. $data['cp_type_ucs'] .'</li>
						</ul>
					</td>';;
						if (empty($data['dr_type_sh_kk']) && 
						empty($data['dr_type_nelson_n']) && 
						empty($data['dr_type_nelson_c']) && 
						empty($data['dr_type_heisig']) &&
						empty($data['dr_type_kodansha_compact']) &&
						empty($data['dr_type_kanji_in_context']) &&
						empty($data['dr_type_moro']) &&
						empty($data['dr_type_gakken']) &&
						empty($data['dr_type_oneill_kk']) &&
						empty($data['dr_type_oneill_names']) &&
						empty($data['dr_type_halpern_kkld']) &&
						empty($data['dr_type_halpern_njecd']) &&
						empty($data['dr_type_busy_people']) &&
						empty($data['dr_type_sakade']) &&
						empty($data['dr_type_henshall3']) &&
						empty($data['dr_type_tutt_cards']) &&
						empty($data['dr_type_crowley']))
						{}
						else
						{
							
							$affichage .= '<td valign="top" width="50%">
							<p><em><strong>Références croisées :</strong></em></p>
							<ul>';
								if ($data['dr_type_sh_kk']) $affichage .= '<li>Kanji et Kana : '. $data['dr_type_sh_kk'] .'</li>';
								if ($data['dr_type_nelson_n']) $affichage .= '<li>New Nelson : '. $data['dr_type_nelson_n'] .'</li>';
								if ($data['dr_type_nelson_c']) $affichage .= '<li>Classic Nelson : '. $data['dr_type_nelson_c'] .'</li>';
								if ($data['dr_type_heisig']) $affichage .= '<li>Remembering the Kanji :'. $data['dr_type_heisig'] .'</li>';
								if ($data['dr_type_kodansha_compact']) $affichage .= '<li>The Kodansha Compact Kanji Guide : '. $data['dr_type_kodansha_compact'] .'</li>';
								if ($data['dr_type_kanji_in_context']) $affichage .= '<li>Kanji in Context : '. $data['dr_type_kanji_in_context'] .'</li>';
								if ($data['dr_type_moro']) $affichage .= '<li>Daikanwa Jiten (Morohashi) : '. $data['dr_type_moro'] .', Volume '. $data['dr_type_m_vol'] .', page '.	$data['dr_type_m_page'] .'</li>';
								if ($data['dr_type_gakken']) $affichage .= '<li>A New Dictionary of Kanji Usage : '. $data['dr_type_gakken'] .'</li>';
								if ($data['dr_type_oneill_kk']) $affichage .= '<li>Essential Kanji : '. $data['dr_type_oneill_kk'] .'</li>';
								if ($data['dr_type_oneill_names']) $affichage .= '<li>Japanese Names : '. $data['dr_type_oneill_names'] .'</li>';
								if ($data['dr_type_halpern_kkld']) $affichage .= '<li>Kanji Learners Dictionary : '. $data['dr_type_halpern_kkld'] .'</li>';
								if ($data['dr_type_halpern_njecd']) $affichage .= '<li>New Japanese English Character Dictionary : '. $data['dr_type_halpern_njecd'] .'</li>';
								if ($data['dr_type_busy_people']) $affichage .= '<li>Japanese for Busy People : '. $data['dr_type_busy_people'] .'</li>';
								if ($data['dr_type_sakade']) $affichage .= '<li>A guide to reading and writing japanese : '. $data['dr_type_sakade'] .'</li>';
								if ($data['dr_type_henshall3']) $affichage .= '<li>A guide to remembering the japanese characters : '. $data['dr_type_henshall3'] .'</li>';
								if ($data['dr_type_tutt_cards']) $affichage .= '<li>Tuttle Kanji Cards : '. $data['dr_type_tutt_cards'] .'</li>';
								if ($data['dr_type_crowley']) $affichage .= '<li>The kanji way to japanese language power : '. $data['dr_type_crowley'] .'</li>';
							$affichage .= '</ul>
						</td>';
						
						}
					$affichage .= '</tr>
			</table>
			<p></p>';		
			}
		}
		else {
			$affichage .= '<b>"'.$value.'"</b> ne correspond à aucun kanji répertorié !<br />';
		}
	}
	echo '<div id="test" style="position: fixed; height: 50px; width: 50px; right: 10px;">';
	echo $lien;
	echo '</div>';
	echo $affichage;
}


?>

Si vous voyez à quel endroit j'ai fait une erreur, merci de m'aider.







MàJ : Le fichier de fonctions liées à l'UTF-8, peut-être que l'erreur est là :
function utf8_to_html($data)
{
	return preg_replace("/([\\xC0-\\xF7]{1,1}[\\x80-\\xBF]+)/e", '_utf8_to_html("\\1")', $data);
}

function _utf8_to_html($data)
{
	$ret = 0;
	foreach((str_split(strrev(chr((ord($data{0}) % 252 % 248 % 240 % 224 % 192) + 128) . substr($data, 1)))) as $k => $v)
	{
		$ret += (ord($v) % 128) * pow(64, $k);
	}
	return "&#$ret;";
}

function utf8_to_html_stripped($data)
{
	$ret = 0;
	foreach((str_split(strrev(chr((ord($data{0}) % 252 % 248 % 240 % 224 % 192) + 128) . substr($data, 1)))) as $k => $v)
	{
		$ret += (ord($v) % 128) * pow(64, $k);
	}
	return "$ret";
}

function html_to_utf8($data)
{
	return preg_replace("/\\&\\#([0-9]{3,10})\\;/e", '_html_to_utf8("\\1")', $data);
}

function _html_to_utf8($data)
{
	if ($data > 127)
	{
		$i = 5;
		while (($i--) > 0)
		{
			if ($data != ($a = $data % ($p = pow(64, $i))))
			{
				$ret = chr(base_convert(str_pad(str_repeat(1, $i + 1), 8, "0"), 2, 10) + (($data - $a) / $p));
				for ($i; $i > 0; $i--)
				$ret .= chr(128 + ((($data % pow(64, $i)) - ($data % ($p = pow(64, $i - 1)))) / $p));
				break;
			}
		}
	}
	else
	$ret = "&#$data;";
	return $ret;
}

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

10 nov. 2007, 14:20

Je n'ai pas lu ton script, mais d'après ce que j'ai vu en utilisant ton lien, le problème ne vient pas d'IE. Peut-être as-tu installé un module Apache qui fait un excès de zèle lorsque le navigateur n'envoit pas d'en-tête Accept-Charset, comme c'est le cas avec la version d'IE que j'ai essayé.

Une version simple de vérifier cette théorie :
var_dump(bin2hex($_GET['k']));
Mets ça sur ta page et vois si le résultat diffère d'un navigateur à l'autre. Si c'est le cas, j'imagine que tu as quelque part un bout de code pour générer cette URL, qui ressemble à
echo '?mod=dico_kanji&k=' . urlencode($k);
À la place, utilise
echo '?mod=dico_kanji&k=' . bin2hex($k);
...puis dans le script où tu utilises $_GET['k']:
function hex2bin($hex)
{
	return implode('', array_map('chr', array_map('hexdec', str_split($hex, 2))));
}

$k = hex2bin($_GET['k']);