<?php
// 경로/파일: /var/www/html/elfinder/php/connector.minimal.php
// ✅ 변경 핵심:
// - roots에 넣기 전에 "실제로 마운트된 경로인지" 확인
// - /mnt/usb* 폴더만 있고 마운트 안 됐으면 절대 roots로 안 뜸
// - /mnt/storage, /mnt/tmp 도 "마운트된 경우에만" 노출 (진짜 있는 것만)

error_reporting(0);
header('X-REALNAS-CONNECTOR: v20251228');


is_readable(__DIR__ . '/vendor/autoload.php') && require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/autoload.php';

elFinder::$netDrivers['ftp'] = 'FTP';

// -------------------------------------------------
// 접근 제어 (UI 차단)
// -------------------------------------------------
function access($attr, $path, $data, $volume, $isDir, $relpath) {
    $basename = basename($path);

    // 1) 숨김파일/폴더 (.xxx) 차단
    if (strlen($basename) > 0 && $basename[0] === '.' && strlen($relpath) !== 1) {
        return !($attr === 'read' || $attr === 'write');
    }

    // 2) lost+found 차단
    if ($basename === 'lost+found') {
        return !($attr === 'read' || $attr === 'write');
    }

    return null;
}

// -------------------------------------------------
// util
// -------------------------------------------------
function norm_path($p) {
    $p = trim((string)$p);
    $p = str_replace("\0", '', $p);
    $p = rtrim($p, "/");
    return $p === '' ? '/' : $p;
}

function detect_scheme() {
    if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
        $p = explode(',', $_SERVER['HTTP_X_FORWARDED_PROTO'])[0];
        $p = trim($p);
        if ($p === 'http' || $p === 'https') return $p;
    }
    if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') return 'https';
    return 'http';
}

function detect_host() {
    if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
        $h = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST'])[0];
        return trim($h);
    }
    if (!empty($_SERVER['HTTP_HOST'])) return $_SERVER['HTTP_HOST'];
    if (!empty($_SERVER['SERVER_NAME'])) return $_SERVER['SERVER_NAME'];
    return 'localhost';
}

function script_base_url() {
    $scheme = detect_scheme();
    $host   = detect_host();
    $script = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';

    // /files/php/connector.minimal.php -> /files
    $basePath = preg_replace('#/php/[^/]+\.php$#', '', $script);
    $basePath = rtrim($basePath, '/');

    $host = trim($host);
    $host = preg_replace('/\s+/', '', $host);

    return $scheme . '://' . $host . $basePath;
}

function load_config($path) {
    if (!is_readable($path)) return null;
    $raw = @file_get_contents($path);
    if ($raw === false) return null;
    $json = @json_decode($raw, true);
    if (!is_array($json)) return null;
    return $json;
}

function safe_web_path($s) {
    $s = trim((string)$s);
    $s = trim($s, "/");
    $s = str_replace(array('..', '\\', '/'), '', $s);
    $s = preg_replace('/\s+/', '-', $s);
    $s = preg_replace('/[^a-zA-Z0-9._-]/', '', $s);
    return $s;
}

// -------------------------------------------------
// ✅ "마운트된 경로" 판별
// - /proc/self/mountinfo 기반 (exec 안 씀)
// -------------------------------------------------
function is_mounted_path($p) {
    $p = norm_path($p);
    if ($p === '/' || $p === '') return false;

    // findmnt -T <path> : 해당 경로가 실제 마운트 포인트일 때만 성공
    $cmd = 'findmnt -T ' . escapeshellarg($p) . ' >/dev/null 2>&1';
    $rc  = 1;
    @exec($cmd, $out, $rc);

    return ($rc === 0);
}


// -------------------------------------------------
// ✅ 허용 루트 정책 (중요)
// -------------------------------------------------
function is_allowed_root($p) {
    $p = norm_path($p);

    // ✅ 절대 금지: OS 루트
    if ($p === '/') return false;

    if ($p === '/mnt/storage') return true;
    if ($p === '/mnt/tmp') return true;

    if (preg_match('#^/mnt/usb[0-9]+$#', $p)) return true;

    return false;
}

