# Practical 5 – Encrypted File Transfer: Server
# Install: pip install cryptography
# Run p5_networkSec_auth.py first to create the demo user.
import os
import socket
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from p5_networkSec_auth import authenticate_user, init_db

KEY = bytes.fromhex("054f0c5c692ffa3e0d0fa7d156966812")  # Demo key only

def receive_exact(conn, size):
    data = b""
    while len(data) < size:
        part = conn.read(size - len(data))
        if not part:
            raise ConnectionError("Client disconnected")
        data += part
    return data

init_db()
with socket.socket() as server:
    server.bind(("127.0.0.1", 8888))
    server.listen(1)
    print("Local file server listening on port 8888")
    conn, _ = server.accept()
    with conn:
        login = conn.makefile("rb")
        username, password = login.readline().decode().strip().split("|", 1)
        if not authenticate_user(username, password):
            conn.sendall(b"AUTH_FAILED\n")
        else:
            conn.sendall(b"AUTH_OK\n")
            nonce = receive_exact(login, 12)
            filename = login.readline().decode().strip()
            size = int(login.readline())
            if not 0 <= size <= 10_000_000:
                raise ValueError("Invalid file size")
            encrypted = receive_exact(login, size)
            data = AESGCM(KEY).decrypt(nonce, encrypted, None)
            safe_name = os.path.basename(filename)
            with open("received_" + safe_name, "wb") as file:
                file.write(data)
            conn.sendall(b"File received and decrypted")
            print("Saved received_" + safe_name)

# What this code does: accepts an authenticated local client, decrypts the
# received file, and saves it with a received_ prefix.
