Subversion Repositories Sites.tela-botanica.org

Rev

Rev 609 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 david 1
<?php
2
 
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2005                                                *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
 
13
 
14
// Ce fichier ne sera execute qu'une fois
15
if (defined("_ECRIRE_INC_ORTHO")) return;
16
define("_ECRIRE_INC_ORTHO", "1");
17
 
18
 
19
// Mettre a jour la liste locale des miroirs
20
function maj_miroirs_ortho() {
21
	$liste = explode(" ", lire_meta("liste_miroirs_ortho"));
22
	$miroirs_old = array();
23
	foreach ($liste as $index) {
24
		list($url) = explode(" ", lire_meta("miroir_ortho_$index"));
25
		$miroirs_old[$url] = $index;
26
	}
27
 
28
	// TODO: recuperer la liste dynamiquement depuis ortho.spip.net
29
	$urls = array(
30
		'http://tony.ortho.spip.net/ortho_serveur.php',
31
		'http://spip-ortho.linagora.org:18080/ortho_serveur.php',
32
		'http://ortho.spip.net/ortho_serveur.php'
33
	);
34
	$liste = array();
35
	$miroirs_new = array();
36
	$index = 1;
37
	foreach ($urls as $url) {
38
		if ($index_old = $miroirs_old[$url]) {
39
			$s = lire_meta("miroir_ortho_$index_old");
40
		}
41
		else {
42
			$s = $url." ".time();
43
		}
44
		$miroirs_new[$index] = $s;
45
		$liste[] = $index++;
46
	}
47
	foreach ($miroirs_old as $index) {
48
		effacer_meta("miroir_ortho_$index");
49
	}
50
	foreach ($miroirs_new as $index => $s) {
51
		ecrire_meta("miroir_ortho_$index", $s);
52
	}
53
	ecrire_meta("liste_miroirs_ortho", join(" ", $liste));
54
}
55
 
56
// Lire la liste des miroirs et les langues associees
57
function lire_miroirs_ortho() {
58
	global $miroirs_ortho, $index_miroirs_ortho, $duree_cache_miroirs_ortho;
59
 
60
	$miroirs_ortho = array();
61
	$index_miroirs_ortho = array();
62
 
63
	$t = time();
64
	$maj = lire_meta("maj_miroirs_ortho");
65
	if ($maj < $t - $duree_cache_miroirs_ortho) {
66
		maj_miroirs_ortho();
67
		ecrire_meta("maj_miroirs_ortho", $t);
68
		lire_metas();
69
	}
70
 
71
	$liste = explode(" ", lire_meta("liste_miroirs_ortho"));
72
	foreach ($liste as $index) {
73
		$s = explode(" ", lire_meta("miroir_ortho_$index"));
74
		$url = $s[0];
75
		$maj = $s[1];
76
		$langs = explode(",", $s[2]);
77
		// Reinitialiser periodiquement la liste des langues non-supportees
78
		if ($maj < $t - $duree_cache_miroirs_ortho) {
79
			foreach ($langs as $key => $lang) {
80
				if (substr($lang, 0, 1) == '!') unset($langs[$key]);
81
			}
82
			$s[1] = $t;
83
			$s[2] = join(",", $langs);
84
			ecrire_meta("miroir_ortho_$index", join(" ", $s));
85
		}
86
		$index_miroirs_ortho[$url] = $index;
87
		$miroirs_ortho[$url] = array();
88
		foreach ($langs as $lang) {
89
			if ($lang) $miroirs_ortho[$url][$lang] = $lang;
90
		}
91
	}
92
	lire_metas();
93
	mt_srand(time());
94
}
95
 
96
// Sauvegarder les infos de langues pour le miroir
97
function ecrire_miroir_ortho($url, $langs) {
98
	global $index_miroirs_ortho;
99
 
100
	$index = $index_miroirs_ortho[$url];
101
	$s = explode(" ", lire_meta("miroir_ortho_$index"));
102
	$s[2] = join(",", $langs);
103
	ecrire_meta("miroir_ortho_$index", join(" ", $s));
104
}
105
 
