<?php
error_reporting(0);

// ==========================================
// 1. 기본 경로 및 설정
// ==========================================
$vroot_path = isset($_GET['vroot']) ? str_replace(['..', './'], '', $_GET['vroot']) : '';
$actual_base = __DIR__;

if ($vroot_path && is_dir($actual_base . '/' . $vroot_path)) {
    $base_dir = realpath($actual_base . '/' . $vroot_path);
    $is_locked = true;
} else { 
    $base_dir = $actual_base; 
    $is_locked = false; 
}

$rel_dir = isset($_GET['dir']) ? str_replace(['..', './'], '', $_GET['dir']) : '';
$current_dir = realpath($base_dir . '/' . $rel_dir);

if (!$current_dir || strpos($current_dir, $base_dir) !== 0) { 
    $current_dir = $base_dir; 
    $rel_dir = ''; 
}

// ==========================================
// 1-1. ZIP 임시파일 정리 함수
// ==========================================
function lk_cleanup_old_zip_files($tmp_dir, $max_age_seconds = 3600) {
    if (!is_dir($tmp_dir)) return;

    $now = time();
    $patterns = [
        rtrim($tmp_dir, '/\\') . DIRECTORY_SEPARATOR . 'zip_*',
        rtrim($tmp_dir, '/\\') . DIRECTORY_SEPARATOR . 'download_*.zip',
        rtrim($tmp_dir, '/\\') . DIRECTORY_SEPARATOR . 'tmp_*.zip'
    ];

    foreach ($patterns as $pattern) {
        $files = glob($pattern);
        if (!$files) continue;

        foreach ($files as $file) {
            if (!is_file($file)) continue;

            $mtime = @filemtime($file);
            if ($mtime === false) continue;

            // 현재 생성 중일 수 있는 파일 보호를 위해 일정 시간 지난 파일만 삭제
            if (($now - $mtime) > $max_age_seconds) {
                @unlink($file);
            }
        }
    }
}

function lk_human_filesize($bytes) {
    $bytes = (float)$bytes;
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $i = 0;
    while ($bytes >= 1024 && $i < count($units) - 1) {
        $bytes /= 1024;
        $i++;
    }
    return round($bytes, 2) . ' ' . $units[$i];
}

