<?php 



// Returns base URL used to access product
function get_base_url($usefullpath = true) {

    return get_base_uri($usefullpath);
}

function get_dashlets_base_url($usefullpath = false) {

    return get_base_url($usefullpath) . 'includes/dashlets/';
}

function get_components_base_url($usefullpath = false) {

    return get_base_url($usefullpath) . 'includes/components/';
}

function get_image_url($img) {

    return get_base_url() . '/static/images/' . $img;
}

function get_icon_url($img) {

    return get_image_url('icons/' . $img);
}


// Returns URL used to access Fusion from public networks
function get_external_url() {

    $url = get_option('external_url');
    if (empty($url))
        $url = get_option('internal_url');
    
    return $url;
}

// Returns the URL used to access Fusion from internal networks or itself
function get_internal_url() {

    $url = get_option('internal_url');
    return $url;
}


// Returns base URI used to access product
function get_base_uri($usefullpath = true) {

    global $cfg;

    $base_url = $cfg['base_url'] . '/';

    $force_relative_path = false;
    if (isset($cfg['force_relative_path']))
        $force_relative_path = (bool) $cfg['force_relative_path'];

    $url = $base_url;

    if ($usefullpath == true && $force_relative_path == false) {

        if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
            $proto = 'https';
        } else {
            $proto = 'http';
        }

        if (isset($_SERVER['SERVER_PORT']) && ($proto == 'http' && $_SERVER['SERVER_PORT'] != '80') || ($proto == 'https' && $_SERVER['SERVER_PORT'] != '443')) {
            $port = ':' . $_SERVER['SERVER_PORT'];
        } else {
            $port = '';
        }

        $hostname = 'localhost';
        if (isset($_SERVER['SERVER_NAME'])) {
            $hostname = $_SERVER['SERVER_NAME'];
        }

        $url = $proto . '://' . $hostname . $port . $base_url;

    }

    return $url;
}


// Returns URL to ajax helper
function get_ajax_helper_url() {

    $url = get_base_url(true) . 'ajaxhelper.php';
    return $url;
}


// Returns URL to ajax proxy
function get_ajax_proxy_url() {

    $url = get_base_url(true) . 'ajaxproxy.php';
    return $url;
}



// Returns URL to update check page
function get_update_check_url() {

    $url = 'https://www.nagios.com/checkforupdates/?product=' . get_product_name(true) . '&version=' . get_product_version() . '&build=' . get_product_build();
    return $url;
}


// Returns URL used to access current page
function get_current_url($baseonly = false, $fulluri = false) {

    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
        $proto = 'https';
    } else {
        $proto = 'http';
    }

    if (($proto == 'http' && $_SERVER['SERVER_PORT'] != '80') || ($proto == 'https' && $_SERVER['SERVER_PORT'] != '443')) {
        $port = ':' . $_SERVER['SERVER_PORT'];
    } else {
        $port = '';
    }

    if ($fulluri == true) {

        $uri = $_SERVER['REQUEST_URI'];
        $url = $proto . '://' . $_SERVER['SERVER_NAME'] . $port . $uri;

    } else {

        $page = $_SERVER['PHP_SELF'];

        if ($baseonly == true && ($last_slash = strrpos($page, '/'))) {
            $page = substr($page, 0, $last_slash + 1);
        }

        $url = $proto . '://' . $_SERVER['SERVER_NAME'] . $port . $page;
    }

    return $url;
}


// Returns current page (used for online help and feedback submissions)
function get_current_page($baseonly = false) {

    $page = $_SERVER['PHP_SELF'];

    if ($last_slash = strrpos($page, '/')) {
        $page_name = substr($page, $last_slash + 1);
    } else {
        $page_name = $page;
    }

    return $page_name;
}


function build_url_from_current($args) {

    global $request;
    $url = get_current_url();

    // Possible override original request variables
    $r = $request;
    foreach ($args as $var => $val) {
        $r[$var] = $val;
    }

    // Generate query string
    $url .= '?';
    foreach ($r as $var => $val) {
        $url .= '&' . $var . '=' . $val;
    }

    return $url;
}


