分享一个php 发送post请求的类库

程序中,非常多的时候需要请求接口,这里分享一个一直使用的类库:

<?php

 * Samle usage:
 * $curl = &new Curl_HTTP_Client();
 * $useragent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
 * $curl->set_user_agent($useragent);
 * $curl->store_cookies("/tmp/cookies.txt");
 * $post_data = array('login' => 'pera', 'password' => 'joe');
 * $html_data = $curl->send_post_data(http://www.foo.com/login.php, $post_data);
 */
class TNet_Dinke
{

    /**
     * Curl handler
     *
     * @access private
     * @var resource
     */
    var $ch;

    /**
     * set debug to true in order to get usefull output
     *
     * @access private
     * @var string
     */
    var $debug = false;

    /**
     * Contain last error message if error occured
     *
     * @access private
     * @var string
     */
    var $error_msg;
    
    var $n_referrer;
    var $n_useragent;
    var $n_header;

    /**
     * Curl_HTTP_Client constructor
     *
     * @param
     *            boolean debug
     * @access public
     * @return TNet_Http_Dinke
     */
    function __construct($debug = false)
    {
        $this->debug = $debug;
        $this->_init();
    }

    /**
     * Init Curl session
     *
     * @access public
     */
    function _init()
    {
        // initialize curl handle
        $this->ch = curl_init();
        
        // set various options
        
        // set error in case http return code bigger than 300
        curl_setopt($this->ch, CURLOPT_FAILONERROR, true);
        
        // allow redirects
        curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
        
        // use gzip if possible
        curl_setopt($this->ch, CURLOPT_ENCODING, 'gzip, deflate');
        
        // do not veryfy ssl
        // this is important for windows
        // as well for being able to access pages with non valid cert
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
        
        curl_setopt($this->ch, CURLOPT_MAXREDIRS, 2000);
    }

    /**
     * Set username/pass for basic http auth
     *
     * @param
     *            string user
     * @param
     *            string pass
     * @access public
     */
    function set_credentials($username, $password)
    {
        curl_setopt($this->ch, CURLOPT_USERPWD, "$username:$password");
    }

    /**
     * Set referrer
     *
     * @param
     *            string referrer url
     * @access public
     */
    function set_referrer($referrer_url)
    {
        $this->n_referrer = $referrer_url;
        curl_setopt($this->ch, CURLOPT_REFERER, $referrer_url);
    }

    /**
     * Set client's useragent
     *
     * @param
     *            string user agent
     * @access public
     */
    function set_user_agent($useragent)
    {
        $this->n_useragent = $useragent;
        curl_setopt($this->ch, CURLOPT_USERAGENT, $useragent);
    }

    function set_header($header)
    {
        $this->n_header = $header;
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, $header);
    }

    /**
     * Set to receive output headers in all output functions
     *
     * @param
     *            boolean true to include all response headers with output, false otherwise
     * @access public
     */
    function include_response_headers($value)
    {
        curl_setopt($this->ch, CURLOPT_HEADER, $value);
    }

    /**
     * Set proxy to use for each curl request
     *
     * @param
     *            string proxy
     * @access public
     */
    function set_proxy($proxy)
    {
        curl_setopt($this->ch, CURLOPT_PROXY, $proxy);
    }

    /**
     * Send post data to target URL
     * return data returned from url or false if error occured
     *
     * @param
     *            string url
     * @param
     *            mixed post data (assoc array ie. $foo['post_var_name'] = $value or as string like var=val1&var2=val2)
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 10)
     * @return string data
     * @access public
     */
    function send_post_data($url, $postdata, $ip = null, $timeout = 10)
    {
        // set various curl options first
        
        // set url to post to
        curl_setopt($this->ch, CURLOPT_URL, $url);
        
        // return into a variable rather than displaying it
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        
        // bind to specific ip address if it is sent trough arguments
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        // set curl function timeout to $timeout
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        // set method to post
        curl_setopt($this->ch, CURLOPT_POST, true);
        
        // generate post string
        $post_array = array ();
        if (is_array($postdata)) {
            foreach ($postdata as $key => $value) {
                $post_array[] = urlencode($key) . "=" . urlencode($value);
            }
            
            $post_string = implode("&", $post_array);
            
            if ($this->debug) {
                echo "Url: $url\nPost String: $post_string\n";
            }
        } else {
            $post_string = $postdata;
        }
        
        // set post string
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post_string);
        
        // and finally send curl request
        $result = curl_exec($this->ch);
        $returninfo = curl_getinfo($this->ch);
        
        $this->log($url, $result, array (
            "post" => $postdata,
            "returninfo" => $returninfo
        ));
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return $result;
        }
    }

    /**
     * fetch data from target URL
     * return data returned from url or false if error occured
     *
     * @param
     *            string url
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 5)
     * @return string data
     * @access public
     */
    function fetch_url($url, $ip = null, $timeout = 30)
    {
        // set url to post to
        curl_setopt($this->ch, CURLOPT_URL, $url);
        
        // set method to get
        curl_setopt($this->ch, CURLOPT_HTTPGET, true);
        
        // return into a variable rather than displaying it
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        
        // bind to specific ip address if it is sent trough arguments
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        // set curl function timeout to $timeout
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        // and finally send curl request
        $result = curl_exec($this->ch);
        $returninfo = curl_getinfo($this->ch);
        // log the result;
        $this->log($url, $result, array (
            "returninfo" => $returninfo
        ));
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return $result;
        }
    }

    public function getArrByRs($string)
    {
        $headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
        
        $rs = array ();
        
        $rs['header'] = substr($string, 0, $headerSize);
        $rs['body'] = substr($string, $headerSize);
        $rs['headerSize'] = $headerSize;
        
        return $rs;
    }

    public static function formatHeader($header, $keysArr = array())
    {
        $delimeter = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? "\r\n" : "\r";
        
        $headerArr = explode($delimeter, $header);
        
        $headerArr = array_filter($headerArr);
        
        $headerKeys = array (
            'Content-Type:',
            'Content-Type:',
            'HTTP/1.1',
            'Content-Length:',
            'Server:',
            'Date:',
            'Connection:'
        );
        
        if (is_array($keysArr)) {
            $headerKeys = array_merge($headerKeys, $keysArr);
        }
        
        $headerInfo = array ();
        $tempArr = array ();
        
        foreach ($headerKeys as $v) {
            
            foreach ($headerArr as $val) {
                
                if (strpos($val, $v) === false) {
                    continue;
                }
                
                $tempArr = explode($v, $val);
                $tempArr[1] = trim($tempArr[1]);
                
                $tempArr[1] != null && ($headerInfo[$v] = $tempArr[1]);
                
                break;
            }
        }
        
        return $headerInfo;
    }

    /**
     * Fetch data from target URL
     * and store it directly to file
     *
     * @param
     *            string url
     * @param
     *            resource value stream resource(ie. fopen)
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 5)
     * @return boolean true on success false othervise
     * @access public
     */
    function fetch_into_file($url, $fp, $ip = null, $timeout = 5)
    {
        // set url to post to
        curl_setopt($this->ch, CURLOPT_URL, $url);
        
        // set method to get
        curl_setopt($this->ch, CURLOPT_HTTPGET, true);
        
        // store data into file rather than displaying it
        curl_setopt($this->ch, CURLOPT_FILE, $fp);
        
        // bind to specific ip address if it is sent trough arguments
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        // set curl function timeout to $timeout
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        // and finally send curl request
        $result = curl_exec($this->ch);
        
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return true;
        }
    }

    /**
     * Send multipart post data to the target URL
     * return data returned from url or false if error occured
     * (contribution by vule nikolic, vule@dinke.net)
     *
     * @param
     *            string url
     * @param
     *            array assoc post data array ie. $foo['post_var_name'] = $value
     * @param
     *            array assoc $file_field_array, contains file_field name = value - path pairs
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 30 sec)
     * @return string data
     * @access public
     */
    function send_multipart_post_data($url, $postdata, $file_field_array = array(), $ip = null, $timeout = 30)
    {
        // set various curl options first
        
        // set url to post to
        curl_setopt($this->ch, CURLOPT_URL, $url);
        
        // return into a variable rather than displaying it
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        
        // bind to specific ip address if it is sent trough arguments
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        // set curl function timeout to $timeout
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        // set method to post
        curl_setopt($this->ch, CURLOPT_POST, true);
        
        // disable Expect header
        // hack to make it working
        $headers = array (
            "Expect: "
        );
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
        
        // initialize result post array
        $result_post = array ();
        
        // generate post string
        $post_array = array ();
        $post_string_array = array ();
        if (! is_array($postdata)) {
            return false;
        }
        
        foreach ($postdata as $key => $value) {
            $post_array[$key] = $value;
            $post_string_array[] = urlencode($key) . "=" . urlencode($value);
        }
        
        $post_string = implode("&", $post_string_array);
        
        if ($this->debug) {
            echo "Post String: $post_string\n";
        }
        
        // set post string
        // curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post_string);
        
        // set multipart form data - file array field-value pairs
        if (! empty($file_field_array)) {
            foreach ($file_field_array as $var_name => $var_value) {
                if (strpos(PHP_OS, "WIN") !== false)
                    $var_value = str_replace("/", "\\", $var_value); // win hack
                $file_field_array[$var_name] = "@" . $var_value;
            }
        }
        
        // set post data
        $result_post = array_merge($post_array, $file_field_array);
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $result_post);
        
        // and finally send curl request
        $result = curl_exec($this->ch);
        
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return $result;
        }
    }

    /**
     * Set file location where cookie data will be stored and send on each new request
     *
     * @param
     *            string absolute path to cookie file (must be in writable dir)
     * @access public
     */
    function store_cookies($cookie_file)
    {
        // use cookies on each request (cookies stored in $cookie_file)
        curl_setopt($this->ch, CURLOPT_COOKIEJAR, $cookie_file);
        curl_setopt($this->ch, CURLOPT_COOKIEFILE, $cookie_file);
    }

    /**
     * Set custom cookie
     *
     * @param
     *            string cookie
     * @access public
     */
    function set_cookie($cookie)
    {
        curl_setopt($this->ch, CURLOPT_COOKIE, $cookie);
    }

    /**
     * Get last URL info
     * usefull when original url was redirected to other location
     *
     * @access public
     * @return string url
     */
    function get_effective_url()
    {
        return curl_getinfo($this->ch, CURLINFO_EFFECTIVE_URL);
    }

    /**
     * Get http response code
     *
     * @access public
     * @return int
     */
    function get_http_response_code()
    {
        return curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
    }

    /**
     * Return last error message and error number
     *
     * @return string error msg
     * @access public
     */
    function get_error_msg()
    {
        $err = "Error number: " . curl_errno($this->ch) . "\n";
        $err .= "Error message: " . curl_error($this->ch) . "\n";
        
        return $err;
    }

    /**
     * Close curl session and free resource
     * Usually no need to call this function directly
     * in case you do you have to call init() to recreate curl
     *
     * @access public
     */
    function close()
    {
        // close curl session and free up resources
        curl_close($this->ch);
    }

    /**
     *
     * @return TNet_Dinke
     */
    public static function instance()
    {
        return new self();
    }

    public function get_client_ip()
    {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
            $ip = getenv("HTTP_CLIENT_IP");
        else 
            if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
                $ip = getenv("HTTP_X_FORWARDED_FOR");
            else 
                if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
                    $ip = getenv("REMOTE_ADDR");
                else 
                    if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
                        $ip = $_SERVER['REMOTE_ADDR'];
                    else
                        $ip = "";
        
        return ($ip);
    }

    function log($url, $msg, $retrun = array())
    {
       // $logs_dir = "/data/logs/nginx/fetch_api_log_api";
        $time = time();
        $date = date("Y-m-d H:i:s", $time);
        $log = $time . "\r\n";
        $log .= $date . "\r\n";
        $log .= "#########  URL  ######## \r\n";
        $log .= $url . "\r\n";
        if (isset($retrun['post'])) {
            $log .= "############ post param ########## \r\n";
            if (is_string($retrun['post'])) {
                $log .= $retrun['post'] . "\n";
            } elseif (is_array($retrun['post'])) {
                $log .= http_build_query($retrun['post']) . "\n";
            }
        }
        if (isset($this->n_header)) {
            $log .= "###### header ###### \r\n";
            if (is_string($this->n_header)) {
                $log .= $this->n_header . "\n";
            } elseif (is_array($this->n_header)) {
                $log .= json_encode(($this->n_header)) . "\n";
            }
        }
        if (isset($this->n_useragent)) {
            $log .= "###### useragent ###### \r\n";
            if (is_string($this->n_useragent)) {
                $log .= $this->n_useragent . "\n";
            } elseif (is_array($this->n_useragent)) {
                $log .= json_encode(($this->n_useragent)) . "\n";
            }
        }
        if (isset($this->n_referrer)) {
            $log .= "####### referrer ###### \r\n";
            if (is_string($this->n_referrer)) {
                $log .= $this->n_referrer . "\n";
            } elseif (is_array($this->n_referrer)) {
                $log .= json_encode(($this->n_referrer)) . "\n";
            }
        }
        $log .= "######## RESULT ###### \r\n";
        $log .= $msg . "\r\n";
        if (isset($retrun['returninfo']["total_time"])) {
            $log .= "######    request time ######\r\n";
            $log .= "total_time:" . $retrun['returninfo']["total_time"] . "\r\n";
        }
        $log .= "***********************************************************************\r\n";
        $log .= "\r\n";
        //if (! is_file($logs_dir)) {
          //  touch($logs_dir);
        //}
        wlog($log,"network_request");
        //file_put_contents($logs_dir, $log, FILE_APPEND);
    }
}