106
function ajouter_langue_miroir($url, $lang) {
107
	global $miroirs_ortho;
108
	$langs = $miroirs_ortho[$url];
109
	$langs[$lang] = $lang;
110
	unset($langs["!$lang"]);
111
	ecrire_miroir_ortho($url, $langs);
112
}
113
 
114
function enlever_langue_miroir($url, $lang) {
115
	global $miroirs_ortho;
116
	$langs = $miroirs_ortho[$url];
117
	unset($langs[$lang]);
118
	$langs["!$lang"] = "!$lang";
119
	ecrire_miroir_ortho($url, $langs);
120
}
121
 
122
function reset_miroir($url) {
123
	global $miroirs_ortho;
124
	ecrire_miroir_ortho($url, array());
125
}
126
 
127
//
128
// Renvoie la liste des miroirs utilisables pour une langue donnee
129
//
130
function chercher_miroirs_ortho($lang) {
131
	global $miroirs_ortho;
132
 
133
	$result = array();
134
	$chercher = true;
135
	foreach ($miroirs_ortho as $url => $langs) {
136
		if ($langs[$lang]) {
137
			$result[] = $url;
138
		}
139
		else if ($chercher && !$langs["!$lang"]) {
140
			//echo "test $lang $url<br />";
141
			if (verifier_langue_miroir($url, $lang)) $result[] = $url;
142
			// Ne recuperer la langue d'un miroir qu'une seule fois par requete
143
			if ($result) $chercher = false;
144
		}
145
	}
146
	return $result;
147
}
148
 
149
function choisir_miroirs_ortho($lang) {
150
	$liste = chercher_miroirs_ortho($lang);
151
	if (!count($liste)) return false;
152
	foreach ($liste as $url) {
153
		$miroirs[md5(mt_rand().$url.rand())] = $url;
154
	}
155
	ksort($miroirs);
156
	return $miroirs;
157
}
158
 
159
//
160
// Envoyer une requete a un serveur d'orthographe
161
//
162
function post_ortho($url, $texte, $lang) {
163
	include_ecrire('inc_sites.php3');
164
 
165
	list($f, $fopen) = init_http('POST', $url);
166
	if (!$f OR $fopen) {
167
		spip_log("Echec connexion $url");
168
		return false;
169
	}
170
 
171
	// Si le texte est petit, l'overhead du multipart est dispendieux
172
	if (!$GLOBALS['flag_gz'] || strlen($texte) < 200) {
173
		$gz = false;
174
		$body = "op=spell&lang=".urlencode($lang)."&texte=".urlencode($texte);
175
		fputs($f, "Content-Type: application/x-www-form-urlencoded\r\n");
176
	}
177
	// Sinon, on passe en multipart pour compresser la chaine a corriger
178
	else {
179
		// Il faut eliminer les caracteres 0 sinon PHP ne lit pas la suite du parametre
180
		// passe en multipart/form-data (gros hack bien sale)
181
		$texte_gz = gzcompress($texte);
182
		for ($echap = 255; $echap > 0; $echap--) {
183
			$str_echap = chr($echap ^ 1).chr($echap).chr($echap).chr($echap ^ 2);
184
			if (!is_int(strpos($texte_gz, $str_echap))) break;
185
		}
186
		$texte_gz = str_replace("\x00", $str_echap, $texte_gz);
187
		$gz = true;
188
		$vars = array('op' => 'spell', 'lang' => $lang, 'texte' => $texte_gz, 'gz' => 1, 'nul_echap' => $str_echap);
189
		$boundary = substr(md5(rand().'ortho'), 0, 8);
190
		$body = '';
191
		foreach ($vars as $key => $val) {
192
			$body .= "\r\n--$boundary\r\n";
193
			$body .= "Content-Disposition: form-data; name=\"$key\"\r\n";
194
			$body .= "\r\n";
195
			$body .= $val;
196
		}
197
		$body .= "\r\n--$boundary\r\n";
198
		fputs($f, "Content-Type: multipart/form-data; boundary=$boundary\r\n");
199
	}
200
 
201
	// On envoie le contenu
202
	fputs($f, "Content-Length: ".strlen($body)."\r\n");
203
	fputs($f, "\r\n");	// Fin des entetes
204
	fputs($f, $body);
205
 
206
	// Lire les en-tetes HTTP de la reponse et decoder le Content-Length
207
	$length = 0;
208
	$s = fgets($f, 1000);
209
	$statut = 0;
210
	if (preg_match(',^HTTP/\d+\.\d+ (\d+) ,', $s, $r))
211
		$statut = intval($r[1]);
212
	if ($statut != 200) {
213
		fclose($f);
214
		return false;
215
	}
216
	while ($s = trim(fgets($f, 1000))) {
217
		if (preg_match(',Content-Length:(.*),i', $s, $r))
218
			$length = intval($r[1]);
219
	}
220
	$r = "";
221
 
222
	// Lire le corps de la reponse HTTP
223
	if ($length) {
224
		while (($l = strlen($r)) < $length) $r .= fread($f, $length - $l);
225
	}
226
	else while (!feof($f) AND $r .= fread($f, 1024));
227
 
228
	fclose($f);
229
	if ($gz) $r = gzuncompress($r);
230
	return $r;
231
}
232
 
