Issues (3)

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/Parser/RelevantSelectorParser.php (3 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 namespace Luminaire\Premailer\Parser;
2
3
/**
4
 * Created by Sublime Text 3
5
 *
6
 * @user     Kevin Tanjung
7
 * @website  http://kevintanjung.github.io
8
 * @email    [email protected]
9
 * @date     04/08/2016
10
 * @time     09:09
11
 */
12
13
use Crossjoin\Css\Reader\CssString as StylesheetReader;
14
use Crossjoin\Css\Format\Rule\AtMedia\MediaQuery;
15
use Crossjoin\Css\Format\Rule\AtMedia\MediaRule;
16
use Crossjoin\Css\Format\Rule\Style\StyleRuleSet;
17
use Crossjoin\Css\Format\Rule\Style\StyleSelector;
18
use Illuminate\Support\Arr;
19
use InvalidArgumentException;
20
21
/**
22
 * Retrieve relevant CSS selector from a given CSS rules
23
 *
24
 * @package  \Luminaire\Poseidon\Parser
25
 */
26
class RelevantSelectorParser
27
{
28
29
    /**
30
     * The pseudo classes that can be set in a style attribute and that are
31
     * supported by the Symfony CssSelector (doesn't support CSS4 yet).
32
     *
33
     * @var array
34
     */
35
    protected $allowed_pseudo_classes = [
36
        StyleSelector::PSEUDO_CLASS_FIRST_CHILD,
37
        StyleSelector::PSEUDO_CLASS_ROOT,
38
        StyleSelector::PSEUDO_CLASS_NTH_CHILD,
39
        StyleSelector::PSEUDO_CLASS_NTH_LAST_CHILD,
40
        StyleSelector::PSEUDO_CLASS_NTH_OF_TYPE,
41
        StyleSelector::PSEUDO_CLASS_NTH_LAST_OF_TYPE,
42
        StyleSelector::PSEUDO_CLASS_LAST_CHILD,
43
        StyleSelector::PSEUDO_CLASS_FIRST_OF_TYPE,
44
        StyleSelector::PSEUDO_CLASS_LAST_OF_TYPE,
45
        StyleSelector::PSEUDO_CLASS_ONLY_CHILD,
46
        StyleSelector::PSEUDO_CLASS_ONLY_OF_TYPE,
47
        StyleSelector::PSEUDO_CLASS_EMPTY,
48
        StyleSelector::PSEUDO_CLASS_NOT,
49
    ];
50
51
    /**
52
     * The stylesheet reader instance
53
     *
54
     * @var \Crossjoin\Css\Reader\CssString
55
     */
56
    protected $reader;
57
58
    /**
59
     * The charset of the stylesheet
60
     *
61
     * @var string
62
     */
63
    protected $charset;
64
65
    /**
66
     * Create a new instance of "Relevant Selector Parser"
67
     *
68
     * @param  \Crossjoin\Css\Reader\CssString|string|null  $stylesheet
69
     * @param  string                                       $charset
70
     */
71
    public function __construct($stylesheet = null, $charset = 'UTF-8')
72
    {
73
        $this->charset = $charset;
74
75
        if ( ! is_null($stylesheet))
76
        {
77
            $this->setStylesheetReader($stylesheet);
78
        }
79
    }
80
81
    /**
82
     * Get the relevant selectors
83
     *
84
     * @return array
85
     */
86
    public function extract()
87
    {
88
        $selectors = [];
89
        $rules     = $this->reader->getStyleSheet()->getRules();
90
        $relevant  = $this->getRelevantStyleRules($rules);
91
92
        foreach ($relevant as $rule)
93
        {
94
            $this->populateSelectors($selectors, $rule);
0 ignored issues
show
$rule is of type object<Crossjoin\Css\For...ule\Style\StyleRuleSet>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
95
        }
96
97
        return $selectors;
98
    }
99
100
    /**
101
     * Store the selectors from the rule to the tank
102
     *
103
     * @param  array   &$tank
104
     * @param  array   $rule
105
     * @return void
106
     */
107
    protected function populateSelectors(array &$tank, $rule)
108
    {
109
        foreach ($rule->getSelectors() as $selector)
0 ignored issues
show
The method getSelectors cannot be called on $rule (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
110
        {
111
            if ( ! $this->isPseudoClassAllowed($selector))
112
            {
113
                continue;
114
            }
115
116
            $this->prepareSelectorArray(
117
                $tank,
118
                $selector->getSpecificity(),
119
                $selector->getValue()
120
            );
121
122
            foreach ($rule->getDeclarations() as $declaration)
0 ignored issues
show
The method getDeclarations cannot be called on $rule (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
123
            {
124
                $this->storeDeclaration(
125
                    $tank,
126
                    $declaration,
127
                    $selector->getSpecificity(),
128
                    $selector->getValue()
129
                );
130
            }
131
        }
132
    }
133
134
    /**
135
     * Store the declaration in the selector tank
136
     *
137
     * @param  array                                              &$tank
138
     * @param  \Crossjoin\Css\Format\Rule\Style\StyleDeclaration  $declaration
139
     * @param  string                                             $specifity
140
     * @param  string                                             $name
141
     * @return void
142
     */
143
    protected function storeDeclaration(array &$tank, $declaration, $specifity, $name)
144
    {
145
        $tank[$specifity][$name][] = $declaration;
146
    }
147
148
    /**
149
     * Before we build the dictionary of style declaration, we will need to make
150
     * sure, there is an array to be inserted.
151
     *
152
     * @param  array   &$selectors
153
     * @param  string  $specifity
154
     * @param  string  $name
155
     * @return void
156
     */
157
    protected function prepareSelectorArray(array &$selectors, $specifity, $name)
158
    {
159
        if ( ! isset($selectors[$specifity]))
160
        {
161
            $selectors[$specifity] = [];
162
        }
163
164
        if ( ! isset($selectors[$specifity][$name]))
165
        {
166
            $selectors[$specifity][$name] = [];
167
        }
168
    }
169
170
    /**
171
     * Set the stylesheet reader instance
172
     *
173
     * @param  \Crossjoin\Css\Reader\CssString|string  $stylesheet
174
     * @return $this
175
     *
176
     * @throws \InvalidArgumentException
177
     */
178
    public function setStylesheetReader($stylesheet)
179
    {
180
        if (is_string($stylesheet))
181
        {
182
            $stylesheet = new StylesheetReader($stylesheet);
183
        }
184
185
        if ( ! $stylesheet instanceof StylesheetReader)
186
        {
187
            throw new InvalidArgumentException('The argument 0 of the [setStylesheetReader] method expects to be a string of CSS or a [Crossjoin\Css\Reader\CssString]');
188
        }
189
190
        $this->reader = $stylesheet;
191
        $this->reader->setEnvironmentEncoding($this->getCharset());
192
193
        return $this;
194
    }
195
196
    /**
197
     * Get the stylesheet reader instance
198
     *
199
     * @return \Crossjoin\Css\Reader\CssString|null
200
     */
201
    public function getStylesheetReader()
202
    {
203
        return $this->reader;
204
    }
205
206
    /**
207
     * Set the charset of the stylesheet
208
     *
209
     * @param  string  $charset
210
     * @return $this
211
     */
212
    public function setCharset($charset)
213
    {
214
        $this->charset = $charset;
215
216
        return $this;
217
    }
218
219
    /**
220
     * Get the charset of the stylesheet
221
     *
222
     * @return string
223
     */
224
    public function getCharset()
225
    {
226
        return $this->charset;
227
    }
228
229
    /**
230
     * Check if a Selector has a valid Pseudo Class
231
     *
232
     * @param  \Crossjoin\Css\Format\Rule\Style\StyleSelector  $selector
233
     * @return bool
234
     */
235
    public function isPseudoClassAllowed(StyleSelector $selector)
236
    {
237
        foreach ($selector->getPseudoClasses() as $pseudo_class)
238
        {
239
            if ( ! in_array($pseudo_class, $this->allowed_pseudo_classes))
240
            {
241
                return false;
242
            }
243
        }
244
245
        return true;
246
    }
247
248
    /**
249
     * Gets all generally relevant style rules
250
     *
251
     * @param  \Crossjoin\Css\Format\Rule\RuleAbstract[]  $rules
252
     * @return \Crossjoin\Css\Format\Rule\Style\StyleRuleSet[]
253
     */
254
    protected function getRelevantStyleRules(array $rules)
255
    {
256
        $relevants = [];
257
258
        foreach ($rules as $rule)
259
        {
260
            if ($rule instanceof StyleRuleSet)
261
            {
262
                $relevants[] = $rule;
263
            }
264
265
            if ($rule instanceof MediaRule)
266
            {
267
                $this->getRelevantMediaRule($rule, $relevants);
268
            }
269
        }
270
271
        return $relevants;
272
    }
273
274
    /**
275
     * Gets the relevant style rules from a media rule
276
     *
277
     * @param  \Crossjoin\Css\Format\Rule\AtMedia\MediaRule  $rule
278
     * @param  array                                         &$collection
279
     * @return void
280
     */
281
    protected function getRelevantMediaRule(MediaRule $rule, &$collection)
282
    {
283
        foreach ($rule->getQueries() as $media_query)
284
        {
285
            if ( ! $this->isAllowedMediaRule($media_query))
286
            {
287
                continue;
288
            }
289
290
            foreach ($this->getRelevantStyleRules($rule->getRules()) as $style_rule)
291
            {
292
                $collection[] = $style_rule;
293
            }
294
295
            break;
296
        }
297
    }
298
299
    /**
300
     * Check if the media rule should be included
301
     *
302
     * @param  \Crossjoin\Css\Format\Rule\AtMedia\MediaQuery  $media_query
303
     * @return bool
304
     */
305
    protected function isAllowedMediaRule(MediaQuery $media_query)
306
    {
307
        $type      = $media_query->getType();
308
        $condition = count($media_query->getConditions());
309
310
        return ($type === MediaQuery::TYPE_ALL || $type === MediaQuery::TYPE_SCREEN) && $condition === 0;
311
    }
312
313
}
314