root = realpath(__DIR__);
// 2. Mevcut çalışma dizinini ayarla
$sessCwd = $_SESSION[‘sys_cwd’] ?? $this->root;
// Eğer session’daki dizin root’un dışındaysa veya yoksa, root’a sıfırla
if ($this->isAllowedPath($sessCwd) && is_dir($sessCwd)) {
$this->cwd = $sessCwd;
} else {
$this->cwd = $this->root;
$_SESSION[‘sys_cwd’] = $this->root;
}
}
/**
* ROOT JAIL KONTROLÜ
* Verilen yolun, kök dizin sınırları içinde olup olmadığını kontrol eder.
*/
private function isAllowedPath($path) {
$realRoot = $this->root;
$realPath = realpath($path);
// Dosya henüz yoksa (yeni oluşturulacaksa) üst klasörüne bak
if ($realPath === false) {
$realPath = realpath(dirname($path));
}
// Eğer yol çözülemiyorsa veya Root ile başlamıyorsa yasakla
if ($realPath && strpos($realPath, $realRoot) === 0) {
return true;
}
return false;
}
private function sendJSON($status, $message = », $data = []) {
header(‘Content-Type: application/json’);
echo json_encode([
‘status’ => $status,
‘message’ => $message,
‘data’ => $data,
‘cwd’ => $this->cwd,
‘csrf’ => $_SESSION[‘csrf_token’] ?? »
]);
exit;
}
private function checkAuth() {
if (!isset($_SESSION[‘sys_auth’]) || $_SESSION[‘sys_auth’] !== true) {
$this->sendJSON(‘error’, ‘Unauthorized’);
}
}
private function validateCSRF($token) {
if (!isset($_SESSION[‘csrf_token’]) || $token !== $_SESSION[‘csrf_token’]) {
$this->sendJSON(‘error’, ‘Invalid Security Token’);
}
}
public function handleRequest() {
$method = $_SERVER[‘REQUEST_METHOD’];
// 1. Dosya Yükleme
if ($method === ‘POST’ && isset($_FILES[‘file’])) {
$this->checkAuth();
$this->validateCSRF($_POST[‘csrf’] ?? »);
// Hedef dizin zaten Constructor’da jail kontrolünden geçtiği için güvenli
$target = $this->cwd . DIRECTORY_SEPARATOR . basename($_FILES[‘file’][‘name’]);
// Ekstra kontrol: Yüklenen dosya adı ile directory traversal denenirse
if (!$this->isAllowedPath(dirname($target))) {
$this->sendJSON(‘error’, ‘Security Violation: Path traversal detected’);
}
if (move_uploaded_file($_FILES[‘file’][‘tmp_name’], $target)) {
$this->sendJSON(‘ok’, ‘File uploaded successfully’);
} else {
$this->sendJSON(‘error’, ‘Upload failed. Check permissions.’);
}
}
// 2. JSON Komutları
$input = json_decode(file_get_contents(‘php://input’), true);
if (!$input) return;
$action = $input[‘action’] ?? »;
if ($action !== ‘login’) {
$this->checkAuth();
if(isset($input[‘csrf’])) $this->validateCSRF($input[‘csrf’]);
}
switch ($action) {
case ‘login’:
if (($input[‘key’] ?? ») === ACCESS_PASS) {
$_SESSION[‘sys_auth’] = true;
$_SESSION[‘csrf_token’] = bin2hex(random_bytes(32));
$this->sendJSON(‘ok’, ‘Authorized’, [‘token’ => $_SESSION[‘csrf_token’]]);
}
$this->sendJSON(‘error’, ‘Invalid credentials’);
break;
case ‘list’:
$reqPath = $input[‘path’] ?? $this->cwd;
// GÜVENLİK: Eğer istenen yol root dışındaysa, kök dizine zorla
if (!$this->isAllowedPath($reqPath)) {
$reqPath = $this->root;
}
if (is_dir($reqPath)) {
$_SESSION[‘sys_cwd’] = realpath($reqPath);
$this->cwd = $_SESSION[‘sys_cwd’];
$items = $this->scanDir($this->cwd);
$this->sendJSON(‘ok’, », $items);
} else {
$this->sendJSON(‘error’, ‘Directory not found’);
}
break;
case ‘read’:
$file = $input[‘file’] ?? »;
// GÜVENLİK: Dosya root içinde mi?
if (!$this->isAllowedPath($file)) $this->sendJSON(‘error’, ‘Access Denied (Jail)’);
if (is_file($file)) {
if(filesize($file) > 1024 * 1024) $this->sendJSON(‘error’, ‘File too large to edit online’);
$content = file_get_contents($file);
$this->sendJSON(‘ok’, », [‘content’ => $content]);
}
$this->sendJSON(‘error’, ‘File not found’);
break;
case ‘save’:
$file = $input[‘file’] ?? »;
// GÜVENLİK: Kaydedilecek yer root içinde mi?
if (!$this->isAllowedPath($file)) $this->sendJSON(‘error’, ‘Access Denied (Jail)’);
$content = $input[‘content’] ?? »;
if (is_writable(dirname($file))) {
file_put_contents($file, $content);
$this->sendJSON(‘ok’, ‘File saved’);
} else {
$this->sendJSON(‘error’, ‘Permission denied’);
}
break;
case ‘rename’:
$old = $input[‘old’] ?? »;
$newVal = $input[‘new’] ?? »;
// Sadece dosya ismini al, path’i temizle (../ engellemek için basename)
$new = dirname($old) . DIRECTORY_SEPARATOR . basename($newVal);
// GÜVENLİK: Hem eski dosya hem yeni hedef root içinde olmalı
if (!$this->isAllowedPath($old) || !$this->isAllowedPath($new)) {
$this->sendJSON(‘error’, ‘Access Denied (Jail)’);
}
if (rename($old, $new)) $this->sendJSON(‘ok’, ‘Renamed’);
else $this->sendJSON(‘error’, ‘Rename failed’);
break;
case ‘delete’:
$path = $input[‘path’] ?? »;
// GÜVENLİK: Silinecek yer root içinde mi?
// Root dizininin kendisini silmeyi de engelle
if (!$this->isAllowedPath($path) || realpath($path) === $this->root) {
$this->sendJSON(‘error’, ‘Access Denied (Jail)’);
}
$this->deleteRecursive($path);
$this->sendJSON(‘ok’, ‘Deleted’);
break;
case ‘mkdir’:
$name = $input[‘name’] ?? »;
// Sadece isim al, path’i temizle
$path = $this->cwd . DIRECTORY_SEPARATOR . basename($name);
// GÜVENLİK:
if (!$this->isAllowedPath($path)) $this->sendJSON(‘error’, ‘Access Denied (Jail)’);
if (@mkdir($path)) $this->sendJSON(‘ok’, ‘Folder created’);
else $this->sendJSON(‘error’, ‘Failed to create folder’);
break;
}
}
private function scanDir($dir) {
$files = @scandir($dir);
$res = [‘folders’ => [], ‘files’ => []];
if (!$files) return $res;
foreach ($files as $f) {
if ($f == ‘.’ || $f == ‘..’) continue;
$path = $dir . DIRECTORY_SEPARATOR . $f;
$info = [
‘name’ => $f,
‘path’ => $path,
‘size’ => is_file($path) ? $this->formatSize(@filesize($path)) : ‘-‘,
‘perms’ => substr(sprintf(‘%o’, fileperms($path)), -4)
];
if (is_dir($path)) $res[‘folders’][] = $info;
else $res[‘files’][] = $info;
}
return $res;
}
private function formatSize($bytes) {
$units = [‘B’, ‘KB’, ‘MB’, ‘GB’];
$power = $bytes > 0 ? floor(log($bytes, 1024)) : 0;
return number_format($bytes / pow(1024, $power), 2, ‘.’, ‘,’) . ‘ ‘ . $units[$power];
}
private function deleteRecursive($path) {
// Ekstra güvenlik: Root dışına çıkma
if (!$this->isAllowedPath($path)) return;
if (is_dir($path)) {
$files = array_diff(scandir($path), [‘.’, ‘..’]);
foreach ($files as $file) $this->deleteRecursive($path . DIRECTORY_SEPARATOR . $file);
rmdir($path);
} elseif (is_file($path)) {
unlink($path);
}
}
}
$api = new FileManagerAPI();
$api->handleRequest();
// Oturum Kontrolü (Login Ekranı vs App Ekranı)
if (!isset($_SESSION[‘sys_auth’])) {
?>
Authentication
| Name | Size | Perms | Actions |
|---|
