feat: mobile-like window size and always-visible stats
- Changed window size to mobile phone format (400x800) - Removed width condition for ActiveProxyFooter - now always visible - Added run-umbrix.sh launch script with icon copying - Stats cards now display on all screen sizes
This commit is contained in:
193
update-server/api.php
Normal file
193
update-server/api.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/**
|
||||
* Umbrix Update Server API для Desktop Платформ
|
||||
*
|
||||
* Сервер обновлений для Windows, macOS и Linux версий приложения.
|
||||
* Android использует Google Play Store для обновлений.
|
||||
*
|
||||
* Версия: 1.1
|
||||
*
|
||||
* Использование:
|
||||
* GET /api/latest - получить последнюю версию для Desktop
|
||||
* GET /api/latest?include_prerelease=true - включая бета-версии
|
||||
*/
|
||||
|
||||
// === НАСТРОЙКИ ===
|
||||
|
||||
// Разрешенные домены для CORS (замените на свой домен)
|
||||
$allowed_origins = [
|
||||
'https://umbrix.net',
|
||||
'https://www.umbrix.net',
|
||||
'https://api.umbrix.net'
|
||||
];
|
||||
|
||||
// Путь к файлу с информацией о версии
|
||||
$version_file = __DIR__ . '/latest.json';
|
||||
|
||||
// Включить логирование запросов
|
||||
$enable_logging = true;
|
||||
$log_file = __DIR__ . '/logs/access.log';
|
||||
|
||||
// Ограничение запросов (Rate Limiting)
|
||||
$rate_limit_enabled = true;
|
||||
$max_requests_per_minute = 10;
|
||||
|
||||
// === КОНЕЦ НАСТРОЕК ===
|
||||
|
||||
// Установка заголовков
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('X-Powered-By: Umbrix Update Server');
|
||||
|
||||
// CORS - разрешаем запросы с приложения
|
||||
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
|
||||
if (in_array($origin, $allowed_origins)) {
|
||||
header("Access-Control-Allow-Origin: $origin");
|
||||
} else {
|
||||
header('Access-Control-Allow-Origin: *'); // Разрешаем все для начала
|
||||
}
|
||||
header('Access-Control-Allow-Methods: GET, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type');
|
||||
|
||||
// Обработка preflight запроса
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||
http_response_code(200);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Только GET запросы
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
sendError(405, 'Method Not Allowed');
|
||||
}
|
||||
|
||||
// Rate Limiting
|
||||
if ($rate_limit_enabled && !checkRateLimit($max_requests_per_minute)) {
|
||||
sendError(429, 'Too Many Requests', 'Превышен лимит запросов. Попробуйте позже.');
|
||||
}
|
||||
|
||||
// Логирование
|
||||
if ($enable_logging) {
|
||||
logRequest($log_file);
|
||||
}
|
||||
|
||||
// Проверка существования файла с версией
|
||||
if (!file_exists($version_file)) {
|
||||
sendError(500, 'Internal Server Error', 'Файл с версией не найден');
|
||||
}
|
||||
|
||||
// Чтение и парсинг JSON
|
||||
$version_data = file_get_contents($version_file);
|
||||
$version_info = json_decode($version_data, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
sendError(500, 'Internal Server Error', 'Ошибка парсинга JSON: ' . json_last_error_msg());
|
||||
}
|
||||
|
||||
// Проверка обязательных полей
|
||||
$required_fields = ['version', 'build_number', 'download_url', 'published_at'];
|
||||
foreach ($required_fields as $field) {
|
||||
if (!isset($version_info[$field])) {
|
||||
sendError(500, 'Internal Server Error', "Отсутствует обязательное поле: $field");
|
||||
}
|
||||
}
|
||||
|
||||
// Фильтр пре-релизов
|
||||
$include_prerelease = isset($_GET['include_prerelease']) && $_GET['include_prerelease'] === 'true';
|
||||
|
||||
if (!$include_prerelease && isset($version_info['is_prerelease']) && $version_info['is_prerelease'] === true) {
|
||||
// Вернуть пустой ответ, если пре-релиз не запрошен
|
||||
sendError(404, 'Not Found', 'Стабильная версия не найдена');
|
||||
}
|
||||
|
||||
// Добавление дополнительной информации
|
||||
$version_info['server_time'] = date('c');
|
||||
$version_info['api_version'] = '1.0';
|
||||
|
||||
// Успешный ответ
|
||||
http_response_code(200);
|
||||
echo json_encode($version_info, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
exit();
|
||||
|
||||
// === ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ===
|
||||
|
||||
/**
|
||||
* Отправка ошибки в формате JSON
|
||||
*/
|
||||
function sendError($code, $message, $details = null) {
|
||||
http_response_code($code);
|
||||
$error = [
|
||||
'error' => $message,
|
||||
'code' => $code,
|
||||
'timestamp' => date('c')
|
||||
];
|
||||
if ($details) {
|
||||
$error['details'] = $details;
|
||||
}
|
||||
echo json_encode($error, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка лимита запросов
|
||||
*/
|
||||
function checkRateLimit($max_requests) {
|
||||
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
||||
$cache_file = sys_get_temp_dir() . '/umbrix_ratelimit_' . md5($ip);
|
||||
|
||||
$current_time = time();
|
||||
$window_start = $current_time - 60; // Окно в 1 минуту
|
||||
|
||||
$requests = [];
|
||||
if (file_exists($cache_file)) {
|
||||
$requests = json_decode(file_get_contents($cache_file), true) ?? [];
|
||||
}
|
||||
|
||||
// Удаляем старые запросы
|
||||
$requests = array_filter($requests, function($timestamp) use ($window_start) {
|
||||
return $timestamp > $window_start;
|
||||
});
|
||||
|
||||
// Проверяем лимит
|
||||
if (count($requests) >= $max_requests) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Добавляем текущий запрос
|
||||
$requests[] = $current_time;
|
||||
file_put_contents($cache_file, json_encode($requests));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Логирование запроса
|
||||
*/
|
||||
function logRequest($log_file) {
|
||||
$log_dir = dirname($log_file);
|
||||
if (!is_dir($log_dir)) {
|
||||
mkdir($log_dir, 0755, true);
|
||||
}
|
||||
|
||||
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
||||
$user_agent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
|
||||
$request_uri = $_SERVER['REQUEST_URI'] ?? 'unknown';
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
|
||||
// Извлекаем версию приложения из User-Agent (если есть)
|
||||
$app_version = 'unknown';
|
||||
if (preg_match('/Umbrix\/([0-9.]+)/', $user_agent, $matches)) {
|
||||
$app_version = $matches[1];
|
||||
}
|
||||
|
||||
$log_entry = sprintf(
|
||||
"[%s] IP: %s | App Version: %s | URI: %s | User-Agent: %s\n",
|
||||
$timestamp,
|
||||
$ip,
|
||||
$app_version,
|
||||
$request_uri,
|
||||
$user_agent
|
||||
);
|
||||
|
||||
file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user