233
//
234
// Verifier si un serveur gere une langue donnee
235
//
236
function verifier_langue_miroir($url, $lang) {
237
	// Envoyer une requete bidon
238
	$result = post_ortho($url, " ", $lang);
239
	if (!preg_match(',<ortho>.*</ortho>,s', $result)) {
240
		reset_miroir($url);
241
		return false;
242
	}
243
	if (!preg_match(',<erreur>.*<code>E_LANG_ABSENT</code>.*</erreur>,s', $result)) {
244
		ajouter_langue_miroir($url, $lang);
245
		return true;
246
	}
247
	enlever_langue_miroir($url, $lang);
248
	return false;
249
}
250
 
251
 
252
//
253
// Gestion du dictionnaire local
254
//
255
function suggerer_dico_ortho(&$mots, $lang) {
256
	$lang = addslashes($lang);
257
	$query = "SELECT mot FROM spip_ortho_dico WHERE lang='$lang' ".
258
		"AND mot IN ('".join("', '", array_map('addslashes', $mots))."')";
259
	$result = spip_query($query);
260
 
261
	$mots = array_flip($mots);
262
	$bons = array();
263
	if (isset($mots[''])) unset($mots['']);
264
	while ($row = spip_fetch_array($result)) {
265
		$mot = $row['mot'];
266
		if (isset($mots[$mot])) {
267
			unset($mots[$mot]);
268
			$bons[] = $mot;
269
		}
270
	}
271
 
272
	if (count($mots)) $mots = array_flip($mots);
273
	else $mots = array();
274
	return $bons;
275
}
276
 
277
function ajouter_dico_ortho($mot, $lang) {
278
	global $connect_id_auteur;
279
 
280
	$lang = addslashes($lang);
281
	$mot = addslashes($mot);
282
	$id_auteur = intval($connect_id_auteur);
283
	$query = "INSERT IGNORE INTO spip_ortho_dico (lang, mot, id_auteur) ".
284
		"VALUES ('$lang', '$mot', '$id_auteur')";
285
	spip_query($query);
286
}
287
 
288
function supprimer_dico_ortho($mot, $lang) {
289
	$lang = addslashes($lang);
290
	$mot = addslashes($mot);
291
	$query = "DELETE FROM spip_ortho_dico WHERE lang='$lang' AND mot='$mot'";
292
	spip_query($query);
293
}
294
 
295
function gerer_dico_ortho($lang) {
296
	global $ajout_ortho, $supp_ortho;
297
	if ($mot = strval($ajout_ortho)) {
298
		ajouter_dico_ortho($mot, $lang);
299
	}
300
	if ($mot = strval($supp_ortho)) {
301
		supprimer_dico_ortho($mot, $lang);
302
	}
303
}
304
 
305
 
