X-Git-Url: http://git.cyclocoop.org/?p=ptitvelo%2Fweb%2Fwww.git;a=blobdiff_plain;f=www%2Fecrire%2Finc%2Ffiltres.php;h=39fe12e4cd591ab953d5dc8a3f635d577e0b2e36;hp=971b8637dfeaa18ea83d11417912bb936a3bfa88;hb=e847eea4a82a7396dd0abf860f9b30d654f38629;hpb=52cf8ed924d5dcd0c28dde4b6c3196be6ec2d4f7 diff --git a/www/ecrire/inc/filtres.php b/www/ecrire/inc/filtres.php index 971b863..39fe12e 100644 --- a/www/ecrire/inc/filtres.php +++ b/www/ecrire/inc/filtres.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2012 * + * Copyright (c) 2001-2014 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * @@ -68,11 +68,33 @@ function chercher_filtre($fonc, $default=NULL) { return $default; } -// http://doc.spip.org/@appliquer_filtre -function appliquer_filtre($arg, $filtre) { +/** + * Applique un filtre + * + * Fonction générique qui prend en argument l’objet (texte, etc) à modifier + * et le nom du filtre. Retrouve les arguments du filtre demandé dans les arguments + * transmis à cette fonction, via func_get_args(). + * + * @see filtrer() Assez proche + * + * @param string $arg + * Texte sur lequel appliquer le filtre + * @param string $filtre + * Nom du filtre a appliquer + * @param string $force + * La fonction doit-elle retourner le texte ou rien ? + * @return string + * Texte avec le filtre appliqué s'il a été trouvé, + * Texte sans le filtre appliqué s'il n'a pas été trouvé et que $force n'a + * pas été fourni, + * Chaîne vide si le filtre n'a pas été trouvé et que $force a été fourni. +**/ +function appliquer_filtre($arg, $filtre, $force=NULL) { $f = chercher_filtre($filtre); - if (!$f) - return ''; // ou faut-il retourner $arg inchange == filtre_identite? + if (!$f) { + if (!$force) return ''; + else return $arg; + } $args = func_get_args(); array_shift($args); // enlever $arg @@ -167,6 +189,39 @@ function filtrer($filtre) { } } +/* + * + * [(#CALCUL|set{toto})] enregistre le résultat de #CALCUL + * dans la variable toto et renvoie vide + * + * [(#CALCUL|set{toto,1})] enregistre le résultat de #CALCUL + * dans la variable toto et renvoie la valeur + * + */ +function filtre_set(&$Pile, $val, $key, $continue = null) { + $Pile['vars'][$key] = $val; + return $continue ? $val : ''; +} + +/* + * [(#TRUC|debug{avant}|calcul|debug{apres}|etc)] affiche + * la valeur de #TRUC avant et après le calcul + */ +function filtre_debug($val, $key=null) { + $debug = ( + is_null($key) ? '' : (var_export($key,true)." = ") + ) . var_export($val, true); + + include_spip('inc/autoriser'); + if (autoriser('webmestre')) + echo "
\n",$debug,"
\n"; + + spip_log($debug, 'debug'); + + return $val; +} + + // fonction generique d'entree des filtres images // accepte en entree un texte complet, un img-log (produit par #LOGO_XX), // un tag complet, ou encore un nom de fichier *local* (passer @@ -341,7 +396,8 @@ function entites_html($texte, $tout=false, $quote=true) { OR strpbrk($texte, "&\"'<>")==false ) return $texte; include_spip('inc/texte'); - $texte = htmlspecialchars(echappe_retour(echappe_html($texte,'',true),'','proteger_amp'),$quote?ENT_QUOTES:(ENT_COMPAT|ENT_HTML401)); + $flags = !defined('PHP_VERSION_ID') OR PHP_VERSION_ID < 50400 ? ENT_COMPAT : ENT_COMPAT|ENT_HTML401; + $texte = spip_htmlspecialchars(echappe_retour(echappe_html($texte, '', true), '', 'proteger_amp'), $quote?ENT_QUOTES:$flags); if ($tout) return corriger_toutes_entites_html($texte); else @@ -355,7 +411,12 @@ function filtrer_entites($texte) { // filtrer $texte = html2unicode($texte); // remettre le tout dans le charset cible - return unicode2charset($texte); + $texte = unicode2charset($texte); + // cas particulier des " et ' qu'il faut filtrer aussi + // (on le faisait deja avec un ") + if (strpos($texte,"&#")!==false) + $texte = str_replace(array("'","'",""","""), array("'","'",'"','"'), $texte); + return $texte; } // caracteres de controle - http://www.w3.org/TR/REC-xml/#charsets @@ -408,6 +469,8 @@ function texte_backend($texte) { $texte = preg_replace('/\s{2,}/S'.$u, " ", $texte); // ne pas echapper les sinqle quotes car certains outils de syndication gerent mal $texte = entites_html($texte, false, false); + // mais bien echapper les double quotes ! + $texte = str_replace('"','"',$texte); // verifier le charset $texte = charset2unicode($texte); @@ -445,7 +508,7 @@ function recuperer_numero($texte) { if (preg_match( ",^[[:space:]]*([0-9]+)([.)]|".chr(194).'?'.chr(176).")[[:space:]]+,S", $texte, $regs)) - return intval($regs[1]); + return strval($regs[1]); else return ''; } @@ -490,6 +553,29 @@ function liens_ouvrants ($texte) { "", $texte); } +/** + * Ajouter un attribut rel="nofollow" sur tous les liens d'un texte + * @param string $texte + * @return string + */ +function liens_nofollow($texte) { + if (stripos($texte,"]*>,UimsS",$texte, $regs, PREG_PATTERN_ORDER)){ + foreach($regs[0] as $a){ + $rel = extraire_attribut($a,"rel"); + if (strpos($rel,"nofollow")===false){ + $rel = "nofollow" . ($rel?" $rel":""); + $anofollow = inserer_attribut($a,"rel",$rel); + $texte = str_replace($a,$anofollow,$texte); + } + } + } + + return $texte; +} + // Transformer les sauts de paragraphe en simples passages a la ligne // http://doc.spip.org/@PtoBR function PtoBR($texte){ @@ -582,14 +668,9 @@ function attribut_html($texte,$textebrut = true) { function vider_url($url, $entites = true) { # un message pour abs_url $GLOBALS['mode_abs_url'] = 'url'; - $url = trim($url); - if (preg_match(",^(http:?/?/?|mailto:?)$,iS", $url)) - return ''; - - if ($entites) $url = entites_html($url); - - return $url; + $r = ",^(?:" . _PROTOCOLES_STD . '):?/?/?$,iS'; + return preg_match($r, $url) ? '': ($entites ? entites_html($url) : $url); } // Extraire une date de n'importe quel champ (a completer...) @@ -926,6 +1007,7 @@ function affdate_base($numdate, $vue, $options = array()) { switch ($vue) { case 'saison': + case 'saison_annee': $saison = ''; if ($mois > 0){ $saison = 1; @@ -934,7 +1016,10 @@ function affdate_base($numdate, $vue, $options = array()) { if (($mois == 9 AND $jour >= 21) OR $mois > 9) $saison = 4; if (($mois == 12 AND $jour >= 21) OR $mois > 12) $saison = 1; } - return $saison?_T('date_saison_'.$saison):''; + if($vue == 'saison') + return $saison?_T('date_saison_'.$saison):''; + else + return $saison?trim(_T('date_fmt_saison_annee', array('saison'=>_T('date_saison_'.$saison), 'annee'=>$annee))) :''; case 'court': if ($avjc) return $annee; @@ -1034,6 +1119,11 @@ function saison($numdate) { return affdate_base($numdate, 'saison'); } +// http://doc.spip.org/@saison_annee +function saison_annee($numdate) { + return affdate_base($numdate, 'saison_annee'); +} + // http://doc.spip.org/@affdate function affdate($numdate, $format='entier') { return affdate_base($numdate, $format); @@ -1080,6 +1170,10 @@ function affdate_heure($numdate) { * @param string $date_fin * @param string $horaire * @param string $forme + * abbr pour afficher le nom du jour en abbrege (Dim. au lieu de Dimanche) + * annee pour forcer l'affichage de l'annee courante + * jour pour forcer l'affichage du nom du jour + * hcal pour pour avoir un markup microformat abbr * @return string */ function affdate_debut_fin($date_debut, $date_fin, $horaire = 'oui', $forme=''){ @@ -1117,14 +1211,14 @@ function affdate_debut_fin($date_debut, $date_fin, $horaire = 'oui', $forme=''){ }else{ // Le lundi 20 fevrier de 18h00 a 20h00 if($dtabbr && $dtstart && $dtend) - $s = spip_ucfirst(_T('date_fmt_jour_heure_debut_fin_abbr',array('jour'=>$s,'heure_debut'=>$hd,'heure_fin'=>$hf,'dtstart'=>$dtstart,'dtend'=>$dtend,'dtabbr'=>$dtabbr))); + $s = _T('date_fmt_jour_heure_debut_fin_abbr',array('jour'=>spip_ucfirst($s),'heure_debut'=>$hd,'heure_fin'=>$hf,'dtstart'=>$dtstart,'dtend'=>$dtend,'dtabbr'=>$dtabbr)); // Le lundi 20 fevrier de 18h00 a 20h00 else $s = spip_ucfirst(_T('date_fmt_jour_heure_debut_fin',array('jour'=>$s,'heure_debut'=>$hd,'heure_fin'=>$hf))); } }else{ if($dtabbr && $dtstart) - $s = $dtstart.spip_ucfirst($s).$dabbr; + $s = $dtstart.spip_ucfirst($s).$dtabbr; else $s = spip_ucfirst($s); } @@ -1134,7 +1228,7 @@ function affdate_debut_fin($date_debut, $date_fin, $horaire = 'oui', $forme=''){ if(!$h) $date_debut = jour($d); else - $date_debut = $affdate($d); + $date_debut = affdate_jourcourt($d,date("Y",$date_fin)); $date_fin = $affdate($f); if($jour){ $nomjour_debut = nom_jour($d,$abbr); @@ -1152,13 +1246,13 @@ function affdate_debut_fin($date_debut, $date_fin, $horaire = 'oui', $forme=''){ $s = _T('date_fmt_periode',array('date_debut' => $date_debut,'date_fin'=>$date_fin)); } else { - $date_debut = affdate($d); - $date_fin = affdate($f); + $date_debut = affdate_jourcourt($d,date("Y",$date_fin)); + $date_fin = $affdate($f); if($jour){ $nomjour_debut = nom_jour($d,$abbr); - $date_debut = _T('date_fmt_jour_periode',array('nomjour'=>$nomjour_debut,'jour' => $date_debut)); + $date_debut = _T('date_fmt_jour',array('nomjour'=>$nomjour_debut,'jour' => $date_debut)); $nomjour_fin = nom_jour($f,$abbr); - $date_fin = _T('date_fmt_jour_periode',array('nomjour'=>$nomjour_fin,'jour' => $date_fin)); + $date_fin = _T('date_fmt_jour',array('nomjour'=>$nomjour_fin,'jour' => $date_fin)); } if ($h){ $date_debut = _T('date_fmt_jour_heure',array('jour'=>$date_debut,'heure'=>$hd)); @@ -1399,6 +1493,11 @@ function extraire_trads($bloc) { return $trads; } +// Calculer l'initiale d'un nom +function initiale($nom){ + return spip_substr(trim(strtoupper(extraire_multi($nom))),0,1); +} + // // Ce filtre retourne la donnee si c'est la premiere fois qu'il la voit ; // possibilite de gerer differentes "familles" de donnees |unique{famille} @@ -1488,7 +1587,10 @@ function extraire_attribut($balise, $attribut, $complet = false) { } else { $r[4] = trim($r[2]); } - $att = filtrer_entites(str_replace("'", "'", $r[4])); + $att = $r[4]; + if (strpos($att,"&#")!==false) + $att = str_replace(array("'","'",""","""), array("'","'",'"','"'), $att); + $att = filtrer_entites($att); } else $att = NULL; @@ -1550,13 +1652,14 @@ function vider_attribut ($balise, $attribut) { /** * Un filtre pour determiner le nom du satut des inscrits - * @param void $dummy + * + * @param void|int $id * @param string $mode * @return string */ -function tester_config($dummy, $mode='') { +function tester_config($id, $mode='') { include_spip('action/inscrire_auteur'); - return tester_statut_inscription($mode); + return tester_statut_inscription($mode, $id); } // @@ -1584,6 +1687,34 @@ function modulo($nb, $mod, $add=0) { } +/** + * Vérifie qu'un nom (d'auteur) ne comporte pas d'autres tags que + * et ceux volontairement spécifiés dans la constante + * + * @param string $nom + * Nom (signature) proposé + * @return bool + * - false si pas conforme, + * - true sinon +**/ +function nom_acceptable($nom) { + if (!is_string($nom)) { + return false; + } + if (!defined('_TAGS_NOM_AUTEUR')) define('_TAGS_NOM_AUTEUR',''); + $tags_acceptes = array_unique(explode(',', 'multi,' . _TAGS_NOM_AUTEUR)); + foreach($tags_acceptes as $tag) { + if (strlen($tag)) { + $remp1[] = '<'.trim($tag).'>'; + $remp1[] = ''; + $remp2[] = '\x60'.trim($tag).'\x61'; + $remp2[] = '\x60/'.trim($tag).'\x61'; + } + } + $v_nom = str_replace($remp2, $remp1, supprimer_tags(str_replace($remp1, $remp2, $nom))); + return str_replace('<', '<', $v_nom) == $nom; +} + // Verifier la conformite d'une ou plusieurs adresses email // retourne false ou la normalisation de la derniere adresse donnee // http://doc.spip.org/@email_valide @@ -1649,9 +1780,9 @@ function enclosure2microformat($e) { } $fichier = basename($url); return ''.$fichier.''; } // La fonction inverse @@ -1666,8 +1797,8 @@ function microformat2enclosure($tags) { $length = intval(extraire_attribut($e, 'length')); # vieux data $fichier = basename($url); $enclosures[] = ''; } @@ -2186,16 +2317,17 @@ function concat(){ // http://doc.spip.org/@charge_scripts -function charge_scripts($scripts) { - $flux = ""; - $args = is_array($scripts)?$scripts:explode("|",$scripts); - foreach($args as $script) { - if(preg_match(",^\w+$,",$script)) { - $path = find_in_path("javascript/$script.js"); - if($path) $flux .= spip_file_get_contents($path); - } - } - return $flux; +// http://doc.spip.org/@charge_scripts +function charge_scripts($files, $script = true) { + $flux = ""; + foreach(is_array($files)?$files:explode("|",$files) as $file) { + if (!is_string($file)) continue; + if ($script) + $file = preg_match(",^\w+$,",$file) ? "javascript/$file.js" : ''; + if ($file) $path = find_in_path($file); + if ($path) $flux .= spip_file_get_contents($path); + } + return $flux; } @@ -2849,6 +2981,7 @@ function generer_info_entite($id_objet, $type_objet, $info, $etoile=""){ if (!$etoile AND is_array($traitement) AND (isset($traitement[$table_sql]) OR isset($traitement[0]))){ + include_spip('inc/texte'); $traitement = $traitement[isset($traitement[$table_sql]) ? $table_sql : 0]; $traitement = str_replace('%s', "'".texte_script($info_generee)."'", $traitement); // FIXME: $connect et $Pile[0] font souvent partie des traitements. @@ -2879,20 +3012,54 @@ function wrap($texte,$wrap) { } -// afficher proprement n'importe quoi -// en cas de table profonde, l'option $join ne s'applique qu'au plus haut niveau -// c'est VOULU ! Exemple : [(#VALEUR|print{
})] va afficher de gros blocs -// separes par des lignes, avec a l'interieur des trucs separes par des virgules -function filtre_print_dist($u, $join=', ') { - if (is_string($u)) - return typo($u); - - if (is_array($u)) - return join($join, array_map('filtre_print_dist', $u)); +/** + * afficher proprement n'importe quoi + * On affiche in fine un pseudo-yaml qui premet de lire humainement les tableaux et de s'y reperer + * + * Les textes sont retournes avec simplement mise en forme typo + * + * le $join sert a separer les items d'un tableau, c'est en general un \n ou
selon si on fait du html ou du texte + * les tableaux-listes (qui n'ont que des cles numeriques), sont affiches sous forme de liste separee par des virgules : + * c'est VOULU ! + * + * @param $u + * @param string $join + * @param int $indent + * @return array|mixed|string + */ +function filtre_print_dist($u, $join="
", $indent=0) { + if (is_string($u)){ + $u = typo($u); + return $u; + } + // caster $u en array si besoin if (is_object($u)) - return join($join, array_map('filtre_print_dist', (array) $u)); + $u = (array) $u; + + if (is_array($u)){ + $out = ""; + // toutes les cles sont numeriques ? + // et aucun enfant n'est un tableau + // liste simple separee par des virgules + $numeric_keys = array_map('is_numeric',array_keys($u)); + $array_values = array_map('is_array',$u); + $object_values = array_map('is_object',$u); + if (array_sum($numeric_keys)==count($numeric_keys) + AND !array_sum($array_values) + AND !array_sum($object_values)){ + return join(", ", array_map('filtre_print_dist', $u)); + } + // sinon on passe a la ligne et on indente + $i_str = str_pad("",$indent," "); + foreach($u as $k => $v){ + $out .= $join . $i_str . "$k: " . filtre_print_dist($v,$join,$indent+2); + } + return $out; + } + + // on sait pas quoi faire... return $u; } @@ -2995,10 +3162,12 @@ function produire_fond_statique($fond, $contexte=array(), $options = array(), $c // mettre a jour le fichier si il n'existe pas // ou trop ancien + // le dernier fichier produit est toujours suffixe par .last + // et recopie sur le fichier cible uniquement si il change if (!file_exists($filename) - OR (isset($cache['lastmodified']) AND $cache['lastmodified'] AND filemtime($filename)<$cache['lastmodified']) - OR (defined('_VAR_MODE') AND _VAR_MODE=='recalcul')) - { + OR !file_exists($filename.".last") + OR (isset($cache['lastmodified']) AND $cache['lastmodified'] AND filemtime($filename.".last")<$cache['lastmodified']) + OR (defined('_VAR_MODE') AND _VAR_MODE=='recalcul')) { $contenu = $cache['texte']; // passer les urls en absolu si c'est une css if ($extension=="css") @@ -3009,10 +3178,18 @@ function produire_fond_statique($fond, $contexte=array(), $options = array(), $c $comment = "/* #PRODUIRE{fond=$fond"; foreach($contexte as $k=>$v) $comment .= ",$k=$v"; - $comment .="} le ".date("Y-m-d H:i:s")." */\n"; + // pas de date dans le commentaire car sinon ca invalide le md5 et force la maj + // mais on peut mettre un md5 du contenu, ce qui donne un aperu rapide si la feuille a change ou non + $comment .="}\n md5:".md5($contenu)." */\n"; } // et ecrire le fichier - ecrire_fichier($filename,$comment.$contenu); + ecrire_fichier($filename.".last",$comment.$contenu); + // regarder si on recopie + if (!file_exists($filename) + OR md5_file($filename)!==md5_file($filename.".last")){ + @copy($filename.".last",$filename); + spip_clearstatcache(true,$filename); // eviter que PHP ne reserve le vieux timestamp + } } return $filename; @@ -3026,7 +3203,7 @@ function produire_fond_statique($fond, $contexte=array(), $options = array(), $c * @return string */ function timestamp($fichier){ - if (!$fichier) return $fichier; + if (!$fichier OR !file_exists($fichier)) return $fichier; $m = filemtime($fichier); return "$fichier?$m"; }