1 | <?php |
||||
2 | |||||
3 | namespace Extender; |
||||
4 | |||||
5 | use Curl\Curl; |
||||
6 | use Filemanager\file; |
||||
7 | use JSON\json; |
||||
8 | use MVC\Exception; |
||||
9 | use MVC\helper; |
||||
10 | |||||
11 | class request extends Curl |
||||
12 | { |
||||
13 | private $result_request = []; |
||||
14 | /** |
||||
15 | * request instances. |
||||
16 | * |
||||
17 | * @var request |
||||
18 | */ |
||||
19 | private static $_instance = null; |
||||
20 | |||||
21 | public function __construct($base = null) |
||||
22 | { |
||||
23 | parent::__construct($base); |
||||
24 | } |
||||
25 | |||||
26 | public function disableSSL() |
||||
27 | { |
||||
28 | $this->setOpt(CURLOPT_SSL_VERIFYPEER, false); |
||||
29 | $this->setOpt(CURLOPT_SSL_VERIFYHOST, false); |
||||
30 | |||||
31 | return $this; |
||||
32 | } |
||||
33 | |||||
34 | public $cache = false; |
||||
35 | |||||
36 | /** |
||||
37 | * Execute curl. |
||||
38 | * |
||||
39 | * @return string|array|null |
||||
40 | */ |
||||
41 | public function execute(string $method, string $path, bool $rewrite = false) |
||||
42 | { |
||||
43 | $self = $this; |
||||
44 | $self->set_method($method); |
||||
45 | $self->set_url($path); |
||||
46 | if ($self->cache) { |
||||
47 | if (!$rewrite) { |
||||
48 | if (file_exists($self->cache_path())) { |
||||
49 | $this->response = $self->get_cache(); |
||||
50 | } |
||||
51 | } |
||||
52 | } |
||||
53 | |||||
54 | if (!$this->response || empty($this->response)) { |
||||
55 | $this->exec(); |
||||
56 | } else { |
||||
57 | $this->error = false; |
||||
58 | } |
||||
59 | |||||
60 | if (!$this->error) { |
||||
61 | if ($this->cache) { |
||||
62 | \Filemanager\file::file($this->cache_path(), $this->response, true); |
||||
63 | } |
||||
64 | if (is_object($this->response)) { |
||||
65 | $this->response = (array) $this->response; |
||||
66 | } |
||||
67 | |||||
68 | return $this->response; |
||||
69 | } |
||||
70 | |||||
71 | return null; |
||||
72 | } |
||||
73 | |||||
74 | /** |
||||
75 | * Get Cache Path. |
||||
76 | * |
||||
77 | * @return string |
||||
78 | */ |
||||
79 | private function cache_path() |
||||
80 | { |
||||
81 | return ROOT . '/tmp/curl/' . md5($this->url); |
||||
82 | } |
||||
83 | |||||
84 | /** |
||||
85 | * Get cached content. |
||||
86 | * |
||||
87 | * @return string|array|null |
||||
88 | */ |
||||
89 | private function get_cache() |
||||
90 | { |
||||
91 | if (file_exists($this->cache_path())) { |
||||
92 | return \Filemanager\file::get($this->cache_path(), true); |
||||
93 | } |
||||
94 | } |
||||
95 | |||||
96 | public function set_url(string $url) |
||||
97 | { |
||||
98 | $this->setUrl($url); |
||||
99 | |||||
100 | return $this; |
||||
101 | } |
||||
102 | |||||
103 | public function set_method(string $method) |
||||
104 | { |
||||
105 | $this->setOpt(CURLOPT_CUSTOMREQUEST, strtoupper($method)); |
||||
106 | |||||
107 | return $this; |
||||
108 | } |
||||
109 | |||||
110 | public static function getInstance($base = null) |
||||
111 | { |
||||
112 | if (null === self::$_instance) { |
||||
113 | self::$_instance = new self($base); |
||||
114 | } |
||||
115 | |||||
116 | return self::$_instance; |
||||
117 | } |
||||
118 | |||||
119 | public static function static_request($opt) |
||||
120 | { |
||||
121 | return self::getInstance()->request($opt); |
||||
122 | //return self::request($opt); |
||||
123 | } |
||||
124 | |||||
125 | private $require_content_length = false; |
||||
126 | private $dumpNow = false; |
||||
127 | |||||
128 | public function isDUMPNow() |
||||
129 | { |
||||
130 | return true === $this->dumpNow; |
||||
131 | } |
||||
132 | |||||
133 | public function DUMPNow(...$what) |
||||
134 | { |
||||
135 | if ($this->isDUMPNow()) { |
||||
136 | $this->exitJSON($what); |
||||
137 | } |
||||
138 | } |
||||
139 | |||||
140 | public function exitJSON(...$what) |
||||
141 | { |
||||
142 | foreach ($what as $these) { |
||||
143 | json::json($these); |
||||
144 | echo "\n\n"; |
||||
145 | } |
||||
146 | exit; |
||||
0 ignored issues
–
show
|
|||||
147 | } |
||||
148 | |||||
149 | /** |
||||
150 | * cURL shooter request. |
||||
151 | * |
||||
152 | * @param array $opt |
||||
153 | * |
||||
154 | * @return array |
||||
155 | */ |
||||
156 | public function request($opt) |
||||
157 | { |
||||
158 | if (!isset($opt['url'])) { |
||||
159 | throw new Exception('URL needed', 1); |
||||
160 | } |
||||
161 | $msisdn = isset($_SESSION['telkomsel']['msisdn']) ? $_SESSION['telkomsel']['msisdn'] : 'default'; |
||||
162 | //$verbose = __DIR__ . '/otp/http/' . $msisdn . '.' . substr(clean_string(urldecode(urldecode($opt['url']))), 0, 50) . '.txt'; |
||||
163 | //file_put_contents($verbose, ''); |
||||
164 | //$curl_log = fopen($verbose, 'a'); |
||||
165 | $ch = curl_init(); |
||||
166 | |||||
167 | $result = ['request' => [], 'response' => []]; |
||||
168 | if (isset($opt['postdata'])) { |
||||
169 | if (is_array($opt['postdata'])) { |
||||
170 | $opt['postdata'] = http_build_query($opt['postdata'], '', '&'); |
||||
171 | } |
||||
172 | curl_setopt($ch, CURLOPT_POSTFIELDS, $opt['postdata']); |
||||
173 | $result['request']['postdata'] = $opt['postdata']; |
||||
174 | $this->require_content_length = true; |
||||
175 | } |
||||
176 | if (isset($opt['headers']) && is_array($opt['headers'])) { |
||||
177 | $headers = $opt['headers']; |
||||
178 | if (isset($opt['headers_trim'])) { |
||||
179 | $headers = array_map('trim', $headers); |
||||
180 | $headers = array_filter($headers); |
||||
181 | $headers = array_values($headers); |
||||
182 | } |
||||
183 | for ($i = 0; $i < count($headers); ++$i) { |
||||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||||
184 | $header = array_map('trim', explode(':', $headers[$i])); |
||||
185 | $small_header = strtolower($header[0]); |
||||
186 | if ('content-length' == $small_header && true === $this->require_content_length) { |
||||
187 | $headers[$i] = $header[0] . ': ' . strlen($opt['postdata']); |
||||
188 | } |
||||
189 | if ('user-agent' == $small_header) { |
||||
190 | curl_setopt($ch, CURLOPT_USERAGENT, $header[1]); |
||||
191 | } |
||||
192 | } |
||||
193 | //$this->DUMPNow($headers, $opt); |
||||
194 | |||||
195 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); |
||||
196 | $result['request']['headers'] = $headers; |
||||
197 | } |
||||
198 | curl_setopt($ch, CURLOPT_URL, trim($opt['url'])); |
||||
199 | $result['url'] = $opt['url']; |
||||
200 | if (isset($opt['post']) && $opt['post']) { |
||||
201 | curl_setopt($ch, CURLOPT_POST, 1); |
||||
202 | } |
||||
203 | |||||
204 | //evj($_SESSION, isset($opt['cookie']) && true === $opt['cookie'] && isset($_SESSION['cookie'])); |
||||
205 | if (isset($opt['cookie']) && true === $opt['cookie'] && isset($_SESSION['cookie'])) { |
||||
206 | $cookie = isset($_SESSION['cookie']) ? $_SESSION['cookie'] : null; |
||||
207 | if (is_string($opt['cookie']) && !empty($opt['cookie'])) { |
||||
208 | $cookie = $opt['cookie']; |
||||
209 | } |
||||
210 | |||||
211 | if ($cookie = file::file($cookie, '')) { |
||||
0 ignored issues
–
show
'' of type string is incompatible with the type boolean expected by parameter $create of Filemanager\file::file() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
212 | if (!file_exists($cookie)) { |
||||
213 | throw new Exception("$cookie not exists", 1); |
||||
214 | //file_put_contents($cookie, ''); |
||||
215 | } |
||||
216 | curl_setopt($ch, CURLOPT_COOKIEJAR, realpath($cookie)); |
||||
217 | curl_setopt($ch, CURLOPT_COOKIEFILE, realpath($cookie)); |
||||
218 | $result['request']['cookie-file'] = realpath($cookie); |
||||
219 | $result['response']['cookie-file'] = realpath($cookie); |
||||
220 | } |
||||
221 | } |
||||
222 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); |
||||
223 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||
224 | curl_setopt($ch, CURLOPT_HEADER, true); |
||||
225 | //curl_setopt($ch, CURLOPT_VERBOSE, true); |
||||
226 | //curl_setopt($ch, CURLOPT_STDERR, $curl_log); |
||||
227 | curl_setopt($ch, CURLINFO_HEADER_OUT, true); |
||||
228 | //curl_setopt($ch, CURLOPT_ENCODING, ''); |
||||
229 | if (isset($opt['setopt']) && is_array($opt['setopt']) && !empty($opt['setopt'])) { |
||||
230 | foreach ($opt['setopt'] as $key => $value) { |
||||
231 | curl_setopt($ch, $key, $value); |
||||
232 | } |
||||
233 | } |
||||
234 | |||||
235 | if (isset($opt['proxy'])) { |
||||
236 | curl_setopt($ch, CURLOPT_PROXY, $opt['proxy']); |
||||
237 | curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); |
||||
238 | if (isset($opt['proxy_type'])) { |
||||
239 | switch ($opt['proxy_type']) { |
||||
240 | case 'socks5': |
||||
241 | curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); |
||||
242 | break; |
||||
243 | case 'http': |
||||
244 | curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); |
||||
245 | break; |
||||
246 | case 'https': |
||||
247 | curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); |
||||
248 | break; |
||||
249 | case 'socks4': |
||||
250 | curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); |
||||
251 | break; |
||||
252 | } |
||||
253 | } |
||||
254 | } |
||||
255 | |||||
256 | $data = curl_exec($ch); |
||||
257 | if (!is_string($data) && $data) { |
||||
258 | $data = json::assoc($data); |
||||
0 ignored issues
–
show
$data of type true is incompatible with the type array|object expected by parameter $arr of JSON\json::assoc() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
259 | } |
||||
260 | $result['curl_exec'] = $data; |
||||
261 | // save to log |
||||
262 | $parse_url = helper::parse_url2($opt['url']); |
||||
263 | $filesave = "{$parse_url['host']}/{$parse_url['path']}"; |
||||
264 | $filepath = helper::platformSlashes(__DIR__ . "/log/curl_exec/$msisdn/$filesave"); |
||||
265 | if (!is_dir(dirname($filepath))) { |
||||
266 | mkdir(dirname($filepath), 0777, true); |
||||
267 | } |
||||
268 | file::file($filepath, $data, true); |
||||
269 | //rewind($curl_log); |
||||
270 | $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); |
||||
271 | $headerSent = curl_getinfo($ch, CURLINFO_HEADER_OUT); |
||||
272 | $headerSent = explode("\n", $headerSent); |
||||
273 | $headerSent = array_map(function ($v) { |
||||
274 | return preg_replace("/\r$/m", '', $v); |
||||
275 | }, $headerSent); |
||||
276 | $result['request']['raw'] = $headerSent; |
||||
277 | $header = substr($data, 0, $header_size); |
||||
278 | $body = substr($data, $header_size); |
||||
279 | if (json::is_json($body)) { |
||||
280 | $body = json_decode($body, true); |
||||
281 | } |
||||
282 | |||||
283 | $header = explode("\n", $header); |
||||
284 | $header = array_map(function ($v) { |
||||
285 | return preg_replace("/\r$/m", '', $v); |
||||
286 | }, $header); |
||||
287 | |||||
288 | $result['response']['headers'] = $header; |
||||
289 | foreach ($header as $h) { |
||||
290 | $ex = explode(':', $h); |
||||
291 | if (isset($ex[0]) && isset($ex[1])) { |
||||
292 | $hkey = $ex[0]; |
||||
293 | //var_dump($hkey, strpos(strtolower(trim($hkey)), 'oauth')); |
||||
294 | if (false !== strpos(strtolower($hkey), 'oauth')) { |
||||
295 | $_SESSION['im3'][$opt['url']]['oauth'] = trim($ex[1]); |
||||
296 | $_SESSION['im3']['oauth'] = trim($ex[1]); |
||||
297 | } |
||||
298 | } |
||||
299 | } |
||||
300 | if (is_iterable($body)) { |
||||
301 | foreach ($body as $key => $value) { |
||||
302 | $_SESSION['im3'][$key] = $value; |
||||
303 | } |
||||
304 | if (isset($body['data']['tokenid'])) { |
||||
305 | $_SESSION['im3']['tokenid'] = $body['data']['tokenid']; |
||||
306 | } |
||||
307 | } |
||||
308 | $result['response']['body'] = $body; |
||||
309 | $result['options'] = $opt; |
||||
310 | if (isset($opt['verbose'])) { |
||||
311 | $_SESSION['verbose'][$opt['url']] = $result; |
||||
312 | } |
||||
313 | //exit(gettype($ch)); |
||||
314 | curl_close($ch); |
||||
315 | |||||
316 | return $result; |
||||
317 | } |
||||
318 | |||||
319 | public static function getCurlOpt($ch, int $what) |
||||
320 | { |
||||
321 | return curl_getinfo($ch, $what); |
||||
322 | } |
||||
323 | |||||
324 | public function set_header_array($headers, $trim = false) |
||||
325 | { |
||||
326 | if (!is_array($headers)) { |
||||
327 | throw new \MVC\Exception('Header must array formatted', 1); |
||||
328 | } |
||||
329 | if ($trim) { |
||||
330 | $headers = array_map('trim', $headers); |
||||
331 | } |
||||
332 | $this->setOpt(CURLOPT_HTTPHEADER, $headers); |
||||
333 | $this->result_request['request']['headers'] = $headers; |
||||
334 | |||||
335 | return $this; |
||||
336 | } |
||||
337 | |||||
338 | public function set_cookie_file($cookie = null) |
||||
339 | { |
||||
340 | if (!$cookie) { |
||||
341 | $cookie = __DIR__ . '/cookie/default.txt'; |
||||
342 | if (isset($_SERVER['HTTP_USER_AGENT'])) { |
||||
343 | $cookie = __DIR__ . '/cookie/' . $_SERVER['HTTP_USER_AGENT'] . '.txt'; |
||||
344 | } |
||||
345 | } |
||||
346 | if ($cookie) { |
||||
347 | \Filemanager\file::file($cookie, '#cookie'); |
||||
0 ignored issues
–
show
'#cookie' of type string is incompatible with the type boolean expected by parameter $create of Filemanager\file::file() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
348 | } |
||||
349 | $this->setCookieFile($cookie); |
||||
350 | $this->setCookieJar($cookie); |
||||
351 | $this->result_request['cookie'] = $cookie; |
||||
352 | |||||
353 | return $this; |
||||
354 | } |
||||
355 | |||||
356 | /** |
||||
357 | * Check array is assoc |
||||
358 | * * var_dump(isAssoc(['a', 'b', 'c'])); // false |
||||
359 | * * var_dump(isAssoc(["0" => 'a', "1" => 'b', "2" => 'c'])); // false |
||||
360 | * * var_dump(isAssoc(["1" => 'a', "0" => 'b', "2" => 'c'])); // true |
||||
361 | * * var_dump(isAssoc(["a" => 'a', "b" => 'b', "c" => 'c'])); // true. |
||||
362 | * |
||||
363 | * @return bool |
||||
364 | */ |
||||
365 | public function isAssoc(array $arr) |
||||
366 | { |
||||
367 | if ([] === $arr) { |
||||
368 | return false; |
||||
369 | } |
||||
370 | |||||
371 | return array_keys($arr) !== range(0, count($arr) - 1); |
||||
372 | } |
||||
373 | |||||
374 | /** |
||||
375 | * Check array has some string key. |
||||
376 | * |
||||
377 | * @return bool |
||||
378 | */ |
||||
379 | public function has_string_keys(array $array) |
||||
380 | { |
||||
381 | return count(array_filter(array_keys($array), 'is_string')) > 0; |
||||
382 | } |
||||
383 | } |
||||
384 | |||||
385 | if (!function_exists('is_iterable')) { |
||||
386 | function is_iterable($var) |
||||
387 | { |
||||
388 | return is_array($var) || $var instanceof \Traversable; |
||||
389 | } |
||||
390 | } |
||||
391 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.