T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/lavocat.quebec/private_html/php-migration/websocket/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.quebec/private_html/php-migration/websocket/chat-server.php
<?php
/**
 * WebSocket Chat Server
 * Real-time messaging system
 */

require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../models/Message.php';
require_once __DIR__ . '/../models/ChatRoom.php';
require_once __DIR__ . '/../models/User.php';
require_once __DIR__ . '/../config/database.php';

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\WebSocket\WsServer;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;

class ChatServer implements MessageComponentInterface {
    protected $clients;
    protected $users;
    protected $database;
    protected $messageModel;
    protected $chatRoomModel;
    protected $userModel;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
        $this->users = [];
        
        // Initialize database connection
        $db = new Database();
        $this->database = $db->getConnection();
        $this->messageModel = new Message($this->database);
        $this->chatRoomModel = new ChatRoom($this->database);
        $this->userModel = new User($this->database);
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $data = json_decode($msg, true);
        
        if (!$data || !isset($data['type'])) {
            return;
        }

        switch ($data['type']) {
            case 'auth':
                $this->handleAuth($from, $data);
                break;
            case 'join_room':
                $this->handleJoinRoom($from, $data);
                break;
            case 'leave_room':
                $this->handleLeaveRoom($from, $data);
                break;
            case 'message':
                $this->handleMessage($from, $data);
                break;
            case 'typing':
                $this->handleTyping($from, $data);
                break;
            case 'stop_typing':
                $this->handleStopTyping($from, $data);
                break;
        }
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
        
        // Remove user from users array
        foreach ($this->users as $userId => $userConn) {
            if ($userConn === $conn) {
                unset($this->users[$userId]);
                break;
            }
        }
        
        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close();
    }

    private function handleAuth(ConnectionInterface $conn, $data) {
        $token = $data['token'] ?? '';
        
        // Verify token and get user
        $user = $this->verifyToken($token);
        
        if ($user) {
            $this->users[$user['id']] = $conn;
            $conn->user = $user;
            
            $conn->send(json_encode([
                'type' => 'auth_success',
                'user' => $user
            ]));
            
            echo "User {$user['name']} authenticated\n";
        } else {
            $conn->send(json_encode([
                'type' => 'auth_error',
                'message' => 'Invalid token'
            ]));
        }
    }

    private function handleJoinRoom(ConnectionInterface $conn, $data) {
        if (!isset($conn->user)) {
            return;
        }

        $roomId = $data['roomId'] ?? '';
        
        // Verify user has access to room
        if ($this->hasRoomAccess($conn->user['id'], $roomId)) {
            $conn->roomId = $roomId;
            
            // Send recent messages
            $messages = $this->messageModel->getRecentByChatRoomId($roomId, 50);
            
            $conn->send(json_encode([
                'type' => 'room_joined',
                'roomId' => $roomId,
                'messages' => $messages
            ]));
            
            echo "User {$conn->user['name']} joined room {$roomId}\n";
        }
    }

    private function handleLeaveRoom(ConnectionInterface $conn, $data) {
        if (isset($conn->roomId)) {
            unset($conn->roomId);
            echo "User {$conn->user['name']} left room\n";
        }
    }

    private function handleMessage(ConnectionInterface $conn, $data) {
        if (!isset($conn->user) || !isset($conn->roomId)) {
            return;
        }

        $content = $data['content'] ?? '';
        $messageType = $data['messageType'] ?? 'TEXT';
        $replyToId = $data['replyToId'] ?? null;

        if (empty($content) && $messageType === 'TEXT') {
            return;
        }

        // Create message in database
        $this->messageModel->content = $content;
        $this->messageModel->type = $messageType;
        $this->messageModel->chatRoomId = $conn->roomId;
        $this->messageModel->userId = $conn->user['id'];
        $this->messageModel->isEdited = 0;
        $this->messageModel->isDeleted = 0;
        $this->messageModel->replyToId = $replyToId;
        $this->messageModel->fileUrl = $data['fileUrl'] ?? null;
        $this->messageModel->fileName = $data['fileName'] ?? null;
        $this->messageModel->fileSize = $data['fileSize'] ?? null;
        $this->messageModel->fileType = $data['fileType'] ?? null;

        if ($this->messageModel->create()) {
            // Get the created message with user info
            $this->messageModel->findById($this->messageModel->id);
            
            $messageData = [
                'type' => 'new_message',
                'message' => [
                    'id' => $this->messageModel->id,
                    'content' => $this->messageModel->content,
                    'type' => $this->messageModel->type,
                    'chatRoomId' => $this->messageModel->chatRoomId,
                    'userId' => $this->messageModel->userId,
                    'userName' => $conn->user['name'],
                    'userRole' => $conn->user['role'],
                    'profilePicture' => $conn->user['profilePicture'],
                    'createdAt' => $this->messageModel->createdAt,
                    'isEdited' => $this->messageModel->isEdited,
                    'replyToId' => $this->messageModel->replyToId,
                    'fileUrl' => $this->messageModel->fileUrl,
                    'fileName' => $this->messageModel->fileName,
                    'fileSize' => $this->messageModel->fileSize,
                    'fileType' => $this->messageModel->fileType
                ]
            ];

            // Broadcast to all clients in the room
            $this->broadcastToRoom($conn->roomId, $messageData, $conn);
            
            echo "Message sent in room {$conn->roomId} by {$conn->user['name']}\n";
        }
    }

    private function handleTyping(ConnectionInterface $conn, $data) {
        if (!isset($conn->user) || !isset($conn->roomId)) {
            return;
        }

        $this->broadcastToRoom($conn->roomId, [
            'type' => 'user_typing',
            'userId' => $conn->user['id'],
            'userName' => $conn->user['name'],
            'roomId' => $conn->roomId
        ], $conn);
    }

    private function handleStopTyping(ConnectionInterface $conn, $data) {
        if (!isset($conn->user) || !isset($conn->roomId)) {
            return;
        }

        $this->broadcastToRoom($conn->roomId, [
            'type' => 'user_stop_typing',
            'userId' => $conn->user['id'],
            'userName' => $conn->user['name'],
            'roomId' => $conn->roomId
        ], $conn);
    }

    private function broadcastToRoom($roomId, $data, $exclude = null) {
        foreach ($this->clients as $client) {
            if ($client !== $exclude && 
                isset($client->roomId) && 
                $client->roomId === $roomId) {
                $client->send(json_encode($data));
            }
        }
    }

    private function verifyToken($token) {
        // Simple token verification - in production, use JWT
        if (empty($token)) {
            return false;
        }

        // For now, we'll use a simple approach
        // In production, implement proper JWT verification
        $query = "SELECT id, name, email, role, profilePicture FROM User WHERE id = :token LIMIT 1";
        $stmt = $this->database->prepare($query);
        $stmt->bindParam(':token', $token);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            return $stmt->fetch(PDO::FETCH_ASSOC);
        }

        return false;
    }

    private function hasRoomAccess($userId, $roomId) {
        // Check if user is participant in the room
        $query = "SELECT COUNT(*) as count FROM ChatParticipant 
                  WHERE userId = :userId AND chatRoomId = :roomId";
        $stmt = $this->database->prepare($query);
        $stmt->bindParam(':userId', $userId);
        $stmt->bindParam(':roomId', $roomId);
        $stmt->execute();

        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return $result['count'] > 0;
    }
}

// Start the server
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new ChatServer()
        )
    ),
    8080
);

echo "Chat server started on port 8080\n";
$server->run();
?>

CasperSecurity Mini