Newer
Older
<?php
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
\***************************************************************************/
if (!defined("_ECRIRE_INC_VERSION")) return;
//
// Gestion des inclusions et infos repertoires
//
$included_files = array();
function include_local($file, $silence=false) {
$nom = preg_replace("/\.php[3]?$/",'', $file);
# spip_log("$nom $file");
if (@$GLOBALS['included_files'][$nom]++) return;
if (is_readable($f = $nom . '.php'))
include($f);
else if (is_readable($f = $nom . _EXTENSION_PHP))
include($f);
else if (!$silence) spip_log($file . " illisible");
}
function include_ecrire($file) {
# Hack pour etre compatible avec les mes_options qui appellent cette fonction
define_once('_DIR_INCLUDE', _DIR_RESTREINT);
include_local(_DIR_INCLUDE . $file);
}
// charge un fichier perso ou, a defaut, standard
// et retourne si elle existe le nom de la fonction homonyme, ou de prefixe _dist
function include_fonction($nom) {
# Hack pour etre compatible avec les mes_options qui appellent cette fonction
define_once('_DIR_INCLUDE', _DIR_RESTREINT);
$nom = preg_replace("/\.php[3]?$/",'', basename($nom));
$inc = ('inc_' . $nom);
# spip_log("if $inc");
$f = find_in_path($inc . '.php');
if ($f && is_readable($f)) {
if (!$GLOBALS['included_files'][$inc]++) include($f);
$f = _DIR_INCLUDE . $inc . '.php';
if (!$GLOBALS['included_files'][$inc]++) include($f);
// provisoire avant renommage
$f = _DIR_INCLUDE . ('inc_' . $nom . _EXTENSION_PHP);
if (!$GLOBALS['included_files'][$inc]++) include($f);
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
} else $inc = "";
}
}
$f = str_replace('-','_',$nom); // pour config-fonc etc. A renommer
if (function_exists($f))
return $f;
elseif (function_exists($f .= "_dist"))
return $f;
else {
spip_log("fonction $nom indisponible" .
($inc ? "" : "(aucun fichier inc_$f disponible)"));
exit;
}
}
// un pipeline est lie a une action et une valeur
// chaque element du pipeline est autorise a modifier la valeur
//
// le pipeline execute les elements disponibles pour cette action,
// les uns apres les autres, et retourne la valeur finale
function pipeline($cause, $val) {
global $spip_pipeline, $spip_matrice;
if (!is_array($spip_pipeline[$cause])) return $val;
foreach ($spip_pipeline[$cause] as $plug) {
// charger un fichier le cas echeant
if (!function_exists($plug)) {
if ($f = $spip_matrice[$plug]) {
include($f);
$ok = function_exists($plug);
}
if (!$ok) {
spip_log("Erreur - $plug n'est pas definie ($f)");
return $val;
}
}
// appliquer le filtre
$val = $plug($val);
}
return $val;
}
//
// Enregistrement des evenements
//
function spip_log($message, $logname='spip') {
static $compteur;
if ($compteur++ > 100) return;
$pid = '(pid '.@getmypid().')';
if (!$ip = $GLOBALS['REMOTE_ADDR']) $ip = '-';
$message = date("M d H:i:s")." $ip $pid "
.preg_replace("/\n*$/", "\n", $message);
$logfile = _DIR_SESSIONS . $logname . '.log';
if (@file_exists($logfile) && (@filesize($logfile) > 10*1024)) {
$rotate = true;
$message .= "[-- rotate --]\n";
}
$f = @fopen($logfile, "ab");
if ($f) {
fputs($f, $message);
fclose($f);
}
if ($rotate) {
@unlink($logfile.'.3');
@rename($logfile.'.2',$logfile.'.3');
@rename($logfile.'.1',$logfile.'.2');
@rename($logfile,$logfile.'.1');
}
// recopier les spip_log mysql (ce sont uniquement des erreurs)
// dans le spip_log general
if ($logname == 'mysql')
spip_log($message);
}
// API d'appel a la base de donnees
function spip_query($query) {
// Remarque : si on est appele par l'install,
// la connexion initiale a ete faite avant
if (!$GLOBALS['db_ok']) {
// Essaie de se connecter
if (_FILE_CONNECT)
include_local(_FILE_CONNECT);
}
// Erreur de connexion
if (!$GLOBALS['db_ok'])
return;
// Vieux format de fichier connexion
// Note: la version 0.1 est compatible avec la 0.2 (mais elle gere
// moins bien les erreurs timeout sur SQL), on ne force donc pas l'upgrade
if ($GLOBALS['spip_connect_version'] < 0.1) {
if (!_DIR_RESTREINT) {$GLOBALS['db_ok'] = false; return;}
redirige_par_entete(generer_url_ecrire("upgrade"),"?reinstall=oui");
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
exit;
}
// Faire la requete
return spip_query_db($query);
}
class Link {
var $file;
var $vars;
var $arrays;
//
// Contructeur : a appeler soit avec l'URL du lien a creer,
// soit sans parametres, auquel cas l'URL est l'URL courante
//
// parametre $root = demander un lien a partir de la racine du serveur /
function Link($url = '', $root = false) {
global $_POST;
static $link = '';
$this->vars = array();
$this->arrays = array();
// Normal case
if ($link) {
if ($url) {
$v = split('[\?\&]', $url);
list(, $this->file) = each($v);
while (list(, $var) = each($v)) {
list($name, $value) = split('=', $var, 2);
$name = urldecode($name);
$value = urldecode($value);
if (preg_match(',^(.*)\[\]$,', $name, $regs)) {
$this->arrays[$regs[1]][] = $value;
}
else {
$this->vars[$name] = $value;
}
}
}
else {
$this->file = $link->file;
$this->vars = $link->vars;
$this->arrays = $link->arrays;
}
return;
}
// Si aucun URL n'est specifie, creer le lien "propre"
// ou l'on supprime de l'URL courant les bidules inutiles
if (!$url) {
// GET variables are read from the original URL
// (_GET may contain additional variables
// introduced by rewrite-rules)
$url = $GLOBALS['REQUEST_URI'];
// Warning !!!!
// since non encoded arguments may be present
// (especially those coming from Rewrite Rule)
// find the begining of the query string
// to compute the script-name
if ($v = strpos($url,'?'))
$v = strrpos(substr($url, 0, $v), '/');
else $v = strrpos($url, '/');
if (!$root) $url = substr($url, $v + 1);
if (!$url) $url = "./";
if (count($_POST)) {
$vars = array();
foreach ($_POST as $var => $val)
if (preg_match('/^id_/', $var))
$vars[$var] = $val;
}
}
$v = split('[\?\&]', $url);
list(, $this->file) = each($v);
if (!$vars) {
while (list(,$var) = each($v)) {
list($name, $value) = split('=', $var, 2);
$name = urldecode($name);
$value = urldecode($value);
if (preg_match(',^(.*)\[\]$,', $name, $regs))
$vars[$regs[1]][] = $value;
else
$vars[$name] = $value;
}
}
if (is_array($vars)) {
foreach ($vars as $name => $value) {
// items supprimes
if (!preg_match('/^('.
(!_DIR_RESTREINT ?
'|lang|set_options|set_couleur|set_disp|set_ecran':
'var_mode|show_docs')
. ')$/i', $name)) {
if (is_array($value))
$this->arrays[$name] = $value;
else
$this->vars[$name] = $value;
}
}
}
}
//
// Effacer une variable
//
function delVar($name) {
if(isset($this->vars[$name])) unset($this->vars[$name]);
if($this->arrays[$name]) unset($this->arrays[$name]);
}
//
// Ajouter une variable
// (si aucune valeur n'est specifiee, prend la valeur globale actuelle)
//
function addVar($name, $value = '__global__') {
if ($value == '__global__') $value = $GLOBALS[$name];
if (is_array($value))
$this->arrays[$name] = $value;
else
$this->vars[$name] = $value;
}
//
// Recuperer l'URL correspondant au lien
//
function getUrl($anchor = '') {
$url = $this->file;
if (!$url) $url = './';
$query = '';
foreach($this->vars as $name => $value) {
$query .= '&'.$name;
if (strlen($value))
$query .= '='.urlencode($value);
}
foreach ($this->arrays as $name => $table)
foreach ($table as $value)
$query .= '&'.$name.'[]='.urlencode($value);
if ($query) $query = '?'. substr($query, 1);
if ($anchor) $anchor = '#'.$anchor;
return "$url$query$anchor";
}
//
// Recuperer le debut de formulaire correspondant au lien
// (tag ouvrant + entrees cachees representant les variables)
//
function getForm($method = 'get', $query = '', $enctype = '') {
if (preg_match(',^[a-z],i', $query))
$action = $query;
else
$action = $this->file.$query;
$form = "<form method='$method' action='"
.quote_amp($action)."'";
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
if ($enctype) $form .= " enctype='$enctype'";
$form .= " style='border: 0px; margin: 0px;'>\n";
foreach ($this->vars as $name => $value) {
$value = preg_replace(',&(#[0-9]+;),', '&\1',
htmlspecialchars($value));
$form .= "<input type=\"hidden\" name=\"$name\" "
. "value=\"$value\" />\n";
}
foreach ($this->arrays as $name => $table)
foreach ($table as $value) {
$value = preg_replace(',&(#[0-9]+;),', '&\1',
htmlspecialchars($value));
$form .= "<input type=\"hidden\" name=\"".$name."[]\" "
. "value=\"".$value."\" />\n";
}
return $form;
}
}
//
// Gerer les valeurs meta
//
// Fonction lire_meta abandonnee, remplacee par son contenu. Ne plus utiliser
function lire_meta($nom) {
global $meta;
return $meta[$nom];
}
//
// Traduction des textes de SPIP
//
function _T($texte, $args = '') {
include_ecrire('inc_lang');
$text = traduire_chaine($texte, $args);
if (!empty($GLOBALS['xhtml'])) {
include_ecrire("inc_charsets");
$text = html2unicode($text, true /* secure */);
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
}
return $text ? $text :
// pour les chaines non traduites
(($n = strpos($texte,':')) === false ? $texte :
substr($texte, $n+1));
}
// chaines en cours de traduction
function _L($text) {
if ($GLOBALS['test_i18n'])
return "<span style='color:red;'>$text</span>";
else
return $text;
}
// Nommage bizarre des tables d'objets
function table_objet($type) {
if ($type == 'site' OR $type == 'syndic')
return 'syndic';
else if ($type == 'forum')
return 'forum';
else
return $type.'s';
}
function id_table_objet($type) {
if ($type == 'site' OR $type == 'syndic')
return 'id_syndic';
else if ($type == 'forum')
return 'id_forum';
else
return 'id_'.$type;
}
//
// spip_timer : on l'appelle deux fois et on a la difference, affichable
//
function spip_timer($t='rien') {
static $time;
$a=time(); $b=microtime();
if (isset($time[$t])) {
$p = $a + $b - $time[$t];
unset($time[$t]);
return sprintf("%.2fs", $p);
} else
$time[$t] = $a + $b;
}
// spip_touch : verifie si un fichier existe et n'est pas vieux (duree en s)
// et le cas echeant le touch() ; renvoie true si la condition est verifiee
// et fait touch() sauf si ca n'est pas souhaite
// (regle aussi le probleme des droits sur les fichiers touch())
function spip_touch($fichier, $duree=0, $touch=true) {
if (!($exists = @file_exists($fichier))
|| ($duree == 0)
|| (@filemtime($fichier) < time() - $duree)) {
if ($touch) {
if (!@touch($fichier)) { @unlink($fichier); @touch($fichier); };
if (!$exists) @chmod($fichier, 0666);
}
return true;
}
return false;
}
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
// Pour executer des taches de fond discretement, on utilise background-image
// car contrairement a un iframe vide, les navigateurs ne diront pas qu'ils
// n'ont pas fini de charger, c'est plus rassurant.
// C'est aussi plus discret qu'un <img> sous un navigateur non graphique.
// Cette fonction est utilisee pour l'espace prive (cf inc_presentation)
// et pour l'espace public (cf #SPIP_CRON dans inc_balise)
function generer_spip_cron() {
return '<div align="right" class="verdana2" style="background-image: url(\'' .
generer_url_public('spip_action.php', 'action=cron') .
'\');">';
}
// envoi de l'image demandee dans le code ci-dessus
function spip_action_cron() {
$image = pack("H*", "47494638396118001800800000ffffff00000021f90401000000002c0000000018001800000216848fa9cbed0fa39cb4da8bb3debcfb0f86e248965301003b");
header("Content-Type: image/gif");
header("Content-Length: ".strlen($image));
header("Cache-Control: no-cache,no-store");
header("Pragma: no-cache");
header("Connection: close");
echo $image;
flush();
cron (1);
}
//
// cron() : execution des taches de fond
// quand il est appele par inc-public.php il n'est pas gourmand;
// quand il est appele par spip_action.php, il est gourmand
function cron ($gourmand=false) {
// Si on est gourmand, ou si le fichier gourmand n'existe pas
// (ou est trop vieux -> 60 sec), on va voir si un cron est necessaire.
// Au passage si on est gourmand on le dit aux autres
if (spip_touch(_FILE_CRON_LOCK.'-gourmand', 60, $gourmand)
OR $gourmand) {
// Faut-il travailler ? Pas tous en meme temps svp
// Au passage si on travaille on bloque les autres
if (spip_touch(_FILE_CRON_LOCK, 2)) {
include_ecrire('inc_cron');
spip_cron();
}
}
}
//
// Entetes les plus courants (voir inc_headers.php pour les autres)
//
function http_gmoddate($lastmodified) {
return gmdate("D, d M Y H:i:s", $lastmodified);
}
function http_last_modified($lastmodified, $expire = 0) {
$gmoddate = http_gmoddate($lastmodified);
if ($GLOBALS['HTTP_IF_MODIFIED_SINCE']
AND !preg_match(',IIS/,', $_SERVER['SERVER_SOFTWARE'])) # MSoft IIS is dumb
{
$if_modified_since = preg_replace('/;.*/', '',
$GLOBALS['HTTP_IF_MODIFIED_SINCE']);
$if_modified_since = trim(str_replace('GMT', '', $if_modified_since));
if ($if_modified_since == $gmoddate) {
include_ecrire('inc_headers');
http_status(304);
$headers_only = true;
}
}
@Header ("Last-Modified: ".$gmoddate." GMT");
if ($expire)
@Header ("Expires: ".http_gmoddate($expire)." GMT");
return $headers_only;
}
// envoyer le navigateur sur une nouvelle adresse
esj
a validé
function redirige_par_entete($url, $fin="") {
include_ecrire('inc_headers');
esj
a validé
spip_header("Location: $url$fin");
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
exit;
}
// transformation XML des "&" en "&"
function quote_amp($u) {
return preg_replace(
"/&(?![a-z]{0,4}\w{2,3};|#x?[0-9a-f]{2,5};)/i",
"&",$u);
}
// Transforme n'importe quel champ en une chaine utilisable
// en PHP ou Javascript en toute securite
// < ? php $x = '[(#TEXTE|texte_script)]'; ? >
function texte_script($texte) {
return str_replace('\'', '\\\'', str_replace('\\', '\\\\', $texte));
}
//
// find_in_path() : chercher un fichier nomme x selon le chemin rep1:rep2:rep3
//
function find_in_path ($filename, $path='AUTO') {
// Chemin standard depuis l'espace public
if ($path == 'AUTO') {
$path = _SPIP_PATH;
if ($GLOBALS['dossier_squelettes'])
$path = $GLOBALS['dossier_squelettes'].'/:'.$path;
}
// Parcourir le chemin
foreach (split(':', $path) as $dir) {
// Depuis l'espace prive, remonter d'un cran, sauf pour les absolus
$racine = ($dir[0]=='/') ? '' : _DIR_RACINE;
if ($dir[0] == '.') $dir = "";
else if ($dir && $dir[strlen($dir)-1] <> '/') $dir .= "/";
$f = "$racine$dir$filename";
# spip_log("find_in_path: essai $racine $dir $filename");
if (@is_readable($f)) {
return $f;
}
}
}
// charger les definitions des plugins
function charger_plugins($plugins) {
foreach ($plugins as $plug) {
include(_DIR_RACINE.'plugins/'.$plug.'/version.php');
}
#var_dump($plugins);var_dump($spip_pipeline);var_dump($spip_matrice);exit;
}
// Cette fonction charge le bon inc-urls selon qu'on est dans l'espace
// public ou prive, la presence d'un (old style) inc-urls.php3, etc.
function charger_generer_url() {
static $ok;
if ($ok++) return; # fichier deja charge
// espace prive ?
if (!_DIR_RESTREINT)
include_ecrire('inc_urls');
// fichier inc-urls ?
else if (@file_exists("inc-urls" . _EXTENSION_PHP))
include_local("inc-urls");
// fichier inc-urls-xxx ?
else
include_local("inc-urls-".$GLOBALS['type_urls']);
}
// cette fonction fabrique un appel a un script php
// elle est destinee a assurer la transition
esj
a validé
// entre les scripts ecrire/*.php[3] et le script generique ecrire/index.php
function generer_url_ecrire($script, $args="", $retour="", $retour_args="") {
return $script .
esj
a validé
(ereg('.php[3]?$', $script) ? '' :_EXTENSION_PHP) .
(!$args ? "" : ('?' .str_replace('&', '&', $args))) .
(!$retour ? "" :
urlencode($retour . _EXTENSION_PHP .
(!$retour_args ? "" : ('?' . $retour_args))));
}
// scripts publics appeles a partir de l'espace prive ou de l'exterieur (mail)
// il faudra substituer a l'appel ci-dessous la definition ci-dessus
// lorsque celle-ci deviendra generique
function generer_url_public($script, $args="", $retour="", $retour_args="") {
if (!($site = $GLOBALS['meta']["adresse_site"]))
$site = _DIR_RACINE;
$site .= (($site[strlen($site)-1] <> '/') ?'/':'') . $script;
return generer_url_ecrire($site, $args, $retour, $retour_args);