3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
29 * This class handles HTTP downloads
31 * FIXME: fetch() and get() report errors differently -- e.g.
32 * fetch() returns fatal and get() returns an error code. Should
33 * refactor both (or get a third-party HTTP library) but don't
34 * want to deal with that so late in the 4.3 dev cycle.
37 * @copyright CiviCRM LLC (c) 2004-2013
41 class CRM_Utils_HttpClient
{
43 const STATUS_OK
= 'ok';
44 const STATUS_WRITE_ERROR
= 'write-error';
45 const STATUS_DL_ERROR
= 'dl-error';
48 * @var CRM_Utils_HttpClient
50 protected static $singleton;
53 * @var int|NULL seconds; or NULL to use system default
55 protected $connectionTimeout;
57 public static function singleton() {
58 if (!self
::$singleton) {
59 self
::$singleton = new CRM_Utils_HttpClient();
61 return self
::$singleton;
64 public function __construct($connectionTimeout = NULL) {
65 $this->connectionTimeout
= $connectionTimeout;
69 * Download the remote zipfile.
71 * @param string $remoteFile URL of a .zip file
72 * @param string $localFile path at which to store the .zip file
73 * @return STATUS_OK|STATUS_WRITE_ERROR|STATUS_DL_ERROR
75 public function fetch($remoteFile, $localFile) {
76 // Download extension zip file ...
77 if (!function_exists('curl_init')) {
78 CRM_Core_Error
::fatal('Cannot install this extension - curl is not installed!');
81 list($ch, $caConfig) = $this->createCurl($remoteFile);
82 if (preg_match('/^https:/', $remoteFile) && !$caConfig->isEnableSSL()) {
83 CRM_Core_Error
::fatal('Cannot install this extension - does not support SSL');
86 $fp = @fopen
($localFile, "w");
88 CRM_Core_Session
::setStatus(ts('Unable to write to %1.<br />Is the location writable?', array(1 => $localFile)), ts('Write Error'), 'error');
89 return self
::STATUS_WRITE_ERROR
;
91 curl_setopt($ch, CURLOPT_FILE
, $fp);
94 if (curl_errno($ch)) {
95 CRM_Core_Session
::setStatus(ts('Unable to download extension from %1. Error Message: %2',
96 array(1 => $remoteFile, 2 => curl_error($ch))), ts('Download Error'), 'error');
97 return self
::STATUS_DL_ERROR
;
105 return self
::STATUS_OK
;
109 * Send an HTTP GET for a remote resource
111 * @param string $remoteFile URL of a .zip file
112 * @param string $localFile path at which to store the .zip file
113 * @return array array(0 => STATUS_OK|STATUS_DL_ERROR, 1 => string)
115 public function get($remoteFile) {
116 // Download extension zip file ...
117 if (!function_exists('curl_init')) {
118 //CRM_Core_Error::fatal('Cannot install this extension - curl is not installed!');
119 return array(self
::STATUS_DL_ERROR
, NULL);
122 list($ch, $caConfig) = $this->createCurl($remoteFile);
124 if (preg_match('/^https:/', $remoteFile) && !$caConfig->isEnableSSL()) {
125 //CRM_Core_Error::fatal('Cannot install this extension - does not support SSL');
126 return array(self
::STATUS_DL_ERROR
, NULL);
129 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, 1);
130 $data = curl_exec($ch);
131 if (curl_errno($ch)) {
132 return array(self
::STATUS_DL_ERROR
, $data);
138 return array(self
::STATUS_OK
, $data);
142 * Send an HTTP POST for a remote resource
144 * @param string $remoteFile URL of a .zip file
145 * @param string $localFile path at which to store the .zip file
146 * @return array array(0 => STATUS_OK|STATUS_DL_ERROR, 1 => string)
148 public function post($remoteFile, $params) {
149 // Download extension zip file ...
150 if (!function_exists('curl_init')) {
151 //CRM_Core_Error::fatal('Cannot install this extension - curl is not installed!');
152 return array(self
::STATUS_DL_ERROR
, NULL);
155 list($ch, $caConfig) = $this->createCurl($remoteFile);
157 if (preg_match('/^https:/', $remoteFile) && !$caConfig->isEnableSSL()) {
158 //CRM_Core_Error::fatal('Cannot install this extension - does not support SSL');
159 return array(self
::STATUS_DL_ERROR
, NULL);
162 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, 1);
163 curl_setopt($ch, CURLOPT_POST
, true);
164 curl_setopt($ch, CURLOPT_POST
,count($params));
165 curl_setopt($ch, CURLOPT_POSTFIELDS
,$params);
166 $data = curl_exec($ch);
167 if (curl_errno($ch)) {
168 return array(self
::STATUS_DL_ERROR
, $data);
174 return array(self
::STATUS_OK
, $data);
178 * @param string $remoteFile
179 * @return array (0 => resource, 1 => CA_Config_Curl)
181 protected function createCurl($remoteFile) {
182 require_once 'CA/Config/Curl.php';
183 $caConfig = CA_Config_Curl
::probe(array(
184 'verify_peer' => (bool) CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
, 'verifySSL', NULL, TRUE)
188 curl_setopt($ch, CURLOPT_URL
, $remoteFile);
189 curl_setopt($ch, CURLOPT_HEADER
, FALSE);
190 curl_setopt($ch, CURLOPT_ENCODING
, 'gzip');
191 curl_setopt($ch, CURLOPT_VERBOSE
, 0);
192 curl_setopt($ch, CURLOPT_FOLLOWLOCATION
, TRUE);
193 if ($this->connectionTimeout
!== NULL) {
194 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT
, $this->connectionTimeout
);
196 if (preg_match('/^https:/', $remoteFile) && $caConfig->isEnableSSL()) {
197 curl_setopt_array($ch, $caConfig->toCurlOptions());
200 return array($ch, $caConfig);