Dépôt officiel du core SPIP * Anciennement présent sur svn://trac.rezo.net/spip * Les plugins-dist faisant partie de la distribution SPIP sont présents dans https://git.spip.net/SPIP/[nom du plugin dist] https://www.spip.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

739 lines
22 KiB

  1. <?php
  2. /***************************************************************************\
  3. * SPIP, Systeme de publication pour l'internet *
  4. * *
  5. * Copyright (c) 2001-2019 *
  6. * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
  7. * *
  8. * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
  9. * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
  10. \***************************************************************************/
  11. /**
  12. * Gestion de l'authentification par sessions
  13. * à utiliser pour valider l'accès (bloquant)
  14. * ou pour reconnaître un utilisateur (non bloquant)
  15. *
  16. * @package SPIP\Core\Session
  17. */
  18. if (!defined('_ECRIRE_INC_VERSION')) {
  19. return;
  20. }
  21. $GLOBALS['visiteur_session'] = array(); # globale decrivant l'auteur
  22. /**
  23. * 3 actions sur les sessions, selon le type de l'argument:
  24. *
  25. * - numerique: efface toutes les sessions de l'auteur (retour quelconque)
  26. * - tableau: cree une session pour l'auteur decrit et retourne l'identifiant
  27. * - bool: predicat de validite de la session indiquee par le cookie
  28. *
  29. * @uses supprimer_sessions()
  30. * @uses ajouter_session()
  31. * @uses verifier_session()
  32. *
  33. * @param int|array|bool $auteur
  34. * @return bool|null|void
  35. */
  36. function inc_session_dist($auteur = false) {
  37. if (is_numeric($auteur)) {
  38. return supprimer_sessions($auteur, $auteur > 0);
  39. } else {
  40. if (is_array($auteur)) {
  41. return ajouter_session($auteur);
  42. } else {
  43. return verifier_session($auteur);
  44. }
  45. }
  46. }
  47. /**
  48. * Supprimer toutes les vieilles sessions d'un auteur
  49. *
  50. * Cette fonction efface toutes les sessions appartenant a l'auteur
  51. * On en profite pour effacer toutes les sessions
  52. * creees il y a plus de 4*_RENOUVELLE_ALEA
  53. * Tenir compte de l'ancien format ou les noms commencaient par "session_"
  54. * et du meme coup des repertoires plats
  55. *
  56. * Attention : id_auteur peut etre negatif (cas des auteurs temporaires pendant le dump)
  57. *
  58. * @uses verifier_session()
  59. * @uses fichier_session()
  60. * @uses spip_session()
  61. *
  62. * @param int $id_auteur
  63. * Identifiant d'auteur dont on veut supprimer les sessions
  64. * @param bool $toutes
  65. * Supprimer aussi les vieilles sessions des autres auteurs ?
  66. * @param bool $actives
  67. * false pour ne pas supprimer les sessions valides de $id_auteur.
  68. * false revient donc a uniquement supprimer les vieilles sessions !
  69. */
  70. function supprimer_sessions($id_auteur, $toutes = true, $actives = true) {
  71. $nb_files = 0;
  72. $nb_max_files = (defined('_MAX_NB_SESSIONS_OUVERTES') ? _MAX_NB_SESSIONS_OUVERTES : 1000);
  73. spip_log("supprimer sessions auteur $id_auteur", "session");
  74. if ($toutes or $id_auteur !== $GLOBALS['visiteur_session']['id_auteur']) {
  75. if ($dir = opendir(_DIR_SESSIONS)) {
  76. $t = $_SERVER['REQUEST_TIME'] - (4*_RENOUVELLE_ALEA); // 48h par defaut
  77. $t_short = $_SERVER['REQUEST_TIME'] - max(_RENOUVELLE_ALEA/4,3*3600); // 3h par defaut
  78. $t = time() - (4 * _RENOUVELLE_ALEA);
  79. while (($f = readdir($dir)) !== false) {
  80. $nb_files++;
  81. if (preg_match(",^[^\d-]*(-?\d+)_\w{32}\.php[3]?$,", $f, $regs)) {
  82. $f = _DIR_SESSIONS . $f;
  83. if (($actives and $regs[1] == $id_auteur) or ($t > filemtime($f))) {
  84. spip_unlink($f);
  85. }
  86. // si il y a trop de sessions ouvertes, on purge les sessions anonymes de plus de 3H
  87. // cf http://core.spip.org/issues/3276
  88. elseif ($nb_files>$nb_max_files and !intval($regs[1]) and ($t_short > filemtime($f))) {
  89. spip_unlink($f);
  90. }
  91. }
  92. }
  93. }
  94. } else {
  95. verifier_session();
  96. spip_unlink(fichier_session('alea_ephemere', true));
  97. }
  98. // forcer le recalcul de la session courante
  99. spip_session(true);
  100. }
  101. /**
  102. * Ajoute une session pour l'auteur décrit par un tableau issu d'un SELECT-SQL
  103. *
  104. * @uses spip_php_session_start() Lorsque session anonyme
  105. * @uses hash_env()
  106. * @uses preparer_ecriture_session()
  107. * @uses fichier_session()
  108. * @uses ecrire_fichier_session()
  109. *
  110. * @param array $auteur
  111. * Description de la session de l'auteur. Peut contenir (par exemple)
  112. * les clés : id_auteur, nom, login, email, statut, lang, ...
  113. * @return bool|string
  114. */
  115. function ajouter_session($auteur) {
  116. // Si le client a deja une session valide pour son id_auteur
  117. // on conserve le meme fichier
  118. // Attention un visiteur peut avoir une session et un id=0,
  119. // => ne pas melanger les sessions des differents visiteurs
  120. $id_auteur = isset($auteur['id_auteur']) ? intval($auteur['id_auteur']) : 0;
  121. // Si ce n'est pas un inscrit (les inscrits ont toujours des choses en session)
  122. // on va vérifier s'il y a vraiment des choses à écrire
  123. if (!$id_auteur) {
  124. // On supprime les données de base pour voir le contenu réel de la session
  125. $auteur_verif = $auteur;
  126. if (isset($auteur_verif['id_auteur'])) {
  127. unset($auteur_verif['id_auteur']);
  128. }
  129. if (isset($auteur_verif['hash_env'])) {
  130. unset($auteur_verif['hash_env']);
  131. }
  132. if (isset($auteur_verif['ip_change'])) {
  133. unset($auteur_verif['ip_change']);
  134. }
  135. if (isset($auteur_verif['date_session'])) {
  136. unset($auteur_verif['date_session']);
  137. }
  138. // Les variables vraiment nulle ne sont pas à prendre en compte non plus
  139. foreach ($auteur_verif as $variable => $valeur) {
  140. if ($valeur === null) {
  141. unset($auteur_verif[$variable]);
  142. }
  143. }
  144. // Si après ça la session est vide alors on supprime l'éventuel fichier et on arrête là
  145. if (!$auteur_verif) {
  146. if (isset($_COOKIE['spip_session']) and isset($_SESSION[$_COOKIE['spip_session']])) {
  147. unset($_SESSION[$_COOKIE['spip_session']]);
  148. }
  149. if (isset($_COOKIE['spip_session'])) {
  150. unset($_COOKIE['spip_session']);
  151. }
  152. return false;
  153. }
  154. }
  155. if (!isset($_COOKIE['spip_session'])
  156. or !preg_match(',^' . $id_auteur . '_,', $_COOKIE['spip_session'])
  157. ) {
  158. $_COOKIE['spip_session'] = $id_auteur . '_' . md5(uniqid(rand(), true));
  159. }
  160. // Maintenant on sait qu'on a des choses à écrire
  161. // On s'assure d'avoir au moins ces valeurs
  162. $auteur['id_auteur'] = $id_auteur;
  163. if (!isset($auteur['hash_env'])) {
  164. $auteur['hash_env'] = hash_env();
  165. }
  166. if (!isset($auteur['ip_change'])) {
  167. $auteur['ip_change'] = false;
  168. }
  169. if (!isset($auteur['date_session'])) {
  170. $auteur['date_session'] = time();
  171. }
  172. if (isset($auteur['prefs'])
  173. and is_string($auteur['prefs'])
  174. and $prefs = @unserialize($auteur['prefs'])) {
  175. $auteur['prefs'] = $prefs;
  176. }
  177. $fichier_session = "";
  178. // les sessions anonymes sont stockees dans $_SESSION
  179. if (!$id_auteur) {
  180. spip_php_session_start();
  181. $_SESSION[$_COOKIE['spip_session']] = preparer_ecriture_session($auteur);
  182. } else {
  183. $fichier_session = fichier_session('alea_ephemere');
  184. if (!ecrire_fichier_session($fichier_session, $auteur)) {
  185. spip_log('Echec ecriture fichier session ' . $fichier_session, "session" . _LOG_HS);
  186. include_spip('inc/minipres');
  187. echo minipres();
  188. exit;
  189. }
  190. // verifier et limiter le nombre maxi de sessions
  191. // https://core.spip.net/issues/3807
  192. lister_sessions_auteur($id_auteur);
  193. }
  194. // poser le cookie de session SPIP
  195. include_spip('inc/cookie');
  196. $duree = definir_duree_cookie_session($auteur);
  197. spip_setcookie( 'spip_session', $_COOKIE['spip_session'], time() + $duree);
  198. spip_log("ajoute session $fichier_session cookie $duree", "session");
  199. // Si on est admin, poser le cookie de correspondance
  200. if (!function_exists('autoriser')) {
  201. include_spip('inc/autoriser');
  202. }
  203. if (autoriser('ecrire','','',$auteur) and _DUREE_COOKIE_ADMIN) {
  204. spip_setcookie('spip_admin', '@' . ($auteur['email'] ?: $auteur['login']), time() + max(_DUREE_COOKIE_ADMIN, $duree));
  205. } // sinon le supprimer ...
  206. else {
  207. spip_setcookie('spip_admin', '', 1);
  208. }
  209. # on en profite pour purger les vieilles sessions anonymes abandonnees
  210. # supprimer_sessions(0, true, false);
  211. return $_COOKIE['spip_session'];
  212. }
  213. /**
  214. * Calcule le temps de validité en seconde du cookie de session
  215. *
  216. * Applique un coefficient multiplicateur à la durée de renouvellement de l'alea
  217. * (noté ensuite `dR`, valant 12h par défaut) pour déterminer la durée du cookie.
  218. *
  219. * - `2 * dR`, par défaut
  220. * - `20 * dR` si le visiteur a indiqué vouloir rester connecté quelques jours
  221. * sur le formulaire de login (la clé `cookie` vaut alors `oui`)
  222. * - `c * dR`, un coeficient défini manuellement si la clé `cookie` est numérique
  223. *
  224. * @param array $auteur
  225. * Description de l'auteur
  226. * @return int
  227. * Durée en secondes
  228. **/
  229. function definir_duree_cookie_session($auteur) {
  230. $coef = 2;
  231. if (isset($auteur['cookie'])) {
  232. if (is_numeric($auteur['cookie'])) {
  233. $coef = $auteur['cookie'];
  234. } else {
  235. $coef = 20;
  236. }
  237. }
  238. return (int)(_RENOUVELLE_ALEA * $coef);
  239. }
  240. /**
  241. * Vérifie si le cookie spip_session indique une session valide
  242. *
  243. * Si oui, la decrit dans le tableau $visiteur_session et retourne id_auteur
  244. * La rejoue si IP change puis accepte le changement si $change=true
  245. *
  246. * Retourne false en cas d'echec, l'id_auteur de la session si defini, null sinon
  247. *
  248. * @uses spip_php_session_start() Si session anonyme
  249. * @uses fichier_session()
  250. * @uses ajouter_session()
  251. * @uses hash_env()
  252. *
  253. * @param bool $change
  254. * @return bool|int|null
  255. */
  256. function verifier_session($change = false) {
  257. // si pas de cookie, c'est fichu
  258. if (!isset($_COOKIE['spip_session'])) {
  259. return false;
  260. }
  261. $fichier_session = "";
  262. // est-ce une session anonyme ?
  263. if (!intval($_COOKIE['spip_session'])) {
  264. spip_php_session_start();
  265. if (!isset($_SESSION[$_COOKIE['spip_session']]) or !is_array($_SESSION[$_COOKIE['spip_session']])) {
  266. return false;
  267. }
  268. $GLOBALS['visiteur_session'] = $_SESSION[$_COOKIE['spip_session']];
  269. } else {
  270. // Tester avec alea courant
  271. $fichier_session = fichier_session('alea_ephemere', true);
  272. if ($fichier_session and @file_exists($fichier_session)) {
  273. include($fichier_session);
  274. } else {
  275. // Sinon, tester avec alea precedent
  276. $fichier_session = fichier_session('alea_ephemere_ancien', true);
  277. if (!$fichier_session or !@file_exists($fichier_session)) {
  278. return false;
  279. }
  280. // Renouveler la session avec l'alea courant
  281. include($fichier_session);
  282. spip_log('renouvelle session ' . $GLOBALS['visiteur_session']['id_auteur'], "session");
  283. spip_unlink($fichier_session);
  284. ajouter_session($GLOBALS['visiteur_session']);
  285. }
  286. }
  287. // Compatibilite ascendante : auteur_session est visiteur_session si
  288. // c'est un auteur SPIP authentifie (tandis qu'un visiteur_session peut
  289. // n'etre qu'identifie, sans aucune authentification).
  290. if (isset($GLOBALS['visiteur_session']['id_auteur']) and $GLOBALS['visiteur_session']['id_auteur']) {
  291. $GLOBALS['auteur_session'] = &$GLOBALS['visiteur_session'];
  292. }
  293. // Si l'adresse IP change, inc/presentation mettra une balise image
  294. // avec un URL de rappel demandant a changer le nom de la session.
  295. // Seul celui qui a l'IP d'origine est rejoue
  296. // ainsi un eventuel voleur de cookie ne pourrait pas deconnecter
  297. // sa victime, mais se ferait deconnecter par elle.
  298. if (hash_env() != $GLOBALS['visiteur_session']['hash_env']) {
  299. if (!$GLOBALS['visiteur_session']['ip_change']) {
  300. define('_SESSION_REJOUER', true);
  301. $GLOBALS['visiteur_session']['ip_change'] = true;
  302. ajouter_session($GLOBALS['visiteur_session']);
  303. } else {
  304. if ($change) {
  305. spip_log("session non rejouee, vol de cookie ?", "session");
  306. }
  307. }
  308. } else {
  309. if ($change) {
  310. spip_log("rejoue session $fichier_session " . $_COOKIE['spip_session'], "session");
  311. if ($fichier_session) {
  312. spip_unlink($fichier_session);
  313. }
  314. $GLOBALS['visiteur_session']['ip_change'] = false;
  315. unset($_COOKIE['spip_session']);
  316. ajouter_session($GLOBALS['visiteur_session']);
  317. }
  318. }
  319. // Si la session a ete initiee il y a trop longtemps, elle est annulee
  320. if (isset($GLOBALS['visiteur_session'])
  321. and defined('_AGE_SESSION_MAX')
  322. and _AGE_SESSION_MAX > 0
  323. and time() - @$GLOBALS['visiteur_session']['date_session'] > _AGE_SESSION_MAX
  324. ) {
  325. unset($GLOBALS['visiteur_session']);
  326. return false;
  327. }
  328. return is_numeric($GLOBALS['visiteur_session']['id_auteur'])
  329. ? $GLOBALS['visiteur_session']['id_auteur']
  330. : null;
  331. }
  332. /**
  333. * Lire une valeur dans la session SPIP
  334. *
  335. * @api
  336. * @example `$login = session_get('login');`
  337. *
  338. * @param string $nom
  339. * Clé dont on souhaite la valeur
  340. * @return mixed|null
  341. * Valeur, si trouvée, `null` sinon.
  342. */
  343. function session_get($nom) {
  344. return isset($GLOBALS['visiteur_session'][$nom]) ? $GLOBALS['visiteur_session'][$nom] : null;
  345. }
  346. /**
  347. * Ajouter une donnée dans la session SPIP
  348. *
  349. * @api
  350. * @uses ajouter_session()
  351. * @uses terminer_actualiser_sessions() Ajoute la fonction en fin de hit.
  352. *
  353. * @param string $nom
  354. * @param null $val
  355. * @return void|array
  356. */
  357. function session_set($nom, $val = null) {
  358. static $remove = array();
  359. static $actualiser_sessions = false;
  360. if ($nom === false) {
  361. return $remove;
  362. }
  363. if (is_null($val)) {
  364. // rien a faire
  365. if (!isset($GLOBALS['visiteur_session'][$nom])) {
  366. return;
  367. }
  368. unset($GLOBALS['visiteur_session'][$nom]);
  369. $remove[] = $nom;
  370. } else {
  371. // On ajoute la valeur dans la globale
  372. $GLOBALS['visiteur_session'][$nom] = $val;
  373. if ($remove) {
  374. $remove = array_diff($remove, array($nom));
  375. }
  376. }
  377. if (!$actualiser_sessions) {
  378. // il faut creer la session si on en a pas, la premiere fois
  379. ajouter_session($GLOBALS['visiteur_session']);
  380. // in register la fonction qui mettra a jour toutes les sessions en fin de hit
  381. register_shutdown_function('terminer_actualiser_sessions');
  382. $actualiser_sessions = true;
  383. }
  384. }
  385. /**
  386. * En fin de hit, synchroniser toutes les sessions
  387. *
  388. * @uses actualiser_sessions()
  389. */
  390. function terminer_actualiser_sessions() {
  391. // se remettre dans le dossier de travail au cas ou Apache a change
  392. chdir(_ROOT_CWD);
  393. // recuperer les variables a effacer
  394. $remove = session_set(false);
  395. // mettre a jour toutes les sessions
  396. actualiser_sessions($GLOBALS['visiteur_session'], $remove);
  397. }
  398. /**
  399. * Mettre à jour les sessions existantes pour un auteur
  400. *
  401. * Quand on modifie une fiche auteur on appelle cette fonction qui va
  402. * mettre à jour les fichiers de session de l'auteur en question.
  403. * (auteurs identifiés seulement)
  404. *
  405. * Ne concerne que les sessions des auteurs loges (id_auteur connu)
  406. *
  407. * @uses ajouter_session()
  408. * @uses fichier_session()
  409. * @uses preg_files()
  410. * @uses preparer_ecriture_session()
  411. * @uses ecrire_fichier_session()
  412. *
  413. * @param array $auteur
  414. * @param array $supprimer_cles
  415. * Liste des clés à supprimer des tableaux de sessions
  416. */
  417. function actualiser_sessions($auteur, $supprimer_cles = array()) {
  418. $id_auteur = isset($auteur['id_auteur']) ? intval($auteur['id_auteur']) : 0;
  419. $id_auteur_courant = isset($GLOBALS['visiteur_session']['id_auteur']) ? intval($GLOBALS['visiteur_session']['id_auteur']) : 0;
  420. // si l'auteur est celui de la session courante, verifier/creer la session si besoin
  421. $fichier_session_courante = "";
  422. if ($id_auteur == $id_auteur_courant) {
  423. $auteur = array_merge($GLOBALS['visiteur_session'], $auteur);
  424. ajouter_session($auteur);
  425. if ($id_auteur) {
  426. $fichier_session_courante = fichier_session('alea_ephemere');
  427. }
  428. }
  429. // si session anonyme on ne fait rien d'autre ici : les sessions anonymes sont non partagees
  430. if (!$id_auteur) {
  431. return;
  432. }
  433. // les préférences sont désérialisées, toujours.
  434. // [fixme] Le champ 'prefs' sert aussi à l’inscription
  435. if (isset($auteur['prefs']) and is_string($auteur['prefs'])) {
  436. $auteur['prefs'] = @unserialize($auteur['prefs']);
  437. if (!is_array($auteur['prefs'])) {
  438. $auteur['prefs'] = [];
  439. }
  440. }
  441. // memoriser l'auteur courant (celui qui modifie la fiche)
  442. $sauve = $GLOBALS['visiteur_session'];
  443. // .. mettre a jour les sessions de l'auteur cible
  444. // attention au $ final pour ne pas risquer d'embarquer un .php.jeton temporaire
  445. // cree par une ecriture concurente d'une session (fichier atomique temporaire)
  446. $sessions = lister_sessions_auteur($id_auteur);
  447. // 1ere passe : lire et fusionner les sessions
  448. foreach ($sessions as $session) {
  449. $GLOBALS['visiteur_session'] = array();
  450. // a pu etre supprime entre le preg initial et le moment ou l'on arrive la (concurrence)
  451. if ($session !== $fichier_session_courante
  452. and @file_exists($session)
  453. ) {
  454. include $session; # $GLOBALS['visiteur_session'] est alors l'auteur cible
  455. $auteur = array_merge($GLOBALS['visiteur_session'], $auteur);
  456. }
  457. }
  458. // supprimer les eventuelles cles dont on ne veut plus
  459. foreach ($supprimer_cles as $cle) {
  460. unset($auteur[$cle]);
  461. }
  462. $auteur_session = preparer_ecriture_session($auteur);
  463. // seconde passe : ecrire les sessions qui ne sont pas a jour
  464. foreach ($sessions as $session) {
  465. $GLOBALS['visiteur_session'] = array();
  466. // a pu etre supprime entre le preg initial et le moment ou l'on arrive la (concurrence)
  467. if (@file_exists($session)) {
  468. include $session; # $GLOBALS['visiteur_session'] est alors l'auteur cible
  469. // est-ce que cette session est a mettre a jour ?
  470. if ($auteur_session != $GLOBALS['visiteur_session']) {
  471. ecrire_fichier_session($session, $auteur);
  472. }
  473. }
  474. }
  475. if ($id_auteur == $id_auteur_courant) {
  476. $GLOBALS['visiteur_session'] = $auteur;
  477. $GLOBALS['auteur_session'] = &$GLOBALS['visiteur_session'];
  478. } else {
  479. // restaurer l'auteur courant
  480. $GLOBALS['visiteur_session'] = $sauve;
  481. }
  482. }
  483. /**
  484. * lister les sessions et en verifier le nombre maxi
  485. * en supprimant les plus anciennes si besoin
  486. * https://core.spip.net/issues/3807
  487. *
  488. * @param int $id_auteur
  489. * @param int $nb_max
  490. * @return array
  491. */
  492. function lister_sessions_auteur($id_auteur, $nb_max = null) {
  493. if (is_null($nb_max)) {
  494. if (!defined('_NB_SESSIONS_MAX')) {
  495. define('_NB_SESSIONS_MAX', 100);
  496. }
  497. $nb_max = _NB_SESSIONS_MAX;
  498. }
  499. // liste des sessions
  500. $sessions = preg_files(_DIR_SESSIONS, '/' . $id_auteur . '_.*\.php$');
  501. // si on en a plus que la limite, supprimer les plus vieilles
  502. // si ce ne sont pas des sessions anonymes car elles sont alors chacune differentes
  503. if ($id_auteur
  504. and count($sessions) > $nb_max) {
  505. // limiter le nombre de sessions ouvertes par un auteur
  506. // filemtime sur les sessions
  507. $sessions = array_flip($sessions);
  508. // 1ere passe : lire les filemtime
  509. foreach ($sessions as $session => $z) {
  510. if ($d = @filemtime($session)
  511. ) {
  512. $sessions[$session] = $d;
  513. } else {
  514. $sessions[$session] = 0;
  515. }
  516. }
  517. // les plus anciennes en premier
  518. asort($sessions);
  519. $sessions = array_keys($sessions);
  520. while (count($sessions) > $nb_max) {
  521. $session = array_shift($sessions);
  522. @unlink($session);
  523. }
  524. }
  525. return $sessions;
  526. }
  527. /**
  528. * Préparer le tableau de session avant écriture
  529. *
  530. * Nettoyage de quelques variables sensibles, et appel d'un pipeline
  531. *
  532. * @pipeline preparer_fichier_session
  533. * @param array $auteur
  534. * @return array
  535. */
  536. function preparer_ecriture_session($auteur) {
  537. $row = $auteur;
  538. // ne pas enregistrer ces elements de securite
  539. // dans le fichier de session
  540. unset($auteur['pass']);
  541. unset($auteur['htpass']);
  542. unset($auteur['low_sec']);
  543. unset($auteur['alea_actuel']);
  544. unset($auteur['alea_futur']);
  545. $auteur = pipeline('preparer_fichier_session', array('args' => array('row' => $row), 'data' => $auteur));
  546. // ne pas enregistrer les valeurs vraiment nulle dans le fichier
  547. foreach ($auteur as $variable => $valeur) {
  548. if ($valeur === null) {
  549. unset($auteur[$variable]);
  550. }
  551. }
  552. return $auteur;
  553. }
  554. /**
  555. * Ecrire le fichier d'une session
  556. *
  557. * @param string $fichier
  558. * @param array $auteur
  559. * @return bool
  560. */
  561. function ecrire_fichier_session($fichier, $auteur) {
  562. $auteur = preparer_ecriture_session($auteur);
  563. // enregistrer les autres donnees du visiteur
  564. $texte = "<" . "?php\n";
  565. foreach ($auteur as $var => $val) {
  566. $texte .= '$GLOBALS[\'visiteur_session\'][' . var_export($var, true) . '] = '
  567. . var_export($val, true) . ";\n";
  568. }
  569. $texte .= "?" . ">\n";
  570. return ecrire_fichier($fichier, $texte);
  571. }
  572. /**
  573. * Calculer le nom du fichier session
  574. *
  575. * @param string $alea
  576. * @param bool $tantpis
  577. * @return string
  578. */
  579. function fichier_session($alea, $tantpis = false) {
  580. include_spip('inc/acces');
  581. charger_aleas();
  582. if (empty($GLOBALS['meta'][$alea])) {
  583. if (!$tantpis) {
  584. spip_log("fichier session ($tantpis): $alea indisponible", "session");
  585. include_spip('inc/minipres');
  586. echo minipres();
  587. }
  588. return ''; // echec mais $tanpis
  589. } else {
  590. $repertoire = sous_repertoire(_DIR_SESSIONS, '', false, $tantpis);
  591. $c = $_COOKIE['spip_session'];
  592. return $repertoire . intval($c) . '_' . md5($c . ' ' . $GLOBALS['meta'][$alea]) . '.php';
  593. }
  594. }
  595. /**
  596. * Code à insérer par `inc/presentation` pour rejouer la session
  597. *
  598. * @note
  599. * Pourquoi insère-t-on le src par js et non directement en statique dans le HTML ?
  600. * Historiquement, inséré par une balise `<script>` en r424
  601. * puis modifié par `<img>` statique + js en r427
  602. *
  603. * @see action_cookie_dist() qui sera appelé
  604. *
  605. * @return string
  606. */
  607. function rejouer_session() {
  608. return '<img src="' . generer_url_action('cookie', 'change_session=oui', true) . '" width="0" height="0" alt="" />';
  609. }
  610. /**
  611. * On verifie l'IP et le nom du navigateur
  612. *
  613. * @return string
  614. */
  615. function hash_env() {
  616. static $res = '';
  617. if ($res) {
  618. return $res;
  619. }
  620. return $res = md5($GLOBALS['ip'] . (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''));
  621. }
  622. /**
  623. * Démarre une session PHP si ce n'est pas déjà fait.
  624. *
  625. * @link http://php.net/manual/fr/function.session-start.php
  626. * @uses is_php_session_started()
  627. * @return bool True si une session PHP est ouverte.
  628. **/
  629. function spip_php_session_start() {
  630. if (!is_php_session_started()) {
  631. return session_start();
  632. }
  633. return true;
  634. }
  635. /**
  636. * Indique si une sesssion PHP est active
  637. *
  638. * @link http://php.net/manual/fr/function.session-status.php#113468
  639. * @return bool true si une session PHP est active
  640. **/
  641. function is_php_session_started() {
  642. if (php_sapi_name() !== 'cli') {
  643. return session_status() === PHP_SESSION_ACTIVE ? true : false;
  644. }
  645. return false;
  646. }