diff --git a/ecrire/action/redirect.php b/ecrire/action/redirect.php index 5b908fb7a9b1d2a4e67666e5339bf16d502a671d..371f3b0c760e0782541ddfccb43cafcb71a1b59e 100644 --- a/ecrire/action/redirect.php +++ b/ecrire/action/redirect.php @@ -38,50 +38,92 @@ if (!defined('_ECRIRE_INC_VERSION')) { function action_redirect_dist() { $type = _request('type'); $id = intval(_request('id')); + $page = false; - if ($m = _request('var_mode')) { + // verifier le type ou page transmis + if (!preg_match('/^\w+$/', $type)) { + $page = _request('page'); + if (!preg_match('/^\w+$/', $page)) { + return; + } + } + + if ($var_mode = _request('var_mode')) { // forcer la mise a jour de l'url de cet objet ! if (!defined('_VAR_URLS')) { define('_VAR_URLS', true); } } - if (preg_match('/^\w+$/', $type)) { - $h = generer_url_entite_absolue($id, $type, '', '', true); + if ($page) { + $url = generer_url_public($page, '', true); } else { - if ($page = _request('page') - and preg_match('/^\w+$/', $page) + $url = calculer_url_redirect_entite($type, $id, $var_mode); + } + + $status = '302'; + if ($url) { + if ($var_mode) { + $url = parametre_url($url, 'var_mode', $var_mode); + } + + if ($var_mode == 'preview' + and defined('_PREVIEW_TOKEN') + and _PREVIEW_TOKEN + and autoriser('previsualiser') ) { - $h = generer_url_public($page, '', true); - } else { - return; + include_spip('inc/securiser_action'); + $token = calculer_token_previsu($url); + $url = parametre_url($url, 'var_previewtoken', $token); } - } - if ($m > '') { - $h = parametre_url($h, 'var_mode', $m); + if (_request('status') and _request('status') == '301') { + $status = '301'; + } + } else { + $url = generer_url_public('404', '', true); } - if ($m == 'preview' - and defined('_PREVIEW_TOKEN') - and _PREVIEW_TOKEN - and $type - and $id - and autoriser('previsualiser') - ) { - include_spip('inc/securiser_action'); - $token = calculer_token_previsu($type, $id); - $h = parametre_url($h, 'var_previewtoken', $token); + redirige_par_entete(str_replace('&', '&', $url), '', $status); +} + +/** + * Retourne l’URL de l’objet sur lequel on doit rediriger + * + * On met en cache les calculs (si memoization), + * et on ne donne pas l’URL si la personne n’y a pas accès + * + * @param string $type + * @param int $id + * @param string $var_mode + */ +function calculer_url_redirect_entite($type, $id, $var_mode) { + // invalider le cache à chaque modif en bdd + $date = 0; + if (isset($GLOBALS['meta']['derniere_modif'])) { + $date = $GLOBALS['meta']['derniere_modif']; } + $key = "url-$date-$type-$id"; - $status = '302'; - if (_request('status') and _request('status') == '301') { - $status = '301'; + // Obtenir l’url et si elle est publié du cache memoization + if (function_exists('cache_get') and $desc = cache_get($key)) { + list($url, $publie) = $desc; + } + // Si on ne l’a pas trouvé, ou si var mode, on calcule l’url et son état publie + if (!$desc or $var_mode) { + $publie = objet_test_si_publie($type, $id); + $url = generer_url_entite_absolue($id, $type, '', '', true); + if (function_exists('cache_set')) { + cache_set($key, array($url, $publie), 3600); + } } - if ($h) { - redirige_par_entete(str_replace('&', '&', $h), '', $status); - } else { - redirige_par_entete('/', '', $status); + // On valide l’url si elle est publiee ; sinon si preview on teste l’autorisation + if ($publie) { + return $url; + } elseif (defined('_VAR_PREVIEW') and _VAR_PREVIEW and autoriser('voir', $type, $id)) { + return $url; } -} + + return; +} \ No newline at end of file diff --git a/ecrire/inc/securiser_action.php b/ecrire/inc/securiser_action.php index 4bbebfbc1bed0b9302a136131688d03497dbcc75..8fcbed6d418ead890468f78594f740957e3a1176 100644 --- a/ecrire/inc/securiser_action.php +++ b/ecrire/inc/securiser_action.php @@ -301,13 +301,12 @@ function verifier_cle_action($action, $cle) { * pour qu’une personne tierce le relise. Valable quelques temps. * * @see verifier_token_previsu() - * @param string $type Type d’objet - * @param int $id_objet Identifiant de l’objet + * @param string $url Url à autoriser en prévisu * @param int|null id_auteur qui génère le token de prévisu. Null utilisera auteur courant. * @param string $alea Nom de l’alea à utiliser * @return string Token, de la forme "{id}*{hash}" */ -function calculer_token_previsu($type, $id_objet, $id_auteur = null, $alea = 'alea_ephemere') { +function calculer_token_previsu($url, $id_auteur = null, $alea = 'alea_ephemere') { if (is_null($id_auteur)) { if (!empty($GLOBALS['visiteur_session']['id_auteur'])) { $id_auteur = $GLOBALS['visiteur_session']['id_auteur']; @@ -316,7 +315,10 @@ function calculer_token_previsu($type, $id_objet, $id_auteur = null, $alea = 'al if (!$id_auteur = intval($id_auteur)) { return ""; } - $token = _action_auteur('previsualiser-' . $type . '-' . $id_objet, $id_auteur, null, $alea); + // On nettoie l’URL de tous les var_. + $url = nettoyer_uri_var($url); + + $token = _action_auteur('previsualiser-' . $url, $id_auteur, null, $alea); return "$id_auteur-$token"; } @@ -338,8 +340,7 @@ function verifier_token_previsu($token) { // retrouver auteur / hash $e = explode('-', $token, 2); if (count($e) == 2 and is_numeric(reset($e))) { - list($id_auteur, $hash) = $e; - $id_auteur = intval($id_auteur); + $id_auteur = intval(reset($e)); } else { return false; } @@ -347,22 +348,12 @@ function verifier_token_previsu($token) { // calculer le type et id de l’url actuelle include_spip('inc/urls'); include_spip('inc/filtres_mini'); - $self = url_absolue(self()); - $contexte = urls_decoder_url($self); - list($type, $contexte) = $contexte; - if (is_numeric($type)) { - return false; - } - $_id_table = id_table_objet($type); - if (empty($contexte[$_id_table])) { - return false; - } - $id = $contexte[$_id_table]; + $url = url_absolue(self()); // verifier le token - $_token = calculer_token_previsu($type, $id, $id_auteur, 'alea_ephemere'); + $_token = calculer_token_previsu($url, $id_auteur, 'alea_ephemere'); if (!$_token or $token !== $_token) { - $_token = calculer_token_previsu($type, $id, $id_auteur, 'alea_ephemere_ancien'); + $_token = calculer_token_previsu($url, $id_auteur, 'alea_ephemere_ancien'); if (!$_token or $token !== $_token) { return false; } @@ -370,8 +361,6 @@ function verifier_token_previsu($token) { return array( 'id_auteur' => $id_auteur, - 'type' => $type, - 'id_objet' => $id ); } diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php index 7610de0d5864ae0029750729546b14190d595da2..57afa33e78f011e54aa479b7351b2ff019894dee 100644 --- a/ecrire/inc/utils.php +++ b/ecrire/inc/utils.php @@ -591,15 +591,22 @@ function nettoyer_uri($reset = null) { return $propre; } $done = true; + return $propre = nettoyer_uri_var($GLOBALS['REQUEST_URI']); +} - $uri1 = $GLOBALS['REQUEST_URI']; +/** + * Nettoie une request_uri des paramètres var_xxx + * @param $request_uri + * @return string + */ +function nettoyer_uri_var($request_uri) { + $uri1 = $request_uri; do { $uri = $uri1; $uri1 = preg_replace(',([?&])(PHPSESSID|(var_[^=&]*))=[^&]*(&|$),i', '\1', $uri); } while ($uri <> $uri1); - - return $propre = (preg_replace(',[?&]$,', '', $uri1)); + return preg_replace(',[?&]$,', '', $uri1); }