diff --git a/MIGRATION.md b/MIGRATION.md index 7f13d2c9..99e62141 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -33,8 +33,8 @@ | Nginx MAIN | `src/bin/nginx/conf/nginx.conf` использует `root /home/xc_vm/www/` и rewrite на `www/*.php`/`www/stream/*.php` | Нельзя удалить `www` без outage | | Nginx LB | `lb_configs/nginx.conf` использует `root /home/xc_vm/www/` и rewrite на `/stream/*.php` | LB останется привязан к `www` | | Certbot | `src/cli/Commands/CertbotCommand.php` использует `--webroot -w /home/xc_vm/www/` | Поломка issue/renew при cutover | -| Ministra runtime | `src/ministra/portal.php` делает `require '/home/xc_vm/www/stream/init.php'` | Прямая hard-зависимость от `www` | -| Ministra lifecycle | `RootSignalsCronJob` и `SettingsService` управляют symlink `www/c` и `www/portal.php` | Нельзя убрать `www` без переезда схемы | +| Ministra runtime | `src/ministra/portal.php` использует `StreamingRequestBootstrap::init('portal')` напрямую | ~~Закрыто L-6~~ | +| Ministra lifecycle | `RootSignalsCronJob` и `SettingsService` больше не управляют symlink `www/c` и `www/portal.php` | ~~Закрыто L-6~~ | ### 2.3. Модули: состояние интеграции @@ -59,7 +59,7 @@ | --- | --- | --- | --- | --- | | ~~L-3D~~ | ~~P2~~ | ~~Декомпозировать procedural admin table endpoint~~ | ~~Нет~~ | **Закрыто.** `TableController::index()` — thin switch-dispatcher. 45 веток → private-методы. `filterRow` → `private static`. | | ~~L-5~~ | ~~P0~~ | ~~Cutover HTTP routing и certbot c `www`~~ | ~~Нет~~ | **Закрыто.** Nginx не роутит в `www/*.php`; certbot не использует `/home/xc_vm/www/`. | -| L-6 | P0 | Развязка Ministra от `www/c` и `www/portal.php` | L-5 | Включение/выключение Ministra не создает/удаляет файлы в `www` | +| ~~L-6~~ | ~~P0~~ | ~~Развязка Ministra от `www/c` и `www/portal.php`~~ | ~~L-5~~ | **Закрыто.** `portal.php` использует `StreamingRequestBootstrap::init('portal')`. Symlink-операции удалены из `RootSignalsCronJob` и `SettingsService`. | | M-1 | P1 | Включить web boot модулей | Нет | В web-контексте реально вызываются `loadAll()` и `bootAll()` | | M-2 | P1 | Убрать хардкод модульных маршрутов и меню | M-1 | Ядро не содержит статических route/menu для модулей | | M-3 | P1 | Ввести navbar extension points | M-2 | Модули добавляют навигацию декларативно | @@ -245,8 +245,8 @@ Rollback: ### Итерация 2 -1. Закрыть L-6 (Ministra отвязка от `www`). -2. После успешного gate перейти к модульной волне M-1/M-2. +1. ~~Закрыть L-6 (Ministra отвязка от `www`).~~ +2. Перейти к модульной волне M-1/M-2. ## 9. Жесткие правила удаления diff --git a/src/bin/nginx/conf/codes/template_ministra b/src/bin/nginx/conf/codes/template_ministra new file mode 100644 index 00000000..7d898cce --- /dev/null +++ b/src/bin/nginx/conf/codes/template_ministra @@ -0,0 +1,42 @@ +location = /#CODE# { + return 302 /#CODE#/; +} + +location ^~ /#CODE#/assets/ { + alias /home/xc_vm/public/assets/#TYPE#/; +} + +location ^~ /#CODE#/ { + alias /home/xc_vm/#ALIAS#/; + try_files $uri $uri.html $uri/ @fc_#CODE#; + #WHITELIST# + location ~ \.php$ { + limit_req zone=one burst=#BURST# nodelay; + try_files $uri @fc_#CODE#; + fastcgi_index index.php; + fastcgi_pass php; + include fastcgi_params; + fastcgi_buffering on; + fastcgi_buffers 96 32k; + fastcgi_buffer_size 32k; + fastcgi_max_temp_file_size 0; + fastcgi_keep_conn on; + fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + } +} + +location @fc_#CODE# { + fastcgi_index index.php; + fastcgi_pass php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /home/xc_vm/public/index.php; + fastcgi_param SCRIPT_NAME /public/index.php; + fastcgi_param XC_SCOPE #TYPE#; + fastcgi_param XC_CODE #CODE#; + fastcgi_buffering on; + fastcgi_buffers 96 32k; + fastcgi_buffer_size 32k; + fastcgi_max_temp_file_size 0; + fastcgi_keep_conn on; +} diff --git a/src/bin/nginx/conf/ministra_legacy.conf b/src/bin/nginx/conf/ministra_legacy.conf new file mode 100644 index 00000000..c6cb21b2 --- /dev/null +++ b/src/bin/nginx/conf/ministra_legacy.conf @@ -0,0 +1 @@ +set $ministra_legacy_redirect 0; diff --git a/src/bin/nginx/conf/nginx.conf b/src/bin/nginx/conf/nginx.conf index a96bebff..13aa904d 100644 --- a/src/bin/nginx/conf/nginx.conf +++ b/src/bin/nginx/conf/nginx.conf @@ -46,6 +46,7 @@ http { include codes/*.conf; include ssl.conf; include custom.conf; + include ministra_legacy.conf; index index.php index.html index.htm; try_files $uri $uri.html $uri/ @extensionless-php; root /home/xc_vm/www/; @@ -304,23 +305,50 @@ http { fastcgi_param XC_API internal; } - # ─── Ministra Legacy Portal (L-6 pending) ──────────────── - location = /c/portal.php { - limit_req zone=one burst=8; - include limit_queue.conf; - fastcgi_index index.php; - fastcgi_pass php; - include fastcgi_params; - fastcgi_buffering on; - fastcgi_buffers 128 32k; - fastcgi_buffer_size 32k; - fastcgi_max_temp_file_size 0; - fastcgi_keep_conn on; - fastcgi_param SCRIPT_FILENAME /home/xc_vm/ministra/portal.php; - fastcgi_param SCRIPT_NAME /ministra/portal.php; + # ─── Ministra Legacy URL /c/ ───────────────────────────── + location = /c { + if ($ministra_legacy_redirect = 0) { + return 404; + } + + return 302 /c/; + } + + location ^~ /c/ { + if ($ministra_legacy_redirect = 0) { + return 404; + } + + alias /home/xc_vm/ministra/; + index index.html; + try_files $uri $uri.html $uri/ /c/index.html =404; + + location ~ \.php$ { + if ($ministra_legacy_redirect = 0) { + return 404; + } + + limit_req zone=one burst=8; + include limit_queue.conf; + try_files $uri =404; + fastcgi_index index.php; + fastcgi_pass php; + include fastcgi_params; + fastcgi_buffering on; + fastcgi_buffers 128 32k; + fastcgi_buffer_size 32k; + fastcgi_max_temp_file_size 0; + fastcgi_keep_conn on; + fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + } } location = /portal.php { + if ($ministra_legacy_redirect = 0) { + return 404; + } + return 302 /c/portal.php?$args; } diff --git a/src/cli/CronJobs/RootSignalsCronJob.php b/src/cli/CronJobs/RootSignalsCronJob.php index 702cbf41..4a7e15c7 100644 --- a/src/cli/CronJobs/RootSignalsCronJob.php +++ b/src/cli/CronJobs/RootSignalsCronJob.php @@ -232,6 +232,13 @@ class RootSignalsCronJob implements CommandInterface { } } $rReload = false; + $rMinistraLegacyConf = 'set $ministra_legacy_redirect ' . (SettingsManager::getAll()['mag_legacy_redirect'] ? '1' : '0') . ';'; + $rCurrentMinistraLegacyConf = (trim(@file_get_contents(BIN_PATH . 'nginx/conf/ministra_legacy.conf')) ?: ''); + if ($rMinistraLegacyConf != $rCurrentMinistraLegacyConf) { + echo 'Updating Ministra legacy /c toggle...' . "\n"; + file_put_contents(BIN_PATH . 'nginx/conf/ministra_legacy.conf', $rMinistraLegacyConf); + $rReload = true; + } $rAllowedIPs = ServerRepository::getAllowedIPs(); $rXC_VMList = []; foreach ($rAllowedIPs as $rIP) { @@ -353,7 +360,7 @@ class RootSignalsCronJob implements CommandInterface { } if ($db->query("SELECT `signal_id`, `custom_data` FROM `signals` WHERE `server_id` = ? AND `custom_data` <> '' AND `cache` = 0 ORDER BY signal_id ASC;", SERVER_ID)) { $rRows = $db->get_rows(); - $rCheck = ['mag' => false, 'php' => false, 'services' => false, 'ports' => false, 'ramdisk' => false]; + $rCheck = ['php' => false, 'services' => false, 'ports' => false, 'ramdisk' => false]; foreach ($rRows as $rRow) { $rData = json_decode($rRow['custom_data'], true); switch ($rData['action']) { @@ -361,10 +368,6 @@ class RootSignalsCronJob implements CommandInterface { case 'enable_ramdisk': $rCheck['ramdisk'] = true; break; - case 'enable_ministra': - case 'disable_ministra': - $rCheck['mag'] = true; - break; case 'set_services': $rCheck['services'] = true; break; @@ -373,17 +376,6 @@ class RootSignalsCronJob implements CommandInterface { break; } } - if ($rCheck['mag']) { - if (SettingsManager::getAll()['mag_legacy_redirect']) { - if (!file_exists(MAIN_HOME . 'www/c')) { - array_unshift($rRows, ['custom_data' => json_encode(['action' => 'enable_ministra'])]); - } - } else { - if (file_exists(MAIN_HOME . 'www/c')) { - array_unshift($rRows, ['custom_data' => json_encode(['action' => 'disable_ministra'])]); - } - } - } if ($rCheck['services']) { $rCurServices = 0; $rStartScript = explode("\n", file_get_contents(MAIN_HOME . 'bin/daemons.sh')); @@ -539,16 +531,6 @@ class RootSignalsCronJob implements CommandInterface { $db->query("INSERT INTO `mysql_syslog`(`server_id`, `type`, `error`, `username`, `ip`, `database`, `date`) VALUES(?, 'UPDATE', 'Updating XC_VM...', 'root', 'localhost', NULL, ?);", SERVER_ID, time()); shell_exec('sudo ' . PHP_BIN . ' ' . MAIN_HOME . 'console.php update update 2>&1 &'); break; - case 'enable_ministra': - echo 'Enabling ministra /c...'; - shell_exec('sudo ln -sfn ' . MAIN_HOME . 'ministra ' . MAIN_HOME . 'www/c'); - shell_exec('sudo ln -sfn ' . MAIN_HOME . 'ministra/portal.php ' . MAIN_HOME . 'www/portal.php'); - break; - case 'disable_ministra': - echo 'Disabling ministra /c...'; - shell_exec('sudo rm ' . MAIN_HOME . 'www/c'); - shell_exec('sudo rm ' . MAIN_HOME . 'www/portal.php'); - break; case 'set_services': echo 'Setting PHP Services' . "\n"; $rServices = intval($rData['count']); diff --git a/src/domain/Auth/AuthRepository.php b/src/domain/Auth/AuthRepository.php index acfc1cde..40d67121 100644 --- a/src/domain/Auth/AuthRepository.php +++ b/src/domain/Auth/AuthRepository.php @@ -51,6 +51,7 @@ class AuthRepository { $rMainHome = MAIN_HOME; $rServerId = SERVER_ID; $rTemplate = file_get_contents($rMainHome . 'bin/nginx/conf/codes/template'); + $rMinistraTemplate = file_get_contents($rMainHome . 'bin/nginx/conf/codes/template_ministra'); shell_exec('rm -f ' . $rMainHome . 'bin/nginx/conf/codes/*.conf'); foreach (self::getAllCodes() as $rCode) { @@ -73,11 +74,12 @@ class AuthRepository { $rType = array('admin', 'reseller', 'ministra', 'includes/api/admin', 'includes/api/reseller', 'ministra/new', 'player')[$rCode['type']]; $rAlias = array('public/Views/admin', 'reseller', 'ministra', 'includes/api/admin', 'includes/api/reseller', 'ministra/new', 'public/assets/player')[$rCode['type']]; $rBurst = array(500, 50, 50, 1000, 1000, 50, 500)[$rCode['type']]; + $rCurrentTemplate = in_array($rType, array('ministra', 'ministra/new')) ? $rMinistraTemplate : $rTemplate; - if (strlen($rCode['code']) >= 4) { - file_put_contents($rMainHome . 'bin/nginx/conf/codes/' . $rCode['code'] . '.conf', str_replace(array('#WHITELIST#', '#CODE#', '#TYPE#', '#BURST#', '#ALIAS#'), array(implode(' ', $rWhitelist), $rCode['code'], $rType, $rBurst, $rAlias), $rTemplate)); + if (in_array($rType, array('ministra', 'ministra/new')) || strlen($rCode['code']) >= 4) { + file_put_contents($rMainHome . 'bin/nginx/conf/codes/' . $rCode['code'] . '.conf', str_replace(array('#WHITELIST#', '#CODE#', '#TYPE#', '#BURST#', '#ALIAS#'), array(implode(' ', $rWhitelist), $rCode['code'], $rType, $rBurst, $rAlias), $rCurrentTemplate)); } else { - file_put_contents($rMainHome . 'bin/nginx/conf/codes/' . $rCode['code'] . '.conf', str_replace(array('#WHITELIST#', '#CODE#', '#TYPE#', '#BURST#', '#ALIAS#'), array(implode(' ', $rWhitelist), $rCode['code'] . '/', $rType . '/', $rBurst, $rAlias . '/'), $rTemplate)); + file_put_contents($rMainHome . 'bin/nginx/conf/codes/' . $rCode['code'] . '.conf', str_replace(array('#WHITELIST#', '#CODE#', '#TYPE#', '#BURST#', '#ALIAS#'), array(implode(' ', $rWhitelist), $rCode['code'] . '/', $rType . '/', $rBurst, $rAlias . '/'), $rCurrentTemplate)); } } } diff --git a/src/domain/Device/MagService.php b/src/domain/Device/MagService.php index bbbacc8b..22305ced 100644 --- a/src/domain/Device/MagService.php +++ b/src/domain/Device/MagService.php @@ -318,6 +318,7 @@ class MagService { $rInsertID = $db->last_insert_id(); $rArray['user_id'] = $rInsertID; LineService::updateLineSignal($rArray['user_id']); + unset($rArray['user'], $rArray['paired']); if (!isset($rData['edit'])) { $rArray['ver'] = ''; $rArray['device_id2'] = $rArray['ver']; diff --git a/src/domain/Server/SettingsService.php b/src/domain/Server/SettingsService.php index 6932b06d..bfc091c1 100644 --- a/src/domain/Server/SettingsService.php +++ b/src/domain/Server/SettingsService.php @@ -44,16 +44,6 @@ class SettingsService { $rArray['allow_countries'] = array('ALL'); } - if ($rArray['mag_legacy_redirect']) { - if (!file_exists(MAIN_HOME . 'www/c/')) { - $db->query('INSERT INTO `signals`(`server_id`, `time`, `custom_data`) VALUES(?, ?, ?);', SERVER_ID, time(), json_encode(array('action' => 'enable_ministra'))); - } - } else { - if (file_exists(MAIN_HOME . 'www/c/')) { - $db->query('INSERT INTO `signals`(`server_id`, `time`, `custom_data`) VALUES(?, ?, ?);', SERVER_ID, time(), json_encode(array('action' => 'disable_ministra'))); - } - } - if (100 < $rArray['search_items']) { $rArray['search_items'] = 100; } diff --git a/src/ministra/portal.php b/src/ministra/portal.php index 254f69e2..3e06aa4d 100644 --- a/src/ministra/portal.php +++ b/src/ministra/portal.php @@ -13,7 +13,16 @@ require __DIR__ . '/../modules/ministra/PortalHandler.php'; PortalHandler::handlePreInit($rReqType, $rReqAction); register_shutdown_function('shutdown'); -require '/home/xc_vm/www/stream/init.php'; +require_once dirname(__DIR__) . '/autoload.php'; +StreamingRequestBootstrap::init('portal'); + +$rRequestPath = parse_url(($_SERVER['REQUEST_URI'] ?? ''), PHP_URL_PATH); +$rLegacyPortalRequest = in_array($rRequestPath, array('/c/portal.php', '/portal.php')); + +if ($rLegacyPortalRequest && empty($rSettings['mag_legacy_redirect'])) { + http_response_code(404); + exit(); +} if (!$rSettings['disable_ministra']) { if (!in_array($rReqAction, array('get_categories', 'get_genres', 'get_ordered_list', 'get_all_channels', 'get_all_fav_channels', 'get_all_fav_radio'))) { @@ -21,9 +30,10 @@ if (!$rSettings['disable_ministra']) { $rCategories = CacheReader::get('categories'); } - $rIP = $_SERVER['REMOTE_ADDR']; - $rCountryCode = GeoIPService::getIPInfo($rIP)['country']['iso_code']; - $rMAC = (!empty($rRequest['mac']) ? $rRequest['mac'] : $_COOKIE['mac']); + $rIP = ($_SERVER['REMOTE_ADDR'] ?? ''); + $rGeoIPInfo = GeoIPService::getIPInfo($rIP); + $rCountryCode = (is_array($rGeoIPInfo) && !empty($rGeoIPInfo['country']['iso_code']) ? $rGeoIPInfo['country']['iso_code'] : null); + $rMAC = (!empty($rRequest['mac']) ? $rRequest['mac'] : (!empty($_COOKIE['mac']) ? $_COOKIE['mac'] : null)); $rUserAgent = (!empty($_SERVER['HTTP_X_USER_AGENT']) ? $_SERVER['HTTP_X_USER_AGENT'] : null); $rGMode = (!empty($rRequest['gmode']) ? intval($rRequest['gmode']) : null); $rDebug = $rSettings['enable_debug_stalker']; @@ -42,23 +52,44 @@ if (!$rSettings['disable_ministra']) { } $rAuthToken = null; - $rAuthHeader = (!empty($rHeaders['Authorization']) ? $rHeaders['Authorization'] : null); + $rAuthHeader = null; - if (!($rAuthHeader && preg_match('/Bearer\\s+(.*)$/i', $rAuthHeader, $rMatches))) { - } else { + if (is_array($rHeaders) && !empty($rHeaders['Authorization'])) { + $rAuthHeader = $rHeaders['Authorization']; + } else if (is_array($rHeaders) && !empty($rHeaders['authorization'])) { + $rAuthHeader = $rHeaders['authorization']; + } + + if (empty($rAuthHeader) && !empty($_SERVER['HTTP_AUTHORIZATION'])) { + $rAuthHeader = $_SERVER['HTTP_AUTHORIZATION']; + } else if (empty($rAuthHeader) && !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { + $rAuthHeader = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; + } + + if ($rAuthHeader && preg_match('/Bearer\\s+(.*)$/i', $rAuthHeader, $rMatches)) { $rAuthToken = trim($rMatches[1]); + } else if (!empty($rRequest['token'])) { + $rAuthToken = trim($rRequest['token']); } if (!$rAuthToken) { } else { $rVerify = igbinary_unserialize(Encryption::decrypt($rAuthToken, $rSettings['live_streaming_pass'], OPENSSL_EXTRA)); - $rDevice = (isset($rVerify['id']) ? getdevice($rVerify['id']) : array()); - if ($rDevice['token'] != $rVerify['token']) { - $rDevice = array(); + if (is_array($rVerify) && isset($rVerify['id']) && isset($rVerify['token'])) { + $rDevice = getdevice($rVerify['id']); + if (!is_array($rDevice)) { + $rDevice = array(); + } + + if (!isset($rDevice['token']) || $rDevice['token'] != $rVerify['token']) { + $rDevice = array(); + } else { + $rDevice['authenticated'] = true; + updatecache(); + } } else { - $rDevice['authenticated'] = true; - updatecache(); + $rDevice = array(); } } @@ -145,12 +176,15 @@ if (!$rSettings['disable_ministra']) { $db->query('UPDATE `mag_devices` SET `ip` = ?, `stb_type` = ?, `sn` = ?, `ver` = ?, `image_version` = ?, `device_id` = ?, `device_id2` = ?, `hw_version` = ? WHERE `mag_id` = ?;', $rIP, $rSTBType, $rSerialNumber, $rVersion, $rImageVersion, $rDeviceID, $rDeviceID2, $rHWVersion, $rDevice['mag_id']); updatecache(); } else { - unlink(MINISTRA_TMP_PATH . 'ministra_' . $rDevice['id']); + if (!empty($rDevice['id']) && file_exists(MINISTRA_TMP_PATH . 'ministra_' . $rDevice['id'])) { + unlink(MINISTRA_TMP_PATH . 'ministra_' . $rDevice['id']); + } $rDevice = array(); } } - $rAuthenticated = ($rDevice['authenticated'] ?: false); + $rAuthenticated = !empty($rDevice['authenticated']); + $rMagID = (!empty($rDevice['mag_id']) ? intval($rDevice['mag_id']) : 0); if (empty($rDevice['locale']) && !empty($_COOKIE['locale'])) { $rDevice['locale'] = $_COOKIE['locale']; @@ -159,7 +193,7 @@ if (!$rSettings['disable_ministra']) { } $rMagData = array(); - $rProfile = array('id' => $rDevice['mag_id'], 'name' => $rDevice['mag_id'], 'sname' => '', 'pass' => '', 'use_embedded_settings' => '', 'parent_password' => '0000', 'bright' => '200', 'contrast' => '127', 'saturation' => '127', 'video_out' => '', 'volume' => '70', 'playback_buffer_bytes' => '0', 'playback_buffer_size' => '0', 'audio_out' => '1', 'mac' => $rMAC, 'ip' => '127.0.0.1', 'ls' => '', 'version' => '', 'lang' => '', 'locale' => $rDevice['locale'], 'city_id' => '0', 'hd' => '1', 'main_notify' => '1', 'fav_itv_on' => '0', 'now_playing_start' => '2018-02-18 17:33:43', 'now_playing_type' => '1', 'now_playing_content' => 'Test channel', 'additional_services_on' => '1', 'time_last_play_tv' => '0000-00-00 00:00:00', 'time_last_play_video' => '0000-00-00 00:00:00', 'operator_id' => '0', 'storage_name' => '', 'hd_content' => '0', 'image_version' => 'undefined', 'last_change_status' => '0000-00-00 00:00:00', 'last_start' => '2018-02-18 17:33:38', 'last_active' => '2018-02-18 17:33:43', 'keep_alive' => '2018-02-18 17:33:43', 'screensaver_delay' => '10', 'phone' => '', 'fname' => '', 'login' => '', 'password' => '', 'stb_type' => '', 'num_banks' => '0', 'tariff_plan_id' => '0', 'comment' => null, 'now_playing_link_id' => '0', 'now_playing_streamer_id' => '0', 'just_started' => '1', 'last_watchdog' => '2018-02-18 17:33:39', 'created' => '2018-02-18 14:40:12', 'plasma_saving' => '0', 'ts_enabled' => '0', 'ts_enable_icon' => '1', 'ts_path' => '', 'ts_max_length' => '3600', 'ts_buffer_use' => 'cyclic', 'ts_action_on_exit' => 'no_save', 'ts_delay' => 'on_pause', 'video_clock' => 'Off', 'verified' => '0', 'hdmi_event_reaction' => 1, 'pri_audio_lang' => '', 'sec_audio_lang' => '', 'pri_subtitle_lang' => '', 'sec_subtitle_lang' => '', 'subtitle_color' => '16777215', 'subtitle_size' => '20', 'show_after_loading' => '', 'play_in_preview_by_ok' => null, 'hw_version' => 'undefined', 'openweathermap_city_id' => '0', 'theme' => '', 'settings_password' => '0000', 'expire_billing_date' => '0000-00-00 00:00:00', 'reseller_id' => null, 'account_balance' => '', 'client_type' => 'STB', 'hw_version_2' => '62', 'blocked' => '0', 'units' => 'metric', 'tariff_expired_date' => null, 'tariff_id_instead_expired' => null, 'activation_code_auto_issue' => '1', 'last_itv_id' => 0, 'updated' => array('id' => '1', 'uid' => '1', 'anec' => '0', 'vclub' => '0'), 'rtsp_type' => '4', 'rtsp_flags' => '0', 'stb_lang' => 'en', 'display_menu_after_loading' => '', 'record_max_length' => 180, 'web_proxy_host' => '', 'web_proxy_port' => '', 'web_proxy_user' => '', 'web_proxy_pass' => '', 'web_proxy_exclude_list' => '', 'demo_video_url' => '', 'tv_quality' => 'high', 'tv_quality_filter' => '', 'is_moderator' => false, 'timeslot_ratio' => 0.33333333333333, 'timeslot' => 40, 'kinopoisk_rating' => '1', 'enable_tariff_plans' => '', 'strict_stb_type_check' => '', 'cas_type' => 0, 'cas_params' => null, 'cas_web_params' => null, 'cas_additional_params' => array(), 'cas_hw_descrambling' => 0, 'cas_ini_file' => '', 'logarithm_volume_control' => '', 'allow_subscription_from_stb' => '1', 'deny_720p_gmode_on_mag200' => '1', 'enable_arrow_keys_setpos' => '1', 'show_purchased_filter' => '', 'timezone_diff' => 0, 'enable_connection_problem_indication' => '1', 'invert_channel_switch_direction' => '', 'play_in_preview_only_by_ok' => false, 'enable_stream_error_logging' => '', 'always_enabled_subtitles' => ($rSettings['always_enabled_subtitles'] == 1 ? '1' : ''), 'enable_service_button' => '', 'enable_setting_access_by_pass' => '', 'tv_archive_continued' => '', 'plasma_saving_timeout' => '600', 'show_tv_only_hd_filter_option' => '', 'tv_playback_retry_limit' => '0', 'fading_tv_retry_timeout' => '1', 'epg_update_time_range' => 0.6, 'store_auth_data_on_stb' => false, 'account_page_by_password' => '', 'tester' => false, 'enable_stream_losses_logging' => '', 'external_payment_page_url' => '', 'max_local_recordings' => '10', 'tv_channel_default_aspect' => 'fit', 'default_led_level' => '10', 'standby_led_level' => '90', 'show_version_in_main_menu' => '1', 'disable_youtube_for_mag200' => '1', 'auth_access' => false, 'epg_data_block_period_for_stb' => '5', 'standby_on_hdmi_off' => '1', 'force_ch_link_check' => '', 'stb_ntp_server' => 'pool.ntp.org', 'overwrite_stb_ntp_server' => '', 'hide_tv_genres_in_fullscreen' => null, 'advert' => null); + $rProfile = array('id' => $rMagID, 'name' => $rMagID, 'sname' => '', 'pass' => '', 'use_embedded_settings' => '', 'parent_password' => '0000', 'bright' => '200', 'contrast' => '127', 'saturation' => '127', 'video_out' => '', 'volume' => '70', 'playback_buffer_bytes' => '0', 'playback_buffer_size' => '0', 'audio_out' => '1', 'mac' => $rMAC, 'ip' => '127.0.0.1', 'ls' => '', 'version' => '', 'lang' => '', 'locale' => $rDevice['locale'], 'city_id' => '0', 'hd' => '1', 'main_notify' => '1', 'fav_itv_on' => '0', 'now_playing_start' => '2018-02-18 17:33:43', 'now_playing_type' => '1', 'now_playing_content' => 'Test channel', 'additional_services_on' => '1', 'time_last_play_tv' => '0000-00-00 00:00:00', 'time_last_play_video' => '0000-00-00 00:00:00', 'operator_id' => '0', 'storage_name' => '', 'hd_content' => '0', 'image_version' => 'undefined', 'last_change_status' => '0000-00-00 00:00:00', 'last_start' => '2018-02-18 17:33:38', 'last_active' => '2018-02-18 17:33:43', 'keep_alive' => '2018-02-18 17:33:43', 'screensaver_delay' => '10', 'phone' => '', 'fname' => '', 'login' => '', 'password' => '', 'stb_type' => '', 'num_banks' => '0', 'tariff_plan_id' => '0', 'comment' => null, 'now_playing_link_id' => '0', 'now_playing_streamer_id' => '0', 'just_started' => '1', 'last_watchdog' => '2018-02-18 17:33:39', 'created' => '2018-02-18 14:40:12', 'plasma_saving' => '0', 'ts_enabled' => '0', 'ts_enable_icon' => '1', 'ts_path' => '', 'ts_max_length' => '3600', 'ts_buffer_use' => 'cyclic', 'ts_action_on_exit' => 'no_save', 'ts_delay' => 'on_pause', 'video_clock' => 'Off', 'verified' => '0', 'hdmi_event_reaction' => 1, 'pri_audio_lang' => '', 'sec_audio_lang' => '', 'pri_subtitle_lang' => '', 'sec_subtitle_lang' => '', 'subtitle_color' => '16777215', 'subtitle_size' => '20', 'show_after_loading' => '', 'play_in_preview_by_ok' => null, 'hw_version' => 'undefined', 'openweathermap_city_id' => '0', 'theme' => '', 'settings_password' => '0000', 'expire_billing_date' => '0000-00-00 00:00:00', 'reseller_id' => null, 'account_balance' => '', 'client_type' => 'STB', 'hw_version_2' => '62', 'blocked' => '0', 'units' => 'metric', 'tariff_expired_date' => null, 'tariff_id_instead_expired' => null, 'activation_code_auto_issue' => '1', 'last_itv_id' => 0, 'updated' => array('id' => '1', 'uid' => '1', 'anec' => '0', 'vclub' => '0'), 'rtsp_type' => '4', 'rtsp_flags' => '0', 'stb_lang' => 'en', 'display_menu_after_loading' => '', 'record_max_length' => 180, 'web_proxy_host' => '', 'web_proxy_port' => '', 'web_proxy_user' => '', 'web_proxy_pass' => '', 'web_proxy_exclude_list' => '', 'demo_video_url' => '', 'tv_quality' => 'high', 'tv_quality_filter' => '', 'is_moderator' => false, 'timeslot_ratio' => 0.33333333333333, 'timeslot' => 40, 'kinopoisk_rating' => '1', 'enable_tariff_plans' => '', 'strict_stb_type_check' => '', 'cas_type' => 0, 'cas_params' => null, 'cas_web_params' => null, 'cas_additional_params' => array(), 'cas_hw_descrambling' => 0, 'cas_ini_file' => '', 'logarithm_volume_control' => '', 'allow_subscription_from_stb' => '1', 'deny_720p_gmode_on_mag200' => '1', 'enable_arrow_keys_setpos' => '1', 'show_purchased_filter' => '', 'timezone_diff' => 0, 'enable_connection_problem_indication' => '1', 'invert_channel_switch_direction' => '', 'play_in_preview_only_by_ok' => false, 'enable_stream_error_logging' => '', 'always_enabled_subtitles' => ($rSettings['always_enabled_subtitles'] == 1 ? '1' : ''), 'enable_service_button' => '', 'enable_setting_access_by_pass' => '', 'tv_archive_continued' => '', 'plasma_saving_timeout' => '600', 'show_tv_only_hd_filter_option' => '', 'tv_playback_retry_limit' => '0', 'fading_tv_retry_timeout' => '1', 'epg_update_time_range' => 0.6, 'store_auth_data_on_stb' => false, 'account_page_by_password' => '', 'tester' => false, 'enable_stream_losses_logging' => '', 'external_payment_page_url' => '', 'max_local_recordings' => '10', 'tv_channel_default_aspect' => 'fit', 'default_led_level' => '10', 'standby_led_level' => '90', 'show_version_in_main_menu' => '1', 'disable_youtube_for_mag200' => '1', 'auth_access' => false, 'epg_data_block_period_for_stb' => '5', 'standby_on_hdmi_off' => '1', 'force_ch_link_check' => '', 'stb_ntp_server' => 'pool.ntp.org', 'overwrite_stb_ntp_server' => '', 'hide_tv_genres_in_fullscreen' => null, 'advert' => null); $rLocales['get_locales']['English'] = 'en_GB.utf8'; $rLocales['get_locales']['Ελληνικά'] = 'el_GR.utf8'; $rMagData['get_years'] = array('js' => array(array('id' => '*', 'title' => '*'))); @@ -496,11 +530,16 @@ function getItems($rTypes = array(), $rCategoryID = null, $rFav = null, $rOrderB foreach ($rRows as $rStream) { $rStream["snumber"] = $rKey; $rStream["number"] = $rStream["snumber"]; + $rStreamCategories = json_decode($rStream["category_id"], true); - if (in_array($rCategoryID, json_decode($rStream["category_id"], true))) { + if (!is_array($rStreamCategories)) { + $rStreamCategories = array(); + } + + if (in_array($rCategoryID, $rStreamCategories)) { $rStream["category_id"] = $rCategoryID; } else { - list($rStream["category_id"]) = json_decode($rStream["category_id"], true); + $rStream["category_id"] = (isset($rStreamCategories[0]) ? $rStreamCategories[0] : 0); } if (in_array($rStream["category_id"], $rAdultCategories)) { @@ -509,7 +548,8 @@ function getItems($rTypes = array(), $rCategoryID = null, $rFav = null, $rOrderB $rStream["is_adult"] = 0; } - $rStream["now_playing"] = getEPG($rStream["id"], time(), time() + 86400)[0] ?: NULL; + $rEPGNow = getEPG($rStream["id"], time(), time() + 86400); + $rStream["now_playing"] = (isset($rEPGNow[0]) ? $rEPGNow[0] : NULL); $rStream["stream_info"] = json_decode($rStream["stream_info"], true); $rStreams["streams"][$rStream["id"]] = $rStream; $rKey++; @@ -518,8 +558,7 @@ function getItems($rTypes = array(), $rCategoryID = null, $rFav = null, $rOrderB } function sortArrayStreamRating($a, $b) { - if (isset($a['rating'])) { - } else { + if (!isset($a['rating'])) { if (isset($a['movie_properties']) && isset($b['movie_properties'])) { if (!is_array($a['movie_properties'])) { $a = json_decode($a['movie_properties'], true); @@ -699,7 +738,12 @@ function getProgramme($rStreamID, $rProgrammeID) { function updateCache() { global $rDevice; - file_put_contents(MINISTRA_TMP_PATH . 'ministra_' . $rDevice['mag_id'], igbinary_serialize($rDevice)); + + if (!is_array($rDevice) || empty($rDevice['mag_id'])) { + return; + } + + file_put_contents(MINISTRA_TMP_PATH . 'ministra_' . intval($rDevice['mag_id']), igbinary_serialize($rDevice)); } function getMovies($rCategoryID = null, $rFav = null, $rOrderBy = null, $rSearchBy = null, $rPicking = array()) { @@ -965,13 +1009,13 @@ function getStreams($rCategoryID = null, $rAll = false, $rFav = null, $rOrderBy global $rForceProtocol; global $rServers; $rDefaultPage = false; - $rPage = (isset($rRequest['p']) ? intval($rRequest['p']) : 0); + $rPage = (!empty($rRequest['p']) ? intval($rRequest['p']) : 0); + $rPosition = 0; - if (!($rPage == 0 && $rCategoryID != -1)) { - } else { + if ($rPage == 0 && $rCategoryID != -1) { $rDefaultPage = true; - if ($rRequest['p'] != 0 || empty($rDevice['last_itv_id'])) { + if ($rPage != 0 || empty($rDevice['last_itv_id'])) { } else { $rPosition = getitems(array('live', 'created_live'), $rCategoryID, $rFav, $rOrderBy, $rSearchBy, null, 0, 0, $rDevice['last_itv_id']); diff --git a/src/ministra/xpcom.common.js b/src/ministra/xpcom.common.js index e092b89a..b5f26de4 100644 --- a/src/ministra/xpcom.common.js +++ b/src/ministra/xpcom.common.js @@ -327,6 +327,8 @@ function common_xpcom() { var login = self.auth_dialog.getItemByName("login").getValue(); var password = self.auth_dialog.getItemByName("password").getValue(); + var device_id = self.get_device_id(); + var device_id2 = self.get_device_id2(); _debug("login", login); _debug("password", password); @@ -337,8 +339,8 @@ function common_xpcom() { "action": "do_auth", "login": login, "password": password, - 'device_id': stb.GetUID ? stb.GetUID() : '', - 'device_id2': stb.GetUID ? (stb.GetUID(self.access_token) == stb.GetUID(self.access_token, self.access_token) ? '' : stb.GetUID('device_id', self.access_token)) : '' + 'device_id': device_id, + 'device_id2': device_id2 }, function (result) { _debug('auth result', result); @@ -619,15 +621,49 @@ function common_xpcom() { if (debug) { - if (_GET['mac']) { - this.mac = _GET['mac']; + var debugMac = this.get_debug_param('mac'); + + if (debugMac) { + this.mac = debugMac; this.set_cookie('mac_emu', 1); } + var debugSerialNumber = this.get_debug_param('sn'); + + if (debugSerialNumber) { + this.serial_number = debugSerialNumber; + } + + var debugStbType = this.get_debug_param('stb_type'); + + if (debugStbType) { + this.type = debugStbType; + } + + var debugHwVersion = this.get_debug_param('hw_version'); + + if (debugHwVersion) { + this.hw_version = debugHwVersion; + } + + var debugVersion = this.get_debug_param('ver'); + + if (debugVersion) { + this.version = debugVersion; + } + + var debugImageVersion = this.get_debug_param('image_version'); + + if (debugImageVersion) { + this.image_version = debugImageVersion; + } + this.set_cookie('debug', 1); - if (_GET['debug_key']) { - this.set_cookie('debug_key', _GET['debug_key']); + var debugKey = this.get_debug_param('debug_key'); + + if (debugKey) { + this.set_cookie('debug_key', debugKey); } } @@ -653,6 +689,38 @@ function common_xpcom() { document.cookie = name + '=' + encodeURIComponent(val) + '; path=/;'; }; + this.get_debug_param = function (name) { + if (!_GET || !_GET.hasOwnProperty(name) || typeof _GET[name] == 'undefined' || _GET[name] === '') { + return ''; + } + + try { + return decodeURIComponent(_GET[name]); + } catch (e) { + return _GET[name]; + } + }; + + this.get_device_id = function () { + var debugDeviceId = this.get_debug_param('device_id'); + + if (debugDeviceId) { + return debugDeviceId; + } + + return stb.GetUID ? stb.GetUID() : ''; + }; + + this.get_device_id2 = function () { + var debugDeviceId2 = this.get_debug_param('device_id2'); + + if (debugDeviceId2) { + return debugDeviceId2; + } + + return stb.GetUID ? (stb.GetUID(this.access_token) == stb.GetUID(this.access_token, this.access_token) ? '' : stb.GetUID('device_id', this.access_token)) : ''; + }; + this.delete_cookie = function (name) { document.cookie = name + '=; path=/; expires=Thu, 01-Jan-1970 00:00:01 GMT;'; }; @@ -688,6 +756,10 @@ function common_xpcom() { _debug('stb.load()'); _debug('params:', params); + if (params && this.access_token && params.action != 'handshake' && this.get_debug_param('auth_via_query') == '1' && !params.hasOwnProperty('token')) { + params.token = this.access_token; + } + var callback = arguments[1]; var context = window; @@ -912,11 +984,13 @@ function common_xpcom() { _debug('stb.handshake'); var prehash = stb.GetHashVersion1 ? stb.GetHashVersion1(this.type, this.version.substr(0, 56)) : 0; + var currentMac = this.mac || this.get_debug_param('mac') || ''; this.load( { "type": "stb", "action": "handshake", + "mac": currentMac, "token": this.get_saved_access_token() || '', "prehash": prehash }, @@ -946,12 +1020,20 @@ function common_xpcom() { this.get_user_profile = function (auth_second_step, prehash) { _debug('this.get_user_profile', auth_second_step, prehash); - var device_id2 = stb.GetUID ? (stb.GetUID(this.access_token) == stb.GetUID(this.access_token, this.access_token) ? '' : stb.GetUID('device_id', this.access_token)) : ''; + var currentMac = this.mac || this.get_debug_param('mac') || ''; + var serial_number = this.serial_number || this.get_debug_param('sn') || ''; + var stb_type = this.type || this.get_debug_param('stb_type') || ''; + var version = (typeof this.version == 'undefined' || this.version === null ? '' : this.version); + var num_banks = (typeof this.num_banks == 'undefined' || this.num_banks === null ? 0 : this.num_banks); + var image_version = this.image_version || this.get_debug_param('image_version') || ''; + var hw_version = this.hw_version || this.get_debug_param('hw_version') || ''; + var device_id = this.get_device_id(); + var device_id2 = this.get_device_id2(); var metrics = { - mac: this.mac, - sn: this.serial_number, - model: this.type, + mac: currentMac, + sn: serial_number, + model: stb_type, type: "STB", uid: device_id2, random: this.random @@ -963,19 +1045,20 @@ function common_xpcom() { { 'type': 'stb', 'action': 'get_profile', + 'mac': currentMac, 'hd': this.hd, - 'ver': this.version, - 'num_banks': this.num_banks, - 'sn': this.serial_number, - 'stb_type': this.type, + 'ver': version, + 'num_banks': num_banks, + 'sn': serial_number, + 'stb_type': stb_type, 'client_type': 'STB', - 'image_version': this.image_version, + 'image_version': image_version, 'video_out': (stb.GetHDMIConnectionState ? (stb.GetHDMIConnectionState() == 0 && window.innerHeight <= 576 ? "rca" : "hdmi") : ""), - 'device_id': stb.GetUID ? stb.GetUID() : '', + 'device_id': device_id, 'device_id2': device_id2, 'signature': stb.GetUID ? stb.GetUID(this.random) : '', 'auth_second_step': auth_second_step ? 1 : 0, - 'hw_version': this.hw_version, + 'hw_version': hw_version, 'not_valid_token': this.not_valid_token ? 1 : 0, 'metrics': encodeURIComponent(JSON.stringify(metrics)), 'hw_version_2': stb.GetHashVersion1 ? stb.GetHashVersion1(JSON.stringify(metrics), this.random) : '', diff --git a/src/modules/ministra/PortalHandler.php b/src/modules/ministra/PortalHandler.php index 4040adcb..032f8a19 100644 --- a/src/modules/ministra/PortalHandler.php +++ b/src/modules/ministra/PortalHandler.php @@ -1326,7 +1326,7 @@ class PortalHandler { * @param string $rMAC */ public static function handleHandshake($rMAC) { - global $db, $rSettings; + global $db, $rSettings, $rDevice; $rDevice = getdevice(null, $rMAC); $rVerifyToken = null; diff --git a/src/public/index.php b/src/public/index.php index be00404e..d2640fbb 100644 --- a/src/public/index.php +++ b/src/public/index.php @@ -35,8 +35,8 @@ $pageName = ''; $accessCode = null; $rawScope = null; -// Режим A: access code (nginx XC_SCOPE/XC_CODE) if (!empty($_SERVER['XC_SCOPE'])) { + // Режим A: access code (nginx XC_SCOPE/XC_CODE) $rawScope = $_SERVER['XC_SCOPE']; $accessCode = $_SERVER['XC_CODE'] ?? null; @@ -59,14 +59,12 @@ if (!empty($_SERVER['XC_SCOPE'])) { $parts = explode('/', $pageName, 2); $pageName = $parts[1] ?? ''; } -} -// Режим B: прямой URL /admin/... или /reseller/... -elseif (preg_match('#^/(admin|reseller)(?:/(.*))?$#', $urlPath, $m)) { +} elseif (preg_match('#^/(admin|reseller)(?:/(.*))?$#', $urlPath, $m)) { + // Режим B: прямой URL /admin/... или /reseller/... $scope = $m[1]; $pageName = isset($m[2]) ? trim($m[2], '/') : ''; -} -// Режим C: access code без XC_SCOPE (fallback admin) -else { +} else { + // Режим C: access code без XC_SCOPE (fallback admin) $selfDir = basename(dirname($_SERVER['PHP_SELF'] ?? '')); if (!in_array($selfDir, ['admin', 'reseller'], true)) { @@ -88,20 +86,22 @@ if ($pageName === '') { // 3. REST API (access code type 3/4) — dispatch до редиректа и роутера if (isset($rawScope) && in_array($rawScope, ['includes/api/admin', 'includes/api/reseller'], true)) { - require_once MAIN_HOME . 'bootstrap.php'; - XC_Bootstrap::boot(XC_Bootstrap::CONTEXT_ADMIN); - if ($rawScope === 'includes/api/admin') { - $controller = new AdminApiController(); - } else { - $controller = new ResellerRestApiController(); - } - $controller->index(); - exit; + require_once MAIN_HOME . 'bootstrap.php'; + XC_Bootstrap::boot(XC_Bootstrap::CONTEXT_ADMIN); + if ($rawScope === 'includes/api/admin') { + $controller = new AdminApiController(); + } else { + $controller = new ResellerRestApiController(); + } + $controller->index(); + exit; } // 4. Redirect /CODE/ → /CODE/login (иначе relative assets ломаются) -if ($pageName === 'index' && $accessCode && in_array($scope, ['admin', 'reseller'], true) - && ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'GET') { +if ( + $pageName === 'index' && $accessCode && in_array($scope, ['admin', 'reseller'], true) + && ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'GET' +) { header('Location: /' . $accessCode . '/login'); exit; } @@ -119,34 +119,34 @@ if (in_array($ext, ['css', 'js', 'png', 'jpg', 'jpeg', 'gif', 'svg', 'ico', 'wof // 6. Streaming API (XC_SCOPE=api, XC_API={endpoint}) if (isset($rawScope) && $rawScope === 'api' && !empty($_SERVER['XC_API'])) { - $rApiName = $_SERVER['XC_API']; - $rApiControllerMap = [ - 'player_api' => 'PlayerApiController', - 'enigma2' => 'Enigma2ApiController', - 'xplugin' => 'XPluginApiController', - 'epg' => 'EpgApiController', - 'playlist' => 'PlaylistApiController', - 'internal' => 'InternalApiController', - ]; + $rApiName = $_SERVER['XC_API']; + $rApiControllerMap = [ + 'player_api' => 'PlayerApiController', + 'enigma2' => 'Enigma2ApiController', + 'xplugin' => 'XPluginApiController', + 'epg' => 'EpgApiController', + 'playlist' => 'PlaylistApiController', + 'internal' => 'InternalApiController', + ]; - if (!isset($rApiControllerMap[$rApiName])) { - http_response_code(404); - exit; - } + if (!isset($rApiControllerMap[$rApiName])) { + http_response_code(404); + exit; + } - $rFilename = ($rApiName === 'internal') ? 'api' : $rApiName; + $rFilename = ($rApiName === 'internal') ? 'api' : $rApiName; - if ($rApiName === 'player_api') { - StreamingRequestBootstrap::init($rFilename); - } else { - WebApiBootstrap::init($rFilename); - } + if ($rApiName === 'player_api') { + StreamingRequestBootstrap::init($rFilename); + } else { + WebApiBootstrap::init($rFilename); + } - $rControllerClass = $rApiControllerMap[$rApiName]; - $controller = new $rControllerClass(); - register_shutdown_function([$controller, 'shutdown']); - $controller->index(); - exit; + $rControllerClass = $rApiControllerMap[$rApiName]; + $controller = new $rControllerClass(); + register_shutdown_function([$controller, 'shutdown']); + $controller->index(); + exit; } // 4. Bootstrap diff --git a/src/resources/langs/en.ini b/src/resources/langs/en.ini index 1f402bf4..15729db8 100644 --- a/src/resources/langs/en.ini +++ b/src/resources/langs/en.ini @@ -1323,7 +1323,7 @@ preferred_method_of_channel_sorting_in_playlists_and_apps = "Preferred method of preferred_method_of_load_balancing_connections = "Preferred method of load balancing connections." reason_for_adjustment = "Reason for Adjustment..." redirect_api_stream_requests_using_tooltip = "Redirect API stream requests using AES encrypted tokens instead of defaulting the app to user / pass requests. This will be more widely used in the future and can remain disabled for now." -redirect_c_to_ministra_folder_tooltip = "Redirect /c to Ministra folder using symlinks. This will allow legacy devices to access the Ministra portal using the old address, however it isn 't recommended for security purposes. Root access is required so this will action within the next minute during the cron run." +redirect_c_to_ministra_folder_tooltip = "Enable or disable legacy Ministra URL /c/portal.php. When disabled, legacy URL returns 404. This switch is applied by runtime settings and does not create symlinks." redirect_clients_to_the_source_tooltip = "Redirect clients to the source directly. Do not use if you want to keep your source secure." removes_the_restart_count_next_to_stream_uptime = "Removes the restart count next to stream uptime." resize_command_for_gpu_acceleration_example_1920x1080 = "Resize command for GPU acceleration. Example: 1920x1080" diff --git a/src/resources/langs/ru.ini b/src/resources/langs/ru.ini index f1c9ebd0..986cd60d 100644 --- a/src/resources/langs/ru.ini +++ b/src/resources/langs/ru.ini @@ -1261,7 +1261,7 @@ recording = "RECORDING" records = "Records" recreate_channels = "Recreate Channels" redirect_api_stream_requests_using_tooltip = "Redirect API stream requests using AES encrypted tokens instead of defaulting the app to user / pass requests. This will be more widely used in the future and can remain disabled for now." -redirect_c_to_ministra_folder_tooltip = "Redirect /c to Ministra folder using symlinks. This will allow legacy devices to access the Ministra portal using the old address, however it isn 't recommended for security purposes. Root access is required so this will action within the next minute during the cron run." +redirect_c_to_ministra_folder_tooltip = "Enable or disable legacy Ministra URL /c/portal.php. When disabled, legacy URL returns 404. This switch is applied by runtime settings and does not create symlinks." redirect_clients_to_the_source_tooltip = "Redirect clients to the source directly. Do not use if you want to keep your source secure." redis_connection_handler = "Redis Connection Handler" regenerate_cache = "Regenerate Cache" diff --git a/src/www/admin/proxy_api.php b/src/www/admin/proxy_api.php index 741da03a..545dc1b5 100644 --- a/src/www/admin/proxy_api.php +++ b/src/www/admin/proxy_api.php @@ -18,9 +18,9 @@ if (BlocklistService::isProxy($_SERVER['REMOTE_ADDR'])) { $db = new DatabaseHandler($_INFO['username'], $_INFO['password'], $_INFO['database'], $_INFO['hostname'], $_INFO['port']); DatabaseFactory::set($db); $rServers = ServerRepository::getAll(); - $rServerID = intval($_POST['server_id']); + $rServerIDRequest = intval($_POST['server_id']); $rStats = $_POST['stats']; - $db->query('SELECT `bytes_sent_total`, `bytes_received_total`, `time` FROM `servers_stats` WHERE `server_id` = ? ORDER BY `id` DESC LIMIT 1;', $rServerID); + $db->query('SELECT `bytes_sent_total`, `bytes_received_total`, `time` FROM `servers_stats` WHERE `server_id` = ? ORDER BY `id` DESC LIMIT 1;', $rServerIDRequest); if ($db->num_rows() != 1) { } else { @@ -32,7 +32,7 @@ if (BlocklistService::isProxy($_SERVER['REMOTE_ADDR'])) { $rAddresses = $_POST['addresses']; $rHardware = array('total_ram' => $rStats['total_mem'], 'total_used' => $rStats['total_mem_used'], 'cores' => $rStats['cpu_cores'], 'threads' => $rStats['cpu_cores'], 'kernel' => $rStats['kernel'], 'total_running_streams' => $rStats['total_running_streams'], 'cpu_name' => $rStats['cpu_name'], 'cpu_usage' => $rStats['cpu'], 'network_speed' => $rStats['network_speed'], 'bytes_sent' => $rStats['bytes_sent'], 'bytes_received' => $rStats['bytes_received']); - $rPing = (pingserver($rServers[$rServerID]['server_ip'], $rServers[$rServerID]['http_broadcast_port']) ?: 0); + $rPing = (pingserver($rServers[$rServerIDRequest]['server_ip'], $rServers[$rServerIDRequest]['http_broadcast_port']) ?: 0); if ($rPing >= 0) { } else { @@ -40,29 +40,29 @@ if (BlocklistService::isProxy($_SERVER['REMOTE_ADDR'])) { } if (SettingsManager::getAll()['redis_handler']) { - $rConnections = $rServers[$rServerID]['connections']; - $rUsers = $rServers[$rServerID]['users']; + $rConnections = $rServers[$rServerIDRequest]['connections']; + $rUsers = $rServers[$rServerIDRequest]['users']; $rAllUsers = 0; - foreach (array_keys($rServers) as $rServerID) { - if (!$rServers[$rServerID]['server_online']) { + foreach (array_keys($rServers) as $rServer) { + if (!$rServers[$rServer]['server_online']) { } else { - $rAllUsers += $rServers[$rServerID]['users']; + $rAllUsers += $rServers[$rServer]['users']; } } } else { - $db->query('SELECT COUNT(*) AS `count` FROM `lines_live` WHERE `proxy_id` = ? AND `hls_end` = 0;', $rServerID); + $db->query('SELECT COUNT(*) AS `count` FROM `lines_live` WHERE `proxy_id` = ? AND `hls_end` = 0;', $rServerIDRequest); $rConnections = intval($db->get_row()['count']); - $db->query('SELECT `activity_id` FROM `lines_live` WHERE `proxy_id` = ? AND `hls_end` = 0 GROUP BY `user_id`;', $rServerID); + $db->query('SELECT `activity_id` FROM `lines_live` WHERE `proxy_id` = ? AND `hls_end` = 0 GROUP BY `user_id`;', $rServerIDRequest); $rUsers = intval($db->num_rows()); $db->query('SELECT `activity_id` FROM `lines_live` WHERE `hls_end` = 0 GROUP BY `user_id`;'); $rAllUsers = intval($db->num_rows()); } - $db->query('INSERT INTO `servers_stats`(`server_id`, `cpu`, `cpu_cores`, `cpu_avg`, `total_mem`, `total_mem_free`, `total_mem_used`, `total_mem_used_percent`, `total_disk_space`, `uptime`, `total_running_streams`, `bytes_sent`, `bytes_received`, `bytes_sent_total`, `bytes_received_total`, `cpu_load_average`, `connections`, `total_users`, `users`, `time`) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);', $rServerID, $rStats['cpu'], $rStats['cpu_cores'], $rStats['cpu_avg'], $rStats['total_mem'], $rStats['total_mem_free'], $rStats['total_mem_used'], $rStats['total_mem_used_percent'], $rStats['total_disk_space'], $rStats['uptime'], $rStats['total_running_streams'], $rStats['bytes_sent'], $rStats['bytes_received'], $rStats['bytes_sent_total'], $rStats['bytes_received_total'], $rStats['cpu_load_average'], $rConnections, $rAllUsers, $rUsers, time()); - $db->query('UPDATE `servers` SET `connections` = ?, `users` = ?, `ping` = ?,`server_hardware` = ?,`whitelist_ips` = ?, `interfaces` = ?, `watchdog_data` = ?, `last_check_ago` = ? WHERE `id` = ?', $rConnections, $rUsers, $rPing, json_encode($rHardware), json_encode($rAddresses), json_encode($rStats['interfaces']), json_encode($rStats, JSON_PARTIAL_OUTPUT_ON_ERROR), time(), $rServerID); + $db->query('INSERT INTO `servers_stats`(`server_id`, `cpu`, `cpu_cores`, `cpu_avg`, `total_mem`, `total_mem_free`, `total_mem_used`, `total_mem_used_percent`, `total_disk_space`, `uptime`, `total_running_streams`, `bytes_sent`, `bytes_received`, `bytes_sent_total`, `bytes_received_total`, `cpu_load_average`, `connections`, `total_users`, `users`, `time`) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);', $rServerIDRequest, $rStats['cpu'], $rStats['cpu_cores'], $rStats['cpu_avg'], $rStats['total_mem'], $rStats['total_mem_free'], $rStats['total_mem_used'], $rStats['total_mem_used_percent'], $rStats['total_disk_space'], $rStats['uptime'], $rStats['total_running_streams'], $rStats['bytes_sent'], $rStats['bytes_received'], $rStats['bytes_sent_total'], $rStats['bytes_received_total'], $rStats['cpu_load_average'], $rConnections, $rAllUsers, $rUsers, time()); + $db->query('UPDATE `servers` SET `connections` = ?, `users` = ?, `ping` = ?,`server_hardware` = ?,`whitelist_ips` = ?, `interfaces` = ?, `watchdog_data` = ?, `last_check_ago` = ? WHERE `id` = ?', $rConnections, $rUsers, $rPing, json_encode($rHardware), json_encode($rAddresses), json_encode($rStats['interfaces']), json_encode($rStats, JSON_PARTIAL_OUTPUT_ON_ERROR), time(), $rServerIDRequest); - if ($db->query("SELECT `signal_id`, `custom_data` FROM `signals` WHERE `server_id` = ? AND `custom_data` <> '' ORDER BY signal_id ASC;", $rServerID)) { + if ($db->query("SELECT `signal_id`, `custom_data` FROM `signals` WHERE `server_id` = ? AND `custom_data` <> '' ORDER BY signal_id ASC;", $rServerIDRequest)) { if (0 >= $db->num_rows()) {