<?php
/**
 * Security helper funkcije za webshop
 * 
 * Ovaj fajl sadrži funkcije za povećanje sigurnosti web prodavnice,
 * uključujući CSRF zaštitu, sigurnosno logiranje, validaciju unosa i dr.
 */

/**
 * Generiše CSRF token i smešta ga u sesiju
 * 
 * @return string CSRF token
 */
function generate_csrf_token() {
    if (!isset($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

/**
 * Verifikuje CSRF token
 * 
 * @param string $token Token za verifikaciju
 * @return bool True ako je token validan, false inače
 */
function verify_csrf_token($token) {
    if (!isset($_SESSION['csrf_token'])) {
        return false;
    }
    
    $valid = hash_equals($_SESSION['csrf_token'], $token);
    
    // Logiraj pokušaj ako token nije validan
    if (!$valid) {
        security_log('Invalid CSRF token', 'warning');
    }
    
    return $valid;
}

/**
 * Sanitizuje input podatke za bezbednu upotrebu
 * 
 * @param string $data Podatak koji treba sanitizovati
 * @return string Sanitizovan podatak
 */
function sanitize_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
    return $data;
}

/**
 * Validira email adresu
 * 
 * @param string $email Email za validaciju
 * @return bool True ako je email validan, false inače
 */
function validate_email($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

/**
 * Bezbedno logiraj sigurnosne događaje
 * 
 * @param string $event Opis događaja
 * @param string $level Nivo logiranja (info, warning, error, critical)
 * @param string $details Dodatni detalji
 * @return bool Uspeh operacije
 */
function security_log($event, $level = 'info', $details = '') {
    $log_dir = __DIR__ . '/../logs';
    $log_file = $log_dir . '/security.log';
    
    // Kreiraj logs direktorijum ako ne postoji
    if (!is_dir($log_dir)) {
        mkdir($log_dir, 0755, true);
    }
    
    $timestamp = date('Y-m-d H:i:s');
    $ip = $_SERVER['REMOTE_ADDR'];
    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
    $user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 'guest';
    
    $log_entry = "[{$timestamp}] [{$level}] [{$ip}] [User:{$user_id}] {$event} {$details}\n";
    
    return file_put_contents($log_file, $log_entry, FILE_APPEND) !== false;
}

/**
 * Proverava ograničenje broja pokušaja za određenu akciju
 * 
 * @param string $action Identifikator akcije (npr. 'login', 'checkout')
 * @param string $identifier Identifikator korisnika (npr. IP adresa)
 * @param int $max_attempts Maksimalan broj dozvoljenih pokušaja
 * @param int $time_period Vremenski period za ograničenje u sekundama
 * @return bool True ako je u granicama, false ako je prekoračen limit
 */
function check_rate_limit($action, $identifier, $max_attempts, $time_period) {
    global $conn;
    
    try {
        // Proveri da li tabela postoji, ako ne, kreiraj je
        $table_exists = $conn->query("SHOW TABLES LIKE 'rate_limits'")->rowCount() > 0;
        
        if (!$table_exists) {
            $conn->exec("CREATE TABLE rate_limits (
                id INT AUTO_INCREMENT PRIMARY KEY,
                action VARCHAR(50) NOT NULL,
                identifier VARCHAR(255) NOT NULL,
                timestamp DATETIME NOT NULL,
                INDEX (action, identifier)
            )");
        }
        
        // Obriši stare pokušaje
        $stmt = $conn->prepare("DELETE FROM rate_limits WHERE action = ? AND timestamp < (NOW() - INTERVAL ? SECOND)");
        $stmt->execute([$action, $time_period]);
        
        // Prebrojavanje pokušaja
        $stmt = $conn->prepare("SELECT COUNT(*) FROM rate_limits WHERE action = ? AND identifier = ?");
        $stmt->execute([$action, $identifier]);
        $count = $stmt->fetchColumn();
        
        if ($count >= $max_attempts) {
            security_log("Rate limit exceeded", "warning", "Action: {$action}, IP: {$identifier}, Attempts: {$count}");
            return false; // Prekoračeno ograničenje
        }
        
        // Dodaj novi pokušaj
        $stmt = $conn->prepare("INSERT INTO rate_limits (action, identifier, timestamp) VALUES (?, ?, NOW())");
        $stmt->execute([$action, $identifier]);
        
        return true; // Ispod ograničenja
    } catch (PDOException $e) {
        error_log("Rate limit error: " . $e->getMessage());
        // U slučaju greške, dozvoli akciju da ne bi blokirali legitimne korisnike
        return true;
    }
}

/**
 * Postavlja sigurnosna HTTP zaglavlja
 */
function set_security_headers() {
    // Osnovna zaštita od XSS napada
    header("X-XSS-Protection: 1; mode=block");
    
    // Sprečava klikjacking napade
    header("X-Frame-Options: SAMEORIGIN");
    
    // Sprečava MIME-type sniffing napade
    header("X-Content-Type-Options: nosniff");
    
    // Referrer policy - ograničava informacije koje se šalju kada korisnik klikne na link
    header("Referrer-Policy: strict-origin-when-cross-origin");
    
    // Content Security Policy - ograničava vrste sadržaja koje browser može da učita
    // header("Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; img-src 'self' data:;");
    
    // Feature policy - ograničava pristup određenim API-jima
    header("Permissions-Policy: geolocation=(), microphone=(), camera=()");
}

/**
 * Forsiraj HTTPS konekciju
 * 
 * @return bool True ako je konekcija HTTPS ili je napravljen redirect
 */
function force_https() {
    if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
        if (!headers_sent()) {
            $redirect_url = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
            header("Location: $redirect_url", true, 301);
            exit;
        } else {
            return false;
        }
    }
    return true;
}

function secure_session() {
    // Postavi sigurna podešavanja za kolačiće
    ini_set('session.cookie_httponly', 1); // Spreči JavaScript pristup ID-u sesije
    
    // Koristi kolačić samo preko HTTPS (isključeno u razvoju)
    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
        ini_set('session.cookie_secure', 1);
    }
    
    ini_set('session.use_only_cookies', 1);
    ini_set('session.cookie_samesite', 'Lax'); // Vrednosti: Lax, Strict, None
    
    // Ako sesija nije započeta, započni je
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
    
    // Regeneriši ID sesije za sprečavanje session fixation napada
    if (!isset($_SESSION['last_regeneration']) || time() - $_SESSION['last_regeneration'] > 1800) {
        session_regenerate_id(true);
        $_SESSION['last_regeneration'] = time();
    }
}

/**
 * Enkripcija osetljivih podataka
 * 
 * @param string $data Podatak za enkripciju
 * @param string $key Ključ za enkripciju (postavlja se u config fajlu)
 * @return string Enkriptovani podatak
 */
function encrypt_data($data, $key) {
    $method = "AES-256-CBC";
    $iv = random_bytes(16);
    $encrypted = openssl_encrypt($data, $method, $key, 0, $iv);
    return base64_encode($iv . $encrypted);
}

/**
 * Dekripcija enkriptovanih podataka
 * 
 * @param string $data Enkriptovani podatak
 * @param string $key Ključ za dekripciju
 * @return string Dekriptovani podatak ili false u slučaju greške
 */
function decrypt_data($data, $key) {
    try {
        $data = base64_decode($data);
        if ($data === false) {
            return false;
        }
        
        $method = "AES-256-CBC";
        $iv = substr($data, 0, 16);
        $encrypted = substr($data, 16);
        
        return openssl_decrypt($encrypted, $method, $key, 0, $iv);
    } catch (Exception $e) {
        error_log("Decryption error: " . $e->getMessage());
        return false;
    }
}

/**
 * Validiraj URL
 * 
 * @param string $url URL za validaciju
 * @return bool True ako je URL validan, false inače
 */
function validate_url($url) {
    return filter_var($url, FILTER_VALIDATE_URL) !== false;
}

/**
 * Generiše CSRF token i HTML za skriveno polje forme
 * 
 * @return string HTML za CSRF token polje
 */
function csrf_token_field() {
    $token = generate_csrf_token();
    return '<input type="hidden" name="csrf_token" value="' . $token . '">';
}

// Automatsko podešavanje sigurnosnih zaglavlja na svakoj stranici
set_security_headers();

// Osiguraj sesije
secure_session();