<?php
/**
 * upload-audit.php — cum se urcă și se afișează pozele (DOAR CITEȘTE).
 *   https://admingrandfather.com/upload-audit.php?key=CHEIA
 * Apasă „Descarcă .txt” și trimite fișierul. Șterge scriptul după folosire.
 */
const KEY = '20657f68cc21b5dac9eefbd54f113db4';
if (!isset($_GET['key']) || !hash_equals(KEY, (string)$_GET['key'])) { http_response_code(404); exit('Not found'); }
@set_time_limit(120);
error_reporting(E_ALL); ini_set('display_errors', '1');
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }

$DOC = rtrim($_SERVER['DOCUMENT_ROOT'] ?: __DIR__, '/');
$R = ['# UPLOAD AUDIT ' . ($_SERVER['HTTP_HOST'] ?? '') . ' · ' . date('Y-m-d H:i') . ' · PHP ' . PHP_VERSION . ' · ' . PHP_SAPI];

/* 1. limite + librării de imagine */
$R[] = "\n## PHP";
foreach (['upload_max_filesize', 'post_max_size', 'max_file_uploads', 'memory_limit', 'max_execution_time', 'max_input_time', 'file_uploads'] as $k) $R[] = "$k = " . ini_get($k);
if (function_exists('gd_info')) { $g = gd_info(); $R[] = 'GD: ' . ($g['GD Version'] ?? '?') . ' · WebP: ' . (!empty($g['WebP Support']) ? 'DA' : 'NU') . ' · JPEG: ' . (!empty($g['JPEG Support']) ? 'DA' : 'NU') . ' · PNG: ' . (!empty($g['PNG Support']) ? 'DA' : 'NU') . ' · AVIF: ' . (!empty($g['AVIF Support']) ? 'DA' : 'NU'); }
else $R[] = 'GD: LIPSĂ';
$R[] = 'Imagick: ' . (class_exists('Imagick') ? 'DA · WEBP ' . (in_array('WEBP', Imagick::queryFormats('WEBP'), true) ? 'DA' : 'NU') : 'NU');
$R[] = 'exif_read_data: ' . (function_exists('exif_read_data') ? 'DA' : 'NU') . ' · imagewebp: ' . (function_exists('imagewebp') ? 'DA' : 'NU');

/* 2. fișierele care urcă / afișează / șterg poze */
$rx = '/move_uploaded_file|\$_FILES|vehicle_images|equipment_images|image_path|main_image|imagecreatefrom|imagewebp|sort_order|uploads\/vehicles|gallery/i';
$found = [];
$it = new RecursiveIteratorIterator(new RecursiveCallbackFilterIterator(
    new RecursiveDirectoryIterator($DOC, FilesystemIterator::SKIP_DOTS),
    function ($f) { return $f->isDir() ? !preg_match('/^(\.git|\.trash|\.cache|node_modules|vendor|uploads|cache|tmp|logs?|.*backup.*|_bak.*)$/i', $f->getFilename()) : true; }
), RecursiveIteratorIterator::LEAVES_ONLY, RecursiveIteratorIterator::CATCH_GET_CHILD);
foreach ($it as $f) {
    $p = $f->getPathname(); $rel = substr($p, strlen($DOC));
    if ($p === __FILE__ || !preg_match('/\.(php|js|tpl)$/i', $p) || preg_match('/\.bak|\.old|audit|patch|fix-|wipe-|check-|diag/i', basename($p))) continue;
    $c = (string)@file_get_contents($p);
    $n = preg_match_all($rx, $c);
    if (!$n) continue;
    $score = preg_match_all('/move_uploaded_file|\$_FILES/i', $c) * 5 + preg_match_all('/vehicle_images|equipment_images/i', $c) * 3 + $n;
    $found[$rel] = ['c' => $c, 'n' => $n, 'score' => $score, 'lines' => substr_count($c, "\n") + 1];
}
uasort($found, function ($a, $b) { return $b['score'] <=> $a['score']; });
$R[] = "\n## FIȘIERE RELEVANTE (scor)";
foreach ($found as $rel => $i) $R[] = sprintf('%4d  %s  [%d linii]', $i['score'], $rel, $i['lines']);

