X-Git-Url: https://git.cyclocoop.org/?a=blobdiff_plain;f=www%2Fecrire%2Fxml%2Fvalider.php;fp=www%2Fecrire%2Fxml%2Fvalider.php;h=f2553090f5cf374a73c28e53800de96686ca39b0;hb=4f443dce95ff6f8221c189880a70c74ce1c1f238;hp=d2a02d18c7170dca588115169cb3da53051ea4fc;hpb=4a628e9b277d3617535f99d663ca79fa2e891177;p=lhc%2Fweb%2Fwww.git diff --git a/www/ecrire/xml/valider.php b/www/ecrire/xml/valider.php index d2a02d18..f2553090 100644 --- a/www/ecrire/xml/valider.php +++ b/www/ecrire/xml/valider.php @@ -3,346 +3,364 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2017 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * \***************************************************************************/ -if (!defined('_ECRIRE_INC_VERSION')) return; - -// Validateur XML en deux passes, fonde sur SAX pour la premiere -// Faudrait faire deux classes car pour la premiere passe -// on a les memes methodes et variables que l'indenteur +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} +/** + * Validateur XML en deux passes, fondé sur SAX pour la première + * + * @note + * Faudrait faire deux classes car pour la première passe + * on a les memes methodes et variables que l'indenteur + **/ class ValidateurXML { -// http://doc.spip.org/@validerElement -function validerElement($phraseur, $name, $attrs) -{ - if (!($p = isset($this->dtc->elements[$name]))) { - if ($p = strpos($name, ':')) { - $name = substr($name, $p+1); - $p = isset($this->dtc->elements[$name]); + // http://code.spip.net/@validerElement + public function validerElement($phraseur, $name, $attrs) { + if (!($p = isset($this->dtc->elements[$name]))) { + if ($p = strpos($name, ':')) { + $name = substr($name, $p + 1); + $p = isset($this->dtc->elements[$name]); + } + if (!$p) { + coordonnees_erreur($this, " $name : " + . _T('zxml_inconnu_balise')); + + return; + } } - if (!$p) { - coordonnees_erreur($this," $name : " - . _T('zxml_inconnu_balise')); - return; + // controler les filles illegitimes, ca suffit + $depth = $this->depth; + $ouvrant = $this->ouvrant; + #spip_log("trouve $name apres " . $ouvrant[$depth]); + if (isset($ouvrant[$depth])) { + if (preg_match('/^\s*(\w+)/', $ouvrant[$depth], $r)) { + $pere = $r[1]; + #spip_log("pere $pere"); + if (isset($this->dtc->elements[$pere])) { + $fils = $this->dtc->elements[$pere]; + #spip_log("rejeton $name fils " . @join(',',$fils)); + if (!($p = @in_array($name, $fils))) { + if ($p = strpos($name, ':')) { + $p = substr($name, $p + 1); + $p = @in_array($p, $fils); + } + } + if (!$p) { + $bons_peres = @join(', ', $this->dtc->peres[$name]); + coordonnees_erreur($this, " $name " + . _T('zxml_non_fils') + . ' ' + . $pere + . '' + . (!$bons_peres ? '' + : ('

' . _T('zxml_mais_de') . ' ' . $bons_peres . '

'))); + } elseif ($this->dtc->regles[$pere][0] == '/') { + $frat = substr($depth, 2); + if (!isset($this->fratrie[$frat])) { + $this->fratrie[$frat] = ''; + } + $this->fratrie[$frat] .= "$name "; + } + } + } } - } - // controler les filles illegitimes, ca suffit - $depth = $this->depth; - $ouvrant = $this->ouvrant; -# spip_log("trouve $name apres " . $ouvrant[$depth]); - if (isset($ouvrant[$depth])) { - if (preg_match('/^\s*(\w+)/', $ouvrant[$depth], $r)) { - $pere = $r[1]; -# spip_log("pere $pere"); - if (isset($this->dtc->elements[$pere])) { - $fils = $this->dtc->elements[$pere]; -# spip_log("rejeton $name fils " . @join(',',$fils)); - if (!($p = @in_array($name, $fils))) { - if ($p = strpos($name, ':')) { - $p = substr($name, $p+1); - $p = @in_array($p, $fils); + // Init de la suite des balises a memoriser si regle difficile + if ($this->dtc->regles[$name] and $this->dtc->regles[$name][0] == '/') { + $this->fratrie[$depth] = ''; + } + if (isset($this->dtc->attributs[$name])) { + foreach ($this->dtc->attributs[$name] as $n => $v) { + if (($v[1] == '#REQUIRED') and (!isset($attrs[$n]))) { + coordonnees_erreur($this, " $n" + . ' : ' + . _T('zxml_obligatoire_attribut') + . " $name"); + } } } - if (!$p) { - $bons_peres = @join ('
, ', $this->dtc->peres[$name]); - coordonnees_erreur($this, " $name " - . _T('zxml_non_fils') - . ' ' - . $pere - . '' - . (!$bons_peres ? '' - : ('

