PHP WebShell

Текущая директория: /var/www/bitcardoApp/backyard/models/giftcards

Просмотр файла: bulk_preview.php

<?php
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');

// capture any warnings/notices so we don't break JSON
ob_start();
ini_set('display_errors','0');
error_reporting(E_ALL);

function out($data, int $code=200){
    http_response_code($code);
    $buf = ob_get_clean();
    if ($buf) $data['_diag'] = substr($buf, 0, 500);
    echo json_encode($data);
    exit;
}

function scheme_host(): array {
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host   = $_SERVER['HTTP_HOST'] ?? 'localhost';
    return [$scheme, $host];
}

/**
 * Normalize whatever is in card_trade_images.path into an absolute URL.
 * Accepted forms (examples of $p):
 * - "2025/10/PK3737/file.jpg"
 * - "uploads/cards/2025/10/PK3737/file.jpg"
 * - "backyard/uploads/cards/2025/10/PK3737/file.jpg"
 * - "../../uploads/cards/2025/10/PK3737/file.jpg"
 * - Full "https://domain/backyard/uploads/cards/2025/10/PK3737/file.jpg"
 */
function build_image_url(string $p): string {
    $p = trim($p);
    if ($p === '') return '';

    // If already absolute URL, return as-is
    if (preg_match('~^https?://~i', $p)) return $p;

    // Remove leading ../ or ./ and leading slash noise
    $p = preg_replace('~^(\.\./)+~', '', $p);
    $p = preg_replace('~^\./~', '', $p);
    $p = ltrim($p, '/');

    // If it starts with "backyard/uploads/cards/..." we're almost there
    if (stripos($p, 'backyard/uploads/cards/') === 0) {
        [$sch, $host] = scheme_host();
        return $sch . '://' . $host . '/' . $p;
    }

    // If it starts with "uploads/cards/...", prefix "backyard/"
    if (stripos($p, 'uploads/cards/') === 0) {
        [$sch, $host] = scheme_host();
        return $sch . '://' . $host . '/backyard/' . $p;
    }

    // Common case: just the year/month/... path from DB ("2025/10/.../file.jpg")
    // Prepend "backyard/uploads/cards/"
    [$sch, $host] = scheme_host();
    return $sch . '://' . $host . '/backyard/uploads/cards/' . $p;
}

try {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        out(['success'=>false,'message'=>'Method not allowed'], 405);
    }

    // --- DB include (correct relative path from models/giftcards/) ---
    $dbPath = __DIR__ . '/../../config/db_config.php';
    if (!file_exists($dbPath)) out(['success'=>false,'message'=>'DB config missing'], 500);
    include_once $dbPath;
    if (!isset($conn) || !($conn instanceof mysqli)) {
        out(['success'=>false,'message'=>'DB connection not available'], 500);
    }

    // --- payload ---
    $raw = file_get_contents('php://input');
    $payload = json_decode($raw, true);
    $refs = $payload['refs'] ?? [];
    if (!is_array($refs) || empty($refs)) out(['success'=>false,'message'=>'No refs'], 400);

    // sanitize & limit
    $refs = array_values(array_unique(array_filter(array_map(fn($r)=> substr(trim((string)$r), 0, 64), $refs))));
    if (empty($refs)) out(['success'=>false,'message'=>'No refs'], 400);
    if (count($refs) > 100) $refs = array_slice($refs, 0, 100);

    // build IN()
    $in = implode(',', array_map(fn($r) => "'" . mysqli_real_escape_string($conn, $r) . "'", $refs));

    // --- main rows ---
    $sql = "
        SELECT ct.trade_id, ct.card_ref, ct.batch_ref, ct.card_value, ct.card_curr,
               ct.est_payout_ngn, ct.trade_status, cb.card_brand, gc.demon
        FROM card_trade ct
        LEFT JOIN card_brands cb ON cb.cbrand_id = ct.cbrand_id
        LEFT JOIN gift_cards gc   ON gc.gc_id     = ct.gc_id
        WHERE ct.card_ref IN ($in)
        ORDER BY ct.trade_created DESC
    ";
    $rows = [];
    if ($res = mysqli_query($conn, $sql)) {
        while ($r = mysqli_fetch_assoc($res)) $rows[] = $r;
        mysqli_free_result($res);
    } else {
        out(['success'=>false,'message'=>'Query failed'], 500);
    }

    // --- first image per trade (ONLY_FULL_GROUP_BY safe) ---
    $thumbs = [];
    if (!empty($rows)) {
        $ids = implode(',', array_map(fn($r) => (int)$r['trade_id'], $rows));
        $iq = "
            SELECT i.trade_id, i.path
            FROM card_trade_images i
            INNER JOIN (
                SELECT trade_id, MIN(image_id) AS min_id
                FROM card_trade_images
                WHERE trade_id IN ($ids)
                GROUP BY trade_id
            ) x ON x.trade_id = i.trade_id AND x.min_id = i.image_id
        ";
        if ($ir = mysqli_query($conn, $iq)) {
            while ($irow = mysqli_fetch_assoc($ir)) {
                $thumbs[(int)$irow['trade_id']] = $irow['path'];
            }
            mysqli_free_result($ir);
        }
    }

    foreach ($rows as &$r) {
        $p = $thumbs[(int)$r['trade_id']] ?? '';
        $r['thumb'] = $p ? build_image_url($p) : '';
    }
    unset($r);

    out(['success'=>true,'items'=>$rows]);
}
catch (Throwable $e) {
    out(['success'=>false,'message'=>'Server error','_err'=>substr($e->getMessage(),0,200)], 500);
}

Выполнить команду


Для локальной разработки. Не используйте в интернете!