Issues (32)

Security Analysis    not enabled

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/Whoops/Util/TemplateHelper.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
 * Whoops - php errors for cool kids
4
 * @author Filipe Dobreira <http://github.com/filp>
5
 */
6
7
namespace Whoops\Util;
8
9
use Symfony\Component\VarDumper\Caster\Caster;
10
use Symfony\Component\VarDumper\Cloner\AbstractCloner;
11
use Symfony\Component\VarDumper\Cloner\VarCloner;
12
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
13
use Whoops\Exception\Frame;
14
15
/**
16
 * Exposes useful tools for working with/in templates
17
 */
18
class TemplateHelper
19
{
20
    /**
21
     * An array of variables to be passed to all templates
22
     * @var array
23
     */
24
    private $variables = [];
25
26
    /**
27
     * @var HtmlDumper
28
     */
29
    private $htmlDumper;
30
31
    /**
32
     * @var HtmlDumperOutput
33
     */
34
    private $htmlDumperOutput;
35
36
    /**
37
     * @var AbstractCloner
38
     */
39
    private $cloner;
40
41
    /**
42
     * @var string
43
     */
44
    private $applicationRootPath;
45
46 2
    public function __construct()
47
    {
48
        // root path for ordinary composer projects
49 2
        $this->applicationRootPath = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__))))));
50 2
    }
51
52
    /**
53
     * Escapes a string for output in an HTML document
54
     *
55
     * @param  string $raw
56
     * @return string
57
     */
58 2
    public function escape($raw)
59
    {
60 2
        $flags = ENT_QUOTES;
61
62
        // HHVM has all constants defined, but only ENT_IGNORE
63
        // works at the moment
64 2
        if (defined("ENT_SUBSTITUTE") && !defined("HHVM_VERSION")) {
65 2
            $flags |= ENT_SUBSTITUTE;
66 2
        } else {
67
            // This is for 5.3.
68
            // The documentation warns of a potential security issue,
69
            // but it seems it does not apply in our case, because
70
            // we do not blacklist anything anywhere.
71
            $flags |= ENT_IGNORE;
72
        }
73
74 2
        $raw = str_replace(chr(9), '    ', $raw);
75
76 2
        return htmlspecialchars($raw, $flags, "UTF-8");
77
    }
78
79
    /**
80
     * Escapes a string for output in an HTML document, but preserves
81
     * URIs within it, and converts them to clickable anchor elements.
82
     *
83
     * @param  string $raw
84
     * @return string
85
     */
86 1
    public function escapeButPreserveUris($raw)
87
    {
88 1
        $escaped = $this->escape($raw);
89 1
        return preg_replace(
90 1
            "@([A-z]+?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@",
91 1
            "<a href=\"$1\" target=\"_blank\" rel=\"noreferrer noopener\">$1</a>",
92
            $escaped
93 1
        );
94
    }
95
96
    /**
97
     * Makes sure that the given string breaks on the delimiter.
98
     *
99
     * @param  string $delimiter
100
     * @param  string $s
101
     * @return string
102
     */
103 1
    public function breakOnDelimiter($delimiter, $s)
104
    {
105 1
        $parts = explode($delimiter, $s);
106 1
        foreach ($parts as &$part) {
107 1
            $part = '<span class="delimiter">' . $part . '</span>';
108 1
        }
109
110 1
        return implode($delimiter, $parts);
111
    }
112
113
    /**
114
     * Replace the part of the path that all files have in common.
115
     *
116
     * @param  string $path
117
     * @return string
118
     */
119 1
    public function shorten($path)
120
    {
121 1
        if ($this->applicationRootPath != "/") {
122 1
            $path = str_replace($this->applicationRootPath, '&hellip;', $path);
123 1
        }
124
125 1
        return $path;
126
    }
127
128
    private function getDumper()
129
    {
130
        if (!$this->htmlDumper && class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) {
131
            $this->htmlDumperOutput = new HtmlDumperOutput();
132
            // re-use the same var-dumper instance, so it won't re-render the global styles/scripts on each dump.
133
            $this->htmlDumper = new HtmlDumper($this->htmlDumperOutput);
134
135
            $styles = [
136
                'default' => 'color:#FFFFFF; line-height:normal; font:12px "Inconsolata", "Fira Mono", "Source Code Pro", Monaco, Consolas, "Lucida Console", monospace !important; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: normal',
137
                'num' => 'color:#BCD42A',
138
                'const' => 'color: #4bb1b1;',
139
                'str' => 'color:#BCD42A',
140
                'note' => 'color:#ef7c61',
141
                'ref' => 'color:#A0A0A0',
142
                'public' => 'color:#FFFFFF',
143
                'protected' => 'color:#FFFFFF',
144
                'private' => 'color:#FFFFFF',
145
                'meta' => 'color:#FFFFFF',
146
                'key' => 'color:#BCD42A',
147
                'index' => 'color:#ef7c61',
148
            ];
149
            $this->htmlDumper->setStyles($styles);
150
        }
151
152
        return $this->htmlDumper;
153
    }
154
155
    /**
156
     * Format the given value into a human readable string.
157
     *
158
     * @param  mixed $value
159
     * @return string
160
     */
161
    public function dump($value)
