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//mobile-access.php
<?php
/**
 * mobile-access.php – Backoffice-Endpunkt für „Mobile Zugänge" (Tagesansicht-Tab).
 *
 * Nur für eingeloggte Administratoren. Aktionen (action=):
 *   create  POST  -> neuen Zugang anlegen, liefert Token/Link/QR zurück
 *   list    GET   -> aktive Zugänge eines Tages (für die Verwaltungsliste)
 *   revoke  POST  -> Zugang deaktivieren (ma_active=0)
 *   push    POST  -> Link + QR via Pushover an den eingeloggten Benutzer senden
 *   qr      GET   -> QR-Code-PNG zu einem Token (Bildquelle in der Liste)
 */
require_once( __DIR__ . '/includes/config.inc.php' );
require_once( __DIR__ . '/includes/day-arrivals.php' );
require_once( __DIR__ . '/includes/mobileaccess.php' );
@ini_set( 'display_errors', '0' );
error_reporting( 0 );

function ma_json( $a ) { while ( ob_get_level() > 0 ) ob_end_clean(); header( 'Content-Type: application/json; charset=utf-8' ); echo json_encode( $a ); exit(); }
function ma_fail( $m ) { ma_json( array( 'ok' => false, 'error' => $m ) ); }

if ( ! function_exists( 'is_admin' ) || ! is_admin() ) ma_fail( 'Nicht berechtigt.' );

$action = (string) ( $_GET['action'] ?? ( $_POST['action'] ?? '' ) );
$db = new MysqliDb( MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB );
pacim_ma_ensure_table( $db );
$uid = function_exists( 'current_user_id' ) ? current_user_id() : 0;

/** Eingabe-Felder eines Zugangs aus dem POST säubern (für create + update). */
function ma_read_fields() {
    $expires = null;
    $exRaw = trim( (string) ( $_POST['expires'] ?? '' ) );
    if ( $exRaw !== '' ) { $ts = strtotime( str_replace( 'T', ' ', $exRaw ) ); if ( $ts ) $expires = date( 'Y-m-d H:i:s', $ts ); }
    return array(
        'ma_label'       => ( ( $l = trim( mb_substr( (string) ( $_POST['label'] ?? '' ), 0, 120 ) ) ) !== '' ? $l : null ),
        'ma_mode'        => pacim_ma_clean_mode( $_POST['mode'] ?? 'anreise' ),
        'ma_parking'     => implode( ',', pacim_ma_clean_parking( $_POST['parking'] ?? '' ) ),
        'ma_statuses'    => implode( ',', pacim_ma_clean_statuses( $_POST['statuses'] ?? '' ) ),
        'ma_ship'        => trim( (string) ( $_POST['ship'] ?? '' ) ),
        'ma_trip'        => (int) ( $_POST['trip'] ?? 0 ),
        'ma_from'        => preg_match( '/^([01]\d|2[0-3]):[0-5]\d$/', (string) ( $_POST['from'] ?? '' ) ) ? $_POST['from'] : '',
        'ma_to'          => preg_match( '/^([01]\d|2[0-3]):[0-5]\d$/', (string) ( $_POST['to'] ?? '' ) ) ? $_POST['to'] : '',
        'ma_cols'        => implode( ',', pacim_ma_clean_cols( $_POST['cols'] ?? 'type,time,dur' ) ),
        'ma_perm_action' => ! empty( $_POST['perm_action'] ) ? 1 : 0,
        'ma_perm_search' => ! empty( $_POST['perm_search'] ) ? 1 : 0,
        'ma_img_perms'   => implode( ',', pacim_ma_clean_imgperms( $_POST['img_perms'] ?? '' ) ),
        'ma_notes'       => ! empty( $_POST['notes'] ) ? 1 : 0,
        'ma_expires'     => $expires,
    );
}
/** Antwort-Objekt zu einem Zugang (für create/update). */
function ma_result( $db, $id, $uid ) {
    $r = $db->rawQueryOne( "SELECT * FROM pacim_mobile_access WHERE ma_id = ?", array( (int) $id ) );
    $url = ma_url( $r['ma_token'] );
    return array(
        'ok' => true, 'id' => (int) $id, 'token' => $r['ma_token'], 'url' => $url,
        'qr' => 'data:image/png;base64,' . base64_encode( ma_qr_png( $url, 8 ) ),
        'qr_url' => SITE_URL . '/mobile-access.php?action=qr&token=' . $r['ma_token'],
        'label' => (string) $r['ma_label'], 'summary' => pacim_ma_summary( $r ),
        'perm_action' => (int) $r['ma_perm_action'], 'perm_search' => (int) $r['ma_perm_search'],
        'notes' => (int) ( $r['ma_notes'] ?? 0 ),
        'has_pin' => ( (string) $r['ma_pin'] !== '' ),
        'expires' => ! empty( $r['ma_expires'] ) ? date( 'd.m.Y H:i', strtotime( $r['ma_expires'] ) ) : '',
        'pushAvailable' => ( class_exists( 'pushnotify' ) && pushnotify::configured() && pushnotify::userKey( $uid ) !== '' ),
    );
}

