| [ 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 14 15 // fonctions de recherche et de reservation 16 // dans l'arborescence des boucles 17 18 if (!defined("_ECRIRE_INC_VERSION")) return; 19 20 // index_pile retourne la position dans la pile du champ SQL $nom_champ 21 // en prenant la boucle la plus proche du sommet de pile (indique par $idb). 22 // Si on ne trouve rien, on considere que ca doit provenir du contexte 23 // (par l'URL ou l'include) qui a ete recopie dans Pile[0] 24 // (un essai d'affinage a debouche sur un bug vicieux) 25 // Si ca reference un champ SQL, on le memorise dans la structure $boucles 26 // afin de construire un requete SQL minimale (plutot qu'un brutal 'SELECT *') 27 28 // http://doc.spip.org/@index_pile 29 function index_pile($idb, $nom_champ, &$boucles, $explicite='') { 30 global $exceptions_des_tables, $table_des_tables, $tables_des_serveurs_sql; 31 32 $i = 0; 33 if (strlen($explicite)) { 34 // Recherche d'un champ dans un etage superieur 35 while (($idb != $explicite) && ($idb !='')) { 36 # spip_log("Cherchexpl: $nom_champ '$explicite' '$idb' '$i'"); 37 $i++; 38 $idb = $boucles[$idb]->id_parent; 39 } 40 } 41 42 # spip_log("Cherche: $nom_champ a partir de '$idb'"); 43 $nom_champ = strtolower($nom_champ); 44 // attention: entre la boucle nommee 0, "" et le tableau vide, 45 // il y a incoherences qu'il vaut mieux eviter 46 while (isset($boucles[$idb])) { 47 list ($t, $c) = index_tables_en_pile($idb, $nom_champ, $boucles); 48 if ($t) { 49 if (!in_array($t, $boucles[$idb]->select)) 50 $boucles[$idb]->select[] = $t; 51 return '$Pile[$SP' . ($i ? "-$i" : "") . '][\'' . $c . '\']'; 52 } 53 # spip_log("On remonte vers $i"); 54 // Sinon on remonte d'un cran 55 $idb = $boucles[$idb]->id_parent; 56 $i++; 57 } 58 59 # spip_log("Pas vu $nom_champ"); 60 // esperons qu'il y sera 61 return('$Pile[0][\''. strtolower($nom_champ) . '\']'); 62 } 63 64 /** 65 * retourne la description de la table associee a un type de boucle 66 * retourne un tableau avec les entrees field et key (comme dans serial.php) 67 * et type = type de boucle, serveur = serveur bdd associe et table = nom de 68 * la table concernee 69 * retourne null si on ne trouve pas la table 70 */ 71 // http://doc.spip.org/@description_type_requete 72 function description_type_requete($type, $serveur='') { 73 global $table_des_tables, $tables_des_serveurs_sql; 74 75 if (!$serveur) { 76 $s = 'localhost'; 77 // indirection (pour les rares cas ou le nom de la table!=type) 78 $t = $table_des_tables[$type]; 79 } else $s = $serveur; 80 // pour les tables non Spip 81 if (!$t) { 82 $nom_table = $t = $type; 83 } else { 84 $nom_table = 'spip_' . $t; 85 } 86 87 $desc = $tables_des_serveurs_sql[$s][$nom_table]; 88 if (!isset($desc['field'])) { 89 $desc = $table_des_tables[$type] ? 90 (($GLOBALS['table_prefix'] ? $GLOBALS['table_prefix'] : 'spip') 91 . '_' . $t) : $nom_table; 92 93 $desc = spip_abstract_showtable($desc, $serveur); 94 if (!isset($desc['field'])) 95 return null; 96 $tables_des_serveurs_sql[$s][$nom_table]= $desc; 97 } 98 $desc['serveur']= $s; 99 $desc['type']= $t; 100 $desc['table']= $nom_table; 101 102 return $desc; 103 } 104 105 // http://doc.spip.org/@index_tables_en_pile 106 function index_tables_en_pile($idb, $nom_champ, &$boucles) { 107 global $exceptions_des_tables; 108 109 $r = $boucles[$idb]->type_requete; 110 $s = $boucles[$idb]->sql_serveur; 111 112 $desc= description_type_requete($r, $s); 113 114 if(!$desc) { 115 erreur_squelette(_T('zbug_table_inconnue', array('table' => $r)), 116 "'$idb'"); 117 # continuer pour chercher l'erreur suivante 118 return array("'#" . $r . ':' . $nom_champ . "'",''); 119 } 120 121 $t= $desc['type']; 122 $excep = isset($exceptions_des_tables[$r]) ? $exceptions_des_tables[$r] : ''; 123 if ($excep) 124 $excep = isset($excep[$nom_champ]) ? $excep[$nom_champ] : ''; 125 126 if ($excep) { 127 return index_exception($boucles[$idb], $desc, $nom_champ, $excep); 128 } else { 129 if (isset($desc['field'][$nom_champ])) 130 return array("$t.$nom_champ", $nom_champ); 131 else { 132 if ($boucles[$idb]->jointures_explicites) { 133 $t = trouver_champ_exterieur($nom_champ, 134 $boucles[$idb]->jointures, 135 $boucles[$idb]); 136 if ($t) 137 return index_exception($boucles[$idb], 138 $desc, 139 $nom_champ, 140 array($t[0], $nom_champ)); 141 } 142 return array('',''); 143 } 144 } 145 } 146 147 // Reference a une entite SPIP alias d'un champ SQL 148 // Ca peut meme etre d'un champ dans une jointure 149 // qu'il faut provoquer si ce n'est fait 150 151 // http://doc.spip.org/@index_exception 152 function index_exception(&$boucle, $desc, $nom_champ, $excep) 153 { 154 global $tables_des_serveurs_sql; 155 156 if (is_array($excep)) { 157 // permettre aux plugins de gerer eux meme des jointures derogatoire ingérables 158 $t = NULL; 159 if (count($excep)==3){ 160 $index_exception_derogatoire = array_pop($excep); 161 $t = $index_exception_derogatoire($boucle, $desc, $nom_champ, $excep); 162 } 163 if ($t == NULL) { 164 list($e, $x) = $excep; #PHP4 affecte de gauche a droite 165 $excep = $x; #PHP5 de droite a gauche ! 166 if (!$t = array_search($e, $boucle->from)) { 167 $t = 'J' . count($boucle->from); 168 $boucle->from[$t] = $e; 169 $j = $tables_des_serveurs_sql[$desc['serveur']][$e]; 170 # essayer ca un jour: list($nom, $j) = trouver_def_table($e, $boucle); 171 $j = $j['key']['PRIMARY KEY']; 172 $boucle->where[]= array("'='", "'$boucle->id_table." . "$j'", "'$t.$j'"); 173 } 174 } 175 } 176 else $t = $desc['type']; 177 // demander a SQL de gerer le synonyme 178 // ca permet que excep soit dynamique (Cedric, 2/3/06) 179 if ($excep != $nom_champ) $excep .= ' AS '. $nom_champ; 180 return array("$t.$excep", $nom_champ); 181 } 182 183 184 // cette fonction sert d'API pour demander le champ '$champ' dans la pile 185 // http://doc.spip.org/@champ_sql 186 function champ_sql($champ, $p) { 187 return index_pile($p->id_boucle, $champ, $p->boucles, $p->nom_boucle); 188 } 189 190 // cette fonction sert d'API pour demander une balise Spip avec filtres 191 192 // http://doc.spip.org/@calculer_champ 193 function calculer_champ($p) { 194 $p = calculer_balise($p->nom_champ, $p); 195 return applique_filtres($p); 196 } 197 198 // Cette fonction sert d'API pour demander une balise SPIP sans filtres. 199 // Pour une balise nommmee NOM, elle demande a charger_fonction de chercher 200 // s'il existe une fonction balise_NOM ou balise_NOM_dist 201 // eventuellement en chargeant le fichier balise/NOM.php. 202 // Si ce n'est pas le cas, hormis le cas historique des balise LOGO_*, 203 // elle estime que c'est une reference a une colonne de table connue. 204 // Les surcharges via charger_fonction sont donc possibles. 205 206 // http://doc.spip.org/@calculer_balise 207 function calculer_balise($nom, $p) { 208 209 // S'agit-t-il d'une balise_XXXX[_dist]() ? 210 if ($f = charger_fonction($nom, 'balise', true)) { 211 $res = $f($p); 212 if ($res !== NULL) 213 return $res; 214 } 215 216 // S'agit-il d'un logo ? Une fonction speciale les traite tous 217 if (ereg('^LOGO_', $nom)) { 218 if (!function_exists($f = 'calculer_balise_logo')) $f .= '_dist'; 219 $res = $f($p); 220 if ($res !== NULL) 221 return $res; 222 } 223 224 // ca pourrait etre un champ SQL homonyme, 225 $p->code = index_pile($p->id_boucle, $nom, $p->boucles, $p->nom_boucle); 226 227 // compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour 228 // il faut recracher {...} quand ce n'est finalement pas des args 229 if ($p->fonctions AND (!$p->fonctions[0][0]) AND $p->fonctions[0][1]) { 230 $code = addslashes($p->fonctions[0][1]); 231 $p->code .= " . '$code'"; 232 } 233 234 // ne pas passer le filtre securite sur les id_xxx 235 if (strpos($nom, 'ID_') === 0) 236 $p->interdire_scripts = false; 237 238 // Compatibilite ascendante avec les couleurs html (#FEFEFE) : 239 // SI le champ SQL n'est pas trouve 240 // ET si la balise a une forme de couleur 241 // ET s'il n'y a ni filtre ni etoile 242 // ALORS retourner la couleur. 243 // Ca permet si l'on veut vraiment de recuperer [(#ACCEDE*)] 244 if (preg_match("/^[A-F]{1,6}$/i", $nom) 245 AND !$p->etoile 246 AND !$p->fonctions) { 247 $p->code = "'#$nom'"; 248 $p->interdire_scripts = false; 249 } 250 251 return $p; 252 } 253 254 /* 255 256 L'appel direct de #ARTICLE_TRADUCTIONS devient #MODELE{article_traductions} 257 258 // fonction speciale d'appel a un modele modeles/truc.html pour la balise #TRUC 259 // exemples : #TRADUCTIONS, #DOC, #IMG... 260 // http://doc.spip.org/@calculer_balise_modele_dist 261 function calculer_balise_modele_dist($p){ 262 $nom = strtolower($p->nom_champ); 263 $contexte = array(); 264 265 if (isset($p->param[0])){ 266 while (count($p->param[0])>2){ 267 $p->param[]=array($p->param[0][0],array_pop($p->param[0])); 268 } 269 } 270 print_r($p->param); 271 $champ = phraser_arguments_inclure($p, true); 272 // a priori true 273 // si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise 274 // si true, les arguments simples (sans truc=chose) vont degager 275 $code_contexte = argumenter_inclure($champ, $p->descr, $p->boucles, $p->id_boucle, false); 276 277 // Si le champ existe dans la pile, on le met dans le contexte 278 // (a priori c'est du code mort ; il servait pour #LESAUTEURS dans 279 // le cas spip_syndic_articles) 280 #$code_contexte[] = "'$nom='.".champ_sql($nom, $p); 281 282 // Reserver la cle primaire de la boucle courante 283 if ($primary = $p->boucles[$p->id_boucle]->primary) { 284 $id = champ_sql($primary, $p); 285 $code_contexte[] = "'$primary='.".$id; 286 } 287 288 #print_r($code_contexte); 289 290 $p->code = "( ((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))<5)? 291 recuperer_fond('modeles/".$nom."', 292 creer_contexte_de_modele(array(".join(',', $code_contexte).",'recurs='.++\$recurs, \$GLOBALS['spip_lang']))):'')"; 293 $p->interdire_scripts = false; // securite assuree par le squelette 294 295 print $p->code."\n<hr/>\n"; 296 297 return $p; 298 } 299 */ 300 301 // 302 // Traduction des balises dynamiques, notamment les "formulaire_*" 303 // Inclusion du fichier associe a son nom. 304 // Ca donne les arguments a chercher dans la pile,on compile leur localisation 305 // Ensuite on delegue a une fonction generale definie dans executer_squelette 306 // qui recevra a l'execution la valeur des arguments, 307 // ainsi que les pseudo filtres qui ne sont donc pas traites a la compil 308 // mais on traite le vrai parametre si present. 309 310 // http://doc.spip.org/@calculer_balise_dynamique 311 function calculer_balise_dynamique($p, $nom, $l) { 312 313 balise_distante_interdite($p); 314 $param = ""; 315 if ($a = $p->param) { 316 $c = array_shift($a); 317 if (!array_shift($c)) { 318 $p->fonctions = $a; 319 array_shift( $p->param ); 320 $param = compose_filtres_args($p, $c, ','); 321 } 322 } 323 $collecte = join(',',collecter_balise_dynamique($l, $p, $nom)); 324 $p->code = "executer_balise_dynamique('" . $nom . "',\n\tarray(" 325 . $collecte 326 . ($collecte ? $param : substr($param,1)) # virer la virgule 327 . "),\n\tarray(" 328 . argumenter_balise($p->param, "', '") 329 . "), \$GLOBALS['spip_lang']," 330 . $p->ligne 331 . ')'; 332 $p->interdire_scripts = false; 333 $p->fonctions = array(); 334 $p->param = array(); 335 336 return $p; 337 } 338 339 // Construction du tableau des arguments d'une balise dynamique. 340 // Ces arguments peuvent etre eux-meme des balises (cf FORMULAIRE_SIGNATURE) 341 // mais gare au bouclage (on peut s'aider de $nom pour le reperer au besoin) 342 343 // http://doc.spip.org/@collecter_balise_dynamique 344 function collecter_balise_dynamique($l, &$p, $nom) { 345 $args = array(); 346 foreach($l as $c) { $x = calculer_balise($c, $p); $args[] = $x->code;} 347 return $args; 348 } 349 350 351 // il faudrait savoir traiter les formulaires en local 352 // tout en appelant le serveur SQL distant. 353 // En attendant, cette fonction permet de refuser une authentification 354 // sur qqch qui n'a rien a voir. 355 356 // http://doc.spip.org/@balise_distante_interdite 357 function balise_distante_interdite($p) { 358 $nom = $p->id_boucle; 359 if ($nom AND $p->boucles[$nom]->sql_serveur) { 360 erreur_squelette($p->nom_champ .' '._T('zbug_distant_interdit'), $nom); 361 } 362 } 363 364 365 // 366 // Traitements standard de divers champs 367 // definis par $table_des_traitements, cf. inc-compilo-api.php3 368 // 369 // http://doc.spip.org/@champs_traitements 370 function champs_traitements ($p) { 371 global $table_des_traitements; 372 373 if (!isset($table_des_traitements[$p->nom_champ])) 374 return $p->code; 375 $ps = $table_des_traitements[$p->nom_champ]; 376 if (is_array($ps)) { 377 // new style 378 379 if ($p->nom_boucle) 380 $type = $p->boucles[$p->nom_boucle]->type_requete; 381 else 382 $type = $p->type_requete; 383 $ps = $ps[isset($ps[$type]) ? $type : 0]; 384 } 385 386 if (!$ps) return $p->code; 387 388 // Si une boucle sous-jacente (?) traite les documents, on insere ici 389 // une fonction de remplissage du tableau des doublons -- mais seulement 390 // si on rencontre le filtre propre (qui traite les 391 // raccourcis <docXX> qui nous interessent) 392 if (isset($p->descr['documents']) 393 AND preg_match(',propre,', $ps)) 394 $ps = 'traiter_doublons_documents($doublons, '.$ps.')'; 395 396 // De meme, en cas de sql_serveur, on supprime les < IMGnnn > tant 397 // qu'on ne rapatrie pas les documents distants joints.. 398 // il faudrait aussi corriger les raccourcis d'URL locales 399 if ($p->id_boucle AND $p->boucles[$p->id_boucle]->sql_serveur) 400 $p->code = 'supprime_img(' . $p->code . ')'; 401 402 403 // Passer |safehtml sur les boucles "sensibles" 404 // sauf sur les champs dont on est surs 405 switch ($p->type_requete) { 406 case 'forums': 407 case 'signatures': 408 case 'syndic_articles': 409 $champs_surs = array( 410 'date', 'date_heure', 'statut', 'ip', 'url_article', 'maj', 'idx', 411 'parametres_forum'); 412 if (!in_array(strtolower($p->nom_champ), $champs_surs) 413 AND !preg_match(',^ID_,', $p->nom_champ)) 414 $ps = 'safehtml('.$ps.')'; 415 break; 416 default: 417 break; 418 } 419 420 // Remplacer enfin le placeholder %s par le vrai code de la balise 421 return str_replace('%s', $p->code, $ps); 422 } 423 424 425 // 426 // Appliquer les filtres a un champ [(#CHAMP|filtre1|filtre2)] 427 // retourne un code php compile exprimant ce champ filtre et securise 428 // - une etoile => pas de processeurs standards 429 // - deux etoiles => pas de securite non plus ! 430 // 431 // http://doc.spip.org/@applique_filtres 432 function applique_filtres($p) { 433 434 // Traitements standards (cf. supra) 435 if ($p->etoile == '') 436 $code = champs_traitements($p); 437 else 438 $code = $p->code; 439 440 // Appliquer les filtres perso 441 if ($p->param) 442 $code = compose_filtres($p, $code); 443 444 // Securite 445 if ($p->interdire_scripts 446 AND $p->etoile != '**') 447 $code = "interdire_scripts($code)"; 448 449 return $code; 450 } 451 452 // Cf. function pipeline dans ecrire/inc_utils.php 453 // http://doc.spip.org/@compose_filtres 454 function compose_filtres($p, $code) { 455 foreach($p->param as $filtre) { 456 $fonc = array_shift($filtre); 457 if ($fonc) { 458 // recuperer les arguments du filtre, les separer par des virgules 459 // *sauf* dans le cas du filtre "?" qui demande un ":" 460 if ($fonc == '?') { 461 // |?{a,b} *doit* avoir exactement 2 arguments ; on les force 462 if (count($filtre) != 2) 463 $filtre = array($filtre[0], $filtre[1]); 464 $arglist = compose_filtres_args($p, $filtre, ':'); 465 } else 466 $arglist = compose_filtres_args($p, $filtre, ','); 467 468 // le filtre est defini dans la matrice ? il faut alors l'appeler 469 // de maniere indirecte, pour charger au prealable sa definition 470 if (isset($GLOBALS['spip_matrice'][$fonc])) { 471 $code = "filtrer('$fonc',$code$arglist)"; 472 } 473 // le filtre est defini sous forme de fonction ou de methode 474 // par ex. dans inc_texte, inc_filtres ou mes_fonctions 475 else if (function_exists($fonc) 476 OR (preg_match("/^(\w*)::(\w*)$/", $fonc, $regs) 477 AND is_callable(array($regs[1], $regs[2])) 478 )) 479 $code = "$fonc($code$arglist)"; 480 // est-ce un test ? 481 else if (strpos("x < > <= >= == === != !== <> ? ", " $fonc ")) 482 $code = "($code $fonc " . substr($arglist,1) . ')'; 483 else 484 $code = "erreur_squelette('" 485 .texte_script(_T('zbug_erreur_filtre', array('filtre'=>$fonc))) 486 ."','" . $p->id_boucle . "')"; 487 } 488 } 489 return $code; 490 } 491 492 // http://doc.spip.org/@compose_filtres_args 493 function compose_filtres_args($p, $args, $sep) 494 { 495 $arglist = ""; 496 foreach ($args as $arg) { 497 $arglist .= $sep . 498 calculer_liste($arg, $p->descr, $p->boucles, $p->id_boucle); 499 } 500 return $arglist; 501 } 502 503 // 504 // Reserve les champs necessaires a la comparaison avec le contexte donne par 505 // la boucle parente ; attention en recursif il faut les reserver chez soi-meme 506 // ET chez sa maman 507 // 508 // http://doc.spip.org/@calculer_argument_precedent 509 function calculer_argument_precedent($idb, $nom_champ, &$boucles) { 510 511 // si recursif, forcer l'extraction du champ SQL mais ignorer le code 512 if ($boucles[$idb]->externe) 513 index_pile ($idb, $nom_champ, $boucles); 514 // retourner $Pile[$SP] et pas $Pile[0] (bug recursion en 1ere boucle) 515 $prec = $boucles[$idb]->id_parent; 516 return (($prec==="") ? ('$Pile[$SP][\''.$nom_champ.'\']') : 517 index_pile($prec, $nom_champ, $boucles)); 518 } 519 520 // 521 // Rechercher dans la pile des boucles actives celle ayant un critere 522 // comportant un certain $motif, et construire alors une reference 523 // a l'environnement de cette boucle, qu'on indexe avec $champ. 524 // Sert a referencer une cellule non declaree dans la table et pourtant la. 525 // Par exemple pour la balise #POINTS on produit $Pile[$SP-n]['points'] 526 // si la n-ieme boucle a un critere "recherche", car on sait qu'il a produit 527 // "SELECT XXXX AS points" 528 // 529 530 // http://doc.spip.org/@rindex_pile 531 function rindex_pile($p, $champ, $motif) 532 { 533 $n = 0; 534 $b = $p->id_boucle; 535 $p->code = ''; 536 while ($b != '') { 537 if ($s = $p->boucles[$b]->param) { 538 foreach($s as $v) { 539 if (strpos($v[1][0]->texte,$motif) !== false) { 540 $p->code = '$Pile[$SP' . (($n==0) ? "" : "-$n") . 541 "]['$champ']"; 542 $b = ''; 543 break; 544 } 545 } 546 } 547 $n++; 548 $b = $p->boucles[$b]->id_parent; 549 } 550 if (!$p->code) { 551 erreur_squelette(_T('zbug_champ_hors_motif', 552 array('champ' => '#' . strtoupper($champ), 553 'motif' => $motif) 554 ), $p->id_boucle); 555 } 556 $p->interdire_scripts = false; 557 return $p; 558 } 559 560 ?>
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 |
|