CRM_Utils_HttpClient - Add get() method
[civicrm-core.git] / CRM / Utils / HttpClient.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * This class handles downloads of remotely-provided extensions
30 *
31 * @package CRM
32 * @copyright CiviCRM LLC (c) 2004-2013
33 * $Id$
34 *
35 */
36 class CRM_Utils_HttpClient {
37
38 const STATUS_OK = 'ok';
39 const STATUS_WRITE_ERROR = 'write-error';
40 const STATUS_DL_ERROR = 'dl-error';
41
42 /**
43 * @var CRM_Utils_HttpClient
44 */
45 protected static $singleton;
46
47 /**
48 * @var int
49 */
50 protected $timeout;
51
52 public static function singleton() {
53 if (!self::$singleton) {
54 self::$singleton = new CRM_Utils_HttpClient();
55 }
56 return self::$singleton;
57 }
58
59 public function __construct($timeout = 10) {
60 $this->timeout = $timeout;
61 }
62
63 /**
64 * Download the remote zipfile.
65 *
66 * @param string $remoteFile URL of a .zip file
67 * @param string $localFile path at which to store the .zip file
68 * @return STATUS_OK|STATUS_WRITE_ERROR|STATUS_DL_ERROR
69 */
70 public function fetch($remoteFile, $localFile) {
71 require_once 'CA/Config/Curl.php';
72 $caConfig = CA_Config_Curl::probe(array(
73 'verify_peer' => (bool) CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL', NULL, TRUE)
74 ));
75
76 // Download extension zip file ...
77 if (!function_exists('curl_init')) {
78 CRM_Core_Error::fatal('Cannot install this extension - curl is not installed!');
79 }
80 if (preg_match('/^https:/', $remoteFile) && !$caConfig->isEnableSSL()) {
81 CRM_Core_Error::fatal('Cannot install this extension - does not support SSL');
82 }
83
84 //setting the curl parameters.
85 $ch = curl_init();
86 curl_setopt($ch, CURLOPT_URL, $remoteFile);
87 curl_setopt($ch, CURLOPT_HEADER, FALSE);
88 curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
89 curl_setopt($ch, CURLOPT_VERBOSE, 0);
90 if (preg_match('/^https:/', $remoteFile)) {
91 curl_setopt_array($ch, $caConfig->toCurlOptions());
92 }
93
94 //follow redirects
95 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
96
97 $fp = @fopen($localFile, "w");
98 if (!$fp) {
99 CRM_Core_Session::setStatus(ts('Unable to write to %1.<br />Is the location writable?', array(1 => $localFile)), ts('Write Error'), 'error');
100 return self::STATUS_WRITE_ERROR;
101 }
102 curl_setopt($ch, CURLOPT_FILE, $fp);
103
104 curl_exec($ch);
105 if (curl_errno($ch)) {
106 CRM_Core_Session::setStatus(ts('Unable to download extension from %1. Error Message: %2',
107 array(1 => $remoteFile, 2 => curl_error($ch))), ts('Download Error'), 'error');
108 return self::STATUS_DL_ERROR;
109 }
110 else {
111 curl_close($ch);
112 }
113
114 fclose($fp);
115
116 return self::STATUS_OK;
117 }
118
119 /**
120 * Send an HTTP GET for a remote resource
121 *
122 * @param string $remoteFile URL of a .zip file
123 * @param string $localFile path at which to store the .zip file
124 * @return array array(0 => STATUS_OK|STATUS_DL_ERROR, 1 => string)
125 */
126 public function get($remoteFile) {
127 /* This untested implementation should work on more sites because it doesn't
128 use curl, but file_get_contents() seems to handle gzipped replies badly
129
130 require_once 'CA/Config/Stream.php';
131 $caConfig = CA_Config_Stream::probe(array(
132 'verify_peer' => (bool) CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL', NULL, TRUE)
133 ));
134
135 $ctxParams = array(); // HTTP stream context options
136
137 if (preg_match('/^https:/', $remoteFile)) {
138 if ($caConfig->isEnableSSL()) {
139 $ctxParams['ssl'] = $caConfig->toStreamOptions();
140 }
141 else {
142 return array(self::STATUS_DL_ERROR, NULL);
143 }
144 }
145
146 ini_set('default_socket_timeout', $this->timeout);
147 $ctx = stream_context_create($ctxParams);
148 $data = @file_get_contents($remoteFile, FALSE, $ctx);
149 ini_restore('default_socket_timeout');
150
151 $status = !empty($data) ? self::STATUS_OK : self::STATUS_DL_ERROR; // TODO something better
152 return array($status, $data);
153 */
154
155 require_once 'CA/Config/Curl.php';
156 $caConfig = CA_Config_Curl::probe(array(
157 'verify_peer' => (bool) CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'verifySSL', NULL, TRUE)
158 ));
159
160 // Download extension zip file ...
161 if (!function_exists('curl_init')) {
162 //CRM_Core_Error::fatal('Cannot install this extension - curl is not installed!');
163 return array(self::STATUS_DL_ERROR, NULL);
164 }
165 if (preg_match('/^https:/', $remoteFile) && !$caConfig->isEnableSSL()) {
166 //CRM_Core_Error::fatal('Cannot install this extension - does not support SSL');
167 return array(self::STATUS_DL_ERROR, NULL);
168 }
169
170 //setting the curl parameters.
171 $ch = curl_init();
172 curl_setopt($ch, CURLOPT_URL, $remoteFile);
173 curl_setopt($ch, CURLOPT_HEADER, FALSE);
174 curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
175 curl_setopt($ch, CURLOPT_VERBOSE, 0);
176 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
177 if (preg_match('/^https:/', $remoteFile)) {
178 curl_setopt_array($ch, $caConfig->toCurlOptions());
179 }
180
181 //follow redirects
182 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
183
184 $data = curl_exec($ch);
185 if (curl_errno($ch)) {
186 CRM_Core_Session::setStatus(ts('Unable to download extension from %1. Error Message: %2',
187 array(1 => $remoteFile, 2 => curl_error($ch))), ts('Download Error'), 'error');
188 return array(self::STATUS_DL_ERROR. $data);
189 }
190 else {
191 curl_close($ch);
192 }
193
194 return array(self::STATUS_OK, $data);
195
196 }
197
198 }