Issues (13)

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.

sources/lib/ModelLayer/ModelLayer.php (1 issue)

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
 * This file is part of the PommProject/ModelManager package.
4
 *
5
 * (c) 2014 - 2015 Grégoire HUBERT <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace PommProject\ModelManager\ModelLayer;
11
12
use PommProject\Foundation\Client\Client;
13
use PommProject\Foundation\Client\ClientInterface;
14
use PommProject\Foundation\Session\Connection;
15
use PommProject\Foundation\Session\ResultHandler;
16
use PommProject\ModelManager\Exception\ModelLayerException;
17
use PommProject\ModelManager\Model\Model;
18
19
/**
20
 * ModelLayer
21
 *
22
 * ModelLayer handles mechanisms around model method calls (transactions,
23
 * events etc.).
24
 *
25
 * @package     ModelManager
26
 * @copyright   2014 - 2015 Grégoire HUBERT
27
 * @author      Grégoire HUBERT
28
 * @license     X11 {@link http://opensource.org/licenses/mit-license.php}
29
 * @see         Client
30
 */
31
abstract class ModelLayer extends Client
32
{
33
    /**
34
     * getClientType
35
     *
36
     * @see ClientInterface
37
     */
38
    public function getClientType()
39
    {
40
        return 'model_layer';
41
    }
42
43
    /**
44
     * getClientIdentifier
45
     *
46
     * @see ClientInterface
47
     */
48
    public function getClientIdentifier()
49
    {
50
        return get_class($this);
51
    }
52
53
    /**
54
     * shutdown
55
     *
56
     * @see ClientInterface
57
     */
58
    public function shutdown()
59
    {
60
    }
61
62
    /**
63
     * startTransaction
64
     *
65
     * Start a new transaction.
66
     *
67
     * @access protected
68
     * @return ModelLayer $this
69
     */
70
    protected function startTransaction()
71
    {
72
        $this->executeAnonymousQuery('begin transaction');
73
74
        return $this;
75
    }
76
77
    /**
78
     * setDeferrable
79
     *
80
     * Set given constraints to deferred/immediate in the current transaction.
81
     * This applies to constraints being deferrable or deferred by default.
82
     * If the keys is an empty arrays, ALL keys will be set at the given state.
83
     * @see http://www.postgresql.org/docs/9.0/static/sql-set-constraints.html
84
     *
85
     * @access protected
86
     * @param  array      $keys
87
     * @param  string     $state
88
     * @throws  ModelLayerException if not valid state
89
     * @return ModelLayer $this
90
     */
91
    protected function setDeferrable(array $keys, $state)
92
    {
93
        if (count($keys) === 0) {
94
            $string = 'ALL';
95
        } else {
96
            $string = join(
97
                ', ',
98
                array_map(
99
                    function ($key) {
100
                        $parts = explode('.', $key);
101
                        $escaped_parts = [];
102
103
                        foreach ($parts as $part) {
104
                            $escaped_parts[] = $this->escapeIdentifier($part);
105
                        }
106
107
                        return join('.', $escaped_parts);
108
                    },
109
                    $keys
110
                )
111
            );
112
        }
113
114
        if (!in_array($state, [ Connection::CONSTRAINTS_DEFERRED, Connection::CONSTRAINTS_IMMEDIATE ])) {
115
            throw new ModelLayerException(
116
                sprintf(<<<EOMSG
117
'%s' is not a valid constraint modifier.
118
Use Connection::CONSTRAINTS_DEFERRED or Connection::CONSTRAINTS_IMMEDIATE.
119
EOMSG
120
,
121
                    $state
122
                )
123
            );
124
        }
125
126
        $this->executeAnonymousQuery(
127
            sprintf(
128
                "set constraints %s %s",
129
                $string,
130
                $state
131
            )
132
        );
133
134
        return $this;
135
    }
136
137
    /**
138
     * setTransactionIsolationLevel
139
     *
140
     * Transaction isolation level tells PostgreSQL how to manage with the
141
     * current transaction. The default is "READ COMMITTED".
142
     * @see http://www.postgresql.org/docs/9.0/static/sql-set-transaction.html
143
     *
144
     * @access protected
145
     * @param   string     $isolation_level
146
     * @throws  ModelLayerException if not valid isolation level
147
     * @return  ModelLayer $this
148
     */
149 View Code Duplication
    protected function setTransactionIsolationLevel($isolation_level)
150
    {
151
        $valid_isolation_levels =
152
            [
153
                Connection::ISOLATION_READ_COMMITTED,
154
                Connection::ISOLATION_REPEATABLE_READ,
155
                Connection::ISOLATION_SERIALIZABLE
156
            ];
157
158
        if (!in_array(
159
            $isolation_level,
160
            $valid_isolation_levels
161
        )) {
162
            throw new ModelLayerException(
163
                sprintf(
164
                    "'%s' is not a valid transaction isolation level. Valid isolation levels are {%s} see Connection class constants.",
165
                    $isolation_level,
166
                    join(', ', $valid_isolation_levels)
167
                )
168
            );
169
        }
170
171
        return $this->sendParameter(
172
            "set transaction isolation level %s",
173
            $isolation_level
174
        );
175
    }
176
177
    /**
178
     * setTransactionAccessMode
179
     *
180
     * Transaction access modes tell PostgreSQL if transaction are able to
181
     * write or read only.
182
     * @see http://www.postgresql.org/docs/9.0/static/sql-set-transaction.html
183
     *
184
     * @access protected
185
     * @param   string     $access_mode
186
     * @throws  ModelLayerException if not valid access mode
187
     * @return  ModelLayer $this
188
     */
189 View Code Duplication
    protected function setTransactionAccessMode($access_mode)
190
    {
191
        $valid_access_modes =
192
            [
193
                Connection::ACCESS_MODE_READ_ONLY,
194
                Connection::ACCESS_MODE_READ_WRITE
195
            ];
196
197
        if (!in_array(
198
            $access_mode,
199
            $valid_access_modes
200
        )) {
201
            throw new ModelLayerException(
202
                sprintf(
203
                    "'%s' is not a valid transaction access mode. Valid access modes are {%s}, see Connection class constants.",
204
                    $access_mode,
205
                    join(', ', $valid_access_modes)
206
                )
207
            );
208
        }
209
210
        return $this->sendParameter(
211
            "set transaction %s",
212
            $access_mode
213
        );
214
    }
215
216
    /**
217
     * setSavePoint
218
     *
219
     * Set a savepoint in a transaction.
220
     *
221
     * @access protected
222
     * @param  string     $name
223
     * @return ModelLayer $this
224
     */
225
    protected function setSavepoint($name)
226
    {
227
        return $this->sendParameter(
228
            "savepoint %s",
229
            $this->escapeIdentifier($name)
230
        );
231
    }
232
233
    /**
234
     * releaseSavepoint
235
     *
236
     * Drop a savepoint.
237
     *
238
     * @access protected
239
     * @param  string     $name
240
     * @return ModelLayer $this
241
     */
242
    protected function releaseSavepoint($name)
243
    {
244
        return $this->sendParameter(
245
            "release savepoint %s",
246
            $this->escapeIdentifier($name)
247
        );
248
    }
249
250
    /**
251
     * rollbackTransaction
252
     *
253
     * Rollback a transaction. If a name is specified, the transaction is
254
     * rollback to the given savepoint. Otherwise, the whole transaction is
255
     * rollback.
256
     *
257
     * @access protected
258
     * @param  string|null $name
259
     * @return ModelLayer  $this
260
     */
261
    protected function rollbackTransaction($name = null)
262
    {
263
        $sql = "rollback transaction";
264
        if ($name !== null) {
265
            $sql = sprintf("rollback to savepoint %s", $this->escapeIdentifier($name));
266
        }
267
268
        $this->executeAnonymousQuery($sql);
269
270
        return $this;
271
    }
272
273
    /**
274
     * commitTransaction
275
     *
276
     * Commit a transaction.
277
     *
278
     * @access protected
279
     * @return ModelLayer $this
280
     */
281
    protected function commitTransaction()
282
    {
283
        $this->executeAnonymousQuery('commit transaction');
284
285
        return $this;
286
    }
287
288
    /**
289
     * isInTransaction
290
     *
291
     * Tell if a transaction is open or not.
292
     *
293
     * @see    Cient
294
     * @access protected
295
     * @return bool
296
     */
297
    protected function isInTransaction()
298
    {
299
        $status = $this
300
            ->getSession()
301
            ->getConnection()
302
            ->getTransactionStatus()
303
            ;
304
305
        return (bool) ($status === \PGSQL_TRANSACTION_INTRANS || $status === \PGSQL_TRANSACTION_INERROR || $status === \PGSQL_TRANSACTION_ACTIVE);
306
    }
307
308
    /**
309
     * isTransactionOk
310
     *
311
     * In PostgreSQL, an error during a transaction cancels all the queries and
312
     * rollback the transaction on commit. This method returns the current
313
     * transaction's status. If no transactions are open, it returns null.
314
     *
315
     * @access public
316
     * @return bool|null
317
     */
318
    protected function isTransactionOk()
319
    {
320
        if (!$this->isInTransaction()) {
321
            return null;
322
        }
323
324
        $status = $this
325
            ->getSession()
326
            ->getConnection()
327
            ->getTransactionStatus()
328
            ;
329
330
        return (bool) ($status === \PGSQL_TRANSACTION_INTRANS);
331
    }
332
333
    /**
334
     * sendNotify
335
     *
336
     * Send a NOTIFY event to the database server. An optional data can be sent
337
     * with the notification.
338
     *
339
     * @access protected
340
     * @param  string     $channel
341
     * @param  string     $data
342
     * @return ModelLayer $this
343
     */
344
    protected function sendNotify($channel, $data = '')
345
    {
346
        return $this->sendParameter(
347
            'notify %s, %s',
348
            $channel,
349
            $this->escapeLiteral($data)
350
        );
351
    }
352
353
    /**
354
     * executeAnonymousQuery
355
     *
356
     * Proxy to Connection::executeAnonymousQuery()
357
     *
358
     * @access protected
359
     * @param  string        $sql
360
     * @return ResultHandler
361
     */
362
    protected function executeAnonymousQuery($sql)
363
    {
364
        return $this
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->getSession()->get...teAnonymousQuery($sql); of type PommProject\Foundation\Session\ResultHandler|array adds the type array to the return on line 364 which is incompatible with the return type documented by PommProject\ModelManager...::executeAnonymousQuery of type PommProject\Foundation\Session\ResultHandler.
Loading history...
365
            ->getSession()
366
            ->getConnection()
367
            ->executeAnonymousQuery($sql)
368
            ;
369
    }
370
371
    /**
372
     * escapeIdentifier
373
     *
374
     * Proxy to Connection::escapeIdentifier()
375
     *
376
     * @access protected
377
     * @param  string $string
378
     * @return string
379
     */
380
    protected function escapeIdentifier($string)
381
    {
382
        return $this
383
            ->getSession()
384
            ->getConnection()
385
            ->escapeIdentifier($string)
386
            ;
387
    }
388
389
    /**
390
     * escapeLiteral
391
     *
392
     * Proxy to Connection::escapeLiteral()
393
     *
394
     * @access protected
395
     * @param  string $string
396
     * @return string
397
     */
398
    protected function escapeLiteral($string)
399
    {
400
        return $this
401
            ->getSession()
402
            ->getConnection()
403
            ->escapeLiteral($string)
404
            ;
405
    }
406
407
    /**
408
     * getModel
409
     *
410
     * Proxy to Session::getModel();
411
     *
412
     * @access protected
413
     * @param  string    model identifier
414
     * @return Model
415
     */
416
    protected function getModel($identifier)
417
    {
418
        return $this
419
            ->getSession()
420
            ->getClientUsingPooler('model', $identifier);
421
    }
422
423
    /**
424
     * sendParameter
425
     *
426
     * Send a parameter to the server.
427
     * The parameter MUST have been properly checked and escaped if needed as
428
     * it is going to be passed AS IS to the server. Sending untrusted
429
     * parameters may lead to potential SQL injection.
430
     *
431
     * @access private
432
     * @param  string     $sql
433
     * @param  string     $identifier
434
     * @param  string     $parameter
435
     * @return ModelLayer $this
436
     */
437
    private function sendParameter($sql, $identifier, $parameter = null)
438
    {
439
        $this
440
            ->executeAnonymousQuery(
441
                sprintf(
442
                    $sql,
443
                    $identifier,
444
                    $parameter
445
                )
446
            );
447
448
        return $this;
449
    }
450
}
451