Your IP : 3.144.200.28


Current Path : /var/www/axolotl/data/www/nn.axolotls.ru/bitrix/modules/webdav/classes/
Upload File :
Current File : /var/www/axolotl/data/www/nn.axolotls.ru/bitrix/modules/webdav/classes/file.php

<?php
##############################################
# Bitrix Site Manager WebDav #
# Copyright (c) 2002-2010 Bitrix #
# http://www.bitrixsoft.com #
# mailto:admin@bitrixsoft.com #
##############################################
IncludeModuleLangFile(__FILE__);

class CWebDavFile extends CWebDavBase
{
	var $base_url;

	var $Type = "folder";

	var $real_path = "";

	var $real_path_full = "";

	var $arFilePermissions = array(
		"WRITE" => array(
			".php" => "X",
			".htaccess" => "X",
			".html" => "X",
			".htm" => "X",
			".mht" => "X",
			".xhtml" => "X",
			".js" => "X"),
		"READ" => array(
			".php" => "X",
			".htaccess" => "X")
		);
	var $arFileForbiddenExtentions = array(
		"WRITE" => array(),
		"READ" => array()
		);
	var $allow = array(
		"POST"		=> array("rights" => "U", "min_rights" => "R"),
		"HEAD"		=> array("rights" => "R", "min_rights" => "R"),
		"OPTIONS"	=> array("rights" => "A", "min_rights" => "A"),
		"PROPPATCH"	=> array("rights" => "U", "min_rights" => "U"),
		"PROPFIND"	=> array("rights" => "R", "min_rights" => "R"),
		"GET"		=> array("rights" => "R", "min_rights" => "R"),
		"PUT"		=> array("rights" => "U", "min_rights" => "U"),
		"LOCK"		=> array("rights" => "U", "min_rights" => "U"),
		"UNLOCK"	=> array("rights" => "U", "min_rights" => "U"),
		"MOVE"		=> array("rights" => "W", "min_rights" => "U"),
		"COPY"		=> array("rights" => "W", "min_rights" => "U"),
		"MKCOL"		=> array("rights" => "U", "min_rights" => "U"),
		"DELETE"	=> array("rights" => "W", "min_rights" => "U"),
		"UNDELETE"	=> array("rights" => "W", "min_rights" => "W"),
	);

	function CWebDavFile($arParams, $base_url)
	{
		$io = self::GetIo();
		$arParams = (is_array($arParams) ? $arParams : array());
		$this->RegisterVirtualIOCompatibility();

		$arParams["FOLDER"] = $io->CombinePath("/", trim($arParams["FOLDER"]));
		$this->real_path = $arParams["FOLDER"];
		$this->real_path_full = $io->CombinePath($_SERVER['DOCUMENT_ROOT'], $arParams["FOLDER"]);

		$this->CWebDavBase($base_url);

		if (! $io->DirectoryExists($this->real_path_full))
		{
			$this->arError[] = array(
				"id" => "folder is not exists",
				"text" => GetMessage("WD_FILE_ERROR1"));
		}
		elseif (substr($this->real_path, 0, 7) == "/bitrix")
		{
			$this->arError[] = array(
				"id" => "forbidden folder",
				"text" => GetMessage("WD_FILE_ERROR15"));
		}

		$this->permission = $GLOBALS['APPLICATION']->GetFileAccessPermission($arParams["FOLDER"]);

		foreach ($this->arFilePermissions as $right => $perms)
		{
			foreach ($this->arFilePermissions[$right] as $ext => $perms)
			{
				if ($this->permission < $perms)
				{
					$this->arFileForbiddenExtentions[$right][] = $ext;
				}
			}
		}

		if (!$GLOBALS["USER"]->IsAdmin())
		{
			$res = GetScriptFileExt();
			foreach ($res as $ext)
			{
				$this->arFileForbiddenExtentions["WRITE"][] = ".".$ext;
			}
		}

		$this->workflow = false;
	}

	function RegisterVirtualIOCompatibility($baseDir='')
	{
		static $IOCompartible = 'BX_IO_Compartible';
		if (defined($IOCompartible))
			return false;

		define($IOCompartible, 'Y');
		AddEventHandler('main', 'BXVirtualIO_ConvertCharset', array($this, 'VirtualIO_ConvertCharset'));

		return true;
	}

	function VirtualIO_ConvertCharset($arParams=array())
	{
		static $resultCache = array();
		static $bxLang = null;
		$io = self::GetIo();

		if ($bxLang === null) // from VirtualIO
		{
			if (defined('BX_UTF'))
				$bxLang = "utf-8";
			elseif (defined("SITE_CHARSET") && (strlen(SITE_CHARSET) > 0))
				$bxLang = SITE_CHARSET;
			elseif (defined("LANG_CHARSET") && (strlen(LANG_CHARSET) > 0))
				$bxLang = LANG_CHARSET;
			else
				$bxLang = "windows-1251";

			$bxLang = strtolower($bxLang);
		}

		if (
			isset($arParams['original'])
			&& (strpos($arParams['original'], $this->real_path_full) === 0)
			&& ($arParams['converted'] !== $arParams['original'])
		)
		{
			if (!isset($resultCache[$arParams['original']]))
			{
				$libPath = substr($arParams['original'], strlen($this->real_path_full)+1);
				$libPath = explode('/', $libPath);

				$pathLength = sizeof($libPath);
				for ($i=0; $i<$pathLength; $i++)
				{
					$p = $libPath[$i];
					if ($i > 0)
					{
						$parent = array_slice($libPath, 0, $i);
						$parent = $io->CombinePath($this->real_path_full, implode('/', $parent));
					}
					else
					{
						$parent = $this->real_path_full;
					}


					if ($arParams['direction'] == CBXVirtualIoFileSystem::directionEncode) // bx to system
					{
						if (file_exists($io->CombinePath($parent, $p)))
						{
							$libPath[$i] = $p;
						}
						else
						{
							$pc = CBXVirtualIoFileSystem::ConvertCharset($p, CBXVirtualIoFileSystem::directionEncode, true);
							if (file_exists($io->CombinePath($parent, $pc)))
							{
								$libPath[$i] = $pc;
							}
							else
							{
								$libPath[$i] = $pc; // creating new ?
							}
						}
					}
					elseif ($arParams['direction'] == CBXVirtualIoFileSystem::directionDecode) /// system to bx
					{
						$decoded = CBXVirtualIoFileSystem::ConvertCharset($p, CBXVirtualIoFileSystem::directionDecode, true);
						$restored = CBXVirtualIoFileSystem::ConvertCharset($decoded, CBXVirtualIoFileSystem::directionEncode, true);
						if ($restored == $p)
						{
							$reverse = CBXVirtualIoFileSystem::ConvertCharset($p, CBXVirtualIoFileSystem::directionEncode, true);
							$restored_reverse = CBXVirtualIoFileSystem::ConvertCharset($reverse, CBXVirtualIoFileSystem::directionDecode, true);
							if (
								($restored_reverse == $p)
								&& ($bxLang != "windows-1251")
							)
							{
								$libPath[$i] = $p;
							}
							else
							{
								$libPath[$i] = $decoded;
							}
						}
						else // conversion failed, assume original was correct
						{
							$libPath[$i] = $p;
						}
					}
					else
					{
						die('invalid encoding direction');
					}
				}
				$resultCache[$arParams['original']] = $io->CombinePath($this->real_path_full, implode('/', $libPath));
			}
			return $resultCache[$arParams['original']];
		}
		return false;
	}

	function PROPPATCH(&$options)
	{
		$this->IsDir($options);
		if ($this->arParams["not_found"] === true)
		{
			return "404 Not Found";
		}
		$res = $this->_get_props($this->arParams["item_id"]);
		foreach ($options["props"] as $key => $prop)
		{
			if ($prop["ns"] == "DAV:")
			{
				$options["props"][$key]['status'] = "403 Forbidden";
			}
			else
			{
				if (isset($prop["val"]))
				{
					$res[$prop["name"].$prop["ns"]] = array(
						"name" => $prop["name"],
						"ns" => $prop["ns"],
						"value" => $prop["val"]);
				}
				else
				{
					unset($res[$prop["name"].$prop["ns"]]);
				}
			}
		}
		$this->_set_props($this->arParams["item_id"], $res);
		return "";
	}

