source: spip-zone/_core_/plugins/urls_etendues/urls/propres.php @ 62146

Last change on this file since 62146 was 62146, checked in by marcimat@…, 7 years ago

Correction de notices PHP

File size: 13.8 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2011                                                *
7 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8 *                                                                         *
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\***************************************************************************/
12
13if (!defined("_ECRIRE_INC_VERSION")) return; // securiser
14
15# donner un exemple d'url pour le formulaire de choix
16define('URLS_PROPRES_EXEMPLE', 'Titre-de-l-article -Rubrique-');
17# specifier le form de config utilise pour ces urls
18define('URLS_PROPRES_CONFIG', 'propres');
19
20// TODO: une interface permettant de verifier qu'on veut effectivment modifier
21// une adresse existante
22define('CONFIRMER_MODIFIER_URL', false);
23
24/*
25
26- Comment utiliser ce jeu d'URLs ?
27
28Recopiez le fichier "htaccess.txt" du repertoire de base du site SPIP sous
29le sous le nom ".htaccess" (attention a ne pas ecraser d'autres reglages
30que vous pourriez avoir mis dans ce fichier) ; si votre site est en
31"sous-repertoire", vous devrez aussi editer la ligne "RewriteBase" ce fichier.
32Les URLs definies seront alors redirigees vers les fichiers de SPIP.
33
34Dans les pages de configuration, choisissez 'propres' comme type d'url
35
36SPIP calculera alors ses liens sous la forme
37        "Mon-titre-d-article".
38
39La variante 'propres2' ajoutera '.html' aux adresses generees :
40        "Mon-titre-d-article.html"
41
42Variante 'qs' (experimentale) : ce systeme fonctionne en "Query-String",
43c'est-a-dire sans utilisation de .htaccess ; les adresses sont de la forme
44        "/?Mon-titre-d-article"
45*/
46
47if (!defined('_terminaison_urls_propres')) define ('_terminaison_urls_propres', '');
48if (!defined('_debut_urls_propres')) define ('_debut_urls_propres', '');
49
50$config_urls_propres = isset($GLOBALS['meta']['urls_propres'])?unserialize($GLOBALS['meta']['urls_propres']):array();
51// pour choisir le caractere de separation titre-id en cas de doublon
52// (ne pas utiliser '/')
53if (!defined('_url_propres_sep_id')) define('_url_propres_sep_id',isset($config_urls_propres['url_propres_sep_id'])?$config_urls_propres['url_propres_sep_id']:'-');
54// option pour tout passer en minuscules
55if (!defined('_url_minuscules')) define('_url_minuscules',isset($config_urls_propres['url_minuscules'])?$config_urls_propres['url_minuscules']:0);
56if (!defined('_URLS_PROPRES_MAX')) define('_URLS_PROPRES_MAX', isset($config_urls_propres['URLS_PROPRES_MAX'])?$config_urls_propres['URLS_PROPRES_MAX']:35);
57if (!defined('_URLS_PROPRES_MIN')) define('_URLS_PROPRES_MIN', isset($config_urls_propres['URLS_PROPRES_MIN'])?$config_urls_propres['URLS_PROPRES_MIN']:3);
58
59if (!defined('_url_sep_id')) define('_url_sep_id',_url_propres_sep_id);
60
61// Ces chaines servaient de marqueurs a l'epoque ou les URL propres devaient
62// indiquer la table ou les chercher (articles, auteurs etc),
63// et elles etaient retirees par les preg_match dans la fonction ci-dessous.
64// Elles peuvent a present etre definies a "" pour avoir des URL plus jolies.
65// Les preg_match restent necessaires pour gerer les anciens signets.
66
67if (!defined('_MARQUEUR_URL')) define('_MARQUEUR_URL', serialize(array('rubrique1' => '-', 'rubrique2' => '-', 'breve1' => '+', 'breve2' => '+', 'site1' => '@', 'site2' => '@', 'auteur1' => '_', 'auteur2' => '_', 'mot1' => '+-', 'mot2' => '-+')));
68
69// Retire les marqueurs de type dans une URL propre ancienne maniere
70
71// http://doc.spip.org/@retirer_marqueurs_url_propre
72function retirer_marqueurs_url_propre($url_propre) {
73        if (preg_match(',^[+][-](.*?)[-][+]$,', $url_propre, $regs)) {
74                return $regs[1];
75        }
76        else if (preg_match(',^([-+_@])(.*?)\1?$,', $url_propre, $regs)) {
77                return $regs[2];
78        }
79        // les articles n'ont pas de marqueur
80        return $url_propre;
81}
82
83
84// Pipeline pour creation d'une adresse : il recoit l'url propose par le
85// precedent, un tableau indiquant le titre de l'objet, son type, son id,
86// et doit donner en retour une chaine d'url, sans se soucier de la
87// duplication eventuelle, qui sera geree apres
88// http://doc.spip.org/@creer_chaine_url
89function urls_propres_creer_chaine_url($x) {
90        // NB: ici url_old ne sert pas, mais un plugin qui ajouterait une date
91        // pourrait l'utiliser pour juste ajouter la
92        $url_old = $x['data'];
93        $objet = $x['objet'];
94        include_spip('inc/filtres');
95
96        include_spip('action/editer_url');
97        if (!$url = url_nettoyer($objet['titre'],_URLS_PROPRES_MAX,_URLS_PROPRES_MIN,'-',_url_minuscules?'strtolower':''))
98                $url = $objet['type'].$objet['id_objet'];
99
100        $x['data'] = $url;
101
102        return $x;
103}
104
105// Trouver l'URL associee a la n-ieme cle primaire d'une table SQL
106
107// http://doc.spip.org/@declarer_url_propre
108function declarer_url_propre($type, $id_objet) {
109        $trouver_table = charger_fonction('trouver_table', 'base');
110        $desc = $trouver_table(table_objet($type));
111        $table = $desc['table'];
112        $champ_titre = $desc['titre'] ? $desc['titre'] : 'titre';
113        $col_id =  @$desc['key']["PRIMARY KEY"];
114        if (!$col_id) return false; // Quand $type ne reference pas une table
115
116        $id_objet = intval($id_objet);
117
118
119        // Recuperer une URL propre correspondant a l'objet.
120        // mais urls a 1 segment uniquement (pas d'urls /)
121        $row = sql_fetsel("U.url, U.date, U.perma, $champ_titre",
122                          "$table AS O LEFT JOIN spip_urls AS U ON (U.type='$type' AND U.id_objet=O.$col_id)",
123                          "O.$col_id=$id_objet AND (U.segments IS NULL OR U.segments=1)", '', 'U.date DESC', 1);
124       
125        if (!$row) return ""; # Quand $id_objet n'est pas un numero connu
126
127        $url_propre = $row['url'];
128
129        // Se contenter de cette URL si elle existe ;
130        // sauf si on invoque par "voir en ligne" avec droit de modifier l'url
131
132        // l'autorisation est verifiee apres avoir calcule la nouvelle url propre
133        // car si elle ne change pas, cela ne sert a rien de verifier les autorisations
134        // qui requetent en base
135        $modifier_url = (defined('_VAR_URLS') AND _VAR_URLS AND !$row['perma']);
136        if ($url_propre AND !$modifier_url)
137                return $url_propre;
138
139        // Sinon, creer une URL
140        $url = pipeline('propres_creer_chaine_url',
141                array(
142                        'data' => $url_propre,  // le vieux url_propre
143                        'objet' => array_merge($row,
144                                array('type' => $type, 'id_objet' => $id_objet)
145                        )
146                )
147        );
148
149        // Eviter de tamponner les URLs a l'ancienne (cas d'un article
150        // intitule "auteur2")
151        include_spip('inc/urls');
152        $objets = urls_liste_objets();
153        if (preg_match(',^('.$objets.')[0-9]+$,', $url, $r)
154        AND $r[1] != $type)
155                $url = $url._url_propres_sep_id.$id_objet;
156
157        // Pas de changement d'url
158        if ($url == $url_propre)
159                return $url_propre;
160
161        // verifier l'autorisation, maintenant qu'on est sur qu'on va agir
162        if ($modifier_url) {
163                include_spip('inc/autoriser');
164                $modifier_url = autoriser('modifierurl', $type, $id_objet);
165        }
166
167        // Verifier si l'utilisateur veut effectivement changer l'URL
168        if ($modifier_url
169                AND CONFIRMER_MODIFIER_URL
170                AND $url_propre
171                AND $url != preg_replace('/,.*/', '', $url_propre))
172                $confirmer = true;
173        else
174                $confirmer = false;
175
176        if ($confirmer AND !_request('ok')) {
177                die ("vous changez d'url ? $url_propre -&gt; $url");
178        }
179
180        $set = array('url' => $url, 'type' => $type, 'id_objet' => $id_objet);
181        include_spip('action/editer_url');
182        if (!url_insert($set,$confirmer,_url_propres_sep_id))
183                return $url_propre; //serveur out ? retourner au mieux
184
185        return $set['url'];
186}
187
188// http://doc.spip.org/@_generer_url_propre
189function _generer_url_propre($type, $id, $args='', $ancre='') {
190
191        if ($generer_url_externe = charger_fonction("generer_url_$type",'urls',true)) {
192                $url = $generer_url_externe($id, $args, $ancre);
193                if (NULL != $url) return $url;
194        }
195
196        // Mode compatibilite pour conserver la distinction -Rubrique-
197        if (_MARQUEUR_URL) {
198                $marqueur = unserialize(_MARQUEUR_URL);
199                $marqueur1 = isset($marqueur[$type.'1']) ? $marqueur[$type.'1'] : '' ; // debut '+-'
200                $marqueur2 = isset($marqueur[$type.'2']) ? $marqueur[$type.'2'] : '' ; // fin '-+'
201        } else
202                $marqueur1 = $marqueur2 = '';
203        // fin
204
205        // Mode propre
206        $propre = declarer_url_propre($type, $id);
207
208        if ($propre === false) return ''; // objet inconnu. raccourci ?
209
210        if ($propre) {
211                $url = _debut_urls_propres
212                        . $marqueur1
213                        . $propre
214                        . $marqueur2
215                        . _terminaison_urls_propres;
216
217                if (!defined('_SET_HTML_BASE') OR !_SET_HTML_BASE)
218                        // Repositionne l'URL par rapport a la racine du site (#GLOBALS)
219                        $url = str_repeat('../', $GLOBALS['profondeur_url']).$url;
220                else
221                        $url = _DIR_RACINE . $url;
222        } else {
223
224                // objet connu mais sans possibilite d'URL lisible, revenir au defaut
225                include_spip('base/connect_sql');
226                $id_type = id_table_objet($type);
227                $url = _DIR_RACINE . get_spip_script('./')."?"._SPIP_PAGE."=$type&$id_type=$id";
228        }
229
230        // Ajouter les args
231        if ($args)
232                $url .= ((strpos($url, '?')===false) ? '?' : '&') . $args;
233
234        // Ajouter l'ancre
235        if ($ancre)
236                $url .= "#$ancre";
237
238        return $url;
239}
240
241// retrouve le fond et les parametres d'une URL propre
242// ou produit une URL propre si on donne un parametre
243// @return array([contexte],[type],[url_redirect],[fond]) : url decodee
244// http://doc.spip.org/@urls_propres_dist
245function urls_propres_dist($i, $entite, $args='', $ancre='') {
246
247        if (is_numeric($i))
248                return _generer_url_propre($entite, $i, $args, $ancre);
249
250        $url = $i;
251        $id_objet = $type = 0;
252        $url_redirect = null;
253        // recuperer les &debut_xx;
254        if (is_array($args))
255                $contexte = $args;
256        else
257                parse_str($args,$contexte);
258
259
260        // Migration depuis anciennes URLs ?
261        // traiter les injections domain.tld/spip.php/n/importe/quoi/rubrique23
262        if ($GLOBALS['profondeur_url']<=0
263        AND $_SERVER['REQUEST_METHOD'] != 'POST') {
264                include_spip('inc/urls');
265                $r = nettoyer_url_page($i, $contexte);
266                if ($r) {
267                        list($contexte, $type,,, $suite) = $r;
268                        $_id = id_table_objet($type);
269                        $id_objet = $contexte[$_id];
270                        $url_propre = generer_url_entite($id_objet, $type);
271                        if (strlen($url_propre)
272                        AND !strstr($url,$url_propre)) {
273                                list(,$hash) = explode('#', $url_propre);
274                                $args = array();
275                                foreach(array_filter(explode('&', $suite)) as $fragment) {
276                                        if ($fragment != "$_id=$id_objet")
277                                                $args[] = $fragment;
278                                }
279                                $url_redirect = generer_url_entite($id_objet, $type, join('&',array_filter($args)), $hash);
280
281                                return array($contexte, $type, $url_redirect, $type);
282                        }
283                }
284        }
285        /* Fin compatibilite anciennes urls */
286        // Chercher les valeurs d'environnement qui indiquent l'url-propre
287        if (isset($_SERVER['REDIRECT_url_propre']))
288                $url_propre = $_SERVER['REDIRECT_url_propre'];
289        elseif (isset($_ENV['url_propre']))
290                $url_propre = $_ENV['url_propre'];
291        else {
292                // ne prendre que le segment d'url qui correspond, en fonction de la profondeur calculee
293                $url = ltrim($url,'/');
294                $url = explode('/',$url);
295                while (count($url)>$GLOBALS['profondeur_url']+1)
296                        array_shift($url);
297                $url = implode('/',$url);
298                $url_propre = preg_replace(',[?].*,', '', $url);
299        }
300
301        // Mode Query-String ?
302        $is_qs = false;
303        if (!$url_propre
304        AND preg_match(',[?]([^=/?&]+)(&.*)?$,', $url, $r)) {
305                $url_propre = $r[1];
306                $is_qs = true;
307        }
308
309        if (!$url_propre
310          OR $url_propre==_DIR_RESTREINT_ABS
311          OR $url_propre==_SPIP_SCRIPT) return; // qu'est-ce qu'il veut ???
312
313       
314        // gerer le cas de retour depuis des urls arbos
315        // mais si url arbo ne trouve pas, on veut une 404 par securite
316        if ($GLOBALS['profondeur_url']>0 AND !defined('_FORCE_URLS_PROPRES')){
317                $urls_anciennes = charger_fonction('arbo','urls');
318                return $urls_anciennes($url_propre, $entite, $contexte);
319        }
320       
321        include_spip('base/abstract_sql'); // chercher dans la table des URLS
322
323        // Compatibilite avec propres2
324        $url_propre = preg_replace(',\.html$,i', '', $url_propre);
325
326        // Revenir en utf-8 si encodage type %D8%A7 (farsi)
327        $url_propre = rawurldecode($url_propre);
328
329        // Compatibilite avec les anciens marqueurs d'URL propres
330        // Tester l'entree telle quelle (avec 'url_libre' des sites ont pu avoir des entrees avec marqueurs dans la table spip_urls)
331        if (!$row = sql_fetsel('id_objet, type, date, url', 'spip_urls', 'url='.sql_quote($url_propre))) {
332                // Sinon enlever les marqueurs eventuels
333                $url_propre2 = retirer_marqueurs_url_propre($url_propre);
334
335                $row = sql_fetsel('id_objet, type, date, url', 'spip_urls', 'url='.sql_quote($url_propre2));
336        }
337
338        if ($row) {
339                $type = $row['type'];
340                $col_id = id_table_objet($type);
341                $contexte[$col_id] = $row['id_objet'];
342                $entite = $row['type'];
343
344                // Si l'url est vieux, donner le nouveau
345                if ($recent = sql_fetsel('url, date', 'spip_urls',
346                'type='.sql_quote($row['type']).' AND id_objet='.sql_quote($row['id_objet'])
347                .' AND date>'.sql_quote($row['date'])
348                .' AND url<>'.sql_quote($row['url']), '', 'date DESC', 1)) {
349                        // Mode compatibilite pour conserver la distinction -Rubrique-
350                        if (_MARQUEUR_URL) {
351                                $marqueur = unserialize(_MARQUEUR_URL);
352                                $marqueur1 = $marqueur[$type.'1']; // debut '+-'
353                                $marqueur2 = $marqueur[$type.'2']; // fin '-+'
354                        } else
355                                $marqueur1 = $marqueur2 = '';
356                        $url_redirect = $marqueur1 . $recent['url'] . $marqueur2;
357                }
358        }
359
360        if ($entite=='' OR $entite=='type_urls' /* compat .htaccess 2.0 */) {
361                if ($type) {
362                        $entite =  objet_type($type);
363                } else {
364                        // Si ca ressemble a une URL d'objet, ce n'est pas la home
365                        // et on provoque un 404
366                        if (preg_match(',^.*/[^\.]+(\.html)?$,', $url)) {
367                                $entite = '404';
368                                $contexte['erreur'] = '';
369
370                                // l'url n'existe pas...
371                                // on ne sait plus dire de quel type d'objet il s'agit
372                                // sauf si on a le marqueur. et la c'est un peu sale...
373                                if (_MARQUEUR_URL) {
374                                        $fmarqueur = @array_flip(unserialize(_MARQUEUR_URL));
375                                        preg_match(',^([+][-]|[-+@_]),', $url_propre, $regs);
376                                        $objet = $regs ? substr($fmarqueur[$regs[1]],0,n-1) : 'article';
377                                        $contexte['erreur'] = _T(
378                                                ($objet=='rubrique' OR $objet=='breve')
379                                                        ? 'public:aucune_'.$objet
380                                                        : 'public:aucun_'.$objet
381                                        );
382                                }
383                        }
384                }
385        }
386
387        return array($contexte, $entite, $url_redirect, $is_qs?$entite:null);
388}
389
390?>
Note: See TracBrowser for help on using the repository browser.