๐ฅ
๐
๐ป
Z
U
๐f
(โฆ)
๐n
(โฆ)
โฐ
๐พS
๐ฅ
๐C
๐
๐
ฦ
yE
Fn
St
Fi
Hd
<?php // ํ์ผ โจ/var/www/html/y/yyy_used_files.php // ๋ฒ์ : v008 // ๋ชฉ์ : ์์ PHP/HTML/JS/JSX/TS/TSX 1๊ฐ ๊ธฐ์ค ์ฌ์ฉ ํ์ผ ๋ชฉ๋ก ์ถ์ถ + PHP include ๋ฐ JS/React import/require/๋์ import ์ถ์ + debug=1 ์์ธ ๋ก์ง ์ถ๋ ฅ define("_CMD_", true); include_once 'yyy_config_host.php'; include_once 'yyy_allowed_ips.php'; ini_set('display_errors', 1); error_reporting(E_ALL); $YUF_VERSION = 'v008'; $MAX_FILES = 3000; $MAX_READ_BYTES = 3 * 1024 * 1024; $YUF_DEBUG = (isset($_GET['debug']) && $_GET['debug'] == '1') ? 1 : 0; $YUF_DEBUG_LOG = array(); /* * ํ์ฉ ๊ฒฝ๋ก ์ค์ * - yyy_config_{host}.php ์์ $ALLOWED_ROOTS / $MANUAL_URL_MAP ์ ์ ์ํด๋ * ์ฌ๊ธฐ์ ๋ฎ์ด์ฐ์ง ์๊ณ ๊ธฐ๋ณธ๊ฐ๊ณผ ๋ณํฉํฉ๋๋ค. * - n.yjm.kr / home.yjm.kr ์ฒ๋ผ ์๋ฒ ๋ฃจํธ๊ฐ ๋ฌ๋ผ๋ ๊ณตํต ํ๋ก์ ํธ ๊ฒฝ๋ก๋ ํต๊ณผํฉ๋๋ค. * - ๋ณด์์ ์ํด '/' ์ ์ฒด ํ์ฉ์ ํ์ง ์์ต๋๋ค. ํ์ํ ์์ ํ๋ก์ ํธ ๋ฃจํธ๋ง ์ถ๊ฐํฉ๋๋ค. */ $YUF_CONFIG_ALLOWED_ROOTS = (isset($ALLOWED_ROOTS) && is_array($ALLOWED_ROOTS)) ? $ALLOWED_ROOTS : array(); $YUF_CONFIG_MANUAL_URL_MAP = (isset($MANUAL_URL_MAP) && is_array($MANUAL_URL_MAP)) ? $MANUAL_URL_MAP : array(); $YUF_CONFIG_JS_ALIAS_MAP = array(); if (isset($JS_IMPORT_ALIAS_MAP) && is_array($JS_IMPORT_ALIAS_MAP)) { $YUF_CONFIG_JS_ALIAS_MAP = array_merge($YUF_CONFIG_JS_ALIAS_MAP, $JS_IMPORT_ALIAS_MAP); } if (isset($YUF_JS_ALIAS_MAP) && is_array($YUF_JS_ALIAS_MAP)) { $YUF_CONFIG_JS_ALIAS_MAP = array_merge($YUF_CONFIG_JS_ALIAS_MAP, $YUF_JS_ALIAS_MAP); } $YUF_DEFAULT_ALLOWED_ROOTS = array( // common web roots '/var/www/html', '/var/www', '/data/php56-web/htdocs', '/data/www', // n.yjm.kr ๊ณ์ด '/data/git', '/data/_bak', '/data/yE', '/data/_py', '/ns8ext/www/jjy', // home.yjm.kr / WSL / Windows mount ๊ณ์ด '/mnt/d', '/mnt/d/wDrv', '/mnt/d/wDrv/__py', '/mnt/d/wDrv/__py/group', '/mnt/d/wDrv/__py/group/yjm_pmonit', '/mnt/c', // ๊ธฐํ ์๋ฒ์์ ์์ฃผ ์ฐ๋ ์น/์์ ๋ฃจํธ '/home', '/srv', '/www' ); $ALLOWED_ROOTS = array_values(array_unique(array_merge($YUF_DEFAULT_ALLOWED_ROOTS, $YUF_CONFIG_ALLOWED_ROOTS))); $YUF_DEFAULT_MANUAL_URL_MAP = array( '/y/' => __DIR__ . '/' ); $MANUAL_URL_MAP = array_merge($YUF_DEFAULT_MANUAL_URL_MAP, $YUF_CONFIG_MANUAL_URL_MAP); function yuf_strip_php_comments($text, $strip_hash_comments) { $text = (string)$text; $len = strlen($text); $out = ''; $quote = ''; $escaped = false; $line_has_content = false; for ($i = 0; $i < $len; $i++) { $ch = $text[$i]; $next = ($i + 1 < $len) ? $text[$i + 1] : ''; if ($quote !== '') { $out .= $ch; if ($ch === "\n" || $ch === "\r") $line_has_content = false; elseif ($ch !== ' ' && $ch !== "\t") $line_has_content = true; if ($escaped) { $escaped = false; } elseif ($ch === '\\') { $escaped = true; } elseif ($ch === $quote) { $quote = ''; } continue; } if ($ch === '"' || $ch === "'" || $ch === '`') { $quote = $ch; $out .= $ch; $line_has_content = true; continue; } if ($ch === '/' && $next === '/') { $i += 2; while ($i < $len && $text[$i] !== "\n" && $text[$i] !== "\r") $i++; if ($i < $len) { $out .= $text[$i]; $line_has_content = false; } continue; } if ($ch === '/' && $next === '*') { $i += 2; while ($i + 1 < $len && !($text[$i] === '*' && $text[$i + 1] === '/')) { if ($text[$i] === "\n" || $text[$i] === "\r") { $out .= $text[$i]; $line_has_content = false; } $i++; } $i++; continue; } if ($strip_hash_comments && !$line_has_content && $ch === '#') { while ($i < $len && $text[$i] !== "\n" && $text[$i] !== "\r") $i++; if ($i < $len) { $out .= $text[$i]; $line_has_content = false; } continue; } $out .= $ch; if ($ch === "\n" || $ch === "\r") $line_has_content = false; elseif ($ch !== ' ' && $ch !== "\t") $line_has_content = true; } return $out; } function yuf_dbg($msg) { global $YUF_DEBUG, $YUF_DEBUG_LOG; if (!$YUF_DEBUG) return; $YUF_DEBUG_LOG[] = '[' . date('H:i:s') . '] ' . (string)$msg; } function yuf_h($s) { $s = (string)$s; $s = htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); $s = str_replace('&', '&', $s); return $s; } function yuf_fail($msg) { header('Content-Type: text/html; charset=utf-8'); echo '<h3>ERROR</h3><pre>' . yuf_h($msg) . '</pre>'; exit; } function yuf_norm_slash($s) { return str_replace('\\', '/', (string)$s); } function yuf_clean_path($path) { $path = yuf_norm_slash($path); $is_abs = (strlen($path) > 0 && $path[0] === '/'); $parts = explode('/', $path); $out = array(); foreach ($parts as $p) { if ($p === '' || $p === '.') continue; if ($p === '..') { array_pop($out); continue; } $out[] = $p; } return ($is_abs ? '/' : '') . implode('/', $out); } function yuf_remove_qf($u) { return preg_replace('/[#?].*$/', '', (string)$u); } function yuf_is_skip_url($u) { $u = trim((string)$u); if ($u === '') return true; if ($u[0] === '#') return true; if (preg_match('/^(javascript|mailto|tel|data|blob|chrome|about):/i', $u)) return true; return false; } function yuf_under_allowed_root($path, $roots) { $path = yuf_norm_slash($path); foreach ($roots as $root) { $root = rtrim(yuf_norm_slash($root), '/'); if ($root !== '' && strpos($path . '/', $root . '/') === 0) return true; } return false; } function yuf_allowed_fail_detail($path, $roots) { $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''; $script = isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['SCRIPT_FILENAME'] : ''; $docroot = isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : ''; return 'ํ์ฉ ๊ฒฝ๋ก ๋ฐ์ ๋๋ค: ' . $path . "\n\nํ์ฌ ALLOWED_ROOTS:\n" . print_r($roots, true) . "\nSCRIPT_FILENAME: " . $script . "\nDOCUMENT_ROOT: " . $docroot . "\nHTTP_HOST: " . $host; } function yuf_url_dir($url_path) { $d = dirname($url_path); if ($d === '\\' || $d === '.') $d = '/'; $d = rtrim(yuf_norm_slash($d), '/') . '/'; if ($d === '//') $d = '/'; return $d; } function yuf_file_dir($file) { return rtrim(yuf_norm_slash(dirname($file)), '/') . '/'; } function yuf_ext($file) { $p = pathinfo($file); return isset($p['extension']) ? strtolower($p['extension']) : ''; } function yuf_kind($file) { $ext = yuf_ext($file); if ($ext === 'php' || $ext === 'phtml' || $ext === 'inc') return 'php'; if (in_array($ext, array('js','mjs','cjs','jsx','ts','tsx','mts','cts'), true)) return 'js'; if (in_array($ext, array('css','scss','sass','less'), true)) return 'css'; if (in_array($ext, array('png','jpg','jpeg','gif','webp','avif','svg','ico'), true)) return 'img'; if (in_array($ext, array('woff','woff2','ttf','otf','eot'), true)) return 'font'; return $ext ? $ext : 'etc'; } function yuf_is_parse_file($file) { $ext = yuf_ext($file); return in_array($ext, array( 'php','phtml','html','htm','inc', 'js','mjs','cjs','jsx','ts','tsx','mts','cts', 'css','scss','sass','less', 'json','txt' ), true); } function yuf_is_js_module_ref_type($type) { return in_array((string)$type, array( 'js_import', 'js_export', 'js_dynamic_import', 'js_require', 'js_new_url', 'js_worker', 'js_import_scripts' ), true); } function yuf_is_js_package_ref_type($type) { return in_array((string)$type, array( 'js_import', 'js_export', 'js_dynamic_import', 'js_require' ), true); } function yuf_resolve_existing_local_path($path) { $path = yuf_clean_path($path); if (is_file($path)) { $real = realpath($path); return $real !== false ? yuf_norm_slash($real) : $path; } $ext = yuf_ext($path); $try_exts = array('js','jsx','ts','tsx','mts','cts','mjs','cjs','json','css','scss','sass','less'); $candidates = array(); if ($ext === '') { foreach ($try_exts as $one_ext) { $candidates[] = $path . '.' . $one_ext; } } if (is_dir($path) || $ext === '') { $dir = rtrim($path, '/'); foreach ($try_exts as $one_ext) { $candidates[] = $dir . '/index.' . $one_ext; } } foreach ($candidates as $candidate) { if (!is_file($candidate)) continue; $real = realpath($candidate); return $real !== false ? yuf_norm_slash($real) : yuf_clean_path($candidate); } return $path; } function yuf_find_up_file($start_file, $names) { $dir = is_dir($start_file) ? $start_file : dirname($start_file); $dir = yuf_clean_path($dir); while ($dir !== '' && $dir !== '/' && $dir !== '.') { foreach ($names as $name) { $candidate = rtrim($dir, '/') . '/' . $name; if (is_file($candidate)) return yuf_norm_slash($candidate); } $parent = dirname($dir); if ($parent === $dir) break; $dir = yuf_clean_path($parent); } return false; } function yuf_find_project_root($start_file) { $package_file = yuf_find_up_file($start_file, array('package.json')); if ($package_file !== false) return yuf_clean_path(dirname($package_file)); return yuf_clean_path(dirname($start_file)); } function yuf_strip_json_comments($text) { $text = (string)$text; $len = strlen($text); $out = ''; $in_string = false; $escaped = false; for ($i = 0; $i < $len; $i++) { $ch = $text[$i]; $next = ($i + 1 < $len) ? $text[$i + 1] : ''; if ($in_string) { $out .= $ch; if ($escaped) { $escaped = false; } elseif ($ch === '\\') { $escaped = true; } elseif ($ch === '"') { $in_string = false; } continue; } if ($ch === '"') { $in_string = true; $out .= $ch; continue; } if ($ch === '/' && $next === '/') { $i += 2; while ($i < $len && $text[$i] !== "\n" && $text[$i] !== "\r") $i++; if ($i < $len) $out .= $text[$i]; continue; } if ($ch === '/' && $next === '*') { $i += 2; while ($i + 1 < $len && !($text[$i] === '*' && $text[$i + 1] === '/')) $i++; $i++; continue; } $out .= $ch; } return $out; } function yuf_json_decode_loose($file) { $text = yuf_read_file($file, 1024 * 1024); if ($text === false) return false; $text = yuf_strip_json_comments($text); $text = preg_replace('/,\s*([}\]])/', '$1', $text); $data = json_decode($text, true); return is_array($data) ? $data : false; } function yuf_add_js_alias(&$aliases, $pattern, $target, $source, $base_dir) { $pattern = trim((string)$pattern); $target = trim((string)$target); if ($pattern === '' || $target === '') return; $target = yuf_norm_slash($target); if ($target[0] !== '/' && !preg_match('/^[A-Za-z]:\//', $target)) { $target = yuf_clean_path(rtrim($base_dir, '/') . '/' . $target); } else { $target = yuf_clean_path($target); } foreach ($aliases as $old) { if ($old['pattern'] === $pattern) return; } $aliases[] = array( 'pattern' => $pattern, 'target' => $target, 'source' => (string)$source ); } function yuf_build_js_aliases($start_file, $configured) { $aliases = array(); $project_root = yuf_find_project_root($start_file); if (is_array($configured)) { foreach ($configured as $pattern => $target) { if (is_array($target)) $target = count($target) ? reset($target) : ''; yuf_add_js_alias($aliases, $pattern, $target, 'config', $project_root); } } $js_config = yuf_find_up_file($start_file, array('tsconfig.json', 'jsconfig.json')); if ($js_config !== false) { $data = yuf_json_decode_loose($js_config); if (is_array($data)) { $compiler = isset($data['compilerOptions']) && is_array($data['compilerOptions']) ? $data['compilerOptions'] : array(); $config_dir = yuf_clean_path(dirname($js_config)); $base_url = isset($compiler['baseUrl']) ? trim((string)$compiler['baseUrl']) : '.'; $base_dir = yuf_clean_path($config_dir . '/' . $base_url); $paths = isset($compiler['paths']) && is_array($compiler['paths']) ? $compiler['paths'] : array(); foreach ($paths as $pattern => $targets) { if (is_array($targets)) $target = count($targets) ? reset($targets) : ''; else $target = $targets; yuf_add_js_alias($aliases, $pattern, $target, basename($js_config), $base_dir); } } } $src_dir = yuf_clean_path($project_root . '/src'); if (is_dir($src_dir)) { yuf_add_js_alias($aliases, '@/', $src_dir . '/', 'auto-src', $project_root); yuf_add_js_alias($aliases, '~/', $src_dir . '/', 'auto-src', $project_root); } usort($aliases, function($a, $b) { return strlen($b['pattern']) - strlen($a['pattern']); }); foreach ($aliases as $alias) { yuf_dbg('JS_ALIAS ' . $alias['pattern'] . ' => ' . $alias['target'] . ' [' . $alias['source'] . ']'); } return $aliases; } function yuf_resolve_js_alias($raw, $aliases) { $raw = yuf_remove_qf(trim((string)$raw)); foreach ($aliases as $alias) { $pattern = $alias['pattern']; $target = $alias['target']; $star_pos = strpos($pattern, '*'); if ($star_pos !== false) { $prefix = substr($pattern, 0, $star_pos); $suffix = substr($pattern, $star_pos + 1); if (strpos($raw, $prefix) !== 0) continue; if ($suffix !== '' && substr($raw, -strlen($suffix)) !== $suffix) continue; $middle_len = strlen($raw) - strlen($prefix) - strlen($suffix); if ($middle_len < 0) continue; $middle = substr($raw, strlen($prefix), $middle_len); $resolved = str_replace('*', $middle, $target); return yuf_resolve_existing_local_path($resolved); } if (substr($pattern, -1) === '/') { if (strpos($raw, $pattern) !== 0) continue; $resolved = rtrim($target, '/') . '/' . substr($raw, strlen($pattern)); return yuf_resolve_existing_local_path($resolved); } if ($raw === $pattern) { return yuf_resolve_existing_local_path($target); } } return false; } function yuf_resolve_js_alias_pattern($raw, $aliases) { $raw = trim((string)$raw); foreach ($aliases as $alias) { $pattern = $alias['pattern']; $target = $alias['target']; $star_pos = strpos($pattern, '*'); if ($star_pos !== false) { $prefix = substr($pattern, 0, $star_pos); $suffix = substr($pattern, $star_pos + 1); if (strpos($raw, $prefix) !== 0) continue; if ($suffix !== '' && substr($raw, -strlen($suffix)) !== $suffix) continue; $middle_len = strlen($raw) - strlen($prefix) - strlen($suffix); if ($middle_len < 0) continue; $middle = substr($raw, strlen($prefix), $middle_len); return yuf_clean_path(str_replace('*', $middle, $target)); } if (substr($pattern, -1) === '/' && strpos($raw, $pattern) === 0) { return yuf_clean_path(rtrim($target, '/') . '/' . substr($raw, strlen($pattern))); } } return false; } function yuf_glob_regex($pattern) { $pattern = yuf_norm_slash($pattern); $len = strlen($pattern); $regex = ''; for ($i = 0; $i < $len; $i++) { $ch = $pattern[$i]; if ($ch === '*') { if ($i + 1 < $len && $pattern[$i + 1] === '*') { $i++; if ($i + 1 < $len && $pattern[$i + 1] === '/') { $i++; $regex .= '(?:.*/)?'; } else { $regex .= '.*'; } } else { $regex .= '[^/]*'; } continue; } if ($ch === '?') { $regex .= '[^/]'; continue; } if ($ch === '{') { $end = strpos($pattern, '}', $i + 1); if ($end !== false) { $parts = explode(',', substr($pattern, $i + 1, $end - $i - 1)); $escaped_parts = array(); foreach ($parts as $part) $escaped_parts[] = preg_quote($part, '#'); $regex .= '(?:' . implode('|', $escaped_parts) . ')'; $i = $end; continue; } } $regex .= preg_quote($ch, '#'); } return '#^' . $regex . '$#'; } function yuf_expand_js_glob($raw, $base_file, $js_aliases, $max_matches) { $raw = trim((string)$raw); if ($raw === '' || $raw[0] === '!') return array(); $pattern = yuf_resolve_js_alias_pattern($raw, $js_aliases); if ($pattern === false) { if (strpos($raw, './') === 0 || strpos($raw, '../') === 0) { $pattern = yuf_clean_path(yuf_file_dir($base_file) . $raw); } else { return array(); } } $wild_pos = strcspn($pattern, '*?{['); $fixed = substr($pattern, 0, $wild_pos); $root = is_dir($fixed) ? $fixed : dirname($fixed); while ($root !== '' && $root !== '/' && !is_dir($root)) { $parent = dirname($root); if ($parent === $root) break; $root = $parent; } if (!is_dir($root)) return array(); $regex = yuf_glob_regex($pattern); $matches = array(); try { $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ($it as $info) { if (!$info->isFile()) continue; $file = yuf_norm_slash($info->getPathname()); if (!preg_match($regex, $file)) continue; $matches[$file] = $file; if (count($matches) >= $max_matches) break; } } catch (Exception $e) { yuf_dbg('JS_GLOB_ERROR pattern=' . $pattern . ' error=' . $e->getMessage()); return array(); } ksort($matches); yuf_dbg('JS_GLOB pattern=' . $raw . ' resolved=' . $pattern . ' matches=' . count($matches)); return array_values($matches); } function yuf_is_bare_js_specifier($raw) { $raw = yuf_remove_qf(trim((string)$raw)); if ($raw === '') return false; if (strpos($raw, './') === 0 || strpos($raw, '../') === 0) return false; if ($raw[0] === '/' || $raw[0] === '\\') return false; if (preg_match('/^[A-Za-z]:\//', $raw)) return false; if (preg_match('#^(?:https?:)?//#i', $raw)) return false; if (preg_match('/^[a-z][a-z0-9+.-]*:/i', $raw)) { return preg_match('/^(node|virtual):/i', $raw) ? true : false; } return true; } function yuf_read_file($file, $max_bytes) { if (!is_file($file)) return false; $size = filesize($file); if ($size === false) return false; if ($size > $max_bytes) return false; return file_get_contents($file); } function yuf_strip_excluded($text) { $text = preg_replace('/yyy-used-files-exclude:start.*?yyy-used-files-exclude:end/is', '', $text); $text = preg_replace('/<!--\s*yyy_used_files\s*=\s*no\s*-->.*?<!--\s*\/yyy_used_files\s*-->/is', '', $text); $text = preg_replace('/\/\*\s*yyy_used_files\s*=\s*no\s*\*\/.*?\/\*\s*\/yyy_used_files\s*\*\//is', '', $text); $text = preg_replace('/\/\/\s*yyy_used_files\s*=\s*no.*$/im', '', $text); $text = preg_replace('/^.*yyy_used_files\s*=\s*no.*$/im', '', $text); return $text; } function yuf_source_line($text, $offset) { $text = (string)$text; $offset = intval($offset); if ($offset < 0) $offset = 0; if ($offset > strlen($text)) $offset = strlen($text); $before = substr($text, 0, $offset); $line_no = substr_count($before, "\n") + 1; $line_start = strrpos($before, "\n"); $line_start = ($line_start === false) ? 0 : $line_start + 1; $line_end = strpos($text, "\n", $offset); if ($line_end === false) $line_end = strlen($text); $line = trim(substr($text, $line_start, $line_end - $line_start)); if (strlen($line) > 500) $line = substr($line, 0, 500) . '...'; return 'L' . $line_no . ': ' . $line; } function yuf_add_hit(&$hits, $type, $raw, $from_file, $from_url, $source_line = '') { $raw = trim((string)$raw); if ($raw === '') return; if (strpos($raw, 'yyy_used_files=no') !== false) return; /* * script/link ๊ฒฝ๋ก ๋ค ์ฟผ๋ฆฌ์คํธ๋ง์ <?=...?> ๊ฐ์ PHP ์ถ๋ ฅ ํ๊ทธ๊ฐ ๋ถ์ผ๋ฉด * ๊ธฐ์กด ๋ก์ง์ <, > ๊ฒ์ฌ ๋๋ฌธ์ JS/CSS ํ์ผ ๊ฒฝ๋ก๊น์ง ํต์งธ๋ก ๋ฒ๋ ธ์ต๋๋ค. * ํ์ผ ์ถ์ ์๋ ?/# ์์ ์ค์ ๊ฒฝ๋ก๋ง ํ์ํ๋ฏ๋ก ๋จผ์ ์ ๊ฑฐํ ๊ฐ์ผ๋ก ๊ฒ์ฆ/์ ์ฅํฉ๋๋ค. */ $raw_path = ($type === 'js_glob') ? trim($raw) : trim(yuf_remove_qf($raw)); if ($raw_path === '') return; if ($raw_path === '\\') return; if (strpos($raw_path, '<') !== false || strpos($raw_path, '>') !== false) return; if (preg_match('/\s/', $raw_path) && !preg_match('/^https?:\/\//i', $raw_path)) return; yuf_dbg('HIT type=' . $type . ' raw=' . $raw_path . ' from=' . $from_file . ' source=' . $source_line); $hits[] = array( 'type' => $type, 'raw' => $raw_path, 'raw_original' => $raw, 'from_file' => $from_file, 'from_url' => $from_url, 'source' => trim((string)$source_line) ); } function yuf_eval_php_path_expr($expr, $from_file) { $orig = trim((string)$expr); $expr = $orig; $expr = preg_replace('/\s*;.*$/s', '', $expr); $expr = preg_replace('/^\s*\(\s*/', '', $expr); $expr = preg_replace('/\s*\)\s*$/', '', $expr); $expr = trim($expr); $dir = rtrim(yuf_norm_slash(dirname($from_file)), '/'); $file = yuf_norm_slash($from_file); yuf_dbg('PHP_INCLUDE_EXPR_ORIG: ' . $orig); yuf_dbg('PHP_INCLUDE_EXPR_FROM: ' . $from_file); yuf_dbg('PHP_INCLUDE_EXPR_DIR: ' . $dir); if (strpos($expr, '__DIR__') !== false) { $expr = str_replace('__DIR__', "'" . str_replace("'", "\\'", $dir) . "'", $expr); } if (stripos($expr, 'dirname(__FILE__)') !== false) { $expr = preg_replace('/dirname\s*\(\s*__FILE__\s*\)/i', "'" . str_replace("'", "\\'", $dir) . "'", $expr); } if (strpos($expr, '__FILE__') !== false) { $expr = str_replace('__FILE__', "'" . str_replace("'", "\\'", $file) . "'", $expr); } yuf_dbg('PHP_INCLUDE_EXPR_AFTER_CONST: ' . $expr); if (!preg_match_all('/["\']([^"\']*)["\']/', $expr, $m)) { yuf_dbg('PHP_INCLUDE_EXPR_NO_STRING_PART: ' . $expr); return false; } $out = ''; foreach ($m[1] as $part) { $out .= stripcslashes($part); yuf_dbg('PHP_INCLUDE_EXPR_PART_OK: ' . $part); } if ($out === '') { yuf_dbg('PHP_INCLUDE_EXPR_RESULT_FAIL_EMPTY'); return false; } if ($out[0] !== '/') { $out = yuf_file_dir($from_file) . $out; } $out = yuf_clean_path($out); yuf_dbg('PHP_INCLUDE_EXPR_RESULT: ' . $out); return $out; } function yuf_extract_php_include_exprs(&$hits, $text, $from_file, $from_url) { if (!preg_match_all('/\b(include|include_once|require|require_once)\b\s*(?:\(\s*)?(.+?)\s*\)?\s*;/is', $text, $m, PREG_SET_ORDER)) { yuf_dbg('PHP_INCLUDE_EXPR_NONE from=' . $from_file); return; } foreach ($m as $one) { $cmd = isset($one[1]) ? $one[1] : ''; $expr = isset($one[2]) ? trim($one[2]) : ''; if ($expr === '') continue; yuf_dbg('PHP_INCLUDE_FOUND cmd=' . $cmd . ' expr=' . $expr . ' from=' . $from_file); $path = yuf_eval_php_path_expr($expr, $from_file); if ($path === false) { yuf_dbg('PHP_INCLUDE_EVAL_FAIL expr=' . $expr); continue; } yuf_add_hit($hits, 'php_include_expr', $path, $from_file, $from_url, 'include expr: ' . $expr); } } function yuf_extract_refs($text, $from_file, $from_url) { $hits = array(); $from_ext = yuf_ext($from_file); $text = yuf_strip_excluded($text); $text = yuf_strip_php_comments($text, in_array($from_ext, array('php','phtml','inc'), true)); if (in_array($from_ext, array('php','phtml','inc'), true)) { yuf_extract_php_include_exprs($hits, $text, $from_file, $from_url); } if (preg_match_all('/<[^>]*\b(?:src|href|poster|data-src|data-href)\s*=\s*["\']([^"\']+)["\']/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'html_attr', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/<[^>]*\b(?:src|href|poster|data-src|data-href)\s*=\s*([^\s"\'<>]+)/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'html_attr_unquoted', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\burl\s*\(\s*([\'\"]?)(.*?)\1\s*\)/', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'css_url', $one[2][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/@import\s+(?:url\s*\(\s*)?[\'\"]?([^\'\"\);]+)[\'\"]?\s*\)?/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'css_import', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\bimport\s+(?!\s*\()(?:(?:type\s+)?[\w$*{},\s]+?\s+from\s+)?[\'\"]([^\'\"]+)[\'\"]/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'js_import', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\bexport\s+(?:type\s+)?(?:\*(?:\s+as\s+[\w$]+)?|\{[^}]*\})\s+from\s+[\'\"]([^\'\"]+)[\'\"]/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'js_export', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\bimport\s*\(\s*[\'\"]([^\'\"]+)[\'\"]/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'js_dynamic_import', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\brequire(?:\.resolve)?\s*\(\s*[\'\"]([^\'\"]+)[\'\"]/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'js_require', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\bnew\s+URL\s*\(\s*[\'\"]([^\'\"]+)[\'\"]\s*,\s*import\.meta\.url/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'js_new_url', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\bnew\s+(?:Shared)?Worker\s*\(\s*[\'\"]([^\'\"]+)[\'\"]/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'js_worker', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } if (preg_match_all('/\bimportScripts\s*\((.*?)\)/is', $text, $calls, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($calls as $call) { if (!preg_match_all('/[\'\"]([^\'\"]+)[\'\"]/', $call[1][0], $args, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) continue; foreach ($args as $arg) { $offset = $call[1][1] + $arg[0][1]; yuf_add_hit($hits, 'js_import_scripts', $arg[1][0], $from_file, $from_url, yuf_source_line($text, $offset)); } } } if (preg_match_all('/\bimport\.meta\.glob(?:Eager)?\s*\(\s*([\'\"])(.*?)\1/is', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) { yuf_add_hit($hits, 'js_glob', $one[2][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); $last = count($hits) - 1; if ($last >= 0 && $hits[$last]['type'] === 'js_glob') $hits[$last]['glob_group'] = 'glob@' . $one[0][1]; } } if (preg_match_all('/\bimport\.meta\.glob(?:Eager)?\s*\(\s*\[(.*?)\]/is', $text, $calls, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($calls as $call) { if (!preg_match_all('/([\'\"])(.*?)\1/', $call[1][0], $args, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) continue; $glob_group = 'glob@' . $call[0][1]; foreach ($args as $arg) { $offset = $call[1][1] + $arg[0][1]; yuf_add_hit($hits, 'js_glob', $arg[2][0], $from_file, $from_url, yuf_source_line($text, $offset)); $last = count($hits) - 1; if ($last >= 0 && $hits[$last]['type'] === 'js_glob') $hits[$last]['glob_group'] = $glob_group; } } } if (preg_match_all('/\b(?:fetch|register)\s*\(\s*[\'\"]([^\'\"]+)[\'\"]/i', $text, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { foreach ($m as $one) yuf_add_hit($hits, 'js_runtime_url', $one[1][0], $from_file, $from_url, yuf_source_line($text, $one[0][1])); } /* old php_include parser disabled */ return $hits; } function yuf_build_maps($start_file, $start_url, $manual_map) { $maps = array(); foreach ($manual_map as $url_prefix => $disk_prefix) { $url_prefix = '/' . trim(yuf_norm_slash($url_prefix), '/') . '/'; if ($url_prefix === '//') $url_prefix = '/'; $maps[$url_prefix] = rtrim(yuf_norm_slash($disk_prefix), '/') . '/'; } $p = parse_url($start_url); $start_path = isset($p['path']) ? $p['path'] : '/'; $start_url_dir = yuf_url_dir($start_path); $start_file_dir = yuf_file_dir($start_file); if (!isset($maps[$start_url_dir])) $maps[$start_url_dir] = $start_file_dir; /* * ์์ URL์ด /api/ns/n_moni01.php ์ด๋ฉด /api/ns/ ๋ฟ ์๋๋ผ * /api/ => /var/www/html/api/, / => /var/www/html/ ๋ ๊ฐ์ด ์์ธก ๋งคํํฉ๋๋ค. * ๊ทธ๋์ผ ๊ฐ์ ํ์ด์ง ์์ /api/__/..., /api/firebase-messaging-sw.js ๊ฐ์ ์ ๋ URL๋ ๋๋ฝ์ผ๋ก ์คํํ์ง ์์ต๋๋ค. */ $u_parts = explode('/', trim($start_url_dir, '/')); $f_dir = rtrim($start_file_dir, '/'); while (count($u_parts) > 0) { array_pop($u_parts); $f_dir = dirname($f_dir); $u_prefix = '/' . implode('/', $u_parts) . '/'; if ($u_prefix === '//') $u_prefix = '/'; if (!isset($maps[$u_prefix])) $maps[$u_prefix] = rtrim(yuf_norm_slash($f_dir), '/') . '/'; } if (isset($_SERVER['DOCUMENT_ROOT']) && $_SERVER['DOCUMENT_ROOT'] !== '') { if (!isset($maps['/'])) $maps['/'] = rtrim(yuf_norm_slash($_SERVER['DOCUMENT_ROOT']), '/') . '/'; } uksort($maps, function($a, $b) { return strlen($b) - strlen($a); }); foreach ($maps as $u => $d) yuf_dbg('MAP ' . $u . ' => ' . $d); return $maps; } function yuf_url_to_file($raw, $base_url, $base_file, $host, $maps, $roots, $ref_type, $js_aliases) { $raw0 = trim((string)$raw); $raw = yuf_remove_qf($raw0); yuf_dbg('RESOLVE raw=' . $raw0 . ' base_file=' . $base_file . ' base_url=' . $base_url . ' type=' . $ref_type); if (yuf_is_js_module_ref_type($ref_type)) { $alias_file = yuf_resolve_js_alias($raw, $js_aliases); if ($alias_file !== false) { yuf_dbg('RESOLVE_JS_ALIAS ' . $raw . ' => ' . $alias_file); return array('kind' => 'local', 'raw' => $raw0, 'file' => $alias_file, 'url_path' => ''); } if (yuf_is_js_package_ref_type($ref_type) && yuf_is_bare_js_specifier($raw)) { yuf_dbg('RESOLVE_JS_PACKAGE raw=' . $raw0); return array('kind' => 'package', 'raw' => $raw0, 'package' => $raw); } } if (yuf_is_skip_url($raw)) { yuf_dbg('RESOLVE_SKIP raw=' . $raw0); return array('kind' => 'skip', 'raw' => $raw0); } if (preg_match('/^\/\//', $raw)) { yuf_dbg('RESOLVE_EXTERNAL_PROTOCOL_RELATIVE raw=' . $raw0); return array('kind' => 'external', 'raw' => $raw0); } if (strlen($raw) > 0 && $raw[0] === '/') { if (preg_match('#^/(var|data|home|mnt|opt|usr|etc)/#', $raw)) { $direct = realpath($raw); if ($direct !== false && is_file($direct) && yuf_under_allowed_root($direct, $roots)) { yuf_dbg('RESOLVE_REAL_ABS_FILE_OK ' . $raw . ' => ' . yuf_norm_slash($direct)); return array( 'kind' => 'local', 'raw' => $raw0, 'file' => yuf_norm_slash($direct), 'url_path' => '' ); } yuf_dbg('RESOLVE_REAL_ABS_FILE_FAIL ' . $raw); return array( 'kind' => 'local', 'raw' => $raw0, 'file' => yuf_clean_path($raw), 'url_path' => '' ); } } if (preg_match('/^https?:\/\//i', $raw)) { $p = parse_url($raw); if (!is_array($p)) return array('kind' => 'skip', 'raw' => $raw0); if (isset($p['host']) && strtolower($p['host']) !== strtolower($host)) { yuf_dbg('RESOLVE_EXTERNAL_HOST raw=' . $raw0); return array('kind' => 'external', 'raw' => $raw0); } $path = isset($p['path']) ? $p['path'] : ''; if ($path === '') return array('kind' => 'skip', 'raw' => $raw0); foreach ($maps as $url_prefix => $disk_prefix) { if (strpos($path, $url_prefix) === 0) { $rel = substr($path, strlen($url_prefix)); $file = yuf_clean_path($disk_prefix . $rel); if (yuf_is_js_module_ref_type($ref_type)) $file = yuf_resolve_existing_local_path($file); yuf_dbg('RESOLVE_URL_MAP ' . $path . ' => ' . $file); return array('kind' => 'local', 'raw' => $raw0, 'file' => $file, 'url_path' => $path); } } yuf_dbg('RESOLVE_MISSING_MAP path=' . $path); return array('kind' => 'missing_map', 'raw' => $raw0, 'url_path' => $path); } if (strlen($raw) > 0 && $raw[0] === '/') { $path = yuf_clean_path($raw); foreach ($maps as $url_prefix => $disk_prefix) { if (strpos($path, $url_prefix) === 0) { $rel = substr($path, strlen($url_prefix)); $file = yuf_clean_path($disk_prefix . $rel); if (yuf_is_js_module_ref_type($ref_type)) $file = yuf_resolve_existing_local_path($file); yuf_dbg('RESOLVE_ROOT_URL_MAP ' . $path . ' => ' . $file); return array('kind' => 'local', 'raw' => $raw0, 'file' => $file, 'url_path' => $path); } } yuf_dbg('RESOLVE_ROOT_MISSING_MAP path=' . $path); return array('kind' => 'missing_map', 'raw' => $raw0, 'url_path' => $path); } $file = yuf_clean_path(yuf_file_dir($base_file) . $raw); if (yuf_is_js_module_ref_type($ref_type)) $file = yuf_resolve_existing_local_path($file); yuf_dbg('RESOLVE_REL ' . $raw . ' => ' . $file); return array('kind' => 'local', 'raw' => $raw0, 'file' => $file, 'url_path' => ''); } function yuf_file_to_url_guess($file, $maps, $host, $scheme) { $file = yuf_norm_slash($file); foreach ($maps as $url_prefix => $disk_prefix) { $disk_prefix = rtrim(yuf_norm_slash($disk_prefix), '/') . '/'; if (strpos($file . '/', $disk_prefix) === 0) { $rel = substr($file, strlen($disk_prefix)); return $scheme . '://' . $host . rtrim($url_prefix, '/') . '/' . ltrim($rel, '/'); } } return ''; } function yuf_scan($start_file, $start_url, $roots, $manual_map, $max_files, $max_read_bytes) { $p = parse_url($start_url); if (!is_array($p) || !isset($p['host'])) yuf_fail('url ๊ฐ์ ๋ฐ๋์ https://๋๋ฉ์ธ/๊ฒฝ๋ก ํํ์ฌ์ผ ํฉ๋๋ค.'); $host = $p['host']; $scheme = isset($p['scheme']) ? $p['scheme'] : 'https'; yuf_dbg('SCAN_START file=' . $start_file . ' url=' . $start_url); $real_start = realpath(yuf_norm_slash($start_file)); if ($real_start === false || !is_file($real_start)) yuf_fail('์์ ํ์ผ์ด ์์ต๋๋ค: ' . $start_file); $real_start = yuf_norm_slash($real_start); if (!yuf_under_allowed_root($real_start, $roots)) yuf_fail(yuf_allowed_fail_detail($real_start, $roots)); $maps = yuf_build_maps($real_start, $start_url, $manual_map); $js_aliases = yuf_build_js_aliases($real_start, $GLOBALS['YUF_CONFIG_JS_ALIAS_MAP']); $queue = array(array('file' => $real_start, 'url' => $start_url, 'via' => 'start', 'from' => '')); $visited = array(); $files = array(); $missing = array(); $external = array(); $packages = array(); $skipped = array(); while (count($queue) > 0) { if (count($visited) >= $max_files) break; $cur = array_shift($queue); $file = yuf_norm_slash($cur['file']); $real = realpath($file); yuf_dbg('QUEUE_POP file=' . $file . ' via=' . (isset($cur['via']) ? $cur['via'] : '') . ' from=' . (isset($cur['from']) ? $cur['from'] : '')); if ($real === false || !is_file($real)) { yuf_dbg('QUEUE_MISSING file=' . $file); $missing[$file] = array('file' => $file, 'from' => isset($cur['from']) ? $cur['from'] : '', 'via' => isset($cur['via']) ? $cur['via'] : '', 'raw' => '', 'source' => ''); continue; } $real = yuf_norm_slash($real); if (isset($visited[$real])) { yuf_dbg('QUEUE_ALREADY_VISITED file=' . $real); continue; } if (!yuf_under_allowed_root($real, $roots)) { yuf_dbg('QUEUE_OUTSIDE_ROOT file=' . $real); $skipped[$real] = array('reason' => 'outside_allowed_root', 'from' => isset($cur['from']) ? $cur['from'] : ''); continue; } $visited[$real] = 1; $guess_url = isset($cur['url']) && $cur['url'] !== '' ? $cur['url'] : yuf_file_to_url_guess($real, $maps, $host, $scheme); $files[$real] = array( 'file' => $real, 'url' => $guess_url, 'ext' => yuf_ext($real), 'kind' => yuf_kind($real), 'via' => isset($cur['via']) ? $cur['via'] : '', 'from' => isset($cur['from']) ? $cur['from'] : '' ); yuf_dbg('FILE_ADD file=' . $real . ' url=' . $guess_url); if (!yuf_is_parse_file($real)) { yuf_dbg('PARSE_SKIP_NOT_PARSE_FILE file=' . $real); continue; } $text = yuf_read_file($real, $max_read_bytes); if ($text === false) { yuf_dbg('READ_FAIL_OR_TOO_LARGE file=' . $real); $skipped[$real] = array('reason' => 'read_failed_or_too_large', 'from' => ''); continue; } $refs = yuf_extract_refs($text, $real, $guess_url); yuf_dbg('REF_COUNT file=' . $real . ' count=' . count($refs)); $glob_excludes = array(); foreach ($refs as $glob_ref) { if ($glob_ref['type'] !== 'js_glob') continue; if (!isset($glob_ref['raw'][0]) || $glob_ref['raw'][0] !== '!') continue; $glob_group = isset($glob_ref['glob_group']) ? $glob_ref['glob_group'] : 'default'; $excluded_files = yuf_expand_js_glob(substr($glob_ref['raw'], 1), $real, $js_aliases, $max_files); foreach ($excluded_files as $excluded_file) { if (!isset($glob_excludes[$glob_group])) $glob_excludes[$glob_group] = array(); $glob_excludes[$glob_group][yuf_norm_slash($excluded_file)] = 1; } } foreach ($refs as $ref) { if ($ref['type'] === 'js_glob') { if (isset($ref['raw'][0]) && $ref['raw'][0] === '!') continue; $glob_group = isset($ref['glob_group']) ? $ref['glob_group'] : 'default'; $glob_files = yuf_expand_js_glob($ref['raw'], $real, $js_aliases, $max_files); if (!count($glob_files)) { $missing['glob:' . $ref['raw']] = array('file' => '', 'from' => $real, 'via' => $ref['type'], 'raw' => isset($ref['raw_original']) ? $ref['raw_original'] : $ref['raw'], 'source' => isset($ref['source']) ? $ref['source'] : ''); continue; } foreach ($glob_files as $glob_file) { $glob_file = yuf_norm_slash($glob_file); if (isset($glob_excludes[$glob_group][$glob_file])) continue; if (!yuf_under_allowed_root($glob_file, $roots)) continue; $glob_real = realpath($glob_file); if ($glob_real === false) continue; $glob_real = yuf_norm_slash($glob_real); if (!isset($visited[$glob_real])) { $queue[] = array('file' => $glob_real, 'url' => yuf_file_to_url_guess($glob_real, $maps, $host, $scheme), 'via' => $ref['type'], 'from' => $real); } } continue; } $r = yuf_url_to_file($ref['raw'], $guess_url, $real, $host, $maps, $roots, $ref['type'], $js_aliases); if ($r['kind'] === 'skip') { $skipped[$ref['raw']] = array('reason' => 'skip_url', 'from' => $real); continue; } if ($r['kind'] === 'external') { $external[$ref['raw']] = array('url' => $ref['raw'], 'from' => $real); continue; } if ($r['kind'] === 'package') { $package_name = isset($r['package']) ? $r['package'] : $ref['raw']; $packages[$package_name] = array('package' => $package_name, 'from' => $real, 'via' => $ref['type']); continue; } if ($r['kind'] === 'missing_map') { yuf_dbg('ADD_MISSING_MAP raw=' . $ref['raw']); $missing[$ref['raw']] = array('file' => '', 'url_path' => isset($r['url_path']) ? $r['url_path'] : '', 'from' => $real, 'via' => $ref['type'], 'raw' => isset($ref['raw_original']) ? $ref['raw_original'] : $ref['raw'], 'source' => isset($ref['source']) ? $ref['source'] : ''); continue; } if ($r['kind'] === 'local') { $next_file = yuf_norm_slash($r['file']); if (!is_file($next_file)) { yuf_dbg('ADD_MISSING_FILE file=' . $next_file . ' raw=' . $ref['raw']); $missing[$next_file] = array('file' => $next_file, 'from' => $real, 'via' => $ref['type'], 'raw' => isset($ref['raw_original']) ? $ref['raw_original'] : $ref['raw'], 'source' => isset($ref['source']) ? $ref['source'] : ''); continue; } $next_real = realpath($next_file); if ($next_real === false) continue; $next_real = yuf_norm_slash($next_real); if (!isset($visited[$next_real])) { yuf_dbg('QUEUE_ADD file=' . $next_real . ' via=' . $ref['type'] . ' from=' . $real); $queue[] = array('file' => $next_real, 'url' => yuf_file_to_url_guess($next_real, $maps, $host, $scheme), 'via' => $ref['type'], 'from' => $real); } } } } ksort($files); ksort($missing); ksort($external); ksort($packages); ksort($skipped); return array( 'version' => $GLOBALS['YUF_VERSION'], 'start_file' => $real_start, 'start_url' => $start_url, 'host' => $host, 'maps' => $maps, 'js_aliases' => $js_aliases, 'files' => $files, 'missing' => $missing, 'external' => $external, 'packages' => $packages, 'skipped' => $skipped, 'debug' => $GLOBALS['YUF_DEBUG_LOG'], 'count_files' => count($files), 'count_missing' => count($missing), 'count_external' => count($external), 'count_packages' => count($packages) ); } function yuf_show_form($version) { $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''; header('Content-Type: text/html; charset=utf-8'); echo '<!doctype html><html><head><meta charset="utf-8"><title>yyy_used_files ' . yuf_h($version) . '</title>'; echo '<link rel="stylesheet" href="yyy__theme_style.css?v=' . yuf_h($version) . '">'; echo '<link rel="stylesheet" href="yyy_cmd_css.css?v=' . yuf_h($version) . '">'; echo '</head><body><div class="container main-wrapper">'; echo '<div class="topbar"><div class="left-icons"><div class="yuf-toolbar" yy="yyy-used-files-exclude:start" style="display:flex;gap:4px;align-items:center;flex-wrap:wrap;margin:0 0 8px 0;">' . '<a class="icon-btn" href="yyy_cmd.php">๐ปCMD</a>' . '<a class="icon-btn" href="yyy_view.php?view=' . yuf_h(yuf_norm_slash(__FILE__)) . '">๐์์ </a>' . '<button type="button" class="icon-btn" id="yyy-diff">โ๋น๊ต</button>' . '<label class="icon-btn"><input type="checkbox" id="chk-all" style="margin-right:4px;"> ์ ์ฒด</label>' . '<button type="button" id="themeToggle" class="icon-btn">๐</button>' . '<span class="icon-btn" style="cursor:default;">yyy_used_files ' . yuf_h($version) . '</span>' . '<a class="icon-btn" href="yyy_find.php">find</a>' . '</div><!-- yyy-used-files-exclude:end --></div><div class="right-icons"></div></div>'; echo '<form method="get" class="find-form">'; echo '<div>์์ ํ์ผ ์ ์ฒด๊ฒฝ๋ก</div><input class="form-control" name="file" value="/var/www/html/index.php" style="width:100%;">'; echo '<div style="margin-top:6px;">์์ Web URL</div><input class="form-control" name="url" value="' . yuf_h($scheme . '://' . $host . '/index.php') . '" style="width:100%;">'; echo '<label style="display:block;margin-top:6px;"><input type="checkbox" name="debug" value="1"> debug=1</label>'; echo '<div style="margin-top:8px;"><button class="icon-btn" type="submit">๋ถ์</button></div>'; echo '</form></div><div id="yy-toast-wrap"></div>' . "<script>window.YY_BATCH_FILES_CFG={fileCheckboxSelector:'.cmp-file',checkAllSelector:'#chk-all',compareButtonSelector:'#yyy-diff',diffUrl:'yyy_diff.php'};</script>" . '<script src="yy__theme.js?v=' . yuf_h($version) . '"></script>' . '<script src="yyy_batch_files.js?v=' . yuf_h($version) . '"></script>' . '<script>if(window.yyBatchFiles&&window.yyBatchFiles.init)window.yyBatchFiles.init();</script></body></html>'; exit; } $file = isset($_GET['file']) ? trim($_GET['file']) : ''; $url = isset($_GET['url']) ? trim($_GET['url']) : ''; $format = isset($_GET['format']) ? strtolower(trim($_GET['format'])) : 'html'; if ($file === '' || $url === '') yuf_show_form($YUF_VERSION); $result = yuf_scan($file, $url, $ALLOWED_ROOTS, $MANUAL_URL_MAP, $MAX_FILES, $MAX_READ_BYTES); if ($format === 'json') { header('Content-Type: application/json; charset=utf-8'); echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); exit; } if ($format === 'text') { header('Content-Type: text/plain; charset=utf-8'); foreach ($result['files'] as $row) echo $row['file'] . "\n"; if ($YUF_DEBUG) { echo "\n# DEBUG\n"; foreach ($result['debug'] as $line) echo $line . "\n"; } exit; } $groups = array(); foreach ($result['files'] as $row) { $k = $row['kind']; if (!isset($groups[$k])) $groups[$k] = array(); $groups[$k][] = $row; } $order = array('php','js','css','img','font','etc'); foreach ($groups as $k => $v) { if (!in_array($k, $order, true)) $order[] = $k; } header('Content-Type: text/html; charset=utf-8'); ?> <!doctype html> <html> <head> <meta charset="utf-8"> <title>yyy_used_files <?php echo yuf_h($YUF_VERSION); ?></title> <link rel="stylesheet" href="yyy__theme_style.css?v=<?php echo yuf_h($YUF_VERSION); ?>"> <link rel="stylesheet" href="yyy_cmd_css.css?v=<?php echo yuf_h($YUF_VERSION); ?>"> <style> .yuf-toolbar{display:flex;gap:4px;align-items:center;flex-wrap:wrap;margin:0 0 8px 0;} .yuf-summary{font-size:12px;opacity:.85;margin:4px 0 8px 0;} .yuf-table{width:100%;border-collapse:collapse;font-size:13px;background:var(--input-bg);color:var(--text);} .yuf-table th,.yuf-table td{border:1px solid var(--border);padding:4px 6px;vertical-align:top;} .yuf-table th{background:var(--panel2);} .yuf-kind-head{background:color-mix(in srgb, var(--panel2) 86%, #0d6efd 14%) !important;font-weight:700;} .yuf-path{font-family:Consolas,monospace;word-break:break-all;} .yuf-table,.yuf-table *{-webkit-user-select:none;user-select:none;} .yuf-copy-path,.yuf-copy-path *{-webkit-user-select:text !important;user-select:text !important;cursor:text;} body.yuf-select-all .yuf-table,body.yuf-select-all .yuf-table *{-webkit-user-select:text !important;user-select:text !important;} .yuf-missing-row{background:color-mix(in srgb, var(--panel2) 82%, #dc3545 18%);} .yuf-missing-path{text-decoration:line-through;text-decoration-thickness:2px;text-decoration-color:currentColor;} .yuf-origin{display:block;margin-top:3px;font-family:Consolas,monospace;font-size:11px;opacity:.78;white-space:normal;word-break:break-all;} .yuf-origin b{font-family:inherit;} .yuf-small{font-size:12px;opacity:.80;} .yuf-badge{display:inline-block;border:1px solid var(--border);border-radius:6px;padding:1px 5px;background:var(--panel2);} .yuf-debug{font-family:Consolas,monospace;font-size:12px;white-space:pre-wrap;background:#111;color:#eee;padding:10px;border-radius:6px;max-height:520px;overflow:auto;} </style> <script> window.YY_BATCH_FILES_CFG = { fileCheckboxSelector: '.cmp-file', checkAllSelector: '#chk-all', zipButtonSelector: '#yyy-zip-download', aiZipButtonSelector: '#yyy-ai-zip-url', compareButtonSelector: '#yyy-diff', zipDownloadUrl: 'yyy_batch_files.php?action=zip_download', diffUrl: 'yyy_diff.php' }; function yufToggleKind(kind, on){ document.querySelectorAll('.cmp-file[data-kind="' + kind + '"]').forEach(function(cb){ cb.checked = !!on; }); if (window.yyBatchFiles && window.yyBatchFiles.updateCheckAllState) window.yyBatchFiles.updateCheckAllState(); } function yufInitSelectMode(){ var cb = document.getElementById('yuf-path-only-select'); if (!cb) return; var saved = localStorage.getItem('yyy_used_files_path_only_select'); if (saved === '0') cb.checked = false; function apply(){ document.body.classList.toggle('yuf-select-all', !cb.checked); localStorage.setItem('yyy_used_files_path_only_select', cb.checked ? '1' : '0'); } cb.addEventListener('change', apply); apply(); } </script> </head> <body> <div class="container main-wrapper" > <div class="topbar"> <div class="left-icons"> <div class="yuf-toolbar" yy="yyy-used-files-exclude:start" > <a class="icon-btn" href="yyy_cmd.php">๐ปCMD</a> <a class="icon-btn" href="yyy_view.php?view=<?php echo yuf_h(yuf_norm_slash(__FILE__)); ?>">๐์์ </a> <button type="button" class="icon-btn" id="yyy-diff">โ๋น๊ต</button> <label class="icon-btn"><input type="checkbox" id="chk-all" style="margin-right:4px;"> ์ ์ฒด</label> <button type="button" id="themeToggle" class="icon-btn">๐</button> <span class="icon-btn" style="cursor:default;">yyy_used_files <?php echo yuf_h($YUF_VERSION); ?></span> <a class="icon-btn" href="yyy_find.php">find</a> <button type="button" class="icon-btn" id="yyy-zip-download">๐ฆ์์ถ</button> <button type="button" class="icon-btn" id="yyy-ai-zip-url">AI๋ค์ดURL</button> <label class="icon-btn" title="์ฒดํฌ ON=ํ์ผ ์ ์ฒด๊ฒฝ๋ก๋ง ๋๋๊ทธ ๋ณต์ฌ, OFF=ํ ์ด๋ธ ์ ์ฒด ๋๋๊ทธ ํ์ฉ"><input type="checkbox" id="yuf-path-only-select" checked style="margin-right:4px;">๊ฒฝ๋ก๋ง ๋๋๊ทธ</label> </div yy="yyy-used-files-exclude:end" > <div class="yuf-summary"> ์์ ํ์ผ: <span class="yuf-badge yuf-path"><?php echo yuf_h($result['start_file']); ?></span> URL: <span class="yuf-badge yuf-path"><?php echo yuf_h($result['start_url']); ?></span> ํ์ผ <?php echo intval($result['count_files']); ?> / ๋๋ฝ <?php echo intval($result['count_missing']); ?> / ์ธ๋ถ <?php echo intval($result['count_external']); ?> / ํจํค์ง <?php echo intval($result['count_packages']); ?> <?php if ($YUF_DEBUG) { ?><span class="yuf-badge">debug=1</span><?php } ?> </div> </div> <div class="right-icons"></div> </div> <form method="get" class="find-form" style="padding:8px;margin-bottom:8px;"> <input type="text" name="file" value="<?php echo yuf_h($file); ?>" style="width:36%;" class="cmd-textarea"> <input type="text" name="url" value="<?php echo yuf_h($url); ?>" style="width:46%;" class="cmd-textarea"> <input type="hidden" name="debug" value="<?php echo $YUF_DEBUG ? '1' : '0'; ?>"> <button type="submit" class="icon-btn">์ฌ๋ถ์</button> <?php if ($YUF_DEBUG) { ?> <a class="icon-btn" href="?file=<?php echo yuf_h(rawurlencode($file)); ?>&url=<?php echo yuf_h(rawurlencode($url)); ?>">debug OFF</a> <?php } else { ?> <a class="icon-btn" href="?file=<?php echo yuf_h(rawurlencode($file)); ?>&url=<?php echo yuf_h(rawurlencode($url)); ?>&debug=1">debug ON</a> <?php } ?> </form> <?php if ($YUF_DEBUG) { ?> <h4>debug log</h4> <div class="yuf-debug"><?php echo yuf_h(implode("\n", $result['debug'])); ?></div> <?php } ?> <table class="yuf-table"> <tr><th style="width:38px;">์ ํ</th><th style="width:50px;">No</th><th>ํ์ผ ์ ์ฒด๊ฒฝ๋ก</th><th style="width:70px;">์ข ๋ฅ</th><th style="width:130px;">๋ฐ๊ฒฌ</th><th>์ฐธ์กฐํ ํ์ผ</th></tr> <?php $no = 0; foreach ($order as $kind) { if (!isset($groups[$kind]) || !count($groups[$kind])) continue; echo '<tr><th colspan="6" class="yuf-kind-head"><label><input type="checkbox" onchange="yufToggleKind(\'' . yuf_h($kind) . '\', this.checked)"> ' . yuf_h(strtoupper($kind)) . ' ์ผ๊ด์ ํ</label> <span class="yuf-small">' . count($groups[$kind]) . '๊ฐ</span></th></tr>'; foreach ($groups[$kind] as $row) { $no++; echo '<tr>'; echo '<td><input type="checkbox" class="cmp-file" data-kind="' . yuf_h($kind) . '" value="' . yuf_h($row['file']) . '"></td>'; echo '<td>' . $no . '</td>'; echo '<td class="yuf-path yuf-copy-path">' . yuf_h($row['file']) . '</td>'; echo '<td>' . yuf_h($row['kind']) . '</td>'; echo '<td>' . yuf_h($row['via']) . '</td>'; echo '<td class="yuf-path yuf-small">' . yuf_h($row['from']) . '</td>'; echo '</tr>'; } } if ($result['count_missing'] > 0) { echo '<tr><th colspan="6" class="yuf-kind-head yuf-missing-row">๋๋ฝ/๋งคํ์คํจ <span class="yuf-small">' . intval($result['count_missing']) . '๊ฐ</span></th></tr>'; foreach ($result['missing'] as $k => $row) { $no++; $target = isset($row['file']) && $row['file'] !== '' ? $row['file'] : $k; echo '<tr class="yuf-missing-row">'; echo '<td><input type="checkbox" disabled title="๋๋ฝ ํ์ผ์ ์์ถ ๋์์์ ์ ์ธ๋ฉ๋๋ค"></td>'; echo '<td>' . $no . '</td>'; $source = isset($row['source']) ? $row['source'] : ''; $raw = isset($row['raw']) ? $row['raw'] : ''; $origin = ''; if ($raw !== '') $origin .= '<span class="yuf-origin"><b>์๋ฌธ๊ฐ:</b> ' . yuf_h($raw) . '</span>'; if ($source !== '') $origin .= '<span class="yuf-origin"><b>์๋ฌธ์์น:</b> ' . yuf_h($source) . '</span>'; echo '<td class="yuf-path yuf-copy-path" title="' . yuf_h($raw . ' ' . $source) . '"><span class="yuf-missing-path">' . yuf_h($target) . '</span>' . $origin . '</td>'; echo '<td>๋๋ฝ</td>'; echo '<td>' . yuf_h(isset($row['via']) ? $row['via'] : '') . '</td>'; echo '<td class="yuf-path yuf-small">' . yuf_h(isset($row['from']) ? $row['from'] : '') . '</td>'; echo '</tr>'; } } ?> </table> <?php if ($result['count_missing'] > 0) { ?> <h4>๋๋ฝ ๋๋ ๋งคํ ์คํจ</h4> <table class="yuf-table"> <tr><th>๋์</th><th>์ฐธ์กฐํ ํ์ผ</th><th>๋ฐฉ์</th><th>์๋ฌธ๊ฐ/์๋ฌธ์์น</th></tr> <?php foreach ($result['missing'] as $k => $row) { ?> <tr><td class="yuf-path yuf-missing-path"><?php echo yuf_h($k); ?></td><td class="yuf-path yuf-small"><?php echo yuf_h(isset($row['from']) ? $row['from'] : ''); ?></td><td><?php echo yuf_h(isset($row['via']) ? $row['via'] : ''); ?></td><td class="yuf-path yuf-small"><?php echo yuf_h(isset($row['raw']) ? $row['raw'] : ''); ?><br><?php echo yuf_h(isset($row['source']) ? $row['source'] : ''); ?></td></tr> <?php } ?> </table> <?php } ?> <?php if ($result['count_packages'] > 0) { ?> <h4>JS ํจํค์ง import</h4> <table class="yuf-table"> <tr><th>ํจํค์ง</th><th>์ฐธ์กฐํ ํ์ผ</th><th>๋ฐฉ์</th></tr> <?php foreach ($result['packages'] as $k => $row) { ?> <tr><td class="yuf-path"><?php echo yuf_h($k); ?></td><td class="yuf-path yuf-small"><?php echo yuf_h(isset($row['from']) ? $row['from'] : ''); ?></td><td><?php echo yuf_h(isset($row['via']) ? $row['via'] : ''); ?></td></tr> <?php } ?> </table> <?php } ?> <?php if ($result['count_external'] > 0) { ?> <h4>์ธ๋ถ URL</h4> <table class="yuf-table"> <tr><th>URL</th><th>์ฐธ์กฐํ ํ์ผ</th></tr> <?php foreach ($result['external'] as $k => $row) { ?> <tr><td class="yuf-path"><?php echo yuf_h($k); ?></td><td class="yuf-path yuf-small"><?php echo yuf_h(isset($row['from']) ? $row['from'] : ''); ?></td></tr> <?php } ?> </table> <?php } ?> </div> <div id="yy-toast-wrap" style="position:fixed;right:16px;bottom:16px;z-index:99999;display:flex;flex-direction:column;gap:8px;"></div> <script src="yy__theme.js?v=<?php echo yuf_h($YUF_VERSION); ?>"></script> <script src="yyy_batch_files.js?v=<?php echo yuf_h($YUF_VERSION); ?>"></script> <script> if (window.yyBatchFiles && window.yyBatchFiles.init) window.yyBatchFiles.init(); yufInitSelectMode(); </script> </body> </html>
โจ/mnt/d/_St/y/yyy_used_files.php
59,217 bytes
::
php
Y:0px 0%
X:0px 0%
Split:--
Line:1
A0
Aโ
A+
Lh0
Lhโ
Lh+
pre+
ฦ ํจ์ / ํด๋์ค ๋ชฉ๋ก
โ
๐พ
Aa
.*
bF
1
๐
๐
๊ฒ์์ด๋ฅผ ๋จผ์ ์ ๋ ฅํ์ธ์.
1
At
์ ์ฒด์ ์ฉ
๋ค์์ฐพ๊ธฐ
1๊ฐ์ ์ฉ
-----------