source: spip-zone/_plugins_/couteau_suisse/cout_utils.php

Last change on this file was 111530, checked in by patfr@…, 2 years ago

Notice/coquille en moins

File size: 40.0 KB
Line 
1<?php
2#-----------------------------------------------------#
3#  Plugin  : Couteau Suisse - Licence : GPL           #
4#  Auteur  : Patrice Vanneufville, 2006               #
5#  Contact : patrice¡.!vanneufville¡@!laposte¡.!net   #
6#  Infos : https://contrib.spip.net/?article2166      #
7#-----------------------------------------------------#
8#  Fichier contenant les fonctions utilisees pendant  #
9#  la configuration du plugin                         #
10#-----------------------------------------------------#
11if(!defined("_ECRIRE_INC_VERSION")) return;
12
13cs_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
21global $outils, $cs_variables;
22$cs_variables = $outils = array();
23// liste des types de variable
24$cs_variables['_chaines'] = $cs_variables['_nombres'] = array();
25define('_format_CHAINE', 10);
26define('_format_NOMBRE', 20);
27
28/*************/
29/* FONCTIONS */
30/*************/
31
32// ajoute un outil a $outils;
33function 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'] = couteauprive_T('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
69function 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
89function 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
93function 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']) && strpos($f, ',couteau_suisse/,')!==false)
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
106function 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
124function 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
151function 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'
174function 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";
185if(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'\nisset(\$GLOBALS['cs_$type'])?\$GLOBALS['cs_$type']++:\$GLOBALS['cs_$type']=1;\n$code?".'>', true))
187                cs_log("ERREUR ECRITURE : $fichier_dest");
188}
189
190function 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);
205if(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// basename sans argument
211function cs_basename($file, $suffix=null) {
212        preg_match('/[^?]*/', $file, $reg); 
213        return basename($reg[0], $suffix);
214}
215
216// fonction ecrire_fichier() tres prudente
217function cs_ecrire_fichier($file, $contenu) {
218        $inf = pathinfo($file);
219        if(!ecrire_fichier($test = $inf['dirname'].'/test_'.$inf['basename'], $contenu)) 
220                return false;
221        $old = $inf['dirname'].'/'.$inf['basename'].'.old';
222        // le fichier actuel, s'il existe, remplace la sauvegarde eventuelle
223        if(@is_readable($file)) { @spip_unlink($old); @rename($file, $old); }
224        return @rename($test, $file); // le fichier test est promu
225}
226
227// est-ce que $pipe est un pipeline ?
228function is_pipeline_outil($pipe, &$set_pipe) {
229        if($ok=(strncmp('pipeline:', $pipe, 9)==0)) $set_pipe = trim(substr($pipe, 9));
230        return $ok;
231}
232// est-ce que $pipe est un pipeline inline?
233function is_pipeline_outil_inline($pipe, &$set_pipe) {
234        if($ok=(strncmp('pipelinecode:', $pipe, 13)==0)) $set_pipe = trim(substr($pipe, 13));
235        return $ok;
236}
237
238// est-ce que $traitement est un traitement ?
239function is_traitements_outil($traitement, $fonction, &$set_traitements_utilises) {
240        if(strncmp('traitement', $traitement, 10)!=0) return false;
241        if($ok = preg_match(',^traitement:([A-Z_]+)/?([a-z]+)?:(pre|post)_([a-zA-Z0-9_-]+)$,', $traitement, $t)) {
242                if(!strlen($t[2])) $t[2] = 0;
243                // 'typo' et 'propre' ne cohabitent pas : le premier l'emporte !
244                if($t[4]=='typo') { if(isset($set_traitements_utilises[$t[1]][$t[2]]['propre'])) $t[4]='propre'; }
245                elseif($t[4]=='propre') { if(isset($set_traitements_utilises[$t[1]][$t[2]]['typo'])) $t[4]='typo'; }
246                $set_traitements_utilises[$t[1]][$t[2]][$t[4]][$t[3]][] = $fonction;
247        } elseif($ok = preg_match(',^traitement:([A-Z]+)$,', $traitement, $t))
248                $set_traitements_utilises[$t[1]][0][0][] = $fonction;
249        return $ok;
250}
251
252// lire un fichier php et retirer si possible les balises ?php
253function cs_lire_fichier_php($file) {
254        $file=find_in_path($file);
255        if($file && lire_fichier($file, $php)) {
256                if(preg_match(',^<\?php(.*)?\?>$,msi', trim($php), $regs)) return trim($regs[1]);
257                return "\n"."?>\n".trim($php)."\n<"."?php\n";
258        }
259        return false;
260}
261
262// retourne les raccourcis ajoutes par l'outil, s'il est actif
263function cs_aide_raccourci($id) {
264        global $outils;
265        // stockage de la liste des fonctions par pipeline, si l'outil est actif...
266        if($outils[$id]['actif']) {
267                include_spip('outils/'.$id);   
268                if(function_exists($f = $id.'_raccourcis')) return $f();
269                if(!preg_match(',:aide(?:<|$),', $x = _T("couteauprive:$id:aide") )) return $x;
270        }
271        return '';
272}
273
274function cs_aide_raccourcis_callback($matches) {
275        return defined($matches[1])?constant($matches[1]):"";
276}
277
278// retourne la liste des raccourcis disponibles
279function cs_aide_raccourcis() {
280        global $outils;
281        $aide = array();
282        foreach ($outils as $outil) 
283                if($a = cs_aide_raccourci($outil['id'])) $aide[] = '<li style="margin: 0.7em 0 0 0;">&bull; ' . $a . '</li>';
284        if(!count($aide)) return '';
285        // remplacement des constantes de forme @_CS_XXXX@
286        $aide = preg_replace_callback(',@(_CS_[a-zA-Z0-9_]+)@,', 'cs_aide_raccourcis_callback', join("\n", $aide));
287        return '<p><b>' . couteauprive_T('raccourcis') . '</b></p><ul class="cs_raccourcis">' . $aide . '</ul>';
288}
289
290// retourne une aide concernant les pipelines utilises par l'outil
291function cs_aide_pipelines($outils_affiches_actifs) {
292        global $cs_metas_pipelines, $outils, $metas_outils;
293        $aide = array();
294        $keys = array_keys($cs_metas_pipelines); sort($keys);
295        foreach ($keys as $pipe) {
296                // stockage de la liste des pipelines et du nombre d'outils actifs concernes
297                $nb=0; foreach($outils as $outil) if($outil['actif'] && (isset($outil['pipeline:'.$pipe]) || isset($outil['pipelinecode:'.$pipe]))) $nb++;
298                if(($len=strlen($pipe))>25) $pipe = substr($pipe, 0, 8).'...'.substr($pipe, $len - 14);
299                if($nb) $aide[] = couteauprive_T('outil_nb'.($nb>1?'s':''), array('pipe'=>$pipe, 'nb'=>$nb));
300        }
301        // nombre d'outils actifs / interdits par les autorisations (hors versionnage SPIP)
302        $nb = $ca2 = 0; 
303        foreach($metas_outils as $o) if(isset($o['actif']) && $o['actif']) $nb++;
304        foreach($outils as $o) if(isset($o['interdit']) && $o['interdit'] && !cs_version_erreur($o)) $ca2++;
305        // nombre d'outils caches de la configuration par l'utilisateur
306        $ca1 = isset($GLOBALS['meta']['tweaks_caches'])?count(unserialize($GLOBALS['meta']['tweaks_caches'])):0;
307        return '<p><b>' . couteauprive_T('outils_actifs') . "</b> $nb"
308                . '<br /><b>' . couteauprive_T('outils_caches') . "</b> $ca1"
309                . (!$ca2?'':('<br /><b>' . couteauprive_T('outils_non_parametrables') . "</b> $ca2"))
310                .'<br /><b>' . couteauprive_T('pipelines') . '</b> '.count($aide)
311                . '</p><p style="font-size:80%; line-height: 1.4em;">' . join("<br />", $aide) . '</p>';
312}
313
314// sauve la configuration dans un fichier tmp/couteau-suisse/config.php
315function cs_sauve_configuration() {
316        global $outils, $metas_vars;
317        $metas = $metas_actifs = $variables = $lesoutils = $actifs = array();
318        foreach($outils as $t) {
319                $lesoutils[] = "\t// ".$t['nom']."\n\t'".$t['id']."' => '".join('|', $t['variables']) . "'";
320                if($t['actif']) {
321                        $actifs[] = $t['id'];
322                        $variables = array_merge($variables, $t['variables']);
323                }
324        }
325        foreach($metas_vars as $i => $v) if($i!='_chaines' && $i!='_nombres') {
326                $metas[] = $temp = "\t'$i' => " . cs_php_format($v, in_array($i, $metas_vars['_chaines']));
327                if(in_array($i, $variables)) $metas_actifs[] = $temp;
328        }
329        $sauve = "// Tous les outils et leurs variables\n\$liste_outils = array(\n" . join(",\n", $lesoutils) . "\n);\n"
330                . "\n// Outils actifs\n\$outils_actifs =\n\t'" . join('|', $actifs) . "';\n"
331                . "\n// Variables actives\n\$variables_actives =\n\t'" . join('|', $variables) . "';\n"
332                . "\n// Valeurs validees en metas\n\$valeurs_validees = array(\n" . join(",\n", $metas) . "\n);\n";
333
334        include_spip('inc/charset');
335        $nom_pack = couteauprive_T('pack_actuel', array('date'=>cs_date()));
336        $fct_pack = md5($nom_pack.time());
337        $sauve .= $temp = "\n######## ".couteauprive_T('pack_actuel_titre')." #########\n\n// "
338                . filtrer_entites(couteauprive_T('pack_actuel_avert')."\n\n"
339                        . "\$GLOBALS['cs_installer']['$nom_pack'] =\t'cs_$fct_pack';\nfunction cs_$fct_pack() { return array(\n\t// "
340                        . couteauprive_T('pack_outils_defaut')."\n"
341                        . "\t'outils' =>\n\t\t'".join(",\n\t\t", $actifs)."',\n"
342                        . "\n\t// ".couteauprive_T('pack_variables_defaut')."\n")
343                . "\t'variables' => array(\n\t" . join(",\n\t", $metas_actifs) . "\n\t)\n);} # $nom_pack #\n";
344
345        ecrire_fichier(_DIR_CS_TMP.'config.php', '<'."?php\n// Configuration de controle pour le plugin 'Couteau Suisse'\n\n$sauve?".'>');
346        if(_request('cmd')=='pack' || (_request('cmd')=='descrip' && _request('outil')=='pack')) $GLOBALS['cs_pack_actuel'] = $temp;
347}
348
349function cs_autorisation_alias(&$tab, $autoriser) {
350        static $ok = array();
351        if(isset($ok[$autoriser])) return;
352        if(function_exists($f='autoriser_'.$autoriser.'_configurer') || function_exists($f.='_dist')) {
353                $g = str_replace('_','',objet_type($autoriser));
354                if($g != $autoriser) {
355                        $tab[] = "function autoriser_{$g}_configurer(\$faire,\$type,\$id,\$qui,\$opt) {\n\treturn function_exists('$f')\n\t?$f(\$faire, \$type, \$id, \$qui, \$opt):true; }";
356                        $ok[$autoriser] = 1;
357                }
358        }
359}
360
361function cs_nom_outil_callback($m) {
362        return _T($m[1]);
363}
364
365function cs_nom_outil(&$outil, $traduit=true) {
366        if($outil['pas_de_nom']) {
367                // outil classique
368