public function __construct($Url = '', $Utf8 = false)
 {
     if ($Url == '') {
         return;
     }
     $info = parse_url($Url);
     if ($info === false) {
         return;
     }
     if (isset($info['scheme'])) {
         $this->Protocol = $info['scheme'];
     }
     if (isset($info['host'])) {
         $this->Host = $info['host'];
     }
     if (isset($info['port'])) {
         $this->Port = $info['port'];
     }
     if (isset($info['user'])) {
         $this->User = $info['user'];
     }
     if (isset($info['pass'])) {
         $this->Password = $info['pass'];
     }
     if (isset($info['path'])) {
         $this->Path = GetPathName($info['path']);
         $this->Document = GetFileName($info['path']);
     }
     if (isset($info['fragment'])) {
         $this->Anchor = $info['fragment'];
     }
     if (isset($info['query'])) {
         parse_str($info['query'], $params);
         parent::__construct($params);
         if ($Utf8) {
             foreach ($this as $key => $value) {
                 $value = Utf8ToCp1251($value);
                 $this[$key] = $value;
             }
         }
     } else {
         parent::__construct();
     }
 }
/**
 * Проверяет возможность создания папки или файла.
 * Если предполагается что файл или папка будет создаваться в папке в которую нет прав на запись, возвращается false.
 *
 * @param $FileName
 * @return bool
 */
