Issues (2037)

main/inc/lib/online.inc.php (1 issue)

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use ChamiloSession as Session;
6
7
/**
8
 * Code library for showing Who is online.
9
 *
10
 * @author Istvan Mandak, principal author
11
 * @author Denes Nagy, principal author
12
 * @author Bart Mollet
13
 * @author Roan Embrechts, cleaning and bugfixing
14
 * Insert a login reference for the current user into the track_e_online stats
15
 * table. This table keeps trace of the last login. Nothing else matters (we
16
 * don't keep traces of anything older).
17
 *
18
 * @param int user id
19
 */
20
function LoginCheck($uid)
21
{
22
    $uid = (int) $uid;
23
    if (!empty($uid)) {
24
        $online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
25
        $_course = api_get_course_info();
26
        $user_ip = '';
27
        if (!empty($_SERVER['REMOTE_ADDR'])) {
28
            $user_ip = Database::escape_string(api_get_real_ip());
29
        }
30
31
        $login_date = api_get_utc_datetime();
32
        $access_url_id = 1;
33
        if (api_get_multiple_access_url() && api_get_current_access_url_id() != -1) {
34
            $access_url_id = api_get_current_access_url_id();
35
        }
36
        $session_id = api_get_session_id();
37
        $cid = 0;
38
        if (is_array($_course) && count($_course) > 0 && !empty($_course['real_id'])) {
39
            $cid = intval($_course['real_id']);
40
        }
41
        $query = "SELECT login_id FROM $online_table WHERE login_user_id = $uid";
42
        $resLogin = Database::query($query);
43
        if (Database::num_rows($resLogin) > 0) {
44
            $query = "UPDATE $online_table SET
45
                      login_date = '$login_date',
46
                      user_ip = '$user_ip',
47
                      c_id = $cid,
48
                      session_id = $session_id,
49
                      access_url_id = $access_url_id
50
                      WHERE login_user_id = $uid";
51
            Database::query($query);
52
        } else {
53
            $query = "INSERT $online_table (
54
                login_user_id,
55
                login_date,
56
                user_ip,
57
                c_id,
58
                session_id,
59
                access_url_id
60
            ) values (
61
                $uid,
62
                '$login_date',
63
                '$user_ip',
64
                $cid,
65
                $session_id,
66
                $access_url_id
67
            )";
68
            Database::query($query);
69
        }
70
    }
71
}
72
73
/**
74
 * @param int $userId
75
 */
76
function preventMultipleLogin($userId)
77
{
78
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
79
    $userId = (int) $userId;
80
    if (api_get_setting('prevent_multiple_simultaneous_login') === 'true') {
81
        if (!empty($userId) && !api_is_anonymous()) {
82
            $isFirstLogin = Session::read('first_user_login');
83
            $currentIp = Session::read('current_ip');
84
            $differentIp = false;
85
            if (!empty($currentIp) && api_get_real_ip() !== $currentIp) {
86
                //$isFirstLogin = null;
87
                $differentIp = true;
88
            }
89
90
            if (empty($isFirstLogin)) {
91
                $sql = "SELECT login_id FROM $table
92
                        WHERE login_user_id = $userId
93
                        LIMIT 1";
94
95
                $result = Database::query($sql);
96
                $loginData = [];
97
                if (Database::num_rows($result)) {
98
                    $loginData = Database::fetch_array($result);
99
                }
100
101
                $userIsReallyOnline = user_is_online($userId);
102
103
                // Trying double login.
104
                if ((!empty($loginData) && $userIsReallyOnline) || $differentIp) {
105
                    session_regenerate_id();
106
                    Session::destroy();
107
                    header('Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=multiple_connection_not_allowed');
108
                    exit;
109
                } else {
110
                    // First time
111
                    Session::write('first_user_login', 1);
112
                    Session::write('current_ip', api_get_real_ip());
113
                }
114
            }
115
        }
116
    }
117
}
118
119
/**
120
 * This function handles the logout and is called whenever there is a $_GET['logout'].
121
 *
122
 * @param int  $user_id
123
 * @param bool $logout_redirect
124
 *
125
 * @author Fernando P. García <[email protected]>
126
 */
