Issues (65)

Security Analysis    no request data  

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/Phossa2/Config/Config.php (1 issue)

Severity

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
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Config
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Config;
16
17
use Phossa2\Shared\Tree\Tree;
18
use Phossa2\Config\Message\Message;
19
use Phossa2\Config\Loader\DummyLoader;
20
use Phossa2\Shared\Tree\TreeInterface;
21
use Phossa2\Shared\Base\ObjectAbstract;
22
use Phossa2\Config\Traits\WritableTrait;
23
use Phossa2\Config\Traits\ArrayAccessTrait;
24
use Phossa2\Shared\Reference\ReferenceTrait;
25
use Phossa2\Config\Exception\LogicException;
26
use Phossa2\Config\Interfaces\ConfigInterface;
27
use Phossa2\Config\Loader\ConfigLoaderInterface;
28
use Phossa2\Shared\Reference\ReferenceInterface;
29
use Phossa2\Config\Interfaces\WritableInterface;
30
use Phossa2\Shared\Delegator\DelegatorAwareTrait;
31
use Phossa2\Shared\Delegator\DelegatorAwareInterface;
32
33
/**
34
 * Config
35
 *
36
 * @package Phossa2\Config
37
 * @author  Hong Zhang <[email protected]>
38
 * @see     ObjectAbstract
39
 * @see     ConfigInterface
40
 * @see     WritableInterface
41
 * @see     \ArrayAccess
42
 * @see     ReferenceInterface
43
 * @see     DelegatorAwareInterface
44
 * @version 2.1.0
45
 * @since   2.0.0 added
46
 * @since   2.0.7 changed DelegatorAware* stuff
47
 * @since   2.0.10 using recursive getDelegator
48
 * @since   2.0.12 changed `set()` return value
49
 */