function IsPossiblyCreated($FileName)
{
    $FileName = RemoveLastSlash($FileName);
    $path = GetPathName($FileName, false);
    if (is_dir($path)) {
        return is_writable($path);
    }
    $len = substr_count($path, '/');
    for ($i = 0; $i < $len; $i++) {
        $pos = strrpos($path, '/');
        $path = substr($path, 0, $pos);
        if (is_dir($path)) {
            return is_writable($path);
        }
    }
    return is_writable('.');
}
function AdminUpdateCheck()
{
    global $updates_folder;
    $selected_file = '';
    // Выбранное имя файла обновления
    // Выбираем файл обновления и читаем метаданные
    if (!isset($_FILES['upload_file'])) {
        System::admin()->AddCenterBox('Ошибка');
        System::admin()->HighlightError('Неизвестная ошибка.');
        return;
    }
    $uploaded_file = $_FILES['upload_file'];
    // Загруженный файл
    // Сохраняем загруженный файл
    if ($uploaded_file['error'] != 4) {
        if ($uploaded_file['error'] != 0) {
            System::admin()->AddTextBox('Ошибка', 'Ошибка при загрузке файла. Код ошибки: ' . $_FILES['upload_file'] . '.');
            return;
        }
        if (!is_writable($updates_folder)) {
            System::admin()->AddCenterBox('Ошибка');
            System::admin()->HighlightError('Папка "' . SafeDB($updates_folder, 255, str) . '" не доступна для записи. Не удалось загрузить обновление.');
        } else {
            if (is_file($uploaded_file['tmp_name'])) {
                // Был загружен файл
                // Проверяем тип файла и сохраняем в папку updates
                if (strtolower(GetFileExt($_FILES['upload_file']['name'])) == '.zip') {
                    $selected_file = $updates_folder . $_FILES['upload_file']['name'];
                    copy($_FILES['upload_file']['tmp_name'], $selected_file);
                    Audit('Обновление системы: Загружен архив обновления "' . $selected_file . '"');
                } else {
                    System::admin()->AddCenterBox('Ошибка');
                    System::admin()->HighlightError('Разрешено загружать только ZIP файлы.');
                }
            }
        }
    } else {
        // Берем выбранный ранее загруженный файл
        if (isset($_POST['select_file'])) {
            $selected_file = $updates_folder . $_POST['select_file'];
        } else {
            System::admin()->AddCenterBox('Ошибка');
            System::admin()->HighlightError('Файл обновления не выбран.');
            return;
        }
    }
    // Проверяем select_file, пытаемся открыть и прочитать метаданные
    $zip = new ZipArchive();
    if ($zip->open($selected_file) !== true) {
        System::admin()->AddCenterBox('Ошибка');
        System::admin()->HighlightError('Не удалось открыть файл обновления, возможно архив повреждён.');
        return;
    }
    // Читаем метаданные
    $metadata = $zip->getFromName('metadata');
    $metadata = JsonDecode($metadata);
    if (!isset($metadata) || !isset($metadata['product']) || $metadata['product'] != CMS_UPDATE_PRODUCT || !isset($metadata['type']) || $metadata['type'] != 'update' || !isset($metadata['from_version']) || $metadata['from_version'] != CMS_VERSION || !isset($metadata['to_version']) || !isset($metadata['changelog'])) {
        System::admin()->AddCenterBox('Ошибка');
        System::admin()->HighlightError('Файл не является файлом обновления или не подходит к вашей версии системы.');
        return;
    }
    System::admin()->AddCenterBox('Обновление системы ' . SafeDB($metadata['from_version'], 20, str) . ' › ' . SafeDB($metadata['to_version'], 20, str));
    UseLib('markdown');
    $md = new Markdown();
    $metadata['changelog'] = $md->transform(SafeDB($metadata['changelog'], 0, str, false));
    // Проверяем разрешения на запись в файлы
    $update_files = '<h2>Обновляемые файлы:</h2><ul>';
    $numFiles = $zip->numFiles;
    $create = false;
    $reason = '';
    $create_dirs = array();
    $errors = false;
    for ($i = 0; $i < $numFiles; $i++) {
        $reason = '';
        $fn = $zip->getNameIndex($i);
        if ($fn == 'metadata') {
            continue;
        }
        if (substr($fn, -1) != '/') {
            // Файл
            if (is_file($fn)) {
                // Существует
                $create = is_writable($fn);
                $reason = 'Нет прав на запись';
            } else {
                $fn_path = GetPathName($fn, false);
                if (isset($create_dirs[$fn_path . '/'])) {
                    $create = $create_dirs[$fn_path . '/'];
                    $reason = 'Невозможно создать папку ' . $fn_path . '';
                } else {
                    $create = is_writable($fn_path);
                    $reason = 'Нет прав на запись в папку ' . $fn_path . '';
                }
            }
        } else {
            // Папка
            $create = IsPossiblyCreated($fn);
            $create_dirs[$fn] = $create;
            $reason = 'Невозможно создать, нет прав на запись';
        }
        if ($create) {
            $update_files .= '<li>' . SafeDB($fn, 255, str) . '</li>';
        } else {
            $update_files .= '<li style="color: red;">' . SafeDB($fn, 255, str) . ' (' . $reason . ')</li>';
            $errors = true;
        }
    }
    $update_files .= '</ul>';
    $zip->close();
    // Вывод информации
    System::site()->AddOnLoadJS(Indent('
		AdminUpdateShowChangelog = function(){
			$("#update_changelog").show();
			$("#update_files").hide();
		}
		AdminUpdateShowFiles = function(){
			$("#update_files").show();
			$("#update_changelog").hide();
		}
	'));
    if ($errors) {
        System::admin()->HighlightError('Невозможно обновить некоторые файлы и папки. Смотрите список файлов для более детальной информации.<br>');
    } else {
        System::admin()->Highlight('Ошибок не обнаружено, нажмите кнопку "Обновить" для обновления системы.');
    }
    $html = '
		<div style="margin: 10px 0 10px;">
			<a href="#" onclick="AdminUpdateShowChangelog(); return false;" class="button">Показать изменения</a>
			<a href="#" onclick="AdminUpdateShowFiles(); return false;" class="button">Показать файлы</a>
			' . ($errors ? '' : System::admin()->SpeedButton('Обновить', ADMIN_FILE . '?exe=update&a=apply&file=' . GetFileName($selected_file), '', true, true)) . '
		</div>
		<div id="update_changelog" style="' . ($errors ? 'display: none;' : '') . '">' . $metadata['changelog'] . '</div>
		<div id="update_files" style="' . ($errors ? '' : 'display: none;') . '">' . $update_files . '</div>
';
    System::admin()->AddText($html);
}