SESSION_LIFETIME) { logout_user(); return false; } } $_SESSION['last_activity'] = time(); return true; } // ============================================ // FUNZIONI SICUREZZA // ============================================ /** * Hash sicuro di una password * * @param string $password Password in chiaro * @return string Password hashata */ function hash_password($password) { return password_hash($password, PASSWORD_DEFAULT); } /** * Verifica una password contro il suo hash * * @param string $password Password in chiaro * @param string $hash Hash salvato nel database * @return bool True se corrisponde, false altrimenti */ function verify_password($password, $hash) { return password_verify($password, $hash); } /** * Genera un token casuale sicuro * * @param int $length Lunghezza del token * @return string Token generato */ function generate_token($length = 32) { return bin2hex(random_bytes($length)); } /** * Sanitizza input utente per prevenire XSS * * @param string $data Dati da sanitizzare * @return string Dati sanitizzati */ function sanitize_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); return $data; } /** * Valida un indirizzo email * * @param string $email Email da validare * @return bool True se valida, false altrimenti */ function validate_email($email) { return filter_var($email, FILTER_VALIDATE_EMAIL) !== false; } // ============================================ // FUNZIONI DATABASE - UTENTI // ============================================ /** * Ottiene un utente dal database tramite email * * @param string $email Email dell'utente * @return array|false Dati utente o false se non trovato */ function get_user_by_email($email) { $pdo = get_db_connection(); $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ? AND deleted_at IS NULL"); $stmt->execute([$email]); return $stmt->fetch(); } /** * Ottiene un utente dal database tramite ID * * @param int $user_id ID dell'utente * @return array|false Dati utente o false se non trovato */ function get_user_by_id($user_id) { $pdo = get_db_connection(); $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ? AND deleted_at IS NULL"); $stmt->execute([$user_id]); return $stmt->fetch(); } /** * Crea un nuovo utente nel database * * @param string $email Email * @param string $password Password in chiaro (verrà hashata) * @param string $first_name Nome * @param string $last_name Cognome * @param bool $is_admin Se è amministratore * @return int|false ID del nuovo utente o false in caso di errore */ function create_user($email, $password, $first_name, $last_name, $is_admin = false) { $pdo = get_db_connection(); $hashed_password = hash_password($password); try { $stmt = $pdo->prepare(" INSERT INTO users (email, password, first_name, last_name, is_admin, created_at) VALUES (?, ?, ?, ?, ?, NOW()) "); $stmt->execute([ $email, $hashed_password, $first_name, $last_name, $is_admin ? 1 : 0 ]); return $pdo->lastInsertId(); } catch (PDOException $e) { return false; } } // ============================================ // FUNZIONI DATABASE - LEZIONI // ============================================ /** * Ottiene tutte le lezioni demo (gratuite) * * @return array Array di lezioni demo */ function get_demo_lessons() { $pdo = get_db_connection(); $stmt = $pdo->query(" SELECT * FROM lessons WHERE is_demo = 1 AND is_active = 1 ORDER BY created_at DESC "); return $stmt->fetchAll(); } /** * Ottiene tutte le lezioni attive * * @param string $type Tipo di lezione: 'all', 'video', 'live' * @return array Array di lezioni */ function get_all_lessons($type = 'all') { $pdo = get_db_connection(); $sql = "SELECT * FROM lessons WHERE is_active = 1"; if ($type !== 'all') { $sql .= " AND type = :type"; } $sql .= " ORDER BY created_at DESC"; $stmt = $pdo->prepare($sql); if ($type !== 'all') { $stmt->execute(['type' => $type]); } else { $stmt->execute(); } return $stmt->fetchAll(); } /** * Ottiene una lezione specifica tramite ID * * @param int $lesson_id ID della lezione * @return array|false Dati lezione o false se non trovata */ function get_lesson_by_id($lesson_id) { $pdo = get_db_connection(); $stmt = $pdo->prepare("SELECT * FROM lessons WHERE id = ?"); $stmt->execute([$lesson_id]); return $stmt->fetch(); } /** * Verifica se un utente ha acquistato una lezione * * @param int $user_id ID utente * @param int $lesson_id ID lezione * @return bool True se acquistata, false altrimenti */ function user_owns_lesson($user_id, $lesson_id) { $pdo = get_db_connection(); $stmt = $pdo->prepare(" SELECT COUNT(*) as count FROM purchases WHERE user_id = ? AND lesson_id = ? AND status = 'completed' "); $stmt->execute([$user_id, $lesson_id]); $result = $stmt->fetch(); return $result['count'] > 0; } /** * Ottiene tutte le lezioni acquistate da un utente * * @param int $user_id ID utente * @return array Array di lezioni acquistate */ function get_user_purchased_lessons($user_id) { $pdo = get_db_connection(); $stmt = $pdo->prepare(" SELECT l.*, p.purchased_at, p.amount as paid_amount FROM lessons l INNER JOIN purchases p ON l.id = p.lesson_id WHERE p.user_id = ? AND p.status = 'completed' ORDER BY p.purchased_at DESC "); $stmt->execute([$user_id]); return $stmt->fetchAll(); } // ============================================ // FUNZIONI RECUPERO PASSWORD // ============================================ /** * Crea un token per il recupero password * * @param int $user_id ID utente * @return string Token generato */ function create_password_reset_token($user_id) { $pdo = get_db_connection(); $token = generate_token(32); $expires_at = date('Y-m-d H:i:s', time() + PASSWORD_RESET_TOKEN_LIFETIME); // Cancella eventuali token precedenti per questo utente $stmt = $pdo->prepare("DELETE FROM password_resets WHERE user_id = ?"); $stmt->execute([$user_id]); // Crea nuovo token $stmt = $pdo->prepare(" INSERT INTO password_resets (user_id, token, expires_at, created_at) VALUES (?, ?, ?, NOW()) "); $stmt->execute([$user_id, $token, $expires_at]); return $token; } /** * Verifica la validità di un token di reset password * * @param string $token Token da verificare * @return int|false User ID se valido, false altrimenti */ function verify_password_reset_token($token) { $pdo = get_db_connection(); $stmt = $pdo->prepare(" SELECT user_id FROM password_resets WHERE token = ? AND expires_at > NOW() AND used_at IS NULL "); $stmt->execute([$token]); $result = $stmt->fetch(); return $result ? $result['user_id'] : false; } /** * Marca un token come utilizzato * * @param string $token Token da marcare */ function mark_token_as_used($token) { $pdo = get_db_connection(); $stmt = $pdo->prepare("UPDATE password_resets SET used_at = NOW() WHERE token = ?"); $stmt->execute([$token]); } // ============================================ // FUNZIONI EMAIL // ============================================ /** * Invia un'email (funzione base con mail() PHP) * * @param string $to Destinatario * @param string $subject Oggetto * @param string $message Messaggio HTML * @return bool True se inviata, false altrimenti */ function send_email($to, $subject, $message) { if (USE_SMTP) { return send_smtp_email($to, $subject, $message); } else { // Fallback a mail() PHP nativo $headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n"; $headers .= "From: " . MAIL_FROM_NAME . " <" . MAIL_FROM . ">" . "\r\n"; return mail($to, $subject, $message, $headers); } } /** * Invia email tramite SMTP (Gmail) * * @param string $to Email destinatario * @param string $subject Oggetto email * @param string $message Corpo email (HTML) * @return bool True se inviata, false altrimenti */ function send_smtp_email($to, $subject, $message) { try { // Connessione al server SMTP $smtp = fsockopen(SMTP_HOST, SMTP_PORT, $errno, $errstr, 30); if (!$smtp) { error_log("SMTP Error: Impossibile connettersi a " . SMTP_HOST . ":" . SMTP_PORT); return false; } // Funzione helper per leggere risposta $read = function() use ($smtp) { return fgets($smtp, 515); }; // Funzione helper per inviare comando $send = function($cmd) use ($smtp) { fputs($smtp, $cmd . "\r\n"); }; // Leggi il banner di benvenuto $read(); // Inizia handshake SMTP $send("EHLO " . SMTP_HOST); $read(); // Inizia TLS se richiesto if (SMTP_ENCRYPTION === 'tls') { $send("STARTTLS"); $read(); stream_socket_enable_crypto($smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); $send("EHLO " . SMTP_HOST); $read(); } // Autenticazione $send("AUTH LOGIN"); $read(); $send(base64_encode(SMTP_USERNAME)); $read(); $send(base64_encode(SMTP_PASSWORD)); $response = $read(); // Verifica autenticazione if (strpos($response, '235') === false) { error_log("SMTP Error: Autenticazione fallita - " . $response); fclose($smtp); return false; } // Imposta mittente $send("MAIL FROM: <" . MAIL_FROM . ">"); $read(); // Imposta destinatario $send("RCPT TO: <" . $to . ">"); $read(); // Inizia corpo messaggio $send("DATA"); $read(); // Costruisci headers $headers = "From: " . MAIL_FROM_NAME . " <" . MAIL_FROM . ">\r\n"; $headers .= "To: <" . $to . ">\r\n"; $headers .= "Subject: " . $subject . "\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: text/html; charset=UTF-8\r\n"; $headers .= "Date: " . date('r') . "\r\n"; // Invia email $send($headers . "\r\n" . $message . "\r\n."); $read(); // Chiudi connessione $send("QUIT"); $read(); fclose($smtp); return true; } catch (Exception $e) { error_log("SMTP Error: " . $e->getMessage()); return false; } } /** * Invia email di recupero password * * @param string $email Email destinatario * @param string $token Token di reset * @return bool True se inviata, false altrimenti */ function send_password_reset_email($email, $token) { $reset_link = SITE_URL . "/reset_password.php?token=" . $token; $subject = "Recupero Password - " . SITE_NAME; $message = "

