| Server IP : 188.114.96.3 / Your IP : 216.73.216.143 Web Server : Apache System : Linux sv058.home.net.pl 6.8.2 husak_dirty_pages_fix #1 SMP PREEMPT_DYNAMIC Tue Apr 2 22:06:51 CEST 2024 x86_64 User : ( 3194769) PHP Version : 8.5.12 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /polana/admin/ |
Upload File : |
<?php
declare(strict_types=1);
/** POLANA V18.3 — read-only site/backup audit. Never mutates DB or site files. */
require_once dirname(__DIR__) . '/includes/polana_backup_v182.php';
require_admin_role();
header('Cache-Control: private, no-store');
header('X-Robots-Tag: noindex, nofollow');
function pba183_e($value): string { return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
function pba183_http_head(string $relative): string {
$parts = array_map('rawurlencode', explode('/', $relative));
$uri = 'https://mojapolanasmakow.pl/' . implode('/', $parts);
$context = stream_context_create(['http' => ['method' => 'HEAD', 'ignore_errors' => true, 'follow_location' => 0, 'timeout' => 7], 'ssl' => ['verify_peer' => true, 'verify_peer_name' => true]]);
$headers = @get_headers($uri, true, $context);
if (!is_array($headers) || !isset($headers[0])) return 'Nie udało się sprawdzić HTTP';
preg_match('~HTTP/\\S+\\s+(\\d+)~', (string)$headers[0], $m);
$code = (int)($m[1] ?? 0);
if ($code === 200 || $code === 206) return 'KRYTYCZNE — HTTP ' . $code . ': plik może być publicznie pobieralny';
if ($code === 403 || $code === 404 || $code === 410) return 'Zablokowany (HTTP ' . $code . ') — sprawdź także GET';
return $code ? 'HTTP ' . $code . ' — sprawdź ręcznie' : 'Status HTTP nieznany';
}
$checks = []; $files = []; $notes = [];
function pba183_add(string $label, string $level, string $details): void {
global $checks;
$checks[] = [$label, $level, $details];
}
$root = realpath(dirname(__DIR__));
pba183_add('PHP', PHP_VERSION_ID >= 80200 ? 'OK' : 'UWAGA', PHP_VERSION);
pba183_add('Rozszerzenie OpenSSL', extension_loaded('openssl') ? 'OK' : 'BŁĄD', 'Wymagane do szyfrowania kopii');
pba183_add('Kompresja zlib', extension_loaded('zlib') ? 'OK' : 'BŁĄD', 'Wymagana do archiwów SQL');
pba183_add('PDO MySQL', extension_loaded('pdo_mysql') ? 'OK' : 'BŁĄD', 'Wymagane do eksportu MariaDB');
pba183_add('PharData', class_exists('PharData') ? 'OK' : 'BŁĄD', 'Wymagane do cotygodniowego TAR');
pba183_add('HTTP do Google API', ini_get('allow_url_fopen') ? 'OK' : 'UWAGA', 'Biblioteka V18.2 używa strumieni HTTPS; hosting musi pozwalać na połączenia wychodzące');
try {
$path = pbk_private();
pba183_add('Katalog backupów', 'OK', $path);
$cfg = pbk_cfg();
pba183_add('Backup automatyczny', !empty($cfg['enabled']) ? 'OK' : 'DO WŁĄCZENIA', !empty($cfg['enabled']) ? 'Włączony w ustawieniach; osobno wymaga CRON' : 'Przełącznik jest wyłączony');
$archives = glob($path . '/daily/*.pbackup') ?: [];
rsort($archives);
if ($archives) {
$latest = $archives[0];
$age = (time() - filemtime($latest)) / 86400;
$ok = $age < 2 && pbk_verify_encrypted($latest);
pba183_add('Ostatnia kopia SQL', $ok ? 'OK' : 'UWAGA', basename($latest) . ', wiek ' . round($age,1) . ' dni; ' . ($ok ? 'integralność AES-GCM OK' : 'kopia stara lub nieprzechodząca kontroli'));
} else pba183_add('Ostatnia kopia SQL', 'DO TESTU', 'Nie znaleziono zaszyfrowanego eksportu SQL');
$log = $path . '/history.log';
if (is_file($log)) {
foreach (array_slice(file($log, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [], -50) as $line) {
$event = json_decode($line, true);
if (is_array($event) && in_array(($event['status'] ?? ''), ['ERROR','WARN'], true)) {
$notes[] = ($event['time'] ?? '') . ' · ' . ($event['kind'] ?? '') . ' · ' . ($event['message'] ?? '');
}
}
}
} catch (Throwable $e) { pba183_add('Katalog backupów', 'BŁĄD', $e->getMessage()); }
if ($root !== false) {
// No symlink recursion. Cap traversal to avoid expensive scans on shared hosting.
$ignore = ['.git','node_modules','vendor','cache','tmp','sessions'];
$iterator = new RecursiveIteratorIterator(new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
static function (SplFileInfo $entry) use ($ignore): bool {
if ($entry->isLink()) return false;
return !$entry->isDir() || !in_array(strtolower($entry->getFilename()), $ignore, true);
}
));
$seen = 0;
foreach ($iterator as $entry) {
if (++$seen > 15000) { $notes[] = 'Skan plików zakończono po 15 000 elementów (limit bezpieczeństwa).'; break; }
if (!$entry->isFile()) continue;
$rel = str_replace('\\', '/', substr($entry->getPathname(), strlen($root) + 1));
if (preg_match('~(\\.sql|\\.sql\\.gz|\\.bak|\\.dump|\\.pbackup|\\.tar|\\.zip|\\.env|\\.pem|\\.key)$~i', $rel)) {
if (count($files) < 60) $files[] = $rel;
}
}
}
pba183_add('Historyczne kopie/sekrety w WWW', !$files ? 'OK' : 'UWAGA', !$files ? 'Skan nie wykrył podejrzanych rozszerzeń w pierwszych 15 000 plików' : 'Wykryto ' . count($files) . ' plików wymagających sprawdzenia; nie zostały przeniesione ani usunięte');
$headChecks = [];
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
verify_csrf();
if (($_POST['action'] ?? '') === 'check_http') {
foreach (array_slice($files, 0, 8) as $name) $headChecks[$name] = pba183_http_head($name);
}
}
render_admin_header('POLANA V18.3 — audyt ostrzeżeń');
?>
<style>
.pba183{max-width:1100px;margin:22px auto 60px;padding:0 14px;color:#213629}.pba183 *{box-sizing:border-box}.pba183 article{border:1px solid #d6e3d6;border-radius:14px;padding:20px;background:#fff;margin:15px 0}.pba183 table{border-collapse:collapse;width:100%}.pba183 th,.pba183 td{border-bottom:1px solid #e2e9e2;padding:10px;text-align:left;vertical-align:top}.pba183 code{overflow-wrap:anywhere}.pba183 button{background:#17442e;color:white;border:0;border-radius:9px;padding:11px 15px;cursor:pointer}.pba183 .scroll{overflow:auto}.pba183 li{margin:8px 0}
</style>
<div class="pba183"><h1>Audyt POLANA V18.3</h1><p>Raport tylko do odczytu: nie zmienia bazy danych, nie wysyła e-maili i nie usuwa plików. Test HTTP jest wykonywany tylko po naciśnięciu przycisku.</p>
<article><h2>Stan backupów i serwera</h2><div class="scroll"><table><thead><tr><th>Kontrola</th><th>Stan</th><th>Szczegóły</th></tr></thead><tbody>
<?php foreach ($checks as [$name,$level,$detail]): ?><tr><td><?=pba183_e($name)?></td><td><b><?=pba183_e($level)?></b></td><td><?=pba183_e($detail)?></td></tr><?php endforeach; ?>
</tbody></table></div></article>
<article><h2>Ostrzeżenia z diagnostyki V18.0</h2><ul>
<li><b>GTM — tryb direct:</b> nie musi oznaczać awarii. Decyzję o uruchomieniu GTM i konfiguracji zgód podejmij w <a href="/admin/polana-analityka.php">Analityka i piksele</a>; sam zapis identyfikatora kontenera nie aktywuje GTM.</li>
<li><b>Numer #POLANA:</b> moduł V17.5.2 zgłosił WARN. Bez źródeł modułu rezerwacji i wiadomości nie można potwierdzić, czy numer jest dodawany do potwierdzeń. Nie wykonano automatycznej zmiany treści e-maili.</li>
<li><b>Google Calendar OAuth:</b> w raporcie V18.0 konto było niepołączone; trzeba uruchomić proces autoryzacji w <a href="/admin/polana-kalendarz.php">Kalendarz</a>. Uprawnienia Drive dla backupów są osobne.</li>
<li><b>Historyczne kopie SQL w WWW:</b> lista poniżej to lokalny skan. Blokada przez .htaccess musi zostać potwierdzona realną odpowiedzią HTTP. Docelowo należy skopiować pliki poza WWW po sprawdzeniu, że nie są używane.</li>
<li><b>IndexNow kolejka 0 i newsletter 0 potwierdzonych:</b> to informacje, nie samodzielne błędy.</li></ul></article>
<article><h2>Potencjalnie prywatne pliki w WWW</h2>
<?php if (!$files): ?><p>W przejrzanej części witryny nie znaleziono pasujących rozszerzeń. To nie gwarantuje, że nie ma innych plików.</p><?php else: ?>
<p><b>Nie kasuj tych plików w ciemno.</b> Najpierw sprawdź ich przeznaczenie i przygotuj zweryfikowaną kopię poza WWW.</p>
<div class="scroll"><table><thead><tr><th>Plik względny</th><th>Weryfikacja HEAD</th></tr></thead><tbody><?php foreach ($files as $name): ?><tr><td><code><?=pba183_e($name)?></code></td><td><?=pba183_e($headChecks[$name] ?? 'Nie sprawdzono')?></td></tr><?php endforeach; ?></tbody></table></div>
<form method="post"><?=csrf_field()?><input type="hidden" name="action" value="check_http"><button type="submit">Sprawdź dostęp HTTP (maks. 8 plików)</button></form>
<p><small>HEAD to tylko kontrola wstępna. HTTP 403/404 oznacza blokadę tego żądania, ale nie zastępuje sprawdzenia GET ani przeglądu konfiguracji Apache/Nginx.</small></p>
<?php endif; ?></article>
<?php if ($notes): ?><article><h2>Ostatnie problemy i uwagi</h2><ul><?php foreach (array_slice($notes,-15) as $note): ?><li><?=pba183_e($note)?></li><?php endforeach; ?></ul></article><?php endif; ?>
<p><a href="/admin/polana-v183-naprawa.php">← Wróć do naprawy V18.3</a></p></div>
<?php render_admin_footer(); ?>