clearUploadDir()   A
last analyzed

Complexity

Conditions 6
Paths 5

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 7
c 0
b 0
f 0
nc 5
nop 0
dl 0
loc 12
rs 9.2222
1
<?php
2
3
// Copyright (C) 2014-2023 Universitätsbibliothek Mannheim
4
// See file LICENSE for license details.
5
6
function confValue(string $name): ?string
7
{
8
  // Try setting constants from a configuration file.
9
  static $conf = null;
10
  if (is_null($conf)) {
11
    $conf_fn = 'palma.ini';
12
    if (!file_exists($conf_fn)) {
13
      $conf_fn = '/etc/palma.ini';
14
    }
15
    $conf = parse_ini_file($conf_fn);
16
  }
17
  if (array_key_exists($name, $conf)) {
18
    return $conf[$name];
19
  }
20
  return null;
21
}
22
23
// Entries in group 'display'.
24
define('CONFIG_DISPLAY', confValue('id') ?? ':1');
25
define('CONFIG_SSH', confValue('ssh'));
26
27
// Entries in group 'general'.
28
define('CONFIG_PASSWORD', confValue('password') ?? false);
29
define('CONFIG_PIN', confValue('pin') ?? true);
30
define('CONFIG_STATIONNAME', confValue('stationname') ??
31
       str_replace(array("\r", "\n", " "), '', `hostname -f`));
32
define('CONFIG_THEME', confValue('theme') ?? 'demo/simple');
33
define('CONFIG_BROWSER', confValue('browser'));
34
define('CONFIG_DEBUG', confValue('debug') ?? false);
35
36
// Entries in group 'path'.
37
define('CONFIG_START_URL', confValue('start_url') ??
38
       'http://' . str_replace(array("\r", "\n", " "), '', `hostname -f`) . '/');