306
//
307
// Gestion du cache de corrections
308
//
309
function suggerer_cache_ortho(&$mots, $lang) {
310
	global $duree_cache_ortho;
311
 
312
	$lang = addslashes($lang);
313
	$query = "SELECT mot, ok, suggest FROM spip_ortho_cache WHERE lang='$lang' ".
314
		"AND mot IN ('".join("', '", array_map('addslashes', $mots))."') ".
315
		"AND maj > FROM_UNIXTIME(".(time() - $duree_cache_ortho).")";
316
	$result = spip_query($query);
317
 
318
	$mots = array_flip($mots);
319
	$suggest = array();
320
	if (isset($mots[''])) unset($mots['']);
321
	while ($row = spip_fetch_array($result)) {
322
		$mot = $row['mot'];
323
		if (isset($mots[$mot])) {
324
			unset($mots[$mot]);
325
			if (!$row['ok']) {
326
				if (strlen($row['suggest']))
327
					$suggest[$mot] = explode(",", $row['suggest']);
328
				else
329
					$suggest[$mot] = array();
330
			}
331
		}
332
	}
333
	if (count($mots)) $mots = array_flip($mots);
334
	else $mots = array();
335
	return $suggest;
336
}
337
 
338
function ajouter_cache_ortho($tous, $mauvais, $lang) {
339
	global $duree_cache_ortho;
340
 
341
	$values = array();
342
	$lang = addslashes($lang);
343
	if (count($mauvais)) {
344
		foreach ($mauvais as $mot => $suggest) {
345
			$values[] = "('$lang', '".addslashes($mot)."', 0, '".addslashes(join(",", $suggest))."')";
346
		}
347
	}
348
	if (count($tous)) {
349
		foreach ($tous as $mot) {
350
			if (!isset($mauvais[$mot]))
351
				$values[] = "('$lang', '".addslashes($mot)."', 1, '')";
352
		}
353
	}
354
	if (count($values)) {
355
		$query = "DELETE FROM spip_ortho_cache ".
356
			"WHERE maj < FROM_UNIXTIME(".(time() - $duree_cache_ortho).")";
357
		spip_query($query);
358
		$query = "INSERT IGNORE INTO spip_ortho_cache (lang, mot, ok, suggest) ".
359
			"VALUES ".join(", ", $values);
360
		spip_query($query);
361
	}
362
}
363
 
364
 
365
//
366
// Cette fonction doit etre appelee pour reecrire le texte en utf-8 "propre"
367
//
368
function preparer_ortho($texte, $lang) {
369
	include_spip("charsets.php");
370
 
371
	$charset = lire_meta('charset');
372
 
373
	if ($charset == 'utf-8')
374
		return unicode_to_utf_8(html2unicode($texte));
375
	else
376
		return unicode_to_utf_8(html2unicode(charset2unicode($texte, $charset, true)));
377
}
378
 
379
function afficher_ortho($texte) {
380
	$charset = lire_meta('charset');
381
	if ($charset == 'utf-8') return $texte;
382
 
383
	if (!is_array($texte)) return charset2unicode($texte, 'utf-8');
384
	foreach ($texte as $key => $val) {
385
		$texte[$key] = afficher_ortho($val);
386
	}
387
	return $texte;
388
}
389
 
