Issues (1844)

Security Analysis    not enabled

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

  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.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  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.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  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.
  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.
  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.
  Header Injection
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.

vendor/composer/ClassLoader.php (4 issues)

1
<?php
2
3
/*
4
 * This file is part of Composer.
5
 *
6
 * (c) Nils Adermann <[email protected]>
7
 *     Jordi Boggiano <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Composer\Autoload;
14
15
/**
16
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
 *
18
 *     $loader = new \Composer\Autoload\ClassLoader();
19
 *
20
 *     // register classes with namespaces
21
 *     $loader->add('Symfony\Component', __DIR__.'/component');
22
 *     $loader->add('Symfony',           __DIR__.'/framework');
23
 *
24
 *     // activate the autoloader
25
 *     $loader->register();
26
 *
27
 *     // to enable searching the include path (eg. for PEAR packages)
28
 *     $loader->setUseIncludePath(true);
29
 *
30
 * In this example, if you try to use a class in the Symfony\Component
31
 * namespace or one of its children (Symfony\Component\Console for instance),
32
 * the autoloader will first look for the class under the component/
33
 * directory, and it will then fallback to the framework/ directory if not
34
 * found before giving up.
35
 *
36
 * This class is loosely based on the Symfony UniversalClassLoader.
37
 *
38
 * @author Fabien Potencier <[email protected]>
39
 * @author Jordi Boggiano <[email protected]>
40
 * @see    https://www.php-fig.org/psr/psr-0/
41
 * @see    https://www.php-fig.org/psr/psr-4/
42
 */
43
class ClassLoader
44
{
45
    /** @var ?string */
46
    private $vendorDir;
47
48
    // PSR-4
49
    /**
50
     * @var array[]
51
     * @psalm-var array<string, array<string, int>>
52
     */
53
    private $prefixLengthsPsr4 = array();
54
    /**
55
     * @var array[]
56
     * @psalm-var array<string, array<int, string>>
57
     */
58
    private $prefixDirsPsr4 = array();
59
    /**
60
     * @var array[]
61
     * @psalm-var array<string, string>
62
     */
63
    private $fallbackDirsPsr4 = array();
64
65
    // PSR-0
66
    /**
67
     * @var array[]
68
     * @psalm-var array<string, array<string, string[]>>
69
     */
70
    private $prefixesPsr0 = array();
71
    /**
72
     * @var array[]
73
     * @psalm-var array<string, string>
74
     */
75
    private $fallbackDirsPsr0 = array();
76
77
    /** @var bool */
78
    private $useIncludePath = false;
79
80
    /**
81
     * @var string[]
82
     * @psalm-var array<string, string>
83
     */
84
    private $classMap = array();
85
86
    /** @var bool */
87
    private $classMapAuthoritative = false;
88
89
    /**
90
     * @var bool[]
91
     * @psalm-var array<string, bool>
92
     */
93
    private $missingClasses = array();
94
95
    /** @var ?string */
96
    private $apcuPrefix;
97
98
    /**
99
     * @var self[]
100
     */
101
    private static $registeredLoaders = array();
102
103
    /**
104
     * @param ?string $vendorDir
105
     */
106
    public function __construct($vendorDir = null)
107
    {
108
        $this->vendorDir = $vendorDir;
109
    }
110
111
    /**
112
     * @return string[]
113
     */
114
    public function getPrefixes()
115
    {
116
        if (!empty($this->prefixesPsr0)) {
117
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
118
        }
119
120
        return array();
121
    }
122
123
    /**
124
     * @return array[]
125
     * @psalm-return array<string, array<int, string>>
126
     */
127
    public function getPrefixesPsr4()
128
    {
129
        return $this->prefixDirsPsr4;
130
    }
131
132
    /**
133
     * @return array[]
134
     * @psalm-return array<string, string>
135
     */
136
    public function getFallbackDirs()
137
    {
138
        return $this->fallbackDirsPsr0;
139
    }
140
141
    /**
142
     * @return array[]
143
     * @psalm-return array<string, string>
144
     */
145
    public function getFallbackDirsPsr4()
146
    {
147
        return $this->fallbackDirsPsr4;
148
    }
149
150
    /**
151
     * @return string[] Array of classname => path
152
     * @psalm-var array<string, string>
153
     */
154
    public function getClassMap()
155
    {
156
        return $this->classMap;
157
    }
158
159
    /**
160
     * @param string[] $classMap Class to filename map
161
     * @psalm-param array<string, string> $classMap
162
     *
163
     * @return void
164
     */
165
    public function addClassMap(array $classMap)
166
    {
167
        if ($this->classMap) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->classMap of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
168
            $this->classMap = array_merge($this->classMap, $classMap);
169
        } else {
170
            $this->classMap = $classMap;
171
        }
172
    }