/**
 * @version $Id$
 * @package dinke.net
 * @copyright &copy; 2005 Dinke.net
 * @author Dragan Dinic <dragan@dinke.net>
 */

/**
require_once("curl_http_client.php");

$curl = &new Curl_HTTP_Client();

//pretend to be IE6 on windows
$useragent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
$curl->set_user_agent($useragent);

//un comment next two lines if you want to manage cookies
//$cookies_file = "/tmp/cookies.txt";
//$curl->store_cookies($cookies_file);

//Uncomment next line if you want to set credentials
//$curl->set_credentials($username, $password);

//Uncomment next line if you want to set specific referrer
//$curl->set_referrer("http://my.referrer.url");

//if you want to send some post data
//form post data array like this one
$post_data = array('login' => 'pera', 'password' => 'joe', 'other_foo_field' => 'foo_value');
//and send request to http://www.foo.com/login.php. Result page is stored in $html_data string
$html_data = $curl->send_post_data("http://www.foo.com/login.php", $post_data);
 
//You can also fetch data from somewhere using get method!
//Fetch html from url 
$html_data = $curl->fetch_url("http://www.foo.com/foobar.php?login=pera&password=joe&other_foo_field=foo_value");

//if you have more than one IP on your server, 
//you can also bind to specific IP address like ...
//$bind_ip = "192.168.0.1";
//$curl->fetch_url("http://www.foo.com/login.php", $bind_ip);
//$html_data = $curl->send_post_data("http://www.foo.com/login.php", $post_data, $bind_ip);
 */<?php

