|
31 | 31 | *
|
32 | 32 | * @package Browscap
|
33 | 33 | * @author Jonathan Stoppani <[email protected]>
|
| 34 | + * @author Vítor Brandão <[email protected]> |
34 | 35 | * @copyright Copyright (c) 2006-2012 Jonathan Stoppani
|
35 | 36 | * @version 1.0
|
36 | 37 | * @license http://www.opensource.org/licenses/MIT MIT License
|
@@ -179,6 +180,28 @@ class Browscap
|
179 | 180 | protected $_patterns = array();
|
180 | 181 | protected $_properties = array();
|
181 | 182 |
|
| 183 | + /** |
| 184 | + * An associative array of associative arrays in the format |
| 185 | + * `$arr['wrapper']['option'] = $value` passed to stream_context_create() |
| 186 | + * when building a stream resource. |
| 187 | + * |
| 188 | + * Proxy settings are stored in this variable. |
| 189 | + * |
| 190 | + * @see http://www.php.net/manual/en/function.stream-context-create.php |
| 191 | + * |
| 192 | + * @var array |
| 193 | + */ |
| 194 | + protected $_streamContextOptions = array(); |
| 195 | + |
| 196 | + /** |
| 197 | + * A valid context resource created with stream_context_create(). |
| 198 | + * |
| 199 | + * @see http://www.php.net/manual/en/function.stream-context-create.php |
| 200 | + * |
| 201 | + * @var resource |
| 202 | + */ |
| 203 | + protected $_streamContext = null; |
| 204 | + |
182 | 205 | /**
|
183 | 206 | * Constructor class, checks for the existence of (and loads) the cache and
|
184 | 207 | * if needed updated the definitions
|
@@ -308,6 +331,107 @@ public function getBrowser($user_agent = null, $return_array = false)
|
308 | 331 | return $return_array ? $array : (object) $array;
|
309 | 332 | }
|
310 | 333 |
|
| 334 | + /** |
| 335 | + * Load (auto-set) proxy settings from environment variables. |
| 336 | + */ |
| 337 | + public function autodetectProxySettings() |
| 338 | + { |
| 339 | + $wrappers = array('http', 'https', 'ftp'); |
| 340 | + |
| 341 | + foreach ($wrappers as $wrapper) { |
| 342 | + $url = getenv($wrapper.'_proxy'); |
| 343 | + if (!empty($url)) { |
| 344 | + $params = array_merge(array( |
| 345 | + 'port' => null, |
| 346 | + 'user' => null, |
| 347 | + 'pass' => null, |
| 348 | + ), parse_url($url)); |
| 349 | + $this->addProxySettings($params['host'], $params['port'], $wrapper, $params['user'], $params['pass']); |
| 350 | + } |
| 351 | + } |
| 352 | + } |
| 353 | + |
| 354 | + /** |
| 355 | + * Add proxy settings to the stream context array. |
| 356 | + * |
| 357 | + * @param string $server Proxy server/host |
| 358 | + * @param int $port Port |
| 359 | + * @param string $wrapper Wrapper: "http", "https", "ftp", others... |
| 360 | + * @param string $username Username (when requiring authentication) |
| 361 | + * @param string $password Password (when requiring authentication) |
| 362 | + * |
| 363 | + * @return Browscap |
| 364 | + */ |
| 365 | + public function addProxySettings($server, $port = 3128, $wrapper = 'http', $username = null, $password = null) |
| 366 | + { |
| 367 | + $settings = array($wrapper => array( |
| 368 | + 'proxy' => sprintf('tcp://%s:%d', $server, $port), |
| 369 | + 'request_fulluri' => true, |
| 370 | + )); |
| 371 | + |
| 372 | + // Proxy authentication (optional) |
| 373 | + if (isset($username) && isset($password)) { |
| 374 | + $settings[$wrapper]['header'] = 'Proxy-Authorization: Basic '.base64_encode($username.':'.$password); |
| 375 | + } |
| 376 | + |
| 377 | + // Add these new settings to the stream context options array |
| 378 | + $this->_streamContextOptions = array_merge( |
| 379 | + $this->_streamContextOptions, |
| 380 | + $settings |
| 381 | + ); |
| 382 | + |
| 383 | + /* Return $this so we can chain addProxySettings() calls like this: |
| 384 | + * $browscap-> |
| 385 | + * addProxySettings('http')-> |
| 386 | + * addProxySettings('https')-> |
| 387 | + * addProxySettings('ftp'); |
| 388 | + */ |
| 389 | + return $this; |
| 390 | + } |
| 391 | + |
| 392 | + /** |
| 393 | + * Clear proxy settings from the stream context options array. |
| 394 | + * |
| 395 | + * @param string $wrapper Remove settings from this wrapper only |
| 396 | + * |
| 397 | + * @return array Wrappers cleared |
| 398 | + */ |
| 399 | + public function clearProxySettings($wrapper = null) |
| 400 | + { |
| 401 | + $wrappers = isset($wrapper) ? array($wrappers) : array_keys($this->_streamContextOptions); |
| 402 | + |
| 403 | + $affectedProtocols = array(); |
| 404 | + $options = array('proxy', 'request_fulluri', 'header'); |
| 405 | + foreach ($wrappers as $wrapper) { |
| 406 | + |
| 407 | + // remove wrapper options related to proxy settings |
| 408 | + if (isset($this->_streamContextOptions[$wrapper]['proxy'])) { |
| 409 | + foreach ($options as $option){ |
| 410 | + unset($this->_streamContextOptions[$wrapper][$option]); |
| 411 | + } |
| 412 | + |
| 413 | + // remove wrapper entry if there are no other options left |
| 414 | + if (empty($this->_streamContextOptions[$wrapper])) { |
| 415 | + unset($this->_streamContextOptions[$wrapper]); |
| 416 | + } |
| 417 | + |
| 418 | + $clearedWrappers[] = $wrapper; |
| 419 | + } |
| 420 | + } |
| 421 | + |
| 422 | + return $clearedWrappers; |
| 423 | + } |
| 424 | + |
| 425 | + /** |
| 426 | + * Returns the array of stream context options. |
| 427 | + * |
| 428 | + * @return array |
| 429 | + */ |
| 430 | + public function getStreamContextOptions() |
| 431 | + { |
| 432 | + return $this->_streamContextOptions; |
| 433 | + } |
| 434 | + |
311 | 435 | /**
|
312 | 436 | * Parses the ini file and updates the cache files
|
313 | 437 | *
|
@@ -431,6 +555,20 @@ protected function _buildCache()
|
431 | 555 | );
|
432 | 556 | }
|
433 | 557 |
|
| 558 | + /** |
| 559 | + * Lazy getter for the stream context resource. |
| 560 | + * |
| 561 | + * @return resource |
| 562 | + */ |
| 563 | + protected function _getStreamContext($recreate = false) |
| 564 | + { |
| 565 | + if (!isset($this->_streamContext) || true === $recreate) { |
| 566 | + $this->_streamContext = stream_context_create($this->_streamContextOptions); |
| 567 | + } |
| 568 | + |
| 569 | + return $this->_streamContext; |
| 570 | + } |
| 571 | + |
434 | 572 | /**
|
435 | 573 | * Updates the local copy of the ini file (by version checking) and adapts
|
436 | 574 | * his syntax to the PHP ini parser
|
@@ -605,7 +743,9 @@ protected function _getRemoteData($url)
|
605 | 743 | throw new Exception('Cannot open the local file');
|
606 | 744 | }
|
607 | 745 | case self::UPDATE_FOPEN:
|
608 |
| - $file = file_get_contents($url); |
| 746 | + // include proxy settings in the file_get_contents() call |
| 747 | + $context = $this->_getStreamContext(); |
| 748 | + $file = file_get_contents($url, false, $context); |
609 | 749 |
|
610 | 750 | if ($file !== false) {
|
611 | 751 | return $file;
|
|
0 commit comments