From b8bebc4b35c0814dd57c8029b16df28c1e36c6a9 Mon Sep 17 00:00:00 2001 From: Cerdic <cedric@yterium.com> Date: Sat, 23 Oct 2010 09:43:08 +0000 Subject: [PATCH] Centralisation du code complexe d'appels de fonctions pour decoder une url. La complexite est liee a la compat ascendante, car les vieilles fonctions manipulaient directement des globales. La fonction urls_decoder_url() de inc/urls gere donc tout cela une fois pour toute, en isolant les globales concernees (sauvegarde/restauration) ce qui permet de l'utiliser partout sans precaution. Un flag $assembler par defaut a false permet de distinguer l'appel principal depuis public/assembler, qui accepter une redirection brutale, et necessite de prendre en compte les globales $_SERVER['REDIRECT_url_propre'] et $_ENV['url_propre'] Celles-ci ne sont plus videes par assembler car elles sont gerees proprement par la fonction urls_decoder_url Il serait neanmoins plus prudent d'evacuer aussi ces arguments implicites au profit d'arguments explicites, pour plus de clarete du code. Si les tests sur form_hidden sont exhaustif, on ne casse rien en passant par cette fonction depuis le filtre form_hidden. Si des cas de bugs sont remontes, il faudra completer les tests avant de corriger la fonction ou le filtre. --- ecrire/inc/filtres.php | 15 ++-- ecrire/inc/urls.php | 169 ++++++++++++++++++++++++++++++++++-- ecrire/public/assembler.php | 64 ++++---------- 3 files changed, 185 insertions(+), 63 deletions(-) diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php index d0d2f4a3b1..9bfb3ceda5 100644 --- a/ecrire/inc/filtres.php +++ b/ecrire/inc/filtres.php @@ -1680,15 +1680,14 @@ function regledetrois($a,$b,$c) // http://doc.spip.org/@form_hidden function form_hidden($action) { - $fond = ''; // inutilise mais necessaire $contexte = array(); - if ( - ($renommer = generer_url_entite() OR $renommer = charger_fonction('page','urls')) - AND $p = $renommer($action, $fond, $contexte) - AND $p[3]) { - $contexte = $p[0]; - $contexte['page'] = $p[3]; - $action = preg_replace('/([?]'.$p[3].'[^&=]*[0-9]+)(&|$)/', '?&', $action); + include_spip('inc/urls'); + if ($p = urls_decoder_url($action, '') + AND reset($p)) { + $fond = array_shift($p); + $contexte = array_shift($p); + $contexte['page'] = $fond; + $action = preg_replace('/([?]'.preg_quote($fond).'[^&=]*[0-9]+)(&|$)/', '?&', $action); } // on va remplir un tableau de valeurs en prenant bien soin de ne pas diff --git a/ecrire/inc/urls.php b/ecrire/inc/urls.php index 1d4b08a89c..ad64c5c815 100644 --- a/ecrire/inc/urls.php +++ b/ecrire/inc/urls.php @@ -12,7 +12,108 @@ if (!defined("_ECRIRE_INC_VERSION")) return; +/** + * Decoder une url en utilisant les fonctions inverse + * gestion des URLs transformee par le htaccess + * $renommer = 'urls_propres_dist'; + * renvoie array($contexte, $type, $url_redirect, $nfond) + * $nfond n'est retourne que si l'url est definie apres le ? + * et risque d'etre effacee par un form en get + * elle est utilisee par form_hidden exclusivement + * Compat ascendante si le retour est null en gerant une sauvegarde/restauration + * des globales modifiees par les anciennes fonctions + * + * @param string $url + * url a decoder + * @param string $fond + * fond initial par defaut + * @param array $contexte + * contexte initial a prendre en compte + * @param bool $assembler + * true si l'url correspond a l'url principale de la page qu'on est en train d'assembler + * dans ce cas la fonction redirigera automatiquement si besoin + * et utilisera les eventuelles globales $_SERVER['REDIRECT_url_propre'] et $_ENV['url_propre'] + * provenant du htaccess + * @return array + * ($fond,$contexte,$url_redirect) + * si l'url n'est pas valide, $fond restera a la valeur initiale passee + * il suffit d'appeler la fonction sans $fond et de verifier qu'a son retour celui-ci + * est non vide pour verifier une url + * + */ +function urls_decoder_url($url, $fond='', $contexte=array(), $assembler=false){ + // les anciennes fonctions modifient directement les globales + // on les sauve avant l'appel, et on les retablit apres ! + $save = array(@$GLOBALS['fond'],@$GLOBALS['contexte'],@$_SERVER['REDIRECT_url_propre'],@$_ENV['url_propre']); + // si on est pas en train d'assembler la page principale, + // vider les globales url propres qui ne doivent pas etre utilisees en cas + // d'inversion url => objet + if (!$assembler) { + unset($_SERVER['REDIRECT_url_propre']); + unset($_ENV['url_propre']); + } + + + $url_redirect = ""; + $renommer = generer_url_entite(); + if (!$renommer AND !function_exists('recuperer_parametres_url')) + $renommer = charger_fonction('page','urls'); // fallback pour decoder l'url + if ($renommer) { + $a = $renommer($url, $fond, $contexte); + if (is_array($a)) { + list($ncontexte, $type, $url_redirect, $nfond) = $a; + if ($url_redirect == $url) + $url_redirect = ""; // securite pour eviter une redirection infinie + if ($assembler AND strlen($url_redirect)) { + spip_log("Redirige $url vers $url_redirect"); + include_spip('inc/headers'); + http_status(301); + redirige_par_entete($url_redirect); + } + if (isset($nfond)) + $fond = $nfond; + else if ($fond == '' + OR $fond == 'type_urls' /* compat avec htaccess 2.0.0 */ + ) + $fond = $type; + if (isset($ncontexte)) + $contexte = $ncontexte; + } + } + // compatibilite <= 1.9.2 + elseif (function_exists('recuperer_parametres_url')) { + $GLOBALS['fond'] = $fond; + $GLOBALS['contexte'] = $contexte; + recuperer_parametres_url($fond, nettoyer_uri()); + // fond est en principe modifiee directement + $contexte = $GLOBALS['contexte']; + } + + // retablir les globales + list($GLOBALS['fond'],$GLOBALS['contexte'],$_SERVER['REDIRECT_url_propre'],$_ENV['url_propre']) = $save; + + // vider les globales url propres qui ne doivent plus etre utilisees en cas + // d'inversion url => objet + // maintenir pour compat ? + #if ($assembler) { + # unset($_SERVER['REDIRECT_url_propre']); + # unset($_ENV['url_propre']); + #} + + return array($fond,$contexte,$url_redirect); +} + + +/** + * Lister les objets pris en compte dans les urls + * c'est a dire suceptibles d'avoir une url propre + * + * @param bool $preg + * permet de definir si la fonction retourne une chaine avec | comme separateur + * pour utiliser en preg, ou un array() + * @return string/array + */ function urls_liste_objets($preg = true){ $url_objets = pipeline('declarer_url_objets',array('article','rubrique','auteur')); if (!$preg) return $url_objets; @@ -20,6 +121,15 @@ function urls_liste_objets($preg = true){ return $url_objets; } +/** + * Nettoyer une url, en reperant notamment les raccourcis d'entites + * comme ?article13, ?rubrique21 ... + * et en les traduisant pour completer le contexte fourni en entree + * + * @param string $url + * @param array $contexte + * @return array + */ function nettoyer_url_page($url, $contexte=array()) { $url_objets = urls_liste_objets(); @@ -40,10 +150,19 @@ function nettoyer_url_page($url, $contexte=array()) } -// fonction produisant les URL d'acces en lecture ou en ecriture -// des items des tables SQL principales, selon le statut de publication - -// http://doc.spip.org/@generer_url_ecrire_article +/** + * Generer l'url d'un article dans l'espace prive, + * fonction du statut de l'a rubrique'article + * + * @param int $id + * @param string $args + * @param string $ancre + * @param string $statut + * @param string $connect + * @return string + * + * http://doc.spip.org/@generer_url_ecrire_article + */ function generer_url_ecrire_article($id, $args='', $ancre='', $statut='', $connect='') { $a = "id_article=" . intval($id); if (!$statut) { @@ -56,7 +175,19 @@ function generer_url_ecrire_article($id, $args='', $ancre='', $statut='', $conne return $h; } -// http://doc.spip.org/@generer_url_ecrire_rubrique +/** + * Generer l'url d'une rubrique dans l'espace prive, + * fonction du statut de la rubrique + * + * @param int $id + * @param string $args + * @param string $ancre + * @param string $statut + * @param string $connect + * @return string + * + * http://doc.spip.org/@generer_url_ecrire_rubrique + */ function generer_url_ecrire_rubrique($id, $args='', $ancre='', $statut='', $connect='') { $a = "id_rubrique=" . intval($id); if (!$statut) { @@ -70,7 +201,19 @@ function generer_url_ecrire_rubrique($id, $args='', $ancre='', $statut='', $conn } -// http://doc.spip.org/@generer_url_ecrire_auteur +/** + * Generer l'url d'un auteur dans l'espace prive, + * fonction du statut de l'auteur + * + * @param int $id + * @param string $args + * @param string $ancre + * @param string $statut + * @param string $connect + * @return string + * + * http://doc.spip.org/@generer_url_ecrire_auteur + */ function generer_url_ecrire_auteur($id, $args='', $ancre='', $statut='', $connect='') { $a = (intval($id)?"id_auteur=" . intval($id):''); $h = (!$statut OR $connect) @@ -80,7 +223,19 @@ function generer_url_ecrire_auteur($id, $args='', $ancre='', $statut='', $connec return $h; } -// http://doc.spip.org/@generer_url_ecrire_document +/** + * Generer l'url d'un document dans l'espace prive, + * fonction du statut du document + * + * @param int $id + * @param string $args + * @param string $ancre + * @param string $statut + * @param string $connect + * @return string + * + * http://doc.spip.org/@generer_url_ecrire_document + */ function generer_url_ecrire_document($id, $args='', $ancre='', $statut='', $connect='') { include_spip('inc/documents'); return generer_url_document_dist($id); diff --git a/ecrire/public/assembler.php b/ecrire/public/assembler.php index c782ee14fc..9377db626a 100644 --- a/ecrire/public/assembler.php +++ b/ecrire/public/assembler.php @@ -22,7 +22,9 @@ if (!defined("_ECRIRE_INC_VERSION")) return; // http://doc.spip.org/@assembler function assembler($fond, $connect='') { - global $flag_preserver,$lastmodified, $use_cache, $contexte; + // flag_preserver est modifie ici, et utilise en globale + // contexte est utilise en globale dans le formulaire d'admin + global $flag_preserver, $contexte; $contexte = calculer_contexte(); $page = array('contexte_implicite'=>calculer_contexte_implicite()); @@ -31,7 +33,7 @@ function assembler($fond, $connect='') { $cacher = charger_fonction('cacher', 'public'); // Les quatre derniers parametres sont modifies par la fonction: // emplacement, validite, et, s'il est valide, contenu & age - $res = $cacher($GLOBALS['contexte'], $use_cache, $chemin_cache, $page, $lastmodified); + $res = $cacher($contexte, $use_cache, $chemin_cache, $page, $lastmodified); // Si un resultat est retourne, c'est un message d'impossibilite if ($res) {return array('texte' => $res);} @@ -67,57 +69,23 @@ function assembler($fond, $connect='') { } else { // si la page est prise dans le cache if (!$use_cache) { - // Informer les boutons d'admin du contexte - // (fourni par $renommer ci-dessous lors de la mise en cache) + // Informer les boutons d'admin du contexte + // (fourni par urls_decoder_url ci-dessous lors de la mise en cache) $contexte = $page['contexte']; // vider les globales url propres qui ne doivent plus etre utilisees en cas // d'inversion url => objet - unset($_SERVER['REDIRECT_url_propre']); - unset($_ENV['url_propre']); + // plus necessaire si on utilise bien la fonction urls_decoder_url + #unset($_SERVER['REDIRECT_url_propre']); + #unset($_ENV['url_propre']); } - // ATTENTION, gestion des URLs transformee par le htaccess - // $renommer = 'urls_propres_dist'; - // renvoie array($contexte, $type, $url_redirect, $nfond) - // $nfond n'est retourne que si l'url est definie apres le ? - // et risque d'etre effacee par un form en get - // elle est utilisee par form_hidden exclusivement - // Compat ascendante si le retour est null: - // 1. $contexte est global car cette fonction le modifie. - // 2. $fond est passe par reference, pour la meme raison - // et calculer la page else { - $renommer = generer_url_entite(); - if ($renommer) { - $url = nettoyer_uri(); - $a = $renommer($url, $fond, $contexte); - if (is_array($a)) { - list($ncontexte, $type, $url_redirect, $nfond) = $a; - if (strlen($url_redirect) - AND $url !== $url_redirect) { - spip_log("Redirige $url vers $url_redirect"); - include_spip('inc/headers'); - http_status(301); - redirige_par_entete($url_redirect); - } - if (isset($nfond)) - $fond = $nfond; - else if ($fond == '' - OR $fond == 'type_urls' /* compat avec htaccess 2.0.0 */ - ) - $fond = $type; - if (isset($ncontexte)) - $contexte = $ncontexte; - } - } - // compatibilite <= 1.9.2 - elseif (function_exists('recuperer_parametres_url')) - recuperer_parametres_url($fond, nettoyer_uri()); - - // vider les globales url propres qui ne doivent plus etre utilisees en cas - // d'inversion url => objet - unset($_SERVER['REDIRECT_url_propre']); - unset($_ENV['url_propre']); + // Compat ascendante : + // 1. $contexte est global + // (a evacuer car urls_decoder_url gere ce probleme ?) + // et calculer la page + include_spip('inc/urls'); + list($fond,$contexte,$url_redirect) = urls_decoder_url(nettoyer_uri(),$fond,$contexte,true); // squelette par defaut if (!strlen($fond)) @@ -125,7 +93,7 @@ function assembler($fond, $connect='') { // produire la page : peut mettre a jour $lastmodified $produire_page = charger_fonction('produire_page','public'); - $page = $produire_page($fond, $GLOBALS['contexte'], $use_cache, $chemin_cache, NULL, $page, $lastmodified, $connect); + $page = $produire_page($fond, $contexte, $use_cache, $chemin_cache, NULL, $page, $lastmodified, $connect); } if ($page AND $chemin_cache) $page['cache'] = $chemin_cache; -- GitLab