[SPIP] +2.1.12
[velocampus/web/www.git] / www / plugins / auto / couteau_suisse / couteau_suisse / cout_utils.php
1 <?php
2 #-----------------------------------------------------#
3 # Plugin : Couteau Suisse - Licence : GPL #
4 # Auteur : Patrice Vanneufville, 2006 #
5 # Contact : patrice¡.!vanneufville¡@!laposte¡.!net #
6 # Infos : http://www.spip-contrib.net/?article2166 #
7 #-----------------------------------------------------#
8 # Fichier contenant les fonctions utilisees pendant #
9 # la configuration du plugin #
10 #-----------------------------------------------------#
11 if(!defined("_ECRIRE_INC_VERSION")) return;
12
13 cs_log("chargement de cout_utils.php");
14 $GLOBALS['cs_utils']++;
15
16 // $outils : tableau ultra complet avec tout ce qu'il faut savoir sur chaque outil
17 // $cs_variables : tableau de toutes les variables que les outils peuvent utiliser et manipuler
18 // - ces deux tableaux ne sont remplis qu'une seule fois, lors d'une initialisation totale
19 // les hits ordinaires ne se servent que des metas, non des fichiers.
20 // - l'initialisation totale insere en premier lieu config_outils.php
21 global $outils, $cs_variables;
22 $cs_variables = $outils = array();
23 // liste des types de variable
24 $cs_variables['_chaines'] = $cs_variables['_nombres'] = array();
25 define('_format_CHAINE', 10);
26 define('_format_NOMBRE', 20);
27
28 /*************/
29 /* FONCTIONS */
30 /*************/
31
32 // ajoute un outil a $outils;
33 function add_outil($tableau) {
34 global $outils;
35 // sert encore a qqchose ?
36 static $index; $index = isset($index)?$index + 10:0;
37 $tableau['index'] = $index;
38 // grave erreur si pas d'id
39 if(!isset($tableau['id'])) { $tableau['id']='erreur'.count($outils); $tableau['nom'] = _T('couteauprive:erreur_id'); }
40 // surcharges perso. Ex : $GLOBALS['mes_outils']['supprimer_numero_perso']
41 // (methode par variable globale depreciee)
42 if(isset($GLOBALS['mes_outils'][$perso = $tableau['id'].'_perso']) && is_array($GLOBALS['mes_outils'][$perso])) {
43 // ici pour compatibilite anterieure
44 $tableau = array_merge($tableau, $GLOBALS['mes_outils'][$perso]);
45 unset($GLOBALS['mes_outils'][$perso]);
46 $tableau['surcharge'] = 1;
47 // surcharges perso. Ex : function supprimer_numero_surcharger_outil($tab) { return $tab; }
48 } elseif(function_exists($perso = $tableau['id'].'_surcharger_outil')) {
49 if(is_array($perso = $perso($tableau))) $tableau = $perso;
50 $tableau['surcharge'] = 1;
51 }
52 // desactiver l'outil si les fichiers distants ne sont pas permis
53 if(defined('_CS_PAS_D_OUTIL_DISTANT') && isset($tableau['fichiers_distants']))
54 $tableau['version-max'] = '0';
55 foreach($tableau as $i=>$v) {
56 // parametres multiples separes par des virgules
57 if(strpos($i,',')!==false) {
58 $a = explode(',', $i);
59 foreach($a as $b) $tableau[trim($b)] = $v;
60 unset($tableau[$i]);
61 }
62 // liste des fichiers distants eventuels
63 if(strncmp('distant', $i, 7)==0) $tableau['fichiers_distants'][] = $i;
64 }
65 $outils[$tableau['id']] = $tableau;
66 }
67
68 // ajoute une variable a $cs_variables et fabrique une liste des chaines et des nombres
69 function add_variable($tableau) {
70 global $cs_variables;
71 if(isset($tableau['nom'])) $nom = $tableau['nom']; else return;
72 if(isset($cs_variables[$nom])) {
73 cs_log("Variable $nom dupliquee ??");
74 return;
75 }
76 if(isset($tableau['check'])) $tableau['format'] = _format_NOMBRE;
77 // code '%s' par defaut si aucun code n'est defini
78 $test=isset($tableau['code']);
79 if(!$test) foreach(array_keys($tableau) as $key)
80 if($test=(strncmp('code:', $key, 5)==0)) break;
81 if(!$test) $tableau['code'] = '%s';
82 // enregistrement
83 $cs_variables[$nom] = $tableau;
84 // on fabrique ici une liste des chaines et une liste des nombres
85 if(@$tableau['format']==_format_NOMBRE) $cs_variables['_nombres'][] = $nom;
86 elseif(@$tableau['format']==_format_CHAINE) $cs_variables['_chaines'][] = $nom;
87 }
88 // idem, arguments variables
89 function add_variables() { foreach(func_get_args() as $t) add_variable($t); }
90
91 // les 3 fonction suivantes decodent les fichiers de configuration xml
92 // et les convertissent (pour l'instant car experimental) dans l'ancien format
93 function add_outils_xml($f) {
94 include_spip('inc/xml');
95 $arbre = spip_xml_load($f);
96 if(isset($arbre['variable'])) foreach($arbre['variable'] as $a)
97 add_variable(parse_variable_xml($a));
98 if(isset($arbre['outil'])) foreach($arbre['outil'] as $a) {
99 $out = parse_outil_xml($a);
100 if(isset($out['nom']) && is_string($out['nom']) && strlen($out['nom']) && !preg_match(',couteau_suisse/outils/,', $f))
101 $outil['nom'] = "<i>$out[nom]</i>";
102 add_outil($out);
103 }
104 }
105 // Attention : conversion incomplete. ajouter les tests au fur et a mesure
106 function parse_variable_xml(&$arbre) {
107 $var = array();
108 if(isset($arbre['id'])) $var['nom'] = $arbre['id'][0];
109 if(isset($arbre['format'])) $var['format'] = $arbre['format'][0]=='string'?_format_CHAINE:_format_NOMBRE;
110 if(isset($arbre['radio'])) {
111 $temp = &$arbre['radio'][0];
112 if(isset($temp['par_ligne'])) $var['radio/ligne'] = $temp['par_ligne'][0];
113 foreach($temp['item'] as $a) $var['radio'][$a['valeur'][0]] = $a['label'][0];
114 }
115 if(isset($arbre['label'])) $var['label'] = $arbre['label'][0];
116 if(isset($arbre['defaut_php'])) $var['defaut'] = $arbre['defaut_php'][0];
117 if(isset($arbre['code'])) foreach($arbre['code'] as $a) {
118 $temp = isset($a['condition_php'])?'code:'.$a['condition_php'][0]:'code';
119 if(isset($a['script_php'])) $var[$temp] = str_replace('\n', "\n", $a['script_php'][0]);
120 }
121 return $var;
122 }
123 // Attention : conversion incomplete. ajouter les tests au fur et a mesure
124 function parse_outil_xml(&$arbre) {
125 $out = array();
126 foreach(array('id','nom','description','categorie','auteur') as $n)
127 if(isset($arbre[$n])) $out[$n] = $arbre[$n][0];
128 if(isset($arbre['code'])) foreach($arbre['code'] as $a) {
129 $temp = isset($a['type'])?'code:'.$a['type'][0]:'code';
130 if(isset($a['script_php'])) $out[$temp] = str_replace('\n', "\n", $a['script_php'][0]);
131 }
132 if(isset($arbre['pipeline'])) foreach($arbre['pipeline'] as $a) {
133 if(isset($a['fonction'])) {
134 $temp = isset($a['nom'])?'pipeline:'.$a['nom'][0]:'pipeline';
135 $out[$temp] = $a['fonction'][0];
136 } elseif(isset($a['script_php'])) {
137 $temp = isset($a['nom'])?'pipelinecode:'.$a['nom'][0]:'pipelinecode';
138 $out[$temp] = $a['script_php'][0];
139 }
140 }
141 if(isset($arbre['version'])) {
142 $temp = &$arbre['version'][0];
143 if(isset($temp['spip_min'])) $out['version-min'] = $temp['spip_min'][0];
144 if(isset($temp['spip_max'])) $out['version-max'] = $temp['spip_max'][0];
145 }
146 return $out;
147 }
148
149 // retourne la valeur 'defaut' (format php) de la variable apres compilation du code
150 // le resultat comporte des guillemets si c'est une chaine
151 function cs_get_defaut($variable) {
152 global $cs_variables;
153 // si la variable n'est pas declaree, serieux pb dans config_outils !
154 if(!isset($cs_variables[$variable])) {
155 spip_log("Erreur - variable '$variable' non declaree dans config_outils.php !");
156 return false;
157 }
158 $variable = &$cs_variables[$variable];
159 if(isset($variable['externe'])) $variable['defaut'] = $variable['externe'];
160 $defaut = !isset($variable['defaut'])?'':$variable['defaut'];
161 if(function_exists($f='initialiser_variable_'.$variable['nom']))
162 $defaut = $f($defaut);
163 if(!strlen($defaut)) $defaut = "''";
164 if(@$variable['format']==_format_NOMBRE) $defaut = "intval($defaut)";
165 elseif(@$variable['format']==_format_CHAINE) $defaut = "strval($defaut)";
166 //cs_log("cs_get_defaut() - \$defaut[{$variable['nom']}] = $defaut");
167 eval("\$defaut=$defaut;");
168 $defaut2 = cs_php_format($defaut, @$variable['format']!=_format_NOMBRE, true);
169 //cs_log(" -- cs_get_defaut() - \$defaut[{$variable['nom']}] est devenu : $defaut2");
170 return $defaut2;
171 }
172
173 // $type ici est egal a 'spip_options', 'options' ou 'fonctions'
174 function ecrire_fichier_en_tmp(&$infos_fichiers, $type) {
175 $code = '';
176 if(isset($infos_fichiers['inc_'.$type]))
177 foreach ($infos_fichiers['inc_'.$type] as $inc) $code .= "include_spip('outils/$inc');\n";
178 if(isset($infos_fichiers['code_'.$type]))
179 foreach ($infos_fichiers['code_'.$type] as $inline) $code .= $inline."\n";
180 // on optimise avant...
181 $code = str_replace(array('intval("")',"intval('')"), '0', $code);
182 $code = str_replace("\n".'if(strlen($foo="")) ',"\n\$foo=''; //", $code);
183 // ... en avant le code !
184 $fichier_dest = _DIR_CS_TMP . "mes_$type.php";
185 if(defined('_LOG_CS')) cs_log("ecrire_fichier_en_tmp($type) : lgr=".strlen($code))." pour $fichier_dest";
186 if(!ecrire_fichier($fichier_dest, '<'."?php\n// Code d'inclusion pour le plugin 'Couteau Suisse'\n++\$GLOBALS['cs_$type'];\n$code?".'>', true))
187 cs_log("ERREUR ECRITURE : $fichier_dest");
188 }
189
190 function set_cs_metas_pipelines(&$infos_pipelines) {
191 global $cs_metas_pipelines;
192 $controle='';
193 foreach($infos_pipelines as $pipe=>$infos) {
194 $code = "\n# Copie du code utilise en eval() pour le pipeline '$pipe(\$flux)'\n";
195 // compilation des differentes facon d'utiliser un pipeline
196 if(is_array(@$infos['inclure'])) foreach ($infos['inclure'] as $inc) {
197 $code .= "include_spip('$inc');\n";
198 }
199 if(is_array(@$infos['inline'])) foreach ($infos['inline'] as $inc) $code .= "$inc\n";
200 if(is_array(@$infos['fonction'])) foreach ($infos['fonction'] as $fonc)
201 $code .= "function_exists('$fonc')?\$flux=$fonc(\$flux):cs_deferr('$fonc');\n";
202 $controle .= $cs_metas_pipelines[$pipe] = $code;
203 }
204 $nb = count($infos_pipelines);
205 if(defined('_LOG_CS')) cs_log("$nb pipeline(s) actif(s) : strlen=".strlen($controle));
206 ecrire_fichier(_DIR_CS_TMP . "pipelines.php",
207 '<'."?php\n// Code de controle pour le plugin 'Couteau Suisse' : $nb pipeline(s) actif(s)\n{$controle}?".'>');
208 }
209
210 // est-ce que $pipe est un pipeline ?
211 function is_pipeline_outil($pipe, &$set_pipe) {
212 if($ok=(strncmp('pipeline:', $pipe, 9)==0)) $set_pipe = trim(substr($pipe, 9));
213 return $ok;
214 }
215 // est-ce que $pipe est un pipeline inline?
216 function is_pipeline_outil_inline($pipe, &$set_pipe) {
217 if($ok=(strncmp('pipelinecode:', $pipe, 13)==0)) $set_pipe = trim(substr($pipe, 13));
218 return $ok;
219 }
220
221 // est-ce que $traitement est un traitement ?
222 function is_traitements_outil($traitement, $fonction, &$set_traitements_utilises) {
223 if(strncmp('traitement', $traitement, 10)!=0) return false;
224 if($ok = preg_match(',^traitement:([A-Z_]+)/?([a-z]+)?:(pre|post)_([a-zA-Z0-9_-]+)$,', $traitement, $t)) {
225 if(!strlen($t[2])) $t[2] = 0;
226 $set_traitements_utilises[$t[1]][$t[2]][$t[4]][$t[3]][] = $fonction;
227 } elseif($ok = preg_match(',^traitement:([A-Z]+)$,', $traitement, $t))
228 $set_traitements_utilises[$t[1]][0][0][] = $fonction;
229 return $ok;
230 }
231
232 // lire un fichier php et retirer si possible les balises ?php
233 function cs_lire_fichier_php($file) {
234 $file=find_in_path($file);
235 if($file && lire_fichier($file, $php)) {
236 if(preg_match(',^<\?php(.*)?\?>$,msi', trim($php), $regs)) return trim($regs[1]);
237 return "\n"."?>\n".trim($php)."\n<"."?php\n";
238 }
239 return false;
240 }
241
242 // retourne les raccourcis ajoutes par l'outil, s'il est actif
243 function cs_aide_raccourci($id) {
244 global $outils;
245 // stockage de la liste des fonctions par pipeline, si l'outil est actif...
246 if($outils[$id]['actif']) {
247 include_spip('outils/'.$id);
248 if(function_exists($f = $id.'_raccourcis')) return $f();
249 if(!preg_match(',:aide(?:<|$),', $x = _T("couteauprive:$id:aide") )) return $x;
250 }
251 return '';
252 }
253
254 // retourne la liste des raccourcis disponibles
255 function cs_aide_raccourcis() {
256 global $outils;
257 $aide = array();
258 foreach ($outils as $outil)
259 if($a = cs_aide_raccourci($outil['id'])) $aide[] = '<li style="margin: 0.7em 0 0 0;">&bull; ' . $a . '</li>';
260 if(!count($aide)) return '';
261 // remplacement des constantes de forme @_CS_XXXX@
262 $aide = preg_replace_callback(',@(_CS_[a-zA-Z0-9_]+)@,',
263 create_function('$matches','return defined($matches[1])?constant($matches[1]):"";'), join("\n", $aide));
264 return '<p><b>' . _T('couteauprive:raccourcis') . '</b></p><ul class="cs_raccourcis">' . $aide . '</ul>';
265 }
266
267 // retourne une aide concernant les pipelines utilises par l'outil
268 function cs_aide_pipelines($outils_affiches_actifs) {
269 global $cs_metas_pipelines, $outils, $metas_outils;
270 $aide = array();
271 $keys = array_keys($cs_metas_pipelines); sort($keys);
272 foreach ($keys as $pipe) {
273 // stockage de la liste des pipelines et du nombre d'outils actifs concernes
274 $nb=0; foreach($outils as $outil) if($outil['actif'] && (isset($outil['pipeline:'.$pipe]) || isset($outil['pipelinecode:'.$pipe]))) $nb++;
275 if(($len=strlen($pipe))>25) $pipe = substr($pipe, 0, 8).'...'.substr($pipe, $len - 14);
276 if($nb) $aide[] = _T('couteauprive:outil_nb'.($nb>1?'s':''), array('pipe'=>$pipe, 'nb'=>$nb));
277 }
278 // nombre d'outils actifs / interdits par les autorisations (hors versionnage SPIP)
279 $nb = $ca2 = 0;
280 foreach($metas_outils as $o) if(isset($o['actif']) && $o['actif']) $nb++;
281 foreach($outils as $o) if(isset($o['interdit']) && $o['interdit'] && !cs_version_erreur($o)) $ca2++;
282 // nombre d'outils caches de la configuration par l'utilisateur
283 $ca1 = isset($GLOBALS['meta']['tweaks_caches'])?count(unserialize($GLOBALS['meta']['tweaks_caches'])):0;
284 return '<p><b>' . _T('couteauprive:outils_actifs') . "</b> $nb"
285 . '<br /><b>' . _T('couteauprive:outils_caches') . "</b> $ca1"
286 . (!$ca2?'':('<br /><b>' . _T('couteauprive:outils_non_parametrables') . "</b> $ca2"))
287 .'<br /><b>' . _T('couteauprive:pipelines') . '</b> '.count($aide)
288 . '</p><p style="font-size:80%; margin-left:0.4em;">' . join("<br />", $aide) . '</p>';
289 }
290
291 // sauve la configuration dans un fichier tmp/couteau-suisse/config.php
292 function cs_sauve_configuration() {
293 global $outils, $metas_vars;
294 $metas = $metas_actifs = $variables = $lesoutils = $actifs = array();
295 foreach($outils as $t) {
296 $lesoutils[] = "\t// ".$t['nom']."\n\t'".$t['id']."' => '".join('|', $t['variables']) . "'";
297 if($t['actif']) {
298 $actifs[] = $t['id'];
299 $variables = array_merge($variables, $t['variables']);
300 }
301 }
302 foreach($metas_vars as $i => $v) if($i!='_chaines' && $i!='_nombres') {
303 $metas[] = $temp = "\t'$i' => " . cs_php_format($v, in_array($i, $metas_vars['_chaines']));
304 if(in_array($i, $variables)) $metas_actifs[] = $temp;
305 }
306 $sauve = "// Tous les outils et leurs variables\n\$liste_outils = array(\n" . join(",\n", $lesoutils) . "\n);\n"
307 . "\n// Outils actifs\n\$outils_actifs =\n\t'" . join('|', $actifs) . "';\n"
308 . "\n// Variables actives\n\$variables_actives =\n\t'" . join('|', $variables) . "';\n"
309 . "\n// Valeurs validees en metas\n\$valeurs_validees = array(\n" . join(",\n", $metas) . "\n);\n";
310
311 include_spip('inc/charset');
312 $nom_pack = _T('couteauprive:pack_actuel', array('date'=>cs_date()));
313 $fct_pack = md5($nom_pack.time());
314 $sauve .= $temp = "\n######## "._T('couteauprive:pack_actuel_titre')." #########\n\n// "
315 . filtrer_entites(_T('couteauprive:pack_actuel_avert')."\n\n"
316 . "\$GLOBALS['cs_installer']['$nom_pack'] =\t'cs_$fct_pack';\nfunction cs_$fct_pack() { return array(\n\t// "
317 . _T('couteauprive:pack_outils_defaut')."\n"
318 . "\t'outils' =>\n\t\t'".join(",\n\t\t", $actifs)."',\n"
319 . "\n\t// "._T('couteauprive:pack_variables_defaut')."\n")
320 . "\t'variables' => array(\n\t" . join(",\n\t", $metas_actifs) . "\n\t)\n);} # $nom_pack #\n";
321
322 ecrire_fichier(_DIR_CS_TMP.'config.php', '<'."?php\n// Configuration de controle pour le plugin 'Couteau Suisse'\n\n$sauve?".'>');
323 if(_request('cmd')=='pack' || (_request('cmd')=='descrip' && _request('outil')=='pack')) $GLOBALS['cs_pack_actuel'] = $temp;
324 }
325
326 function cs_autorisation_alias(&$tab, $autoriser) {
327 static $ok = array();
328 if(isset($ok[$autoriser])) return;
329 if(function_exists($f='autoriser_'.$autoriser.'_configurer') || function_exists($f.='_dist')) {
330 $g = str_replace('_','',objet_type($autoriser));
331 if($g != $autoriser) {
332 $tab[] = "function autoriser_{$g}_configurer(\$faire,\$type,\$id,\$qui,\$opt) {\n\treturn function_exists('$f')\n\t?$f(\$faire, \$type, \$id, \$qui, \$opt):true; }";
333 $ok[$autoriser] = 1;
334 }
335 }
336 }
337
338 // cree les tableaux $infos_pipelines et $infos_fichiers, puis initialise $cs_metas_pipelines
339 function cs_initialise_includes($count_metas_outils) {
340 global $outils, $cs_metas_pipelines;
341 // toutes les infos sur les fichiers mes_options/mes_fonctions et sur les pipelines;
342 $infos_pipelines = $infos_fichiers =
343 // liste des traitements utilises
344 $traitements_utilises =
345 // variables temporaires
346 $temp_js_html = $temp_css_html = $temp_css = $temp_js = $temp_jq = $temp_jq_init = $temp_filtre_imprimer = array();
347 @define('_CS_HIT_EXTERNE', 1500);
348 // inclure d'office outils/couteau_suisse_fonctions.php
349 if($temp=cs_lire_fichier_php("outils/cout_fonctions.php"))
350 $infos_fichiers['code_fonctions'][] = $temp;
351 // variable de verification
352 $infos_fichiers['code_options'][] = "\$GLOBALS['cs_verif']=$count_metas_outils;";
353 // horrible hack sur les autorisations SPIP 3.0 (en attendant la correction !!)
354 if(defined('_SPIP30000')) {
355 cs_autorisation_alias($infos_fichiers['code_spip_options'], 'plugins');
356 cs_autorisation_alias($infos_fichiers['code_spip_options'], 'cs');
357 global $cs_variables;
358 for($i=2; $i<count($tmp=array_keys($cs_variables)); $i++)
359 cs_autorisation_alias($infos_fichiers['code_spip_options'], 'variable_'.$tmp[$i]);
360 foreach ($outils as $i=>$outil) {
361 cs_autorisation_alias($infos_fichiers['code_spip_options'], 'outil_'.$outil['id']);
362 if(isset($outil['categorie']))
363 cs_autorisation_alias($infos_fichiers['code_spip_options'], 'categorie_'.$outil['categorie']);
364 }
365 cs_autorisation_alias($infos_fichiers['code_spip_options'], 'categorie_divers');
366 }
367 // parcours de tous les outils
368 foreach ($outils as $i=>$outil) {
369 $inc = $outil['id'];
370 // stockage de la liste des fonctions par pipeline
371 if($outil['actif']) {
372 $pipe2 = '';
373 foreach ($outil as $pipe=>$fonc) {
374 if(is_pipeline_outil($pipe, $pipe2)) {
375 // module a inclure
376 if(find_in_path("outils/$inc.php"))
377 $infos_pipelines[$pipe2]['inclure'][] = "outils/$inc";
378 if(isset($outil['distant_pipelines']) && find_in_path("lib/$inc/distant_".basename($outil['distant_pipelines'])))
379 $infos_pipelines[$pipe2]['inclure'][] = "lib/$inc/distant_".basename($outil['distant_pipelines'],'.php');
380 // fonction a appeler
381 $infos_pipelines[$pipe2]['fonction'][] = $fonc;
382 } elseif(is_pipeline_outil_inline($pipe, $pipe2)) {
383 // code inline
384 $infos_pipelines[$pipe2]['inline'][] = cs_optimise_if(cs_parse_code_js($fonc));
385 } elseif(is_traitements_outil($pipe, $fonc, $traitements_utilises)) {
386 // rien a faire : $traitements_utilises est rempli par is_traitements_outil()
387 }
388 }
389 // recherche des fichiers .css, .css.html, .js et .js.html eventuellement present dans outils/
390 foreach(array('css', 'js') as $f) {
391 if($file=find_in_path("outils/$inc.$f")) { lire_fichier($file, $ff); ${'temp_'.$f}[] = $ff; }
392 // en fait on ne peut pas compiler ici car les balises vont devoir etre traitees et les traitements ne sont pas encore dispo !
393 // le code est mis de cote. il sera compile plus tard au moment du pipeline grace a cs_compile_header()
394 if($file=find_in_path("outils/$inc.$f.html")) { lire_fichier($file, $ff); ${'temp_'.$f.'_html'}[] = $ff; }
395 // TODO : librairies distantes placees dans lib/
396 /* if(isset($outil['distant_'.$type]) && ($file=find_in_path("lib/$inc/distant_{$f}_".basename($outil["distant_$f"])))) etc. */
397 }
398 // recherche d'un code inline eventuellement propose
399 if(isset($outil['code:spip_options'])) $infos_fichiers['code_spip_options'][] = $outil['code:spip_options'];
400 if(isset($outil['code:options'])) $infos_fichiers['code_options'][] = $outil['code:options'];
401 if(isset($outil['code:fonctions'])) $infos_fichiers['code_fonctions'][] = $outil['code:fonctions'];
402 if(isset($outil['code:css'])) $temp_css[] = cs_optimise_if(cs_parse_code_js($outil['code:css']));
403 if(isset($outil['code:js'])) $temp_js[] = cs_optimise_if(cs_parse_code_js($outil['code:js']));
404 if(isset($outil['code:jq_init'])) $temp_jq_init[] = cs_optimise_if(cs_parse_code_js($outil['code:jq_init']));
405 if(isset($outil['code:jq'])) $temp_jq[] = cs_optimise_if(cs_parse_code_js($outil['code:jq']));
406 // recherche d'un fichier monoutil_options.php ou monoutil_fonctions.php pour l'inserer dans le code
407 // TODO : librairies distantes placees dans lib/
408 foreach(array('options', 'fonctions') as $f) {
409 if($temp=cs_lire_fichier_php("outils/{$inc}_{$f}.php")) $infos_fichiers['code_'.$f][] = $temp;
410 /* if(isset($outil['distant_'.$f]) && find_in_path("lib/$inc/distant_{$f}_".basename($outil["distant_$f"])))
411 if($temp=cs_lire_fichier_php("lib/$inc/distant_{$f}_$outil[distant_$f].php"))
412 $infos_fichiers['code_'.$f][] = $temp;
413 */ }
414 } else foreach(array('pre_description_outil', 'fichier_distant') as $p) {
415 // exceptions pour les outils inactifs
416 if(isset($outil[$t='pipelinecode:'.$p]))
417 $infos_pipelines[$p]['inline'][] = cs_optimise_if(cs_parse_code_js($outil[$t]));
418 if(isset($outil[$t='pipeline:'.$p])) {
419 $infos_pipelines[$p]['inclure'][] = "outils/$inc";
420 $infos_pipelines[$p]['fonction'][] = $outil[$t];
421 }
422 }
423 }
424 // insertion du css pour la BarreTypo
425 if(isset($infos_pipelines['bt_toolbox']) && defined('_DIR_PLUGIN_BARRETYPOENRICHIE'))
426 $temp_css[] = 'span.cs_BT {background-color:#FFDDAA; font-weight:bold; border:1px outset #CCCC99; padding:0.2em 0.3em;}
427 span.cs_BTg {font-size:140%; padding:0 0.3em;}';
428 // prise en compte des css.html et js.html qu'il faudra compiler plus tard
429 if(count($temp_css_html)){
430 $temp_css[] = '<cs_html>'.join("\n", $temp_css_html).'</cs_html>';
431 unset($temp_css_html);
432 }
433 if(count($temp_js_html)){
434 $temp_js[] = '<cs_html>'.join("\n", $temp_js_html).'</cs_html>';
435 unset($temp_js_html);
436 }
437 // concatenation des css inline, js inline et filtres trouves
438 if(strlen(trim($temp_css = join("\n", $temp_css)))) {
439 if(function_exists('compacte_css')) $temp_css = compacte_css($temp_css);
440 if(strlen($temp_css)>_CS_HIT_EXTERNE) {
441 // hit externe
442 $cs_metas_pipelines['header_css_ext'] = $temp_css;
443 } else {
444 // css inline
445 $temp = array("<style type=\"text/css\">\n$temp_css\n</style>");
446 if(is_array($cs_metas_pipelines['header_css'])) $temp = array_merge($temp, $cs_metas_pipelines['header_css']);
447 $cs_metas_pipelines['header_css'] = $cs_metas_pipelines['header_css_prive'] = join("\n", $temp);
448 }
449 unset($temp_css);
450 }
451 if(count($temp_jq_init)) {
452 $temp_js[] = "var cs_init = function() {\n\t".join("\n\t", $temp_jq_init)."\n}\nif(typeof onAjaxLoad=='function') onAjaxLoad(cs_init);";
453 $temp_jq[] = "cs_init.apply(document);";
454 unset($temp_jq_init);
455 }
456 $temp_jq = count($temp_jq)?"\njQuery(document).ready(function(){\n\t".join("\n\t", $temp_jq)."\n});":'';
457 $temp_js[] = "if(window.jQuery) {\nvar cs_sel_jQuery=typeof jQuery(document).selector=='undefined'?'@':'';\nvar cs_CookiePlugin=\"<cs_html>#CHEMIN{javascript/jquery.cookie.js}</cs_html>\";$temp_jq\n}";
458 unset($temp_jq);
459 if(count($temp_js)) {
460 $temp_js = "var cs_prive=window.location.pathname.match(/\\/ecrire\\/\$/)!=null;
461 jQuery.fn.cs_todo=function(){return this.not('.cs_done').addClass('cs_done');};\n" . join("\n", $temp_js);
462 if(function_exists('compacte_js')) $temp_js = compacte_js($temp_js);
463 if(strlen($temp_js)>_CS_HIT_EXTERNE) {
464 // hit externe
465 $cs_metas_pipelines['header_js_ext'] = $temp_js;
466 } else {
467 // js inline
468 $temp = array("<script type=\"text/javascript\"><!--\n$temp_js\n// --></script>\n");
469 if(is_array($cs_metas_pipelines['header_js'])) $temp = array_merge($temp, $cs_metas_pipelines['header_js']);
470 $cs_metas_pipelines['header_js'] = $cs_metas_pipelines['header_js_prive'] = join("\n", $temp);
471 }
472 unset($temp_js);
473 }
474 // effacement du repertoire temporaire de controle
475 if(@file_exists(_DIR_CS_TMP) && ($handle = @opendir(_DIR_CS_TMP))) {
476 while (($fichier = @readdir($handle)) !== false)
477 if($fichier[0] != '.') supprimer_fichier(_DIR_CS_TMP.$fichier);
478 closedir($handle);
479 } else spip_log('Erreur - cs_initialise_includes() : '._DIR_CS_TMP.' introuvable !');
480 // join final...
481 foreach(array('css', 'js') as $type) {
482 $f = 'header_'.$type;
483 if(isset($cs_metas_pipelines[$temp = $f.'_ext'])) {
484 $fichier_dest = _DIR_CS_TMP . "header.$type.html";
485 if(!ecrire_fichier($fichier_dest, $cs_metas_pipelines[$temp], true)) cs_log("ERREUR ECRITURE : $fichier_dest");
486 unset($cs_metas_pipelines[$temp]);
487 $infos_pipelines['header_prive']['inline'][] = "cs_header_hit(\$flux, '$type', '_prive');";
488 $infos_pipelines['insert_head'.($type=='css'?'_css':'')]['inline'][] = "cs_header_hit(\$flux, '$type');";
489 }
490 }
491 // SPIP 2.0 ajoute les parametres "TYPO" et $connect aux fonctions typo() et propre()
492 $liste_pivots = defined('_SPIP19300')
493 ?array(
494 // Fonctions pivots : on peut en avoir plusieurs pour un meme traitement
495 // Exception : 'typo' et 'propre' ne cohabitent pas ensemble
496 'typo' => defined('_TRAITEMENT_TYPO')?_TRAITEMENT_TYPO:'typo(%s,"TYPO",$connect)', // guillemets doubles requises pour le compilo
497 'propre' => defined('_TRAITEMENT_RACCOURCIS')?_TRAITEMENT_RACCOURCIS:'propre(%s,$connect)',
498 ):array(
499 'typo' => 'typo(%s)',
500 'propre' => 'propre(%s)',
501 );
502 // mise en code des traitements trouves
503 $traitements_post_propre = 0;
504 foreach($traitements_utilises as $bal=>$balise) {
505 foreach($balise as $obj=>$type_objet) {
506 // ici, on fait attention de ne pas melanger propre et typo
507 if(array_key_exists('typo', $type_objet) && array_key_exists('propre', $type_objet))
508 die(var_dump($type_objet) . "<br/>>> <b>#$bal/$obj</b><br/>" . _T('couteauprive:erreur:traitements'));
509 $traitements_type_objet = &$traitements_utilises[$bal][$obj];
510 foreach($type_objet as $f=>$fonction) {
511 // pas d'objet precis
512 if($f===0) $traitements_type_objet[$f] = cs_fermer_parentheses(join("(", array_reverse($fonction)).'(%s');
513 // un objet precis
514 else {
515 if(!isset($liste_pivots[$f])) $liste_pivots[$f] = $f . '(%s)';
516 $traitements_type_objet[$f] = !isset($fonction['pre'])?$liste_pivots[$f]
517 :str_replace('%s',
518 cs_fermer_parentheses(join('(', $fonction['pre']) . '(%s'),
519 $liste_pivots[$f]
520 );
521 if(isset($fonction['post']))
522 $traitements_type_objet[$f] = cs_fermer_parentheses(join('(', $fonction['post']) . '(' . $traitements_type_objet[$f]);
523 }
524 }
525 // nombre de fonctions pivot ?
526 if(count($traitements_type_objet)===1) $temp = join('', $traitements_type_objet);
527 else {
528 // compilation de plusieurs pivots
529 $temp = '%s';
530 foreach($traitements_type_objet as $t) $temp = str_replace('%s', $t, $temp);
531 }
532 // detection d'un traitement post_propre
533 if(strpos($temp, '(propre(')) {
534 $traitements_post_propre = 1;
535 $temp = "cs_nettoie($temp)";
536 }
537 // traitement particulier des forums (SPIP>=2.1)
538 if(defined('_SPIP20100') && $obj==='forums') $temp = "safehtml($temp)";
539 $traitements_type_objet = "\$GLOBALS['table_des_traitements']['$bal'][" . ($obj=='0'?'':"'$obj'") . "]='$temp';";
540 }
541 $traitements_utilises[$bal] = join("\n", $traitements_utilises[$bal]);
542 }
543 // mes_options.php : ajout des traitements
544 if(count($traitements_utilises))
545 $infos_fichiers['code_options'][] = "\n// Table des traitements\n" . join("\n", $traitements_utilises);
546 $infos_fichiers['code_options'][] = "\$GLOBALS['cs_post_propre']=$traitements_post_propre;";
547 // ecriture des fichiers mes_options et mes_fonctions
548 ecrire_fichier_en_tmp($infos_fichiers, 'spip_options');
549 ecrire_fichier_en_tmp($infos_fichiers, 'options');
550 ecrire_fichier_en_tmp($infos_fichiers, 'fonctions');
551 // installation de cs_metas_pipelines[]
552 set_cs_metas_pipelines($infos_pipelines);
553 }
554
555 function cs_fermer_parentheses($expr) {
556 return $expr . str_repeat(')', substr_count($expr, '(') - substr_count($expr, ')'));
557 }
558
559 define('_CS_SPIP_OPTIONS_A', "// Partie reservee au Couteau Suisse. Ne pas modifier, merci");
560 define('_CS_SPIP_OPTIONS_B', "// Fin du code. Ne pas modifier ces lignes, merci");
561
562 // verifier le fichier d'options _FILE_OPTIONS (ecrire/mes_options.php ou config/mes_options.php)
563 function cs_verif_FILE_OPTIONS($activer=false, $ecriture = false) {
564 $include = str_replace('\\','/',realpath(_DIR_CS_TMP.'mes_spip_options.php'));
565 $include = "@include_once \"$include\";\nif(\$GLOBALS['cs_spip_options']) define('_CS_SPIP_OPTIONS_OK',1);";
566 $inclusion = _CS_SPIP_OPTIONS_A."\n// Please don't modify; this code is auto-generated\n$include\n"._CS_SPIP_OPTIONS_B;
567 cs_log("cs_verif_FILE_OPTIONS($activer, $ecriture) : le code d'appel est $include");
568 if($fo = cs_spip_file_options(1)) {
569 if(lire_fichier($fo, $t)) {
570 // verification du contenu inclu
571 $ok = preg_match('`\s*('.preg_quote(_CS_SPIP_OPTIONS_A,'`').'.*'.preg_quote(_CS_SPIP_OPTIONS_B,'`').')\s*`ms', $t, $regs);
572 // s'il faut une inclusion
573 if($activer) {
574 // pas besoin de reecrire si le contenu est identique a l'inclusion
575 if(($regs[1]==$inclusion)) $ecriture = false;
576 $t2 = $ok?str_replace($regs[0], "\n$inclusion\n\n", $t):preg_replace(',<\?(?:php)?\s*,', '<?'."php\n$inclusion\n\n", $t);
577 } else {
578 $t2 = $ok?str_replace($regs[0], "\n", $t):$t;
579 }
580 cs_log(" -- fichier $fo present. Inclusion " . ($ok?" trouvee".($ecriture?" et remplacee":""):"absente".(($ecriture && $activer)?" mais ajoutee":"")));
581 if($ecriture) if($t2<>$t) {
582 $ok = ecrire_fichier($fo, $t2);
583 if(!$ok) cs_log("ERREUR : l'ecriture du fichier $fo a echoue !");
584 }
585 return;
586 } else cs_log(" -- fichier $fo illisible. Inclusion non permise");
587 } else
588 $fo = cs_spip_file_options(2);
589 // creation
590 if($activer) {
591 if($ecriture) $ok=ecrire_fichier($fo, '<?'."php\n".$inclusion."\n\n?".'>');
592 cs_log(" -- fichier $fo absent. Fichier '$fo' et inclusion ".((!$ecriture || !$ok)?"non ":"")."crees");
593 }
594 }
595
596 function cs_retire_guillemets($valeur) {
597 $valeur = trim($valeur);
598 return (strncmp($valeur,$g="'",1)===0 /*|| strncmp($valeur,$g='"',1)===0*/)
599 && preg_match(",^$g(.*)$g$,s", $valeur, $matches)
600 ?stripslashes($matches[1])
601 :$valeur;
602 }
603
604 // met en forme une valeur dans le style php
605 function cs_php_format($valeur, $is_chaine = true, $dblguill=false) {
606 $valeur = trim($valeur);
607 if( (strncmp($valeur,$g="'",1)===0 || ($dblguill && strncmp($valeur,$g='"',1)===0))
608 && preg_match(",^$g(.*)$g$,s", $valeur, $matches)) {
609 if($is_chaine) return $valeur;
610 $valeur = stripslashes($matches[1]);
611 }
612 if(!strlen($valeur)) return $is_chaine?"''":0;
613 return $is_chaine?var_export($valeur, true):$valeur;
614 }
615
616 // retourne le code compile d'une variable en fonction de sa valeur
617 function cs_get_code_php_variable($variable, $valeur) {
618 global $cs_variables;
619 // si la variable n'a pas ete declaree
620 if(!isset($cs_variables[$variable])) return _L("/* Variable '$variable' inconnue ! */");
621 $cs_variable = &$cs_variables[$variable];
622 // mise en forme php de $valeur
623 if(!strlen($valeur)) {
624 if($cs_variable['format']==_format_NOMBRE) $valeur='0'; else $valeur='""';
625 } else
626 $valeur = cs_php_format($valeur, @$cs_variable['format']!=_format_NOMBRE);
627 $code = '';
628 foreach($cs_variable as $type=>$param) if(preg_match(',^code(:(.*))?$,', $type, $regs)) {
629 $eval = '$test = ' . (isset($regs[2])?str_replace('%s', $valeur, $regs[2]):'true') . ';';
630 $test = false;
631 eval($eval);
632 $code .= $test?str_replace('%s', $valeur, $param):'';
633 }
634 return $code;
635 }
636
637
638 // remplace les valeurs marquees comme %%toto%% par le code reel prevu par $cs_variables['toto']['code:condition']
639 // attention de bien declarer les variables a l'aide de add_variable()
640 function cs_parse_code_php($code, $debut='%%', $fin='%%') {
641 global $metas_vars, $cs_variables;
642 while(preg_match(",([']?)$debut([a-zA-Z_][a-zA-Z0-9_]*?)$fin([']?),", $code, $matches)) {
643 $cotes = $matches[1]=="'" && $matches[3]=="'";
644 $nom = $matches[2];
645 // la valeur de la variable n'est stockee dans les metas qu'au premier post
646 if(isset($metas_vars[$nom])) {
647 $rempl = cs_get_code_php_variable($nom, $metas_vars[$nom]);
648 if(!strlen($rempl)) $code = "/* Pour info : $nom = $metas_vars[$nom] */\n" . $code;
649 } else {
650 // tant que le webmestre n'a pas poste, on prend la valeur (dynamique) par defaut
651 $defaut = cs_get_defaut($nom);
652 $rempl = cs_get_code_php_variable($nom, $defaut);
653 $code = "/* Par defaut : {$nom} = $defaut */\n" . $code;
654 }
655 //echo '<br>',$nom, ':',isset($metas_vars[$nom]), " - $code";
656 if($cotes) $rempl = str_replace("'", "\'", $rempl);
657 $code = str_replace($matches[0], $matches[1].$rempl.$matches[3], $code);
658 }
659 return $code;
660 }
661
662 // remplace les valeurs marquees comme %%toto%% par la valeur reelle de $metas_vars['toto']
663 // si cette valeur n'existe pas encore, la valeur utilisee sera $cs_variables['toto']['defaut']
664 // attention de bien declarer les variables a l'aide de add_variable()
665 function cs_parse_code_js($code) {
666 global $metas_vars, $cs_variables;
667 // parse d'abord [[%toto%]] pour le code reel de la variable
668 $code = cs_parse_code_php($code, '\[\[%', '%\]\]');
669 // parse ensuite %%toto%% pour la valeur reelle de la variable
670 while(preg_match(',%%([a-zA-Z_][a-zA-Z0-9_]*)%%,U', $code, $matches)) {
671 // la valeur de la variable n'est stockee dans les metas qu'au premier post
672 if(isset($metas_vars[$matches[1]])) {
673 // la valeur de la variable est directement inseree dans le code js
674 $rempl = $metas_vars[$matches[1]];
675 } else {
676 // tant que le webmestre n'a pas poste, on prend la valeur (dynamique) par defaut
677 $rempl = cs_retire_guillemets(cs_get_defaut($matches[1]));
678 }
679 $code = str_replace($matches[0], $rempl, $code);
680 }
681 return $code;
682 }
683
684 // attention : optimisation tres sommaire, pour codes simples !
685 // -> optimise les if(0), if(1), if(false), if(true)
686 function cs_optimise_if($code, $root=true) {
687 if($root) {
688 $code = preg_replace(',if\s*\(\s*([^)]*\s*)\)\s*{\s*,imsS', 'if(\\1){', $code);
689 $code = str_replace(array('if(false){', 'if(!1){', 'if()'), 'if(0){', $code);
690 $code = str_replace(array('if(true){', 'if(!0){'), 'if(1){', $code);
691 }
692 if(preg_match_all(',if\(([0-9])+\){(.*)$,msS', $code, $regs, PREG_SET_ORDER))
693 foreach($regs as $r) {
694 $temp = $r[2]; $ouvre = $ferme = -1; $nbouvre = 1;
695 do {
696 if($ouvre===false) $min = $ferme + 1; else $min = min($ouvre, $ferme) + 1;
697 $ouvre=strpos($temp, '{', $min);
698 $ferme=strpos($temp, '}', $min);
699 if($ferme!==false) { if($ouvre!==false && $ouvre<$ferme) $nbouvre++; else $nbouvre--; }
700 } while($ferme!==false && $nbouvre>0);
701 if($ferme===false) return "/* Erreur sur les accolades : \{$r[2] */";
702 $temp2 = cs_optimise_if($temp3=substr($temp, $ferme+1), false);
703 $temp = substr($temp, 0, $ferme);
704 $rempl = "if($r[1]){".$temp."}$temp3";
705 if(intval($r[1])) $code = str_replace($rempl, "/* optimisation : 'IF($r[1])' */ {$temp}{$temp2}", $code);
706 else $code = str_replace($rempl, "/* optimisation : 'IF($r[1]) \{$temp\}' */{$temp2}", $code);
707 }
708 return $code;
709 }
710
711 // lance la fonction d'installation de chaque outil actif, si elle existe.
712 // la fonction doit etre ecrite sous la forme monoutil_installe_dist() et placee
713 // dans le fichier outils/monoutil.php
714 // une surcharge de la fnction native est possible en ecrivant une fonction monoutil_installe()
715 function cs_installe_outils() {
716 global $metas_outils;
717 $datas = array();
718 foreach($metas_outils as $nom=>$o) if(isset($o['actif']) && $o['actif']) {
719 include_spip('outils/'.$nom);
720 if(function_exists($f = $nom.'_installe') || function_exists($f = $f.'_dist')) {
721 if(is_array($tmp=$f())) foreach($tmp as $i=>$v) {
722 $j=($i && $i!==$nom)?$nom.'_'.$i:$nom;
723 $datas[$j] = "function cs_data_$j() { return " . var_export($v, true) . ';}';
724 }
725 if(defined('_LOG_CS')) cs_log(" -- $f() : OK !");
726 }
727 }
728 $datas = array('code_outils' => $datas);
729 ecrire_fichier_en_tmp($datas, 'outils');
730 ecrire_metas();
731 }
732
733 function cs_outils_concernes($key, $off=false){
734 global $outils, $metas_outils; $s='';
735 foreach($outils as $o) if(isset($o[$key]))
736 $s .= ($s?' - ':'')."[.->$o[id]]".(isset($metas_outils[$o[id]]['actif']) && $metas_outils[$o[id]]['actif']?' ('._T('couteauprive:outil_actif_court').')':'');
737 if(!$s) return '';
738 $s = _T('couteauprive:outils_'.($off?'desactives':'concernes')).$s;
739 return "<q1><q3>$s</q3></q1>";
740 }
741 ?>