173
174
    /**
175
     * Registers a set of PSR-0 directories for a given prefix, either
176
     * appending or prepending to the ones previously set for this prefix.
177
     *
178
     * @param string          $prefix  The prefix
179
     * @param string[]|string $paths   The PSR-0 root directories
180
     * @param bool            $prepend Whether to prepend the directories
181
     *
182
     * @return void
183
     */
184
    public function add($prefix, $paths, $prepend = false)
185
    {
186
        if (!$prefix) {
187
            if ($prepend) {
188
                $this->fallbackDirsPsr0 = array_merge(
189
                    (array) $paths,
190
                    $this->fallbackDirsPsr0
191
                );
192
            } else {
193
                $this->fallbackDirsPsr0 = array_merge(
194
                    $this->fallbackDirsPsr0,
195
                    (array) $paths
196
                );
197
            }
198
199
            return;
200
        }
201
202
        $first = $prefix[0];
203
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
204
            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
205
206
            return;
207
        }
208
        if ($prepend) {
209
            $this->prefixesPsr0[$first][$prefix] = array_merge(
210
                (array) $paths,
211
                $this->prefixesPsr0[$first][$prefix]
212
            );
213
        } else {
214
            $this->prefixesPsr0[$first][$prefix] = array_merge(
215
                $this->prefixesPsr0[$first][$prefix],
216
                (array) $paths
217
            );
218
        }
219
    }
220
221
    /**
222
     * Registers a set of PSR-4 directories for a given namespace, either
223
     * appending or prepending to the ones previously set for this namespace.
224
     *
225
     * @param string          $prefix  The prefix/namespace, with trailing '\\'
226
     * @param string[]|string $paths   The PSR-4 base directories
227
     * @param bool            $prepend Whether to prepend the directories
228
     *
229
     * @throws \InvalidArgumentException
230
     *
231
     * @return void
232
     */
233
    public function addPsr4($prefix, $paths, $prepend = false)
234
    {
235
        if (!$prefix) {
236
            // Register directories for the root namespace.
237
            if ($prepend) {
238
                $this->fallbackDirsPsr4 = array_merge(
239
                    (array) $paths,
240
                    $this->fallbackDirsPsr4
241
                );
242
            } else {
243
                $this->fallbackDirsPsr4 = array_merge(
244
                    $this->fallbackDirsPsr4,
245
                    (array) $paths
246
                );
247
            }
248
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
249
            // Register directories for a new namespace.
250
            $length = strlen($prefix);
251
            if ('\\' !== $prefix[$length - 1]) {
252
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
253
            }
254
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
255
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
256
        } elseif ($prepend) {
257
            // Prepend directories for an already registered namespace.
258
            $this->prefixDirsPsr4[$prefix] = array_merge(
259
                (array) $paths,
260
                $this->prefixDirsPsr4[$prefix]
261
            );
262
        } else {
263
            // Append directories for an already registered namespace.
264
            $this->prefixDirsPsr4[$prefix] = array_merge(
265
                $this->prefixDirsPsr4[$prefix],
266
                (array) $paths
267
            );
268
        }
269
    }