390
//
391
// Cette fonction envoie le texte prepare a un serveur d'orthographe
392
// et retourne un tableau de mots mal orthographies associes chacun a un tableau de mots suggeres
393
//
394
function corriger_ortho($texte, $lang, $charset = 'AUTO') {
395
	include_spip("charsets.php");
396
	include_spip("index.php");
397
	include_spip("filtres.php");
398
 
399
	$texte = preg_replace(',<code>.*?</code>,is', '', $texte);
400
	$texte = preg_replace(',<cadre>.*?</cadre>,is', '', $texte);
401
	$texte = preg_replace(',\[([^][]*)->([^][]*)\],is', '\\1', $texte);
402
	$texte = supprimer_tags($texte);
403
 
404
	$texte = " ".$texte." ";
405
 
406
	// Virer les caracteres non-alphanumeriques
407
	if (test_pcre_unicode()) {
408
		$texte = preg_replace(',[^-\''.pcre_lettres_unicode().']+,us', ' ', $texte);
409
	}
410
	else {
411
		// Ici bidouilles si PCRE en mode UTF-8 ne fonctionne pas correctement ...
412
		// Caracteres non-alphanumeriques de la plage latin-1 + saloperies non-conformes
413
		$texte = preg_replace(',\xC2[\x80-\xBF],', ' ', $texte);
414
		// Poncutation etendue (unicode)
415
		$texte = preg_replace(",".plage_punct_unicode().",", ' ', $texte);
416
		// Caracteres ASCII non-alphanumeriques
417
		$texte = preg_replace(",[^-a-zA-Z0-9\x80-\xFF']+,", ' ', $texte);
418
	}
419
	$texte = preg_replace(', [-\']+,', ' ', $texte); // tirets de typo
420
	$texte = preg_replace(',\' ,', ' ', $texte); // apostrophes utilisees comme guillemets
421
 
422
	//echo htmlspecialchars($texte)."<br>";
423
 
424
	// Virer les mots contenant au moins un chiffre
425
	$texte = preg_replace(', ([^ ]*\d[^ ]* )+,', ' ', $texte);
426
 
427
	// Melanger les mots
428
	$mots = preg_split(', +,', $texte);
429
	sort($mots);
430
	$mots = array_unique($mots);
431
 
432
	// 1. Enlever les mots du dico local
433
	$bons = suggerer_dico_ortho($mots, $lang);
434
 
435
	// 2. Enlever les mots du cache local
436
	$result_cache = suggerer_cache_ortho($mots, $lang);
437
 
438
	// 3. Envoyer les mots restants a un serveur
439
	$mauvais = array();
440
	if (count($mots)) {
441
		$texte = join(' ', $mots);
442
 
443
		// Hack : ligatures en francais pas gerees par aspell
444
		unset($trans_rev);
445
		$texte_envoi = $texte;
446
		if ($lang == 'fr') {
447
			$trans = array(chr(197).chr(146) => 'OE', chr(197).chr(147) => 'oe',
448
					chr(195).chr(134) => 'AE', chr(195).chr(166) => 'ae');
449
			$texte_envoi = strtr($texte_envoi, $trans);
450
			$trans_rev = array_flip($trans);
451
		}
452
 
453
		// POST de la requete et recuperation du resultat XML
454
		$urls = choisir_miroirs_ortho($lang);
455
		if (!$urls) return false;
456
		unset($ok);
457
		$erreur = false;
458
		foreach ($urls as $url) {
459
			$xml = post_ortho($url, $texte_envoi, $lang);
460
			if ($xml && preg_match(',<ortho>(.*)</ortho>,s', $xml, $r)) {
461
				$xml = $r[1];
462
				if (preg_match(',<erreur>.*<code>(.*)</code>.*</erreur>,s', $xml, $r))
463
					$erreur = $r[1];
464
				if (preg_match(',<ok>(.*)</ok>,s', $xml, $r)) {
465
					$ok = $r[1];
466
					break;
467
				}
468
			}
469
			reset_miroir($url);
470
		}
471
		if (!isset($ok)) return $erreur;
472
 
473
		// Remplir le tableau des resultats (mots mal orthographies)
474
		if ($trans_rev) {
475
			$assoc_mots = array_flip($mots);
476
		}
477
		while (preg_match(',<mot>(.*?)</mot>(\s*<suggest>(.*?)</suggest>)?,s', $ok, $r)) {
478
			$p = strpos($ok, $r[0]);
479
			$ok = substr($ok, $p + strlen($r[0]));
480
			$mot = $r[1];
481
			if ($suggest = $r[3])
482
				$s = preg_split('/[ ,]+/', $suggest);
483
			else
484
				$s = array();
485
			// Hack ligatures
486
			if ($trans_rev) {
487
				$mot_rev = strtr($mot, $trans_rev);
488
				if ($mot != $mot_rev) {
489
					if ($assoc_mots[$mot])
490
						$mauvais[$mot] = $s;
491
					if ($assoc_mots[$mot_rev])
492
						$mauvais[$mot_rev] = $s;
493
				}
494
				else $mauvais[$mot] = $s;
495
			}
496
			else $mauvais[$mot] = $s;
497
		}
498
	}
499
	if (!$erreur) ajouter_cache_ortho($mots, $mauvais, $lang);
500
 
501
	// Retour a l'envoyeur
502
	$mauvais = array_merge($result_cache, $mauvais);
503
	$result = array(
504
		'bons' => $bons,
505
		'mauvais' => $mauvais
506
	);
507
	if ($erreur) $result['erreur'] = $erreur;
508
	return $result;
509
}
510
 
