Issues (1752)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Fwlib/Net/Curl.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Fwlib\Net;
3
4
use Fwlib\Util\UtilContainer;
5
6
/**
7
 * Helper class for easy curl usage
8
 *
9
 * @copyright   Copyright 2007-2015 Fwolf
10
 * @license     http://www.gnu.org/licenses/lgpl.html LGPL-3.0+
11
 */
12
class Curl
13
{
14
    /**
15
     * File to save cookie
16
     *
17
     * @var string
18
     */
19
    protected $cookieFile = '';
20
21
    /**
22
     * Debug mode, will log more information, like get/post url
23
     *
24
     * @var boolean
25
     */
26
    protected $debug = false;
27
28
    /**
29
     * cURL handle
30
     *
31
     * @var resource
32
     */
33
    protected $handle;
34
35
    /**
36
     * Result read from web server
37
     *
38
     * @var string
39
     */
40
    protected $html = '';
41
42
    /**
43
     * File to save log
44
     *
45
     * Empty for direct print out(default), or set to a valid file to save, or
46
     * set to /dev/null to do nothing.
47
     *
48
     * @var string
49
     */
50
    protected $logFile = null;
51
52
53
    /**
54
     * Destructor
55
     */
56
    public function __destruct()
57
    {
58
        curl_close($this->getHandle());
59
    }
60
61
62
    /**
63
     * Http get method
64
     *
65
     * @param   string          $url    Host address
66
     * @param   string|array    $param  Get parameter
67
     * @return  string
68
     */
69
    public function get($url, $param = null)
70
    {
71
        $handle = $this->getHandle();
72
73
        curl_setopt($handle, CURLOPT_HTTPGET, true);
74
75
        // Remove tailing '?" from url
76 View Code Duplication
        if ('?' == substr($url, -1, 1)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
77
            $url = substr($url, 0, strlen($url) - 1);
78
        }
79
80
        // Char used between url & param
81
        $linker = (false === strpos($url, '?')) ? '?' : '&';
82
83
        // Parse param, join array and fix linker char with url
84
        if (!empty($param)) {
85 View Code Duplication
            if (is_array($param)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
                $queryString = '';
87
                foreach ($param as $k => $v) {
88
                    $queryString .= '&' . urlencode($k) . '=' . urlencode($v);
89
                }
90
                $param = $queryString;
91
            }
92
93
            $param{0} = $linker;
94
        }
95
96
        curl_setopt($handle, CURLOPT_URL, $url . $param);
97
        $this->html = curl_exec($handle);
98
99
        if ($this->debug) {
100
            $this->log('Get: ' . $url . $param);
101
        }
102
103
        if (0 != curl_errno($handle)) {
104
            $this->log(curl_error($handle));
105
        }
106
107
        return $this->html;
108
    }
109
110
111
    /**
112
     * Get and initialize curl handle
113
     *
114
     * @return  resource
115
     */
116
    public function getHandle()
117
    {
118
        if (is_null($this->handle)) {
119
            $this->handle = curl_init();
120
            $this->setDefaultOptions($this->handle);
121
        }
122
123
        return $this->handle;
124
    }
125
126
127
    /**
128
     * Get server return code of last curl_exec
129
     *
130
     * 200-ok, 404-missing file, etc
131
     *
132
     * @return  int
133
     */
134
    public function getLastCode()
135
    {
136
        $handle = $this->getHandle();
137
138
        $code = curl_getinfo($handle, CURLINFO_HTTP_CODE);
139
140
        return intval($code);
141
    }
142
143
144
    /**
145
     * Get server return content type of last curl_exec
146
     *
147
     * text/html, image/png, etc
148
     *
149
     * @return  string
150
     */
151
    public function getLastContentType()
152
    {
153
        $handle = $this->getHandle();
154
155
        $type = curl_getinfo($handle, CURLINFO_CONTENT_TYPE);
156
157
        return $type;
158
    }
159
160
161
    /**
162
     * Log curl action
163
     *
164
     * @param   string  $msg
165
     */
166
    protected function log($msg)
167
    {
168
        // Prepend msg with time, append with newline
169
        $msg = date('[Y-m-d H:i:s] ') . $msg . PHP_EOL;
170
171
        if (empty($this->logFile)) {
172
            // Print
173
            UtilContainer::getInstance()->getEnv()->ecl($msg);
174
175
        } elseif (is_writable($this->logFile)) {
176
            // Write to log file
177
            file_put_contents($this->logFile, $msg, FILE_APPEND);
178
        }
179
180
        // Invalid $this->logFile will do nothing.
181
    }
182
183
184
    /**
185
     * Match content to variables using preg
186
     *
187
     * Return value maybe string(for single result) or array(for multiple
188
     * result), use carefully and remind which value you use it for.
189
     *
190
     * Regex should surround wih '/', and mark match target with '()'.
191
     *
192
     * @param   string  $preg
193
     * @param   string  $html   If omitted, use $this->html
194
     * @return  string|array
195
     */
196
    public function match($preg, $html = '')
197
    {
198
        // Param check
199
        if (empty($preg)) {
200
            return null;
201
        }
202
        if (empty($html)) {
203
            $html = $this->html;
204
        }
205
206
207
        $matchCount = preg_match_all($preg, $html, $matches, PREG_SET_ORDER);
208
        if (0 == $matchCount || false === $matchCount) {
209
            // Got none match or Got error
210
            $matches = null;
211
212
        } elseif (1 == $matchCount) {
213
            // Got 1 match, return as string or array(2 value in 1 match)
214
            $matches = $matches[0];
215
            array_shift($matches);
216
            if (1 == count($matches)) {
217
                $matches = $matches[0];
218
            }
219
220
        } else {
221
            // Got more than 1 match return array contains string or sub-array
222 View Code Duplication
            foreach ($matches as &$row) {
0 ignored issues
show
The expression $matches of type null|array<integer,array<integer,string>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
223
                array_shift($row);
224
                if (1 == count($row)) {
225
                    $row = $row[0];
226
                }
227
            }
228
        }
229
230
        return $matches;
231
    }
232
233
234
    /**
235
     * Http post method
236
     *
237
     * @param   string          $url    Host address
238
     * @param   string|array    $params Post parameter, prefer array
239
     * @return  string
240
     */
241
    public function post($url, $params = [])
242
    {
243
        $handle = $this->getHandle();
244
245
        curl_setopt($handle, CURLOPT_POST, true);
246
247
        curl_setopt($handle, CURLOPT_POSTFIELDS, $params);
248
        curl_setopt($handle, CURLOPT_URL, $url);
249
        $this->html = curl_exec($handle);
250
251
        if (is_array($params)) {
252
            $params = implode('&', array_keys($params));
253
        }
254
        $linker = (false === strpos($url, '?')) ? '?' : '&';
255
        $params = rtrim($linker . ltrim($params, '&'), '?&');
256
257
        if ($this->debug) {
258
            $this->log('Post: ' . $url . $params);
259
        }
260
261
        if (0 != curl_errno($handle)) {
262
            $this->log(curl_error($handle), 4);
0 ignored issues
show
The call to Curl::log() has too many arguments starting with 4.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
263
        }
264
265
        return $this->html;
266
    }
267
268
269
    /**
270
     * Renew handle
271
     *
272
     * This is useful when cookie file is used, and want to reload cookies,
273
     * eg: after login, reload cookie then they will be used in next operation.
274
     *
275
     * @return  static
276
     */
277
    public function renewHandle()
278
    {
279
        if (!is_null($this->handle)) {
280
            curl_close($this->handle);
281
            $this->handle = null;
282
283
            $this->getHandle();
284
285
            // Re-assign options
286
            if (!is_null($this->cookieFile)) {
287
                $this->setCookieFile($this->cookieFile);
288
            }
289
290
            // More option to set ?
291
        }
292
293
        return $this;
294
    }
295
296
297
    /**
298
     * Set cookie option
299
     *
300
     * If filename is not given, use default,
301
     * If file is given, use & set it as default.
302
     *
303
     * @param   string  $cookieFile
304
     */
305
    public function setCookieFile($cookieFile = '')
306
    {
307
        $handle = $this->getHandle();
308
309
        $this->cookieFile = $cookieFile;
310
311
        if (!empty($cookieFile) && (is_writable($cookieFile))) {
312
            curl_setopt($handle, CURLOPT_COOKIEFILE, $cookieFile);
313
            curl_setopt($handle, CURLOPT_COOKIEJAR, $cookieFile);
314
        }
315
    }
316
317
318
    /**
319
     * Setter of $debug
320
     *
321
     * @param   boolean $debug
322
     * @return  static
323
     */
324
    public function setDebug($debug)
325
    {
326
        $this->debug = $debug;
327
328
        return $this;
329
    }
330
331
332
    /**
333
     * Set default options
334
     *
335
     * @param   resource    $handle
336
     * @return  static
337
     */
338
    protected function setDefaultOptions($handle)
339
    {
340
        curl_setopt($handle, CURLOPT_AUTOREFERER, true);
341
        // If got http error, report.
342
        curl_setopt($handle, CURLOPT_FAILONERROR, true);
343
344
        // CURLOPT_FOLLOWLOCATION cannot set when open_basedir is set.
345
        // Also safe_mode, which are DEPRECATED in 5.3.0 and REMOVED in 5.4.0.
346
        if ('' == ini_get('open_basedir')) {
347
            curl_setopt($handle, CURLOPT_FOLLOWLOCATION, true);
348
        }
349
350
        // Return result instead of display it.
351
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
352
        curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 300);
353
        curl_setopt($handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
354
        curl_setopt($handle, CURLOPT_MAXREDIRS, 10);
355
        curl_setopt($handle, CURLOPT_TIMEOUT, 300);
356
357
        // Accept all supported encoding(identity, deflate, gzip)
358
        // See CURLOPT_ACCEPT_ENCODING in libcurl
359
        // Set this to get uncompressed html content
360
        curl_setopt($handle, CURLOPT_ENCODING, '');
361
362
        // Cipher list depends on curl lib use OpenSSL or NSS module
363
        // @see https://github.com/PayU/openpayu_php/issues/38
364
        // Wrong cipher will got error: Unknown cipher in list: ...
365
        $cipher = ('NSS' == substr(curl_version()['ssl_version'], 0, 3))
366
            ? 'rsa_aes_128_sha'
367
            : 'TLSv1';
368
        curl_setopt($handle, CURLOPT_SSL_CIPHER_LIST, $cipher);
369
370
        return $this;
371
    }
372
373
374
    /**
375
     * Setter of $logFile
376
     *
377
     * @param   string $logFile
378
     * @return  static
379
     */
380
    public function setLogFile($logFile)
381
    {
382
        $this->logFile = $logFile;
383
384
        return $this;
385
    }
386
387
388
    /**
389
     * Set proxy option
390
     *
391
     * @param   int     $type  0-no proxy, 1-http, 2-socks5
392
     * @param   string  $host
393
     * @param   int     $port
394
     * @param   string  $auth  [username]:[password]
395
     */
396
    public function setProxy($type, $host, $port, $auth = '')
397
    {
398
        $handle = $this->getHandle();
399
400
        if (0 == $type) {
401
            // Some server refuse http proxy tunnel, it's useless settings.
402
            //curl_setopt($handle, CURLOPT_HTTPPROXYTUNNEL, false);
403
            curl_setopt($handle, CURLOPT_PROXY, null);
404
405
        } else {
406
            //curl_setopt($handle, CURLOPT_HTTPPROXYTUNNEL, true);
407
408
            curl_setopt($handle, CURLOPT_PROXY, $host);
409
410
            curl_setopt(
411
                $handle,
412
                CURLOPT_PROXYTYPE,
413
                (1 == $type) ? CURLPROXY_HTTP : CURLPROXY_SOCKS5
414
            );
415
416
            curl_setopt($handle, CURLOPT_PROXYPORT, $port);
417
            if (!empty($auth)) {
418
                curl_setopt($handle, CURLOPT_PROXYUSERPWD, $auth);
419
            }
420
        }
421
    }
422
423
424
    /**
425
     * Set http referrer url
426
     *
427
     * @param   string  $url
428
     */
429
    public function setReferrer($url = null)
430
    {
431
        $handle = $this->getHandle();
432
433
        if (!empty($url)) {
434
            curl_setopt($handle, CURLOPT_REFERER, $url);
435
        }
436
    }
437
438
439
    /**
440
     * Enable or disable ssl verify function
441
     *
442
     * Ssl verify is enabled by curl in default.
443
     *
444
     * @param   boolean $enable
445
     */
446
    public function setSslVerify($enable = true)
447
    {
448
        $handle = $this->getHandle();
449
450
        curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, $enable);
451
        curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, $enable);
452
    }
453
454
455
    /**
456
     * Set browser agent option
457
     *
458
     * @param   string  $userAgent
459
     */
460
    public function setUserAgent($userAgent = 'curl')
461
    {
462
        $handle = $this->getHandle();
463
464
        curl_setopt($handle, CURLOPT_USERAGENT, $userAgent);
465
    }
466
}
467