270
271
    /**
272
     * Registers a set of PSR-0 directories for a given prefix,
273
     * replacing any others previously set for this prefix.
274
     *
275
     * @param string          $prefix The prefix
276
     * @param string[]|string $paths  The PSR-0 base directories
277
     *
278
     * @return void
279
     */
280
    public function set($prefix, $paths)
281
    {
282
        if (!$prefix) {
283
            $this->fallbackDirsPsr0 = (array) $paths;
0 ignored issues
show
Documentation Bug introduced by
It seems like (array)$paths of type string[] is incompatible with the declared type array<mixed,array> of property $fallbackDirsPsr0.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
284
        } else {
285
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
286
        }
287
    }
288
289
    /**
290
     * Registers a set of PSR-4 directories for a given namespace,
291
     * replacing any others previously set for this namespace.
292
     *
293
     * @param string          $prefix The prefix/namespace, with trailing '\\'
294
     * @param string[]|string $paths  The PSR-4 base directories
295
     *
296
     * @throws \InvalidArgumentException
297
     *
298
     * @return void
299
     */
300
    public function setPsr4($prefix, $paths)
301
    {
302
        if (!$prefix) {
303
            $this->fallbackDirsPsr4 = (array) $paths;
0 ignored issues
show
Documentation Bug introduced by
It seems like (array)$paths of type string[] is incompatible with the declared type array<mixed,array> of property $fallbackDirsPsr4.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
304
        } else {
305
            $length = strlen($prefix);
306
            if ('\\' !== $prefix[$length - 1]) {
307
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
308
            }
309
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
310
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
311
        }
312
    }
313
314
    /**
315
     * Turns on searching the include path for class files.
316
     *
317
     * @param bool $useIncludePath
318
     *
319
     * @return void
320
     */
321
    public function setUseIncludePath($useIncludePath)
322
    {
323
        $this->useIncludePath = $useIncludePath;
324
    }
325
326
    /**
327
     * Can be used to check if the autoloader uses the include path to check
328
     * for classes.
329
     *
330
     * @return bool
331
     */
332
    public function getUseIncludePath()
333
    {
334
        return $this->useIncludePath;
335
    }
336
337
    /**
338
     * Turns off searching the prefix and fallback directories for classes
339
     * that have not been registered with the class map.
340
     *
341
     * @param bool $classMapAuthoritative
342
     *
343
     * @return void
344
     */
345
    public function setClassMapAuthoritative($classMapAuthoritative)
346
    {
347
        $this->classMapAuthoritative = $classMapAuthoritative;
348
    }
349
350
    /**
351
     * Should class lookup fail if not found in the current class map?
352
     *
353
     * @return bool
354
     */
355
    public function isClassMapAuthoritative()
356
    {
357
        return $this->classMapAuthoritative;
358
    }
359
360
    /**
361
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
362
     *
363
     * @param string|null $apcuPrefix
364
     *
365
     * @return void
366
     */
367
    public function setApcuPrefix($apcuPrefix)
368
    {
369
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
370
    }
371
372
    /**
373
     * The APCu prefix in use, or null if APCu caching is not enabled.
374
     *
375
     * @return string|null
376
     */
377
    public function getApcuPrefix()
378
    {
379
        return $this->apcuPrefix;
380
    }
381
382
    /**
383
     * Registers this instance as an autoloader.
384
     *
385
     * @param bool $prepend Whether to prepend the autoloader or not
386
     *
387
     * @return void
388
     */
389
    public function register($prepend = false)
390
    {
391
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
392
393
        if (null === $this->vendorDir) {
394
            return;
395
        }
396
397
        if ($prepend) {
398
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
399
        } else {
400
            unset(self::$registeredLoaders[$this->vendorDir]);
401
            self::$registeredLoaders[$this->vendorDir] = $this;
402
        }
403
    }
404
405
    /**
406
     * Unregisters this instance as an autoloader.
407
     *
408
     * @return void
409
     */
410
    public function unregister()
411
    {
412
        spl_autoload_unregister(array($this, 'loadClass'));
413
414
        if (null !== $this->vendorDir) {
415
            unset(self::$registeredLoaders[$this->vendorDir]);
416
        }
417
    }