511
//
512
// Fonctions d'affichage HTML
513
//
514
 
515
function panneau_ortho($ortho_result) {
516
	global $id_suggest;
517
 
518
	$id_suggest = array();
519
	$i = 1;
520
 
521
	$mauvais = $ortho_result['mauvais'];
522
	$bons = $ortho_result['bons'];
523
	if (!count($mauvais) && !count($bons)) return;
524
	ksort($mauvais);
525
 
526
	echo "<script type='text/javascript'><!--
527
	var curr_suggest = null;
528
	function suggest(id) {
529
		var menu_box;
530
		if (curr_suggest)
531
			document.getElementById('suggest' + curr_suggest).className = 'suggest-inactif';
532
		if (1 || id!=curr_suggest) {
533
			document.getElementById('suggest' + id).className = 'suggest-actif';
534
			curr_suggest = id;
535
		}
536
		else curr_suggest = null;
537
		menu_box = document.getElementById('select_ortho');
538
		if (menu_box.length > id) menu_box.selectedIndex = id;
539
	}";
540
	echo "//--></script>";
541
 
542
	echo "<form class='form-ortho verdana2' action='' method='get'>\n";
543
	echo "<select name='select_ortho' id='select_ortho' onChange='suggest(this.selectedIndex);'>\n";
544
	echo "<option value='0'>... "._T('ortho_mots_a_corriger')." ...</option>\n";
545
	foreach ($mauvais as $mot => $suggest) {
546
		$id = $id_suggest[$mot] = "$i";
547
		$i++;
548
		$mot_html = afficher_ortho($mot);
549
		echo "<option value='$id'>$mot_html</option>\n";
550
	}
551
	foreach ($bons as $mot) {
552
		$id = $id_suggest[$mot] = "$i";
553
		$i++;
554
	}
555
	echo "</select>\n";
556
	echo "</form>\n";
557
	// Mots mal orthographies :
558
	// liste des suggestions plus lien pour ajouter au dico
559
	foreach ($mauvais as $mot => $suggest) {
560
		$id = $id_suggest[$mot];
561
		$mot_html = afficher_ortho($mot);
562
		echo "<div class='suggest-inactif' id='suggest$id'>";
563
		echo "<span class='ortho'>$mot_html</span>\n";
564
		echo "<div class='detail'>\n";
565
		if (is_array($suggest) && count($suggest)) {
566
			echo "<ul>\n";
567
			$i = 0;
568
			foreach ($suggest as $sug) {
569
				if (++$i > 12) {
570
					echo "<li><i>(...)</i></li>\n";
571
					break;
572
				}
573
				echo "<li>".typo(afficher_ortho($sug))."</li>\n";
574
			}
575
			echo "</ul>\n";
576
		}
577
		else {
578
			echo "<i>"._T('ortho_aucune_suggestion')."</i>";
579
		}
580
		echo "<br />";
581
		$link = new Link;
582
		$link->delVar('supp_ortho');
583
		$link->addVar('ajout_ortho', $mot);
584
		icone_horizontale(_T('ortho_ajouter_ce_mot'), $link->getUrl(), "ortho-24.gif", "creer.gif");
585
		echo "</div>\n";
586
		echo "</div>\n\n";
587
	}
588
	// Mots trouves dans le dico :
589
	// message plus lien pour retirer du dico
590
	foreach ($bons as $mot) {
591
		$id = $id_suggest[$mot];
592
		$mot_html = afficher_ortho($mot);
593
		echo "<div class='suggest-inactif' id='suggest$id'>";
594
		echo "<span class='ortho-dico'>$mot_html</span>";
595
		echo "<div class='detail'>\n";
596
		echo "<i>"._T('ortho_ce_mot_connu')."</i>";
597
		echo "<br />";
598
		$link = new Link;
599
		$link->delVar('ajout_ortho');
600
		$link->addVar('supp_ortho', $mot);
601
		icone_horizontale(_T('ortho_supprimer_ce_mot'), $link->getUrl(), "ortho-24.gif", "supprimer.gif");
602
		echo "</div>\n";
603
		echo "</div>\n";
604
	}
605
}
606
 
