summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/tests/inc/httpclient_http_proxy.test.php19
-rw-r--r--_test/tests/inc/httpclient_https.test.php1
-rw-r--r--_test/tests/inc/httpclient_https_proxy.test.php15
-rw-r--r--inc/HTTPClient.php66
4 files changed, 96 insertions, 5 deletions
diff --git a/_test/tests/inc/httpclient_http_proxy.test.php b/_test/tests/inc/httpclient_http_proxy.test.php
new file mode 100644
index 000000000..81abdbca0
--- /dev/null
+++ b/_test/tests/inc/httpclient_http_proxy.test.php
@@ -0,0 +1,19 @@
+<?php
+
+class httpclient_http_proxy_test extends DokuWikiTest {
+ protected $url = 'http://www.dokuwiki.org/README';
+
+ /**
+ * @group internet
+ */
+ function test_simpleget(){
+ $http = new HTTPClient();
+ $http->proxy_host = 'localhost'; //FIXME we need a public server
+ $http->proxy_port = 3128;
+
+ $data = $http->get($this->url);
+ $this->assertFalse($data === false, 'HTTP response');
+ $this->assertTrue(strpos($data,'DokuWiki') !== false, 'response content');
+ }
+
+} \ No newline at end of file
diff --git a/_test/tests/inc/httpclient_https.test.php b/_test/tests/inc/httpclient_https.test.php
index 26a0f86db..955d467ec 100644
--- a/_test/tests/inc/httpclient_https.test.php
+++ b/_test/tests/inc/httpclient_https.test.php
@@ -1,4 +1,5 @@
<?php
+require_once dirname(__FILE__).'/httpclient_http.test.php';
class httpclient_https_test extends httpclient_http_test {
protected $server = 'https://httpbin.org/';
diff --git a/_test/tests/inc/httpclient_https_proxy.test.php b/_test/tests/inc/httpclient_https_proxy.test.php
new file mode 100644
index 000000000..aca3b3be2
--- /dev/null
+++ b/_test/tests/inc/httpclient_https_proxy.test.php
@@ -0,0 +1,15 @@
+<?php
+require_once dirname(__FILE__).'/httpclient_http_proxy.test.php';
+
+class httpclient_https_proxy_test extends httpclient_http_proxy_test {
+ protected $url = 'https://www.dokuwiki.org/README';
+
+ public function setUp(){
+ // skip tests when this PHP has no SSL support
+ $transports = stream_get_transports();
+ if(!in_array('ssl',$transports)){
+ $this->markTestSkipped('No SSL support available.');
+ }
+ parent::setUp();
+ }
+} \ No newline at end of file
diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php
index a25846c31..8d2c10be1 100644
--- a/inc/HTTPClient.php
+++ b/inc/HTTPClient.php
@@ -254,11 +254,7 @@ class HTTPClient {
if(!empty($uri['port'])) $headers['Host'].= ':'.$uri['port'];
$headers['User-Agent'] = $this->agent;
$headers['Referer'] = $this->referer;
- if ($this->keep_alive) {
- $headers['Connection'] = 'Keep-Alive';
- } else {
- $headers['Connection'] = 'Close';
- }
+
if($method == 'POST'){
if(is_array($data)){
if($headers['Content-Type'] == 'multipart/form-data'){
@@ -299,6 +295,14 @@ class HTTPClient {
return false;
}
+ // try establish a CONNECT tunnel for SSL
+ if($this->_ssltunnel($socket, $request_url)){
+ // no keep alive for tunnels
+ $this->keep_alive = false;
+ // tunnel is authed already
+ if(isset($headers['Proxy-Authentication'])) unset($headers['Proxy-Authentication']);
+ }
+
// keep alive?
if ($this->keep_alive) {
self::$connections[$connectionId] = $socket;
@@ -307,6 +311,15 @@ class HTTPClient {
}
}
+ if ($this->keep_alive && !$this->proxy_host) {
+ // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
+ // connection token to a proxy server. We still do keep the connection the
+ // proxy alive (well except for CONNECT tunnels)
+ $headers['Connection'] = 'Keep-Alive';
+ } else {
+ $headers['Connection'] = 'Close';
+ }
+
try {
//set non-blocking
stream_set_blocking($socket, false);
@@ -485,6 +498,49 @@ class HTTPClient {
}
/**
+ * Tries to establish a CONNECT tunnel via Proxy
+ *
+ * Protocol, Servername and Port will be stripped from the request URL when a successful CONNECT happened
+ *
+ * @param ressource &$socket
+ * @param string &$requesturl
+ * @return bool true if a tunnel was established
+ */
+ function _ssltunnel(&$socket, &$requesturl){
+ if(!$this->proxy_host) return false;
+ $requestinfo = parse_url($requesturl);
+ if($requestinfo['scheme'] != 'https') return false;
+ if(!$requestinfo['port']) $requestinfo['port'] = 443;
+
+ // build request
+ $request = "CONNECT {$requestinfo['host']}:{$requestinfo['port']} HTTP/1.0".HTTP_NL;
+ $request .= "Host: {$requestinfo['host']}".HTTP_NL;
+ if($this->proxy_user) {
+ 'Proxy-Authorization Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass).HTTP_NL;
+ }
+ $request .= HTTP_NL;
+
+ $this->_debug('SSL Tunnel CONNECT',$request);
+ $this->_sendData($socket, $request, 'SSL Tunnel CONNECT');
+
+ // read headers from socket
+ $r_headers = '';
+ do{
+ $r_line = $this->_readLine($socket, 'headers');
+ $r_headers .= $r_line;
+ }while($r_line != "\r\n" && $r_line != "\n");
+
+ $this->_debug('SSL Tunnel Response',$r_headers);
+ if(preg_match('/^HTTP\/1\.0 200/i',$r_headers)){
+ if (stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)) {
+ $requesturl = $requestinfo['path'];
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Safely write data to a socket
*
* @param handle $socket An open socket handle