/**
 * @version 1.2
 * @package dinke.net
 * @copyright &copy; 2008 Dinke.net
 * @author Dragan Dinic <dragan@dinke.net>
 */

/**
 * Curl based HTTP Client
 * Simple but effective OOP wrapper around Curl php lib.
 * Contains common methods needed
 * for getting data from url, setting referrer, credentials,
 * sending post data, managing cookies, etc.
 *
 * Samle usage:
 * $curl = &new Curl_HTTP_Client();
 * $useragent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
 * $curl->set_user_agent($useragent);
 * $curl->store_cookies("/tmp/cookies.txt");
 * $post_data = array('login' => 'pera', 'password' => 'joe');
 * $html_data = $curl->send_post_data(http://www.foo.com/login.php, $post_data);
 */
class TNet_Dinke
{

    /**
     * Curl handler
     *
     * @access private
     * @var resource
     */
    var $ch;

    /**
     * set debug to true in order to get usefull output
     *
     * @access private
     * @var string
     */
    var $debug = false;

    /**
     * Contain last error message if error occured
     *
     * @access private
     * @var string
     */
    var $error_msg;
    
    var $n_referrer;
    var $n_useragent;
    var $n_header;

    /**
     * Curl_HTTP_Client constructor
     *
     * @param
     *            boolean debug
     * @access public
     * @return TNet_Http_Dinke
     */
    function __construct($debug = false)
    {
        $this->debug = $debug;
        $this->_init();
    }

