Issues (6)

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/Drest/Manager/Representation.php (1 issue)

Labels
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
 * This file is part of the Drest package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author Lee Davis
9
 * @copyright Copyright (c) Lee Davis <@leedavis81>
10
 * @link https://github.com/leedavis81/drest/blob/master/LICENSE
11
 * @license http://opensource.org/licenses/MIT The MIT X License (MIT)
12
 */
13
namespace Drest\Manager;
14
15
use Drest\EntityManagerRegistry;
16
use Drest\Mapping\RouteMetaData;
17
use Drest\Configuration;
18
use Drest\Query\ExposeFields;
19
use DrestCommon\Representation\RepresentationException;
20
use DrestCommon\Representation\UnableToMatchRepresentationException;
21
use DrestCommon\Representation\AbstractRepresentation;
22
use DrestCommon\Request\Request;
23
24
class Representation
25
{
26
27
    /**
28
     * Drest configuration object - referenced to same instance used in Manager
29
     * @var Configuration $config
30
     */
31
    protected $config;
32
33
    /**
34
     * A request instance for inspection
35
     * Reset on each getDeterminedRepresentation()
36
     * @var Request $request
37
     */
38
    protected $request;
39
40
    /**
41
     * Doctrine Entity Manager Registry
42
     * @var EntityManagerRegistry $emr
43
     */
44
    protected $emr;
45
46
    /**
47
     * @param Configuration $config
48
     */
49 31
    public function __construct(Configuration &$config)
50
    {
51 31
        $this->config = &$config;
52 31
    }
53
54
    /**
55
     * Static call to create a representation instance
56
     * @param Configuration $config
57
     * @return Representation
58
     */
59 31
    public static function create(Configuration &$config)
60
    {
61 31
        return new self($config);
62
    }
63
64
    /**
65
     * @param Request $request
66
     * @param RouteMetaData $route
67
     * @param EntityManagerRegistry $emr
68
     * @return AbstractRepresentation
69
     */
70 25
    public function handleExposureSettingsFromHttpMethod($request, $route, EntityManagerRegistry $emr)
71
    {
72 25
        $this->emr = $emr;
73 25
        $this->request = $request;
74
75 25
        $representation = $this->getDeterminedRepresentation($request, $route);
76
77
        // If expose setting lookup isn't disabled, determine it
78 25
        if (!$route->isExposeDisabled())
0 ignored issues
show
It seems like $route is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
79 25
        {
80 25
            switch ($request->getHttpMethod())
81
            {
82
                // Match on content option
83 25
                case Request::METHOD_GET:
84 18
                    $this->handlePullExposureConfiguration($route);
85 18
                    break;
86
                // Match on content-type
87 7
                case Request::METHOD_POST:
88 7
                case Request::METHOD_PUT:
89 7
                case Request::METHOD_PATCH:
90 3
                    $representation = $this->handlePushExposureConfiguration($route, $representation);
91 3
                    break;
92 25
            }
93 25
        }
94
95 25
        return $representation;
96
    }
97
98
    /**
99
     * Detect an instance of a representation class using a matched route, or default representation classes
100
     * @param  Request                      $request
101
     * @param  RouteMetaData                $route
102
     * @throws UnableToMatchRepresentationException
103
     * @throws RepresentationException              - if unable to instantiate a representation object from config settings
104
     * @return AbstractRepresentation               $representation
105
     */
106 26
    public function getDeterminedRepresentation(Request $request, RouteMetaData &$route = null)
107
    {
108 26
        $this->request = $request;
109
110 26
        if (($representations = $this->getRepresentationClasses($route)) === []) {
111
            $name = (is_null($route)) ? '"unknown name"' : $route->getName();
112
            $className = (is_null($route)) ? '"unknown class"' : $route->getClassMetaData()->getClassName();
113
            throw RepresentationException::noRepresentationsSetForRoute(
114
                $name,
115
                $className
116
            );
117
        }
118
119 26
        if (($representation = $this->searchAndValidateRepresentations($representations)) !== null) {
120 26
            return $representation;
121
        }
122
123
        // We have no representation instances from either annotations or config object
124
        throw UnableToMatchRepresentationException::noMatch();
125
    }
126
127
128
    /**
129
     * Handle a pull requests' exposure configuration (GET)
130
     * @param RouteMetaData          $route (referenced object)
131
     */
132 18
    protected function handlePullExposureConfiguration(RouteMetaData &$route)
133
    {
134 18
        $route->setExpose(
135 18
            ExposeFields::create($route)
136 18
                ->configureExposeDepth(
137 18
                    $this->emr,
138 18
                    $this->config->getExposureDepth(),
139 18
                    $this->config->getExposureRelationsFetchType()
140 18
                )
141 18
                ->configurePullRequest($this->config->getExposeRequestOptions(), $this->request)
142 18
                ->toArray()
143 18
        );
144 18
    }
145
146
    /**
147
     * Handle a push requests' exposure configuration (POST/PUT/PATCH)
148
     * @param  RouteMetaData          $route          - the matched route
149
     * @param  AbstractRepresentation $representation - the representation class to be used
150
     * @return AbstractRepresentation $representation
151
     */
152 3
    protected function handlePushExposureConfiguration(RouteMetaData $route, AbstractRepresentation $representation)
153
    {
154 3
        $representation = $representation::createFromString($this->request->getBody());
155
        // Write the filtered expose data
156 3
        $representation->write(
157 3
            ExposeFields::create($route)
158 3
                ->configureExposeDepth(
159 3
                    $this->emr,
160 3
                    $this->config->getExposureDepth(),
161 3
                    $this->config->getExposureRelationsFetchType()
162 3
                )
163 3
                ->configurePushRequest($representation->toArray())
164 3
        );
165
166 3
        return $representation;
167
    }
168
169
    /**
170
     * Get representation options. Determined from route or config
171
     * @param RouteMetaData|null $route
172
     * @return array
173
     */
174 26
    protected function getRepresentationClasses(RouteMetaData &$route = null)
175
    {
176 26
        return (is_null($route) || [] === $route->getClassMetaData()->getRepresentations())
177 26
            ? $this->config->getDefaultRepresentations()
178 26
            : $route->getClassMetaData()->getRepresentations();
179
    }
180
181
182
    /**
183
     * Iterate through an array of representations and return a match
184
     * @param array $representations
185
     * @return AbstractRepresentation|null
186
     * @throws RepresentationException
187
     * @throws UnableToMatchRepresentationException
188
     */
189 26
    protected function searchAndValidateRepresentations(array $representations)
190
    {
191 26
        $representationObjects = [];
192 26
        foreach ($representations as $representation) {
193 26
            if (($representationObj = $this->matchRepresentation($representation, $representationObjects)) instanceof AbstractRepresentation)
194 26
            {
195 17
                return $representationObj;
196
            }
197 22
        }
198
199
        // For get requests with "415 for no media match" set on, throw an exception
200 9
        if ($this->request->getHttpMethod() == Request::METHOD_GET && $this->config->get415ForNoMediaMatchSetting()) {
201
            throw UnableToMatchRepresentationException::noMatch();
202
        }
203
204
        // Return the first instantiated representation instance
205 9
        if (isset($representationObjects[0])) {
206 9
            return $representationObjects[0];
207
        }
208
209
        return null;
210
    }
211
212
213
    /**
214
     * Attempt to match a representation
215
     *
216
     * @param AbstractRepresentation|string $representation
217
     * @param array $representationObjects
218
     * @return AbstractRepresentation|null
219
     * @throws RepresentationException
220
     */
221 26
    protected function matchRepresentation($representation, array &$representationObjects)
222
    {
223 26
        if (!is_object($representation)) {
224 26
            $className = $this->getRepresentationClassName($representation);
225 26
            $representationObjects[] = $representation = new $className();
226 26
        }
227 26
        if (!$representation instanceof AbstractRepresentation) {
228
            throw RepresentationException::representationMustBeInstanceOfDrestRepresentation();
229
        }
230
231 26
        if (($representation = $this->determineRepresentationByHttpMethod($representation, $this->config->getDetectContentOptions())) !== null)
232 26
        {
233 17
            return $representation;
234
        }
235 22
        return null;
236
    }
237
238
    /**
239
     * Determine the representation by inspecting the HTTP method
240
     * @param AbstractRepresentation $representation
241
     * @param array $detectContentOptions - Eg array(self::DETECT_CONTENT_HEADER => 'Accept')
242
     * @return AbstractRepresentation|null
243
     */
244 26
    protected function determineRepresentationByHttpMethod(AbstractRepresentation $representation, array $detectContentOptions = [])
245
    {
246 26
        switch ($this->request->getHttpMethod()) {
247
            // Match on content option
248 26
            case Request::METHOD_GET:
249
                // This representation matches the required media type requested by the client
250 19
                if ($representation->isExpectedContent($detectContentOptions, $this->request)) {
251 16
                    return $representation;
252
                }
253 16
                break;
254
            // Match on content-type
255 7
            case Request::METHOD_POST:
256 7
            case Request::METHOD_PUT:
257 7
            case Request::METHOD_PATCH:
258 3
                if ($representation->getContentType() === $this->request->getHeaders('Content-Type')) {
259 1
                    return $representation;
260
                }
261 2
                break;
262 22
        }
263 22
        return null;
264
    }
265
266
267
    /**
268
     * Get's the representation class name.
269
     * Removes any root NS chars
270
     * Falls back to a DrestCommon Representation lookup
271
     *
272
     * @param string $representation
273
     * @return string
274
     * @throws RepresentationException
275
     */
276 26
    protected function getRepresentationClassName($representation)
277
    {
278 26
        $className = (strstr($representation, '\\') !== false)
279 26
            ? '\\' . ltrim($representation, '\\')
280 26
            : $representation;
281 26
        $className = (!class_exists($className))
282 26
            ? '\\DrestCommon\\Representation\\' . ltrim($className, '\\')
283 26
            : $className;
284 26
        if (!class_exists($className)) {
285
            throw RepresentationException::unknownRepresentationClass($representation);
286
        }
287 26
        return $className;
288
    }
289
}