mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-05 04:02:31 +02:00
chore(psr4): phase 1 — rename 7 top-level dirs to PascalCase
Atomic case-rename of the seven class-holding source directories to match the PSR-4 namespace casing, plus every consequent path reference. No code logic changes — pure structural rename. (config/content/resources/signals/migrations/ ministra/storage/tmp/vendor/www/bin stay lowercase.) - git mv: core→Core, domain→Domain, infrastructure→Infrastructure, streaming→Streaming, modules→Modules, cli→Cli, public→Public (module subdirs like Modules/plex stay lowercase; loaded by ModuleLoader, not Composer). - PHP filesystem paths updated across src/ + tests/: require/include, glob/scandir bases, view includes, asset/nginx-alias paths, autoload.php registerDirectories(), ModuleLoader/ModuleManager module roots, console.php discovery dirs. - src/composer.json PSR-4 vendored-lib paths → Core/Parsing/...; vendor/ regenerated. - nginx.conf: docroot + SCRIPT_FILENAME → Public/. SCRIPT_NAME and the public-facing /streaming/*.php compat routes are URLs, left unchanged. - Build/CI: Makefile LB_DIRS / LB_DIRS_TO_REMOVE / LB_FILES_TO_REMOVE PascalCased (closes the LB-archive privileged-leak blocker); phpstan.dist.neon paths/ scanDirectories/excludePaths; phpunit.xml.dist coverage; phpstan-baseline.neon regenerated (294→294 errors, no new resolution failures). - migrations/deleted_files.txt: old lowercase trees listed for client cleanup (assumes case-sensitive FS — the supported Linux target). Verified: grep-gate 0 live lowercase-dir require/include in src+tests; php -l clean; PHPUnit 292/292; PHPStan no errors; Composer first / XC_Autoloader last in SPL stack; global classes resolve from the renamed dirs.
This commit is contained in:
@@ -0,0 +1,642 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UserRepository — user repository
|
||||
*
|
||||
* @package XC_VM_Domain_User
|
||||
* @author Divarion_D <https://github.com/Divarion-D>
|
||||
* @copyright 2025-2026 Vateron Media
|
||||
* @link https://github.com/Vateron-Media/XC_VM
|
||||
* @license AGPL-3.0 https://www.gnu.org/licenses/agpl-3.0.html
|
||||
*/
|
||||
|
||||
class UserRepository {
|
||||
private static $db = null;
|
||||
|
||||
/**
|
||||
* Inject the database handler (dependency injection).
|
||||
*
|
||||
* @param \DatabaseHandler $db Database handler.
|
||||
* @return void
|
||||
*/
|
||||
public static function setDb($db): void {
|
||||
self::$db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the injected database handler.
|
||||
*
|
||||
* @return object Database handler.
|
||||
* @throws \RuntimeException If setDb() was not called first.
|
||||
*/
|
||||
private static function db(): object {
|
||||
if (self::$db === null) {
|
||||
throw new \RuntimeException(static::class . '::setDb() must be called before use.');
|
||||
}
|
||||
return self::$db;
|
||||
}
|
||||
/**
|
||||
* Fetch an admin/reseller user matching the given login credentials.
|
||||
*
|
||||
* @param string $rUsername Username.
|
||||
* @param string $rPassword Plain-text password.
|
||||
* @return array|null The user row, or null if credentials are invalid.
|
||||
*/
|
||||
public static function getAuthUserByCredentials($rUsername, $rPassword) {
|
||||
$db = self::db();
|
||||
$db->query('SELECT `id`, `username`, `password`, `member_group_id`, `status` FROM `users` WHERE `username` = ? LIMIT 1;', $rUsername);
|
||||
|
||||
if ($db->num_rows() == 1) {
|
||||
$rRow = $db->get_row();
|
||||
|
||||
if (Authenticator::checkPassword($rPassword, $rRow['password'])) {
|
||||
return $rRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List resellers under a given owner.
|
||||
*
|
||||
* @param int $rOwner Owner user id.
|
||||
* @param bool $rIncludeSelf Include the owner in the result.
|
||||
* @return array Reseller rows.
|
||||
*/
|
||||
public static function getResellers($rOwner, $rIncludeSelf = true) {
|
||||
$db = self::db();
|
||||
if ($rIncludeSelf) {
|
||||
$db->query('SELECT `id`, `username` FROM `users` WHERE `owner_id` = ? OR `id` = ? ORDER BY `username` ASC;', $rOwner, $rOwner);
|
||||
} else {
|
||||
$db->query('SELECT `id`, `username` FROM `users` WHERE `owner_id` = ? ORDER BY `username` ASC;', $rOwner);
|
||||
}
|
||||
|
||||
return $db->get_rows(true, 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the direct sub-users (reports) of the current user.
|
||||
*
|
||||
* @param array $rPermissions Effective permissions.
|
||||
* @param array $rUserInfo Current user row.
|
||||
* @param bool $rIncludeSelf Include the user themselves.
|
||||
* @return array Direct report rows.
|
||||
*/
|
||||
public static function getDirectReports($rPermissions, $rUserInfo, $rIncludeSelf = true) {
|
||||
$db = self::db();
|
||||
$rUserIDs = $rPermissions['direct_reports'];
|
||||
|
||||
if (!$rIncludeSelf) {
|
||||
} else {
|
||||
$rUserIDs[] = $rUserInfo['id'];
|
||||
}
|
||||
|
||||
$rReturn = array();
|
||||
|
||||
if (0 >= count($rUserIDs)) {
|
||||
} else {
|
||||
$db->query('SELECT * FROM `users` WHERE `owner_id` IN (' . implode(',', array_map('intval', $rUserIDs)) . ') ORDER BY `username` ASC;');
|
||||
|
||||
if (0 >= $db->num_rows()) {
|
||||
} else {
|
||||
foreach ($db->get_rows() as $rRow) {
|
||||
$rReturn[intval($rRow['id'])] = $rRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $rReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the parent of a user within the permission scope.
|
||||
*
|
||||
* @param array $rPermissions Effective permissions.
|
||||
* @param array $rUserInfo Current user row.
|
||||
* @param int $rID Target user id.
|
||||
* @return int Resolved parent user id.
|
||||
*/
|
||||
public static function getParent($rPermissions, $rUserInfo, $rID) {
|
||||
if (!isset($rPermissions['users'][$rID]['parent']) || $rPermissions['users'][$rID]['parent'] == 0 || $rPermissions['users'][$rID]['parent'] == $rUserInfo['id']) {
|
||||
return $rID;
|
||||
}
|
||||
|
||||
return self::getParent($rPermissions, $rUserInfo, $rPermissions['users'][$rID]['parent']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all descendant sub-users of a user (full report tree).
|
||||
*
|
||||
* @param int $rUser User id.
|
||||
* @return array Sub-user rows keyed by id.
|
||||
*/
|
||||
public static function getSubUsers($rUser) {
|
||||
$db = self::db();
|
||||
$rReturn = array();
|
||||
$db->query('SELECT `id`, `username` FROM `users` WHERE `owner_id` = ?;', $rUser);
|
||||
|
||||
foreach ($db->get_rows() as $rRow) {
|
||||
$rReturn[$rRow['id']] = array('username' => $rRow['username'], 'parent' => $rUser);
|
||||
|
||||
foreach (self::getSubUsers($rRow['id']) as $rUserID => $rUserData) {
|
||||
$rReturn[$rUserID] = $rUserData;
|
||||
}
|
||||
}
|
||||
|
||||
return $rReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a line by id.
|
||||
*
|
||||
* @param int $rID Line id.
|
||||
* @return array|null The line row, or null if not found.
|
||||
*/
|
||||
public static function getLineById($rID) {
|
||||
$db = self::db();
|
||||
$db->query('SELECT * FROM `lines` WHERE `id` = ?;', $rID);
|
||||
|
||||
if ($db->num_rows() != 1) {
|
||||
} else {
|
||||
return $db->get_row();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a registered (panel) user by id.
|
||||
*
|
||||
* @param int $rID User id.
|
||||
* @return array|null The user row, or null if not found.
|
||||
*/
|
||||
public static function getRegisteredUserById($rID) {
|
||||
$db = self::db();
|
||||
$db->query('SELECT * FROM `users` WHERE `id` = ?;', $rID);
|
||||
|
||||
if ($db->num_rows() != 1) {
|
||||
} else {
|
||||
return $db->get_row();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List registered users under an owner.
|
||||
*
|
||||
* @param int|null $rOwner Owner id, or null for all.
|
||||
* @param bool $rIncludeSelf Include the owner in the result.
|
||||
* @return array Registered user rows.
|
||||
*/
|
||||
public static function getRegisteredUsers($rOwner = null, $rIncludeSelf = true) {
|
||||
$db = self::db();
|
||||
$rReturn = array();
|
||||
$db->query('SELECT * FROM `users` ORDER BY `username` ASC;');
|
||||
|
||||
if (0 >= $db->num_rows()) {
|
||||
} else {
|
||||
foreach ($db->get_rows() as $rRow) {
|
||||
if (!(!$rOwner || $rRow['owner_id'] == $rOwner || $rRow['id'] == $rOwner && $rIncludeSelf)) {
|
||||
} else {
|
||||
$rReturn[intval($rRow['id'])] = $rRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($rReturn) == 0) {
|
||||
$rReturn[-1] = array();
|
||||
}
|
||||
|
||||
return $rReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a streaming user's info (auth + entitlements).
|
||||
*
|
||||
* Looks the user up by id or username/password, then assembles their
|
||||
* bouquets and, optionally, allowed channel ids and active connections.
|
||||
*
|
||||
* @param array $rSettings Panel settings.
|
||||
* @param bool $rCached Use cached lookups.
|
||||
* @param array $rBouquets Bouquet definitions.
|
||||
* @param int|null $rUserID User id (when known).
|
||||
* @param string|null $rUsername Username (credential lookup).
|
||||
* @param string|null $rPassword Password (credential lookup).
|
||||
* @param bool $rGetChannelIDs Include allowed channel ids.
|
||||
* @param bool $rGetConnections Include active connections.
|
||||
* @param string $rIP Client IP.
|
||||
* @return array|null User info, or null if not found.
|
||||
*/
|
||||
public static function getStreamingUserInfo($rSettings, $rCached, $rBouquets, $rUserID = null, $rUsername = null, $rPassword = null, $rGetChannelIDs = false, $rGetConnections = false, $rIP = '') {
|
||||
global $rBlockedISP, $rBlockedServers;
|
||||
$db = self::db();
|
||||
$rUserInfo = null;
|
||||
|
||||
if ($rCached) {
|
||||
if (empty($rPassword) && empty($rUserID) && strlen($rUsername) == 32) {
|
||||
if ($rSettings['case_sensitive_line']) {
|
||||
$rTokenPath = LINES_TMP_PATH . 'line_t_' . $rUsername;
|
||||
$rUserID = (file_exists($rTokenPath) ? intval(file_get_contents($rTokenPath)) : 0);
|
||||
} else {
|
||||
$rTokenPath = LINES_TMP_PATH . 'line_t_' . strtolower($rUsername);
|
||||
$rUserID = (file_exists($rTokenPath) ? intval(file_get_contents($rTokenPath)) : 0);
|
||||
}
|
||||
} else {
|
||||
if (!empty($rUsername) && !empty($rPassword)) {
|
||||
if ($rSettings['case_sensitive_line']) {
|
||||
$rCachePath = LINES_TMP_PATH . 'line_c_' . $rUsername . '_' . $rPassword;
|
||||
$rUserID = (file_exists($rCachePath) ? intval(file_get_contents($rCachePath)) : 0);
|
||||
} else {
|
||||
$rCachePath = LINES_TMP_PATH . 'line_c_' . strtolower($rUsername) . '_' . strtolower($rPassword);
|
||||
$rUserID = (file_exists($rCachePath) ? intval(file_get_contents($rCachePath)) : 0);
|
||||
}
|
||||
} else {
|
||||
if (empty($rUserID)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rUserID) {
|
||||
$rInfoPath = LINES_TMP_PATH . 'line_i_' . $rUserID;
|
||||
if (file_exists($rInfoPath)) {
|
||||
$rUserInfo = igbinary_unserialize(file_get_contents($rInfoPath));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (empty($rPassword) && empty($rUserID) && strlen($rUsername) == 32) {
|
||||
$db->query('SELECT * FROM `lines` WHERE `is_mag` = 0 AND `is_e2` = 0 AND `access_token` = ? AND LENGTH(`access_token`) = 32', $rUsername);
|
||||
} else {
|
||||
if (!empty($rUsername) && !empty($rPassword)) {
|
||||
$db->query('SELECT `lines`.*, `mag_devices`.`token` AS `mag_token` FROM `lines` LEFT JOIN `mag_devices` ON `mag_devices`.`user_id` = `lines`.`id` WHERE `username` = ? AND `password` = ? LIMIT 1', $rUsername, $rPassword);
|
||||
} else {
|
||||
if (!empty($rUserID)) {
|
||||
$db->query('SELECT `lines`.*, `mag_devices`.`token` AS `mag_token` FROM `lines` LEFT JOIN `mag_devices` ON `mag_devices`.`user_id` = `lines`.`id` WHERE `id` = ?', $rUserID);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < $db->num_rows()) {
|
||||
$rUserInfo = $db->get_row();
|
||||
}
|
||||
}
|
||||
|
||||
if (!$rUserInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($rCached) {
|
||||
if (empty($rPassword) && empty($rUserID) && strlen($rUsername) == 32) {
|
||||
if ($rUsername != $rUserInfo['access_token']) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!empty($rUsername) && !empty($rPassword)) {
|
||||
if ($rUsername != $rUserInfo['username'] || $rPassword != $rUserInfo['password']) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rSettings['county_override_1st'] == 1 && empty($rUserInfo['forced_country']) && !empty($rIP) && $rUserInfo['max_connections'] == 1) {
|
||||
$rUserInfo['forced_country'] = GeoIPService::getIPInfo($rIP)['registered_country']['iso_code'];
|
||||
|
||||
if ($rCached) {
|
||||
file_put_contents(SIGNALS_TMP_PATH . 'cache_' . md5('forced_country/' . $rUserInfo['id']), json_encode(array('forced_country/' . $rUserInfo['id'], $rUserInfo['forced_country'])));
|
||||
} else {
|
||||
$db->query('UPDATE `lines` SET `forced_country` = ? WHERE `id` = ?', $rUserInfo['forced_country'], $rUserInfo['id']);
|
||||
}
|
||||
}
|
||||
|
||||
$allowedIPS = json_decode($rUserInfo['allowed_ips'], true);
|
||||
$allowedUa = json_decode($rUserInfo['allowed_ua'], true);
|
||||
$rUserInfo['bouquet'] = json_decode($rUserInfo['bouquet'], true);
|
||||
$rUserInfo['allowed_ips'] = array_filter(array_map('trim', is_array($allowedIPS) ? $allowedIPS : []));
|
||||
$rUserInfo['allowed_ua'] = array_filter(array_map('trim', is_array($allowedUa) ? $allowedUa : []));
|
||||
$rUserInfo['allowed_outputs'] = array_map('intval', json_decode($rUserInfo['allowed_outputs'], true));
|
||||
$rUserInfo['output_formats'] = array();
|
||||
|
||||
if ($rCached) {
|
||||
foreach (igbinary_unserialize(file_get_contents(CACHE_TMP_PATH . 'output_formats')) as $rRow) {
|
||||
if (in_array(intval($rRow['access_output_id']), $rUserInfo['allowed_outputs'])) {
|
||||
$rUserInfo['output_formats'][] = $rRow['output_key'];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$db->query('SELECT `access_output_id`, `output_key` FROM `output_formats`;');
|
||||
|
||||
foreach ($db->get_rows() as $rRow) {
|
||||
if (in_array(intval($rRow['access_output_id']), $rUserInfo['allowed_outputs'])) {
|
||||
$rUserInfo['output_formats'][] = $rRow['output_key'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rUserInfo['con_isp_name'] = null;
|
||||
$rUserInfo['isp_violate'] = 0;
|
||||
$rUserInfo['isp_is_server'] = 0;
|
||||
|
||||
if ($rSettings['show_isps'] == 1 && !empty($rIP)) {
|
||||
$rISPLock = GeoIPService::getISP($rIP);
|
||||
|
||||
if (is_array($rISPLock) && !empty($rISPLock['isp'])) {
|
||||
$rUserInfo['con_isp_name'] = $rISPLock['isp'];
|
||||
$rUserInfo['isp_asn'] = $rISPLock['autonomous_system_number'];
|
||||
$rUserInfo['isp_violate'] = BlocklistService::checkISP($rBlockedISP, $rUserInfo['con_isp_name']);
|
||||
|
||||
if ($rSettings['block_svp'] == 1) {
|
||||
$rUserInfo['isp_is_server'] = intval(BlocklistService::checkServer($rBlockedServers, $rUserInfo['isp_asn']));
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($rUserInfo['con_isp_name']) && $rSettings['enable_isp_lock'] == 1 && $rUserInfo['is_stalker'] == 0 && $rUserInfo['is_isplock'] == 1 && !empty($rUserInfo['isp_desc']) && strtolower($rUserInfo['con_isp_name']) != strtolower($rUserInfo['isp_desc'])) {
|
||||
$rUserInfo['isp_violate'] = 1;
|
||||
}
|
||||
|
||||
if ($rUserInfo['isp_violate'] == 0 && strtolower($rUserInfo['con_isp_name']) != strtolower($rUserInfo['isp_desc'])) {
|
||||
if ($rCached) {
|
||||
$rSignalKey = 'isp/' . $rUserInfo['id'];
|
||||
file_put_contents(SIGNALS_TMP_PATH . 'cache_' . md5($rSignalKey), json_encode(array($rSignalKey, json_encode(array($rUserInfo['con_isp_name'], $rUserInfo['isp_asn'])))));
|
||||
} else {
|
||||
$db->query('UPDATE `lines` SET `isp_desc` = ?, `as_number` = ? WHERE `id` = ?', $rUserInfo['con_isp_name'], $rUserInfo['isp_asn'], $rUserInfo['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rGetChannelIDs) {
|
||||
$rLiveIDs = $rVODIDs = $rRadioIDs = $rCategoryIDs = $rChannelIDs = $rSeriesIDs = array();
|
||||
|
||||
foreach ($rUserInfo['bouquet'] as $rID) {
|
||||
if (isset($rBouquets[$rID]['streams'])) {
|
||||
$rChannelIDs = array_merge($rChannelIDs, $rBouquets[$rID]['streams']);
|
||||
}
|
||||
|
||||
if (isset($rBouquets[$rID]['series'])) {
|
||||
$rSeriesIDs = array_merge($rSeriesIDs, $rBouquets[$rID]['series']);
|
||||
}
|
||||
|
||||
if (isset($rBouquets[$rID]['channels'])) {
|
||||
$rLiveIDs = array_merge($rLiveIDs, $rBouquets[$rID]['channels']);
|
||||
}
|
||||
|
||||
if (isset($rBouquets[$rID]['movies'])) {
|
||||
$rVODIDs = array_merge($rVODIDs, $rBouquets[$rID]['movies']);
|
||||
}
|
||||
|
||||
if (isset($rBouquets[$rID]['radios'])) {
|
||||
$rRadioIDs = array_merge($rRadioIDs, $rBouquets[$rID]['radios']);
|
||||
}
|
||||
}
|
||||
|
||||
$rUserInfo['channel_ids'] = array_map('intval', array_unique($rChannelIDs));
|
||||
$rUserInfo['series_ids'] = array_map('intval', array_unique($rSeriesIDs));
|
||||
$rUserInfo['vod_ids'] = array_map('intval', array_unique($rVODIDs));
|
||||
$rUserInfo['live_ids'] = array_map('intval', array_unique($rLiveIDs));
|
||||
$rUserInfo['radio_ids'] = array_map('intval', array_unique($rRadioIDs));
|
||||
}
|
||||
|
||||
$rAllowedCategories = array();
|
||||
$rCategoryMap = igbinary_unserialize(file_get_contents(CACHE_TMP_PATH . 'category_map'));
|
||||
|
||||
foreach ($rUserInfo['bouquet'] as $rID) {
|
||||
$rAllowedCategories = array_merge($rAllowedCategories, ($rCategoryMap[$rID] ?: array()));
|
||||
}
|
||||
|
||||
$rUserInfo['category_ids'] = array_values(array_unique($rAllowedCategories));
|
||||
return $rUserInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve user info for streaming endpoints (wrapper over getStreamingUserInfo).
|
||||
*
|
||||
* @param int|null $rUserID User id (when known).
|
||||
* @param string|null $rUsername Username (credential lookup).
|
||||
* @param string|null $rPassword Password (credential lookup).
|
||||
* @param bool $rGetChannelIDs Include allowed channel ids.
|
||||
* @param bool $rGetConnections Include active connections.
|
||||
* @param string $rIP Client IP.
|
||||
* @return array|null User info, or null if not found.
|
||||
*/
|
||||
public static function getUserInfo($rUserID = null, $rUsername = null, $rPassword = null, $rGetChannelIDs = false, $rGetConnections = false, $rIP = '') {
|
||||
global $rSettings;
|
||||
$db = self::db();
|
||||
$rCached = $rSettings['enable_cache'];
|
||||
$rBouquets = BouquetService::getAll();
|
||||
$rUserInfo = null;
|
||||
if ($rCached) {
|
||||
if (empty($rPassword) && empty($rUserID) && strlen($rUsername) == 32) {
|
||||
if ($rSettings['case_sensitive_line']) {
|
||||
$rTokenPath = LINES_TMP_PATH . 'line_t_' . $rUsername;
|
||||
$rUserID = (file_exists($rTokenPath) ? intval(file_get_contents($rTokenPath)) : 0);
|
||||
} else {
|
||||
$rTokenPath = LINES_TMP_PATH . 'line_t_' . strtolower($rUsername);
|
||||
$rUserID = (file_exists($rTokenPath) ? intval(file_get_contents($rTokenPath)) : 0);
|
||||
}
|
||||
} else {
|
||||
if (!empty($rUsername) && !empty($rPassword)) {
|
||||
if ($rSettings['case_sensitive_line']) {
|
||||
$rCachePath = LINES_TMP_PATH . 'line_c_' . $rUsername . '_' . $rPassword;
|
||||
$rUserID = (file_exists($rCachePath) ? intval(file_get_contents($rCachePath)) : 0);
|
||||
} else {
|
||||
$rCachePath = LINES_TMP_PATH . 'line_c_' . strtolower($rUsername) . '_' . strtolower($rPassword);
|
||||
$rUserID = (file_exists($rCachePath) ? intval(file_get_contents($rCachePath)) : 0);
|
||||
}
|
||||
} else {
|
||||
if (!empty($rUserID)) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$rUserID) {
|
||||
} else {
|
||||
$rInfoPath = LINES_TMP_PATH . 'line_i_' . $rUserID;
|
||||
if (file_exists($rInfoPath)) {
|
||||
$rUserInfo = igbinary_unserialize(file_get_contents($rInfoPath));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (empty($rPassword) && empty($rUserID) && strlen($rUsername) == 32) {
|
||||
$db->query('SELECT * FROM `lines` WHERE `is_mag` = 0 AND `is_e2` = 0 AND `access_token` = ? AND LENGTH(`access_token`) = 32', $rUsername);
|
||||
} else {
|
||||
if (!empty($rUsername) && !empty($rPassword)) {
|
||||
$db->query('SELECT `lines`.*, `mag_devices`.`token` AS `mag_token` FROM `lines` LEFT JOIN `mag_devices` ON `mag_devices`.`user_id` = `lines`.`id` WHERE `username` = ? AND `password` = ? LIMIT 1', $rUsername, $rPassword);
|
||||
} else {
|
||||
if (!empty($rUserID)) {
|
||||
$db->query('SELECT `lines`.*, `mag_devices`.`token` AS `mag_token` FROM `lines` LEFT JOIN `mag_devices` ON `mag_devices`.`user_id` = `lines`.`id` WHERE `id` = ?', $rUserID);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0 >= $db->num_rows()) {
|
||||
} else {
|
||||
$rUserInfo = $db->get_row();
|
||||
}
|
||||
}
|
||||
if (!$rUserInfo) {
|
||||
return false;
|
||||
}
|
||||
if (!$rCached) {
|
||||
} else {
|
||||
if (empty($rPassword) && empty($rUserID) && strlen($rUsername) == 32) {
|
||||
if ($rUsername == $rUserInfo['access_token']) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (empty($rUsername) || empty($rPassword)) {
|
||||
} else {
|
||||
if (!($rUsername != $rUserInfo['username'] || $rPassword != $rUserInfo['password'])) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!($rSettings['county_override_1st'] == 1 && empty($rUserInfo['forced_country']) && !empty($rIP) && $rUserInfo['max_connections'] == 1)) {
|
||||
} else {
|
||||
$rUserInfo['forced_country'] = GeoIP::getCountry($rIP)['registered_country']['iso_code'];
|
||||
if ($rCached) {
|
||||
RedisManager::setSignal('forced_country/' . $rUserInfo['id'], $rUserInfo['forced_country']);
|
||||
} else {
|
||||
$db->query('UPDATE `lines` SET `forced_country` = ? WHERE `id` = ?', $rUserInfo['forced_country'], $rUserInfo['id']);
|
||||
}
|
||||
}
|
||||
|
||||
$allowedIPS = json_decode($rUserInfo['allowed_ips'], true);
|
||||
$allowedUa = json_decode($rUserInfo['allowed_ua'], true);
|
||||
$rUserInfo['bouquet'] = json_decode($rUserInfo['bouquet'], true);
|
||||
$rUserInfo['allowed_ips'] = array_filter(array_map('trim', is_array($allowedIPS) ? $allowedIPS : []));
|
||||
$rUserInfo['allowed_ua'] = array_filter(array_map('trim', is_array($allowedUa) ? $allowedUa : []));
|
||||
$rUserInfo['allowed_outputs'] = array_map('intval', json_decode($rUserInfo['allowed_outputs'], true));
|
||||
$rUserInfo['output_formats'] = array();
|
||||
if ($rCached) {
|
||||
foreach (igbinary_unserialize(file_get_contents(CACHE_TMP_PATH . 'output_formats')) as $rRow) {
|
||||
if (!in_array(intval($rRow['access_output_id']), $rUserInfo['allowed_outputs'])) {
|
||||
} else {
|
||||
$rUserInfo['output_formats'][] = $rRow['output_key'];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$db->query('SELECT `access_output_id`, `output_key` FROM `output_formats`;');
|
||||
foreach ($db->get_rows() as $rRow) {
|
||||
if (!in_array(intval($rRow['access_output_id']), $rUserInfo['allowed_outputs'])) {
|
||||
} else {
|
||||
$rUserInfo['output_formats'][] = $rRow['output_key'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$rUserInfo['con_isp_name'] = null;
|
||||
$rUserInfo['isp_violate'] = 0;
|
||||
$rUserInfo['isp_is_server'] = 0;
|
||||
if ($rSettings['show_isps'] != 1 || empty($rIP)) {
|
||||
} else {
|
||||
$rISPLock = GeoIP::getISP($rIP);
|
||||
if (is_array($rISPLock)) {
|
||||
if (!empty($rISPLock['isp'])) {
|
||||
$rUserInfo['con_isp_name'] = $rISPLock['isp'];
|
||||
$rUserInfo['isp_asn'] = $rISPLock['autonomous_system_number'];
|
||||
$rUserInfo['isp_violate'] = GeoIP::isISPBlocked($rUserInfo['con_isp_name'], BlocklistService::getBlockedISP());
|
||||
if ($rSettings['block_svp'] == 1) {
|
||||
$rUserInfo['isp_is_server'] = intval(GeoIP::isASNBlocked($rUserInfo['isp_asn'], BlocklistService::getBlockedServers()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(!empty($rUserInfo['con_isp_name']) && $rSettings['enable_isp_lock'] == 1 && $rUserInfo['is_stalker'] == 0 && $rUserInfo['is_isplock'] == 1 && !empty($rUserInfo['isp_desc']) && strtolower($rUserInfo['con_isp_name']) != strtolower($rUserInfo['isp_desc']))) {
|
||||
} else {
|
||||
$rUserInfo['isp_violate'] = 1;
|
||||
}
|
||||
if (!($rUserInfo['isp_violate'] == 0 && strtolower($rUserInfo['con_isp_name']) != strtolower($rUserInfo['isp_desc']))) {
|
||||
} else {
|
||||
if ($rCached) {
|
||||
RedisManager::setSignal('isp/' . $rUserInfo['id'], json_encode(array($rUserInfo['con_isp_name'], $rUserInfo['isp_asn'])));
|
||||
} else {
|
||||
$db->query('UPDATE `lines` SET `isp_desc` = ?, `as_number` = ? WHERE `id` = ?', $rUserInfo['con_isp_name'], $rUserInfo['isp_asn'], $rUserInfo['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$rGetChannelIDs) {
|
||||
} else {
|
||||
$rLiveIDs = $rVODIDs = $rRadioIDs = $rCategoryIDs = $rChannelIDs = $rSeriesIDs = array();
|
||||
foreach ($rUserInfo['bouquet'] as $rID) {
|
||||
if (!isset($rBouquets[$rID]['streams'])) {
|
||||
} else {
|
||||
$rChannelIDs = array_merge($rChannelIDs, $rBouquets[$rID]['streams']);
|
||||
}
|
||||
if (!isset($rBouquets[$rID]['series'])) {
|
||||
} else {
|
||||
$rSeriesIDs = array_merge($rSeriesIDs, $rBouquets[$rID]['series']);
|
||||
}
|
||||
if (!isset($rBouquets[$rID]['channels'])) {
|
||||
} else {
|
||||
$rLiveIDs = array_merge($rLiveIDs, $rBouquets[$rID]['channels']);
|
||||
}
|
||||
if (!isset($rBouquets[$rID]['movies'])) {
|
||||
} else {
|
||||
$rVODIDs = array_merge($rVODIDs, $rBouquets[$rID]['movies']);
|
||||
}
|
||||
if (!isset($rBouquets[$rID]['radios'])) {
|
||||
} else {
|
||||
$rRadioIDs = array_merge($rRadioIDs, $rBouquets[$rID]['radios']);
|
||||
}
|
||||
}
|
||||
$rUserInfo['channel_ids'] = array_map('intval', array_unique($rChannelIDs));
|
||||
$rUserInfo['series_ids'] = array_map('intval', array_unique($rSeriesIDs));
|
||||
$rUserInfo['vod_ids'] = array_map('intval', array_unique($rVODIDs));
|
||||
$rUserInfo['live_ids'] = array_map('intval', array_unique($rLiveIDs));
|
||||
$rUserInfo['radio_ids'] = array_map('intval', array_unique($rRadioIDs));
|
||||
}
|
||||
$rAllowedCategories = array();
|
||||
$rCategoryMap = igbinary_unserialize(file_get_contents(CACHE_TMP_PATH . 'category_map'));
|
||||
foreach ($rUserInfo['bouquet'] as $rID) {
|
||||
$rAllowedCategories = array_merge($rAllowedCategories, ($rCategoryMap[$rID] ?: array()));
|
||||
}
|
||||
$rUserInfo['category_ids'] = array_values(array_unique($rAllowedCategories));
|
||||
return $rUserInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve Enigma2 device user info.
|
||||
*
|
||||
* @param array $rDevice Device row (MAC etc.).
|
||||
* @param bool $rGetChannelIDs Include allowed channel ids.
|
||||
* @param bool $rGetBouquetInfo Include bouquet info.
|
||||
* @param bool $rGetConnections Include active connections.
|
||||
* @return array|null Device user info, or null if not found.
|
||||
*/
|
||||
public static function getE2Info($rDevice, $rGetChannelIDs = false, $rGetBouquetInfo = false, $rGetConnections = false) {
|
||||
$db = self::db();
|
||||
if (empty($rDevice['device_id'])) {
|
||||
$db->query('SELECT * FROM `enigma2_devices` WHERE `mac` = ?', $rDevice['mac']);
|
||||
} else {
|
||||
$db->query('SELECT * FROM `enigma2_devices` WHERE `device_id` = ?', $rDevice['device_id']);
|
||||
}
|
||||
if (0 >= $db->num_rows()) {
|
||||
return false;
|
||||
}
|
||||
$rReturn = array();
|
||||
$rReturn['enigma2'] = $db->get_row();
|
||||
$rReturn['user_info'] = array();
|
||||
if (!($rUserInfo = self::getUserInfo($rReturn['enigma2']['user_id'], null, null, $rGetChannelIDs, $rGetConnections))) {
|
||||
} else {
|
||||
$rReturn['user_info'] = $rUserInfo;
|
||||
}
|
||||
$rReturn['pair_line_info'] = array();
|
||||
if (empty($rReturn['user_info'])) {
|
||||
} else {
|
||||
$rReturn['pair_line_info'] = array();
|
||||
if (is_null($rReturn['user_info']['pair_id'])) {
|
||||
} else {
|
||||
if (!($rUserInfo = self::getUserInfo($rReturn['user_info']['pair_id'], null, null, $rGetChannelIDs, $rGetConnections))) {
|
||||
} else {
|
||||
$rReturn['pair_line_info'] = $rUserInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $rReturn;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user