Polished.
[moodle.git] / lib / moodlelib.php
CommitLineData
dcb1bd3c 1<?php // $Id$
f9903ed0 2
9fa49e22 3///////////////////////////////////////////////////////////////////////////
4// //
5// moodlelib.php //
6// //
7// Main library file of miscellaneous general-purpose Moodle functions //
8// //
9// Other main libraries: //
10// //
11// weblib.php - functions that produce web output //
12// datalib.php - functions that access the database //
13// //
14///////////////////////////////////////////////////////////////////////////
15// //
16// NOTICE OF COPYRIGHT //
17// //
18// Moodle - Modular Object-Oriented Dynamic Learning Environment //
abc3b857 19// http://moodle.org //
9fa49e22 20// //
abc3b857 21// Copyright (C) 1999-2004 Martin Dougiamas http://dougiamas.com //
9fa49e22 22// //
23// This program is free software; you can redistribute it and/or modify //
24// it under the terms of the GNU General Public License as published by //
25// the Free Software Foundation; either version 2 of the License, or //
26// (at your option) any later version. //
27// //
28// This program is distributed in the hope that it will be useful, //
29// but WITHOUT ANY WARRANTY; without even the implied warranty of //
30// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
31// GNU General Public License for more details: //
32// //
33// http://www.gnu.org/copyleft/gpl.html //
34// //
35///////////////////////////////////////////////////////////////////////////
65ccdd8c 36
f374fb10 37/// CONSTANTS /////////////////////////////////////////////////////////////
38
d8ba183c 39define('NOGROUPS', 0);
f374fb10 40define('SEPARATEGROUPS', 1);
41define('VISIBLEGROUPS', 2);
42
f9903ed0 43
9fa49e22 44/// PARAMETER HANDLING ////////////////////////////////////////////////////
6b174680 45
9fa49e22 46function require_variable($var) {
47/// Variable must be present
48 if (! isset($var)) {
b0ccd3fb 49 error('A required parameter was missing');
6b174680 50 }
51}
52
9fa49e22 53function optional_variable(&$var, $default=0) {
54/// Variable may be present, if not then set a default
55 if (! isset($var)) {
56 $var = $default;
6b174680 57 }
58}
59
60
9fa49e22 61function set_config($name, $value) {
62/// No need for get_config because they are usually always available in $CFG
70812e39 63
42282810 64 global $CFG;
65
66 $CFG->$name = $value; // So it's defined for this invocation at least
dfc9ba9b 67
b0ccd3fb 68 if (get_field('config', 'name', 'name', $name)) {
69 return set_field('config', 'value', $value, 'name', $name);
d897cae4 70 } else {
9fa49e22 71 $config->name = $name;
72 $config->value = $value;
b0ccd3fb 73 return insert_record('config', $config);
39917a09 74 }
39917a09 75}
76
39917a09 77
70812e39 78function reload_user_preferences() {
79/// Refresh current USER with all their current preferences
80
81 global $USER;
82
d8ba183c 83 unset($USER->preference);
70812e39 84
85 if ($preferences = get_records('user_preferences', 'userid', $USER->id)) {
86 foreach ($preferences as $preference) {
87 $USER->preference[$preference->name] = $preference->value;
88 }
4586d60c 89 } else {
90 //return empty preference array to hold new values
91 $USER->preference = array();
92 }
70812e39 93}
94
d35757eb 95function set_user_preference($name, $value, $user=NULL) {
70812e39 96/// Sets a preference for the current user
d35757eb 97/// Optionally, can set a preference for a different user object
70812e39 98
99 global $USER;
100
d35757eb 101 if (empty($user)){
102 $user = $USER;
103 }
104
70812e39 105 if (empty($name)) {
106 return false;
107 }
108
d35757eb 109 if ($preference = get_record('user_preferences', 'userid', $user->id, 'name', $name)) {
b0ccd3fb 110 if (set_field('user_preferences', 'value', $value, 'id', $preference->id)) {
d35757eb 111 $user->preference[$name] = $value;
066af654 112 return true;
113 } else {
114 return false;
115 }
70812e39 116
117 } else {
d35757eb 118 $preference->userid = $user->id;
70812e39 119 $preference->name = $name;
120 $preference->value = (string)$value;
066af654 121 if (insert_record('user_preferences', $preference)) {
d35757eb 122 $user->preference[$name] = $value;
70812e39 123 return true;
124 } else {
125 return false;
126 }
127 }
128}
129
130function set_user_preferences($prefarray) {
131/// Sets a whole array of preferences for the current user
132
133 if (!is_array($prefarray) or empty($prefarray)) {
134 return false;
135 }
136
137 $return = true;
138 foreach ($prefarray as $name => $value) {
139 // The order is important; if the test for return is done first,
140 // then if one function call fails all the remaining ones will
141 // be "optimized away"
142 $return = set_user_preference($name, $value) and $return;
143 }
144 return $return;
145}
146
147function get_user_preferences($name=NULL, $default=NULL) {
148/// Without arguments, returns all the current user preferences
d8ba183c 149/// as an array. If a name is specified, then this function
150/// attempts to return that particular preference value. If
70812e39 151/// none is found, then the optional value $default is returned,
152/// otherwise NULL.
153
154 global $USER;
155
156 if (empty($USER->preference)) {
157 return $default; // Default value (or NULL)
158 }
159 if (empty($name)) {
160 return $USER->preference; // Whole array
161 }
162 if (!isset($USER->preference[$name])) {
163 return $default; // Default value (or NULL)
164 }
165 return $USER->preference[$name]; // The single value
166}
167
168
9fa49e22 169/// FUNCTIONS FOR HANDLING TIME ////////////////////////////////////////////
39917a09 170
3db75c62 171function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99) {
9fa49e22 172/// Given date parts in user time, produce a GMT timestamp
39917a09 173
f30fe8d0 174 $timezone = get_user_timezone($timezone);
94e34118 175
176 if (abs($timezone) > 13) {
03c17ddf 177 return mktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
178 } else {
179 $time = gmmktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
180 return usertime($time, $timezone); // This is GMT
181 }
39917a09 182}
183
8dbed6be 184function format_time($totalsecs, $str=NULL) {
9fa49e22 185/// Given an amount of time in seconds, returns string
186/// formatted nicely as months, days, hours etc as needed
c7e3ac2a 187
6b174680 188 $totalsecs = abs($totalsecs);
c7e3ac2a 189
8dbed6be 190 if (!$str) { // Create the str structure the slow way
b0ccd3fb 191 $str->day = get_string('day');
192 $str->days = get_string('days');
193 $str->hour = get_string('hour');
194 $str->hours = get_string('hours');
195 $str->min = get_string('min');
196 $str->mins = get_string('mins');
197 $str->sec = get_string('sec');
198 $str->secs = get_string('secs');
8dbed6be 199 }
200
201 $days = floor($totalsecs/86400);
6b174680 202 $remainder = $totalsecs - ($days*86400);
8dbed6be 203 $hours = floor($remainder/3600);
6b174680 204 $remainder = $remainder - ($hours*3600);
8dbed6be 205 $mins = floor($remainder/60);
206 $secs = $remainder - ($mins*60);
207
208 $ss = ($secs == 1) ? $str->sec : $str->secs;
209 $sm = ($mins == 1) ? $str->min : $str->mins;
210 $sh = ($hours == 1) ? $str->hour : $str->hours;
211 $sd = ($days == 1) ? $str->day : $str->days;
212
b0ccd3fb 213 $odays = '';
214 $ohours = '';
215 $omins = '';
216 $osecs = '';
9c9f7d77 217
b0ccd3fb 218 if ($days) $odays = $days .' '. $sd;
219 if ($hours) $ohours = $hours .' '. $sh;
220 if ($mins) $omins = $mins .' '. $sm;
221 if ($secs) $osecs = $secs .' '. $ss;
6b174680 222
b0ccd3fb 223 if ($days) return $odays .' '. $ohours;
224 if ($hours) return $ohours .' '. $omins;
225 if ($mins) return $omins .' '. $osecs;
226 if ($secs) return $osecs;
227 return get_string('now');
6b174680 228}
f9903ed0 229
b0ccd3fb 230function userdate($date, $format='', $timezone=99, $fixday = true) {
9fa49e22 231/// Returns a formatted string that represents a date in user time
232/// WARNING: note that the format is for strftime(), not date().
d8ba183c 233/// Because of a bug in most Windows time libraries, we can't use
9fa49e22 234/// the nicer %e, so we have to use %d which has leading zeroes.
d8ba183c 235/// A lot of the fuss below is just getting rid of these leading
9fa49e22 236/// zeroes as efficiently as possible.
61ae5d36 237///
d8ba183c 238/// If parammeter fixday = true (default), then take off leading
61ae5d36 239/// zero from %d, else mantain it.
7a302afc 240
b0ccd3fb 241 if ($format == '') {
242 $format = get_string('strftimedaydatetime');
5fa51a39 243 }
035cdbff 244
b0ccd3fb 245 $formatnoday = str_replace('%d', 'DD', $format);
61ae5d36 246 if ($fixday) {
247 $fixday = ($formatnoday != $format);
248 }
dcde9f02 249
f30fe8d0 250 $timezone = get_user_timezone($timezone);
90207a06 251
0431bd7c 252 if (abs($timezone) > 13) {
035cdbff 253 if ($fixday) {
254 $datestring = strftime($formatnoday, $date);
b0ccd3fb 255 $daystring = str_replace(' 0', '', strftime(" %d", $date));
256 $datestring = str_replace('DD', $daystring, $datestring);
035cdbff 257 } else {
258 $datestring = strftime($format, $date);
259 }
bea7a51e 260 } else {
70d4cf82 261 $date = $date + (int)($timezone * 3600);
035cdbff 262 if ($fixday) {
70d4cf82 263 $datestring = gmstrftime($formatnoday, $date);
b0ccd3fb 264 $daystring = str_replace(' 0', '', gmstrftime(" %d", $date));
265 $datestring = str_replace('DD', $daystring, $datestring);
035cdbff 266 } else {
70d4cf82 267 $datestring = gmstrftime($format, $date);
035cdbff 268 }
873960de 269 }
bea7a51e 270
035cdbff 271 return $datestring;
873960de 272}
273
5fa51a39 274function usergetdate($date, $timezone=99) {
d8ba183c 275/// Given a $date timestamp in GMT, returns an array
9fa49e22 276/// that represents the date in user time
6b174680 277
f30fe8d0 278 $timezone = get_user_timezone($timezone);
a36166d3 279
0431bd7c 280 if (abs($timezone) > 13) {
873960de 281 return getdate($date);
282 }
d2d6171f 283 //There is no gmgetdate so I have to fake it...
284 $date = $date + (int)($timezone * 3600);
b0ccd3fb 285 $getdate['seconds'] = gmstrftime("%S", $date);
286 $getdate['minutes'] = gmstrftime("%M", $date);
287 $getdate['hours'] = gmstrftime("%H", $date);
288 $getdate['mday'] = gmstrftime("%d", $date);
289 $getdate['wday'] = gmstrftime("%u", $date);
290 $getdate['mon'] = gmstrftime("%m", $date);
291 $getdate['year'] = gmstrftime("%Y", $date);
292 $getdate['yday'] = gmstrftime("%j", $date);
293 $getdate['weekday'] = gmstrftime("%A", $date);
294 $getdate['month'] = gmstrftime("%B", $date);
d2d6171f 295 return $getdate;
d552ead0 296}
297
298function usertime($date, $timezone=99) {
d8ba183c 299/// Given a GMT timestamp (seconds since epoch), offsets it by
9fa49e22 300/// the timezone. eg 3pm in India is 3pm GMT - 7 * 3600 seconds
a36166d3 301
f30fe8d0 302 $timezone = get_user_timezone($timezone);
0431bd7c 303 if (abs($timezone) > 13) {
d552ead0 304 return $date;
305 }
306 return $date - (int)($timezone * 3600);
307}
308
edf7fe8c 309function usergetmidnight($date, $timezone=99) {
9fa49e22 310/// Given a time, return the GMT timestamp of the most recent midnight
311/// for the current user.
edf7fe8c 312
f30fe8d0 313 $timezone = get_user_timezone($timezone);
edf7fe8c 314 $userdate = usergetdate($date, $timezone);
4606d9bb 315
0431bd7c 316 if (abs($timezone) > 13) {
b0ccd3fb 317 return mktime(0, 0, 0, $userdate['mon'], $userdate['mday'], $userdate['year']);
4606d9bb 318 }
319
b0ccd3fb 320 $timemidnight = gmmktime (0, 0, 0, $userdate['mon'], $userdate['mday'], $userdate['year']);
edf7fe8c 321 return usertime($timemidnight, $timezone); // Time of midnight of this user's day, in GMT
322
323}
324
d552ead0 325function usertimezone($timezone=99) {
9fa49e22 326/// Returns a string that prints the user's timezone
d552ead0 327
f30fe8d0 328 $timezone = get_user_timezone($timezone);
329
0431bd7c 330 if (abs($timezone) > 13) {
b0ccd3fb 331 return 'server time';
d552ead0 332 }
333 if (abs($timezone) < 0.5) {
b0ccd3fb 334 return 'GMT';
d552ead0 335 }
336 if ($timezone > 0) {
b0ccd3fb 337 return 'GMT+'. $timezone;
d552ead0 338 } else {
b0ccd3fb 339 return 'GMT'. $timezone;
d552ead0 340 }
f9903ed0 341}
342
f30fe8d0 343function get_user_timezone($tz = 99) {
344// Returns a float which represents the user's timezone difference from GMT in hours
345// Checks various settings and picks the most dominant of those which have a value
346
347 // Variables declared explicitly global here so that if we add
348 // something later we won't forget to global it...
349 $timezones = array(
350 isset($GLOBALS['USER']->timezone) ? $GLOBALS['USER']->timezone : 99,
351 isset($GLOBALS['CFG']->timezone) ? $GLOBALS['CFG']->timezone : 99,
352 );
353 while($tz == 99 && $next = each($timezones)) {
354 $tz = (float)$next['value'];
355 }
356
357 return $tz;
358}
f9903ed0 359
9fa49e22 360/// USER AUTHENTICATION AND LOGIN ////////////////////////////////////////
f9903ed0 361
8e8d0524 362function require_login($courseid=0, $autologinguest=true) {
9fa49e22 363/// This function checks that the current user is logged in, and optionally
364/// whether they are "logged in" or allowed to be in a particular course.
365/// If not, then it redirects them to the site login or course enrolment.
8e8d0524 366/// $autologinguest determines whether visitors should automatically be
367/// logged in as guests provide $CFG->autologinguests is set to 1
f9903ed0 368
73047f2f 369 global $CFG, $SESSION, $USER, $FULLME, $MoodleSession;
d8ba183c 370
da5c172a 371 // First check that the user is logged in to the site.
c21c671d 372 if (! (isset($USER->loggedin) and $USER->confirmed and ($USER->site == $CFG->wwwroot)) ) { // They're not
f9903ed0 373 $SESSION->wantsurl = $FULLME;
b0ccd3fb 374 if (!empty($_SERVER['HTTP_REFERER'])) {
375 $SESSION->fromurl = $_SERVER['HTTP_REFERER'];
9f44d972 376 }
c21c671d 377 $USER = NULL;
8e8d0524 378 if ($autologinguest and $CFG->autologinguests and $courseid and get_field('course','guest','id',$courseid)) {
379 $loginguest = '?loginguest=true';
380 } else {
381 $loginguest = '';
a2ebe6a5 382 }
8a33e371 383 if (empty($CFG->loginhttps)) {
b0ccd3fb 384 redirect($CFG->wwwroot .'/login/index.php'. $loginguest);
8a33e371 385 } else {
b0ccd3fb 386 $wwwroot = str_replace('http','https', $CFG->wwwroot);
387 redirect($wwwroot .'/login/index.php'. $loginguest);
8a33e371 388 }
f9903ed0 389 die;
f9903ed0 390 }
808a3baa 391
d35757eb 392 // check whether the user should be changing password
393 reload_user_preferences();
4586d60c 394 if (isset($USER->preference['auth_forcepasswordchange'])){
d35757eb 395 if (is_internal_auth() || $CFG->{'auth_'.$USER->auth.'_stdchangepassword'}){
b0ccd3fb 396 redirect($CFG->wwwroot .'/login/change_password.php');
d35757eb 397 } elseif($CFG->changepassword) {
398 redirect($CFG->changepassword);
399 } else {
b0ccd3fb 400 error('You cannot proceed without changing your password.
d35757eb 401 However there is no available page for changing it.
b0ccd3fb 402 Please contact your Moodle Administrator.');
d35757eb 403 }
404 }
405
808a3baa 406 // Check that the user account is properly set up
407 if (user_not_fully_set_up($USER)) {
b0ccd3fb 408 redirect($CFG->wwwroot .'/user/edit.php?id='. $USER->id .'&amp;course='. SITEID);
808a3baa 409 die;
410 }
d8ba183c 411
da5c172a 412 // Next, check if the user can be in a particular course
413 if ($courseid) {
9c9f7d77 414 if (!empty($USER->student[$courseid]) or !empty($USER->teacher[$courseid]) or !empty($USER->admin)) {
cb909d74 415 if (isset($USER->realuser)) { // Make sure the REAL person can also access this course
416 if (!isteacher($courseid, $USER->realuser)) {
417 print_header();
b0ccd3fb 418 notice(get_string('studentnotallowed', '', fullname($USER, true)), $CFG->wwwroot .'/');
cb909d74 419 }
3ce2f1e0 420 }
da5c172a 421 return; // user is a member of this course.
422 }
b0ccd3fb 423 if (! $course = get_record('course', 'id', $courseid)) {
424 error('That course doesn\'t exist');
da5c172a 425 }
1efa27fd 426 if (!$course->visible) {
427 print_header();
b0ccd3fb 428 notice(get_string('studentnotallowed', '', fullname($USER, true)), $CFG->wwwroot .'/');
1efa27fd 429 }
b0ccd3fb 430 if ($USER->username == 'guest') {
7363ff91 431 switch ($course->guest) {
432 case 0: // Guests not allowed
433 print_header();
b0ccd3fb 434 notice(get_string('guestsnotallowed', '', $course->fullname));
7363ff91 435 break;
436 case 1: // Guests allowed
7363ff91 437 return;
438 case 2: // Guests allowed with key (drop through)
439 break;
440 }
da5c172a 441 }
f9903ed0 442
7363ff91 443 // Currently not enrolled in the course, so see if they want to enrol
da5c172a 444 $SESSION->wantsurl = $FULLME;
b0ccd3fb 445 redirect($CFG->wwwroot .'/course/enrol.php?id='. $courseid);
da5c172a 446 die;
447 }
f9903ed0 448}
449
f950af3c 450function require_course_login($course, $autologinguest=true) {
451// This is a weaker version of require_login which only requires login
452// when called from within a course rather than the site page, unless
453// the forcelogin option is turned on.
454 global $CFG;
455 if ($CFG->forcelogin) {
456 require_login();
457 }
458 if ($course->category) {
459 require_login($course->id, $autologinguest);
460 }
461}
462
1d881d92 463function update_user_login_times() {
464 global $USER;
465
466 $USER->lastlogin = $user->lastlogin = $USER->currentlogin;
2a2f5f11 467 $USER->currentlogin = $user->lastaccess = $user->currentlogin = time();
1d881d92 468
469 $user->id = $USER->id;
470
b0ccd3fb 471 return update_record('user', $user);
1d881d92 472}
473
808a3baa 474function user_not_fully_set_up($user) {
b0ccd3fb 475 return ($user->username != 'guest' and (empty($user->firstname) or empty($user->lastname) or empty($user->email)));
808a3baa 476}
f9903ed0 477
f9903ed0 478function update_login_count() {
9fa49e22 479/// Keeps track of login attempts
480
f9903ed0 481 global $SESSION;
482
483 $max_logins = 10;
484
485 if (empty($SESSION->logincount)) {
486 $SESSION->logincount = 1;
487 } else {
488 $SESSION->logincount++;
489 }
490
491 if ($SESSION->logincount > $max_logins) {
9fa49e22 492 unset($SESSION->wantsurl);
b0ccd3fb 493 error(get_string('errortoomanylogins'));
d578afc8 494 }
495}
496
9fa49e22 497function reset_login_count() {
498/// Resets login attempts
499 global $SESSION;
d578afc8 500
9fa49e22 501 $SESSION->logincount = 0;
d578afc8 502}
503
b0ccd3fb 504function check_for_restricted_user($username=NULL, $redirect='') {
cb98d312 505 global $CFG, $USER;
506
507 if (!$username) {
508 if (!empty($USER->username)) {
509 $username = $USER->username;
510 } else {
511 return false;
512 }
513 }
514
515 if (!empty($CFG->restrictusers)) {
516 $names = explode(',', $CFG->restrictusers);
517 if (in_array($username, $names)) {
b0ccd3fb 518 error(get_string('restricteduser', 'error', fullname($USER)), $redirect);
cb98d312 519 }
520 }
521}
522
581d7b49 523function isadmin($userid=0) {
9fa49e22 524/// Is the user an admin?
f9903ed0 525 global $USER;
aa095969 526 static $admins = array();
527 static $nonadmins = array();
f9903ed0 528
581d7b49 529 if (!$userid){
530 if (empty($USER->id)) {
531 return false;
532 }
533 $userid = $USER->id;
9bd2c874 534 }
535
581d7b49 536 if (in_array($userid, $admins)) {
aa095969 537 return true;
581d7b49 538 } else if (in_array($userid, $nonadmins)) {
aa095969 539 return false;
b0ccd3fb 540 } else if (record_exists('user_admins', 'userid', $userid)){
581d7b49 541 $admins[] = $userid;
aa095969 542 return true;
543 } else {
581d7b49 544 $nonadmins[] = $userid;
aa095969 545 return false;
f9903ed0 546 }
f9903ed0 547}
548
9d3c795c 549function isteacher($courseid=0, $userid=0, $includeadmin=true) {
9fa49e22 550/// Is the user a teacher or admin?
f9903ed0 551 global $USER;
552
9788367b 553 if ($includeadmin and isadmin($userid)) { // admins can do anything the teacher can
d115a57f 554 return true;
555 }
556
f9903ed0 557 if (!$userid) {
71f9abf9 558 if ($courseid) {
559 return !empty($USER->teacher[$courseid]);
560 }
561 if (!isset($USER->id)) {
562 return false;
563 }
564 $userid = $USER->id;
f9903ed0 565 }
566
9d3c795c 567 if (!$courseid) {
b0ccd3fb 568 return record_exists('user_teachers', 'userid', $userid);
9d3c795c 569 }
570
b0ccd3fb 571 return record_exists('user_teachers', 'userid', $userid, 'course', $courseid);
f9903ed0 572}
573
73047f2f 574function isteacheredit($courseid, $userid=0) {
575/// Is the user allowed to edit this course?
576 global $USER;
577
d8ba183c 578 if (isadmin($userid)) { // admins can do anything
73047f2f 579 return true;
580 }
581
582 if (!$userid) {
583 return !empty($USER->teacheredit[$courseid]);
584 }
585
b0ccd3fb 586 return get_field('user_teachers', 'editall', 'userid', $userid, 'course', $courseid);
73047f2f 587}
588
1924074c 589function iscreator ($userid=0) {
590/// Can user create new courses?
591 global $USER;
8a205861 592 if (empty($USER->id)) {
593 return false;
594 }
1924074c 595 if (isadmin($userid)) { // admins can do anything
596 return true;
597 }
8a205861 598 if (empty($userid)) {
b0ccd3fb 599 return record_exists('user_coursecreators', 'userid', $USER->id);
1924074c 600 }
601
b0ccd3fb 602 return record_exists('user_coursecreators', 'userid', $userid);
1924074c 603}
604
8a9e3fd7 605function isstudent($courseid, $userid=0) {
9fa49e22 606/// Is the user a student in this course?
2cc72e84 607/// If course is site, is the user a confirmed user on the site?
71f9abf9 608 global $USER, $CFG;
f9903ed0 609
2700d113 610 if (empty($USER->id) and !$userid) {
7064e18f 611 return false;
612 }
613
222ac91b 614 if ($courseid == SITEID) {
2cc72e84 615 if (!$userid) {
616 $userid = $USER->id;
617 }
618 if (isguest($userid)) {
619 return false;
620 }
71f9abf9 621 // a site teacher can never be a site student
622 if (isteacher($courseid, $userid)) {
623 return false;
624 }
2700d113 625 if ($CFG->allusersaresitestudents) {
626 return record_exists('user', 'id', $userid);
627 } else {
628 return (record_exists('user_students', 'userid', $userid)
71f9abf9 629 or record_exists('user_teachers', 'userid', $userid));
2700d113 630 }
8f0cd6ef 631 }
2cc72e84 632
f9903ed0 633 if (!$userid) {
346b1a24 634 return !empty($USER->student[$courseid]);
f9903ed0 635 }
636
ebc3bd2b 637 // $timenow = time(); // todo: add time check below
f9903ed0 638
b0ccd3fb 639 return record_exists('user_students', 'userid', $userid, 'course', $courseid);
f9903ed0 640}
641
da5c172a 642function isguest($userid=0) {
9fa49e22 643/// Is the user a guest?
da5c172a 644 global $USER;
645
646 if (!$userid) {
b35e8568 647 if (empty($USER->username)) {
648 return false;
649 }
b0ccd3fb 650 return ($USER->username == 'guest');
da5c172a 651 }
652
b0ccd3fb 653 return record_exists('user', 'id', $userid, 'username', 'guest');
da5c172a 654}
655
9fa49e22 656
2c309dc2 657function isediting($courseid, $user=NULL) {
9fa49e22 658/// Is the current user in editing mode?
2c309dc2 659 global $USER;
660 if (!$user){
661 $user = $USER;
662 }
9c9f7d77 663 if (empty($user->editing)) {
664 return false;
665 }
2c309dc2 666 return ($user->editing and isteacher($courseid, $user->id));
667}
668
7977cffd 669function ismoving($courseid) {
670/// Is the current user currently moving an activity?
671 global $USER;
672
673 if (!empty($USER->activitycopy)) {
674 return ($USER->activitycopycourse == $courseid);
675 }
676 return false;
677}
678
e2cd5065 679function fullname($user, $override=false) {
b5cbb64d 680/// Given an object containing firstname and lastname
d8ba183c 681/// values, this function returns a string with the
b5cbb64d 682/// full name of the person.
e2cd5065 683/// The result may depend on system settings
b5cbb64d 684/// or language. 'override' will force both names
e2cd5065 685/// to be used even if system settings specify one.
b5cbb64d 686
f374fb10 687 global $CFG, $SESSION;
688
6527c077 689 if (!isset($user->firstname) and !isset($user->lastname)) {
690 return '';
691 }
692
f374fb10 693 if (!empty($SESSION->fullnamedisplay)) {
694 $CFG->fullnamedisplay = $SESSION->fullnamedisplay;
695 }
e2cd5065 696
b5cbb64d 697 if ($CFG->fullnamedisplay == 'firstname lastname') {
b0ccd3fb 698 return $user->firstname .' '. $user->lastname;
b5cbb64d 699
700 } else if ($CFG->fullnamedisplay == 'lastname firstname') {
b0ccd3fb 701 return $user->lastname .' '. $user->firstname;
e2cd5065 702
b5cbb64d 703 } else if ($CFG->fullnamedisplay == 'firstname') {
704 if ($override) {
705 return get_string('fullnamedisplay', '', $user);
706 } else {
707 return $user->firstname;
708 }
709 }
e2cd5065 710
b5cbb64d 711 return get_string('fullnamedisplay', '', $user);
e2cd5065 712}
713
f9903ed0 714
715function set_moodle_cookie($thing) {
9fa49e22 716/// Sets a moodle cookie with an encrypted string
7185e073 717 global $CFG;
482b6e6e 718
719 $cookiename = 'MOODLEID_'.$CFG->sessioncookie;
f9903ed0 720
721 $days = 60;
722 $seconds = 60*60*24*$days;
723
b0ccd3fb 724 setCookie($cookiename, '', time() - 3600, '/');
725 setCookie($cookiename, rc4encrypt($thing), time()+$seconds, '/');
f9903ed0 726}
727
728
729function get_moodle_cookie() {
9fa49e22 730/// Gets a moodle cookie with an encrypted string
7185e073 731 global $CFG;
732
482b6e6e 733 $cookiename = 'MOODLEID_'.$CFG->sessioncookie;
7185e073 734
1079c8a8 735 if (empty($_COOKIE[$cookiename])) {
b0ccd3fb 736 return '';
1079c8a8 737 } else {
738 return rc4decrypt($_COOKIE[$cookiename]);
739 }
f9903ed0 740}
741
39a5a35d 742function is_internal_auth($auth='') {
ba7166c3 743/// Returns true if an internal authentication method is being used.
39a5a35d 744/// if method not specified then, global default is assumed
ba7166c3 745
746 global $CFG;
747
39a5a35d 748 $method = $CFG->auth;
749
750 if (!empty($auth)) {
751 $method = $auth;
752 }
753
b0ccd3fb 754 return ($method == 'email' || $method == 'none' || $method == 'manual');
ba7166c3 755}
f9903ed0 756
71f9abf9 757function create_user_record($username, $password, $auth='') {
d8ba183c 758/// Creates a bare-bones user record
e858f9da 759 global $REMOTE_ADDR, $CFG;
71f9abf9 760
1e22bc9c 761 //just in case check text case
762 $username = trim(moodle_strtolower($username));
71f9abf9 763
3271b70f 764 if (function_exists('auth_get_userinfo')) {
e858f9da 765 if ($newinfo = auth_get_userinfo($username)) {
34daec9b 766 foreach ($newinfo as $key => $value){
9f44d972 767 $newuser->$key = addslashes(stripslashes($value)); // Just in case
e858f9da 768 }
769 }
770 }
f9903ed0 771
85a1d4c9 772 if (!empty($newuser->email)) {
773 if (email_is_not_allowed($newuser->email)) {
774 unset($newuser->email);
775 }
776 }
777
71f9abf9 778 $newuser->auth = (empty($auth)) ? $CFG->auth : $auth;
faebaf0f 779 $newuser->username = $username;
780 $newuser->password = md5($password);
a0bac19d 781 $newuser->lang = $CFG->lang;
faebaf0f 782 $newuser->confirmed = 1;
59619427 783 $newuser->lastIP = getremoteaddr();
faebaf0f 784 $newuser->timemodified = time();
f9903ed0 785
b0ccd3fb 786 if (insert_record('user', $newuser)) {
787 $user = get_user_info_from_db('username', $newuser->username);
d35757eb 788 if($CFG->{'auth_'.$newuser->auth.'_forcechangepassword'}){
789 set_user_preference('auth_forcepasswordchange', 1, $user);
790 }
791 return $user;
faebaf0f 792 }
793 return false;
794}
795
d35757eb 796function update_user_record($username) {
797/// will update a local user record from an external source.
798 global $CFG;
799
800 if (function_exists('auth_get_userinfo')) {
801 $username = trim(moodle_strtolower($username)); /// just in case check text case
802
803 if ($newinfo = auth_get_userinfo($username)) {
804 foreach ($newinfo as $key => $value){
805 if (!empty($CFG->{'auth_user_' . $key. '_updatelocal'})) {
806 $value = addslashes(stripslashes($value)); // Just in case
807 set_field('user', $key, $value, 'username', $username);
808 }
809 }
810 }
811 }
b0ccd3fb 812 return get_user_info_from_db('username', $username);
d35757eb 813}
0609562b 814
815function guest_user() {
816 global $CFG;
817
b0ccd3fb 818 if ($newuser = get_record('user', 'username', 'guest')) {
0609562b 819 $newuser->loggedin = true;
820 $newuser->confirmed = 1;
821 $newuser->site = $CFG->wwwroot;
822 $newuser->lang = $CFG->lang;
823 }
824
825 return $newuser;
826}
827
faebaf0f 828function authenticate_user_login($username, $password) {
d8ba183c 829/// Given a username and password, this function looks them
9fa49e22 830/// up using the currently selected authentication mechanism,
d8ba183c 831/// and if the authentication is successful, it returns a
9fa49e22 832/// valid $user object from the 'user' table.
833///
834/// Uses auth_ functions from the currently active auth module
faebaf0f 835
836 global $CFG;
837
466558e3 838 $md5password = md5($password);
839
27286aeb 840 // First try to find the user in the database
466558e3 841
b0ccd3fb 842 $user = get_user_info_from_db('username', $username);
39a5a35d 843
27286aeb 844 // Sort out the authentication method we are using.
39a5a35d 845
27286aeb 846 if (empty($CFG->auth)) {
b0ccd3fb 847 $CFG->auth = 'manual'; // Default authentication module
27286aeb 848 }
39a5a35d 849
27286aeb 850 if (empty($user->auth)) { // For some reason it isn't set yet
851 if (isadmin($user->id) or isguest($user->id)) {
71f9abf9 852 $auth = 'manual'; // Always assume these guys are internal
27286aeb 853 } else {
71f9abf9 854 $auth = $CFG->auth; // Normal users default to site method
27286aeb 855 }
d35757eb 856 // update user record from external DB
857 if ($user->auth != 'manual' && $user->auth != 'email') {
858 $user = update_user_record($username);
859 }
71f9abf9 860 } else {
861 $auth = $user->auth;
27286aeb 862 }
8f0cd6ef 863
b0ccd3fb 864 if (!file_exists($CFG->dirroot .'/auth/'. $auth .'/lib.php')) {
865 $auth = 'manual'; // Can't find auth module, default to internal
466558e3 866 }
867
b0ccd3fb 868 require_once($CFG->dirroot .'/auth/'. $auth .'/lib.php');
faebaf0f 869
870 if (auth_user_login($username, $password)) { // Successful authentication
71f9abf9 871 if ($user) { // User already exists in database
872 if (empty($user->auth)) { // For some reason auth isn't set yet
873 set_field('user', 'auth', $auth, 'username', $username);
874 }
92710226 875 if ($md5password <> $user->password) { // Update local copy of password for reference
71f9abf9 876 set_field('user', 'password', $md5password, 'username', $username);
faebaf0f 877 }
d35757eb 878 // update user record from external DB
879 if ($user->auth != 'manual' && $user->auth != 'email'){
880 $user = update_user_record($username);
881 }
faebaf0f 882 } else {
71f9abf9 883 $user = create_user_record($username, $password, $auth);
faebaf0f 884 }
89b54325 885
e582b65e 886 if (function_exists('auth_iscreator')) { // Check if the user is a creator
887 if (auth_iscreator($username)) {
b0ccd3fb 888 if (! record_exists('user_coursecreators', 'userid', $user->id)) {
39a5a35d 889 $cdata->userid = $user->id;
b0ccd3fb 890 if (! insert_record('user_coursecreators', $cdata)) {
891 error('Cannot add user to course creators.');
39a5a35d 892 }
893 }
e582b65e 894 } else {
b0ccd3fb 895 if ( record_exists('user_coursecreators', 'userid', $user->id)) {
896 if (! delete_records('user_coursecreators', 'userid', $user->id)) {
897 error('Cannot remove user from course creators.');
39a5a35d 898 }
899 }
e582b65e 900 }
39a5a35d 901 }
e582b65e 902 return $user;
9d3c795c 903
e582b65e 904 } else {
b0ccd3fb 905 add_to_log(0, 'login', 'error', $_SERVER['HTTP_REFERER'], $username);
9d3c795c 906 $date = date('Y-m-d H:i:s');
b0ccd3fb 907 error_log($date ."\tfailed login\t". getremoteaddr() ."\t". $_SERVER['HTTP_USER_AGENT'] ."\t". $username);
e582b65e 908 return false;
909 }
f9903ed0 910}
911
b40bc478 912function enrol_student($userid, $courseid, $timestart=0, $timeend=0) {
631cf796 913/// Enrols (or re-enrols) a student in a given course
b40bc478 914
b0ccd3fb 915 if (!$course = get_record('course', 'id', $courseid)) { // Check course
3041b0f8 916 return false;
4d312bbe 917 }
b0ccd3fb 918 if (!$user = get_record('user', 'id', $userid)) { // Check user
631cf796 919 return false;
920 }
b0ccd3fb 921 if ($student = get_record('user_students', 'userid', $userid, 'course', $courseid)) {
631cf796 922 $student->timestart = $timestart;
923 $student->timeend = $timeend;
924 $student->time = time();
b0ccd3fb 925 return update_record('user_students', $student);
8f0cd6ef 926
631cf796 927 } else {
928 $student->userid = $userid;
929 $student->course = $courseid;
930 $student->timestart = $timestart;
931 $student->timeend = $timeend;
932 $student->time = time();
b0ccd3fb 933 return insert_record('user_students', $student);
631cf796 934 }
d7facad8 935}
936
9fa62805 937function unenrol_student($userid, $courseid=0) {
9fa49e22 938/// Unenrols a student from a given course
d7facad8 939
9fa62805 940 if ($courseid) {
9fa49e22 941 /// First delete any crucial stuff that might still send mail
b0ccd3fb 942 if ($forums = get_records('forum', 'course', $courseid)) {
9fa49e22 943 foreach ($forums as $forum) {
b0ccd3fb 944 delete_records('forum_subscriptions', 'forum', $forum->id, 'userid', $userid);
9fa62805 945 }
946 }
947 if ($groups = get_groups($courseid, $userid)) {
948 foreach ($groups as $group) {
b0ccd3fb 949 delete_records('groups_members', 'groupid', $group->id, 'userid', $userid);
bb09fb11 950 }
f9903ed0 951 }
b0ccd3fb 952 return delete_records('user_students', 'userid', $userid, 'course', $courseid);
9fa49e22 953
f9903ed0 954 } else {
b0ccd3fb 955 delete_records('forum_subscriptions', 'userid', $userid);
956 delete_records('groups_members', 'userid', $userid);
957 return delete_records('user_students', 'userid', $userid);
f9903ed0 958 }
959}
960
b0ccd3fb 961function add_teacher($userid, $courseid, $editall=1, $role='', $timestart=0, $timeend=0) {
3041b0f8 962/// Add a teacher to a given course
7b5944cd 963 global $CFG;
3041b0f8 964
61451a36 965 if ($teacher = get_record('user_teachers', 'userid', $userid, 'course', $courseid)) {
b40bc478 966 $newteacher = NULL;
967 $newteacher->id = $teacher->id;
968 $newteacher->editall = $editall;
969 if ($role) {
970 $newteacher->role = $role;
971 }
972 if ($timestart) {
973 $newteacher->timestart = $timestart;
3041b0f8 974 }
b40bc478 975 if ($timeend) {
976 $newteacher->timeend = $timeend;
977 }
978 return update_record('user_teachers', $newteacher);
3041b0f8 979 }
61451a36 980
b0ccd3fb 981 if (!record_exists('user', 'id', $userid)) {
61451a36 982 return false; // no such user
983 }
984
b0ccd3fb 985 if (!record_exists('course', 'id', $courseid)) {
61451a36 986 return false; // no such course
987 }
988
989 $teacher = NULL;
990 $teacher->userid = $userid;
991 $teacher->course = $courseid;
992 $teacher->editall = $editall;
993 $teacher->role = $role;
5a2dea02 994 $teacher->timemodified = time();
995 $newteacher->timestart = $timestart;
996 $newteacher->timeend = $timeend;
b0ccd3fb 997 if ($student = get_record('user_students', 'userid', $userid, 'course', $courseid)) {
5a2dea02 998 $teacher->timestart = $student->timestart;
999 $teacher->timeend = $student->timeend;
1000 $teacher->timeaccess = $student->timeaccess;
1001 }
61451a36 1002
b0ccd3fb 1003 if (record_exists('user_teachers', 'course', $courseid)) {
61451a36 1004 $teacher->authority = 2;
1005 } else {
1006 $teacher->authority = 1;
1007 }
b0ccd3fb 1008 delete_records('user_students', 'userid', $userid, 'course', $courseid); // Unenrol as student
8f0cd6ef 1009
709f0ec8 1010 /// Add forum subscriptions for new users
7b5944cd 1011 require_once('../mod/forum/lib.php');
1012 forum_add_user($userid, $courseid);
61451a36 1013
b0ccd3fb 1014 return insert_record('user_teachers', $teacher);
61451a36 1015
3041b0f8 1016}
1017
1018function remove_teacher($userid, $courseid=0) {
9fa49e22 1019/// Removes a teacher from a given course (or ALL courses)
1020/// Does not delete the user account
3041b0f8 1021 if ($courseid) {
9fa49e22 1022 /// First delete any crucial stuff that might still send mail
b0ccd3fb 1023 if ($forums = get_records('forum', 'course', $courseid)) {
9fa49e22 1024 foreach ($forums as $forum) {
b0ccd3fb 1025 delete_records('forum_subscriptions', 'forum', $forum->id, 'userid', $userid);
9fa49e22 1026 }
1027 }
b02193e6 1028
1029 /// Next if the teacher is not registered as a student, but is
1030 /// a member of a group, remove them from the group.
1031 if (!isstudent($courseid, $userid)) {
1032 if ($groups = get_groups($courseid, $userid)) {
1033 foreach ($groups as $group) {
b0ccd3fb 1034 delete_records('groups_members', 'groupid', $group->id, 'userid', $userid);
b02193e6 1035 }
1036 }
1037 }
1038
b0ccd3fb 1039 return delete_records('user_teachers', 'userid', $userid, 'course', $courseid);
57507290 1040 } else {
b0ccd3fb 1041 delete_records('forum_subscriptions', 'userid', $userid);
1042 return delete_records('user_teachers', 'userid', $userid);
57507290 1043 }
f9903ed0 1044}
1045
3041b0f8 1046
1047function add_creator($userid) {
1048/// Add a creator to the site
1049
b0ccd3fb 1050 if (!record_exists('user_admins', 'userid', $userid)) {
1051 if (record_exists('user', 'id', $userid)) {
3041b0f8 1052 $creator->userid = $userid;
b0ccd3fb 1053 return insert_record('user_coursecreators', $creator);
3041b0f8 1054 }
1055 return false;
1056 }
1057 return true;
1058}
1059
1060function remove_creator($userid) {
1061/// Removes a creator from a site
1062 global $db;
1063
b0ccd3fb 1064 return delete_records('user_coursecreators', 'userid', $userid);
3041b0f8 1065}
1066
1067function add_admin($userid) {
1068/// Add an admin to the site
1069
b0ccd3fb 1070 if (!record_exists('user_admins', 'userid', $userid)) {
1071 if (record_exists('user', 'id', $userid)) {
3041b0f8 1072 $admin->userid = $userid;
8f0cd6ef 1073
f950af3c 1074 // any admin is also a teacher on the site course
222ac91b 1075 if (!record_exists('user_teachers', 'course', SITEID, 'userid', $userid)) {
1076 if (!add_teacher($userid, SITEID)) {
f950af3c 1077 return false;
1078 }
1079 }
8f0cd6ef 1080
b0ccd3fb 1081 return insert_record('user_admins', $admin);
3041b0f8 1082 }
1083 return false;
1084 }
1085 return true;
1086}
1087
1088function remove_admin($userid) {
9fa49e22 1089/// Removes an admin from a site
1090 global $db;
f9903ed0 1091
f950af3c 1092 // remove also from the list of site teachers
222ac91b 1093 remove_teacher($userid, SITEID);
f950af3c 1094
b0ccd3fb 1095 return delete_records('user_admins', 'userid', $userid);
f9903ed0 1096}
1097
f9903ed0 1098
07aeb7b0 1099function remove_course_contents($courseid, $showfeedback=true) {
1100/// Clear a course out completely, deleting all content
1101/// but don't delete the course itself
1102
ee23f384 1103 global $CFG, $THEME, $USER, $SESSION;
07aeb7b0 1104
1105 $result = true;
1106
b0ccd3fb 1107 if (! $course = get_record('course', 'id', $courseid)) {
1108 error('Course ID was incorrect (can\'t find it)');
07aeb7b0 1109 }
1110
b0ccd3fb 1111 $strdeleted = get_string('deleted');
07aeb7b0 1112
1113 // First delete every instance of every module
d8ba183c 1114
b0ccd3fb 1115 if ($allmods = get_records('modules') ) {
07aeb7b0 1116 foreach ($allmods as $mod) {
1117 $modname = $mod->name;
b0ccd3fb 1118 $modfile = $CFG->dirroot .'/mod/'. $modname .'/lib.php';
1119 $moddelete = $modname .'_delete_instance'; // Delete everything connected to an instance
1120 $moddeletecourse = $modname .'_delete_course'; // Delete other stray stuff (uncommon)
07aeb7b0 1121 $count=0;
1122 if (file_exists($modfile)) {
1123 include_once($modfile);
1124 if (function_exists($moddelete)) {
b0ccd3fb 1125 if ($instances = get_records($modname, 'course', $course->id)) {
07aeb7b0 1126 foreach ($instances as $instance) {
1127 if ($moddelete($instance->id)) {
1128 $count++;
1129 } else {
b0ccd3fb 1130 notify('Could not delete '. $modname .' instance '. $instance->id .' ('. $instance->name .')');
07aeb7b0 1131 $result = false;
1132 }
1133 }
1134 }
1135 } else {
b0ccd3fb 1136 notify('Function '. $moddelete() .'doesn\'t exist!');
07aeb7b0 1137 $result = false;
1138 }
1139
ca952b03 1140 if (function_exists($moddeletecourse)) {
1141 $moddeletecourse($course);
1142 }
07aeb7b0 1143 }
1144 if ($showfeedback) {
b0ccd3fb 1145 notify($strdeleted .' '. $count .' x '. $modname);
07aeb7b0 1146 }
1147 }
1148 } else {
b0ccd3fb 1149 error('No modules are installed!');
07aeb7b0 1150 }
1151
1152 // Delete any user stuff
1153
b0ccd3fb 1154 if (delete_records('user_students', 'course', $course->id)) {
07aeb7b0 1155 if ($showfeedback) {
b0ccd3fb 1156 notify($strdeleted .' user_students');
07aeb7b0 1157 }
1158 } else {
1159 $result = false;
1160 }
1161
b0ccd3fb 1162 if (delete_records('user_teachers', 'course', $course->id)) {
07aeb7b0 1163 if ($showfeedback) {
b0ccd3fb 1164 notify($strdeleted .' user_teachers');
07aeb7b0 1165 }
1166 } else {
1167 $result = false;
1168 }
1169
082e3ebc 1170 // Delete any groups
1171
b0ccd3fb 1172 if ($groups = get_records('groups', 'courseid', $course->id)) {
082e3ebc 1173 foreach ($groups as $group) {
b0ccd3fb 1174 if (delete_records('groups_members', 'groupid', $group->id)) {
082e3ebc 1175 if ($showfeedback) {
b0ccd3fb 1176 notify($strdeleted .' groups_members');
082e3ebc 1177 }
1178 } else {
1179 $result = false;
1180 }
b0ccd3fb 1181 if (delete_records('groups', 'id', $group->id)) {
082e3ebc 1182 if ($showfeedback) {
b0ccd3fb 1183 notify($strdeleted .' groups');
082e3ebc 1184 }
1185 } else {
1186 $result = false;
1187 }
1188 }
1189 }
1190
1191 // Delete events
1192
b0ccd3fb 1193 if (delete_records('event', 'courseid', $course->id)) {
082e3ebc 1194 if ($showfeedback) {
b0ccd3fb 1195 notify($strdeleted .' event');
082e3ebc 1196 }
1197 } else {
1198 $result = false;
1199 }
1200
07aeb7b0 1201 // Delete logs
1202
b0ccd3fb 1203 if (delete_records('log', 'course', $course->id)) {
07aeb7b0 1204 if ($showfeedback) {
b0ccd3fb 1205 notify($strdeleted .' log');
07aeb7b0 1206 }
1207 } else {
1208 $result = false;
1209 }
1210
1211 // Delete any course stuff
1212
b0ccd3fb 1213 if (delete_records('course_sections', 'course', $course->id)) {
07aeb7b0 1214 if ($showfeedback) {
b0ccd3fb 1215 notify($strdeleted .' course_sections');
07aeb7b0 1216 }
1217 } else {
1218 $result = false;
1219 }
1220
b0ccd3fb 1221 if (delete_records('course_modules', 'course', $course->id)) {
07aeb7b0 1222 if ($showfeedback) {
b0ccd3fb 1223 notify($strdeleted .' course_modules');
07aeb7b0 1224 }
1225 } else {
1226 $result = false;
1227 }
1228
1229 return $result;
1230
1231}
1232
3831de52 1233function remove_course_userdata($courseid, $showfeedback=true,
1234 $removestudents=true, $removeteachers=false, $removegroups=true,
1235 $removeevents=true, $removelogs=false) {
8f0cd6ef 1236/// This function will empty a course of USER data as much as
1237/// possible. It will retain the activities and the structure
3831de52 1238/// of the course.
1239
1240 global $CFG, $THEME, $USER, $SESSION;
1241
1242 $result = true;
1243
b0ccd3fb 1244 if (! $course = get_record('course', 'id', $courseid)) {
1245 error('Course ID was incorrect (can\'t find it)');
3831de52 1246 }
1247
b0ccd3fb 1248 $strdeleted = get_string('deleted');
3831de52 1249
1250 // Look in every instance of every module for data to delete
1251
b0ccd3fb 1252 if ($allmods = get_records('modules') ) {
3831de52 1253 foreach ($allmods as $mod) {
1254 $modname = $mod->name;
b0ccd3fb 1255 $modfile = $CFG->dirroot .'/mod/'. $modname .'/lib.php';
1256 $moddeleteuserdata = $modname .'_delete_userdata'; // Function to delete user data
3831de52 1257 $count=0;
1258 if (file_exists($modfile)) {
1259 @include_once($modfile);
1260 if (function_exists($moddeleteuserdata)) {
1261 $moddeleteuserdata($course, $showfeedback);
1262 }
1263 }
1264 }
1265 } else {
b0ccd3fb 1266 error('No modules are installed!');
3831de52 1267 }
1268
1269 // Delete other stuff
1270
1271 if ($removestudents) {
1272 /// Delete student enrolments
b0ccd3fb 1273 if (delete_records('user_students', 'course', $course->id)) {
3831de52 1274 if ($showfeedback) {
b0ccd3fb 1275 notify($strdeleted .' user_students');
3831de52 1276 }
1277 } else {
1278 $result = false;
1279 }
1280 /// Delete group members (but keep the groups)
b0ccd3fb 1281 if ($groups = get_records('groups', 'courseid', $course->id)) {
3831de52 1282 foreach ($groups as $group) {
b0ccd3fb 1283 if (delete_records('groups_members', 'groupid', $group->id)) {
3831de52 1284 if ($showfeedback) {
b0ccd3fb 1285 notify($strdeleted .' groups_members');
3831de52 1286 }
1287 } else {
1288 $result = false;
1289 }
1290 }
1291 }
1292 }
1293
1294 if ($removeteachers) {
b0ccd3fb 1295 if (delete_records('user_teachers', 'course', $course->id)) {
3831de52 1296 if ($showfeedback) {
b0ccd3fb 1297 notify($strdeleted .' user_teachers');
3831de52 1298 }
1299 } else {
1300 $result = false;
1301 }
1302 }
1303
1304 if ($removegroups) {
b0ccd3fb 1305 if ($groups = get_records('groups', 'courseid', $course->id)) {
3831de52 1306 foreach ($groups as $group) {
b0ccd3fb 1307 if (delete_records('groups', 'id', $group->id)) {
3831de52 1308 if ($showfeedback) {
b0ccd3fb 1309 notify($strdeleted .' groups');
3831de52 1310 }
1311 } else {
1312 $result = false;
1313 }
1314 }
1315 }
1316 }
1317
1318 if ($removeevents) {
b0ccd3fb 1319 if (delete_records('event', 'courseid', $course->id)) {
3831de52 1320 if ($showfeedback) {
b0ccd3fb 1321 notify($strdeleted .' event');
3831de52 1322 }
1323 } else {
1324 $result = false;
1325 }
1326 }
1327
1328 if ($removelogs) {
b0ccd3fb 1329 if (delete_records('log', 'course', $course->id)) {
3831de52 1330 if ($showfeedback) {
b0ccd3fb 1331 notify($strdeleted .' log');
3831de52 1332 }
1333 } else {
1334 $result = false;
1335 }
1336 }
1337
1338 return $result;
1339
1340}
1341
1342
f9903ed0 1343
f374fb10 1344/// GROUPS /////////////////////////////////////////////////////////
d8ba183c 1345
f374fb10 1346
1347/**
1348* Returns a boolean: is the user a member of the given group?
d8ba183c 1349*
dcd338ff 1350* @param type description
f374fb10 1351*/
1352function ismember($groupid, $userid=0) {
1353 global $USER;
1354
8a2c9076 1355 if (!$groupid) { // No point doing further checks
1356 return false;
1357 }
1358
f374fb10 1359 if (!$userid) {
0d67c514 1360 if (empty($USER->groupmember)) {
1361 return false;
1362 }
1363 foreach ($USER->groupmember as $courseid => $mgroupid) {
1364 if ($mgroupid == $groupid) {
1365 return true;
1366 }
1367 }
1368 return false;
f374fb10 1369 }
1370
b0ccd3fb 1371 return record_exists('groups_members', 'groupid', $groupid, 'userid', $userid);
f374fb10 1372}
1373
0d67c514 1374/**
1375* Returns the group ID of the current user in the given course
d8ba183c 1376*
dcd338ff 1377* @param type description
0d67c514 1378*/
1379function mygroupid($courseid) {
1380 global $USER;
1381
1382 if (empty($USER->groupmember[$courseid])) {
1383 return 0;
1384 } else {
1385 return $USER->groupmember[$courseid];
1386 }
1387}
1388
f374fb10 1389/**
d8ba183c 1390* For a given course, and possibly course module, determine
f374fb10 1391* what the current default groupmode is:
1392* NOGROUPS, SEPARATEGROUPS or VISIBLEGROUPS
d8ba183c 1393*
dcd338ff 1394* @param type description
f374fb10 1395*/
1396function groupmode($course, $cm=null) {
1397
1398 if ($cm and !$course->groupmodeforce) {
1399 return $cm->groupmode;
1400 }
1401 return $course->groupmode;
1402}
1403
1404
1405/**
1406* Sets the current group in the session variable
d8ba183c 1407*
dcd338ff 1408* @param type description
f374fb10 1409*/
1410function set_current_group($courseid, $groupid) {
1411 global $SESSION;
1412
1413 return $SESSION->currentgroup[$courseid] = $groupid;
1414}
1415
1416
1417/**
1418* Gets the current group for the current user as an id or an object
d8ba183c 1419*
dcd338ff 1420* @param type description
f374fb10 1421*/
1422function get_current_group($courseid, $full=false) {
1423 global $SESSION, $USER;
1424
ce04df6b 1425 if (!isset($SESSION->currentgroup[$courseid])) {
f374fb10 1426 if (empty($USER->groupmember[$courseid])) {
8a2c9076 1427 return 0;
f374fb10 1428 } else {
1429 $SESSION->currentgroup[$courseid] = $USER->groupmember[$courseid];
1430 }
1431 }
1432
1433 if ($full) {
0da33e07 1434 return get_record('groups', 'id', $SESSION->currentgroup[$courseid]);
f374fb10 1435 } else {
1436 return $SESSION->currentgroup[$courseid];
1437 }
1438}
1439
0d67c514 1440/**
1441* A combination function to make it easier for modules
1442* to set up groups.
1443*
1444* It will use a given "groupid" parameter and try to use
1445* that to reset the current group for the user.
1446*
dcd338ff 1447* @param type description
0d67c514 1448*/
eb6147a8 1449function get_and_set_current_group($course, $groupmode, $groupid=-1) {
0d67c514 1450
1451 if (!$groupmode) { // Groups don't even apply
d8ba183c 1452 return false;
0d67c514 1453 }
1454
1455 $currentgroupid = get_current_group($course->id);
1456
eb6147a8 1457 if ($groupid < 0) { // No change was specified
1458 return $currentgroupid;
1459 }
1460
1461 if ($groupid) { // Try to change the current group to this groupid
0d67c514 1462 if ($group = get_record('groups', 'id', $groupid, 'courseid', $course->id)) { // Exists
1463 if (isteacheredit($course->id)) { // Sets current default group
1464 $currentgroupid = set_current_group($course->id, $group->id);
1465
1466 } else if ($groupmode == VISIBLEGROUPS) { // All groups are visible
1467 $currentgroupid = $group->id;
1468 }
1469 }
eb6147a8 1470 } else { // When groupid = 0 it means show ALL groups
1471 if (isteacheredit($course->id)) { // Sets current default group
1472 $currentgroupid = set_current_group($course->id, 0);
1473
1474 } else if ($groupmode == VISIBLEGROUPS) { // All groups are visible
1475 $currentgroupid = 0;
1476 }
0d67c514 1477 }
1478
1479 return $currentgroupid;
1480}
1481
1482
c3cbfe7f 1483/**
1484* A big combination function to make it easier for modules
1485* to set up groups.
1486*
1487* Terminates if the current user shouldn't be looking at this group
1488* Otherwise returns the current group if there is one
1489* Otherwise returns false if groups aren't relevant
1490*
dcd338ff 1491* @param type description
c3cbfe7f 1492*/
1493function setup_and_print_groups($course, $groupmode, $urlroot) {
1494
eb6147a8 1495 if (isset($_GET['group'])) {
1496 $changegroup = $_GET['group']; /// 0 or higher
1497 } else {
1498 $changegroup = -1; /// This means no group change was specified
1499 }
1500
1501 $currentgroup = get_and_set_current_group($course, $groupmode, $changegroup);
c3cbfe7f 1502
eb6147a8 1503 if ($currentgroup === false) {
c3cbfe7f 1504 return false;
1505 }
1506
4b6d8dd5 1507 if ($groupmode == SEPARATEGROUPS and !isteacheredit($course->id) and !$currentgroup) {
1508 print_heading(get_string('notingroup'));
c3cbfe7f 1509 print_footer($course);
1510 exit;
1511 }
1512
1513 if ($groupmode == VISIBLEGROUPS or ($groupmode and isteacheredit($course->id))) {
b0ccd3fb 1514 if ($groups = get_records_menu('groups', 'courseid', $course->id, 'name ASC', 'id,name')) {
eb6147a8 1515 echo '<div align="center">';
c3cbfe7f 1516 print_group_menu($groups, $groupmode, $currentgroup, $urlroot);
eb6147a8 1517 echo '</div>';
c3cbfe7f 1518 }
1519 }
1520
1521 return $currentgroup;
1522}
0d67c514 1523
f374fb10 1524
1525
f9903ed0 1526/// CORRESPONDENCE ////////////////////////////////////////////////
1527
b0ccd3fb 1528function email_to_user($user, $from, $subject, $messagetext, $messagehtml='', $attachment='', $attachname='', $usetrueaddress=true) {
9fa49e22 1529/// user - a user record as an object
1530/// from - a user record as an object
1531/// subject - plain text subject line of the email
1532/// messagetext - plain text version of the message
1533/// messagehtml - complete html version of the message (optional)
1534/// attachment - a file on the filesystem, relative to $CFG->dataroot
1535/// attachname - the name of the file (extension indicates MIME)
a402bdcb 1536/// usetrueaddress - determines whether $from email address should be sent out.
6e506bf9 1537/// Will be overruled by user profile setting for maildisplay
579dcca4 1538///
1539/// Returns "true" if mail was sent OK, "emailstop" if email was blocked by user
1540/// and "false" if there was another sort of error.
f9903ed0 1541
4216daa6 1542 global $CFG, $_SERVER;
f9903ed0 1543
0cc6fa6a 1544 global $course; // This is a bit of an ugly hack to be gotten rid of later
1545 if (!empty($course->lang)) { // Course language is defined
1546 $CFG->courselang = $course->lang;
1547 }
1548
b0ccd3fb 1549 include_once($CFG->libdir .'/phpmailer/class.phpmailer.php');
f9903ed0 1550
cadb96f2 1551 if (empty($user)) {
1552 return false;
1553 }
1554
1555 if (!empty($user->emailstop)) {
579dcca4 1556 return 'emailstop';
f9903ed0 1557 }
d8ba183c 1558
f9903ed0 1559 $mail = new phpmailer;
1560
b0ccd3fb 1561 $mail->Version = 'Moodle '. $CFG->version; // mailer version
1562 $mail->PluginDir = $CFG->libdir .'/phpmailer/'; // plugin directory (eg smtp plugin)
562bbe90 1563
98c4eae3 1564
b0ccd3fb 1565 if (current_language() != 'en') {
1566 $mail->CharSet = get_string('thischarset');
98c4eae3 1567 }
1568
b0ccd3fb 1569 if ($CFG->smtphosts == 'qmail') {
62740736 1570 $mail->IsQmail(); // use Qmail system
1571
1572 } else if (empty($CFG->smtphosts)) {
1573 $mail->IsMail(); // use PHP mail() = sendmail
1574
1575 } else {
1e411ffc 1576 $mail->IsSMTP(); // use SMTP directly
57ef3480 1577 if ($CFG->debug > 7) {
b0ccd3fb 1578 echo '<pre>' . "\n";
57ef3480 1579 $mail->SMTPDebug = true;
1580 }
b0ccd3fb 1581 $mail->Host = $CFG->smtphosts; // specify main and backup servers
9f58537a 1582
1583 if ($CFG->smtpuser) { // Use SMTP authentication
1584 $mail->SMTPAuth = true;
1585 $mail->Username = $CFG->smtpuser;
1586 $mail->Password = $CFG->smtppass;
1587 }
7f86ce17 1588 }
f9903ed0 1589
2b97bd71 1590 $adminuser = get_admin();
1591
b0ccd3fb 1592 $mail->Sender = $adminuser->email;
2b97bd71 1593
a402bdcb 1594 if (is_string($from)) { // So we can pass whatever we want if there is need
1595 $mail->From = $CFG->noreplyaddress;
0d8a590a 1596 $mail->FromName = $from;
a402bdcb 1597 } else if ($usetrueaddress and $from->maildisplay) {
b0ccd3fb 1598 $mail->From = $from->email;
6e506bf9 1599 $mail->FromName = fullname($from);
1600 } else {
b0ccd3fb 1601 $mail->From = $CFG->noreplyaddress;
0d8a590a 1602 $mail->FromName = fullname($from);
6e506bf9 1603 }
136dabd8 1604 $mail->Subject = stripslashes($subject);
f9903ed0 1605
b0ccd3fb 1606 $mail->AddAddress($user->email, fullname($user) );
f9903ed0 1607
58d24720 1608 $mail->WordWrap = 79; // set word wrap
f9903ed0 1609
857b798b 1610 if (!empty($from->customheaders)) { // Add custom headers
1611 if (is_array($from->customheaders)) {
1612 foreach ($from->customheaders as $customheader) {
1613 $mail->AddCustomHeader($customheader);
1614 }
1615 } else {
1616 $mail->AddCustomHeader($from->customheaders);
1617 }
b68dca19 1618 }
8f0cd6ef 1619
136dabd8 1620 if ($messagehtml) {
1621 $mail->IsHTML(true);
b0ccd3fb 1622 $mail->Encoding = 'quoted-printable'; // Encoding to use
136dabd8 1623 $mail->Body = $messagehtml;
78681899 1624 $mail->AltBody = "\n$messagetext\n";
136dabd8 1625 } else {
1626 $mail->IsHTML(false);
78681899 1627 $mail->Body = "\n$messagetext\n";
f9903ed0 1628 }
1629
136dabd8 1630 if ($attachment && $attachname) {
1631 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
b0ccd3fb 1632 $mail->AddAddress($adminuser->email, fullname($adminuser) );
1633 $mail->AddStringAttachment('Error in attachment. User attempted to attach a filename with a unsafe name.', 'error.txt', '8bit', 'text/plain');
136dabd8 1634 } else {
b0ccd3fb 1635 include_once($CFG->dirroot .'/files/mimetypes.php');
1636 $mimetype = mimeinfo('type', $attachname);
1637 $mail->AddAttachment($CFG->dataroot .'/'. $attachment, $attachname, 'base64', $mimetype);
136dabd8 1638 }
f9903ed0 1639 }
1640
136dabd8 1641 if ($mail->Send()) {
1642 return true;
1643 } else {
b0ccd3fb 1644 mtrace('ERROR: '. $mail->ErrorInfo);
1645 add_to_log(SITEID, 'library', 'mailer', $_SERVER['REQUEST_URI'], 'ERROR: '. $mail->ErrorInfo);
f9903ed0 1646 return false;
1647 }
f9903ed0 1648}
1649
1d881d92 1650function reset_password_and_mail($user) {
1651
1652 global $CFG;
1653
1654 $site = get_site();
1655 $from = get_admin();
1656
1657 $newpassword = generate_password();
1658
b0ccd3fb 1659 if (! set_field('user', 'password', md5($newpassword), 'id', $user->id) ) {
1660 error('Could not set user password!');
1d881d92 1661 }
1662
1663 $a->firstname = $user->firstname;
1664 $a->sitename = $site->fullname;
1665 $a->username = $user->username;
1666 $a->newpassword = $newpassword;
b0ccd3fb 1667 $a->link = $CFG->wwwroot .'/login/change_password.php';
1668 $a->signoff = fullname($from, true).' ('. $from->email .')';
1d881d92 1669
b0ccd3fb 1670 $message = get_string('newpasswordtext', '', $a);
1d881d92 1671
b0ccd3fb 1672 $subject = $site->fullname .': '. get_string('changedpassword');
1d881d92 1673
1674 return email_to_user($user, $from, $subject, $message);
1675
1676}
1677
1678function send_confirmation_email($user) {
1679
1680 global $CFG;
1681
1682 $site = get_site();
1683 $from = get_admin();
1684
1685 $data->firstname = $user->firstname;
1686 $data->sitename = $site->fullname;
b0ccd3fb 1687 $data->link = $CFG->wwwroot .'/login/confirm.php?p='. $user->secret .'&amp;s='. $user->username;
1688 $data->admin = fullname($from) .' ('. $from->email .')';
1d881d92 1689
b0ccd3fb 1690 $message = get_string('emailconfirmation', '', $data);
1691 $subject = get_string('emailconfirmationsubject', '', $site->fullname);
1d881d92 1692
58d24720 1693 $messagehtml = text_to_html($message, false, false, true);
1694
1695 return email_to_user($user, $from, $subject, $message, $messagehtml);
1d881d92 1696
1697}
1698
eb347b6b 1699function send_password_change_confirmation_email($user) {
1700
1701 global $CFG;
1702
1703 $site = get_site();
1704 $from = get_admin();
1705
1706 $data->firstname = $user->firstname;
1707 $data->sitename = $site->fullname;
b0ccd3fb 1708 $data->link = $CFG->wwwroot .'/login/forgot_password.php?p='. $user->secret .'&amp;s='. $user->username;
1709 $data->admin = fullname($from).' ('. $from->email .')';
eb347b6b 1710
b0ccd3fb 1711 $message = get_string('emailpasswordconfirmation', '', $data);
1712 $subject = get_string('emailpasswordconfirmationsubject', '', $site->fullname);
eb347b6b 1713
1714 return email_to_user($user, $from, $subject, $message);
1715
1716}
1717
1718
85a1d4c9 1719function email_is_not_allowed($email) {
8f0cd6ef 1720/// Check that an email is allowed. It returns an error message if there
85a1d4c9 1721/// was a problem.
1722
1723 global $CFG;
1724
1725 if (!empty($CFG->allowemailaddresses)) {
1726 $allowed = explode(' ', $CFG->allowemailaddresses);
1727 foreach ($allowed as $allowedpattern) {
1728 $allowedpattern = trim($allowedpattern);
1729 if (!$allowedpattern) {
1730 continue;
1731 }
1732 if (strpos($email, $allowedpattern) !== false) { // Match!
1733 return false;
1734 }
1735 }
b0ccd3fb 1736 return get_string('emailonlyallowed', '', $CFG->allowemailaddresses);
85a1d4c9 1737
1738 } else if (!empty($CFG->denyemailaddresses)) {
1739 $denied = explode(' ', $CFG->denyemailaddresses);
1740 foreach ($denied as $deniedpattern) {
1741 $deniedpattern = trim($deniedpattern);
1742 if (!$deniedpattern) {
1743 continue;
1744 }
1745 if (strpos($email, $deniedpattern) !== false) { // Match!
b0ccd3fb 1746 return get_string('emailnotallowed', '', $CFG->denyemailaddresses);
85a1d4c9 1747 }
1748 }
1749 }
1750
1751 return false;
1752}
1d881d92 1753
136dabd8 1754
f9903ed0 1755/// FILE HANDLING /////////////////////////////////////////////
1756
1e03c552 1757
66f9a82c 1758function make_upload_directory($directory, $shownotices=true) {
9fa49e22 1759/// $directory = a string of directory names under $CFG->dataroot
1760/// eg stuff/assignment/1
1761/// Returns full directory if successful, false if not
6b174680 1762
1763 global $CFG;
1764
1765 $currdir = $CFG->dataroot;
fe287429 1766
2e6d4273 1767 umask(0000);
1768
6b174680 1769 if (!file_exists($currdir)) {
2e6d4273 1770 if (! mkdir($currdir, $CFG->directorypermissions)) {
66f9a82c 1771 if ($shownotices) {
b0ccd3fb 1772 notify('ERROR: You need to create the directory '. $currdir .' with web server write access');
66f9a82c 1773 }
6b174680 1774 return false;
1775 }
1776 }
1777
b0ccd3fb 1778 $dirarray = explode('/', $directory);
6b174680 1779
1780 foreach ($dirarray as $dir) {
b0ccd3fb 1781 $currdir = $currdir .'/'. $dir;
6b174680 1782 if (! file_exists($currdir)) {
2e6d4273 1783 if (! mkdir($currdir, $CFG->directorypermissions)) {
66f9a82c 1784 if ($shownotices) {
b0ccd3fb 1785 notify('ERROR: Could not find or create a directory ('. $currdir .')');
66f9a82c 1786 }
6b174680 1787 return false;
1788 }
feffa4e6 1789 @chmod($currdir, $CFG->directorypermissions); // Just in case mkdir didn't do it
6b174680 1790 }
1791 }
1792
1793 return $currdir;
1794}
1e03c552 1795
1796
ca4f8eb8 1797function make_mod_upload_directory($courseid) {
9fa49e22 1798/// Makes an upload directory for a particular module
ca4f8eb8 1799 global $CFG;
1800
b0ccd3fb 1801 if (! $moddata = make_upload_directory($courseid .'/'. $CFG->moddata)) {
ca4f8eb8 1802 return false;
1803 }
1804
b0ccd3fb 1805 $strreadme = get_string('readme');
ca4f8eb8 1806
b0ccd3fb 1807 if (file_exists($CFG->dirroot .'/lang/'. $CFG->lang .'/docs/module_files.txt')) {
1808 copy($CFG->dirroot .'/lang/'. $CFG->lang .'/docs/module_files.txt', $moddata .'/'. $strreadme .'.txt');
ca4f8eb8 1809 } else {
b0ccd3fb 1810 copy($CFG->dirroot .'/lang/en/docs/module_files.txt', $moddata .'/'. $strreadme .'.txt');
ca4f8eb8 1811 }
1812 return $moddata;
1813}
1814
6b174680 1815
44e2d2bb 1816function valid_uploaded_file($newfile) {
9fa49e22 1817/// Returns current name of file on disk if true
9c9f7d77 1818 if (empty($newfile)) {
b0ccd3fb 1819 return '';
9c9f7d77 1820 }
44e2d2bb 1821 if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
1822 return $newfile['tmp_name'];
1823 } else {
b0ccd3fb 1824 return '';
44e2d2bb 1825 }
1826}
1827
4909e176 1828function get_max_upload_file_size($sitebytes=0, $coursebytes=0, $modulebytes=0) {
9fa49e22 1829/// Returns the maximum size for uploading files
316ebf78 1830/// There are seven possible upload limits:
4909e176 1831///
1832/// 1) in Apache using LimitRequestBody (no way of checking or changing this)
1833/// 2) in php.ini for 'upload_max_filesize' (can not be changed inside PHP)
1834/// 3) in .htaccess for 'upload_max_filesize' (can not be changed inside PHP)
316ebf78 1835/// 4) in php.ini for 'post_max_size' (can not be changed inside PHP)
1836/// 5) by the Moodle admin in $CFG->maxbytes
1837/// 6) by the teacher in the current course $course->maxbytes
1838/// 7) by the teacher for the current module, eg $assignment->maxbytes
4909e176 1839///
1840/// These last two are passed to this function as arguments (in bytes).
1841/// Anything defined as 0 is ignored.
1842/// The smallest of all the non-zero numbers is returned.
1843
b0ccd3fb 1844 if (! $filesize = ini_get('upload_max_filesize')) {
1845 $filesize = '5M';
44e2d2bb 1846 }
4909e176 1847 $minimumsize = get_real_size($filesize);
1848
b0ccd3fb 1849 if ($postsize = ini_get('post_max_size')) {
316ebf78 1850 $postsize = get_real_size($postsize);
1851 if ($postsize < $minimumsize) {
1852 $minimumsize = $postsize;
1853 }
1854 }
1855
4909e176 1856 if ($sitebytes and $sitebytes < $minimumsize) {
1857 $minimumsize = $sitebytes;
1858 }
1859
1860 if ($coursebytes and $coursebytes < $minimumsize) {
1861 $minimumsize = $coursebytes;
1862 }
1863
1864 if ($modulebytes and $modulebytes < $minimumsize) {
1865 $minimumsize = $modulebytes;
1866 }
1867
1868 return $minimumsize;
1869}
1870
1871function get_max_upload_sizes($sitebytes=0, $coursebytes=0, $modulebytes=0) {
d8ba183c 1872/// Related to the above function - this function returns an
1873/// array of possible sizes in an array, translated to the
4909e176 1874/// local language.
1875
1876 if (!$maxsize = get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes)) {
1877 return array();
1878 }
1879
1880 $filesize[$maxsize] = display_size($maxsize);
1881
d8ba183c 1882 $sizelist = array(10240, 51200, 102400, 512000, 1048576, 2097152,
4909e176 1883 5242880, 10485760, 20971520, 52428800, 104857600);
1884
1885 foreach ($sizelist as $sizebytes) {
1886 if ($sizebytes < $maxsize) {
1887 $filesize[$sizebytes] = display_size($sizebytes);
1888 }
1889 }
1890
1891 krsort($filesize, SORT_NUMERIC);
1892
1893 return $filesize;
44e2d2bb 1894}
1895
ebd52396 1896
1897function print_file_upload_error($filearray = '', $returnerror = false) {
1898/// If there has been an error uploading a file, print the appropriate error message
1899/// Numerical constants used as constant definitions not added until PHP version 4.2.0
1900///
1901/// filearray is a 1-dimensional sub-array of the $_FILES array
1902/// eg $filearray = $_FILES['userfile1']
1903/// If left empty then the first element of the $_FILES array will be used
1904
1905 if ($filearray == '' or !isset($filearray['error'])) {
1906
1907 if (empty($_FILES)) return false;
1908
1909 $files = $_FILES; /// so we don't mess up the _FILES array for subsequent code
1910 $filearray = array_shift($files); /// use first element of array
1911 }
1912
1913 switch ($filearray['error']) {
1914
1915 case 0: // UPLOAD_ERR_OK
1916 if ($filearray['size'] > 0) {
1917 $errmessage = get_string('uploadproblem', $filearray['name']);
1918 } else {
1919 $errmessage = get_string('uploadnofilefound'); /// probably a dud file name
1920 }
1921 break;
1922
1923 case 1: // UPLOAD_ERR_INI_SIZE
1924 $errmessage = get_string('uploadserverlimit');
1925 break;
1926
1927 case 2: // UPLOAD_ERR_FORM_SIZE
1928 $errmessage = get_string('uploadformlimit');
1929 break;
1930
1931 case 3: // UPLOAD_ERR_PARTIAL
1932 $errmessage = get_string('uploadpartialfile');
1933 break;
1934
1935 case 4: // UPLOAD_ERR_NO_FILE
1936 $errmessage = get_string('uploadnofilefound');
1937 break;
1938
1939 default:
1940 $errmessage = get_string('uploadproblem', $filearray['name']);
1941 }
1942
1943 if ($returnerror) {
1944 return $errmessage;
1945 } else {
1946 notify($errmessage);
1947 return true;
1948 }
1949
1950}
1951
1952
b0ccd3fb 1953function get_directory_list($rootdir, $excludefile='', $descend=true, $getdirs=false, $getfiles=true) {
d8ba183c 1954/// Returns an array with all the filenames in
9fa49e22 1955/// all subdirectories, relative to the given rootdir.
1956/// If excludefile is defined, then that file/directory is ignored
16a5602c 1957/// If getdirs is true, then (sub)directories are included in the output
1958/// If getfiles is true, then files are included in the output
1959/// (at least one of these must be true!)
f9903ed0 1960
1961 $dirs = array();
f9903ed0 1962
16a5602c 1963 if (!$getdirs and !$getfiles) { // Nothing to show
12407705 1964 return $dirs;
1965 }
1966
16a5602c 1967 if (!is_dir($rootdir)) { // Must be a directory
1968 return $dirs;
1969 }
1970
1971 if (!$dir = opendir($rootdir)) { // Can't open it for some reason
d897cae4 1972 return $dirs;
1973 }
1974
81fcd0f0 1975 while (false !== ($file = readdir($dir))) {
b35e8568 1976 $firstchar = substr($file, 0, 1);
b0ccd3fb 1977 if ($firstchar == '.' or $file == 'CVS' or $file == $excludefile) {
b35e8568 1978 continue;
1979 }
b0ccd3fb 1980 $fullfile = $rootdir .'/'. $file;
1981 if (filetype($fullfile) == 'dir') {
16a5602c 1982 if ($getdirs) {
55fd8177 1983 $dirs[] = $file;
1984 }
bf5c2e84 1985 if ($descend) {
16a5602c 1986 $subdirs = get_directory_list($fullfile, $excludefile, $descend, $getdirs, $getfiles);
bf5c2e84 1987 foreach ($subdirs as $subdir) {
b0ccd3fb 1988 $dirs[] = $file .'/'. $subdir;
bf5c2e84 1989 }
f9903ed0 1990 }
16a5602c 1991 } else if ($getfiles) {
b35e8568 1992 $dirs[] = $file;
f9903ed0 1993 }
1994 }
44e2d2bb 1995 closedir($dir);
f9903ed0 1996
774ab660 1997 asort($dirs);
1998
f9903ed0 1999 return $dirs;
2000}
2001
b0ccd3fb 2002function get_directory_size($rootdir, $excludefile='') {
16a5602c 2003/// Adds up all the files in a directory and works out the size
2004
2005 $size = 0;
2006
2007 if (!is_dir($rootdir)) { // Must be a directory
2008 return $dirs;
2009 }
2010
b5b90f26 2011 if (!$dir = @opendir($rootdir)) { // Can't open it for some reason
16a5602c 2012 return $dirs;
2013 }
2014
2015 while (false !== ($file = readdir($dir))) {
2016 $firstchar = substr($file, 0, 1);
b0ccd3fb 2017 if ($firstchar == '.' or $file == 'CVS' or $file == $excludefile) {
16a5602c 2018 continue;
2019 }
b0ccd3fb 2020 $fullfile = $rootdir .'/'. $file;
2021 if (filetype($fullfile) == 'dir') {
16a5602c 2022 $size += get_directory_size($fullfile, $excludefile);
2023 } else {
2024 $size += filesize($fullfile);
2025 }
2026 }
2027 closedir($dir);
2028
2029 return $size;
2030}
2031
989bfa9d 2032function get_real_size($size=0) {
9fa49e22 2033/// Converts numbers like 10M into bytes
989bfa9d 2034 if (!$size) {
d8ba183c 2035 return 0;
989bfa9d 2036 }
2037 $scan['MB'] = 1048576;
64efda84 2038 $scan['Mb'] = 1048576;
989bfa9d 2039 $scan['M'] = 1048576;
266a416e 2040 $scan['m'] = 1048576;
989bfa9d 2041 $scan['KB'] = 1024;
64efda84 2042 $scan['Kb'] = 1024;
989bfa9d 2043 $scan['K'] = 1024;
266a416e 2044 $scan['k'] = 1024;
989bfa9d 2045
2046 while (list($key) = each($scan)) {
2047 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
2048 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
2049 break;
2050 }
2051 }
2052 return $size;
2053}
2054
44e2d2bb 2055function display_size($size) {
9fa49e22 2056/// Converts bytes into display form
4909e176 2057
2058 static $gb,$mb,$kb,$b;
2059
2060 if (empty($gb)) {
2061 $gb = get_string('sizegb');
2062 $mb = get_string('sizemb');
2063 $kb = get_string('sizekb');
2064 $b = get_string('sizeb');
2065 }
2066
44e2d2bb 2067 if ($size >= 1073741824) {
4909e176 2068 $size = round($size / 1073741824 * 10) / 10 . $gb;
44e2d2bb 2069 } else if ($size >= 1048576) {
4909e176 2070 $size = round($size / 1048576 * 10) / 10 . $mb;
44e2d2bb 2071 } else if ($size >= 1024) {
4909e176 2072 $size = round($size / 1024 * 10) / 10 . $kb;
d8ba183c 2073 } else {
b0ccd3fb 2074 $size = $size .' '. $b;
44e2d2bb 2075 }
2076 return $size;
2077}
2078
6b174680 2079function clean_filename($string) {
9fa49e22 2080/// Cleans a given filename by removing suspicious or troublesome characters
bbf4d8e6 2081/// Only these are allowed:
a402bdcb 2082/// alphanumeric _ - .
bbf4d8e6 2083
b0ccd3fb 2084 $string = eregi_replace("\.\.+", '', $string);
8644437d 2085 $string = preg_replace('/[^\.a-zA-Z\d\_-]/','_', $string ); // only allowed chars
b0ccd3fb 2086 $string = eregi_replace("_+", '_', $string);
bbf4d8e6 2087 return $string;
6b174680 2088}
2089
2090
1180c6dc 2091/// STRING TRANSLATION ////////////////////////////////////////
2092
4bfa92e7 2093function current_language() {
9fa49e22 2094/// Returns the code for the current language
3db3acfb 2095 global $CFG, $USER, $SESSION;
4bfa92e7 2096
e5415d58 2097 if (!empty($CFG->courselang)) { // Course language can override all other settings for this page
b3153e4b 2098 return $CFG->courselang;
2099
e5415d58 2100 } else if (!empty($SESSION->lang)) { // Session language can override other settings
3db3acfb 2101 return $SESSION->lang;
2102
e5415d58 2103 } else if (!empty($USER->lang)) { // User language can override site language
4bfa92e7 2104 return $USER->lang;
3db3acfb 2105
4bfa92e7 2106 } else {
2107 return $CFG->lang;
2108 }
2109}
bcc83c41 2110
b0ccd3fb 2111function print_string($identifier, $module='', $a=NULL) {
9fa49e22 2112/// Given a string to translate - prints it out.
2113 echo get_string($identifier, $module, $a);
2114}
2115
b0ccd3fb 2116function get_string($identifier, $module='', $a=NULL) {
d8ba183c 2117/// Return the translated string specified by $identifier as
9fa49e22 2118/// for $module. Uses the same format files as STphp.
2119/// $a is an object, string or number that can be used
2120/// within translation strings
2121///
2122/// eg "hello \$a->firstname \$a->lastname"
2123/// or "hello \$a"
1180c6dc 2124
4bfa92e7 2125 global $CFG;
1180c6dc 2126
e11dc9b6 2127 global $course; /// Not a nice hack, but quick
ac8abb5f 2128 if (empty($CFG->courselang)) {
2129 if (!empty($course->lang)) {
2130 $CFG->courselang = $course->lang;
2131 }
e11dc9b6 2132 }
2133
4bfa92e7 2134 $lang = current_language();
1180c6dc 2135
b0ccd3fb 2136 if ($module == '') {
2137 $module = 'moodle';
1180c6dc 2138 }
2139
b0ccd3fb 2140 $langpath = $CFG->dirroot .'/lang';
2141 $langfile = $langpath .'/'. $lang .'/'. $module .'.php'.;
1180c6dc 2142
b947c69a 2143 // Look for the string - if found then return it
2144
2145 if (file_exists($langfile)) {
2146 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2147 eval($result);
2148 return $resultstring;
1180c6dc 2149 }
2150 }
2151
cdac797c 2152 // If it's a module, then look within the module pack itself mod/xxxx/lang/en/module.php
2153
b0ccd3fb 2154 if ($module != 'moodle') {
2155 $modlangpath = $CFG->dirroot .'/mod/'. $module .'/lang';
2156 $langfile = $modlangpath .'/'. $lang .'/'. $module .'.php';
cdac797c 2157 if (file_exists($langfile)) {
2158 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2159 eval($result);
2160 return $resultstring;
2161 }
2162 }
2163 }
1180c6dc 2164
cdac797c 2165 // If the preferred language was English we can abort now
b0ccd3fb 2166 if ($lang == 'en') {
2167 return '[['. $identifier .']]';
b947c69a 2168 }
1180c6dc 2169
b947c69a 2170 // Is a parent language defined? If so, try it.
d8ba183c 2171
b0ccd3fb 2172 if ($result = get_string_from_file('parentlanguage', $langpath .'/'. $lang .'/moodle.php', "\$parentlang")) {
b947c69a 2173 eval($result);
2174 if (!empty($parentlang)) {
b0ccd3fb 2175 $langfile = $langpath .'/'. $parentlang .'/'. $module .'.php';
b947c69a 2176 if (file_exists($langfile)) {
2177 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2178 eval($result);
2179 return $resultstring;
2180 }
1180c6dc 2181 }
2182 }
2183 }
b947c69a 2184
2185 // Our only remaining option is to try English
2186
b0ccd3fb 2187 $langfile = $langpath .'/en/'. $module .'.php';
b947c69a 2188 if (!file_exists($langfile)) {
b0ccd3fb 2189 return 'ERROR: No lang file ('. $langpath .'/en/'. $module .'.php)!';
b947c69a 2190 }
2191 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2192 eval($result);
2193 return $resultstring;
2194 }
2195
cdac797c 2196 // If it's a module, then look within the module pack itself mod/xxxx/lang/en/module.php
2197
b0ccd3fb 2198 if ($module != 'moodle') {
2199 $langfile = $modlangpath .'/en/'. $module .'.php';
cdac797c 2200 if (file_exists($langfile)) {
2201 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2202 eval($result);
2203 return $resultstring;
2204 }
2205 }
2206 }
2207
b0ccd3fb 2208 return '[['. $identifier .']]'; // Last resort
1180c6dc 2209}
2210
2211
1180c6dc 2212function get_string_from_file($identifier, $langfile, $destination) {
9fa49e22 2213/// This function is only used from get_string().
2b32bddd 2214
2215 static $strings; // Keep the strings cached in memory.
2216
2217 if (empty($strings[$langfile])) {
a32c99e2 2218 $string = array();
2b32bddd 2219 include ($langfile);
2220 $strings[$langfile] = $string;
2221 } else {
2222 $string = &$strings[$langfile];
2223 }
1180c6dc 2224
2225 if (!isset ($string[$identifier])) {
2226 return false;
2227 }
2228
b0ccd3fb 2229 return $destination .'= sprintf("'. $string[$identifier] .'");';
1180c6dc 2230}
f9903ed0 2231
9d3c795c 2232function get_strings($array, $module='') {
2233/// Converts an array of strings
2234
2235 $string = NULL;
2236 foreach ($array as $item) {
2237 $string->$item = get_string($item, $module);
2238 }
2239 return $string;
2240}
f9903ed0 2241
1a72314d 2242function get_list_of_languages() {
2243/// Returns a list of language codes and their full names
2244 global $CFG;
2245
984a8bf3 2246 $languages = array();
2247
2248 if (!empty($CFG->langlist)) { // use admin's list of languages
2249 $langlist = explode(',', $CFG->langlist);
2250 foreach ($langlist as $lang) {
b0ccd3fb 2251 if (file_exists($CFG->dirroot .'/lang/'. $lang .'/moodle.php')) {
2252 include($CFG->dirroot .'/lang/'. $lang .'/moodle.php');
2253 $languages[$lang] = $string['thislanguage'].' ('. $lang .')';
984a8bf3 2254 unset($string);
2255 }
2256 }
2257 } else {
b0ccd3fb 2258 if (!$langdirs = get_list_of_plugins('lang')) {
984a8bf3 2259 return false;
2260 }
2261 foreach ($langdirs as $lang) {
b0ccd3fb 2262 include($CFG->dirroot .'/lang/'. $lang .'/moodle.php');
2263 $languages[$lang] = $string['thislanguage'] .' ('. $lang .')';
984a8bf3 2264 unset($string);
2265 }
1a72314d 2266 }
2267
1a72314d 2268 return $languages;
2269}
2270
5833a6c8 2271function get_list_of_countries() {
2272/// Returns a list of country names in the current language
2273 global $CFG, $USER;
2274
2275 $lang = current_language();
2276
b0ccd3fb 2277 if (!file_exists($CFG->dirroot .'/lang/'. $lang .'/countries.php')) {
2278 if ($parentlang = get_string('parentlanguage')) {
2279 if (file_exists($CFG->dirroot .'/lang/'. $parentlang .'/countries.php')) {
aa3eb050 2280 $lang = $parentlang;
2281 } else {
b0ccd3fb 2282 $lang = 'en'; // countries.php must exist in this pack
aa3eb050 2283 }
2284 } else {
b0ccd3fb 2285 $lang = 'en'; // countries.php must exist in this pack
aa3eb050 2286 }
5833a6c8 2287 }
2288
b0ccd3fb 2289 include($CFG->dirroot .'/lang/'. $lang .'/countries.php');
5833a6c8 2290
f8dbffb1 2291 if (!empty($string)) {
2292 asort($string);
2293 }
5833a6c8 2294
2295 return $string;
2296}
2297
82196932 2298function get_list_of_pixnames() {
2299/// Returns a list of picture names in the current language
2300 global $CFG;
2301
2302 $lang = current_language();
2303
b0ccd3fb 2304 if (!file_exists($CFG->dirroot .'/lang/'. $lang .'/pix.php')) {
2305 if ($parentlang = get_string('parentlanguage')) {
2306 if (file_exists($CFG->dirroot .'/lang/'. $parentlang .'/pix.php')) {
82196932 2307 $lang = $parentlang;
2308 } else {
b0ccd3fb 2309 $lang = 'en'; // countries.php must exist in this pack
82196932 2310 }
2311 } else {
b0ccd3fb 2312 $lang = 'en'; // countries.php must exist in this pack
82196932 2313 }
2314 }
2315
b0ccd3fb 2316 include_once($CFG->dirroot .'/lang/'. $lang .'/pix.php');
82196932 2317
2318 return $string;
2319}
2320
9bd2c874 2321function document_file($file, $include=true) {
2322/// Can include a given document file (depends on second
2323/// parameter) or just return info about it
2324
c9d4e6da 2325 global $CFG;
9bd2c874 2326
db356340 2327 $file = clean_filename($file);
2328
9bd2c874 2329 if (empty($file)) {
9bd2c874 2330 return false;
2331 }
2332
b0ccd3fb 2333 $langs = array(current_language(), get_string('parentlanguage'), 'en');
9bd2c874 2334
db356340 2335 foreach ($langs as $lang) {
b0ccd3fb 2336 $info->filepath = $CFG->dirroot .'/lang/'. $lang .'/docs/'. $file;
2337 $info->urlpath = $CFG->wwwroot .'/lang/'. $lang .'/docs/'. $file;
9bd2c874 2338
db356340 2339 if (file_exists($info->filepath)) {
2340 if ($include) {
2341 include($info->filepath);
2342 }
2343 return $info;
0c106cd3 2344 }
9bd2c874 2345 }
2346
db356340 2347 return false;
9bd2c874 2348}
2349
1a72314d 2350
f9903ed0 2351/// ENCRYPTION ////////////////////////////////////////////////
2352
2353function rc4encrypt($data) {
b0ccd3fb 2354 $password = 'nfgjeingjk';
2355 return endecrypt($password, $data, '');
f9903ed0 2356}
2357
2358function rc4decrypt($data) {
b0ccd3fb 2359 $password = 'nfgjeingjk';
2360 return endecrypt($password, $data, 'de');
f9903ed0 2361}
2362
2363function endecrypt ($pwd, $data, $case) {
9fa49e22 2364/// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
f9903ed0 2365
2366 if ($case == 'de') {
2367 $data = urldecode($data);
2368 }
2369
b0ccd3fb 2370 $key[] = '';
2371 $box[] = '';
2372 $temp_swap = '';
f9903ed0 2373 $pwd_length = 0;
2374
2375 $pwd_length = strlen($pwd);
2376
2377 for ($i = 0; $i <= 255; $i++) {
2378 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
2379 $box[$i] = $i;
2380 }
2381
2382 $x = 0;
2383
2384 for ($i = 0; $i <= 255; $i++) {
2385 $x = ($x + $box[$i] + $key[$i]) % 256;
2386 $temp_swap = $box[$i];
2387 $box[$i] = $box[$x];
2388 $box[$x] = $temp_swap;
2389 }
2390
b0ccd3fb 2391 $temp = '';
2392 $k = '';
f9903ed0 2393
b0ccd3fb 2394 $cipherby = '';
2395 $cipher = '';
f9903ed0 2396
2397 $a = 0;
2398 $j = 0;
2399
2400 for ($i = 0; $i < strlen($data); $i++) {
2401 $a = ($a + 1) % 256;
2402 $j = ($j + $box[$a]) % 256;
2403 $temp = $box[$a];
2404 $box[$a] = $box[$j];
2405 $box[$j] = $temp;
2406 $k = $box[(($box[$a] + $box[$j]) % 256)];
2407 $cipherby = ord(substr($data, $i, 1)) ^ $k;
2408 $cipher .= chr($cipherby);
2409 }
2410
2411 if ($case == 'de') {
2412 $cipher = urldecode(urlencode($cipher));
2413 } else {
2414 $cipher = urlencode($cipher);
2415 }
2416
2417 return $cipher;
2418}
2419
2420
5fba04fb 2421/// CALENDAR MANAGEMENT ////////////////////////////////////////////////////////////////
2422
2423
2424function add_event($event) {
2425/// call this function to add an event to the calendar table
2426/// and to call any calendar plugins
2427/// The function returns the id number of the resulting record
2428/// The object event should include the following:
2429/// $event->name Name for the event
2430/// $event->description Description of the event (defaults to '')
2431/// $event->courseid The id of the course this event belongs to (0 = all courses)
2432/// $event->groupid The id of the group this event belongs to (0 = no group)
2433/// $event->userid The id of the user this event belongs to (0 = no user)
2434/// $event->modulename Name of the module that creates this event
2435/// $event->instance Instance of the module that owns this event
2436/// $event->eventtype The type info together with the module info could
2437/// be used by calendar plugins to decide how to display event
2438/// $event->timestart Timestamp for start of event
2439/// $event->timeduration Duration (defaults to zero)
2440
2441 global $CFG;
2442
2443 $event->timemodified = time();
d8ba183c 2444
b0ccd3fb 2445 if (!$event->id = insert_record('event', $event)) {
5fba04fb 2446 return false;
2447 }
d8ba183c 2448
5fba04fb 2449 if (!empty($CFG->calendar)) { // call the add_event function of the selected calendar
b0ccd3fb 2450 if (file_exists($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php')) {
2451 include_once($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php');
5fba04fb 2452 $calendar_add_event = $CFG->calendar.'_add_event';
2453 if (function_exists($calendar_add_event)) {
2454 $calendar_add_event($event);
2455 }
2456 }
2457 }
d8ba183c 2458
5fba04fb 2459 return $event->id;
2460}
2461
2462
2463function update_event($event) {
2464/// call this function to update an event in the calendar table
2465/// the event will be identified by the id field of the $event object
2466
2467 global $CFG;
2468
2469 $event->timemodified = time();
d8ba183c 2470
5fba04fb 2471 if (!empty($CFG->calendar)) { // call the update_event function of the selected calendar
b0ccd3fb 2472 if (file_exists($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php')) {
2473 include_once($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php');
5fba04fb 2474 $calendar_update_event = $CFG->calendar.'_update_event';
2475 if (function_exists($calendar_update_event)) {
2476 $calendar_update_event($event);
2477 }
2478 }
2479 }
b0ccd3fb 2480 return update_record('event', $event);
5fba04fb 2481}
2482
2483
2484function delete_event($id) {
2485/// call this function to delete the event with id $id from calendar table
2486
2487 global $CFG;
2488
2489 if (!empty($CFG->calendar)) { // call the delete_event function of the selected calendar
b0ccd3fb 2490 if (file_exists($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php')) {
2491 include_once($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php');
5fba04fb 2492 $calendar_delete_event = $CFG->calendar.'_delete_event';
2493 if (function_exists($calendar_delete_event)) {
2494 $calendar_delete_event($id);
2495 }
2496 }
2497 }
b0ccd3fb 2498 return delete_records('event', 'id', $id);
5fba04fb 2499}
2500
2501
dcd338ff 2502function hide_event($event) {
2503/// call this function to hide an event in the calendar table
2504/// the event will be identified by the id field of the $event object
2505
2506 global $CFG;
2507
2508 if (!empty($CFG->calendar)) { // call the update_event function of the selected calendar
b0ccd3fb 2509 if (file_exists($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php')) {
2510 include_once($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php');
dcd338ff 2511 $calendar_hide_event = $CFG->calendar.'_hide_event';
2512 if (function_exists($calendar_hide_event)) {
2513 $calendar_hide_event($event);
2514 }
2515 }
2516 }
2517 return set_field('event', 'visible', 0, 'id', $event->id);
2518}
2519
2520
2521function show_event($event) {
2522/// call this function to unhide an event in the calendar table
2523/// the event will be identified by the id field of the $event object
2524
2525 global $CFG;
2526
2527 if (!empty($CFG->calendar)) { // call the update_event function of the selected calendar
b0ccd3fb 2528 if (file_exists($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php')) {
2529 include_once($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php');
dcd338ff 2530 $calendar_show_event = $CFG->calendar.'_show_event';
2531 if (function_exists($calendar_show_event)) {
2532 $calendar_show_event($event);
2533 }
2534 }
2535 }
2536 return set_field('event', 'visible', 1, 'id', $event->id);
2537}
5fba04fb 2538
2539
9fa49e22 2540/// ENVIRONMENT CHECKING ////////////////////////////////////////////////////////////
1e3e716f 2541
b0ccd3fb 2542function get_list_of_plugins($plugin='mod', $exclude='') {
1d881d92 2543/// Lists plugin directories within some directory
2544
2545 global $CFG;
2546
b0ccd3fb 2547 $basedir = opendir($CFG->dirroot .'/'. $plugin);
1d881d92 2548 while ($dir = readdir($basedir)) {
b35e8568 2549 $firstchar = substr($dir, 0, 1);
b0ccd3fb 2550 if ($firstchar == '.' or $dir == 'CVS' or $dir == '_vti_cnf' or $dir == $exclude) {
1d881d92 2551 continue;
2552 }
b0ccd3fb 2553 if (filetype($CFG->dirroot .'/'. $plugin .'/'. $dir) != 'dir') {
1d881d92 2554 continue;
2555 }
2556 $plugins[] = $dir;
2557 }
2558 if ($plugins) {
2559 asort($plugins);
2560 }
2561 return $plugins;
2562}
2563
b0ccd3fb 2564function check_php_version($version='4.1.0') {
9fa49e22 2565/// Returns true is the current version of PHP is greater that the specified one
b0ccd3fb 2566 $minversion = intval(str_replace('.', '', $version));
2567 $curversion = intval(str_replace('.', '', phpversion()));
b0cb5e22 2568 return ($curversion >= $minversion);
2569}
2570
b0ccd3fb 2571function check_browser_version($brand='MSIE', $version=5.5) {
9fa49e22 2572/// Checks to see if is a browser matches the specified
2573/// brand and is equal or better version.
0095d5cd 2574
b0ccd3fb 2575 $agent = $_SERVER['HTTP_USER_AGENT'];
4c46c425 2576
2577 if (empty($agent)) {
0095d5cd 2578 return false;
2579 }
4c46c425 2580
2581 switch ($brand) {
2582
b0ccd3fb 2583 case 'Gecko': /// Gecko based browsers
4c46c425 2584
b0ccd3fb 2585 if (substr_count($agent, 'Camino')) { // MacOS X Camino not supported.
4c46c425 2586 return false;
2587 }
2588
2589 // the proper string - Gecko/CCYYMMDD Vendor/Version
2590 if (ereg("^([a-zA-Z]+)/([0-9]+\.[0-9]+) \((.*)\) (.*)$", $agent, $match)) {
2591 if (ereg("^([Gecko]+)/([0-9]+)",$match[4], $reldate)) {
2592 if ($reldate[2] > $version) {
2593 return true;
2594 }
2595 }
2596 }
2597 break;
2598
2599
b0ccd3fb 2600 case 'MSIE': /// Internet Explorer
4c46c425 2601
0e2585ac 2602 if (strpos($agent, 'Opera')) { // Reject Opera
2603 return false;
2604 }
b0ccd3fb 2605 $string = explode(';', $agent);
4c46c425 2606 if (!isset($string[1])) {
2607 return false;
2608 }
b0ccd3fb 2609 $string = explode(' ', trim($string[1]));
4c46c425 2610 if (!isset($string[0]) and !isset($string[1])) {
2611 return false;
2612 }
2613 if ($string[0] == $brand and (float)$string[1] >= $version ) {
2614 return true;
2615 }
2616 break;
2617
0095d5cd 2618 }
4c46c425 2619
0095d5cd 2620 return false;
2621}
2622
c39c66a5 2623function ini_get_bool($ini_get_arg) {
2624/// This function makes the return value of ini_get consistent if you are
2625/// setting server directives through the .htaccess file in apache.
2626/// Current behavior for value set from php.ini On = 1, Off = [blank]
2627/// Current behavior for value set from .htaccess On = On, Off = Off
2628/// Contributed by jdell@unr.edu
2629
2630 $temp = ini_get($ini_get_arg);
2631
b0ccd3fb 2632 if ($temp == '1' or strtolower($temp) == 'on') {
c39c66a5 2633 return true;
2634 }
2635 return false;
2636}
2637
0095d5cd 2638function can_use_richtext_editor() {
47037513 2639/// Compatibility stub to provide backward compatibility
2640 return can_use_html_editor();
2641}
2642
2643function can_use_html_editor() {
4c46c425 2644/// Is the HTML editor enabled? This depends on site and user
2645/// settings, as well as the current browser being used.
47037513 2646/// Returns false is editor is not being used, otherwise
2647/// returns "MSIE" or "Gecko"
4c46c425 2648
0095d5cd 2649 global $USER, $CFG;
4c46c425 2650
ce78926d 2651 if (!empty($USER->htmleditor) and !empty($CFG->htmleditor)) {
b0ccd3fb 2652 if (check_browser_version('MSIE', 5.5)) {
2653 return 'MSIE';
2654 } else if (check_browser_version('Gecko', 20030516)) {
2655 return 'Gecko';
4c46c425 2656 }
7ce20f09 2657 }
2658 return false;
0095d5cd 2659}
2660
47037513 2661
74944b73 2662function check_gd_version() {
9fa49e22 2663/// Hack to find out the GD version by parsing phpinfo output
aa095969 2664 $gdversion = 0;
74944b73 2665
aa095969 2666 if (function_exists('gd_info')){
2667 $gd_info = gd_info();
b0ccd3fb 2668 if (substr_count($gd_info['GD Version'], '2.')) {
aa095969 2669 $gdversion = 2;
b0ccd3fb 2670 } else if (substr_count($gd_info['GD Version'], '1.')) {
3ee23682 2671 $gdversion = 1;
aa095969 2672 }
3ee23682 2673
aa095969 2674 } else {
2675 ob_start();
2676 phpinfo(8);
2677 $phpinfo = ob_get_contents();
2678 ob_end_clean();
74944b73 2679
aa095969 2680 $phpinfo = explode("\n",$phpinfo);
74944b73 2681
92a4b0f1 2682
aa095969 2683 foreach ($phpinfo as $text) {
2684 $parts = explode('</td>',$text);
2685 foreach ($parts as $key => $val) {
2686 $parts[$key] = trim(strip_tags($val));
2687 }
b0ccd3fb 2688 if ($parts[0] == 'GD Version') {
2689 if (substr_count($parts[1], '2.0')) {
2690 $parts[1] = '2.0';
aa095969 2691 }
2692 $gdversion = intval($parts[1]);
92a4b0f1 2693 }
74944b73 2694 }
2695 }
2696
2697 return $gdversion; // 1, 2 or 0
2698}
f9903ed0 2699
0095d5cd 2700
9fa49e22 2701function moodle_needs_upgrading() {
2702/// Checks version numbers of Main code and all modules to see
2703/// if there are any mismatches ... returns true or false
2704 global $CFG;
2705
b0ccd3fb 2706 include_once($CFG->dirroot .'/version.php'); # defines $version and upgrades
d8ba183c 2707 if ($CFG->version) {
9fa49e22 2708 if ($version > $CFG->version) {
2709 return true;
2710 }
b0ccd3fb 2711 if ($mods = get_list_of_plugins('mod')) {
9fa49e22 2712 foreach ($mods as $mod) {
b0ccd3fb 2713 $fullmod = $CFG->dirroot .'/mod/'. $mod;
9fa49e22 2714 unset($module);
b0ccd3fb 2715 if (!is_readable($fullmod .'/version.php')) {
2716 notify('Module "'. $mod .'" is not readable - check permissions');
1079c8a8 2717 continue;
2718 }
b0ccd3fb 2719 include_once($fullmod .'/version.php'); # defines $module with version etc
2720 if ($currmodule = get_record('modules', 'name', $mod)) {
9fa49e22 2721 if ($module->version > $currmodule->version) {
2722 return true;
2723 }
2724 }
2725 }
2726 }
2727 } else {
2728 return true;
2729 }
2730 return false;
2731}
2732
2733
2734/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
2735
9d3c795c 2736function notify_login_failures() {
b40bc478 2737 global $CFG, $db;
9d3c795c 2738
2739 // notify admin users or admin user of any failed logins (since last notification).
2740 switch ($CFG->notifyloginfailures) {
2741 case 'mainadmin' :
2742 $recip = array(get_admin());
2743 break;
2744 case 'alladmins':
2745 $recip = get_admins();
2746 break;
2747 }
8f0cd6ef 2748
9d3c795c 2749 if (empty($CFG->lastnotifyfailure)) {
2750 $CFG->lastnotifyfailure=0;
2751 }
8f0cd6ef 2752
2753 // we need to deal with the threshold stuff first.
27106bac 2754 if (empty($CFG->notifyloginthreshold)) {
2755 $CFG->notifyloginthreshold = 10; // default to something sensible.
9d3c795c 2756 }
2757
b0ccd3fb 2758 $notifyipsrs = $db->Execute('SELECT ip FROM '. $CFG->prefix .'log WHERE time > '. $CFG->lastnotifyfailure .'
2759 AND module=\'login\' AND action=\'error\' GROUP BY ip HAVING count(*) > '. $CFG->notifyloginthreshold);
9d3c795c 2760
b0ccd3fb 2761 $notifyusersrs = $db->Execute('SELECT info FROM '. $CFG->prefix .'log WHERE time > '. $CFG->lastnotifyfailure .'
2762 AND module=\'login\' AND action=\'error\' GROUP BY info HAVING count(*) > '. $CFG->notifyloginthreshold);
8f0cd6ef 2763
9d3c795c 2764 if ($notifyipsrs) {
b40bc478 2765 $ipstr = '';
9d3c795c 2766 while ($row = $notifyipsrs->FetchRow()) {
b0ccd3fb 2767 $ipstr .= "'". $row['ip'] ."',";
9d3c795c 2768 }
2769 $ipstr = substr($ipstr,0,strlen($ipstr)-1);
2770 }
2771 if ($notifyusersrs) {
b40bc478 2772 $userstr = '';
9d3c795c 2773 while ($row = $notifyusersrs->FetchRow()) {
b0ccd3fb 2774 $userstr .= "'". $row['info'] ."',";
9d3c795c 2775 }
2776 $userstr = substr($userstr,0,strlen($userstr)-1);
2777 }
2778
2779 if (strlen($userstr) > 0 || strlen($ipstr) > 0) {
2780 $count = 0;
b0ccd3fb 2781 $logs = get_logs('time > '. $CFG->lastnotifyfailure .' AND module=\'login\' AND action=\'error\' '
2782 .((strlen($ipstr) > 0 && strlen($userstr) > 0) ? ' AND ( ip IN ('. $ipstr .') OR info IN ('. $userstr .') ) '
2783 : ((strlen($ipstr) != 0) ? ' AND ip IN ('. $ipstr .') ' : ' AND info IN ('. $userstr .') ')), 'l.time DESC', '', '', $count);
8f0cd6ef 2784
9d3c795c 2785 // if we haven't run in the last hour and we have something useful to report and we are actually supposed to be reporting to somebody
8f0cd6ef 2786 if (is_array($recip) and count($recip) > 0 and ((time() - (60 * 60)) > $CFG->lastnotifyfailure)
9d3c795c 2787 and is_array($logs) and count($logs) > 0) {
8f0cd6ef 2788
b40bc478 2789 $message = '';
9d3c795c 2790 $site = get_site();
b0ccd3fb 2791 $subject = get_string('notifyloginfailuressubject', '', $site->fullname);
2792 $message .= get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot)
9d3c795c 2793 .(($CFG->lastnotifyfailure != 0) ? '('.userdate($CFG->lastnotifyfailure).')' : '')."\n\n";
2794 foreach ($logs as $log) {
780dd11c 2795 $log->time = userdate($log->time);
2796 $message .= get_string('notifyloginfailuresmessage','',$log)."\n";
9d3c795c 2797 }
2798 $message .= "\n\n".get_string('notifyloginfailuresmessageend','',$CFG->wwwroot)."\n\n";
2799 foreach ($recip as $admin) {
b0ccd3fb 2800 mtrace('Emailing '. $admin->username .' about '. count($logs) .' failed login attempts');
9d3c795c 2801 email_to_user($admin,get_admin(),$subject,$message);
2802 }
b0ccd3fb 2803 $conf->name = 'lastnotifyfailure';
9d3c795c 2804 $conf->value = time();
b0ccd3fb 2805 if ($current = get_record('config', 'name', 'lastnotifyfailure')) {
9d3c795c 2806 $conf->id = $current->id;
b0ccd3fb 2807 if (! update_record('config', $conf)) {
2808 mtrace('Could not update last notify time');
9d3c795c 2809 }
2810
b0ccd3fb 2811 } else if (! insert_record('config', $conf)) {
2812 mtrace('Could not set last notify time');
9d3c795c 2813 }
2814 }
2815 }
2816}
2817
a2fa19d8 2818function moodle_setlocale($locale='') {
2819
2820 global $SESSION, $USER, $CFG;
2821
2822 if ($locale) {
2823 $CFG->locale = $locale;
2824 } else if (!empty($CFG->courselang) and ($CFG->courselang != $CFG->lang) ) {
2825 $CFG->locale = get_string('locale');
2826 } else if (!empty($SESSION->lang) and ($SESSION->lang != $CFG->lang) ) {
2827 $CFG->locale = get_string('locale');
2828 } else if (!empty($USER->lang) and ($USER->lang != $CFG->lang) ) {
2829 $CFG->locale = get_string('locale');
2830 } else if (empty($CFG->locale)) {
2831 $CFG->locale = get_string('locale');
2832 set_config('locale', $CFG->locale); // cache it to save lookups in future
2833 }
2834 setlocale (LC_TIME, $CFG->locale);
2835 setlocale (LC_COLLATE, $CFG->locale);
2836
2837 if ($CFG->locale != 'tr_TR') { // To workaround a well-known PHP bug with Turkish
2838 setlocale (LC_CTYPE, $CFG->locale);
2839 }
2840}
2841
7d6cac54 2842function moodle_strtolower ($string, $encoding='') {
2843/// Converts string to lowercase using most compatible function available
2844 if (function_exists('mb_strtolower')) {
2845 if($encoding===''){
2846 return mb_strtolower($string); //use multibyte support with default encoding
2847 } else {
dbe0be00 2848 return mb_strtolower($string,$encoding); //use given encoding
d8ba183c 2849 }
7d6cac54 2850 } else {
2851 return strtolower($string); // use common function what rely on current locale setting
d8ba183c 2852 }
7d6cac54 2853}
2854
9fa49e22 2855function count_words($string) {
2856/// Words are defined as things between whitespace
2857 $string = strip_tags($string);
2858 return count(preg_split("/\w\b/", $string)) - 1;
2859}
2860
1d881d92 2861function random_string ($length=15) {
b0ccd3fb 2862 $pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
2863 $pool .= 'abcdefghijklmnopqrstuvwxyz';
2864 $pool .= '0123456789';
1d881d92 2865 $poollen = strlen($pool);
2866 mt_srand ((double) microtime() * 1000000);
b0ccd3fb 2867 $string = '';
1d881d92 2868 for ($i = 0; $i < $length; $i++) {
2869 $string .= substr($pool, (mt_rand()%($poollen)), 1);
2870 }
2871 return $string;
2872}
2873
2874
9fa49e22 2875function getweek ($startdate, $thedate) {
2876/// Given dates in seconds, how many weeks is the date from startdate
d8ba183c 2877/// The first week is 1, the second 2 etc ...
2878
9fa49e22 2879 if ($thedate < $startdate) { // error
d8ba183c 2880 return 0;
9fa49e22 2881 }
2882
2883 return floor(($thedate - $startdate) / 604800.0) + 1;
2884}
2885
2886function generate_password($maxlen=10) {
2887/// returns a randomly generated password of length $maxlen. inspired by
d8ba183c 2888/// http://www.phpbuilder.com/columns/jesus19990502.php3
9fa49e22 2889
2890 global $CFG;
2891
b0ccd3fb 2892 $fillers = '1234567890!$-+';
9fa49e22 2893 $wordlist = file($CFG->wordlist);
2894
2895 srand((double) microtime() * 1000000);
2896 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2897 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2898 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
2899
2900 return substr($word1 . $filler1 . $word2, 0, $maxlen);
2901}
2902
12659521 2903function format_float($num, $places=1) {
9fa49e22 2904/// Given a float, prints it nicely
2905 return sprintf("%.$places"."f", $num);
2906}
2907
ee0e5d57 2908function swapshuffle($array) {
2909/// Given a simple array, this shuffles it up just like shuffle()
2910/// Unlike PHP's shuffle() ihis function works on any machine.
2911
2912 srand ((double) microtime() * 10000000);
2913 $last = count($array) - 1;
2914 for ($i=0;$i<=$last;$i++) {
2915 $from = rand(0,$last);
2916 $curr = $array[$i];
2917 $array[$i] = $array[$from];
2918 $array[$from] = $curr;
d8ba183c 2919 }
ee0e5d57 2920 return $array;
2921}
2922
bc700e65 2923function swapshuffle_assoc($array) {
2924/// Like swapshuffle, but works on associative arrays
2925
2926 $newkeys = swapshuffle(array_keys($array));
2927 foreach ($newkeys as $newkey) {
2928 $newarray[$newkey] = $array[$newkey];
2929 }
2930 return $newarray;
2931}
2932
ee0e5d57 2933function draw_rand_array($array, $draws) {
d8ba183c 2934/// Given an arbitrary array, and a number of draws,
2935/// this function returns an array with that amount
ee0e5d57 2936/// of items. The indexes are retained.
2937
2938 srand ((double) microtime() * 10000000);
2939
2940 $return = array();
2941
2942 $last = count($array);
2943
2944 if ($draws > $last) {
2945 $draws = $last;
2946 }
2947
2948 while ($draws > 0) {
2949 $last--;
2950
2951 $keys = array_keys($array);
2952 $rand = rand(0, $last);
2953
2954 $return[$keys[$rand]] = $array[$keys[$rand]];
2955 unset($array[$keys[$rand]]);
d8ba183c 2956
ee0e5d57 2957 $draws--;
2958 }
2959
2960 return $return;
d8ba183c 2961}
9fa49e22 2962
f5e82bc7 2963function microtime_diff($a, $b) {
b0ccd3fb 2964 list($a_dec, $a_sec) = explode(' ', $a);
2965 list($b_dec, $b_sec) = explode(' ', $b);
f5e82bc7 2966 return $b_sec - $a_sec + $b_dec - $a_dec;
2967}
2968
b0ccd3fb 2969function make_menu_from_list($list, $separator=',') {
d8ba183c 2970/// Given a list (eg a,b,c,d,e) this function returns
02ebf404 2971/// an array of 1->a, 2->b, 3->c etc
2972
2973 $array = array_reverse(explode($separator, $list), true);
2974 foreach ($array as $key => $item) {
2975 $outarray[$key+1] = trim($item);
2976 }
2977 return $outarray;
2978}
2979
fdc47ee6 2980function make_grades_menu($gradingtype) {
2981/// Creates an array that represents all the current grades that
2982/// can be chosen using the given grading type. Negative numbers
2983/// are scales, zero is no grade, and positive numbers are maximum
2984/// grades.
2985
2986 $grades = array();
2987 if ($gradingtype < 0) {
b0ccd3fb 2988 if ($scale = get_record('scale', 'id', - $gradingtype)) {
fdc47ee6 2989 return make_menu_from_list($scale->scale);
2990 }
2991 } else if ($gradingtype > 0) {
2992 for ($i=$gradingtype; $i>=0; $i--) {
b0ccd3fb 2993 $grades[$i] = $i .' / '. $gradingtype;
fdc47ee6 2994 }
2995 return $grades;
2996 }
2997 return $grades;
2998}
2999
2127fedd 3000function course_scale_used($courseid,$scaleid) {
3001////This function returns the nummber of activities
3002////using scaleid in a courseid
3003
3004 global $CFG;
a402bdcb 3005
2127fedd 3006 $return = 0;
3007
3008 if (!empty($scaleid)) {
3009 if ($cms = get_course_mods($courseid)) {
3010 foreach ($cms as $cm) {
3011 //Check cm->name/lib.php exists
3012 if (file_exists($CFG->dirroot.'/mod/'.$cm->modname.'/lib.php')) {
3013 include_once($CFG->dirroot.'/mod/'.$cm->modname.'/lib.php');
3014 $function_name = $cm->modname.'_scale_used';
3015 if (function_exists($function_name)) {
3016 if ($function_name($cm->instance,$scaleid)) {
3017 $return++;
3018 }
3019 }
3020 }
3021 }
3022 }
3023 }
3024 return $return;
3025}
3026
3027function site_scale_used($scaleid) {
a402bdcb 3028////This function returns the nummber of activities
2127fedd 3029////using scaleid in the entire site
3030
3031 global $CFG;
3032
3033 $return = 0;
3034
3035 if (!empty($scaleid)) {
3036 if ($courses = get_courses()) {
3037 foreach ($courses as $course) {
3038 $return += course_scale_used($course->id,$scaleid);
3039 }
3040 }
3041 }
3042 return $return;
3043}
3044
b0ccd3fb 3045function make_unique_id_code($extra='') {
280faf9f 3046
b0ccd3fb 3047 $hostname = 'unknownhost';
3048 if (!empty($_SERVER['HTTP_HOST'])) {
3049 $hostname = $_SERVER['HTTP_HOST'];
3050 } else if (!empty($_ENV['HTTP_HOST'])) {
3051 $hostname = $_ENV['HTTP_HOST'];
3052 } else if (!empty($_SERVER['SERVER_NAME'])) {
3053 $hostname = $_SERVER['SERVER_NAME'];
3054 } else if (!empty($_ENV['SERVER_NAME'])) {
3055 $hostname = $_ENV['SERVER_NAME'];
280faf9f 3056 }
3057
1ccc73ac 3058 $date = gmdate("ymdHis");
280faf9f 3059
3060 $random = random_string(6);
3061
757a0abd 3062 if ($extra) {
b0ccd3fb 3063 return $hostname .'+'. $date .'+'. $random .'+'. $extra;
757a0abd 3064 } else {
b0ccd3fb 3065 return $hostname .'+'. $date .'+'. $random;
757a0abd 3066 }
280faf9f 3067}
3068
0095d5cd 3069
47efbb04 3070/**
3071* Function to check the passed address is within the passed subnet
3072*
3073* The parameter is a comma separated string of subnet definitions.
3074* Subnet strings can be in one of two formats:
3075* 1: xxx.xxx.xxx.xxx/xx
3076* 2: xxx.xxx
3077* Return boolean
3078* Code for type 1 modified from user posted comments by mediator at
3079* http://au.php.net/manual/en/function.ip2long.php
3080*
3081* @param addr the address you are checking
3082* @param subnetstr the string of subnet addresses
3083*/
3084
3085function address_in_subnet($addr, $subnetstr) {
3086
b0ccd3fb 3087 $subnets = explode(',', $subnetstr);
47efbb04 3088 $found = false;
3089 $addr = trim($addr);
3090
3091 foreach ($subnets as $subnet) {
3092 $subnet = trim($subnet);
b0ccd3fb 3093 if (strpos($subnet, '/') !== false) { /// type 1
47efbb04 3094
3095 list($ip, $mask) = explode('/', $subnet);
3096 $mask = 0xffffffff << (32 - $mask);
3097 $found = ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
3098
3099 } else { /// type 2
3100 $found = (strpos($addr, $subnet) === 0);
3101 }
3102
3103 if ($found) {
3104 continue;
3105 }
3106 }
3107
3108 return $found;
3109}
3110
defaac4c 3111function mtrace($string, $eol="\n") {
8f0cd6ef 3112// For outputting debugging info
622ebc6a 3113
3114 if (defined('STDOUT')) {
3115 fwrite(STDOUT, $string.$eol);
3116 } else {
b0ccd3fb 3117 echo $string . $eol;
622ebc6a 3118 }
3119
defaac4c 3120 flush();
3121}
3122
f97ab1ec 3123function getremoteaddr() {
3124//Returns most reliable client address
b0ccd3fb 3125 if (getenv('HTTP_CLIENT_IP')) $ip = getenv('HTTP_CLIENT_IP');
3126 else if(getenv('HTTP_X_FORWARDED_FOR')) $ip = getenv('HTTP_X_FORWARDED_FOR');
3127 else if(getenv('REMOTE_ADDR')) $ip = getenv('REMOTE_ADDR');
f97ab1ec 3128 else $ip = false; //just in case
3129 return $ip;
3130}
defaac4c 3131
8f0cd6ef 3132if(!function_exists('html_entity_decode')) {
3133// html_entity_decode is only supported by php 4.3.0 and higher
3134// so if it is not predefined, define it here
3135 function html_entity_decode($string) {
3136 $trans_tbl = get_html_translation_table(HTML_ENTITIES);
3137 $trans_tbl = array_flip($trans_tbl);
3138 return strtr($string, $trans_tbl);
3139 }
3140}
3141
9d5b689c 3142// vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140:
d35757eb 3143?>