| 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 V16.6 — diagnostyka/naprawa XML bez crona i bez zmian danych. */
require_once dirname(__DIR__).'/includes/functions.php';
require_admin_role();
header('Cache-Control: private, no-store');
header('X-Robots-Tag: noindex, nofollow');
$root=dirname(__DIR__);
$ext=$root.'/includes/polana_v164_seo.php';
if(!is_file($ext))$ext=$root.'/includes/polana_v166_seo.php';
$loadError='';
try{require_once $ext;}catch(Throwable $e){$loadError=$e->getMessage();}
$backupDir=dirname($root).'/.polana_v166_sitemap_backups';
$manifest=$backupDir.'/manifest.json';
$ok='';$error='';
function pv166_h($v):string{return htmlspecialchars((string)$v,ENT_QUOTES|ENT_SUBSTITUTE,'UTF-8');}
function pv166_write(string $file,string $content):void{
$tmp=tempnam(dirname($file),'.p166-');
if($tmp===false)throw new RuntimeException('Nie można utworzyć pliku tymczasowego.');
try{
if(file_put_contents($tmp,$content,LOCK_EX)!==strlen($content))throw new RuntimeException('Niepełny zapis '.basename($file));
@chmod($tmp,is_file($file)?(fileperms($file)&0777):0644);
if(!rename($tmp,$file))throw new RuntimeException('Brak prawa do podmiany '.basename($file));
}finally{if(is_file($tmp))@unlink($tmp);}
}
function pv166_script():string{return <<<'SCRIPT'
<?php
declare(strict_types=1);
/** POLANA V16.6: dynamiczna mapa XML, identyczna pod /sitemap.xml i /sitemap.php */
require_once __DIR__.'/includes/functions.php';
require_once (is_file(__DIR__.'/includes/polana_v164_seo.php') ? __DIR__.'/includes/polana_v164_seo.php' : __DIR__.'/includes/polana_v166_seo.php');
try {
$data=p164_sitemap_data();
$xml=p164_sitemap_xml($data);
header('Content-Type: application/xml; charset=UTF-8');
header('Cache-Control: public, max-age=300');
header('X-Content-Type-Options: nosniff');
echo $xml;
} catch (Throwable $e) {
error_log('POLANA V166 sitemap: '.$e->getMessage());
http_response_code(503);
header('Content-Type: text/plain; charset=UTF-8');
header('Cache-Control: no-store');
echo 'Sitemap temporarily unavailable';
}
SCRIPT;
}
function pv166_route(string $src):string {
// Check active RewriteRule, not commented examples.
foreach(preg_split('/\R/',$src)?:[] as $line){
if(preg_match('~^\s*RewriteRule\s+\^?sitemap\\?\.xml\$?\s+sitemap\.php\b~i',$line))return $src;
if(!str_starts_with(ltrim($line),'#')&&preg_match('~RewriteRule[^\r\n]*sitemap[^\r\n]*sitemap\.php~i',$line))return $src;
}
if(!preg_match('/^\s*RewriteEngine\s+On\b/im',$src))throw new RuntimeException('Brak aktywnego RewriteEngine On w .htaccess. Nie zmieniono reguł.');
return preg_replace('/^(\s*RewriteEngine\s+On\b[^\r\n]*)(\r?\n)/im', '$1$2# POLANA V166 XML sitemap$2RewriteRule ^sitemap\\.xml$ sitemap.php [L,QSA]$2',$src,1)??$src;
}
function pv166_routes_ok(string $src):bool{
foreach(preg_split('/\R/',$src)?:[] as $line){if(!str_starts_with(ltrim($line),'#')&&preg_match('~RewriteRule[^\r\n]*sitemap[^\r\n]*sitemap\.php~i',$line))return true;}
return false;
}
if(($_SERVER['REQUEST_METHOD']??'GET')==='POST'){
verify_csrf();
try{
$action=(string)($_POST['action']??'');
if($action==='install'){
if(is_file($manifest))throw new RuntimeException('Ta poprawka jest już zainstalowana. Użyj panelu kontroli, nie instaluj ponownie.');
if(is_file($root.'/sitemap.xml'))throw new RuntimeException('Fizyczny plik sitemap.xml już istnieje. Nie nadpisuję go: trzeba najpierw wyjaśnić konflikt z dynamiczną mapą.');
$htfile=$root.'/.htaccess';
if(!is_file($htfile)||!is_readable($htfile))throw new RuntimeException('Brak dostępu do .htaccess — nie można bezpiecznie włączyć trasy /sitemap.xml');
if(!function_exists('p164_sitemap_data'))throw new RuntimeException('Brakuje modułu mapy. Wgraj includes/polana_v166_seo.php.');
$data=p164_sitemap_data();$xml=p164_sitemap_xml($data);
if(!str_starts_with($xml,'<?xml ')||!str_contains($xml,'<urlset '))throw new RuntimeException('Generowanie XML nie powiodło się. Nic nie zmieniono.');
$target=[];
$target['sitemap.php']=pv166_script();
$ht=(string)file_get_contents($htfile);
$patched=pv166_route($ht);
if($patched!==$ht)$target['.htaccess']=$patched;
// Do not touch robots.php: existing robots.php already links sitemap.xml.
if(!is_dir($backupDir)&&!mkdir($backupDir,0700,true))throw new RuntimeException('Nie można utworzyć kopii bezpieczeństwa poza WWW.');
if(!is_writable($backupDir))throw new RuntimeException('Katalog backupów nie jest zapisywalny.');
$meta=[];
foreach($target as $rel=>$content){
$file=$root.'/'.$rel;
if(!is_writable(dirname($file)))throw new RuntimeException('Brak zapisu w katalogu dla '.$rel);
$old=is_file($file)?file_get_contents($file):null;
if($old===false)throw new RuntimeException('Brak dostępu do '.$rel);
$backup=$backupDir.'/'.($rel==='.htaccess'?'htaccess':'sitemap_php').'.backup';
if($old!==null){if(file_put_contents($backup,$old,LOCK_EX)!==strlen($old))throw new RuntimeException('Błąd zapisu kopii '.$rel);@chmod($backup,0600);}
$meta[$rel]=['old_sha'=>$old===null?null:hash('sha256',$old),'new_sha'=>hash('sha256',$content),'new_file'=>$old===null];
}
$json=json_encode(['files'=>$meta,'created'=>date(DATE_ATOM)],JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE);
if(file_put_contents($manifest,$json,LOCK_EX)!==strlen($json))throw new RuntimeException('Nie zapisano manifestu kopii.');
@chmod($manifest,0600);
$changed=[];
try {foreach($target as $rel=>$content){pv166_write($root.'/'.$rel,$content);$changed[]=$rel;}}
catch(Throwable $ex){
foreach(array_reverse($changed) as $rel){$info=$meta[$rel];if($info['new_file'])@unlink($root.'/'.$rel);else{$back=$backupDir.'/'.($rel==='.htaccess'?'htaccess':'sitemap_php').'.backup';pv166_write($root.'/'.$rel,(string)file_get_contents($back));}}
@unlink($manifest);throw $ex;
}
admin_log('polana_v166_xml','Naprawiono sitemap.php i trasę XML');
$ok='Generator mapy został włączony. Sprawdź teraz /sitemap.xml oraz jego typ odpowiedzi.';
}elseif($action==='rollback'){
if(!is_file($manifest))throw new RuntimeException('Brak informacji o instalacji.');
$meta=json_decode((string)file_get_contents($manifest),true,512,JSON_THROW_ON_ERROR);
$files=$meta['files']??[];
if(!$files||!is_array($files))throw new RuntimeException('Niepoprawny manifest backupu.');
foreach($files as $rel=>$info){
if(!in_array($rel,['sitemap.php','.htaccess'],true))throw new RuntimeException('Nieznana ścieżka.');
$file=$root.'/'.$rel;
if(!is_file($file)||hash_file('sha256',$file)!==$info['new_sha'])throw new RuntimeException('Plik '.$rel.' zmienił się po instalacji — automatyczne cofnięcie wstrzymane.');
if(!$info['new_file']){
$backup=$backupDir.'/'.($rel==='.htaccess'?'htaccess':'sitemap_php').'.backup';
if(!is_file($backup)||hash_file('sha256',$backup)!==$info['old_sha'])throw new RuntimeException('Niepoprawna kopia '.$rel);
}
}
foreach($files as $rel=>$info){
$path=$root.'/'.$rel;
if($info['new_file'])unlink($path);
else pv166_write($path,(string)file_get_contents($backupDir.'/'.($rel==='.htaccess'?'htaccess':'sitemap_php').'.backup'));
}
rename($manifest,$manifest.'.restored_'.date('Ymd_His'));
$ok='Przywrócono pliki sitemap.php i .htaccess.';
}else throw new RuntimeException('Nieznana operacja.');
}catch(Throwable $e){$error=$e->getMessage();error_log('POLANA V166 sitemap installer: '.$error);}
}
$stats=['pl'=>0,'en'=>0,'de'=>0,'es'=>0];$xml='';$invalid='';$ready=false;$splash=false;
try{
if(!function_exists('p164_sitemap_data'))throw new RuntimeException($loadError?:'Brak funkcji generującej sitemap');
$data=p164_sitemap_data();
$xml=p164_sitemap_xml($data);
foreach($data['urls'] as $row)if(isset($stats[$row['lang']]))$stats[$row['lang']]++;
$splash=(bool)($data['splash']??false);
if(class_exists('DOMDocument')){
$dom=new DOMDocument();$prior=libxml_use_internal_errors(true);
$valid=$dom->loadXML($xml,LIBXML_NONET);
libxml_clear_errors();libxml_use_internal_errors($prior);
if(!$valid)throw new RuntimeException('Błąd składni generowanego XML.');
}
$ready=true;
}catch(Throwable $e){$invalid=$e->getMessage();}
$ht=is_file($root.'/.htaccess')?(string)file_get_contents($root.'/.htaccess'):'';
$hasRoute=pv166_routes_ok($ht);
$hasXmlFile=is_file($root.'/sitemap.xml');
$existing=is_file($root.'/sitemap.php');
$oldScript=$existing?(string)file_get_contents($root.'/sitemap.php'):'';
$newScript=str_contains($oldScript,'POLANA V16.6');
$oldV164=str_contains($oldScript,'polana_v164_seo.php');
render_admin_header('SEO — diagnostyka sitemap.xml');
?>
<style>
.pv166{max-width:1050px;margin:22px auto 70px;padding:15px;color:#22382a}
.pv166 .panel{padding:18px;margin:14px 0;border:1px solid #d7e3d8;border-radius:15px;background:#fff}
.pv166 .grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.pv166 .tile{padding:14px;background:#eef5ed;border-radius:11px;text-align:center}
.pv166 .btn{display:inline-flex;padding:12px 16px;border-radius:10px;background:#285438;color:white;border:0;text-decoration:none;cursor:pointer;font:inherit;margin:4px 7px 4px 0}
.pv166 .btn.alt{background:#e7f0e7;color:#21442c}.pv166 .ok{color:#196d32}.pv166 .bad{color:#ab3b23}.pv166 pre{white-space:pre-wrap;word-break:break-word;background:#f2f5f2;padding:13px;border-radius:9px}
@media(max-width:680px){.pv166 .grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
</style>
<main class="pv166">
<h1>Mapa strony Google — XML</h1>
<p>Poprawny adres do Google: <b>https://mojapolanasmakow.pl/sitemap.xml</b>. Plik <code>sitemap.php</code> generuje XML po stronie serwera; fizyczny <code>sitemap.xml</code> nie jest potrzebny.</p>
<?php if($error):?><section class="panel bad"><?=pv166_h($error)?></section><?php endif;?>
<?php if($ok):?><section class="panel ok"><?=pv166_h($ok)?></section><?php endif;?>
<div class="grid"><?php foreach($stats as $lang=>$n):?><div class="tile"><b><?=strtoupper($lang)?></b><h2><?=$n?></h2><small>adresów</small></div><?php endforeach;?></div>
<section class="panel">
<h2>Diagnostyka</h2>
<p class="<?=$ready?'ok':'bad'?>">Generator XML: <?=$ready?'OK, prawidłowy format':'BŁĄD: '.pv166_h($invalid)?></p>
<p class="<?=$hasRoute?'ok':'bad'?>">Przekierowanie <code>/sitemap.xml</code> w .htaccess: <?=$hasRoute?'ZNALEZIONE':'BRAK / nierozpoznana reguła'?></p>
<p class="<?=$hasXmlFile?'bad':'ok'?>">Fizyczny sitemap.xml: <?=$hasXmlFile?'ISTNIEJE (możliwy konflikt — poprawka nie nadpisuje pliku)':'BRAK (prawidłowo dla mapy dynamicznej)'?></p>
<p>Generator w <code>sitemap.php</code>: <?=$newScript?'V16.6':($oldV164?'V16.4':($existing?'starsza/innego rodzaju wersja':'BRAK'))?></p>
<?php if($splash):?><p class="bad">Aktywna zaślepka: mapa jest pusta, bo publiczne indeksowanie zostało wyłączone.</p><?php endif;?>
<div><a class="btn alt" href="/sitemap.xml" target="_blank" rel="noopener">Otwórz sitemap.xml</a><a class="btn alt" href="/sitemap.php" target="_blank" rel="noopener">Otwórz sitemap.php</a><a class="btn alt" href="/robots.txt" target="_blank" rel="noopener">robots.txt</a><button type="button" class="btn alt" id="pv166-check">Sprawdź odpowiedź HTTP/XML</button></div>
<pre id="pv166-result" aria-live="polite">Kliknij „Sprawdź odpowiedź HTTP/XML”, aby wykonać test z tej przeglądarki na własnej domenie.</pre>
</section>
<section class="panel">
<h2>Naprawa jednym kliknięciem</h2>
<p>Instalator tworzy kopię <code>sitemap.php</code> i ewentualnie <code>.htaccess</code> poza WWW. Nie zmienia menu, danych klientów, tłumaczeń ani bloga. Nie instaluje crona.</p>
<form method="post" onsubmit="return confirm('Włączyć dynamiczną mapę XML i zrobić backup plików?')"><?=csrf_field()?><button class="btn" name="action" value="install" type="submit">Napraw XML / uruchom mapę Google</button></form>
<form method="post" onsubmit="return confirm('Przywrócić poprzedni generator mapy i reguły?')"><?=csrf_field()?><button class="btn alt" name="action" value="rollback" type="submit">Przywróć poprzednią wersję</button></form>
<p>Jeżeli działa już mapa V16.4, nie trzeba jej ponownie instalować — wystarczy sprawdzić odpowiedź HTTP i zgłosić właściwy adres w Search Console.</p>
</section>
<section class="panel">
<h2>Google Search Console</h2>
<p>Do zgłoszenia użyj <code>https://mojapolanasmakow.pl/sitemap.xml</code> (nie <code>/sitemap.php</code>).</p>
<a class="btn alt" href="https://search.google.com/search-console/welcome" target="_blank" rel="noopener noreferrer">Google Search Console</a>
<a class="btn alt" href="/admin/polana-v164-seo.php">Panel SEO</a>
<a class="btn alt" href="/admin/polana-menu-centrum.php">Panel menu</a>
</section>
</main>
<script>
(()=>{const b=document.querySelector('#pv166-check'),out=document.querySelector('#pv166-result');if(!b||!out)return;
b.addEventListener('click',async()=>{b.disabled=true;out.textContent='Sprawdzam /sitemap.xml…';try{
const r=await fetch('/sitemap.xml?check='+Date.now(),{cache:'no-store',credentials:'same-origin'});
const type=r.headers.get('content-type')||'(brak)';const body=await r.text();const d=new DOMParser().parseFromString(body,'application/xml');const bad=d.querySelector('parsererror');
const urls=bad?0:d.getElementsByTagNameNS('http://www.sitemaps.org/schemas/sitemap/0.9','url').length;
out.textContent='HTTP: '+r.status+'\nContent-Type: '+type+'\nXML: '+(!bad&&d.documentElement.localName==='urlset'?'POPRAWNY':'NIEPOPRAWNY')+'\nAdresy w XML: '+urls+'\nPierwsze 200 znaków: '+body.slice(0,200);
}catch(e){out.textContent='Błąd testu: '+String(e.message||e)}finally{b.disabled=false}})})();
</script>
<?php render_admin_footer(); ?>