View file webcopier/url.php

File size: 8.14Kb
<?php

/**************************************************************************************
						Класс для обработки урл адресов								   
**************************************************************************************/

// Этот класс написал не я, копирайта автора нет и небыло.

class Url
{
    var $scheme;
    var $user;
    var $pass;
    var $host;
    var $port;
    var $path;
    var $query;
    var $fragment;
    var $cache;
	function Url($url=null)
    {
        if (isset($url)) {
            $this->set($url);
        }
    }

    function set($url) {
        $this->cache = null;
        $url = $this->_encode(trim($url));
        $parts = $this->_parse_url($url);
        $this->_set_parts($parts);
    }

    function set_relative($url) {
        $this->cache = null;
        $url = $this->_encode(trim($url));
        $parts = $this->_parse_url($url);
        $this->fragment = (isset($parts['fragment']) ? $parts['fragment'] : null);
        if (($parts['path'] == '') && !isset($parts['scheme']) && !isset($parts['host']) && !isset($parts['query'])) {
            return;
    }

        if (isset($parts['scheme'])) {
            $this->_set_parts($parts);
            return;
        }
        $this->query = (isset($parts['query']) ? $parts['query'] : null);
        if (isset($parts['host'])) {
            $this->host = $parts['host'];
            $this->path = $parts['path'];
            return;
        }
        if (substr($parts['path'], 0, 1) == '/') {
            $this->path = $parts['path'];
            return;
        }
        // copy base path excluding any characters after the last (right-most) slash character
        $buffer = substr($this->path, 0, (int)strrpos($this->path, '/')+1);
        // append relative path
        $buffer .= $parts['path'];
        // remove "./" where "." is a complete path segment.
        $buffer = str_replace('/./', '/', $buffer);
        if (substr($buffer, 0, 2) == './') {
            $buffer = substr($buffer, 2);
        }
        // if buffer ends with "." as a complete path segment, remove it
        if (substr($buffer, -2) == '/.') {
            $buffer = substr($buffer, 0, -1);
        }
        // remove "<segment>/../" where <segment> is a complete path segment not equal to ".."
        $search_finished = false;
        $segment = explode('/', $buffer);
        while (!$search_finished) {
            for ($x=0; $x+1 < count($segment);) {
                if (($segment[$x] != '') && ($segment[$x] != '..') && ($segment[$x+1] == '..')) {
                    if ($x+2 == count($segment)) $segment[] = '';
                    unset($segment[$x], $segment[$x+1]);
                    $segment = array_values($segment);
                    continue 2;
                } else {
                    $x++;
                }
            }
            $search_finished = true;
        }
        $buffer = (count($segment) == 1) ? '/' : implode('/', $segment);
        $this->path = $buffer;
    }

    function get() {
        if (isset($this->cache)) {
            return $this->cache;
        }
        $url = '';
        if (isset($this->scheme)) {
            $url .= $this->scheme.':';
        }
        if (isset($this->host)) {
            $url .= '//'.$this->host;
            if (isset($this->port)) {
                $url .= ':'.$this->port;
            }
        }
        $url .= $this->path;
        if (isset($this->query)) {
            $url .= '?'.$this->query;
        }
        if (isset($this->fragment)) {
            $url .= '#'.$this->fragment;
        }
        $this->cache = $url;
        return $url;
    }

    function is_absolute()
    {
        return (isset($this->scheme));
    }

    function is_relative()
    {
        return (!$this->is_absolute());
    }

    function get_scheme()
    {
        return (isset($this->scheme)) ? $this->scheme : false;
    }

    function get_user()
    {
        return (isset($this->user)) ? $this->user : false;
    }

    function get_pass()
    {
        return (isset($this->pass)) ? $this->pass : false;
    }

    function get_host()
    {
        return (isset($this->host)) ? $this->host : false;
    }

    function get_port()
    {
        return (isset($this->port)) ? $this->port : false;
    }

    function get_path()
    {
        return $this->path;
    }

    function get_query()
    {
        return (isset($this->query)) ? $this->query : false;
    }

    function get_fragment()
    {
        return (isset($this->fragment)) ? $this->fragment : false;
    }

    function _set_parts($parts)
    {
        $this->scheme   = (isset($parts['scheme'])   ? strtolower($parts['scheme']) : null);
        $this->user     = (isset($parts['user'])     ? $parts['user']               : null);
        $this->pass     = (isset($parts['pass'])     ? $parts['pass']               : null);
        $this->host     = (isset($parts['host'])     ? $parts['host']               : null);
        $this->port     = (isset($parts['port'])     ? (int)$parts['port']          : null);
        $this->path     = (isset($parts['path'])     ? $parts['path']               : '');
        $this->query    = (isset($parts['query'])    ? $parts['query']              : null);
        $this->fragment = (isset($parts['fragment']) ? $parts['fragment']           : null);
    }

    function _parse_url($url)
    {
        // I'm using this pattern instead of parse_url() as there's a few strings where parse_url() 
        // generates a warning.
        if (preg_match('!^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?!', $url, $match)) {
            $parts = array();
            if ($match[1] != '') $parts['scheme'] = $match[2];
            if ($match[3] != '') $parts['auth'] = $match[4];
            // parse auth
            if (isset($parts['auth'])) {
                // store user info
                if (($at_pos = strpos($parts['auth'], '@')) !== false) {
                    $userinfo = explode(':', substr($parts['auth'], 0, $at_pos), 2);
                    $parts['user'] = $userinfo[0];
                    if (isset($userinfo[1])) $parts['pass'] = $userinfo[1];
                    $parts['auth'] = substr($parts['auth'], $at_pos+1);
                }
                // get port number
                if ($port_pos = strrpos($parts['auth'], ':')) {
                    $parts['host'] = substr($parts['auth'], 0, $port_pos);
                    $parts['port'] = (int)substr($parts['auth'], $port_pos+1);
                    if ($parts['port'] < 1) $parts['port'] = null;
                } else {
                    $parts['host'] = $parts['auth'];
                }
            }
            unset($parts['auth']);
            $parts['path'] = $match[5];
            if (isset($match[6]) && ($match[6] != '')) $parts['query'] = $match[7];
            if (isset($match[8]) && ($match[8] != '')) $parts['fragment'] = $match[9];
            return $parts;
        }
        // shouldn't reach here
        return array('path'=>'');
    }

    /*
    * Encode string - will try to escape certain chars which are safe to escape, cannot do them all
    * as it's impossible to detect which characters the user intends to be escaped.
    */
    function _encode($string)
    {
        static $replace = array();
        if (!count($replace)) {
            $find = array(32, 34, 60, 62, 123, 124, 125, 91, 92, 93, 94, 96, 127);
            $find = array_merge(range(0, 31), $find);
            $find = array_map('chr', $find);
            foreach ($find as $char) {
                $replace[$char] = '%'.bin2hex($char);
            }
        }
        // escape control characters and a few other characters
        $encoded = strtr($string, $replace);
        // remove any character outside the hex range: 21 - 7E (see www.asciitable.com)
        return preg_replace('/[^\x21-\x7e]/', '', $encoded);
    }
}

// (c) jeka!
function parseurl($cur_url, $new_url = '', $ret = 1) {
	$url = &new Url($cur_url);
	$url -> set_relative($new_url);
	if ($ret == 0) return $url -> get(); // Новый урл
	$protocol = $url -> get_scheme();
	$host = $url -> get_host(); // Host
	$query = $url -> get_query();
	$path = $url -> get_path().($query ? '?'.$query : ''); // Full Path
	if (substr($path, 0, 1) != '/') $path = "/".$path;
	return array($host,$path,$protocol);
}

?>