	function CheckUniqueName($basename, $section_id, &$res)
	{
		$section_id = trim($section_id);
		$basename = trim($basename);
		if (empty($basename))
			return false;
		$this->IsDir(array("path" => $section_id . "/" . $basename));
		return $this->arParams["not_found"];
	}


	function _getShowParams($res)
	{
		$result = array();

		if ($this->permission > "W")
		{
			$result = array(
				"EDIT" => "Y",
				"DELETE" => "Y",
			);

			if ($res['LOCK_STATUS'] == 'green')
			{
				$result['LOCK'] = 'Y';
			}
			else
			{
				$result['UNLOCK'] = 'Y';
			}

			if (isset($res["PROPS"]["UNDELETEBX:"])) // in trash
			{
				$res["SHOW"]["UNDELETE"] = "Y";
			}
		}
		elseif ($this->permission >= "W")
		{
			$result = array(
				"EDIT" => "Y",
				"DELETE" => "Y"
			);

			if ($res['LOCK_STATUS'] == 'green')
			{
				$result['LOCK'] = 'Y';
			}
			elseif ($res['LOCK_STATUS'] == 'yellow')
			{
				$result['UNLOCK'] = 'Y';
			}

			if (isset($res["PROPS"]["UNDELETEBX:"])) // in trash
			{
				$result["UNDELETE"] = "Y";
				$result["DELETE"] = "N";
			}
		}

		return $result;
	}

	function PROPFIND(&$options, &$files, $arParams = array())
	{
		global $by, $order, $USER;
		$io = self::GetIo();
		if (!function_exists("__sort_array_folder_and_file"))
		{
			function __sort_array_folder_and_file($res1, $res2)
			{
				global $by, $order;
				InitSorting();
				if (empty($by))
				{
					$by = "NAME"; $order = "ASC";
				}
				$by = strtoupper($by);
				$order = strtoupper($order);

				if ($res1["~TYPE"] == "FOLDER" && $res2["~TYPE"] == "FILE")
					return -1;
				elseif ($res1["~TYPE"] == "FILE" && $res2["~TYPE"] == "FOLDER")
					return 1;
				else
				{
					$by = (is_set($res1, $by) ? $by : "NAME");

					$ord = $order;
					if ($by == "TIMESTAMP_X")
						$ord = ($order == "ASC" ? "DESC" : "ASC");

					if ($ord == "ASC")
						return ($res1[$by] < $res2[$by] ? -1 : 1);
					else
						return ($res1[$by] < $res2[$by] ? 1 : -1);
				}
			}
		}
		$this->IsDir($options);
		$files['files'] = array();
		$arResult = array("NAV_RESULT" => false, "RESULT" => array());

		if (empty($options["FILTER"]))
		{
			if ($this->arParams["not_found"] === true)
			{
				return false;
			}
			elseif($this->arParams["is_dir"] != true)
			{
				//$files["files"]["E".$res["ID"]] = $this->_get_fileinfo($this->arParams["item_id"]);
				$files["files"]["E"] = $this->_get_fileinfo($this->arParams["item_id"]);
			}
			else
			{
				$files["files"]["section"] = $this->_get_fileinfo($this->arParams["item_id"]);

				if (
					!empty($this->arParams["item_id"])
					&& $this->arParams["item_id"] != "/"
				)
					$arResult["SECTION"] = array("ID" => $this->arParams["item_id"], "NAME" => $this->arParams["item_id"]);

				//$path = $this->_slashify($io->CombinePath($this->real_path_full, $this->arParams["item_id"]));
				$path = CWebDavBase::CleanRelativePathString($this->arParams["item_id"], $this->real_path_full);
				if($path === false)
				{
					return false;
				}
				$path = $this->_slashify($path);

				if (!empty($options["depth"]))
				{
					$dir = $io->GetDirectory($path);
					if ($dir->IsExists())
					{
						$this->arParams["item_id"] = $this->_slashify(str_replace("//", "/", $this->arParams["item_id"]));

						$tzOffset = CTimeZone::GetOffset();

						$arChildren = $dir->GetChildren();
						foreach($arChildren as $node)
						{

							$filename = $node->GetName();
							$filePath = $io->CombinePath($this->arParams["item_id"], $filename);

							$res = array(
								"~TYPE" => "FOLDER",
								"TYPE" => "S",
								"ID" => $filePath,
								"NAME" => $filename,
								"TIMESTAMP_X" => $node->GetModificationTime() + $tzOffset,
								"PERMISSION" => $this->permission,
								"PATH" => $filePath,
								"REAL_PATH" => $path.$filename,
								"FILE_SIZE" => 0
							);

							if ($this->MetaNames($res))
							{
								if (! $node->IsDirectory())
								{
									$ext = strtolower(strrchr($filename , '.'));
									if (in_array($ext, $this->arFileForbiddenExtentions["READ"]))
										continue;

									$res["~TYPE"] = "FILE";
									$res["TYPE"] = "E";
									$res["LOCK_STATUS"] = "green";
									$res["EXTENTION"] = $ext;
									$res["FILE_SIZE"] = $node->GetFileSize();

									$res["FILE_ARRAY"] = array(
										"TIMESTAMP_X" => $res["TIMESTAMP_X"],
										"MODULE_ID" => "webdav",
										"HEIGHT" => 0,
										"WIDTH" => 0,
										"FILE_SIZE" => $res["FILE_SIZE"],
										"CONTENT_TYPE" => ($node->IsReadable() ? $this->_mimetype($path.$filename) : 'application/x-non-readable'),
										"SUBDIR" => $io->CombinePath("/", $this->real_path, $this->arParams["item_id"]),
										"FILE_NAME" => $filename,
										"ORIGINAL_NAME" => $filename,
										"DESCRIPTION" => ""
									);
								}
								$res["PROPS"] = $this->_get_props($filePath);

								$res["LOCK_STATUS"] = 'green';
								if (is_array($res['PROPS']['LOCK']))
								{
									$userLogin = $GLOBALS['USER']->GetLogin();
									$now = time();
									foreach($res['PROPS']['LOCK'] as $arLock)
									{
										if (
											$arLock['exclusivelock'] == 1
											&& $arLock['expires'] >= $now
											&& $arLock['created'] <= $now
										)
										{
											$res['LOCK_STATUS'] = (($userLogin == $arLock['owner']) ? 'yellow' : 'red');
											$rsUser = CUser::GetByLogin($arLock['owner']);
											$arUser = $rsUser->GetNext();
											$res['LOCKED_USER_NAME'] = '('.$arUser['LOGIN'].')';
											if (strlen($arUser['NAME']) > 0 && strlen($arUser['LAST_NAME']) > 0)
												$res['LOCKED_USER_NAME'] .= ' '.$arUser['NAME'].' '.$arUser['LAST_NAME'];
											break;
										}
									}
								}

								$res['SHOW'] = $this->_getShowParams($res);

								$arResult["RESULT"][($res["TYPE"] == "FOLDER" ? "S" : "E").$filename] = $res;

								$files['files'][] = $this->_get_fileinfo($this->arParams["item_id"].$filename);
							}
						}
					}
				}
			}
		}
		else // search
		{
			$arSearchResults = array();
			if (
				IsModuleInstalled('search')
				&& CModule::IncludeModule('search')
			)
			{
				$arSearchParams = array(
					"MODULE_ID" => "main",
					"URL" => $this->base_url.'%'
				);

				if (
					isset($options["FILTER"]["content"])
					&& strlen($options["FILTER"]["content"])>0
				)
				{
					$arSearchParams += array(
						"QUERY" => $options["FILTER"]["content"]
					);
				}

				$obSearch = new CSearch;
				$obSearch->Search($arSearchParams);
				if ($obSearch->errorno != 0)
				{
					$arResult["ERROR_MESSAGE"] = $obSearch->error;
				}
				else
				{
					while($arSearchResultItem = $obSearch->GetNext())
					{
						$arSearchResults[] = $arSearchResultItem['ITEM_ID'];
					}
				}

				$tzOffset = CTimeZone::GetOffset();

				foreach ($arSearchResults as $sSearchItem)
				{
					$file = array_pop(explode("|", $sSearchItem));

					$filename = GetFileName($file);
					$sFullFileName = $io->CombinePath($_SERVER['DOCUMENT_ROOT'], $file);
					if (strpos($sFullFileName, $this->real_path_full) === 0)
					{
						$filePath = CWebDavBase::ConvertPathToRelative($sFullFileName, $this->real_path_full);
					}

					$filePath = CWebDavBase::CleanRelativePathString($filePath, $this->real_path_full);
					if($filePath === false)
					{
						return false;
					}

					/*$sFullFileName = $io->CombinePath($_SERVER['DOCUMENT_ROOT'], $file);
					$filename = array_pop(explode("/", $file));
					$path = implode("/", array_slice(explode("/", $sFullFileName), 0 , -1)) . "/";
					$filePath = $io->CombinePath($path, $filename);*/

					$oFile = $io->GetFile($filePath);

					$res = array(
						"ID" => $file,
						"NAME" => $filename,
						"TIMESTAMP_X" => $oFile->GetModificationTime() + $tzOffset,
						"PERMISSION" => $this->permission,
						"PATH" => substr($file, strlen($this->real_path)),
						"REAL_PATH" => $filePath,
						"FILE_SIZE" => 0
					);
					$res['SHOW'] = $this->_getShowParams($res);

					if ($this->MetaNames($res))
					{
						$res["PROPS"] = $this->_get_props(substr($file, strlen($this->real_path)));
						if (!isset($res["PROPS"]["UNDELETEBX:"]))
						{
							if ($oFile->IsExists())
							{
								$ext = strtolower(strrchr($filename , '.'));
								if (in_array($ext, $this->arFileForbiddenExtentions["READ"]))
									continue;

								$fileSize = $oFile->GetFileSize();

								$res["~TYPE"] = "FILE";
								$res["TYPE"] = "E";
								$res["LOCK_STATUS"] = "green";
								$res["EXTENTION"] = $ext;
								$res["FILE_SIZE"] = $fileSize;
								$res["FILE_ARRAY"] = array(
									"TIMESTAMP_X" => $res["TIMESTAMP_X"],
									"MODULE_ID" => "webdav",
									"HEIGHT" => 0,
									"WIDTH" => 0,
									"FILE_SIZE" => $fileSize,
									"CONTENT_TYPE" => ($oFile->IsReadable() ? $this->_mimetype($filePath) : 'application/x-non-readable'),
									"SUBDIR" => implode("/", array_slice(explode("/", $file), 0 , -1)),
									"FILE_NAME" => $filename,
									"ORIGINAL_NAME" => $filename,
									"DESCRIPTION" => "");
							}
							$arResult["RESULT"][($res["TYPE"] == "FOLDER" ? "S" : "E").$filename] = $res;
						}
					}
				}
			}
		}

		if ($arParams["return"] == "nav_result" || $arParams["return"] == "array")
		{
			uasort($arResult["RESULT"], "__sort_array_folder_and_file");
			$arResult["NAV_RESULT"] = new CDBResult();
			$arResult["NAV_RESULT"]->InitFromArray($arResult["RESULT"]);
			$arResult["NAV_RESULT"] = new CDBResultWebDAVFiles($arResult["NAV_RESULT"]);

			return $arResult;
		}

		return true;
	}

