Bitrix-D7  20.0.0
main/lib/io/path.php
См. документацию.
1 <?php
2 namespace Bitrix\Main\IO;
3 
4 use Bitrix\Main;
6 
7 /**
8  *
9  */
10 class Path
11 {
12  const DIRECTORY_SEPARATOR = '/';
15 
16  const INVALID_FILENAME_CHARS = "\\/:*?\"'<>|~#&;";
17 
18  //the pattern should be quoted, "|" is allowed below as a delimiter
19  const INVALID_FILENAME_BYTES = "\xE2\x80\xAE"; //Right-to-Left Override Unicode Character
20 
21  protected static $physicalEncoding = "";
22  protected static $logicalEncoding = "";
23 
24  protected static $directoryIndex = null;
25 
26  public static function normalize($path)
27  {
28  if (!is_string($path) || ($path == ""))
29  return null;
30 
31  //slashes doesn't matter for Windows
32  static $pattern = null, $tailPattern;
33  if (!$pattern)
34  {
35  if(strncasecmp(PHP_OS, "WIN", 3) == 0)
36  {
37  //windows
38  $pattern = "'[\\\\/]+'";
39  $tailPattern = "\0.\\/+ ";
40  }
41  else
42  {
43  //unix
44  $pattern = "'[/]+'";
45  $tailPattern = "\0/";
46  }
47  }
48  $pathTmp = preg_replace($pattern, "/", $path);
49 
50  if (strpos($pathTmp, "\0") !== false)
51  throw new InvalidPathException($path);
52 
53  if (preg_match("#(^|/)(\\.|\\.\\.)(/|\$)#", $pathTmp))
54  {
55  $arPathTmp = explode('/', $pathTmp);
56  $arPathStack = array();
57  foreach ($arPathTmp as $i => $pathPart)
58  {
59  if ($pathPart === '.')
60  continue;
61 
62  if ($pathPart === "..")
63  {
64  if (array_pop($arPathStack) === null)
65  throw new InvalidPathException($path);
66  }
67  else
68  {
69  array_push($arPathStack, $pathPart);
70  }
71  }
72  $pathTmp = implode("/", $arPathStack);
73  }
74 
75  $pathTmp = rtrim($pathTmp, $tailPattern);
76 
77  if (substr($path, 0, 1) === "/" && substr($pathTmp, 0, 1) !== "/")
78  $pathTmp = "/".$pathTmp;
79 
80  if ($pathTmp === '')
81  $pathTmp = "/";
82 
83  return $pathTmp;
84  }
85 
86  public static function getExtension($path)
87  {
88  $path = self::getName($path);
89  if ($path != '')
90  {
91  $pos = Text\UtfSafeString::getLastPosition($path, '.');
92  if ($pos !== false)
93  return substr($path, $pos + 1);
94  }
95  return '';
96  }
97 
98  public static function getName($path)
99  {
100  //$path = self::normalize($path);
101 
102  $p = Text\UtfSafeString::getLastPosition($path, self::DIRECTORY_SEPARATOR);
103  if ($p !== false)
104  return substr($path, $p + 1);
105 
106  return $path;
107  }
108 
109  public static function getDirectory($path)
110  {
111  return substr($path, 0, -strlen(self::getName($path)) - 1);
112  }
113 
114  public static function convertLogicalToPhysical($path)
115  {
116  if (self::$physicalEncoding == "")
117  self::$physicalEncoding = self::getPhysicalEncoding();
118 
119  if (self::$logicalEncoding == "")
120  self::$logicalEncoding = self::getLogicalEncoding();
121 
122  if (self::$physicalEncoding == self::$logicalEncoding)
123  return $path;
124 
125  return Text\Encoding::convertEncoding($path, self::$logicalEncoding, self::$physicalEncoding);
126  }
127 
128  public static function convertPhysicalToLogical($path)
129  {
130  if (self::$physicalEncoding == "")
131  self::$physicalEncoding = self::getPhysicalEncoding();
132 
133  if (self::$logicalEncoding == "")
134  self::$logicalEncoding = self::getLogicalEncoding();
135 
136  if (self::$physicalEncoding == self::$logicalEncoding)
137  return $path;
138 
139  return Text\Encoding::convertEncoding($path, self::$physicalEncoding, self::$logicalEncoding);
140  }
141 
142  public static function convertLogicalToUri($path)
143  {
144  if (self::$logicalEncoding == "")
145  self::$logicalEncoding = self::getLogicalEncoding();
146 
147  if (self::$directoryIndex == null)
148  self::$directoryIndex = self::getDirectoryIndexArray();
149 
150  if (isset(self::$directoryIndex[self::getName($path)]))
151  $path = self::getDirectory($path)."/";
152 
153  if ('utf-8' !== self::$logicalEncoding)
154  $path = Text\Encoding::convertEncoding($path, self::$logicalEncoding, 'utf-8');
155 
156  return implode('/', array_map("rawurlencode", explode('/', $path)));
157  }
158 
159  public static function convertPhysicalToUri($path)
160  {
161  if (self::$physicalEncoding == "")
162  self::$physicalEncoding = self::getPhysicalEncoding();
163 
164  if (self::$directoryIndex == null)
165  self::$directoryIndex = self::getDirectoryIndexArray();
166 
167  if (isset(self::$directoryIndex[self::getName($path)]))
168  $path = self::getDirectory($path)."/";
169 
170  if ('utf-8' !== self::$physicalEncoding)
171  $path = Text\Encoding::convertEncoding($path, self::$physicalEncoding, 'utf-8');
172 
173  return implode('/', array_map("rawurlencode", explode('/', $path)));
174  }
175 
176  public static function convertUriToPhysical($path)
177  {
178  if (self::$physicalEncoding == "")
179  self::$physicalEncoding = self::getPhysicalEncoding();
180 
181  if (self::$directoryIndex == null)
182  self::$directoryIndex = self::getDirectoryIndexArray();
183 
184  $path = implode('/', array_map("rawurldecode", explode('/', $path)));
185 
186  if ('utf-8' !== self::$physicalEncoding)
187  $path = Text\Encoding::convertEncoding($path, 'utf-8', self::$physicalEncoding);
188 
189  return $path;
190  }
191 
192  protected static function getLogicalEncoding()
193  {
194  if (defined('BX_UTF'))
195  $logicalEncoding = "utf-8";
196  elseif (defined("SITE_CHARSET") && (strlen(SITE_CHARSET) > 0))
197  $logicalEncoding = SITE_CHARSET;
198  elseif (defined("LANG_CHARSET") && (strlen(LANG_CHARSET) > 0))
199  $logicalEncoding = LANG_CHARSET;
200  elseif (defined("BX_DEFAULT_CHARSET"))
201  $logicalEncoding = BX_DEFAULT_CHARSET;
202  else
203  $logicalEncoding = "windows-1251";
204 
205  return strtolower($logicalEncoding);
206  }
207 
208  protected static function getPhysicalEncoding()
209  {
210  $physicalEncoding = defined("BX_FILE_SYSTEM_ENCODING") ? BX_FILE_SYSTEM_ENCODING : "";
211  if ($physicalEncoding == "")
212  {
213  if (strtoupper(substr(PHP_OS, 0, 3)) === "WIN")
214  $physicalEncoding = "windows-1251";
215  else
216  $physicalEncoding = "utf-8";
217  }
218  return strtolower($physicalEncoding);
219  }
220 
221  public static function combine()
222  {
223  $numArgs = func_num_args();
224  if ($numArgs <= 0)
225  return "";
226 
227  $arParts = array();
228  for ($i = 0; $i < $numArgs; $i++)
229  {
230  $arg = func_get_arg($i);
231  if (is_array($arg))
232  {
233  if (empty($arg))
234  continue;
235 
236  foreach ($arg as $v)
237  {
238  if (!is_string($v) || $v == "")
239  continue;
240  $arParts[] = $v;
241  }
242  }
243  elseif (is_string($arg))
244  {
245  if ($arg == "")
246  continue;
247 
248  $arParts[] = $arg;
249  }
250  }
251 
252  $result = "";
253  foreach ($arParts as $part)
254  {
255  if ($result !== "")
256  $result .= self::DIRECTORY_SEPARATOR;
257  $result .= $part;
258  }
259 
260  $result = self::normalize($result);
261 
262  return $result;
263  }
264 
265  public static function convertRelativeToAbsolute($relativePath)
266  {
267  if (!is_string($relativePath))
268  throw new Main\ArgumentTypeException("relativePath", "string");
269  if ($relativePath == "")
270  throw new Main\ArgumentNullException("relativePath");
271 
272  return self::combine($_SERVER["DOCUMENT_ROOT"], $relativePath);
273  }
274 
275  public static function convertSiteRelativeToAbsolute($relativePath, $site = null)
276  {
277  if (!is_string($relativePath) || $relativePath == "")
278  $site = SITE_ID;
279 
280  $basePath = Main\SiteTable::getDocumentRoot($site);
281 
282  return self::combine($basePath, $relativePath);
283  }
284 
285  protected static function validateCommon($path)
286  {
287  if (!is_string($path))
288  {
289  return false;
290  }
291 
292  if (trim($path) == "")
293  {
294  return false;
295  }
296 
297  if (strpos($path, "\0") !== false)
298  {
299  return false;
300  }
301 
302  if(preg_match("#(".self::INVALID_FILENAME_BYTES.")#", $path))
303  {
304  return false;
305  }
306 
307  return true;
308  }
309 
310  public static function validate($path)
311  {
312  if(!static::validateCommon($path))
313  {
314  return false;
315  }
316 
317  return (preg_match("#^([a-z]:)?/([^\x01-\x1F".preg_quote(self::INVALID_FILENAME_CHARS, "#")."]+/?)*$#isD", $path) > 0);
318  }
319 
320  public static function validateFilename($filename)
321  {
322  if(!static::validateCommon($filename))
323  {
324  return false;
325  }
326 
327  return (preg_match("#^[^\x01-\x1F".preg_quote(self::INVALID_FILENAME_CHARS, "#")."]+$#isD", $filename) > 0);
328  }
329 
330  /**
331  * @param string $filename
332  * @param callable $callback
333  * @return string
334  */
335  public static function replaceInvalidFilename($filename, $callback)
336  {
337  return preg_replace_callback(
338  "#([\x01-\x1F".preg_quote(self::INVALID_FILENAME_CHARS, "#")."]|".self::INVALID_FILENAME_BYTES.")#",
339  $callback,
340  $filename
341  );
342  }
343 
344  /**
345  * @param string $filename
346  * @return string
347  */
348  public static function randomizeInvalidFilename($filename)
349  {
350  return static::replaceInvalidFilename($filename,
351  function()
352  {
353  return chr(rand(97, 122));
354  }
355  );
356  }
357 
358  public static function isAbsolute($path)
359  {
360  return (substr($path, 0, 1) === "/") || preg_match("#^[a-z]:/#i", $path);
361  }
362 
363  protected static function getDirectoryIndexArray()
364  {
365  static $directoryIndexDefault = array("index.php" => 1, "index.html" => 1, "index.htm" => 1, "index.phtml" => 1, "default.html" => 1, "index.php3" => 1);
366 
367  $directoryIndex = Main\Config\Configuration::getValue("directory_index");
368  if ($directoryIndex !== null)
369  return $directoryIndex;
370 
371  return $directoryIndexDefault;
372  }
373 }
Bitrix\Main\SiteTable\getDocumentRoot
static getDocumentRoot($siteId=null)
Definition: main/lib/site.php:16
Bitrix\Main\IO\Path\convertLogicalToUri
static convertLogicalToUri($path)
Definition: main/lib/io/path.php:142
Bitrix\Main\IO\Path\getName
static getName($path)
Definition: main/lib/io/path.php:98
Bitrix\Main\IO\Path\getLogicalEncoding
static getLogicalEncoding()
Definition: main/lib/io/path.php:192
Bitrix\Main\IO\Path\validate
static validate($path)
Definition: main/lib/io/path.php:310
Bitrix\Main\IO\Path\isAbsolute
static isAbsolute($path)
Definition: main/lib/io/path.php:358
Bitrix\Main
Bitrix\Main\IO\InvalidPathException
Definition: ioexception.php:35
Bitrix\Main\IO\Path\PATH_SEPARATOR
const PATH_SEPARATOR
Definition: main/lib/io/path.php:14
Bitrix\Main\IO\Path\getDirectoryIndexArray
static getDirectoryIndexArray()
Definition: main/lib/io/path.php:363
Bitrix\Main\IO\Path\normalize
static normalize($path)
Definition: main/lib/io/path.php:26
Bitrix\Main\IO\Path\DIRECTORY_SEPARATOR_ALT
const DIRECTORY_SEPARATOR_ALT
Definition: main/lib/io/path.php:13
Bitrix\Main\IO\Path\combine
static combine()
Definition: main/lib/io/path.php:221
Bitrix\Main\IO\Path\getDirectory
static getDirectory($path)
Definition: main/lib/io/path.php:109
Bitrix\Main\IO\Path\convertUriToPhysical
static convertUriToPhysical($path)
Definition: main/lib/io/path.php:176
Bitrix\Main\IO\Path
Definition: main/lib/io/path.php:10
Bitrix\Main\IO\Path\INVALID_FILENAME_CHARS
const INVALID_FILENAME_CHARS
Definition: main/lib/io/path.php:16
Bitrix\Main\Text
Definition: base32.php:2
Bitrix\Main\ArgumentTypeException
Exception is thrown when the type of an argument is not accepted by function.
Definition: main/lib/exception.php:113
Bitrix\Main\IO\Path\$physicalEncoding
static $physicalEncoding
Definition: main/lib/io/path.php:21
Bitrix\Main\IO\Path\replaceInvalidFilename
static replaceInvalidFilename($filename, $callback)
Definition: main/lib/io/path.php:335
Bitrix\Main\Text\UtfSafeString\getLastPosition
static getLastPosition($haystack, $needle)
Definition: utfsafestring.php:14
Bitrix\Main\IO\Path\convertPhysicalToLogical
static convertPhysicalToLogical($path)
Definition: main/lib/io/path.php:128
Bitrix\Main\Text\Encoding\convertEncoding
static convertEncoding($data, $charsetFrom, $charsetTo, &$errorMessage="")
Converts data from a source encoding to a target encoding.
Definition: encoding.php:53
Bitrix\Main\IO\Path\randomizeInvalidFilename
static randomizeInvalidFilename($filename)
Definition: main/lib/io/path.php:348
Bitrix\Main\IO\Path\INVALID_FILENAME_BYTES
const INVALID_FILENAME_BYTES
Definition: main/lib/io/path.php:19
Bitrix\Main\IO
Definition: main/lib/io/directory.php:2
Bitrix\Main\IO\Path\getPhysicalEncoding
static getPhysicalEncoding()
Definition: main/lib/io/path.php:208
Bitrix\Main\IO\Path\validateFilename
static validateFilename($filename)
Definition: main/lib/io/path.php:320
Bitrix\Main\IO\Path\$directoryIndex
static $directoryIndex
Definition: main/lib/io/path.php:24
Bitrix\Main\IO\Path\getExtension
static getExtension($path)
Definition: main/lib/io/path.php:86
Bitrix\Main\ArgumentNullException
Exception is thrown when "empty" value is passed to a function that does not accept it as a valid arg...
Definition: main/lib/exception.php:53
Bitrix\Main\IO\Path\validateCommon
static validateCommon($path)
Definition: main/lib/io/path.php:285
Bitrix\Main\IO\Path\$logicalEncoding
static $logicalEncoding
Definition: main/lib/io/path.php:22
Bitrix\Main\IO\Path\convertSiteRelativeToAbsolute
static convertSiteRelativeToAbsolute($relativePath, $site=null)
Definition: main/lib/io/path.php:275
Bitrix\Main\IO\Path\convertPhysicalToUri
static convertPhysicalToUri($path)
Definition: main/lib/io/path.php:159
Bitrix\Main\IO\Path\DIRECTORY_SEPARATOR
const DIRECTORY_SEPARATOR
Definition: main/lib/io/path.php:12
Bitrix\Main\IO\Path\convertRelativeToAbsolute
static convertRelativeToAbsolute($relativePath)
Definition: main/lib/io/path.php:265
Bitrix\Main\IO\Path\convertLogicalToPhysical
static convertLogicalToPhysical($path)
Definition: main/lib/io/path.php:114