/* 3. conținut: primele fișiere complet (dacă sunt mici), altfel zonele relevante */
$budget = 900 * 1024; $used = 0; $k = 0;
foreach ($found as $rel => $i) {
    if ($k++ >= 14 || $used > $budget) break;
    $lines = explode("\n", $i['c']);
    if (strlen($i['c']) < 45000) {
        $R[] = "\n## COMPLET: $rel\n```\n" . $i['c'] . "\n```"; $used += strlen($i['c']); continue;
    }
    $hits = [];
    foreach ($lines as $n => $l) if (preg_match($rx, $l)) $hits[] = $n;
    $ranges = [];
    foreach ($hits as $n) {
        $a = max(0, $n - 20); $b = min(count($lines) - 1, $n + 20); $last = count($ranges) - 1;
        if ($last >= 0 && $a <= $ranges[$last][1] + 1) $ranges[$last][1] = max($ranges[$last][1], $b);
        else $ranges[] = [$a, $b];
    }
    $R[] = "\n## ZONE: $rel (" . count($lines) . ' linii)';
    foreach (array_slice($ranges, 0, 20) as [$a, $b]) {
        $chunk = implode("\n", array_map(function ($x) use ($lines) { return sprintf('%5d | %s', $x + 1, rtrim($lines[$x])); }, range($a, $b)));
        $R[] = "```\n$chunk\n```"; $used += strlen($chunk);
    }
}

/* 4. DB + fișiere pe disc */
foreach (['config.php', 'includes/config.php', 'inc/config.php', 'config/config.php'] as $cf) if (is_file($DOC . '/' . $cf)) { ob_start(); @include_once $DOC . '/' . $cf; ob_end_clean(); break; }
if (defined('DB_NAME')) {
    try {
        $pdo = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4', DB_USER, DB_PASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
        $R[] = "\n## DB";
        foreach ($pdo->query('SHOW TABLES')->fetchAll(PDO::FETCH_COLUMN) as $t) {
            if (!preg_match('/image|photo|vehicle|gallery|media/i', $t)) continue;
            $cols = array_map(function ($c) { return $c['Field'] . ' ' . $c['Type']; }, $pdo->query("SHOW COLUMNS FROM `$t`")->fetchAll());
            $R[] = "$t (" . $pdo->query("SELECT COUNT(*) FROM `$t`")->fetchColumn() . '): ' . implode(', ', $cols);
            foreach ($pdo->query("SELECT * FROM `$t` ORDER BY 1 DESC LIMIT 2")->fetchAll() as $row)
                $R[] = '  ex: ' . mb_substr(json_encode(array_map(function ($v) { return is_string($v) ? mb_substr($v, 0, 80) : $v; }, $row), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), 0, 400);
        }
    } catch (Throwable $e) { $R[] = 'DB: ' . $e->getMessage(); }
}
$R[] = "\n## FOLDERE CU POZE";
foreach (glob($DOC . '/uploads/*', GLOB_ONLYDIR) ?: [] as $d) {
    $n = 0; $sz = 0; $ext = [];
    foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($d, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::LEAVES_ONLY, RecursiveIteratorIterator::CATCH_GET_CHILD) as $f) {
        if (++$n > 20000) break; $sz += $f->getSize(); $e = strtolower($f->getExtension()); $ext[$e] = ($ext[$e] ?? 0) + 1;
    }
    $R[] = substr($d, strlen($DOC)) . ": $n fișiere, " . round($sz / 1048576, 1) . ' MB · ' . json_encode($ext);
}
$REPORT = implode("\n", $R);
?><!doctype html><html lang="ro"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Upload audit</title>
<style>body{font:14px/1.5 system-ui,sans-serif;margin:0;padding:16px;background:#f6f7f9}pre{background:#11151c;color:#d6dbe4;padding:12px;border-radius:6px;overflow:auto;font-size:12px;max-height:80vh;white-space:pre-wrap}
button{background:#1d4ed8;color:#fff;border:0;padding:10px 16px;border-radius:6px;font-weight:600;cursor:pointer}</style></head><body>
<h1>Upload audit</h1><p><button id="dl">Descarcă .txt</button> <button id="copy">Copiază</button></p>
<pre id="rep"><?= h($REPORT) ?></pre><p><b style="color:#b3261e">Șterge upload-audit.php după folosire.</b></p>
<script>const t=document.getElementById('rep').textContent;
document.getElementById('copy').onclick=()=>navigator.clipboard.writeText(t).then(()=>alert('Copiat'));
document.getElementById('dl').onclick=()=>{const a=document.createElement('a');a.href=URL.createObjectURL(new Blob([t],{type:'text/plain'}));a.download='upload-audit.txt';a.click();};</script>
</body></html>