    /**
     * Init Curl session
     *
     * @access public
     */
    function _init()
    {
        // initialize curl handle
        $this->ch = curl_init();
        
        // set various options
        
        // set error in case http return code bigger than 300
        curl_setopt($this->ch, CURLOPT_FAILONERROR, true);
        
        // allow redirects
        curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
        
        // use gzip if possible
        curl_setopt($this->ch, CURLOPT_ENCODING, 'gzip, deflate');
        
        // do not veryfy ssl
        // this is important for windows
        // as well for being able to access pages with non valid cert
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
        
        curl_setopt($this->ch, CURLOPT_MAXREDIRS, 2000);
    }

    /**
     * Set username/pass for basic http auth
     *
     * @param
     *            string user
     * @param
     *            string pass
     * @access public
     */
    function set_credentials($username, $password)
    {
        curl_setopt($this->ch, CURLOPT_USERPWD, "$username:$password");
    }

    /**
     * Set referrer
     *
     * @param
     *            string referrer url
     * @access public
     */
    function set_referrer($referrer_url)
    {
        $this->n_referrer = $referrer_url;
        curl_setopt($this->ch, CURLOPT_REFERER, $referrer_url);
    }

    /**
     * Set client's useragent
     *
     * @param
     *            string user agent
     * @access public
     */
    function set_user_agent($useragent)
    {
        $this->n_useragent = $useragent;
        curl_setopt($this->ch, CURLOPT_USERAGENT, $useragent);
    }

