Пример #1
0
/**
 * API : retourner l'url d'un objet si i est numerique
 * ou decoder cette url si c'est une chaine
 * array([contexte],[type],[url_redirect],[fond]) : url decodee
 *
 * http://doc.spip.org/@urls_arbo_dist
 *
 * @param string|int $i
 * @param string $entite
 * @param string|array $args
 * @param string $ancre
 * @return array|string
 */
function urls_arbo_dist($i, $entite, $args = '', $ancre = '')
{
    if (is_numeric($i)) {
        return _generer_url_arbo($entite, $i, $args, $ancre);
    }
    // traiter les injections du type domaine.org/spip.php/cestnimportequoi/ou/encore/plus/rubrique23
    if ($GLOBALS['profondeur_url'] > 0 and $entite == 'sommaire') {
        $entite = 'type_urls';
    }
    // recuperer les &debut_xx;
    if (is_array($args)) {
        $contexte = $args;
    } else {
        parse_str($args, $contexte);
    }
    $url = $i;
    $id_objet = $type = 0;
    $url_redirect = null;
    // Migration depuis anciennes URLs ?
    // traiter les injections domain.tld/spip.php/n/importe/quoi/rubrique23
    if ($GLOBALS['profondeur_url'] <= 0 and $_SERVER['REQUEST_METHOD'] != 'POST') {
        include_spip('inc/urls');
        $r = nettoyer_url_page($i, $contexte);
        if ($r) {
            list($contexte, $type, , , $suite) = $r;
            $_id = id_table_objet($type);
            $id_objet = $contexte[$_id];
            $url_propre = generer_url_entite($id_objet, $type);
            if (strlen($url_propre) and !strstr($url, $url_propre)) {
                list(, $hash) = explode('#', $url_propre);
                $args = array();
                foreach (array_filter(explode('&', $suite)) as $fragment) {
                    if ($fragment != "{$_id}={$id_objet}") {
                        $args[] = $fragment;
                    }
                }
                $url_redirect = generer_url_entite($id_objet, $type, join('&', array_filter($args)), $hash);
                return array($contexte, $type, $url_redirect, $type);
            }
        }
    }
    /* Fin compatibilite anciennes urls */
    // Chercher les valeurs d'environnement qui indiquent l'url-propre
    if (isset($_SERVER['REDIRECT_url_propre'])) {
        $url_propre = $_SERVER['REDIRECT_url_propre'];
    } elseif (isset($_ENV['url_propre'])) {
        $url_propre = $_ENV['url_propre'];
    } else {
        // ne prendre que le segment d'url qui correspond, en fonction de la profondeur calculee
        $url = ltrim($url, '/');
        $url = explode('/', $url);
        while (count($url) > $GLOBALS['profondeur_url'] + 1) {
            array_shift($url);
        }
        $url = implode('/', $url);
        $url_propre = preg_replace(',[?].*,', '', $url);
    }
    // Mode Query-String ?
    if (!$url_propre and preg_match(',[?]([^=/?&]+)(&.*)?$,', $url, $r)) {
        $url_propre = $r[1];
    }
    if (!$url_propre or $url_propre == _DIR_RESTREINT_ABS or $url_propre == _SPIP_SCRIPT) {
        return;
    }
    // qu'est-ce qu'il veut ???
    include_spip('base/abstract_sql');
    // chercher dans la table des URLS
    // Revenir en utf-8 si encodage type %D8%A7 (farsi)
    $url_propre = rawurldecode($url_propre);
    // Compatibilite avec .htm/.html et autres terminaisons
    $t = array_diff(array_unique(array_merge(array('.html', '.htm', '/'), url_arbo_terminaison(''))), array(''));
    if (count($t)) {
        $url_propre = preg_replace('{(' . implode('|', array_map('preg_quote', $t)) . ')$}i', '', $url_propre);
    }
    if (strlen($url_propre) and !preg_match(',^[^/]*[.]php,', $url_propre)) {
        $parents_vus = array();
        // recuperer tous les objets de larbo xxx/article/yyy/mot/zzzz
        // on parcourt les segments de gauche a droite
        // pour pouvoir contextualiser un segment par son parent
        $url_arbo = explode('/', $url_propre);
        $url_arbo_new = array();
        $dernier_parent_vu = false;
        $objet_segments = 0;
        while (count($url_arbo) > 0) {
            $type = null;
            if (count($url_arbo) > 1) {
                $type = array_shift($url_arbo);
            }
            $url_segment = array_shift($url_arbo);
            // Rechercher le segment de candidat
            // si on est dans un contexte de parent, donne par le segment precedent,
            // prefixer le segment recherche avec ce contexte
            $cp = "0";
            // par defaut : parent racine, id=0
            if ($dernier_parent_vu) {
                $cp = $parents_vus[$dernier_parent_vu];
            }
            // d'abord recherche avec prefixe parent, en une requete car aucun risque de colision
            $row = sql_fetsel('id_objet, type, url', 'spip_urls', is_null($type) ? "url=" . sql_quote($url_segment) : sql_in('url', array("{$type}/{$url_segment}", $type)), '', (intval($cp) ? "id_parent=" . intval($cp) . " DESC, " : "") . "segments DESC, id_parent");
            if ($row) {
                if (!is_null($type) and $row['url'] == $type) {
                    array_unshift($url_arbo, $url_segment);
                    $url_segment = $type;
                    $type = null;
                }
                $type = $row['type'];
                $col_id = id_table_objet($type);
                // le plus a droite l'emporte pour des objets presents plusieurs fois dans l'url (ie rubrique)
                $contexte[$col_id] = $row['id_objet'];
                $type_parent = '';
                if ($p = url_arbo_parent($type)) {
                    $type_parent = end($p);
                }
                // l'entite la plus a droite l'emporte, si le type de son parent a ete vu
                // sinon c'est un segment contextuel supplementaire a ignorer
                // ex : rub1/article/art1/mot1 : il faut ignorer le mot1, la vrai url est celle de l'article
                if (!$entite or $dernier_parent_vu == $type_parent) {
                    if ($objet_segments == 0) {
                        $entite = $type;
                    }
                } else {
                    $objet_segments++;
                }
                $url_arbo_new[$objet_segments]['id_objet'] = $row['id_objet'];
                $url_arbo_new[$objet_segments]['objet'] = $type;
                $url_arbo_new[$objet_segments]['segment'][] = $row['url'];
                // on note le dernier parent vu de chaque type
                $parents_vus[$dernier_parent_vu = $type] = $row['id_objet'];
            } else {
                // un segment est inconnu
                if ($entite == '' or $entite == 'type_urls') {
                    // on genere une 404 comme il faut si on ne sait pas ou aller
                    return array(array(), '404');
                }
                // ici on a bien reconnu un segment en amont, mais le segment en cours est inconnu
                // on pourrait renvoyer sur le dernier segment identifie
                // mais de fait l'url entiere est inconnu : 404 aussi
                // mais conserver le contexte qui peut contenir un fond d'ou venait peut etre $entite (reecriture urls)
                return array($contexte, '404');
            }
        }
        if (count($url_arbo_new)) {
            $caller = debug_backtrace();
            $caller = $caller[1]['function'];
            // si on est appele par un autre module d'url c'est du decodage d'une ancienne URL
            // ne pas regenerer des segments arbo, mais rediriger vers la nouvelle URL
            // dans la nouvelle forme
            if (strncmp($caller, "urls_", 5) == 0 and $caller !== "urls_decoder_url") {
                // en absolue, car assembler ne gere pas ce cas particulier
                include_spip('inc/filtres_mini');
                $col_id = id_table_objet($entite);
                $url_new = generer_url_entite($contexte[$col_id], $entite);
                // securite contre redirection infinie
                if ($url_new !== $url_propre and rtrim($url_new, "/") !== rtrim($url_propre, "/")) {
                    $url_redirect = url_absolue($url_new);
                }
            } else {
                foreach ($url_arbo_new as $k => $o) {
                    if ($s = declarer_url_arbo($o['objet'], $o['id_objet'])) {
                        $url_arbo_new[$k] = $s;
                    } else {
                        $url_arbo_new[$k] = implode('/', $o['segment']);
                    }
                }
                $url_arbo_new = ltrim(implode('/', $url_arbo_new), '/');
                if ($url_arbo_new !== $url_propre) {
                    $url_redirect = $url_arbo_new;
                    // en absolue, car assembler ne gere pas ce cas particulier
                    include_spip('inc/filtres_mini');
                    $url_redirect = url_absolue($url_redirect);
                }
            }
        }
        // gerer le retour depuis des urls propres
        if (($entite == '' or $entite == 'type_urls') and $GLOBALS['profondeur_url'] <= 0) {
            $urls_anciennes = charger_fonction('propres', 'urls');
            return $urls_anciennes($url_propre, $entite, $contexte);
        }
    }
    if ($entite == '' or $entite == 'type_urls') {
        if ($type) {
            $entite = objet_type($type);
        } else {
            // Si ca ressemble a une URL d'objet, ce n'est pas la home
            // et on provoque un 404
            if (preg_match(',^[^\\.]+(\\.html)?$,', $url)) {
                $entite = '404';
                $contexte['erreur'] = '';
                // qu'afficher ici ?  l'url n'existe pas... on ne sait plus dire de quel type d'objet il s'agit
            }
        }
    }
    define('_SET_HTML_BASE', 1);
    return array($contexte, $entite, $url_redirect, null);
}
Пример #2
0
function urls_arbo_dist($i, $entite, $args='', $ancre='') {
	if (is_numeric($i))
		return _generer_url_arbo($entite, $i, $args, $ancre);

	// traiter les injections du type domaine.org/spip.php/cestnimportequoi/ou/encore/plus/rubrique23
	if ($GLOBALS['profondeur_url']>0 AND $entite=='sommaire'){
		$entite = 'type_urls';
	}

	// recuperer les &debut_xx;
	if (is_array($args))
		$contexte = $args;
	else
		parse_str($args,$contexte);

	$url = $i;
	$id_objet = $type = 0;
	$url_redirect = null;

	// Migration depuis anciennes URLs ?
	// traiter les injections domain.tld/spip.php/n/importe/quoi/rubrique23
	if ($GLOBALS['profondeur_url']<=0
	AND $_SERVER['REQUEST_METHOD'] != 'POST') {
		include_spip('inc/urls');
		$r = nettoyer_url_page($i, $contexte);
		if ($r) {
			list($contexte, $type,,, $suite) = $r;
			$_id = id_table_objet($type);
			$id_objet = $contexte[$_id];
			$url_propre = generer_url_entite($id_objet, $type);
			if (strlen($url_propre)
			AND !strstr($url,$url_propre)) {
				list(,$hash) = explode('#', $url_propre);
				$args = array();
				foreach(array_filter(explode('&', $suite)) as $fragment) {
					if ($fragment != "$_id=$id_objet")
						$args[] = $fragment;
				}
				$url_redirect = generer_url_entite($id_objet, $type, join('&',array_filter($args)), $hash);

				return array($contexte, $type, $url_redirect, $type);
			}
		}
	}
	/* Fin compatibilite anciennes urls */

	// Chercher les valeurs d'environnement qui indiquent l'url-propre
	if (isset($_SERVER['REDIRECT_url_propre']))
		$url_propre = $_SERVER['REDIRECT_url_propre'];
	elseif (isset($_ENV['url_propre']))
		$url_propre = $_ENV['url_propre'];
	else {
		// ne prendre que le segment d'url qui correspond, en fonction de la profondeur calculee
		$url = ltrim($url,'/');
		$url = explode('/',$url);
		while (count($url)>$GLOBALS['profondeur_url']+1)
			array_shift($url);
		$url = implode('/',$url);
		$url_propre = preg_replace(',[?].*,', '', $url);
	}

	// Mode Query-String ?
	if (!$url_propre
	AND preg_match(',[?]([^=/?&]+)(&.*)?$,', $url, $r)) {
		$url_propre = $r[1];
	}

	if (!$url_propre) return; // qu'est-ce qu'il veut ???
	
	include_spip('base/abstract_sql'); // chercher dans la table des URLS

	// Revenir en utf-8 si encodage type %D8%A7 (farsi)
	$url_propre = rawurldecode($url_propre);

	// Compatibilite avec .htm/.html et autres terminaisons
	$t = array_diff(array_unique(array_merge(array('.html','.htm','/'),url_arbo_terminaison(''))),array(''));
	if (count($t))
		$url_propre = preg_replace('{('
		  .implode('|',array_map('preg_quote',$t)).')$}i', '', $url_propre);

	if (strlen($url_propre) AND !preg_match(',^[^/]*[.]php,',$url_propre)){
		$types_parents = array();
		
		// recuperer tous les objets de larbo xxx/article/yyy/mot/zzzz
		$url_arbo = explode('/',$url_propre);
		while (count($url_arbo)>0){
			$url_propre = array_pop($url_arbo);
			if (count($url_arbo))
				$type = array_pop($url_arbo);
			else
				$type=null;
			// Compatibilite avec les anciens marqueurs d'URL propres
			// Tester l'entree telle quelle (avec 'url_libre' des sites ont pu avoir des entrees avec marqueurs dans la table spip_urls)
			if (is_null($type)
			OR !$row=sql_fetsel('id_objet, type, date', 'spip_urls',array('url='.sql_quote("$type/$url_propre")))) {
				if (!is_null($type))
					array_push($url_arbo,$type);
				$row = sql_fetsel('id_objet, type, date', 'spip_urls',array('url='.sql_quote($url_propre)));
			}
			if ($row) {
				$type = $row['type'];
				$col_id = id_table_objet($type);
				
				// n'affecter que la premiere fois un parent de type id_rubrique
				if (!isset($contexte[$col_id]))
					$contexte[$col_id] = $row['id_objet'];

				if (!$entite
				OR !in_array($type,$types_parents))
					$entite = $type;
	
				if ($p = url_arbo_parent($type))
					$types_parents[]=end($p);
			}
			else {
				// un segment est inconnu
				if ($entite=='' OR $entite=='type_urls') {
					// on genere une 404 comme il faut si on ne sait pas ou aller
					return array(array(),'404');
				}
				return; // ?
			}
		}

		// gerer le retour depuis des urls propres
		if (($entite=='' OR $entite=='type_urls')
		AND $GLOBALS['profondeur_url']<=0){
			$urls_anciennes = charger_fonction('propres','urls');
			return $urls_anciennes($url_propre, $entite, $contexte);
		}
	}
	if ($entite=='' OR $entite=='type_urls' /* compat .htaccess 2.0 */) {
		if ($type)
			$entite =  ($type == 'syndic') ?  'site' : $type;
		else {
			// Si ca ressemble a une URL d'objet, ce n'est pas la home
			// et on provoque un 404
			if (preg_match(',^[^\.]+(\.html)?$,', $url)) {
				$entite = '404';
				$contexte['erreur'] = ''; // qu'afficher ici ?  l'url n'existe pas... on ne sait plus dire de quel type d'objet il s'agit
			}
		}
	}
	define('_SET_HTML_BASE',1);

	return array($contexte, $entite, null, $is_qs?$entite:null);
}