summaryrefslogtreecommitdiff
path: root/inc/HTTPClient.php
diff options
context:
space:
mode:
authorghi <dokuwiki@imz.re>2015-02-17 11:08:15 +0100
committerghi <dokuwiki@imz.re>2015-02-17 11:08:15 +0100
commit7d0b7e5ed7aa0f9c56def8f6c9866aa4fc8315b8 (patch)
tree08330b0a548a402caeb02ee7a185e745386ad45d /inc/HTTPClient.php
parentd6dc28be40fb3202a3df69458db164e20999ac2b (diff)
parentf8803275a58a05b29e4029cc539a6f8c60ad2ea5 (diff)
downloadrpg-7d0b7e5ed7aa0f9c56def8f6c9866aa4fc8315b8.tar.gz
rpg-7d0b7e5ed7aa0f9c56def8f6c9866aa4fc8315b8.tar.bz2
Merge https://github.com/splitbrain/dokuwiki into html_showrev_output
Diffstat (limited to 'inc/HTTPClient.php')
-rw-r--r--inc/HTTPClient.php119
1 files changed, 94 insertions, 25 deletions
diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php
index 96954fb47..76d973c38 100644
--- a/inc/HTTPClient.php
+++ b/inc/HTTPClient.php
@@ -35,6 +35,19 @@ class DokuHTTPClient extends HTTPClient {
$this->proxy_pass = conf_decodeString($conf['proxy']['pass']);
$this->proxy_ssl = $conf['proxy']['ssl'];
$this->proxy_except = $conf['proxy']['except'];
+
+ // allow enabling debugging via URL parameter (if debugging allowed)
+ if($conf['allowdebug']) {
+ if(
+ isset($_REQUEST['httpdebug']) ||
+ (
+ isset($_SERVER['HTTP_REFERER']) &&
+ strpos($_SERVER['HTTP_REFERER'], 'httpdebug') !== false
+ )
+ ) {
+ $this->debug = true;
+ }
+ }
}
@@ -44,6 +57,12 @@ class DokuHTTPClient extends HTTPClient {
* @triggers HTTPCLIENT_REQUEST_SEND
* @author Andreas Gohr <andi@splitbrain.org>
*/
+ /**
+ * @param string $url
+ * @param string|array $data the post data either as array or raw data
+ * @param string $method
+ * @return bool
+ */
function sendRequest($url,$data='',$method='GET'){
$httpdata = array('url' => $url,
'data' => $data,
@@ -61,6 +80,9 @@ class DokuHTTPClient extends HTTPClient {
}
+/**
+ * Class HTTPClientException
+ */
class HTTPClientException extends Exception { }
/**
@@ -88,7 +110,7 @@ class HTTPClient {
var $header_regexp; // if set this RE must match against the headers, else abort
var $headers;
var $debug;
- var $start = 0; // for timings
+ var $start = 0.0; // for timings
var $keep_alive = true; // keep alive rocks
// don't set these, read on error
@@ -150,7 +172,8 @@ class HTTPClient {
*
* @param string $url The URL to fetch
* @param bool $sloppy304 Return body on 304 not modified
- * @return bool|string response body, false on error
+ * @return false|string response body, false on error
+ *
* @author Andreas Gohr <andi@splitbrain.org>
*/
function get($url,$sloppy304=false){
@@ -171,7 +194,8 @@ class HTTPClient {
* @param string $url The URL to fetch
* @param array $data Associative array of parameters
* @param bool $sloppy304 Return body on 304 not modified
- * @return bool|string response body, false on error
+ * @return false|string response body, false on error
+ *
* @author Andreas Gohr <andi@splitbrain.org>
*/
function dget($url,$data,$sloppy304=false){
@@ -191,7 +215,7 @@ class HTTPClient {
*
* @param string $url The URL to fetch
* @param array $data Associative array of parameters
- * @return bool|string response body, false on error
+ * @return false|string response body, false on error
* @author Andreas Gohr <andi@splitbrain.org>
*/
function post($url,$data){
@@ -213,6 +237,7 @@ class HTTPClient {
* @param mixed $data - the post data either as array or raw data
* @param string $method - HTTP Method usually GET or POST.
* @return bool - true on success
+ *
* @author Andreas Goetz <cpuidle@gmx.de>
* @author Andreas Gohr <andi@splitbrain.org>
*/
@@ -249,12 +274,17 @@ class HTTPClient {
if (empty($port)) $port = 8080;
}else{
$request_url = $path;
- $server = $server;
if (!isset($port)) $port = ($uri['scheme'] == 'https') ? 443 : 80;
}
// add SSL stream prefix if needed - needs SSL support in PHP
- if($port == 443 || $this->proxy_ssl) $server = 'ssl://'.$server;
+ if($port == 443 || $this->proxy_ssl) {
+ if(!in_array('ssl', stream_get_transports())) {
+ $this->status = -200;
+ $this->error = 'This PHP version does not support SSL - cannot connect to server';
+ }
+ $server = 'ssl://'.$server;
+ }
// prepare headers
$headers = $this->headers;
@@ -274,7 +304,6 @@ class HTTPClient {
}
}
$headers['Content-Length'] = strlen($data);
- $rmethod = 'POST';
}elseif($method == 'GET'){
$data = ''; //no data allowed on GET requests
}
@@ -304,11 +333,18 @@ class HTTPClient {
}
// 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']);
+ try {
+ 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']);
+ }
+ } catch (HTTPClientException $e) {
+ $this->status = $e->getCode();
+ $this->error = $e->getMessage();
+ fclose($socket);
+ return false;
}
// keep alive?
@@ -330,7 +366,7 @@ class HTTPClient {
try {
//set non-blocking
- stream_set_blocking($socket, false);
+ stream_set_blocking($socket, 0);
// build request
$request = "$method $request_url HTTP/".$this->http.HTTP_NL;
@@ -363,7 +399,7 @@ class HTTPClient {
// get Status
if (!preg_match('/^HTTP\/(\d\.\d)\s*(\d+).*?\n/', $r_headers, $m))
- throw new HTTPClientException('Server returned bad answer');
+ throw new HTTPClientException('Server returned bad answer '.$r_headers);
$this->status = $m[2];
@@ -445,7 +481,7 @@ class HTTPClient {
if ($chunk_size > 0) {
$r_body .= $this->_readData($socket, $chunk_size, 'chunk');
- $byte = $this->_readData($socket, 2, 'chunk'); // read trailing \r\n
+ $this->_readData($socket, 2, 'chunk'); // read trailing \r\n
}
} while ($chunk_size && !$abort);
}elseif(isset($this->resp_headers['content-length']) && !isset($this->resp_headers['transfer-encoding'])){
@@ -467,7 +503,6 @@ class HTTPClient {
$r_body = $this->_readData($socket, $this->max_bodysize, 'response (content-length limited)', true);
}else{
// read entire socket
- $r_size = 0;
while (!feof($socket)) {
$r_body .= $this->_readData($socket, 4096, 'response (unlimited)', true);
}
@@ -496,7 +531,6 @@ class HTTPClient {
if (!$this->keep_alive ||
(isset($this->resp_headers['connection']) && $this->resp_headers['connection'] == 'Close')) {
// close socket
- $status = socket_get_status($socket);
fclose($socket);
unset(self::$connections[$connectionId]);
}
@@ -526,6 +560,7 @@ class HTTPClient {
*
* @param resource &$socket
* @param string &$requesturl
+ * @throws HTTPClientException when a tunnel is needed but could not be established
* @return bool true if a tunnel was established
*/
function _ssltunnel(&$socket, &$requesturl){
@@ -538,7 +573,7 @@ class HTTPClient {
$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 .= 'Proxy-Authorization: Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass).HTTP_NL;
}
$request .= HTTP_NL;
@@ -554,12 +589,24 @@ class HTTPClient {
$this->_debug('SSL Tunnel Response',$r_headers);
if(preg_match('/^HTTP\/1\.[01] 200/i',$r_headers)){
- if (stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)) {
+ // set correct peer name for verification (enabled since PHP 5.6)
+ stream_context_set_option($socket, 'ssl', 'peer_name', $requestinfo['host']);
+
+ // Because of older PHP versions having trouble with TLS (enable_crypto returns true, but
+ // the conection still borks) we try SSLv3 first
+ if (@stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)) {
+ $requesturl = $requestinfo['path'];
+ return true;
+ }
+
+ // If the proxy does not support SSLv3 we try TLS
+ if (@stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
$requesturl = $requestinfo['path'];
return true;
}
}
- return false;
+
+ throw new HTTPClientException('Failed to establish secure proxy connection', -150);
}
/**
@@ -569,6 +616,7 @@ class HTTPClient {
* @param string $data The data to write
* @param string $message Description of what is being read
* @throws HTTPClientException
+ *
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function _sendData($socket, $data, $message) {
@@ -613,6 +661,7 @@ class HTTPClient {
* @param bool $ignore_eof End-of-file is not an error if this is set
* @throws HTTPClientException
* @return string
+ *
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function _readData($socket, $nbytes, $message, $ignore_eof = false) {
@@ -662,6 +711,7 @@ class HTTPClient {
* @param string $message Description of what is being read
* @throws HTTPClientException
* @return string
+ *
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function _readLine($socket, $message) {
@@ -696,6 +746,9 @@ class HTTPClient {
* Uses _debug_text or _debug_html depending on the SAPI name
*
* @author Andreas Gohr <andi@splitbrain.org>
+ *
+ * @param string $info
+ * @param mixed $var
*/
function _debug($info,$var=null){
if(!$this->debug) return;
@@ -709,8 +762,8 @@ class HTTPClient {
/**
* print debug info as HTML
*
- * @param $info
- * @param null $var
+ * @param string $info
+ * @param mixed $var
*/
function _debug_html($info, $var=null){
print '<b>'.$info.'</b> '.($this->_time() - $this->start).'s<br />';
@@ -726,8 +779,8 @@ class HTTPClient {
/**
* prints debug info as plain text
*
- * @param $info
- * @param null $var
+ * @param string $info
+ * @param mixed $var
*/
function _debug_text($info, $var=null){
print '*'.$info.'* '.($this->_time() - $this->start)."s\n";
@@ -737,6 +790,8 @@ class HTTPClient {
/**
* Return current timestamp in microsecond resolution
+ *
+ * @return float
*/
static function _time(){
list($usec, $sec) = explode(" ", microtime());
@@ -749,6 +804,9 @@ class HTTPClient {
* All Keys are lowercased.
*
* @author Andreas Gohr <andi@splitbrain.org>
+ *
+ * @param string $string
+ * @return array
*/
function _parseHeaders($string){
$headers = array();
@@ -777,11 +835,14 @@ class HTTPClient {
* convert given header array to header string
*
* @author Andreas Gohr <andi@splitbrain.org>
+ *
+ * @param array $headers
+ * @return string
*/
function _buildHeaders($headers){
$string = '';
foreach($headers as $key => $value){
- if(empty($value)) continue;
+ if($value === '') continue;
$string .= $key.': '.$value.HTTP_NL;
}
return $string;
@@ -791,6 +852,8 @@ class HTTPClient {
* get cookies as http header string
*
* @author Andreas Goetz <cpuidle@gmx.de>
+ *
+ * @return string
*/
function _getCookies(){
$headers = '';
@@ -806,6 +869,9 @@ class HTTPClient {
* Encode data for posting
*
* @author Andreas Gohr <andi@splitbrain.org>
+ *
+ * @param array $data
+ * @return string
*/
function _postEncode($data){
return http_build_query($data,'','&');
@@ -816,6 +882,9 @@ class HTTPClient {
*
* @fixme use of urlencode might be wrong here
* @author Andreas Gohr <andi@splitbrain.org>
+ *
+ * @param array $data
+ * @return string
*/
function _postMultipartEncode($data){
$boundary = '--'.$this->boundary;