418
419
    /**
420
     * Loads the given class or interface.
421
     *
422
     * @param  string    $class The name of the class
423
     * @return true|null True if loaded, null otherwise
424
     */
425
    public function loadClass($class)
426
    {
427
        if ($file = $this->findFile($class)) {
428
            includeFile($file);
429
430
            return true;
431
        }
432
433
        return null;
434
    }
435
436
    /**
437
     * Finds the path to the file where the class is defined.
438
     *
439
     * @param string $class The name of the class
440
     *
441
     * @return string|false The path if found, false otherwise
442
     */
443
    public function findFile($class)
444
    {
445
        // class map lookup
446
        if (isset($this->classMap[$class])) {
447
            return $this->classMap[$class];
448
        }
449
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
450
            return false;
451
        }
452
        if (null !== $this->apcuPrefix) {
453
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
454
            if ($hit) {
455
                return $file;
456
            }
457
        }
458
459
        $file = $this->findFileWithExtension($class, '.php');
460
461
        // Search for Hack files if we are running on HHVM
462
        if (false === $file && defined('HHVM_VERSION')) {
463
            $file = $this->findFileWithExtension($class, '.hh');
464
        }
465
466
        if (null !== $this->apcuPrefix) {
467
            apcu_add($this->apcuPrefix.$class, $file);
468
        }
469
470
        if (false === $file) {
471
            // Remember that this class does not exist.
472
            $this->missingClasses[$class] = true;
473
        }
474
475
        return $file;
476
    }
477
478
    /**
479
     * Returns the currently registered loaders indexed by their corresponding vendor directories.
480
     *
481
     * @return self[]
482
     */
483
    public static function getRegisteredLoaders()
484
    {
485
        return self::$registeredLoaders;
486
    }
487
488
    /**
489
     * @param  string       $class
490
     * @param  string       $ext
491
     * @return string|false
492
     */
493
    private function findFileWithExtension($class, $ext)
494
    {
495
        // PSR-4 lookup
496
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
497
498
        $first = $class[0];
499
        if (isset($this->prefixLengthsPsr4[$first])) {
500
            $subPath = $class;
501
            while (false !== $lastPos = strrpos($subPath, '\\')) {
502
                $subPath = substr($subPath, 0, $lastPos);
503
                $search = $subPath . '\\';
504
                if (isset($this->prefixDirsPsr4[$search])) {
505
                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
506
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
507
                        if (file_exists($file = $dir . $pathEnd)) {
508
                            return $file;
509
                        }
510
                    }
511
                }
512
            }
513
        }
514
515
        // PSR-4 fallback dirs
516
        foreach ($this->fallbackDirsPsr4 as $dir) {
517
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
0 ignored issues
show
Are you sure $dir of type array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

517
            if (file_exists($file = /** @scrutinizer ignore-type */ $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
Loading history...
518
                return $file;
519
            }
520
        }
521
522
        // PSR-0 lookup
523
        if (false !== $pos = strrpos($class, '\\')) {
524
            // namespaced class name
525
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
526
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
527
        } else {
528
            // PEAR-like class name
529
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
530
        }
531
532
        if (isset($this->prefixesPsr0[$first])) {
533
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
534
                if (0 === strpos($class, $prefix)) {
535
                    foreach ($dirs as $dir) {
536
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
537
                            return $file;
538
                        }
539
                    }
540
                }
541
            }
542
        }
543
544
        // PSR-0 fallback dirs
545
        foreach ($this->fallbackDirsPsr0 as $dir) {
546
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
547
                return $file;
548
            }
549
        }
550
551
        // PSR-0 include paths.
552
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
553
            return $file;
554
        }
555
556
        return false;
557
    }
558
}
559
560
/**
561
 * Scope isolated include.
562
 *
563
 * Prevents access to $this/self from included files.
564
 *
565
 * @param  string $file
566
 * @return void
567
 * @private
568
 */
569
function includeFile($file)
570
{
571
    include $file;
572
}
573