articles.php3 articles_ortho.php inc.php inc_auxbase.php3 inc_diff.php3 inc_majbase.php3 inc_ortho.php inc_presentation.php3 inc_revisions.php3 inc_texte.php3 inc_version.php3 spip_style.php3 1.187 NONE NONE 1.3 1.4 1.9 NONE 1.433 1.2 1.226

Update of /home/spip-cvs/spip/ecrire
In directory alan:/tmp/cvs-serv30276/ecrire

Modified Files:
  articles.php3 inc_auxbase.php3 inc_diff.php3 inc_majbase.php3
  inc_presentation.php3 inc_revisions.php3 inc_texte.php3
  inc_version.php3 spip_style.php3
Added Files:
  articles_ortho.php inc.php inc_ortho.php
Log Message:
petites corrections + backpourt spip-lab (gestion de diff & correction d'orthogaffe)

--- NEW FILE: inc.php ---
<?php

  //
  // Ce fichier assure la compatibilite avec spip-lab
  //
  if (defined('_COMPATIBLE_SPIP_LAB')) {
    return;
  } else {
    define('_COMPATIBLE_SPIP_LAB', 1);
    include('inc_version.php3');

    // Pour l'instant ne connait que ecrire/
    function include_spip($fichier) {
      global $dir_ecrire;

      switch ($fichier) {
        case 'ecrire.php':
          global $spip_version;
          include('inc.php3');
          break;
        default:
          // charger la version spip-lab si presente
          if (@file_exists($dir_ecrire.'inc_'.$fichier))
            include_ecrire('inc_'.$fichier);
          // sinon prendre la version spip-stable
          else
            if (@file_exists($dir_ecrire.'inc_'.$fichier.'3'))
              include_ecrire('inc_'.$fichier.'3');
          else
            die ("Fichier SPIP-Lab \"$fichier\" manquant.");
          break;
      }
    }

    // pas encore backportee
    function html_background() {
    }

  }

?>
Index: inc_revisions.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_revisions.php3,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- inc_revisions.php3 18 Jul 2004 20:21:52 -0000 1.2
+++ inc_revisions.php3 27 Aug 2004 18:55:23 -0000 1.3
@@ -5,6 +5,7 @@
if (defined("_ECRIRE_INC_REVISIONS")) return;
define("_ECRIRE_INC_REVISIONS", "1");

+$GLOBALS['agregation_versions'] = 10;

function separer_paras($texte, $paras = "") {
   if (!$paras) $paras = array();
@@ -17,11 +18,45 @@
   return $paras;
}

+function replace_fragment($id_article, $version_min, $version_max, $id_fragment, $fragment) {
+ global $flag_gz;
+
+ $fragment = serialize($fragment);
+ $compress = 0;
+ if ($flag_gz) {
+ $s = gzcompress($fragment);
+ if (strlen($s) < strlen($fragment)) {
+ //echo "gain gz: ".(100 - 100 * strlen($s) / strlen($fragment))."%<br />";
+ $compress = 1;
+ $fragment = $s;
+ }
+ }
+ // Attention a bien echapper le $fragment qui est en binaire
+ return "($id_article, $version_min, $version_max, $id_fragment, $compress, '"
+ .mysql_escape_string($fragment)."')";
+}
+
+function exec_replace_fragments($replaces) {
+ if (count($replaces)) {
+ $query = "REPLACE spip_versions_fragments (id_article, version_min, version_max, id_fragment, compress, fragment) ".
+ "VALUES ".join(", ", $replaces);
+ spip_query($query);
+ }
+}
+function exec_delete_fragments($id_article, $deletes) {
+ if (count($deletes)) {
+ $query = "DELETE FROM spip_versions_fragments WHERE id_article=$id_article AND ((".
+ join(") OR (", $deletes)."))";
+ spip_query($query);
+ }
+}
+
+
//
// Ajouter les fragments de la derniere version (tableau associatif id_fragment => texte)
//
function ajouter_fragments($id_article, $id_version, $fragments) {
- global $flag_gz;
+ global $flag_gz, $agregation_versions;

   $replaces = array();
   foreach ($fragments as $id_fragment => $texte) {
@@ -39,7 +74,8 @@
       if (is_array($fragment)) {
         unset($fragment[$id_version]);
         // Si le fragment n'est pas trop gros, prolonger celui-ci
- $nouveau = count($fragment) > 8 && strlen($row['fragment']) > 1000;
+ $nouveau = count($fragment) >= $agregation_versions
+ && strlen($row['fragment']) > 1000;
       }
     }
     if ($nouveau) {
@@ -59,27 +95,132 @@
     }
     
     // Preparer l'enregistrement du fragment
- $fragment = serialize($fragment);
- $compress = 0;
- $version_max = $id_version;
- if ($flag_gz) {
- $s = gzcompress($fragment);
- if (strlen($s) < strlen($fragment)) {
- //echo "gain gz: ".(100 - 100 * strlen($s) / strlen($fragment))."%<br />";
- $compress = 1;
- $fragment = $s;
+ $replaces[] = replace_fragment($id_article, $version_min, $id_version, $id_fragment, $fragment);
+ }
+
+ exec_replace_fragments($replaces);
+}
+
+//
+// Supprimer tous les fragments d'un article lies a un intervalle de versions
+// (essaie d'eviter une trop grande fragmentation)
+//
+function supprimer_fragments($id_article, $version_debut, $version_fin) {
+ global $flag_gz, $agregation_versions;
+
+ $replaces = array();
+ $deletes = array();
+
+ // D'abord, vider les fragments inutiles
+ $query = "DELETE FROM spip_versions_fragments WHERE id_article=$id_article ".
+ "AND version_min>=$version_debut AND version_max<=$version_fin";
+ spip_query($query);
+
+ // Fragments chevauchant l'ensemble de l'intervalle, s'ils existent
+ $query = "SELECT id_fragment, compress, fragment, version_min, version_max FROM spip_versions_fragments ".
+ "WHERE id_article=$id_article AND version_min<$version_debut AND version_max>$version_fin";
+ $result = spip_query($query);
+
+ while ($row = spip_fetch_array($result)) {
+ $id_fragment = $row['id_fragment'];
+ $fragment = $row['fragment'];
+ if ($row['compress'] > 0) $fragment = gzuncompress($fragment);
+ $fragment = unserialize($fragment);
+ for ($i = $version_fin; $i >= $version_debut; $i--) {
+ if (isset($fragment[$i])) {
+ // Recopier le dernier fragment si implicite
+ if (!isset($fragment[$version_fin + 1]))
+ $fragment[$version_fin + 1] = $fragment[$i];
+ unset($fragment[$i]);
       }
     }
- // (attention a bien echapper le $fragment qui est en binaire)
- $replaces[] = "($id_article, $version_min, $version_max, $id_fragment, $compress, '"
- .mysql_escape_string($fragment)."')";
+
+ $replaces[] = replace_fragment($id_article,
+ $row['version_min'], $row['version_max'], $id_fragment, $fragment);
   }

- if (count($replaces)) {
- $query = "REPLACE spip_versions_fragments (id_article, version_min, version_max, id_fragment, compress, fragment) ".
- "VALUES ".join(", ", $replaces);
- spip_query($query);
+ // Fragments chevauchant le debut de l'intervalle, s'ils existent
+ $query = "SELECT id_fragment, compress, fragment, version_min, version_max FROM spip_versions_fragments ".
+ "WHERE id_article=$id_article AND version_min<$version_debut ".
+ "AND version_max>=$version_debut AND version_max<=$version_fin";
+ $result = spip_query($query);
+
+ $deb_fragment = array();
+ while ($row = spip_fetch_array($result)) {
+ $id_fragment = $row['id_fragment'];
+ $fragment = $row['fragment'];
+ $version_min = $row['version_min'];
+ $version_max = $row['version_max'];
+ if ($row['compress'] > 0) $fragment = gzuncompress($fragment);
+ $fragment = unserialize($fragment);
+ for ($i = $version_debut; $i <= $version_max; $i++) {
+ if (isset($fragment[$i])) unset($fragment[$i]);
+ }
+
+ // Stocker temporairement le fragment pour agregation
+ $deb_fragment[$id_fragment] = $fragment;
+ // Ajuster l'intervalle des versions
+ $deb_version_min[$id_fragment] = $version_min;
+ $deb_version_max[$id_fragment] = $version_debut - 1;
   }
+
+ // Fragments chevauchant la fin de l'intervalle, s'ils existent
+ $query = "SELECT id_fragment, compress, fragment, version_min, version_max FROM spip_versions_fragments ".
+ "WHERE id_article=$id_article AND version_max>$version_fin ".
+ "AND version_min>=$version_debut AND version_min<=$version_fin";
+ $result = spip_query($query);
+
+ while ($row = spip_fetch_array($result)) {
+ $id_fragment = $row['id_fragment'];
+ $fragment = $row['fragment'];
+ $version_min = $row['version_min'];
+ $version_max = $row['version_max'];
+ if ($row['compress'] > 0) $fragment = gzuncompress($fragment);
+ $fragment = unserialize($fragment);
+ for ($i = $version_fin; $i >= $version_min; $i--) {
+ if (isset($fragment[$i])) {
+ // Recopier le dernier fragment si implicite
+ if (!isset($fragment[$version_fin + 1]))
+ $fragment[$version_fin + 1] = $fragment[$i];
+ unset($fragment[$i]);
+ }
+ }
+
+ // Virer l'ancien enregistrement (la cle primaire va changer)
+ $deletes[] = "id_fragment=$id_fragment AND version_min=$version_min";
+ // Essayer l'agregation
+ $agreger = false;
+ if (isset($deb_fragment[$id_fragment])) {
+ $agreger = (count($deb_fragment[$id_fragment]) + count($fragment) <= $agregation_versions);
+ if ($agreger) {
+ $fragment = $deb_fragment[$id_fragment] + $fragment;
+ $version_min = $deb_version_min[$id_fragment];
+ }
+ else {
+ $replaces[] = replace_fragment($id_article,
+ $deb_version_min[$id_fragment], $deb_version_max[$id_fragment],
+ $id_fragment, $deb_fragment[$id_fragment]);
+ }
+ unset($deb_fragment[$id_fragment]);
+ }
+ if (!$agreger) {
+ // Ajuster l'intervalle des versions
+ $version_min = $version_fin + 1;
+ }
+ $replaces[] = replace_fragment($id_article, $version_min, $version_max, $id_fragment, $fragment);
+ }
+
+ // Ajouter fragments restants
+ if (is_array($deb_fragment) && count($deb_fragment) > 0) {
+ foreach ($deb_fragment as $id_fragment => $fragment) {
+ $replaces[] = replace_fragment($id_article,
+ $deb_version_min[$id_fragment], $deb_version_max[$id_fragment],
+ $id_fragment, $deb_fragment[$id_fragment]);
+ }
+ }
+
+ exec_replace_fragments($replaces);
+ exec_delete_fragments($id_article, $deletes);
}

//
@@ -87,7 +228,6 @@
// renvoie un tableau associatif (id_fragment => texte)
//
function recuperer_fragments($id_article, $id_version) {
- $id_version = intval($id_version);
   $fragments = array();

   $query = "SELECT id_fragment, version_min, compress, fragment FROM spip_versions_fragments ".
@@ -187,12 +327,10 @@
   return array($src_dest, $dest_src);
}

-
//
// Recuperer les champs d'une version donnee
//
function recuperer_version($id_article, $id_version) {
- if (!$id_version) $id_version = '0';
   $query = "SELECT champs FROM spip_versions ".
     "WHERE id_article=$id_article AND id_version=$id_version";
   $result = spip_query($query);
@@ -212,10 +350,17 @@
   return $textes;
}

+function supprimer_versions($id_article, $version_min, $version_max) {
+ $query = "DELETE FROM spip_versions WHERE id_article=$id_article ".
+ "AND id_version>=$version_min AND id_version<=$version_max";
+ spip_query($query);
+ supprimer_fragments($id_article, $version_min, $version_max);
+}
+
//
// Ajouter une version a un article
//
-function ajouter_version($id_article, $champs) {
+function ajouter_version($id_article, $champs, $titre_version = "") {
   global $connect_id_auteur;

   // Eviter les validations entremelees
@@ -280,13 +425,16 @@
   ajouter_fragments($id_article, $id_version_new, $fragments);
   if (!$codes) $codes = array();
   $codes = addslashes(serialize($codes));
+ $permanent = empty($titre_version) ? 'non' : 'oui';
+ $titre_version = addslashes($titre_version);
   if ($nouveau) {
- $query = "INSERT spip_versions (id_article, id_version, permanent, date, id_auteur, champs) ".
- "VALUES ($id_article, $id_version_new, 'non', NOW(), '$connect_id_auteur', '$codes')";
+ $query = "INSERT spip_versions (id_article, id_version, titre_version, permanent, date, id_auteur, champs) ".
+ "VALUES ($id_article, $id_version_new, '$titre_version', '$permanent', NOW(), '$connect_id_auteur', '$codes')";
     spip_query($query);
   }
   else {
- $query = "UPDATE spip_versions SET date=NOW(), id_auteur=$connect_id_auteur, champs='$codes' ".
+ $query = "UPDATE spip_versions SET date=NOW(), id_auteur=$connect_id_auteur, champs='$codes', ".
+ "permanent='$permanent', titre_version='$titre_version' ".
        "WHERE id_article=$id_article AND id_version=$id_version";
     spip_query($query);
   }
@@ -298,5 +446,4 @@
   return $id_version_new;
}

-
?>

Index: articles.php3

RCS file: /home/spip-cvs/spip/ecrire/articles.php3,v
retrieving revision 1.187
retrieving revision 1.188
diff -u -d -r1.187 -r1.188
--- articles.php3 26 Aug 2004 03:47:01 -0000 1.187
+++ articles.php3 27 Aug 2004 18:55:23 -0000 1.188
@@ -400,6 +400,10 @@
   icone_horizontale(_T('info_historique_lien'), "articles_versions.php3?id_article=$id_article", "historique-24.gif", "rien.gif");
}

+ // Correction orthographique
+ $js_ortho = "onclick=\"window.open(this.href, 'spip_ortho', 'scrollbars=yes, resizable=yes, width=740, height=580'); return false;\"";
+ icone_horizontale(_L("V&eacute;rifier l'orthographe"), "articles_ortho.php?id_article=$id_article", "ortho-24.gif", "rien.gif", 'echo', $js_ortho);
+
echo "</div>\n";

fin_boite_info();

--- NEW FILE: articles_ortho.php ---
<?php

include("inc.php");

include_spip("ecrire.php");
include_spip("ortho.php");
include_spip("layer.php"); // Pour $browser_name

$articles_surtitre = lire_meta("articles_surtitre");
$articles_soustitre = lire_meta("articles_soustitre");
$articles_descriptif = lire_meta("articles_descriptif");
$articles_urlref = lire_meta("articles_urlref");
$articles_chapeau = lire_meta("articles_chapeau");
$articles_ps = lire_meta("articles_ps");
$articles_redac = lire_meta("articles_redac");
$articles_mots = lire_meta("articles_mots");

//
// Lire l'article
//

$query = "SELECT * FROM spip_articles WHERE id_article='$id_article'";
$result = spip_query($query);

if ($row = spip_fetch_array($result)) {
  $id_article = $row["id_article"];
  $surtitre = $row["surtitre"];
  $titre = $row["titre"];
  $soustitre = $row["soustitre"];
  $id_rubrique = $row["id_rubrique"];
  $descriptif = $row["descriptif"];
  $nom_site = $row["nom_site"];
  $url_site = $row["url_site"];
  $chapo = $row["chapo"];
  $texte = $row["texte"];
  $ps = $row["ps"];
  $date = $row["date"];
  $statut_article = $row["statut"];
  $maj = $row["maj"];
  $date_redac = $row["date_redac"];
  $visites = $row["visites"];
  $referers = $row["referers"];
  $extra = $row["extra"];
  $id_trad = $row["id_trad"];
  $lang_article = $row["lang"];
}
if (!$lang_article) $lang_article = lire_meta('langue_site');

// pour l'affichage du virtuel
unset($virtuel);
if (substr($chapo, 0, 1) == '=') {
  $virtuel = substr($chapo, 1);
  $chapo = "";
}

$champs = array('surtitre', 'titre', 'soustitre', 'descriptif', 'chapo', 'texte', 'ps');
$echap = array();
$ortho = "";

//
// Affichage HTML
//

// Gros hack IE pour le "position: fixed"
$code_ie = "<!--[if IE]>
<style type=\"text/css\" media=\"screen\">
body {
  height: 100%; margin: 0px; padding: 0px;
  overflow: hidden;
}
.ortho-content {
  position: absolute; left: 0px;
  height: 100%; margin: 0px; padding: 0px;
  width: 72%;
  overflow-y: auto;
}
#ortho-fixed {
  position: absolute; right: 0px; width: 25%;
  height: 100%; margin: 0px; padding: 0px;
  overflow: hidden;
}
.ortho-padding {
  padding: 12px;
}
</style>
<script type=\"text/javascript\">
onload = function() { ortho-content.focus(); }
</script>
<![endif]-->";

debut_html("Orthographe", $code_ie);

changer_typo('','article'.$id_article);

// Ajouts et suppressions de mots par l'utilisateur
gerer_dico_ortho($lang_article);

//
// Panneau de droite
//
echo "<div id='ortho-fixed'>";
echo "<div class='ortho-padding serif'>";

debut_cadre_enfonce();

foreach ($champs as $champ) {
  $$champ = preparer_ortho($$champ, $lang_article);
  $ortho .= $$champ." ";
}
$result_ortho = corriger_ortho($ortho, $lang_article);
if (is_array($result_ortho)) {
  $mots = $result_ortho['mauvais'];
  if ($erreur = $result_ortho['erreur']) {
    echo "<b>Attention&nbsp;: votre texte contient trop de fautes, aucune correction n'est sugg&eacute;r&eacute;e ".
      "afin de ne pas surcharger le syst&egrave;me.</b><p>\n";
    echo "<b>Commencez par corriger les fautes les plus &eacute;videntes et r&eacute;essayez ensuite.</b><p>";
  }
  else {
    echo "<b>Les mots mal orthographi&eacute;s sont surlign&eacute;s en rouge. Vous pouvez cliquer ".
      "sur chaque mot pour afficher des suggestions de correction.</b><p>\n";
  }

  panneau_ortho($result_ortho);

  foreach ($champs as $champ) {
    list($$champ, $echap[$champ]) = echappe_html($$champ);
    $$champ = souligner_ortho($$champ, $lang_article, $result_ortho);
    $echap[$champ] = afficher_ortho($echap[$champ]);
  }
}
else {
  $erreur = $result_ortho;
  echo "<b>Aucun dictionnaire n'a &eacute;t&eacute; trouv&eacute; pour cette langue (";
  echo traduire_nom_langue($lang_article);
  echo "). ";
  echo "Le syst&egrave;me ne peut pas v&eacute;rifier l'orthographe de ce texte.</b>";
  foreach ($champs as $champ) {
    $$champ = afficher_ortho($$champ);
  }
}

fin_cadre_enfonce();

echo "</div>";
echo "</div>";

//
// Colonne de gauche : textes de l'article
//
echo "<div class='ortho-content'>";
echo "<div class='ortho-padding serif'>";

debut_cadre_relief();

if ($surtitre) {
  echo "<span $dir_lang><font face='arial,helvetica' size='3'><b>";
  echo typo($surtitre);
  echo "</b></font></span>\n";
}
gros_titre($titre);

if ($soustitre) {
  echo "<span $dir_lang><font face='arial,helvetica' size='3'><b>";
  echo typo($soustitre);
  echo "</b></font></span>\n";
}

if ($descriptif OR $url_site OR $nom_site) {
  echo "<p><div align='left' style='padding: 5px; border: 1px dashed #aaaaaa; background-color: #e4e4e4;' $dir_lang>";
  echo "<font size='2' face='Verdana,Arial,Sans,sans-serif'>";
  $texte_case = ($descriptif) ? "{{"._T('info_descriptif')."}} $descriptif\n\n" : '';
  $texte_case .= ($nom_site.$url_site) ? "{{"._T('info_urlref')."}} [".$nom_site."->".$url_site."]" : '';
  echo propre($texte_case, $echap['descriptif']);
  echo "</font>";
  echo "</div>";
}

//////////////////////////////////////////////////////
// Corps de l'article
//

echo "\n\n<div align='justify'>";

if ($virtuel) {
  debut_boite_info();
  echo _T('info_renvoi_article')." ".propre("<center>[->$virtuel]</center>");
  fin_boite_info();
}
else {
  echo "<div $dir_lang><b>";
  echo justifier(propre($chapo, $echap['chapo']));
  echo "</b></div>\n\n";

  echo "<div $dir_lang>".justifier(propre($texte, $echap['texte']))."</div>";

  if ($ps) {
    echo debut_cadre_enfonce();
    echo "<div $dir_lang><font size='2' face='Verdana,Arial,Sans,sans-serif'>";
    echo justifier("<b>"._T('info_ps')."</b> ".propre($ps, $echap['ps']));
    echo "</font></div>";
    echo fin_cadre_enfonce();
  }

  if ($les_notes) {
    echo debut_cadre_relief();
    echo "<div $dir_lang><font size='2'>";
    echo justifier("<b>"._T('info_notes')."&nbsp;:</b> ".$les_notes);
    echo "</font></div>";
    echo fin_cadre_relief();
  }

  if ($champs_extra AND $extra) {
    include_spip("extra.php");
    extra_affichage($extra, "articles");
  }
}

echo "</div>";

fin_cadre_relief();

html_background();
echo "</div>";
echo "</div>";

fin_html();

?>

Index: spip_style.php3

RCS file: /home/spip-cvs/spip/ecrire/spip_style.php3,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -d -r1.78 -r1.79
--- spip_style.php3 5 Aug 2004 13:00:21 -0000 1.78
+++ spip_style.php3 27 Aug 2004 18:55:23 -0000 1.79
@@ -629,19 +629,42 @@
/*
  * Correction orthographique
  */
-
+
.ortho {
   background: #ffe0e0;
- border: 2px transparent;
+ margin: 0px;
+ margin-bottom: -2px;
   border-bottom: 2px dashed red;
   color: inherit;
   text-decoration: none;
}
a.ortho:hover {
+ margin: -2px;
   border: 2px dashed red;
   color: inherit;
   text-decoration: none;
}
+.ortho-dico {
+ background: #e0f4d0;
+ margin: 0px;
+ margin-bottom: -2px;
+ border-bottom: 2px dashed #a0b890;
+ color: inherit;
+ text-decoration: none;
+}
+a.ortho-dico:hover {
+ margin: -2px;
+ border: 2px dashed #a0b890;
+ color: inherit;
+ text-decoration: none;
+}
+
+#ortho-fixed {
+ position: fixed; top: 0px; right: 0px; width: 25%; padding: 15px; margin: 0px;
+}
+.ortho-content {
+ position: absolute; top: 0px; width: 70%; padding: 15px; margin: 0px;
+}
.suggest-actif, .suggest-inactif {
   font-family: "Trebuchet Sans MS", Verdana, Arial, sans-serif;
   font-size: 95%;
@@ -660,12 +683,23 @@
   font-weight: normal;
   z-index: 0;
}
-.suggest-actif .detail {
+.suggest-actif .detail ul, .suggest-inactif .detail ul {
+ list-style-image: url(img_pack/puce.gif);
+ background: #f3f2f3;
+ margin: 0px;
+ padding: 0px;
+ padding-left: 25px;
+}
+.suggest-actif {
   display: block;
}
-.suggest-inactif .detail {
+.suggest-inactif {
   display: none;
}
+.form-ortho select {
+ background: #ffe0e0;
+}
+

/*
  * Comparaison d'articles

Index: inc_texte.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_texte.php3,v
retrieving revision 1.226
retrieving revision 1.227
diff -u -d -r1.226 -r1.227
--- inc_texte.php3 26 Jul 2004 10:19:27 -0000 1.226
+++ inc_texte.php3 27 Aug 2004 18:55:23 -0000 1.227
@@ -15,12 +15,8 @@
// Par securite ne pas accepter les variables passees par l'utilisateur
//
function tester_variable($nom_var, $val){
- if (!isset($GLOBALS[$nom_var])
- OR $_GET[$nom_var] OR $GLOBALS['HTTP_GET_VARS'][$nom_var]
- OR $_PUT[$nom_var] OR $GLOBALS['HTTP_PUT_VARS'][$nom_var]
- OR $_POST[$nom_var] OR $GLOBALS['HTTP_POST_VARS'][$nom_var]
- OR $_COOKIE[$nom_var] OR $GLOBALS['HTTP_COOKIE_VARS'][$nom_var]
- OR $_REQUEST[$nom_var]) {
+ global $INSECURE;
+ if (!isset($GLOBALS[$nom_var]) || $INSECURE[$nom_var]) {
     $GLOBALS[$nom_var] = $val;
     return false;
   }
@@ -127,7 +123,7 @@

// Mise de cote des echappements
-function echappe_html($letexte, $source, $no_transform=false) {
+function echappe_html($letexte, $source='SOURCEPROPRE', $no_transform=false) {
   global $flag_pcre;

   if ($flag_pcre) { // beaucoup plus rapide si on a pcre
@@ -250,7 +246,7 @@
}

// Traitement final des echappements
-function echappe_retour($letexte, $les_echap, $source) {
+function echappe_retour($letexte, $les_echap, $source='') {
   while (ereg("@@SPIP_$source([0-9]+)@@", $letexte, $match)) {
     $lenum = $match[1];
     $cherche = $match[0];
@@ -955,8 +951,8 @@

// Filtre a appliquer aux champs du type #TEXTE*
-function propre($letexte) {
- return interdire_scripts(traiter_raccourcis(trim($letexte)));
+function propre($letexte, $echap=false) {
+ return interdire_scripts(traiter_raccourcis(trim($letexte), $echap));
// $a=time(); $b=microtime();
// interdire_scripts(traiter_raccourcis(trim($letexte)));
// return time()-$a + microtime()-$b;

Index: inc_presentation.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_presentation.php3,v
retrieving revision 1.433
retrieving revision 1.434
diff -u -d -r1.433 -r1.434
--- inc_presentation.php3 26 Aug 2004 12:26:01 -0000 1.433
+++ inc_presentation.php3 27 Aug 2004 18:55:23 -0000 1.434
@@ -1250,6 +1250,12 @@
   global $mode;
   global $connect_statut, $connect_toutes_rubriques;
   global $browser_name, $browser_version, $browser_rev;
+
+ // hack pour compatibilite spip-lab
+ if (strpos($rubrique, 'script>')) {
+ $code = $rubrique;
+ $rubrique = '';
+ }
   
   $nom_site_spip = entites_html(lire_meta("nom_site"));
   $titre = textebrut(typo($titre));
@@ -1280,6 +1286,8 @@
   $link->addVar('right', $GLOBALS['spip_lang_right']);
   echo $link->getUrl()."\">\n";

+ if ($code) echo $code."\n";
+
   afficher_script_layer();
?>
<script type="text/javascript" src="../mathmlinHTML.js"></script>
@@ -1857,7 +1865,7 @@
     return $icone;
}

-function icone_horizontale($texte, $lien, $fond = "", $fonction = "", $echo = true) {
+function icone_horizontale($texte, $lien, $fond = "", $fonction = "", $echo = true, $javascript='') {
   global $spip_display, $couleur_claire, $couleur_foncee, $compteur_survol;

   $retour = '';
@@ -1867,7 +1875,7 @@

   if ($danger) $retour .= "<div class='danger'>";
   if ($spip_display != 1) {
- $retour .= "<a href='$lien' class='cellule-h'><table cellpadding='0' valign='middle'><tr>\n";
+ $retour .= "<a href='$lien' class='cellule-h' $javascript><table cellpadding='0' valign='middle'><tr>\n";
     $retour .= "<td><a href='$lien'><div class='cell-i'><img style='background: url(\"img_pack/$fond\") center center no-repeat;' src='img_pack/$fonction' alt=''></div></a></td>\n";
     $retour .= "<td class='cellule-h-lien'><a href='$lien' class='cellule-h'>$texte</a></td>\n";
     $retour .= "</tr></table></a>\n";

--- NEW FILE: inc_ortho.php ---
<?php

// Ce fichier ne sera execute qu'une fois
if (defined("_ECRIRE_INC_ORTHO")) return;
define("_ECRIRE_INC_ORTHO", "1");

// Mettre a jour la liste locale des miroirs
function maj_miroirs_ortho() {
  $liste = explode(" ", lire_meta("liste_miroirs_ortho"));
  $miroirs_old = array();
  foreach ($liste as $index) {
    list($url) = explode(" ", lire_meta("miroir_ortho_$index"));
    $miroirs_old[$url] = $index;
  }

  // TODO: recuperer la liste dynamiquement depuis ortho.spip.net
  $urls = array(
    ‹ http://tony.ortho.spip.net/ortho_serveur.php ›,
    ‹ http://ortho.spip.net/ortho_serveur.php ›,
    ‹ http://spip-ortho.linagora.org:18080/ortho_serveur.php ›
  );
  $liste = array();
  $miroirs_new = array();
  $index = 1;
  foreach ($urls as $url) {
    if ($miroirs_old[$url]) {
      $s = lire_meta(« miroir_ortho_$index »);
    }
    else {
      $s = $url." « .time();
    }
    $miroirs_new[$index] = $s;
    $liste[] = $index++;
  }
  foreach ($miroirs_old as $index) {
    effacer_meta(« miroir_ortho_$index »);
  }
  foreach ($miroirs_new as $index => $s) {
    ecrire_meta(« miroir_ortho_$index », $s);
  }
  ecrire_meta(« liste_miroirs_ortho », join( » ", $liste));
}

// Lire la liste des miroirs et les langues associees
function lire_miroirs_ortho() {
  global $miroirs_ortho, $index_miroirs_ortho, $duree_cache_miroirs_ortho;

  $miroirs_ortho = array();
  $index_miroirs_ortho = array();

  $t = time();
  $maj = lire_meta("maj_miroirs_ortho");
  if ($maj < $t - $duree_cache_miroirs_ortho) {
    maj_miroirs_ortho();
    ecrire_meta("maj_miroirs_ortho", $t);
    lire_metas();
  }

  $liste = explode(" ", lire_meta("liste_miroirs_ortho"));
  foreach ($liste as $index) {
    $s = explode(" ", lire_meta("miroir_ortho_$index"));
    $url = $s[0];
    $maj = $s[1];
    $langs = explode(",", $s[2]);
    // Reinitialiser periodiquement la liste des langues non-supportees
    if ($maj < $t - $duree_cache_miroirs_ortho) {
      foreach ($langs as $lang)
        if (substr($lang, 0, 1) == '!') unset($langs[$lang]);
      $s[1] = $t;
      $s[2] = join(",", $langs);
      ecrire_meta("miroir_ortho_$index", join(" ", $s));
    }
    $index_miroirs_ortho[$url] = $index;
    $miroirs_ortho[$url] = array();
    foreach ($langs as $lang) {
      if ($lang) $miroirs_ortho[$url][$lang] = $lang;
    }
  }
  srand(time());
}

// Sauvegarder les infos de langues pour le miroir
function ecrire_miroir_ortho($url, $langs) {
  global $index_miroirs_ortho;

  $index = $index_miroirs_ortho[$url];
  $s = explode(" ", lire_meta("miroir_ortho_$index"));
  $s[2] = join(",", $langs);
  ecrire_meta("miroir_ortho_$index", join(" ", $s));
}

function ajouter_langue_miroir($url, $lang) {
  global $miroirs_ortho;
  $langs = $miroirs_ortho[$url];
  $langs[$lang] = $lang;
  unset($langs["!$lang"]);
  ecrire_miroir_ortho($url, $langs);
}

function enlever_langue_miroir($url, $lang) {
  global $miroirs_ortho;
  $langs = $miroirs_ortho[$url];
  unset($langs[$lang]);
  $langs["!$lang"] = "!$lang";
  ecrire_miroir_ortho($url, $langs);
}

//
// Renvoie la liste des miroirs utilisables pour une langue donnee
//
function chercher_miroirs_ortho($lang) {
  global $miroirs_ortho;
  
  $result = array();
  $chercher = true;
  foreach ($miroirs_ortho as $url => $langs) {
    if ($langs[$lang]) {
      $result[] = $url;
    }
    else if ($chercher && !$langs["!$lang"]) {
      //echo "test $lang $url<br />";
      if (verifier_langue_miroir($url, $lang)) $result[] = $url;
      // Ne recuperer la langue d'un miroir qu'une seule fois par requete
      if ($result) $chercher = false;
    }
  }
  return $result;
}

function choisir_miroir_ortho($lang) {
  $miroirs = chercher_miroirs_ortho($lang);
  if (!($n = count($miroirs))) return false;
  return $miroirs[($n > 1) ? rand(0, $n - 1) : 0];
}

//
// Envoyer une requete a un serveur d'orthographe
//
function post_ortho($url, $texte, $lang) {
  $errno = $errstr = "";

  $t = parse_url($url);
  if ($t['scheme'] != 'http') return false;
  $host = $t['host'];
  $port = $t['port'] ? $t['port'] : 80;
  $path = $t['path'] ? $t['path'] : "/";

  // Envoyer la requete en POST
  $f = @fsockopen($host, $port, $errno, $errstr, 2);
  if (!$f) return false;
  fputs($f, "POST $path HTTP/1.0\r\n");

  // Si le texte est petit, l'overhead du multipart est dispendieux
  if (!$GLOBALS['flag_gz'] || strlen($texte) < 200) {
    $gz = false;
    $body = "op=spell&lang=".urlencode($lang)."&texte=".urlencode($texte);
    fputs($f, "Content-Type: application/x-www-form-urlencoded\r\n");
  }
  // Sinon, on passe en multipart pour compresser la chaine a corriger
  else {
    // Il faut eliminer les caracteres 0 sinon PHP ne lit pas la suite du parametre
    // passe en multipart/form-data (gros hack bien sale)
    $texte_gz = gzcompress($texte);
    for ($echap = 255; $echap > 0; $echap--) {
      $str_echap = chr($echap ^ 1).chr($echap).chr($echap).chr($echap ^ 2);
      if (!is_int(strpos($texte_gz, $str_echap))) break;
    }
    $texte_gz = str_replace("\x00", $str_echap, $texte_gz);
    $gz = true;
    $vars = array('op' => 'spell', 'lang' => $lang, 'texte' => $texte_gz, 'gz' => 1, 'nul_echap' => $str_echap);
    $boundary = substr(md5(rand().'ortho'), 0, 8);
    $body = '';
    foreach ($vars as $key => $val) {
      $body .= "\r\n--$boundary\r\n";
      $body .= "Content-Disposition: form-data; name=\"$key\"\r\n";
      $body .= "\r\n";
      $body .= $val;
    }
    $body .= "\r\n--$boundary\r\n";
    fputs($f, "Content-Type: multipart/form-data; boundary=$boundary\r\n");
  }

  // On envoie le contenu
  fputs($f, "Content-Length: ".strlen($body)."\r\n");
  fputs($f, "Host: $host\r\n\r\n");
  fputs($f, $body);

  // Lire les en-tetes HTTP de la reponse et decoder le Content-Length
  $length = 0;
  $s = fgets($f, 1000);
  $statut = 0;
  if (preg_match(',^HTTP/\d+\.\d+ (\d+) ,', $s, $r))
    $statut = intval($r[1]);
  if ($statut != 200) {
    fclose($f);
    return false;
  }
  while ($s = trim(fgets($f, 1000))) {
    if (preg_match(',Content-Length:(.*),i', $s, $r))
      $length = intval($r[1]);
  }
  $r = "";

  // Lire le corps de la reponse HTTP
  if ($length) {
    while (($l = strlen($r)) < $length) $r .= fread($f, $length - $l);
  }
  else while (!feof($f) AND $r .= fread($f, 1024));

  fclose($f);
  if ($gz) $r = gzuncompress($r);
  return $r;
}

//
// Verifier si un serveur gere une langue donnee
//
function verifier_langue_miroir($url, $lang) {
  // Envoyer une requete bidon
  $result = post_ortho($url, " ", $lang);
  //if (!$result) return false;
  if (preg_match(',<ortho>.*</ortho>,s', $result) &&
    !preg_match(',<erreur>.*<code>E_LANG_ABSENT</code>.*</erreur>,s', $result)) {
    ajouter_langue_miroir($url, $lang);
    return true;
  }
  enlever_langue_miroir($url, $lang);
  return false;
}

//
// Gestion du dictionnaire local
//
function suggerer_dico_ortho(&$mots, $lang) {
  $lang = addslashes($lang);
  $query = "SELECT mot FROM spip_ortho_dico WHERE lang='$lang' ".
    "AND mot IN ('".join("', '", array_map('addslashes', $mots))."')";
  $result = spip_query($query);

  $mots = array_flip($mots);
  $bons = array();
  if (isset($mots[''])) unset($mots['']);
  while ($row = spip_fetch_array($result)) {
    $mot = $row['mot'];
    if (isset($mots[$mot])) {
      unset($mots[$mot]);
      $bons[] = $mot;
    }
  }

  if (count($mots)) $mots = array_flip($mots);
  else $mots = array();
  return $bons;
}

function ajouter_dico_ortho($mot, $lang) {
  global $connect_id_auteur;

  $lang = addslashes($lang);
  $mot = addslashes($mot);
  $id_auteur = intval($connect_id_auteur);
  $query = "INSERT IGNORE INTO spip_ortho_dico (lang, mot, id_auteur) ".
    "VALUES ('$lang', '$mot', '$id_auteur')";
  spip_query($query);
}

function supprimer_dico_ortho($mot, $lang) {
  $lang = addslashes($lang);
  $mot = addslashes($mot);
  $query = "DELETE FROM spip_ortho_dico WHERE lang='$lang' AND mot='$mot'";
  spip_query($query);
}

function gerer_dico_ortho($lang) {
  global $ajout_ortho, $supp_ortho;
  if ($mot = strval($ajout_ortho)) {
    ajouter_dico_ortho($mot, $lang);
  }
  if ($mot = strval($supp_ortho)) {
    supprimer_dico_ortho($mot, $lang);
  }
}

//
// Gestion du cache de corrections
//
function suggerer_cache_ortho(&$mots, $lang) {
  global $duree_cache_ortho;

  $lang = addslashes($lang);
  $query = "SELECT mot, ok, suggest FROM spip_ortho_cache WHERE lang='$lang' ".
    "AND mot IN ('".join("', '", array_map('addslashes', $mots))."') ".
    "AND maj > FROM_UNIXTIME(".(time() - $duree_cache_ortho).")";
  $result = spip_query($query);
  
  $mots = array_flip($mots);
  $suggest = array();
  if (isset($mots[''])) unset($mots['']);
  while ($row = spip_fetch_array($result)) {
    $mot = $row['mot'];
    if (isset($mots[$mot])) {
      unset($mots[$mot]);
      if (!$row['ok']) {
        if (strlen($row['suggest']))
          $suggest[$mot] = explode(",", $row['suggest']);
        else
          $suggest[$mot] = array();
      }
    }
  }
  if (count($mots)) $mots = array_flip($mots);
  else $mots = array();
  return $suggest;
}

function ajouter_cache_ortho($tous, $mauvais, $lang) {
  global $duree_cache_ortho;

  $values = array();
  $lang = addslashes($lang);
  if (count($mauvais)) {
    foreach ($mauvais as $mot => $suggest) {
      $values[] = "('$lang', '".addslashes($mot)."', 0, '".addslashes(join(",", $suggest))."')";
    }
  }
  if (count($tous)) {
    foreach ($tous as $mot) {
      if (!isset($mauvais[$mot]))
        $values[] = "('$lang', '".addslashes($mot)."', 1, '')";
    }
  }
  if (count($values)) {
    $query = "DELETE FROM spip_ortho_cache ".
      "WHERE maj < FROM_UNIXTIME(".(time() - $duree_cache_ortho).")";
    spip_query($query);
    $query = "INSERT IGNORE INTO spip_ortho_cache (lang, mot, ok, suggest) ".
      "VALUES ".join(", ", $values);
    spip_query($query);
  }
}

//
// Cette fonction doit etre appelee pour reecrire le texte en utf-8 "propre"
//
function preparer_ortho($texte, $lang) {
  include_spip("charsets.php");

  $charset = lire_meta('charset');

  if ($charset == 'utf-8')
    return unicode_to_utf_8(html2unicode($texte));
  return unicode_to_utf_8(html2unicode(charset2unicode($texte, $charset, true)));
}

function afficher_ortho($texte) {
  $charset = lire_meta('charset');
  if ($charset == 'utf-8') return $texte;

  if (!is_array($texte)) return charset2unicode($texte, 'utf-8');
  foreach ($texte as $key => $val) {
    $texte[$key] = afficher_ortho($val);
  }
  return $texte;
}

//
// Cette fonction envoie le texte prepare a un serveur d'orthographe
// et retourne un tableau de mots mal orthographies associes chacun a un tableau de mots suggeres
//
function corriger_ortho($texte, $lang, $charset = 'AUTO') {
  include_spip("charsets.php");
  include_spip("index.php");
  include_spip("filtres.php");

  $texte = preg_replace(',<code>.*?</code>,is', '', $texte);
  $texte = preg_replace(',<cadre>.*?</cadre>,is', '', $texte);
  $texte = preg_replace(',\[([^][]*)->([^][]*)\],is', '\\1', $texte);
  $texte = supprimer_tags($texte);

  $texte = " ".$texte." ";
  
  // Virer les caracteres non-alphanumeriques
  if (test_pcre_unicode()) {
    $texte = preg_replace(',[^-\''.pcre_lettres_unicode().']+,us', ' ', $texte);
  }
  else {
    // Ici bidouilles si PCRE en mode UTF-8 ne fonctionne pas correctement ...
    // Guillemets francais (plage iso-latin)
    $trans = array(chr(194).chr(171) => ' ', chr(194).chr(187) => ' ');
    $texte = strtr($texte, $trans);
    // Saloperies non-conformes
    $trans = array(chr(194).chr(133) => ' ', chr(194).chr(150) => ' ', chr(194).chr(151) => ' ');
    $texte = strtr($texte, $trans);
    // Plage ponctuation de 0x2000 a 0x206F
    // (i.e. de 226-128-128 a 226-129-176)
    $texte = preg_replace(",\xE2(\x80[\x80-\xBF]|\x81[\x80-\xAF]),", ' ', $texte);
    // Caracteres ASCII non-alphanumeriques
    $texte = preg_replace(",[^-a-zA-Z0-9\x80-\xFF']+,", ' ', $texte);
  }
  $texte = preg_replace(',\s[-\']+,', ' ', $texte); // tirets de typo
  $texte = preg_replace(',\'\s,', ' ', $texte); // apostrophes utilisees comme guillemets
  $texte = preg_replace(',\s+,', ' ', $texte);

  // Virer les mots contenant au moins un chiffre
  $texte = preg_replace(', ([^ ]*\d[^ ]* )+,', ' ', $texte);

  // Melanger les mots
  $mots = preg_split(',\s+,u', $texte);
  sort($mots);
  $mots = array_unique($mots);

  // 1. Enlever les mots du dico local
  $bons = suggerer_dico_ortho($mots, $lang);

  // 2. Enlever les mots du cache local
  $result_cache = suggerer_cache_ortho($mots, $lang);

  // 3. Envoyer les mots restants a un serveur
  $mauvais = array();

  if (count($mots)) {
    #echo count($mots);
    $texte = join(' ', $mots);
    $url = choisir_miroir_ortho($lang);
    $xml = post_ortho($url, $texte, $lang);
    if (!$xml) return false;
    if (!preg_match(',<ortho>(.*)</ortho>,s', $xml, $r)) return false;
    $xml = $r[1];
    $erreur = false;
    if (preg_match(',<erreur>.*<code>(.*)</code>.*</erreur>,s', $xml, $r))
      $erreur = $r[1];
    if (!preg_match(',<ok>(.*)</ok>,s', $xml, $r))
      return $erreur;

    // Remplir le tableau des resultats (mots mal orthographies)
    $ok = $r[1];
    while (preg_match(',<mot>(.*?)</mot>(\s*<suggest>(.*?)</suggest>)?,s', $ok, $r)) {
      $p = strpos($ok, $r[0]);
      $ok = substr($ok, $p + strlen($r[0]));
      $mot = $r[1];
      if ($suggest = $r[3]) {
        $mauvais[$mot] = preg_split('/[\s,]+/', $suggest);
      }
      else {
        $mauvais[$mot] = array();
      }
    }
  }
  if (!$erreur) ajouter_cache_ortho($mots, $mauvais, $lang);

  // Retour a l'envoyeur
  $mauvais = array_merge($result_cache, $mauvais);
  $result = array(
    'bons' => $bons,
    'mauvais' => $mauvais
  );
  if ($erreur) $result['erreur'] = $erreur;
  return $result;
}

//
// Fonctions d'affichage HTML
//

function panneau_ortho($ortho_result) {
  global $id_suggest;

  $id_suggest = array();
  $i = 1;

  $mauvais = $ortho_result['mauvais'];
  $bons = $ortho_result['bons'];
  if (!count($mauvais) && !count($bons)) return;
  ksort($mauvais);

  echo "<script type='text/javascript'><!--
  var curr_suggest = null;
  function suggest(id) {
    var menu_box;
    if (curr_suggest)
      document.getElementById('suggest' + curr_suggest).className = 'suggest-inactif';
    if (1 || id!=curr_suggest) {
      document.getElementById('suggest' + id).className = 'suggest-actif';
      curr_suggest = id;
    }
    else curr_suggest = null;
    menu_box = document.getElementById('select_ortho');
    if (menu_box.length > id) menu_box.selectedIndex = id;
  }";
  echo "//--></script>";

  echo "<form class='form-ortho verdana2' action='' method='get'>\n";
  echo "<select name='select_ortho' id='select_ortho' onChange='suggest(this.selectedIndex);'>\n";
  echo "<option value='0'>"._L("... mots &agrave; corriger ...")."</option>\n";
  foreach ($mauvais as $mot => $suggest) {
    $id = $id_suggest[$mot] = "$i";
    $i++;
    $mot_html = afficher_ortho($mot);
    echo "<option value='$id'>$mot_html</option>\n";
  }
  foreach ($bons as $mot) {
    $id = $id_suggest[$mot] = "$i";
    $i++;
  }
  echo "</select>\n";
  echo "</form>\n";
  // Mots mal orthographies :
  // liste des suggestions plus lien pour ajouter au dico
  foreach ($mauvais as $mot => $suggest) {
    $id = $id_suggest[$mot];
    $mot_html = afficher_ortho($mot);
    echo "<div class='suggest-inactif' id='suggest$id'>";
    echo "<span class='ortho'>$mot_html</span>\n";
    echo "<div class='detail'>\n";
    if (is_array($suggest) && count($suggest)) {
      echo "<ul>\n";
      $i = 0;
      foreach ($suggest as $sug) {
        if (++$i > 12) {
          echo "<li><i>(...)</i></li>\n";
          break;
        }
        echo "<li>".afficher_ortho(typo($sug))."</li>\n";
      }
      echo "</ul>\n";
    }
    else {
      echo "<i>Aucune suggestion n'a &eacute;t&eacute; trouv&eacute;e pour ce mot.</i>";
    }
    echo "<br />";
    $link = new Link;
    $link->delVar('supp_ortho');
    $link->addVar('ajout_ortho', $mot);
    icone_horizontale(_L("Ajouter ce mot au dictionnaire"), $link->getUrl(), "ortho-24.gif", "creer.gif");
    echo "</div>\n";
    echo "</div>\n\n";
  }
  // Mots trouves dans le dico :
  // message plus lien pour retirer du dico
  foreach ($bons as $mot) {
    $id = $id_suggest[$mot];
    $mot_html = afficher_ortho($mot);
    echo "<div class='suggest-inactif' id='suggest$id'>";
    echo "<span class='ortho-dico'>$mot_html</span>";
    echo "<div class='detail'>\n";
    echo "<i>"._L("Ce mot fait partie du dictionnaire du site.")."</i>";
    echo "<br />";
    $link = new Link;
    $link->delVar('ajout_ortho');
    $link->addVar('supp_ortho', $mot);
    icone_horizontale(_L("Enlever ce mot du dictionnaire"), $link->getUrl(), "ortho-24.gif", "supprimer.gif");
    echo "</div>\n";
    echo "</div>\n";
  }
}

function souligner_ortho($texte, $lang, $ortho_result) {
  global $id_suggest;
  $vu = array();

  $mauvais = $ortho_result['mauvais'];
  $bons = $ortho_result['bons'];

  $texte = " ".$texte." ";
  // Chercher et remplacer les mots un par un
  $t0 = explode(" ", microtime());
  $delim = '[^-\''.pcre_lettres_unicode().']';
  foreach ($mauvais as $mot => $suggest) {
    $pattern = ",$delim".$mot."$delim,us";
    // Recuperer les occurences du mot dans le texte
    if (preg_match_all($pattern, $texte, $regs, PREG_SET_ORDER)) {
      $id = $id_suggest[$mot];
      $mot_html = afficher_ortho($mot);
      foreach ($regs as $r) {
        if ($vu[$cherche = $r[0]]) continue;
        $vu[$cherche] = 1;
        $html = "<a class='ortho' onclick=\"suggest($id);return false;\" href=''>$mot_html</a>";
        $remplace = str_replace($mot, $html, $cherche);
        $table = explode($cherche, $texte);
        unset($avant);
        $texte = '';
        foreach ($table as $s) {
          if (!isset($avant)) {
            $avant = $s;
            continue;
          }
          $ok = true;
          $texte .= $avant;
          if (is_int($deb_tag = strrpos($texte, '<'))) {
            if (strrpos($texte, '>') <= $deb_tag)
              $ok = false;
          }
          if ($ok) {
            $texte .= $remplace;
          }
          else {
            $texte .= $cherche;
          }
          $avant = $s;
        }
        $texte .= $avant;
      }
    }
  }
  foreach ($bons as $mot) {
    $pattern = ",$delim".$mot."$delim,us";
    // Recuperer les occurences du mot dans le texte
    if (preg_match_all($pattern, $texte, $regs, PREG_SET_ORDER)) {
      $id = $id_suggest[$mot];
      $mot_html = afficher_ortho($mot);
      foreach ($regs as $r) {
        if ($vu[$cherche = $r[0]]) continue;
        $vu[$cherche] = 1;
        $html = "<a class='ortho-dico' onclick=\"suggest($id);return false;\" href=''>$mot_html</a>";
        $remplace = str_replace($mot, $html, $cherche);
        $table = explode($cherche, $texte);
        unset($avant);
        $texte = '';
        foreach ($table as $s) {
          if (!isset($avant)) {
            $avant = $s;
            continue;
          }
          $ok = true;
          $texte .= $avant;
          if (is_int($deb_tag = strrpos($texte, '<'))) {
            if (strrpos($texte, '>') <= $deb_tag)
              $ok = false;
          }
          if ($ok) {
            $texte .= $remplace;
          }
          else {
            $texte .= $cherche;
          }
          $avant = $s;
        }
        $texte .= $avant;
      }
    }
  }
  $t1 = explode(" ", microtime());
  $dt = floor(1000 * ($t1[0] + $t1[1] - $t0[0] - $t0[1])) / 1000;
  //echo "<div style='font-weight: bold; color: red;'>$dt s.</div>";
  
  $texte = preg_replace(',(^ | $),', '', $texte);
  $texte = afficher_ortho($texte);
  return $texte;
}

// Test de fonctionnement du support UTF-8 dans PCRE
// (contournement bug Debian Woody)
function test_pcre_unicode() {
  static $pcre_ok = 0;

  if (!$pcre_ok) {
    include_spip("charsets.php");
    $s = " ".chr(195).chr(169)."t".chr(195).chr(169)." ";
    if (preg_match(',\W\w\w\w\W,u', $s)) $pcre_ok = 1;
    else $pcre_ok = -1;
  }
  return $pcre_ok == 1;
}

function pcre_lettres_unicode() {
  static $plage_unicode;

  if (!$plage_unicode) {
    if (test_pcre_unicode()) {
      // cf. http://www.unicode.org/charts/
      $plage_unicode = '\w' // iso-latin
        . '\x{100}-\x{24f}' // europeen etendu
/* . '\x{370}-\x{3ff}' // grec
        . '\x{400}-\x{52f}' // cyrillique*/
        . '\x{300}-\x{1cff}' // des tas de trucs
      ;
    }
    else {
      // fallback a trois sous
      $plage_unicode = '\w';
    }
  }
  return $plage_unicode;
}

