diff options
author | Morris Jobke <hey@morrisjobke.de> | 2015-03-26 11:06:48 +0100 |
---|---|---|
committer | Morris Jobke <hey@morrisjobke.de> | 2015-03-26 11:06:48 +0100 |
commit | 20f5290462cddee766025bd5671430836b054cc8 (patch) | |
tree | a0b33a654f6fa2ed4c75dffd9f65ddd437ada90f /lib | |
parent | c8f0cbab5a994aadfaa9c984bb9959ca872fe781 (diff) | |
parent | 5f044ebf1bc6f45acec2e79dc05185acd0405f42 (diff) | |
download | nextcloud-server-20f5290462cddee766025bd5671430836b054cc8.tar.gz nextcloud-server-20f5290462cddee766025bd5671430836b054cc8.zip |
Merge pull request #15195 from owncloud/reanimate-add-guzzle
Add wrapper for Guzzle
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/http/client/client.php | 268 | ||||
-rw-r--r-- | lib/private/http/client/clientservice.php | 43 | ||||
-rw-r--r-- | lib/private/http/client/response.php | 58 | ||||
-rw-r--r-- | lib/private/httphelper.php | 164 | ||||
-rw-r--r-- | lib/private/installer.php | 5 | ||||
-rw-r--r-- | lib/private/ocsclient.php | 59 | ||||
-rw-r--r-- | lib/private/security/certificatemanager.php | 10 | ||||
-rw-r--r-- | lib/private/server.php | 27 | ||||
-rw-r--r-- | lib/private/util.php | 28 | ||||
-rw-r--r-- | lib/public/http/client/iclient.php | 181 | ||||
-rw-r--r-- | lib/public/http/client/iclientservice.php | 21 | ||||
-rw-r--r-- | lib/public/http/client/iresponse.php | 37 | ||||
-rw-r--r-- | lib/public/iservercontainer.php | 8 | ||||
-rw-r--r-- | lib/repair/updatecertificatestore.php | 77 |
14 files changed, 812 insertions, 174 deletions
diff --git a/lib/private/http/client/client.php b/lib/private/http/client/client.php new file mode 100644 index 00000000000..7c022272375 --- /dev/null +++ b/lib/private/http/client/client.php @@ -0,0 +1,268 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Http\Client; + +use GuzzleHttp\Client as GuzzleClient; +use OCP\Http\Client\IClient; +use OCP\ICertificateManager; +use OCP\IConfig; + +/** + * Class Client + * + * @package OC\Http + */ +class Client implements IClient { + /** @var GuzzleClient */ + private $client; + /** @var IConfig */ + private $config; + /** @var ICertificateManager */ + private $certificateManager; + + /** + * @param IConfig $config + * @param ICertificateManager $certificateManager + * @param GuzzleClient $client + */ + public function __construct(IConfig $config, + ICertificateManager $certificateManager, + GuzzleClient $client) { + $this->config = $config; + $this->client = $client; + $this->certificateManager = $certificateManager; + $this->setDefaultOptions(); + } + + /** + * Sets the default options to the client + */ + private function setDefaultOptions() { + // Either use default bundle or the user bundle if nothing is specified + if($this->certificateManager->listCertificates() !== []) { + $dataDir = $this->config->getSystemValue('datadirectory'); + $this->client->setDefaultOption('verify', $dataDir.'/'.$this->certificateManager->getCertificateBundle()); + } else { + $this->client->setDefaultOption('verify', \OC::$SERVERROOT . '/config/ca-bundle.crt'); + } + + $this->client->setDefaultOption('headers/User-Agent', 'ownCloud Server Crawler'); + if($this->getProxyUri() !== '') { + $this->client->setDefaultOption('proxy', $this->getProxyUri()); + } + } + + /** + * Get the proxy URI + * @return string + */ + private function getProxyUri() { + $proxyHost = $this->config->getSystemValue('proxy', null); + $proxyUserPwd = $this->config->getSystemValue('proxyuserpwd', null); + $proxyUri = ''; + + if(!is_null($proxyUserPwd)) { + $proxyUri .= $proxyUserPwd.'@'; + } + if(!is_null($proxyHost)) { + $proxyUri .= $proxyHost; + } + + return $proxyUri; + } + + /** + * Sends a GET request + * @param string $uri + * @param array $options Array such as + * 'query' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * 'timeout' => 5, + * @return Response + * @throws \Exception If the request could not get completed + */ + public function get($uri, array $options = []) { + $response = $this->client->get($uri, $options); + return new Response($response); + } + + /** + * Sends a HEAD request + * @param string $uri + * @param array $options Array such as + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * 'timeout' => 5, + * @return Response + */ + public function head($uri, $options = []) { + $response = $this->client->head($uri, $options); + return new Response($response); + } + + /** + * Sends a POST request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * 'timeout' => 5, + * @return Response + */ + public function post($uri, array $options = []) { + $response = $this->client->post($uri, $options); + return new Response($response); + } + + /** + * Sends a PUT request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * 'timeout' => 5, + * @return Response + */ + public function put($uri, array $options = []) { + $response = $this->client->put($uri, $options); + return new Response($response); + } + + /** + * Sends a DELETE request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * 'timeout' => 5, + * @return Response + */ + public function delete($uri, array $options = []) { + $response = $this->client->delete($uri, $options); + return new Response($response); + } + + + /** + * Sends a options request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * 'timeout' => 5, + * @return Response + */ + public function options($uri, array $options = []) { + $response = $this->client->options($uri, $options); + return new Response($response); + } +} diff --git a/lib/private/http/client/clientservice.php b/lib/private/http/client/clientservice.php new file mode 100644 index 00000000000..795d508e5f9 --- /dev/null +++ b/lib/private/http/client/clientservice.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Http\Client; + +use GuzzleHttp\Client as GuzzleClient; +use OCP\Http\Client\IClientService; +use OCP\ICertificateManager; +use OCP\IConfig; + +/** + * Class ClientService + * + * @package OC\Http + */ +class ClientService implements IClientService { + /** @var IConfig */ + private $config; + /** @var ICertificateManager */ + private $certificateManager; + + /** + * @param IConfig $config + * @param ICertificateManager $certificateManager + */ + public function __construct(IConfig $config, + ICertificateManager $certificateManager) { + $this->config = $config; + $this->certificateManager = $certificateManager; + } + + /** + * @return Client + */ + public function newClient() { + return new Client($this->config, $this->certificateManager, new GuzzleClient()); + } +} diff --git a/lib/private/http/client/response.php b/lib/private/http/client/response.php new file mode 100644 index 00000000000..54b7a93543c --- /dev/null +++ b/lib/private/http/client/response.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Http\Client; + +use OCP\Http\Client\IResponse; +use GuzzleHttp\Message\Response as GuzzleResponse; + +/** + * Class Response + * + * @package OC\Http + */ +class Response implements IResponse { + /** @var GuzzleResponse */ + private $response; + + /** + * @param GuzzleResponse $response + */ + public function __construct(GuzzleResponse $response) { + $this->response = $response; + } + + /** + * @return string + */ + public function getBody() { + return $this->response->getBody()->getContents(); + } + + /** + * @return int + */ + public function getStatusCode() { + return $this->response->getStatusCode(); + } + + /** + * @param $key + * @return string + */ + public function getHeader($key) { + return $this->response->getHeader($key); + } + + /** + * @return array + */ + public function getHeaders() { + return $this->response->getHeaders(); + } +} diff --git a/lib/private/httphelper.php b/lib/private/httphelper.php index 6bb8e1d3ec0..16b824e927f 100644 --- a/lib/private/httphelper.php +++ b/lib/private/httphelper.php @@ -1,6 +1,6 @@ <?php /** - * Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> + * Copyright (c) 2014-2015 Lukas Reschke <lukas@owncloud.com> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -8,41 +8,31 @@ namespace OC; +use OCP\Http\Client\IClientService; use OCP\IConfig; -use OCP\ICertificateManager; +/** + * Class HTTPHelper + * + * @package OC + * @deprecated Use \OCP\Http\Client\IClientService + */ class HTTPHelper { const USER_AGENT = 'ownCloud Server Crawler'; /** @var \OCP\IConfig */ private $config; - - /** @var \OC\Security\CertificateManager */ - private $certificateManager; + /** @var IClientService */ + private $clientService; /** - * @param \OCP\IConfig $config + * @param IConfig $config + * @param IClientService $clientService */ - public function __construct(IConfig $config, ICertificateManager $certificateManager) { + public function __construct(IConfig $config, + IClientService $clientService) { $this->config = $config; - $this->certificateManager = $certificateManager; - } - - /** - * Returns the default context array - * @return array - */ - public function getDefaultContextArray() { - return array( - 'http' => array( - 'header' => 'User-Agent: ' . self::USER_AGENT . "\r\n", - 'timeout' => 10, - 'follow_location' => false, // Do not follow the location since we can't limit the protocol - ), - 'ssl' => array( - 'disable_compression' => true - ) - ); + $this->clientService = $clientService; } /** @@ -52,87 +42,28 @@ class HTTPHelper { * @return string of the response or false on error * This function get the content of a page via curl, if curl is enabled. * If not, file_get_contents is used. + * @deprecated Use \OCP\Http\Client\IClientService */ public function getUrlContent($url) { - if (!$this->isHTTPURL($url)) { - throw new \Exception('$url must start with https:// or http://', 1); - } - - $proxy = $this->config->getSystemValue('proxy', null); - $proxyUserPwd = $this->config->getSystemValue('proxyuserpwd', null); - $curl = curl_init(); - $max_redirects = 10; - - curl_setopt($curl, CURLOPT_HEADER, 0); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); - curl_setopt($curl, CURLOPT_URL, $url); - curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); - curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); - - curl_setopt($curl, CURLOPT_USERAGENT, self::USER_AGENT); - if ($proxy !== null) { - curl_setopt($curl, CURLOPT_PROXY, $proxy); - } - if ($proxyUserPwd !== null) { - curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyUserPwd); - } - - if (ini_get('open_basedir') === '') { - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($curl, CURLOPT_MAXREDIRS, $max_redirects); - $data = curl_exec($curl); - } else { - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); - $mr = $max_redirects; - if ($mr > 0) { - $newURL = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); - $rCurl = curl_copy_handle($curl); - curl_setopt($rCurl, CURLOPT_HEADER, true); - curl_setopt($rCurl, CURLOPT_NOBODY, true); - curl_setopt($rCurl, CURLOPT_FORBID_REUSE, false); - curl_setopt($rCurl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($rCurl, CURLOPT_USERAGENT, self::USER_AGENT); - do { - curl_setopt($rCurl, CURLOPT_URL, $newURL); - $header = curl_exec($rCurl); - if (curl_errno($rCurl)) { - $code = 0; - } else { - $code = curl_getinfo($rCurl, CURLINFO_HTTP_CODE); - if ($code == 301 || $code == 302) { - preg_match('/Location:(.*?)\n/', $header, $matches); - $newURL = trim(array_pop($matches)); - } else { - $code = 0; - } - } - } while ($code && --$mr); - curl_close($rCurl); - if ($mr > 0) { - curl_setopt($curl, CURLOPT_URL, $newURL); - } - } - - if ($mr == 0 && $max_redirects > 0) { - $data = false; - } else { - $data = curl_exec($curl); - } + try { + $client = $this->clientService->newClient(); + $response = $client->get($url); + return $response->getBody(); + } catch (\Exception $e) { + return false; } - curl_close($curl); - - return $data; } /** * Returns the response headers of a HTTP URL without following redirects * @param string $location Needs to be a HTTPS or HTTP URL * @return array + * @deprecated Use \OCP\Http\Client\IClientService */ public function getHeaders($location) { - stream_context_set_default($this->getDefaultContextArray()); - return get_headers($location, 1); + $client = $this->clientService->newClient(); + $response = $client->get($location); + return $response->getHeaders(); } /** @@ -145,50 +76,23 @@ class HTTPHelper { } /** - * create string of parameters for post request - * - * @param array $parameters - * @return string - */ - private function assemblePostParameters(array $parameters) { - $parameterString = ''; - foreach ($parameters as $key => $value) { - $parameterString .= $key . '=' . urlencode($value) . '&'; - } - - return rtrim($parameterString, '&'); - } - - /** * send http post request * * @param string $url * @param array $fields data send by the request - * @return bool + * @return array + * @deprecated Use \OCP\Http\Client\IClientService */ public function post($url, array $fields) { + $client = $this->clientService->newClient(); - $fieldsString = $this->assemblePostParameters($fields); - - $certBundle = $this->certificateManager->getCertificateBundle(); - - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_POST, count($fields)); - curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$fieldsString); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); - if (is_readable($certBundle)) { - curl_setopt($ch, CURLOPT_CAINFO, $certBundle); + try { + $response = $client->post($url, ['body' => $fields]); + } catch (\Exception $e) { + return ['success' => false, 'result' => $e->getMessage()]; } - $result = curl_exec($ch); - $success = $result ? true : false; - - curl_close($ch); - - return array('success' => $success, 'result' => $result); + return ['success' => true, 'result' => $response->getBody()]; } } diff --git a/lib/private/installer.php b/lib/private/installer.php index 3956e503767..3af8fcf3b23 100644 --- a/lib/private/installer.php +++ b/lib/private/installer.php @@ -244,8 +244,9 @@ class OC_Installer{ if(!isset($data['href'])) { throw new \Exception($l->t("No href specified when installing app from http")); } - file_put_contents($path, \OC_Util::getUrlContent($data['href'])); - }else{ + $client = \OC::$server->getHTTPClientService()->newClient(); + $client->get($data['href'], ['save_to' => $path]); + } else { if(!isset($data['path'])) { throw new \Exception($l->t("No path specified when installing app from local file")); } diff --git a/lib/private/ocsclient.php b/lib/private/ocsclient.php index f27ab487efc..1e09d409297 100644 --- a/lib/private/ocsclient.php +++ b/lib/private/ocsclient.php @@ -67,16 +67,24 @@ class OCSClient { return null; } $url = self::getAppStoreURL() . '/content/categories'; - $xml = \OC::$server->getHTTPHelper()->getUrlContent($url); - if ($xml == false) { + + $client = \OC::$server->getHTTPClientService()->newClient(); + try { + $response = $client->get($url, ['timeout' => 5]); + } catch(\Exception $e) { + return null; + } + + if($response->getStatusCode() !== 200) { return null; } + $loadEntities = libxml_disable_entity_loader(true); - $data = simplexml_load_string($xml); + $data = simplexml_load_string($response->getBody()); libxml_disable_entity_loader($loadEntities); $tmp = $data->data; - $cats = array(); + $cats = []; foreach ($tmp->category as $value) { @@ -114,14 +122,21 @@ class OCSClient { $filterUrl = '&filter=' . urlencode($filter); $url = self::getAppStoreURL() . '/content/data?categories=' . urlencode($categoriesString) . '&sortmode=new&page=' . urlencode($page) . '&pagesize=100' . $filterUrl . $version; - $apps = array(); - $xml = \OC::$server->getHTTPHelper()->getUrlContent($url); + $apps = []; + + $client = \OC::$server->getHTTPClientService()->newClient(); + try { + $response = $client->get($url, ['timeout' => 5]); + } catch(\Exception $e) { + return null; + } - if ($xml == false) { + if($response->getStatusCode() !== 200) { return null; } + $loadEntities = libxml_disable_entity_loader(true); - $data = simplexml_load_string($xml); + $data = simplexml_load_string($response->getBody()); libxml_disable_entity_loader($loadEntities); $tmp = $data->data->content; @@ -163,14 +178,19 @@ class OCSClient { return null; } $url = self::getAppStoreURL() . '/content/data/' . urlencode($id); - $xml = \OC::$server->getHTTPHelper()->getUrlContent($url); + $client = \OC::$server->getHTTPClientService()->newClient(); + try { + $response = $client->get($url, ['timeout' => 5]); + } catch(\Exception $e) { + return null; + } - if ($xml == false) { - \OC_Log::write('core', 'Unable to parse OCS content for app ' . $id, \OC_Log::FATAL); + if($response->getStatusCode() !== 200) { return null; } + $loadEntities = libxml_disable_entity_loader(true); - $data = simplexml_load_string($xml); + $data = simplexml_load_string($response->getBody()); libxml_disable_entity_loader($loadEntities); $tmp = $data->data->content; @@ -178,7 +198,7 @@ class OCSClient { \OC_Log::write('core', 'Invalid OCS content returned for app ' . $id, \OC_Log::FATAL); return null; } - $app = array(); + $app = []; $app['id'] = $tmp->id; $app['name'] = $tmp->name; $app['version'] = $tmp->version; @@ -212,14 +232,19 @@ class OCSClient { return null; } $url = self::getAppStoreURL() . '/content/download/' . urlencode($id) . '/' . urlencode($item); - $xml = \OC::$server->getHTTPHelper()->getUrlContent($url); + $client = \OC::$server->getHTTPClientService()->newClient(); + try { + $response = $client->get($url, ['timeout' => 5]); + } catch(\Exception $e) { + return null; + } - if ($xml == false) { - \OC_Log::write('core', 'Unable to parse OCS content', \OC_Log::FATAL); + if($response->getStatusCode() !== 200) { return null; } + $loadEntities = libxml_disable_entity_loader(true); - $data = simplexml_load_string($xml); + $data = simplexml_load_string($response->getBody()); libxml_disable_entity_loader($loadEntities); $tmp = $data->data->content; diff --git a/lib/private/security/certificatemanager.php b/lib/private/security/certificatemanager.php index 7bc83766365..d3a6dcd71eb 100644 --- a/lib/private/security/certificatemanager.php +++ b/lib/private/security/certificatemanager.php @@ -63,11 +63,13 @@ class CertificateManager implements ICertificateManager { /** * create the certificate bundle of all trusted certificated */ - protected function createCertificateBundle() { + public function createCertificateBundle() { $path = $this->getPathToCertificates(); $certs = $this->listCertificates(); $fh_certs = $this->view->fopen($path . '/rootcerts.crt', 'w'); + + // Write user certificates foreach ($certs as $cert) { $file = $path . '/uploads/' . $cert->getName(); $data = $this->view->file_get_contents($file); @@ -77,6 +79,9 @@ class CertificateManager implements ICertificateManager { } } + // Append the default certificates + $defaultCertificates = file_get_contents(\OC::$SERVERROOT . '/config/ca-bundle.crt'); + fwrite($fh_certs, $defaultCertificates); fclose($fh_certs); } @@ -137,6 +142,9 @@ class CertificateManager implements ICertificateManager { return $this->getPathToCertificates() . 'rootcerts.crt'; } + /** + * @return string + */ private function getPathToCertificates() { $path = is_null($this->uid) ? '/files_external/' : '/' . $this->uid . '/files_external/'; diff --git a/lib/private/server.php b/lib/private/server.php index fd7a2bea2d1..1f275d658bf 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -13,6 +13,7 @@ use OC\Diagnostics\EventLogger; use OC\Diagnostics\QueryLogger; use OC\Mail\Mailer; use OC\Memcache\ArrayCache; +use OC\Http\Client\ClientService; use OC\Security\CertificateManager; use OC\Files\Node\Root; use OC\Files\View; @@ -236,9 +237,18 @@ class Server extends SimpleContainer implements IServerContainer { }); $this->registerService('HTTPHelper', function (Server $c) { $config = $c->getConfig(); - $user = $c->getUserSession()->getUser(); - $uid = $user ? $user->getUID() : null; - return new HTTPHelper($config, new \OC\Security\CertificateManager($uid, new \OC\Files\View())); + return new HTTPHelper( + $config, + $c->getHTTPClientService() + ); + }); + $this->registerService('HttpClientService', function (Server $c) { + $user = \OC_User::getUser(); + $uid = $user ? $user : null; + return new ClientService( + $c->getConfig(), + new \OC\Security\CertificateManager($uid, new \OC\Files\View()) + ); }); $this->registerService('EventLogger', function (Server $c) { if (defined('DEBUG') and DEBUG) { @@ -664,7 +674,7 @@ class Server extends SimpleContainer implements IServerContainer { /** * Returns an instance of the HTTP helper class - * + * @deprecated Use getHTTPClientService() * @return \OC\HTTPHelper */ function getHTTPHelper() { @@ -690,6 +700,15 @@ class Server extends SimpleContainer implements IServerContainer { } /** + * Returns an instance of the HTTP client service + * + * @return \OCP\Http\Client\IClientService + */ + function getHTTPClientService() { + return $this->query('HttpClientService'); + } + + /** * Create a new event source * * @return \OCP\IEventSource diff --git a/lib/private/util.php b/lib/private/util.php index a048996da6e..921bfd8067e 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -1193,33 +1193,21 @@ class OC_Util { /** * Check if the ownCloud server can connect to the internet * + * @param \OCP\Http\Client\IClientService $clientService * @return bool */ - public static function isInternetConnectionWorking() { + public static function isInternetConnectionWorking(\OCP\Http\Client\IClientService $clientService) { // in case there is no internet connection on purpose return false if (self::isInternetConnectionEnabled() === false) { return false; } - // in case the connection is via proxy return true to avoid connecting to owncloud.org - if (OC_Config::getValue('proxy', '') != '') { - return true; - } - - // try to connect to owncloud.org to see if http connections to the internet are possible. - $connected = @fsockopen("www.owncloud.org", 80); - if ($connected) { - fclose($connected); - return true; - } else { - // second try in case one server is down - $connected = @fsockopen("apps.owncloud.com", 80); - if ($connected) { - fclose($connected); - return true; - } else { - return false; - } + try { + $client = $clientService->newClient(); + $response = $client->get('https://www.owncloud.org/'); + return $response->getStatusCode() === 200; + } catch (\Exception $e) { + return false; } } diff --git a/lib/public/http/client/iclient.php b/lib/public/http/client/iclient.php new file mode 100644 index 00000000000..2946bcfa18d --- /dev/null +++ b/lib/public/http/client/iclient.php @@ -0,0 +1,181 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP\Http\Client; + +/** + * Interface IClient + * + * @package OCP\Http + */ +interface IClient { + + /** + * Sends a GET request + * @param string $uri + * @param array $options Array such as + * 'query' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * @return IResponse + * @throws \Exception If the request could not get completed + */ + public function get($uri, array $options = []); + + /** + * Sends a HEAD request + * @param string $uri + * @param array $options Array such as + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * @return IResponse + */ + public function head($uri, $options = []); + + /** + * Sends a POST request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * @return IResponse + */ + public function post($uri, array $options = []); + + /** + * Sends a PUT request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * @return IResponse + */ + public function put($uri, array $options = []); + + /** + * Sends a DELETE request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * @return IResponse + */ + public function delete($uri, array $options = []); + + /** + * Sends a options request + * @param string $uri + * @param array $options Array such as + * 'body' => [ + * 'field' => 'abc', + * 'other_field' => '123', + * 'file_name' => fopen('/path/to/file', 'r'), + * ], + * 'headers' => [ + * 'foo' => 'bar', + * ], + * 'cookies' => [' + * 'foo' => 'bar', + * ], + * 'allow_redirects' => [ + * 'max' => 10, // allow at most 10 redirects. + * 'strict' => true, // use "strict" RFC compliant redirects. + * 'referer' => true, // add a Referer header + * 'protocols' => ['https'] // only allow https URLs + * ], + * 'save_to' => '/path/to/file', // save to a file or a stream + * 'verify' => true, // bool or string to CA file + * 'debug' => true, + * @return IResponse + */ + public function options($uri, array $options = []); +} diff --git a/lib/public/http/client/iclientservice.php b/lib/public/http/client/iclientservice.php new file mode 100644 index 00000000000..4dc65f1721e --- /dev/null +++ b/lib/public/http/client/iclientservice.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP\Http\Client; + +/** + * Interface IClientService + * + * @package OCP\Http + */ +interface IClientService { + /** + * @return IClient + */ + public function newClient(); +} diff --git a/lib/public/http/client/iresponse.php b/lib/public/http/client/iresponse.php new file mode 100644 index 00000000000..5355046a2a7 --- /dev/null +++ b/lib/public/http/client/iresponse.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP\Http\Client; + +/** + * Interface IResponse + * + * @package OCP\Http + */ +interface IResponse { + /** + * @return string + */ + public function getBody(); + + /** + * @return int + */ + public function getStatusCode(); + + /** + * @param $key + * @return string + */ + public function getHeader($key); + + /** + * @return array + */ + public function getHeaders(); +} diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 20345e61212..a01ae5e200d 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -267,10 +267,18 @@ interface IServerContainer { /** * Returns an instance of the HTTP helper class * @return \OC\HTTPHelper + * @deprecated Use \OCP\Http\Client\IClientService */ function getHTTPHelper(); /** + * Returns an instance of the HTTP client service + * + * @return \OCP\Http\Client\IClientService + */ + function getHTTPClientService(); + + /** * Get the active event logger * * @return \OCP\Diagnostics\IEventLogger diff --git a/lib/repair/updatecertificatestore.php b/lib/repair/updatecertificatestore.php new file mode 100644 index 00000000000..e1f6be45ef9 --- /dev/null +++ b/lib/repair/updatecertificatestore.php @@ -0,0 +1,77 @@ +<?php +/** + * @author Lukas Reschke + * @copyright 2015 Lukas Reschke lukas@owncloud.com + * + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Repair; + +use OC\Files\View; +use OC\Hooks\BasicEmitter; +use OC\RepairStep; +use OC\Server; +use OCP\IConfig; + +/** + * Class UpdateCertificateStore rewrites the user specific certificate store after + * an update has been performed. This is done because a new root certificate file + * might have been added. + * + * @package OC\Repair + */ +class UpdateCertificateStore extends BasicEmitter implements RepairStep { + /** + * FIXME: The certificate manager does only allow specifying the user + * within the constructor. This makes DI impossible. + * @var Server + */ + protected $server; + /** @var IConfig */ + protected $config; + + /** + * @param Server $server + * @param IConfig $config + */ + public function __construct(Server $server, + IConfig $config) { + $this->server = $server; + $this->config = $config; + } + + /** {@inheritDoc} */ + public function getName() { + return 'Update user certificate stores with new root certificates'; + } + + /** {@inheritDoc} */ + public function run() { + $rootView = new View(); + $dataDirectory = $this->config->getSystemValue('datadirectory', null); + if(is_null($dataDirectory)) { + throw new \Exception('No data directory specified'); + } + + $pathToRootCerts = '/files_external/rootcerts.crt'; + + foreach($rootView->getDirectoryContent('', 'httpd/unix-directory') as $fileInfo) { + $uid = trim($fileInfo->getPath(), '/'); + if($rootView->file_exists($uid . $pathToRootCerts)) { + // Delete the existing root certificate + $rootView->unlink($uid . $pathToRootCerts); + + /** + * FIXME: The certificate manager does only allow specifying the user + * within the constructor. This makes DI impossible. + */ + // Regenerate the certificates + $certificateManager = $this->server->getCertificateManager($uid); + $certificateManager->createCertificateBundle(); + } + } + } +} |