127
function online_logout($user_id = null, $logout_redirect = false)
128
{
129
    global $extAuthSource;
130
131
    // Database table definition
132
    $tbl_track_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
133
134
    if (empty($user_id)) {
135
        $user_id = isset($_GET['uid']) ? intval($_GET['uid']) : 0;
136
    }
137
138
    // Changing global chat status to offline
139
    if (api_is_global_chat_enabled()) {
140
        $chat = new Chat();
141
        $chat->setUserStatus(0);
142
    }
143
144
    $chat = new Chat();
145
    $chat->close();
146
147
    // selecting the last login of the user
148
    $sql = "SELECT login_id, login_date
149
    		FROM $tbl_track_login
150
    		WHERE login_user_id = $user_id
151
    		ORDER BY login_date DESC
152
    		LIMIT 0,1";
153
    $q_last_connection = Database::query($sql);
154
    $i_id_last_connection = 0;
155
    if (Database::num_rows($q_last_connection) > 0) {
156
        $i_id_last_connection = Database::result($q_last_connection, 0, "login_id");
157
    }
158
159
    if (!isset($_SESSION['login_as']) && !empty($i_id_last_connection)) {
160
        $current_date = api_get_utc_datetime();
161
        $sql = "UPDATE $tbl_track_login SET logout_date='".$current_date."'
162
        		WHERE login_id='$i_id_last_connection'";
163
        Database::query($sql);
164
    }
165
    $logInfo = [
166
        'tool' => 'logout',
167
        'tool_id' => 0,
168
        'tool_id_detail' => 0,
169
    ];
170
    Event::registerLog($logInfo);
171
172
    UserManager::loginDelete($user_id);
173
174
    //the following code enables the use of an external logout function.
175
    //example: define a $extAuthSource['ldap']['logout']="file.php" in configuration.php
176
    // then a function called ldap_logout() inside that file
177
    // (using *authent_name*_logout as the function name) and the following code
178
    // will find and execute it
179
    $uinfo = api_get_user_info($user_id);
180
    if (($uinfo['auth_source'] != PLATFORM_AUTH_SOURCE) && is_array($extAuthSource)) {
181
        if (is_array($extAuthSource[$uinfo['auth_source']])) {
182
            $subarray = $extAuthSource[$uinfo['auth_source']];
183
            if (!empty($subarray['logout']) && file_exists($subarray['logout'])) {
184
                require_once $subarray['logout'];
185
                $logout_function = $uinfo['auth_source'].'_logout';
186
                if (function_exists($logout_function)) {
187
                    $logout_function($uinfo);
188
                }
189
            }
190
        }
191
    }
192
193
    // After logout redirect to
194
    $url = api_get_path(WEB_PATH).'index.php';
195
196
    if ($logout_redirect && api_get_plugin_setting('azure_active_directory', 'enable') === 'true') {
197
        if (ChamiloSession::read('_user_auth_source') === 'azure_active_directory') {
198
            $activeDirectoryPlugin = AzureActiveDirectory::create();
199
            $azureLogout = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_LOGOUT);
200
            if (!empty($azureLogout)) {
201
                $url = $azureLogout;
202
            }
203
        }
204
    }
205
206
    if ('true' === api_get_plugin_setting('oauth2', 'enable')
207
        && 'oauth2' === ChamiloSession::read('_user_auth_source')
208
        && ChamiloSession::has('oauth2AccessToken')
209
    ) {
210
        if (!isset($oAuth2Plugin)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $oAuth2Plugin seems to never exist and therefore isset should always be false.
Loading history...
211
            $oAuth2Plugin = OAuth2::create();
212
        }
213
        $logoutUrl = $oAuth2Plugin->getLogoutUrl();
214
        if (!empty($logoutUrl)) {
215
            $url = $logoutUrl;
216
        }
217
    }
218
219
    api_delete_firstpage_parameter();
220
    Session::erase('last_id');
221
    CourseChatUtils::exitChat($user_id);
222
    session_regenerate_id();
223
    Session::destroy();
224
225
    $pluginKeycloak = api_get_plugin_setting('keycloak', 'tool_enable') === 'true';
226
    if ($pluginKeycloak && $uinfo['auth_source'] === 'keycloak') {
227
        $pluginUrl = api_get_path(WEB_PLUGIN_PATH).'keycloak/start.php?slo';
228
        header('Location: '.$pluginUrl);
229
        exit;
230
    }
231
232
    if ($uinfo['auth_source'] === CAS_AUTH_SOURCE && api_is_cas_activated()) {
233
        require_once __DIR__.'/../../auth/cas/cas_var.inc.php';
234
        if (phpCas::isInitialized()) {
235
            phpCAS::logout();
236
        }
237
    }
238
239
    if ($logout_redirect) {
240
        header("Location: $url");
241
        exit;
242
    }
243
}
244
245
/**
246
 * @param int $user_id
247
 *
248
 * @return bool
249
 */
