Login   Register  
PHP Classes
elePHPant
Icontem

File: gCurl/gcurl.class.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Grigori Kochanov  >  gCurl  >  gCurl/gcurl.class.php  >  Download  
File: gCurl/gcurl.class.php
Role: Class source
Content type: text/plain
Description: core class
Class: gCurl
Perform HTTP requests using Curl
Author: By
Last change: added a url as author contact details
Date: 6 years ago
Size: 13,241 bytes
 

Contents

Class file image Download
<?php
/**
 * This file contains class gCurl, abstract class gCurlHandlers and exception class gCurlException.
 * It requires gCurlRequest and gCurlResponse classes as well
 * 
 * @package gCurl
 * @author Grigori Kochanov http://www.grik.net/
 */

//Load package classes
if (!class_exists('gCurlRequest')){
    require_once('gCurlRequest.class.php');
}
if (!class_exists('gCurlResponse')){
    require_once('gCurlResponse.class.php');
}
if (!class_exists('gURI')){
    require_once('URI.class.php');
}

//load the exception base class
if (!class_exists('gksException')){
    require_once('gksException.class.php');
}

/**
 * The class extending this interface will contain methods that will be used as handlers
 * for processing HTTP response
 * 
 * @package GCurl
 * @author Grigori Kochanov
 * @version 2
 * @abstract 
 */
abstract class gCurlHandlers{
    /**
     * Name of the method to handle the response body.
     * You can redefine it while processing response headers or cookies.
     * Use NULL to avoid setting a handler for the body.
     *
     * @var string
     */
    public $bodyHandlerName = 'bodyHandler';
    
    /**
     * Instance of the gCurl class utilizing this handler
     *
     * @var gCurl
     */
    protected $gCurl;
    
    /**
     * The handler method triggered after the response headers are received and processed
     * but before receiving the body
     * 
     * @param array $headers
     */
    function headersHandler(array $headers){}
    
    /**
     * The method is triggered after the response headers are received,
     * it receives an array of cookies set by the server as parameter
     *
     * @param array $cookies
     */
    function cookiesHandler(array $cookies){}
    
    /**
     * Default body handler
     *
     * @param string $chunk
     */
    function bodyHandler($ch, $chunk){}
        
    /**
     * Set the reference to the gCurl object that uses this class methods as handlers
     *
     * @param gCurl $gCurl
     */
    final function setGCurlReference(gCurl $gCurl){
        $this->gCurl = $gCurl;
    }
    
    /**
     * Destructor - to avoid a circular reference
     *
     */
    final function cleanGCurlReference(){
        $this->gCurl = null;
    }
}

/**
 * A class to simplify complex tasks for performing and processing HTTP requests with CURL
 *
 * @package GCurl
 * @author Grigori Kochanov
 * @version 2
 */
class gCurl {
    
    /**
     * Error number returned by cURL
     *
     * @var int
     */
    public $curl_errno=0;
    
    /**
     * Error text returned by cURL
     *
     * @var string
     */
    public $curl_error='';
    
    /**
     * instance of the URI class
     *
     * @var gURI
     */
    public $URI;
    
    /**
     * CURL resource handler
     *
     * @var resource
     */
    public $ch;
    
    /**
     * Full URL requested
     *
     * @var string
     */
    protected $location_href= '';
    
    /**
     * Instance of the gCurlRequest object
     *
     * @var gCurlRequest
     * @see gCurlRequest.class.php
     */
    public $Request;
    /**
     * Response object reference
     *
     * @var gCurlResponse
     * @see gCurlResponse.class.php
     */
    public $Response;
    
    /**
     * Flag that defines if cURL should automatically follow the "Location" header or not
     *
     * @var bool
     */
    private $followlocation=0;
    
    /**
     * Flag that defines if cURL should return the body of the response
     *
     * @var bool
     */
    private $return_transfer=1;
    
    /**
     * System network interface (IP)
     * 
     * @var string
     */
    private $interface=null;
    
    
    /**
     * Constants - flags
     */
    const 
    HTTP_BODY = 1,
    HTTP_HEADERS=2,
    HTTP_FULL=3;
    /**
     * sets the status of the data to show the end
     */
    const FLAG_EOF=1;
    /**
     * the HTTP response is received
     */
    const FLAG_HTTP_OK=2;
    /**
     * headers are received and processed
     */
    const FLAG_HEADERS_RECEIVED=4;
    
