allejo /
bzion
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace BZIon\Socket; |
||
| 4 | |||
| 5 | use BZIon\Event\EventSubscriber; |
||
| 6 | use Player; |
||
| 7 | use Ratchet\ConnectionInterface; |
||
| 8 | use Ratchet\MessageComponentInterface; |
||
| 9 | use React\EventLoop\LoopInterface; |
||
| 10 | use Symfony\Component\Console\Output\OutputInterface; |
||
| 11 | |||
| 12 | class EventPusher implements MessageComponentInterface |
||
| 13 | { |
||
| 14 | /** |
||
| 15 | * The connected clients |
||
| 16 | * @var \SplObjectStorage |
||
| 17 | */ |
||
| 18 | protected $clients; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * The event subscriber |
||
| 22 | * @var EventSubscriber |
||
| 23 | */ |
||
| 24 | protected $subscriber; |
||
| 25 | |||
| 26 | /** |
||
| 27 | * The event loop |
||
| 28 | * @var LoopInterface |
||
| 29 | */ |
||
| 30 | protected $loop; |
||
| 31 | |||
| 32 | /** |
||
| 33 | * The console output |
||
| 34 | * @var OutputInterface|null |
||
| 35 | */ |
||
| 36 | protected $output; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * Max pong time and interval between pings in seconds |
||
| 40 | * @var int |
||
| 41 | */ |
||
| 42 | const KEEP_ALIVE = 300; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * Create a new event pusher handler |
||
| 46 | */ |
||
| 47 | public function __construct(LoopInterface $loop, OutputInterface $output = null) |
||
| 48 | { |
||
| 49 | $this->loop = $loop; |
||
| 50 | $this->output = $output; |
||
| 51 | |||
| 52 | $this->clients = new \SplObjectStorage(); |
||
| 53 | $this->subscriber = \Service::getContainer()->get('kernel.subscriber.bzion_subscriber'); |
||
| 54 | |||
| 55 | // Ping timer |
||
| 56 | $loop->addPeriodicTimer(self::KEEP_ALIVE, array($this, 'ping')); |
||
| 57 | } |
||
| 58 | |||
| 59 | /** |
||
| 60 | * Open the connection |
||
| 61 | * @param ConnectionInterface $conn |
||
| 62 | */ |
||
| 63 | public function onOpen(ConnectionInterface $conn) |
||
| 64 | { |
||
| 65 | // Find which player opened the connection |
||
| 66 | $conn->Player = Player::get($conn->Session->get('playerId')); |
||
|
0 ignored issues
–
show
Accessing
Session on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 67 | |||
| 68 | $conn->pong = true; |
||
|
0 ignored issues
–
show
Accessing
pong on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 69 | |||
| 70 | // Store the new connection to send messages to later |
||
| 71 | $this->clients->attach($conn); |
||
| 72 | |||
| 73 | $this->log( |
||
| 74 | sprintf( |
||
| 75 | "<fg=cyan>Client #{$conn->resourceId} connected from {$conn->remoteAddress}\t ({$conn->Player->getUsername()})</>", |
||
|
0 ignored issues
–
show
Accessing
resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
Accessing
remoteAddress on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
Accessing
Player on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 76 | $conn->resourceId, |
||
|
0 ignored issues
–
show
Accessing
resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 77 | $conn->remoteAddress, |
||
|
0 ignored issues
–
show
Accessing
remoteAddress on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 78 | $conn->Player->getUsername() |
||
|
0 ignored issues
–
show
Accessing
Player on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 79 | ), OutputInterface::VERBOSITY_VERBOSE |
||
| 80 | ); |
||
| 81 | } |
||
| 82 | |||
| 83 | /** |
||
| 84 | * Send a message as a client |
||
| 85 | * @param ConnectionInterface $from |
||
| 86 | * @param mixed $msg |
||
| 87 | */ |
||
| 88 | public function onMessage(ConnectionInterface $from, $msg) |
||
| 89 | { |
||
| 90 | $this->log("Received message from #{$from->resourceId}"); |
||
|
0 ignored issues
–
show
Accessing
resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 91 | |||
| 92 | // Record the reception of the message to prevent a ping timeout |
||
| 93 | $from->pong = true; |
||
|
0 ignored issues
–
show
Accessing
pong on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 94 | } |
||
| 95 | |||
| 96 | /** |
||
| 97 | * Close a connection |
||
| 98 | * @param ConnectionInterface $conn |
||
| 99 | */ |
||
| 100 | public function onClose(ConnectionInterface $conn) |
||
| 101 | { |
||
| 102 | // The connection is closed, remove it, as we can no longer send it messages |
||
| 103 | $this->clients->detach($conn); |
||
| 104 | |||
| 105 | $this->log( |
||
| 106 | sprintf( |
||
| 107 | "<fg=yellow>Client #{$conn->resourceId} disconnected from {$conn->remoteAddress}\t ({$conn->Player->getUsername()})</>", |
||
|
0 ignored issues
–
show
Accessing
resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
Accessing
remoteAddress on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
Accessing
Player on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 108 | $conn->resourceId, |
||
|
0 ignored issues
–
show
Accessing
resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 109 | $conn->remoteAddress, |
||
|
0 ignored issues
–
show
Accessing
remoteAddress on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 110 | $conn->Player->getUsername() |
||
|
0 ignored issues
–
show
Accessing
Player on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 111 | ), OutputInterface::VERBOSITY_VERBOSE |
||
| 112 | ); |
||
| 113 | } |
||
| 114 | |||
| 115 | /** |
||
| 116 | * Action to call on an error |
||
| 117 | */ |
||
| 118 | public function onError(ConnectionInterface $conn, \Exception $e) |
||
| 119 | { |
||
| 120 | echo "An error has occurred: {$e->getMessage()}\n"; |
||
| 121 | |||
| 122 | $conn->close(); |
||
| 123 | } |
||
| 124 | |||
| 125 | /** |
||
| 126 | * Pushes or emails a new private message to the user |
||
| 127 | * |
||
| 128 | * @param array $event The event data we received from the web server |
||
| 129 | */ |
||
| 130 | private function onMessageServerEvent($event) |
||
| 131 | { |
||
| 132 | // A list of players who received a message so that we can e-mail the |
||
| 133 | // ones who didn't |
||
| 134 | $received = array(); |
||
| 135 | |||
| 136 | $conversation = \Conversation::get($event->data->conversation); |
||
| 137 | |||
| 138 | $conversationMembers = $conversation->getPlayerIds(); |
||
| 139 | |||
| 140 | foreach ($this->clients as $client) { |
||
| 141 | $player = $client->Player; |
||
| 142 | |||
| 143 | if (!in_array($player->getId(), $conversationMembers)) { |
||
| 144 | // Don't notify that player, he doesn't belong in the conversation |
||
| 145 | continue; |
||
| 146 | } |
||
| 147 | |||
| 148 | $event->notification_count = $player->countUnreadNotifications(); |
||
| 149 | $event->message_count = $player->countUnreadMessages(); |
||
| 150 | |||
| 151 | $this->send($client, $event); |
||
| 152 | $received[] = $player->getId(); |
||
| 153 | } |
||
| 154 | |||
| 155 | // Send e-mails |
||
| 156 | foreach ($event->data->recipients as $recipient) { |
||
| 157 | // Only send an email to users who aren't currently logged in |
||
| 158 | if (!in_array($recipient, $received)) { |
||
| 159 | $this->log("<fg=green>E-mailing player {$recipient->getId()} ({$recipient->getUsername()})</>"); |
||
| 160 | |||
| 161 | $this->subscriber->sendEmails( |
||
| 162 | 'New message received', |
||
| 163 | array($recipient), |
||
| 164 | 'message', |
||
| 165 | array('message' => \Message::get($event->data->message)) |
||
| 166 | ); |
||
| 167 | } |
||
| 168 | } |
||
| 169 | } |
||
| 170 | |||
| 171 | /** |
||
| 172 | * Pushes or emails a new notification to the user |
||
| 173 | * |
||
| 174 | * @param array $event The event data we received from the web server |
||
| 175 | */ |
||
| 176 | private function onNotificationServerEvent($event) |
||
| 177 | { |
||
| 178 | $notification = \Notification::get($event->data->notification); |
||
| 179 | |||
| 180 | // Whether we've notified that player in real time - if he isn't online |
||
| 181 | // at the moment, we'll send an e-mail to him |
||
| 182 | $active = false; |
||
| 183 | |||
| 184 | foreach ($this->clients as $client) { |
||
| 185 | if ($client->Player->getId() == $event->data->receiver) { |
||
| 186 | $this->send($client, $event); |
||
| 187 | $active = true; |
||
| 188 | } |
||
| 189 | } |
||
| 190 | |||
| 191 | if (!$active) { |
||
| 192 | $player = $notification->getReceiver(); |
||
| 193 | $this->log("<fg=green>E-mailing player {$player->getId()} ({$player->getUsername()})</>"); |
||
| 194 | |||
| 195 | $this->subscriber->emailNotification($notification); |
||
| 196 | } |
||
| 197 | } |
||
| 198 | |||
| 199 | /** |
||
| 200 | * Send some data to the client |
||
| 201 | * |
||
| 202 | * @param ConnectionInterface $client The client that will receive the data |
||
| 203 | * @param array $data The data to send |
||
| 204 | */ |
||
| 205 | protected function send(ConnectionInterface $client, $data) |
||
| 206 | { |
||
| 207 | $this->log("<fg=green>Notifying #{$client->resourceId} ({$client->Player->getUsername()})</>"); |
||
|
0 ignored issues
–
show
Accessing
resourceId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
Accessing
Player on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 208 | |||
| 209 | $data->notification_count = $client->Player->countUnreadNotifications(); |
||
|
0 ignored issues
–
show
Accessing
Player on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 210 | $data->message_count = $client->Player->countUnreadMessages(); |
||
|
0 ignored issues
–
show
Accessing
Player on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
If you access a property on an interface, you most likely code against a concrete implementation of the interface. Available Fixes
Loading history...
|
|||
| 211 | |||
| 212 | $client->send(json_encode(array('event' => $data))); |
||
| 213 | } |
||
| 214 | |||
| 215 | /** |
||
| 216 | * Action to call when the server notifies us about something |
||
| 217 | * @param string $event JSON'ified string we'll receive from the webserver |
||
| 218 | */ |
||
| 219 | public function onServerEvent($event) |
||
| 220 | { |
||
| 221 | $event = $event->event; |
||
| 222 | |||
| 223 | switch ($event->type) { |
||
| 224 | case 'message': |
||
| 225 | $this->log("New message received", OutputInterface::VERBOSITY_VERY_VERBOSE); |
||
| 226 | $this->onMessageServerEvent($event); |
||
| 227 | break; |
||
| 228 | case 'notification': |
||
| 229 | $this->log("New notification received", OutputInterface::VERBOSITY_VERY_VERBOSE); |
||
| 230 | $this->onNotificationServerEvent($event); |
||
| 231 | break; |
||
| 232 | default: |
||
| 233 | $this->log("Generic message received", OutputInterface::VERBOSITY_VERY_VERBOSE); |
||
| 234 | foreach ($this->clients as $client) { |
||
| 235 | $this->send($client, $event); |
||
| 236 | } |
||
| 237 | } |
||
| 238 | } |
||
| 239 | |||
| 240 | /** |
||
| 241 | * Log a debugging message to the console |
||
| 242 | * |
||
| 243 | * @param string $message The message to log |
||
| 244 | * @param int $level The output verbosity level of the message |
||
| 245 | */ |
||
| 246 | private function log($message, $level = OutputInterface::VERBOSITY_DEBUG) |
||
| 247 | { |
||
| 248 | if (!$this->output) { |
||
| 249 | return; |
||
| 250 | } |
||
| 251 | |||
| 252 | if ($level <= $this->output->getVerbosity()) { |
||
| 253 | $this->output->writeln($message); |
||
| 254 | } |
||
| 255 | } |
||
| 256 | |||
| 257 | /** |
||
| 258 | * Send a ping message to all clients and kick those who didn't respond |
||
| 259 | */ |
||
| 260 | public function ping() |
||
| 261 | { |
||
| 262 | $this->log("Sending pings"); |
||
| 263 | |||
| 264 | foreach ($this->clients as $client) { |
||
| 265 | if (!$client->pong) { |
||
| 266 | $this->log("Dropping #{$client->resourceId}"); |
||
| 267 | |||
| 268 | $client->close(); |
||
| 269 | continue; |
||
| 270 | } |
||
| 271 | |||
| 272 | $this->log("Pinging #{$client->resourceId}"); |
||
| 273 | $client->send('ping'); |
||
| 274 | $client->pong = false; |
||
| 275 | } |
||
| 276 | } |
||
| 277 | } |
||
| 278 |
If you access a property on an interface, you most likely code against a concrete implementation of the interface.
Available Fixes
Adding an additional type check:
Changing the type hint: