Example #1
0
function migration_recuperer_page($url, $trans=false, $get_headers=false,
	$taille_max = null, $datas='', $boundary='', $refuser_gz = false,
	$date_verif = '', $uri_referer = '') {
	$gz = false;

	// $copy = copier le fichier ?
	$copy = (is_string($trans) AND strlen($trans) > 5); // eviter "false" :-)

	if (is_null($taille_max))
		$taille_max = $copy ? _COPIE_LOCALE_MAX_SIZE : 1048576;

	// Accepter les URLs au format feed:// ou qui ont oublie le http://
	$url = preg_replace(',^feed://,i', 'http://', $url);
	if (!preg_match(',^[a-z]+://,i', $url)) $url = 'http://'.$url;

	if ($taille_max == 0)
		$get = 'HEAD';
	else
		$get = 'GET';

	if (!empty($datas)) {
		$get = 'POST';
		list($type, $postdata) = prepare_donnees_post($datas, $boundary);
		$datas = $type . 'Content-Length: '.strlen($postdata)."\r\n\r\n".$postdata;
	}

	// dix tentatives maximum en cas d'entetes 301...
	for ($i=0;$i<10;$i++) {
		$url = migration_recuperer_lapage($url, $trans, $get, $taille_max, $datas, $refuser_gz, $date_verif, $uri_referer);
		if (!$url) return false;
		if (is_array($url)) {
			list($headers, $result) = $url;
			return ($get_headers ? $headers."\n" : '').$result;
		} else spip_log("recuperer page recommence sur $url");
	}
}
Example #2
0
/**
 * Récupère le contenu d'une URL
 * au besoin encode son contenu dans le charset local
 *
 * @uses init_http()
 * @uses recuperer_entetes()
 * @uses recuperer_body()
 * @uses transcoder_page()
 *
 * @param string $url
 * @param array $options
 *   bool transcoder : true si on veut transcoder la page dans le charset du site
 *   string methode : Type de requête HTTP à faire (HEAD, GET ou POST)
 *   int taille_max : Arrêter le contenu au-delà (0 = seulement les entetes ==> requête HEAD). Par defaut taille_max = 1Mo ou 16Mo si copie dans un fichier
 *   string|array datas : Pour faire un POST de données (force la methode POST si non vide)
 *   string boundary : boundary pour formater les datas au format array
 *   bool refuser_gz : Pour forcer le refus de la compression (cas des serveurs orthographiques)
 *   int if_modified_since : Un timestamp unix pour arrêter la récuperation si la page distante n'a pas été modifiée depuis une date donnée
 *   string uri_referer : Pour préciser un référer différent
 *   string file : nom du fichier dans lequel copier le contenu
 *   int follow_location : nombre de redirections a suivre (0 pour ne rien suivre)
 *   string version_http : version du protocole HTTP a utiliser (par defaut defini par la constante _INC_DISTANT_VERSION_HTTP)
 * @return array|bool
 *   false si echec
 *   array sinon :
 *     int status : le status de la page
 *     string headers : les entetes de la page
 *     string page : le contenu de la page (vide si copie dans un fichier)
 *     int last_modified : timestamp de derniere modification
 *     string location : url de redirection envoyee par la page
 *     string url : url reelle de la page recuperee
 *     int length : taille du contenu ou du fichier
 *
 *     string file : nom du fichier si enregistre dans un fichier
 */
