From 28490c47e0e549195b7a65b171076d8329c809b0 Mon Sep 17 00:00:00 2001
From: "Committo,Ergo:sum" <esj@rezo.net>
Date: Sat, 13 Jan 2007 12:06:27 +0000
Subject: [PATCH] =?UTF-8?q?Am=C3=A9lioration=20de=20[8179]:=20dans=20l'esp?=
 =?UTF-8?q?ace=20priv=C3=A9=20comme=20dans=20le=20public=20(i.e.=20les=20s?=
 =?UTF-8?q?quelettes),=20on=20profite=20de=20la=20mise=20en=20cache=20de?=
 =?UTF-8?q?=20l'analyse=20des=20DTD=20pour=20aller=20y=20chercher=20la=20d?=
 =?UTF-8?q?efinition=20des=20entites=20html=20et=20ainsi=20contourner=20le?=
 =?UTF-8?q?=20bug=20de=20SAX=20de=20mani=C3=A8re=20totalement=20fiable.=20?=
 =?UTF-8?q?En=20cas=20de=20Doctype=20indisponible=20(squelettes=20perso=20?=
 =?UTF-8?q?ou=20plugin,=20pour=20la=20distrib=20standard=20elle=20y=20est?=
 =?UTF-8?q?=20toujours)=20on=20continue=20=C3=A0=20utiliser=20html2unicode?=
 =?UTF-8?q?=20(=C3=A0=20qui=20il=20manque=20les=20entites=20dfinies=20dans?=
 =?UTF-8?q?=20xhmt=5Fsymbol.ent).=20A=20noter=20que=20SAX=20ne=20consid?=
 =?UTF-8?q?=C3=A8re=20pas=20comme=20des=20entit=C3=A9s=20les=204=20cas=20p?=
 =?UTF-8?q?articuliers=20notoires=20(amp=20lt=20gt=20quot)=20lorsqu'ils=20?=
 =?UTF-8?q?sont=20dans=20un=20attribut;=20c'est=20insuffisant=20mais=20?=
 =?UTF-8?q?=C3=A7a=20suffit=20=C3=A0=20contourner=20le=20bug=20proprement.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ecrire/inc/indenter_xml.php |  4 ---
 ecrire/inc/sax.php          | 60 ++++++++++++++++++++++++++++++++++++-
 ecrire/inc/valider_xml.php  | 44 ---------------------------
 3 files changed, 59 insertions(+), 49 deletions(-)

diff --git a/ecrire/inc/indenter_xml.php b/ecrire/inc/indenter_xml.php
index 2504a48a76..5ba800146f 100644
--- a/ecrire/inc/indenter_xml.php
+++ b/ecrire/inc/indenter_xml.php
@@ -39,10 +39,6 @@ function defautElement($phraseur, $data)
 // http://doc.spip.org/@phraserTout
 function phraserTout($phraseur, $data)
 {
-  // bug de SAX qui ne dit pas si une Entite est dans un attribut ou non
-  // ==> eliminer toutes les entites
-
-	$data = unicode2charset(html2unicode($data, true));
 	xml_parsestring($phraseur, $data);
 	return !$this->err ?  $this->res : join('<br />', $this->err) . '<br />';
 }
diff --git a/ecrire/inc/sax.php b/ecrire/inc/sax.php
index eba92dd3fd..ba5f5b020c 100644
--- a/ecrire/inc/sax.php
+++ b/ecrire/inc/sax.php
@@ -14,6 +14,7 @@ if (!defined("_ECRIRE_INC_VERSION")) return;
 
 include_spip('inc/filtres');
 include_spip('inc/charsets');
+include_spip('xml/interfaces');
 
 // http://doc.spip.org/@xml_debutElement
 function xml_debutElement($parser, $name, $attrs)
@@ -190,7 +191,7 @@ function inc_sax_dist($page, $apply=false)
 		ob_end_clean();
 	}
 
-	$res = $phraseur_xml->phraserTout($xml_parser, $page);
+	$res = $phraseur_xml->phraserTout($xml_parser, sax_bug($page));
 
 	xml_parser_free($xml_parser);
 
@@ -200,4 +201,61 @@ function inc_sax_dist($page, $apply=false)
 	return $page;
 }
 
