From 63812b7b66d7c2b0ba9891f0d8ccf125abc17ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 13 Feb 2018 19:23:02 +0100 Subject: [PATCH] Support legacy PHP 5.3 --- .travis.yml | 6 ++ README.md | 2 +- composer.json | 4 +- composer.lock | 146 +++++++++++++------------- leproxy.php | 4 +- src/ConnectorFactory.php | 2 +- src/HttpProxyServer.php | 38 ++++--- src/LoggingConnector.php | 9 +- tests/FunctionalLeProxyServerTest.php | 5 +- 9 files changed, 114 insertions(+), 102 deletions(-) diff --git a/.travis.yml b/.travis.yml index 19e60b8..85359d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: php php: +# - 5.3 # requires old distro, see below - 5.4 - 5.5 - 5.6 @@ -10,6 +11,11 @@ php: # lock distro so new future defaults will not break the build dist: trusty +matrix: + include: + - php: 5.3 + dist: precise + install: - composer install diff --git a/README.md b/README.md index 3c84adb..0ac43fc 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ accepting both common HTTP and SOCKS proxy protocols on a single listening port. ## Install LeProxy requires only PHP. -*PHP 7+ is highly recommended*, but it runs on any system that uses PHP 5.4+ or +*PHP 7+ is highly recommended*, but it runs on any system that uses PHP 5.3+ or HHVM. If you have not installed PHP already, on a recent Ubuntu/Debian system, simply run: diff --git a/composer.json b/composer.json index 942217b..0a82062 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ } ], "require": { - "php": ">=5.4", + "php": ">=5.3.8", "clue/commander": "^1.3", "clue/connection-manager-extra": "^1.1", "clue/http-proxy-react": "^1.2", @@ -31,7 +31,7 @@ ], "config": { "platform": { - "php": "5.4" + "php": "5.3.8" } }, "autoload": { diff --git a/composer.lock b/composer.lock index 6b4f7b7..ca51e1e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "3074fb344e97a593fd45c93a5a67f41f", + "content-hash": "b8f26ef0acc33fa4489fc881320c4fe1", "packages": [ { "name": "clue/commander", @@ -224,23 +224,20 @@ }, { "name": "evenement/evenement", - "version": "v2.1.0", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/igorw/evenement.git", - "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a" + "reference": "e24176d20f6dab44dd4768b32c897f63b6f2b7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/6ba9a777870ab49f417e703229d53931ed40fd7a", - "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a", + "url": "https://api.github.com/repos/igorw/evenement/zipball/e24176d20f6dab44dd4768b32c897f63b6f2b7c3", + "reference": "e24176d20f6dab44dd4768b32c897f63b6f2b7c3", "shasum": "" }, "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0||^5.7||^4.8.35" + "php": ">=5.3.0" }, "type": "library", "extra": { @@ -263,12 +260,11 @@ "email": "igor@wiedler.ch" } ], - "description": "Événement is a very simple event dispatching library for PHP", + "description": "Événement is a very simple event dispatching library for PHP 5.3", "keywords": [ - "event-dispatcher", - "event-emitter" + "event-dispatcher" ], - "time": "2017-07-17T17:39:19+00:00" + "time": "2017-07-17T17:04:59+00:00" }, { "name": "psr/http-message", @@ -407,33 +403,35 @@ }, { "name": "react/event-loop", - "version": "v0.4.3", + "version": "v0.3.5", + "target-dir": "React/EventLoop", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f" + "reference": "13e03b17e54ea864c6653a2cf6d146dad8464e91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/8bde03488ee897dc6bb3d91e4e17c353f9c5252f", - "reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/13e03b17e54ea864c6653a2cf6d146dad8464e91", + "reference": "13e03b17e54ea864c6653a2cf6d146dad8464e91", "shasum": "" }, "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" + "php": ">=5.3.3" }, "suggest": { - "ext-event": "~1.0", "ext-libev": "*", - "ext-libevent": ">=0.1.0" + "ext-libevent": ">=0.0.5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } + }, "autoload": { - "psr-4": { - "React\\EventLoop\\": "src" + "psr-0": { + "React\\EventLoop": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -442,10 +440,9 @@ ], "description": "Event loop abstraction layer that libraries can use for evented I/O.", "keywords": [ - "asynchronous", "event-loop" ], - "time": "2017-04-27T10:56:23+00:00" + "time": "2016-12-28T22:48:03+00:00" }, { "name": "react/http", @@ -539,31 +536,33 @@ }, { "name": "react/promise", - "version": "v2.5.1", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "62785ae604c8d69725d693eb370e1d67e94c4053" + "reference": "eefff597e67ff66b719f8171480add3c91474a1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/62785ae604c8d69725d693eb370e1d67e94c4053", - "reference": "62785ae604c8d69725d693eb370e1d67e94c4053", + "url": "https://api.github.com/repos/reactphp/promise/zipball/eefff597e67ff66b719f8171480add3c91474a1e", + "reference": "eefff597e67ff66b719f8171480add3c91474a1e", "shasum": "" }, "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" + "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, "autoload": { - "psr-4": { - "React\\Promise\\": "src/" + "psr-0": { + "React\\Promise": "src/" }, "files": [ - "src/functions_include.php" + "src/React/Promise/functions_include.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -577,11 +576,7 @@ } ], "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "keywords": [ - "promise", - "promises" - ], - "time": "2017-03-25T12:08:31+00:00" + "time": "2016-03-07T13:46:50+00:00" }, { "name": "react/promise-stream", @@ -998,33 +993,33 @@ }, { "name": "phpspec/prophecy", - "version": "v1.7.0", + "version": "1.7.5", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", "sebastian/comparator": "^1.1|^2.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -1057,7 +1052,7 @@ "spy", "stub" ], - "time": "2017-03-02T20:05:34+00:00" + "time": "2018-02-19T10:16:54+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1123,16 +1118,16 @@ }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -1166,7 +1161,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -1260,16 +1255,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.11", + "version": "1.4.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", "shasum": "" }, "require": { @@ -1305,7 +1300,7 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27T10:12:30+00:00" + "time": "2017-12-04T08:55:13+00:00" }, { "name": "phpunit/phpunit", @@ -1809,34 +1804,35 @@ }, { "name": "symfony/yaml", - "version": "v2.8.25", + "version": "v2.6.13", + "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5" + "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5", - "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", + "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "2.6-dev" } }, "autoload": { - "psr-4": { + "psr-0": { "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1854,7 +1850,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-06-01T20:52:29+00:00" + "time": "2015-07-26T08:59:42+00:00" } ], "aliases": [], @@ -1863,10 +1859,10 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.4" + "php": ">=5.3.8" }, "platform-dev": [], "platform-overrides": { - "php": "5.4" + "php": "5.3.8" } } diff --git a/leproxy.php b/leproxy.php index 3a064f7..058842b 100755 --- a/leproxy.php +++ b/leproxy.php @@ -20,8 +20,8 @@ use React\EventLoop\Factory; use React\Dns\Config\HostsFile; -if (PHP_VERSION_ID < 50400 || PHP_SAPI !== 'cli') { - echo 'LeProxy HTTP/SOCKS proxy requires running ' . (PHP_SAPI !== 'cli' ? ('via command line (not ' . PHP_SAPI . ')') : ('on PHP 5.4+ (is ' . PHP_VERSION . ')')) . PHP_EOL; +if (PHP_VERSION_ID < 50308 || PHP_SAPI !== 'cli') { + echo 'LeProxy HTTP/SOCKS proxy requires running ' . (PHP_SAPI !== 'cli' ? ('via command line (not ' . PHP_SAPI . ')') : ('on PHP 5.3.8+ (is ' . PHP_VERSION . ')')) . PHP_EOL; exit(1); } diff --git a/src/ConnectorFactory.php b/src/ConnectorFactory.php index ae7e177..b7df54d 100644 --- a/src/ConnectorFactory.php +++ b/src/ConnectorFactory.php @@ -193,7 +193,7 @@ public static function coerceBlockUri($uri) public static function createBlockingConnector(array $block, ConnectorInterface $base) { $reject = new ConnectionManagerReject(function () { - throw new \RuntimeException('Connection blocked', self::CODE_BLOCKED); + throw new \RuntimeException('Connection blocked', ConnectorFactory::CODE_BLOCKED); }); // reject all hosts given in the block list diff --git a/src/HttpProxyServer.php b/src/HttpProxyServer.php index 96a2f19..1e95140 100644 --- a/src/HttpProxyServer.php +++ b/src/HttpProxyServer.php @@ -49,7 +49,9 @@ public function __construct(LoopInterface $loop, ServerInterface $socket, Connec $this->client = $client; $that = $this; - $server = new HttpServer(array($this, 'handleRequest')); + $server = new HttpServer(function (ServerRequestInterface $request) use ($that) { + return $that->handleRequest($request); + }); $server->listen($socket); } @@ -151,22 +153,24 @@ public function handleConnectRequest(ServerRequestInterface $request) } // try to connect to given target host + $headers = $this->headers; + $that = $this; return $this->connector->connect($uri)->then( - function (ConnectionInterface $remote) { + function (ConnectionInterface $remote) use ($headers) { // connection established => forward data return new Response( 200, - $this->headers, + $headers, $remote ); }, - function (\Exception $e) { + function (\Exception $e) use ($headers, $that) { return new Response( - $this->getCode($e), + $that->getCode($e), array( 'Content-Type' => 'text/plain' - ) + $this->headers, - 'Unable to connect: ' . $this->getMessage($e) + ) + $headers, + 'Unable to connect: ' . $that->getMessage($e) ); } ); @@ -231,13 +235,15 @@ public function handlePlainRequest(ServerRequestInterface $request) $deferred->resolve($response); }); - $outgoing->on('error', function (Exception $e) use ($deferred) { + $headers = $this->headers; + $that = $this; + $outgoing->on('error', function (Exception $e) use ($deferred, $headers, $that) { $deferred->resolve(new Response( - $this->getCode($e), + $that->getCode($e), array( 'Content-Type' => 'text/plain' - ) + $this->headers, - 'Unable to request: ' . $this->getMessage($e) + ) + $headers, + 'Unable to request: ' . $that->getMessage($e) )); }); @@ -292,12 +298,13 @@ function FindProxyForURL(url, host) { } /** - * Returns an appropriate HTTP status code for the given Exception + * [Internal] Returns an appropriate HTTP status code for the given Exception * * @param \Exception $e * @return int + * @internal */ - private function getCode(\Exception $e) + public function getCode(\Exception $e) { if ($e->getCode() === ConnectorFactory::CODE_BLOCKED) { // Only map our block list to 403 (Forbidden) @@ -315,12 +322,13 @@ private function getCode(\Exception $e) } /** - * Returns the exception message and all its previous exceptions concatenated + * [Internal] Returns the exception message and all its previous exceptions concatenated * * @param Exception $e * @return string + * @internal */ - private function getMessage(Exception $e) + public function getMessage(Exception $e) { $message = ''; while ($e !== null) { diff --git a/src/LoggingConnector.php b/src/LoggingConnector.php index 8ade3ef..5749841 100644 --- a/src/LoggingConnector.php +++ b/src/LoggingConnector.php @@ -32,14 +32,15 @@ public function connect($uri) } $source = isset($args['source']) ? $args['source'] : null; + $logger = $this->logger; return $this->connector->connect($uri)->then( - function (ConnectionInterface $connection) use ($source, $uri) { - $this->logger->logConnection($source, $uri, $connection->getRemoteAddress()); + function (ConnectionInterface $connection) use ($source, $uri, $logger) { + $logger->logConnection($source, $uri, $connection->getRemoteAddress()); return $connection; }, - function (\Exception $e) use ($source, $uri) { - $this->logger->logFailConnection($source, $uri, $e->getMessage()); + function (\Exception $e) use ($source, $uri, $logger) { + $logger->logFailConnection($source, $uri, $e->getMessage()); throw $e; } diff --git a/tests/FunctionalLeProxyServerTest.php b/tests/FunctionalLeProxyServerTest.php index 40d1466..02f63d9 100644 --- a/tests/FunctionalLeProxyServerTest.php +++ b/tests/FunctionalLeProxyServerTest.php @@ -28,10 +28,11 @@ public function setUp() $this->socketOrigin = new Socket(8082, $this->loop); - $origin = new Server(function (ServerRequestInterface $request) { + $headers =& $this->headers; + $origin = new Server(function (ServerRequestInterface $request) use (&$headers) { return new Response( 200, - $this->headers + array( + $headers + array( 'X-Powered-By' => '', 'Date' => '', ),