function recuperer_url($url, $options = array())
{
    $default = array('transcoder' => false, 'methode' => 'GET', 'taille_max' => null, 'datas' => '', 'boundary' => '', 'refuser_gz' => false, 'if_modified_since' => '', 'uri_referer' => '', 'file' => '', 'follow_location' => 10, 'version_http' => _INC_DISTANT_VERSION_HTTP);
    $options = array_merge($default, $options);
    // copier directement dans un fichier ?
    $copy = $options['file'];
    if ($options['methode'] == "HEAD") {
        $options['taille_max'] = 0;
    }
    if (is_null($options['taille_max'])) {
        $options['taille_max'] = $copy ? _COPIE_LOCALE_MAX_SIZE : _INC_DISTANT_MAX_SIZE;
    }
    if (!empty($options['datas'])) {
        $options['methode'] = 'POST';
        list($head, $postdata) = prepare_donnees_post($options['datas'], $options['boundary']);
        if (stripos($head, "Content-Length:") === false) {
            $head .= 'Content-Length: ' . strlen($postdata);
        }
        $options['datas'] = $head . "\r\n\r\n" . $postdata;
    }
    // Accepter les URLs au format feed:// ou qui ont oublie le http:// ou les urls relatives au protocole
    $url = preg_replace(',^feed://,i', 'http://', $url);
    if (!tester_url_absolue($url)) {
        $url = 'http://' . $url;
    } elseif (strncmp($url, "//", 2) == 0) {
        $url = 'http:' . $url;
    }
    $result = array('status' => 0, 'headers' => '', 'page' => '', 'length' => 0, 'last_modified' => '', 'location' => '', 'url' => $url);
    // si on ecrit directement dans un fichier, pour ne pas manipuler en memoire refuser gz
    $refuser_gz = ($options['refuser_gz'] or $copy) ? true : false;
    // ouvrir la connexion et envoyer la requete et ses en-tetes
    list($handle, $fopen) = init_http($options['methode'], $url, $refuser_gz, $options['uri_referer'], $options['datas'], $options['version_http'], $options['if_modified_since']);
    if (!$handle) {
        spip_log("ECHEC init_http {$url}");
        return false;
    }
    // Sauf en fopen, envoyer le flux d'entree
    // et recuperer les en-tetes de reponses
    if (!$fopen) {
        $res = recuperer_entetes_complets($handle, $options['if_modified_since']);
        if (!$res) {
            fclose($handle);
            $t = @parse_url($url);
            $host = $t['host'];
            // Chinoisierie inexplicable pour contrer
            // les actions liberticides de l'empire du milieu
            if (!need_proxy($host) and $res = @file_get_contents($url)) {
                $result['length'] = strlen($res);
                if ($copy) {
                    ecrire_fichier($copy, $res);
                    $result['file'] = $copy;
                } else {
                    $result['page'] = $res;
                }
                $res = array('status' => 200);
            } else {
                return false;
            }
        } elseif ($res['location'] and $options['follow_location']) {
            $options['follow_location']--;
            fclose($handle);
            include_spip('inc/filtres');
            $url = suivre_lien($url, $res['location']);
            spip_log("recuperer_url recommence sur {$url}");
            return recuperer_url($url, $options);
        } elseif ($res['status'] !== 200) {
            spip_log("HTTP status " . $res['status'] . " pour {$url}");
        }
        $result['status'] = $res['status'];
        if (isset($res['headers'])) {
            $result['headers'] = $res['headers'];
        }
        if (isset($res['last_modified'])) {
            $result['last_modified'] = $res['last_modified'];
        }
        if (isset($res['location'])) {
            $result['location'] = $res['location'];
        }
    }
    // on ne veut que les entetes
    if (!$options['taille_max'] or $options['methode'] == 'HEAD' or $result['status'] == "304") {
        return $result;
    }
    // s'il faut deballer, le faire via un fichier temporaire
    // sinon la memoire explose pour les gros flux
    $gz = false;
    if (preg_match(",\\bContent-Encoding: .*gzip,is", $result['headers'])) {
        $gz = _DIR_TMP . md5(uniqid(mt_rand())) . '.tmp.gz';
    }
    // si on a pas deja recuperer le contenu par une methode detournee
    if (!$result['length']) {
        $res = recuperer_body($handle, $options['taille_max'], $gz ? $gz : $copy);
        fclose($handle);
        if ($copy) {
            $result['length'] = $res;
            $result['file'] = $copy;
        } elseif ($res) {
            $result['page'] =& $res;
            $result['length'] = strlen($result['page']);
        }
    }
    if (!$result['page']) {
        return $result;
    }
    // Decompresser au besoin
    if ($gz) {
        $result['page'] = implode('', gzfile($gz));
        supprimer_fichier($gz);
    }
    // Faut-il l'importer dans notre charset local ?
    if ($options['transcoder']) {
        include_spip('inc/charsets');
        $result['page'] = transcoder_page($result['page'], $result['headers']);
    }
    return $result;
}