]> git.mxchange.org Git - friendica.git/blob - src/Network/CurlResult.php
Move all warning text in L10n + frio: make warning closable
[friendica.git] / src / Network / CurlResult.php
1 <?php
2
3 namespace Friendica\Network;
4
5 use Friendica\Core\Logger;
6 use Friendica\Network\HTTPException\InternalServerErrorException;
7
8 /**
9  * A content class for Curl call results
10  */
11 class CurlResult
12 {
13         /**
14          * @var int HTTP return code or 0 if timeout or failure
15          */
16         private $returnCode;
17
18         /**
19          * @var string the content type of the Curl call
20          */
21         private $contentType;
22
23         /**
24          * @var string the HTTP headers of the Curl call
25          */
26         private $header;
27
28         /**
29          * @var boolean true (if HTTP 2xx result) or false
30          */
31         private $isSuccess;
32
33         /**
34          * @var string the URL which was called
35          */
36         private $url;
37
38         /**
39          * @var string in case of redirect, content was finally retrieved from this URL
40          */
41         private $redirectUrl;
42
43         /**
44          * @var string fetched content
45          */
46         private $body;
47
48         /**
49          * @var array some informations about the fetched data
50          */
51         private $info;
52
53         /**
54          * @var boolean true if the URL has a redirect
55          */
56         private $isRedirectUrl;
57
58         /**
59          * @var boolean true if the curl request timed out
60          */
61         private $isTimeout;
62
63         /**
64          * @var int the error number or 0 (zero) if no error
65          */
66         private $errorNumber;
67
68         /**
69          * @var string the error message or '' (the empty string) if no
70          */
71         private $error;
72
73         /**
74          * Creates an errored CURL response
75          *
76          * @param string $url optional URL
77          *
78          * @return CurlResult a CURL with error response
79          */
80         public static function createErrorCurl($url = '')
81         {
82                 return new CurlResult($url, '', ['http_code' => 0]);
83         }
84
85         /**
86          * Curl constructor.
87          * @param string $url the URL which was called
88          * @param string $result the result of the curl execution
89          * @param array $info an additional info array
90          * @param int $errorNumber the error number or 0 (zero) if no error
91          * @param string $error the error message or '' (the empty string) if no
92          *
93          * @throws InternalServerErrorException when HTTP code of the CURL response is missing
94          */
95         public function __construct($url, $result, $info, $errorNumber = 0, $error = '')
96         {
97                 if (!array_key_exists('http_code', $info)) {
98                         throw new InternalServerErrorException('CURL response doesn\'t contains a response HTTP code');
99                 }
100
101                 $this->returnCode = $info['http_code'];
102                 $this->url = $url;
103                 $this->info = $info;
104                 $this->errorNumber = $errorNumber;
105                 $this->error = $error;
106
107                 Logger::log($url . ': ' . $this->returnCode . " " . $result, Logger::DATA);
108
109                 $this->parseBodyHeader($result);
110                 $this->checkSuccess();
111                 $this->checkRedirect();
112                 $this->checkInfo();
113         }
114
115         private function parseBodyHeader($result)
116         {
117                 // Pull out multiple headers, e.g. proxy and continuation headers
118                 // allow for HTTP/2.x without fixing code
119
120                 $header = '';
121                 $base = $result;
122                 while (preg_match('/^HTTP\/.+? \d+/', $base)) {
123                         $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4);
124                         $header .= $chunk;
125                         $base = substr($base, strlen($chunk));
126                 }
127
128                 $this->body = substr($result, strlen($header));
129                 $this->header = $header;
130         }
131
132         private function checkSuccess()
133         {
134                 $this->isSuccess = ($this->returnCode >= 200 && $this->returnCode <= 299) || $this->errorNumber == 0;
135
136                 // Everything higher or equal 400 is not a success
137                 if ($this->returnCode >= 400) {
138                         $this->isSuccess = false;
139                 }
140
141                 if (!$this->isSuccess) {
142                         Logger::log('error: ' . $this->url . ': ' . $this->returnCode . ' - ' . $this->error, Logger::INFO);
143                         Logger::log('debug: ' . print_r($this->info, true), Logger::DATA);
144                 }
145
146                 if (!$this->isSuccess && $this->errorNumber == CURLE_OPERATION_TIMEDOUT) {
147                         $this->isTimeout = true;
148                 } else {
149                         $this->isTimeout = false;
150                 }
151         }
152
153         private function checkRedirect()
154         {
155                 if (!array_key_exists('url', $this->info)) {
156                         $this->redirectUrl = '';
157                 } else {
158                         $this->redirectUrl = $this->info['url'];
159                 }
160
161                 if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode== 307) {
162                         $new_location_info = (!array_key_exists('redirect_url', $this->info) ? '' : @parse_url($this->info['redirect_url']));
163                         $old_location_info = (!array_key_exists('url', $this->info) ? '' : @parse_url($this->info['url']));
164
165                         $this->redirectUrl = $new_location_info;
166
167                         if (empty($new_location_info['path']) && !empty($new_location_info['host'])) {
168                                 $this->redirectUrl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
169                         }
170
171                         $matches = [];
172
173                         if (preg_match('/(Location:|URI:)(.*?)\n/i', $this->header, $matches)) {
174                                 $this->redirectUrl = trim(array_pop($matches));
175                         }
176                         if (strpos($this->redirectUrl, '/') === 0) {
177                                 $this->redirectUrl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $this->redirectUrl;
178                         }
179                         $old_location_query = @parse_url($this->url, PHP_URL_QUERY);
180
181                         if ($old_location_query != '') {
182                                 $this->redirectUrl .= '?' . $old_location_query;
183                         }
184
185                         $this->isRedirectUrl = filter_var($this->redirectUrl, FILTER_VALIDATE_URL) !== false;
186                 } else {
187                         $this->isRedirectUrl = false;
188                 }
189         }
190
191         private function checkInfo()
192         {
193                 if (isset($this->info['content_type'])) {
194                         $this->contentType = $this->info['content_type'];
195                 } else {
196                         $this->contentType = '';
197                 }
198         }
199
200         /**
201          * Gets the Curl Code
202          *
203          * @return string The Curl Code
204          */
205         public function getReturnCode()
206         {
207                 return $this->returnCode;
208         }
209
210         /**
211          * Returns the Curl Content Type
212          *
213          * @return string the Curl Content Type
214          */
215         public function getContentType()
216         {
217                 return $this->contentType;
218         }
219
220         /**
221          * Returns the Curl headers
222          *
223          * @return string the Curl headers
224          */
225         public function getHeader()
226         {
227                 return $this->header;
228         }
229
230         /**
231          * @return bool
232          */
233         public function isSuccess()
234         {
235                 return $this->isSuccess;
236         }
237
238         /**
239          * @return string
240          */
241         public function getUrl()
242         {
243                 return $this->url;
244         }
245
246         /**
247          * @return string
248          */
249         public function getRedirectUrl()
250         {
251                 return $this->redirectUrl;
252         }
253
254         /**
255          * @return string
256          */
257         public function getBody()
258         {
259                 return $this->body;
260         }
261
262         /**
263          * @return array
264          */
265         public function getInfo()
266         {
267                 return $this->info;
268         }
269
270         /**
271          * @return bool
272          */
273         public function isRedirectUrl()
274         {
275                 return $this->isRedirectUrl;
276         }
277
278         /**
279          * @return int
280          */
281         public function getErrorNumber()
282         {
283                 return $this->errorNumber;
284         }
285
286         /**
287          * @return string
288          */
289         public function getError()
290         {
291                 return $this->error;
292         }
293
294         /**
295          * @return bool
296          */
297         public function isTimeout()
298         {
299                 return $this->isTimeout;
300         }
301 }