<?php
//----------------------------------------//
// classes/http.class..php
// Classe pour gérer des requetes http
//----------------------------------------//
// Auteur : winzou
// Date de creation : 20/06/04
// Date de derniere modification : 20/10/04
//----------------------------------------//


class http
{

// options pour l'ouverture de socket
    var $open;

// donnees à envoyer sur les requetes
    var $cookies;
    var $data;

// var de config
    var $config;

// contient l'host en cours
    var $host;

// ressource du fsockopen. [bug -> non utilise]
    var $gblfp;

// Tableaux des requetes, erreurs, reponses serveur, page html
    var $array_req;
    var $array_err;
    var $array_rep;
    var $array_htm;
    

/*
* HTTP
* ===============
* Constructeur
* Préciser l'host et, facultatif, la connection automatique ou non
* connection auto par défaut
* ===============
* (bool) http( (string)host [,(bool)connect] )
*/
function http($host,$connect = true)
    {
    $this->open['port']    = 80;
    $this->open['timeout'] = 10;
    $this->open['error']   = NULL;
    $this->open['errno']   = NULL;
    
    $this->cookies = array();
    
    $this->config['redir']   = true;
    $this->config['referer'] = $host;
    
    $this->array_req = array('Aucune requete actuellement envoyée.');
    $this->array_req = array('Aucune erreur rencontrée.');
    
    $this->gblfp = NULL;
    
    $this->host = $host;
    
    if($connect)
        {
        $this->gblfp = $this->connect($host);
        return $this->gblfp;
        }
    }

/*
* CONNECT
* ==================
* Fonction de connection au socket sur l'host precise
* retourne la ressource ou false si erreur
* ==================
* (bool) connect( (string)$host )
*/
function connect($host)
    {
    if($fp = fsockopen($host,$this->open['port'],$this->open['errno'],$this->open['error'],$this->open['timeout']))
        {return $fp;}
    else
        {
        $this->array_err[] = 'Impossible de se connecter à la socket sur l\'host '.$host.':'.$this->open['port'].'.';
        return false;
        }
    }

/*
* HTTP_ERROR
* ===================
* Retourne la derniere erreur rencontree
* ===================
* (string) http_error( void )
*/
function http_error()
    {return end($this->array_err);}

/*
* GET_COOKIES_FROM_HEADER
* ==========================
* Extrait un array contenant les cookies d'une reponse http server
* Si aucun argument precise, derniere data utilisee
* ==========================
* (array) get_cookie_from_header( [(string)$header] )
*/
function get_cookies_from_header($header = 'def')
    {
    if($header == 'def')
        {$header = end($this->array_rep);}
    
    preg_match_all('`Set-Cookie: (.*?)=(.*?);.*?\S`is',$header,$output);

//    preg_match_all('` (.*?)=(.*?);`is',$header,$output2);
    
    for($i=0;$i<count($output[1]);$i++)
        {$cookies[$output[1][$i]] = $output[2][$i];}
//    for($i=0;$i<count($output2[1]);$i++)
//        {$cookies[$output2[1][$i]] = $output2[2][$i];}
        
    return isset($cookies)?(array)$cookies:array();
    }

/*
* GET_HEADER_FROM_COOKIES
* =========================
* Cree les headers a partir d'un array contenant des cookies
* Si aucun argument precise, derniere data utilise
* =========================
* (string) get_header_from_cookies( [(array)$cookies] )
*/
function get_header_from_cookies($cookies = 'def')
    {
    if($cookies == 'def')
        {$cookies = $this->cookies;}
    
    if(count($cookies) > 0)
        {
        $cook = 'Cookie:';
        foreach($cookies as $key => $val)
            {$cook .= ' '.$key.'='.$val.';';}
        $cook = substr($cook,0,-1)."\r\n";
        
        return $cook;
        }
    else
        {return '';}
    }

/*
* GET_HEADER_FROM_DATA
* ======================
* Cree les headers à partir d'un array contenant les donnees à envoyer en post
* Si aucun argument precise, renvoie une string vide
* ======================
* (string) get_header_form_data( [(array)$data] )
*/
function get_header_from_data($data = 'none')
    {
    if($data == 'none')
        {return '';}
    else
        {
        $new_data = '';
        foreach($data as $key => $val)
            {$new_data .= '&'.$key.'='.urlencode($val);}
        return substr($new_data,1,strlen($new_data));
        }
    }

/*
* REQUEST
* ===============
* Envoie une requete http au server
* Requiere la methode et le chemin
* Les cookies sont envoyes automatiquement si existant
* ===============
* (bool) request( (string)$method, (string)$path [, (array)$data [, (array)$cookies ]] )
*/
function request($method,$path,$data = 'none',$cookies = 'def')
    {
    $this->gblfp = $this->connect($this->host);
        
    $data = $this->get_header_from_data($data);
    
    $this->array_req[] = strtoupper($method).' '.$path." HTTP/1.1\r\n"
    .'Host: '.$this->host."\r\n"
    .$this->get_header_from_cookies($cookies)
    .'User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1)'."\r\n"
    //.'Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1'."\r\n"
    //.'Accept-Language: en-us, en;q=0.50'."\r\n"
    //.'Accept-Encoding: gzip, deflate, compress;q=0.9'."\r\n"
    //.'Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66'."\r\n"
    //.'Keep-Alive: 300'."\r\n"
    //.'Connection: keep-alive'."\r\n"
    .'Referer: '.$this->config['referer']."\r\n"
    //.'Cache-Control: max-age=0'."\r\n"
    .'Content-type: application/x-www-form-urlencoded'."\r\n"
    .'Content-length: '.strlen($data)."\r\n"
    ."\r\n".$data."\r\n\r\n";

    if(@fputs($this->gblfp,end($this->array_req)))
        {return true;}
    else
        {
        $this->array_err[] = 'Erreur lors de l\'envoie de la requete';
        return false;
        }
    }


/*
* GET_CONTENT
* =================
* Recupere le resultat de la derniere requete
* =================
* (string) get_content( (bool) $html )
*/
function get_content($html = true)
    {
    $data = array();        
    while($line = @fgets($this->gblfp,4096))
        {$data[] = $line;}
    
    //fclose($this->gblfp);
    $data = implode('',$data);
    
    if(count($data) == 0)
        {
        $this->array_err[] = 'Aucun contenu a la sortie du socket dans get_content()';
        return false;
        }
    
    if($html)
    {
    	$pos  = strpos($data,'<html');
    	if(!is_integer($pos))
    	    {$pos = strpos($data,'<HTML');}
    	
    	$pos2 = strpos($data,'</html>');
    	if(!is_integer($pos2))
    	    {$pos2 = strpos($data,'</HTML>');}
    	    
    	$this->array_rep[] = substr($data,0,$pos);
    	$this->array_htm[] = substr($data,$pos,-(strlen($data)-$pos2));
    	    
    	return end($this->array_htm);
     }
     else
     {
     	$this->array_rep[] = substr($data,0,$pos);
     	
     	$data = explode("\r\n\r\n",$data);
	
	$this->array_data[] = end($data);
	
     	return end($this->array_data);
     }
    }


/*
* LOAD_PAGE
* =====================
* Charge une page, redirige si besoin, verifie les erreurs
* =====================
* (string) load_page( (string)$method, (string)$path [, (array)$data [, (array)$cookies ]] )
*/
function load_page($method,$path,$data = 'none',$cookies = 'def')
    {
    if(!$this->request($method,$path,$data,$cookies))
        {return false;}
    else
        {
        $html = $this->get_content(true);
        
        if(preg_match('`<title>.*?([0-9]+).*?</title>`is',$html,$output))
            {
            $this->array_err[] = 'Erreur dans la requete, erreur "'.$output[1].'" rencontrée.<br />Requete : <br /><em>'.end($this->array_req).'</em><br /><br />'.$this->data;
            return false;
            }
        else
            {
            $cookies = $this->get_cookies_from_header();
            
            foreach($cookies as $key => $val)
                {$this->cookies[$key] = $val;}
            
            if($this->config['redir'] AND preg_match('`location: (.*?)\s`is',end($this->array_rep),$output))
                {return $this->load_page('get','/'.$output[1]);}
            else
                {return $this->get_html();}
            }
        }
    }

/*
* LOAD_FILE
* =====================
* Charge une file, redirige si besoin, verifie les erreurs
* =====================
* (string) load_file( (string)$method, (string)$path [, (array)$data [, (array)$cookies ]] )
*/
function load_file($method,$path,$data = 'none',$cookies = 'def')
    {
    if(!$this->request($method,$path,$data,$cookies))
        {return false;}
    else
        {
        $html = $this->get_content(false);
        
        if(preg_match('`<title>.*?([0-9]+).*?</title>`is',$html,$output))
            {
            $this->array_err[] = 'Erreur dans la requete, erreur "'.$output[1].'" rencontrée.<br />Requete : <br /><em>'.end($this->array_req).'</em><br /><br />'.$this->data;
            return false;
            }
        else
            {
            $cookies = $this->get_cookies_from_header();
            
            foreach($cookies as $key => $val)
                {$this->cookies[$key] = $val;}
            
            if($this->config['redir'] AND preg_match('`location: (.*?)\s`is',end($this->array_rep),$output))
                {return $this->load_page('get','/'.$output[1]);}
            else
                {return $this->get_data();}
            }
        }
    }
    
/*
* GET_HTML
* ==============
* Retourne le contenu de la page html resultant de la derniere requete effectuee
* ==============
* (string) get_html( void )
*/
function get_html()
    {return end($this->array_htm);}

/*
* GET_DATA
* =================
* Retourne la réponse serveur de la derniere requete effectuee sans le header
* =================
* (string) get_header( void )
*/
function get_data()
    {return end($this->array_data);}



/*
* GET_BRUT_DATA
* =================
* Retourne la réponse serveur de la derniere requete effectuee
* =================
* (string) get_brut_data( void )
*/
function get_brut_data()
    {return end($this->array_rep);}


} // fin classe


// end
?>