[ Index ] |
|
Code source de SPIP 1.8.3 |
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 // 15 // Ce fichier ne sera execute qu'une fois 16 if (defined("_ECRIRE_INC_INDEX")) return; 17 define("_ECRIRE_INC_INDEX", "1"); 18 19 function separateurs_indexation($requete = false) { 20 // Merci a Herve Lefebvre pour son apport sur cette fonction 21 $liste = "],:;*\"!\r\n\t\\/)}{[|@<>$%"; 22 23 // pour autoriser les recherches en vietnamien, 24 // ne pas eliminer les accents de translitteration 25 if (!$requete) 26 $liste .= "'`?\~.^+(-"; 27 28 // windowzeries iso-8859-1 29 $charset = lire_meta('charset'); 30 if ($charset == 'iso-8859-1') 31 $liste .= chr(187).chr(171).chr(133).chr(145).chr(146).chr(180).chr(147).chr(148); 32 33 return $liste; 34 } 35 36 function nettoyer_chaine_indexation($texte) { 37 global $translitteration_complexe; 38 include_ecrire ("inc_charsets.php3"); 39 40 // translitteration complexe (vietnamien, allemand) 41 if ($translitteration_complexe) { 42 $texte_c = translitteration_complexe ($texte); 43 $texte_c = " ".strtr($texte_c, "'`?~.^+(-", "123456789"); 44 } 45 46 $texte = translitteration($texte).$texte_c; 47 48 return $texte; 49 } 50 51 function indexer_chaine($texte, $val = 1, $min_long = 3) { 52 global $index, $mots, $translitteration_complexe; 53 54 // Nettoyer les tags, entites HTML, signes diacritiques... 55 $texte = ' '.ereg_replace("<[^>]*>"," ",$texte).' '; 56 $texte = nettoyer_chaine_indexation($texte); 57 58 // Nettoyer les caracteres non-alphanumeriques 59 $regs = separateurs_indexation(); 60 $texte = strtr($texte, $regs, ereg_replace('.', ' ', $regs)); 61 62 // Cas particulier : sigles d'au moins deux lettres 63 $texte = ereg_replace(" ([A-Z][0-9A-Z]{1,".($min_long - 1)."}) ", ' \\1___ ', $texte); 64 $texte = strtolower($texte); 65 66 // Separer les mots 67 $table = preg_split("/ +/", $texte); 68 69 while (list(, $mot) = each($table)) { 70 if (strlen($mot) > $min_long) { 71 $h = substr(md5($mot), 0, 16); 72 $index[$h] += $val/(1+$translitteration_complexe); 73 $mots .= ",(0x$h,'$mot')"; 74 } 75 } 76 } 77 78 function deja_indexe($type, $id_objet) { 79 $table_index = 'spip_index_'.table_objet($type); 80 $col_id = 'id_'.$type; 81 $query = "SELECT $col_id FROM $table_index WHERE $col_id=$id_objet LIMIT 0,1"; 82 $n = @spip_num_rows(@spip_query($query)); 83 return ($n > 0); 84 } 85 86 87 // Extracteur des documents 'txt' 88 function extracteur_txt($fichier, &$charset) { 89 lire_fichier($fichier, $contenu); 90 91 // Reconnaitre le BOM utf-8 (0xEFBBBF) 92 include_ecrire ('inc_charsets.php3'); 93 if (bom_utf8($contenu)) 94 $charset = 'utf-8'; 95 96 return $contenu; 97 } 98 99 // Extracteur des documents 'html' 100 function extracteur_html($fichier, &$charset) { 101 lire_fichier($fichier, $contenu); 102 103 // Importer dans le charset local 104 include_ecrire ('inc_charsets.php3'); 105 $contenu = transcoder_page($contenu); 106 $charset = lire_meta('charset'); 107 108 return $contenu; 109 } 110 111 // Quels formats sait-on extraire ? 112 $GLOBALS['extracteur'] = array ( 113 'txt' => 'extracteur_txt', 114 'pas' => 'extracteur_txt', 115 'c' => 'extracteur_txt', 116 'css' => 'extracteur_txt', 117 'html' => 'extracteur_html' 118 ); 119 120 // Indexer le contenu d'un document 121 function indexer_contenu_document ($row) { 122 global $extracteur; 123 124 if ($row['mode'] == 'vignette') return; 125 list($extension) = spip_fetch_array(spip_query( 126 "SELECT extension FROM spip_types_documents 127 WHERE id_type = ".$row['id_type'] 128 )); 129 130 // Voir si on sait lire le contenu (eventuellement en chargeant le 131 // fichier extract_pdf.php dans find_in_path() ) 132 if ($plugin = find_in_path('extract_'.$extension.'.php')) { 133 include_local($plugin); 134 } 135 if (function_exists($lire = $extracteur[$extension])) { 136 // Voir si on a deja une copie du doc distant 137 // Note: si copie_locale() charge le doc, elle demande une reindexation 138 if (!$fichier = copie_locale($row['fichier'], 'test')) { 139 spip_log("pas de copie locale de '$fichier'"); 140 return; 141 } 142 // par defaut, on pense que l'extracteur va retourner ce charset 143 $charset = 'iso-8859-1'; 144 // lire le contenu 145 $contenu = $lire($fichier, $charset); 146 if (!$contenu) { 147 spip_log("Echec de l'extraction de '$fichier'"); 148 } else { 149 // Ne retenir que les 50 premiers ko 150 $contenu = substr($contenu, 0, 50000); 151 // importer le charset 152 $contenu = importer_charset($contenu, $charset); 153 // Indexer le texte 154 indexer_chaine($contenu, 1); 155 } 156 } else { 157 spip_log("pas d'extracteur '$extension' fonctionnel"); 158 } 159 } 160 161 162 // Indexer les documents, auteurs, mots-cles associes a l'objet 163 function indexer_elements_associes($objet, $id_objet, $associe, $valeur) { 164 switch ($associe) { 165 case 'document': 166 $r = spip_query("SELECT doc.titre, doc.descriptif 167 FROM spip_documents AS doc, 168 spip_documents_".table_objet($objet)." AS lien 169 WHERE lien.".id_table_objet($objet)."=$id_objet 170 AND doc.id_document=lien.id_document"); 171 while ($row = spip_fetch_array($r)) { 172 indexer_chaine($row['titre'],2 * $valeur); 173 indexer_chaine($row['descriptif'],1 * $valeur); 174 } 175 break; 176 177 case 'auteur': 178 $r = spip_query("SELECT auteurs.nom 179 FROM spip_auteurs AS auteurs, 180 spip_auteurs_".table_objet($objet)." AS lien 181 WHERE lien.".id_table_objet($objet)."=$id_objet 182 AND auteurs.id_auteur=lien.id_auteur"); 183 while ($row = spip_fetch_array($r)) { 184 indexer_chaine($row['nom'], 1 * $valeur, 2); 185 } 186 break; 187 188 case 'mot': 189 $r = spip_query("SELECT mots.titre, mots.descriptif 190 FROM spip_mots AS mots, 191 spip_mots_".table_objet($objet)." AS lien 192 WHERE lien.".id_table_objet($objet)."=$id_objet 193 AND mots.id_mot = lien.id_mot"); 194 while ($row = spip_fetch_array($r)) { 195 indexer_chaine($row['titre'],4 * $valeur); 196 indexer_chaine($row['descriptif'],1 * $valeur); 197 } 198 break; 199 } 200 } 201 202 203 function indexer_objet($type, $id_objet, $forcer_reset = true) { 204 global $index, $mots, $translitteration_complexe; 205 206 $table = 'spip_'.table_objet($type); 207 $table_index = 'spip_index_'.table_objet($type); 208 $col_id = id_table_objet($type); 209 210 if (!$id_objet) return; 211 if (!$forcer_reset AND deja_indexe($type, $id_objet)) { 212 spip_log ("$type $id_objet deja indexe"); 213 spip_query("UPDATE $table SET idx='oui' WHERE $col_id=$id_objet"); 214 return; 215 } 216 // marquer "en cours d'indexation" 217 spip_query("UPDATE $table SET idx='idx' WHERE $col_id=$id_objet"); 218 219 include_ecrire ("inc_texte.php3"); 220 include_ecrire ("inc_filtres.php3"); 221 222 spip_log("indexation $type $id_objet"); 223 $index = ''; 224 $mots = ''; 225 226 $query = "SELECT * FROM $table WHERE $col_id=$id_objet"; 227 $result = spip_query($query); 228 $row = spip_fetch_array($result); 229 230 if (!$row) return; 231 232 // translitteration complexe ? 233 if (!$lang = $row['lang']) $lang = lire_meta('langue_site'); 234 if ($lang == 'de' OR $lang=='vi') { 235 $translitteration_complexe = 1; 236 spip_log ('-> translitteration complexe'); 237 } else $translitteration_complexe = 0; 238 239 switch($type) { 240 case 'article': 241 indexer_chaine($row['titre'], 8); 242 indexer_chaine($row['soustitre'], 5); 243 indexer_chaine($row['surtitre'], 5); 244 indexer_chaine($row['descriptif'], 4); 245 indexer_chaine($row['chapo'], 3); 246 indexer_chaine($row['texte'], 1); 247 indexer_chaine($row['ps'], 1); 248 indexer_chaine($row['nom_site'], 1); 249 indexer_chaine(@join(' ', unserialize($row['extra'])), 1); 250 indexer_elements_associes('article', $id_objet, 'document', 1); 251 indexer_elements_associes('article', $id_objet, 'auteur', 10); 252 indexer_elements_associes('article', $id_objet, 'mot', 3); 253 break; 254 255 case 'breve': 256 indexer_chaine($row['titre'], 8); 257 indexer_chaine($row['texte'], 2); 258 indexer_chaine(@join(' ', unserialize($row['extra'])), 1); 259 indexer_elements_associes('breve', $id_objet, 'document', 1); 260 indexer_elements_associes('breve', $id_objet, 'mot', 3); 261 break; 262 263 case 'rubrique': 264 indexer_chaine($row['titre'], 8); 265 indexer_chaine($row['descriptif'], 5); 266 indexer_chaine($row['texte'], 1); 267 indexer_chaine(@join(' ', unserialize($row['extra'])), 1); 268 indexer_elements_associes('rubrique', $id_objet, 'document', 1); 269 indexer_elements_associes('rubrique', $id_objet, 'mot', 3); 270 break; 271 272 case 'auteur': 273 indexer_chaine($row['nom'], 5, 2); 274 indexer_chaine($row['bio'], 1); 275 indexer_chaine(@join(' ', unserialize($row['extra'])), 1); 276 break; 277 278 case 'mot': 279 indexer_chaine($row['titre'], 8); 280 indexer_chaine($row['descriptif'], 5); 281 indexer_chaine($row['texte'], 1); 282 indexer_chaine(@join(' ', unserialize($row['extra'])), 1); 283 break; 284 285 case 'signature': 286 indexer_chaine($row['nom_email'], 2, 2); 287 indexer_chaine($row['ad_email'], 2); 288 indexer_chaine($row['nom_site'], 2); 289 indexer_chaine($row['url_site'], 1); 290 indexer_chaine($row['message'], 1); 291 break; 292 293 case 'syndic': 294 indexer_chaine($row['nom_site'], 50); 295 indexer_chaine($row['descriptif'], 30); 296 indexer_elements_associes('syndic', $id_objet, 'document', 1); 297 indexer_elements_associes('syndic', $id_objet, 'mot', 3); 298 299 // Ajouter les titres des articles syndiques de ce site, le cas echeant 300 if ($row['syndication'] = "oui") { 301 $query_syndic = "SELECT titre FROM spip_syndic_articles 302 WHERE id_syndic=$id_objet AND statut='publie' 303 ORDER BY date DESC LIMIT 0,100"; 304 $result_syndic = spip_query($query_syndic); 305 while ($row_syndic = spip_fetch_array($result_syndic)) { 306 indexer_chaine($row_syndic['titre'], 5); 307 } 308 } 309 // Aller chercher la page d'accueil 310 if (lire_meta("visiter_sites") == "oui") { 311 include_ecrire ("inc_sites.php3"); 312 spip_log ("indexation contenu syndic ".$row['url_site']); 313 indexer_chaine(supprimer_tags( 314 recuperer_page($row['url_site'], true, false, 50000) 315 ), 1); 316 } 317 break; 318 319 // 320 // Cas tres particulier du forum : 321 // on indexe le thread comme un tout 322 case 'forum': 323 // 1. chercher la racine du thread 324 $id_forum = $id_objet; 325 while ($row['id_parent']) { 326 $id_forum = $row['id_parent']; 327 $s = spip_query("SELECT id_forum,id_parent FROM spip_forum WHERE id_forum=$id_forum"); 328 $row = spip_fetch_array($s); 329 } 330 331 // 2. chercher tous les forums du thread 332 // (attention le forum de depart $id_objet n'appartient pas forcement 333 // a son propre thread car il peut etre le fils d'un forum non 'publie') 334 $thread="$id_forum"; 335 $fini = false; 336 while (!$fini) { 337 $s = spip_query("SELECT id_forum FROM spip_forum WHERE id_parent IN ($thread) AND id_forum NOT IN ($thread) AND statut='publie'"); 338 if (spip_num_rows($s) == 0) $fini = true; 339 while ($t = spip_fetch_array($s)) 340 $thread.=','.$t['id_forum']; 341 } 342 343 // 3. marquer le thread comme "en cours d'indexation" 344 spip_log("-> indexation thread $thread"); 345 spip_query("UPDATE spip_forum SET idx='idx' 346 WHERE id_forum IN ($thread,$id_objet) AND idx!='non'"); 347 348 // 4. Indexer le thread 349 $s = spip_query("SELECT * FROM spip_forum 350 WHERE id_forum IN ($thread) AND idx!='non'"); 351 while ($row = spip_fetch_array($s)) { 352 indexer_chaine($row['titre'], 3); 353 indexer_chaine($row['texte'], 1); 354 indexer_chaine($row['auteur'], 2, 2); 355 indexer_chaine($row['email_auteur'], 2); 356 indexer_chaine($row['nom_site'], 2); 357 indexer_chaine($row['url_site'], 1); 358 } 359 360 // 5. marquer le thread comme "indexe" 361 spip_query("UPDATE spip_forum SET idx='oui' 362 WHERE id_forum IN ($thread,$id_objet) AND idx!='non'"); 363 364 // 6. Changer l'id_objet en id_forum de la racine du thread 365 $id_objet = $id_forum; 366 367 break; 368 369 370 case 'document': 371 // 1. Indexer le descriptif 372 indexer_chaine($row['titre'], 20); 373 indexer_chaine($row['descriptif'], 10); 374 indexer_chaine(preg_replace(',^(IMG/|.*://),', '', $row['fichier']), 1); 375 indexer_elements_associes('document', $id_objet, 'mot', 3); 376 377 // 2. Indexer le contenu si on sait le lire 378 indexer_contenu_document($row); 379 break; 380 381 382 } // switch 383 384 $query = "DELETE FROM $table_index WHERE $col_id=$id_objet"; 385 $result = spip_query($query); 386 387 if ($index) { 388 if ($mots) { 389 $mots = "INSERT IGNORE INTO spip_index_dico (hash, dico) VALUES ".substr($mots,1); // supprimer la virgule du debut 390 spip_query($mots); 391 } 392 reset($index); 393 unset($q); 394 while (list($hash, $points) = each($index)) $q[] = "(0x$hash,".ceil($points).",$id_objet)"; 395 spip_query("INSERT INTO $table_index (hash, points, $col_id) VALUES ".join(',',$q)); 396 } 397 398 // marquer "indexe" 399 spip_query("UPDATE $table SET idx='oui' WHERE $col_id=$id_objet"); 400 } 401 402 /* 403 Valeurs du champ 'idx' de la table spip_objet(s) 404 '' ne sait pas 405 '1' ˆ (re)indexer 406 'oui' deja indexe 407 'idx' en cours 408 'non' ne jamais indexer 409 */ 410 411 // API pour l'espace prive 412 function marquer_indexer ($objet, $id_objet) { 413 spip_log ("demande indexation $objet $id_objet"); 414 $table = 'spip_'.table_objet($objet); 415 $id = id_table_objet($objet); 416 spip_query ("UPDATE $table SET idx='1' WHERE $id=$id_objet AND idx!='non'"); 417 } 418 419 // A garder pour compatibilite bouton memo... 420 function indexer_article($id_article) { 421 marquer_indexer('article', $id_article); 422 } 423 424 // n'indexer que les objets publies 425 function critere_indexation($type) { 426 switch ($type) { 427 case 'article': 428 case 'breve': 429 case 'rubrique': 430 case 'syndic': 431 case 'forum': 432 case 'signature': 433 $critere = "statut='publie'"; 434 break; 435 case 'auteur': 436 $critere = "statut IN ('0minirezo', '1comite')"; 437 break; 438 case 'mot': 439 case 'document': 440 default: 441 $critere = '1=1'; 442 break; 443 } 444 return $critere; 445 } 446 447 function effectuer_une_indexation($nombre_indexations = 1) { 448 449 // chercher un objet a indexer dans chacune des tables d'objets 450 $vu = array(); 451 $types = array('article','auteur','breve','mot','rubrique','signature','syndic','forum','document'); 452 453 while (list(,$type) = each($types)) { 454 $table_objet = 'spip_'.table_objet($type); 455 $table_index = 'spip_index_'.table_objet($type); 456 457 $critere = critere_indexation($type); 458 459 if ($type == 'syndic' OR $type == 'document') 460 $limit = 1; 461 else 462 $limit = $nombre_indexations; 463 464 $s = spip_query("SELECT id_$type, idx FROM $table_objet WHERE idx IN ('','1','idx') AND $critere ORDER BY idx='idx',idx='' LIMIT 0,$limit"); 465 while ($t = spip_fetch_array($s)) { 466 $vu[$type] .= $t[0].", "; 467 indexer_objet($type, $t[0], $t[1]); 468 } 469 } 470 return $vu; 471 } 472 473 function executer_une_indexation_syndic() { 474 $id_syndic = 0; 475 if ($row = spip_fetch_array(spip_query("SELECT id_syndic FROM spip_syndic WHERE statut='publie' AND date_index < DATE_SUB(NOW(), INTERVAL 7 DAY) ORDER BY date_index LIMIT 0,1"))) { 476 $id_syndic = $row['id_syndic']; 477 spip_query("UPDATE spip_syndic SET date_index=NOW() WHERE id_syndic=$id_syndic"); 478 marquer_indexer('syndic', $id_syndic); 479 } 480 return $id_syndic; 481 } 482 483 function creer_liste_indexation() { 484 $types = array('article','auteur','breve','mot','rubrique','syndic','forum','signature','document'); 485 while (list(,$type) = each($types)) { 486 $table = 'spip_'.table_objet($type); 487 spip_query("UPDATE $table SET idx='1' WHERE idx!='non'"); 488 } 489 } 490 491 function purger_index() { 492 spip_query("DELETE FROM spip_index_articles"); 493 spip_query("DELETE FROM spip_index_auteurs"); 494 spip_query("DELETE FROM spip_index_breves"); 495 spip_query("DELETE FROM spip_index_mots"); 496 spip_query("DELETE FROM spip_index_rubriques"); 497 spip_query("DELETE FROM spip_index_syndic"); 498 spip_query("DELETE FROM spip_index_forum"); 499 spip_query("DELETE FROM spip_index_signatures"); 500 spip_query("DELETE FROM spip_index_documents"); 501 spip_query("DELETE FROM spip_index_dico"); 502 } 503 504 // cree la requete pour une recherche en txt integral 505 function requete_txt_integral($objet, $hash_recherche) { 506 $table = "spip_".table_objet($objet); 507 $index_table = "spip_index_".table_objet($objet); 508 $id_objet = "id_".$objet; 509 return "SELECT objet.*, SUM(rec.points) AS points 510 FROM $table AS objet, $index_table AS rec 511 WHERE objet.$id_objet = rec.$id_objet 512 AND rec.hash IN ($hash_recherche) 513 GROUP BY objet.$id_objet 514 ORDER BY points DESC 515 LIMIT 0,10"; 516 } 517 518 // rechercher un mot dans le dico 519 // retourne deux methodes : lache puis strict 520 function requete_dico($val) { 521 $min_long = 3; 522 523 // cas normal 524 if (strlen($val) > $min_long) { 525 return array("dico LIKE '".addslashes($val)."%'", "dico = '".addslashes($val)."'"); 526 } else 527 return array("dico = '".addslashes($val)."___'", "dico = '".addslashes($val)."___'"); 528 } 529 530 531 // decode la chaine recherchee et la traduit en hash 532 function requete_hash ($rech) { 533 // recupere les mots de la recherche 534 $translitteration_complexe = true; 535 $rech = nettoyer_chaine_indexation($rech); 536 $regs = separateurs_indexation(true)." "; 537 $rech = strtr($rech, $regs, ereg_replace('.', ' ', $regs)); 538 $s = preg_split("/ +/", $rech); 539 unset($dico); 540 unset($h); 541 542 // cherche les mots dans le dico 543 while (list(, $val) = each($s)) { 544 list($rq, $rq_strict) = requete_dico ($val); 545 if ($rq) 546 $dico[] = $rq; 547 if ($rq_strict) 548 $dico_strict[] = $rq_strict; 549 } 550 551 // Attention en MySQL 3.x il faut passer par HEX(hash) 552 // alors qu'en MySQL 4.1 c'est interdit ! 553 $vers = spip_fetch_array(spip_query("SELECT VERSION()")); 554 if (substr($vers[0], 0, 1) >= 4 555 AND substr($vers[0], 2, 1) >= 1 ) { 556 $hex_fmt = ''; 557 $select_hash = 'hash AS h'; 558 } else { 559 $hex_fmt = '0x'; 560 $select_hash = 'HEX(hash) AS h'; 561 } 562 563 // compose la recherche dans l'index 564 if ($dico_strict) { 565 $query2 = "SELECT $select_hash FROM spip_index_dico WHERE " 566 .join(" OR ", $dico_strict); 567 $result2 = spip_query($query2); 568 while ($row2 = spip_fetch_array($result2)) 569 $h_strict[] = $hex_fmt.$row2['h']; 570 } 571 if ($dico) { 572 $query2 = "SELECT $select_hash FROM spip_index_dico WHERE " 573 .join(" OR ", $dico); 574 $result2 = spip_query($query2); 575 while ($row2 = spip_fetch_array($result2)) 576 $h[] = $hex_fmt.$row2['h']; 577 } 578 if ($h_strict) 579 $hash_recherche_strict = join(",", $h_strict); 580 else 581 $hash_recherche_strict = "0"; 582 583 if ($h) 584 $hash_recherche = join(",", $h); 585 else 586 $hash_recherche = "0"; 587 588 return array($hash_recherche, $hash_recherche_strict); 589 } 590 591 592 function prepare_recherche($recherche, $type = 'id_article', $table='articles') { 593 static $cache = array(); 594 595 if (!$cache[$type][$recherche]) { 596 597 if (!$cache['hash'][$recherche]) 598 $cache['hash'][$recherche] = requete_hash($recherche); 599 list($hash_recherche, $hash_recherche_strict) 600 = $cache['hash'][$recherche]; 601 602 $strict = array(); 603 if ($hash_recherche_strict) 604 foreach (split(',',$hash_recherche_strict) as $h) 605 $strict[$h] = 99; 606 607 $points = array(); 608 $s = spip_query ("SELECT hash,points,$type as id 609 FROM spip_index_$table 610 WHERE hash IN ($hash_recherche)"); 611 612 while ($r = spip_fetch_array($s)) 613 $points[$r['id']] 614 += (1 + $strict[$r['hash']]) * $r['points']; 615 spip_free_result($s); 616 617 arsort($points, SORT_NUMERIC); 618 619 # calculer le {id_article IN()} et le {... as points} 620 if (!count($points)) { 621 $cache[$type][$recherche] = array('', ''); 622 } else { 623 $ids = array(); 624 $select = '0'; 625 foreach ($points as $id => $p) 626 $listes_ids[$p] .= ','.$id; 627 foreach ($listes_ids as $p => $liste_ids) 628 $select .= "+$p*(".calcul_mysql_in("$table.$type", substr($liste_ids, 1)).") "; 629 630 $cache[$type][$recherche] = array($select, 631 '('.calcul_mysql_in("$table.$type", join(',',array_keys($points))).')'); 632 } 633 } 634 635 return $cache[$type][$recherche]; 636 } 637 638 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Feb 22 22:27:47 2007 | par Balluche grâce à PHPXref 0.7 |