🐘
index_copy.php
Back
📝 Php ⚡ Executable Ctrl+S: Save • Ctrl+R: Run • Ctrl+F: Find
<?php // Force login + disable caching session_start(); require_once __DIR__ . '/../core/db_config.php'; // Anti-cache headers (dev) header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Expires: 0'); // Redirect if not logged in if (empty($_SESSION['username'])) { $redirect = urlencode($_SERVER['REQUEST_URI'] ?? '/'); header("Location: /core/auth/login.php?redirect={$redirect}"); exit; } // Cache-busting helper (absolute & relative paths) function asset($path) { $isAbsolute = strlen($path) && $path[0] === '/'; $abs = $isAbsolute ? rtrim($_SERVER['DOCUMENT_ROOT'], '/') . $path : __DIR__ . '/' . $path; $v = is_file($abs) ? filemtime($abs) : time(); return $path . '?v=' . $v; } // Handle SFTP connect form $msg = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $ip = trim($_POST['sftp_ip'] ?? ''); $user = trim($_POST['sftp_user'] ?? ''); $pass = trim($_POST['sftp_pass'] ?? ''); $port = (int)($_POST['sftp_port'] ?? 22); if ($ip && $user && $pass) { $conn = @ssh2_connect($ip, $port); if ($conn && @ssh2_auth_password($conn, $user, $pass)) { // Optionally keep credentials in session (short-lived) — uncomment if desired: // $_SESSION['sftp'] = ['ip'=>$ip,'user'=>$user,'pass'=>$pass,'port'=>$port]; $msg = "✅ Connected successfully to <b>" . htmlspecialchars($ip) . "</b> on port <b>" . intval($port) . "</b>."; } else { $msg = "❌ Connection failed. Please check your credentials."; } } else { $msg = "⚠️ All fields are required."; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>App Index</title> <!-- Shared overlay CSS --> <link rel="stylesheet" href="<?= asset('/core/css/overlay.css') ?>"> <style> html, body { height:100%; margin:0; overscroll-behavior-y:contain; } body { background:#0b0f14; color:#e6edf3; font-family:system-ui,-apple-system,Segoe UI,Roboto,Inter,"Helvetica Neue",Arial; } .body-lock { overflow:hidden!important; touch-action:none; } .topbar { position:sticky; top:0; z-index:5; background:linear-gradient(180deg,rgba(11,15,20,.95),rgba(11,15,20,.85)); border-bottom:1px solid #1e2633; backdrop-filter:blur(6px); } .topbar-inner { max-width:1000px; margin:0 auto; padding:.75rem; display:flex; align-items:center; gap:.75rem; } #buttonRow { flex:1 1 auto; min-width:0; display:flex; gap:.75rem; align-items:center; overflow-x:auto; overflow-y:hidden; scrollbar-width:thin; -webkit-overflow-scrolling:touch; } #menuContainer { flex:0 0 auto; margin-left:.25rem; position:relative; } .chip { flex:0 0 auto; border:1px solid #2a3648; background:#1a2332; color:#e6edf3; padding:.55rem .9rem; border-radius:999px; font-weight:600; cursor:pointer; transition:background .15s ease; } .chip:hover { background:#263244; } .container { max-width:1000px; margin:1.25rem auto; padding:0 .75rem; } .lead { color:#9aa4b2; } .menu-trigger { width:38px; text-align:center; } .menu-list { display:none; position:absolute; right:0; top:calc(100% + 6px); background:#1a2332; border:1px solid #2a3648; border-radius:10px; min-width:180px; padding:.25rem 0; z-index:9999; box-shadow:0 10px 30px rgba(0,0,0,.3); } .menu-list.open { display:block; } .menu-item { display:block; width:100%; text-align:left; background:none; border:none; color:#e6edf3; padding:.6rem 1rem; cursor:pointer; font:inherit; } .menu-item:hover { background:#263244; } /* SFTP Form */ form.sftp-form { margin-top: 2rem; background: #1a2332; border: 1px solid #2a3648; border-radius: 12px; padding: 1.5rem; max-width: 460px; } form.sftp-form label { display:block; margin-top:0.75rem; font-weight:600; } form.sftp-form .row { display:flex; gap:0.5rem; align-items:center; } form.sftp-form input[type="text"], form.sftp-form input[type="password"], form.sftp-form input[type="number"] { width:100%; padding:0.6rem; margin-top:0.3rem; border-radius:6px; border:1px solid #2a3648; background:#0f1725; color:#e6edf3; } .pw-wrap { position:relative; display:flex; width:100%; } .pw-toggle { position:absolute; right:8px; top:50%; transform:translateY(-50%); background:transparent; border:none; color:#9aa4b2; cursor:pointer; padding:6px; border-radius:6px; } form.sftp-form button[type="submit"] { margin-top:1rem; padding:0.6rem 1.2rem; border:none; border-radius:8px; background:linear-gradient(135deg,#3b82f6,#9333ea); color:white; font-weight:600; cursor:pointer; } .msg { margin-top:1rem; font-weight:600; } </style> </head> <body> <?php include __DIR__ . '/../core/auth/header.php'; ?> <header class="topbar" aria-label="Top navigation"> <div class="topbar-inner"> <div id="buttonRow" role="tablist" aria-label="App sections"></div> <div id="menuContainer" aria-label="More actions"></div> </div> </header> <main class="container"> <h1>Modular Overlay Index</h1> <p class="lead">Each module adds its own button and overlay content. If modules register extra actions, a 3-dots menu appears on the right.</p> <!-- 🔹 Simple SFTP Connect Form --> <form method="POST" class="sftp-form" id="sftpForm" autocomplete="off"> <label for="sftp_ip">Server IP / Host</label> <input type="text" id="sftp_ip" name="sftp_ip" value="files.devbrewing" required> <label for="sftp_user">Username</label> <input type="text" id="sftp_user" name="sftp_user" value="<?= htmlspecialchars($_SESSION['username'] ?? '') ?>" required> <label for="sftp_pass">Password</label> <div class="pw-wrap"> <input type="password" id="sftp_pass" name="sftp_pass" required aria-describedby="pwHelp"> <button type="button" class="pw-toggle" id="togglePw" aria-label="Show password">👁️</button> </div> <label for="sftp_port">Port</label> <input type="number" id="sftp_port" name="sftp_port" value="22" required> <button type="submit">Connect</button> </form> <?php if ($msg): ?> <div class="msg"><?= $msg ?></div> <?php endif; ?> </main> <script> window.AppItems = []; window.AppMenu = []; </script> <script src="<?= asset('/core/js/overlay.js') ?>" defer></script> <script src="<?= asset('menu.js') ?>" defer></script> <script src="<?= asset('filemanager.js') ?>" defer></script> <script defer> // toggle password visibility document.addEventListener('DOMContentLoaded', () => { const toggle = document.getElementById('togglePw'); const pass = document.getElementById('sftp_pass'); if (!toggle || !pass) return; toggle.addEventListener('click', () => { if (pass.type === 'password') { pass.type = 'text'; toggle.textContent = '🙈'; // eye closed toggle.setAttribute('aria-label','Hide password'); } else { pass.type = 'password'; toggle.textContent = '👁️'; // eye open toggle.setAttribute('aria-label','Show password'); } }); }); </script> <!-- render chips & menu (unchanged from your layout) --> <script defer> document.addEventListener('DOMContentLoaded', () => { const row = document.getElementById('buttonRow'); row.innerHTML = ''; (window.AppItems || []).forEach((item, i) => { const btn = document.createElement('button'); btn.className = 'chip'; btn.textContent = item.title || `Item ${i+1}`; btn.onclick = () => window.AppOverlay && AppOverlay.open(window.AppItems, i, btn); row.appendChild(btn); }); const menuContainer = document.getElementById('menuContainer'); menuContainer.innerHTML = ''; const menuItems = window.AppMenu || []; if (menuItems.length > 0) { const trigger = document.createElement('button'); trigger.className = 'chip menu-trigger'; trigger.textContent = '⋮'; menuContainer.appendChild(trigger); const dropdown = document.createElement('div'); dropdown.className = 'menu-list'; menuContainer.appendChild(dropdown); menuItems.forEach((m, idx) => { const item = document.createElement('button'); item.className = 'menu-item'; item.textContent = m.label || `Action ${idx+1}`; item.onclick = () => { dropdown.classList.remove('open'); m.action && m.action(); }; dropdown.appendChild(item); }); trigger.addEventListener('click', (e)=>{ e.stopPropagation(); dropdown.classList.toggle('open'); }); document.addEventListener('click', (e)=>{ if (!menuContainer.contains(e.target)) dropdown.classList.remove('open'); }); } }); </script> </body> </html>