3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2012 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
13 if (!defined('_ECRIRE_INC_VERSION')) return;
14 include_spip('base/objets');
17 * Decoder une url en utilisant les fonctions inverse
18 * gestion des URLs transformee par le htaccess
19 * $renommer = 'urls_propres_dist';
20 * renvoie array($contexte, $type, $url_redirect, $nfond)
21 * $nfond n'est retourne que si l'url est definie apres le ?
22 * et risque d'etre effacee par un form en get
23 * elle est utilisee par form_hidden exclusivement
24 * Compat ascendante si le retour est null en gerant une sauvegarde/restauration
25 * des globales modifiees par les anciennes fonctions
30 * fond initial par defaut
31 * @param array $contexte
32 * contexte initial a prendre en compte
33 * @param bool $assembler
34 * true si l'url correspond a l'url principale de la page qu'on est en train d'assembler
35 * dans ce cas la fonction redirigera automatiquement si besoin
36 * et utilisera les eventuelles globales $_SERVER['REDIRECT_url_propre'] et $_ENV['url_propre']
37 * provenant du htaccess
39 * ($fond,$contexte,$url_redirect)
40 * si l'url n'est pas valide, $fond restera a la valeur initiale passee
41 * il suffit d'appeler la fonction sans $fond et de verifier qu'a son retour celui-ci
42 * est non vide pour verifier une url
45 function urls_decoder_url($url, $fond='', $contexte=array(), $assembler=false){
46 static $current_base = null;
47 // les anciennes fonctions modifient directement les globales
48 // on les sauve avant l'appel, et on les retablit apres !
49 $save = array(@$GLOBALS['fond'],@$GLOBALS['contexte'],@$_SERVER['REDIRECT_url_propre'],@$_ENV['url_propre'],$GLOBALS['profondeur_url']);
50 if (is_null($current_base)){
51 include_spip('inc/filtres_mini');
52 // le decodage des urls se fait toujours par rapport au site public
53 $current_base = url_absolue(_DIR_RACINE?_DIR_RACINE
:'./');
55 if (strncmp($url,$current_base,strlen($current_base))==0)
56 $url = substr($url,strlen($current_base));
58 // si on est pas en train d'assembler la page principale,
59 // vider les globales url propres qui ne doivent pas etre utilisees en cas
60 // d'inversion url => objet
62 unset($_SERVER['REDIRECT_url_propre']);
63 unset($_ENV['url_propre']);
64 include_spip('inc/filtres_mini');
65 if (strpos($url,"://")===false){
66 $GLOBALS['profondeur_url'] = substr_count(ltrim(resolve_path("/$url"),'/'),'/');
69 $GLOBALS['profondeur_url'] = max(0,substr_count($url,"/")-substr_count($current_base,"/"));
75 $renommer = generer_url_entite('','','','',true);
76 if (!$renommer AND !function_exists('recuperer_parametres_url'))
77 $renommer = charger_fonction('page','urls'); // fallback pour decoder l'url
79 $a = $renommer($url, $fond, $contexte);
81 list($ncontexte, $type, $url_redirect, $nfond) = array_pad($a, 4, null);
82 if ($url_redirect == $url)
83 $url_redirect = ""; // securite pour eviter une redirection infinie
84 if ($assembler AND strlen($url_redirect)) {
85 spip_log("Redirige $url vers $url_redirect");
86 include_spip('inc/headers');
87 redirige_par_entete($url_redirect, '', 301);
92 OR $fond == 'type_urls' /* compat avec htaccess 2.0.0 */
95 if (isset($ncontexte))
96 $contexte = $ncontexte;
97 if (defined('_DEFINIR_CONTEXTE_TYPE') AND _DEFINIR_CONTEXTE_TYPE
)
98 $contexte['type'] = $type;
99 if (defined('_DEFINIR_CONTEXTE_TYPE_PAGE') AND _DEFINIR_CONTEXTE_TYPE_PAGE
)
100 $contexte['type-page'] = $type;
103 // compatibilite <= 1.9.2
104 elseif (function_exists('recuperer_parametres_url')) {
105 $GLOBALS['fond'] = $fond;
106 $GLOBALS['contexte'] = $contexte;
107 recuperer_parametres_url($fond, nettoyer_uri());
108 // fond est en principe modifiee directement
109 $contexte = $GLOBALS['contexte'];
112 // retablir les globales
113 list($GLOBALS['fond'],$GLOBALS['contexte'],$_SERVER['REDIRECT_url_propre'],$_ENV['url_propre'],$GLOBALS['profondeur_url']) = $save;
115 // vider les globales url propres qui ne doivent plus etre utilisees en cas
116 // d'inversion url => objet
117 // maintenir pour compat ?
119 # unset($_SERVER['REDIRECT_url_propre']);
120 # unset($_ENV['url_propre']);
123 return array($fond,$contexte,$url_redirect);
128 * Lister les objets pris en compte dans les urls
129 * c'est a dire suceptibles d'avoir une url propre
132 * permet de definir si la fonction retourne une chaine avec | comme separateur
133 * pour utiliser en preg, ou un array()
134 * @return string/array
136 function urls_liste_objets($preg = true){
137 static $url_objets = null;
138 if (is_null($url_objets)){
139 $url_objets = array();
140 // recuperer les tables_objets_sql declarees
141 $tables_objets = lister_tables_objets_sql();
142 foreach($tables_objets as $t=>$infos){
143 if ($infos['page']) {
144 $url_objets[] = $infos['type'];
145 $url_objets = array_merge($url_objets,$infos['type_surnoms']);
148 $url_objets = pipeline('declarer_url_objets',$url_objets);
150 if (!$preg) return $url_objets;
151 return implode('|',array_map('preg_quote',$url_objets));
155 * Nettoyer une url, en reperant notamment les raccourcis d'entites
156 * comme ?article13, ?rubrique21 ...
157 * et en les traduisant pour completer le contexte fourni en entree
160 * @param array $contexte
163 function nettoyer_url_page($url, $contexte=array())
165 $url_objets = urls_liste_objets();
166 $raccourci_url_page_html = ',^(?:[^?]*/)?('. $url_objets . ')([0-9]+)(?:\.html)?([?&].*)?$,';
167 $raccourci_url_page_id = ',^(?:[^?]*/)?('. $url_objets .')\.php3?[?]id_\1=([0-9]+)([?&].*)?$,';
168 $raccourci_url_page_spip = ',^(?:[^?]*/)?(?:spip[.]php)?[?]('. $url_objets .')([0-9]+)(&.*)?$,';
170 if (preg_match($raccourci_url_page_html, $url, $regs)
171 OR preg_match($raccourci_url_page_id, $url, $regs)
172 OR preg_match($raccourci_url_page_spip, $url, $regs)) {
173 $type = objet_type($regs[1]);
174 $_id = id_table_objet($type);
175 $contexte[$_id] = $regs[2];
177 return array($contexte, $type, null, $type, $suite);
183 * Generer l'url d'un objet dans l'espace prive,
184 * fonction de son etat publie ou non
185 * calcule a partir de la declaration de statut
188 * @param string $args
189 * @param string $ancre
190 * @param string $statut
191 * @param string $connect
195 function generer_url_ecrire_objet($objet,$id, $args='', $ancre='', $public=null, $connect=''){
196 static $furls = array();
197 if (!isset($furls[$objet])){
198 if (function_exists($f = 'generer_url_ecrire_' . $objet)
199 // ou definie par un plugin
200 OR $f = charger_fonction($f,'urls',true))
206 return $furls[$objet]($id, $args, $ancre, $public, $connect);
207 // si pas de flag public fourni
208 // le calculer en fonction de la declaration de statut
209 if (is_null($public) AND !$connect)
210 $public = objet_test_si_publie($objet, $id, $connect);
211 if ($public OR $connect){
212 return generer_url_entite_absolue($id, $objet, $args, $ancre, $connect);
214 $a = id_table_objet($objet) . "=" . intval($id);
215 if (!function_exists('objet_info'))
216 include_spip('inc/filtres');
217 return generer_url_ecrire(objet_info($objet,'url_voir'), $a . ($args ?
"&$args" : '')). ($ancre ?
"#$ancre" : '');