PathStackResolver::setLfiProtection()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace AssetManager\Core\Resolver;
4
5
use Assetic\Factory\Resource\DirectoryResource;
6
use AssetManager\Core\Exception;
7
use SplFileInfo;
8
use Traversable;
9
use Zend\Stdlib\SplStack;
10
11
/**
12
 * This resolver allows you to resolve from a stack of paths.
13
 */
14
class PathStackResolver extends FileResolverAbstract
15
{
16
    /**
17
     * @var SplStack
18
     */
19
    protected $paths;
20
21
    /**
22
     * Flag indicating whether or not LFI protection for rendering view scripts is enabled
23
     *
24
     * @var bool
25
     */
26
    protected $lfiProtectionOn = true;
27
28
    /**
29
     * Constructor
30
     */
31
    public function __construct()
32
    {
33
        $this->paths = new SplStack();
34
    }
35
36
    /**
37
     * Add many paths to the stack at once
38
     *
39
     * @param array|Traversable $paths
40
     *
41
     * @return void
42
     */
43
    public function addPaths($paths)
44
    {
45
        foreach ($paths as $path) {
46
            $this->addPath($path);
47
        }
48
    }
49
50
    /**
51
     * Rest the path stack to the paths provided
52
     *
53
     * @param  Traversable|array                  $paths
54
     *
55
     * @return void
56
     * @throws Exception\InvalidArgumentException
57
     */
58
    public function setPaths($paths)
59
    {
60
        if (!is_array($paths) && !$paths instanceof Traversable) {
61
            throw new Exception\InvalidArgumentException(sprintf(
62
                'Invalid argument provided for $paths, expecting either an array or Traversable object, "%s" given',
63
                is_object($paths) ? get_class($paths) : gettype($paths)
64
            ));
65
        }
66
67
        $this->clearPaths();
68
        $this->addPaths($paths);
69
    }
70
71
    /**
72
     * Normalize a path for insertion in the stack
73
     *
74
     * @param  string $path
75
     *
76
     * @return string
77
     */
78
    protected function normalizePath($path)
79
    {
80
        $path = rtrim($path, '/\\');
81
        $path .= DIRECTORY_SEPARATOR;
82
83
        return $path;
84
    }
85
86
    /**
87
     * Add a single path to the stack
88
     *
89
     * @param  string                             $path
90
     *
91
     * @return void
92
     * @throws Exception\InvalidArgumentException
93
     */
94
    public function addPath($path)
95
    {
96
        if (!is_string($path)) {
97
            throw new Exception\InvalidArgumentException(sprintf(
98
                'Invalid path provided; must be a string, received %s',
99
                gettype($path)
100
            ));
101
        }
102
103
        $this->paths[] = $this->normalizePath($path);
104
    }
105
106
    /**
107
     * Clear all paths
108
     *
109
     * @return void
110
     */
111
    public function clearPaths()
112
    {
113
        $this->paths = new SplStack();
114
    }
115
116
    /**
117
     * Returns stack of paths
118
     *
119
     * @return SplStack
120
     */
121
    public function getPaths()
122
    {
123
        return $this->paths;
124
    }
125
126
    /**
127
     * Set LFI protection flag
128
     *
129
     * @param  bool $flag
130
     * @return void
131
     */
132
    public function setLfiProtection($flag)
133
    {
134
        $this->lfiProtectionOn = (bool) $flag;
135
    }
136
137
    /**
138
     * Return status of LFI protection flag
139
     *
140
     * @return bool
141
     */
142
    public function isLfiProtectionOn()
143
    {
144
        return $this->lfiProtectionOn;
145
    }
146
147
    /**
148
     * {@inheritDoc}
149
     */
150
    public function resolve($name)
151
    {
152
        if ($this->isLfiProtectionOn() && preg_match('#\.\.[\\\/]#', $name)) {
153
            return null;
154
        }
155
156
        foreach ($this->getPaths() as $path) {
157
            $asset = $this->resolveFile($path . $name);
158
159
            if (!$asset) {
160
                return null;
161
            }
162
163
            $asset->mimetype = $this->getMimeResolver()->getMimeType($name);
164
165
            return $asset;
166
        }
167
168
        return null;
169
    }
170
171
    /**
172
     * {@inheritDoc}
173
     */
174
    public function collect()
175
    {
176
        $collection = array();
177
        foreach ($this->getPaths() as $path) {
178
            $locations = new SplStack();
179
            $pathInfo = new SplFileInfo($path);
180
            $locations->push($pathInfo);
181
            $basePath = $this->normalizePath($pathInfo->getRealPath());
182
183
            while (!$locations->isEmpty()) {
184
                /** @var SplFileInfo $pathInfo */
185
                $pathInfo = $locations->pop();
186
                if (!$pathInfo->isReadable()) {
187
                    continue;
188
                }
189
                if ($pathInfo->isDir()) {
190
                    $dir = new DirectoryResource($pathInfo->getRealPath());
191
                    foreach ($dir as $resource) {
192
                        $locations->push(new SplFileInfo($resource));
193
                    }
194
                } elseif (!isset($collection[$pathInfo->getPath()])) {
195
                    $collection[] = substr($pathInfo->getRealPath(), strlen($basePath));
196
                }
197
            }
198
        }
199
200
        return $collection;
201
    }
202
}
203