    /**
     * Constructor of the class
     *
     * @return void
     */
    function __construct($url,$method='GET'){
        if (!defined('CURLE_OK')){
            throw new gCurlException(10);
        }
        //init service objects
        $this->URI = new gURI();
    
        $this->ch = curl_init();
        if ($this->catchCurlError() || !$this->ch){
            throw new gCurlException(15);
        }
    
    
        //define basic parameters
        curl_setopt ($this->ch, CURLOPT_HEADER, 0);
        curl_setopt ($this->ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt ($this->ch, CURLOPT_FOLLOWLOCATION, false);
        curl_setopt ($this->ch, CURLOPT_ENCODING, '');
        curl_setopt ($this->ch, CURLOPT_RETURNTRANSFER, 1);
        
        //create request and response objects
        $this->Request= new gCurlRequest();
        $this->Response = new gCurlResponse($this->ch,$this->URI);
        
        //set the headers handler
        curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, array($this->Response,'headersHandler'));

        //prepare the URL to browse to
        $this->URI->process($url);
        $this->location_href = $this->URI->full;
    
        $this->Request->setRequestMethod($method);
        if (strcasecmp($method, 'POST')==0){
            curl_setopt ($this->ch, CURLOPT_POST, 1);
        }
    }

    /**
     * signal a redirect URL
     *
     * @param string $new_uri
     */
    function redirect($new_uri){
        $this->URI->parse_http_redirect($new_uri);
        $this->location_href = $this->URI->full;
        
        //create request and response objects
        $this->Request = new gCurlRequest();
        $this->Response->cleanup();
    }

    /**
     * Define whether to return the transfer or not
     *
     * @param bool $value
     */
    function returnTransfer($value){
        $this->return_transfer=(bool)$value;
    }
    
    /**
     * sets the time limit of time the CURL can execute
     *
     * @param int $seconds
     */
    function setTimeout($seconds){
        curl_setopt($this->ch,CURLOPT_TIMEOUT,$seconds);
        if ($this->catchCurlError()){
            throw new gCurlException(22);
        }
    }
    
    /**
     * Set the network interface for the outgoing connection
     *
     * @param string $interface
     */
    function setInterface($interface){
        $this->interface = $interface;
        curl_setopt($this->ch,CURLOPT_INTERFACE,$this->interface);
    }
    
    /**
     * Set extra options for the connection
     *
     * @param array $options
     */
    function setOptions(array $options){
        curl_setopt_array($this->ch,$options);
    }
    
    /**
     * Run the CURL engine
     *
     * @return gCurlResponse
     */
    function exec(){
        //add cookies to headers
        if ($this->Request->cookie_string){
            $this->Request->registerCustomHeader('Cookie: '.$this->Request->cookie_string);
        }
        //process user-defined request headers
        if ($this->Request->custom_headers){
            curl_setopt ($this->ch, CURLOPT_HTTPHEADER, $this->Request->custom_headers);
        }
        //prepare the POST data
        if ($this->Request->method=='POST' && $this->Request->post_data){
            curl_setopt ($this->ch,CURLOPT_POSTFIELDS, $this->Request->post_data);
        }
        //use proxy if defined
        if ($this->Request->proxy && $this->Request->proxy_port){
            curl_setopt ($this->ch, CURLOPT_PROXY, $this->Request->proxy);
            curl_setopt ($this->ch, CURLOPT_PROXYPORT, $this->Request->proxy_port);
            if($this->Request->proxyuser){
                curl_setopt ($this->ch, CURLOPT_PROXYUSERPWD, $this->Request->proxyuser.':'.$this->Request->proxypwd);
            }
        }
        
        //set the URI to connect to
        curl_setopt ($this->ch, CURLOPT_URL, $this->location_href);
        curl_setopt($this->ch,CURLOPT_NOBODY,!$this->return_transfer);

        //run the request
        if ($this->return_transfer){
            $result = curl_exec($this->ch);
        }else{
            curl_exec($this->ch);
            $result='';
        }
        //clear the reference in the handler to avoid circular references
        if ($this->Response->gCurlHandlers){
            $this->Response->gCurlHandlers->cleanGCurlReference();
        }
        
        if ($this->return_transfer && !$result && !$this->Response->headers['len']){
            throw new gCurlException(115);
        }
        //return the response data if required
        if ($this->return_transfer && is_string($result)){
            $this->Response->body = $result;
        }
        return $this->Response;
    }

