X-Git-Url: http://git.cyclocoop.org/?p=velocampus%2Fweb%2Fwww.git;a=blobdiff_plain;f=www%2Fecrire%2Fpublic%2Freferences.php;fp=www%2Fecrire%2Fpublic%2Freferences.php;h=9cf87c57f1ff54b7b27e4e2fb668bf217899d940;hp=0000000000000000000000000000000000000000;hb=80b4d3e85f78d402ed2e73f8f5d1bf4c19962eed;hpb=aaf970bf4cdaf76689ecc10609048e18d073820c diff --git a/www/ecrire/public/references.php b/www/ecrire/public/references.php new file mode 100644 index 0000000..9cf87c5 --- /dev/null +++ b/www/ecrire/public/references.php @@ -0,0 +1,552 @@ +id_parent; + } + } + +# spip_log("Cherche: $nom_champ a partir de '$idb'"); + $nom_champ = strtolower($nom_champ); + // attention: entre la boucle nommee 0, "" et le tableau vide, + // il y a incoherences qu'il vaut mieux eviter + while (isset($boucles[$idb])) { + list ($t, $c) = index_tables_en_pile($idb, $nom_champ, $boucles); + + if ($t) { + if (!in_array($t, $boucles[$idb]->select)) { + $boucles[$idb]->select[] = $t; + } + return '$Pile[$SP' . ($i ? "-$i" : "") . '][\'' . $c . '\']'; + } +# spip_log("On remonte vers $i"); + // Sinon on remonte d'un cran + $idb = $boucles[$idb]->id_parent; + $i++; + } + +# spip_log("Pas vu $nom_champ"); + // esperons qu'il y sera + return('@$Pile[0][\''. strtolower($nom_champ) . '\']'); +} + +// http://doc.spip.org/@index_tables_en_pile +function index_tables_en_pile($idb, $nom_champ, &$boucles) { + global $exceptions_des_tables; + + $r = $boucles[$idb]->type_requete; + + if ($r == 'boucle') return array(); + if (!$r) { + # continuer pour chercher l'erreur suivante + return array("'#" . $r . ':' . $nom_champ . "'",''); + } + + $desc = $boucles[$idb]->show; + $excep = isset($exceptions_des_tables[$r]) ? $exceptions_des_tables[$r] : ''; + if ($excep) + $excep = isset($excep[$nom_champ]) ? $excep[$nom_champ] : ''; + if ($excep) { + return index_exception($boucles[$idb], $desc, $nom_champ, $excep); + } else { + if (isset($desc['field'][$nom_champ])) { + $t = $boucles[$idb]->id_table; + return array("$t.$nom_champ", $nom_champ); + } else { + if ($boucles[$idb]->jointures_explicites) { + $t = trouver_champ_exterieur($nom_champ, + $boucles[$idb]->jointures, + $boucles[$idb]); + if ($t) + return index_exception($boucles[$idb], + $desc, + $nom_champ, + array($t[1]['id_table'], $nom_champ)); + } + return array('',''); + } + } +} + +// Reference a une entite SPIP alias d'un champ SQL +// Ca peut meme etre d'un champ dans une jointure +// qu'il faut provoquer si ce n'est fait + +// http://doc.spip.org/@index_exception +function index_exception(&$boucle, $desc, $nom_champ, $excep) +{ + static $trouver_table; + if (!$trouver_table) + $trouver_table = charger_fonction('trouver_table', 'base'); + + if (is_array($excep)) { + // permettre aux plugins de gerer eux meme des jointures derogatoire ingerables + $t = NULL; + if (count($excep)==3){ + $index_exception_derogatoire = array_pop($excep); + $t = $index_exception_derogatoire($boucle, $desc, $nom_champ, $excep); + } + if ($t == NULL) { + list($e, $x) = $excep; #PHP4 affecte de gauche a droite + $excep = $x; #PHP5 de droite a gauche ! + $j = $trouver_table($e, $boucle->sql_serveur); + if (!$j) return array('',''); + $e = $j['table']; + if (!$t = array_search($e, $boucle->from)) { + $k = $j['key']['PRIMARY KEY']; + if (strpos($k,',')) { + $l = (preg_split('/\s*,\s*/', $k)); + $k = $desc['key']['PRIMARY KEY']; + if (!in_array($k, $l)) { + spip_log("jointure impossible $e " . join(',', $l)); + return array('',''); + } + } + $k = array($boucle->id_table, array($e), $k); + fabrique_jointures($boucle, array($k)); + $t = array_search($e, $boucle->from); + } + } + } + else $t = $boucle->id_table; + // demander a SQL de gerer le synonyme + // ca permet que excep soit dynamique (Cedric, 2/3/06) + if ($excep != $nom_champ) $excep .= ' AS '. $nom_champ; + return array("$t.$excep", $nom_champ); +} + + +// cette fonction sert d'API pour demander le champ '$champ' dans la pile +// http://doc.spip.org/@champ_sql +function champ_sql($champ, $p) { + return index_pile($p->id_boucle, $champ, $p->boucles, $p->nom_boucle); +} + +// cette fonction sert d'API pour demander une balise Spip avec filtres + +// http://doc.spip.org/@calculer_champ +function calculer_champ($p) { + $p = calculer_balise($p->nom_champ, $p); + return applique_filtres($p); +} + +// Cette fonction sert d'API pour demander une balise SPIP sans filtres. +// Pour une balise nommmee NOM, elle demande a charger_fonction de chercher +// s'il existe une fonction balise_NOM ou balise_NOM_dist +// eventuellement en chargeant le fichier balise/NOM.php. +// Si la balise est de la forme PREFIXE_SUFFIXE (cf LOGO_* et URL_*) +// elle fait de meme avec juste le PREFIXE. +// Si pas de fonction, c'est une reference a une colonne de table SQL connue. +// Les surcharges des colonnes SQL via charger_fonction sont donc possibles. + +// http://doc.spip.org/@calculer_balise +function calculer_balise($nom, $p) { + + // S'agit-t-il d'une balise_XXXX[_dist]() ? + if ($f = charger_fonction($nom, 'balise', true)) { + $res = $f($p); + if ($res !== NULL) + return $res; + } + + // Certaines des balises comportant un _ sont generiques + if ($f = strpos($nom, '_') + AND $f = charger_fonction(substr($nom,0,$f+1), 'balise', true)) { + $res = $f($p); + if ($res !== NULL) + return $res; + } + + $f = charger_fonction('DEFAUT', 'calculer_balise'); + + return $f($nom, $p); +} + +function calculer_balise_DEFAUT_dist($nom, $p) { + + // ca pourrait etre un champ SQL homonyme, + $p->code = index_pile($p->id_boucle, $nom, $p->boucles, $p->nom_boucle); + + // compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour + // il faut recracher {...} quand ce n'est finalement pas des args + if ($p->fonctions AND (!$p->fonctions[0][0]) AND $p->fonctions[0][1]) { + $code = addslashes($p->fonctions[0][1]); + $p->code .= " . '$code'"; + } + + // ne pas passer le filtre securite sur les id_xxx + if (strpos($nom, 'ID_') === 0) + $p->interdire_scripts = false; + + // Compatibilite ascendante avec les couleurs html (#FEFEFE) : + // SI le champ SQL n'est pas trouve + // ET si la balise a une forme de couleur + // ET s'il n'y a ni filtre ni etoile + // ALORS retourner la couleur. + // Ca permet si l'on veut vraiment de recuperer [(#ACCEDE*)] + if (preg_match("/^[A-F]{1,6}$/i", $nom) + AND !$p->etoile + AND !$p->fonctions) { + $p->code = "'#$nom'"; + $p->interdire_scripts = false; + } + + return $p; +} + + +// +// Traduction des balises dynamiques, notamment les "formulaire_*" +// Inclusion du fichier associe a son nom, qui contient la fonction homonyme +// donnant les arguments a chercher dans la pile, et qui sont donc compiles. +// On leur adjoint les arguments explicites de la balise (cf #LOGIN{url}) +// et d'eventuelles valeurs transmises d'autorite par la balise. +// (cf http://trac.rezo.net/trac/spip/ticket/1728) +// La fonction nommee ci-dessous recevra a l'execution la valeur de tout ca. + +define('CODE_EXECUTER_BALISE', "executer_balise_dynamique('%s', + array(%s%s), + array(%s%s))"); + +// http://doc.spip.org/@calculer_balise_dynamique +function calculer_balise_dynamique($p, $nom, $l, $supp=array()) { + + if (!balise_distante_interdite($p)) { + $p->code = "''"; + return $p; + } + // compatibilite: depuis qu'on accepte #BALISE{ses_args} sans [(...)] autour + // il faut recracher {...} quand ce n'est finalement pas des args + if ($p->fonctions AND (!$p->fonctions[0][0]) AND $p->fonctions[0][1]) { + $p->fonctions = null; + } + + if ($p->param AND ($c = $p->param[0])) { + // liste d'arguments commence toujours par la chaine vide + array_shift($c); + // construire la liste d'arguments comme pour un filtre + $param = compose_filtres_args($p, $c, ','); + } else $param = ""; + $collecte = collecter_balise_dynamique($l, $p, $nom); + + $p->code = sprintf(CODE_EXECUTER_BALISE, $nom, + join(',', $collecte), + ($collecte ? $param : substr($param,1)), # virer la virgule + memoriser_contexte_compil($p), + (!$supp ? '' : (', ' . join(',', $supp)))); + + $p->interdire_scripts = false; + return $p; +} + +// Construction du tableau des arguments d'une balise dynamique. +// Ces arguments peuvent etre eux-meme des balises (cf FORMULAIRE_SIGNATURE) +// mais gare au bouclage (on peut s'aider de $nom pour le reperer au besoin) +// En revanche ils n'ont pas de filtres, donc on appelle calculer_balise qui +// ne s'occupe pas de ce qu'il y a dans $p (mais qui va y ecrire le code) + +// http://doc.spip.org/@collecter_balise_dynamique +function collecter_balise_dynamique($l, &$p, $nom) { + $args = array(); + foreach($l as $c) { $x = calculer_balise($c, $p); $args[] = $x->code;} + return $args; +} + + +// il faudrait savoir traiter les formulaires en local +// tout en appelant le serveur SQL distant. +// En attendant, cette fonction permet de refuser une authentification +// sur qqch qui n'a rien a voir. + +// http://doc.spip.org/@balise_distante_interdite +function balise_distante_interdite($p) { + $nom = $p->id_boucle; + + if ($nom + AND $p->boucles[$nom]->sql_serveur + AND !in_array($p->boucles[$nom]->sql_serveur,$GLOBALS['exception_des_connect'])) { + spip_log( $nom .':' . $p->nom_champ .' '._T('zbug_distant_interdit')); + return false; + } + return true; +} + + +// +// Traitements standard de divers champs +// definis par $table_des_traitements, cf. ecrire/public/interfaces +// +// http://doc.spip.org/@champs_traitements +function champs_traitements ($p) { + global $table_des_traitements; + + if (!isset($table_des_traitements[$p->nom_champ])) + return $p->code; + $ps = $table_des_traitements[$p->nom_champ]; + if (is_array($ps)) { + // new style + + if ($p->nom_boucle) + $type = $p->boucles[$p->nom_boucle]->type_requete; + else + $type = $p->type_requete; + // le traitement peut n'etre defini que pour une table en particulier + if (isset($ps[$type])) + $ps = $ps[$type]; + elseif(isset($ps[0])) + $ps = $ps[0]; + else $ps=false; + } + + if (!$ps) return $p->code; + + // Si une boucle DOCUMENTS{doublons} est presente dans le squelette, + // ou si in INCLURE contient {doublons} + // on insere une fonction de remplissage du tableau des doublons + // dans les filtres propre() ou typo() + // (qui traitent les raccourcis referencant les docs) + + if (isset($p->descr['documents']) + AND + $p->descr['documents'] + AND ( + (strpos($ps,'propre') !== false) + OR + (strpos($ps,'typo') !== false) + )) + $ps = 'traiter_doublons_documents($doublons, '.$ps.')'; + + // Passer |safehtml sur les boucles "sensibles" + // sauf sur les champs dont on est surs + // ces exceptions doivent etre ventilees dans les plugins fonctionnels concernes + // dans la globale table_des_traitements + switch ($p->type_requete) { + case 'signatures': + case 'syndic_articles': + $champs_surs = array( + 'date', 'date_heure', 'statut', 'ip', 'url_article', 'maj', 'idx' + ); + if (!in_array(strtolower($p->nom_champ), $champs_surs) + AND !preg_match(',^ID_,', $p->nom_champ)) + $ps = 'safehtml('.$ps.')'; + break; + default: + break; + } + + // Remplacer enfin le placeholder %s par le vrai code de la balise + return str_replace('%s', $p->code, $ps); +} + + +// +// Appliquer les filtres a un champ [(#CHAMP|filtre1|filtre2)] +// retourne un code php compile exprimant ce champ filtre et securise +// - une etoile => pas de processeurs standards +// - deux etoiles => pas de securite non plus ! +// +// http://doc.spip.org/@applique_filtres +function applique_filtres($p) { + + // Traitements standards (cf. supra) + if ($p->etoile == '') + $code = champs_traitements($p); + else + $code = $p->code; + + // Appliquer les filtres perso + if ($p->param) + $code = compose_filtres($p, $code); + + // S'il y a un lien avec la session, ajouter un code qui levera + // un drapeau dans la structure d'invalidation $Cache + if (isset($p->descr['session'])) + $code = "invalideur_session(\$Cache, $code)"; + + // Securite + if ($p->interdire_scripts + AND $p->etoile != '**') { + if (!preg_match("/^sinon[(](.*),'([^']*)'[)]$/", $code, $r)) + $code = "interdire_scripts($code)"; + else { + $code = interdire_scripts($r[2]); + $code = "sinon(interdire_scripts($r[1]),'$code')"; + } + } + return $code; +} + +// Cf. function pipeline dans ecrire/inc_utils.php +// http://doc.spip.org/@compose_filtres +function compose_filtres(&$p, $code) { + + $image_miette = false; + foreach($p->param as $filtre) { + $fonc = array_shift($filtre); + if (!$fonc) continue; // normalement qu'au premier tour. + $is_filtre_image = ((substr($fonc,0,6)=='image_') AND $fonc!='image_graver'); + if ($image_miette AND !$is_filtre_image){ + // il faut graver maintenant car apres le filtre en cours + // on est pas sur d'avoir encore le nom du fichier dans le pipe + $code = "filtrer('image_graver', $code)"; + $image_miette = false; + } + // recuperer les arguments du filtre, + // a separer par "," ou ":" dans le cas du filtre "?{a,b}" + if ($fonc !== '?') { + $sep = ','; + } else {$sep = ':'; + // |?{a,b} *doit* avoir exactement 2 arguments ; on les force + if (count($filtre) != 2) + $filtre = array(isset($filtre[0])?$filtre[0]:"", isset($filtre[1])?$filtre[1]:""); + } + $arglist = compose_filtres_args($p, $filtre, $sep); + $logique = filtre_logique($fonc, $code, substr($arglist,1)); + if ($logique) + $code = $logique; + else { + if (isset($GLOBALS['spip_matrice'][$fonc])) { + $code = "filtrer('$fonc',$code$arglist)"; + if ($is_filtre_image) $image_miette = true; + } + + // le filtre est defini sous forme de fonction ou de methode + // par ex. dans inc_texte, inc_filtres ou mes_fonctions + elseif ($f = chercher_filtre($fonc)) { + $code = "$f($code$arglist)"; + } + // le filtre n'existe pas, + // on le notifie + else erreur_squelette(array('zbug_erreur_filtre', array('filtre'=> texte_script($fonc))), $p); + } + } + // ramasser les images intermediaires inutiles et graver l'image finale + if ($image_miette) + $code = "filtrer('image_graver',$code)"; + + return $code; +} + +// Filtres et,ou,oui,non,sinon,xou,xor,and,or,not,yes +// et comparateurs +function filtre_logique($fonc, $code, $arg) +{ + global $table_criteres_infixes; + switch (true) { + case in_array($fonc, $table_criteres_infixes): + return "($code $fonc $arg)"; + case ($fonc == 'and') OR ($fonc == 'et'): + return "((($code) AND ($arg)) ?' ' :'')"; + case ($fonc == 'or') OR ($fonc == 'ou'): + return "((($code) OR ($arg)) ?' ' :'')"; + case ($fonc == 'xor') OR ($fonc == 'xou'): + return "((($code) XOR ($arg)) ?' ' :'')"; + case ($fonc == 'sinon'): + return "(((\$a = $code) OR (!is_array(\$a) AND strlen(\$a))) ? \$a : $arg)"; + case ($fonc == 'not') OR ($fonc == 'non'): + return "(($code) ?'' :' ')"; + case ($fonc == 'yes') OR ($fonc == 'oui'): + return "(($code) ?' ' :'')"; + } + return ''; +} + +// http://doc.spip.org/@compose_filtres_args +function compose_filtres_args($p, $args, $sep) +{ + $arglist = ""; + foreach ($args as $arg) { + $arglist .= $sep . + calculer_liste($arg, $p->descr, $p->boucles, $p->id_boucle); + } + return $arglist; +} + +// +// Reserve les champs necessaires a la comparaison avec le contexte donne par +// la boucle parente ; attention en recursif il faut les reserver chez soi-meme +// ET chez sa maman +// +// http://doc.spip.org/@calculer_argument_precedent +function calculer_argument_precedent($idb, $nom_champ, &$boucles) { + + // si recursif, forcer l'extraction du champ SQL mais ignorer le code + if ($boucles[$idb]->externe) { + index_pile ($idb, $nom_champ, $boucles); + $zero = '$SP'; + } else $zero = '0'; + // retourner $Pile[$SP] et pas $Pile[0] si recursion en 1ere boucle + $prec = $boucles[$idb]->id_parent; + return (($prec === '') + ? ('$Pile[' . $zero . "]['$nom_champ']") + : index_pile($prec, $nom_champ, $boucles)); +} + +// +// Rechercher dans la pile des boucles actives celle ayant un critere +// comportant un certain $motif, et construire alors une reference +// a l'environnement de cette boucle, qu'on indexe avec $champ. +// Sert a referencer une cellule non declaree dans la table et pourtant la. +// Par exemple pour la balise #POINTS on produit $Pile[$SP-n]['points'] +// si la n-ieme boucle a un critere "recherche", car on sait qu'il a produit +// "SELECT XXXX AS points" +// + +// http://doc.spip.org/@rindex_pile +function rindex_pile($p, $champ, $motif) +{ + $n = 0; + $b = $p->id_boucle; + $p->code = ''; + while ($b != '') { + foreach($p->boucles[$b]->criteres as $critere) { + if ($critere->op == $motif) { + $p->code = '$Pile[$SP' . (($n==0) ? "" : "-$n") . + "]['$champ']"; + $b = ''; + break 2; + } + } + $n++; + $b = $p->boucles[$b]->id_parent; + } + + // si on est hors d'une boucle de {recherche}, cette balise est vide + if (!$p->code) + $p->code = "''"; + + $p->interdire_scripts = false; + return $p; +} + +?>