'._T('zxml_mais_de').' '. $bons_peres . '

'))); - } else if ($this->dtc->regles[$pere][0]=='/') { - $frat = substr($depth,2); - if (!isset($this->fratrie[$frat])) { - $this->fratrie[$frat] = ''; + } + + // http://code.spip.net/@validerAttribut + public function validerAttribut($phraseur, $name, $val, $bal) { + // Si la balise est inconnue, eviter d'insister + if (!isset($this->dtc->attributs[$bal])) { + return; + } + + $a = $this->dtc->attributs[$bal]; + if (!isset($a[$name])) { + $bons = join(', ', array_keys($a)); + if ($bons) { + $bons = " title=' " . + _T('zxml_connus_attributs') . + ' : ' . + $bons . + "'"; + } + $bons .= " style='font-weight: bold'"; + coordonnees_erreur($this, " $name " + . _T('zxml_inconnu_attribut') . ' ' . _T('zxml_de') + . " $bal (" + . _T('zxml_survoler') + . ")"); + } else { + $type = $a[$name][0]; + if (!preg_match('/^\w+$/', $type)) { + $this->valider_motif($phraseur, $name, $val, $bal, $type); + } else { + if (method_exists($this, $f = 'validerAttribut_' . $type)) { + $this->$f($phraseur, $name, $val, $bal); + } } - $this->fratrie[$frat] .= "$name "; + # else spip_log("$type type d'attribut inconnu"); } - } - } } - // Init de la suite des balises a memoriser si regle difficile - if ($this->dtc->regles[$name][0]=='/') - $this->fratrie[$depth]=''; - if (isset($this->dtc->attributs[$name])) { - foreach ($this->dtc->attributs[$name] as $n => $v) - { if (($v[1] == '#REQUIRED') AND (!isset($attrs[$n]))) - coordonnees_erreur($this, " $n" - . ' : ' - . _T('zxml_obligatoire_attribut') - . " $name"); - } + + public function validerAttribut_NMTOKEN($phraseur, $name, $val, $bal) { + $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKEN); } -} -// http://doc.spip.org/@validerAttribut -function validerAttribut($phraseur, $name, $val, $bal) -{ - // Si la balise est inconnue, eviter d'insister - if (!isset($this->dtc->attributs[$bal])) - return ; - - $a = $this->dtc->attributs[$bal]; - if (!isset($a[$name])) { - $bons = join(', ',array_keys($a)); - if ($bons) - $bons = " title=' " . - _T('zxml_connus_attributs') . - ' : ' . - $bons . - "'"; - $bons .= " style='font-weight: bold'"; - coordonnees_erreur($this, " $name " - . _T('zxml_inconnu_attribut').' '._T('zxml_de') - . " $bal (" - . _T('zxml_survoler') - . ")"); - } else{ - $type = $a[$name][0]; - if (!preg_match('/^\w+$/', $type)) - $this->valider_motif($phraseur, $name, $val, $bal, $type); - else if (method_exists($this, $f = 'validerAttribut_' . $type)) - $this->$f($phraseur, $name, $val, $bal); -# else spip_log("$type type d'attribut inconnu"); + public function validerAttribut_NMTOKENS($phraseur, $name, $val, $bal) { + $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKENS); } -} -function validerAttribut_NMTOKEN($phraseur, $name, $val, $bal) -{ - $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKEN); -} + // http://code.spip.net/@validerAttribut_ID + public function validerAttribut_ID($phraseur, $name, $val, $bal) { + if (isset($this->ids[$val])) { + list($l, $c) = $this->ids[$val]; + coordonnees_erreur($this, "

$val " + . _T('zxml_valeur_attribut') + . " $name " + . _T('zxml_de') + . " $bal " + . _T('zxml_vu') + . " (L$l,C$c)"); + } else { + $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_ID); + $this->ids[$val] = array(xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)); + } + } -function validerAttribut_NMTOKENS($phraseur, $name, $val, $bal) -{ - $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKENS); -} + // http://code.spip.net/@validerAttribut_IDREF + public function validerAttribut_IDREF($phraseur, $name, $val, $bal) { + $this->idrefs[] = array($val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)); + } -// http://doc.spip.org/@validerAttribut_ID -function validerAttribut_ID($phraseur, $name, $val, $bal) -{ - if (isset($this->ids[$val])) { - list($l,$c) = $this->ids[$val]; - coordonnees_erreur($this, "

$val " - . _T('zxml_valeur_attribut') - . " $name " - . _T('zxml_de') - . " $bal " - . _T('zxml_vu') - . " (L$l,C$c)"); - } else { - $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_ID); - $this->ids[$val] = array(xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)); + // http://code.spip.net/@validerAttribut_IDREFS + public function validerAttribut_IDREFS($phraseur, $name, $val, $bal) { + $this->idrefss[] = array($val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)); } -} -// http://doc.spip.org/@validerAttribut_IDREF -function validerAttribut_IDREF($phraseur, $name, $val, $bal) -{ - $this->idrefs[] = array($val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)); -} + // http://code.spip.net/@valider_motif + public function valider_motif($phraseur, $name, $val, $bal, $motif) { + if (!preg_match($motif, $val)) { + coordonnees_erreur($this, "$val " + . _T('zxml_valeur_attribut') + . " $name " + . _T('zxml_de') + . " $bal " + . _T('zxml_non_conforme') + . "

" + . "" . $motif . ""); + } + } -// http://doc.spip.org/@validerAttribut_IDREFS -function validerAttribut_IDREFS($phraseur, $name, $val, $bal) -{ - $this->idrefss[] = array($val, xml_get_current_line_number($phraseur), xml_get_current_column_number($phraseur)); -} + // http://code.spip.net/@valider_idref + public function valider_idref($nom, $ligne, $col) { + if (!isset($this->ids[$nom])) { + $this->err[] = array("

$nom " . _T('zxml_inconnu_id'), $ligne, $col); + } + } -// http://doc.spip.org/@valider_motif -function valider_motif($phraseur, $name, $val, $bal, $motif) -{ - if (!preg_match($motif, $val)) { - coordonnees_erreur($this, "$val " - . _T('zxml_valeur_attribut') - . " $name " - . _T('zxml_de') - . " $bal " - . _T('zxml_non_conforme') - . "

" - . "" . $motif . ""); + // http://code.spip.net/@valider_passe2 + public function valider_passe2() { + if (!$this->err) { + foreach ($this->idrefs as $idref) { + list($nom, $ligne, $col) = $idref; + $this->valider_idref($nom, $ligne, $col); + } + foreach ($this->idrefss as $idref) { + list($noms, $ligne, $col) = $idref; + foreach (preg_split('/\s+/', $noms) as $nom) { + $this->valider_idref($nom, $ligne, $col); + } + } + } } -} -// http://doc.spip.org/@valider_idref -function valider_idref($nom, $ligne, $col) -{ - if (!isset($this->ids[$nom])) - $this->err[]= array("

$nom " . _T('zxml_inconnu_id'), $ligne, $col); -} + // http://code.spip.net/@debutElement + public function debutElement($phraseur, $name, $attrs) { + if ($this->dtc->elements) { + $this->validerElement($phraseur, $name, $attrs); + } -// http://doc.spip.org/@valider_passe2 -function valider_passe2() -{ - if (!$this->err) { - foreach ($this->idrefs as $idref) { - list($nom, $ligne, $col) = $idref; - $this->valider_idref($nom, $ligne, $col); + if ($f = $this->process['debut']) { + $f($this, $name, $attrs); } - foreach ($this->idrefss as $idref) { - list($noms, $ligne, $col) = $idref; - foreach(preg_split('/\s+/', $noms) as $nom) - $this->valider_idref($nom, $ligne, $col); + $depth = $this->depth; + $this->debuts[$depth] = strlen($this->res); + foreach ($attrs as $k => $v) { + $this->validerAttribut($phraseur, $k, $v, $name); } } -} -// http://doc.spip.org/@debutElement -function debutElement($phraseur, $name, $attrs) -{ - if ($this->dtc->elements) - $this->validerElement($phraseur, $name, $attrs); - - if ($f = $this->process['debut']) $f($this, $name, $attrs); - $depth = $this->depth; - $this->debuts[$depth] = strlen($this->res); - foreach ($attrs as $k => $v) { - $this->validerAttribut($phraseur, $k, $v, $name); - } -} + // http://code.spip.net/@finElement + public function finElement($phraseur, $name) { + $depth = $this->depth; + $contenu = $this->contenu; -// http://doc.spip.org/@finElement -function finElement($phraseur, $name) -{ - $depth = $this->depth; - $contenu = $this->contenu; - - $n = strlen($this->res); - $c = strlen(trim($contenu[$depth])); - $k = $this->debuts[$depth]; - - $regle = $this->dtc->regles[$name]; - $vide = ($regle == 'EMPTY'); - // controler que les balises devant etre vides le sont - if ($vide) { - if ($n <> ($k + $c)) - coordonnees_erreur($this, "

$name " - . _T('zxml_nonvide_balise')); - // pour les regles PCDATA ou iteration de disjonction, tout est fait - } elseif ($regle AND ($regle != '*')) { - if ($regle == '+') { - // iteration de disjonction non vide: 1 balise au - - if ($n == $k) { - coordonnees_erreur($this, "

\n$name " - . _T('zxml_vide_balise')); + $n = strlen($this->res); + $c = strlen(trim($contenu[$depth])); + $k = $this->debuts[$depth]; + + $regle = isset($this->dtc->regles[$name]) ? $this->dtc->regles[$name] : false; + $vide = ($regle == 'EMPTY'); + // controler que les balises devant etre vides le sont + if ($vide) { + if ($n <> ($k + $c)) { + coordonnees_erreur($this, "

$name " . _T('zxml_nonvide_balise')); } - } else { - $f = $this->fratrie[substr($depth,2)]; - if (!preg_match($regle, $f)) { - coordonnees_erreur($this, - "

\n$name " - . _T('zxml_succession_fils_incorrecte') - . ' : ' - . $f - . ''); + // pour les regles PCDATA ou iteration de disjonction, tout est fait + } elseif ($regle and ($regle != '*')) { + if ($regle == '+') { + // iteration de disjonction non vide: 1 balise au - + if ($n == $k) { + coordonnees_erreur($this, "

\n$name " + . _T('zxml_vide_balise')); + } + } else { + $f = isset($this->fratrie[substr($depth, 2)]) ? $this->fratrie[substr($depth, 2)] : null; + if (is_null($f) or !preg_match($regle, $f)) { + coordonnees_erreur($this, + "

\n$name " + . _T('zxml_succession_fils_incorrecte') + . ' : ' + . $f + . ''); + } } + + } + if ($f = $this->process['fin']) { + $f($this, $name, $vide); } + } + // http://code.spip.net/@textElement + public function textElement($phraseur, $data) { + if (trim($data)) { + $d = $this->depth; + $d = $this->ouvrant[$d]; + preg_match('/^\s*(\S+)/', $d, $m); + if (isset($this->dtc->pcdata[$m[1]]) and ($this->dtc->pcdata[$m[1]])) { + coordonnees_erreur($this, "

" . $m[1] . " " + . _T('zxml_nonvide_balise') // message a affiner + ); + } + } + if ($f = $this->process['text']) { + $f($this, $data); + } } - if ($f = $this->process['fin']) $f($this, $name, $vide); -} -// http://doc.spip.org/@textElement -function textElement($phraseur, $data) -{ - if (trim($data)) { - $d = $this->depth; - $d = $this->ouvrant[$d]; - preg_match('/^\s*(\S+)/', $d, $m); - if ($this->dtc->pcdata[$m[1]]) { - coordonnees_erreur($this, "

". $m[1] . " " - . _T('zxml_nonvide_balise') // message a affiner - ); + public function piElement($phraseur, $target, $data) { + if ($f = $this->process['pi']) { + $f($this, $target, $data); } } - if ($f = $this->process['text']) $f($this, $data); -} -function piElement($phraseur, $target, $data) -{ - if ($f = $this->process['pi']) $f($this, $target, $data); -} + // Denonciation des entitees XML inconnues + // Pour contourner le bug de conception de SAX qui ne signale pas si elles + // sont dans un attribut, les entites les plus frequentes ont ete + // transcodees au prealable (sauf & < > " que SAX traite correctement). + // On ne les verra donc pas passer a cette etape, contrairement a ce que + // le source de la page laisse legitimement supposer. -// Denonciation des entitees XML inconnues -// Pour contourner le bug de conception de SAX qui ne signale pas si elles -// sont dans un attribut, les entites les plus frequentes ont ete -// transcodees au prealable (sauf & < > " que SAX traite correctement). -// On ne les verra donc pas passer a cette etape, contrairement a ce que -// le source de la page laisse legitimement supposer. - -// http://doc.spip.org/@defautElement -function defaultElement($phraseur, $data) -{ - if (!preg_match('/^