343 lines
7.1 KiB
PHP
343 lines
7.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Contao Open Source CMS
|
|
* Copyright (C) 2005-2012 Leo Feyer
|
|
*
|
|
* Formerly known as TYPOlight Open Source CMS.
|
|
*
|
|
* Proxy Module
|
|
*
|
|
* PHP version 5
|
|
* @copyright Jörg Kleuver 2008, TYPOlight Version
|
|
* @author Jörg Kleuver <joerg@kleuver.de>
|
|
*
|
|
* @copyright Glen Langer 2012
|
|
* @author Glen Langer (BugBuster); for Contao 3
|
|
* @package Proxy
|
|
* @license LGPL
|
|
*/
|
|
|
|
/**
|
|
* Class Proxy
|
|
*
|
|
* Provide methods to handle HTTP Proxy informations.
|
|
* @copyright Jörg Kleuver 2008, TYPOlight Version
|
|
* @author Jörg Kleuver <joerg@kleuver.de>
|
|
*
|
|
* @copyright Glen Langer 2012
|
|
* @author Glen Langer (BugBuster); for Contao 3
|
|
* @version 3.0.0
|
|
* @package Proxy
|
|
* @license LGPL
|
|
*/
|
|
class Proxy
|
|
{
|
|
|
|
/**
|
|
* Proxy settings
|
|
* @var array
|
|
*/
|
|
protected $arrProxy = array(
|
|
'proxy_host' => '',
|
|
'proxy_port' => 8080,
|
|
'proxy_user' => '',
|
|
'proxy_pass' => ''
|
|
);
|
|
|
|
/**
|
|
* Local settings
|
|
* @var array
|
|
*/
|
|
protected $arrLocal = array();
|
|
|
|
/**
|
|
* Set default values
|
|
* @param string $strUrl
|
|
* @param string $strLocal
|
|
* @throws Exception
|
|
*/
|
|
public function __construct($strUrl = '', $strLocal = '')
|
|
{
|
|
$this->setProxy($strUrl);
|
|
$this->setLocal($strLocal);
|
|
}
|
|
|
|
/**
|
|
* Set an object property
|
|
* @param string
|
|
* @param mixed
|
|
* @throws Exception
|
|
*/
|
|
public function __set($strKey, $varValue)
|
|
{
|
|
switch ($strKey)
|
|
{
|
|
case 'proxy':
|
|
$this->setProxy($varValue);
|
|
break;
|
|
|
|
case 'local':
|
|
$this->setLocal($varValue);
|
|
break;
|
|
|
|
case 'host':
|
|
case 'port':
|
|
case 'user':
|
|
case 'pass':
|
|
$this->arrProxy['proxy_'.$strKey] = $varValue;
|
|
break;
|
|
|
|
default:
|
|
throw new Exception(sprintf('Invalid argument "%s"', $strKey));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return an object property
|
|
* @param string
|
|
* @return mixed
|
|
* @throws Exception
|
|
*/
|
|
public function __get($strKey)
|
|
{
|
|
switch ($strKey)
|
|
{
|
|
case 'host':
|
|
case 'port':
|
|
case 'user':
|
|
case 'pass':
|
|
return $this->arrProxy['proxy_'.$strKey];
|
|
break;
|
|
|
|
default:
|
|
throw new Exception(sprintf('Unknown or protected property "%s"', $strKey));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if strHost is Local
|
|
* @param string
|
|
* @return bool
|
|
*/
|
|
public function isLocal($strHost)
|
|
{
|
|
if ($this->arrLocal)
|
|
{
|
|
// check if $strHost matches $local
|
|
foreach ($this->arrLocal as $local)
|
|
{
|
|
// check if strings match
|
|
if ($strHost == $local) return true;
|
|
|
|
switch ($this->hostType($strHost))
|
|
{
|
|
case 'host-name':
|
|
switch ($this->hostType($local))
|
|
{
|
|
case 'host-name':
|
|
// should never reach this, already checked
|
|
if ($strHost == $local) return true;
|
|
break;
|
|
|
|
case 'domain-name':
|
|
if ($this->inDomain($strHost, $local)) return true;
|
|
break;
|
|
|
|
// // Question: Do we rally want to check a host name against ip-adress or ip-range ?
|
|
// case 'ip-address':
|
|
// // do reverse lookup of $strHost and then check if ip-addresses match $local
|
|
// // Don't do a reverse lookup of an ip-address !
|
|
// foreach (gethostbynamel($strHost) as $ip)
|
|
// {
|
|
// if ($ip == $local) return true;
|
|
// }
|
|
// break;
|
|
//
|
|
// case 'ip-range':
|
|
// // do reverse lookup of $strHost and then check if addresses is in ip-range of $local
|
|
// foreach (gethostbynamel($strHost) as $ip)
|
|
// {
|
|
// if ($this->inRange($ip, $local)) return true;
|
|
// }
|
|
// break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'ip-address':
|
|
switch ($this->hostType($local))
|
|
{
|
|
// // Question: Do we rally want to check an ip-address against a host name ?
|
|
// case 'host-name':
|
|
// // do reverse lookup of $local and then check if addresses match $strHost
|
|
// // Don't do a reverse lookup of an ip-address !
|
|
// foreach (gethostbynamel($local) as $ip)
|
|
// {
|
|
// if ($ip == $strHost) return true;
|
|
// }
|
|
// break;
|
|
|
|
case 'ip-address':
|
|
// should never reach this, already checked
|
|
if ($strHost == $local) return true;
|
|
break;
|
|
|
|
case 'ip-range':
|
|
if ($this->inRange($strHost, $local)) return true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Set Proxy and return true if set
|
|
* @param string
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
private function setProxy($strUrl = '')
|
|
{
|
|
// set arrProxy
|
|
if ($strUrl)
|
|
{
|
|
$proxy_uri = parse_url($strUrl);
|
|
if (! $proxy_uri)
|
|
{
|
|
throw new Exception(sprintf($GLOBALS['TL_LANG']['tl_proxy']['error_url'], $strUrl));
|
|
}
|
|
|
|
if ($proxy_uri['scheme'] != 'http')
|
|
{
|
|
throw new Exception(sprintf($GLOBALS['TL_LANG']['tl_proxy']['error_scheme'], $proxy_uri['scheme']));
|
|
return false;
|
|
}
|
|
|
|
$this->arrProxy = array(
|
|
'proxy_host' => $proxy_uri['host'],
|
|
'proxy_port' => $proxy_uri['port'],
|
|
'proxy_user' => $proxy_uri['user'],
|
|
'proxy_pass' => $proxy_uri['pass']
|
|
);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Set Local and return true if set
|
|
* @param string
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
private function setLocal($strLocal = '')
|
|
{
|
|
// set arrLocal
|
|
if ($strLocal)
|
|
{
|
|
$arrLocal = explode(",", $strLocal);
|
|
foreach ($arrLocal as $key => $value)
|
|
{
|
|
$arrLocal[$key] = strtolower(trim($value));
|
|
if (! $this->hostType($arrLocal[$key]))
|
|
{
|
|
throw new Exception(sprintf($GLOBALS['TL_LANG']['tl_proxy']['error_local'], $arrLocal[$key]));
|
|
}
|
|
}
|
|
|
|
$this->arrLocal = $arrLocal;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return type of Host
|
|
* @param string
|
|
* @return mixed
|
|
*/
|
|
private function hostType($strHost)
|
|
{
|
|
// sanity check of $strHost
|
|
if(preg_match("/[^a-z0-9\.\-]/i", $strHost)) return false;
|
|
|
|
$strSlices = explode('.', $strHost);
|
|
|
|
// check for domain or ip range
|
|
if ($strHost[0] == '.')
|
|
{
|
|
if(count($strSlices) < 2) return false;
|
|
|
|
$TLD = array_pop($strSlices); // TLD is last
|
|
$ccTLD = array_pop($strSlices); // ccTLD is 2nd last
|
|
if((strlen($TLD) < 2) || (strlen($ccTLD) < 2)) return false;
|
|
|
|
return 'domain-name';
|
|
}
|
|
else if (substr($strHost, -1) == '.')
|
|
{
|
|
if(count($strSlices) < 1) return false;
|
|
if(preg_match("/[^0-9\.]/i", $strHost)) return false;
|
|
return 'ip-range';
|
|
}
|
|
|
|
// check for missing '.' at beginning of domains
|
|
if(count($strSlices) == 2) return false;
|
|
|
|
// check for missing '.' at end of ip range
|
|
if(count($strSlices) < 4 && ! preg_match("/[^0-9\.]/i", $strHost)) return false;
|
|
|
|
// if it's not an ip address, it's an host name
|
|
if ((ip2long($strHost)) === false)
|
|
{
|
|
return 'host-name';
|
|
}
|
|
else
|
|
{
|
|
return 'ip-address';
|
|
}
|
|
|
|
// we should never reach this
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param string
|
|
* Check if IP Address is in IP Range
|
|
* @param string
|
|
* @return bool
|
|
*/
|
|
private function inRange($strIp, $strRange)
|
|
{
|
|
if (preg_match("/^{$strRange}/", $strIp)) return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if Host is in Domain
|
|
* @param string
|
|
* @param string
|
|
* @return bool
|
|
*/
|
|
private function inDomain($strHost, $strDomain)
|
|
{
|
|
if (preg_match("/{$strDomain}$/", $strHost)) return true;
|
|
return false;
|
|
}
|
|
}
|