    function set_header($header)
    {
        $this->n_header = $header;
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, $header);
    }

    /**
     * Set to receive output headers in all output functions
     *
     * @param
     *            boolean true to include all response headers with output, false otherwise
     * @access public
     */
    function include_response_headers($value)
    {
        curl_setopt($this->ch, CURLOPT_HEADER, $value);
    }

    /**
     * Set proxy to use for each curl request
     *
     * @param
     *            string proxy
     * @access public
     */
    function set_proxy($proxy)
    {
        curl_setopt($this->ch, CURLOPT_PROXY, $proxy);
    }

    /**
     * Send post data to target URL
     * return data returned from url or false if error occured
     *
     * @param
     *            string url
     * @param
     *            mixed post data (assoc array ie. $foo['post_var_name'] = $value or as string like var=val1&var2=val2)
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 10)
     * @return string data
     * @access public
     */
    function send_post_data($url, $postdata, $ip = null, $timeout = 10)
    {
        // set various curl options first
        
        // set url to post to
        curl_setopt($this->ch, CURLOPT_URL, $url);
        
        // return into a variable rather than displaying it
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        
        // bind to specific ip address if it is sent trough arguments
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        // set curl function timeout to $timeout
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        // set method to post
        curl_setopt($this->ch, CURLOPT_POST, true);
        
        // generate post string
        $post_array = array ();
        if (is_array($postdata)) {
            foreach ($postdata as $key => $value) {
                $post_array[] = urlencode($key) . "=" . urlencode($value);
            }
            
            $post_string = implode("&", $post_array);
            
            if ($this->debug) {
                echo "Url: $url\nPost String: $post_string\n";
            }
        } else {
            $post_string = $postdata;
        }
        
        // set post string
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post_string);
        
        // and finally send curl request
        $result = curl_exec($this->ch);
        $returninfo = curl_getinfo($this->ch);
        
        $this->log($url, $result, array (
            "post" => $postdata,
            "returninfo" => $returninfo
        ));
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return $result;
        }
    }

    /**
     * fetch data from target URL
     * return data returned from url or false if error occured
     *
     * @param
     *            string url
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 5)
     * @return string data
     * @access public
     */
    function fetch_url($url, $ip = null, $timeout = 30)
    {
        // set url to post to
        curl_setopt($this->ch, CURLOPT_URL, $url);
        
        // set method to get
        curl_setopt($this->ch, CURLOPT_HTTPGET, true);
        
        // return into a variable rather than displaying it
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        
        // bind to specific ip address if it is sent trough arguments
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        // set curl function timeout to $timeout
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        // and finally send curl request
        $result = curl_exec($this->ch);
        $returninfo = curl_getinfo($this->ch);
        // log the result;
        $this->log($url, $result, array (
            "returninfo" => $returninfo
        ));
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return $result;
        }
    }

    public function getArrByRs($string)
    {
        $headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
        
        $rs = array ();
        
        $rs['header'] = substr($string, 0, $headerSize);
        $rs['body'] = substr($string, $headerSize);
        $rs['headerSize'] = $headerSize;
        
        return $rs;
    }

    public static function formatHeader($header, $keysArr = array())
    {
        $delimeter = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? "\r\n" : "\r";
        
        $headerArr = explode($delimeter, $header);
        
        $headerArr = array_filter($headerArr);
        
        $headerKeys = array (
            'Content-Type:',
            'Content-Type:',
            'HTTP/1.1',
            'Content-Length:',
            'Server:',
            'Date:',
            'Connection:'
        );
        
        if (is_array($keysArr)) {
            $headerKeys = array_merge($headerKeys, $keysArr);
        }
        
        $headerInfo = array ();
        $tempArr = array ();
        
        foreach ($headerKeys as $v) {
            
            foreach ($headerArr as $val) {
                
                if (strpos($val, $v) === false) {
                    continue;
                }
                
                $tempArr = explode($v, $val);
                $tempArr[1] = trim($tempArr[1]);
                
                $tempArr[1] != null && ($headerInfo[$v] = $tempArr[1]);
                
                break;
            }
        }
        
        return $headerInfo;
    }

    /**
     * Fetch data from target URL
     * and store it directly to file
     *
     * @param
     *            string url
     * @param
     *            resource value stream resource(ie. fopen)
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 5)
     * @return boolean true on success false othervise
     * @access public
     */
    function fetch_into_file($url, $fp, $ip = null, $timeout = 5)
    {
        // set url to post to
        curl_setopt($this->ch, CURLOPT_URL, $url);
        
        // set method to get
        curl_setopt($this->ch, CURLOPT_HTTPGET, true);
        
        // store data into file rather than displaying it
        curl_setopt($this->ch, CURLOPT_FILE, $fp);
        
        // bind to specific ip address if it is sent trough arguments
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        // set curl function timeout to $timeout
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        // and finally send curl request
        $result = curl_exec($this->ch);
        
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return true;
        }
    }

    /**
     * Send multipart post data to the target URL
     * return data returned from url or false if error occured
     * (contribution by vule nikolic, vule@dinke.net)
     *
     * @param
     *            string url
     * @param
     *            array assoc post data array ie. $foo['post_var_name'] = $value
     * @param
     *            array assoc $file_field_array, contains file_field name = value - path pairs
     * @param
     *            string ip address to bind (default null)
     * @param
     *            int timeout in sec for complete curl operation (default 30 sec)
     * @return string data
     * @access public
     */
    function send_multipart_post_data($url, $postdata, $file_field_array = array(), $ip = null, $timeout = 30)
    {

        curl_setopt($this->ch, CURLOPT_URL, $url);

        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        
        if ($ip) {
            if ($this->debug) {
                echo "Binding to ip $ip\n";
            }
            curl_setopt($this->ch, CURLOPT_INTERFACE, $ip);
        }
        
        curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
        
        curl_setopt($this->ch, CURLOPT_POST, true);

        $headers = array (
            "Expect: "
        );
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
        
        $result_post = array ();
        
        $post_array = array ();
        $post_string_array = array ();
        if (! is_array($postdata)) {
            return false;
        }
        
        foreach ($postdata as $key => $value) {
            $post_array[$key] = $value;
            $post_string_array[] = urlencode($key) . "=" . urlencode($value);
        }
        
        $post_string = implode("&", $post_string_array);
        
        if ($this->debug) {
            echo "Post String: $post_string\n";
        }
        
        if (! empty($file_field_array)) {
            foreach ($file_field_array as $var_name => $var_value) {
                if (strpos(PHP_OS, "WIN") !== false)
                    $var_value = str_replace("/", "\\", $var_value); // win hack
                $file_field_array[$var_name] = "@" . $var_value;
            }
        }
        
        $result_post = array_merge($post_array, $file_field_array);
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $result_post);
        
        $result = curl_exec($this->ch);
        
        if (curl_errno($this->ch)) {
            if ($this->debug) {
                echo "Error Occured in Curl\n";
                echo "Error number: " . curl_errno($this->ch) . "\n";
                echo "Error message: " . curl_error($this->ch) . "\n";
            }
            
            return false;
        } else {
            return $result;
        }
    }

    /**
     * 以文件的形式设置cookie
     *
     * @param
     *            string absolute path to cookie file (must be in writable dir)
     * @access public
     */
    function store_cookies($cookie_file)
    {
        // use cookies on each request (cookies stored in $cookie_file)
        curl_setopt($this->ch, CURLOPT_COOKIEJAR, $cookie_file);
        curl_setopt($this->ch, CURLOPT_COOKIEFILE, $cookie_file);
    }

    /**
     * 自定义cookie
     *
     * @param
     *            string cookie
     * @access public
     */
    function set_cookie($cookie)
    {
        curl_setopt($this->ch, CURLOPT_COOKIE, $cookie);
    }

    /**
     *
     * @access public
     * @return string url
     */
    function get_effective_url()
    {
        return curl_getinfo($this->ch, CURLINFO_EFFECTIVE_URL);
    }

    /**
     *
     * @access public
     * @return int
     */
    function get_http_response_code()
    {
        return curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
    }

    /**
     *
     * @return string error msg
     * @access public
     */
    function get_error_msg()
    {
        $err = "Error number: " . curl_errno($this->ch) . "\n";
        $err .= "Error message: " . curl_error($this->ch) . "\n";
        
        return $err;
    }

    /**
     * 关闭连接
     *
     * @access public
     */
    function close()
    {
        // close curl session and free up resources
        curl_close($this->ch);
    }

    /**
     *
     * @return 返回当前实例
     */
    public static function instance()
    {
        return new self();
    }

    public function get_client_ip()
    {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
            $ip = getenv("HTTP_CLIENT_IP");
        else 
            if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
                $ip = getenv("HTTP_X_FORWARDED_FOR");
            else 
                if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
                    $ip = getenv("REMOTE_ADDR");
                else 
                    if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
                        $ip = $_SERVER['REMOTE_ADDR'];
                    else
                        $ip = "";
        
        return ($ip);
    }

    function log($url, $msg, $retrun = array())
    {
       //记录你的log
    }
}