PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/spip/ecrire/inc/filtres.php

https://github.com/eyeswebcrea/espace-couture-sittler.fr
PHP | 2667 lines | 1962 code | 280 blank | 425 comment | 309 complexity | ce8c22ea3d09041a59539a675f5f3c13 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /***************************************************************************\
  3. * SPIP, Systeme de publication pour l'internet *
  4. * *
  5. * Copyright (c) 2001-2011 *
  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. if (!defined('_ECRIRE_INC_VERSION')) return;
  12. include_spip('inc/charsets');
  13. include_spip('inc/filtres_mini');
  14. /**
  15. * Charger un filtre depuis le php :
  16. * - on inclue tous les fichiers fonctions des plugins et du skel
  17. * - on appelle chercher_filtre
  18. */
  19. function charger_filtre($fonc, $default=NULL) {
  20. include_spip('public/parametrer'); // inclure les fichiers fonctions
  21. return chercher_filtre($fonc, $default);
  22. }
  23. // http://adoc.spip.org/@chercher_filtre
  24. function chercher_filtre($fonc, $default=NULL) {
  25. // Cas MIME = type/subtype
  26. // sans confondre avec les appels de fonction de classe Foo::Bar
  27. // qui peuvent etre avec un namespace : space\Foo::Bar
  28. if (strpos($fonc, '/')){
  29. $f = preg_replace(',\W,','_', $fonc);
  30. if ($f = chercher_filtre($f)) return $f;
  31. // cas du sous-type MIME sans filtre associe, passer au type:
  32. // si filtre_text_plain pas defini, passe a filtre_text
  33. $fonc = preg_replace(',\W.*$,','', $fonc);
  34. }
  35. if (!$fonc) return $default;
  36. foreach (
  37. array('filtre_'.$fonc, 'filtre_'.$fonc.'_dist', $fonc) as $f){
  38. if (is_string($g = $GLOBALS['spip_matrice'][$f]))
  39. find_in_path($g,'', true);
  40. if (function_exists($f)
  41. OR (preg_match("/^(\w*)::(\w*)$/", $f, $regs)
  42. AND is_callable(array($regs[1], $regs[2]))
  43. )) {
  44. return $f;
  45. }
  46. }
  47. return $default;
  48. }
  49. // http://doc.spip.org/@appliquer_filtre
  50. function appliquer_filtre($arg, $filtre) {
  51. $f = chercher_filtre($filtre);
  52. if (!$f)
  53. return ''; // ou faut-il retourner $arg inchange == filtre_identite?
  54. $args = func_get_args();
  55. array_shift($args); // enlever $arg
  56. array_shift($args); // enlever $filtre
  57. array_unshift($args, $arg); // remettre $arg
  58. return call_user_func_array($f,$args);
  59. }
  60. // http://doc.spip.org/@spip_version
  61. function spip_version() {
  62. $version = $GLOBALS['spip_version_affichee'];
  63. if ($svn_revision = version_svn_courante(_DIR_RACINE))
  64. $version .= ($svn_revision<0 ? ' SVN':'').' ['.abs($svn_revision).']';
  65. return $version;
  66. }
  67. //
  68. // Mention de la revision SVN courante de l'espace restreint standard
  69. // (numero non garanti pour l'espace public et en cas de mutualisation)
  70. // on est negatif si on est sur .svn, et positif si on utilise svn.revision
  71. // http://doc.spip.org/@version_svn_courante
  72. function version_svn_courante($dir) {
  73. if (!$dir) $dir = '.';
  74. // version installee par paquet ZIP
  75. if (lire_fichier($dir.'/svn.revision', $c)
  76. AND preg_match(',Revision: (\d+),', $c, $d))
  77. return intval($d[1]);
  78. // version installee par SVN
  79. if (lire_fichier($dir . '/.svn/entries', $c)
  80. AND (
  81. (preg_match_all(
  82. ',committed-rev="([0-9]+)",', $c, $r1, PREG_PATTERN_ORDER)
  83. AND $v = max($r1[1])
  84. )
  85. OR
  86. (preg_match(',^\d.*dir[\r\n]+(\d+),ms', $c, $r1) # svn >= 1.4
  87. AND $v = $r1[1]
  88. )))
  89. return -$v;
  90. // Bug ou paquet fait main
  91. return 0;
  92. }
  93. // La matrice est necessaire pour ne filtrer _que_ des fonctions definies dans filtres_images
  94. // et laisser passer les fonctions personnelles baptisees image_...
  95. $GLOBALS['spip_matrice']['image_graver'] = 'inc/filtres_images_mini.php';
  96. $GLOBALS['spip_matrice']['image_select'] = 'inc/filtres_images_mini.php';
  97. $GLOBALS['spip_matrice']['image_reduire'] = 'inc/filtres_images_mini.php';
  98. $GLOBALS['spip_matrice']['image_reduire_par'] = 'inc/filtres_images_mini.php';
  99. $GLOBALS['spip_matrice']['image_passe_partout'] = 'inc/filtres_images_mini.php';
  100. $GLOBALS['spip_matrice']['couleur_html_to_hex'] = 'inc/filtres_images_mini.php';
  101. $GLOBALS['spip_matrice']['couleur_foncer'] = 'inc/filtres_images_mini.php';
  102. $GLOBALS['spip_matrice']['couleur_eclaircir'] = 'inc/filtres_images_mini.php';
  103. // ou pour inclure un script au moment ou l'on cherche le filtre
  104. $GLOBALS['spip_matrice']['filtre_image_dist'] = 'inc/filtres_mime.php';
  105. $GLOBALS['spip_matrice']['filtre_audio_dist'] = 'inc/filtres_mime.php';
  106. $GLOBALS['spip_matrice']['filtre_video_dist'] = 'inc/filtres_mime.php';
  107. $GLOBALS['spip_matrice']['filtre_application_dist'] = 'inc/filtres_mime.php';
  108. $GLOBALS['spip_matrice']['filtre_message_dist'] = 'inc/filtres_mime.php';
  109. $GLOBALS['spip_matrice']['filtre_multipart_dist'] = 'inc/filtres_mime.php';
  110. $GLOBALS['spip_matrice']['filtre_text_dist'] = 'inc/filtres_mime.php';
  111. $GLOBALS['spip_matrice']['filtre_text_csv_dist'] = 'inc/filtres_mime.php';
  112. $GLOBALS['spip_matrice']['filtre_text_html_dist'] = 'inc/filtres_mime.php';
  113. $GLOBALS['spip_matrice']['filtre_audio_x_pn_realaudio'] = 'inc/filtres_mime.php';
  114. // charge les fonctions graphiques et applique celle demandee
  115. // http://doc.spip.org/@filtrer
  116. function filtrer($filtre) {
  117. include_spip('public/parametrer'); // charger les fichiers fonctions
  118. if (is_string($f = $GLOBALS['spip_matrice'][$filtre]))
  119. find_in_path($f,'', true);
  120. $tous = func_get_args();
  121. if (substr($filtre,0,6)=='image_' && $GLOBALS['spip_matrice'][$filtre])
  122. return image_filtrer($tous);
  123. elseif($f = chercher_filtre($filtre)) {
  124. array_shift($tous);
  125. return call_user_func_array($f, $tous);
  126. }
  127. else {
  128. // le filtre n'existe pas, on provoque une erreur
  129. $msg = array('zbug_erreur_filtre', array('filtre'=>texte_script($filtre)));
  130. erreur_squelette($msg);
  131. return '';
  132. }
  133. }
  134. // fonction generique d'entree des filtres images
  135. // accepte en entree un texte complet, un img-log (produit par #LOGO_XX),
  136. // un tag <img ...> complet, ou encore un nom de fichier *local* (passer
  137. // le filtre |copie_locale si on veut l'appliquer a un document)
  138. // applique le filtre demande a chacune des occurrences
  139. // http://doc.spip.org/@image_filtrer
  140. function image_filtrer($args){
  141. $filtre = array_shift($args); # enlever $filtre
  142. $texte = array_shift($args);
  143. if (!strlen($texte)) return;
  144. find_in_path('filtres_images_mini.php','inc/', true);
  145. statut_effacer_images_temporaires(true); // activer la suppression des images temporaires car le compilo finit la chaine par un image_graver
  146. // Cas du nom de fichier local
  147. if ( strpos(substr($texte,strlen(_DIR_RACINE)),'..')===FALSE
  148. AND !preg_match(',^/|[<>]|\s,S', $texte)
  149. AND (
  150. file_exists(preg_replace(',[?].*$,','',$texte))
  151. OR preg_match(';^(\w{3,7}://);', $texte)
  152. )) {
  153. array_unshift($args,"<img src='$texte' />");
  154. $res = call_user_func_array($filtre, $args);
  155. statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
  156. return $res;
  157. }
  158. // Cas general : trier toutes les images, avec eventuellement leur <span>
  159. if (preg_match_all(
  160. ',(<([a-z]+) [^<>]*spip_documents[^<>]*>)?\s*(<img\s.*>),UimsS',
  161. $texte, $tags, PREG_SET_ORDER)) {
  162. foreach ($tags as $tag) {
  163. $class = extraire_attribut($tag[3],'class');
  164. if (!$class || (strpos($class,'no_image_filtrer')===FALSE)){
  165. array_unshift($args,$tag[3]);
  166. if ($reduit = call_user_func_array($filtre, $args)) {
  167. // En cas de span spip_documents, modifier le style=...width:
  168. if($tag[1]){
  169. $w = extraire_attribut($reduit, 'width');
  170. if (!$w AND preg_match(",width:\s*(\d+)px,S",extraire_attribut($reduit,'style'),$regs))
  171. $w = $regs[1];
  172. if ($w AND ($style = extraire_attribut($tag[1], 'style'))){
  173. $style = preg_replace(",width:\s*\d+px,S", "width:${w}px", $style);
  174. $replace = inserer_attribut($tag[1], 'style', $style);
  175. $texte = str_replace($tag[1], $replace, $texte);
  176. }
  177. }
  178. // traiter aussi un eventuel mouseover
  179. if ($mouseover = extraire_attribut($reduit,'onmouseover')){
  180. if (preg_match(",this[.]src=['\"]([^'\"]+)['\"],ims", $mouseover, $match)){
  181. $srcover = $match[1];
  182. array_shift($args);
  183. array_unshift($args,"<img src='".$match[1]."' />");
  184. $srcover_filter = call_user_func_array($filtre, $args);
  185. $srcover_filter = extraire_attribut($srcover_filter,'src');
  186. $reduit = str_replace($srcover,$srcover_filter,$reduit);
  187. }
  188. }
  189. $texte = str_replace($tag[3], $reduit, $texte);
  190. }
  191. array_shift($args);
  192. }
  193. }
  194. }
  195. statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
  196. return $texte;
  197. }
  198. // pour les feuilles de style CSS du prive
  199. function filtre_background_image_dist ($img, $couleur, $pos="") {
  200. if (!function_exists("imagecreatetruecolor")
  201. OR !include_spip('filtres/images_transforme')
  202. OR !function_exists('image_sepia')
  203. OR !function_exists('image_aplatir')
  204. )
  205. return "background-color: #$couleur;";
  206. return "background: url(".url_absolue(extraire_attribut(image_aplatir(image_sepia($img, $couleur),"gif","cccccc", 64, true), "src")).") $pos;";
  207. }
  208. //
  209. // Retourner taille d'une image
  210. // pour les filtres |largeur et |hauteur
  211. //
  212. // http://doc.spip.org/@taille_image
  213. function taille_image($img) {
  214. static $largeur_img =array(), $hauteur_img= array();
  215. $srcWidth = 0;
  216. $srcHeight = 0;
  217. $logo = extraire_attribut($img,'src');
  218. if (!$logo) $logo = $img;
  219. else {
  220. $srcWidth = extraire_attribut($img,'width');
  221. $srcHeight = extraire_attribut($img,'height');
  222. }
  223. // ne jamais operer directement sur une image distante pour des raisons de perfo
  224. // la copie locale a toutes les chances d'etre la ou de resservir
  225. if (preg_match(';^(\w{3,7}://);', $logo)){
  226. include_spip('inc/distant');
  227. $fichier = copie_locale($logo);
  228. $logo = $fichier ? _DIR_RACINE . $fichier : $logo;
  229. }
  230. if (($p=strpos($logo,'?'))!==FALSE)
  231. $logo=substr($logo,0,$p);
  232. $srcsize = false;
  233. if (isset($largeur_img[$logo]))
  234. $srcWidth = $largeur_img[$logo];
  235. if (isset($hauteur_img[$logo]))
  236. $srcHeight = $hauteur_img[$logo];
  237. if (!$srcWidth OR !$srcHeight){
  238. if ($srcsize = @getimagesize($logo)){
  239. if (!$srcWidth) $largeur_img[$logo] = $srcWidth = $srcsize[0];
  240. if (!$srcHeight) $hauteur_img[$logo] = $srcHeight = $srcsize[1];
  241. }
  242. // $logo peut etre une reference a une image temporaire dont a n'a que le log .src
  243. // on s'y refere, l'image sera reconstruite en temps utile si necessaire
  244. elseif(@file_exists($f = "$logo.src")
  245. AND lire_fichier($f,$valeurs)
  246. AND $valeurs=unserialize($valeurs)) {
  247. if (!$srcWidth) $largeur_img[$mem] = $srcWidth = $valeurs["largeur_dest"];
  248. if (!$srcHeight) $hauteur_img[$mem] = $srcHeight = $valeurs["hauteur_dest"];
  249. }
  250. }
  251. return array($srcHeight, $srcWidth);
  252. }
  253. // http://doc.spip.org/@largeur
  254. function largeur($img) {
  255. if (!$img) return;
  256. list ($h,$l) = taille_image($img);
  257. return $l;
  258. }
  259. // http://doc.spip.org/@hauteur
  260. function hauteur($img) {
  261. if (!$img) return;
  262. list ($h,$l) = taille_image($img);
  263. return $h;
  264. }
  265. // Echappement des entites HTML avec correction des entites "brutes"
  266. // (generees par les butineurs lorsqu'on rentre des caracteres n'appartenant
  267. // pas au charset de la page [iso-8859-1 par defaut])
  268. //
  269. // Attention on limite cette correction aux caracteres "hauts" (en fait > 99
  270. // pour aller plus vite que le > 127 qui serait logique), de maniere a
  271. // preserver des echappements de caracteres "bas" (par exemple [ ou ")
  272. // et au cas particulier de &amp; qui devient &amp;amp; dans les url
  273. // http://doc.spip.org/@corriger_entites_html
  274. function corriger_entites_html($texte) {
  275. if (strpos($texte,'&amp;') === false) return $texte;
  276. return preg_replace(',&amp;(#[0-9][0-9][0-9]+;|amp;),iS', '&\1', $texte);
  277. }
  278. // idem mais corriger aussi les &amp;eacute; en &eacute;
  279. // http://doc.spip.org/@corriger_toutes_entites_html
  280. function corriger_toutes_entites_html($texte) {
  281. if (strpos($texte,'&amp;') === false) return $texte;
  282. return preg_replace(',&amp;(#?[a-z0-9]+;),iS', '&\1', $texte);
  283. }
  284. // http://doc.spip.org/@proteger_amp
  285. function proteger_amp($texte){
  286. return str_replace('&','&amp;',$texte);
  287. }
  288. // http://doc.spip.org/@entites_html
  289. function entites_html($texte, $tout=false) {
  290. if (!is_string($texte) OR !$texte
  291. OR !preg_match(",[&\"'<>],S", $texte) # strpbrk($texte, "&\"'<>")!==false
  292. ) return $texte;
  293. include_spip('inc/texte');
  294. $texte = htmlspecialchars(echappe_retour(echappe_html($texte,'',true),'','proteger_amp'));
  295. if ($tout)
  296. return corriger_toutes_entites_html($texte);
  297. else
  298. return corriger_entites_html($texte);
  299. }
  300. // Transformer les &eacute; dans le charset local
  301. // http://doc.spip.org/@filtrer_entites
  302. function filtrer_entites($texte) {
  303. if (strpos($texte,'&') === false) return $texte;
  304. // filtrer
  305. $texte = html2unicode($texte);
  306. // remettre le tout dans le charset cible
  307. return unicode2charset($texte);
  308. }
  309. // caracteres de controle - http://www.w3.org/TR/REC-xml/#charsets
  310. // http://doc.spip.org/@supprimer_caracteres_illegaux
  311. function supprimer_caracteres_illegaux($texte) {
  312. static $from = "\x0\x1\x2\x3\x4\x5\x6\x7\x8\xB\xC\xE\xF\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
  313. static $to = null;
  314. if (is_array($texte)) {
  315. return array_map('supprimer_caracteres_illegaux', $texte);
  316. }
  317. if (!$to) $to = str_repeat('-', strlen($from));
  318. return strtr($texte, $from, $to);
  319. }
  320. // Supprimer caracteres windows et les caracteres de controle ILLEGAUX
  321. // http://doc.spip.org/@corriger_caracteres
  322. function corriger_caracteres ($texte) {
  323. $texte = corriger_caracteres_windows($texte);
  324. $texte = supprimer_caracteres_illegaux($texte);
  325. return $texte;
  326. }
  327. // Encode du HTML pour transmission XML
  328. // http://doc.spip.org/@texte_backend
  329. function texte_backend($texte) {
  330. static $apostrophe = array("&#8217;", "'"); # n'allouer qu'une fois
  331. // si on a des liens ou des images, les passer en absolu
  332. $texte = liens_absolus($texte);
  333. // echapper les tags &gt; &lt;
  334. $texte = preg_replace(',&(gt|lt);,S', '&amp;\1;', $texte);
  335. // importer les &eacute;
  336. $texte = filtrer_entites($texte);
  337. // " -> &quot; et tout ce genre de choses
  338. $u = $GLOBALS['meta']['pcre_u'];
  339. $texte = str_replace("&nbsp;", " ", $texte);
  340. $texte = preg_replace('/\s{2,}/S'.$u, " ", $texte);
  341. $texte = entites_html($texte);
  342. // verifier le charset
  343. $texte = charset2unicode($texte);
  344. // Caracteres problematiques en iso-latin 1
  345. if ($GLOBALS['meta']['charset'] == 'iso-8859-1') {
  346. $texte = str_replace(chr(156), '&#156;', $texte);
  347. $texte = str_replace(chr(140), '&#140;', $texte);
  348. $texte = str_replace(chr(159), '&#159;', $texte);
  349. }
  350. // l'apostrophe curly pose probleme a certains lecteure de RSS
  351. // et le caractere apostrophe alourdit les squelettes avec PHP
  352. // ==> on les remplace par l'entite HTML
  353. return str_replace($apostrophe, "'", $texte);
  354. }
  355. // Comme ci-dessus, mais avec addslashes final pour squelettes avec PHP (rss)
  356. function texte_backendq($texte) {
  357. return addslashes(texte_backend($texte));
  358. }
  359. // Enleve le numero des titres numerotes ("1. Titre" -> "Titre")
  360. // http://doc.spip.org/@supprimer_numero
  361. function supprimer_numero($texte) {
  362. return preg_replace(
  363. ",^[[:space:]]*([0-9]+)([.)]|".chr(194).'?'.chr(176).")[[:space:]]+,S",
  364. "", $texte);
  365. }
  366. // et la fonction inverse
  367. // http://doc.spip.org/@recuperer_numero
  368. function recuperer_numero($texte) {
  369. if (preg_match(
  370. ",^[[:space:]]*([0-9]+)([.)]|".chr(194).'?'.chr(176).")[[:space:]]+,S",
  371. $texte, $regs))
  372. return intval($regs[1]);
  373. else
  374. return '';
  375. }
  376. // Suppression basique et brutale de tous les <...>
  377. // http://doc.spip.org/@supprimer_tags
  378. function supprimer_tags($texte, $rempl = "") {
  379. $texte = preg_replace(",<[^>]*>,US", $rempl, $texte);
  380. // ne pas oublier un < final non ferme
  381. // mais qui peut aussi etre un simple signe plus petit que
  382. $texte = str_replace('<', ' ', $texte);
  383. return $texte;
  384. }
  385. // Convertit les <...> en la version lisible en HTML
  386. // http://doc.spip.org/@echapper_tags
  387. function echapper_tags($texte, $rempl = "") {
  388. $texte = preg_replace("/<([^>]*)>/", "&lt;\\1&gt;", $texte);
  389. return $texte;
  390. }
  391. // Convertit un texte HTML en texte brut
  392. // http://doc.spip.org/@textebrut
  393. function textebrut($texte) {
  394. $u = $GLOBALS['meta']['pcre_u'];
  395. $texte = preg_replace('/\s+/S'.$u, " ", $texte);
  396. $texte = preg_replace("/<(p|br)( [^>]*)?".">/iS", "\n\n", $texte);
  397. $texte = preg_replace("/^\n+/", "", $texte);
  398. $texte = preg_replace("/\n+$/", "", $texte);
  399. $texte = preg_replace("/\n +/", "\n", $texte);
  400. $texte = supprimer_tags($texte);
  401. $texte = preg_replace("/(&nbsp;| )+/S", " ", $texte);
  402. // nettoyer l'apostrophe curly qui pose probleme a certains rss-readers, lecteurs de mail...
  403. $texte = str_replace("&#8217;","'",$texte);
  404. return $texte;
  405. }
  406. // Remplace les liens SPIP en liens ouvrant dans une nouvelle fenetre (target=blank)
  407. // http://doc.spip.org/@liens_ouvrants
  408. function liens_ouvrants ($texte) {
  409. return preg_replace(",<a ([^>]*https?://[^>]*class=[\"']spip_(out|url)\b[^>]+)>,",
  410. "<a \\1 target=\"_blank\">", $texte);
  411. }
  412. // Transformer les sauts de paragraphe en simples passages a la ligne
  413. // http://doc.spip.org/@PtoBR
  414. function PtoBR($texte){
  415. $u = $GLOBALS['meta']['pcre_u'];
  416. $texte = preg_replace("@</p>@iS", "\n", $texte);
  417. $texte = preg_replace("@<p\b.*>@UiS", "<br />", $texte);
  418. $texte = preg_replace("@^\s*<br />@S".$u, "", $texte);
  419. return $texte;
  420. }
  421. // Couper les "mots" de plus de $l caracteres (souvent des URLs)
  422. // en mettant des espaces (par defaut, soft hyphen &#173: = &shy;)
  423. // http://doc.spip.org/@lignes_longues
  424. function lignes_longues($texte, $l = 70, $espace='&#173;') {
  425. if ($l<1) return $texte;
  426. if (!preg_match("/[\w,\/.]{".$l."}/UmsS", $texte))
  427. return $texte;
  428. // Passer en utf-8 pour ne pas avoir de coupes trop courtes avec les &#xxxx;
  429. // qui prennent 7 caracteres
  430. #include_spip('inc/charsets');
  431. $texte = str_replace("&nbsp;","<&nbsp>",$texte);
  432. $texte = html2unicode($texte, true);
  433. $texte = str_replace("<&nbsp>","&nbsp;",$texte);
  434. $texte = unicode_to_utf_8(charset2unicode(
  435. $texte, $GLOBALS['meta']['charset'], true));
  436. // echapper les tags (on ne veut pas casser les a href=...)
  437. $tags = array();
  438. if (preg_match_all('/<.+>|&(?:amp;)?#x?[0-9]+;|&(?:amp;)?[a-zA-Z1-4]{2,6};/UumsS', $texte, $t, PREG_SET_ORDER)) {
  439. foreach ($t as $n => $tag) {
  440. $tags[$n] = $tag[0];
  441. $texte = str_replace($tag[0], "<---$n--->", $texte);
  442. }
  443. }
  444. // casser les mots longs qui restent
  445. // note : on pourrait preferer couper sur les / , etc.
  446. if (preg_match_all("/[\w,\/.]{".$l."}/UmsS", $texte, $longs, PREG_SET_ORDER)) {
  447. foreach ($longs as $long) {
  448. $texte = str_replace($long[0], $long[0].$espace, $texte);
  449. }
  450. }
  451. // retablir les tags
  452. if (preg_match_all('/<---[\s0-9]+--->/UumsS', $texte, $t, PREG_SET_ORDER)) {
  453. foreach ($t as $tag) {
  454. $n = intval(preg_replace(',[^0-9]+,U','',$tag[0]));
  455. $texte = str_replace($tag[0], $tags[$n], $texte);
  456. }
  457. }
  458. return importer_charset($texte, 'utf-8');
  459. }
  460. // Majuscules y compris accents, en HTML
  461. // http://doc.spip.org/@majuscules
  462. function majuscules($texte) {
  463. if (!strlen($texte)) return '';
  464. // Cas du turc
  465. if ($GLOBALS['spip_lang'] == 'tr') {
  466. # remplacer hors des tags et des entites
  467. if (preg_match_all(',<[^<>]+>|&[^;]+;,S', $texte, $regs, PREG_SET_ORDER))
  468. foreach ($regs as $n => $match)
  469. $texte = str_replace($match[0], "@@SPIP_TURC$n@@", $texte);
  470. $texte = str_replace('i', '&#304;', $texte);
  471. if ($regs)
  472. foreach ($regs as $n => $match)
  473. $texte = str_replace("@@SPIP_TURC$n@@", $match[0], $texte);
  474. }
  475. // Cas general
  476. return "<span style='text-transform: uppercase;'>$texte</span>";
  477. }
  478. // "127.4 ko" ou "3.1 Mo"
  479. // http://doc.spip.org/@taille_en_octets
  480. function taille_en_octets ($taille) {
  481. if ($taille < 1024) {$taille = _T('taille_octets', array('taille' => $taille));}
  482. else if ($taille < 1024*1024) {
  483. $taille = _T('taille_ko', array('taille' => ((floor($taille / 102.4))/10)));
  484. } else {
  485. $taille = _T('taille_mo', array('taille' => ((floor(($taille / 1024) / 102.4))/10)));
  486. }
  487. return $taille;
  488. }
  489. // Rend une chaine utilisable sans dommage comme attribut HTML
  490. // http://doc.spip.org/@attribut_html
  491. function attribut_html($texte,$textebrut = true) {
  492. $u = $GLOBALS['meta']['pcre_u'];
  493. if ($textebrut)
  494. $texte = preg_replace(array(",\n,",",\s(?=\s),msS".$u),array(" ",""),textebrut($texte));
  495. $texte = texte_backend($texte);
  496. $texte = str_replace(array("'",'"'),array('&#39;', '&#34;'), $texte);
  497. return preg_replace(array("/&(amp;|#38;)/","/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/"),array("&","&#38;") , $texte);
  498. }
  499. // Vider les url nulles comme 'http://' ou 'mailto:'
  500. // et leur appliquer un htmlspecialchars() + gerer les &amp;
  501. // http://doc.spip.org/@vider_url
  502. function vider_url($url, $entites = true) {
  503. # un message pour abs_url
  504. $GLOBALS['mode_abs_url'] = 'url';
  505. $url = trim($url);
  506. if (preg_match(",^(http:?/?/?|mailto:?)$,iS", $url))
  507. return '';
  508. if ($entites) $url = entites_html($url);
  509. return $url;
  510. }
  511. // Extraire une date de n'importe quel champ (a completer...)
  512. // http://doc.spip.org/@extraire_date
  513. function extraire_date($texte) {
  514. // format = 2001-08
  515. if (preg_match(",([1-2][0-9]{3})[^0-9]*(1[0-2]|0?[1-9]),",$texte,$regs))
  516. return $regs[1]."-".sprintf("%02d", $regs[2])."-01";
  517. }
  518. // Maquiller une adresse e-mail
  519. // http://doc.spip.org/@antispam
  520. function antispam($texte) {
  521. include_spip('inc/acces');
  522. $masque = creer_pass_aleatoire(3);
  523. return preg_replace("/@/", " $masque ", $texte);
  524. }
  525. // http://doc.spip.org/@securiser_acces
  526. function securiser_acces($id_auteur, $cle, $dir, $op='', $args='')
  527. {
  528. include_spip('inc/acces');
  529. if ($op) $dir .= " $op $args";
  530. return verifier_low_sec($id_auteur, $cle, $dir);
  531. }
  532. // sinon{texte, rien} : affiche "rien" si la chaine est vide,
  533. // affiche la chaine si non vide ;
  534. // attention c'est compile directement dans inc/references
  535. // http://doc.spip.org/@sinon
  536. function sinon ($texte, $sinon='') {
  537. if ($texte OR (!is_array($texte) AND strlen($texte)))
  538. return $texte;
  539. else
  540. return $sinon;
  541. }
  542. // |choixsivide{vide,pasvide} affiche pasvide si la chaine n'est pas vide...
  543. // http://doc.spip.org/@choixsivide
  544. function choixsivide($a, $vide, $pasvide) {
  545. return $a ? $pasvide : $vide;
  546. }
  547. // |choixsiegal{aquoi,oui,non} affiche oui si la chaine est egal a aquoi ...
  548. // http://doc.spip.org/@choixsiegal
  549. function choixsiegal($a1,$a2,$v,$f) {
  550. return ($a1 == $a2) ? $v : $f;
  551. }
  552. //
  553. // Date, heure, saisons
  554. //
  555. // on normalise la date, si elle vient du contexte (public/parametrer.php), on force le jour
  556. // http://doc.spip.org/@normaliser_date
  557. function normaliser_date($date, $forcer_jour = false) {
  558. $date = vider_date($date);
  559. if ($date) {
  560. if (preg_match("/^[0-9]{8,10}$/", $date))
  561. $date = date("Y-m-d H:i:s", $date);
  562. if (preg_match("#^([12][0-9]{3})([-/]00)?( [-0-9:]+)?$#", $date, $regs))
  563. $date = $regs[1]."-00-00".$regs[3];
  564. else if (preg_match("#^([12][0-9]{3}[-/][01]?[0-9])([-/]00)?( [-0-9:]+)?$#", $date, $regs))
  565. $date = preg_replace("@/@","-",$regs[1])."-00".$regs[3];
  566. else
  567. $date = date("Y-m-d H:i:s", strtotime($date));
  568. if ($forcer_jour)
  569. $date = str_replace('-00', '-01', $date);
  570. }
  571. return $date;
  572. }
  573. // http://doc.spip.org/@vider_date
  574. function vider_date($letexte) {
  575. if (strncmp("0000-00-00", $letexte,10)==0) return '';
  576. if (strncmp("0001-01-01", $letexte,10)==0) return '';
  577. if (strncmp("1970-01-01", $letexte,10)==0) return ''; // eviter le bug GMT-1
  578. return $letexte;
  579. }
  580. // http://doc.spip.org/@recup_heure
  581. function recup_heure($date){
  582. static $d = array(0,0,0);
  583. if (!preg_match('#([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $date, $r))
  584. return $d;
  585. array_shift($r);
  586. return $r;
  587. }
  588. // http://doc.spip.org/@heures
  589. function heures($numdate) {
  590. $date_array = recup_heure($numdate);
  591. if ($date_array)
  592. list($heures, $minutes, $secondes) = $date_array;
  593. return $heures;
  594. }
  595. // http://doc.spip.org/@minutes
  596. function minutes($numdate) {
  597. $date_array = recup_heure($numdate);
  598. if ($date_array)
  599. list($heures, $minutes, $secondes) = $date_array;
  600. return $minutes;
  601. }
  602. // http://doc.spip.org/@secondes
  603. function secondes($numdate) {
  604. $date_array = recup_heure($numdate);
  605. if ($date_array)
  606. list($heures,$minutes,$secondes) = $date_array;
  607. return $secondes;
  608. }
  609. // http://doc.spip.org/@heures_minutes
  610. function heures_minutes($numdate) {
  611. return _T('date_fmt_heures_minutes', array('h'=> heures($numdate), 'm'=> minutes($numdate)));
  612. }
  613. // http://doc.spip.org/@recup_date
  614. function recup_date($numdate, $forcer_jour = true){
  615. if (!$numdate) return '';
  616. $heures = $minutes = $secondes = 0;
  617. if (preg_match('#([0-9]{1,2})/([0-9]{1,2})/([0-9]{4}|[0-9]{1,2})#', $numdate, $regs)) {
  618. $jour = $regs[1];
  619. $mois = $regs[2];
  620. $annee = $regs[3];
  621. if ($annee < 90){
  622. $annee = 2000 + $annee;
  623. } elseif ($annee<100) {
  624. $annee = 1900 + $annee ;
  625. }
  626. list($heures, $minutes, $secondes) = recup_heure($numdate);
  627. }
  628. elseif (preg_match('#([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})#',$numdate, $regs)) {
  629. $annee = $regs[1];
  630. $mois = $regs[2];
  631. $jour = $regs[3];
  632. list($heures, $minutes, $secondes) = recup_heure($numdate);
  633. }
  634. elseif (preg_match('#([0-9]{4})-([0-9]{2})#', $numdate, $regs)){
  635. $annee = $regs[1];
  636. $mois = $regs[2];
  637. $jour ='';
  638. list($heures, $minutes, $secondes) = recup_heure($numdate);
  639. }
  640. elseif (preg_match('#^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$#', $numdate, $regs)){
  641. $annee = $regs[1];
  642. $mois = $regs[2];
  643. $jour = $regs[3];
  644. $heures = $regs[4];
  645. $minutes = $regs[5];
  646. $secondes = $regs[6];
  647. } else $annee = $mois = $jour ='';
  648. if ($annee > 4000) $annee -= 9000;
  649. if (substr($jour, 0, 1) == '0') $jour = substr($jour, 1);
  650. if ($forcer_jour AND $jour == '0') $jour = '1';
  651. if ($forcer_jour AND $mois == '0') $mois = '1';
  652. if ($annee OR $mois OR $jour OR $heures OR $minutes OR $secondes)
  653. return array($annee, $mois, $jour, $heures, $minutes, $secondes);
  654. }
  655. // une date pour l'interface : utilise date_relative si le decalage
  656. // avec time() est de moins de douze heures, sinon la date complete
  657. // http://doc.spip.org/@date_interface
  658. function date_interface($date, $decalage_maxi = 43200/* 12*3600 */) {
  659. return sinon(
  660. date_relative($date, $decalage_maxi),
  661. affdate_heure($date)
  662. );
  663. }
  664. // http://doc.spip.org/@date_relative
  665. function date_relative($date, $decalage_maxi=0,$ref_date=null) {
  666. if (is_null($ref_date))
  667. $ref_time = time();
  668. else
  669. $ref_time = strtotime($ref_date);
  670. if (!$date) return;
  671. $decal = date("U",$ref_time) - date("U", strtotime($date));
  672. if ($decalage_maxi AND ($decal > $decalage_maxi OR $decal < 0))
  673. return '';
  674. if ($decal < 0) {
  675. $il_y_a = "date_dans";
  676. $decal = -1 * $decal;
  677. } else {
  678. $il_y_a = "date_il_y_a";
  679. }
  680. if ($decal > 3600 * 24 * 30 * 6)
  681. return affdate_court($date);
  682. if ($decal > 3600 * 24 * 30) {
  683. $mois = floor ($decal / (3600 * 24 * 30));
  684. if ($mois < 2)
  685. $delai = "$mois "._T("date_un_mois");
  686. else
  687. $delai = "$mois "._T("date_mois");
  688. }
  689. else if ($decal > 3600 * 24 * 7) {
  690. $semaines = floor ($decal / (3600 * 24 * 7));
  691. if ($semaines < 2)
  692. $delai = "$semaines "._T("date_une_semaine");
  693. else
  694. $delai = "$semaines "._T("date_semaines");
  695. }
  696. else if ($decal > 3600 * 24) {
  697. $jours = floor ($decal / (3600 * 24));
  698. if ($jours < 2)
  699. return $il_y_a=="date_dans"?_T("date_demain"):_T("date_hier");
  700. else
  701. $delai = "$jours "._T("date_jours");
  702. }
  703. else if ($decal >= 3600) {
  704. $heures = floor ($decal / 3600);
  705. if ($heures < 2)
  706. $delai = "$heures "._T("date_une_heure");
  707. else
  708. $delai = "$heures "._T("date_heures");
  709. }
  710. else if ($decal >= 60) {
  711. $minutes = floor($decal / 60);
  712. if ($minutes < 2)
  713. $delai = "$minutes "._T("date_une_minute");
  714. else
  715. $delai = "$minutes "._T("date_minutes");
  716. } else {
  717. $secondes = ceil($decal);
  718. if ($secondes < 2)
  719. $delai = "$secondes "._T("date_une_seconde");
  720. else
  721. $delai = "$secondes "._T("date_secondes");
  722. }
  723. return _T($il_y_a, array("delai"=> $delai));
  724. }
  725. // http://doc.spip.org/@date_relativecourt
  726. function date_relativecourt($date, $decalage_maxi=0) {
  727. if (!$date) return;
  728. $decal = date("U",strtotime(date('Y-m-d'))-strtotime(date('Y-m-d',strtotime($date))));
  729. if ($decalage_maxi AND ($decal > $decalage_maxi OR $decal < 0))
  730. return '';
  731. if ($decal < -24*3600) {
  732. $retour = date_relative($date, $decalage_maxi);
  733. }
  734. elseif ($decal < 0) {
  735. $retour = _T("date_demain");
  736. }
  737. else if ($decal < (3600 * 24) ) {
  738. $retour = _T("date_aujourdhui");
  739. }
  740. else if ($decal < (3600 * 24 *2) ) {
  741. $retour = _T("date_hier");
  742. }
  743. else {
  744. $retour = date_relative($date, $decalage_maxi);
  745. }
  746. return $retour;
  747. }
  748. // http://doc.spip.org/@affdate_base
  749. function affdate_base($numdate, $vue, $param = '') {
  750. global $spip_lang;
  751. $date_array = recup_date($numdate, false);
  752. if (!$date_array) return;
  753. list($annee, $mois, $jour, $heures, $minutes, $secondes)= $date_array;
  754. // 1er, 21st, etc.
  755. $journum = $jour;
  756. if ($jour == 0) {
  757. $jour = '';
  758. } else {
  759. $njour = intval($jour);
  760. if ($jourth = _T('date_jnum'.$jour))
  761. $jour = $jourth;
  762. }
  763. $mois = intval($mois);
  764. if ($mois > 0 AND $mois < 13) {
  765. $nommois = _T('date_mois_'.$mois);
  766. if ($jour)
  767. $jourmois = _T('date_de_mois_'.$mois, array('j'=>$jour, 'nommois'=>$nommois));
  768. else
  769. $jourmois = $nommois;
  770. } else $nommois = '';
  771. if ($annee < 0) {
  772. $annee = -$annee." "._T('date_avant_jc');
  773. $avjc = true;
  774. }
  775. else $avjc = false;
  776. switch ($vue) {
  777. case 'saison':
  778. if ($mois > 0){
  779. $saison = 1;
  780. if (($mois == 3 AND $jour >= 21) OR $mois > 3) $saison = 2;
  781. if (($mois == 6 AND $jour >= 21) OR $mois > 6) $saison = 3;
  782. if (($mois == 9 AND $jour >= 21) OR $mois > 9) $saison = 4;
  783. if (($mois == 12 AND $jour >= 21) OR $mois > 12) $saison = 1;
  784. }
  785. return _T('date_saison_'.$saison);
  786. case 'court':
  787. if ($avjc) return $annee;
  788. $a = date('Y');
  789. if ($annee < ($a - 100) OR $annee > ($a + 100)) return $annee;
  790. if ($annee != $a) return _T('date_fmt_mois_annee', array ('mois'=>$mois, 'nommois'=>ucfirst($nommois), 'annee'=>$annee));
  791. return _T('date_fmt_jour_mois', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
  792. case 'jourcourt':
  793. if ($avjc) return $annee;
  794. $a = date('Y');
  795. if ($annee < ($a - 100) OR $annee > ($a + 100)) return $annee;
  796. if ($annee != $a) return _T('date_fmt_jour_mois_annee', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
  797. return _T('date_fmt_jour_mois', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
  798. case 'entier':
  799. if ($avjc) return $annee;
  800. if ($jour)
  801. return _T('date_fmt_jour_mois_annee', array ('jourmois'=>$jourmois, 'jour'=>$jour, 'mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee));
  802. elseif ($mois)
  803. return trim(_T('date_fmt_mois_annee', array ('mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee)));
  804. else
  805. return $annee;
  806. case 'nom_mois':
  807. return $nommois;
  808. case 'mois':
  809. return sprintf("%02s",$mois);
  810. case 'jour':
  811. return $jour;
  812. case 'journum':
  813. return $journum;
  814. case 'nom_jour':
  815. if (!$mois OR !$njour)
  816. return '';
  817. $nom = mktime(1,1,1,$mois,$njour,$annee);
  818. $nom = 1+date('w',$nom);
  819. $param = $param ? '_'.$param : '';
  820. return _T('date_jour_'.$nom.$param);
  821. case 'mois_annee':
  822. if ($avjc) return $annee;
  823. return trim(_T('date_fmt_mois_annee', array('mois'=>$mois, 'nommois'=>$nommois, 'annee'=>$annee)));
  824. case 'annee':
  825. return $annee;
  826. // Cas d'une vue non definie : retomber sur le format
  827. // de date propose par http://www.php.net/date
  828. default:
  829. return date($vue, strtotime($numdate));
  830. }
  831. }
  832. // http://doc.spip.org/@nom_jour
  833. function nom_jour($numdate, $forme = '') {
  834. if(!($forme == 'abbr' OR $forme == 'initiale')) $forme = '';
  835. return affdate_base($numdate, 'nom_jour', $forme);
  836. }
  837. // http://doc.spip.org/@jour
  838. function jour($numdate) {
  839. return affdate_base($numdate, 'jour');
  840. }
  841. // http://doc.spip.org/@journum
  842. function journum($numdate) {
  843. return affdate_base($numdate, 'journum');
  844. }
  845. // http://doc.spip.org/@mois
  846. function mois($numdate) {
  847. return affdate_base($numdate, 'mois');
  848. }
  849. // http://doc.spip.org/@nom_mois
  850. function nom_mois($numdate) {
  851. return affdate_base($numdate, 'nom_mois');
  852. }
  853. // http://doc.spip.org/@annee
  854. function annee($numdate) {
  855. return affdate_base($numdate, 'annee');
  856. }
  857. // http://doc.spip.org/@saison
  858. function saison($numdate) {
  859. return affdate_base($numdate, 'saison');
  860. }
  861. // http://doc.spip.org/@affdate
  862. function affdate($numdate, $format='entier') {
  863. return affdate_base($numdate, $format);
  864. }
  865. // http://doc.spip.org/@affdate_court
  866. function affdate_court($numdate) {
  867. return affdate_base($numdate, 'court');
  868. }
  869. // http://doc.spip.org/@affdate_jourcourt
  870. function affdate_jourcourt($numdate) {
  871. return affdate_base($numdate, 'jourcourt');
  872. }
  873. // http://doc.spip.org/@affdate_mois_annee
  874. function affdate_mois_annee($numdate) {
  875. return affdate_base($numdate, 'mois_annee');
  876. }
  877. // http://doc.spip.org/@affdate_heure
  878. function affdate_heure($numdate) {
  879. $date_array = recup_date($numdate);
  880. if (!$date_array) return;
  881. list($annee, $mois, $jour, $heures, $minutes, $sec)= $date_array;
  882. return _T('date_fmt_jour_heure', array('jour' => affdate($numdate), 'heure' => _T('date_fmt_heures_minutes', array('h'=> $heures, 'm'=> $minutes))));
  883. }
  884. //
  885. // Alignements en HTML (Old-style, preferer CSS)
  886. //
  887. // Cette fonction cree le paragraphe s'il n'existe pas (texte sur un seul para)
  888. // http://doc.spip.org/@aligner
  889. function aligner($letexte, $justif='') {
  890. $letexte = trim($letexte);
  891. if (!strlen($letexte)) return '';
  892. // Paragrapher proprement
  893. $letexte = paragrapher($letexte, true);
  894. // Inserer les alignements
  895. if ($justif)
  896. $letexte = str_replace(
  897. '<p class="spip">', '<p class="spip" align="'.$justif.'">',
  898. $letexte);
  899. return $letexte;
  900. }
  901. // http://doc.spip.org/@justifier
  902. function justifier($letexte) {
  903. return aligner($letexte,'justify');
  904. }
  905. // http://doc.spip.org/@aligner_droite
  906. function aligner_droite($letexte) {
  907. return aligner($letexte,'right');
  908. }
  909. // http://doc.spip.org/@aligner_gauche
  910. function aligner_gauche($letexte) {
  911. return aligner($letexte,'left');
  912. }
  913. // http://doc.spip.org/@centrer
  914. function centrer($letexte) {
  915. return aligner($letexte,'center');
  916. }
  917. // http://doc.spip.org/@style_align
  918. function style_align($bof) {
  919. global $spip_lang_left;
  920. return "text-align: $spip_lang_left";
  921. }
  922. //
  923. // Export iCal
  924. //
  925. // http://doc.spip.org/@filtrer_ical
  926. function filtrer_ical($texte) {
  927. #include_spip('inc/charsets');
  928. $texte = html2unicode($texte);
  929. $texte = unicode2charset(charset2unicode($texte, $GLOBALS['meta']['charset'], 1), 'utf-8');
  930. $texte = preg_replace("/\n/", " ", $texte);
  931. $texte = preg_replace("/,/", "\,", $texte);
  932. return $texte;
  933. }
  934. // http://doc.spip.org/@date_ical
  935. function date_ical($date, $addminutes = 0) {
  936. list($heures, $minutes, $secondes) = recup_heure($date);
  937. list($annee, $mois, $jour) = recup_date($date);
  938. return date("Ymd\THis",
  939. mktime($heures, $minutes+$addminutes,$secondes,$mois,$jour,$annee));
  940. }
  941. // date_iso retourne la date au format "RFC 3339" / "ISO 8601"
  942. // voir http://www.php.net/manual/fr/ref.datetime.php#datetime.constants
  943. // http://doc.spip.org/@date_iso
  944. function date_iso($date_heure) {
  945. list($annee, $mois, $jour) = recup_date($date_heure);
  946. list($heures, $minutes, $secondes) = recup_heure($date_heure);
  947. $time = @mktime($heures, $minutes, $secondes, $mois, $jour, $annee);
  948. return gmdate('Y-m-d\TH:i:s\Z', $time);
  949. }
  950. // date_822 retourne la date au format "RFC 822"
  951. // utilise pour <pubdate> dans certains feeds RSS
  952. // http://doc.spip.org/@date_822
  953. function date_822($date_heure) {
  954. list($annee, $mois, $jour) = recup_date($date_heure);
  955. list($heures, $minutes, $secondes) = recup_heure($date_heure);
  956. $time = mktime($heures, $minutes, $secondes, $mois, $jour, $annee);
  957. return date('r', $time);
  958. }
  959. // http://doc.spip.org/@date_anneemoisjour
  960. function date_anneemoisjour($d) {
  961. if (!$d) $d = date("Y-m-d");
  962. return substr($d, 0, 4) . substr($d, 5, 2) .substr($d, 8, 2);
  963. }
  964. // http://doc.spip.org/@date_anneemois
  965. function date_anneemois($d) {
  966. if (!$d) $d = date("Y-m-d");
  967. return substr($d, 0, 4) . substr($d, 5, 2);
  968. }
  969. // http://doc.spip.org/@date_debut_semaine
  970. function date_debut_semaine($annee, $mois, $jour) {
  971. $w_day = date("w", mktime(0,0,0,$mois, $jour, $annee));
  972. if ($w_day == 0) $w_day = 7; // Gaffe: le dimanche est zero
  973. $debut = $jour-$w_day+1;
  974. return date("Ymd", mktime(0,0,0,$mois,$debut,$annee));
  975. }
  976. // http://doc.spip.org/@date_fin_semaine
  977. function date_fin_semaine($annee, $mois, $jour) {
  978. $w_day = date("w", mktime(0,0,0,$mois, $jour, $annee));
  979. if ($w_day == 0) $w_day = 7; // Gaffe: le dimanche est zero
  980. $debut = $jour-$w_day+1;
  981. return date("Ymd", mktime(0,0,0,$mois,$debut+6,$annee));
  982. }
  983. // http://doc.spip.org/@agenda_connu
  984. function agenda_connu($type)
  985. {
  986. return in_array($type, array('jour','mois','semaine','periode', 'trimestre')) ? ' ' : '';
  987. }
  988. // Cette fonction memorise dans un tableau indexe par son 5e arg
  989. // un evenement decrit par les 4 autres (date, descriptif, titre, URL).
  990. // Appellee avec une date nulle, elle renvoie le tableau construit.
  991. // l'indexation par le 5e arg autorise plusieurs calendriers dans une page
  992. // http://doc.spip.org/@agenda_memo
  993. function agenda_memo($date=0 , $descriptif='', $titre='', $url='', $cal='')
  994. {
  995. static $agenda = array();
  996. if (!$date) return $agenda;
  997. $idate = date_ical($date);
  998. $cal = trim($cal); // func_get_args (filtre alterner) rajoute \n !!!!
  999. $agenda[$cal][(date_anneemoisjour($date))][] = array(
  1000. 'CATEGORIES' => $cal,
  1001. 'DTSTART' => $idate,
  1002. 'DTEND' => $idate,
  1003. 'DESCRIPTION' => texte_script($descriptif),
  1004. 'SUMMARY' => texte_script($titre),
  1005. 'URL' => $url);
  1006. // toujours retourner vide pour qu'il ne se passe rien
  1007. return "";
  1008. }
  1009. // Cette fonction recoit:
  1010. // - un nombre d'evenements,
  1011. // - une chaine a afficher si ce nombre est nul,
  1012. // - un type de calendrier
  1013. // -- et une suite de noms N.
  1014. // Elle demande a la fonction precedente son tableau
  1015. // et affiche selon le type les elements indexes par N dans ce tableau.
  1016. // Si le suite de noms est vide, tout le tableau est pris
  1017. // Ces noms N sont aussi des classes CSS utilisees par http_calendrier_init
  1018. // Cette fonction recupere aussi par _request les parametres
  1019. // jour, mois, annee, echelle, partie_cal (a ameliorer)
  1020. // http://doc.spip.org/@agenda_affiche
  1021. function agenda_affiche($i)
  1022. {
  1023. $args = func_get_args();
  1024. // date (ou nombre d'evenements qu'on pourrait alors afficher)
  1025. $nb = array_shift($args);
  1026. $evt = array_shift($args);
  1027. $type = array_shift($args);
  1028. if ($nb) {
  1029. $agenda = agenda_memo(0);
  1030. $evt = array();
  1031. foreach (($args ? $args : array_keys($agenda)) as $k) {
  1032. if (is_array($agenda[$k]))
  1033. foreach($agenda[$k] as $d => $v) {
  1034. $evt[$d] = $evt[$d] ? (array_merge($evt[$d], $v)) : $v;
  1035. }
  1036. }
  1037. }
  1038. return agenda_periode($type, $nb, $evt);
  1039. }
  1040. function agenda_periode($type, $nb, $avec, $sans='')
  1041. {
  1042. include_spip('inc/agenda');
  1043. $start = agenda_controle();
  1044. if ($start<0) $start = time();
  1045. $mindate = date("Ymd", $start);
  1046. if ($type != 'periode')
  1047. $evt = array($sans, $avec);
  1048. else {
  1049. $min = substr($mindate,6,2);
  1050. $max = !(is_array($avec) AND $avec) ? time() : strtotime(max(array_keys($avec)));
  1051. $max = $min + (($max - $start) / (3600 * 24));
  1052. if ($max < 31) $max = 0;
  1053. $evt = array($sans, $avec, $min, $max);
  1054. $type = 'mois';
  1055. }
  1056. $ancre = _request('ancre');
  1057. $s = self('&') . (preg_match('/^[\w-]+$/', $ancre) ? "#$ancre" : '');
  1058. return http_calendrier_init($start, $type, _request('echelle'), _request('partie_cal'), $s, $evt);
  1059. }
  1060. // Controle la coherence des 3 nombres d'une date et retourne le temps Unix,
  1061. // sinon retourne un code d'erreur, toujours negatif
  1062. function agenda_controle($date='date', $jour='jour', $mois='mois', $annee='annee')
  1063. {
  1064. $jour = _request($jour);
  1065. $mois = _request($mois);
  1066. $annee = _request($annee);
  1067. if (!($jour||$mois||$anne)) {
  1068. if ($date = recup_date(_request($date))) {
  1069. list($annee, $mois, $jour ) = $date;
  1070. } else return -1;
  1071. }
  1072. if (!$d = mktime(0,0,0, $mois, $jour, $annee)) return -2;
  1073. if ($jour != date("d", $d)) return -3;
  1074. if ($mois != date("m", $d)) return -4;
  1075. if ($annee != date("Y", $d)) return -5;
  1076. return $d;
  1077. }
  1078. //
  1079. // Recuperation de donnees dans le champ extra
  1080. // Ce filtre n'a de sens qu'avec la balise #EXTRA
  1081. //
  1082. // http://doc.spip.org/@extra
  1083. function extra($letexte, $champ) {
  1084. $champs = unserialize($letexte);
  1085. return $champs[$champ];
  1086. }
  1087. // postautobr : transforme les sauts de ligne en _
  1088. // http://doc.spip.org/@post_autobr
  1089. function post_autobr($texte, $delim="\n_ ") {
  1090. $texte = str_replace("\r\n", "\r", $texte);
  1091. $texte = str_replace("\r", "\n", $texte);
  1092. if (preg_match(",\n+$,", $texte, $fin))
  1093. $texte = substr($texte, 0, -strlen($fin = $fin[0]));
  1094. else
  1095. $fin = '';
  1096. $texte = echappe_html($texte, '', true);
  1097. $debut = '';
  1098. $suite = $texte;
  1099. while ($t = strpos('-'.$suite, "\n", 1)) {
  1100. $debut .= substr($suite, 0, $t-1);
  1101. $suite = substr($suite, $t);
  1102. $car = substr($suite, 0, 1);
  1103. if (($car<>'-') AND ($car<>'_') AND ($car<>"\n") AND ($car<>"|") AND ($car<>"}")
  1104. AND !preg_match(',^\s*(\n|</?(quote|div)|$),S',($suite))
  1105. AND !preg_match(',</?(quote|div)> *$,iS', $debut)) {
  1106. $debut .= $delim;
  1107. } else
  1108. $debut .= "\n";
  1109. if (preg_match(",^\n+,", $suite, $regs)) {
  1110. $debut.=$regs[0];
  1111. $suite = substr($suite, strlen($regs[0]));
  1112. }
  1113. }
  1114. $texte = $debut.$suite;
  1115. $texte = echappe_retour($texte);
  1116. return $texte.$fin;
  1117. }
  1118. //
  1119. // Gestion des blocs multilingues
  1120. //
  1121. define('_EXTRAIRE_MULTI', "@<multi>(.*?)</multi>@sS");
  1122. // Extraire et transformer les blocs multi ; on indique la langue courante
  1123. // pour ne pas mettre de span@lang=fr si on est deja en fr
  1124. // http://doc.spip.org/@extraire_multi
  1125. function extraire_multi($letexte, $lang=null, $echappe_span=false) {
  1126. if (strpos($letexte, '<multi>') === false) return $letexte; // perf
  1127. if (preg_match_all(_EXTRAIRE_MULTI, $letexte, $regs, PREG_SET_ORDER)) {
  1128. if (!$lang) $lang = $GLOBALS['spip_lang'];
  1129. foreach ($regs as $reg) {
  1130. // chercher la version de la langue courante
  1131. $trads = extraire_trads($reg[1]);
  1132. if ($l = approcher_langue($trads, $lang)) {
  1133. $trad = $trads[$l];
  1134. } else {
  1135. include_spip('inc/texte');
  1136. // langue absente, prendre la premiere dispo
  1137. // mais typographier le texte selon les regles de celle-ci
  1138. // Attention aux blocs multi sur plusieurs lignes
  1139. $l = key($trads);
  1140. $trad = $trads[$l];
  1141. $typographie = charger_fonction(lang_typo($l), 'typographie');
  1142. $trad = traiter_retours_chariots($typographie($trad));
  1143. $trad = explode("\n", $trad);
  1144. foreach($trad as $i => $ligne) {
  1145. if (strlen($ligne)) {
  1146. $ligne = code_echappement($ligne, 'multi');
  1147. $ligne = str_replace("'", '"', inserer_attribut($ligne, 'lang', $l));
  1148. if (lang_dir($l) !== lang_dir($lang))
  1149. $ligne = str_replace("'", '"', inserer_attribut($ligne, 'dir', lang_dir($l)));
  1150. $trad[$i] = $ligne;
  1151. }
  1152. }
  1153. $trad = join("\n", $trad);
  1154. if (!$echappe_span)
  1155. $trad = echappe_retour($trad, 'multi');
  1156. }
  1157. $letexte = str_replace($reg[0], $trad, $letexte);
  1158. }
  1159. }
  1160. return $letexte;
  1161. }
  1162. //
  1163. // Selection dans un tableau dont les index sont des noms de langues
  1164. // de la valeur associee a la langue en cours
  1165. // si absente, retourne le premier
  1166. // remarque : on pourrait aussi appeler un service de traduction externe
  1167. // ou permettre de choisir une langue "plus proche",
  1168. // par exemple le francais pour l'espagnol, l'anglais pour l'allemand, etc.
  1169. function multi_trad ($trads, $lang='') {
  1170. $k = multi_trads($trads, $lang);
  1171. return $k ? $trads[$k] : array_shift($trads);
  1172. }
  1173. // idem, mais retourne l'index
  1174. function multi_trads ($trads, $lang='') {
  1175. if (!$lang) $lang = $GLOBALS['spip_lang'];
  1176. if (isset($trads[$lang])) {
  1177. return $lang;
  1178. } // cas des langues xx_yy
  1179. else if (preg_match(',^([a-z]+)_,', $lang, $regs) AND isset($trads[$regs[1]])) {
  1180. return $regs[1];
  1181. }
  1182. else return '';
  1183. }
  1184. // convertit le contenu d'une balise multi en un tableau
  1185. // http://doc.spip.org/@extraire_trad
  1186. function extraire_trads($bloc) {
  1187. $lang = '';
  1188. // ce reg fait planter l'analyse multi s'il y a de l'{italique} dans le champ
  1189. // while (preg_match("/^(.*?)[{\[]([a-z_]+)[}\]]/siS", $bloc, $regs)) {
  1190. while (preg_match("/^(.*?)[\[]([a-z_]+)[\]]/siS", $bloc, $regs)) {
  1191. $texte = trim($regs[1]);
  1192. if ($texte OR $lang)
  1193. $trads[$lang] = $texte;
  1194. $bloc = substr($bloc, strlen($regs[0]));
  1195. $lang = $regs[2];
  1196. }
  1197. $trads[$lang] = $bloc;
  1198. return $trads;
  1199. }
  1200. //
  1201. // Ce filtre retourne la donnee si c'est la premiere fois qu'il la voit ;
  1202. // possibilite de gerer differentes "familles" de donnees |unique{famille}
  1203. # |unique{famille,1} affiche le nombre d'elements affiches (preferer toutefois #TOTAL_UNIQUE)
  1204. # ameliorations possibles :
  1205. # 1) si la donnee est grosse, mettre son md5 comme cle
  1206. # 2) purger $mem quand on change de squelette (sinon bug inclusions)
  1207. //
  1208. // http://www.spip.net/@unique
  1209. // http://doc.spip.org/@unique
  1210. function unique($donnee, $famille='', $cpt = false) {
  1211. static $mem;
  1212. // permettre de vider la pile et de la restaurer
  1213. // pour le calcul de introduction...
  1214. if ($famille=='_spip_raz_'){
  1215. $tmp = $mem;
  1216. $mem = array();
  1217. return $tmp;
  1218. } elseif ($famille=='_spip_set_'){
  1219. $mem = $donnee;
  1220. return;
  1221. }
  1222. if ($cpt)
  1223. return count($mem[$famille]);
  1224. if (!($mem[$famille][$donnee]++))
  1225. return $donnee;
  1226. }
  1227. //
  1228. // Filtre |alterner
  1229. //
  1230. // Exemple [(#COMPTEUR_BOUCLE|alterner{'bleu','vert','rouge'})]
  1231. //
  1232. // http://doc.spip.org/@alterner
  1233. function alterner($i) {
  1234. // recuperer les arguments (attention fonctions un peu space)
  1235. $num = func_num_args();
  1236. $args = func_get_args();
  1237. if($num == 2 && is_array($args[1])) {
  1238. $args = $args[1];
  1239. array_unshift($args,'');
  1240. $num = count($args);
  1241. }
  1242. // renvoyer le i-ieme argument, modulo le nombre d'arguments
  1243. return $args[(intval($i)-1)%($num-1)+1];
  1244. }
  1245. // recuperer un attribut d'une balise html
  1246. // ($complet demande de retourner $r)
  1247. // la regexp est mortelle : cf. tests/filtres/extraire_attribut.php
  1248. // Si on a passe un tableau de balises, renvoyer un tableau de resultats
  1249. // (dans ce cas l'option $complet n'est pas disponible)
  1250. // http://doc.spip.org/@extraire_attribut
  1251. function extraire_attribut($balise, $attribut, $complet = false) {
  1252. if (is_array($balise)) {
  1253. array_walk($balise,
  1254. create_function('&$a,$key,$t',
  1255. '$a = extraire_attribut($a,$t);'
  1256. ),
  1257. $attribut);
  1258. return $balise;
  1259. }
  1260. if (preg_match(
  1261. ',(^.*?<(?:(?>\s*)(?>[\w:.-]+)(?>(?:=(?:"[^"]*"|\'[^\']*\'|[^\'"]\S*))?))*?)(\s+'
  1262. .$attribut
  1263. .'(?:=\s*("[^"]*"|\'[^\']*\'|[^\'"]\S*))?)()([^>]*>.*),isS',
  1264. $balise, $r)) {
  1265. if ($r[3][0] == '"' || $r[3][0] == "'") {
  1266. $r[4] = substr($r[3], 1, -1);
  1267. $r[3] = $r[3][0];
  1268. } elseif ($r[3]!=='') {
  1269. $r[4] = $r[3];
  1270. $r[3] = '';
  1271. } else {
  1272. $r[4] = trim($r[2]);
  1273. }
  1274. $att = filtrer_entites(str_replace("&#39;", "'", $r[4]));
  1275. }
  1276. else
  1277. $att = NULL;
  1278. if ($complet)
  1279. return array($att, $r);
  1280. else
  1281. return $att;
  1282. }
  1283. // modifier (ou inserer) un attribut html dans une balise
  1284. // http://doc.spip.org/@inserer_attribut
  1285. function inserer_attribut($balise, $attribut, $val, $proteger=true, $vider=false) {
  1286. // preparer l'attribut
  1287. // supprimer les &nbsp; etc mais pas les balises html
  1288. // qui ont un sens dans un attribut value d'un input
  1289. if ($proteger) $val = attribut_html($val,false);
  1290. // echapper les ' pour eviter tout bug
  1291. $val = str_replace("'", "&#39;", $val);
  1292. if ($vider AND strlen($val)==0)
  1293. $insert = '';
  1294. else
  1295. $insert = " $attribut='$val'";
  1296. list($old, $r) = extraire_attribut($balise, $attribut, true);
  1297. if ($old !== NULL) {
  1298. // Remplacer l'ancien attribut du meme nom
  1299. $balise = $r[1].$insert.$r[5];
  1300. }
  1301. else {
  1302. // preferer une balise " />" (comme <img />)
  1303. if (preg_match(',/>,', $balise))
  1304. $balise = preg_replace(",\s?/>,S", $insert." />", $balise, 1);
  1305. // sinon une balise <a ...> ... </a>
  1306. else
  1307. $balise = preg_replace(",\s?>,S", $insert.">", $balise, 1);
  1308. }
  1309. return $balise;
  1310. }
  1311. // http://doc.spip.org/@vider_attribut
  1312. function vider_attribut ($balise, $attribut) {
  1313. return inserer_attribut($balise, $attribut, '', false, true);
  1314. }
  1315. // Un filtre pour determiner le nom du mode des librement inscrits,
  1316. // a l'aide de la liste globale des statuts (tableau mode => nom du mode)
  1317. // Utile pour le formulaire d'inscription.
  1318. // Si un mode est fourni, verifier que la configuration l'accepte.
  1319. // Si mode inconnu laisser faire, c'est une extension non std
  1320. // mais verifier que la syntaxe est compatible avec SQL
  1321. // http://doc.spip.org/@tester_config
  1322. function tester_config($id, $mode='') {
  1323. $s = array_search($mode, $GLOBALS['liste_des_statuts']);
  1324. switch ($s) {
  1325. case 'info_redacteurs' :
  1326. return (($GLOBALS['meta']['accepter_inscriptions'] == 'oui') ? $mode : '');
  1327. case 'info_visiteurs' :
  1328. return (($GLOBALS['meta']['accepter_visiteurs'] == 'oui' OR $GLOBALS['meta']['forums_publics'] == 'abo') ? $mode : '');
  1329. default:
  1330. if ($mode AND $mode == addslashes($mode))
  1331. return $mode;
  1332. if ($GLOBALS['meta']["accepter_inscriptions"] == "oui")
  1333. return $GLOBALS['liste_des_statuts']['info_redacteurs'];
  1334. if ($GLOBALS['meta']["accepter_visiteurs"] == "oui")
  1335. return $GLOBALS['liste_des_statuts']['info_visiteurs'];
  1336. return '';
  1337. }
  1338. }
  1339. //
  1340. // Un filtre qui, etant donne un #PARAMETRES_FORUM, retourne un URL de suivi rss
  1341. // dudit forum
  1342. // Attention applique a un #PARAMETRES_FORUM complexe (id_article=x&id_forum=y)
  1343. // ca retourne un url de suivi du thread y (que le thread existe ou non)
  1344. // http://doc.spip.org/@url_rss_forum
  1345. function url_rss_forum($param) {
  1346. if (!preg_match(',.*(id_(\w*?))=([0-9]+),S', $param, $regs)) return '';
  1347. list(,$k,$t,$v) = $regs;
  1348. if ($t == 'forum') $k = 'id_' . ($t = 'thread');
  1349. return generer_url_public("rss_forum_$t", array($k => $v));
  1350. }
  1351. //
  1352. // Un filtre applique a #PARAMETRES_FORUM, qui donne l'adresse de la page
  1353. // de reponse
  1354. //
  1355. // http://doc.spip.org/@url_reponse_forum
  1356. function url_reponse_forum($parametres) {
  1357. if (!$parametres) return '';
  1358. return generer_url_public('forum', $parametres);
  1359. }
  1360. //
  1361. // Quelques fonctions de calcul arithmetique
  1362. //
  1363. // http://doc.spip.org/@plus
  1364. function plus($a,$b) {
  1365. return $a+$b;
  1366. }
  1367. // http://doc.spip.org/@moins
  1368. function moins($a,$b) {
  1369. return $a-$b;
  1370. }
  1371. // http://doc.spip.org/@mult
  1372. function mult($a,$b) {
  1373. return $a

Large files files are truncated, but you can click here to view the full file