๐ฅ
๐
๐ป
Z
U
๐f
(โฆ)
๐n
(โฆ)
โฐ
๐พS
๐ฅ
๐C
๐
๐
ฦ
yE
Fn
St
Fi
Hd
<?php /** * ํ์ผ: yyy_find.php * ๋ฒ์ : /var/www/html/y/yyy_find.php * ๋ฒ์ : 1.0 ZIP ๋ด๋ถ ์ฝ๊ธฐ ์ ์ฉ ๊ฒ์ ํตํฉ */ define("_CMD_", true); error_reporting(E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_PARSE | E_USER_ERROR); include_once __DIR__ . "/yyy_config_host.php"; include_once "yyy_func.php"; include_once('yyy_host_link.php'); # ๋งํฌ๊ด๋ จํจ์ include_once('yyy_url_fav.php'); //include_once('yyy_ip_auth.php'); $yyy_find_zip_request = isset($_REQUEST['zip_search']) && in_array($_REQUEST['zip_search'], ['1', 1, 'on', 'true', 'checked'], true); /* =============================== ๊ธฐ์กด POST / GET ์ฒ๋ฆฌ (์๋ณธ ์ ์ง) =============================== */ if ($yyy_find_zip_request && isset($_REQUEST['save_file']) && $_REQUEST['save_file'] == '1') { http_response_code(400); die('โ ZIP ๋ด๋ถ ๊ฒ์ ๋ชจ๋์์๋ ํ์ผ ์ ์ฅ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.'); } if (isset($_REQUEST['save_file']) && $_REQUEST['save_file'] == '1') { $file_path = $_REQUEST['file_path'] ?? ''; $content = $_REQUEST['content'] ?? ''; $no_bak = $_REQUEST['no_bak'] ?? false; if (!$file_path) die("โ ํ์ผ ๊ฒฝ๋ก๊ฐ ์์ต๋๋ค."); $dir = dirname($file_path); if (!is_dir($dir)) { if (!mkdir($dir, 0755, true)) { die("โ ๋๋ ํ ๋ฆฌ ์์ฑ ์คํจ: " . htmlspecialchars($dir)); } } if (file_exists($file_path)) { if (!createBackup($file_path, $no_bak)) { $err = getBackupLastError(); if ($err) { var_dump($err); echo ("yy71:[{$err['code']}] {$err['message']}\n"); } else { echo ("[UNKNOWN] ์ ์ ์๋ ์ค๋ฅ\n"); } exit; } } $result = file_put_contents($file_path, $content); if ($result === false) die("โ ํ์ผ ์ ์ฅ์ ์คํจํ์ต๋๋ค."); echo "โ ์ ์ฅ ์ฑ๊ณต: " . htmlspecialchars($file_path) . " (" . number_format($result) . " bytes)"; exit; } $action = $_REQUEST['action'] ?? ''; yyy_urlfav_handle_ajax(); /* ---- ๊ฐ๋ณ์์ (AJAX) ---- */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'single_replace' && $yyy_find_zip_request) { http_response_code(400); echo 'โ ZIP ๋ด๋ถ ๊ฒ์ ๋ชจ๋์์๋ ๊ฐ๋ณ์์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.'; exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'single_replace') { $file = $_POST['target_file'] ?? ''; $line = (int)($_POST['target_line'] ?? 0); $content = $_POST['new_content'] ?? ''; $no_bak = $_POST['no_bak'] ?? 0; if ($file && $line && is_writable($file)) { $lines = file($file); if (isset($lines[$line - 1])) { $lines[$line - 1] = $content . "\n"; if (!$no_bak) createBackup($file); if (file_put_contents($file, implode('', $lines)) !== false) { echo "โ " . basename($file) . " {$line}๋ผ์ธ ์์ ์๋ฃ!"; exit; } } } echo "โ ์์ ์คํจ (ํ์ผ ๊ถํ์ด๋ ๋ผ์ธ ํ์ธ ํ์)"; exit; } $R = $_REQUEST; $req_bool = function($k){ return isset($_REQUEST[$k]) && $_REQUEST[$k] == '1'; }; /* =============================== ZIP ๋ด๋ถ ์ฝ๊ธฐ ์ ์ฉ ๊ฒ์ =============================== */ function yyy_find_zip_h($value) { return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function yyy_find_zip_split_csv($raw) { $items = array_map('trim', explode(',', (string)$raw)); return array_values(array_filter($items, static function($v) { return $v !== ''; })); } function yyy_find_zip_glob_match($value, $pattern, $case_sensitive) { $value = (string)$value; $pattern = trim((string)$pattern); if ($pattern === '') return false; $quoted = preg_quote($pattern, '~'); $quoted = str_replace(array('\\*', '\\?'), array('.*', '.'), $quoted); $flags = $case_sensitive ? '' : 'i'; return preg_match('~^' . $quoted . '$~' . $flags, $value) === 1; } function yyy_find_zip_contains($haystack, $needle, $case_sensitive) { if ($needle === '') return true; return $case_sensitive ? strpos((string)$haystack, (string)$needle) !== false : stripos((string)$haystack, (string)$needle) !== false; } function yyy_find_zip_path_has_excluded_dir($path, $exclude_dirs, $case_sensitive) { $path = str_replace('\\', '/', (string)$path); $path = '/' . trim($path, '/') . '/'; $cmp_path = $case_sensitive ? $path : strtolower($path); foreach ((array)$exclude_dirs as $raw_dir) { $raw_dir = trim((string)$raw_dir); if ($raw_dir === '') continue; $dir = str_replace('\\', '/', $raw_dir); $dir = trim($dir, '/'); if ($dir === '') continue; if (strpos($dir, '*') !== false || strpos($dir, '?') !== false) { $target = trim($path, '/'); if (yyy_find_zip_glob_match($target, trim($dir, '/'), $case_sensitive)) { return true; } continue; } $needle = '/' . $dir . '/'; if (!$case_sensitive) $needle = strtolower($needle); if (strpos($cmp_path, $needle) !== false) { return true; } } return false; } function yyy_find_zip_resolve_base($path_filter) { $base = defined('BASE_ROOT') ? BASE_ROOT : '/var/www/html'; $path_filter = trim((string)$path_filter); if ($path_filter !== '') { $base = (isset($path_filter[0]) && $path_filter[0] === '/') ? $path_filter : rtrim($base, '/') . '/' . ltrim($path_filter, '/'); } return rtrim($base, '/'); } function yyy_find_zip_collect_archives($path_filter, $exclude_dirs, $case_sensitive) { $base = yyy_find_zip_resolve_base($path_filter); $name_opt = $case_sensitive ? '-name' : '-iname'; $cmd_parts = array('find', escapeshellarg($base)); $prune_conditions = array(); foreach ((array)$exclude_dirs as $raw_dir) { $raw_dir = trim((string)$raw_dir); if ($raw_dir === '') continue; if (isset($raw_dir[0]) && $raw_dir[0] === '/') { $pattern = $raw_dir; } else { $pattern = '*/' . trim($raw_dir, '*/'); } $prune_conditions[] = '-path ' . escapeshellarg($pattern); } if ($prune_conditions) { $cmd_parts[] = '\\('; $cmd_parts[] = implode(' -o ', $prune_conditions); $cmd_parts[] = '\\) -prune -o'; } $cmd_parts[] = '-type f'; $cmd_parts[] = $name_opt . ' ' . escapeshellarg('*.zip'); $cmd_parts[] = '-print 2>/dev/null'; $cmd = implode(' ', $cmd_parts); $out = shell_exec($cmd); $files = $out ? array_values(array_filter(explode("\n", trim($out)), static function($v) { return trim($v) !== ''; })) : array(); natcasesort($files); return array($cmd, array_values($files)); } function yyy_find_zip_entry_allowed($entry_name, $ext_filter, $file_like, $exclude_names, $exclude_exts, $exclude_dirs, $case_sensitive) { $entry_name = str_replace('\\', '/', (string)$entry_name); $entry_name = ltrim($entry_name, '/'); if ($entry_name === '' || strpos($entry_name, "\0") !== false || substr($entry_name, -1) === '/') { return false; } if (yyy_find_zip_path_has_excluded_dir(dirname($entry_name), $exclude_dirs, $case_sensitive)) { return false; } $basename = basename($entry_name); $entry_ext = pathinfo($basename, PATHINFO_EXTENSION); $wanted_exts = yyy_find_zip_split_csv($ext_filter); if (!$wanted_exts) $wanted_exts = array('all'); $all_ext = false; $ext_ok = false; foreach ($wanted_exts as $wanted_ext) { if (strcasecmp($wanted_ext, 'all') === 0 || $wanted_ext === '*') { $all_ext = true; break; } if ($case_sensitive ? ($entry_ext === $wanted_ext) : (strcasecmp($entry_ext, $wanted_ext) === 0)) { $ext_ok = true; break; } } if (!$all_ext && !$ext_ok) return false; foreach (yyy_find_zip_split_csv($exclude_exts) as $exclude_ext) { $exclude_ext = ltrim($exclude_ext, '*.'); if ($exclude_ext === '') continue; if ($case_sensitive ? ($entry_ext === $exclude_ext) : (strcasecmp($entry_ext, $exclude_ext) === 0)) { return false; } } foreach (yyy_find_zip_split_csv($exclude_names) as $pattern) { if (yyy_find_zip_glob_match($basename, $pattern, $case_sensitive)) { return false; } } if ($file_like !== '' && !yyy_find_zip_contains($basename, $file_like, $case_sensitive)) { return false; } return true; } function yyy_find_zip_content_lines($content) { $content = str_replace(array("\r\n", "\r"), "\n", (string)$content); if ($content === '') return array(); $lines = explode("\n", $content); if (substr($content, -1) === "\n" && end($lines) === '') { array_pop($lines); } return $lines; } function yyy_find_zip_search_content($content, $find, $caps, $word_mode, $is_multiline) { $lines = yyy_find_zip_content_lines($content); $found_lines = array(); $pattern_regex = ''; $is_multiline = max(1, (int)$is_multiline); if ($is_multiline > 1) { $find_norm = str_replace(array("\r\n", "\r"), "\n", (string)$find); $needle_lines = explode("\n", $find_norm); $line_span = count($needle_lines); $total = count($lines); if ($line_span >= 2 && $total >= $line_span) { for ($i = 0; $i <= $total - $line_span; $i++) { $match_found = true; for ($j = 0; $j < $line_span; $j++) { $file_line = isset($lines[$i + $j]) ? $lines[$i + $j] : ''; $find_line = $needle_lines[$j]; $same = $caps ? ($file_line === $find_line) : (strtolower($file_line) === strtolower($find_line)); if (!$same) { $match_found = false; break; } } if ($match_found) { $found_lines[] = array( 'num' => $i + 1, 'num_end' => $i + $line_span, 'content' => implode("\n", array_slice($lines, $i, $line_span)) ); } } } } else { $caps_flag = $caps ? '' : 'i'; if ($word_mode) { $pattern_regex = '/\\b' . preg_quote((string)$find, '/') . '\\b/' . $caps_flag; } foreach ($lines as $line_no => $line) { if ($word_mode) { $matched = preg_match($pattern_regex, $line) === 1; } else { $matched = $caps ? strpos($line, (string)$find) !== false : stripos($line, (string)$find) !== false; } if ($matched) { $found_lines[] = array( 'num' => $line_no + 1, 'num_end' => $line_no + 1, 'content' => $line ); } } } return array( 'lines' => $lines, 'found_lines' => $found_lines, 'pattern_regex' => $pattern_regex ); } function yyy_find_zip_build_contexts($lines, $found_lines, $m_len, $limit = 5) { $contexts = array(); $line_count = count((array)$lines); $m_len = max(0, (int)$m_len); foreach (array_slice((array)$found_lines, 0, max(1, (int)$limit)) as $found_line) { $line_num = isset($found_line['num']) ? (int)$found_line['num'] : 1; $line_end = isset($found_line['num_end']) ? (int)$found_line['num_end'] : $line_num; $start = max(1, $line_num - $m_len); $end = min($line_count, $line_end + $m_len); $rows = array(); for ($line_idx = $start; $line_idx <= $end; $line_idx++) { $rows[] = array( 'num' => $line_idx, 'content' => isset($lines[$line_idx - 1]) ? $lines[$line_idx - 1] : '', 'is_hit' => ($line_idx >= $line_num && $line_idx <= $line_end) ); } $contexts[] = $rows; } return $contexts; } function yyy_find_zip_highlight_line($line, $find, $caps, $word_mode) { $find = (string)$find; if ($find === '') return yyy_find_zip_h($line); $flags = $caps ? '' : 'i'; $pattern = $word_mode ? '/(\\b' . preg_quote($find, '/') . '\\b)/' . $flags : '/(' . preg_quote($find, '/') . ')/' . $flags; $parts = preg_split($pattern, (string)$line, -1, PREG_SPLIT_DELIM_CAPTURE); if ($parts === false) return yyy_find_zip_h($line); $html = ''; foreach ($parts as $idx => $part) { $safe = yyy_find_zip_h($part); $html .= ($idx % 2 === 1) ? '<mark class="yy-hit">' . $safe . '</mark>' : $safe; } return $html; } function yyy_find_zip_open_error_text($code) { $map = array( ZipArchive::ER_EXISTS => 'ํ์ผ์ด ์ด๋ฏธ ์กด์ฌํจ', ZipArchive::ER_INCONS => 'ZIP ๊ตฌ์กฐ ๋ถ์ผ์น', ZipArchive::ER_INVAL => '์๋ชป๋ ์ธ์', ZipArchive::ER_MEMORY => '๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ', ZipArchive::ER_NOENT => 'ZIP ํ์ผ ์์', ZipArchive::ER_NOZIP => '์ ์ ZIP ํ์ผ์ด ์๋', ZipArchive::ER_OPEN => 'ZIP ํ์ผ ์ด๊ธฐ ์คํจ', ZipArchive::ER_READ => 'ZIP ์ฝ๊ธฐ ์คํจ', ZipArchive::ER_SEEK => 'ZIP ํ์ ์คํจ' ); return isset($map[$code]) ? $map[$code] : ('์ค๋ฅ ์ฝ๋ ' . (int)$code); } function yyy_find_zip_render_results($args) { $find = (string)($args['find'] ?? ''); $path_filter = (string)($args['path_filter'] ?? ''); $ext_filter = (string)($args['ext_filter'] ?? 'all'); $file_like = (string)($args['fileLike'] ?? ''); $exclude_names = (string)($args['eXn'] ?? ''); $exclude_exts = (string)($args['eXt'] ?? ''); $exclude_dirs = (array)($args['exclude_dirs'] ?? array()); $caps = !empty($args['caps']); $word_mode = !empty($args['word_mode']); $is_multiline = max(1, (int)($args['is_multiline'] ?? 1)); $m_len = max(0, (int)($args['mLen'] ?? 10)); $debug = !empty($args['debug']); $max_entry_bytes = 8 * 1024 * 1024; echo '<div id="sch_rst"></div>'; echo '<div class="alert alert-info py-2 mb-2 zip-readonly-note">' . '<strong>๐ฆ ZIP ๋ด๋ถ ๊ฒ์</strong> โ ZIP ์๋ณธ์ ๋ค์ด๋ก๋ํ ์ ์๊ณ ๋ด๋ถ ํ์ผ์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ํ์๋ฉ๋๋ค.' . '</div>'; if (!class_exists('ZipArchive')) { echo '<div class="alert alert-danger"><strong>ZIP ๊ฒ์ ์คํจ:</strong> PHP ZipArchive ํ์ฅ์ด ์ค์น๋์ด ์์ง ์์ต๋๋ค.</div>'; return; } $search_base = yyy_find_zip_resolve_base($path_filter); if (!is_dir($search_base)) { echo '<div class="alert alert-danger"><strong>ZIP ๊ฒ์ ์คํจ:</strong> ๊ฒ์ ๊ฒฝ๋ก๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.<br>' . yyy_find_zip_h($search_base) . '</div>'; return; } if (!is_readable($search_base)) { echo '<div class="alert alert-danger"><strong>ZIP ๊ฒ์ ์คํจ:</strong> ๊ฒ์ ๊ฒฝ๋ก๋ฅผ ์ฝ์ ์ ์์ต๋๋ค.<br>' . yyy_find_zip_h($search_base) . '</div>'; return; } list($zip_cmd, $zip_files) = yyy_find_zip_collect_archives($path_filter, $exclude_dirs, $caps); if ($debug) { echo '<div class="small text-secondary mb-2">ZIP ์์ง ๋ช ๋ น: ' . yyy_find_zip_h($zip_cmd) . '</div>'; } $zip_scanned = 0; $zip_hit_count = 0; $entry_hit_count = 0; $total_matches = 0; $open_errors = 0; $read_errors = 0; $skipped_large = 0; $skipped_binary = 0; foreach ($zip_files as $zip_path) { $zip_path = trim((string)$zip_path); if ($zip_path === '' || !is_file($zip_path) || !is_readable($zip_path)) continue; $zip_scanned++; $zip = new ZipArchive(); $open_ret = $zip->open($zip_path); if ($open_ret !== true) { $open_errors++; echo '<div class="alert alert-danger py-2 mb-2"><strong>๐ฆ ' . yyy_find_zip_h($zip_path) . '</strong><br>' . 'ZIP ์ด๊ธฐ ์คํจ: ' . yyy_find_zip_h(yyy_find_zip_open_error_text($open_ret)) . '</div>'; continue; } $entry_hits = array(); for ($idx = 0; $idx < $zip->numFiles; $idx++) { $stat = $zip->statIndex($idx); if (!is_array($stat) || !isset($stat['name'])) continue; $entry_name = (string)$stat['name']; if (!yyy_find_zip_entry_allowed( $entry_name, $ext_filter, $file_like, $exclude_names, $exclude_exts, $exclude_dirs, $caps )) { continue; } $entry_size = isset($stat['size']) ? (int)$stat['size'] : -1; if ($entry_size > $max_entry_bytes) { $skipped_large++; continue; } $content = $zip->getFromIndex($idx); if ($content === false) { $read_errors++; continue; } if (strpos($content, "\0") !== false) { $skipped_binary++; continue; } $ret = yyy_find_zip_search_content($content, $find, $caps, $word_mode, $is_multiline); $found_lines = isset($ret['found_lines']) && is_array($ret['found_lines']) ? $ret['found_lines'] : array(); if (!$found_lines) continue; $dedup = array(); foreach ($found_lines as $found) { $start_no = isset($found['num']) ? (int)$found['num'] : 0; $end_no = isset($found['num_end']) ? (int)$found['num_end'] : $start_no; $dedup[$start_no . ':' . $end_no] = $found; } $dedup_found = array_values($dedup); $entry_hits[] = array( 'name' => str_replace('\\', '/', $entry_name), 'found_lines' => $dedup_found, 'contexts' => yyy_find_zip_build_contexts( isset($ret['lines']) && is_array($ret['lines']) ? $ret['lines'] : array(), $dedup_found, $m_len, 5 ), 'size' => $entry_size ); } $zip->close(); if (!$entry_hits) continue; $zip_hit_count++; $zip_js = json_encode($zip_path, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_APOS | JSON_HEX_QUOT); echo '<div class="file-result zip-file-result">'; echo '<div class="zip-file-head">'; echo '<span class="file-path" onclick="copyToClipboard(' . yyy_find_zip_h($zip_js) . ')">' . yyy_find_zip_h($zip_path) . '</span> '; echo '<span class="badge bg-primary pointer" onclick="copyToClipboard(' . yyy_find_zip_h($zip_js) . ')">๋ณต์ฌ</span> '; echo get_down_link($zip_path, 'ZIP ์๋ณธ ๋ค์ด๋ก๋', '๐ฅ', '_blank'); echo '<span class="badge bg-secondary">๐ฆ ZIP ์๋ณธ</span> '; echo '<span class="badge text-bg-warning">๋ด๋ถ ์ฝ๊ธฐ ์ ์ฉ</span>'; echo '</div>'; foreach ($entry_hits as $entry_hit) { $entry_hit_count++; $found_lines = $entry_hit['found_lines']; $total_matches += count($found_lines); $entry_js = json_encode($entry_hit['name'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_APOS | JSON_HEX_QUOT); echo '<div class="zip-entry-result">'; echo '<div class="zip-entry-head">โโ <span class="zip-entry-path" onclick="copyToClipboard(' . yyy_find_zip_h($entry_js) . ')">' . yyy_find_zip_h($entry_hit['name']) . '</span>'; echo ' <span class="badge badge-outline secondary">' . number_format(count($found_lines)) . '๊ณณ</span>'; if ($entry_hit['size'] >= 0) { echo ' <span class="small text-secondary">' . number_format($entry_hit['size']) . ' bytes</span>'; } echo '</div>'; foreach ((array)$entry_hit['contexts'] as $context_rows) { echo '<div class="zip-match-block">'; foreach ((array)$context_rows as $row) { $line_idx = isset($row['num']) ? (int)$row['num'] : 0; $line_content = isset($row['content']) ? (string)$row['content'] : ''; $is_hit_line = !empty($row['is_hit']); echo '<div class="match-line editable-danger' . ($is_hit_line ? ' zip-hit-line' : '') . '">'; echo '<span class="line-num">' . $line_idx . '</span> '; echo $is_hit_line ? yyy_find_zip_highlight_line($line_content, $find, $caps, $word_mode) : yyy_find_zip_h($line_content); echo '</div>'; } echo '</div>'; } if (count($found_lines) > 5) { echo '<div class="small text-secondary">... ' . number_format(count($found_lines) - 5) . '๊ฐ ๋</div>'; } echo '</div>'; } echo '</div>'; } echo '<script>document.getElementById("sch_rst").textContent = ' . json_encode('ZIP ' . $zip_hit_count . '๊ฐ / ๋ด๋ถ ํ์ผ ' . $entry_hit_count . '๊ฐ / ์ผ์น ' . $total_matches . '๊ณณ / ๊ฒ์ฌ ZIP ' . $zip_scanned . '๊ฐ', JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . ';</script>'; if ($zip_hit_count > 0) { echo '<p class="text-success"><strong>' . number_format($zip_hit_count) . '๊ฐ ZIP์์ ' . number_format($entry_hit_count) . '๊ฐ ๋ด๋ถ ํ์ผ ๋ฐ๊ฒฌ</strong></p>'; } else { echo '<p class="text-danger"><strong>ZIP ๋ด๋ถ ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์์ต๋๋ค.</strong></p>'; } if ($open_errors || $read_errors || $skipped_large || $skipped_binary) { echo '<div class="small text-secondary">์ฒ๋ฆฌ ์ํ: ์ด๊ธฐ ์คํจ ' . number_format($open_errors) . ', ๋ด๋ถ ์ฝ๊ธฐ ์คํจ ' . number_format($read_errors) . ', 8MB ์ด๊ณผ ์ ์ธ ' . number_format($skipped_large) . ', ๋ฐ์ด๋๋ฆฌ ์ ์ธ ' . number_format($skipped_binary) . '</div>'; } } ?> <!DOCTYPE html> <html lang="ko" data-bs-theme="<?= htmlspecialchars($_COOKIE['theme'] ?? 'light', ENT_QUOTES) ?>"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes"> <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='0.9em' font-size='90'>๐ฅ</text></svg>"> <title>y</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/xml/xml.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/javascript/javascript.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/css/css.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/htmlmixed/htmlmixed.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/clike/clike.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/php/php.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/sql/sql.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/python/python.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/shell/shell.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/properties/properties.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/yaml/yaml.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/markdown/markdown.min.js"></script> <script src="/y/_docs/yy_alarm_ds2gt_final_full.js.php?v=1.19"></script> <script src="yyy_batch_files.js?v=1.2"></script> <script src="yyy_toggle_panel.js?v=1.0.3"></script> <link href="yyy__theme_style.css?v=2.2a" rel="stylesheet"> <link href="yyy_cmd_css.css?v=1.5" rel="stylesheet"> <script src="yy_zip_drop_to_apply.js?v=1.10"></script> </head> <body> <div class="container main-wrapper" > <div id="yy-toast-wrap"></div> <div id="yyyFindUrlFavWrap" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="urlfav" data-yy-toggle-label="์ฆ๊ฒจ์ฐพ๊ธฐ" data-yy-toggle-order="20"> <?php yyy_urlfav_render_top_menu(); ?> </div> <?php $req_bool = function($key) use ($R) { if (!isset($R[$key])) return false; $v = $R[$key]; return $v === '1' || $v === 1 || $v === 'on' || $v === 'true' || $v === 'checked'; }; $file_path = $R['file_path'] ?? ''; $view = $R['view'] ?? ''; $line = isset($R['line']) ? (int)$R['line'] : 0; $auto_edit = $R['auto_edit'] ?? ''; $ckAddFiles= $R['ckAddFiles']?? ''; $find = isset($R['seed']) ? $R['seed'] : ($R['find'] ?? ''); $replace_text = $R['replace_text'] ?? ''; $path_filter = $R['path'] ?? ''; $ext_filter = $R['ext'] ?? 'php'; $fileLike = $R['fileLike'] ?? ''; $eXn = $R['eXn'] ?? ''; $eXt = $R['eXt'] ?? ''; $arrHomeFiles = []; $word_mode = $R['w'] ?? ''; $Caps = $_REQUEST['caps'] ?? ''; $R['caps'] = $Caps; $ed = $R['ed'] ?? ''; $ed2 = $R['ed2'] ?? ''; $no_bak = $R['no_bak'] ?? ''; $rolback = $R['rolback'] ?? ''; $Diff = $R['Diff'] ?? ''; $debug = $_REQUEST['debug'] ?? ''; $dev = $R['dev'] ?? ''; $find2File = $R['find2File'] ?? ''; $mLen = isset($R['mLen']) ? (int)$R['mLen'] : 10; $cmd_mode = $R['cmd'] ?? ''; $is_multiline = (int)($R['is_multiline'] ?? 1); if ($is_multiline < 1) $is_multiline = 1; $exdir_raw = $R['exdir'] ?? ''; $exclude_dirs = array_values(array_filter(array_map('trim', explode(',', $exdir_raw)))); $zip_search = $req_bool('zip_search'); if ($zip_search) { // ZIP ๋ด๋ถ ๊ฒฐ๊ณผ๋ ์ค์ ํ์ผ ๊ฒฝ๋ก๊ฐ ์๋๋ฏ๋ก ์์ /๋น๊ต/๋ณต๊ตฌ ํ๋ฆ์์ ์์ ํ ์ ์ธํ๋ค. $Diff = ''; $dev = ''; $ed = ''; $ed2 = ''; $rolback = ''; $no_bak = ''; $find2File = ''; } ?> <!-- script src="_docs/jcs/highlight.min.js?ver=v11.8.0"></script --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github-dark.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/google/code-prettify@master/loader/run_prettify.js"></script> <?php if (!isset($_REQUEST['mode'])) { ?> <style> a, a:hover, a:focus, a:visited { text-decoration:none; } .btn_edt{ .background:#28a745; padding:3px 8px; font-size:11px; white-space:nowrap; } .form-check-label { vertical-align:middle; padding-top:10px; } textarea.cmd-textarea{ resize:vertical; min-height:72px; font-family:Consolas, Monaco, 'Courier New', monospace; line-height:1.45; } #find{ min-height:96px; } #replace_text{ min-height:96px; width:100%; } .find-form .position-relative{ min-width:0; } .find-form .CodeMirror{ width:100% !important; min-width:0 !important; border:1px solid var(--bs-border-color, #ced4da); border-radius:.375rem; font-family:Consolas, Monaco, 'Courier New', monospace; font-size:13px; line-height:1.45; } .find-form .CodeMirror-focused{ outline:0; box-shadow:0 0 0 .2rem rgba(13,110,253,.15); } .find-form .CodeMirror-gutters{ border-right:1px solid rgba(128,128,128,.18); background:rgba(128,128,128,.06); } .find-form .CodeMirror-linenumber{ padding:0 8px 0 6px; } .find-form .CodeMirror-scroll{ min-height:96px; } .bulk-form textarea.form-control{ width:100%; } .match-line{ display:flex; align-items:center; gap:8px; flex-wrap:nowrap; } .match-line > a{ flex:0 0 auto; min-width:56px; } .match-line .edit-unit{ flex:1 1 auto; min-width:0; display:flex !important; align-items:center; gap:6px; margin-top:0 !important; } .match-line .edit-input{ flex:1 1 auto; min-width:0 !important; width:100%; } .match-line .btn{ flex:0 0 auto; } .zip-mode-box{ display:inline-flex; align-items:center; gap:7px; padding:5px 9px; border:1px solid rgba(255,193,7,.75); border-radius:8px; background:rgba(255,193,7,.12); font-weight:700; } .zip-incompatible-option{ transition:opacity .15s ease, filter .15s ease; } .zip-incompatible-option.is-disabled{ opacity:.32; filter:grayscale(1); text-decoration:line-through; } #zipModeDisabledNotice{ display:none; padding:5px 9px; border:1px solid rgba(220,53,69,.7); border-radius:8px; background:rgba(220,53,69,.10); color:#dc3545; font-weight:700; } #zipModeDisabledNotice.is-visible{display:inline-flex;align-items:center;} .zip-file-result{ border-left:4px solid #ffc107; padding:10px 12px; } .zip-file-head{ display:flex; flex-wrap:wrap; align-items:center; gap:5px; margin-bottom:7px; } .zip-entry-result{ margin:8px 0 8px 18px; padding:8px 10px; border:1px solid var(--border); border-radius:7px; background:color-mix(in srgb, var(--input-bg) 92%, #ffc107 8%); } .zip-entry-head{ margin-bottom:5px; font-weight:700; word-break:break-all; } .zip-entry-path{cursor:pointer;} .zip-entry-path:hover{text-decoration:underline;} .zip-match-block{ margin:6px 0; padding-left:8px; border-left:2px solid rgba(255,193,7,.45); } .zip-hit-line{ background:rgba(255,193,7,.09); } .zip-readonly-note{border-left:4px solid #0dcaf0;} </style> <?php } ?> <?php if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action) { if ($action === 'bulk_replace' && $zip_search) { echo '<div class="alert alert-danger">โ ZIP ๋ด๋ถ ๊ฒ์ ๋ชจ๋์์๋ ์ผ๊ด์์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.</div>'; } elseif ($action === 'bulk_replace' && !empty($_POST['replace_text']) && !empty($_POST['search_term'])) { $find = isset($_POST['search_term']) ? $_POST['search_term'] : ''; $replace_text = isset($_POST['replace_text']) ? $_POST['replace_text'] : ''; $path_filter = isset($_POST['path_filter']) ? $_POST['path_filter'] : ''; $ext_filter = isset($_POST['ext_filter']) ? $_POST['ext_filter'] : 'php'; $no_bak = isset($_POST['no_bak']) ? $_POST['no_bak'] : 0; $eXn = isset($R['eXn']) ? $R['eXn'] : ''; $eXt = isset($R['eXt']) ? $R['eXt'] : ''; $is_multiline_post = (int)($_POST['is_multiline'] ?? 1); if ($is_multiline_post < 1) $is_multiline_post = 1; list($cmd, $file_list) = find_build_and_run(); if (!empty($debug)) { echo '<h3>' . htmlspecialchars($cmd) . '</h3>'; echo '<div style="color:#666">is_multiline=' . (int)$is_multiline_post . '</div>'; } $use_regex = false; $word_mode = !empty($word_mode); $max_bytes = 8 * 1024 * 1024; $success_count = 0; $backup_count = 0; $changed_files = 0; $pattern = null; $Capsi = $Caps ? "" : "i"; if ($is_multiline_post <= 1) { if ($use_regex) { $pattern = (preg_match('#^/.+/[imsxuADSUXJ]*$#', $find)) ? $find : '/' . str_replace('/', '\/', $find) . '/' . $Capsi; } else { if ($word_mode) { $pattern = $Caps ? '/\b' . preg_quote($find, '/') . '\b/' : '/\b' . preg_quote($find, '/') . '\b/i'; $use_regex = true; } } if ($debug) echo "pattern============$pattern<br>"; } if (!empty($file_list)) { foreach ($file_list as $file) { if (!$file || !is_file($file) || !is_readable($file) || !is_writable($file)) { continue; } $sz = @filesize($file); if ($max_bytes > 0 && $sz !== false && $sz > $max_bytes) { continue; } $content = @file_get_contents($file); if ($content === false || strpos($content, "\0") !== false) { continue; } $new_content = $content; $file_changes = 0; if ($is_multiline_post > 1) { $ret_m = yyy_bulk_replace_exact_multiline_content($content, $find, $replace_text, $Caps); $new_content = isset($ret_m['content']) ? $ret_m['content'] : $content; $file_changes = isset($ret_m['count']) ? (int)$ret_m['count'] : 0; if ($debug && $file_changes > 0) { echo '<div style="color:#0d6efd">MULTI HIT: ' . htmlspecialchars($file) . ' / ' . $file_changes . '๊ฑด</div>'; } } else { if ($use_regex && $pattern) { if (preg_match($pattern, $content)) { $new_content = preg_replace($pattern, $replace_text, $content, -1, $file_changes); } } else { if ($Caps) { if (strpos($content, $find) !== false) { $new_content = str_replace($find, $replace_text, $content, $file_changes); } } else { if (stripos($content, $find) !== false) { $new_content = str_ireplace($find, $replace_text, $content, $file_changes); } } } } if ($file_changes > 0 && $new_content !== $content) { if (empty($no_bak) && createBackup($file)) { $backup_count++; } if (@file_put_contents($file, $new_content) !== false) { $success_count += $file_changes; $changed_files++; } } } } echo '<div style="background:#d4edda; color:#155724; padding:10px; margin:10px 0; border-radius:5px;">'; echo 'โ ' . number_format($changed_files) . '๊ฐ ํ์ผ ์์ , ์ด ' . number_format($success_count) . '๊ฑด ์นํ ์๋ฃ' . ' (๋ฐฑ์ : ' . number_format($backup_count) . '๊ฐ)</div>'; } } ?> <!-- div class="container main-wrapper" ์์๋ก ์ด๋ --> <div id="yyyFindHeader" class="header-panel mb-3 d-flex flex-wrap align-items-center justify-content-between" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="header" data-yy-toggle-label="์๋จ" data-yy-toggle-order="10"> <div class="d-flex align-items-center gap-2 mb-2 mb-md-0"> <a href="<?= htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8'); ?>" class="fw-bold text-decoration-none fs-5">๐ฅ ํ์ผ๊ฒ์</a> <span class="text-secondary small"> (<?= BASE_ROOT ?> ์ ์ฒด) </span> </div> <div class="icon-group d-flex align-items-center gap-2 flex-wrap"> <div class="btn btn-sm btn-outline-secondary" id="yy-alarm-icon-here">โฐ</div> <!-- // yyy-used-files-exclude:start --> <a href="yyy_view.php?view=<?= yyy_get_url_fav_json_path($host);?>" target="icon" class="btn btn-sm btn-outline-secondary" data-bs-placement="bottom" data-bs-toggle="tooltip" data-bs-title="json์์ ">๐ ๏ธ</a> <a href="yyy_view.php?view=yyy_find.php" target="icon" class="btn btn-sm btn-outline-secondary" data-bs-placement="bottom" data-bs-toggle="tooltip" data-bs-title="yyy์์ ">๐</a> <a href="yyy_cmd.php" class="btn btn-sm btn-outline-secondary" target="icon" data-bs-placement="bottom" data-bs-toggle="tooltip" data-bs-title="๋ช ๋ น์คํ">๐ป </a> <a class="btn btn-sm btn-outline-secondary" href="yyy_zip_apply.php" target="yyy_zip_apply" data-bs-placement="bottom" data-bs-toggle="tooltip" data-bs-title="ZIP ์์ถํ๊ธฐ <?=dirname(__FILE__);?>">Z</a> <button id="themeToggle" data-bs-placement="bottom" data-bs-toggle="tooltip" data-bs-title="๋คํฌ๋ชจ๋ ํ ๊ธ" class="btn btn-sm btn-outline-secondary">๐</button> <a href="_docs/yyy_test_bs5_icon_view.php" target="icon" class="btn btn-sm btn-outline-secondary"> <i class="bi bi-grid-fill"></i> </a> <a href="_docs/deep_seek.php" target="icon" class="btn btn-sm btn-outline-secondary">๐</a> <a href="_docs/deep_seek_auto_fit_auto_fill.html" target="icon" class="btn btn-sm btn-outline-secondary"> <i class="bi bi-gear-fill"></i> </a> <!-- // yyy-used-files-exclude:end --> </div> </div> <div id="yy-alarm-timer-here" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="alarm" data-yy-toggle-label="์๋" data-yy-toggle-order="30" data-yy-toggle-default-hidden="1"></div> <div id="yyyFindTogglePanel" data-yy-toggle-panel="1" data-yy-toggle-scope="find" data-yy-toggle-storage="yyy_find_panes" data-yy-toggle-title="find ํ์:" data-yy-toggle-mini="1" data-yy-toggle-mini-default="1" data-yy-toggle-mini-storage="yyy_find_panes_panel_mini" data-yy-toggle-mini-title="find ํ์ ํจ๋ ์ด๊ธฐ"></div> <div class="find-form"> <form method="GET" action="<?= htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8') ?>" class="find-form m-0"> <div id="yyyFindSearchRow" class="row g-2 mb-3 align-items-stretch" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="search" data-yy-toggle-label="๊ฒ์" data-yy-toggle-order="40"> <div class="col"> <div class="position-relative"> <i class="bi bi-search position-absolute top-50 start-0 translate-middle-y ms-3 text-secondary"></i> <textarea id="find" name="find" class="form-control ps-5 cmd-textarea w-100" placeholder="๊ฒ์ํ ๋ด์ฉ์ ์ ๋ ฅํ์ธ์ (์ฌ๋ฌ ์ค ๊ฐ๋ฅ)" onkeydown="handleEnter(event)"><?= htmlspecialchars($find) ?></textarea> </div> </div> <div class="col-auto d-flex align-items-stretch"> <input id="is_multiline" name="is_multiline" size="3" class="form-control form-control-sm text-center" style="width:56px;" value="<?= (int)max(1, (int)$is_multiline) ?>"> </div> <div class="col-6 col-lg-2"> <select name="ext" id="extSelect" class="form-select"> <option value="php" <?= $ext_filter=='php'?'selected':'' ?>>php</option> <option value="bak" <?= $ext_filter=='bak'?'selected':'' ?>>bak</option> <option value="py" <?= $ext_filter=='py'?'selected':'' ?>>py</option> <option value="js" <?= $ext_filter=='js'?'selected':'' ?>>js</option> <option value="ts" <?= $ext_filter=='ts'?'selected':'' ?>>ts</option> <option value="css" <?= $ext_filter=='css'?'selected':'' ?>>css</option> <option value="csv" <?= $ext_filter=='csv'?'selected':'' ?>>csv</option> <option value="html"<?= $ext_filter=='html'?'selected':'' ?>>html</option> <option value="conf"<?= $ext_filter=='conf'?'selected':'' ?>>conf</option> <option value="log" <?= $ext_filter=='log'?'selected':'' ?>>log</option> <option value="zip" <?= $ext_filter=='zip'?'selected':'' ?>>zip</option> <option value="all" <?= $ext_filter=='all'?'selected':'' ?>>ALL</option> </select> </div> <div class="col-6 col-lg-2"> <button type="submit" class="btn btn-primary w-100"> ๊ฒ์ </button> </div> </div> <div id="yyyFindFilterRow" class="row g-2 mb-3" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="filter" data-yy-toggle-label="ํํฐ" data-yy-toggle-order="50"> <div class="col-12 col-md-4"> <input type="text" name="path" id="path_filter" value="<?= htmlspecialchars($path_filter) ?>" class="form-control" placeholder="path_filter"> </div> <div class="col-12 col-md-4"> <input type="text" name="fileLike" value="<?= htmlspecialchars($fileLike) ?>" class="form-control" placeholder="fileLike"> </div> <div class="col-12 col-md-4"> <input type="text" name="eXt" id="eXtInput" value="<?= htmlspecialchars($eXt) ?>" class="form-control" placeholder="์ ์ธ ํ์ฅ์ (bak,tmp)"> </div> </div> <div id="yyyFindExcludeRow" class="row g-2 mb-3" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="exclude" data-yy-toggle-label="์ ์ธ" data-yy-toggle-order="60"> <div class="col-12 col-md-6"> <input type="text" name="eXn" value="<?= htmlspecialchars($eXn) ?>" class="form-control" placeholder="์ ์ธ ํ์ผ๋ช (*.log)"> </div> <div class="col-12 col-md-6"> <input type="text" name="exdir" value="<?= htmlspecialchars($exdir_raw) ?>" class="form-control" placeholder="์ ์ธํด๋ (_trasy,node_modules,.git,_bak)"> </div> </div> <div id="yyyFindOptionRow" class="row g-3 align-items-center small" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="options" data-yy-toggle-label="์ต์ " data-yy-toggle-order="70"> <div class="col-auto form-check zip-mode-box"> <label class="form-check-label"><input class="form-check-input" id="zipSearchInput" type="checkbox" name="zip_search" data-bs-toggle="tooltip" data-bs-title="๊ฒ์ ๊ฒฝ๋ก์ ZIP ํ์ผ๋ง ์ด์ด ๋ด๋ถ ํ์ผ ๋ด์ฉ์ ๊ฒ์" value="1" <?= $zip_search ? 'checked' : '' ?>> ZIP ๊ฒ์</label> </div> <div class="col-auto<?= $zip_search ? ' is-visible' : '' ?>" id="zipModeDisabledNotice">๐ ZIP ๊ฒ์: ์์ ยท๋น๊ตยท๋ณต๊ตฌ ์ฌ์ฉ ๋ถ๊ฐ</div> <div class="col-auto form-check zip-incompatible-option<?= $zip_search ? ' is-disabled' : '' ?>"> <label class="form-check-label"><input class="form-check-input" data-zip-incompatible="1" type="checkbox" name="Diff" value="checked" <?= $Diff ?> <?= $zip_search ? 'disabled' : '' ?>> Diff๋น๊ต</label> </div> <div class="col-auto form-check zip-incompatible-option<?= $zip_search ? ' is-disabled' : '' ?>"> <label class="form-check-label text-primary"><input class="form-check-input" data-zip-incompatible="1" type="checkbox" name="dev" value="checked" <?= $dev ?> <?= $zip_search ? 'disabled' : '' ?>> dev๋น๊ต</label> </div> <div class="col-auto form-check"> <label class="form-check-label"><input class="form-check-input" type="checkbox" name="w" value="checked" <?= $word_mode ?>> ์๋ ๋จ์</label> </div> <div class="col-auto form-check"> <label class="form-check-label"><input class="form-check-input" type="checkbox" name="caps" value="checked" <?= $Caps; ?>> ๋์๋ฌธ์</label> </div> <div class="col-auto form-check zip-incompatible-option<?= $zip_search ? ' is-disabled' : '' ?>"> <label class="form-check-label"><input class="form-check-input form-check-input is-invalid" data-zip-incompatible="1" type="checkbox" name="ed" value="checked" <?= $ed ?> <?= $zip_search ? 'disabled' : '' ?>> ์ผ๊ด์์ </label> </div> <div class="col-auto form-check zip-incompatible-option<?= $zip_search ? ' is-disabled' : '' ?>"> <label class="form-check-label"><input class="form-check-input" data-zip-incompatible="1" type="checkbox" name="ed2" value="checked" <?= $ed2 ?> <?= $zip_search ? 'disabled' : '' ?>> ๊ฐ๋ณ์์ </label> </div> <div class="col-auto form-check zip-incompatible-option<?= $zip_search ? ' is-disabled' : '' ?>"> <label class="form-check-label"><input class="form-check-input" data-zip-incompatible="1" type="checkbox" name="rolback" value="checked" <?= $rolback ?> <?= $zip_search ? 'disabled' : '' ?>> rolback</label> </div> <div class="col-auto form-check zip-incompatible-option<?= $zip_search ? ' is-disabled' : '' ?>"> <label class="form-check-label"><input class="form-check-input" data-zip-incompatible="1" type="checkbox" name="no_bak" value="checked" <?= $no_bak ?> <?= $zip_search ? 'disabled' : '' ?>> ๋ฐฑ์ ์ํจ</label> </div> <div class="col-auto form-check"> <label class="form-check-label"><input class="form-check-input" type="checkbox" name="debug" value="1" <?= $debug?'checked':'' ?>> debug</label> </div> <div class="col-auto"> <input type="text" name="mLen" value="<?= $mLen ?>" size="3" class="form-control form-control-sm" placeholder="mLen"> </div> <div class="col-auto form-check zip-incompatible-option<?= $zip_search ? ' is-disabled' : '' ?>"> <label class="form-check-label"><input class="form-check-input" data-zip-incompatible="1" type="checkbox" name="find2File" value="checked" <?= $find2File ?> <?= $zip_search ? 'disabled' : '' ?>> find2File</label> </div> </div> </form> </div> <div id="yyyFindResultArea" class="result-area mt-3" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="result" data-yy-toggle-label="๊ฒฐ๊ณผ" data-yy-toggle-order="100"> <?php include_once "yyy_rolback.php"; if ($find) { if ($debug) echo '<h2>๊ฒ์: ' . htmlspecialchars($find) . '</h2>'; if ($zip_search) { yyy_find_zip_render_results(array( 'find' => $find, 'path_filter' => $path_filter, 'ext_filter' => $ext_filter, 'fileLike' => $fileLike, 'eXn' => $eXn, 'eXt' => $eXt, 'exclude_dirs' => $exclude_dirs, 'caps' => $Caps, 'word_mode' => $word_mode, 'is_multiline' => $is_multiline, 'mLen' => $mLen, 'debug' => $debug )); } else { if (!$find2File) list($cmd, $file_list) = find_build_and_run(); if ($debug) echo '<h3 style="word-break:break-all">'.htmlspecialchars($cmd).'</h3>'; $results_count = 0; $total_matches = 0; echo '<div id="sch_rst"></div>'; if ($ed) { echo '<div id="yyyFindBulkForm" class="bulk-form mt-3" data-yy-toggle-target="1" data-yy-toggle-scope="find" data-yy-toggle-key="bulk" data-yy-toggle-label="์ผ๊ด" data-yy-toggle-order="80">'; echo '<h4>๐ ์ผ๊ด์์ ๋ชจ๋</h4>'; echo '<form method="POST" class="d-flex align-items-stretch gap-2">'; echo '<input type="hidden" name="action" value="bulk_replace">'; echo '<input type="hidden" name="search_term" value="' . htmlspecialchars($find) . '">'; echo '<textarea name="search_term" style="display:none">' . htmlspecialchars($find) . '</textarea>'; echo '<input type="hidden" name="is_muxXltiline" value="' . (!empty($R['is_multiline']) ? '1' : '0') . '">'; echo '<input type="hidden" name="path_filter" value="' . htmlspecialchars($path_filter) . '">'; echo '<input type="hidden" name="ckAddFiles" value="' . ($ckAddFiles) . '">'; echo '<input type="hidden" name="ext_filter" value="' . htmlspecialchars($ext_filter) . '">'; echo '<input type="hidden" name="no_bak" value="' . $no_bak . '">'; echo '<input type="text" id="is_multiline_post" size="1" name="is_multiline" value="' . (int)max(1, (int)$is_multiline) . '" class="form-control form-control-sm flex-shrink-0 text-center" style="width:56px;">'; echo '<textarea name="replace_text" id="replace_text" placeholder="๋ฐ๊ฟ ๋ด์ฉ" class="form-control ps-3 cmd-textarea flex-grow-1" style="flex:1 1 auto; min-width:0; height:80px;" onkeydown="handleEnter(event)">' . htmlspecialchars($replace_text) . '</textarea>'; echo '<button type="submit" class="btn fw-bold flex-shrink-0" style="background:#ffc107; color:#000; width: 150px; border: none;"> ์ ์ฒด XX๊ฐ<br>์์ ์ ์ฉ </button>'; echo '</form>'; echo '</div>'; } $Caps = !empty($_REQUEST['caps']); $Capsi = $Caps ? "" : "i"; $file_list_cnt = 0; $file_list_cnt2 = 0; if (!empty($file_list)) { $file_list_cnt = count($file_list); $file_list_cnt2 = 0; foreach ($file_list as $file) { $file_list_cnt2++; $file = trim($file); if (!$file || !is_file($file) || !is_readable($file)) continue; if ($debug) echo "file=" . htmlspecialchars($file) . "<br>"; $is_multiline = (int)($_REQUEST['is_multiline'] ?? 1); if ($is_multiline < 1) $is_multiline = 1; if ($is_multiline > 1) { $ret = yyy_find_in_file_multiline($file, $find, $Caps, $word_mode); } else { $ret = yyy_find_in_file_singleline($file, $find, $Caps, $word_mode); } $lines = $ret['lines']; $found_lines = $ret['found_lines']; $pattern_regex1 = $ret['pattern_regex']; $tmp_found = []; foreach ($found_lines as $one_found) { $k1 = isset($one_found['num']) ? (int)$one_found['num'] : 0; $k2 = isset($one_found['num_end']) ? (int)$one_found['num_end'] : $k1; $tmp_found[$k1 . ':' . $k2] = $one_found; } $found_lines = array_values($tmp_found); $total_line_count = count($lines); if (empty($lines) && !is_file($file)) continue; if ($debug && $word_mode) { $pattern_regex1 = '/\b' . preg_quote($find, '/') . '\b/' . $Capsi . "<br>"; } if ($debug && $pattern_regex1) echo "pattern_regex1=$pattern_regex1"; $iSfOUfILE = !empty($found_lines); if ($iSfOUfILE && !$dev) { $results_count++; $total_matches += count($found_lines); $is_writable = is_writable($file); $permission_class = $is_writable ? 'editable-success' : 'editable-danger'; $permission_text = $is_writable ? 'โ ์์ ๊ฐ๋ฅ' : 'โ ์ฝ๊ธฐ์ ์ฉ'; echo '<div class="file-result">'; $first_line_num = $found_lines[0]['num'] ?? 1; $asFile = addslashes($file); echo '<label class="me-1" style="cursor:pointer;">'; echo '<input type="checkbox" class="cmp-file" value="' . htmlspecialchars($file, ENT_QUOTES) . '"> '; echo '</label>'; echo '<span class="file-path" onclick="copyToClipboard(\'' . $asFile . '\')">' . htmlspecialchars($file) . '</span>'; echo '<span class="badge bg-primary pointer" onclick="copyToClipboard(\'' . $asFile . '\')">๋ณต์ฌ</span>'; echo get_down_link($file); $web_url = get_web_url($file); $web_icon = $web_url ? ' <a href="'.$web_url.'" target="_blank" class="selct-none" title="์น์ผ๋ก ์ด๊ธฐ">๐</a> ' : ''; echo $web_icon; // yyy-used-files-exclude:start $A_href_yyy = '<a " target="_blank" href="yyy_view.php?view=' . $file; echo $A_href_yyy . '&line=' . $first_line_num . '" class="badge bg-danger">ํธ์ง</a>'; // yyy-used-files-exclude:end echo '<span style="margin-left:10px;font-size:12px;color:' . ($is_writable ? '#28a745' : '#dc3545') . '">' . $permission_text . '</span>'; $pattern_regex1 = ""; foreach (array_slice($found_lines, 0, 5) as $found_line) { $line_num = (int)$found_line['num']; $start = max(1, $line_num - $mLen); $end = min(count($lines), $line_num + $mLen); for ($i = $start; $i <= $end; $i++) { $line_content = $lines[$i - 1]; echo '<div class="match-line ' . $permission_class . '">'; echo $A_href_yyy . '&line=' . $i . '> <span class="line-num">' . $i . '</span></a> '; if ($i == $line_num) { if ($ed2 && $is_writable) { echo '<div class="edit-unit d-inline-flex gap-1 align-items-center mt-1" style="width:calc(100% - 0px);max-width:100%;vertical-align:middle">'; echo '<textarea type="text" name="new_content" style="flex:1 1 auto;min-width:240px" class="form-control form-control-sm edit-input ' . $permission_class . '">' . htmlspecialchars($line_content) . '</textarea>'; echo '<button type="button" class="btn text-nowrap btn-sm btn-success" onclick="ajaxSaveLine(this)" data-file="' . htmlspecialchars($file) . '" data-line="' . $found_line['num'] . '"> ๐พ ์์ </button></div>'; } else { if ($word_mode) { $pattern_highlight = '/\b(' . preg_quote($find, '/') . ')\b/' . $Capsi; $safe = htmlspecialchars($line_content); $highlighted = preg_replace($pattern_highlight, "<mark class='yy-hit'>$1</mark>", $safe); } else { $safe = htmlspecialchars($line_content); $pattern_highlight = '/' . preg_quote($find, '/') . '/' . $Capsi; $highlighted = preg_replace($pattern_highlight, "<mark class='yy-hit'>$0</mark>", $safe); } echo $highlighted; } } else { echo htmlspecialchars($line_content); } echo '</div>'; } } if ($debug && $pattern_regex1) echo "pattern_regex2=$pattern_regex1<br>"; if (count($found_lines) > 5) { echo '<div style="color:#666">... ' . (count($found_lines) - 5) . '๊ฐ ๋</div>'; } echo '</div>'; } else { if ($iSfOUfILE && $dev) $arrHomeFiles[] = $file; } } if ($results_count) { echo '<script>document.getElementById("sch_rst").innerHTML = "๊ฒฐ๊ณผ ' . $results_count . '๊ฐ '.$total_matches.' ๊ณณ์์ ๋ฐ๊ฒฌ '.$file_list_cnt2.' :Fc";</script>'; } else { echo '<script>document.getElementById("sch_rst").innerHTML = "๊ฒฐ๊ณผ ' . $results_count . '๊ฐ '.$file_list_cnt.' ๊ณณ์ ์์'.$file_list_cnt2.' :Fc";</script>'; } echo '<p style="color:#28a745"><strong>' . $results_count . '๊ฐ ํ์ผ ๋ฐ๊ฒฌ</strong></p>'; if ($dev) print_arrHomeFiles($arrHomeFiles, $mLen); if ($ed) { echo '<script>document.querySelector(".bulk-form button").innerHTML = "์ ์ฒด ' . $total_matches . '๊ฐ<br> ์์ ์ ์ฉ";</script>'; } } else { if (!$find2File) echo '<p style="color:#dc3545"><strong>๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์์ต๋๋ค.</strong></p>'; } } } else { echo '<p style="color:#28a745"><strong>find ๊ฒ์์ด๋ฅผ ์ ๋ ฅํ์ธ์!</strong></p>'; } if (!$zip_search && $find2File) require_once 'yyy_find2file.php'; ?> <script> let yyFindCM = null; function yyApplyZipSearchUi() { const zipInput = document.getElementById('zipSearchInput'); const enabled = !!(zipInput && zipInput.checked); const notice = document.getElementById('zipModeDisabledNotice'); document.querySelectorAll('[data-zip-incompatible="1"]').forEach(function(input) { input.disabled = enabled; if (enabled) input.checked = false; const wrap = input.closest('.zip-incompatible-option'); if (wrap) wrap.classList.toggle('is-disabled', enabled); }); if (notice) notice.classList.toggle('is-visible', enabled); } document.addEventListener('DOMContentLoaded', function() { const zipInput = document.getElementById('zipSearchInput'); if (zipInput) zipInput.addEventListener('change', yyApplyZipSearchUi); yyApplyZipSearchUi(); }); function yyIsDarkTheme() { return document.documentElement.getAttribute('data-bs-theme') === 'dark'; } function yyCountLines(text) { const v = String(text == null ? '' : text).replace(/\r\n/g, '\n').replace(/\r/g, '\n'); if (v === '') return 1; return (v.match(/\n/g) || []).length + 1; } function yyGetFindText() { if (yyFindCM) return yyFindCM.getValue(); const el = document.getElementById('find'); return el ? el.value : ''; } function yyGetReplaceText() { const el = document.getElementById('replace_text'); return el ? el.value : ''; } function yyUpdateMultiLineFlag() { const inputs = document.querySelectorAll('input[name="is_multiline"]'); if (!inputs.length) return; const findLines = yyCountLines(yyGetFindText()); const maxLines = Math.max(findLines, 1); inputs.forEach(function(el) { el.value = maxLines; }); } function yyAutoResizePlainTextarea(el, minPx, maxPx) { if (!el) return; el.style.height = 'auto'; const nextH = Math.max(minPx, Math.min(el.scrollHeight + 2, maxPx)); el.style.height = nextH + 'px'; } function yyFitFindEditorHeight() { if (!yyFindCM) return; const lineCount = Math.max(1, yyFindCM.lineCount()); const lineHeight = (typeof yyFindCM.defaultTextHeight === 'function') ? yyFindCM.defaultTextHeight() : 20; let h = (lineCount * lineHeight) + 12; const minPx = 96; const maxPx = Math.max(220, Math.floor(window.innerHeight * 0.42)); if (h < minPx) h = minPx; if (h > maxPx) h = maxPx; yyFindCM.setSize('100%', h + 'px'); } function yySubmitClosestForm(textarea) { const form = textarea ? textarea.closest('form') : null; if (form) form.submit(); } function yyCmModeByExt(ext) { ext = String(ext || '').toLowerCase(); if (ext === 'php' || ext === 'bak') return 'application/x-httpd-php'; if (ext === 'html' || ext === 'htm') return 'htmlmixed'; if (ext === 'xml') return 'xml'; if (ext === 'js') return 'javascript'; if (ext === 'ts') return 'text/typescript'; if (ext === 'css') return 'css'; if (ext === 'sql') return 'sql'; if (ext === 'py') return 'python'; if (ext === 'conf') return 'shell'; if (ext === 'csv') return 'shell'; if (ext === 'json') return 'application/json'; if (ext === 'yaml' || ext === 'yml') return 'yaml'; if (ext === 'md') return 'markdown'; if (ext === 'ini' || ext === 'properties') return 'properties'; return 'text/plain'; } function yyApplyFindTheme() { if (!yyFindCM) return; yyFindCM.setOption('theme', yyIsDarkTheme() ? 'dracula' : 'default'); yyFindCM.refresh(); } function yyApplyFindMode() { if (!yyFindCM) return; const extEl = document.getElementById('extSelect'); yyFindCM.setOption('mode', yyCmModeByExt(extEl ? extEl.value : '')); yyFindCM.refresh(); } function yyInitFindCodeMirror() { const ta = document.getElementById('find'); if (!ta || typeof CodeMirror === 'undefined') return null; yyFindCM = CodeMirror.fromTextArea(ta, { lineNumbers: true, mode: yyCmModeByExt(document.getElementById('extSelect') ? document.getElementById('extSelect').value : ''), theme: yyIsDarkTheme() ? 'dracula' : 'default', indentUnit: 4, indentWithTabs: false, lineWrapping: false, matchBrackets: true, autoCloseBrackets: true, viewportMargin: Infinity, extraKeys: { "Enter": function() { yySubmitClosestForm(ta); }, "Shift-Enter": function(cm) { cm.replaceSelection("\n", "end"); }, "Ctrl-Enter": function() { yySubmitClosestForm(ta); }, "Cmd-Enter": function() { yySubmitClosestForm(ta); } } }); const wrap = yyFindCM.getWrapperElement(); wrap.style.width = '100%'; wrap.style.minWidth = '0'; wrap.style.flex = '1 1 auto'; yyFindCM.on('change', function() { ta.value = yyFindCM.getValue(); yyUpdateMultiLineFlag(); yyFitFindEditorHeight(); }); setTimeout(function() { yyApplyFindTheme(); yyApplyFindMode(); yyFitFindEditorHeight(); yyUpdateMultiLineFlag(); }, 0); return yyFindCM; } (function yyBindThemeHook(){ try { const moBody = new MutationObserver(function() { yyApplyFindTheme(); }); moBody.observe(document.body, { attributes:true, attributeFilter:['class'] }); const moHtml = new MutationObserver(function() { yyApplyFindTheme(); }); moHtml.observe(document.documentElement, { attributes:true, attributeFilter:['data-bs-theme'] }); } catch(e) {} })(); document.addEventListener('DOMContentLoaded', function() { const findElement = document.getElementById('find'); const replaceElement = document.getElementById('replace_text'); const extSelect = document.getElementById('extSelect'); const pathInput = document.getElementById('path_filter'); yyInitFindCodeMirror(); if (findElement && !yyFindCM) { findElement.addEventListener('input', function() { yyUpdateMultiLineFlag(); yyAutoResizePlainTextarea(this, 96, Math.max(220, Math.floor(window.innerHeight * 0.42))); }); yyAutoResizePlainTextarea(findElement, 96, Math.max(220, Math.floor(window.innerHeight * 0.42))); } if (replaceElement) { replaceElement.addEventListener('input', function() { yyUpdateMultiLineFlag(); yyAutoResizePlainTextarea(this, 96, Math.max(220, Math.floor(window.innerHeight * 0.38))); }); yyAutoResizePlainTextarea(replaceElement, 96, Math.max(220, Math.floor(window.innerHeight * 0.38))); } yyUpdateMultiLineFlag(); function updatePath() { const zipInput = document.getElementById('zipSearchInput'); const zipMode = !!(zipInput && zipInput.checked); if (!zipMode && extSelect && pathInput && extSelect.value === "bak") { pathInput.value = "<?=BACKUP_ROOT?>"; } } updatePath(); if (extSelect) { extSelect.addEventListener("change", function() { updatePath(); yyApplyFindMode(); }); } }); window.addEventListener('resize', function() { if (yyFindCM) yyFitFindEditorHeight(); }); document.addEventListener('submit', function() { if (yyFindCM) { const taFind = document.getElementById('find'); if (taFind) taFind.value = yyFindCM.getValue(); } yyUpdateMultiLineFlag(); }); function handleEnter(e) { const id = e.target && e.target.id ? e.target.id : ''; if (id === 'find' && e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); const form = e.target.closest('form'); if (form) form.submit(); } } // hljs ์ด๊ธฐํ hljs.highlightAll(); // ALL ์ ํ์ ์๋ ์ ๋ ฅ ๊ธฐ๋ฅ document.addEventListener("DOMContentLoaded", function() { const extSelect = document.getElementById("extSelect"); const eXtInput = document.getElementById("eXtInput"); if (extSelect && eXtInput) { if (extSelect.options[extSelect.selectedIndex].value === "all") { if (!eXtInput.value) eXtInput.value = "zip,jpg,png,gif,pdf,mp4,avi,exe,dll,xlsx,xls"; } extSelect.addEventListener("change", function() { if (this.value === "all") { if (!eXtInput.value) eXtInput.value = "zip,jpg,png,gif,pdf,mp4,avi,exe,dll,xlsx,xls"; } }); } }); document.addEventListener("DOMContentLoaded", function() { if (typeof PR !== "undefined") { PR.prettyPrint(); } }); function ajaxSaveLine(btn) { console.log("--- [1] ajaxSaveLine ํธ์ถ๋จ ---"); console.log("ํด๋ฆญ๋ ๋ฒํผ ๊ฐ์ฒด:", btn); const unit = btn.closest('.edit-unit'); if (!unit) { console.error("โ ์๋ฌ: '.edit-unit' ๋ถ๋ชจ ์์๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. HTML ๊ตฌ์กฐ๋ฅผ ํ์ธํ์ธ์."); return; } const input = unit.querySelector('.edit-input'); const targetFile = btn.getAttribute('data-file'); const targetLine = btn.getAttribute('data-line'); const newContent = input ? input.value : null; console.log("--- [2] ์ถ์ถ๋ ๋ฐ์ดํฐ ---"); console.log("- ํ์ผ:", targetFile); console.log("- ๋ผ์ธ:", targetLine); console.log("- ๋ด์ฉ:", newContent); if (!targetFile || !targetLine) { console.error("โ ์๋ฌ: data-file ๋๋ data-line ์์ฑ์ด ๋น์ด์์ต๋๋ค."); return; } const fd = new FormData(); fd.append('action', 'single_replace'); fd.append('target_file', targetFile); fd.append('target_line', targetLine); fd.append('new_content', newContent); const noBak = document.querySelector('input[name="no_bak"]')?.checked ? '1' : '0'; fd.append('no_bak', noBak); console.log("- ๋ฐฑ์ ์ํจ(no_bak) ์ฌ๋ถ:", noBak); console.log("--- [3] ์๋ฒ๋ก ์ ์ก ์์ (fetch) ---"); fetch(window.location.href, { method: 'POST', body: fd }) .then(res => { console.log("- ์๋ต ์ํ(HTTP Status):", res.status); return res.text(); }) .then(data => { console.log("--- [4] ์๋ฒ ์๋ต ๋ณธ๋ฌธ ---"); console.log(data); const msg = (data || '').trim(); if (msg.includes("โ ")) { console.log("โ ๊ฒฐ๊ณผ: ์ฑ๊ณต!"); if (typeof showToast === 'function') showToast(msg, "success"); else alert(msg); if (input) { input.style.transition = 'background-color .25s ease'; input.style.backgroundColor = "#1e3a2f"; setTimeout(() => { input.style.backgroundColor = ""; }, 1000); } } else { console.warn("โ ๏ธ ๊ฒฐ๊ณผ: ์คํจ ํน์ ํ์ ๋ถ์ผ์น"); if (typeof showToast === 'function') showToast(msg || "์ ์ฅ ์คํจ", "error"); else alert(msg || "์ ์ฅ ์คํจ"); } }) .catch(err => { console.error("โ [5] ํต์ ์์ฒด ์คํจ:", err); if (typeof showToast === 'function') showToast("ํต์ ์ค๋ฅ ๋ฐ์", "error"); else alert("ํต์ ์ค๋ฅ ๋ฐ์"); }); } </script> <?php // Display current time (unchanged) echo '<span class="badge badge-outline secondary"> ์๊ฐ: ' . date("Y-m-d H:i:s") . '</span>'; // Display label for allowed IPs echo ' <span class="badge badge-soft secondary">์ ๊ทผ๊ฐ๋ฅ IP:</span> '; // Loop through allowed IPs and apply conditional border foreach ($allowed_ips as $ip) { $border_class = ($ip === $_SERVER['REMOTE_ADDR']) ? 'primary' : 'secondary'; echo '<span class="badge badge-outline ' . $border_class . '">' . $ip . '</span> '; } ?> <script> // GET ๊ฒ์ํผ์ด ๋๋ฌด ๊ธธ๋ฉด ์๋์ผ๋ก POST๋ก ์ ํ document.addEventListener('submit', function(e){ var form = e.target; if (!form || !form.tagName || form.tagName.toUpperCase() !== 'FORM') return; var method = (form.getAttribute('method') || 'GET').toUpperCase(); if (method !== 'GET') return; if (!form.querySelector('[name="find"]')) return; var actionEl = form.querySelector('input[name="action"]'); var actionVal = actionEl ? actionEl.value : ''; if (actionVal === 'single_replace' || actionVal === 'single_replace_block') return; var fd = new FormData(form); var qs = new URLSearchParams(fd).toString(); var MAX_GET_LEN = 1800; if (qs.length <= MAX_GET_LEN) return; e.preventDefault(); e.stopImmediatePropagation(); var postForm = document.createElement('form'); postForm.method = 'POST'; postForm.action = form.getAttribute('action') || window.location.pathname; postForm.style.display = 'none'; var target = form.getAttribute('target'); if (target) postForm.setAttribute('target', target); fd.forEach(function(value, key){ var input = document.createElement('input'); input.type = 'hidden'; input.name = key; input.value = value; postForm.appendChild(input); }); var autoPost = document.createElement('input'); autoPost.type = 'hidden'; autoPost.name = 'auto_post'; autoPost.value = '1'; postForm.appendChild(autoPost); document.body.appendChild(postForm); console.log('๐ฎ GET ๊ธธ์ด ์ด๊ณผ โ POST๋ก ์๋ ์ ํ', qs.length); postForm.submit(); }, true); </script> <?php include "yyy_foot.php"; ?> <script src="yy__theme.js?v=1.3"></script> <script src="_docs/yy_alarm_ds2gt_final_fulld.js.php?v=1.22"></script> <script src="yy_drag_resize.js?v=1.5"></script> </div> </body> </html>
โจyyy_find.php
70,938 bytes
::
php
Y:0px 0%
X:0px 0%
Split:--
Line:1
A0
Aโ
A+
Lh0
Lhโ
Lh+
pre+
ฦ ํจ์ / ํด๋์ค ๋ชฉ๋ก
โ
๐พ
Aa
.*
bF
1
๐
๐
๊ฒ์์ด๋ฅผ ๋จผ์ ์ ๋ ฅํ์ธ์.
1
At
์ ์ฒด์ ์ฉ
๋ค์์ฐพ๊ธฐ
1๊ฐ์ ์ฉ
-----------