function build_local_root($alias, $path, $url) {
    $path  = norm_path($path);
    $alias = trim((string)$alias);

    if ($path === '/' || !is_allowed_root($path)) {
        return null;
    }

    $root = array(
        'driver'        => 'LocalFileSystem',
        'path'          => $path . '/',
        'alias'         => $alias !== '' ? $alias : basename($path),
        'uploadDeny'    => array(),
        'uploadAllow'   => array('all'),
        'uploadOrder'   => array('deny', 'allow'),
        'accessControl' => 'access',
        'archive'       => array(
            'create'  => array('application/zip'),
            'extract' => array('application/zip'),
        ),
    );

    $url = trim((string)$url);
    if ($url !== '') {
        $root['URL'] = rtrim($url, '/') . '/';
    }

    return $root;
}

function pick_conf_path() {
    $p1 = '/etc/realnas/elfinder.json';
    if (is_readable($p1)) return $p1;

    $p2 = '/opt/realcom-nas/config/elfinder.json';
    if (is_readable($p2)) return $p2;

    return $p1;
}

// -------------------------------------------------
// 설정 정책
// -------------------------------------------------
define('AUTO_URL', true);

// -------------------------------------------------
// roots 구성
// -------------------------------------------------
$CONF_PATH = pick_conf_path();
$conf = load_config($CONF_PATH);

$roots   = array();
$baseUrl = script_base_url();

if (is_array($conf) && isset($conf['roots']) && is_array($conf['roots']) && count($conf['roots']) > 0) {
    foreach ($conf['roots'] as $r) {
        if (!is_array($r)) continue;

        $alias = isset($r['alias']) ? trim((string)$r['alias']) : '';
        $path  = isset($r['path'])  ? trim((string)$r['path'])  : '';
        $url   = isset($r['url'])   ? trim((string)$r['url'])   : '';
        $webp  = isset($r['web_path']) ? trim((string)$r['web_path']) : '';

        if ($path === '') continue;

        $np = norm_path($path);

        // ✅ 허용 루트가 아니면 스킵
        if (!is_allowed_root($np)) continue;

        // ✅ 반드시 존재하는 디렉토리만
        if (!is_dir($np)) continue;

        // ✅ "실제로 마운트된 것만" 노출
        // -> /mnt/usb1.. 같은 빈 폴더는 여기서 걸러짐
        if (!is_mounted_path($np)) continue;

        // url 자동생성
        if ($url === '' && AUTO_URL) {
            if ($webp === '') $webp = ($alias !== '') ? $alias : basename($np);
            $webp = safe_web_path($webp);
            if ($webp !== '') {
                $url = $baseUrl . '/' . $webp;
            }
        }

        $root = build_local_root($alias, $np, $url);
        if (is_array($root)) {
            $roots[] = $root;
        }
    }
}

// -------------------------------------------------
// ✅ fallback
// - 여기서도 "마운트된 것만" 잡음
// -------------------------------------------------
if (count($roots) === 0) {
    $cands = array('/mnt/storage', '/mnt/tmp');
    for ($i = 1; $i <= 8; $i++) $cands[] = '/mnt/usb' . $i;

    $fallback = '';
    foreach ($cands as $c) {
        if (is_allowed_root($c) && is_dir($c) && is_mounted_path($c)) {
            $fallback = $c;
            break;
        }
    }

    if ($fallback === '' || !is_allowed_root($fallback)) {
        header('Content-Type: application/json; charset=utf-8');
        http_response_code(500);
        echo json_encode(array(
            'error' => 'No valid mounted elFinder roots. Mount one of: /mnt/storage, /mnt/tmp, /mnt/usbN',
            'conf_path' => $CONF_PATH
        ), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit;
    }

    $root = build_local_root('DATA', $fallback, '');
    if (is_array($root)) $roots[] = $root;
}

// -------------------------------------------------
// elFinder 실행
// -------------------------------------------------
$opts = array('roots' => $roots);
$connector = new elFinderConnector(new elFinder($opts));
$connector->run();
