1 | <?php namespace palma; |
||||
2 | |||||
3 | // Copyright (C) 2014 Universitätsbibliothek Mannheim |
||||
4 | // See file LICENSE for license details. |
||||
5 | |||||
6 | require_once("DBConnector.class.php"); |
||||
7 | require_once("globals.php"); |
||||
8 | |||||
9 | class SSVNCDaemon |
||||
10 | { |
||||
11 | |||||
12 | // all during session connected VNC Clients |
||||
13 | private $VNC_CLIENTS; |
||||
14 | |||||
15 | // count of all connected clients |
||||
16 | // private $_VNC_CLIENT_COUNT; |
||||
17 | |||||
18 | // active client count |
||||
19 | private $CONNECTIONS = 0; |
||||
20 | |||||
21 | // ignored VNC Clients |
||||
22 | // TODO: check if no more longer helpful, has to be cleaned |
||||
23 | private $IGNORE_LIST = array(); |
||||
24 | |||||
25 | public $db; |
||||
26 | |||||
27 | public function __construct() |
||||
28 | { |
||||
29 | global $db; |
||||
30 | $this->db = $db; |
||||
31 | |||||
32 | // Start Vncviewer |
||||
33 | $handle = $this->startVNCViewer(); |
||||
34 | |||||
35 | // Read log in loop |
||||
36 | $this->readLog($handle); |
||||
37 | } |
||||
38 | |||||
39 | protected function startVNCViewer() |
||||
40 | { |
||||
41 | // Startup SSVNC-Viewer in Multilisten-Mode |
||||
42 | $cmd = "export DISPLAY=" . CONFIG_DISPLAY . |
||||
43 | "; killall -q ssvncviewer; ssvncviewer -viewonly -multilisten 0 2>&1"; |
||||
44 | $handle = popen($cmd, 'r'); |
||||
45 | print("[Daemon]: vnc_viewer started"); |
||||
46 | |||||
47 | return $handle; |
||||
48 | } |
||||
49 | |||||
50 | protected function readLog($handle) |
||||
51 | { |
||||
52 | print("\n[Daemon]: +++ readLog() +++"); |
||||
53 | |||||
54 | // local SSVNC-Client info |
||||
55 | $client = array( |
||||
56 | "ip" => "", |
||||
57 | "hostname" => "", |
||||
58 | "active" => 1, |
||||
59 | "exit" => 0 |
||||
60 | ); |
||||
61 | |||||
62 | // Read File continuously |
||||
63 | while (!feof($handle)) { |
||||
64 | $buffer = fgets($handle); |
||||
65 | print($buffer); |
||||
66 | |||||
67 | if ($this->CONNECTIONS == 0) { |
||||
68 | //print("\n --- WAITING FOR NEW CONNECTIONS --- \n"); |
||||
69 | } |
||||
70 | |||||
71 | $ip = $this->parseIP($buffer); |
||||
72 | $hostname = $this->parseHostname($buffer); |
||||
73 | $exit = $this->parseExit($buffer); |
||||
74 | |||||
75 | if ($ip!="") { |
||||
76 | $client["ip"] = $ip; |
||||
77 | } |
||||
78 | if ($hostname!="") { |
||||
79 | $client["hostname"] = $hostname; |
||||
80 | } |
||||
81 | if ($exit!=0) { |
||||
82 | $client["exit"] = $exit; |
||||
83 | } |
||||
84 | |||||
85 | if (strstr($buffer, 'create_image') && $client["ip"] != "" && |
||||
86 | $client["hostname"]!="" ) { |
||||
87 | // add client |
||||
88 | $this->addClient($client["ip"], $client["hostname"]); |
||||
89 | |||||
90 | // reset local Client information after adding it |
||||
91 | $client["ip"] = ""; |
||||
92 | $client["hostname"] = ""; |
||||
93 | } |
||||
94 | |||||
95 | if ($exit == 1) { |
||||
96 | // decrease active client count |
||||
97 | if ($this->CONNECTIONS > 0) { |
||||
98 | $this->CONNECTIONS--; |
||||
99 | $this->deleteInactiveVncWindow(); |
||||
100 | } |
||||
101 | } |
||||
102 | |||||
103 | $halt=$this->CONNECTIONS; |
||||
104 | |||||
105 | if ($halt == -1) { |
||||
106 | exit(0); |
||||
0 ignored issues
–
show
|
|||||
107 | } |
||||
108 | |||||
109 | flush(); |
||||
110 | } |
||||
111 | |||||
112 | pclose($handle); |
||||
113 | } |
||||
114 | |||||
115 | protected function parseIP($buffer) |
||||
116 | { |
||||
117 | $ip = ""; |
||||
118 | $line = $buffer; |
||||
119 | if (strpos($line, "Reverse VNC connection from IP")) { |
||||
120 | $line=trim($line); |
||||
121 | $item=explode(":", $line); |
||||
122 | $ip=trim($item[1]); |
||||
123 | $ip=preg_replace('/\W\W\d{4}\/\d{2}\/\d{2} \d{2}/', '', $ip); |
||||
124 | } |
||||
125 | |||||
126 | if ($ip!="") { |
||||
127 | print("\nFOUND IP: " . $ip . "\n"); |
||||
128 | } |
||||
129 | |||||
130 | return $ip; |
||||
131 | } |
||||
132 | |||||
133 | protected function parseHostname($buffer) |
||||
134 | { |
||||
135 | $hostname = ""; |
||||
136 | $line = $buffer; |
||||
137 | if (strpos($line, "Hostname")) { |
||||
138 | $line=trim($line); |
||||
139 | $item=explode(":", $line); |
||||
140 | $hostname=trim($item[1]); |
||||
141 | $hostname=preg_replace('/\.uni\-mannheim\.de/', '', $hostname); |
||||
142 | } |
||||
143 | |||||
144 | if ($hostname!="") { |
||||
145 | print("\nFOUND HOSTNAME: " . $hostname . "\n"); |
||||
146 | } |
||||
147 | |||||
148 | return $hostname; |
||||
149 | } |
||||
150 | |||||
151 | protected function parseExit($line) |
||||
152 | { |
||||
153 | $exit = 0; |
||||
154 | if (strpos($line, "VNC Viewer exiting")) { |
||||
155 | $exit = 1; |
||||
156 | } |
||||
157 | |||||
158 | if ($exit!=0) { |
||||
159 | print("\nCLIENT HAS DISCONNECTED " . $exit . "\n"); |
||||
160 | } |
||||
161 | |||||
162 | return $exit; |
||||
163 | } |
||||
164 | |||||
165 | protected function addClient($ip, $hostname) |
||||
166 | { |
||||
167 | $vncclient = array( |
||||
168 | "ip" => $ip, |
||||
169 | "hostname" => $hostname, |
||||
170 | "active" => 1, |
||||
171 | "exit" => 0 |
||||
172 | ); |
||||
173 | if (count($this->VNC_CLIENTS) == 0) { |
||||
174 | $id=1; |
||||
175 | } else { |
||||
176 | $id=count($this->VNC_CLIENTS) + 1; |
||||
177 | } |
||||
178 | |||||
179 | $this->VNC_CLIENTS[$id] = $vncclient; |
||||
180 | |||||
181 | print("\nCLIENT OBJECT with ID " . $id . " CREATED : " |
||||
182 | . $vncclient["ip"] . " | " . $vncclient["hostname"] . " | " |
||||
183 | . $vncclient["active"] . " | " . $vncclient["exit"] . "\n"); |
||||
184 | print($this->CONNECTIONS+1 . " CLIENT(S) CONNECTED ..."); |
||||
185 | |||||
186 | $this->sendVncWindowToNuc($id, $vncclient); |
||||
187 | |||||
188 | $this->CONNECTIONS++; |
||||
189 | |||||
190 | print("\n active connections: ".$this->CONNECTIONS+1); |
||||
191 | print("\n all saved clients: " . serialize($this->VNC_CLIENTS)); |
||||
192 | } |
||||
193 | |||||
194 | protected function sendVncWindowToNuc($id, $vncclient) |
||||
195 | { |
||||
196 | print("\n[Daemon]: +++sendVncWindowToNuc() +++ "); |
||||
197 | |||||
198 | $vnc_id = $vncclient["hostname"] . "-" . $id; |
||||
199 | |||||
200 | $db = new DBConnector(); |
||||
201 | |||||
202 | // already existing in db? |
||||
203 | $clients_in_db = array(); |
||||
204 | $client_info = $db->getVNCClientInfo(); |
||||
205 | |||||
206 | foreach ($client_info as $info) { |
||||
207 | $clients_in_db[] = $info["file"]; |
||||
208 | } |
||||
209 | |||||
210 | $ip = $vncclient["ip"]; |
||||
211 | $name = $db->querySingle('SELECT user.name FROM address, user |
||||
212 | WHERE user.userid = ( |
||||
213 | SELECT address.userid |
||||
214 | FROM address |
||||
215 | WHERE address.address ="' . $ip . '" |
||||
216 | )'); |
||||
217 | |||||
218 | // print("\n[Daemon]: USERNAME : " . $name); |
||||
219 | |||||
220 | // $vncClientCount = $db->querySingle('SELECT count(id) FROM window WHERE handler = "vnc"'); |
||||
221 | // $vncClientsAll = $db->query("SELECT user.name FROM address"); |
||||
222 | |||||
223 | // print("\n[Daemon]: clients in db = " . $vncClientCount); |
||||
224 | // print("\n[Daemon]: clients ignored = " . serialize($this->IGNORE_LIST)); |
||||
225 | |||||
226 | // if vnc_id not in database create window and send to nuc |
||||
227 | if (!(in_array($vnc_id, $clients_in_db))) { |
||||
228 | // print("\n[Daemon]: insert $vnc_id into db"); |
||||
229 | |||||
230 | $dt = new \DateTime(); |
||||
231 | $date = $dt->format('Y-m-d H:i:s'); |
||||
232 | |||||
233 | $window = array( |
||||
234 | "id" => "", |
||||
235 | "win_id" => "", |
||||
236 | "name" => "", |
||||
237 | "state" => "", |
||||
238 | "file" => $name . "@" . $vnc_id, |
||||
239 | "handler" => "vnc", |
||||
240 | "userid" => $name, |
||||
241 | "date" => $date |
||||
242 | ); |
||||
243 | |||||
244 | $serializedWindow = serialize($window); |
||||
245 | |||||
246 | $sw = urlencode($serializedWindow); |
||||
247 | // Get cURL resource |
||||
248 | $curl = curl_init(); |
||||
249 | // Set some options - we are passing in a useragent too here |
||||
250 | curl_setopt_array($curl, array( |
||||
0 ignored issues
–
show
It seems like
$curl can also be of type false ; however, parameter $ch of curl_setopt_array() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
251 | CURLOPT_RETURNTRANSFER => 1, |
||||
252 | CURLOPT_URL => CONFIG_CONTROL_FILE . '?newVncWindow=' . $sw, |
||||
253 | CURLOPT_USERAGENT => 'PalMA cURL Request' |
||||
254 | )); |
||||
255 | // Send the request |
||||
256 | curl_exec($curl); |
||||
0 ignored issues
–
show
It seems like
$curl can also be of type false ; however, parameter $ch of curl_exec() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
257 | // Close request to clear up some resources |
||||
258 | curl_close($curl); |
||||
0 ignored issues
–
show
It seems like
$curl can also be of type false ; however, parameter $ch of curl_close() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
259 | } |
||||
260 | |||||
261 | // add unique id to ignore list after sending to nuc |
||||
262 | array_push($this->IGNORE_LIST, $vnc_id); |
||||
263 | } |
||||
264 | |||||
265 | protected function deleteInactiveVncWindow() |
||||
266 | { |
||||
267 | // print("\n[Daemon]: +++ TODO: deleteInactiveWindow() +++"); |
||||
268 | |||||
269 | $db = new DBConnector(); |
||||
270 | |||||
271 | // window_ids in db |
||||
272 | $vnc_windows_in_db = array(); |
||||
273 | $client_info = $db->getVNCClientInfo(); |
||||
274 | foreach ($client_info as $info) { |
||||
275 | $vnc_windows_in_db[] = $info["win_id"]; |
||||
276 | } |
||||
277 | |||||
278 | // window_ids on screen |
||||
279 | $windows_on_screen = array(); |
||||
280 | $windows = explode("\n", shell_exec('wmctrl -l')); |
||||
281 | |||||
282 | foreach ($windows as $w) { |
||||
283 | $field = explode(' ', $w); |
||||
284 | $id = $field[0]; |
||||
285 | if ($id != '') { |
||||
286 | $windows_on_screen[] = $id; |
||||
287 | } |
||||
288 | } |
||||
289 | |||||
290 | // print("[Daemon]: clients in db = " . serialize($vnc_windows_in_db)); |
||||
291 | // print("[Daemon]: client on screen = " . serialize($windows_on_screen)); |
||||
292 | |||||
293 | // window_ids that are in the db, but not on the screen (window already closed) |
||||
294 | $inactive_vnc_window_ids = array_diff($vnc_windows_in_db, $windows_on_screen); |
||||
295 | |||||
296 | foreach ($inactive_vnc_window_ids as $inactive_win_id) { |
||||
297 | // define vnc-id |
||||
298 | $inactive_vnc_id = $db->querySingle("SELECT file FROM window WHERE win_id='".$inactive_win_id."'"); |
||||
0 ignored issues
–
show
|
|||||
299 | |||||
300 | // delete from database (send to control.php) |
||||
301 | $curl = curl_init(); |
||||
302 | |||||
303 | curl_setopt_array($curl, array( |
||||
0 ignored issues
–
show
It seems like
$curl can also be of type false ; however, parameter $ch of curl_setopt_array() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
304 | CURLOPT_RETURNTRANSFER => 1, |
||||
305 | CURLOPT_URL => CONFIG_CONTROL_FILE . |
||||
306 | '?window=vncwin&delete=VNC&vncid=' . $inactive_win_id, |
||||
307 | CURLOPT_USERAGENT => 'PalMA cURL Request' |
||||
308 | )); |
||||
309 | |||||
310 | curl_exec($curl); |
||||
0 ignored issues
–
show
It seems like
$curl can also be of type false ; however, parameter $ch of curl_exec() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
311 | curl_close($curl); |
||||
0 ignored issues
–
show
It seems like
$curl can also be of type false ; however, parameter $ch of curl_close() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
312 | |||||
313 | // print("[Daemon]: inactive vnc_id = $inactive_vnc_id >> add to list: " .serialize($this->IGNORE_LIST)); |
||||
314 | } |
||||
315 | } |
||||
316 | } |
||||
317 | |||||
318 | $vnc = new SSVNCDaemon(); |
||||
319 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.