250
function user_is_online($user_id)
251
{
252
    $track_online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
253
    $table_user = Database::get_main_table(TABLE_MAIN_USER);
254
255
    $access_url_id = api_get_current_access_url_id();
256
    $time_limit = api_get_setting('time_limit_whosonline');
257
258
    $online_time = time() - $time_limit * 60;
259
    $limit_date = api_get_utc_datetime($online_time);
260
    $user_id = (int) $user_id;
261
262
    $query = " SELECT login_user_id, login_date
263
               FROM $track_online_table track
264
               INNER JOIN $table_user u
265
               ON (u.id=track.login_user_id)
266
               WHERE
267
                    track.access_url_id =  $access_url_id AND
268
                    login_date >= '".$limit_date."'  AND
269
                    u.id =  $user_id
270
               LIMIT 1 ";
271
272
    $result = Database::query($query);
273
    if (Database::num_rows($result)) {
274
        return true;
275
    }
276
277
    return false;
278
}
279
280
/**
281
 * Gives a list of people online now (and in the last $valid minutes).
282
 *
283
 * @param $from
284
 * @param $number_of_items
285
 * @param null $column
286
 * @param null $direction
287
 * @param null $time_limit
288
 * @param bool $friends
289
 *
290
 * @return array|bool For each line, a list of user IDs and login dates, or FALSE on error or empty results
291
 */
292
function who_is_online(
293
    $from,
294
    $number_of_items,
295
    $column = null,
296
    $direction = null,
297
    $time_limit = null,
298
    $friends = false
299
) {
300
    // Time limit in seconds?
301
    if (empty($time_limit)) {
302
        $time_limit = api_get_setting('time_limit_whosonline');
303
    } else {
304
        $time_limit = intval($time_limit);
305
    }
306
307
    $from = intval($from);
308
    $number_of_items = intval($number_of_items);
309
310
    if (empty($column)) {
311
        $column = 'picture_uri';
312
        if ($friends) {
313
            $column = 'login_date';
314
        }
315
    }
316
317
    if (empty($direction)) {
318
        $direction = 'DESC';
319
    } else {
320
        if (!in_array(strtolower($direction), ['asc', 'desc'])) {
321
            $direction = 'DESC';
322
        }
323
    }
324
325
    $online_time = time() - $time_limit * 60;
326
    $current_date = api_get_utc_datetime($online_time);
327
    $track_online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
328
    $friend_user_table = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
329
    $table_user = Database::get_main_table(TABLE_MAIN_USER);
330
331
    if ($friends) {
332
        // 	who friends from social network is online
333
        $query = "SELECT DISTINCT login_user_id, login_date
334
                  FROM $track_online_table INNER JOIN $friend_user_table
335
                  ON (friend_user_id = login_user_id)
336
                  WHERE
337
                    login_date >= '".$current_date."' AND
338
                    friend_user_id <> '".api_get_user_id()."' AND
339
                    relation_type='".USER_RELATION_TYPE_FRIEND."' AND
340
                    user_id = '".api_get_user_id()."'
341
                  ORDER BY `$column` $direction
342
                  LIMIT $from, $number_of_items";
343
    } else {
344
        $query = "SELECT DISTINCT login_user_id, login_date
345
                    FROM ".$track_online_table." e
346
                    INNER JOIN ".$table_user." u ON (u.id = e.login_user_id)
347
                  WHERE u.status != ".ANONYMOUS." AND login_date >= '".$current_date."'
348
                  ORDER BY `$column` $direction
349
                  LIMIT $from, $number_of_items";
350
    }
351
352
    if (api_get_multiple_access_url()) {
353
        $access_url_id = api_get_current_access_url_id();
354
        if ($access_url_id != -1) {
355
            if ($friends) {
356
                // 	friends from social network is online
357
                $query = "SELECT distinct login_user_id, login_date
358
                            FROM $track_online_table track INNER JOIN $friend_user_table
359
                            ON (friend_user_id = login_user_id)
360
                            WHERE   track.access_url_id =  $access_url_id AND
361
                                    login_date >= '".$current_date."' AND
362
                                    friend_user_id <> '".api_get_user_id()."' AND
363
                                    relation_type='".USER_RELATION_TYPE_FRIEND."'
364
                            ORDER BY `$column` $direction
365
                            LIMIT $from, $number_of_items";
366
            } else {
367
                // all users online
368
                $query = "SELECT login_user_id, login_date
369
                          FROM ".$track_online_table." track
370
                          INNER JOIN ".$table_user." u
371
                          ON (u.id=track.login_user_id)
372
                          WHERE u.status != ".ANONYMOUS." AND track.access_url_id =  $access_url_id AND
373
                                login_date >= '".$current_date."'
374
                          ORDER BY `$column` $direction
375
                          LIMIT $from, $number_of_items";
376
            }
377
        }
378
    }
379
380
    //This query will show all registered users. Only for dev purposes.
381
    /*$query = "SELECT DISTINCT u.id as login_user_id, login_date
382
            FROM $track_online_table e, $table_user u
383
            GROUP by u.id
384
            ORDER BY $column $direction
385
            LIMIT $from, $number_of_items";*/
386
387
    $result = Database::query($query);
388
    if ($result) {
389
        $users_online = [];
390
        while (list($login_user_id, $login_date) = Database::fetch_row($result)) {
391
            $users_online[] = $login_user_id;
392
        }
393
394
        return $users_online;
395
    } else {
396
        return false;
397
    }
398
}
399
400
/**
401
 * @param string $time_limit
402
 */
403
function who_is_online_count($time_limit = null, $friends = false)
404
{
405
    if (empty($time_limit)) {
406
        $time_limit = api_get_setting('time_limit_whosonline');
407
    } else {
408
        $time_limit = intval($time_limit);
409
    }
410
    $track_online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
411
    $friend_user_table = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
412
    $table_user = Database::get_main_table(TABLE_MAIN_USER);
413
    $online_time = time() - $time_limit * 60;
414
    $current_date = api_get_utc_datetime($online_time);
415
416
    if ($friends) {
417
        // who friends from social network is online
418
        $query = "SELECT DISTINCT count(login_user_id) as count
419
				  FROM $track_online_table INNER JOIN $friend_user_table
420
                  ON (friend_user_id = login_user_id)
421
				  WHERE
422
				        login_date >= '$current_date' AND
423
				        friend_user_id <> '".api_get_user_id()."' AND
424
				        relation_type='".USER_RELATION_TYPE_FRIEND."' AND
425
				        user_id = '".api_get_user_id()."' ";
426
    } else {
427
        // All users online
428
        $query = "SELECT count(login_id) as count
429
                  FROM $track_online_table track INNER JOIN $table_user u
430
                  ON (u.id=track.login_user_id)
431
                  WHERE u.status != ".ANONYMOUS." AND login_date >= '$current_date'  ";
432
    }
433
434
    if (api_get_multiple_access_url()) {
435
        $access_url_id = api_get_current_access_url_id();
436
        if ($access_url_id != -1) {
437
            if ($friends) {
438
                // friends from social network is online
439
                $query = "SELECT DISTINCT count(login_user_id) as count
440
							FROM $track_online_table track
441
							INNER JOIN $friend_user_table ON (friend_user_id = login_user_id)
442
							WHERE
443
							    track.access_url_id = $access_url_id AND
444
							    login_date >= '".$current_date."' AND
445
							    friend_user_id <> '".api_get_user_id()."' AND
446
							    relation_type='".USER_RELATION_TYPE_FRIEND."'  ";
447
            } else {
448
                // all users online
449
                $query = "SELECT count(login_id) as count FROM $track_online_table  track
450
                          INNER JOIN $table_user u ON (u.id=track.login_user_id)
451
						  WHERE
452
						    u.status != ".ANONYMOUS." AND
453
						    track.access_url_id =  $access_url_id AND
454
						    login_date >= '$current_date' ";
455
            }
456
        }
457
    }
458
459
    // Dev purposes show all users online
460
    /*$table_user = Database::get_main_table(TABLE_MAIN_USER);
461
    $query = "SELECT count(*)  as count FROM ".$table_user;*/
462
463
    $result = Database::query($query);
464
    if (Database::num_rows($result) > 0) {
465
        $row = Database::fetch_array($result);
466
467
        return $row['count'];
468
    } else {
469
        return false;
470
    }
471
}
472
473
/**
474
 * Returns a list (array) of users who are online and in this course.
475
 *
476
 * @param    int User ID
477
 * @param    int Number of minutes
478
 * @param    string  Course code (could be empty, but then the function returns false)
479
 *
480
 * @return array Each line gives a user id and a login time
481
 */