    /**
     * Close the connection on object destruction
     *
     */
    function __destruct(){
        $this->disconnect();
    }
    
    /**
     * close connection to the remote host
     *
     */
    function disconnect(){
        if (is_resource($this->ch)){
            curl_close($this->ch);
        }
        $this->ch = NULL;
    }
    
    /**
     * check the memory consumption
     *
     */
    function checkMemoryConsumption(){
        if (memory_get_usage()>MEMORY_USAGE_LIMIT*1024){
            throw new gCurlException(60);
        }
    }
    
    /**
     * Check for an error
     *
     * @return bool
     */
    function catchCurlError(){
        if(!is_resource($this->ch) || !($curl_errno=curl_errno($this->ch))){
            return false;
        }
        $this->curl_errno = $curl_errno;
        $this->curl_error = curl_error($this->ch);
        throw new gCurlException(80,$curl_errno,$this->curl_error);
        return true;
    }
    
    /**
     * Pass the object implementing the handlers
     * 
     * @param gCurlHandlers $Handlers
     */
    function setHandlers(gCurlHandlers $Handlers){
        $Handlers->setGCurlReference($this);
        $this->Response->setHandlers($Handlers);
    }
//end of the class
}



/**
 * Exceptions for gCurl
 *
 */
class gCurlException extends Exception implements gksException {

    /**
     * The list of exception codes
     *
     * @var array
     */
    private $exception_codes= array(
        1=>'Connection error',
        10=>'Curl extension not loaded',
        15=>'Could not initialize CURL',
        20=>'Invalid handler method name',
        21=>'Error assigning the output stream for headers',
        22=>'Error setting CURL timeout',
        23=>'Error setting URL to connect to',
        50=>'Invalid request method',
        51=>'Invalid request parameters',
        60=>'Out of memory',
        70=>'Headers already sent to the user agent',
        80=>'CURL reported error',
        90=>'Invalid delay value',
        110=>'Non-HTTP response headers',
        115=>'Curl returned empty result after execution',
        120=>'Invalid host of the requested URI',
        125=>'Invalid URI',
        130=>'Redirects limit reached',
    );

    /**
     * Error number for CURL operation
     *
     * @var int
     */
    public $curl_errno;
    
    /**
     * Error message returned by CURL
     *
     * @var string
     */
    public $curl_error='';
    
    /**
     * Initialize the exception
     *
     * @param int $code
     * @param int $curl_errno
     * @param string $curl_error
     */
    function __construct($code, $curl_errno=0, $curl_error=''){
        //get the error description
        key_exists($code, $this->exception_codes) || $code=1;
        $message= $this->exception_codes[$code]; 
        if ($curl_errno){
            $message.="\nCurl Error #: ".$curl_errno;
        }
        if ($curl_error){
            $message.="\nError message: ".$curl_error;
        }
        //set the error string through the Exception class constructor
        parent::__construct($message, $code);
        
    }
    
    /**
     * Get the message prepared to write to the log file
     *
     * @return string
     */
    function getLogMessage(){
        $log_string='Exception '.$this->getCode().':'.$this->message."\n";
        if ($this->getCode() != 80){
            $log_string .= 'line '.$this->getLine().' file '.$this->getFile()."\n".$this->getTraceAsString()."\n";
        }
        return $log_string;
    }
    
    /**
     * Get the error message to output to the browser
     *
     * @return string
     */
    function getHtmlMessage(){
        $message='<b>Exception '.$this->getCode().'</b>: '.$this->message."<br>\n";
        if ($this->getCode() != 80){
            $message .= 'file '.$this->getFile()."\n<br> line ".$this->getLine().
            "<br>\nTrace: <br />\n".nl2br($this->getTraceAsString())."<br>\n";
        }
        return $message;
    }

//class end
}