Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
AvailablePath.php
Go to the documentation of this file.
1 <?php
28 
30 {
31  const PROTECTED_PATH = 'protectedPath';
32 
33  const NOT_AVAILABLE_PATH = 'notAvailablePath';
34 
35  const PROTECTED_LFI = 'protectedLfi';
36 
42  protected $_value;
43 
49  protected $_protectedPaths = [];
50 
56  protected $_availablePaths = [];
57 
63  protected $_pathsData;
64 
68  public function __construct()
69  {
70  $this->_initMessageTemplates();
71  }
72 
78  protected function _initMessageTemplates()
79  {
80  if (!$this->_messageTemplates) {
81  $this->_messageTemplates = [
82  self::PROTECTED_PATH => __('Path "%value%" is protected and cannot be used.'),
83  self::NOT_AVAILABLE_PATH => __('Path "%value%" is not available and cannot be used.'),
84  self::PROTECTED_LFI => __('Path "%value%" may not include parent directory traversal ("../", "..\\").'),
85  ];
86  }
87  return $this;
88  }
89 
97  public function setPaths(array $paths)
98  {
99  if (isset($paths['available']) && is_array($paths['available'])) {
100  $this->_availablePaths = $paths['available'];
101  }
102  if (isset($paths['protected']) && is_array($paths['protected'])) {
103  $this->_protectedPaths = $paths['protected'];
104  }
105  return $this;
106  }
107 
114  public function setProtectedPaths(array $paths)
115  {
116  $this->_protectedPaths = $paths;
117  return $this;
118  }
119 
126  public function addProtectedPath($path)
127  {
128  if (is_array($path)) {
129  $this->_protectedPaths = array_merge($this->_protectedPaths, $path);
130  } else {
131  $this->_protectedPaths[] = $path;
132  }
133  return $this;
134  }
135 
141  public function getProtectedPaths()
142  {
143  return $this->_protectedPaths;
144  }
145 
152  public function setAvailablePaths(array $paths)
153  {
154  $this->_availablePaths = $paths;
155  return $this;
156  }
157 
164  public function addAvailablePath($path)
165  {
166  if (is_array($path)) {
167  $this->_availablePaths = array_merge($this->_availablePaths, $path);
168  } else {
169  $this->_availablePaths[] = $path;
170  }
171  return $this;
172  }
173 
179  public function getAvailablePaths()
180  {
181  return $this->_availablePaths;
182  }
183 
196  public function isValid($value)
197  {
198  $value = trim($value);
199  $this->_setValue($value);
200 
201  if (!$this->_availablePaths && !$this->_protectedPaths) {
202  throw new \Exception(__('Please set available and/or protected paths list(s) before validation.'));
203  }
204 
205  if (preg_match('#\.\.[\\\/]#', $this->_value)) {
206  $this->_error(self::PROTECTED_LFI, $this->_value);
207  return false;
208  }
209 
210  //validation
211  $value = str_replace('\\', '/', $this->_value);
212  $valuePathInfo = pathinfo(ltrim($value, '\\/'));
213  if ($valuePathInfo['dirname'] == '.' || $valuePathInfo['dirname'] == '/') {
214  $valuePathInfo['dirname'] = '';
215  }
216 
217  if ($this->_protectedPaths && !$this->_isValidByPaths($valuePathInfo, $this->_protectedPaths, true)) {
218  $this->_error(self::PROTECTED_PATH, $this->_value);
219  return false;
220  }
221  if ($this->_availablePaths && !$this->_isValidByPaths($valuePathInfo, $this->_availablePaths, false)) {
222  $this->_error(self::NOT_AVAILABLE_PATH, $this->_value);
223  return false;
224  }
225 
226  return true;
227  }
228 
239  protected function _isValidByPaths($valuePathInfo, $paths, $protected)
240  {
241  foreach ($paths as $path) {
242  $path = ltrim($path, '\\/');
243  if (!isset($this->_pathsData[$path]['regFilename'])) {
244  $pathInfo = pathinfo($path);
245  $options['file_mask'] = $pathInfo['basename'];
246  if ($pathInfo['dirname'] == '.' || $pathInfo['dirname'] == '/') {
247  $pathInfo['dirname'] = '';
248  } else {
249  $pathInfo['dirname'] = str_replace('\\', '/', $pathInfo['dirname']);
250  }
251  $options['dir_mask'] = $pathInfo['dirname'];
252  $this->_pathsData[$path]['options'] = $options;
253  } else {
254  $options = $this->_pathsData[$path]['options'];
255  }
256 
257  //file mask
258  if (false !== strpos($options['file_mask'], '*')) {
259  if (!isset($this->_pathsData[$path]['regFilename'])) {
260  //make regular
261  $reg = $options['file_mask'];
262  $reg = str_replace('.', '\.', $reg);
263  $reg = str_replace('*', '.*?', $reg);
264  $reg = "/^({$reg})\$/";
265  } else {
266  $reg = $this->_pathsData[$path]['regFilename'];
267  }
268  $resultFile = preg_match($reg, $valuePathInfo['basename']);
269  } else {
270  $resultFile = $options['file_mask'] == $valuePathInfo['basename'];
271  }
272 
273  //directory mask
274  $reg = $options['dir_mask'] . '/';
275  if (!isset($this->_pathsData[$path]['regDir'])) {
276  //make regular
277  $reg = str_replace('.', '\.', $reg);
278  $reg = str_replace('*\\', '||', $reg);
279  $reg = str_replace('*/', '||', $reg);
280  //$reg = str_replace('*', '||', $reg);
281  $reg = str_replace('/', '[\\/]', $reg);
282  $reg = str_replace('?', '([^\\/]+)', $reg);
283  $reg = str_replace('||', '(.*[\\/])?', $reg);
284  $reg = "/^{$reg}\$/";
285  } else {
286  $reg = $this->_pathsData[$path]['regDir'];
287  }
288  $resultDir = preg_match($reg, $valuePathInfo['dirname'] . '/');
289 
290  if ($protected && ($resultDir && $resultFile)) {
291  return false;
292  } elseif (!$protected && ($resultDir && $resultFile)) {
293  //return true because one match with available path mask
294  return true;
295  }
296  }
297  if ($protected) {
298  return true;
299  } else {
300  //return false because no one match with available path mask
301  return false;
302  }
303  }
304 }
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
__()
Definition: __.php:13
_error($messageKey, $value=null)
Definition: Abstract.php:284
$value
Definition: gender.phtml:16
$paths
Definition: _bootstrap.php:83
_isValidByPaths($valuePathInfo, $paths, $protected)