/** QR-Code-PNG (Binärdaten) für eine URL. */
function ma_qr_png( $url, $size = 8 ) {
    require_once( PATH_SYSTEM . '/includes/plugins/tcpdf/tcpdf_barcodes_2d.php' );
    $bc = new TCPDF2DBarcode( (string) $url, 'QRCODE,M' );
    return $bc->getBarcodePngData( $size, $size, array( 13, 44, 68 ) );
}
function ma_url( $token ) { return SITE_URL . '/day-list.php?t=' . $token; }

/* ====================================================== QR-Bild ausliefern */
if ( $action === 'qr' ) {
    $token = trim( (string) ( $_GET['token'] ?? '' ) );
    if ( ! preg_match( '/^[a-f0-9]{8,32}$/', $token ) ) { http_response_code( 404 ); exit(); }
    $png = ma_qr_png( ma_url( $token ), (int) ( $_GET['s'] ?? 8 ) );
    while ( ob_get_level() > 0 ) ob_end_clean();
    header( 'Content-Type: image/png' );
    header( 'Cache-Control: private, max-age=86400' );
    echo $png; exit();
}

/* ====================================================== Erstellen */
if ( $action === 'create' ) {
    $date = substr( (string) ( $_POST['date'] ?? '' ), 0, 10 );
    if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date ) ) ma_fail( 'Ungültiges Datum.' );

    // eindeutigen Token erzeugen
    $token = '';
    for ( $i = 0; $i < 6; $i++ ) {
        $cand = bin2hex( random_bytes( 12 ) );
        if ( ! $db->rawQueryOne( "SELECT 1 AS x FROM pacim_mobile_access WHERE ma_token = ?", array( $cand ) ) ) { $token = $cand; break; }
    }
    if ( $token === '' ) ma_fail( 'Token-Erzeugung fehlgeschlagen.' );

    $uname = trim( (string) ( $_SESSION['user_name'] ?? ( $_SESSION['name'] ?? '' ) ) );
    $data  = ma_read_fields();
    $pin   = preg_replace( '/\D/', '', (string) ( $_POST['pin'] ?? '' ) );
    $data['ma_pin']   = ( strlen( $pin ) >= 4 && strlen( $pin ) <= 10 ) ? pacim_ma_pin_hash( $token, $pin ) : '';
    $data['ma_token'] = $token; $data['ma_date'] = $date; $data['ma_active'] = 1;
    $data['ma_created_by'] = $uid; $data['ma_created_name'] = ( $uname !== '' ? $uname : null );
    $data['ma_created'] = date( 'Y-m-d H:i:s' );

    $ok = $db->insert( 'pacim_mobile_access', $data );
    if ( ! $ok ) ma_fail( 'Konnte nicht gespeichert werden.' );
    ma_json( ma_result( $db, (int) $ok, $uid ) );
}

/* ====================================================== Einstellungen laden (zum Bearbeiten) */
if ( $action === 'get' ) {
    $id = (int) ( $_GET['id'] ?? 0 );
    $r = $db->rawQueryOne( "SELECT * FROM pacim_mobile_access WHERE ma_id = ? AND ma_active = 1", array( $id ) );
    if ( ! $r ) ma_fail( 'Zugang nicht gefunden.' );
    ma_json( array( 'ok' => true, 'access' => array(
        'id' => (int) $r['ma_id'], 'label' => (string) $r['ma_label'],
        'mode' => pacim_ma_mode( $r ),
        'parking' => $r['ma_parking'], 'statuses' => $r['ma_statuses'], 'cols' => $r['ma_cols'],
        'ship' => (string) $r['ma_ship'], 'trip' => (int) $r['ma_trip'],
        'from' => (string) $r['ma_from'], 'to' => (string) $r['ma_to'],
        'perm_action' => (int) $r['ma_perm_action'], 'perm_search' => (int) $r['ma_perm_search'],
        'img_perms' => isset( $r['ma_img_perms'] ) ? (string) $r['ma_img_perms'] : '',
        'notes' => (int) ( $r['ma_notes'] ?? 0 ),
        'has_pin' => ( (string) $r['ma_pin'] !== '' ),
        'expires' => ! empty( $r['ma_expires'] ) ? date( 'Y-m-d\TH:i', strtotime( $r['ma_expires'] ) ) : '',
    ) ) );
}

/* ====================================================== Bearbeiten (Token bleibt gültig) */
if ( $action === 'update' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    $r = $db->rawQueryOne( "SELECT ma_id, ma_token FROM pacim_mobile_access WHERE ma_id = ? AND ma_active = 1", array( $id ) );
    if ( ! $r ) ma_fail( 'Zugang nicht gefunden.' );
    $upd = ma_read_fields();
    // PIN: leer = unverändert; „entfernen" löscht; 4–10 Ziffern = neue PIN.
    $pin = preg_replace( '/\D/', '', (string) ( $_POST['pin'] ?? '' ) );
    if ( ! empty( $_POST['pin_remove'] ) )                       $upd['ma_pin'] = '';
    elseif ( strlen( $pin ) >= 4 && strlen( $pin ) <= 10 )        $upd['ma_pin'] = pacim_ma_pin_hash( $r['ma_token'], $pin );
    $db->where( 'ma_id', $id );
    if ( $db->update( 'pacim_mobile_access', $upd ) === false ) ma_fail( 'Konnte nicht gespeichert werden.' );
    ma_json( ma_result( $db, $id, $uid ) );
}

/* ====================================================== Liste (eines Tages) */
if ( $action === 'list' ) {
    $date = substr( (string) ( $_GET['date'] ?? '' ), 0, 10 );
    if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date ) ) ma_fail( 'Ungültiges Datum.' );
    // Für diesen Tag gültige Zugänge: eigener Tag (ma_date) ODER längerer/unbegrenzter Gültigkeitszeitraum,
    // der diesen Tag noch abdeckt (ma_date <= Tag UND (ma_expires leer ODER ma_expires >= Tagesbeginn)).
    $rows = $db->rawQuery(
        "SELECT * FROM pacim_mobile_access
          WHERE ma_active = 1 AND DATE(ma_date) <= ? AND ( ma_expires IS NULL OR ma_expires = '0000-00-00 00:00:00' OR ma_expires >= ? )
          ORDER BY ma_date DESC, ma_id DESC",
        array( $date, $date . ' 00:00:00' ) );
    $items = array();
    foreach ( (array) $rows as $r ) {
        $expTs = ! empty( $r['ma_expires'] ) ? strtotime( $r['ma_expires'] ) : 0;
        $items[] = array(
            'id' => (int) $r['ma_id'], 'token' => $r['ma_token'], 'url' => ma_url( $r['ma_token'] ),
            'qr_url' => SITE_URL . '/mobile-access.php?action=qr&token=' . $r['ma_token'],
            'label' => (string) $r['ma_label'], 'summary' => pacim_ma_summary( $r ),
            'perm_action' => (int) $r['ma_perm_action'], 'perm_search' => (int) $r['ma_perm_search'],
            'img_perms' => isset( $r['ma_img_perms'] ) ? (string) $r['ma_img_perms'] : '',
            'notes' => (int) ( $r['ma_notes'] ?? 0 ),
            'has_pin' => ( (string) $r['ma_pin'] !== '' ),
            'pushAvailable' => ( class_exists( 'pushnotify' ) && pushnotify::configured() && pushnotify::userKey( $uid ) !== '' ),
            'expires' => $expTs ? date( 'd.m.Y H:i', $expTs ) : '',
            'expired' => ( $expTs && $expTs < time() ),
            'created' => $r['ma_created'] ? date( 'd.m. H:i', strtotime( $r['ma_created'] ) ) : '',
            'created_name' => (string) $r['ma_created_name'],
        );
    }
    ma_json( array( 'ok' => true, 'items' => $items ) );
}

/* ====================================================== Widerruf */
if ( $action === 'revoke' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    if ( $id <= 0 ) ma_fail( 'Ungültige ID.' );
    $db->where( 'ma_id', $id ); $db->update( 'pacim_mobile_access', array( 'ma_active' => 0 ) );
    ma_json( array( 'ok' => true ) );
}

/* ====================================================== Per Pushover senden */
if ( $action === 'push' ) {
    $token = trim( (string) ( $_POST['token'] ?? '' ) );
    $row = pacim_ma_load( $db, $token );
    if ( ! $row ) ma_fail( 'Zugang nicht gefunden oder abgelaufen.' );
    $uid = function_exists( 'current_user_id' ) ? current_user_id() : 0;
    if ( ! class_exists( 'pushnotify' ) || ! pushnotify::configured() ) ma_fail( 'Pushover ist nicht konfiguriert.' );
    $key = pushnotify::userKey( $uid );
    if ( $key === '' ) ma_fail( 'Für Ihren Account ist kein Pushover-Key hinterlegt.' );

    $url = ma_url( $token );
    $lab = trim( (string) $row['ma_label'] );
    $title = 'Mobil-Zugang' . ( $lab !== '' ? ' · ' . $lab : '' );
    $sum = implode( ' · ', pacim_ma_summary( $row ) );
    $msg = 'Tagesliste ' . date( 'd.m.Y', strtotime( $row['ma_date'] ) )
         . ( $sum !== '' ? "\nFilter: " . $sum : '' )
         . "\nRechte: " . ( (int) $row['ma_perm_action'] ? 'Check-in & Zahlung' : 'nur Ansicht' )
         . ( (int) $row['ma_perm_search'] ? ', Suche über Filter hinaus' : '' )
         . "\n\nLink öffnen und QR-Code scannen lassen.";
    $err = null;
    $png = ma_qr_png( $url, 10 );
    $sent = pushnotify::push( $key, $title, $msg, $url, 'Tagesliste öffnen', $err, false, false, $png );
    if ( ! $sent ) ma_fail( $err ?: 'Pushover-Versand fehlgeschlagen.' );
    ma_json( array( 'ok' => true, 'message' => 'Link & QR an dein Gerät gesendet.' ) );
}

ma_fail( 'Unbekannte Aktion.' );

Youez - 2016 - github.com/yon3zu
LinuXploit