* * @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 * * @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; } }