function get_permalink_base() {

    global $request;

    if (!isset($request)) {
        grab_request_vars();
    }

    // Get current url
    $url = get_current_url(false, true);

    // Parse url and remove permalink option from base
    $a = parse_url($url);

    // Build base url
    $base = $a['scheme'] . '://' . $a['host'] . $a['path'] . '?';
    foreach ($request as $var => $val) {

        if ($var == 'fusionwindow') {
            continue;
        }

        $base .= '&' . urlencode($var) . '=';
        
        if (is_array($val)) {
            $base .= urlencode(serialize($val));
        } else {
            $base .= urlencode($val);
        }
    }

    return $base;
}

// append a specified str (append) to a url
// maintaing the proper use of ? and &
// append should be in the format of "param=val"
// but may also be in the format "&param=val"
// or "?param=val" - likewise with url
// should be "http://somewhere/" but can be
// "http://somewhere/?" or "http://somewhere?so=1&"
function append_url_parameter($url, $append) {

    if (empty($url))
        return '';

    $url = rtrim($url, '?&');
    $query = parse_url($url, PHP_URL_QUERY);

    $append = trim($append, '?&');

    if (!empty($query)) {

        // query paramters already started!
        return $url . '&' . $append;

    } else {

        // no query parameters added yet
        return $url . '?' . $append;
    }

    // shouldn't ever get here..
    return false;
}

/**
 * 10/18/2016 -bh
 *
 * Link: http://www.bin-co.com/php/scripts/load/
 * Version : 3.00.A
 * License : BSD
 *
 * @param       $url
 * @param array $options
 * @param bool  $use_proxy
 *
 * @return array|string
 */