162
    {
163
        $dumper = $this->getDumper();
164
165
        if ($dumper) {
166
            // re-use the same DumpOutput instance, so it won't re-render the global styles/scripts on each dump.
167
            // exclude verbose information (e.g. exception stack traces)
168
            if (class_exists('Symfony\Component\VarDumper\Caster\Caster')) {
169
                $cloneVar = $this->getCloner()->cloneVar($value, Caster::EXCLUDE_VERBOSE);
170
                // Symfony VarDumper 2.6 Caster class dont exist.
171
            } else {
172
                $cloneVar = $this->getCloner()->cloneVar($value);
173
            }
174
175
            $dumper->dump(
176
                $cloneVar,
177
                $this->htmlDumperOutput
178
            );
179
180
            $output = $this->htmlDumperOutput->getOutput();
181
            $this->htmlDumperOutput->clear();
182
183
            return $output;
184
        }
185
186
        return htmlspecialchars(print_r($value, true));
187
    }
188
189
    /**
190
     * Format the args of the given Frame as a human readable html string
191
     *
192
     * @param  Frame $frame
193
     * @return string the rendered html
194
     */
195
    public function dumpArgs(Frame $frame)
196
    {
197
        // we support frame args only when the optional dumper is available
198
        if (!$this->getDumper()) {
199
            return '';
200
        }
201
202
        $html = '';
203
        $numFrames = count($frame->getArgs());
204
205
        if ($numFrames > 0) {
206
            $html = '<ol class="linenums">';
207
            foreach ($frame->getArgs() as $j => $frameArg) {
208
                $html .= '<li>'. $this->dump($frameArg) .'</li>';
209
            }
210
            $html .= '</ol>';
211
        }
212
213
        return $html;
214
    }
215
216
    /**
217
     * Convert a string to a slug version of itself
218
     *
219
     * @param  string $original
220
     * @return string
221
     */
222 1
    public function slug($original)
223
    {
224 1
        $slug = str_replace(" ", "-", $original);
225 1
        $slug = preg_replace('/[^\w\d\-\_]/i', '', $slug);
226 1
        return strtolower($slug);
227
    }
228
229
    /**
230
     * Given a template path, render it within its own scope. This
231
     * method also accepts an array of additional variables to be
232
     * passed to the template.
233
     *
234
     * @param string $template
235
     * @param array  $additionalVariables
236
     */
237 1
    public function render($template, array $additionalVariables = null)
238
    {
239 1
        $variables = $this->getVariables();
240
241
        // Pass the helper to the template:
242 1
        $variables["tpl"] = $this;
243
244 1
        if ($additionalVariables !== null) {
245 1
            $variables = array_replace($variables, $additionalVariables);
246 1
        }
247
248 1
        call_user_func(function () {
249 1
            extract(func_get_arg(1));
0 ignored issues
show
func_get_arg(1) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
250 1
            require func_get_arg(0);
251 1
        }, $template, $variables);
252 1
    }
253
254
    /**
255
     * Sets the variables to be passed to all templates rendered
256
     * by this template helper.
257
     *
258
     * @param array $variables
259
     */
260 1
    public function setVariables(array $variables)
261
    {
262 1
        $this->variables = $variables;
263 1
    }
264
265
    /**
266
     * Sets a single template variable, by its name:
267
     *
268
     * @param string $variableName
269
     * @param mixed  $variableValue
270
     */
271 1
    public function setVariable($variableName, $variableValue)
272
    {
273 1
        $this->variables[$variableName] = $variableValue;
274 1
    }
275
276
    /**
277
     * Gets a single template variable, by its name, or
278
     * $defaultValue if the variable does not exist
279
     *
280
     * @param  string $variableName
281
     * @param  mixed  $defaultValue
282
     * @return mixed
283
     */
284 1
    public function getVariable($variableName, $defaultValue = null)
285
    {
286 1
        return isset($this->variables[$variableName]) ?
287 1
            $this->variables[$variableName] : $defaultValue;
288
    }
289
290
    /**
291
     * Unsets a single template variable, by its name
292
     *
293
     * @param string $variableName
294
     */
295 1
    public function delVariable($variableName)
296
    {
297 1
        unset($this->variables[$variableName]);
298 1
    }
299
300
    /**
301
     * Returns all variables for this helper
302
     *
303
     * @return array
304
     */
305 1
    public function getVariables()
306
    {
307 1
        return $this->variables;
308
    }
309
310
    /**
311
     * Set the cloner used for dumping variables.
312
     *
313
     * @param AbstractCloner $cloner
314
     */
315 1
    public function setCloner($cloner)
316
    {
317 1
        $this->cloner = $cloner;
318 1
    }
319
320
    /**
321
     * Get the cloner used for dumping variables.
322
     *
323
     * @return AbstractCloner
324
     */
325
    public function getCloner()
326
    {
327
        if (!$this->cloner) {
328
            $this->cloner = new VarCloner();
329
        }
330
        return $this->cloner;
331
    }
332
333
    /**
334
     * Set the application root path.
335
     *
336
     * @param string $applicationRootPath
337
     */
338
    public function setApplicationRootPath($applicationRootPath)
339
    {
340
        $this->applicationRootPath = $applicationRootPath;
341
    }
342
343
    /**
344
     * Return the application root path.
345
     *
346
     * @return string
347
     */
348
    public function getApplicationRootPath()
349
    {
350
        return $this->applicationRootPath;
351
    }
352
}
353