'Неизвестное действие', 'action' => $handleRequestAction, 'post_data' => $_POST, 'get_data' => $_GET, 'server' => $_SERVER['REQUEST_URI'] ]); } } /** * @brief Обрабатывает входящий JSON-RPC запрос * @return string JSON-ответ с результатом выполнения метода или ошибкой */ function jsonrpcRequest() { $raw = file_get_contents("php://input"); $data = json_decode($raw, true); $id = $data["id"] ?? null; try { if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception("Parse error", -32700); } $method = $data["method"] ?? ""; $params = $data["params"] ?? []; if (!function_exists($method)) { throw new Exception("Method not found", -32601); } $result = $method($params); header("Content-Type: application/json"); echo json_encode(["jsonrpc" => "2.0", "id" => $id, "result" => $result]); } catch (Exception $e) { header("Content-Type: application/json"); echo json_encode(["jsonrpc" => "2.0", "id" => $id, "error" => ["code" => $e->getCode(), "message" => $e->getMessage()]]); } } /** * @brief Подключает плагин или плагины из директории main_plugin * @param array $params Параметры подключения, ключ 'plugin' содержит имя плагина * @return string HTML-код подключённых плагинов */ function includePlugin($params) { global $path, $config; $html = ''; $pluginDir = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'main_plugin' . DIRECTORY_SEPARATOR; $requested = isset($params['plugin']) ? trim($params['plugin']) : null; if ($requested !== null && ($requested === '' || strpos($requested, '..') !== false)) { throw new Exception("Invalid plugin name", -32602); } if (!is_dir($pluginDir)) return $html; $dirs = $requested ? [$requested] : array_diff(scandir($pluginDir), ['.', '..']); foreach ($dirs as $dir) { $dirPath = $pluginDir . $dir; if (!is_dir($dirPath)) continue; $file = $dirPath . '/plug.php'; if (is_file($file)) { ob_start(); include $file; $html .= ob_get_clean(); } } return $html; } /** * @brief Получает список файлов и DOM-элементов плагина * @param array $params Параметры, ключ 'plugin' содержит имя плагина * @return array Массив ссылок на CSS, JS файлы и id элементов плагина */ function removePluginDom($params) { global $path; $plugin = isset($params['plugin']) ? trim($params['plugin']) : null; if (!$plugin || strpos($plugin, '..') !== false || !preg_match('/^[A-Za-z0-9_\-]+$/', $plugin) || !is_dir($path . 'main_plugin/' . $plugin)) { throw new Exception("Invalid plugin name"); } $pluginDir = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'main_plugin' . DIRECTORY_SEPARATOR . $plugin; $plugFile = $pluginDir . '/plug.php'; if (!is_file($plugFile)) throw new Exception("plug.php not found"); ob_start(); include $plugFile; $html = ob_get_clean(); $files = []; if (preg_match_all('/]+href=["\']([^"\']+)["\']/i', $html, $m)) $files = array_merge($files, $m[1]); if (preg_match_all('/ '; return $s; } /** * @brief Определяет текущий язык пользователя и сохраняет его в сессии * @return string Текущий язык (например, 'en', 'ru', 'lv') */ function SetLanguage(){ global $_SESSION, $path; if (isset($_POST['lng']) && $_POST['lng'] != '') $_SESSION['lng'] = $_POST['lng']; if (empty($_SESSION['lng'])){ $s = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); $a = explode('-', $s[0]); $_SESSION['lng'] = $a[0]; } return $_SESSION['lng']; } /** * @brief Разбирает URL запроса и определяет действие и путь к странице * @param string $URL URL запроса * @return array Массив с ключами 'act' и 'str', где 'act' — действие, 'str' — путь к странице */ function GetRequestURL($URL){ $c=explode('.',$URL); if ($c[1]=='html'&&count($c)!=1){ $mURL['act'] ='view'; $mURL['str'] = explode('/',$c[0]); $mURL['str'][0]="index"; if ($mURL['str'][1]=='index'){ $mURL['str'][1]=''; } if ($mURL['str'][count($mURL['str'])-1]==''){ array_pop($mURL['str']); } } else{ if ($c[1]=='xml'&&count($c)!=1){ $mURL['act'] ='edit'; $mURL['str'] = explode('/',$c[0]); $mURL['str'][0]="index"; } else{ $mURL['str']='error'; } } return $mURL; } /** * @brief Получает новости из XML-файла и формирует HTML-блоки для отображения * @param array $BlockVar Массив блоков с настройками отображения * @param string $side Сторона страницы, для которой формируются новости * @return string Сформированные HTML-блоки с новостями */ function getNews($BlockVar, $side) { global $path, $_SESSION; $lng = $_SESSION['lng'] ?? 'en'; $file = $path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'filepath.' . $lng . '.php'; $content = @file_get_contents($file); if (!$content) $content = ''; $content = preg_replace('/^\s*<\?php.*?\?>\s*/s', '', $content); $xml = @simplexml_load_string($content); $rootReal = realpath(rtrim($path, DIRECTORY_SEPARATOR)); $html = ''; $tplClass = isset($BlockVar[0]['tclass']) ? $BlockVar[0]['tclass'] : 'btitle'; $bclass = isset($BlockVar[0]['bclass']) ? $BlockVar[0]['bclass'] : 'bfloat'; $now = new DateTime(); $walk = function($node) use (&$walk, &$html, $path, $side, $lng, $rootReal, $tplClass, $bclass, $now) { $newsAttr = trim((string)$node['news']); if ($newsAttr === '') { foreach ($node->children() as $child) $walk($child); return; } $parts = explode(',', $newsAttr); if (count($parts) === 0) { foreach ($node->children() as $child) $walk($child); return; } $period = array_shift($parts); $dates = explode('/', $period); if (count($dates) !== 2) { foreach ($node->children() as $child) $walk($child); return; } $parseDate = function($str) { $parts = explode('.', $str); if (count($parts) < 5) return false; list($Y, $m, $d, $H, $i) = $parts; $dateStr = sprintf('%04d-%02d-%02d %02d:%02d:00', $Y, $m, $d, $H, $i); return DateTime::createFromFormat('Y-m-d H:i:s', $dateStr); }; $start = $parseDate($dates[0]); $end = $parseDate($dates[1]); if (!$start || !$end || $now < $start || $now > $end) { foreach ($node->children() as $child) $walk($child); return; } $blocks = array_map('trim', $parts); if (!empty($blocks) && !in_array($side, $blocks)) { foreach ($node->children() as $child) $walk($child); return; } $urlAttrRaw = trim((string)$node['url']); $titleRaw = (string)$node['title']; $urlPart = trim($urlAttrRaw, "/\\"); $pageFile = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $urlPart . '.page.php'; $pageFileReal = realpath($pageFile); $pageContent = ''; if ($pageFileReal && strpos($pageFileReal, $rootReal) === 0 && is_file($pageFileReal) && is_readable($pageFileReal)) { $pageXml = @simplexml_load_file($pageFileReal); if ($pageXml && isset($pageXml->content->{$lng})) { $pageContent = strip_tags((string)$pageXml->content->{$lng}); $maxLength = ($side === 'center') ? 300 : 100; $pageContent = mb_substr($pageContent, 0, $maxLength) . (mb_strlen($pageContent) > $maxLength ? '...' : ''); } } $nameRaw = trim((string)$node['name']); $tagPath = []; $n = $node; while ($n) { $tag = $n->getName(); if ($tag !== 'site' && $tag !== 'index') { $tagPath[] = $tag; } $n = $n->xpath('..') ? $n->xpath('..')[0] : null; } $tagPath = array_reverse($tagPath); if (empty($tagPath)) { $link = '/'; } else { $link = implode('/', $tagPath) . '.html'; } $link = htmlspecialchars($link); $readMore = 'читать дальше'; $title = $titleRaw !== '' ? htmlspecialchars($titleRaw) : ''; $html .= '