Recupero Password

Hai richiesto il recupero della password per il tuo account su " . SITE_NAME . ".

Clicca sul pulsante qui sotto per reimpostare la tua password:

Reimposta Password

Oppure copia e incolla questo link nel tuo browser:

{$reset_link}

Questo link è valido per " . (PASSWORD_RESET_TOKEN_LIFETIME / 60) . " minuti.

Se non hai richiesto tu questo recupero, ignora questa email.


Questa è un'email automatica, non rispondere a questo messaggio.

"; return send_email($email, $subject, $message); } // ============================================ // FUNZIONI MESSAGGI FLASH // ============================================ /** * Imposta un messaggio flash da visualizzare nella prossima pagina * * @param string $type Tipo: 'success', 'error', 'warning', 'info' * @param string $message Messaggio da visualizzare */ function set_flash_message($type, $message) { $_SESSION['flash_message'] = [ 'type' => $type, 'message' => $message ]; } /** * Ottiene e cancella il messaggio flash * * @return array|null Array con tipo e messaggio, o null se non presente */ function get_flash_message() { if (isset($_SESSION['flash_message'])) { $flash = $_SESSION['flash_message']; unset($_SESSION['flash_message']); return $flash; } return null; } /** * Visualizza il messaggio flash HTML * * @return string HTML del messaggio o stringa vuota */ function display_flash_message() { $flash = get_flash_message(); if ($flash) { $type = htmlspecialchars($flash['type']); $message = htmlspecialchars($flash['message']); return "
{$message}
"; } return ''; } // ============================================ // FUNZIONI UTILITY // ============================================ /** * Formatta una data in formato italiano * * @param string $date Data in formato SQL * @return string Data formattata */ function format_date($date) { return date('d/m/Y', strtotime($date)); } /** * Formatta data e ora in formato italiano * * @param string $datetime Datetime in formato SQL * @return string Datetime formattata */ function format_datetime($datetime) { return date('d/m/Y H:i', strtotime($datetime)); } /** * Formatta un prezzo in euro * * @param float $price Prezzo * @return string Prezzo formattato */ function format_price($price) { // Gestisci null o valori non numerici if ($price === null || $price === '') { $price = 0; } return '€ ' . number_format((float)$price, 2, ',', '.'); } /** * Redirect a un'altra pagina * * @param string $url URL di destinazione */ function redirect($url) { header("Location: $url"); exit; } ?>