Issues (292)

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.

lib/Dwoo/Template/File.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
2
/**
3
 * Copyright (c) 2013-2017
4
 *
5
 * @category  Library
6
 * @package   Dwoo\Template
7
 * @author    Jordi Boggiano <[email protected]>
8
 * @author    David Sanchez <[email protected]>
9
 * @copyright 2008-2013 Jordi Boggiano
10
 * @copyright 2013-2017 David Sanchez
11
 * @license   http://dwoo.org/LICENSE LGPLv3
12
 * @version   1.4.0
13
 * @date      2017-03-16
14
 * @link      http://dwoo.org/
15
 */
16
17
namespace Dwoo\Template;
18
19
use Dwoo\Exception as DwooException;
20
use Dwoo\Core as Core;
21
use Dwoo\ICompiler;
22
use Dwoo\ITemplate as ITemplate;
23
use Dwoo\Security\Exception as SecurityException;
24
use Dwoo\Template\File as TemplateFile;
25
26
/**
27
 * Represents a Dwoo template contained in a file.
28
 * This software is provided 'as-is', without any express or implied warranty.
29
 * In no event will the authors be held liable for any damages arising from the use of this software.
30
 */
31
class File extends Str
32
{
33
    /**
34
     * Template filename.
35
     *
36
     * @var string
37
     */
38
    protected $file;
39
40
    /**
41
     * Include path(s) to look into to find this template.
42
     *
43
     * @var array
44
     */
45
    protected $includePath = array();
46
47
    /**
48
     * Resolved path cache when looking for a file in multiple include paths.
49
     * this is reset when the include path is changed
50
     *
51
     * @var string
52
     */
53
    protected $resolvedPath = null;
54
55
    /**
56
     * Creates a template from a file.
57
     *
58
     * @param string $file        the path to the template file, make sure it exists
59
     * @param int    $cacheTime   duration of the cache validity for this template,
60
     *                            if null it defaults to the Dwoo instance that will
61
     *                            render this template
62
     * @param string $cacheId     the unique cache identifier of this page or anything else that
63
     *                            makes this template's content unique, if null it defaults
64
     *                            to the current url
65
     * @param string $compileId   the unique compiled identifier, which is used to distinguish this
66
     *                            template from others, if null it defaults to the filename+bits of the path
67
     * @param mixed  $includePath a string for a single path to look into for the given file, or an array of paths
68
     */
69
    public function __construct($file, $cacheTime = null, $cacheId = null, $compileId = null, $includePath = array())
70
    {
71
        parent::__construct($file, $cacheTime, $cacheId, $compileId);
72
        $this->template = null;
73
        $this->file     = $file;
74
        $this->name     = basename($file);
75
        $this->setIncludePath($includePath);
76
        $this->compileId = $this->getResourceIdentifier();
77
    }
78
79
    /**
80
     * Sets the include path(s) to where the given template filename must be looked up.
81
     *
82
     * @param mixed $paths the path to look into, can be string for a single path or an array of paths
83
     */
84
    public function setIncludePath($paths)
85
    {
86
        if ($paths == null) {
87
          $paths = array();
88
        } elseif (is_array($paths) === false) {
89
            $paths = array($paths);
90
        }
91
92
        $this->includePath  = $paths;
93
        $this->resolvedPath = null;
94
    }
95
96
    /**
97
     * Return the current include path(s).
98
     *
99
     * @return array
100
     */
101
    public function getIncludePath()
102
    {
103
        return $this->includePath;
104
    }
105
106
    /**
107
     * Checks if compiled file is valid (exists and it's the modification is greater or
108
     * equal to the modification time of the template file).
109
     *
110
     * @param string file
111
     *
112
     * @return bool True cache file existance and it's modification time
113
     */
114
    protected function isValidCompiledFile($file)
115
    {
116
        return parent::isValidCompiledFile($file) && (int)$this->getUid() <= filemtime($file);
117
    }
118
119
    /**
120
     * Returns the template source of this template.
121
     *
122
     * @return string
123
     */
124
    public function getSource()
125
    {
126
        return file_get_contents($this->getResourceIdentifier());
127
    }
128
129
    /**
130
     * Returns the resource name for this template class.
131
     *
132
     * @return string
133
     */
134
    public function getResourceName()
135
    {
136
        return 'file';
137
    }
138
139
    /**
140
     * Returns this template's source filename.
141
     *
142
     * @return string
143
     * @throws DwooException
144
     */
145
    public function getResourceIdentifier()
146
    {
147
        if ($this->resolvedPath !== null) {
148
            return $this->resolvedPath;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->resolvedPath; (string) is incompatible with the return type of the parent method Dwoo\Template\Str::getResourceIdentifier of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
149
        } elseif (array_filter($this->getIncludePath()) == array()) {
150
            return $this->file;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->file; (string) is incompatible with the return type of the parent method Dwoo\Template\Str::getResourceIdentifier of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
151
        } else {
152
            foreach ($this->getIncludePath() as $path) {
153
                $path = rtrim($path, DIRECTORY_SEPARATOR);
154
                if (file_exists($path . DIRECTORY_SEPARATOR . $this->file) === true) {
155
                    return $this->resolvedPath = $path . DIRECTORY_SEPARATOR . $this->file;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->resolvedPa...EPARATOR . $this->file; (string) is incompatible with the return type of the parent method Dwoo\Template\Str::getResourceIdentifier of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
156
                }
157
            }
158
159
            throw new DwooException('Template "' . $this->file . '" could not be found in any of your include path(s)');
160
        }
161
    }
162
163
    /**
164
     * Returns an unique value identifying the current version of this template,
165
     * in this case it's the unix timestamp of the last modification.
166
     *
167
     * @return string
168
     */
169
    public function getUid()
170
    {
171
        return (string)filemtime($this->getResourceIdentifier());
172
    }
173
174
    /**
175
     * Returns a new template object from the given include name, null if no include is
176
     * possible (resource not found), or false if include is not permitted by this resource type.
177
     *
178
     * @param Core      $core           the dwoo instance requiring it
179
     * @param mixed     $resourceId     the filename (relative to this template's dir) of the template to
180
     *                                  include
181
     * @param int       $cacheTime      duration of the cache validity for this template, if null it defaults
182
     *                                  to the Dwoo instance that will render this template if null it
183
     *                                  defaults to the Dwoo instance that will render this template if null
184
     *                                  it defaults to the Dwoo instance that will render this template
185
     * @param string    $cacheId        the unique cache identifier of this page or anything else that makes
186
     *                                  this template's content unique, if null it defaults to the current
187
     *                                  url makes this template's content unique, if null it defaults to the
188
     *                                  current url makes this template's content unique, if null it defaults
189
     *                                  to the current url
190
     * @param string    $compileId      the unique compiled identifier, which is used to distinguish this
191
     *                                  template from others, if null it defaults to the filename+bits of the
192
     *                                  path template from others, if null it defaults to the filename+bits
193
     *                                  of the path template from others, if null it defaults to the
194
     *                                  filename+bits of the path
195
     * @param ITemplate $parentTemplate the template that is requesting a new template object (through an
196
     *                                  include, extends or any other plugin) an include, extends or any
197
     *                                  other plugin) an include, extends or any other plugin)
198
     *
199
     * @return TemplateFile|null
200
     * @throws DwooException
201
     * @throws SecurityException
202
     */
203
    public static function templateFactory(Core $core, $resourceId, $cacheTime = null, $cacheId = null,
204
                                           $compileId = null, ITemplate $parentTemplate = null)
205
    {
206
        if (DIRECTORY_SEPARATOR === '\\') {
207
            $resourceId = str_replace(array("\t", "\n", "\r", "\f", "\v"), array(
208
                '\\t',
209
                '\\n',
210
                '\\r',
211
                '\\f',
212
                '\\v'
213
            ), $resourceId);
214
        }
215
        $resourceId = strtr($resourceId, '\\', '/');
216
217
        $includePath = null;
218
219
        if (file_exists($resourceId) === false) {
220
            if ($parentTemplate === null) {
221
                $parentTemplate = $core->getTemplate();
222
            }
223
            if ($parentTemplate instanceof self) {
224
                if ($includePath = $parentTemplate->getIncludePath()) {
225
                    if (strstr($resourceId, '../')) {
226
                        throw new DwooException('When using an include path you can not reference a template into a parent directory (using ../)');
227
                    }
228
                } else {
229
                    $resourceId = dirname($parentTemplate->getResourceIdentifier()) . DIRECTORY_SEPARATOR . $resourceId;
230
                    if (file_exists($resourceId) === false) {
231
                        return null;
232
                    }
233
                }
234
            } else {
235
                return null;
236
            }
237
        }
238
239
        if ($policy = $core->getSecurityPolicy()) {
240
            while (true) {
241
                if (preg_match('{^([a-z]+?)://}i', $resourceId)) {
242
                    throw new SecurityException('The security policy prevents you to read files from external sources : <em>' . $resourceId . '</em>.');
243
                }
244
245
                if ($includePath) {
246
                    break;
247
                }
248
249
                $resourceId = realpath($resourceId);
250
                $dirs       = $policy->getAllowedDirectories();
251
                foreach ($dirs as $dir => $dummy) {
252
                    if (strpos($resourceId, $dir) === 0) {
253
                        break 2;
254
                    }
255
                }
256
                throw new SecurityException('The security policy prevents you to read <em>' . $resourceId . '</em>');
257
            }
258
        }
259
260
        $class = 'Dwoo\Template\File';
261
        if ($parentTemplate) {
262
            $class = get_class($parentTemplate);
263
        }
264
265
        return new $class($resourceId, $cacheTime, $cacheId, $compileId, $includePath);
266
    }
267
268
    /**
269
     * Returns some php code that will check if this template has been modified or not.
270
     * if the function returns null, the template will be instanciated and then the Uid checked
271
     *
272
     * @return string
273
     */
274
    public function getIsModifiedCode()
275
    {
276
        return '"' . $this->getUid() . '" == filemtime(' . var_export($this->getResourceIdentifier(), true) . ')';
277
    }
278
}
279