function init_ortho() {
  global $duree_cache_ortho, $duree_cache_miroirs_ortho;

   $duree_cache_ortho = 7 * 24 * 3600;
  $duree_cache_miroirs_ortho = 24 * 3600;
  lire_miroirs_ortho();
}

init_ortho();

?>

Index: inc_version.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_version.php3,v
retrieving revision 1.349
retrieving revision 1.350
diff -u -d -r1.349 -r1.350
--- inc_version.php3 27 Aug 2004 12:52:00 -0000 1.349
+++ inc_version.php3 27 Aug 2004 18:55:23 -0000 1.350
@@ -174,6 +174,9 @@
// Produire du TeX ou de MathML ?
$traiter_math = 'tex';

+// Masquer les warning
+error_reporting(E_ALL ^ E_NOTICE);
+
/* ATTENTION CES VARIABLES NE FONCTIONNENT PAS ENCORE */
// Extension du fichier du squelette
$extension_squelette = 'html';
@@ -202,7 +205,7 @@
// (utilise pour les modifs de la base de donnees)

// version de la base
-$spip_version = 1.805;
+$spip_version = 1.806;

// version de spip
$spip_version_affichee = "1.8 alpha 6 CVS";
@@ -211,9 +214,6 @@
if (ereg('Name: v(.*) ','$Name$', $regs)) $spip_version_affichee = $regs[1];

-// Pas de warnings idiots
-error_reporting(E_ALL ^ E_NOTICE);
-
// ** Securite **
$auteur_session = '';
$connect_statut = '';
@@ -820,7 +820,7 @@
}
function test_flock ($fichier, $fp=false) {
   static $flock = array();
- global $flag_flock;
+ global $flag_flock, $os_serveur;
   if (!$flag_flock
   OR $os_serveur == 'windows') // sous win rename() plante avec fopen()
     return false;
@@ -864,6 +864,8 @@
}

function spip_file_get_contents ($fichier) {
+ global $os_serveur;
+
   if (substr($fichier, -3) != '.gz') {
     if (function_exists('file_get_contents')
     AND $os_serveur !='windows') # windows retourne ''

Index: inc_diff.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_diff.php3,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- inc_diff.php3 26 Jul 2004 22:17:33 -0000 1.4
+++ inc_diff.php3 27 Aug 2004 18:55:23 -0000 1.5
@@ -51,7 +51,7 @@

   // Insertion des points
   foreach ($t as $y => $c) $t_pos[trim($c)][] = $y;
-
+
   foreach ($s as $x => $c) {
     $c = trim($c);
     if (!$t_pos[$c]) continue;
@@ -60,20 +60,29 @@
       for ($len = $max_len; $len > 0; $len--) {
         if ($paths_ymin[$len] < $y) {
           $paths_ymin[$len + 1] = $y;
- $paths[$len + 1] = $paths[$len];
- $paths[$len + 1][0][$x] = $y;
- $paths[$len + 1][1][$y] = $x;
+ // On construit le resultat sous forme de chaine d'abord,
+ // car les tableaux de PHP sont dispendieux en taille memoire
+ $paths[$len + 1] = $paths[$len]." $x,$y";
           break;
         }
       }
       if ($len + 1 > $max_len) $max_len = $len + 1;
       if ($len == 0) {
         $paths_ymin[1] = $y;
- $paths[1] = array(0 => array($x => $y), 1 => array($y => $x));
+ $paths[1] = "$x,$y";
       }
     }
   }
- if ($paths[$max_len]) return $paths[$max_len];
+ if ($paths[$max_len]) {
+ $path = explode(" ", $paths[$max_len]);
+ $u = $v = array();
+ foreach ($path as $p) {
+ list($x, $y) = explode(",", $p);
+ $u[$x] = $y;
+ $v[$y] = $x;
+ }
+ return array($u, $v);
+ }
   return array(0 => array(), 1 => array());
}

