<?php  if (!defined('BASEPATH')) { exit('No direct script access allowed'); }

/**
 * CodeIgniter helper
 *
 * @category CodeIgniter
 * @license /_licenses/untermStrich/agb_normal.pdf
 * @author Christian Koller
 * @copyright 2009 untermStrich
 * @package helpers
 * @version $Id$
 */

if (!function_exists('secure_url_get_contents')) {
    /**
     * Download a file to a string
     *
     * @param string $url Url to get
     * @param mixed $to_file Download to file (provide name) or false to return a string
     * @param mixed $file_length Setting file length results in the output of process_update_progressbar
     * @param string $proxy_host Optional set proxy host if null get from config, if false no proxy
     * @param integer $proxy_port Optional set proxy port if null get from config, if false no proxy
     * @param string $user_agent Optional User-Agent header string
     * @return  object
     */
    function secure_url_get_contents($url, $to_file = false, $file_length = false, $proxy_host = null, $proxy_port = null, $user_agent = '')
    {
        $CI = CI_Controller::get_instance();
        $use_proxy = false;
        if ($proxy_host === null && $proxy_port === null) {
            $proxy_host = $CI->config->item('us_proxy_host');//'187.50.119.3'
            $proxy_port = $CI->config->item('us_proxy_port');//8080            
        }
        if ($proxy_host !== false && $proxy_port !== false) {
            $use_proxy = true;
            /*#*/#$CI->firephp->log('USING PROXY');
        }

        $data = false;

        //----------------------------------------------------------------------
        $stream_timeout = 8;
        if (substr($url, -5) === '/ping') {
            $stream_timeout = 2;
        }

        //----------------------------------------------------------------------
        //If we have CURL ------------------------------------------------------
        if (function_exists('curl_init')) {
            /*#*/#$CI->firephp->log('CURL');
            //Init curl
            /*#*/
            log_message('debug', 'Start CURL');
            $curl_conn = @curl_init();
            @curl_setopt($curl_conn, CURLOPT_HEADER, false);
            @curl_setopt($curl_conn, CURLOPT_URL, $url);

            @curl_setopt($curl_conn, CURLOPT_CAINFO, APPPATHLIVE . 'config/ca.pem');
            if ($use_proxy === true) {
                @curl_setopt($curl_conn, CURLOPT_PROXY, "$proxy_host:$proxy_port");
                @curl_setopt($curl_conn, CURLOPT_HTTPPROXYTUNNEL, true);
            }

            //Set download parameters
            if ($to_file !== false) {
                $file_to = @fopen($to_file, "w");
                if (!$file_to) {
                    log_message('error', __METHOD__ . ' failed: Cannot fopen ' . $to_file);
                    return false;
                }
                @curl_setopt($curl_conn, CURLOPT_FILE, $file_to);
            } else {
                @curl_setopt($curl_conn, CURLOPT_TIMEOUT, $stream_timeout);
                @curl_setopt($curl_conn, CURLOPT_RETURNTRANSFER, true);
            }

            //Progress output in cli
            if ($file_length && defined('US_CLI_MODE')) {
                @curl_setopt($curl_conn, @CURLOPT_NOPROGRESS, false);
            }

            //Set User-Agent header
            if (!empty($user_agent)) {
                @curl_setopt($curl_conn, @CURLOPT_USERAGENT, $user_agent);
            }

            //Download
            $data = @curl_exec($curl_conn);

            $errno = false;
            if ($data === false) {
                $errno = @curl_errno($curl_conn);
                log_message('error', __METHOD__ . ' failed: ' . @curl_error($curl_conn) . ' - E' . $errno);

                /*#*/echo (@curl_error($curl_conn).' - E'.$errno); die();
            }

            //Close curl
            @curl_close($curl_conn);

            //Close target file
            if ($to_file !== false) {
                @fclose($file_to);
            }

            if ($data !== false || ($errno !== 51 && $errno !== 60)) {
                return $data;
            }
        }

        if ($use_proxy === false && ini_get('allow_url_fopen') == '1') {
            /*#*/#$CI->firephp->log('FOPEN');
            //------------------------------------------------------------------
            //Try using fopen -  if allow_url_fopen ----------------------------
            $mode = 'fopen';

            //Open source file
            $opts = array();
            //Set User-Agent header
            $opts['http'] = array(
                'method' => 'GET',
                'timeout' => $stream_timeout . '.0'
            );
            if (!empty($user_agent)) {
                $opts['http']['header'] = "User-Agent: $user_agent\r\n";
            }
            $file = @fopen($url, "r", false, stream_context_create($opts));

            if (!$file) {
                log_message('error', __METHOD__ . ' failed: Cannot fopen ' . $url);
                return false;
            }

            //Open target file
            if ($to_file !== false) {
                $file_to = fopen($to_file, "w");
                if (!$file_to) {
                    log_message('error', __METHOD__ . ' failed: Cannot fopen ' . $to_file);
                    return false;
                }
            }
        } else {
            /*#*/#$CI->firephp->log('FSOCKOPEN');
            //----------------------------------------------------------------------
            //Try using fsockopen --------------------------------------------------
            $mode = 'fsockopen';

            //Parse url
            $parsedUrl = parse_url($url);

            //Get host
            $host = $parsedUrl['host'];

            //Get path
            if (isset($parsedUrl['path'])) {
                $path = $parsedUrl['path'];
            } else {
                $path = '/';
            }

            //Get port
            if (isset($parsedUrl['port'])) {
                $port = $parsedUrl['port'];
            } else {
                $port = '443';
            }

            //SSL mode
            $fsockhost = 'ssl://' . $host;

            //Connect to source file
            if ($use_proxy === true) {
                $file = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, $stream_timeout); // connect to proxy
            } else {
                $file = @fsockopen($fsockhost, $port, $errno, $errstr, $stream_timeout);
            }

            /*#*/
            log_message('error', 'fsockopen ' . $host . ':' . $port);
            if (!$file) {
                log_message('error', __METHOD__ . ' failed: Cannot fsockopen ' . $host . ':' . $port);
                return false;
            }

            //Send header
            if ($use_proxy === true) {
                fputs($file, "GET $url HTTP/1.1\r\nHost:$host:$port\r\n");
            } else {
                $path = (isset($parsedUrl['query']) && !empty($parsedUrl['query'])) ? $path . '?' . $parsedUrl['query'] : $path;
                @fputs($file, "GET $path HTTP/1.1\r\n");
                @fputs($file, "Host: $host\r\n");
            }

            //Set User-Agent header
            if (!empty($user_agent)) {
                @fputs($file, "User-Agent: $user_agent\r\n");
            }

            //Close connection
            @fputs($file, "Connection: close\r\n\r\n");

            //Open target file
            if ($to_file !== false) {
                $file_to = fopen($to_file, "w");
                if (!$file_to) {
                    log_message('error', __METHOD__ . ' failed: Cannot fopen ' . $to_file);
                    return false;
                }
            }
        }

        //Read lines - download
        $data = '';
        $already_length = 0;
        $last_length = 0;
        while ($line = @fgets($file, 1024)) {
            $already_length += strlen($line);

            //On error
            if (false === $line) {
                log_message('error', __METHOD__ . ' failed: Cannot read (@fgets) ' . $url);
                return false;
            }

            //Save to file if to_file and fopen mode
            if ($mode == 'fopen' && $to_file !== false) {
                if (false === @fputs($file_to, $line)) {
                    log_message('error', __METHOD__ . ' failed: Cannot write (@fputs) ' . $to_file);
                    return false;
                }
            } else {
                $data .= $line;
            }

            //Show progress bar
            if ($file_length) {
                //Update every 500kb
                if ($already_length - 500000 > $last_length) {
                    $last_length = $already_length;
//                    process_update_progressbar($already_length, $file_length);
                }
            }
        }

        //Close source file
        @fclose($file);

        //Remove header if fsockopen mode
        if ($mode == 'fsockopen') {
            //Chunked?
            $chunked = (strpos(strtolower($data), "transfer-encoding: chunked") !== false);

            //Remove header
            $pos = strpos($data, "\r\n\r\n");
            $data = substr($data, $pos + 4);

            if ($chunked) {
                $data = http_chunked_decode($data);
            }

            #log_message('error', print_r($data, true));
        }

        //Save to file if to_file and fsockopen mode
        if ($mode == 'fsockopen' && $to_file !== false) {
            if (false === @fputs($file_to, $data)) {
                log_message('error', __METHOD__ . ' failed: Cannot write (@fputs) ' . $to_file);
                return false;
            }
        }

        //Close target file
        if ($to_file !== false) {
            /*#*/
            log_message('error', __METHOD__ . ' Saved: ' . $to_file);
            @fclose($file_to);
            $data = true;
        }

        return $data;
    }
}

if (!function_exists('http_chunked_decode')) {
    /**
     * Decode chunked encoded data if PHP module HTTP is missing
     *
     * @param string $encoded Encoded data
     * @return  string
     */
    function http_chunked_decode($encoded)
    {
        $len = strlen($encoded);
        $pos = 0;
        $reply = "";
        while ($pos < $len) {
            //Get length
            $rawnum = substr($encoded, $pos, strpos(substr($encoded, $pos), "\r\n") + 2);
            $pos += strlen($rawnum);
            $length_chunk = hexdec(trim($rawnum));

            //Get chunk
            $chunk = substr($encoded, $pos, $length_chunk);
            $reply .= $chunk;
            $pos += strlen($chunk);
        }
        return $reply;
    }
}
