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