function assembler($fond, $connect='') { global $flag_preserver,$lastmodified, $use_cache, $contexte; $contexte = calculer_contexte(); $page = array('contexte_implicite'=>calculer_contexte_implicite()); $page['contexte_implicite']['cache'] = $fond . preg_replace(',\.[a-zA-Z0-9]*$,', '', preg_replace('/[?].*$/', '', $GLOBALS['REQUEST_URI'])); // Cette fonction est utilisee deux fois $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); // Si un resultat est retourne, c'est un message d'impossibilite if ($res) {return array('texte' => $res);} if (!$chemin_cache || !$lastmodified) $lastmodified = time(); $headers_only = ($_SERVER['REQUEST_METHOD'] == 'HEAD'); // Pour les pages non-dynamiques (indiquees par #CACHE{duree,cache-client}) // une perennite valide a meme reponse qu'une requete HEAD (par defaut les // pages sont dynamiques) if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) AND !$GLOBALS['var_mode'] AND $chemin_cache AND isset($page['entetes']) AND isset($page['entetes']['Cache-Control']) AND strstr($page['entetes']['Cache-Control'],'max-age=') AND !strstr($_SERVER['SERVER_SOFTWARE'],'IIS/') ) { $since = preg_replace('/;.*/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']); $since = str_replace('GMT', '', $since); if (trim($since) == gmdate("D, d M Y H:i:s", $lastmodified)) { $page['status'] = 304; $headers_only = true; } } // Si requete HEAD ou Last-modified compatible, ignorer le texte // et pas de content-type (pour contrer le bouton admin de inc-public) if ($headers_only) { $page['entetes']["Connection"] = "close"; $page['texte'] = ""; } 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) $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']); } // 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'); redirige_par_entete($url_redirect, '', 301); } if (isset($nfond)) $fond = $nfond; else if ($fond == '' OR $fond == 'type_urls' /* compat avec htaccess 2.0.0 */ ) $fond = ($type === 'syndic') ? 'site' : $type; if (isset($ncontexte)) $contexte = $ncontexte; if (defined('_DEFINIR_CONTEXTE_TYPE') AND _DEFINIR_CONTEXTE_TYPE) $contexte['type'] = ($type === 'syndic') ? 'site' : $type; } } // 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']); // squelette par defaut if (!strlen($fond)) $fond = 'sommaire'; // 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); if ($page === '') { $erreur = _T('info_erreur_squelette2', array('fichier'=>htmlspecialchars($fond).'.'._EXTENSION_SQUELETTES)); erreur_squelette($erreur); // eviter des erreurs strictes ensuite sur $page['cle'] en PHP >= 5.4 $page = array('texte' => '', 'erreur' => $erreur); } } if ($page AND $chemin_cache) $page['cache'] = $chemin_cache; auto_content_type($page); $flag_preserver |= headers_sent(); // Definir les entetes si ce n'est fait if (!$flag_preserver) { if ($GLOBALS['flag_ob']) { // Si la page est vide, produire l'erreur 404 ou message d'erreur pour les inclusions if (trim($page['texte']) === '' AND $GLOBALS['var_mode'] != 'debug' AND !isset($page['entetes']['Location']) // cette page realise une redirection, donc pas d'erreur ) { // passer le type d'objet recherche au contexte de la page d'erreur $contexte['type'] = (isset($type)?$type:$fond); $page = message_page_indisponible($page, $contexte); // cacher la page d'erreur car celle ci est contextuelle if ($chemin_cache AND is_array($page) AND count($page) AND $page['entetes']['X-Spip-Cache'] > 0){ $cacher = charger_fonction('cacher', 'public'); $lastinclude = time(); $cacher($contexte_cache, $use_cache, $chemin_cache, $page, $lastinclude); } } // pas de cache client en mode 'observation' if ($GLOBALS['var_mode']) { $page['entetes']["Cache-Control"]= "no-cache,must-revalidate"; $page['entetes']["Pragma"] = "no-cache"; } } } } // Entete Last-Modified: // eviter d'etre incoherent en envoyant un lastmodified identique // a celui qu'on a refuse d'honorer plus haut (cf. #655) if ($lastmodified AND !isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) AND !isset($page['entetes']["Last-Modified"])) $page['entetes']["Last-Modified"]=gmdate("D, d M Y H:i:s", $lastmodified)." GMT"; return $page; }
/** * Décoder une URL en utilisant les fonctions inverses * * Gère les URLs transformées par le htaccess. * * @note * `$renommer = 'urls_propres_dist';` * renvoie `array($contexte, $type, $url_redirect, $nfond)` * * `$nfond` n'est retourné que si l'URL est définie apres le `?` * et risque d'être effacée par un form en get. * Elle est utilisée par form_hidden exclusivement. * * Compat ascendante si le retour est NULL en gérant une sauvegarde/restauration * des globales modifiées par les anciennes fonctions * * @param string $url * URL à décoder * @param string $fond * Fond initial par défaut * @param array $contexte * Contexte initial à prendre en compte * @param bool $assembler * `true` si l'URL correspond à 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 * Liste `$fond, $contexte, $url_redirect`. * * Si l'url n'est pas valide, $fond restera à la valeur initiale passée. * Il suffit d'appeler la fonction sans $fond et de vérifier qu'à son retour celui-ci * est non vide pour vérifier une URL * */ function urls_decoder_url($url, $fond = '', $contexte = array(), $assembler = false) { static $current_base = null; // les anciennes fonctions modifient directement les globales // on les sauve avant l'appel, et on les retablit apres ! $save = array(isset($GLOBALS['fond']) ? $GLOBALS['fond'] : null, isset($GLOBALS['contexte']) ? $GLOBALS['contexte'] : null, isset($_SERVER['REDIRECT_url_propre']) ? $_SERVER['REDIRECT_url_propre'] : null, isset($_ENV['url_propre']) ? $_ENV['url_propre'] : null, $GLOBALS['profondeur_url']); if (is_null($current_base)) { include_spip('inc/filtres_mini'); // le decodage des urls se fait toujours par rapport au site public $current_base = url_absolue(_DIR_RACINE ? _DIR_RACINE : './'); } if (strncmp($url, $current_base, strlen($current_base)) == 0) { $url = substr($url, strlen($current_base)); } // si on est en train d'assembler la page principale, // recuperer l'url depuis les globales url propres si fournies // sinon extraire la bonne portion d'url if ($assembler) { if (isset($_SERVER['REDIRECT_url_propre'])) { $url = $_SERVER['REDIRECT_url_propre']; } elseif (isset($_ENV['url_propre'])) { $url = $_ENV['url_propre']; } else { $qs = explode("?", $url); // ne prendre que le segment d'url qui correspond, en fonction de la profondeur calculee $url = ltrim($qs[0], '/'); $url = explode('/', $url); while (count($url) > $GLOBALS['profondeur_url'] + 1) { array_shift($url); } $qs[0] = implode('/', $url); $url = implode("?", $qs); } } unset($_SERVER['REDIRECT_url_propre']); unset($_ENV['url_propre']); include_spip('inc/filtres_mini'); if (strpos($url, "://") === false) { $GLOBALS['profondeur_url'] = substr_count(ltrim(resolve_path("/{$url}"), '/'), '/'); } else { $GLOBALS['profondeur_url'] = max(0, substr_count($url, "/") - substr_count($current_base, "/")); } $url_redirect = ""; $renommer = generer_url_entite('', '', '', '', true); 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) = array_pad($a, 4, null); 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'); redirige_par_entete($url_redirect, '', 301); } if (isset($nfond)) { $fond = $nfond; } else { if ($fond == '' or $fond == 'type_urls') { $fond = $type; } } if (isset($ncontexte)) { $contexte = $ncontexte; } if (defined('_DEFINIR_CONTEXTE_TYPE') and _DEFINIR_CONTEXTE_TYPE) { $contexte['type'] = $type; } if (defined('_DEFINIR_CONTEXTE_TYPE_PAGE') and _DEFINIR_CONTEXTE_TYPE_PAGE) { $contexte['type-page'] = $type; } } } 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'], $GLOBALS['profondeur_url']) = $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); }
/** * 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) { static $current_base = null; // 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']); if (is_null($current_base)) { include_spip('inc/filtres_mini'); // le decodage des urls se fait toujours par rapport au site public $current_base = url_absolue(_DIR_RACINE ? _DIR_RACINE : './'); } if (strncmp($url, $current_base, strlen($current_base)) == 0) { $url = substr($url, strlen($current_base)); } // 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) = array_pad($a, 4, null); 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'); redirige_par_entete($url_redirect, '', 301); } if (isset($nfond)) { $fond = $nfond; } else { if ($fond == '' or $fond == 'type_urls') { $fond = $type; } } if (isset($ncontexte)) { $contexte = $ncontexte; } if (defined('_DEFINIR_CONTEXTE_TYPE') and _DEFINIR_CONTEXTE_TYPE) { $contexte['type'] = $type; } if (defined('_DEFINIR_CONTEXTE_TYPE_PAGE') and _DEFINIR_CONTEXTE_TYPE_PAGE) { $contexte['type-page'] = $type; } } } 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); }