+// SAX ne dit pas si une Entite est dans un attribut ou non.
+// Les eliminer toutes sinon celles des attributs apparaissent en zone texte!
+// Celles fondamentales pour la lecture (lt gt quot amp) sont conservees 
+// (d'ailleurs SAX ne les considere pas comme des entites dans un attribut)
+// Si la DTD est dispo, on va chercher les entites dedans
+// sinon on se rabat sur ce qu'en connait SPIP en standard.
+
+function sax_bug($data)
+{
+	$r = analyser_doctype($data);
+	if (!$r)
+		$data = html2unicode($data, true);
+	else  {
+		list ($topelement, $avail, $grammaire, $rotlvl) = $r;
+		$file = _DIR_DTD . preg_replace('/[^\w.]/','_', $rotlvl) . '.gz';
+		if (lire_fichier($file, $r))
+		  $this->dtc = unserialize($r);
+		else {
+		  include_spip('xml/analyser_dtd');
+		  $this->dtc = charger_dtd($grammaire, $avail);
+		  ecrire_fichier($file, serialize($this->dtc));
+		}
+		$trans = array();
+		
+		foreach($this->dtc->entites as $k => $v)
+		  if (!strpos(" amp lt gt quot ", $k))
+		    $trans["&$k;"] = $v;
+		$data = strtr($data, $trans);
+	}
+	return unicode2charset($data);
+}
+
+// http://doc.spip.org/@analyser_doctype
+function analyser_doctype($data)
+{
+	if (!preg_match(_REGEXP_DOCTYPE, $data, $r))
+		return array();
+
+	list(,,$topelement, $avail,$suite) = $r;
+
+	if (!preg_match('/^"([^"]*)"\s*(.*)$/', $suite, $r))
+		if (!preg_match("/^'([^']*)'\s*(.*)$/", $suite, $r))
+			return  array();
+	list(,$rotlvl, $suite) = $r;
+
+	if (!$suite) {
+		$grammaire = $rotlvl;
+		$rotlvl = '';
+	} else {
+		if (!preg_match('/^"([^"]*)"\s*$/', $suite, $r))
+			if (!preg_match("/^'([^']*)'\s*$/", $suite, $r))
+				return array();
+		$grammaire = $r[1];
+	}
+	return array($topelement, $avail, $grammaire, $rotlvl);
+}
+
 ?>
diff --git a/ecrire/inc/valider_xml.php b/ecrire/inc/valider_xml.php
index ccd7bedcd9..38bfc22f51 100644
--- a/ecrire/inc/valider_xml.php
+++ b/ecrire/inc/valider_xml.php
@@ -13,32 +13,6 @@
 if (!defined("_ECRIRE_INC_VERSION")) return;
 
 include_spip('inc/sax');
-include_spip('xml/interfaces');
-
-// http://doc.spip.org/@analyser_doctype
-function analyser_doctype($data)
-{
-	if (!preg_match(_REGEXP_DOCTYPE, $data, $r))
-		return array();
-
-	list(,,$topelement, $avail,$suite) = $r;
-
-	if (!preg_match('/^"([^"]*)"\s*(.*)$/', $suite, $r))
-		if (!preg_match("/^'([^']*)'\s*(.*)$/", $suite, $r))
-			return  array();
-	list(,$rotlvl, $suite) = $r;
-
-	if (!$suite) {
-		$grammaire = $rotlvl;
-		$rotlvl = '';
-	} else {
-		if (!preg_match('/^"([^"]*)"\s*$/', $suite, $r))
-			if (!preg_match("/^'([^']*)'\s*$/", $suite, $r))
-				return array();
-		$grammaire = $r[1];
-	}
-	return array($topelement, $avail, $grammaire, $rotlvl);
-}
 
 // http://doc.spip.org/@validerElement
 function validerElement($phraseur, $name, $attrs)
@@ -307,24 +281,6 @@ function defautElement($phraseur, $data)
 // http://doc.spip.org/@phraserTout
 function phraserTout($phraseur, $data)
 { 
-	$r = analyser_doctype($data);
-	if ($r) {
-		list ($topelement, $avail, $grammaire, $rotlvl) = $r;
-		$file = _DIR_DTD . preg_replace('/[^\w.]/','_', $rotlvl) . '.gz';
-		if (lire_fichier($file, $r))
-		  $this->dtc = unserialize($r);
-		else {
-		  include_spip('xml/analyser_dtd');
-		  $this->dtc = charger_dtd($grammaire, $avail);
-		  ecrire_fichier($file, serialize($this->dtc));
-		}
-	}
-
-  // bug de SAX qui ne dit pas si une Entite est dans un attribut ou non
-  // ==> eliminer toutes les entites
-
-	$data = unicode2charset(html2unicode($data, true));
-
 	xml_parsestring($phraseur, $data);
 
 	$valider_passe2 = charger_fonction('valider_passe2', 'inc');
-- 
GitLab