// ==========================================
// 2. 강제 다운로드 처리 로직
// ==========================================
if (isset($_GET['action']) && $_GET['action'] === 'download' && isset($_GET['file'])) {
    $file_req = str_replace(['..', './'], '', $_GET['file']);
    $file_path = realpath($current_dir . '/' . $file_req);

    if ($file_path && file_exists($file_path) && strpos($file_path, $base_dir) === 0 && !is_dir($file_path)) {
        $filename = basename($file_path);
        $filesize = filesize($file_path);

        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: private", false);
        header("Content-Type: application/octet-stream");
        $encoded_filename = rawurlencode($filename);
        header("Content-Disposition: attachment; filename=\"$filename\"; filename*=UTF-8''$encoded_filename");
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: " . $filesize);

        readfile($file_path);
        exit;
    } else {
        die("파일을 찾을 수 없거나 접근 권한이 없습니다.");
    }
}
// ==========================================
// 2-1. 폴더 전체 ZIP 다운로드 처리 로직
// ==========================================
if (isset($_GET['action']) && $_GET['action'] === 'zip') {
    set_time_limit(0);
    ignore_user_abort(true);

    if (!class_exists('ZipArchive')) {
        die("ZipArchive(php-zip) 확장이 설치/활성화되어 있지 않습니다.");
    }

    $tmp_dir = __DIR__ . '/tmp';
    if (!is_dir($tmp_dir)) @mkdir($tmp_dir, 0755, true);
    if (!is_writable($tmp_dir)) die("임시 ZIP 저장 폴더(tmp)에 쓰기 권한이 없습니다: " . $tmp_dir);

    // ✅ 이전 다운로드 과정에서 남은 임시 ZIP 파일 자동 삭제
    // 기본값: 1시간 지난 zip_* 파일 삭제
    lk_cleanup_old_zip_files($tmp_dir, 3600);

    $exclude_names = ['.', '..', 'index.php', '@eaDir', '.DS_Store', 'Thumbs.db', '#recycle'];

    $zip_basename = basename($current_dir);
    if ($zip_basename === '' || $zip_basename === DIRECTORY_SEPARATOR) $zip_basename = 'download';
    $zip_filename = $zip_basename . '.zip';

    $tmp_zip_path = tempnam($tmp_dir, 'zip_');
    if ($tmp_zip_path === false) die("임시 ZIP 파일 경로를 만들 수 없습니다.");
    @unlink($tmp_zip_path);
    $tmp_zip_path .= '.zip';

    // ✅ 다운로드 완료/오류/중단 등으로 스크립트가 종료될 때 임시 ZIP 파일 삭제
    register_shutdown_function(function() use ($tmp_zip_path) {
        if (isset($tmp_zip_path) && is_file($tmp_zip_path)) {
            @unlink($tmp_zip_path);
        }
    });

    $zip = new ZipArchive();
    $open_result = $zip->open($tmp_zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE);
    if ($open_result !== true) die("ZIP 파일을 생성할 수 없습니다. (open code: " . $open_result . ")");

    $base_len = strlen($current_dir) + 1;

    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($current_dir, FilesystemIterator::SKIP_DOTS),
        RecursiveIteratorIterator::SELF_FIRST
    );

    $added_count = 0;
   $file_added = 0;   // ✅ 파일만 카운트
    $total_source_bytes = 0; // ✅ 원본 파일 총 용량 계산
    foreach ($iterator as $fileinfo) {
        $name_only = $fileinfo->getFilename();
        if (in_array($name_only, $exclude_names, true)) continue;

        $real = $fileinfo->getRealPath();
        if (!$real) continue;
        if (strpos($real, $current_dir) !== 0) continue;

        // ✅ Synology @eaDir 경로 전체 제외 (재귀 포함)
        if (strpos($real, DIRECTORY_SEPARATOR.'@eaDir'.DIRECTORY_SEPARATOR) !== false ||
            substr($real, -strlen(DIRECTORY_SEPARATOR.'@eaDir')) === DIRECTORY_SEPARATOR.'@eaDir') {
            continue;
        }

        $local_path = substr($real, $base_len);

        if ($fileinfo->isDir()) {
    // 폴더는 넣어도 되고(구조 유지), 안 넣어도 됩니다.
    if ($zip->addEmptyDir($local_path)) $added_count++;
} else {
    $file_size = @filesize($real);
    if ($file_size !== false) {
        $total_source_bytes += (int)$file_size;
    }

    if ($zip->addFile($real, $local_path)) {
        $added_count++;
        $file_added++;   // ✅ 파일이 1개라도 있으면 증가
    }
}
    }

    // ✅ ZIP 마무리 전에 여유 공간을 한 번 더 확인
    // 압축률이 낮은 파일도 있으므로 원본 용량의 약 1.5배 이상 여유 공간 권장
    $free_space = @disk_free_space($tmp_dir);
    if ($free_space !== false && $total_source_bytes > 0 && $free_space < ($total_source_bytes * 1.5)) {
        $zip->close();
        @unlink($tmp_zip_path);
        die("NAS 저장공간이 부족하여 ZIP 파일을 생성할 수 없습니다. 현재 여유공간: " . lk_human_filesize($free_space) . ", 필요 예상공간: " . lk_human_filesize($total_source_bytes * 1.5));
    }

    $close_result = $zip->close();
    if ($close_result !== true) {
        @unlink($tmp_zip_path);
        die("ZIP 압축 마무리 단계에서 실패했습니다. NAS 디스크 용량 또는 tmp 폴더 권한을 확인해주세요.");
    }