Index: inc_majbase.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_majbase.php3,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- inc_majbase.php3 27 Aug 2004 04:27:03 -0000 1.9
+++ inc_majbase.php3 27 Aug 2004 18:55:23 -0000 1.10
@@ -886,6 +886,10 @@
     maj_version(1.805);
   }

+ // tables d'orthographe
+ if ($version_installee < 1.806)
+ maj_version(1.806);
+
   return true;
}

Index: inc_auxbase.php3

RCS file: /home/spip-cvs/spip/ecrire/inc_auxbase.php3,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- inc_auxbase.php3 22 Aug 2004 16:38:32 -0000 1.3
+++ inc_auxbase.php3 27 Aug 2004 18:55:23 -0000 1.4
@@ -289,6 +289,25 @@
     "KEY fichier" => "fichier",
     "KEY id" => "id");

+$spip_ortho_cache = array(
+ "lang" => "VARCHAR(10) NOT NULL",
+ "mot" => "VARCHAR(255) BINARY NOT NULL",
+ "ok" => "TINYINT NOT NULL",
+ "suggest" => "BLOB NOT NULL",
+ "maj" => "TIMESTAMP");
+$spip_ortho_cache_key = array(
+ "PRIMARY KEY" => "lang, mot",
+ "KEY maj" => "maj");
+
+$spip_ortho_dico = array(
+ "lang" => "VARCHAR(10) NOT NULL",
+ "mot" => "VARCHAR(255) BINARY NOT NULL",
+ "id_auteur" => "BIGINT UNSIGNED NOT NULL",
+ "maj" => "TIMESTAMP");
+$spip_ortho_dico_key = array(
+ "PRIMARY KEY" => "lang, mot",);
+
+
global $tables_auxiliaires;

$tables_auxiliaires =
@@ -354,7 +373,11 @@
   'versions_fragments' => array('field' => &$spip_versions_fragments,
            'key' => &$spip_versions_fragments_key),
   'caches' => array('field' => &$spip_caches,
- 'key' => &$spip_caches_key)
+ 'key' => &$spip_caches_key),
+ 'ortho_cache' => array('field' => &$spip_ortho_cache,
+ 'key' => &$spip_ortho_cache_key),
+ 'ortho_dico' => array('field' => &$spip_ortho_dico,
+ 'key' => &$spip_ortho_dico_key)
   );

?>