| 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);
require_once dirname(__DIR__).'/includes/functions.php';
require_once dirname(__DIR__).'/includes/polana_v1751_patch.php';
require_admin_role();
header('Cache-Control: private, no-store');
header('X-Robots-Tag: noindex,nofollow');
function pv1751_targets(): array {
$root=dirname(__DIR__);
return ['includes/polana_v175_booking.php'=>$root.'/includes/polana_v175_booking.php',
'admin/polana-godziny-rezerwacji.php'=>$root.'/admin/polana-godziny-rezerwacji.php'];
}
function pv1751_backup_dir():string {
// Outside the Polana document root. 0700 + deny rules even if parent is served by another domain.
return dirname(dirname(__DIR__)).'/.polana_v1751_backups';
}
function pv1751_write(string $file,string $data):void {
$tmp=$file.'.v1751_'.bin2hex(random_bytes(6)).'.tmp';
if (@file_put_contents($tmp,$data,LOCK_EX)!==strlen($data)) { @unlink($tmp); throw new RuntimeException('Błąd zapisu pliku '.basename($file)); }
$perm=@fileperms($file); if ($perm!==false) @chmod($tmp,$perm&0777);
if (!@rename($tmp,$file)) { @unlink($tmp); throw new RuntimeException('Błąd podmiany pliku '.basename($file)); }
}
function pv1751_prepare():array {
$changes=[];
foreach (pv1751_targets() as $rel=>$file) {
if (!is_file($file)||!is_readable($file)||!is_writable($file)) throw new RuntimeException('Nie można odczytać lub zapisać '.$rel.' — najpierw zainstaluj V17.5.');
$old=@file_get_contents($file); if (!is_string($old)) throw new RuntimeException('Błąd odczytu '.$rel);
$lf=str_replace("\r\n","\n",$old);
$new=($rel==='includes/polana_v175_booking.php')?pv1751_patch_email($lf):pv1751_patch_admin($lf);
if (str_contains($old,"\r\n")) $new=str_replace("\n","\r\n",$new);
if ($new!==$old) $changes[$rel]=['path'=>$file,'before'=>$old,'after'=>$new];
}
return $changes;
}
function pv1751_install():string {
$changes=pv1751_prepare();
if (!$changes) return 'V17.5.1 już zainstalowana. Niczego nie nadpisano.';
$base=pv1751_backup_dir();
if (!is_dir($base)&&!@mkdir($base,0700,true)) throw new RuntimeException('Nie można utworzyć prywatnego katalogu kopii.');
@chmod($base,0700);
@file_put_contents($base.'/.htaccess',"Require all denied\nDeny from all\n");
@file_put_contents($base.'/index.html','');
$dir=$base.'/'.date('Ymd_His').'_'.bin2hex(random_bytes(4));
if (!@mkdir($dir,0700)) throw new RuntimeException('Nie można utworzyć katalogu kopii.');
$manifest=['version'=>'17.5.1','created_at'=>date('c'),'files'=>[],'rolled_back'=>false];
foreach ($changes as $rel=>$c) {
$name=str_replace('/','__',$rel).'.bak';
if (@file_put_contents($dir.'/'.$name,$c['before'],LOCK_EX)!==strlen($c['before'])) throw new RuntimeException('Błąd kopii '.$rel);
$manifest['files'][$rel]=['backup'=>$name,'after_sha256'=>hash('sha256',$c['after'])];
}
$manifestFile=$dir.'/manifest.json';
if (@file_put_contents($manifestFile,json_encode($manifest,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_THROW_ON_ERROR),LOCK_EX)===false) throw new RuntimeException('Nie można zapisać manifestu.');
$written=[];
try {
foreach ($changes as $rel=>$c) { pv1751_write($c['path'],$c['after']); $written[]=$rel; }
} catch(Throwable $e) {
foreach(array_reverse($written) as $rel) {
try {pv1751_write($changes[$rel]['path'],$changes[$rel]['before']);}
catch(Throwable $rollbackError) {error_log('POLANA V1751 restore: '.$rollbackError->getMessage());}
}
$manifest['rolled_back']=true;
@file_put_contents($manifestFile,json_encode($manifest,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE),LOCK_EX);
throw $e;
}
return 'Zainstalowano V17.5.1: poprawiono '.count($written).' pliki. Teraz ustaw telefon w panelu godzin rezerwacji.';
}
function pv1751_rollback():string {
$paths=glob(pv1751_backup_dir().'/*/manifest.json')?:[];
rsort($paths,SORT_STRING);
foreach($paths as $path) {
$m=json_decode((string)@file_get_contents($path),true);
if (!is_array($m)||($m['version']??'')!=='17.5.1'||!empty($m['rolled_back'])) continue;
$restore=[];$targets=pv1751_targets();
foreach($m['files'] as $rel=>$meta) {
if(!isset($targets[$rel])) throw new RuntimeException('Nieznany plik w kopii.');
$current=@file_get_contents($targets[$rel]);
if(!is_string($current)||!hash_equals((string)$meta['after_sha256'],hash('sha256',$current))) throw new RuntimeException('Plik '.$rel.' został później zmieniony — rollback zablokowany.');
$old=@file_get_contents(dirname($path).'/'.$meta['backup']);
if(!is_string($old)) throw new RuntimeException('Brak pliku kopii '.$rel);
$restore[$rel]=$old;
}
foreach($restore as $rel=>$old) pv1751_write($targets[$rel],$old);
$m['rolled_back']=true;
@file_put_contents($path,json_encode($m,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE),LOCK_EX);
return 'Przywrócono poprzednie pliki. Zapisany numer telefonu w bazie pozostał bez zmian.';
}
throw new RuntimeException('Nie znaleziono aktywnej kopii V17.5.1.');
}
if (($_SERVER['REQUEST_METHOD']??'')==='POST') {
verify_csrf();
try {
$action=(string)($_POST['action']??'');
if ($action==='install') $msg=pv1751_install();
elseif($action==='rollback' && ($_POST['confirm']??'')==='1') $msg=pv1751_rollback();
else throw new RuntimeException('Nieprawidłowa operacja.');
flash('success',$msg);
} catch(Throwable $e) {flash('error',$e->getMessage());}
redirect('/admin/polana-v1751-poprawka.php');
}
try { $changes=pv1751_prepare(); $state=$changes?'Gotowa do instalacji':'Zainstalowana'; }
catch(Throwable $e) {$state='Wymaga uwagi: '.$e->getMessage();}
$core=@file_get_contents(dirname(__DIR__).'/includes/functions.php');
$cookies=is_string($core)&&str_contains($core,'POLANA_TRACKING_HEAD_V174')&&str_contains($core,'POLANA_TRACKING_FOOTER_V174');
render_admin_header('POLANA V17.5.1 — e-mail i telefon');
?>
<div style="max-width:920px;margin:26px auto;padding:0 12px">
<div class="form-card" style="padding:26px;border-radius:15px">
<h1>POLANA V17.5.1 — e-mail i telefon</h1>
<p>Usuwamy dodatkowy komunikat o niepotwierdzonym stoliku z e-maila. Dodajemy edytowalny numer telefonu restauracji w stopce, a numer rezerwacji pozostaje w szczegółach.</p>
<p><strong>Stan:</strong> <?= e($state) ?></p>
<form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="install"><button class="btn btn-primary" type="submit" <?= str_starts_with($state,'Wymaga')?'disabled':'' ?>>Zainstaluj poprawkę z backupem</button></form>
<p style="margin-top:16px"><a href="/admin/polana-godziny-rezerwacji.php">Godziny i telefon w e-mailach →</a></p>
</div>
<div class="form-card" style="padding:26px;border-radius:15px;margin-top:18px">
<h2>Cookies i analityka (V17.4)</h2>
<p><strong>Integracja z szablonem:</strong> <?= $cookies?'Wykryta':'Nie wykryto — sprawdź instalator V17.4' ?></p>
<p>Baner zgód na analitykę i marketing jest już w V17.4. Nie instalujemy drugiego banera. Po włączeniu GA4 w panelu analityki sprawdź go w prywatnym oknie przeglądarki.</p>
<p><a href="/admin/polana-analityka.php">Analityka i piksele →</a> · <a href="/admin/polana-v174-instalator.php">Instalator cookies V17.4 →</a></p>
</div>
<div class="form-card" style="padding:26px;border-radius:15px;margin-top:18px">
<h2>Rollback poprawki</h2>
<form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="rollback"><label><input type="checkbox" name="confirm" value="1" required> Cofnij tylko zmiany V17.5.1</label> <button class="btn btn-light" type="submit">Cofnij V17.5.1</button></form>
</div>
</div>
<?php render_admin_footer(); ?>