[ Index ]
 

Code source de SPIP 1.9.2c

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/ecrire/public/ -> references.php (source)

   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  ?>


Généré le : Wed Nov 21 10:20:27 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics