<?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);
}
?>