if ($file_added === 0) {
    @unlink($tmp_zip_path);

die("
<!doctype html>
<html lang='ko'>
<head>
  <meta charset='utf-8'>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <link rel='stylesheet' href='https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'>
  <style>
    body { margin:0; font-family:'Pretendard',sans-serif; background:#fff; }
    .wrap { min-height:100vh; display:flex; align-items:center; justify-content:center; }
    .box { text-align:center; padding:40px 20px; }
    .title { color:#006eb9; font-size:22px; font-weight:800; margin:0 0 10px; }
    .desc { color:#64748b; font-size:14px; line-height:1.6; margin:0; }
    .logo { margin-top:22px; display:flex; justify-content:center; }
    .logo img { max-width:180px; height:auto; }
  </style>
</head>
<body>
  <div class='wrap'>
    <div class='box'>
      <h1 class='title'>자료 업데이트 준비중입니다.</h1>
      <p class='desc'>
        빠른 시일 내에 자료를 제공해드리겠습니다.<br>
        감사합니다. Intelligent LK랩 일동 드림
      </p>
      <div class='logo'>
        <img src='/WebImage/logo.jpg' alt='Intelligent LK랩 로고'>
      </div>
    </div>
  </div>
</body>
</html>
");
}

    while (ob_get_level()) { @ob_end_clean(); }
    @ini_set('zlib.output_compression', 'Off');

    clearstatcache(true, $tmp_zip_path);
    $zip_size = @filesize($tmp_zip_path);
    if ($zip_size === false || $zip_size <= 0) {
        @unlink($tmp_zip_path);
        die("ZIP 파일 크기를 확인할 수 없습니다.");
    }
    $encoded_filename = rawurlencode($zip_filename);

    header('Content-Type: application/zip');
    header('Content-Disposition: attachment; filename="'.$zip_filename.'"; filename*=UTF-8\'\''.$encoded_filename);
    header('Content-Length: ' . $zip_size);
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('Pragma: no-cache');
    header('Expires: 0');

    $fp = fopen($tmp_zip_path, 'rb');
    if ($fp === false) {
        @unlink($tmp_zip_path);
        die("ZIP 파일을 열 수 없습니다.");
    }

    while (!feof($fp)) {
        echo fread($fp, 8192);
        flush();
    }

    fclose($fp);
    @unlink($tmp_zip_path);
    exit;
}
// ==========================================
$folder_title = $vroot_path ? basename($vroot_path) : "Intelligent LK랩 자료실";
?>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css">
    <style>
        :root { --primary: #006eb9; --bg: #ffffff; }
        /* body에 overflow: hidden을 주면 내용이 많아도 스크롤바가 안 생겨서 잘려 보일 수 있음. 
           auto로 변경하되, iframe 리사이징이 잘 되면 스크롤바는 어차피 안 생깁니다. */
        body { font-family: 'Pretendard', sans-serif; background: var(--bg); margin: 0; padding: 0; overflow-y: auto; }
        
        /* 높이를 내용물에 맞게 자동 조절 */
        .container { 
            width: 1000px; 
            margin: 0 auto; 
            background: white; 
            border: 1px solid #eeeeee; 
            border-radius: 8px; 
            box-sizing: border-box;
            height: auto; /* 중요: 높이 자동 */
            min-height: 90px; 
        }
        
        .header { background: var(--primary); padding: 12px 20px; color: white; display: flex; justify-content: space-between; align-items: center; }
        .header h1 { margin: 0; font-size: 15px; font-weight: 700; }
        
        .nav-info { font-size: 13px; font-weight: 700; opacity: 1; letter-spacing: -0.3px; color: #e0f2fe; }
        .nav-sep { opacity: 0.6; margin: 0 5px; font-weight: 400; font-size: 11px; }
        .nav-root { color: white; opacity: 1; }
        
        .item { display: flex; align-items: center; padding: 12px 20px; text-decoration: none; color: #1e293b; border-bottom: 1px solid #f8fafc; transition: 0.2s; }
        .item:hover { background: #f1f9ff; }
        .name { flex: 1; font-weight: 600; font-size: 14px; }
        .btn { padding: 5px 12px; border-radius: 4px; font-size: 11px; font-weight: 700; background: #f1f5f9; color: #64748b; border: 1px solid #e2e8f0; }
	.btn:hover {
  	background: var(--primary);
 	 color: white;
  	border-color: var(--primary);
	}
    .header-actions { display:flex; gap:8px; align-items:center; }

/* 폴더 옆 ZIP 버튼: 테마 컬러로 통일 + 밑줄 제거 */
a.btn,
a.btn:visited {
  text-decoration: none;
}
a.btn:hover {
  text-decoration: none;
}

/* 혹시 브라우저 기본 밑줄이 남는 경우 대비 */
a.btn { text-decoration: none; }

.zip-btn {
  padding: 7px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 700;
  background: rgba(255,255,255,0.15);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.35);
  cursor: pointer;
  text-decoration: none;
}
.zip-btn:hover { background: rgba(255,255,255,0.25); }
  </style>
</head>
<body>
    <div class="container" id="content_wrapper">
<div class="header">
    <h1><?php echo $folder_title; ?></h1>

    <div class="header-actions">
        <?php
            $v_param = $vroot_path ? "&vroot=".urlencode($vroot_path) : "";
            $zip_link = "?action=zip&dir=" . urlencode($rel_dir) . $v_param;
        ?>
        <div class="nav-info">
            <?php 
                $root_name = $is_locked ? "📚 Intelligence LK랩 전용 자료실" : "📂 전체 목록";
                if ($rel_dir) {
                    $display_path = str_replace('/', '<span class="nav-sep">/</span>', $rel_dir);
                    echo "<span class='nav-root'>" . $root_name . "</span> <span class='nav-sep'>/</span> " . $display_path;
                } else {
                    echo $root_name; 
                }
            ?>
        </div>
    </div>
</div>

        
        <div class="file-list">
            <?php
            if ($rel_dir) {
                $parent = dirname($rel_dir); if ($parent == '.') $parent = '';
                $v_param = $vroot_path ? "&vroot=".urlencode($vroot_path) : "";
                echo "<a href='?dir=".urlencode($parent).$v_param."' class='item'><div class='name' style='color:var(--primary)'>⤴ 상위 폴더로 이동</div><div class='btn'>뒤로</div></a>";
            }
            
            // 파일 스캔 및 권한 체크 강화
            $raw_items = @scandir($current_dir); // @로 에러 메시지 억제
            if ($raw_items === false) {
                 echo "<div style='padding:20px; color:red; text-align:center;'>폴더 권한을 확인해주세요. (File Station > 속성 > 권한 > http 읽기 허용)</div>";
            } else {
                $items = array_diff($raw_items, array('.', '..', 'index.php', '@eaDir', '.DS_Store', 'Thumbs.db', '#recycle'));
                natcasesort($items);
                
                foreach ($items as $item) {
                    if (class_exists('Normalizer')) { $item_display = Normalizer::normalize($item, Normalizer::FORM_C); } else { $item_display = $item; }

                    $is_dir = is_dir($current_dir . '/' . $item);
                    $path = $rel_dir ? $rel_dir . '/' . $item : $item;
                    $v_param = $vroot_path ? "&vroot=".urlencode($vroot_path) : "";
                    
                    if ($is_dir) {

    $open_link = "?dir=" . urlencode($path) . $v_param;
    $zip_link  = "?action=zip&dir=" . urlencode($path) . $v_param;

    // ✅ 루트(최상위)에서만 ZIP 버튼 표시
    $zip_btn_html = "";
    if ($rel_dir === "") {
        $zip_btn_html = "<a href='{$zip_link}' target='_blank' class='btn'>전체파일 ZIP 다운로드</a>";
    }

    echo "<div class='item'>
            <div class='name'>📁 $item_display</div>
            <div style='display:flex; gap:6px;'>
                {$zip_btn_html}
                <a href='{$open_link}' class='btn'>열기</a>
            </div>
          </div>";
}else {
                        $download_link = "?action=download&dir=".urlencode($rel_dir)."&file=".urlencode($item).$v_param;
                        echo "<a href='".$download_link."' class='item' target='_blank' rel='noopener'>
        <div class='name'>📄 $item_display</div><div class='btn'>다운로드</div>
      </a>";
                    }
                }
                if(count($items) == 0) echo "<div style='padding:40px; text-align:center; color:#94a3b8; font-size:12px;'>등록된 자료가 없습니다.</div>";
            }
            ?>
        </div>
    </div>

    <script>
        function sendHeight() {
            var wrapper = document.getElementById('content_wrapper');
            if(!wrapper) return;
            
            // 수정: scrollHeight를 사용하여 '숨겨진 영역'까지 포함한 전체 높이를 구함
            // +30px 여유 버퍼를 두어 하단 잘림 방지
            var height = wrapper.scrollHeight + 30; 
            
            window.parent.postMessage({ type: 'resize', height: height }, '*');
        }

        // 로드 시점, 리사이즈 시점, DOM 변경 시점 모두 체크
        window.addEventListener('load', function() {
            sendHeight();
            // 이미지/폰트 로딩 딜레이 고려하여 2번 더 실행
            setTimeout(sendHeight, 100);
            setTimeout(sendHeight, 500);
        });
        window.addEventListener('resize', sendHeight);
        
        var observer = new MutationObserver(sendHeight);
        observer.observe(document.body, { childList: true, subtree: true, attributes: true });
    </script>
</body>
</html>