403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/seaside.pacim.de/web/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/seaside.pacim.de/web/sw.js
/*
 * sw.js – Service Worker der PaCIM Web-App (Terminal / Anreise-Abreise-Ansicht / Buchung).
 * Zweck: Offline-NAVIGATION + LESEN. KEIN Schreib-Queue (Check-in/Zahlung brauchen weiter Verbindung).
 *
 * Strategie:
 *  - App-Seiten (terminal.php / day-list.php / checkin.php): stale-while-revalidate (cache-first) –
 *    gecachte Seite kommt SOFORT, Aktualisierung im Hintergrund. Dadurch öffnet der Wechsel
 *    Ansicht<->Terminal ohne Warten; bei neuem SW wird der Cache geleert -> erster Aufruf frisch.
 *  - Statische Assets (/assets/...): stale-while-revalidate.
 *  - ALLES andere (POST, AJAX-Endpunkte wie action=poll/dashwidget, das CRM) wird NICHT angefasst
 *    und läuft normal über das Netz.
 */
const CACHE = 'pacim-webapp-v40';
// terminal.php bewusst NICHT hier: es ist das Auth-Gateway und liefert unter derselben URL je nach
// PIN-/Login-Cookie unterschiedliche Seiten -> wird separat NETWORK-FIRST behandelt (siehe fetch).
const APP_PAGES = ['/day-list.php', '/checkin.php'];

// Voll-Seite einer App-Ansicht? (GET, App-Pfad, KEIN action=… -> AJAX-Endpunkte wie poll/dashwidget bleiben außen vor)
// Gilt für echte Navigationen UND fürs Hintergrund-Vorladen (prefetch) der Ansichten.
function isAppDoc(req, url) {
  return req.method === 'GET' && APP_PAGES.indexOf(url.pathname) >= 0 && !url.searchParams.has('action');
}

// Offline-Fallback (kein Netz UND nichts im Cache): zentrierte Meldung + „Erneut versuchen"-Button.
const OFFLINE_HTML = `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<style>
  html,body{margin:0;height:100%;}
  body{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;
    font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#0d2c44;text-align:center;padding:24px;}
  .ov-t{font-size:18px;font-weight:700;}
  .ov-s{font-size:15px;color:#5b7488;margin-top:6px;}
  .ov-btn{margin-top:24px;display:inline-flex;align-items:center;gap:8px;background:#1b6ca8;color:#fff;border:0;
    border-radius:12px;padding:14px 24px;font:600 16px -apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer;
    -webkit-tap-highlight-color:transparent;}
  .ov-btn:active{filter:brightness(.92);}
</style></head><body>
  <div class="ov-t">Keine Verbindung</div>
  <div class="ov-s">und keine gespeicherte Ansicht vorhanden.</div>
  <button type="button" class="ov-btn" onclick="location.reload()">
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M23 4v6h-6"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
    Erneut versuchen
  </button>
</body></html>`;

self.addEventListener('install', () => { self.skipWaiting(); });

self.addEventListener('activate', (e) => {
  e.waitUntil((async () => {
    const keys = await caches.keys();
    await Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)));  // alte Caches (alte HTML/JS) wegwerfen
    await self.clients.claim();
    // Offene Fenster auf die frische Version neu laden, damit niemand auf veralteter, gecachter Seite hängenbleibt.
    const clients = await self.clients.matchAll({ type: 'window' });
    for (const c of clients) { try { c.navigate(c.url); } catch (_) {} }
  })());
});

self.addEventListener('fetch', (e) => {
  const req = e.request;
  if (req.method !== 'GET') return;                          // Schreibzugriffe nie abfangen
  let url;
  try { url = new URL(req.url); } catch (_) { return; }
  if (url.origin !== self.location.origin) return;           // nur eigene Domain

  // --- Terminal (Auth-Gateway): NETWORK-FIRST ---
  // terminal.php liefert je nach PIN-/Login-Cookie unterschiedliche Seiten (PIN-Screen / Login-Auswahl /
  // Übersicht) UNTER DERSELBEN URL. Cache-first würde nach Login/Logout die falsche gecachte Seite zeigen
  // (z. B. nach Logout die Übersicht -> „eingeloggt ohne PIN", oder PIN doppelt). Daher immer frisch aus dem
  // Netz; der Cache dient nur als Offline-Rückfallebene.
  if (req.method === 'GET' && url.pathname === '/terminal.php' && !url.searchParams.has('action')) {
    e.respondWith((async () => {
      const cache = await caches.open(CACHE);
      try {
        const resp = await fetch(req);
        if (resp && resp.ok) { try { await cache.put(req, resp.clone()); } catch (_) {} }
        return resp;
      } catch (_) {
        const cached = await cache.match(req, { ignoreVary: true });
        return cached || new Response( OFFLINE_HTML, { headers: { 'Content-Type': 'text/html; charset=utf-8' }, status: 503 } );
      }
    })());
    return;
  }

  // --- App-Seiten: stale-while-revalidate (CACHE-FIRST) ---
  // Ist die Seite gecacht (per Vorladen oder früherem Besuch), kommt sie SOFORT aus dem Cache -> der Klick
  // öffnet ohne Warten. Im Hintergrund wird der Cache frisch nachgeladen. Bei neuem SW ist der Cache nach
  // dem activate leer -> erster Aufruf holt frisch (= neuer Code/Stand landet zuverlässig), dann wieder schnell.
  if (isAppDoc(req, url)) {
    const net = (async () => {
      const resp = await fetch(req).catch(() => null);
      if (resp && resp.ok) { try { const c = await caches.open(CACHE); await c.put(req, resp.clone()); } catch (_) {} }
      return resp;
    })();
    e.waitUntil(net.catch(() => {}));                        // Hintergrund-Aktualisierung am Leben halten
    e.respondWith((async () => {
      const cache = await caches.open(CACHE);
      const cached = await cache.match(req, { ignoreVary: true });
      if (cached) return cached;                             // sofort: gespeicherte Ansicht
      return (await net) || new Response( OFFLINE_HTML,        // kein Cache (erster Besuch / nach Update) -> Netz
        { headers: { 'Content-Type': 'text/html; charset=utf-8' }, status: 503 } );
    })());
    return;
  }

  // --- Statische Assets: stale-while-revalidate ---
  if (url.pathname.indexOf('/assets/') === 0) {
    e.respondWith((async () => {
      const cache = await caches.open(CACHE);
      const cached = await cache.match(req);
      const net = fetch(req).then((resp) => {
        if (resp && resp.ok) cache.put(req, resp.clone());
        return resp;
      }).catch(() => null);
      return cached || (await net) || Response.error();
    })());
    return;
  }

  // alles andere: nicht anfassen (Netz)
});

Youez - 2016 - github.com/yon3zu
LinuXploit