| 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.6 — ntfy monitoring admin, additive: changes nothing in bookings/calendar. */
require_once dirname(__DIR__) . '/includes/polana_ntfy_v186.php';
require_admin_role();
header('Cache-Control: private, no-store, max-age=0');
header('X-Robots-Tag: noindex, nofollow');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: no-referrer');
function pnt186_e($v): string { return htmlspecialchars((string)$v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
$notice = ''; $error = '';
try {
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
verify_csrf();
$action = (string)($_POST['action'] ?? '');
if ($action === 'save') {
$original = pnt186_config();
$cfg = $original;
$cfg['enabled'] = isset($_POST['enabled']);
$cfg['url'] = pnt186_validate_url((string)($_POST['url'] ?? ''));
$cfg['topic'] = pnt186_validate_topic((string)($_POST['topic'] ?? ''));
if (empty(pbk_cfg()['key_exported'])) throw new RuntimeException('Najpierw pobierz i zachowaj klucz odzyskiwania w module backupu V18.2.');
$token = trim((string)($_POST['token'] ?? ''));
if ($token !== '') {
if (!preg_match('/^[\x21-\x7E]{1,500}$/D', $token)) throw new RuntimeException('Nieprawidłowy token ntfy.');
$cfg['token_enc'] = pbk_secret_encrypt($token);
}
if (isset($_POST['clear_token'])) $cfg['token_enc'] = '';
pnt186_save($cfg);
$notice = 'Ustawienia zapisane. Żaden moduł rezerwacji ani Google OAuth nie został zmieniony.';
} elseif ($action === 'test') {
pnt186_send('POLANA test ntfy', 'To test powiadomienia. Brak danych klientów i rezerwacji.', 'white_check_mark');
$notice = 'Serwer ntfy potwierdził odbiór. Sprawdź telefon.';
} elseif ($action === 'check') {
$r = pnt186_check_backup();
$notice = 'Monitoring: ' . (string)$r['status'] . (!empty($r['sent']) ? ' — wysłano powiadomienie.' : ' — bez nowego alertu.');
} elseif ($action === 'disable') {
$cfg = pnt186_config();
$cfg['enabled'] = false;
pnt186_save($cfg);
$notice = 'Powiadomienia zostały wyłączone; konfigurację zachowano.';
} else {
throw new RuntimeException('Nieznana operacja.');
}
}
$cfg = pnt186_config();
$state = pnt186_backup_state();
$statePath = pnt186_state_path();
$lastCheck = is_file($statePath) ? json_decode((string)file_get_contents($statePath), true) : [];
if (!is_array($lastCheck)) $lastCheck = [];
$keyIsExported = !empty(pbk_cfg()['key_exported']);
} catch (Throwable $e) {
$error = $e->getMessage();
try { $cfg = pnt186_config(); $state = pnt186_backup_state(); $keyIsExported = !empty(pbk_cfg()['key_exported']); }
catch (Throwable $ignored) { $cfg = ['enabled'=>false, 'url'=>'', 'topic'=>'', 'token_enc'=>'']; $state = ['count'=>0, 'age_h'=>null, 'healthy'=>false]; $keyIsExported = false; }
$lastCheck = [];
}
if (empty($cfg['topic'])) $cfg['topic'] = 'polana-' . bin2hex(random_bytes(12));
?>
<!doctype html><html lang="pl"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>POLANA V18.6 — ntfy i kontrola backupów</title>
<style>
:root{font-family:system-ui,-apple-system,'Segoe UI',Arial,sans-serif;color-scheme:light;color:#192e26;background:#f5f7f4}*{box-sizing:border-box}body{margin:0}.wrap{max-width:900px;margin:20px auto 60px;padding:0 16px}a{color:#175e47}header{padding:18px 0}h1{margin:8px 0;font-size:clamp(25px,4vw,34px)}h2{font-size:19px;margin:0 0 14px}p{line-height:1.5}.panel{background:white;border:1px solid #d8e4dc;border-radius:14px;padding:22px;margin-bottom:16px}label{display:block;font-weight:600;margin:14px 0 7px}input[type=text],input[type=password],input[type=url]{width:100%;font-size:16px;border:1px solid #b3c5b9;border-radius:9px;padding:11px}input[type=checkbox]{width:19px;height:19px;vertical-align:middle}.btn,button{display:inline-block;border:0;border-radius:9px;padding:11px 17px;background:#196346;color:#fff;font-size:15px;cursor:pointer;margin:5px 6px 5px 0}.secondary{background:#344d40}.warn{background:#fff4dc;color:#724b13;padding:12px;border-radius:9px}.error{background:#ffe9e8;color:#7a2020;padding:12px;border-radius:9px}.ok{background:#e2f4e6;color:#12542b;padding:12px;border-radius:9px}small{color:#53645a}code{word-break:break-all;background:#f0f2f0;border-radius:4px;padding:2px 5px}.status{display:flex;flex-wrap:wrap;gap:12px}.status>div{flex:1;min-width:130px;background:#f2f6f3;padding:15px;border-radius:11px}form{margin:0}footer{font-size:13px;color:#546257;margin:20px 0}
</style></head><body><div class="wrap">
<header><a href="/admin/polana-zarzadzanie.php">← Centrum zarządzania</a> · <a href="/admin/polana-backup-automat.php">Backupy SQL</a> · <a href="/admin/polana-kalendarz.php">Kalendarz</a>
<h1>POLANA V18.6 — alerty ntfy</h1><p>Bez zmian bazy, rezerwacji, OAuth i istniejącego kalendarza. Powiadomienia na telefon o problemach z kopiami SQL.</p></header>
<?php if($notice!==''): ?><p class="ok" role="status"><?=pnt186_e($notice)?></p><?php endif; ?>
<?php if($error!==''): ?><p class="error" role="alert"><?=pnt186_e($error)?></p><?php endif; ?>
<section class="panel"><h2>1. Stan bezpieczeństwa</h2><div class="status"><div>Monitoring ntfy<br><strong><?=empty($cfg['enabled'])?'Wyłączony':'Włączony'?></strong></div>
<div>Kopie SQL<br><strong><?=pnt186_e((int)$state['count'])?></strong></div><div>Ostatni SQL<br><strong><?=($state['age_h'] === null?'Brak':pnt186_e((string)$state['age_h']) . ' h temu')?></strong></div>
<div>Aktualność kopii<br><strong><?=!empty($state['healthy'])?'OK':'Wymaga sprawdzenia'?></strong></div></div>
<p><small>Pomiar według wieku plików .pbackup w prywatnym katalogu. Nie zastępuje odszyfrowania próbnej kopii i testu odzyskania.</small></p>
<?php if(!$keyIsExported): ?><p class="warn">Nie potwierdzono pobrania klucza odzyskiwania. Wejdź do Backupów SQL i pobierz klucz, zanim włączysz ntfy.</p><?php endif; ?>
<?php if(!empty($lastCheck['checked_at'])): ?><p><small>Ostatnia kontrola: <?=pnt186_e($lastCheck['checked_at'])?>; stan: <?=pnt186_e($lastCheck['status']??'—')?>.</small></p><?php endif; ?>
</section>
<section class="panel"><h2>2. Konfiguracja ntfy</h2><p>Zainstaluj aplikację ntfy na telefonie, zasubskrybuj prywatny temat i wpisz ten sam adres tutaj. Temat powinien być trudny do odgadnięcia; jeśli serwer wymaga autoryzacji, podaj token.</p>
<form method="post" autocomplete="off"><?=csrf_field()?><input type="hidden" name="action" value="save">
<label for="url">Adres serwera ntfy (HTTPS)</label><input id="url" name="url" type="url" required placeholder="https://ntfy.example.com" value="<?=pnt186_e($cfg['url'])?>">
<label for="topic">Prywatny temat</label><input id="topic" name="topic" type="text" minlength="12" maxlength="80" required value="<?=pnt186_e($cfg['topic'])?>">
<label for="token">Token dostępu (opcjonalnie)</label><input id="token" name="token" type="password" autocomplete="new-password" value="" placeholder="Pozostaw puste, aby zachować zapisany token">
<p><label style="font-weight:normal"><input type="checkbox" name="clear_token" value="1"> Usuń dotychczasowy token</label><small><?=!empty($cfg['token_enc'])?'Token jest zapisany w postaci zaszyfrowanej poza WWW.':'Brak zapisanego tokenu.'?></small></p>
<p><label><input type="checkbox" name="enabled" value="1" <?=!empty($cfg['enabled'])?'checked':''?>> Włącz alerty ntfy</label></p>
<button type="submit">Zapisz ustawienia</button></form></section>
<section class="panel"><h2>3. Test i harmonogram</h2>
<form method="post" style="display:inline"><?=csrf_field()?><input type="hidden" name="action" value="test"><button type="submit" class="secondary">Wyślij powiadomienie testowe</button></form>
<form method="post" style="display:inline"><?=csrf_field()?><input type="hidden" name="action" value="check"><button type="submit" class="secondary">Sprawdź kopie teraz</button></form>
<form method="post" style="display:inline"><?=csrf_field()?><input type="hidden" name="action" value="disable"><button type="submit" class="secondary">Wyłącz ntfy</button></form>
<p><strong>CRON:</strong> dodaj zadanie w hostingu, np. co 3 godziny, podając rzeczywistą ścieżkę PHP CLI:</p>
<code>15 */3 * * * /usr/bin/php <?=pnt186_e(dirname(__DIR__))?>/cron/polana-ntfy-v186.php</code>
<p><small>W home.pl ustaw harmonogram i komendę zgodnie z panelem hostingu. Cron nie jest uruchamiany automatycznie po instalacji. Jeśli kopii nie ma lub są starsze niż 30 godzin, ntfy wysyła ostrzeżenie; kolejne ostrzeżenie nie wcześniej niż po 24 godzinach. Po naprawie wysyła jedno potwierdzenie.</small></p>
</section><section class="panel"><h2>4. Co z Google Calendar?</h2><p>Połączenie działa — nie ruszamy go. Ta paczka <strong>nie podłącza jeszcze powiadomień o nowych rezerwacjach i nie zmienia ponawiania synchronizacji</strong>. To wymaga aktualnych plików <code>admin/polana-kalendarz.php</code> oraz kodu obsługi statusów rezerwacji, aby nie zrobić duplikatów wydarzeń ani wysyłek.</p></section>
<footer>POLANA V18.6 • Ustawienia i stan ntfy przechowywane wyłącznie poza WWW, bez haseł w HTML • Brak modyfikacji istniejących modułów</footer>
</div></body></html>