api/privacy.php

<?php
declare(strict_types=1);

require_once __DIR__ . '/../includes/core.php';

loadTranslations();

$site = trim((string)($_GET['site'] ?? ''));

if ($site !== '' && !isset(brivacia_sites()[$site])) {
    $site = '';
}

$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$baseUrl = $scheme . '://' . ($_SERVER['HTTP_HOST'] ?? '') . ($_SERVER['SCRIPT_NAME'] ?? '');

if (($_GET['frame'] ?? '') !== '1') {
    header('Content-Type: application/javascript; charset=utf-8');

    $src = $baseUrl . '?frame=1&site=' . rawurlencode($site);
    $label = t('privacy.button');
    $tooltip = t('privacy.title', [
        'instance' => brivacia_setting('dashboard.instance_name', 'Brivacia'),
    ]);
    ?>
(() => {
    const src = <?= json_encode($src, JSON_UNESCAPED_SLASHES) ?>;
    const label = <?= json_encode($label, JSON_UNESCAPED_UNICODE) ?>;
    const tooltip = <?= json_encode($tooltip, JSON_UNESCAPED_UNICODE) ?>;

    const style = document.createElement('style');
    style.textContent = `
.brivacia-privacy-button {
    align-items: center;
    background: transparent;
    border: 0;
    color: inherit;
    cursor: pointer;
    display: inline-flex;
    font: inherit;
    gap: .3em;
    padding: 0;
}
.brivacia-privacy-button svg {
    flex: 0 0 auto;
    height: 1em;
    width: 1em;
}
.brivacia-privacy-overlay {
    background: rgba(0,0,0,.65);
    display: none;
    inset: 0;
    overflow: hidden;
    position: fixed;
    z-index: 2147483647;
}
.brivacia-privacy-overlay.open {
    display: block;
}
.brivacia-privacy-frame {
    background: transparent;
    border: 0;
    height: 100vh;
    inset: 0;
    position: fixed;
    width: 100vw;
}`;
    document.head.appendChild(style);

    const button = document.createElement('button');
    button.className = 'brivacia-privacy-button';
    button.type = 'button';
    button.title = tooltip;
    button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shield-question-mark-icon lucide-shield-question-mark"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg> ${label}`;

    const overlay = document.createElement('div');
    overlay.className = 'brivacia-privacy-overlay';
    overlay.innerHTML = `<iframe class="brivacia-privacy-frame" src="${src}" loading="lazy"></iframe>`;

    const openPrivacy = () => {
        overlay.classList.add('open');
        document.documentElement.style.overflow = 'hidden';
        document.body.style.overflow = 'hidden';
    };

    const closePrivacy = () => {
        overlay.classList.remove('open');
        document.documentElement.style.overflow = '';
        document.body.style.overflow = '';
    };

    button.addEventListener('click', openPrivacy);

    window.addEventListener('message', event => {
        if (event.data === 'brivacia:privacy:close') {
            closePrivacy();
        }
    });

    document.addEventListener('keydown', event => {
        if (event.key === 'Escape') {
            closePrivacy();
        }
    });

    document.currentScript.after(button);
    document.body.appendChild(overlay);
})();
<?php
    exit;
}

$db = brivaciaDb();

function one(PDO $db, string $sql, array $params = []): array {
    return fetchAll($db, $sql, $params)[0] ?? [];
}

require __DIR__ . '/../includes/dashboard/privacy.php';

header('Content-Type: text/html; charset=utf-8');
header('X-Frame-Options: ALLOWALL');
?>
<!doctype html>
<html lang="<?= h(currentLang()) ?>" dir="<?= h(currentDir()) ?>" data-theme="<?= h(!empty(brivacia_setting('dashboard.light_theme')) ? 'light' : 'dark') ?>">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="stylesheet" href="/assets/css/style.min.css">
    <style>
        html,
        body {
            background: transparent;
            height: 100%;
            margin: 0;
            overflow: hidden;
        }

        body {
            align-items: center;
            box-sizing: border-box;
            display: flex;
            justify-content: center;
            padding: 2vh 0;
        }

        .modal {
            display: block;
            margin: 0;
            max-height: 90vh;
            max-width: 90vw;
            overflow: auto;
            position: static;
        }

        .modal>div {
            overflow: visible;
        }

        .privacy-powered {
            align-items: center;
            display: flex;
            flex-direction: column;
            font-size: 1rem;
            gap: .3em;
            justify-content: flex-end;
            margin-left: auto;
            margin-top: -.5em;
            pointer-events: auto;
            z-index: 10000;
        }

        .modal h2,
        .privacy-powered a,
        .privacy-powered span {
            align-items: center;
            display: flex;
            gap: .4em;
        }

        .privacy-powered a {
            overflow-wrap: normal;
            text-decoration: none;
        }

        .privacy-powered img {
            height: 1em;
            width: 1em;
        }
        @media (min-width: 3000px) {
            .privacy-powered {
                font-size: var(--font-size-normal-4k);
            }
        }
    </style>
</head>
<body>
<?php
ob_start();
require __DIR__ . '/../includes/modals/privacy_modal.php';

$html = ob_get_clean();
$html = str_replace('<dialog class="modal"', '<dialog class="modal" open', $html);
$powered = '
<div class="privacy-powered">
    <span>' . h(t('footer.powered')) . ' <a href="https://brivacia.breat.fr/" rel="noopener" target="_blank"><img src="/assets/images/logo.png" alt="" aria-hidden="true">Brivacia</a></span>
    <span>' . h(t('footer.created')) . ' <a href="https://breat.fr/" rel="noopener" target="_blank"><img src="/assets/images/icons/breat.fr.png" alt="" aria-hidden="true">breat.fr</a></span>
</div>';

$html = preg_replace( '/<h2([^>]*)>(.*?)<\/h2>/s', '<h2$1><span>$2</span>' . $powered . '</h2>', $html, 1);
echo $html;
?>

<script>
    const browserLanguage = document.querySelector('[data-browser-language]');

    if (browserLanguage) {
        browserLanguage.textContent = navigator.language || '';
    }

    const modal = document.querySelector('.modal');

    document.addEventListener('click', event => {
        if (modal && !modal.contains(event.target)) {
            parent.postMessage('brivacia:privacy:close', '*');
        }
    });

    document.addEventListener('keydown', event => {
        if (event.key === 'Escape') {
            parent.postMessage('brivacia:privacy:close', '*');
        }
    });
</script>
</body>
</html>