uawdijnntqw1x1x1
IP : 216.73.216.44
Hostname : webm002.cluster111.gra.hosting.ovh.net
Kernel : Linux webm002.cluster111.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
OS : Linux
PATH:
/
home
/
atelierpru
/
provence
/
tmp
/
cache
/
..
/
..
/
52177
/
xml.tar
/
/
valider.php000066600000025333152442520050006714 0ustar00<?php /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * * Copyright (c) 2001-2019 * * 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, 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://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, " <b>$name</b> : " . _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('</b>, <b>', $this->dtc->peres[$name]); coordonnees_erreur($this, " <b>$name</b> " . _T('zxml_non_fils') . ' <b>' . $pere . '</b>' . (!$bons_peres ? '' : ('<p style="font-size: 80%"> ' . _T('zxml_mais_de') . ' <b>' . $bons_peres . '</b></p>'))); } elseif ($this->dtc->regles[$pere][0] == '/') { $frat = substr($depth, 2); if (!isset($this->fratrie[$frat])) { $this->fratrie[$frat] = ''; } $this->fratrie[$frat] .= "$name "; } } } } // 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, " <b>$n</b>" . ' : ' . _T('zxml_obligatoire_attribut') . " <b>$name</b>"); } } } } // 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, " <b>$name</b> " . _T('zxml_inconnu_attribut') . ' ' . _T('zxml_de') . " <a$bons>$bal</a> (" . _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_NMTOKEN($phraseur, $name, $val, $bal) { $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKEN); } public function validerAttribut_NMTOKENS($phraseur, $name, $val, $bal) { $this->valider_motif($phraseur, $name, $val, $bal, _REGEXP_NMTOKENS); } // 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, " <p><b>$val</b> " . _T('zxml_valeur_attribut') . " <b>$name</b> " . _T('zxml_de') . " <b>$bal</b> " . _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_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://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://code.spip.net/@valider_motif public function valider_motif($phraseur, $name, $val, $bal, $motif) { if (!preg_match($motif, $val)) { coordonnees_erreur($this, "<b>$val</b> " . _T('zxml_valeur_attribut') . " <b>$name</b> " . _T('zxml_de') . " <b>$bal</b> " . _T('zxml_non_conforme') . "</p><p>" . "<b>" . $motif . "</b>"); } } // http://code.spip.net/@valider_idref public function valider_idref($nom, $ligne, $col) { if (!isset($this->ids[$nom])) { $this->err[] = array(" <p><b>$nom</b> " . _T('zxml_inconnu_id'), $ligne, $col); } } // 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://code.spip.net/@debutElement public 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; $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, " <p><b>$name</b> " . _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, "<p>\n<b>$name</b> " . _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, " <p>\n<b>$name</b> " . _T('zxml_succession_fils_incorrecte') . ' : <b>' . $f . '</b>'); } } } 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, " <p><b>" . $m[1] . "</b> " . _T('zxml_nonvide_balise') // message a affiner ); } } if ($f = $this->process['text']) { $f($this, $data); } } public 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. // http://code.spip.net/@defautElement public function defaultElement($phraseur, $data) { if (!preg_match('/^<!--/', $data) and (preg_match_all('/&([^;]*)?/', $data, $r, PREG_SET_ORDER)) ) { foreach ($r as $m) { list($t, $e) = $m; if (!isset($this->dtc->entites[$e])) { coordonnees_erreur($this, " <b>$e</b> " . _T('zxml_inconnu_entite') . ' ' ); } } } if (isset($this->process['default']) and ($f = $this->process['default'])) { $f($this, $data); } } // http://code.spip.net/@phraserTout public function phraserTout($phraseur, $data) { xml_parsestring($this, $data); if (!$this->dtc or preg_match(',^' . _MESSAGE_DOCTYPE . ',', $data)) { $this->err[] = array('DOCTYPE ?', 0, 0); } else { $this->valider_passe2($this); } } /** * Constructeur * * @param array $process ? **/ public function __construct($process = array()) { if (is_array($process)) { $this->process = $process; } } public $ids = array(); public $idrefs = array(); public $idrefss = array(); public $debuts = array(); public $fratrie = array(); public $dtc = null; public $sax = null; public $depth = ""; public $entete = ''; public $page = ''; public $res = ""; public $err = array(); public $contenu = array(); public $ouvrant = array(); public $reperes = array(); public $process = array( 'debut' => 'xml_debutElement', 'fin' => 'xml_finElement', 'text' => 'xml_textElement', 'pi' => 'xml_piElement', 'default' => 'xml_defaultElement' ); } /** * Retourne une structure ValidateurXML, dont le champ "err" est un tableau * ayant comme entrees des sous-tableaux [message, ligne, colonne] * **/ function xml_valider_dist($page, $apply = false, $process = false, $doctype = '', $charset = null) { $f = new ValidateurXML($process); $sax = charger_fonction('sax', 'xml'); return $sax($page, $apply, $f, $doctype, $charset); } sax.php000066600000021703152442520050006056 0ustar00<?php /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * * Copyright (c) 2001-2019 * * 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; } include_spip('inc/charsets'); include_spip('xml/interfaces'); /** * Encoder les entites * * @param string $texte * @return string */ function xml_entites_html($texte) { if (!is_string($texte) or !$texte or strpbrk($texte, "&\"'<>") == false ) { return $texte; } if (!function_exists('spip_htmlspecialchars')) { include_spip("inc/filtres_mini"); } $texte = spip_htmlspecialchars($texte, ENT_QUOTES); return $texte; } // http://code.spip.net/@xml_debutElement function xml_debutElement($phraseur, $name, $attrs) { $depth = $phraseur->depth; $t = isset($phraseur->ouvrant[$depth]) ? $phraseur->ouvrant[$depth] : ' '; // espace initial signifie: deja integree au resultat if ($t[0] != ' ') { $phraseur->res .= '<' . $t . '>'; $phraseur->ouvrant[$depth] = ' ' . $t; } $t = $phraseur->contenu[$depth]; // n'indenter que s'il y a un separateur avant $phraseur->res .= preg_replace("/[\n\t ]+$/", "\n$depth", $t); $phraseur->contenu[$depth] = ""; $att = ''; $sep = ' '; foreach ($attrs as $k => $v) { $delim = strpos($v, "'") === false ? "'" : '"'; $val = xml_entites_html($v); $att .= $sep . $k . "=" . $delim . ($delim !== '"' ? str_replace('"', '"', $val) : $val) . $delim; $sep = "\n $depth"; } $phraseur->depth .= ' '; $phraseur->contenu[$phraseur->depth] = ""; $phraseur->ouvrant[$phraseur->depth] = $name . $att; $phraseur->reperes[$phraseur->depth] = xml_get_current_line_number($phraseur->sax); } // http://code.spip.net/@xml_finElement function xml_finElement($phraseur, $name, $fusion_bal = false) { $ouv = $phraseur->ouvrant[$phraseur->depth]; if ($ouv[0] != ' ') { $phraseur->ouvrant[$phraseur->depth] = ' ' . $ouv; } else { $ouv = ""; } $t = $phraseur->contenu[$phraseur->depth]; $phraseur->depth = substr($phraseur->depth, 2); $t = preg_replace("/[\n\t ]+$/", "\n" . $phraseur->depth, $t); // fusion <balise></balise> en <balise />. // ATTENTION, certains clients http croient que fusion ==> pas d'atttributs // en particulier pour les balises Script et A. // en presence d'attributs ne le faire que si la DTD est dispo et d'accord // (param fusion_bal) if ($t || (($ouv != $name) and !$fusion_bal)) { $phraseur->res .= ($ouv ? ('<' . $ouv . '>') : '') . $t . "</" . $name . ">"; } else { $phraseur->res .= ($ouv ? ('<' . $ouv . ' />') : ("</" . $name . ">")); } } // http://code.spip.net/@xml_textElement function xml_textElement($phraseur, $data) { $depth = $phraseur->depth; $phraseur->contenu[$depth] .= preg_match('/^script/', $phraseur->ouvrant[$depth]) ? $data : xml_entites_html($data); } function xml_piElement($phraseur, $target, $data) { $depth = $phraseur->depth; if (strtolower($target) != "php") { $phraseur->contenu[$depth] .= $data; } else { ob_start(); eval($data); $data = ob_get_contents(); ob_end_clean(); $phraseur->contenu[$depth] .= $data; } } // http://code.spip.net/@xml_defautElement function xml_defaultElement($phraseur, $data) { $depth = $phraseur->depth; if (!isset($phraseur->contenu[$depth])) { $phraseur->contenu[$depth] = ''; } $phraseur->contenu[$depth] .= $data; } // http://code.spip.net/@xml_parsestring function xml_parsestring($phraseur, $data) { $phraseur->contenu[$phraseur->depth] = ''; if (!xml_parse($phraseur->sax, $data, true)) { coordonnees_erreur($phraseur, xml_error_string(xml_get_error_code($phraseur->sax)) . "<br />\n" . (!$phraseur->depth ? '' : ('(' . _T('erreur_balise_non_fermee') . " <tt>" . $phraseur->ouvrant[$phraseur->depth] . "</tt> " . _T('ligne') . " " . $phraseur->reperes[$phraseur->depth] . ") <br />\n"))); } } // http://code.spip.net/@coordonnees_erreur function coordonnees_erreur($phraseur, $msg) { $entete_length = substr_count($phraseur->entete, "\n"); $phraseur->err[] = array( $msg, xml_get_current_line_number($phraseur->sax) + $entete_length, xml_get_current_column_number($phraseur->sax) ); } // http://code.spip.net/@xml_sax_dist function xml_sax_dist($page, $apply = false, $phraseur = null, $doctype = '', $charset = null) { if (is_null($charset)) { $charset = $GLOBALS['meta']['charset']; } if ($apply) { ob_start(); if (is_array($apply)) { $r = call_user_func_array($page, $apply); } else { $r = $page(); } $page = ob_get_contents(); ob_end_clean(); // fonction sans aucun "echo", ca doit etre le resultat if (!$page) { $page = $r; } } if (!$page) { return ''; } // charger la DTD et transcoder les entites, // et escamoter le doctype que sax mange en php5 mais pas en php4 if (!$doctype) { if (!$r = analyser_doctype($page)) { $page = _MESSAGE_DOCTYPE . _DOCTYPE_ECRIRE . preg_replace(_REGEXP_DOCTYPE, '', $page); $r = analyser_doctype($page); } list($entete, $avail, $grammaire, $rotlvl) = array_pad($r, 4, null); $page = substr($page, strlen($entete)); } else { $avail = 'SYSTEM'; $grammaire = $doctype; $rotlvl = basename($grammaire); } include_spip('xml/analyser_dtd'); $dtc = charger_dtd($grammaire, $avail, $rotlvl); $page = sax_bug($page, $dtc, $charset); // compatibilite Tidy espace public if (!$phraseur) { $indenter_xml = charger_fonction('indenter', 'xml'); return $indenter_xml($page, $apply); } $xml_parser = xml_parser_create($charset); xml_set_element_handler($xml_parser, array($phraseur, "debutElement"), array($phraseur, "finElement")); xml_set_character_data_handler($xml_parser, array($phraseur, "textElement")); xml_set_processing_instruction_handler($xml_parser, array($phraseur, 'piElement')); xml_set_default_handler($xml_parser, array($phraseur, "defaultElement")); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); $phraseur->sax = $xml_parser; if (isset($entete)) { $phraseur->entete = $entete; } $phraseur->page = $page; $phraseur->dtc = $dtc; $phraseur->phraserTout($xml_parser, $page); xml_parser_free($xml_parser); $phraseur->sax = ''; return $phraseur; } // 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. // http://code.spip.net/@sax_bug function sax_bug($data, $dtc, $charset = null) { if (is_null($charset)) { $charset = $GLOBALS['meta']['charset']; } if ($dtc) { $trans = array(); foreach ($dtc->entites as $k => $v) { if (!strpos(" amp lt gt quot ", $k)) { $trans["&$k;"] = $v; } } $data = strtr($data, $trans); } else { $data = html2unicode($data, true); } return unicode2charset($data, $charset); } // Retirer < ? xml... ? > et autre PI, ainsi que les commentaires en debut // afin de reperer le Doctype et le decomposer selon: // http://www.freebsd.org/doc/fr_FR.ISO8859-1/books/fdp-primer/sgml-primer-doctype-declaration.html // Si pas de Doctype et premiere balise = RSS prendre la doctype RSS 0.91: // les autres formats RSS n'ont pas de DTD, // mais un XML Schema que SPIP ne fait pas encore lire. // http://code.spip.net/@analyser_doctype function analyser_doctype($data) { if (!preg_match(_REGEXP_DOCTYPE, $data, $page)) { if (preg_match(_REGEXP_XML, $data, $page)) { list(, $entete, $topelement) = $page; if ($topelement == 'rss') { return array( $entete, 'PUBLIC', _DOCTYPE_RSS, 'rss-0.91.dtd' ); } else { $dtd = $topelement . '.dtd'; $f = find_in_path($dtd); if (file_exists($f)) { return array($entete, 'SYSTEM', $f, $dtd); } } } spip_log("Dtd pas vu pour " . substr($data, 0, 100)); return array(); } list($entete, , $topelement, $avail, $suite) = $page; if (!preg_match('/^"([^"]*)"\s*(.*)$/', $suite, $r)) { if (!preg_match("/^'([^']*)'\s*(.*)$/", $suite, $r)) { return array(); } } list(, $rotlvl, $suite) = $r; if (!$suite) { if ($avail != 'SYSTEM') { return array(); } $grammaire = $rotlvl; $rotlvl = ''; } else { if (!preg_match('/^"([^"]*)"\s*$/', $suite, $r)) { if (!preg_match("/^'([^']*)'\s*$/", $suite, $r)) { return array(); } } $grammaire = $r[1]; } return array($entete, $avail, $grammaire, $rotlvl); } interfaces.php000066600000004076152442520050007412 0ustar00<?php /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * * Copyright (c) 2001-2019 * * 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; } define('_REGEXP_DOCTYPE', '/^((?:<\001?[?][^>]*>\s*)*(?:<!--.*?-->\s*)*)*<!DOCTYPE\s+(\w+)\s+(\w+)\s*([^>]*)>\s*/s'); define('_REGEXP_XML', '/^(\s*(?:<[?][^x>][^>]*>\s*)?(?:<[?]xml[^>]*>)?\s*(?:<!--.*?-->\s*)*)<(\w+)/s'); define('_MESSAGE_DOCTYPE', '<!-- SPIP CORRIGE -->'); define('_SUB_REGEXP_SYMBOL', '[\w_:.-]'); define('_REGEXP_NMTOKEN', '/^' . _SUB_REGEXP_SYMBOL . '+$/'); define('_REGEXP_NMTOKENS', '/^(' . _SUB_REGEXP_SYMBOL . '+\s*)*$/'); define('_REGEXP_ID', '/^[A-Za-z_:]' . _SUB_REGEXP_SYMBOL . '*$/'); define('_REGEXP_ENTITY_USE', '/%(' . _SUB_REGEXP_SYMBOL . '+);/'); define('_REGEXP_ENTITY_DEF', '/^%(' . _SUB_REGEXP_SYMBOL . '+);/'); define('_REGEXP_TYPE_XML', 'PUBLIC|SYSTEM|INCLUDE|IGNORE|CDATA'); define('_REGEXP_ENTITY_DECL', '/^<!ENTITY\s+(%?)\s*(' . _SUB_REGEXP_SYMBOL . '+;?)\s+(' . _REGEXP_TYPE_XML . ')?\s*(' . "('([^']*)')" . '|("([^"]*)")' . '|\s*(%' . _SUB_REGEXP_SYMBOL . '+;)\s*' . ')\s*(--.*?--)?("([^"]*)")?\s*>\s*(.*)$/s'); define('_REGEXP_INCLUDE_USE', '/^<!\[\s*%\s*([^;]*);\s*\[\s*(.*)$/s'); define('_DOCTYPE_RSS', 'http://www.rssboard.org/rss-0.91.dtd'); /** * Document Type Compilation **/ class DTC { public $macros = array(); public $elements = array(); public $peres = array(); public $attributs = array(); public $entites = array(); public $regles = array(); public $pcdata = array(); } indenter.php000066600000004075152442520050007076 0ustar00<?php /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * * Copyright (c) 2001-2019 * * 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; } class IndenteurXML { // http://code.spip.net/@debutElement public function debutElement($phraseur, $name, $attrs) { xml_debutElement($this, $name, $attrs); } // http://code.spip.net/@finElement public function finElement($phraseur, $name) { xml_finElement($this, $name); } // http://code.spip.net/@textElement public function textElement($phraseur, $data) { xml_textElement($this, $data); } public function piElement($phraseur, $target, $data) { xml_PiElement($this, $target, $data); } // http://code.spip.net/@defautElement public function defaultElement($phraseur, $data) { xml_defaultElement($this, $data); } // http://code.spip.net/@phraserTout public function phraserTout($phraseur, $data) { xml_parsestring($this, $data); } public $depth = ""; public $res = ""; public $err = array(); public $contenu = array(); public $ouvrant = array(); public $reperes = array(); public $entete = ''; public $page = ''; public $dtc = null; public $sax = null; } // http://code.spip.net/@xml_indenter_dist function xml_indenter_dist($page, $apply = false) { $sax = charger_fonction('sax', 'xml'); $f = new IndenteurXML(); $sax($page, $apply, $f); if (!$f->err) { return $f->entete . $f->res; } spip_log("indentation impossible " . count($f->err) . " erreurs de validation"); return $f->entete . $f->page; } index.php000066600000000002152442520050006357 0ustar00X analyser_dtd.php000066600000026201152442520050007732 0ustar00<?php /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * * Copyright (c) 2001-2019 * * 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; } include_spip('xml/interfaces'); // http://code.spip.net/@charger_dtd function charger_dtd($grammaire, $avail, $rotlvl) { static $dtd = array(); # cache bien utile pour le validateur en boucle if (isset($dtd[$grammaire])) { return $dtd[$grammaire]; } if ($avail == 'SYSTEM') { $grammaire = find_in_path($grammaire); } $file = _DIR_CACHE_XML . preg_replace('/[^\w.]/', '_', $rotlvl) . '.gz'; if (lire_fichier($file, $r)) { if (!$grammaire) { return array(); } if (($avail == 'SYSTEM') and filemtime($file) < filemtime($grammaire)) { $r = false; } } if ($r) { $dtc = unserialize($r); } else { spip_timer('dtd'); $dtc = new DTC; // L'analyseur retourne un booleen de reussite et modifie $dtc. // Retourner vide en cas d'echec if (!analyser_dtd($grammaire, $avail, $dtc)) { $dtc = array(); } else { // tri final pour presenter les suggestions de corrections foreach ($dtc->peres as $k => $v) { asort($v); $dtc->peres[$k] = $v; } spip_log("Analyser DTD $avail $grammaire (" . spip_timer('dtd') . ") " . count($dtc->macros) . ' macros, ' . count($dtc->elements) . ' elements, ' . count($dtc->attributs) . " listes d'attributs, " . count($dtc->entites) . " entites"); # $r = $dtc->regles; ksort($r);foreach($r as $l => $v) {$t=array_keys($dtc->attributs[$l]);echo "<b>$l</b> '$v' ", count($t), " attributs: ", join (', ',$t);$t=$dtc->peres[$l];echo "<br />",count($t), " peres: ", @join (', ',$t), "<br />\n";}exit; ecrire_fichier($file, serialize($dtc), true); } } $dtd[$grammaire] = $dtc; return $dtc; } // Compiler une regle de production en une Regexp qu'on appliquera sur la // suite des noms de balises separes par des espaces. Du coup: // supprimer #PCDATA etc, ca ne sert pas pour le controle des balises; // supprimer les virgules (les sequences sont implicites dans une Regexp) // conserver | + * ? ( ) qui ont la meme signification en DTD et en Regexp; // faire suivre chaque nom d'un espace (et supprimer les autres) ... // et parentheser le tout pour que | + * ? s'applique dessus. // http://code.spip.net/@compilerRegle function compilerRegle($val) { $x = str_replace('()', '', preg_replace('/\s*,\s*/', '', preg_replace('/(\w+)\s*/', '(?:\1 )', preg_replace('/\s*\)/', ')', preg_replace('/\s*([(+*|?])\s*/', '\1', preg_replace('/\s*#\w+\s*[,|]?\s*/', '', $val)))))); return $x; } // http://code.spip.net/@analyser_dtd function analyser_dtd($loc, $avail, &$dtc) { // creer le repertoire de cache si ce n'est fait // (utile aussi pour le resultat de la compil) $file = sous_repertoire(_DIR_CACHE_XML); // si DTD locale, ignorer ce repertoire pour le moment if ($avail == 'SYSTEM') { $file = $loc; if (_DIR_RACINE and strncmp($file, _DIR_RACINE, strlen(_DIR_RACINE)) == 0) { $file = substr($file, strlen(_DIR_RACINE)); } $file = find_in_path($file); } else { $file .= preg_replace('/[^\w.]/', '_', $loc); } $dtd = ''; if (@is_readable($file)) { lire_fichier($file, $dtd); } else { if ($avail == 'PUBLIC') { include_spip('inc/distant'); if ($dtd = trim(recuperer_page($loc))) { ecrire_fichier($file, $dtd, true); } } } $dtd = ltrim($dtd); if (!$dtd) { spip_log("DTD '$loc' ($file) inaccessible"); return false; } else { spip_log("analyse de la DTD $loc "); } while ($dtd) { if ($dtd[0] != '<') { $r = analyser_dtd_lexeme($dtd, $dtc, $loc); } elseif ($dtd[1] != '!') { $r = analyser_dtd_pi($dtd, $dtc, $loc); } elseif ($dtd[2] == '[') { $r = analyser_dtd_data($dtd, $dtc, $loc); } else { switch ($dtd[3]) { case '%' : $r = analyser_dtd_data($dtd, $dtc, $loc); break; case 'T' : $r = analyser_dtd_attlist($dtd, $dtc, $loc); break; case 'L' : $r = analyser_dtd_element($dtd, $dtc, $loc); break; case 'N' : $r = analyser_dtd_entity($dtd, $dtc, $loc); break; case 'O' : $r = analyser_dtd_notation($dtd, $dtc, $loc); break; case '-' : $r = analyser_dtd_comment($dtd, $dtc, $loc); break; default: $r = -1; } } if (!is_string($r)) { spip_log("erreur $r dans la DTD " . substr($dtd, 0, 80) . "....."); return false; } $dtd = $r; } return true; } // http://code.spip.net/@analyser_dtd_comment function analyser_dtd_comment($dtd, &$dtc, $grammaire) { // ejecter les commentaires, surtout quand ils contiennent du code. // Option /s car sur plusieurs lignes parfois if (!preg_match('/^<!--.*?-->\s*(.*)$/s', $dtd, $m)) { return -6; } return $m[1]; } // http://code.spip.net/@analyser_dtd_pi function analyser_dtd_pi($dtd, &$dtc, $grammaire) { if (!preg_match('/^<\?.*?>\s*(.*)$/s', $dtd, $m)) { return -10; } return $m[1]; } // http://code.spip.net/@analyser_dtd_lexeme function analyser_dtd_lexeme($dtd, &$dtc, $grammaire) { if (!preg_match(_REGEXP_ENTITY_DEF, $dtd, $m)) { return -9; } list(, $s) = $m; $n = $dtc->macros[$s]; if (is_array($n)) { // en cas d'inclusion, l'espace de nom est le meme // mais gaffe aux DTD dont l'URL est relative a l'engloblante if (($n[0] == 'PUBLIC') and !tester_url_absolue($n[1]) ) { $n[1] = substr($grammaire, 0, strrpos($grammaire, '/') + 1) . $n[1]; } analyser_dtd($n[1], $n[0], $dtc); } return ltrim(substr($dtd, strlen($m[0]))); } // il faudrait gerer plus proprement les niveaux d'inclusion: // ca ne depasse pas 3 ici. // http://code.spip.net/@analyser_dtd_data function analyser_dtd_data($dtd, &$dtc, $grammaire) { if (!preg_match(_REGEXP_INCLUDE_USE, $dtd, $m)) { return -11; } if (!preg_match('/^((\s*<!(\[\s*%\s*[^;]*;\s*\[([^]<]*<[^>]*>)*[^]<]*\]\]>)|([^]>]*>))*[^]<]*)\]\]>\s*/s', $m[2], $r) ) { return -12; } if ($dtc->macros[$m[1]] == 'INCLUDE') { $retour = $r[1] . substr($m[2], strlen($r[0])); } else { $retour = substr($m[2], strlen($r[0])); } return $retour; } // http://code.spip.net/@analyser_dtd_notation function analyser_dtd_notation($dtd, &$dtc, $grammaire) { if (!preg_match('/^<!NOTATION.*?>\s*(.*)$/s', $dtd, $m)) { return -8; } spip_log("analyser_dtd_notation a ecrire"); return $m[1]; } // http://code.spip.net/@analyser_dtd_entity function analyser_dtd_entity($dtd, &$dtc, $grammaire) { if (!preg_match(_REGEXP_ENTITY_DECL, $dtd, $m)) { return -2; } list($t, $term, $nom, $type, $k1, $k2, $k3, $k4, $k5, $k6, $c, $q, $alt, $dtd) = $m; if (isset($dtc->macros[$nom]) and $dtc->macros[$nom]) { return $dtd; } if (isset($dtc->entites[$nom])) { spip_log("redefinition de l'entite $nom"); } if ($k6) { return $k6 . $dtd; } // cas du synonyme complet $val = expanserEntite(($k2 ? $k3 : ($k4 ? $k5 : $k6)), $dtc->macros); // cas particulier double evaluation: 'PUBLIC "..." "...."' if (preg_match('/(PUBLIC|SYSTEM)\s+"([^"]*)"\s*("([^"]*)")?\s*$/s', $val, $r)) { list($t, $type, $val, $q, $alt) = $r; } if (!$term) { $dtc->entites[$nom] = $val; } elseif (!$type) { $dtc->macros[$nom] = $val; } else { if (($type == 'SYSTEM') and !$alt) { $alt = $val; } if (!$alt) { $dtc->macros[$nom] = $val; } else { if (($type == 'PUBLIC') and (strpos($alt, '/') === false) ) { $alt = preg_replace(',/[^/]+$,', '/', $grammaire) . $alt; } $dtc->macros[$nom] = array($type, $alt); } } return $dtd; } // Dresser le tableau des filles potentielles de l'element // pour traquer tres vite les illegitimes. // Si la regle a au moins une sequence (i.e. une virgule) // ou n'est pas une itération (i.e. se termine par * ou +) // en faire une RegExp qu'on appliquera aux balises rencontrees. // Sinon, conserver seulement le type de l'iteration car la traque // aura fait l'essentiel du controle sans memorisation des balises. // Fin du controle en finElement // http://code.spip.net/@analyser_dtd_element function analyser_dtd_element($dtd, &$dtc, $grammaire) { if (!preg_match('/^<!ELEMENT\s+([^>\s]+)([^>]*)>\s*(.*)$/s', $dtd, $m)) { return -3; } list(, $nom, $contenu, $dtd) = $m; $nom = expanserEntite($nom, $dtc->macros); if (isset($dtc->elements[$nom])) { spip_log("redefinition de l'element $nom dans la DTD"); return -4; } $filles = array(); $contenu = expanserEntite($contenu, $dtc->macros); $val = $contenu ? compilerRegle($contenu) : '(?:EMPTY )'; if ($val == '(?:EMPTY )') { $dtc->regles[$nom] = 'EMPTY'; } elseif ($val == '(?:ANY )') { $dtc->regles[$nom] = 'ANY'; } else { $last = substr($val, -1); if (preg_match('/ \w/', $val) or (!empty($last) and strpos('*+?', $last) === false) ) { $dtc->regles[$nom] = "/^$val$/"; } else { $dtc->regles[$nom] = $last; } $filles = array_values(preg_split('/\W+/', $val, -1, PREG_SPLIT_NO_EMPTY)); foreach ($filles as $k) { if (!isset($dtc->peres[$k])) { $dtc->peres[$k] = array(); } if (!in_array($nom, $dtc->peres[$k])) { $dtc->peres[$k][] = $nom; } } } $dtc->pcdata[$nom] = (strpos($contenu, '#PCDATA') === false); $dtc->elements[$nom] = $filles; return $dtd; } // http://code.spip.net/@analyser_dtd_attlist function analyser_dtd_attlist($dtd, &$dtc, $grammaire) { if (!preg_match('/^<!ATTLIST\s+(\S+)\s+([^>]*)>\s*(.*)/s', $dtd, $m)) { return -5; } list(, $nom, $val, $dtd) = $m; $nom = expanserEntite($nom, $dtc->macros); $val = expanserEntite($val, $dtc->macros); if (!isset($dtc->attributs[$nom])) { $dtc->attributs[$nom] = array(); } if (preg_match_all("/\s*(\S+)\s+(([(][^)]*[)])|(\S+))\s+([^\s']*)(\s*'[^']*')?/", $val, $r2, PREG_SET_ORDER)) { foreach ($r2 as $m2) { $v = preg_match('/^\w+$/', $m2[2]) ? $m2[2] : ('/^' . preg_replace('/\s+/', '', $m2[2]) . '$/'); $m21 = expanserEntite($m2[1], $dtc->macros); $m25 = expanserEntite($m2[5], $dtc->macros); $dtc->attributs[$nom][$m21] = array($v, $m25); } } return $dtd; } /** * Remplace dans la chaîne `$val` les sous-chaines de forme `%NOM;` * par leur definition dans le tableau `$macros` * * Si le premier argument n'est pas une chaîne, * retourne les statistiques (pour debug de DTD, inutilise en mode normal) * * @param string $val * @param array $macros * @return string|array **/ function expanserEntite($val, $macros = array()) { static $vu = array(); if (!is_string($val)) { return $vu; } if (preg_match_all(_REGEXP_ENTITY_USE, $val, $r, PREG_SET_ORDER)) { foreach ($r as $m) { $ent = $m[1]; // il peut valoir "" if (!isset($macros[$ent])) { spip_log("Entite $ent inconnu"); } else { if (!isset($vu[$ent])) { $vu[$ent] = 0; } ++$vu[$ent]; $val = str_replace($m[0], $macros[$ent], $val); } } } return trim(preg_replace('/\s+/', ' ', $val)); }
/home/atelierpru/provence/tmp/cache/../../52177/xml.tar