[ Index ] |
|
Code source de SPIP 1.9.2c |
1 <?php 2 3 /***************************************************************************\ 4 * SPIP, Systeme de publication pour l'internet * 5 * * 6 * Copyright (c) 2001-2007 * 7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * 8 * * 9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * 10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * 11 \***************************************************************************/ 12 13 if (!defined("_ECRIRE_INC_VERSION")) return; 14 15 include_spip('xml/interfaces'); 16 17 function charger_dtd($grammaire, $avail) 18 { 19 spip_timer('dtd'); 20 $dtc = new DTC; 21 // L'analyseur retourne un booleen de reussite et modifie $dtc. 22 // Retourner vide en cas d'echec 23 if (!analyser_dtd($grammaire, $avail, $dtc)) return array(); 24 25 // tri final pour presenter les suggestions de corrections 26 foreach ($dtc->peres as $k => $v) { 27 asort($v); 28 $dtc->peres[$k] = $v; 29 } 30 31 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"); 32 # $r = $dtc->regles; ksort($r);foreach($r as $l => $v) echo "<b>$l</b> '$v' ", join (', ',array_keys($dtc->attributs[$l])), "<br />\n";exit; 33 return $dtc; 34 } 35 36 // Compiler une regle de production en une Regexp qu'on appliquera sur la 37 // suite des noms de balises separes par des espaces. Du coup: 38 // supprimer #PCDATA etc, ca ne sert pas pour le controle des balises; 39 // supprimer les virgules (les sequences sont implicites dans une Regexp) 40 // conserver | + * ? ( ) qui ont la meme signification en DTD et en Regexp; 41 // faire suivre chaque nom d'un espace (et supprimer les autres) ... 42 // et parentheser le tout pour que | + * ? s'applique dessus. 43 44 // http://doc.spip.org/@compilerRegle 45 function compilerRegle($val) 46 { 47 $x = str_replace('\s*()\s*','', 48 preg_replace('/\s*,\s*/','', 49 preg_replace('/(\w+)\s*/','(\1 )', 50 preg_replace('/\s*([(+*|])\s*/','\1', 51 preg_replace('/\s*#\w+\s*[,|]?\s*/','', $val))))); 52 return $x; 53 } 54 55 56 // http://doc.spip.org/@analyser_dtd 57 function analyser_dtd($loc, $avail, &$dtc) 58 { 59 if ($avail == 'SYSTEM') 60 $file = $loc; 61 else { 62 $file = sous_repertoire(_DIR_CACHE_XML); 63 $file .= preg_replace('/[^\w.]/','_', $loc); 64 } 65 66 $dtd = ''; 67 if (@is_readable($file)) { 68 lire_fichier($file, $dtd); 69 } else { 70 if ($avail == 'PUBLIC') { 71 include_spip('inc/distant'); 72 if ($dtd = trim(recuperer_page($loc))) 73 ecrire_fichier($file, $dtd, true); 74 } 75 } 76 77 if (!$dtd) { 78 spip_log("DTD '$loc' inaccessible"); 79 return false; 80 } else spip_log("analyse de la DTD $loc "); 81 82 while ($dtd) { 83 if ($dtd[0] != '<') 84 $r = analyser_dtd_lexeme($dtd, $dtc, $loc); 85 elseif ($dtd[1] != '!') 86 $r = analyser_dtd_pi($dtd, $dtc, $loc); 87 elseif ($dtd[2] == '[') 88 $r = analyser_dtd_data($dtd, $dtc, $loc); 89 else switch ($dtd[3]) { 90 case '%' : $r = analyser_dtd_data($dtd, $dtc, $loc); break; 91 case 'T' : $r = analyser_dtd_attlist($dtd, $dtc, $loc);break; 92 case 'L' : $r = analyser_dtd_element($dtd, $dtc, $loc);break; 93 case 'N' : $r = analyser_dtd_entity($dtd, $dtc, $loc);break; 94 case 'O' : $r = analyser_dtd_notation($dtd, $dtc, $loc);break; 95 case '-' : $r = analyser_dtd_comment($dtd, $dtc, $loc); break; 96 default: $r = -1; 97 } 98 if (!is_string($r)) { 99 spip_log("erreur $r dans la DTD " . substr($dtd,0,80) . "....."); 100 return false; 101 } 102 $dtd = $r; 103 } 104 return true; 105 } 106 107 // http://doc.spip.org/@analyser_dtd_comment 108 function analyser_dtd_comment($dtd, &$dtc, $grammaire){ 109 // ejecter les commentaires, surtout quand ils contiennent du code. 110 // Option /s car sur plusieurs lignes parfois 111 112 if (!preg_match('/^<!--.*?-->\s*(.*)$/s',$dtd, $m)) 113 return -6; 114 return $m[1]; 115 } 116 117 // http://doc.spip.org/@analyser_dtd_pi 118 function analyser_dtd_pi($dtd, &$dtc, $grammaire){ 119 if (!preg_match('/^<\?.*?>\s*(.*)$/s', $dtd, $m)) 120 return -10; 121 return $m[1]; 122 } 123 124 // http://doc.spip.org/@analyser_dtd_lexeme 125 function analyser_dtd_lexeme($dtd, &$dtc, $grammaire){ 126 if (!preg_match(_REGEXP_ENTITY_DEF,$dtd, $m)) 127 return -9; 128 129 list(,$s) = $m; 130 $n = $dtc->macros[$s]; 131 if (is_array($n)) { 132 // en cas d'inclusion, l'espace de nom est le meme 133 analyser_dtd($n[1], $n[0], $dtc); 134 } 135 136 return ltrim(substr($dtd,strlen($m[0]))); 137 } 138 139 // il faudrait prevoir plusieurs niveaux d'inclusion. 140 // (Ruby en utilise mais l'erreur est transparente. Scandaleux coup de pot) 141 142 // http://doc.spip.org/@analyser_dtd_data 143 function analyser_dtd_data($dtd, &$dtc, $grammaire){ 144 if (!preg_match('/^<!\[\s*%\s*([^;]*);\s*\[\s*(.*?)\]\]>\s*(.*)$/s',$dtd, $m)) 145 return -11; 146 if ($dtc->macros[$m[1]] == 'INCLUDE') 147 $retour = $m[2] . $m[3]; 148 else $retour = $m[3]; 149 return $retour; 150 } 151 152 // http://doc.spip.org/@analyser_dtd_notation 153 function analyser_dtd_notation($dtd, &$dtc, $grammaire){ 154 if (!preg_match('/^<!NOTATION.*?>\s*(.*)$/s',$dtd, $m)) 155 return -8; 156 spip_log("analyser_dtd_notation a ecrire"); 157 return $m[1]; 158 } 159 160 // http://doc.spip.org/@analyser_dtd_entity 161 function analyser_dtd_entity($dtd, &$dtc, $grammaire) 162 { 163 if (!preg_match(_REGEXP_ENTITY_DECL, $dtd, $m)) 164 return -2; 165 166 list($t, $term, $nom, $type, $val, $q, $c, $alt, $dtd) = $m; 167 168 if (isset($dtc->macros[$nom]) AND $dtc->macros[$nom]) 169 return $dtd; 170 if (isset($dtc->entites[$nom])) 171 spip_log("redefinition de l'entite $nom"); 172 if (!$term) 173 $dtc->entites[$nom] = expanserEntite($val, $dtc->macros); 174 elseif (!$type) 175 $dtc->macros[$nom] = expanserEntite($val, $dtc->macros); 176 elseif (!$alt) 177 $dtc->macros[$nom] = expanserEntite($val, $dtc->macros); 178 else { 179 if (strpos($alt, '/') === false) 180 $alt = preg_replace(',/[^/]+$,', '/', $grammaire) 181 . $alt ; 182 $dtc->macros[$nom] = array($type, $alt); 183 } 184 return $dtd; 185 } 186 187 // Dresser le tableau des filles potentielles de l'element 188 // pour traquer tres vite les illegitimes. 189 // Si la regle a au moins une sequence (i.e. une virgule) 190 // ou n'est pas une itération (i.e. se termine par * ou +) 191 // en faire une RegExp qu'on appliquera aux balises rencontrees. 192 // Sinon, conserver seulement le type de l'iteration car la traque 193 // aura fait l'essentiel du controle sans memorisation des balises. 194 // Fin du controle en finElement 195 196 // http://doc.spip.org/@analyser_dtd_element 197 function analyser_dtd_element($dtd, &$dtc, $grammaire) 198 { 199 if (!preg_match('/^<!ELEMENT\s+(\S+)\s+([^>]*)>\s*(.*)$/s', $dtd, $m)) 200 return -3; 201 202 list(,$nom, $val, $dtd) = $m; 203 $nom = expanserEntite($nom, $dtc->macros); 204 $val = compilerRegle(expanserEntite($val, $dtc->macros)); 205 if (isset($dtc->elements[$nom])) { 206 spip_log("redefinition de l'element $nom dans la DTD"); 207 return -4; 208 } 209 $filles = array(); 210 if ($val == '(EMPTY )') 211 $dtc->regles[$nom] = 'EMPTY'; 212 elseif ($val == '(ANY )') 213 $dtc->regles[$nom] = 'ANY'; 214 else { 215 $last = substr($val,-1); 216 if (preg_match('/ \w/', $val) 217 OR strpos('*+', $last) === false) 218 $dtc->regles[$nom] = "/^$val$/"; 219 else 220 $dtc->regles[$nom] = $last; 221 $filles = array_values(preg_split('/\W+/', $val,-1, PREG_SPLIT_NO_EMPTY)); 222 223 foreach ($filles as $k) { 224 if (!isset($dtc->peres[$k])) 225 $dtc->peres[$k] = array(); 226 if (!in_array($nom, $dtc->peres[$k])) 227 $dtc->peres[$k][]= $nom; 228 } 229 } 230 $dtc->elements[$nom]= $filles; 231 return $dtd; 232 } 233 234 235 // http://doc.spip.org/@analyser_dtd_attlist 236 function analyser_dtd_attlist($dtd, &$dtc, $grammaire) 237 { 238 if (!preg_match('/^<!ATTLIST\s+(\S+)\s+([^>]*)>\s*(.*)/s', $dtd, $m)) 239 return -5; 240 241 list(,$nom, $val, $dtd) = $m; 242 $nom = expanserEntite($nom, $dtc->macros); 243 $val = expanserEntite($val, $dtc->macros); 244 if (!isset($dtc->attributs[$nom])) 245 $dtc->attributs[$nom] = array(); 246 247 if (preg_match_all("/\s*(\S+)\s+(([(][^)]*[)])|(\S+))\s+([^\s']*)(\s*'[^']*')?/", $val, $r2, PREG_SET_ORDER)) { 248 foreach($r2 as $m2) { 249 $v = preg_match('/^\w+$/', $m2[2]) ? $m2[2] 250 : ('/^' . preg_replace('/\s+/', '', $m2[2]) . '$/'); 251 $m21 = expanserEntite($m2[1], $dtc->macros); 252 $m25 = expanserEntite($m2[5], $dtc->macros); 253 $dtc->attributs[$nom][$m21] = array($v, $m25); 254 } 255 } 256 257 return $dtd; 258 } 259 260 261 // http://doc.spip.org/@expanserEntite 262 function expanserEntite($val, $macros) 263 { 264 if (preg_match_all(_REGEXP_ENTITY_USE, $val, $r, PREG_SET_ORDER)){ 265 foreach($r as $m) { 266 $ent = $m[1]; 267 // il peut valoir "" 268 if (isset($macros[$ent])) 269 $val = str_replace($m[0], $macros[$ent], $val); 270 } 271 } 272 return trim(preg_replace('/\s+/', ' ', $val)); 273 } 274 275 276 277 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Wed Nov 21 10:20:27 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |