diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php
index a07d263dd671066a049e111ba2069e2efd7a4fa1..f11621f6aac8082ebf1403fdb0559befa17f98f0 100644
--- a/inc/HTTPClient.php
+++ b/inc/HTTPClient.php
@@ -61,6 +61,8 @@ class DokuHTTPClient extends HTTPClient {
 
 }
 
+class HTTPClientException extends Exception { }
+
 /**
  * This class implements a basic HTTP client
  *
@@ -308,220 +310,200 @@ class HTTPClient {
             }
         }
 
-        //set blocking
-        stream_set_blocking($socket,1);
-
-        // build request
-        $request  = "$method $request_url HTTP/".$this->http.HTTP_NL;
-        $request .= $this->_buildHeaders($headers);
-        $request .= $this->_getCookies();
-        $request .= HTTP_NL;
-        $request .= $data;
-
-        $this->_debug('request',$request);
-
-        // select parameters
-        $sel_r = null;
-        $sel_w = array($socket);
-        $sel_e = null;
-
-        // send request
-        $towrite = strlen($request);
-        $written = 0;
-        while($written < $towrite){
-            // check timeout
-            if(time()-$start > $this->timeout){
-                $this->status = -100;
-                $this->error = sprintf('Timeout while sending request (%.3fs)',$this->_time() - $this->start);
-                unset(self::$connections[$connectionId]);
-                return false;
-            }
-
-            // wait for stream ready or timeout (1sec)
-            if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
-                usleep(1000);
-                continue;
-            }
-
-            // write to stream
-            $ret = fwrite($socket, substr($request,$written,4096));
-            if($ret === false){
-                $this->status = -100;
-                $this->error = 'Failed writing to socket';
-                unset(self::$connections[$connectionId]);
-                return false;
-            }
-            $written += $ret;
-        }
-
-        // continue non-blocking
-        stream_set_blocking($socket,0);
+        try {
+            //set blocking
+            stream_set_blocking($socket,1);
+
+            // build request
+            $request  = "$method $request_url HTTP/".$this->http.HTTP_NL;
+            $request .= $this->_buildHeaders($headers);
+            $request .= $this->_getCookies();
+            $request .= HTTP_NL;
+            $request .= $data;
+
+            $this->_debug('request',$request);
+
+            // select parameters
+            $sel_r = null;
+            $sel_w = array($socket);
+            $sel_e = null;
+
+            // send request
+            $towrite = strlen($request);
+            $written = 0;
+            while($written < $towrite){
+                // check timeout
+                if(time()-$start > $this->timeout)
+                    throw new HTTPClientException(sprintf('Timeout while sending request (%.3fs)',$this->_time() - $this->start), -100);
+
+                // wait for stream ready or timeout (1sec)
+                if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
+                    usleep(1000);
+                    continue;
+                }
 
-        // read headers from socket
-        $r_headers = '';
-        do{
-            if(time()-$start > $this->timeout){
-                $this->status = -100;
-                $this->error = sprintf('Timeout while reading headers (%.3fs)',$this->_time() - $this->start);
-                unset(self::$connections[$connectionId]);
-                return false;
-            }
-            if(feof($socket)){
-                $this->error = 'Premature End of File (socket)';
-                unset(self::$connections[$connectionId]);
-                return false;
+                // write to stream
+                $ret = fwrite($socket, substr($request,$written,4096));
+                if($ret === false)
+                    throw new HTTPClientException('Failed writing to socket', -100);
+                $written += $ret;
             }
-            usleep(1000);
-            $r_headers .= fgets($socket,1024);
-        }while(!preg_match('/\r?\n\r?\n$/',$r_headers));
 
-        $this->_debug('response headers',$r_headers);
+            // continue non-blocking
+            stream_set_blocking($socket,0);
 
-        // check if expected body size exceeds allowance
-        if($this->max_bodysize && preg_match('/\r?\nContent-Length:\s*(\d+)\r?\n/i',$r_headers,$match)){
-            if($match[1] > $this->max_bodysize){
-                $this->error = 'Reported content length exceeds allowed response size';
-                if ($this->max_bodysize_abort)
-                    unset(self::$connections[$connectionId]);
-                    return false;
+            // read headers from socket
+            $r_headers = '';
+            do{
+                if(time()-$start > $this->timeout)
+                    throw new HTTPClientException(sprintf('Timeout while reading headers (%.3fs)',$this->_time() - $this->start), -100);
+                if(feof($socket))
+                    throw new HTTPClientException('Premature End of File (socket)');
+                usleep(1000);
+                $r_headers .= fgets($socket,1024);
+            }while(!preg_match('/\r?\n\r?\n$/',$r_headers));
+
+            $this->_debug('response headers',$r_headers);
+
+            // check if expected body size exceeds allowance
+            if($this->max_bodysize && preg_match('/\r?\nContent-Length:\s*(\d+)\r?\n/i',$r_headers,$match)){
+                if($match[1] > $this->max_bodysize){
+                    if ($this->max_bodysize_abort)
+                        throw new HTTPClientException('Reported content length exceeds allowed response size');
+                    else
+                        $this->error = 'Reported content length exceeds allowed response size';
+                }
             }
-        }
 
-        // get Status
-        if (!preg_match('/^HTTP\/(\d\.\d)\s*(\d+).*?\n/', $r_headers, $m)) {
-            $this->error = 'Server returned bad answer';
-            unset(self::$connections[$connectionId]);
-            return false;
-        }
-        $this->status = $m[2];
-
-        // handle headers and cookies
-        $this->resp_headers = $this->_parseHeaders($r_headers);
-        if(isset($this->resp_headers['set-cookie'])){
-            foreach ((array) $this->resp_headers['set-cookie'] as $cookie){
-                list($cookie)   = explode(';',$cookie,2);
-                list($key,$val) = explode('=',$cookie,2);
-                $key = trim($key);
-                if($val == 'deleted'){
-                    if(isset($this->cookies[$key])){
-                        unset($this->cookies[$key]);
+            // get Status
+            if (!preg_match('/^HTTP\/(\d\.\d)\s*(\d+).*?\n/', $r_headers, $m))
+                throw new HTTPClientException('Server returned bad answer');
+
+            $this->status = $m[2];
+
+            // handle headers and cookies
+            $this->resp_headers = $this->_parseHeaders($r_headers);
+            if(isset($this->resp_headers['set-cookie'])){
+                foreach ((array) $this->resp_headers['set-cookie'] as $cookie){
+                    list($cookie)   = explode(';',$cookie,2);
+                    list($key,$val) = explode('=',$cookie,2);
+                    $key = trim($key);
+                    if($val == 'deleted'){
+                        if(isset($this->cookies[$key])){
+                            unset($this->cookies[$key]);
+                        }
+                    }elseif($key){
+                        $this->cookies[$key] = $val;
                     }
-                }elseif($key){
-                    $this->cookies[$key] = $val;
                 }
             }
-        }
 
-        $this->_debug('Object headers',$this->resp_headers);
+            $this->_debug('Object headers',$this->resp_headers);
 
-        // check server status code to follow redirect
-        if($this->status == 301 || $this->status == 302 ){
-            // close the connection because we don't handle content retrieval here
-            // that's the easiest way to clean up the connection
-            fclose($socket);
-            unset(self::$connections[$connectionId]);
+            // check server status code to follow redirect
+            if($this->status == 301 || $this->status == 302 ){
+                if (empty($this->resp_headers['location'])){
+                    throw new HTTPClientException('Redirect but no Location Header found');
+                }elseif($this->redirect_count == $this->max_redirect){
+                    throw new HTTPClientException('Maximum number of redirects exceeded');
+                }else{
+                    // close the connection because we don't handle content retrieval here
+                    // that's the easiest way to clean up the connection
+                    fclose($socket);
+                    unset(self::$connections[$connectionId]);
 
-            if (empty($this->resp_headers['location'])){
-                $this->error = 'Redirect but no Location Header found';
-                return false;
-            }elseif($this->redirect_count == $this->max_redirect){
-                $this->error = 'Maximum number of redirects exceeded';
-                return false;
-            }else{
-                $this->redirect_count++;
-                $this->referer = $url;
-                // handle non-RFC-compliant relative redirects
-                if (!preg_match('/^http/i', $this->resp_headers['location'])){
-                    if($this->resp_headers['location'][0] != '/'){
-                        $this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uri['port'].
-                                                          dirname($uri['path']).'/'.$this->resp_headers['location'];
-                    }else{
-                        $this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uri['port'].
-                                                          $this->resp_headers['location'];
+                    $this->redirect_count++;
+                    $this->referer = $url;
+                    // handle non-RFC-compliant relative redirects
+                    if (!preg_match('/^http/i', $this->resp_headers['location'])){
+                        if($this->resp_headers['location'][0] != '/'){
+                            $this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uri['port'].
+                                                            dirname($uri['path']).'/'.$this->resp_headers['location'];
+                        }else{
+                            $this->resp_headers['location'] = $uri['scheme'].'://'.$uri['host'].':'.$uri['port'].
+                                                            $this->resp_headers['location'];
+                        }
                     }
+                    // perform redirected request, always via GET (required by RFC)
+                    return $this->sendRequest($this->resp_headers['location'],array(),'GET');
                 }
-                // perform redirected request, always via GET (required by RFC)
-                return $this->sendRequest($this->resp_headers['location'],array(),'GET');
             }
-        }
 
-        // check if headers are as expected
-        if($this->header_regexp && !preg_match($this->header_regexp,$r_headers)){
-            $this->error = 'The received headers did not match the given regexp';
-            unset(self::$connections[$connectionId]);
-            return false;
-        }
+            // check if headers are as expected
+            if($this->header_regexp && !preg_match($this->header_regexp,$r_headers))
+                throw new HTTPClientException('The received headers did not match the given regexp');
 
-        //read body (with chunked encoding if needed)
-        $r_body    = '';
-        if(preg_match('/transfer\-(en)?coding:\s*chunked\r\n/i',$r_headers)){
-            do {
-                $chunk_size = '';
+            //read body (with chunked encoding if needed)
+            $r_body    = '';
+            if(preg_match('/transfer\-(en)?coding:\s*chunked\r\n/i',$r_headers)){
+                stream_set_blocking($socket,1);
                 do {
-                    if(feof($socket)){
-                        $this->error = 'Premature End of File (socket)';
-                        unset(self::$connections[$connectionId]);
-                        return false;
+                    $chunk_size = '';
+                    do {
+                        if(feof($socket))
+                            throw new HTTPClientException('Premature End of File (socket)');
+                        if(time()-$start > $this->timeout)
+                            throw new HTTPClientException(sprintf('Timeout while reading chunk (%.3fs)',$this->_time() - $this->start), -100);
+                        $byte = fread($socket,1);
+                        $chunk_size .= $byte;
+                    } while (preg_match('/^[a-zA-Z0-9]?$/',$byte)); // read chunksize including \r
+
+                    $byte = fread($socket,1);     // readtrailing \n
+                    $chunk_size = hexdec($chunk_size);
+                    if ($chunk_size) {
+                        $read_size = $chunk_size;
+                        while ($read_size > 0) {
+                            $this_chunk = fread($socket,$read_size);
+                            $r_body    .= $this_chunk;
+                            $read_size -= strlen($this_chunk);
+                        }
+                        $byte = fread($socket,2); // read trailing \r\n
+                    }
+
+                    if($this->max_bodysize && strlen($r_body) > $this->max_bodysize){
+                        if ($this->max_bodysize_abort)
+                            throw new HTTPClientException('Allowed response size exceeded');
+                        $this->error = 'Allowed response size exceeded';
+                        break;
                     }
+                } while ($chunk_size);
+                stream_set_blocking($socket,0);
+            }else{
+                // read entire socket
+                while (!feof($socket)) {
                     if(time()-$start > $this->timeout){
                         $this->status = -100;
-                        $this->error = sprintf('Timeout while reading chunk (%.3fs)',$this->_time() - $this->start);
+                        $this->error = sprintf('Timeout while reading response (%.3fs)',$this->_time() - $this->start);
                         unset(self::$connections[$connectionId]);
                         return false;
                     }
-                    $byte = fread($socket,1);
-                    $chunk_size .= $byte;
-                } while (preg_match('/^[a-zA-Z0-9]?$/',$byte)); // read chunksize including \r
-
-                $byte = fread($socket,1);     // readtrailing \n
-                $chunk_size = hexdec($chunk_size);
-                if ($chunk_size) {
-                    $read_size = $chunk_size;
-                    while ($read_size > 0) {
-                        $this_chunk = fread($socket,$read_size);
-                        $r_body    .= $this_chunk;
-                        $read_size -= strlen($this_chunk);
-                    }
-                    $byte = fread($socket,2); // read trailing \r\n
-                }
-
-                if($this->max_bodysize && strlen($r_body) > $this->max_bodysize){
-                    $this->error = 'Allowed response size exceeded';
-                    if ($this->max_bodysize_abort){
-                        unset(self::$connections[$connectionId]);
-                        return false;
-                    } else {
-                        break;
+                    $r_body .= fread($socket,4096);
+                    $r_size = strlen($r_body);
+                    if($this->max_bodysize && $r_size > $this->max_bodysize){
+                        $this->error = 'Allowed response size exceeded';
+                        if ($this->max_bodysize_abort) {
+                            unset(self::$connections[$connectionId]);
+                            return false;
+                        } else {
+                            break;
+                        }
                     }
-                }
-            } while ($chunk_size);
-        }else{
-            // read entire socket
-            while (!feof($socket)) {
-                if(time()-$start > $this->timeout){
-                    $this->status = -100;
-                    $this->error = sprintf('Timeout while reading response (%.3fs)',$this->_time() - $this->start);
-                    unset(self::$connections[$connectionId]);
-                    return false;
-                }
-                $r_body .= fread($socket,4096);
-                $r_size = strlen($r_body);
-                if($this->max_bodysize && $r_size > $this->max_bodysize){
-                    $this->error = 'Allowed response size exceeded';
-                    if ($this->max_bodysize_abort) {
-                        unset(self::$connections[$connectionId]);
-                        return false;
-                    } else {
+                    if(isset($this->resp_headers['content-length']) &&
+                    !isset($this->resp_headers['transfer-encoding']) &&
+                    $this->resp_headers['content-length'] == $r_size){
+                        // we read the content-length, finish here
                         break;
                     }
                 }
-                if(isset($this->resp_headers['content-length']) &&
-                   !isset($this->resp_headers['transfer-encoding']) &&
-                   $this->resp_headers['content-length'] == $r_size){
-                    // we read the content-length, finish here
-                    break;
-                }
             }
+
+        } catch (HTTPClientException $err) {
+            $this->error = $err->getMessage();
+            if ($err->getCode())
+                $this->status = $err->getCode();
+            unset(self::$connections[$connectionId]);
+            fclose($socket);
+            return false;
         }
 
         if (!$this->keep_alive ||