<?php
/**
 * (c) ININOUT & PYXIS. All Rights Reserved.
 * Wszelkie modyfikacje tego pliku wymagaja zgloszenia oraz zgody autorow.
 * Any modifications to this file require notification and consent of the authors.
 */
/**
 * i-BOK 5 - IP Access Control
 *
 * Kontrola dostępu po IP/podsieci do panelu klienta i admina.
 * Emergency bypass: jeśli istnieje plik cfg/.emergency_access, restrykcje admina wyłączone.
 */

/**
 * Załaduj konfigurację kontroli dostępu
 * @return array
 */
function ip_access_load() {
    $file = IBOK_CFG_DIR . '/access_control.cfg';
    $defaults = [
        'client_allowed_ips' => [],
        'admin_allowed_ips'  => [],
        'client_enabled'     => false,
        'admin_enabled'      => false,
    ];
    if (!file_exists($file)) return $defaults;
    $data = @json_decode(file_get_contents($file), true);
    if (!is_array($data)) return $defaults;
    return array_merge($defaults, $data);
}

/**
 * Zapisz konfigurację kontroli dostępu
 * @param array $config
 * @return bool
 */
function ip_access_save($config) {
    $file = IBOK_CFG_DIR . '/access_control.cfg';
    return file_put_contents($file, json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)) !== false;
}

/**
 * Sprawdź czy bieżący IP jest dozwolony
 * @param string $type 'admin' lub 'client'
 * @return bool true = dozwolony, false = zablokowany
 */
function ip_access_check($type) {
    $config = ip_access_load();

    // Emergency bypass dla admina
    if ($type === 'admin' && file_exists(IBOK_CFG_DIR . '/.emergency_access')) {
        return true;
    }

    $enabled_key = $type . '_enabled';
    $ips_key = $type . '_allowed_ips';

    if (empty($config[$enabled_key])) return true;
    if (empty($config[$ips_key]) || !is_array($config[$ips_key])) return true;

    $client_ip = $_SERVER['REMOTE_ADDR'] ?? '';
    if (empty($client_ip)) return false;

    foreach ($config[$ips_key] as $entry) {
        $entry = trim($entry);
        if ($entry === '') continue;
        if (strpos($entry, '/') !== false) {
            if (ip_in_cidr($client_ip, $entry)) return true;
        } else {
            if ($client_ip === $entry) return true;
        }
    }

    return false;
}

/**
 * Sprawdź czy IP pasuje do CIDR
 * @param string $ip Adres IP
 * @param string $cidr CIDR (np. 192.168.1.0/24)
 * @return bool
 */
function ip_in_cidr($ip, $cidr) {
    $parts = explode('/', $cidr, 2);
    if (count($parts) !== 2) return $ip === $cidr;

    $subnet = $parts[0];
    $mask = (int)$parts[1];

    if ($mask < 0 || $mask > 32) return false;

    $ip_long = ip2long($ip);
    $subnet_long = ip2long($subnet);

    if ($ip_long === false || $subnet_long === false) return false;

    $mask_long = -1 << (32 - $mask);
    return ($ip_long & $mask_long) === ($subnet_long & $mask_long);
}

/**
 * Czy emergency access jest aktywny
 * @return bool
 */
function ip_access_emergency_active() {
    return file_exists(IBOK_CFG_DIR . '/.emergency_access');
}