	function GET(&$options)
	{
		$io = self::GetIo();
		if (count($this->arParams) <= 0)
		{
			$this->IsDir($options);
		}
		if ($this->arParams["not_found"])
		{
			return false;
		}
		elseif ($this->arParams["is_dir"])
		{
			return true;
		}

		$fspath = $options["path"];
		//if (strpos($fspath, $this->real_path_full) === false)
		//{
			//$fspath = $this->arParams["item_id"];
			//$fspath = $io->CombinePath($this->real_path_full, $this->arParams["item_id"]);
		//}
		if (strpos($fspath, $this->real_path_full) === 0)
		{
			$fspath = CWebDavBase::ConvertPathToRelative($fspath, $this->real_path_full);
		}
		$fspath = CWebDavBase::CleanRelativePathString($fspath, $this->real_path_full);
		if($fspath === false)
		{
			return false;
		}

		$oFile = $io->GetFile($fspath);

		$options["mimetype"] = $this->_mimetype($fspath);
		$options["mtime"] = $oFile->GetModificationTime() + CTimeZone::GetOffset();
		$options["size"] = $oFile->GetFileSize();
		$options["stream"] = $oFile->Open("rb");

		if (empty($options["mimetype"]))
			$options["mimetype"] = $this->get_mime_type($this->arParams["file_name"]);

		return true;
	}


	function Undelete($options)
	{
		$io = self::GetIo();
		if(!$this->CheckRights("UNDELETE", true, $options["path"]))
		{
			$this->ThrowAccessDenied();
			return "403 Forbidden";
		}

		if (! isset($options['dest_url']))
		{
			$arParams = $this->_get_props($options['path']);
			$options["dest_url"] = $arParams["UNDELETEBX:"]['value'];
		}

		if (! isset($options['dest_url']))
			return "404 Not Found";

		$this->IsDir(array("path" => $options["dest_url"]), $this->replace_symbols);
		$options["dest_url"] = $this->_udecode($options["dest_url"]);
		$arTo = $this->arParams;

		if ($arTo["not_found"])
		{
			do {
				$this->IsDir(array('path' => rtrim($this->arParams['parent_id'], '/')));
			} while (($this->arParams["parent_id"] != '') && ($this->arParams["not_found"]));

			if ($this->arParams['not_found'])
			{
				$options['dest_url'] = $io->CombinePath("/", $arTo['base_name']);
			}
			else
			{
				$options['dest_url'] = $io->CombinePath($this->arParams["item_id"], $arTo["base_name"]);
			}
		}

		$this->IsDir($options);
		$bIsDir = ($this->arParams['is_dir']);

		if ($this->arParams["not_found"] === true)
		{
			return "404 Not Found";
		}
		else
		{
			$result = $this->MOVE($options);
			if (in_array(intval($result), array(201, 204)))   // remove the "UNDELETE" in props
			{
				if (! $bIsDir)
				{
					$options["props"] = array(array("ns"=>"BX:","name"=>"UNDELETE"));
					$options["path"] = $options["dest_url"];
					$this->PROPPATCH($options);
				}
				else
				{
					$params = $this->GetFilesAndFolders($options['dest_url']);
					if (!empty($params))
					{
						$tmpParams = $this->arParams;
						sort($params, SORT_STRING);
						foreach ($params as $file)
						{
							$localpath = str_replace(array($this->real_path_full, "///", "//"), "/", $file);
							$arUndeleteOptions = array("props" => array( array("ns"=>"BX:", "name"=>"UNDELETE") ), "path" => $localpath);
							$this->PROPPATCH($arUndeleteOptions);
						}
						$this->arParams = $tmpParams;
					}
				}
				return "204 No Content";
			}
			else
			{
				return "404 Not Found";
			}
		}
	}

	function PUT(&$options)
	{
		$io = self::GetIo();
		$this->IsDir($options);
		if ($this->arParams["is_dir"] == true)
		{
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage('WD_FILE_ERROR14'), 'FORBIDDEN_NAME');
			return "409 Conflict";
		}
		$options["~path"] = $this->_udecode($options["path"]);
		if ($this->arParams["not_found"] && !$this->CheckRights("PUT", true, $this->arParams["base_name"]) ||
			!$this->arParams["not_found"] && !$this->CheckRights("PUT", true, $this->arParams["item_id"]))
		{
			$this->ThrowAccessDenied();
			return false;
		}

		/*$fspath = $io->CombinePath($this->real_path_full, $this->arParams["item_id"]);
		if ($this->arParams["not_found"])
		{
			$fspath = $io->CombinePath($this->real_path_full, $this->arParams["parent_id"], $this->arParams["base_name"]);
		}*/

		$fspath = $this->arParams["item_id"];
		if ($this->arParams["not_found"])
		{
			$fspath = $io->CombinePath($this->arParams["parent_id"], $this->arParams["base_name"]);
		}

		$fspath = CWebDavBase::CleanRelativePathString($fspath, $this->real_path_full);
		if($fspath === false)
		{
			return false;
		}

		$oFile = $io->GetFile($fspath);
		if (COption::GetOptionInt("main", "disk_space") > 0)
		{
			CDiskQuota::updateDiskQuota("file", $oFile->GetFileSize(), "delete");
		}

		$options["new"] = $this->arParams["not_found"];
		$options["fspath"] = $fspath;

		if ($options["fopen"] != "N")
		{
			$fp = $oFile->Open("w");
			return $fp;
		}
		return true;
	}

	function Reindex($file)
	{
		$io = self::GetIo();
		if (CModule::IncludeModule('search'))
		{
			$path = $file;
			if (strpos($file, $this->real_path_full) !== false)
			{
				$path = substr($file, strlen($this->real_path_full)+1);
			}
			$path = $io->CombinePath($this->real_path, $path);
			$url = $this->base_url . substr($file, strlen($this->real_path_full));

			if (strpos(strtolower(PHP_OS), 'win') !== false)
				usleep(1000); // pass thru windows write cache
			clearstatcache();

			$searchID = CSearch::ReIndexFile(Array(SITE_ID, $path));
			if (intval($searchID) > 0)
			{
				CSearch::Update($searchID, array('URL' => $url));
			}
		}
	}

	function put_commit(&$options)
	{
		$io = self::GetIo();
		$file = $options["~path"];
		/*if (strpos($file, $this->real_path_full) === false)
		{
			$file = $io->CombinePath($this->real_path_full, $file);
		}*/

		if (strpos($file, $this->real_path_full) === 0)
		{
			$file = CWebDavBase::ConvertPathToRelative($file, $this->real_path_full);
		}
		$file = CWebDavBase::CleanRelativePathString($file, $this->real_path_full);
		if($file === false)
		{
			return false;
		}

		$this->Reindex($file);

		if (COption::GetOptionInt("main", "disk_space") > 0)
		{
			$oFile = $io->GetFile($file);
			CDiskQuota::updateDiskQuota("file", $oFile->GetFileSize(), "add");
		}

		return true;
	}

	function checkLock($path)
	{
		$result = false;
		$is_dir = false;
		$ID = 0;
		$strProps = "";

		$this->IsDir(array("path" => $path));
		if ($this->arParams["not_found"] === true)
		{
			return "404 Not Found";
		}

		$arProps = $this->_get_props($this->arParams["item_id"]);

		if (
			!empty($arProps["LOCK"])
			&& is_array($arProps["LOCK"])
		)
		{
			$res = reset($arProps["LOCK"]);

			$result = array(
				"type"	  => "write",
				"scope"   => $res["exclusivelock"] ? "exclusive" : "shared",
				"depth"   => 0,
				"owner"   => $res["owner"],
				"token" => $res["token"],
				"created" => $res["created"],
				"modified" => $res["modified"],
				"expires" => $res["expires"]
			);
		}

		return $result;
	}

	function CheckRight($IBlockPermission, $permission)
	{
		if (is_array($IBlockPermission))
			return (isset($IBlockPermission[$permission]) ? 'Z' : 'A');
		else
			return $IBlockPermission;
	}

	function LOCK(&$options)
	{
		$this->IsDir();
		if (
			$this->arParams["is_dir"]
			&& !empty($options["depth"])
		)
			return "409 Conflict";

		$options["timeout"] = time() + 300;

		$arProps = $this->_get_props($this->arParams["parent_id"].$this->arParams["base_name"]);
		if (isset($options["update"]))
		{
			$token = $options["update"];
			if (
				array_key_exists("LOCK", $arProps) &&
				array_key_exists($token, $arProps["LOCK"]) &&
				(array_key_exists("owner", $arProps["LOCK"][$token]) && strlen($arProps["LOCK"][$token]["owner"]) > 0) &&
				(array_key_exists("exclusivelock", $arProps["LOCK"][$token]) && strlen($arProps["LOCK"][$token]["exclusivelock"]) > 0)
				)
			{
				$arProps["LOCK"][$token]["expires"] = $options["timeout"];
				$arProps["LOCK"][$token]["modified"] = time();

				$options["owner"] = $GLOBALS['USER']->GetLogin();
				$options["scope"] = $arProps["LOCK"][$token]["exclusivelock"] ? "exclusive" : "shared";
				$options["type"]  = $arProps["LOCK"][$token]["exclusivelock"] ? "write"		: "read";
				return true;
			}
			else
			{
				return false;
			}
		}

		$arProps["LOCK"][$options["locktoken"]] = array(
			"created" => time(),
			"modified" => time(),
			"owner" => $GLOBALS['USER']->GetLogin(),
			"token" => $options["locktoken"],
			"expires" => $options["timeout"],
			"exclusivelock" => ($options["scope"] === "exclusive" ? 1 : 0)
		);

		$this->_set_props($this->arParams["parent_id"].$this->arParams["base_name"], $arProps);
		return "200 OK";
	}

	function UNLOCK(&$options)
	{
		$this->IsDir();
		if (!$this->arParams["not_found"])
		{
			$arProps = $this->_get_props($this->arParams["item_id"]);
			unset($arProps["LOCK"]);
			$this->_set_props($this->arParams["item_id"], $arProps);
		}
		return "204 No Content";
	}

	function MOVE(&$options)
	{
		if (!$this->CheckRights("MOVE", true, $options["dest_url"])):
			$this->ThrowAccessDenied();
			return "403 Forbidden";
		endif;
		return $this->COPY($options, true);
	}

	function COPY(&$options, $drop = false)
	{
		$io = self::GetIo();
		$options["dest_url"] = $this->MetaNamesReverse(explode("/", $options["dest_url"]));
		if (!$this->CheckRights("COPY", true, $options["dest_url"])):
			$this->ThrowAccessDenied();
			return "403 Forbidden";
		elseif ($_SERVER['REQUEST_METHOD'] == "MOVE" && !empty($_SERVER["CONTENT_LENGTH"])):
			return "415 Unsupported media type";
		elseif ($options["path"] == $options["dest_url"]):
//			 $GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR2"), "EMPTY_DESTINATION_URL");
			return "204 No Content";
		elseif (empty($options["dest_url"])):
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR2"), "EMPTY_DESTINATION_URL");
			return "502 Bad gateway";
		endif;
		$arDataFrom = array();
		$arDataTo = array();

		$from_parent_id = 0;
		$to_parent_id = 0;

		$from_ID = 0; $from_basename = "";
		$to_ID = 0; $to_basename = "";

		$is_dir = false;

		////////////// CHECK FROM
		$this->IsDir($options);
		$arFrom = $this->arParams;
		if ($this->arParams["is_dir"] === true):
			$from_ID = $this->arParams["item_id"];
			$is_dir = true;
		elseif ($this->arParams["is_file"] === true):
			$from_ID = $this->arParams["item_id"];
		else:
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR3"), "DESTINATION_FILE_OR_FOLDER_IS_NOT_FOUND");
			return "404 Not Found";
		endif;

		$from_basename = $this->arParams["basename"];
		$from_parent_id = $this->arParams["parent_id"];

		if ($_SERVER['REQUEST_METHOD'] == "MOVE" && $is_dir && ($options["depth"] != "infinity")):
			return "400 Bad request";
		endif;

		////////////// CHECK TO

		$this->IsDir(array("path" => $options["dest_url"]), $this->replace_symbols);
		$options["dest_url"] = $this->_udecode($options["dest_url"]);
		$arTo = $this->arParams;
		if ($this->arParams["is_dir"] === true || $this->arParams["is_file"] === true):
			$to_ID = $this->arParams["item_id"];
		endif;

		if ($from_ID == $options["dest_url"]):
			return "204 No Content";
		elseif ($to_ID && $options['rename']):
			$nameSuffix = 1;
			do
			{
				$tmpName = $options["dest_url"]." (". $nameSuffix++ .")";
				$this->IsDir(array("path" => $tmpName), $this->replace_symbols);
				$arTo = $this->arParams;
			} while ($this->arParams["is_dir"] === true || $this->arParams["is_file"] === true);
			$options['dest_url'] = $tmpName;
			$to_ID = 0;
		elseif ($to_ID && !$options["overwrite"]):
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR4"), "FILE_OR_FOLDER_ALREADY_EXISTS");
			return '412 Precondition failed';
		elseif ($is_dir && $this->arParams["is_file"]):
			$GLOBALS["APPLICATION"]->ThrowException(str_replace("#FOLDER#", $this->arParams["item_id"], GetMessage("WD_FILE_ERROR5")), "FOLDER_IS_EXISTS");
			return "400 bad Request";
		elseif ($arFrom['is_file'] && $arTo["is_dir"]):
			$GLOBALS["APPLICATION"]->ThrowException(str_replace("#FOLDER#", $this->arParams["item_id"], GetMessage("WD_FILE_ERROR5")), "FOLDER_IS_EXISTS");
			return "400 bad Request";
		endif;

		if (rtrim($arTo['parent_id'], '/') == $this->GetMetaID('TRASH'))
		{
			$arCheckTrashElement = $this->_get_props($arFrom["item_id"]);
			if ( ! isset($arCheckTrashElement["UNDELETEBX:"]))
			{
				$this->ThrowAccessDenied();
				$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_ACCESS_DENIED"), "BAD_NAME");
				return "403 Forbidden";
			}
		}

		$__from = preg_replace("/\/+/is", "/", strtolower($from_ID)."/");
		$__to = preg_replace("/\/+/is", "/", strtolower(substr($options["dest_url"], 0, strlen($from_ID) + 1)."/"));
		if ($is_dir && $__from == $__to):
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR100"), "SECTION_IS_NOT_UPDATED");
			return "400 Bad Request";
		endif;

		$to_parent_id = $this->arParams["parent_id"];
		$to_basename = $this->arParams["basename"];

		/*$from_url = $io->CombinePath($this->real_path_full, $from_ID);
		$to_url = $io->CombinePath($this->real_path_full, $options["dest_url"]);*/

		$from_url = CWebDavBase::CleanRelativePathString($from_ID, $this->real_path_full);
		$to_url = CWebDavBase::CleanRelativePathString($options["dest_url"], $this->real_path_full);
		if($from_url === false || $to_url === false)
		{
			return "400 Bad Request";
		}

		if (!$is_dir)
		{
			if ($to_ID && $options["overwrite"])
				$this->DELETE(array("path" => $options["dest_url"]));

			if (!$io->Copy($from_url, $to_url))
			{
				$GLOBALS["APPLICATION"]->ThrowException(str_replace("#FILE#", $this->arParams["item_id"], GetMessage("WD_FILE_ERROR6")), "FILE_IS_NOT_COPIED");
				return "500 Internal server error";
			}
			else
			{
				$this->_copy_props($from_ID, $options["dest_url"], $options["overwrite"]);
				$file = $to_url;
				$oFile = $io->GetFile($file);
				$path = str_replace(array($_SERVER['DOCUMENT_ROOT'], "///", "//"), "/", $file);

				if(CModule::IncludeModule("search"))
				{
					if (rtrim($arTo['parent_id'], '/') == $this->GetMetaID('TRASH'))
					{
						CSearch::DeleteIndex('main', SITE_ID.'|'.$path);
					}
					else
					{
						$this->Reindex($file);
					}
				}

				if (COption::GetOptionInt("main", "disk_space") > 0)
				{
					CDiskQuota::updateDiskQuota("file", $oFile->GetFileSize(), "add");
				}
			}
		}
		else
		{
			$params = $this->GetFilesAndFolders($from_ID);
			if (empty($params))
			{
				$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR3"), "DESTINATION_FILE_OR_FOLDER_IS_NOT_EXISTS");
				return "500 Internal Server Error";
			}

			sort($params, SORT_STRING);

			foreach ($params as $file)
			{
				$file = CWebDavBase::CleanRelativePathString($file);
				if($file === false)
				{
					return "409 Conflict";
				}
				$bDir = $io->DirectoryExists($file);
				if ($bDir)
				{
					$file = $this->_slashify($file);
				}

				$destfile = str_replace($from_url, $to_url, $file);

				if ($bDir)
				{
					if (
						! $io->DirectoryExists($destfile)
						&& ! $io->CreateDirectory($destfile)
					)
					{
						$GLOBALS["APPLICATION"]->ThrowException(str_replace("#FOLDER#", str_replace($this->real_path_full, "", $destfile), GetMessage("WD_FILE_ERROR7")), "FOLDER_IS_NOT_CREATED");
						return "409 Conflict";
					}
					else
					{
						$this->_copy_props(str_replace(array($this->real_path_full, "///", "//"), "/", $file), str_replace(array($this->real_path_full, "///", "//"), "/", $destfile), $drop);
					}
				}
				else
				{
					if ($io->FileExists($destfile))
					{
						if (!$options["overwrite"])
						{
							$GLOBALS["APPLICATION"]->ThrowException(str_replace("#FILE#", str_replace($this->real_path_full, "", $destfile), GetMessage("WD_FILE_ERROR8")), "FILE_ALREADY_EXISTS");
							return "409 Conflict";
						}
						$this->DELETE(array("path" => str_replace(array($this->real_path_full, "///", "//"), "/", $destfile)));
					}
					if (!$io->Copy($file, $destfile))
					{
						$GLOBALS["APPLICATION"]->ThrowException(str_replace("#FILE#", str_replace($this->real_path_full, "", $destfile), GetMessage("WD_FILE_ERROR6")), "FILE_IS_NOT_COPIED");
						return "409 Conflict";
					}
					else
					{

						//$this->_copy_props(str_replace(array($this->real_path_full, "///", "//"), "/", $file), str_replace(array($this->real_path_full, "///", "//"), "/", $destfile), $drop);
						$this->_copy_props(str_replace($this->real_path_full, "/", $file), str_replace($this->real_path_full, "/", $destfile), $drop);
						$file = $destfile;

						$this->Reindex($file);
						if (COption::GetOptionInt("main", "disk_space") > 0)
						{
							$oFile = $io->GetFile($file);
							CDiskQuota::updateDiskQuota("file", $oFile->GetFileSize(), "add");
						}
					}
				}
			}
		}

		clearstatcache();

		if ($drop)
		{
			$result = $this->DELETE(array("path" => $from_ID, "force" => true));
			if (intval($result) != 204)
				return $result;
		}
		return (!$to_ID ? "201 Created" : "204 No Content");
	}

	function MKCOL($options)
	{
		$io = self::GetIo();
		$this->IsDir($options);
		$result = '201 Created';

		if ($this->arParams["is_file"])
		{
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR11"), "FOLDER_CAN_NOT_REPLACE_FILE");
			$result = '405 Method not allowed';
		}
		elseif ($_SERVER['REQUEST_METHOD'] == "MKCOL" && !empty($_SERVER['CONTENT_LENGTH']))
		{
			$result = '415 Unsupported media type';
		}
		else
		{
			if ($this->arParams["not_found"])
			{
				$path = $io->CombinePath($this->arParams["parent_id"], $this->arParams["base_name"]);
			}
			else
			{
				$path = $this->arParams['item_id'];
			}
			$res = explode("/", $path);
			$res = array_filter(!empty($res) && is_array($res) ? $res : array($path));

			$path = $io->CombinePath($this->real_path_full, $path);
			$name = trim(array_pop($res));
			$parent = $io->CombinePath($this->real_path_full, implode("/", $res));

			if (! $io->DirectoryExists($parent))
			{
				$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR9"), "PARENT_FOLDER_IS_NOT_FOUNDED");
				$result = '409 Conflict';
			}
			elseif ($io->FileExists($parent))
			{
				$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR10"), "FOLDER_CAN_NOT_BE_CREATED_IN_THE_FILE");
				$result = '403 Forbidden';
			}
			else
			{
				$stat = $io->CreateDirectory($io->CombinePath($parent, $name));
				if (!$stat)
				{
					$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR12"));
					$result = '403 Forbidden';
				}
			}
		}
		return $result;
	}

	function GetMetaID($sMetaName)
	{
		$io = self::GetIo();
		if (isset($this->meta_names[$sMetaName]))
		{
			//$file = $io->CombinePath($this->real_path_full, $this->meta_names[$sMetaName]['name']);
			$file = CWebDavBase::CleanRelativePathString($this->meta_names[$sMetaName]['name'], $this->real_path_full);
			if($file === false)
			{
				return null;
			}
			if ($io->FileExists($file))
			{
				return "/".$this->meta_names[$sMetaName]['name'];
			}
			else
			{
				$stat = $io->CreateDirectory($file);
				return "/".$this->meta_names[$sMetaName]['name'];
			}
		}
		return null;
	}

	function _move_to_trash($options, $arParams)
	{
		$io = self::GetIo();
		if ($arParams['is_dir'])
		{
			$params = $this->GetFilesAndFolders($arParams["item_id"]);
			if (!empty($params))
			{
				$tmpParams = $this->arParams;
				sort($params, SORT_STRING);
				foreach ($params as $file)
				{
					$localpath = str_replace(array($this->real_path_full, "///", "//"), "/", $file);
					$arUndeleteOptions = array(
						"props" => array(
							array(
								"ns" => "BX:",
								"name" => "UNDELETE",
								"val" => $localpath
							)
						),
						"path" => $localpath
					);
					$this->PROPPATCH($arUndeleteOptions);
				}
				$this->arParams = $tmpParams;
			}
			$destName = $arParams['base_name'] . " " . $this->CorrectName(ConvertTimeStamp(time(), "FULL"));
		}
		else
		{
			$arTo = $this->arParams;
			$arUndeleteOptions = array(
				"path" => $arTo["item_id"],
				"props" => array(
					array(
						"ns" => "BX:",
						"name" => "UNDELETE",
						"val" => $arTo["item_id"]
					)
				)
			);
			$this->PROPPATCH($arUndeleteOptions);
			$destName = substr($arTo['base_name'], 0, -strlen($arTo['file_extention'])) . " " . $this->CorrectName(ConvertTimeStamp(time(), "FULL")) . $arTo['file_extention'];
		}

		$options['dest_url'] = $io->CombinePath("/", $this->meta_names['TRASH']['name'], $destName);
		$options['rename'] = true;
		$status = $this->MOVE($options);
		if (intval($status) == 201)
		{
			return "204 No Content";
		}
		else
		{
			$GLOBALS["APPLICATION"]->ResetException();
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR16"), "FILE_OR_FOLDER_TRASH_ERROR");
			return $status;
		}
	}

	function DELETE($options)
	{
		$io = self::GetIo();
		if (isset($options['path']))
			$options['path'] = $this->_udecode($options['path']);
		$this->IsDir($options);
		if ($this->arParams["not_found"])
		{
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR3"), "DESTINATION_FILE_OR_FOLDER_IS_NOT_FOUND");
			return "404 Not found";
		}

		if(!$this->CheckRights("DELETE", true, $options["path"]))
		{
			$this->ThrowAccessDenied();
			return "403 Forbidden";
		}

		$quota = false;
		if (COption::GetOptionInt("main", "disk_space") > 0)
			$quota = new CDiskQuota();

		$trashPath = $this->GetMetaID("TRASH");
		$arPath = explode("/", $this->arParams["item_id"]);
		if (!$this->arParams["is_dir"])
		{

			//$file = $io->CombinePath($this->real_path_full, $this->arParams["item_id"]);
			//$path = $io->CombinePath($this->real_path, $this->arParams["item_id"]);

			$file = CWebDavBase::CleanRelativePathString($this->arParams["item_id"], $this->real_path_full);
			$path = CWebDavBase::CleanRelativePathString($this->arParams["item_id"], $this->real_path);
			if($file === false || $path === false)
			{
				return "404 Not found";
			}

			$arPath = explode("/", $this->arParams["item_id"]);
			if (($arPath[1] != $this->meta_names["TRASH"]["name"]) && (!isset($options['force'])))		   // not in trash yet
			{
				return $this->_move_to_trash($options, $this->arParams);
			} else {											 // in trash or options[force]
				$oFile = $io->GetFile($file);
				$file_size = $oFile->GetFileSize();
				if ($io->Delete($file))
				{
					$this->_delete_props($this->arParams['item_id']);
					$GLOBALS["APPLICATION"]->RemoveFileAccessPermission(Array(SITE_ID, $path));

					if (CModule::IncludeModule("search"))
						CSearch::DeleteIndex("main", SITE_ID."|".$path);
					if ($quota)
						$quota->updateDiskQuota("file", $file_size, "delete");
				}
				else
				{
					$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR3"), "DESTINATION_FILE_OR_FOLDER_IS_NOT_FOUND");
					return "404 Not found";
				}
			}
		}
		else
		{
			if (($arPath[1] != $this->meta_names["TRASH"]["name"]) && (!isset($options['force'])))
			{
				return $this->_move_to_trash($options, $this->arParams);
			}
			else
			{
				$params = $this->GetFilesAndFolders($this->arParams["item_id"]);
				if (empty($params))
					return true;

				rsort($params, SORT_STRING);
				foreach ($params as $file)
				{

					$path = str_replace($this->real_path_full, "", $file);
					$path = $io->CombinePath("/", $path);
					$file = $io->CombinePath($this->real_path_full, $path);
					if(!$io->ValidatePathString($file))
					{
						return "404 Not found";
					}

					if ($io->FileExists($file))
					{
						//$path = str_replace($_SERVER['DOCUMENT_ROOT'], "", $file);
						$oFile = $io->GetFile($file);
						$file_size = $oFile->GetFileSize();
						if ($io->Delete($file))
						{
							$this->_delete_props(str_replace(array($this->real_path_full, "///", "//"), "/", $file));
							$GLOBALS["APPLICATION"]->RemoveFileAccessPermission(Array(SITE_ID, $path));
							if (CModule::IncludeModule("search"))
								CSearch::DeleteIndex("main", SITE_ID."|".$path);
							if ($quota)
								$quota->updateDiskQuota("file", $file_size, "delete");
						}
						else
						{
							$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR3"), "DESTINATION_FILE_OR_FOLDER_IS_NOT_FOUND");
							return "404 Not found";
						}
					}
					elseif ($io->DirectoryExists($file))
					{
						$path = str_replace($_SERVER['DOCUMENT_ROOT'], "", $file);
						if ($io->Delete($file))
						{
							$this->_delete_props(str_replace(array($this->real_path_full, "///", "//"), "/", $file));
							$GLOBALS["APPLICATION"]->RemoveFileAccessPermission(Array(SITE_ID, $path));
						}
						else
						{
							$GLOBALS["APPLICATION"]->ThrowException(GetMessage("WD_FILE_ERROR3"), "DESTINATION_FILE_OR_FOLDER_IS_NOT_FOUND");
							return "404 Not found";
						}
					}
				}

				if ($path == $trashPath) //  all the trash was cleaned
				{
					$trashID = $this->GetMetaID('TRASH');
				}
			}
		}
		clearstatcache();
		return "204 No Content";
	}

	function IsDir($options = array())
	{
		global $DB;
		$io = self::GetIo();
		$options = (is_array($options) ? $options : array());
		$path = $this->_udecode(array_key_exists("path", $options) ? $options["path"] : $this->_path);

		if (is_set($options, "section_id"))
			$path = $options["section_id"];
		elseif (is_set($options, "element_id"))
			$path = $options["element_id"];

		if (substr($path, 0, 1) != "/")
			$path = "/".$path;

		$path = $this->MetaNamesReverse(explode("/", $path));
		$id = md5($path);

		if (in_array($id, $this->CACHE))
		{
			$this->arParams = array_merge($this->arParams, $this->CACHE[$id]);
			return $this->arParams["is_dir"];
		}
		$path = $io->CombinePath("/", $path);
		if(!$io->ValidatePathString($path))
		{
			return false;
		}
		$path_copy = $path;

		$path = $io->CombinePath($this->real_path_full, $path);
		$params = array(
			"item_id" => "/",
			"not_found" => false,
			"is_dir" => false,
			"is_file" => false,
			"parent_id" => false,
			"base_name" => substr(strrchr($path , '/'), 1)
		);

		$res = array_filter(explode("/", $path_copy));
		if ($io->DirectoryExists($path))
		{
			$params["item_id"] = $path_copy;
			$params["is_dir"] = true;
			$name = array_pop($res);
			if ($name)
			{
				$params["dir_array"] = array(
					"ID" => $params["item_id"],
					"IBLOCK_SECTION_ID" => implode("/", $res),
					"NAME" => $name
				);
				$params["parent_id"] = implode("/", $res);
			}
		}
		elseif ($io->FileExists($path))
		{
			$ioFile = $io->GetFile($path);
			$params["item_id"] = $path_copy;
			$params["is_file"] = true;
			$params["element_array"] = array(
				"ID" => $params["item_id"],
				"NAME" => array_pop($res),
				"TIMESTAMP_X" => $ioFile->GetModificationTime() + CTimeZone::GetOffset()
			);

			$params["element_array"]["EXTENTION"] = strtolower(strrchr($params["element_array"]["NAME"] , '.'));
			if ($params["element_array"]["EXTENTION"] == $params["element_array"]["NAME"])
				$params["element_array"]["EXTENTION"] = "";

			$params["parent_id"] = implode("/", $res);
			$params["element_name"] = $params["element_array"]["NAME"];
			$params["file_name"] = $params["element_array"]["NAME"];
			$params["file_extention"] = strtolower(strrchr($params["element_array"]["NAME"] , '.'));
		}
		else
		{
			array_pop($res);
			$params["not_found"] = true;
			$params["parent_id"] = '/'.implode("/", $res);
		}

		$params["element_array"]["SHOW"] = ($this->permission >= "W" ? array("EDIT" => "Y", "DELETE" => "Y") : array());

		if ($params["parent_id"])
		{
			$params["parent_id"] = $this->_slashify($io->CombinePath("/", $params["parent_id"]));
		}

		$this->arParams = $params;
		$this->CACHE[$id] = $params;
		return $params["is_dir"];
	}

	function IsTrashEmpty()
	{
		$io = self::GetIo();
		$trashSectionPath = $this->GetMetaID('TRASH');
		$status = true;
		$realTrashPath = $io->CombinePath($this->real_path_full, $trashSectionPath);
		if ($io->DirectoryExists($realTrashPath))
		{
			$oDir = $io->GetDirectory($realTrashPath);

			$arChildren = $oDir->GetChildren();
			$status = (sizeof($arChildren) <= 0);
		}
		return $status;
	}

	function GetNavChain($options = array(), $utf = false)
	{
		static $nav_chain = array();

		$utf = ($utf === true ? "Y" : "N");
		$this->IsDir($options, $this->replace_symbols);

		if (
			$this->arParams["not_found"] === true
			&& empty($this->arParams["item_id"])
		)
		{
			return array();
		}

		$id = md5($this->arParams["item_id"]);
		if (!is_set($nav_chain, $utf.$id))
		{
			$nav_chain["Y".$id] = array();
			$nav_chain["N".$id] = array();
			$res = explode("/", $this->arParams["item_id"]);
			if (empty($res) && !empty($this->arParams["item_id"]))
				$res = array($this->arParams["item_id"]);

			foreach ($res as $val)
			{
				if (empty($val))
					continue;

				foreach($this->meta_names as $metaName => $metaArr)
				{
					if ($val == $metaArr["name"])
						$val = $metaArr["alias"];
				}

				if (SITE_CHARSET != "UTF-8")
					$nav_chain["Y".$id][] = $GLOBALS["APPLICATION"]->ConvertCharset($val, SITE_CHARSET, "UTF-8");
				else
					$nav_chain["Y".$id][] = $val;
				$nav_chain["N".$id][] = $val;
			}
		}
		return $nav_chain[$utf.$id];
	}

	function GetSectionsTree($options = array()) // DEPRECATED FROM 11.5.0
	{
		$io = self::GetIo();
		if (!function_exists("__get_folder_tree"))
		{
			function __get_folder_tree($path, $path_chunc, $deep, &$arSection)
			{
				static $io = false;

				if ($io === false)
					$io = CBXVirtualIo::GetInstance();

				if (!is_array($arSection))
					$arSection = array();

				if($path === false)
				{
					return false;
				}

				if ($io->DirectoryExists($path))
				{
					$oDir = $io->GetDirectory($path);
					$arChildren = $oDir->GetChildren();
					foreach($arChildren as $node)
					{
						$deep++;
						$filename = $node->GetName();
						$tmp_path = $node->GetPathWithName();

						if ($io->DirectoryExists($tmp_path))
						{
							$filename = $this->MetaNamesReverse($filename);
							$arSection[] = array(
								"ID" => str_replace($path_chunc, "", $tmp_path),
								"DEPTH_LEVEL" => $deep,
								"NAME" => $filename);
							__get_folder_tree($tmp_path, $path_chunc, $deep, $arSection);
						}
					}
				}
			}
		}

		static $sections = array();

		$this->IsDir($options, $this->replace_symbols);

		if ($this->arParams["not_found"] || !$this->arParams["is_dir"])
			return array();

		$id = md5($this->arParams["item_id"]);

		if (!is_set($sections, $id))
		{
			//$path = $io->CombinePath($this->real_path_full, $this->arParams["item_id"]);
			$path = CWebDavBase::CleanRelativePathString($this->arParams["item_id"], $this->real_path_full);
			$arResult = null;
			__get_folder_tree($path, $this->real_path_full, 0, $arResult);
			$sections[$id] = $arResult;
		}

		return $sections[$id];
	}

	function GetFilesAndFolders($path = false)
	{
		$io = self::GetIo();
		if (!function_exists("__get_files_and_folders"))
		{
			function __get_files_and_folders($path, &$arSection)
			{
				static $io = false;

				if ($io === false)
					$io = CBXVirtualIo::GetInstance();

				if (!is_array($arSection))
					$arSection = array();

				$oDir = $io->GetDirectory($path);
				if ($oDir->IsExists())
				{
					$arSection[] = $path;
					$arChildren = $oDir->GetChildren();
					foreach($arChildren as $node)
					{
						$tmp_path = $node->GetPathWithName();
						$arSection[] = $tmp_path;

						if ($node->IsDirectory())
							__get_files_and_folders($tmp_path, $arSection);
					}
				}
				elseif ($io->FileExists($path))
				{
					$arSection[] = $path;
				}
			}
		}

		$result = array();

		if ($path)
		{
			//$path = $io->CombinePath($this->real_path_full, $path);
			$path = CWebDavBase::CleanRelativePathString($path, $this->real_path_full);
			if($path === false)
			{
				return false;
			}
			__get_files_and_folders($path, $result);
		}

		return $result;
	}

	function CheckWebRights($method = "", $arParams = array(), $simple = true)
	{
		$strong = ($method !== "");

		$path = '';
		if (is_array($arParams['arElement']))
			$path = (isset($arParams['arElement']['item_id']) ? $arParams['arElement']['item_id'] : '');
		elseif (is_string($arParams['arElement']))
			$path = $arParams['arElement'];
		$result = $this->CheckRights($method, $strong, $path);
		return $result;
	}

	function CheckRights($method, $strong, &$path)
	{
		$result = true;
		if (!parent::CheckRights($method))
		{
			$result = false;
			$GLOBALS["APPLICATION"]->ThrowException(GetMessage('WD_ACCESS_DENIED'), 'ACCESS_DENIED');
		}
		elseif ($path <> '')
		{
			$io = CBXVirtualIo::GetInstance();
			$path = $io->CombinePath($this->_udecode($path));
			$strFileName = GetFileName($path);
			$extention = ".".strtolower(GetFileExtension($strFileName));
			if (in_array($method, array("COPY", "MOVE", "PUT")))
			{
				if (!$GLOBALS["USER"]->IsAdmin() && HasScriptExtension($strFileName))
				{
					$result = false;
					$GLOBALS['APPLICATION']->ThrowException(GetMessage("WD_FILE_ERROR13"), "FORBIDDEN_EXTENTION");
				}
				elseif (IsFileUnsafe($strFileName) || $strFileName == "index.php")
				{
					$result = false;
					$GLOBALS['APPLICATION']->ThrowException(GetMessage("WD_FILE_ERROR14"), "FORBIDDEN_NAME");
				}
				elseif (!$io->ValidatePathString($io->CombinePath("/", $path)) || !$io->ValidateFilenameString($strFileName))
				{
					$result = false;
					$GLOBALS['APPLICATION']->ThrowException(GetMessage("WD_FILE_ERROR14"), "FORBIDDEN_NAME");
				}
				elseif (in_array($extention, $this->arFileForbiddenExtentions["WRITE"]))
				{
					$result = false;
					$GLOBALS['APPLICATION']->ThrowException(GetMessage("WD_FILE_ERROR13"), "FORBIDDEN_EXTENTION");
				}
			}
			elseif (in_array($extention, $this->arFileForbiddenExtentions["READ"]))
			{
				$result = false;
				$GLOBALS["APPLICATION"]->ThrowException(GetMessage('WD_ACCESS_DENIED'), 'ACCESS_DENIED');
			}
		}

		return $result;
	}

	function __prop_file_name($ID, $oldMode=false)
	{
		static $bDirPathChecked = false;
		if (!$bDirPathChecked)
		{
			CheckDirPath($GLOBALS["WEBDAV"]["PATH"]);
			$bDirPathChecked = true;
		}
		if (substr($ID, 0, 1) !== '/')
			$ID = '/'.$ID;
		$id = md5(rtrim(($oldMode ? $this->base_url_full : $this->base_url).$ID, "/"));
		$file = $GLOBALS["WEBDAV"]["PATH"]."props".$id;
		return $file;
	}

	function _get_props($ID)
	{
		$res = @file_get_contents($this->__prop_file_name($ID));

		if ($res == false)
			$res = @file_get_contents($this->__prop_file_name($ID, true));

		$res = @unserialize($res);
		$res = (is_array($res) ? $res : array());
		return $res;
	}

	function _set_props($ID, $vals)
	{
		if (empty($vals))
		{
			@unlink($this->__prop_file_name($ID));
		}
		else
		{
			@file_put_contents($this->__prop_file_name($ID), @serialize($vals));
		}
	}

	function _copy_props($fromID, $toID, $move=false)
	{
		$pathFrom = $this->__prop_file_name($fromID);
		if (file_exists($pathFrom))
		{
			$pathTo = $this->__prop_file_name($toID);
			if (!$move)
				@copy($pathFrom, $pathTo);
			else
				@rename($pathFrom, $pathTo);
		}
	}

	function _delete_props($ID)
	{
		$this->_set_props($ID, array());
	}

	function _mimetype($fspath)
	{
		$io = self::GetIo();
		if ($io->DirectoryExists($fspath))
		{
			return 'httpd/unix-directory';
		}
		else if (function_exists('mime_content_type') && $io->FileExists($fspath))
		{
			$mime_type = mime_content_type(CBXVirtualIoFileSystem::ConvertCharset($fspath));
		}

		if (empty($mime_type))
		{
			$mime_type = $this->get_mime_type($fspath);
		}

		return $mime_type;
	}

	function _get_path($path)
	{
		$io = self::GetIo();
		if (is_integer($path) && $path <= 0 || $path == "0")
			return "/";
		$res = explode("/", $path);
		if (empty($res))
			$res[] = $path;
		$res = $this->_slashify($io->CombinePath('/', (! empty($res) ? implode("/", $res) : '')));
		return $res;
	}

	function _get_fileinfo($path)
	{
		$io = self::GetIo();
		if (strpos($path, $this->real_path_full) === 0)
		{
			$path = CWebDavBase::ConvertPathToRelative($path, $this->real_path_full);
		}
		$path = CWebDavBase::CleanRelativePathString($path);
		if($path === false)
		{
			return false;
		}
		$fspath = $io->CombinePath($this->real_path_full, $path);


		//$fspath = $path;
		//if (strpos($path, $this->real_path_full) === false)
			//$fspath = str_replace(array("///", "//"), "/", $this->real_path_full."/".$path);
		//else
			//$path = str_replace(array($this->real_path_full, "///", "//"), "/", $path);

		$bDir = $io->DirectoryExists($fspath);

		$info = array();
		$info['path'] = ($bDir ? $this->_slashify($path) : $path);
		$info['path'] = $this->MetaNamesReverse(explode('/', $info['path']), 'name', 'alias');

		if (SITE_CHARSET != "UTF-8")
		{
			$info['path'] = $GLOBALS["APPLICATION"]->ConvertCharset($info['path'], SITE_CHARSET, "UTF-8");
		}

		$info['props'] = array();

		if ($bDir)
			$ioObj = $io->GetDirectory($fspath);
		else
			$ioObj = $io->GetFile($fspath);

		$tzOffset = CTimeZone::GetOffset();
		$info['props'][] = $this->_mkprop('creationdate', $ioObj->GetCreationTime() + $tzOffset);
		$info['props'][] = $this->_mkprop('getlastmodified', $ioObj->GetModificationTime() + $tzOffset);

		if ($bDir)
		{
			$info['props'][] = $this->_mkprop('resourcetype', 'collection');
			$info['props'][] = $this->_mkprop('getcontenttype', 'httpd/unix-directory');
		}
		else
		{
			$info['props'][] = $this->_mkprop('resourcetype', '');
			if ($ioObj->IsReadable())
				$info['props'][] = $this->_mkprop('getcontenttype', $this->_mimetype($fspath));
			else
				$info['props'][] = $this->_mkprop('getcontenttype', 'application/x-non-readable');
			$info['props'][] = $this->_mkprop('getcontentlength', $ioObj->GetFileSize());
		}

		$arProps = $this->_get_props($path);
		if (is_array($arProps))
		{
			foreach ($arProps as $name => $prop)
			{
				if($name != "LOCK")
				{
					$info["props"][] = CWebDavBase::_mkprop($prop["ns"], $prop["name"], $prop["value"]);
				}
			}
		}

		return $info;
	}
}

class CDBResultWebDAVFiles extends CDBResult
{
	function CDBResultWebDAVFiles($res)
	{
		parent::CDBResult($res);
	}

	function Fetch()
	{
		global $DB;
		if ($res = parent::Fetch())
		{
			$res["~TIMESTAMP_X"] = $res["TIMESTAMP_X"];
			$res["TIMESTAMP_X"] = ConvertTimeStamp($res["~TIMESTAMP_X"], "FULL");
		}
		return $res;
	}

	function GetNext()
	{
		global $DB;
		if ($res = parent::GetNext())
		{
			$result = $res;
			foreach ($res as $key => $val)
			{
				if (substr($key, 0, 2) == "~~")
				{
					unset($result[$key]);
					$result[substr($key, 1)] = $val;
				}
			}
		}
		return $result;
	}
}