]> git.mxchange.org Git - friendica.git/blob - src/Network/CurlResult.php
CurlResult Tests & RegEx fix
[friendica.git] / src / Network / CurlResult.php
1 <?php
2
3 namespace Friendica\Network;
4
5
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($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                 if (!$this->isSuccess) {
137                         logger('error: ' . $this->url . ': ' . $this->returnCode . ' - ' . $this->error, LOGGER_INFO);
138                         logger('debug: ' . print_r($this->info, true), LOGGER_DATA);
139                 }
140
141                 if (!$this->isSuccess && $this->errorNumber == CURLE_OPERATION_TIMEDOUT) {
142                         $this->isTimeout = true;
143                 } else {
144                         $this->isTimeout = false;
145                 }
146         }
147
148         private function checkRedirect()
149         {
150                 if (!array_key_exists('url', $this->info)) {
151                         $this->redirectUrl = '';
152                 } else {
153                         $this->redirectUrl = $this->info['url'];
154                 }
155
156                 if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode== 307) {
157                         $new_location_info = (!array_key_exists('redirect_url', $this->info) ? '' : @parse_url($this->info['redirect_url']));
158                         $old_location_info = (!array_key_exists('url', $this->info) ? '' : @parse_url($this->info['url']));
159
160                         $this->redirectUrl = $new_location_info;
161
162                         if (empty($new_location_info['path']) && !empty($new_location_info['host'])) {
163                                 $this->redirectUrl = $new_location_info['scheme'] . '://' . $new_location_info['host'] . $old_location_info['path'];
164                         }
165
166                         $matches = [];
167
168                         if (preg_match('/(Location:|URI:)(.*?)\n/i', $this->header, $matches)) {
169                                 $this->redirectUrl = trim(array_pop($matches));
170                         }
171                         if (strpos($this->redirectUrl, '/') === 0) {
172                                 $this->redirectUrl = $old_location_info["scheme"] . "://" . $old_location_info["host"] . $this->redirectUrl;
173                         }
174                         $old_location_query = @parse_url($this->url, PHP_URL_QUERY);
175
176                         if ($old_location_query != '') {
177                                 $this->redirectUrl .= '?' . $old_location_query;
178                         }
179
180                         $this->isRedirectUrl = filter_var($this->redirectUrl, FILTER_VALIDATE_URL) !== false;
181                 } else {
182                         $this->isRedirectUrl = false;
183                 }
184         }
185
186         private function checkInfo()
187         {
188                 if (isset($this->info['content_type'])) {
189                         $this->contentType = $this->info['content_type'];
190                 } else {
191                         $this->contentType = '';
192                 }
193         }
194
195         /**
196          * Gets the Curl Code
197          *
198          * @return string The Curl Code
199          */
200         public function getReturnCode()
201         {
202                 return $this->returnCode;
203         }
204
205         /**
206          * Returns the Curl Content Type
207          *
208          * @return string the Curl Content Type
209          */
210         public function getContentType()
211         {
212                 return $this->contentType;
213         }
214
215         /**
216          * Returns the Curl headers
217          *
218          * @return string the Curl headers
219          */
220         public function getHeader()
221         {
222                 return $this->header;
223         }
224
225         /**
226          * @return bool
227          */
228         public function isSuccess()
229         {
230                 return $this->isSuccess;
231         }
232
233         /**
234          * @return string
235          */
236         public function getUrl()
237         {
238                 return $this->url;
239         }
240
241         /**
242          * @return string
243          */
244         public function getRedirectUrl()
245         {
246                 return $this->redirectUrl;
247         }
248
249         /**
250          * @return string
251          */
252         public function getBody()
253         {
254                 return $this->body;
255         }
256
257         /**
258          * @return array
259          */
260         public function getInfo()
261         {
262                 return $this->info;
263         }
264
265         /**
266          * @return bool
267          */
268         public function isRedirectUrl()
269         {
270                 return $this->isRedirectUrl;
271         }
272
273         /**
274          * @return int
275          */
276         public function getErrorNumber()
277         {
278                 return $this->errorNumber;
279         }
280
281         /**
282          * @return string
283          */
284         public function getError()
285         {
286                 return $this->error;
287         }
288
289         /**
290          * @return bool
291          */
292         public function isTimeout()
293         {
294                 return $this->isTimeout;
295         }
296 }