Newer
Older
<?php
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* 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',
'/^\s*<!DOCTYPE\s+(\w+)\s+(\w+)\s+(.)([^\3>]*)\3\s+(.)([^\5>]*)\5[^>]*>/');
function inc_validateur_dist($data)
{
if (!preg_match(_REGEXP_DOCTYPE, $data, $r))
return array();
list(,$ns, $type, $s, $nom, $s2, $grammaire) = $r;
$dtd = '';
$file = _DIR_CACHE . preg_replace('/[\W.]/','_', $grammaire);
if (@is_readable($file)) {
lire_fichier($file, $dtd);
} else {
include_spip('inc/distant');
// il faudrait verifier que $type=PUBLIC, et sinon agir
if ($dtd = recuperer_page($grammaire))
ecrire_fichier($file, $dtd);
else spip_log("DTD $grammaire inaccessible");
}
$res = array();
// les entites publiques sont declarees vides. A ameliorer a terme
if (preg_match_all('/<!ENTITY\s+%\s+([.\w]+)\s+(PUBLIC)?\s*"([^"]*)"\s*("[^"]*")?\s*>/', $dtd, $r, PREG_SET_ORDER)) {
foreach($r as $m) {
list(,$nom, $type, $val) = $m;
$res[$nom] = $type ? '': expanserEntite($val, $res) ;
$phraseur_xml->entites = $res;
// reperer pour chaque noeud ses fils potentiels, sans repetitions,
// pour faire une analyse syntaxique sommaire
$res = array();
if (preg_match_all('/<!ELEMENT\s+(\w+)([^>]*)>/', $dtd, $r, PREG_SET_ORDER)) {
foreach($r as $m) {
list(,$nom, $val) = $m;
$val = expanserEntite($val, $phraseur_xml->entites);
$val = array_values(preg_split('/\W+/', $val,-1,PREG_SPLIT_NO_EMPTY));
$res[$nom]= $val;
}
}
$phraseur_xml->elements = $res;
$res = array();
if (preg_match_all('/<!ATTLIST\s+(\S+)\s+([^>]*)>/', $dtd, $r, PREG_SET_ORDER)) {
foreach($r as $m) {
list(,$nom, $val) = $m;
$val = expanserEntite($val, $phraseur_xml->entites);
$att = 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]) . '$/');
$att[$m2[1]] = array($v, $m2[5]);
}
}
$res[$nom] = $att;
}
}
$phraseur_xml->attributs = $res;
spip_log("DTD: " . count($phraseur_xml->entites) . ' entites, ' . count($phraseur_xml->elements) . ' elements');
function expanserEntite($val, $entites)
{
if (preg_match_all('/%([.\w]+);/', $val, $r, PREG_SET_ORDER)) {
foreach($r as $m)
// parfois faux suite au non chargement des entites publiques
if ($x = $entites[$m[1]])
$val = str_replace($m[0], $x, $val);
}
return $val;
}
function validerElement($parser, $name, $attrs)
global $phraseur_xml;
if (!$phraseur_xml->elements) return;
if (!isset($phraseur_xml->elements[$name]))
$phraseur_xml->err[]= " <b>$name</b>"
. _L(' balise inconnue ')
. coordonnees_erreur($parser);
else {
$depth = $phraseur_xml->depth;
$ouvrant = $phraseur_xml->ouvrant;
if (isset($ouvrant[$depth])) {
if (preg_match('/^\s*(\w+)/', $ouvrant[$depth], $r)) {
$pere = $r[1];
if (!@in_array($name, $phraseur_xml->elements[$pere]))
$phraseur_xml->err[]= " <b>$name</b>"
. _L(" n'est pas un fils de ")
. '<b>'
. $pere
. '</b>'
. coordonnees_erreur($parser);
}
}
foreach ($phraseur_xml->attributs[$name] as $n => $v)
{ if (($v[1] == '#REQUIRED') AND (!isset($attrs[$n])))
$phraseur_xml->err[]= " <b>$n</b>"
. _L(" attribut obligatoire mais absent dans ")
. "<b>$name</b>"
. coordonnees_erreur($parser);
function validerAttribut($parser, $name, $val, $bal)
{
global $phraseur_xml;
$a = @$phraseur_xml->attributs[$bal]; // vide ou absent, pareil.
if (!isset($a[$name]))
$phraseur_xml->err[]= " <b>$name</b>"
. _L(' attribut inconnu de ')
. "<b>$bal</b>"
. coordonnees_erreur($parser);
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
else{
$type = $a[$name][0];
if ($type[0]=='/') {
if (!preg_match($a[$name][0], $val)) {
$phraseur_xml->err[]= " <p><b>$val</b>"
. _L(" valeur de l'attribut ")
. "<b>$name</b>"
. _L(' de ')
. "<b>$bal</b>"
. _L(" n'est pas conforme au motif</p><p>")
. "<b>" . $a[$name][0] . "</b></p>"
. coordonnees_erreur($parser);
}
} elseif ($type == 'ID') {
if (isset($phraseur_xml->ids[$val])) {
$phraseur_xml->err[]= " <p><b>$val</b>"
. _L(" valeur de l'attribut ")
. "<b>$name</b>"
. _L(' de ')
. "<b>$bal</b>"
. _L(" incorrect ")
. coordonnees_erreur($parser);
list($l,$c) = $phraseur_xml->ids[$val];
$phraseur_xml->err[]= " <p><b>$val</b>"
. _L(" vu auparavant ligne ")
. $l
. _L(" colonne ")
. $c;
}
else $phraseur_xml->ids[$val] = array(xml_get_current_line_number($parser), xml_get_current_column_number($parser));
}
}