50
class Config extends ObjectAbstract implements ConfigInterface, WritableInterface, \ArrayAccess, ReferenceInterface, DelegatorAwareInterface
51
{
52
    use ReferenceTrait, DelegatorAwareTrait, ArrayAccessTrait, WritableTrait;
53
54
    /**
55
     * error type
56
     *
57
     * @var    int
58
     */
59
    const ERROR_IGNORE    = 0;
60
    const ERROR_WARNING   = 1;
61
    const ERROR_EXCEPTION = 2;
62
63
    /**
64
     * the config loader
65
     *
66
     * @var    ConfigLoaderInterface
67
     * @access protected
68
     */
69
    protected $loader;
70
71
    /**
72
     * the config tree
73
     *
74
     * @var    TreeInterface
75
     * @access protected
76
     */
77
    protected $config;
78
79
    /**
80
     * cache loaded group names
81
     *
82
     * @var    array
83
     * @access protected
84
     */
85
    protected $loaded = [];
86
87
    /**
88
     * How to dealing with error, ignore/trigger_error/exception etc.
89
     *
90
     * @var    int
91
     * @access protected
92
     */
93
    protected $error_type = self::ERROR_WARNING;
94
95
    /**
96
     * @var    string
97
     * @access private
98
     */
99
    private $cached_id;
100
101
    /**
102
     * @var    mixed
103
     * @access private
104
     */
105
    private $cached_value;
106
107
    /**
108
     * Constructor
109
     *
110
     * @param  ConfigLoaderInterface $loader config loader if any
111
     * @param  TreeInterface $configTree config tree if any
112
     * @param  array $configData config data for the tree
113
     * @access public
114
     * @api
115
     */
116
    public function __construct(
117
        ConfigLoaderInterface $loader = null,
118
        TreeInterface $configTree = null,
119
        array $configData = []
120
    ) {
121
        $this->loader = $loader ?: new DummyLoader();
122
        $this->config = $configTree ?: new Tree($configData);
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function get(/*# string */ $id, $default = null)
129
    {
130
        if ($this->has($id)) {
131
            // cached from has()
132
            $val = $this->cached_value;
133
134
            // dereference
135
            $this->deReferenceArray($val);
136
137
            return null === $val ? $default : $val;
138
        }
139
        return $default;
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145
    public function has(/*# string */ $id)/*# : bool */
146
    {
147
        // checked already
148
        if ($id === $this->cached_id) {
149
            return null !== $this->cached_value;
150
        }
151
152
        // default result
153
        $this->cached_id = $id;
154
        $this->cached_value = null;
155
156
        // try get config
157
        try {
158
            $this->loadConfig((string) $id);
159
            $this->cached_value = $this->config->getNode((string) $id);
160
            return null !== $this->cached_value;
161
        } catch (\Exception $e) {
162
            $this->throwError($e->getMessage(), $e->getCode());
163
            return false;
164
        }
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     */
170
    public function set(/*# string */ $id, $value)/*# : bool */
171
    {
172
        if ($this->isWritable()) {
173
            // lazy load, no dereference
174
            $this->loadConfig((string) $id);
175
176
            // replace the node
177
            $this->cached_id = null;
178
            $this->config->addNode($id, $value);
179
180
            return $this->has($id);
181
        } else {
182
            $this->throwError(
183
                Message::get(Message::CONFIG_NOT_WRITABLE),
184
                Message::CONFIG_NOT_WRITABLE
185
            );
186
        }
187
    }
188
189
    /**
190
     * Set error type
191
     *
192
     * @param  int $type
193
     * @return $this
194
     * @access public
195
     * @api
196
     */
197
    public function setErrorType(/*# int */ $type)
198
    {
199
        $this->error_type = (int) $type;
200
        return $this;
201
    }
202
203
    /**
204
     * Load config
205
     *
206
     * @param  string $id
207
     * @return $this
208
     * @throws LogicException if current $error_type is to throw exception
209
     * @access protected
210
     */
211
    protected function loadConfig(/*# string */ $id)
212
    {
213
        // get group name
214
        $group = $this->getGroupName($id);
215
216
        // $group loaded ?
217
        if (isset($this->loaded[$group])) {
218
            return $this;
219
        }
220
221
        // mark as loaded
222
        $this->loaded[$group] = true;
223
224
        // loading the group
225
        return $this->loadByGroup($group);
226
    }
227
228
    /**
229
     * Load one group config, force loading all groups if $group == ''
230
     *
231
     * @param  string $group
232
     * @return $this
233
     * @throws \Exception group loading issues
234
     * @access protected
235
     */
236
    protected function loadByGroup(/*# string */ $group)
237
    {
238
        // load super global
239
        if ('' !== $group && '_' === $group[0]) {
240
            return $this->loadGlobal($group);
241
        }
242
243
        // load from config
244
        $conf = $this->loader->load($group);
245
246
        foreach ($conf as $grp => $data) {
247
            $this->config->addNode($grp, $data);
248
        }
249
250
        return $this;
251
    }
252
253
    /**
254
     * Load super globals
255
     *
256
     * @param  string $group
257
     * @return $this
258
     * @throws LogicException if super global unknown
259
     * @access protected
260
     */
261
    protected function loadGlobal(/*# string */ $group)
0 ignored issues
show
loadGlobal uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
262
    {
263
        if (!isset($GLOBALS[$group])) {
264
            $this->throwError(
265
                Message::get(Message::CONFIG_GLOBAL_UNKNOWN, $group),
266
                Message::CONFIG_GLOBAL_UNKNOWN
267
            );
268
        }
269
270
        // load super global
271
        $this->config->addNode($group, $GLOBALS[$group]);
272
273
        return $this;
274
    }
275
276
    /**
277
     * Get group name
278
     *
279
     * - returns 'system' from $id 'system.dir.tmp'
280
     * - '.system.tmpdir' is invalid
281
     *
282
     * @param  string $id
283
     * @return string
284
     * @access protected
285
     */
286
    protected function getGroupName(/*# string */ $id)/*# : string */
287
    {
288
        return explode(
289
            $this->config->getDelimiter(),
290
            ltrim($id, $this->config->getDelimiter())
291
        )[0];
292
    }
293
294
    /**
295
     * Override 'referenceLookup()' in ReferenceTrait.
296
     *
297
     * Delegator support goes here
298
     *
299
     * @since 2.0.10 using recursive getDelegator
300
     * {@inheritDoc}
301
     */
302
    protected function referenceLookup(/*# string */ $name)
303
    {
304
        if ($this->hasDelegator()) {
305
            // get delegator recursively
306
            $delegator = $this->getDelegator(true);
307
            $val = $delegator->get($name);
308
        } else {
309
            $val = $this->getReference($name);
310
        }
311
        return $val;
312
    }
313
314
    /**
315
     * throw exception if current $error_type is to throw exception
316
     *
317
     * {@inheritDoc}
318
     */
319
    protected function resolveUnknown(/*# string */ $name)
320
    {
321
        // warn if reference unknown
322
        $this->throwError(
323
            Message::get(Message::CONFIG_REFERENCE_UNKNOWN, $name),
324
            Message::CONFIG_REFERENCE_UNKNOWN
325
        );
326
327
        return null;
328
    }
329
330
    /**
331
     * {@inheritDoc}
332
     */
333
    protected function getReference(/*# string */ $name)
334
    {
335
        return $this->get($name);
336
    }
337
338
    /**
339
     * Dealing errors
340
     *
341
     * @param  string $message
342
     * @param  int $code
343
     * @return $this
344
     * @throws LogicException if current $error_type is to throw exception
345
     * @access protected
346
     */
347
    protected function throwError(/*# string */ $message, /*# int */ $code)
348
    {
349
        switch ($this->error_type) {
350
            case self::ERROR_WARNING:
351
                trigger_error($message, \E_USER_WARNING);
352
                break;
353
            case self::ERROR_EXCEPTION:
354
                throw new LogicException($message, $code);
355
            default:
356
                break;
357
        }
358
        return $this;
359
    }
360
}
361