From afcc9be06efa7194963a54898ea637fd837c017b Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Fri, 29 Mar 2013 17:38:47 -0400 Subject: [PATCH] CRM_Utils_HttpClient - Add get() method --- CRM/Utils/HttpClient.php | 89 ++++++++++++++++++++++ tests/phpunit/CRM/Utils/HttpClientTest.php | 30 ++++++++ 2 files changed, 119 insertions(+) diff --git a/CRM/Utils/HttpClient.php b/CRM/Utils/HttpClient.php index e76d563913..13b8a1b262 100644 --- a/CRM/Utils/HttpClient.php +++ b/CRM/Utils/HttpClient.php @@ -44,6 +44,11 @@ class CRM_Utils_HttpClient { */ protected static $singleton; + /** + * @var int + */ + protected $timeout; + public static function singleton() { if (!self::$singleton) { self::$singleton = new CRM_Utils_HttpClient(); @@ -51,6 +56,10 @@ class CRM_Utils_HttpClient { return self::$singleton; } + public function __construct($timeout = 10) { + $this->timeout = $timeout; + } + /** * Download the remote zipfile. * @@ -106,4 +115,84 @@ class CRM_Utils_HttpClient { return self::STATUS_OK; } + + /** + * Send an HTTP GET for a remote resource + * + * @param string $remoteFile URL of a .zip file + * @param string $localFile path at which to store the .zip file + * @return array array(0 => STATUS_OK|STATUS_DL_ERROR, 1 => string) + */ + public function get($remoteFile) { + /* This untested implementation should work on more sites because it doesn't + use curl, but file_get_contents() seems to handle gzipped replies badly + + require_once 'CA/Config/Stream.php'; + $caConfig = CA_Config_Stream::probe(array( + 'verify_peer' => (bool) CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL', NULL, TRUE) + )); + + $ctxParams = array(); // HTTP stream context options + + if (preg_match('/^https:/', $remoteFile)) { + if ($caConfig->isEnableSSL()) { + $ctxParams['ssl'] = $caConfig->toStreamOptions(); + } + else { + return array(self::STATUS_DL_ERROR, NULL); + } + } + + ini_set('default_socket_timeout', $this->timeout); + $ctx = stream_context_create($ctxParams); + $data = @file_get_contents($remoteFile, FALSE, $ctx); + ini_restore('default_socket_timeout'); + + $status = !empty($data) ? self::STATUS_OK : self::STATUS_DL_ERROR; // TODO something better + return array($status, $data); + */ + + require_once 'CA/Config/Curl.php'; + $caConfig = CA_Config_Curl::probe(array( + 'verify_peer' => (bool) CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL', NULL, TRUE) + )); + + // Download extension zip file ... + if (!function_exists('curl_init')) { + //CRM_Core_Error::fatal('Cannot install this extension - curl is not installed!'); + return array(self::STATUS_DL_ERROR, NULL); + } + if (preg_match('/^https:/', $remoteFile) && !$caConfig->isEnableSSL()) { + //CRM_Core_Error::fatal('Cannot install this extension - does not support SSL'); + return array(self::STATUS_DL_ERROR, NULL); + } + + //setting the curl parameters. + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $remoteFile); + curl_setopt($ch, CURLOPT_HEADER, FALSE); + curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); + curl_setopt($ch, CURLOPT_VERBOSE, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + if (preg_match('/^https:/', $remoteFile)) { + curl_setopt_array($ch, $caConfig->toCurlOptions()); + } + + //follow redirects + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); + + $data = curl_exec($ch); + if (curl_errno($ch)) { + CRM_Core_Session::setStatus(ts('Unable to download extension from %1. Error Message: %2', + array(1 => $remoteFile, 2 => curl_error($ch))), ts('Download Error'), 'error'); + return array(self::STATUS_DL_ERROR. $data); + } + else { + curl_close($ch); + } + + return array(self::STATUS_OK, $data); + + } + } diff --git a/tests/phpunit/CRM/Utils/HttpClientTest.php b/tests/phpunit/CRM/Utils/HttpClientTest.php index c698fbb3ca..ffa94a1411 100644 --- a/tests/phpunit/CRM/Utils/HttpClientTest.php +++ b/tests/phpunit/CRM/Utils/HttpClientTest.php @@ -73,4 +73,34 @@ class CRM_Utils_HttpClientTest extends CiviUnitTestCase { $this->assertEquals(CRM_Utils_HttpClient::STATUS_WRITE_ERROR, $result); } + function testGetHttp() { + list($status, $data) = $this->client->get(self::VALID_HTTP_URL); + $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status); + $this->assertRegExp(self::VALID_HTTP_REGEX, $data); + } + + function testGetHttps_valid() { + list($status, $data) = $this->client->get(self::VALID_HTTPS_URL); + $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status); + $this->assertRegExp(self::VALID_HTTPS_REGEX, $data); + } + + function testGetHttps_invalid_verify() { + list($status, $data) = $this->client->get(self::SELF_SIGNED_HTTPS_URL); + $this->assertEquals(CRM_Utils_HttpClient::STATUS_DL_ERROR, $status); + $this->assertEquals('', $data); + } + + function testGetHttps_invalid_noVerify() { + $result = civicrm_api('Setting', 'create', array( + 'version' => 3, + 'verifySSL' => FALSE, + )); + $this->assertAPISuccess($result); + + list($status, $data) = $this->client->get(self::SELF_SIGNED_HTTPS_URL); + $this->assertEquals(CRM_Utils_HttpClient::STATUS_OK, $status); + $this->assertRegExp(self::SELF_SIGNED_HTTPS_REGEX, $data); + } + } -- 2.25.1