| 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_admin_role();
header('Cache-Control: private,no-store');
header('X-Robots-Tag: noindex,nofollow');
function vsi_e($s):string{return htmlspecialchars((string)$s,ENT_QUOTES|ENT_SUBSTITUTE,'UTF-8');}
const V2_MARKER='POLANA_SEO_CRM_V2_LINK';
function vsi_targets():array{
$root=dirname(__DIR__);
return [
$root.'/admin/polana-seo-centrum.php'=>['find'=>'<div class="actions"><a class="button alt" href="/admin/polana-zarzadzanie.php">',
'replace'=>'<div class="actions"><a class="button" href="/admin/polana-seo-poprawki-v2.php" data-seo-patch="'.V2_MARKER.'">Poprawki SEO z CRM</a><a class="button alt" href="/admin/polana-zarzadzanie.php">'],
$root.'/admin/polana-zarzadzanie.php'=>['find'=>'<nav class="quick" aria-label="Przejdź do sekcji">',
'replace'=>'<nav class="quick" aria-label="Przejdź do sekcji"><a data-seo-patch="'.V2_MARKER.'" href="/admin/polana-seo-poprawki-v2.php">🔎 Poprawki SEO z CRM</a>']
];
}
function vsi_install():array{
$targets=vsi_targets();$planned=[];
foreach($targets as $path=>$spec){
if(!is_file($path)||!is_readable($path)||!is_writable($path))throw new RuntimeException('Nie mogę bezpiecznie zmienić pliku: '.basename($path));
$old=file_get_contents($path);if(!is_string($old))throw new RuntimeException('Nie można odczytać: '.$path);
if(str_contains($old,V2_MARKER))continue;
if(substr_count($old,$spec['find'])!==1)throw new RuntimeException('Nieznana wersja panelu: '.basename($path).'. Zatrzymano bez zmian.');
$planned[$path]=['old'=>$old,'new'=>str_replace($spec['find'],$spec['replace'],$old)];
}
if(!$planned)return ['Nie ma zmian: linki już są.'];
$outside=dirname(__DIR__,2).'/polana_private_backups';
if(!is_dir($outside)&&!mkdir($outside,0700,true))throw new RuntimeException('Nie mogę utworzyć prywatnego backupu nad WWW.');
$realRoot=realpath(dirname(__DIR__));$realOutside=realpath($outside);
if($realOutside===false||$realRoot===false||str_starts_with($realOutside.'/',$realRoot.'/'))throw new RuntimeException('Backup musi być POZA katalogiem WWW.');
$dir=$outside.'/seo_v2_'.gmdate('Ymd_His').'_'.bin2hex(random_bytes(4));
if(!mkdir($dir,0700))throw new RuntimeException('Brak praw do backupu');
$manifest=[];$applied=[];
try{
foreach($planned as $path=>$data){
$name=basename($path);$backup=$dir.'/'.$name;
if(file_put_contents($backup,$data['old'],LOCK_EX)!==strlen($data['old']))throw new RuntimeException('Backup niepełny: '.$name);
@chmod($backup,0600);
$manifest[]=['path'=>$path,'backup'=>$backup,'before'=>hash('sha256',$data['old']),'after'=>hash('sha256',$data['new'])];
}
foreach($planned as $path=>$data){
if(file_put_contents($path,$data['new'],LOCK_EX)!==strlen($data['new']))throw new RuntimeException('Zapis niepełny: '.basename($path));
$applied[]=$path;
}
file_put_contents($dir.'/manifest.json',json_encode($manifest,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES),LOCK_EX);
$_SESSION['polana_seo_v2_backup']=$dir.'/manifest.json';
admin_log('polana_seo_v2_nav','Dodano link do poprawek CRM SEO');
return ['Włączono linki. Backup: '.basename($dir)];
}catch(Throwable $e){
foreach($applied as $path){foreach($manifest as $row){if($row['path']===$path && is_file($row['backup'])){copy($row['backup'],$path);break;}}}
throw $e;
}
}
function vsi_rollback():array{
$file=(string)($_SESSION['polana_seo_v2_backup']??'');
$outside=realpath(dirname(__DIR__,2).'/polana_private_backups');
$real=realpath($file);
if(!$outside||!$real||!str_starts_with($real,$outside.'/seo_v2_'))throw new RuntimeException('Brak bezpiecznej kopii w bieżącej sesji.');
$rows=json_decode((string)file_get_contents($real),true);
if(!is_array($rows))throw new RuntimeException('Uszkodzony manifest backupu.');
$msg=[];
foreach($rows as $r){
$path=$r['path']??'';$backup=$r['backup']??'';
if(!isset(vsi_targets()[$path])||!is_file($path)||!is_file($backup)){$msg[]='Pominięto niedostępny plik';continue;}
if(hash_file('sha256',$path)!==($r['after']??'')){$msg[]='Plik '.basename($path).' zmienił się po instalacji; pominięto';continue;}
if(hash_file('sha256',$backup)!==($r['before']??'')){$msg[]='Backup niespójny';continue;}
if(!copy($backup,$path)){$msg[]='Nie udało się przywrócić '.basename($path);continue;}
$msg[]='Przywrócono '.basename($path);
}
unset($_SESSION['polana_seo_v2_backup']);
return $msg;
}
$report=[];$err='';
if(($_SERVER['REQUEST_METHOD']??'')==='POST'){
verify_csrf();
try{$action=(string)($_POST['action']??'');if($action==='install')$report=vsi_install();elseif($action==='rollback')$report=vsi_rollback();else throw new RuntimeException('Nieznana operacja');}
catch(Throwable $e){$err=$e->getMessage();}
}
render_admin_header('SEO CRM — link w nawigacji');
?>
<main style="max-width:850px;margin:24px auto;padding:18px"><h1>Przycisk „Poprawki SEO” w panelu</h1>
<p>Dodaje jeden widoczny przycisk do „SEO i Google” oraz „Zarządzanie”, nie zmienia istniejących funkcji. Wykonuje prywatny backup i blokuje nieznane wersje plików.</p>
<?php if($err):?><p style="color:#a22"><?=vsi_e($err)?></p><?php endif;?>
<?php foreach($report as $line):?><p><?=vsi_e($line)?></p><?php endforeach;?>
<form method="post"><?=csrf_field()?><button type="submit" name="action" value="install">Dodaj skrót do panelu</button></form>
<form method="post" style="margin-top:20px" onsubmit="return confirm('Przywrócić nawigację z prywatnej kopii?');"><?=csrf_field()?><button type="submit" name="action" value="rollback">Cofnij zmianę nawigacji</button></form>
<p><a href="/admin/polana-seo-poprawki-v2.php">Otwórz poprawki SEO bez instalacji skrótu</a></p></main>
<?php render_admin_footer();?>