403Webshell
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 :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /polana/admin/polana-v1818-gcal-autosync.php
<?php
declare(strict_types=1);
/** POLANA V18.18 — diagnostyka i generator kontrolowanej poprawki auto Google Calendar.
 * Nie zapisuje kodu ani danych, nie wywołuje Google, nie odświeża tokenów.
 */
require_once dirname(__DIR__) . '/includes/functions.php';
if (function_exists('require_admin_role')) {
    require_admin_role();
} else {
    require_login();
    $user = function_exists('admin_user') ? admin_user() : [];
    if (!in_array((string)($user['role'] ?? ''), ['admin', 'administrator'], true)) {
        http_response_code(403); exit('Tylko administrator.');
    }
}
header('Cache-Control: no-store, private, max-age=0');
header('X-Robots-Tag: noindex, nofollow');
header('Referrer-Policy: no-referrer');
const V1818_MARK = 'POLANA_V1818_GCAL_AUTO_STATUS';
function v1818_h(string $value): string { return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
function v1818_root(): string { return dirname(__DIR__); }
function v1818_read(string $rel): ?string {
    $f = v1818_root() . '/' . $rel;
    if (!is_file($f) || is_link($f) || !is_readable($f)) return null;
    $s = @file_get_contents($f);
    return is_string($s) ? $s : null;
}
/** Span named function via PHP lexer; strings/comments cannot confuse the closing brace. */
function v1818_function_span(string $source, string $functionName): ?array {
    $tokens = token_get_all($source);
    $positions = []; $at = 0;
    foreach ($tokens as $token) {
        $positions[] = $at;
        $at += strlen(is_array($token) ? $token[1] : $token);
    }
    $count = count($tokens);
    for ($i=0; $i<$count; $i++) {
        if (!is_array($tokens[$i]) || $tokens[$i][0] !== T_FUNCTION) continue;
        $j=$i+1;
        while ($j<$count && is_array($tokens[$j]) && $tokens[$j][0] === T_WHITESPACE) $j++;
        if ($j<$count && $tokens[$j] === '&') $j++;
        while ($j<$count && is_array($tokens[$j]) && $tokens[$j][0] === T_WHITESPACE) $j++;
        if ($j >= $count || !is_array($tokens[$j]) || $tokens[$j][0] !== T_STRING || $tokens[$j][1] !== $functionName) continue;
        $start = $positions[$i];
        $depth = 0; $bodyStart = null;
        for ($k=$j+1; $k<$count; $k++) {
            $part = $tokens[$k];
            if ($part === '{') { if ($bodyStart === null) {$bodyStart=$positions[$k];$depth=1;} else $depth++; }
            elseif ($part === '}' && $bodyStart !== null) {
                $depth--;
                if ($depth === 0) {
                    $end = $positions[$k] + 1;
                    return ['start'=>$start,'end'=>$end,'text'=>substr($source,$start,$end-$start)];
                }
            } elseif ($part === ';' && $bodyStart === null) break;
        }
    }
    return null;
}
function v1818_hook_present(string $source): ?bool {
    $span=v1818_function_span($source,'reservation_change_status');
    if ($span === null) return null;
    return str_contains($span['text'],'pg173_after_change(') || str_contains($span['text'], V1818_MARK);
}
function v1818_patch(string $source): array {
    $span = v1818_function_span($source, 'reservation_change_status');
    if ($span === null) return ['state'=>'unsupported','detail'=>'Nie znaleziono funkcji reservation_change_status() w aktualnym pliku.','content'=>null];
    if (v1818_hook_present($source)) return ['state'=>'present','detail'=>'Wywołanie pg173_after_change już jest w funkcji. Przyczyna może leżeć w innym handlerze, konfiguracji lub błędzie API. Nie dubluję hooka.','content'=>null];
    $function = $span['text'];
    $needle = '/(?m)^([ \t]+)return[ \t]+\$reservation[ \t]*;(?=[ \t]*\r?$)/';
    $matchCount = preg_match_all($needle, $function, $all, PREG_OFFSET_CAPTURE);
    if ($matchCount !== 1) return ['state'=>'unsupported','detail'=>'Funkcja ma niestandardowy przebieg (brak jednego końcowego return $reservation). Odmowa automatycznej modyfikacji.','content'=>null];
    $returnAt = (int)$all[0][0][1];
    $afterReturn = substr($function, $returnAt + strlen($all[0][0][0]));
    if (!preg_match('/^\s*}\s*$/', $afterReturn)) return ['state'=>'unsupported','detail'=>'return $reservation nie jest końcowym poleceniem funkcji.','content'=>null];
    foreach (['$previous','$status','$id','$adminUserId'] as $symbol) {
        if (!str_contains($function,$symbol)) return ['state'=>'unsupported','detail'=>'Nie potwierdzono zmiennej '. $symbol . ' w funkcji. Bez zgadywania.','content'=>null];
    }
    $insert = <<<'HOOK'
    // POLANA_V1818_GCAL_AUTO_STATUS — wyłącznie po rzeczywistej zmianie statusu.
    if (is_array($previous) && (string)($previous['status'] ?? '') !== (string)$status) {
        try {
            require_once __DIR__ . '/polana_gcal.php';
            if (!function_exists('pg173_after_change')) {
                throw new RuntimeException('Brak pg173_after_change w polana_gcal.php');
            }
            pg173_after_change((int)$id, (int)$adminUserId);
        } catch (Throwable $calendarError) {
            error_log('[POLANA V18.18 CALENDAR] Rezerwacja #'.(int)$id.': '.$calendarError->getMessage());
            if (function_exists('reservation_add_event')) {
                try {
                    reservation_add_event((int)$id, 'calendar_error', 'Automatyczna synchronizacja Google: '.substr($calendarError->getMessage(), 0, 200), (int)$adminUserId);
                } catch (Throwable $ignored) {}
            }
        }
    }

HOOK;
    $patchedFunction = substr_replace($function, $insert, $returnAt, 0);
    $patchedSource = substr_replace($source, $patchedFunction, $span['start'], $span['end']-$span['start']);
    if (substr_count($patchedSource, V1818_MARK) !== 1) return ['state'=>'unsupported','detail'=>'Kontrola instalacji markerów nie powiodła się.','content'=>null];
    return ['state'=>'ready','detail'=>'Można pobrać poprawiony plik do ręcznego wgrania przez FileZilla.','content'=>$patchedSource];
}
function v1818_detect(): array {
    $items = [];
    $checks = [
        'includes/reservations.php'=>'Funkcje rezerwacji',
        'admin/reservation.php'=>'Karta rezerwacji',
        'admin/reservations.php'=>'Lista i operacje masowe',
        'includes/polana_gcal.php'=>'Biblioteka Google Calendar',
        'admin/polana-kalendarz.php'=>'Panel Calendar',
    ];
    foreach ($checks as $rel=>$label) {
        $s=v1818_read($rel);
        $items[$rel]=[
            'label'=>$label,'exists'=>$s!==null,
            'change_status'=>$s===null?null:substr_count($s,'reservation_change_status('),
            'after_change'=>$s===null?null:substr_count($s,'pg173_after_change('),
            'direct_update'=>$s===null?null:(bool)preg_match('/UPDATE\s+`?reservations`?\s+SET[\s\S]{0,250}`?status`?\s*=/i',$s),
            'patched_marker'=>$s!==null && str_contains($s,V1818_MARK),
        ];
    }
    return $items;
}
function v1818_oauth_status(): string {
    $lib=v1818_root().'/includes/polana_gcal.php';
    if (!is_file($lib)) return 'BRAK BIBLIOTEKI';
    try {
        require_once $lib;
        if (!function_exists('pg173_connected')) return 'Nie znaleziono pg173_connected()';
        return pg173_connected() ? 'Konfiguracja kompletna wg pg173_connected()' : 'Konfiguracja niekompletna wg pg173_connected()';
    } catch (Throwable $e) {return 'Błąd odczytu stanu OAuth (szczegóły ukryte)';}
}
function v1818_recent(): array {
    if (!function_exists('db')) return ['db_error'=>'Brak db() w bibliotece strony'];
    try {
        $pdo=db();
        $rows=$pdo->query('SELECT id, status FROM reservations ORDER BY id DESC LIMIT 12')->fetchAll(PDO::FETCH_ASSOC);
        $events=[];
        try {
            $columns=$pdo->query('SHOW COLUMNS FROM reservation_events')->fetchAll(PDO::FETCH_COLUMN);
            $etype=in_array('event_type',$columns,true)?'event_type':(in_array('type',$columns,true)?'type':null);
            if ($etype) {
                $sql='SELECT '.$etype.' AS kind, COUNT(*) AS n FROM reservation_events WHERE '.$etype.' IN (\'calendar_error\',\'calendar_sync\',\'calendar\') GROUP BY '.$etype;
                $events=$pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
            }
        } catch (Throwable $e) {/* tabela może mieć inną nazwę */}
        return ['recent'=>$rows,'event_counts'=>$events];
    } catch (Throwable $e) {return ['db_error'=>'Nie można odczytać tabeli rezerwacji w trybie diagnostycznym.'];}
}
$source=v1818_read('includes/reservations.php');
$patch= $source===null ? ['state'=>'unsupported','detail'=>'Nie można odczytać includes/reservations.php','content'=>null] : v1818_patch($source);
$files=v1818_detect();
$hook= $source===null ? null : v1818_hook_present($source);
$oauth=v1818_oauth_status();
$recent=v1818_recent();
$summary=[
    'version'=>'18.18-diagnostic',
    'timestamp'=>date(DATE_ATOM),
    'oauth'=>$oauth,
    'hook_inside_reservation_change_status'=>$hook,
    'patch_state'=>$patch['state'],
    'patch_reason'=>$patch['detail'],
    'routes'=>$files,
    'database'=>$recent,
    'note'=>'Raport nie potwierdza wysłania wydarzenia do Google. Nie zawiera danych klientów ani sekretów.',
];
$action=(string)($_GET['download']??'');
if ($action==='report') {
    header('Content-Type: application/json; charset=UTF-8');
    header('Content-Disposition: attachment; filename="POLANA_V1818_GCAL_DIAG.json"');
    echo json_encode($summary, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_INVALID_UTF8_SUBSTITUTE);
    exit;
}
if ($action==='original' && $source!==null) {
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="reservations-PRZED-V1818.php.txt"');
    header('X-Content-Type-Options: nosniff');
    echo $source;
    exit;
}
if ($action==='patched' && $patch['state']==='ready') {
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="reservations.php"');
    header('X-Content-Type-Options: nosniff');
    echo $patch['content'];
    exit;
}
if (function_exists('render_admin_header')) {
    render_admin_header('POLANA V18.18 — diagnoza automatycznego kalendarza');
} else {
    echo '<!doctype html><html lang="pl"><meta charset="utf-8"><title>POLANA V18.18</title><body>';
}
?>
<main style="max-width:1050px;margin:30px auto;padding:0 16px;font-family:system-ui,Arial">
<h1>POLANA V18.18 — dlaczego Calendar nie synchronizuje się automatycznie?</h1>
<p><strong>Tryb tylko odczyt.</strong> Ten panel nie wysyła wydarzeń, nie zmienia statusów, nie zapisuje plików i nie dotyka OAuth. Generuje wyłącznie poprawiony plik do pobrania.</p>
<div class="card" style="padding:20px;margin:16px 0;border:1px solid #ddd;border-radius:12px">
<p><strong>Google OAuth:</strong> <?=v1818_h($oauth)?></p>
<p><strong>Hook wewnątrz reservation_change_status():</strong> <?= $hook===null?'FUNKCJA NIEZNANA':($hook?'OBECNY':'BRAK') ?></p>
<p><strong>Możliwość przygotowania poprawki:</strong> <?=v1818_h($patch['state'])?> — <?=v1818_h($patch['detail'])?></p>
<p><a href="?download=report">Pobierz bezpieczny raport JSON</a></p>
</div>
<h2>Ścieżki zmiany statusu</h2>
<table style="width:100%;border-collapse:collapse"><thead><tr><th align="left">Plik</th><th>Istnieje</th><th>Wywołania zmiany statusu</th><th>Wywołania Google</th><th>Bezpośredni UPDATE status</th></tr></thead><tbody>
<?php foreach ($files as $rel=>$item): ?>
<tr style="border-bottom:1px solid #ddd"><td style="padding:8px"><?=v1818_h($rel)?></td><td align="center"><?=$item['exists']?'TAK':'NIE'?></td><td align="center"><?=v1818_h((string)($item['change_status']??'-'))?></td><td align="center"><?=v1818_h((string)($item['after_change']??'-'))?></td><td align="center"><?=$item['direct_update']?'TAK':'NIE'?></td></tr>
<?php endforeach; ?></tbody></table>
<h2>Ostatnie identyfikatory i statusy rezerwacji</h2>
<?php if (isset($recent['db_error'])): ?><p><?=v1818_h($recent['db_error'])?></p><?php else: ?>
<p>Bez imion, numerów telefonu i e-maili. Historia może obejmować wcześniejsze synchronizacje.</p>
<table style="width:100%;border-collapse:collapse"><tr><th>ID</th><th>Status</th></tr>
<?php foreach (($recent['recent']??[]) as $item): ?><tr><td align="center"><?=intval($item['id'])?></td><td align="center"><?=v1818_h((string)$item['status'])?></td></tr><?php endforeach;?></table>
<?php if ($recent['event_counts']??[]): ?><p>Zdarzenia kalendarza w historii: <?=v1818_h(json_encode($recent['event_counts'],JSON_UNESCAPED_UNICODE)?:'')?></p><?php endif; ?>
<?php endif; ?>
<h2>Bezpieczna poprawka, jeśli hook nie istnieje</h2>
<?php if ($patch['state']==='ready'): ?>
<p>1. Pobierz oryginalny plik i zachowaj go poza hostingiem. 2. Pobierz poprawiony plik. 3. Wgraj go przez FileZilla do <code>includes/reservations.php</code>. 4. Potwierdź <strong>nową rezerwację testową z panelu szczegółów</strong>. 5. Sprawdź Google Calendar.</p>
<p><a href="?download=original" style="margin-right:20px">Pobierz oryginał (kopia na komputer)</a> <a href="?download=patched">Pobierz poprawiony reservations.php</a></p>
<p>W przypadku problemów przywróć oryginał przez FileZilla. Nie cofaj rezerwacji produkcyjnych tylko po to, aby ponowić test.</p>
<?php else: ?>
<p>Zmiana automatyczna jest wstrzymana. Prześlij raport JSON — trzeba naprawić istniejącą ścieżkę statusu lub błąd API, nie dodawać drugiego wywołania.</p>
<?php endif; ?>
<p><strong>Uwaga:</strong> aktualizacja Google po masowej zmianie statusów może korzystać z innej ścieżki. Wynik diagnostyki pokaże, czy wymaga ona osobnej poprawki.</p>
</main>
<?php if (function_exists('render_admin_footer')) render_admin_footer(); else echo '</body></html>'; ?>

Youez - 2016 - github.com/yon3zu
LinuXploit