[SPIP] ~v3.0.20-->v3.0.25
[lhc/web/clavette_www.git] / www / ecrire / public / sandbox.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2016 *
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 if (!defined('_ECRIRE_INC_VERSION')) return;
15
16 /**
17 * Composer le code d'execution d'un texte
18 * en principe juste un echappement de guillemets
19 * sauf si on veut aussi echapper et interdire les scripts serveurs
20 * dans les squelette
21 *
22 * @param string $texte
23 * @param string $code
24 * @param string $arglist
25 * @param Object $p
26 * @return string
27 */
28 function sandbox_composer_texte($texte, &$p){
29 $code = "'".str_replace(array("\\","'"),array("\\\\","\\'"), $texte)."'";
30 return $code;
31 }
32
33
34 /**
35 * Composer le code d'execution d'un filtre
36 *
37 * @param string $fonc
38 * @param string $code
39 * @param string $arglist
40 * @param Object $p
41 * @return string
42 */
43 function sandbox_composer_filtre($fonc, $code, $arglist, &$p){
44 if (isset($GLOBALS['spip_matrice'][$fonc])) {
45 $code = "filtrer('$fonc',$code$arglist)";
46 }
47
48 // le filtre est defini sous forme de fonction ou de methode
49 // par ex. dans inc_texte, inc_filtres ou mes_fonctions
50 elseif ($f = chercher_filtre($fonc)) {
51 // cas particulier : le filtre |set doit acceder a la $Pile
52 // proto: filtre_set(&$Pile, $val, $args...)
53 if (strpbrk($f, ':')) { // Class::method
54 $refl = new ReflectionMethod($f);
55 } else {
56 $refl = new ReflectionFunction($f);
57 }
58 $refs = $refl->getParameters();
59 if (isset($refs[0]) AND $refs[0]->name == 'Pile') {
60 $code = "$f(\$Pile,$code$arglist)";
61 }
62 else {
63 $code = "$f($code$arglist)";
64 }
65 }
66 // le filtre n'existe pas,
67 // on le notifie
68 else erreur_squelette(array('zbug_erreur_filtre', array('filtre'=> texte_script($fonc))), $p);
69
70 return $code;
71 }
72
73 // Calculer un <INCLURE(xx.php)>
74 // La constante ci-dessous donne le code general quand il s'agit d'un script.
75 define('CODE_INCLURE_SCRIPT', 'if (!($path = %s) OR !is_readable($path))
76 erreur_squelette(array("fichier_introuvable", array("fichier" => "%s")), array(%s));
77 else {
78 $contexte_inclus = %s;
79 include $path;
80 }
81 '
82 );
83
84 /**
85 * Composer le code d'inclusion PHP
86 *
87 * @param string $fichier
88 * @param Object $p
89 * @param array $_contexte
90 * @return string
91 */
92 function sandbox_composer_inclure_php($fichier, &$p, $_contexte){
93 $compil = texte_script(memoriser_contexte_compil($p));
94 // si inexistant, on essaiera a l'execution
95 if ($path = find_in_path($fichier))
96 $path = "\"$path\"";
97 else $path = "find_in_path(\"$fichier\")";
98
99 return sprintf(CODE_INCLURE_SCRIPT, $path, $fichier, $compil, $_contexte);
100 }
101
102 /**
103 * Composer le code se securisation anti script
104 *
105 * @param string $code
106 * @param Object $p
107 * @return string
108 */
109 function sandbox_composer_interdire_scripts($code, &$p){
110 // Securite
111 if ($p->interdire_scripts
112 AND $p->etoile != '**') {
113 if (!preg_match("/^sinon[(](.*),'([^']*)'[)]$/", $code, $r))
114 $code = "interdire_scripts($code)";
115 else {
116 $code = interdire_scripts($r[2]);
117 $code = "sinon(interdire_scripts($r[1]),'$code')";
118 }
119 }
120 return $code;
121 }
122
123
124 /**
125 * Appliquer des filtres sur un squelette complet
126 * la fonction peut plusieurs tableaux de filtres a partir du 3eme argument
127 * qui seront appliques dans l'ordre
128 *
129 * @param array $skel
130 * @param string $corps
131 * @param array $filtres
132 * @param array ...
133 * @return mixed|string
134 */
135 function sandbox_filtrer_squelette($skel, $corps, $filtres){
136 $series_filtres = func_get_args();
137 array_shift($series_filtres);// skel
138 array_shift($series_filtres);// corps
139
140 // proteger les <INCLUDE> et tous les morceaux de php licites
141 if ($skel['process_ins'] == 'php')
142 $corps = preg_replace_callback(',<[?](\s|php|=).*[?]>,UimsS','echapper_php_callback', $corps);
143
144 // recuperer les couples de remplacement
145 $replace = echapper_php_callback();
146
147 foreach($series_filtres as $filtres){
148 if (count($filtres))
149 foreach ($filtres as $filtre) {
150 if ($filtre AND $f = chercher_filtre($filtre))
151 $corps = $f($corps);
152 }
153 }
154
155 // restaurer les echappements
156 return str_replace($replace[0],$replace[1],$corps);
157 }
158
159
160 // http://doc.spip.org/@echapper_php_callback
161 function echapper_php_callback($r=null) {
162 static $src = array();
163 static $dst = array();
164
165 // si on recoit un tableau, on est en mode echappement
166 // on enregistre le code a echapper dans dst, et le code echappe dans src
167 if (is_array($r)) {
168 $dst[] = $r[0];
169 return $src[] = '___'.md5($r[0]).'___';
170 }
171
172 // si on recoit pas un tableau, on renvoit les couples de substitution
173 // et on RAZ les remplacements
174 $r = array($src,$dst);
175 $src = $dst = array();
176 return $r;
177 }