| 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.14 — safe installer, only specific code hooks + menu shortcut. */
require_once dirname(__DIR__) . '/includes/functions.php';
require_once dirname(__DIR__) . '/includes/polana_v1814_patch_lib.php';
require_login();
if ((string)(admin_user()['role'] ?? '') !== 'admin') { http_response_code(403); exit('Dostep tylko dla administratora.'); }
header('Cache-Control: private, no-store, max-age=0');
header('X-Robots-Tag: noindex,nofollow');
function pv1814_e(string $s): string { return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
function pv1814_files(): array {
return [
'includes/reservations.php' => 'pv1814_transform_reservations',
'includes/functions.php' => 'pv1814_transform_nav'
];
}
function pv1814_backup_dir(): string {
$f=dirname(__DIR__).'/includes/polana_backup_v182.php';
if(!is_file($f))throw new RuntimeException('Brak biblioteki prywatnych kopii; najpierw napraw V18.3.');
require_once $f;
if(!function_exists('pbk_private'))throw new RuntimeException('Brak pbk_private().');
$root=realpath(dirname(__DIR__));
$base=pbk_private().'/polana-v1814-code-backups';
if(!is_dir($base)&&!@mkdir($base,0700,true))throw new RuntimeException('Nie mozna utworzyc prywatnego backupu kodu.');
$private=realpath($base);
if(!$root||!$private||$private===$root||str_starts_with($private.'/',$root.'/'))throw new RuntimeException('Niedozwolona sciezka backupu kodu.');
return $private;
}
function pv1814_check(array $targets): array {
$changes=[];
foreach ($targets as $relative=>$transform) {
$target=dirname(__DIR__).'/'.$relative;
if(!is_file($target)||!is_readable($target))throw new RuntimeException('Brak pliku: '.$relative);
$old=file_get_contents($target);
if(!is_string($old))throw new RuntimeException('Blad odczytu: '.$relative);
$eol=str_contains($old,"\r\n")?"\r\n":"\n";
$normalized=str_replace("\r\n","\n",$old);
$new=$transform($normalized);
if($eol==="\r\n")$new=str_replace("\n","\r\n",$new);
$changes[$relative]=['path'=>$target,'before'=>$old,'after'=>$new,'modified'=>$old!==$new];
}
return $changes;
}
function pv1814_write(string $path,string $data): void {
$tmp=$path.'.pv1814-'.bin2hex(random_bytes(7));
$h=@fopen($tmp,'xb');
if(!$h)throw new RuntimeException('Brak mozliwosci zapisu pliku tymczasowego.');
$ok=fwrite($h,$data)===strlen($data);fflush($h);fclose($h);
if(!$ok){@unlink($tmp);throw new RuntimeException('Niepelny zapis pliku.');}
$perm=@fileperms($path);if($perm!==false)@chmod($tmp,$perm&0777);
if(!@rename($tmp,$path)){@unlink($tmp);throw new RuntimeException('Blad atomowej podmiany.');}
}
function pv1814_install(): string {
$changes=pv1814_check(pv1814_files());
$todo=array_filter($changes,static fn($x)=>$x['modified']);
if(!$todo)return 'Hook kalendarza i skrot do modulow sa juz obecne lub istnieje wczesniejszy hook Google. Nic nie zmieniono.';
if(!is_file(dirname(__DIR__).'/includes/polana_gcal.php'))throw new RuntimeException('Brak biblioteki Kalendarza Google.');
if(!is_file(dirname(__DIR__).'/admin/polana-v1814-moduly.php'))throw new RuntimeException('Brak centrum modulow z paczki.');
$root=pv1814_backup_dir();
$dir=$root.'/'.date('Ymd_His').'_'.bin2hex(random_bytes(4));
if(!@mkdir($dir,0700))throw new RuntimeException('Nie mozna utworzyc migawki.');
$manifest=['version'=>'18.14','created'=>date(DATE_ATOM),'files'=>[]];
foreach($todo as $rel=>$change){
if(!is_writable($change['path']))throw new RuntimeException('Plik nie jest zapisywalny: '.$rel);
$name=str_replace('/','__',$rel);
if(file_put_contents($dir.'/'.$name,$change['before'],LOCK_EX)!==strlen($change['before']))throw new RuntimeException('Nie mozna zapisac kopii: '.$rel);
@chmod($dir.'/'.$name,0600);
$manifest['files'][$rel]=['backup'=>$name,'before_sha256'=>hash('sha256',$change['before']),'installed_sha256'=>hash('sha256',$change['after'])];
}
$manifestFile=$dir.'/manifest.json';
if(file_put_contents($manifestFile,json_encode($manifest,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES),LOCK_EX)===false)throw new RuntimeException('Brak manifestu kopii.');
@chmod($manifestFile,0600);
$written=[];
try {
foreach($todo as $rel=>$change){pv1814_write($change['path'],$change['after']);$written[]=$rel;}
}catch(Throwable $error){
foreach(array_reverse($written) as $rel){
try{pv1814_write($changes[$rel]['path'],$changes[$rel]['before']);}catch(Throwable $restore) { error_log('[POLANA V18.14 ROLLBACK] '.$rel.': '.$restore->getMessage()); }
}
throw new RuntimeException('Instalacja przerwana, sprobowano odtworzyc pliki: '.$error->getMessage());
}
return 'Zainstalowano '.count($todo).' zmieniony(e) plik(i). Kopia kodu poza WWW: '.basename($dir).'. Nie zmieniano bazy ani ustawien Google.';
}
function pv1814_rollback(): string {
$base=pv1814_backup_dir();
$directories=glob($base.'/*',GLOB_ONLYDIR)?:[];rsort($directories,SORT_STRING);
$matching=[];
foreach($directories as $dir){
$file=$dir.'/manifest.json';if(!is_file($file))continue;
$data=json_decode((string)file_get_contents($file),true);
if(is_array($data)&&($data['version']??'')==='18.14'){$matching=[$dir,$data];break;}
}
if(!$matching)throw new RuntimeException('Nie znaleziono zapisanej instalacji V18.14.');
[$dir,$manifest]=$matching;
if(is_file($dir.'/rollback.completed'))return 'Poprzedni rollback juz wykonano.';
$restore=[];
foreach(($manifest['files']??[]) as $rel=>$entry){
if(!isset(pv1814_files()[$rel]))throw new RuntimeException('Nieznany plik w manifeście.');
$target=dirname(__DIR__).'/'.$rel;
$backup=$dir.'/'.basename((string)$entry['backup']);
if(!is_file($backup)||hash_file('sha256',$backup)!==($entry['before_sha256']??''))throw new RuntimeException('Bledna kopia kodu: '.$rel);
if(!is_file($target)||hash_file('sha256',$target)!==($entry['installed_sha256']??''))throw new RuntimeException('Kod zmieniony po instalacji: '.$rel.'. Odmowa nadpisania cudzych zmian.');
$restore[$target]=file_get_contents($backup);
}
foreach($restore as $target=>$content){pv1814_write($target,(string)$content);}
@file_put_contents($dir.'/rollback.completed',date(DATE_ATOM));
return 'Przywrocono '.count($restore).' plik(i) z prywatnej kopii. Brak zmian bazy.';
}
$status='';$statusType='ok';
if(($_SERVER['REQUEST_METHOD']??'GET')==='POST'){
verify_csrf();
try{
$action=(string)($_POST['action']??'');
if($action==='install')$status=pv1814_install();
elseif($action==='rollback')$status=pv1814_rollback();
else throw new RuntimeException('Nieznana operacja.');
}catch(Throwable $e){$status=$e->getMessage();$statusType='error';}
}
$check=[];try{$check=pv1814_check(pv1814_files());}catch(Throwable $e){$check=[];$status.=' '. $e->getMessage();$statusType='error';}
$source=isset($check['includes/reservations.php'])?$check['includes/reservations.php']['before']:'';
$hookActive=preg_match('/function reservation_change_status\(.*?pg173_after_change\(/s',$source)===1;
render_admin_header('POLANA V18.14 — kalendarz i menu');
?>
<div style="max-width:940px;margin:24px auto;padding:12px">
<h1>POLANA V18.14 — synchronizacja i brakujące moduły</h1>
<p>Nie zmienia danych rezerwacji, numerów, maili, tokenów Google ani bazy. Naprawia uruchamianie synchronizacji Google po zmianie statusu oraz dodaje skrót do istniejących modułów w panelu.</p>
<?php if(trim($status)!==''):?><section class="card"><b><?=pv1814_e($statusType==='ok'?'Wynik':'Błąd')?></b><p><?=pv1814_e($status)?></p></section><?php endif;?>
<section class="card"><h2>Kontrola przed instalacją</h2>
<p>Automatyczny hook po statusie: <strong><?= $hookActive?'WYKRYTY':'BRAK / wymaga poprawki' ?></strong>.</p>
<?php foreach($check as $rel=>$change):?><p><?=pv1814_e($rel)?> — <?= $change['modified']?'do poprawy':'bez zmian' ?></p><?php endforeach;?>
<p>Wskazówka: wydarzenie powinno powstać po kliknięciu „Potwierdź”. Nowa prośba o rezerwację nie trafia do Google. Nie ponawiaj zatwierdzenia tylko dla testu.</p>
<form method="post"><?=csrf_field()?><input type="hidden" name="action" value="install"><button type="submit" class="btn btn-primary" <?=!$check?'disabled':''?>>Zrób kopię kodu i napraw</button></form>
</section>
<section class="card"><h2>Po instalacji</h2><ol><li>Otwórz <a href="/admin/polana-v1814-moduly.php">Wszystkie moduły</a> i sprawdź, co jest obecne i czego brakuje.</li><li>Potwierdź tylko jedną NOWĄ rezerwację testową; sprawdź Google Calendar i historię jej zdarzeń.</li><li>Przejdź do <a href="/admin/polana-kalendarz.php">Google Calendar</a> i uruchom ręcznie synchronizację wcześniejszych zaległości, jeżeli istnieją.</li></ol></section>
<section class="card"><h2>Rollback</h2><p>Odtwarza zmienione pliki wyłącznie gdy nie były później modyfikowane. Kopia jest prywatna poza WWW.</p><form method="post"><?=csrf_field()?><input type="hidden" name="action" value="rollback"><button type="submit" class="btn btn-light">Cofnij ostatnią instalację V18.14</button></form></section>
</div>
<?php render_admin_footer(); ?>