api/settings.php

<?php
declare(strict_types=1);

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

header('Content-Type: application/json; charset=utf-8');
header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet');

function brivacia_api_settings_response(array $payload, int $status = 200): never
{
    http_response_code($status);
    echo json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    exit;
}

function brivacia_request_json(): array
{
    $raw = file_get_contents('php://input');

    if ($raw === false || trim($raw) === '') {
        return $_POST;
    }

    $data = json_decode($raw, true);

    if (!is_array($data)) {
        brivacia_api_settings_response([
            'ok' => false,
            'error' => 'Invalid JSON payload.',
        ], 400);
    }

    return $data;
}

function brivacia_api_settings_require_post(): void
{
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        brivacia_api_settings_response([
            'ok' => false,
            'error' => 'Method not allowed.',
        ], 405);
    }
}

function brivacia_expand_dotted_input(array $input): array
{
    $expanded = [];

    foreach ($input as $key => $value) {
        if (!is_string($key) || !str_contains($key, '.')) {
            $expanded[$key] = $value;
            continue;
        }

        $target = &$expanded;

        foreach (explode('.', $key) as $part) {
            if (!isset($target[$part]) || !is_array($target[$part])) {
                $target[$part] = [];
            }

            $target = &$target[$part];
        }

        $target = $value;
        unset($target);
    }

    return $expanded;
}

$action = $_GET['action'] ?? '';

try {
    if ($_SERVER['REQUEST_METHOD'] === 'GET') {
        brivacia_api_settings_response([
            'ok' => true,
            'installed' => brivacia_is_installed(),
            'settings' => brivacia_public_settings(),
        ]);
    }

    if ($action === 'install') {
        brivacia_api_settings_require_post();

        if (brivacia_is_installed()) {
            brivacia_api_settings_response([
                'ok' => false,
                'error' => 'Brivacia is already installed.',
            ], 409);
        }

        $settings = brivacia_install(
            brivacia_expand_dotted_input(brivacia_request_json())
        );

        brivacia_api_settings_response([
            'ok' => true,
            'installed' => true,
            'settings' => $settings,
        ]);
    }

    if ($action === 'save') {
        brivacia_api_settings_require_post();

        if (!brivacia_is_installed()) {
            brivacia_api_settings_response([
                'ok' => false,
                'error' => 'Brivacia is not installed yet.',
            ], 403);
        }

        $current = brivacia_settings();
        $input = brivacia_expand_dotted_input(brivacia_request_json());

        unset($input['installed'], $input['secret'], $input['key']);

        if (isset($input['referrers']['max_icon_mb'])) {
            $input['referrers']['max_icon_bytes'] = (int) round(
                ((float) $input['referrers']['max_icon_mb']) * 1048576
            );

            unset($input['referrers']['max_icon_mb']);
        }

        $settings = brivacia_sanitize_settings($input, $current);
        $settings['installed'] = true;

        brivacia_save_settings($settings);

        brivacia_api_settings_response([
            'ok' => true,
            'settings' => $settings,
        ]);
    }

    brivacia_api_settings_response([
        'ok' => false,
        'error' => 'Unknown action.',
    ], 400);
} catch (Throwable $e) {
    brivacia_api_settings_response([
        'ok' => false,
        'error' => $e->getMessage(),
    ], 500);
}