<?php
/**
 * Board Room — 理事会向けシンプル保護（共通パスワード + セッション）
 * フォルダに .protected があると閲覧にログインが必要
 * 設定は config/boardroom.json のみ（Apache 不要）
 */

define('BOARDROOM_MARKER', '.protected');
define('BOARDROOM_CONFIG', dirname(__DIR__) . '/config/boardroom.json');

function boardroom_session_start() {
    if (session_status() === PHP_SESSION_NONE) {
        $https = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
        session_set_cookie_params([
            'lifetime' => 0,
            'path' => '/',
            'secure' => $https,
            'httponly' => true,
            'samesite' => 'Lax',
        ]);
        session_start();
    }
}

function boardroom_load_config() {
    if (!is_file(BOARDROOM_CONFIG)) {
        return ['version' => 1, 'password_hash' => ''];
    }
    $j = json_decode((string)file_get_contents(BOARDROOM_CONFIG), true);
    return is_array($j) ? $j : ['version' => 1, 'password_hash' => ''];
}

function boardroom_save_config(array $cfg) {
    $dir = dirname(BOARDROOM_CONFIG);
    if (!is_dir($dir)) mkdir($dir, 0755, true);
    $cfg['version'] = 1;
    return file_put_contents(
        BOARDROOM_CONFIG,
        json_encode($cfg, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
    ) !== false;
}

function boardroom_index_root() {
    return rtrim(realpath(dirname(__DIR__)), DIRECTORY_SEPARATOR);
}

function boardroom_norm_rel($rel) {
    $rel = str_replace('\\', '/', trim((string)$rel, " \t\n\r\0\x0B/"));
    return (strpos($rel, '..') !== false) ? '' : $rel;
}

function boardroom_is_logged_in() {
    boardroom_session_start();
    return !empty($_SESSION['boardroom_ok']);
}

function boardroom_login($password) {
    $cfg = boardroom_load_config();
    $hash = (string)($cfg['password_hash'] ?? '');
    if ($hash === '') {
        return ['ok' => false, 'message' => 'パスワードが未設定です（R-Scope で設定）'];
    }
    if (!password_verify($password, $hash)) {
        return ['ok' => false, 'message' => 'パスワードが違います'];
    }
    boardroom_session_start();
    $_SESSION['boardroom_ok'] = true;
    return ['ok' => true];
}

function boardroom_logout() {
    boardroom_session_start();
    unset($_SESSION['boardroom_ok']);
}

function boardroom_set_password($password) {
    if (trim($password) === '') {
        return ['ok' => false, 'message' => '空のパスワードは設定できません'];
    }
    $cfg = boardroom_load_config();
    $cfg['password_hash'] = password_hash($password, PASSWORD_DEFAULT);
    if (!boardroom_save_config($cfg)) {
        return ['ok' => false, 'message' => '保存に失敗しました'];
    }
    return ['ok' => true];
}

function boardroom_has_password() {
    return (string)(boardroom_load_config()['password_hash'] ?? '') !== '';
}

function boardroom_is_protected_dir($absDir) {
    return is_dir($absDir) && is_file($absDir . DIRECTORY_SEPARATOR . BOARDROOM_MARKER);
}

/** このパスが保護対象か（自分または親に .protected） */
function boardroom_path_is_protected($relFromIndex) {
    $rel = boardroom_norm_rel($relFromIndex);
    $root = boardroom_index_root();
    $parts = $rel === '' ? [] : explode('/', $rel);
    $built = [];
    foreach ($parts as $p) {
        $built[] = $p;
        $abs = $root . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, implode('/', $built));
        if (boardroom_is_protected_dir($abs)) return true;
    }
    if ($rel === '') {
        return boardroom_is_protected_dir($root);
    }
    return false;
}

function boardroom_can_access($relFromIndex) {
    if (!boardroom_path_is_protected($relFromIndex)) return true;
    return boardroom_is_logged_in();
}

/** News-Archive 直下の添付フォルダ files を一覧から除外 */
function boardroom_is_news_archive_files_entry(string $name, string $parentRel = '', string $listingDirAbs = ''): bool
{
    if (strcasecmp($name, 'files') !== 0) {
        return false;
    }

    if ($listingDirAbs !== '') {
        $base = basename(str_replace('\\', '/', $listingDirAbs));
        if (strcasecmp($base, 'News-Archive') === 0) {
            return true;
        }
    }

    $parent = boardroom_norm_rel($parentRel);
    if ($parent === '') {
        return false;
    }

    $parts = explode('/', $parent);
    $last = $parts[count($parts) - 1];

    return strcasecmp($last, 'News-Archive') === 0;
}

/** data/index.php 一覧に出さない（閲覧対象外のシステム用） */
function boardroom_is_browse_hidden(string $name, string $parentRel = '', string $listingDirAbs = ''): bool
{
    if ($name === '' || $name[0] === '.') {
        return true;
    }

    if (boardroom_is_news_archive_files_entry($name, $parentRel, $listingDirAbs)) {
        return true;
    }

    static $hidden = [
        'index.php',
        'file.php',
        'file-lister.php',
        'save-description.php',
        'fl-path.php',
        'fl-meta.php',
        'htaccess',
        '.htaccess',
        BOARDROOM_MARKER,
        '.htpasswd',
        'web.config',
        'desktop.ini',
        'thumbs.db',
    ];

    $lower = strtolower($name);
    foreach ($hidden as $h) {
        if (strtolower($h) === $lower) {
            return true;
        }
    }

    // 資料閲覧では PHP を一覧・配信対象にしない
    if (strtolower(pathinfo($name, PATHINFO_EXTENSION)) === 'php') {
        return true;
    }

    return false;
}

/** file.php で配信してはいけないパス（basename または相対パス末尾） */
function boardroom_is_delivery_blocked(string $relPath): bool
{
    $rel = boardroom_norm_rel($relPath);
    if ($rel === '') {
        return true;
    }

    $base = basename(str_replace('\\', '/', $rel));
    if (boardroom_is_browse_hidden($base)) {
        return true;
    }

    foreach (explode('/', $rel) as $seg) {
        if (boardroom_is_browse_hidden($seg)) {
            return true;
        }
    }

    return false;
}

function boardroom_protect_folder($relFromIndex) {
    $rel = boardroom_norm_rel($relFromIndex);
    if ($rel === '') return ['ok' => false, 'message' => 'ルートは保護できません'];
    $abs = boardroom_index_root() . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel);
    if (!is_dir($abs)) return ['ok' => false, 'message' => 'フォルダがありません'];
    @unlink($abs . '/.htaccess');
    if (file_put_contents($abs . DIRECTORY_SEPARATOR . BOARDROOM_MARKER, "1\n") === false) {
        return ['ok' => false, 'message' => '.protected を作成できません'];
    }
    return ['ok' => true];
}

function boardroom_unprotect_folder($relFromIndex) {
    $rel = boardroom_norm_rel($relFromIndex);
    $abs = boardroom_index_root() . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $rel);
    if (!is_dir($abs)) return ['ok' => false, 'message' => 'フォルダがありません'];
    @unlink($abs . DIRECTORY_SEPARATOR . BOARDROOM_MARKER);
    @unlink($abs . '/.htaccess');
    return ['ok' => true];
}