482
function who_is_online_in_this_course($from, $number_of_items, $uid, $time_limit, $course_code)
483
{
484
    if (empty($course_code)) {
485
        return false;
486
    }
487
488
    $time_limit = (int) $time_limit;
489
    if (empty($time_limit)) {
490
        $time_limit = api_get_setting('time_limit_whosonline');
491
    }
492
493
    $online_time = time() - $time_limit * 60;
494
    $current_date = api_get_utc_datetime($online_time);
495
    $track_online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
496
    $tableUser = Database::get_main_table(TABLE_MAIN_USER);
497
    $course_code = Database::escape_string($course_code);
498
    $courseInfo = api_get_course_info($course_code);
499
    $courseId = $courseInfo['real_id'];
500
501
    $from = (int) $from;
502
    $number_of_items = (int) $number_of_items;
503
504
    $urlCondition = '';
505
    $urlJoin = '';
506
    if (api_is_multiple_url_enabled()) {
507
        $accessUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
508
        $urlId = api_get_current_access_url_id();
509
        $urlJoin = " INNER JOIN $accessUrlUser a ON (a.user_id = u.id) ";
510
        $urlCondition = " AND a.access_url_id = $urlId ";
511
    }
512
513
    $query = "SELECT o.login_user_id, o.login_date
514
              FROM $track_online_table o
515
              INNER JOIN $tableUser u
516
              ON (o.login_user_id = u.id)
517
              $urlJoin
518
              WHERE
519
                u.status <> '".ANONYMOUS."' AND
520
                o.c_id = $courseId AND
521
                o.login_date >= '$current_date'
522
                $urlCondition
523
              LIMIT $from, $number_of_items ";
524
525
    $result = Database::query($query);
526
    if ($result) {
527
        $users_online = [];
528
        while (list($login_user_id, $login_date) = Database::fetch_row($result)) {
529
            $users_online[] = $login_user_id;
530
        }
531
532
        return $users_online;
533
    } else {
534
        return false;
535
    }
536
}
537
538
/**
539
 * @param int    $uid
540
 * @param string $time_limit
541
 */
542
function who_is_online_in_this_course_count(
543
    $uid,
544
    $time_limit,
545
    $coursecode = null
546
) {
547
    if (empty($coursecode)) {
548
        return false;
549
    }
550
    $track_online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
551
    $tableUser = Database::get_main_table(TABLE_MAIN_USER);
552
    $time_limit = Database::escape_string($time_limit);
553
    $online_time = time() - $time_limit * 60;
554
    $current_date = api_get_utc_datetime($online_time);
555
    $courseId = api_get_course_int_id($coursecode);
556
557
    if (empty($courseId)) {
558
        return false;
559
    }
560
561
    $urlCondition = '';
562
    $urlJoin = '';
563
    if (api_is_multiple_url_enabled()) {
564
        $accessUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
565
        $urlId = api_get_current_access_url_id();
566
        $urlJoin = " INNER JOIN $accessUrlUser a ON (a.user_id = u.id) ";
567
        $urlCondition = " AND a.access_url_id = $urlId ";
568
    }
569
570
    $query = "SELECT count(login_user_id) as count
571
              FROM $track_online_table o
572
              INNER JOIN $tableUser u
573
              ON (login_user_id = u.id)
574
              $urlJoin
575
              WHERE
576
                u.status <> '".ANONYMOUS."' AND
577
                c_id = $courseId AND
578
                login_date >= '$current_date'
579
                $urlCondition
580
                ";
581
    $result = Database::query($query);
582
    if (Database::num_rows($result) > 0) {
583
        $row = Database::fetch_array($result);
584
585
        return $row['count'];
586
    } else {
587
        return false;
588
    }
589
}
590
591
/**
592
 * @param string $timeLimit
593
 * @param int    $sessionId
594
 *
595
 * @return bool
596
 */
597
function whoIsOnlineInThisSessionCount($timeLimit, $sessionId)
598
{
599
    if (!$sessionId) {
600
        return 0;
601
    }
602
603
    $tblTrackOnline = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
604
    $tableUser = Database::get_main_table(TABLE_MAIN_USER);
605
606
    $timeLimit = Database::escape_string($timeLimit);
607
    $online_time = time() - $timeLimit * 60;
608
    $current_date = api_get_utc_datetime($online_time);
609
610
    $urlCondition = '';
611
    $urlJoin = '';
612
    if (api_is_multiple_url_enabled()) {
613
        $accessUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
614
        $urlId = api_get_current_access_url_id();
615
        $urlJoin = " INNER JOIN $accessUrlUser a ON (a.user_id = u.id) ";
616
        $urlCondition = " AND a.access_url_id = $urlId ";
617
    }
618
619
    $query = "SELECT count(login_user_id) as count
620
              FROM $tblTrackOnline o
621
              INNER JOIN $tableUser u
622
              ON (login_user_id = u.id)
623
              $urlJoin
624
              WHERE
625
                    u.status <> '".ANONYMOUS."' AND
626
                    session_id = $sessionId AND
627
                    login_date >= '$current_date'
628
                    $urlCondition
629
            ";
630
    $result = Database::query($query);
631
632
    if (Database::num_rows($result) > 0) {
633
        $row = Database::fetch_assoc($result);
634
635
        return $row['count'];
636
    }
637
638
    return 0;
639
}
640