39
define('CONFIG_POLICY', confValue('policy'));
40
define('CONFIG_CONTROL_FILE', confValue('control_file') ?? CONFIG_START_URL . 'control.php');
41
define('CONFIG_UPLOAD_DIR', confValue('upload_dir') ?? '/tmp/palma');
42
define('CONFIG_INSTITUTION_URL', confValue('institution_url') ?? '');
43
44
// Entries in group 'monitoring'.
45
define('CONFIG_MONITOR_URL', confValue('monitor_url') ?? null);
46
47
function getDevice(): string
48
{
49
  // Try to determine the user's device type. The device which is
50
  // returned is used to select the matching icon for the user list.
51
  $agent = $_SERVER["HTTP_USER_AGENT"];
52
  if (preg_match('/iPad/', $agent)) {
53
    $device = 'tablet';
54
  } elseif (preg_match('/iPhone/', $agent)) {
55
    $device = 'mobile';
56
  } elseif (preg_match('/Android/', $agent)) {
57
    $device = 'android';
58
  } elseif (preg_match('/Linux/', $agent)) {
59
    $device = 'linux';
60
  } elseif (preg_match('/OS X/', $agent)) {
61
    $device = 'apple';
62
  } elseif (preg_match('/Windows/', $agent)) {
63
    $device = 'windows';
64
  } else {
65
    $device = 'laptop';
66
  }
67
  return $device;
68
}
69
70
function checkCredentials(string $username, string $password): bool
71
{
72
  // Check username + password against fixed internal value and
73
  // external proxy with authentisation.
74
75
  global $errtext;
76
77
  $remote = $_SERVER['REMOTE_ADDR'];
78
  if ($username == 'chef' && $password == 'chef') {
79
    if (
80
        $remote == '::1' || $remote == '127.0.0.1' ||
81
        preg_match('/^134[.]155[.]36[.]/', $remote) &&
82
        $remote != '134.155.36.48'
83
    ) {
84
      // Allow test access for restricted remote hosts (localhost,
85
      // UB Mannheim library staff, but not via proxy server).
86
      // TODO: PalMA installations which are accessible from
87
      // the Internet may want to remove this test access.
88
      return true;
89
    } else {
90
      trace("checkCredentials: Test access not allowed for IP address $remote");
91
      return false;
92
    }
93
  }
94
95
  if ($username == '' || $password == '') {
96
    // Don't allow empty user name or password.
97
    // Proxy authentisation can fail with empty values.
98
    trace("checkCredentials: access denied for user '$username'");
99
    return false;
100
  }
101
  // TODO: testurl sollte auf einem lokalen Server liegen.
102
  $testurl = 'http://www.weilnetz.de/proxytest';
103
  $proxy = 'proxy.bib.uni-mannheim.de:3150';
104
  $curl = curl_init($testurl);
105
  curl_setopt($curl, CURLOPT_HEADER, true);
106
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
107
  curl_setopt($curl, CURLOPT_PROXY, $proxy);
108
  curl_setopt($curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
109
  curl_setopt($curl, CURLOPT_PROXYUSERPWD, "$username:$password");
110
  //~ trace("checkCredentials: Start curl");
111
  $out = curl_exec($curl);
112
  curl_close($curl);
113
114
  if (!$out) {
115
    trace("checkCredentials: curl failed for user '$username'");
116
    $errtext = addslashes(__('Invalid credentials!'));
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

116
    $errtext = addslashes(/** @scrutinizer ignore-call */ __('Invalid credentials!'));
Loading history...
117
  } elseif (preg_match('/404 Not Found/', $out)) {
0 ignored issues
show
Bug introduced by
It seems like $out can also be of type true; however, parameter $subject of preg_match() does only seem to accept string, 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 ignore-type  annotation

117
  } elseif (preg_match('/404 Not Found/', /** @scrutinizer ignore-type */ $out)) {
Loading history...
118
    return true;
119
  } elseif (preg_match('/Could not resolve proxy/', $out)) {
120
    trace('checkCredentials: proxy authentication was not possible');
121
    $errtext = addslashes(__('Cannot check credentials, sorry!'));
122
  } elseif (preg_match('/Cache Access Denied/', $out)) {
123
    trace("checkCredentials: access denied for user '$username'");
124
    $errtext = addslashes(__('Invalid credentials!'));
125
  } else {
126
    trace("checkCredentials: access not possible for user '$username'");
127
    $errtext = addslashes(__('Invalid credentials!'));
128
  }
129
  return false;
130
}
131
132
function showLogin(): void
133
{
134
    //if (isset($_SERVER['HTTP_REFERER'])) {
135
    //    error_log("auth.php referred by " . $_SERVER['HTTP_REFERER']);
136
    //}
137
    $header = 'Location: login.php';
138
    $separator = '?';
139
  if (isset($_REQUEST['lang'])) {
140
      $header = $header . $separator . 'lang=' . $_REQUEST['lang'];
141
      $separator = '&';
142
  }
143
  if (isset($_REQUEST['pin'])) {
144
      $header = $header . $separator . 'pin=' . $_REQUEST['pin'];
145
      $separator = '&';
0 ignored issues
show
Unused Code introduced by
The assignment to $separator is dead and can be removed.
Loading history...
146
  }
147
    header($header);
148
149
    exit;
150
}
151
152
function trace(string $text): void
153
{
154
  static $firstRun = true;
155
  if ($firstRun) {
156
    $firstRun = false;
157
    openlog("palma", LOG_PID, LOG_USER);
158
  }
159
  syslog(LOG_NOTICE, $text);
160
}
161
162
function debug(string $text): void
163
{
164
  if (CONFIG_DEBUG) {
165
    trace($text);
166
  }
167
}
168
169
function monitor(string $action): void
170
{
171
  if (is_null(CONFIG_MONITOR_URL)) {
172
    return;
173
  }
174
175
  debug("monitor $action");
176
177
  $ch = curl_init();
178
  $url = CONFIG_MONITOR_URL;
0 ignored issues
show
Unused Code introduced by
The assignment to $url is dead and can be removed.
Loading history...
179
180
  curl_setopt_array(
181
      $ch,
182
      array(
183
      CURLOPT_RETURNTRANSFER => 1,
184
      CURLOPT_URL => CONFIG_MONITOR_URL . '/' . CONFIG_STATIONNAME . '/' . base64_encode($action),
185
      CURLOPT_USERAGENT => 'PalMA cURL Request'
186
      )
187
  );
188
  $resp = curl_exec($ch);
0 ignored issues
show
Unused Code introduced by
The assignment to $resp is dead and can be removed.
Loading history...
189
  curl_close($ch);
190
}
191
192
function displayCommand(string $cmd): ?string
193
{
194
  if (is_null(CONFIG_SSH)) {
195
    $cmd = "DISPLAY=" . CONFIG_DISPLAY . " HOME=/var/www $cmd";
196
  } else {
197
    $cmd = CONFIG_SSH . " 'DISPLAY=" . CONFIG_DISPLAY . " $cmd'";
198
  }
199
200
  monitor("control.php: displayCommand $cmd");
201
202
  // add directories with palma-browser to PATH
203
  $result = shell_exec('PATH=/usr/lib/palma:./scripts:$PATH ' . $cmd);
204
  trace("displayCommand: $cmd, result=$result");
205
  return $result;
206
}
207
208
function wmClose(string $id): void
209
{
210
  monitor("control.php: wmClose");
211
  // Close window gracefully.
212
  displayCommand("wmctrl -i -c $id");
213
}
214
215
function wmHide(string $id): void
216
{
217
  monitor("control.php: wmHide");
218
  // Hide window. This is done by moving it to desktop 1.
219
  displayCommand("wmctrl -i -r $id -t 1");
220
}
221
222
function wmShow(string $id): void
223
{
224
  monitor("control.php: wmShow");
225
  // Show window on current desktop.
226
  displayCommand("wmctrl -i -R $id");
227
}
228
229
/** @return array<string> */
230
function windowListOnScreen(): array
231
{
232
  monitor("control.php: windowListOnScreen");
233
  $list = array();
234
  $windows = explode("\n", displayCommand('wmctrl -l'));
235
  foreach ($windows as $w) {
236
    $field = explode(' ', $w);
237
    $id = $field[0];
238
    if ($id != '') {
239
      array_push($list, $id);
240
    }
241
  }
242
  return $list;
243
}
244
245
// simple list with content from database
246
247
/** @return array<string> */
248
function windowList(): array
249
{
250
  monitor("control.php: windowList");
251
252
  require_once 'DBConnector.class.php';
253
  $db = palma\DBConnector::getInstance();
254
255
  $list = array();
256
257
  // Get ordered list of all windows from the database.
258
  $windows = $db->getWindows();
259
  foreach ($windows as $w) {
260
    $id = $w['win_id'];
261
    if ($id != '') {
262
      array_push($list, $id);
263
    }
264
  }
265
  return $list;
266
}
267
268
function closeAll(): void
269
{
270
  monitor("control.php: closeAll");
271
272
  require_once 'DBConnector.class.php';
273
  $db = palma\DBConnector::getInstance();
274
275
  $windows_on_screen = windowListOnScreen();
276
277
  foreach ($windows_on_screen as $id) {
278
    wmClose($id);
279
    if ($db->getWindowState($id) != null) {
280
      $db->deleteWindow($id);
281
    }
282
  }
283
284
  // Remove any remaining window entries in database.
285
  $db->exec('DELETE FROM window');
286
287
  // Remove any remaining files in the upload directory.
288
  clearUploadDir();
289
}
290
291
function doLogout(string $username): void
292
{
293
  monitor("control.php: doLogout");
294
295
  require_once 'DBConnector.class.php';
296
  $db = palma\DBConnector::getInstance();
297
298
  if ($username == 'ALL') {
299
    // Terminate all user connections and reset system.
300
    closeAll();
301
    $db->resetTables();
302
  }
303
}
304
305
function clearUploadDir(): void
306
{
307
  monitor("control.php: clearUploadDir");
308
  # Remove all files in the upload directory.
309
  if (is_dir(CONFIG_UPLOAD_DIR)) {
310
    if ($dh = opendir(CONFIG_UPLOAD_DIR)) {
311
      while (($file = readdir($dh)) !== false) {
312
        if ($file != "." and $file != "..") {
313
          unlink(CONFIG_UPLOAD_DIR . "/$file");
314
        }
315
      }
316
      closedir($dh);
317
    }
318
  }
319
}
320
321
function setLayout(?string $layout = null): void
322
{
323
  monitor("control.php: setLayout $layout");
324
  // Set layout of team display. Layouts are specified by their name.
325
  // We use names like g1x1, g2x1, g1x2, ...
326
  // Restore the last layout if the function is called with a null argument.
327
328
  trace("setLayout: $layout");
329
330
  require_once 'DBConnector.class.php';
331
  $db = palma\DBConnector::getInstance();
332
333
  $geom = array();
334
  $geom['g1x1'] = array(
335
    array(0, 0, 1, 1)
336
  );
337
  $geom['g2x1'] = array(
338
    array(0, 0, 2, 1), array(1, 0, 2, 1)
339
  );
340
  $geom['g1x2'] = array(
341
    array(0, 0, 1, 2), array(0, 1, 1, 2)
342
  );
343
  $geom['g1a2'] = array(
344
    array(0, 0, 2, 1), array(1, 0, 2, 2),
345
    array(1, 1, 2, 2)
346
  );
347
  $geom['g2x2'] = array(
348
    array(0, 0, 2, 2), array(1, 0, 2, 2),
349
    array(0, 1, 2, 2), array(1, 1, 2, 2)
350
  );
351
352
  if ($layout == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $layout of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
353
    $layout = $db->querySingle("SELECT value FROM setting WHERE key='layout'");
354
  }
355
356
  // Make sure $layout is valid
357
  if (!array_key_exists($layout, $geom)) {
358
    trace("setLayout: layout invalid!");
359
  } else {
360
    $db->exec("UPDATE setting SET value='$layout' WHERE key='layout'");
361
    $dim = $geom[$layout];
362
363
    // Make sure that desktop 0 is selected.
364
    displayCommand('wmctrl -s 0');
365
366
    // Get width and height of desktop.
367
    $desktops = displayCommand("wmctrl -d");
368
    // $desktop looks like this.
369
    // 0  * DG: 1600x900  VP: 0,0  WA: 0,27 1600x873  Arbeitsfläche 1
370
    $fields = preg_split("/[\n ]+/", $desktops);
371
    $geom = preg_split("/x/", $fields[3]);
372
    $screenWidth = intval($geom[0]);
373
    $screenHeight = intval($geom[1]);
374
375
    // Show all windows for the current layout which are not disabled.
376
377
    $maxSection = count($dim);
378
    // Get ordered list of all windows from the database.
379
    $windows = $db->getWindows();
380
    foreach ($windows as $w) {
381
      $id = $w['win_id'];
382
      $enabled = $w['state'] == 'active';
383
      $section = intval($w['section']);
384
      if ($section >= 1 && $section <= $maxSection && $enabled) {
385
        // Show window, set size and position.
386
        $wi = $section - 1;
387
        $dx = $screenWidth / $dim[$wi][2];
388
        $dy = $screenHeight / $dim[$wi][3];
389
        $x = $dim[$wi][0] * $dx;
390
        $y = $dim[$wi][1] * $dy;
391
        wmShow($id);
392
        displayCommand("wmctrl -i -r $id -e 0,$x,$y,$dx,$dy");
393
      } else {
394
        // Hide window.
395
        wmHide($id);
396
      }
397
    }
398
  }
399
}
400
401
function activateControls(string $windowhex): void
402
{
403
  require_once 'DBConnector.class.php';
404
  $db = palma\DBConnector::getInstance();
405
406
  $fhandler = $db->querySingle("SELECT handler FROM window WHERE win_id='$windowhex'");
407
  trace("activateControls: handler $fhandler");
408
  monitor("control.php: activateControls $fhandler");
409
}
410
411
/**
412
 * @param array<string,string> $new
413
 */
414
function addNewWindow(array $new): void
415
{
416
  // Add a new window to the monitor. This window either uses the first
417
  // unused section or it will be hidden.
418
419
  monitor('control.php: addNewWindow ' . serialize($new));
420
  trace('addNewWindow: ' . serialize($new));
421
422
  require_once 'DBConnector.class.php';
423
  $db = palma\DBConnector::getInstance();
424
425
  // '$new' already contains 'file', 'handler' and 'date', as well as the
426
  // username for VNC connections only.
427
  // 'win_id', 'section' have to be defined afterwards.
428
429
  // Get new window. Wait up to 10 s for it.
430
  $t_total = 0;
431
  do {
432
    $window_ids_on_screen = windowListOnScreen();
433
    $windows_in_db = $db->getWindows();
434
435
    $existing_ids = array();
436
    $new_window_id = '';
437
438
    if (count($windows_in_db) > 0) {
439
      // Add db windows to existing_ids.
440
      foreach ($windows_in_db as $win) {
441
        $existing_ids[] = $win['win_id'];
442
      }
443
444
      $new_window = array_diff($window_ids_on_screen, $existing_ids);
445
      foreach ($new_window as $win_id) {
446
        if ($win_id != "") {
447
          $new_window_id = $win_id;
448
        }
449
      }
450
    } elseif (!empty($window_ids_on_screen)) {
451
      $new_window_id = $window_ids_on_screen[0];
452
    }
453
  } while (!$new_window_id && $t_total++ <= 10 && !sleep(1));
454
455
  if (!$new_window_id) {
456
    trace('addNewWindow: warning: no new window found');
457
    return;
458
  }
459
460
  trace("addNewWindow: new window $new_window_id");
461
462
  // Determine last assigned monitor section.
463
  //~ $max_section = $db->querySingle('SELECT MAX(section) FROM window');
464
465
  // Get first unused monitor section.
466
  $section = $db->nextID();
467
468
  // If all information is available, create window object.
469
470
  $new['id'] = $section;
471
  $new['section'] = $section;
472
473
  if ($section <= 4) {
474
    $new['state'] = "active";
475
  } else {
476
    // All sections are used, so there is no free one for the new window.
477
    $new['state'] = "inactive";
478
    // We could hide the new window immediately, but don't do it here:
479
    // Each new window will be shown in the middle of the screen.
480
    //~ wmHide($new_window_id);
481
    //~ trace("addNewWindow: hide new window $new_window_id");
482
  }
483
484
  // $new['file'] = $active_window; (?)
485
486
  // TODO: check how to insert the userid for all content, not just vnc.
487
  // Perhaps better add to array in upload.php ?
488
  $userid = "";
489
  $queryid = $db->querySingle('SELECT user.userid FROM user WHERE user.name="' . $new['userid'] . '"');
490
  if (!empty($queryid)) {
491
    $userid = $queryid;
492
  } else {
493
    $userid = "all";
494
  }
495
496
  $myWindow = array(
497
    $new['id'],
498
    $new_window_id,
499
    $new['section'],
500
    $new['state'],
501
    $new['file'],
502
    $new['handler'],
503
    $userid,
504
    $new['date']
505
  );
506
507
  // Save window in database.
508
  $db->insertWindow($myWindow);
509
510
  setLayout();
511
}
512
513
/**
514
 * @param array<string,string> $w
515
 */
516
function createNewWindowSafe(array $w): void
517
{
518
  require_once 'DBConnector.class.php';
519
  $db = palma\DBConnector::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $db is dead and can be removed.
Loading history...
520
521
  $inFile = $w['file'];
522
  if (!file_exists($inFile)) {
523
    trace("createNewWindowSafe: " . escapeshellarg($inFile) . " is not a file, aborting display");
524
    return;
525
  }
526
527
  require_once 'FileHandler.class.php';
528
  list ($handler, $targetFile) =
529
    palma\FileHandler::getFileHandler($inFile);
530
  trace("createNewWindowSafe: file is now $targetFile, its handler is $handler");
531
532
  $window = array(
533
    "id" => "",
534
    "win_id" => "",
535
    "name" => "",
536
    "state" => "",
537
    "file" => $targetFile,
538
    "handler" => $handler,
539
    "userid" => "",
540
    "date" => $w['date']);
541
542
  createNewWindow($window);
543
}
544
545
/**
546
 * @param array<string,string> $w
547
 */
548
function createNewWindow($w): void
549
{
550
  // '$w' already contains 'file', 'handler' and 'date'.
551
  // 'win_id', 'section' have to be defined afterwards.
552
553
  require_once 'DBConnector.class.php';
554
  $db = palma\DBConnector::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $db is dead and can be removed.
Loading history...
555
556
  $handler = $w['handler'];
557
  // TODO: use escapeshellarg() for filename.
558
  $filename = $w['file'];
559
560
  $cmd = "$handler " . escapeshellarg($filename);
561
  displayCommand("/usr/bin/nohup $cmd >/dev/null 2>&1 &");
562
563
  addNewWindow($w);
564
  monitor("control.php: createNewWindow");
565
}
566
567
function processRequests(): void
568
{
569
  monitor("control.php: processRequests");
570
571
  require_once 'DBConnector.class.php';
572
  $db = palma\DBConnector::getInstance();
573
574
  if (array_key_exists('window', $_REQUEST)) {
575
    // All windows related commands must start with window=.
576
577
    $windownumber = escapeshellcmd($_REQUEST['window']);
578
    $windowname = false;
579
    $windowhex = 0;
580
    // TODO: $win_id und $windowname können vermutlich zusammengefasst werden.
581
    $win_id = 0;
582
583
    if ($windownumber != 'vncwin') {
584
      // This is the normal case.
585
      // Special handling is needed when called with window=vncwin, see below.
586
      $window = intval($windownumber) - 1;
587
588
      $win_id = $db->getWindowIDBySection($windownumber);
589
      $windowlist = windowList();
590
591
      if (count($windowlist) == 0) {
592
        trace("processRequests: no window found for command");
593
      } elseif (is_numeric($window) && count($windowlist) <= $window) {
594
        trace("processRequests: window $window is out of bounds");
595
      } elseif (!is_numeric($window)) {
596
        trace("processRequests: unhandled window $window");
597
      } else {
598
        trace("processRequests: command window");
599
        $windowname = $windowlist[$window];
600
        $windowhex = hexdec($windowname);
601
      }
602
    }
603
604
    if ($windowname && array_key_exists('key', $_REQUEST)) {
605
      $key = escapeshellcmd($_REQUEST['key']);
606
      trace("processRequests: key '$key' in window '$windownumber'");
607
      wmShow($windowname);
608
      // activateControls($windowhex);
609
      // displayCommand("xdotool windowfocus $windowhex key $key");
610
611
      // trying mousemove and click for better vnc control
612
      displayCommand("xdotool mousemove --window $windowhex 100 100 " .
613
                     "key $key");
614
    }
615
616
    if ($windowname && array_key_exists('keydown', $_REQUEST)) {
617
      // TODO: keydown is currently mapped to key because we had problems
618
      // with sticking keys (no keyup seen). This should be fixed by a
619
      // better event handling.
620
      $key = escapeshellcmd($_REQUEST['keydown']);
621
      trace("processRequests: keydown '$key' in window '$windownumber'");
622
      wmShow($windowname);
623
      // activateControls($windowhex);
624
      // displayCommand("xdotool windowfocus $windowhex key $key");
625
626
      // trying mousemove and click for better vnc control
627
      displayCommand("xdotool mousemove --window $windowhex 100 100 " .
628
                     "key $key");
629
      //~ displayCommand("xdotool windowfocus $windowhex keydown $key");
630
    }
631
632
    if ($windowname && array_key_exists('keyup', $_REQUEST)) {
633
      // TODO: keyup is currently ignored, see comment above.
634
      $key = escapeshellcmd($_REQUEST['keyup']);
635
      trace("processRequests: keyup '$key' in window '$windownumber'");
636
      // activateControls($windowhex);
637
      //~ wmShow($windowname);
638
      //~ displayCommand("xdotool windowfocus $windowhex keyup $key");
639
    }
640
641
    if (array_key_exists('delete', $_REQUEST)) {
642
      $delete = addslashes($_REQUEST['delete']);
643
      trace("processRequests: delete='$delete', close window $windownumber");
644
645
      if ($delete == "VNC") {
646
        trace("processRequests: delete vnc window");
647
        // call via daemon: ?window=vncwin&delete=VNC&vncid=123
648
        $win_id = escapeshellcmd($_REQUEST['vncid']);   // = hexWindow in database, but not on screen
649
        trace("VNC via Daemon ... id=$win_id");
650
      } elseif (strstr($delete, "http")) {
651
        trace("processRequests: delete browser window");
652
      } elseif (preg_match('/(^\w{3,}@\w{1,})/', $delete)) {
653
        trace("processRequests: delete vnc client from webinterface");
654
        // call via webinterface
655
        $win_id = $db->querySingle("SELECT win_id FROM window WHERE file='$delete' AND handler='vnc'");
656
      } else {
657
        // Restrict deletion to files known in the db.
658
        // TODO: check if given file and section match the values in the DB,
659
        // but currently, both those values can be ambiguous
660
        $file_in_db = $db->querySingle("SELECT id FROM window WHERE file='$delete'");
661
        $delete = str_replace(" ", "\ ", $delete);
662
        trace("processRequests: file in db: $file_in_db");
663
        if ($file_in_db) {
664
          if(file_exists($delete)) {
665
            trace("processRequests: delete file $delete");
666
            unlink($delete);
667
          }
668
        } else {
669
          trace("processRequests: given file not present in database!");
670
        }
671
      }
672
      wmClose($win_id);
0 ignored issues
show
Bug introduced by
It seems like $win_id can also be of type null; however, parameter $id of wmClose() does only seem to accept string, 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 ignore-type  annotation

672
      wmClose(/** @scrutinizer ignore-type */ $win_id);
Loading history...
673
      $db->deleteWindow($win_id);
0 ignored issues
show
Bug introduced by
It seems like $win_id can also be of type null; however, parameter $window_id of palma\DBConnector::deleteWindow() does only seem to accept string, 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 ignore-type  annotation

673
      $db->deleteWindow(/** @scrutinizer ignore-type */ $win_id);
Loading history...
674
    }
675
676
    if (array_key_exists('closeOrphans', $_REQUEST)) {
677
      // win_ids in db
678
      $windows_in_db = $db->getWindows();
679
      $db_ids = array();
680
681
      if (count($windows_in_db) > 0) {
682
        foreach ($windows_in_db as $win) {
683
          array_push($db_ids, $win['win_id']);
684
        }
685
      }
686
687
      // win_ids on screen
688
      $screen_ids = windowListOnScreen();
689
690
      // orphaned windows
691
      $orphan_ids = array_diff($screen_ids, $db_ids);
692
693
      if (count($orphan_ids) > 0) {
694
        // close windows on screen not existing in database
695
        foreach ($orphan_ids as $id) {
696
          wmClose($id);
697
        }
698
      }
699
    }
700
701
    if (array_key_exists('toggle', $_REQUEST)) {
702
      // Change window state from visible to invisible and vice versa.
703
      $state = $db->getWindowState($win_id);
704
      trace("processRequests: toggle window $windownumber, id=$win_id, state=$state");
705
      if ($state == "active") {
706
        wmHide($win_id);
707
        $db->setWindowState($win_id, "inactive");
708
      } else {
709
        wmShow($win_id);
710
        $db->setWindowState($win_id, "active");
711
      }
712
    }
713
  } elseif (array_key_exists('layout', $_REQUEST)) {
714
    setLayout(escapeshellcmd($_REQUEST['layout']));
715
  } elseif (array_key_exists('logout', $_REQUEST)) {
716
    doLogout($_REQUEST['logout']);
717
  } elseif (array_key_exists('newVncWindow', $_REQUEST)) {
718
    // TODO: Better write new code for VNC window.
719
    addNewWindow(unserialize(urldecode($_REQUEST['newVncWindow'])));
720
  } elseif (array_key_exists('newWindow', $_REQUEST)) {
721
    createNewWindowSafe(unserialize(urldecode($_REQUEST['newWindow'])));
722
  }
723
724
  if (array_key_exists('switchWindows', $_REQUEST)) {
725
    $before = escapeshellcmd($_REQUEST['before']);
726
    $after = escapeshellcmd($_REQUEST['after']);
727
    trace("processRequests: switchWindows $before -> $after");
728
729
    // exchange section
730
    $win_id1 = $db->getWindowIDBySection($before);
731
    $win_id2 = $db->getWindowIDBySection($after);
732
733
    $db->updateWindow($win_id1, 'section', $after);
734
    $db->updateWindow($win_id2, 'section', $before);
735
736
    debug("processRequests: updating database $win_id1 section=$after");
737
    debug("processRequests: updating database $win_id2 section=$before");
738
739
    // Update display (no layout change).
740
    setLayout();
741
  }
742
743
  if (array_key_exists('openURL', $_REQUEST)) {
744
    $openURL = escapeshellcmd($_REQUEST['openURL']);
745
    trace("processRequests: openURL $openURL");
746
747
    // If URL leads to pdf file, download it and treat as upload
748
    $headers = get_headers($openURL, PHP_MAJOR_VERSION < 8 ? 1 : true);
0 ignored issues
show
Bug introduced by
It seems like PHP_MAJOR_VERSION < 8 ? 1 : true can also be of type integer; however, parameter $associative of get_headers() does only seem to accept boolean, 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 ignore-type  annotation

748
    $headers = get_headers($openURL, /** @scrutinizer ignore-type */ PHP_MAJOR_VERSION < 8 ? 1 : true);
Loading history...
749
    if ($headers["Content-Type"] == "application/pdf") {
750
      debug("processRequests: url seems to lead to a pdf file, so downloading it...");
751
      $temp_name = basename($openURL);
752
      $temp_dir = "/tmp";
753
      file_put_contents("$temp_dir/$temp_name", file_get_contents($openURL));
754
      $mimetype = mime_content_type("$temp_dir/$temp_name");
755
      debug("processRequests: mimetype is $mimetype");
756
      if ($mimetype == "application/pdf") {
757
        $_FILES['file']['name'] = "$temp_name";
758
        $_FILES['file']['tmp_name'] = "$temp_dir/$temp_name";
759
        $_FILES['file']['error'] = "downloaded_from_url";
760
        debug("processRequests: handing over to upload.php");
761
        include 'upload.php';
762
      } else {
763
        debug("processRequests: deleting file");
764
        unlink("$temp_dir/$temp_name");
765
      }
766
    } else {
767
      $dt = new DateTime();
768
      $date = $dt->format('Y-m-d H:i:s');
769
      $window = array(
770
        "id" => "",
771
        "win_id" => "",
772
        "section" => "",
773
        "state" => "",
774
        "file" => $openURL,
775
        "handler" => "palma-browser",
776
        "userid" => "",
777
        "date" => $date
778
      );
779
      createNewWindow($window);
780
    }
781
  }
782
783
  // TODO: check if query redundant?
784
  if (array_key_exists('closeAll', $_REQUEST)) {
785
    $close = $_REQUEST['closeAll'];
786
    trace("processRequests: closeAll $close");
787
    closeAll();
788
  }
789
}
790