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 | namespace jones\wschat\components; |
||
3 | |||
4 | use Yii; |
||
5 | use yii\helpers\Json; |
||
6 | use Ratchet\ConnectionInterface; |
||
7 | use Ratchet\MessageComponentInterface; |
||
8 | |||
9 | /** |
||
10 | * Class Chat |
||
11 | * @package \jones\wschat\components |
||
12 | */ |
||
13 | class Chat implements MessageComponentInterface |
||
14 | { |
||
15 | /** @var ConnectionInterface[] */ |
||
16 | private $clients = []; |
||
17 | /** @var \jones\wschat\components\ChatManager */ |
||
18 | private $cm = null; |
||
19 | /** |
||
20 | * @var array list of available requests |
||
21 | */ |
||
22 | private $requests = [ |
||
23 | 'auth', 'message' |
||
24 | ]; |
||
25 | |||
26 | /** |
||
27 | * @param \jones\wschat\components\ChatManager $cm |
||
28 | */ |
||
29 | public function __construct(ChatManager $cm) |
||
30 | { |
||
31 | $this->cm = $cm; |
||
32 | } |
||
33 | |||
34 | /** |
||
35 | * @param ConnectionInterface $conn |
||
36 | */ |
||
37 | public function onOpen(ConnectionInterface $conn) |
||
38 | { |
||
39 | $rid = $this->getResourceId($conn); |
||
40 | $this->clients[$rid] = $conn; |
||
41 | Yii::info('Connection is established: '.$rid, 'chat'); |
||
42 | } |
||
43 | |||
44 | /** |
||
45 | * @param ConnectionInterface $from |
||
46 | * @param string $msg |
||
47 | */ |
||
48 | public function onMessage(ConnectionInterface $from, $msg) |
||
49 | { |
||
50 | $data = Json::decode($msg, true); |
||
51 | $rid = array_search($from, $this->clients); |
||
52 | if (in_array($data['type'], $this->requests)) { |
||
53 | call_user_func_array([$this, $data['type'].'Request'], [$rid, $data['data']]); |
||
54 | } |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * @param ConnectionInterface $conn |
||
59 | */ |
||
60 | public function onClose(ConnectionInterface $conn) |
||
61 | { |
||
62 | $rid = array_search($conn, $this->clients); |
||
63 | if ($this->cm->getUserByRid($rid)) { |
||
64 | $this->closeRequest($rid); |
||
65 | } |
||
66 | unset($this->clients[$rid]); |
||
67 | Yii::info('Connection is closed: '.$rid, 'chat'); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * @param ConnectionInterface $conn |
||
72 | * @param \Exception $e |
||
73 | */ |
||
74 | public function onError(ConnectionInterface $conn, \Exception $e) |
||
75 | { |
||
76 | Yii::error($e->getMessage()); |
||
77 | $conn->send(Json::encode(['type' => 'error', 'data' => [ |
||
78 | 'message' => Yii::t('app', 'Something wrong. Connection will be closed') |
||
79 | ]])); |
||
80 | $conn->close(); |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * Get connection resource id |
||
85 | * |
||
86 | * @access private |
||
87 | * @param ConnectionInterface $conn |
||
88 | * @return string |
||
89 | */ |
||
90 | private function getResourceId(ConnectionInterface $conn) |
||
91 | { |
||
92 | return $conn->resourceId; |
||
0 ignored issues
–
show
|
|||
93 | } |
||
94 | |||
95 | /** |
||
96 | * Process auth request. Find user chat(if not exists - create it) |
||
97 | * and send message to all other clients |
||
98 | * |
||
99 | * @access private |
||
100 | * @param $rid |
||
101 | * @param $data |
||
102 | * @return void |
||
103 | */ |
||
104 | private function authRequest($rid, array $data) |
||
105 | { |
||
106 | $chatId = $data['cid']; |
||
107 | Yii::info('Auth request from rid: '.$rid.' and chat: '.$chatId, 'chat'); |
||
108 | $userId = !empty($data['user']['id']) ? $data['user']['id'] : ''; |
||
109 | //the same user already connected to current chat, need to close old connect |
||
110 | if ($oldRid = $this->cm->isUserExistsInChat($userId, $chatId)) { |
||
111 | $this->closeRequest($oldRid); |
||
112 | } |
||
113 | $this->cm->addUser($rid, $userId, $data['user']); |
||
114 | $chat = $this->cm->findChat($chatId, $rid); |
||
115 | $users = $chat->getUsers(); |
||
116 | $joinedUser = $this->cm->getUserByRid($rid); |
||
117 | $response = [ |
||
118 | 'user' => $joinedUser, |
||
119 | 'join' => true, |
||
120 | ]; |
||
121 | View Code Duplication | foreach ($users as $user) { |
|
122 | //send message for other users of this chat |
||
123 | if ($userId != $user->getId()) { |
||
124 | $conn = $this->clients[$user->getRid()]; |
||
125 | $conn->send(Json::encode(['type' => 'auth', 'data' => $response])); |
||
126 | } |
||
127 | } |
||
128 | //send auth response for joined user |
||
129 | $response = [ |
||
130 | 'user' => $joinedUser, |
||
131 | 'users' => $users, |
||
132 | 'history' => $this->cm->getHistory($chat->getUid()) |
||
133 | ]; |
||
134 | $conn = $this->clients[$rid]; |
||
135 | $conn->send(Json::encode(['type' => 'auth', 'data' => $response])); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Process message request. Find user chat room and send message to other users |
||
140 | * in this chat room |
||
141 | * |
||
142 | * @access private |
||
143 | * @param $rid |
||
144 | * @param array $data |
||
145 | * @return void |
||
146 | */ |
||
147 | private function messageRequest($rid, array $data) |
||
148 | { |
||
149 | Yii::info('Message from: '.$rid, 'chat'); |
||
150 | $chat = $this->cm->getUserChat($rid); |
||
151 | if (!$chat) { |
||
152 | return; |
||
153 | } |
||
154 | $data['message']['timestamp'] = time(); |
||
155 | $user = $this->cm->getUserByRid($rid); |
||
156 | $this->cm->storeMessage($user, $chat, $data['message']); |
||
0 ignored issues
–
show
It seems like
$user defined by $this->cm->getUserByRid($rid) on line 155 can be null ; however, jones\wschat\components\...Manager::storeMessage() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
![]() |
|||
157 | View Code Duplication | foreach ($chat->getUsers() as $user) { |
|
158 | //need not to send message for self |
||
159 | if ($user->getRid() == $rid) { |
||
160 | continue; |
||
161 | } |
||
162 | $conn = $this->clients[$user->getRid()]; |
||
163 | $conn->send(Json::encode(['type' => 'message', 'data' => $data])); |
||
164 | } |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * Process close request. Find user chat, remove user from chat and send message |
||
169 | * to other users in this chat |
||
170 | * |
||
171 | * @access public |
||
172 | * @param $rid |
||
173 | */ |
||
174 | private function closeRequest($rid) |
||
175 | { |
||
176 | //get user for closed connection |
||
177 | $requestUser = $this->cm->getUserByRid($rid); |
||
178 | $chat = $this->cm->getUserChat($rid); |
||
179 | //remove user from chat room |
||
180 | $this->cm->removeUserFromChat($rid); |
||
181 | //send notification for other users in this chat |
||
182 | $users = $chat->getUsers(); |
||
183 | $response = array( |
||
184 | 'type' => 'close', |
||
185 | 'data' => ['user' => $requestUser] |
||
186 | ); |
||
187 | foreach ($users as $user) { |
||
188 | $conn = $this->clients[$user->getRid()]; |
||
189 | $conn->send(Json::encode($response)); |
||
190 | } |
||
191 | } |
||
192 | } |
||
193 | |||
194 | |||
195 |
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: