403Webshell
Server IP : 173.209.174.21  /  Your IP : 216.73.216.89
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux wcfs-server 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64
User : nodor ( 1000)
PHP Version : 8.3.6
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/grangestation/api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/grangestation/api/backup.php
<?php
declare(strict_types=1);

if (PHP_SAPI !== 'cli') {
    http_response_code(404);
    exit('Not found');
}

$config = require __DIR__ . '/config.php';

function backup_db(): PDO {
    global $config;
    $dsn = sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4', $config['db_host'], $config['db_name']);
    return new PDO($dsn, $config['db_user'], $config['db_pass'], [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]);
}

function clean_header(string $value): string {
    return trim(preg_replace('/[\r\n]+/', ' ', $value));
}

function sql_value(mixed $value): string {
    if ($value === null) return 'NULL';
    if (is_int($value) || is_float($value)) return (string)$value;
    return "'" . str_replace(["\\", "'"], ["\\\\", "\\'"], (string)$value) . "'";
}

function write_sql_dump(PDO $pdo, string $path, array $tables): void {
    $out = fopen($path, 'wb');
    fwrite($out, "-- Grange Station backup\n-- Created " . date('c') . "\n\nSET FOREIGN_KEY_CHECKS=0;\n\n");
    foreach ($tables as $table) {
        try {
            $create = $pdo->query("SHOW CREATE TABLE `{$table}`")->fetch();
        } catch (Throwable $error) {
            fwrite($out, "-- Skipped missing table `{$table}`\n\n");
            continue;
        }
        if (!$create) continue;
        fwrite($out, "DROP TABLE IF EXISTS `{$table}`;\n");
        fwrite($out, ($create['Create Table'] ?? array_values($create)[1]) . ";\n\n");

        $rows = $pdo->query("SELECT * FROM `{$table}`")->fetchAll();
        foreach ($rows as $row) {
            $columns = array_map(fn($column) => "`{$column}`", array_keys($row));
            $values = array_map('sql_value', array_values($row));
            fwrite($out, "INSERT INTO `{$table}` (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $values) . ");\n");
        }
        fwrite($out, "\n");
    }
    fwrite($out, "SET FOREIGN_KEY_CHECKS=1;\n");
    fclose($out);
}

function write_csv(PDO $pdo, string $path, string $sql): void {
    $rows = $pdo->query($sql)->fetchAll();
    $out = fopen($path, 'wb');
    if (!$rows) {
        fclose($out);
        return;
    }
    fputcsv($out, array_keys($rows[0]));
    foreach ($rows as $row) fputcsv($out, $row);
    fclose($out);
}

function smtp_read($socket): string {
    $response = '';
    while (($line = fgets($socket, 515)) !== false) {
        $response .= $line;
        if (isset($line[3]) && $line[3] === ' ') break;
    }
    return $response;
}

function smtp_command($socket, string $command, array $expected): void {
    fwrite($socket, $command . "\r\n");
    $response = smtp_read($socket);
    $code = (int)substr($response, 0, 3);
    if (!in_array($code, $expected, true)) {
        throw new RuntimeException('SMTP command failed: ' . trim($response));
    }
}

function send_backup_email(string $subject, string $body, string $attachmentPath): bool {
    global $config;
    if (empty($config['smtp_host']) || empty($config['smtp_user']) || empty($config['smtp_pass'])) return false;

    $host = (string)$config['smtp_host'];
    $port = (int)($config['smtp_port'] ?? 465);
    $secure = (string)($config['smtp_secure'] ?? 'ssl');
    $target = $secure === 'ssl' ? "ssl://{$host}:{$port}" : "tcp://{$host}:{$port}";
    $socket = @stream_socket_client($target, $errno, $errstr, 20, STREAM_CLIENT_CONNECT);
    if (!$socket) throw new RuntimeException("SMTP connection failed: {$errstr}");
    stream_set_timeout($socket, 20);

    smtp_read($socket);
    smtp_command($socket, 'EHLO grangestation.com', [250]);
    if ($secure === 'tls') {
        smtp_command($socket, 'STARTTLS', [220]);
        if (!stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
            throw new RuntimeException('SMTP TLS failed.');
        }
        smtp_command($socket, 'EHLO grangestation.com', [250]);
    }
    smtp_command($socket, 'AUTH LOGIN', [334]);
    smtp_command($socket, base64_encode((string)$config['smtp_user']), [334]);
    smtp_command($socket, base64_encode((string)$config['smtp_pass']), [235]);

    $to = clean_header((string)($config['mail_to'] ?? 'events@grangestation.com'));
    $from = clean_header((string)($config['mail_from'] ?? $config['smtp_user']));
    $boundary = 'grange-backup-' . bin2hex(random_bytes(8));
    $filename = basename($attachmentPath);
    $mime = str_ends_with($filename, '.zip') ? 'application/zip' : 'application/gzip';
    $attachment = chunk_split(base64_encode(file_get_contents($attachmentPath) ?: ''));

    smtp_command($socket, "MAIL FROM:<{$from}>", [250]);
    smtp_command($socket, "RCPT TO:<{$to}>", [250, 251]);
    smtp_command($socket, 'DATA', [354]);
    $message = implode("\r\n", [
        "From: Grange Station <{$from}>",
        "To: {$to}",
        "Subject: " . clean_header($subject),
        "MIME-Version: 1.0",
        "Content-Type: multipart/mixed; boundary=\"{$boundary}\"",
        "",
        "--{$boundary}",
        "Content-Type: text/plain; charset=UTF-8",
        "",
        $body,
        "",
        "--{$boundary}",
        "Content-Type: {$mime}; name=\"{$filename}\"",
        "Content-Transfer-Encoding: base64",
        "Content-Disposition: attachment; filename=\"{$filename}\"",
        "",
        $attachment,
        "--{$boundary}--",
    ]);
    fwrite($socket, $message . "\r\n.\r\n");
    $response = smtp_read($socket);
    smtp_command($socket, 'QUIT', [221]);
    fclose($socket);
    return ((int)substr($response, 0, 3)) === 250;
}

function zip_directory(string $sourceDir, string $zipPath): void {
    if (!class_exists('ZipArchive')) {
        throw new RuntimeException('ZipArchive is not installed.');
    }
    $zip = new ZipArchive();
    if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
        throw new RuntimeException('Could not create zip file.');
    }
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($sourceDir, FilesystemIterator::SKIP_DOTS),
        RecursiveIteratorIterator::LEAVES_ONLY
    );
    foreach ($files as $file) {
        if (!$file->isFile()) continue;
        $zip->addFile($file->getPathname(), substr($file->getPathname(), strlen($sourceDir) + 1));
    }
    $zip->close();
}

function archive_directory(string $sourceDir, string $archivePath): string {
    try {
        zip_directory($sourceDir, $archivePath);
        return $archivePath;
    } catch (Throwable $zipError) {
        $tarPath = preg_replace('/\.zip$/', '.tar', $archivePath);
        $gzPath = $tarPath . '.gz';
        if (file_exists($tarPath)) unlink($tarPath);
        if (file_exists($gzPath)) unlink($gzPath);
        $tar = new PharData($tarPath);
        $tar->buildFromDirectory($sourceDir);
        $tar->compress(Phar::GZ);
        unset($tar);
        if (file_exists($tarPath)) unlink($tarPath);
        return $gzPath;
    }
}

$pdo = backup_db();
$backupRoot = dirname(__DIR__) . '/backups';
if (!is_dir($backupRoot)) mkdir($backupRoot, 0750, true);

$stamp = date('Y-m-d_His');
$workDir = "{$backupRoot}/grange-station-backup-{$stamp}";
mkdir($workDir, 0750, true);

$tables = [
    'booking_requests',
    'booking_request_addons',
    'confirmed_bookings',
    'availability_blocks',
    'contact_messages',
    'site_settings',
    'rental_addons',
    'vendor_categories',
    'preferred_vendors',
    'admin_users',
];

write_sql_dump($pdo, "{$workDir}/database.sql", $tables);
write_csv($pdo, "{$workDir}/booking_requests.csv", "
    SELECT r.id, r.public_id, r.status, r.request_type, r.contact_name, r.contact_email, r.contact_phone,
           r.requested_date, TIME_FORMAT(r.requested_start, '%H:%i') AS requested_start,
           TIME_FORMAT(r.requested_end, '%H:%i') AS requested_end, r.guest_count, r.event_type,
           r.space_preference, r.vendor_help, r.extra_hours, r.price_adjustment, r.amount_owed,
           GROUP_CONCAT(a.addon_name ORDER BY a.id SEPARATOR '; ') AS addons,
           r.message, r.created_at, r.updated_at
    FROM booking_requests r
    LEFT JOIN booking_request_addons a ON a.request_id = r.id
    GROUP BY r.id
    ORDER BY r.created_at DESC
");
write_csv($pdo, "{$workDir}/confirmed_bookings.csv", "
    SELECT id, request_id, title, event_date, TIME_FORMAT(start_time, '%H:%i') AS start_time,
           TIME_FORMAT(end_time, '%H:%i') AS end_time, guest_count, extra_hours, price_adjustment,
           amount_owed, status, private_notes, created_at, updated_at
    FROM confirmed_bookings
    ORDER BY event_date, start_time
");
write_csv($pdo, "{$workDir}/availability_blocks.csv", "
    SELECT id, title, block_date, TIME_FORMAT(start_time, '%H:%i') AS start_time,
           TIME_FORMAT(end_time, '%H:%i') AS end_time, reason, is_public, created_at, updated_at
    FROM availability_blocks
    ORDER BY block_date, start_time
");
write_csv($pdo, "{$workDir}/contact_messages.csv", "
    SELECT id, contact_name, contact_email, contact_phone, reason, message, created_at
    FROM contact_messages
    ORDER BY created_at DESC
");

$zipPath = archive_directory($workDir, "{$backupRoot}/grange-station-backup-{$stamp}.zip");

$sizeMb = round(filesize($zipPath) / 1024 / 1024, 2);
$body = "Grange Station backup created {$stamp}.\n\nAttached: " . basename($zipPath) . "\nSize: {$sizeMb} MB\nServer path: {$zipPath}\n";
$emailed = filesize($zipPath) <= 8 * 1024 * 1024 && send_backup_email('Grange Station booking backup ' . date('Y-m-d'), $body, $zipPath);

echo "Backup created: {$zipPath}\n";
echo "Email sent: " . ($emailed ? 'yes' : 'no') . "\n";

Youez - 2016 - github.com/yon3zu
LinuXploit