607
 
608
function souligner_match_ortho(&$texte, $cherche, $remplace) {
609
	// Eviter les &mdash;, etc.
610
	if ($cherche{0} == '&' AND $cherche{strlen($cherche) - 1} == ';') return;
611
 
612
	if ($cherche{0} == '>')
613
		$texte = str_replace($cherche, $remplace, $texte);
614
	else {
615
		// Ne pas remplacer a l'interieur des tags HTML
616
		$table = explode($cherche, $texte);
617
		unset($avant);
618
		$texte = '';
619
		foreach ($table as $s) {
620
			if (!isset($avant)) {
621
				$avant = $s;
622
				continue;
623
			}
624
			$ok = true;
625
			$texte .= $avant;
626
			// Detecter si le match a eu lieu dans un tag HTML
627
			if (is_int($deb_tag = strrpos($texte, '<'))) {
628
				if (strrpos($texte, '>') <= $deb_tag)
629
					$ok = false;
630
			}
631
			if ($ok) $texte .= $remplace;
632
			else $texte .= $cherche;
633
			$avant = $s;
634
		}
635
		$texte .= $avant;
636
	}
637
}
638
 
639
function souligner_ortho($texte, $lang, $ortho_result) {
640
	global $id_suggest;
641
	$vu = array();
642
 
643
	$mauvais = $ortho_result['mauvais'];
644
	$bons = $ortho_result['bons'];
645
 
646
	// Neutraliser l'apostrophe unicode pour surligner correctement les fautes
647
	$texte = " ".str_replace("\xE2\x80\x99", "'", $texte)." ";
648
	// Chercher et remplacer les mots un par un
649
	$delim = '[^-\''.pcre_lettres_unicode().']';
650
	foreach ($mauvais as $mot => $suggest) {
651
		$pattern = ",$delim".$mot."$delim,us";
652
		// Recuperer les occurences du mot dans le texte
653
		if (preg_match_all($pattern, $texte, $regs, PREG_SET_ORDER)) {
654
			$id = $id_suggest[$mot];
655
			$mot_html = afficher_ortho($mot);
656
			foreach ($regs as $r) {
657
				if ($vu[$cherche = $r[0]]) continue;
658
				$vu[$cherche] = 1;
659
				$html = "<a class='ortho' onclick=\"suggest($id);return false;\" href=''>$mot_html</a>";
660
				$remplace = str_replace($mot, $html, $cherche);
661
				souligner_match_ortho($texte, $cherche, $remplace);
662
			}
663
		}
664
	}
665
	foreach ($bons as $mot) {
666
		$pattern = ",$delim".$mot."$delim,us";
667
		// Recuperer les occurences du mot dans le texte
668
		if (preg_match_all($pattern, $texte, $regs, PREG_SET_ORDER)) {
669
			$id = $id_suggest[$mot];
670
			$mot_html = afficher_ortho($mot);
671
			foreach ($regs as $r) {
672
				if ($vu[$cherche = $r[0]]) continue;
673
				$vu[$cherche] = 1;
674
				$html = "<a class='ortho-dico' onclick=\"suggest($id);return false;\" href=''>$mot_html</a>";
675
				$remplace = str_replace($mot, $html, $cherche);
676
				souligner_match_ortho($texte, $cherche, $remplace);
677
			}
678
		}
679
	}
680
 
681
	$texte = preg_replace(',(^ | $),', '', $texte);
682
	return $texte;
683
}
684
 
685
function init_ortho() {
686
	global $duree_cache_ortho, $duree_cache_miroirs_ortho;
687
 
688
 	$duree_cache_ortho = 7 * 24 * 3600;
689
	$duree_cache_miroirs_ortho = 24 * 3600;
690
	lire_miroirs_ortho();
691
}
692
 
693
init_ortho();
694
 
695
?>