// 10/18/2016 - changed some isset to !empty and 'and' to && -bh
function load_url($url, $options = array(), $use_proxy = false) {
    $default_options = array(
        'method'               => 'get',
        'post_data'            => false,
        'return_info'          => false,
        'return_body'          => true,
        'cache'                => false,
        'referer'              => '',
        'headers'              => array(),
        'session'              => false,
        'session_close'        => false,
        'timeout'              => 15, // -bh
        'verifypeer'           => false,
        'ssl_hostname_verify'  => false
    );
    // Sets the default options.
    foreach($default_options as $opt=>$value) {
        if(!isset($options[$opt])) $options[$opt] = $value;
    }

    $url_parts = parse_url($url);
    $ch = false;
    $info = array(//Currently only supported by curl.
        'http_code'    => 200
    );
    $response = '';
    
    // 10/18/2016 changed from array()+ to array_merge
    $send_header = array_merge(array(
        'Accept' => 'text/*',
        'User-Agent' => 'BinGet/1.00.A (http://www.bin-co.com/php/scripts/load/)'
    ), $options['headers']); // Add custom headers provided by the user.
    
    if($options['cache']) {
        $cache_folder = joinPath(sys_get_temp_dir(), 'php-load-function');
        if(!empty($options['cache_folder'])) $cache_folder = $options['cache_folder'];
        if(!file_exists($cache_folder)) {
            $old_umask = umask(0); // Or the folder will not get write permission for everybody.
            mkdir($cache_folder, 0777);
            umask($old_umask);
        }
        
        $cache_file_name = md5($url) . '.cache';
        $cache_file = joinPath($cache_folder, $cache_file_name); //Don't change the variable name - used at the end of the function.
        
        if(file_exists($cache_file)) { // Cached file exists - return that.
            $response = file_get_contents($cache_file);
            
            //Seperate header and content
            $separator_position = strpos($response,"\r\n\r\n");
            $header_text = substr($response,0,$separator_position);
            $body = substr($response,$separator_position+4);
            
            foreach(explode("\n",$header_text) as $line) {
                $parts = explode(": ",$line);
                if(count($parts) == 2) $headers[$parts[0]] = chop($parts[1]);
            }
            $headers['cached'] = true;
            
            if(!$options['return_info']) return $body;
            else return array('headers' => $headers, 'body' => $body, 'info' => array('cached'=>true));
        }
    }

    if(!empty($options['post_data'])) { //There is an option to specify some data to be posted.

        $options['method'] = 'post';
        
        if(is_array($options['post_data'])) { //The data is in array format.
            $post_data = array();
            foreach($options['post_data'] as $key=>$value) {
                $post_data[] = "$key=" . urlencode($value);
            }
            $url_parts['query'] = implode('&', $post_data);
        } else { //Its a string
            $url_parts['query'] = $options['post_data'];
        }
    } elseif(!empty($options['multipart_data'])) { //There is an option to specify some data to be posted.

        $options['method'] = 'post';
        $url_parts['query'] = $options['multipart_data'];
        /*
            This array consists of a name-indexed set of options.
            For example,
            'name' => array('option' => value)
            Available options are:
            filename: the name to report when uploading a file.
            type: the mime type of the file being uploaded (not used with curl).
            binary: a flag to tell the other end that the file is being uploaded in binary mode (not used with curl).
            contents: the file contents. More efficient for fsockopen if you already have the file contents.
            fromfile: the file to upload. More efficient for curl if you don't have the file contents.

            Note the name of the file specified with fromfile overrides filename when using curl.
         */
    }

    ///////////////////////////// Curl /////////////////////////////////////
    //If curl is available, use curl to get the data.
    if(function_exists("curl_init") 
                && (!(isset($options['use']) && $options['use'] == 'fsocketopen'))) { //Don't use curl if it is specifically stated to use fsocketopen in the options
        
        if(!empty($options['post_data'])) { //There is an option to specify some data to be posted.
            $page = $url;
            $options['method'] = 'post';
            
            if(is_array($options['post_data'])) { //The data is in array format.
                $post_data = array();
                foreach($options['post_data'] as $key=>$value) {
                    $post_data[] = "$key=" . urlencode($value);
                }
                $url_parts['query'] = implode('&', $post_data);
            
            } else { //Its a string
                $url_parts['query'] = $options['post_data'];
            }
        } else {
            if(isset($options['method']) && $options['method'] == 'post') {
                $page = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];
            } else {
                $page = $url;
            }
        }

        if($options['session'] && isset($GLOBALS['_binget_curl_session'])) $ch = $GLOBALS['_binget_curl_session']; //Session is stored in a global variable
        else $ch = curl_init($url_parts['host']);

        curl_setopt($ch, CURLOPT_TIMEOUT, $options['timeout']);
        
        curl_setopt($ch, CURLOPT_URL, $page) or die("Invalid cURL Handle Resouce");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //Just return the data - not print the whole thing.
        curl_setopt($ch, CURLOPT_HEADER, true); //We need the headers
        curl_setopt($ch, CURLOPT_NOBODY, !($options['return_body'])); //The content - if true, will not download the contents. There is a ! operation - don't remove it.
        $tmpdir = NULL; //This acts as a flag for us to clean up temp files
        if(isset($options['method']) && $options['method'] == 'post' && isset($url_parts['query'])) {
            curl_setopt($ch, CURLOPT_POST, true);
            if(is_array($url_parts['query'])) {
                //multipart form data (eg. file upload)
                $postdata = array();
                foreach ($url_parts['query'] as $name => $data) {
                    if (isset($data['contents']) && isset($data['filename'])) {
                        if (!isset($tmpdir)) { //If the temporary folder is not specifed - and we want to upload a file, create a temp folder.
                            //  :TODO:
                            $dir = sys_get_temp_dir();
                            $prefix = 'load';
                            
                            if (substr($dir, -1) != '/') $dir .= '/';
                            do {
                                $path = $dir . $prefix . mt_rand(0, 9999999);
                            } while (!mkdir($path, $mode));
                        
                            $tmpdir = $path;
                        }
                        $tmpfile = $tmpdir.'/'.$data['filename'];
                        file_put_contents($tmpfile, $data['contents']);
                        $data['fromfile'] = $tmpfile;
                    }
                    if (isset($data['fromfile'])) {
                        // Not sure how to pass mime type and/or the 'use binary' flag
                        $postdata[$name] = '@'.$data['fromfile'];
                    } elseif (isset($data['contents'])) {
                        $postdata[$name] = $data['contents'];
                    } else {
                        $postdata[$name] = '';
                    }
                }
                curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
            } else {
                curl_setopt($ch, CURLOPT_POSTFIELDS, $url_parts['query']);
            }
        }

        // Send delete requests and put requests
        if ($options['method'] == 'delete' || $options['method'] == 'put') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($options['method']));
        }

        //Set the headers our spiders sends
        curl_setopt($ch, CURLOPT_USERAGENT, $send_header['User-Agent']); //The Name of the UserAgent we will be using ;)
        $custom_headers = array("Accept: " . $send_header['Accept'] );
        if(isset($options['modified_since']))
            array_push($custom_headers,"If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T',strtotime($options['modified_since'])));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $custom_headers);
        if($options['referer']) curl_setopt($ch, CURLOPT_REFERER, $options['referer']);

        curl_setopt($ch, CURLOPT_COOKIEJAR, "/tmp/binget-cookie.txt"); //If ever needed...
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $options['verifypeer']);

        if ($options['ssl_hostname_verify']) {
            // 10/18/2016 copied from xi utilsx.inc.php
            $curl_version_info = curl_version();
            if ($curl_version_info['version_number'] >= 465921 || version_compare(phpversion(), '5.4', '>'))
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
            else
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        } else {
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        }

        if ($use_proxy) {
            //Added ability to turn off HTTPPROXYTUNNEL from proxy component -SW
            curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, get_option('proxy_tunnel', 1));
            curl_setopt($ch, CURLOPT_PROXY, get_option('proxy_address'));
            curl_setopt($ch, CURLOPT_PROXYPORT, get_option('proxy_port'));
            curl_setopt($ch, CURLOPT_PROXYTYPE, 'HTTP');
            //use auth credentials if specified

            // Have to grab the option, then check for emptyness - otherwise we get a fatal error
            $proxy_auth = get_option('proxy_auth');
            if (!empty($proxy_auth)) {
                curl_setopt($ch, CURLOPT_PROXYUSERPWD, get_option('proxy_auth'));
            }
        }

        $custom_headers = array();
        unset($send_header['User-Agent']); // Already done (above)
        foreach ($send_header as $name => $value) {
            if (is_array($value)) {
                foreach ($value as $item) {
                    $custom_headers[] = "$name: $item";
                }
            } else {
                $custom_headers[] = "$name: $value";
            }
        }
        if(isset($url_parts['user']) && isset($url_parts['pass'])) {

            // we need to fix some encoding issues maybe here (to allow for an @ symbol)
            // but there are other functions that need to encode that, so it almost always
            // will end up here as a %40 (pre-encoded) -bh
            $pass = str_replace('%40', '@', $url_parts['pass']);
            $user = str_replace('%40', '@', $url_parts['user']);

            $custom_headers[] = "Authorization: Basic ".base64_encode($user.':'.$pass);
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $custom_headers);

        $response = curl_exec($ch);

        if(isset($tmpdir)) {
            //rmdirr($tmpdir); //Cleanup any temporary files :TODO:
        }

        $info = curl_getinfo($ch); //Some information on the fetch
        
        if($options['session'] && !$options['session_close']) $GLOBALS['_binget_curl_session'] = $ch; //Dont close the curl session. We may need it later - save it to a global variable
        else curl_close($ch);  //If the session option is not set, close the session.

    //////////////////////////////////////////// FSockOpen //////////////////////////////
    } else { //If there is no curl, use fsocketopen - but keep in mind that most advanced features will be lost with this approch.

        if(!isset($url_parts['query']) || (isset($options['method']) && $options['method'] == 'post'))
            $page = $url_parts['path'];
        else
            $page = $url_parts['path'] . '?' . $url_parts['query'];
        
        if(!isset($url_parts['port'])) $url_parts['port'] = ($url_parts['scheme'] == 'https' ? 443 : 80);
        $host = ($url_parts['scheme'] == 'https' ? 'ssl://' : '').$url_parts['host'];
        $fp = fsockopen($host, $url_parts['port'], $errno, $errstr, 30);
        if ($fp) {
            $out = '';
            if(isset($options['method']) && $options['method'] == 'post' && isset($url_parts['query'])) {
                $out .= "POST $page HTTP/1.1\r\n";
            } else {
                $out .= "GET $page HTTP/1.0\r\n"; //HTTP/1.0 is much easier to handle than HTTP/1.1
            }
            $out .= "Host: $url_parts[host]\r\n";
        foreach ($send_header as $name => $value) {
        if (is_array($value)) {
            foreach ($value as $item) {
            $out .= "$name: $item\r\n";
            }
        } else {
            $out .= "$name: $value\r\n";
        }
        }
            $out .= "Connection: Close\r\n";
            
            //HTTP Basic Authorization support
            if(isset($url_parts['user']) && isset($url_parts['pass'])) {
                $out .= "Authorization: Basic ".base64_encode($url_parts['user'].':'.$url_parts['pass']) . "\r\n";
            }

            //If the request is post - pass the data in a special way.
            if(isset($options['method']) && $options['method'] == 'post') {
                if(is_array($url_parts['query'])) {
                    //multipart form data (eg. file upload)

                    // Make a random (hopefully unique) identifier for the boundary
                    srand((double)microtime()*1000000);
                    $boundary = "---------------------------".substr(md5(rand(0,32000)),0,10);

                    $postdata = array();
                    $postdata[] = '--'.$boundary;
                    foreach ($url_parts['query'] as $name => $data) {
                        $disposition = 'Content-Disposition: form-data; name="'.$name.'"';
                        if (isset($data['filename'])) {
                            $disposition .= '; filename="'.$data['filename'].'"';
                        }
                        $postdata[] = $disposition;
                        if (isset($data['type'])) {
                            $postdata[] = 'Content-Type: '.$data['type'];
                        }
                        if (isset($data['binary']) && $data['binary']) {
                            $postdata[] = 'Content-Transfer-Encoding: binary';
                        } else {
                            $postdata[] = '';
                        }
                        if (isset($data['fromfile'])) {
                            $data['contents'] = file_get_contents($data['fromfile']);
                        }
                        if (isset($data['contents'])) {
                            $postdata[] = $data['contents'];
                        } else {
                            $postdata[] = '';
                        }
                        $postdata[] = '--'.$boundary;
                    }
                    $postdata = implode("\r\n", $postdata)."\r\n";
                    $length = strlen($postdata);
                    $postdata = 'Content-Type: multipart/form-data; boundary='.$boundary."\r\n".
                                'Content-Length: '.$length."\r\n".
                                "\r\n".
                                $postdata;

                    $out .= $postdata;
                } else {
                    $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
                    $out .= 'Content-Length: ' . strlen($url_parts['query']) . "\r\n";
                    $out .= "\r\n" . $url_parts['query'];
                }
            }
            $out .= "\r\n";

            fwrite($fp, $out);
            while (!feof($fp)) {
                $response .= fgets($fp, 128);
            }
            fclose($fp);
        }
    }

    //Get the headers in an associative array
    $headers = array();

    if($info['http_code'] == 404) {
        $body = "";
        $headers['Status'] = 404;
    } else {
        //Seperate header and content
        $header_text = substr($response, 0, $info['header_size']);
        $body = substr($response, $info['header_size']);
        
        foreach(explode("\n",$header_text) as $line) {
            $parts = explode(": ",$line);
            if(count($parts) == 2) {
                if (isset($headers[$parts[0]])) {
                    if (is_array($headers[$parts[0]])) $headers[$parts[0]][] = chop($parts[1]);
                    else $headers[$parts[0]] = array($headers[$parts[0]], chop($parts[1]));
                } else {
                    $headers[$parts[0]] = chop($parts[1]);
                }
            }
        }

    }
    
    if(isset($cache_file)) { //Should we cache the URL?
        file_put_contents($cache_file, $response);
    }

    if($options['return_info']) return array('headers' => $headers, 'body' => $body, 'info' => $info, 'curl_handle'=>$ch);
    return $body;
} 
