Changeset 113654 in spip-zone
- Timestamp:
- Jan 28, 2019, 12:36:57 PM (3 weeks ago)
- Location:
- _plugins_/macrosession/trunk
- Files:
-
- 4 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
_plugins_/macrosession/trunk/macrosession_options.php
r113627 r113654 2 2 3 3 /** 4 * Outils SPIP supplémentaires pour une gestion efficace pour l'hébergement 5 * des accés aux données de la _session courant 4 * Outils SPIP supplémentaires pour une gestion efficace des accés aux données de la _session courant 6 5 * et pour l'accès à des données de session étendue 7 6 * 8 7 * Balises #_SESSION, #_SESSION_SI, #_SESSION_SINON, #_SESSION_FIN 8 * #_AUTORISER_SI, #_AUTORISER_SINON, #_AUTORISER_FIN 9 9 * 10 * @copyright 2016, 2017 10 * @copyright 2016, 2017, 2018, 2019 11 11 * @author JLuc 12 12 * @credit Marcimat … … 16 16 17 17 include_spip('inc/session'); 18 include_spip ('inc/filtres'); 19 20 // TODO : ne charger inc/autoriser qu'au besoin, dans le code inséré à la place de chaque appel de balise 21 include_spip ('inc/autoriser'); 22 23 unset($_GET['debug']); // commenter pour permettre l'analyse et debug 18 include_spip ('inc/filtres'); 19 include_spip('inc/autoriser'); 24 20 25 21 // on utilise nobreak quand il n'y a pas de break entre 2 cases d'un switch, … … 27 23 if (!defined('nobreak')) 28 24 define('nobreak', ''); 29 30 //31 // FIXME : appeler appliquer_filtre dans le code compilé est une somptuosité superfétatoire32 // Au lieu de cela, appeler chercher_filtre à la compilation pour savoir quelle est la fonction appelée par le filtre et insérer dans le code compilé un appel direct à cette fonction33 // Comme ça plus besoin d'inclure inc/filtres dans mes_options34 35 //36 // Accés étendu aux données de session des visiteurs37 //38 // Aucun test n'est fait en amont sur la présence ou non d'une session :39 // le pipeline session_get peut être défini par ailleurs (autre plugin...)40 // Il reçoit un tableau avec 2 arguments : 'champ' contient le champ recherché,41 // et 'visiteur_session' contient la session en cours d'élaboration,42 // qu'il peut, ou non, utiliser pour le calcul ou la recherche de la valeur demandée43 //44 // Actuellement le pipeline n'est appelé que si la valeur demandée45 // n'est pas déjà présente dans la session globale SPIP de base...46 //47 function pipelined_session_get ($champ) {48 if (!isset ($GLOBALS['visiteur_session'])49 or !isset($GLOBALS['visiteur_session']['id_auteur']) // il semble que ces précisions soient nécessaires50 or !$GLOBALS['visiteur_session']['id_auteur'] )51 return '';52 elseif (isset ($GLOBALS['visiteur_session'][$champ]))53 return $GLOBALS['visiteur_session'][$champ];54 55 $session =56 array ( 'champ' => $champ,57 'visiteur_session' => $GLOBALS['visiteur_session']);58 $session = pipeline ('session_get', $session);59 if (isset ($session['visiteur_session'][$champ]))60 return $session['visiteur_session'][$champ];61 else62 return '';63 };64 65 if (!function_exists('existe_argument_balise')) {66 // prolégomène à interprete_argument_balise67 function existe_argument_balise ($n, $p) {68 return (($p->param) && (!$p->param[0][0]) && (count($p->param[0])>$n));69 };70 }71 72 /*73 * Recevant un argument entre quotes (contenant par exemple un nom de filtre)74 * trim_quote enlève les espaces de début et fin *à l'intérieur* des quotes75 * ex : reçoit ' filtre ' (quotes comprises) et renvoie 'filtre'76 */77 function trim_quote($f) {78 $f = trim($f); // c'est pas ça l'important79 $l = strlen($f);80 if ((strpos($f,"'")!== 0) or (strrpos($f,"'")!== $l-1))81 return $f;82 $r = '\''.trim(substr($f, 1, $l-2)).'\'';83 return $r;84 }85 86 // une fonction pour le code de |? (la négation de choixsivide)87 function choix_selon ($test, $sioui, $sinon) {88 return $test ? $sioui : $sinon;89 }90 91 25 define ('V_OUVRE_PHP', "'<'.'" . '?php '); 92 26 define ('V_FERME_PHP', ' ?' . "'.'>'"); 93 27 94 // Appelé uniquement au recalcul pour la compilation 95 // le code renvoyé sera inséré à l'intérieur d'un '...' 96 function compile_appel_macro_session ($p) { 97 $champ = interprete_argument_balise(1, $p); 98 // $champ est entre quotes '' 99 if (!$champ) 100 $champ = "'id_auteur'"; 101 102 if (erreur_argument_macro ('#_SESSION', 'champ', $champ, $p)) 103 return "''"; 104 105 $get_champ = "pipelined_session_get('.\"$champ\".')"; 106 107 // champ sans application de filtre 108 if (!existe_argument_balise(2, $p)) 109 return $get_champ; 110 111 // Application d'un filtre, récupéré entre quotes '' 112 $filtre = trim_quote(interprete_argument_balise (2, $p)); 113 if (erreur_argument_macro ('#_SESSION', 'filtre', $filtre, $p)) 114 return "''"; 115 116 // le filtre est il en fait un opérateur unaire ? 117 if (in_array ($filtre, array ("'!'", "'non'"))) { 118 $unaire = trim ($filtre, "'"); 119 switch ($unaire) { 120 case '!': 121 nobreak; 122 case 'non' : 123 return "(!$get_champ)"; 124 break; 125 } 126 } 127 128 if ($filtre=="'?'") 129 $filtre = "'choix_selon'"; 130 131 // le filtre peut être appelé avec 0, un ou 2 arguments 132 $arg_un = $arg_deux = $virgule_arg_un = $virgule_arg_deux = ''; 133 134 if (existe_argument_balise(3, $p)) { 135 $arg_un = trim_quote(interprete_argument_balise(3, $p)); 136 if ($arg_un and erreur_argument_macro ('#_SESSION', 'arg_un', $arg_un, $p)) 137 return "''"; 138 $virgule_arg_un = ".', '.\"$arg_un\""; 139 }; 140 141 // le filtre est il en fait un opérateur de comparaison ? 142 if (in_array ($filtre, array ("'=='", "'!='", "'<'", "'<='", "'>'", "'>='"))) { 143 $comparateur = trim ($filtre, "'"); 144 145 return "($get_champ $comparateur '.\"$arg_un\".')"; 146 // #_SESSION{nom,==,JLuc} donnera 147 // '<'.'?php echo (pipelined_session_get('."'nom'".') == '."'JLuc'".'); ?'.'>' 148 } 149 150 if (existe_argument_balise(4, $p)) { 151 $arg_deux = trim_quote(interprete_argument_balise(4, $p)); 152 if ($arg_deux and erreur_argument_macro ('#_SESSION', 'arg_deux', $arg_deux, $p)) 153 return "''"; 154 $virgule_arg_deux = ".', '.\"$arg_deux\""; 155 }; 156 157 // produira par exemple ensuite : 158 // '<'.'?php echo appliquer_filtre(pipelined_session_get('."'nom'".'), '."'strlen'".'); ?'.'>' 159 // ou '<'.'?php echo appliquer_filtre( pipelined_session_get('."'nbreste'".'), '."'plus'" .', "'3'" .'); ?'.'>' 160 $r = "appliquer_filtre($get_champ, '.\"$filtre\" $virgule_arg_un $virgule_arg_deux .')"; 161 162 return $r; 163 } 164 165 // 166 // Définition des balises 167 // Attention : on ne peut PAS appliquer de filtre sur ces balises ni les utiliser dans une construction conditionnelle [avant(...) après] 168 // Pour appliquer un filtre, utiliser la syntaxe dédiée avec un argument d'appel de la balise 169 // 170 171 /* 172 * #_SESSION rend l'id_auteur si l'internaute est connecté 173 * #_SESSION(champ) rend la valeur du champ de session étendue de l'internaute connecté 174 * #_SESSION(champ, filtre[, arg1[, arg2]]) applique le filtre au champ de session étendue, avec 0, 1 ou 2 arguments supplémentaires et rend la valeur résultat 175 * 176 */ 177 function balise__SESSION_dist($p) { 178 $p->code = V_OUVRE_PHP . ' echo '. compile_appel_macro_session($p). '; ' . V_FERME_PHP; 179 $p->interdire_scripts = false; 180 // echo "On insèrera l'évaluation du code suivant : <pre>".$p->code."</pre>\n\n"; 181 return $p; 182 } 183 184 /* 185 * #_SESSION_SI teste si l'internaute est authentifié 186 * #_SESSION_SI(champ) teste si le champ de session est non vide 187 * #_SESSION_SI(champ, val) teste si le champ de session est égal à val 188 * C'est un raccourci pour #_SESSION_SI{champ,==,val} 189 * #_SESSION_SI(champ, operateur, val) teste si le champ de session se compare positivement à la valeur spécifiée 190 * selon l'opérateur spécifié, qui peut etre 191 * - soit un comparateur : ==, <, >, >=, <= 192 * - soit un opérateur unaire : ! ou non 193 * - soit un filtre (nom de fonction) recevant 2 arguments : la valeur du champ et val. 194 * C'est alors le retour qui est testé. 195 * Produit par exemple le code suivant : 196 * '<'.'?php if (pipelined_session_get('."'nom'".')) { ?'.'>' 197 */ 198 function balise__SESSION_SI_dist($p) { 199 // Appelé uniquement au recalcul 200 $p->code = V_OUVRE_PHP . 'if ('.compile_appel_macro_session($p).') { ' . V_FERME_PHP; 201 $p->interdire_scripts = false; 202 return $p; 203 } 204 205 function balise__SESSION_SINON_dist($p) { 206 $p->code = V_OUVRE_PHP.' } else { '.V_FERME_PHP; 207 $p->interdire_scripts = false; 208 return $p; 209 } 210 211 function balise__SESSION_FIN_dist($p) { 212 $p->code = V_OUVRE_PHP.' } '.V_FERME_PHP; 213 $p->interdire_scripts = false; 214 return $p; 215 } 216 217 function macrosession_pipe($q="!!! non défini !!!") { 218 if (isset($_GET['debug'])) 219 echo "exec macrosession_pipe($q)<br>"; 220 return $q; 221 } 222 function macrosession_print($a) { 223 if (isset($_GET['debug'])) 224 echo '<pre>'.print_r($a, 1).'</pre>'; 225 return "''"; 226 } 227 228 function compile_appel_macro_autoriser ($p) { 229 if (!existe_argument_balise(1, $p)) { 230 erreur_squelette ("Il faut au moins un argument à la balise #_AUTORISER", $p); 231 return "''"; 232 }; 233 $autorisation = interprete_argument_balise(1, $p); 234 235 if (erreur_argument_macro ('#_AUTORISER_SI', 'autorisation', $autorisation, $p)) 236 return "''"; 237 238 // l'autorisation peut être appelé avec 0, un ou 2 arguments 239 if (!existe_argument_balise(2, $p)) 240 return "autoriser('.\"$autorisation\".')"; 241 242 $type = trim_quote(interprete_argument_balise (2, $p)); 243 if (erreur_argument_macro ("#_AUTORISER_SI{ $autorisation,...}", 'type', $type, $p)) 244 return "''"; 245 246 if (!existe_argument_balise(3, $p)) 247 return "autoriser('.\"$autorisation\".', '.\"$type\".')"; 248 249 $id = trim_quote(interprete_argument_balise (3, $p)); 250 // 251 // 4 possibilités de passer des id calculées à #_AUTORISER_SI : 252 // - Appels directs de #BALISE ou #GET{variable} (non recommandé) 253 // - Passer 'env', 'boucle' et 'url' pour chercher l'id_ associé au type dans l'env reçu, dans la boucle immédiatement englobante ou dans l'url 254 // Ex : #_AUTORISER{modifier,article,env} ou #_AUTORISER{modifier,article,boucle} ou #_AUTORISER{modifier,article,url} 255 // 256 257 // Hacks : décompiler pour reconnaître et gérer #BALISE et #GET{variable} 258 // 259 // 1) Balises genre #ID_ARTICLE 260 // Comme leur source php est inséré dans une chaine il faut l'enchasser entre accolades, et enlever le @ 261 // TODO : assurer une évaluation hors chaine 262 if ((substr ($id,0,11) == '@$Pile[0][\'') 263 and preg_match("/[a-z_]+'\]$/iu", substr ($id, 11))) { // c'était \$ ce qui semble une erreur 264 $id = 'macrosession_pipe({'.substr($id, 1).'})'; 265 } 266 // 2) #GET{variable} 267 // cad : table_valeur($Pile["vars"], (string)'variable', null) 268 // Pour simplifier la réécriture, on ne passe pas par table_valeur 269 elseif (preg_match("/^table_valeur\(\\\$Pile\[\"vars\"\], \(string\)'([a-z_]+)', null\)\s*\$/iu",$id,$matches)) { 270 $id = 'macrosession_pipe({$Pile["vars"]["'.$matches[1].'"]})'; 271 } 272 elseif (erreur_argument_macro ("#_AUTORISER_SI{ $autorisation, $type, ...}", 'id', $id, $p, 'contexte_ok')) 273 return "''"; 274 275 if (!existe_argument_balise(4, $p)) { 276 $id_type = "'id_".substr($type,1); // TODO : utiliser API spip 277 switch($id) { 278 // TODO : gérer ces cas dans la continuité des 1) et 2) plus haut, en affectant $id. Ainsi ce sera compatible avec arguments qui et opt 279 // 3) 280 case "'env'" : 281 if (isset($_GET['debug'])) 282 echo "Avec 'env' : compile appel autoriser($autorisation, $type, \$Pile[0][$id_type])<br>"; 283 $ret = "autoriser('.\"$autorisation\".', '.\"$type\".', '.\"macrosession_pipe({\$Pile[0][$id_type]})\".')"; 284 return $ret; 285 286 case "'boucle'" : 287 if (isset($_GET['debug'])) 288 echo "Avec 'boucle' : compile appel autoriser($autorisation, $type, \$Pile[\$SP][$id_type])<br>"; 289 $ret = "autoriser('.\"$autorisation\".', '.\"$type\".', '.\"macrosession_pipe({\$Pile[\$SP][$id_type]})\".')"; 290 291 return $ret; 292 293 case "'debug'" : 294 $ret = 'time()'; 295 if (isset($_GET['debug'])) { 296 echo "Avec 'debug' : macrosession_print(get_defined_vars())<br>"; 297 $ret = "macrosession_print(get_defined_vars())"; 298 } 299 return $ret; 300 301 // 4) 302 case "'url'" : 303 if (isset($_GET['debug'])) 304 echo "Avec 'url' : compile appel autoriser($autorisation, $type, _request($id_type)<br>"; 305 $ret = "autoriser('.\"$autorisation\".', '.\"$type\".', '.\"macrosession_pipe(_request($id_type))\".')"; 306 return $ret; 307 308 default : 309 return "autoriser('.\"$autorisation\".', '.\"$type\".', '.\"$id\".')"; 310 }; 311 }; 312 313 // ATTENTION : Les appels à #_AUTORISER_SI avec arguments $qui et $opt n'ont pas été testés 314 $qui = trim_quote(interprete_argument_balise (4, $p)); 315 if (erreur_argument_macro ("#_AUTORISER_SI{ $autorisation, $type, $id, ...}", 'qui', $qui, $p)) 316 return "''"; 317 if (!existe_argument_balise(5, $p)) 318 return "autoriser('.\"$autorisation\".', '.\"$type\".', '.\"$id\".')"; 319 320 $opt = trim_quote(interprete_argument_balise (5, $p)); 321 if (erreur_argument_macro ('#_AUTORISER_SI', 'opt', $opt, $p)) 322 return "''"; 323 return "autoriser('.\"$autorisation\".', '.\"$type\".', '.\"$id\".', '.\"$opt\".')"; 324 } 325 326 function balise__AUTORISER_SI_dist($p) { 327 $p->interdire_scripts = false; 328 329 // Appelé uniquement au recalcul 330 $p->code = V_OUVRE_PHP . 'if ('.compile_appel_macro_autoriser ($p).') { ' . V_FERME_PHP; 331 return $p; 332 } 333 334 function balise__AUTORISER_SINON_dist($p) { 335 return balise__SESSION_SINON_dist($p); 336 } 337 338 function balise__AUTORISER_FIN_dist($p) { 339 return balise__SESSION_FIN_dist($p); 340 } 341 342 343 function erreur_argument_macro ($macro, $argument, $val, $p, $contexte_ok='') { 344 if (substr($val, 0, 1) != "'") { 345 if ($contexte_ok) 346 $contexte_ok = "Pour chercher dans les variables d'environnement ou d'url, vous pouvez utiliser 'env', 'boucle', 'url' et aussi '#BALISE' pour les balises reçues par le squelette, mais pas pour les champs de la boucle immédiatement englobante"; 347 erreur_squelette ("L'argument '$argument' de la macro '$macro' ne doit pas être une valeur calculée (".$val."). $contexte_ok", $p); 348 return true; 349 }; 350 return false; 351 } 28 include_spip('inc/macrosession_utils'); 29 include_spip('inc/_session'); 30 include_spip('inc/_autoriser'); -
_plugins_/macrosession/trunk/paquet.xml
r113631 r113654 2 2 prefix="macrosession" 3 3 categorie="outil" 4 version="0.1 0.0"4 version="0.11.0" 5 5 etat="test" 6 6 compatibilite="[2.1.0;3.2.*]" -
_plugins_/macrosession/trunk/plugin.xml
r113631 r113654 5 5 <auteur>JLuc</auteur> 6 6 <licence>GPL</licence> 7 <version>0.1 0.0</version>7 <version>0.11.0</version> 8 8 <etat>test</etat> 9 9 <description> 10 10 Macros SPIP #_SESSION, #_SESSION_SI, #_AUTORISER_SI, etc 11 pour accéder aux données de la session de la _session courant et les tester efficacement11 pour accéder aux données de la session de la _session courant 12 12 ou à des données de sessions d'autre origine que la session spip, 13 et les tester e t testerles autorisations13 et les tester efficacement ainsi que les autorisations 14 14 sans multiplier les caches sessionnés 15 15 </description>
Note: See TracChangeset
for help on using the changeset viewer.