typo
[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)) {
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
9fa49e22 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;
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)) {
066af654 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
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");
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
9c9f7d77 213 $odays = "";
214 $ohours = "";
215 $omins = "";
216 $osecs = "";
217
8dbed6be 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
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");
228}
f9903ed0 229
61ae5d36 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
5fa51a39 241 if ($format == "") {
dcde9f02 242 $format = get_string("strftimedaydatetime");
5fa51a39 243 }
035cdbff 244
dcde9f02 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);
255 $daystring = str_replace(" 0", "", strftime(" %d", $date));
256 $datestring = str_replace("DD", $daystring, $datestring);
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);
9fa49e22 264 $daystring = str_replace(" 0", "", gmstrftime(" %d", $date));
035cdbff 265 $datestring = str_replace("DD", $daystring, $datestring);
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);
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);
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) {
4606d9bb 317 return mktime(0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
318 }
319
edf7fe8c 320 $timemidnight = gmmktime (0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
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) {
d552ead0 331 return "server time";
332 }
333 if (abs($timezone) < 0.5) {
334 return "GMT";
335 }
336 if ($timezone > 0) {
337 return "GMT+$timezone";
338 } else {
339 return "GMT$timezone";
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;
9f44d972 374 if (!empty($_SERVER["HTTP_REFERER"])) {
375 $SESSION->fromurl = $_SERVER["HTTP_REFERER"];
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)) {
fe657136 384 redirect("$CFG->wwwroot/login/index.php$loginguest");
8a33e371 385 } else {
386 $wwwroot = str_replace('http','https',$CFG->wwwroot);
fe657136 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'}){
396 redirect("$CFG->wwwroot/login/change_password.php");
397 } elseif($CFG->changepassword) {
398 redirect($CFG->changepassword);
399 } else {
400 error("You cannot proceed without changing your password.
401 However there is no available page for changing it.
402 Please contact your Moodle Administrator.");
403 }
404 }
405
808a3baa 406 // Check that the user account is properly set up
407 if (user_not_fully_set_up($USER)) {
839f2456 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();
319b4729 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 }
423 if (! $course = get_record("course", "id", $courseid)) {
424 error("That course doesn't exist");
425 }
1efa27fd 426 if (!$course->visible) {
427 print_header();
319b4729 428 notice(get_string("studentnotallowed", "", fullname($USER, true)), "$CFG->wwwroot/");
1efa27fd 429 }
7363ff91 430 if ($USER->username == "guest") {
431 switch ($course->guest) {
432 case 0: // Guests not allowed
433 print_header();
434 notice(get_string("guestsnotallowed", "", $course->fullname));
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;
445 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
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
471 return update_record("user", $user);
472}
473
808a3baa 474function user_not_fully_set_up($user) {
ac5d88eb 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);
1d881d92 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
cb98d312 504function check_for_restricted_user($username=NULL, $redirect="") {
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)) {
9b591be6 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;
581d7b49 540 } else if (record_exists("user_admins", "userid", $userid)){
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) {
568 return record_exists("user_teachers","userid",$userid);
569 }
570
ebc3bd2b 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
586 return get_field("user_teachers", "editall", "userid", $userid, "course", $courseid);
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)) {
1924074c 599 return record_exists("user_coursecreators", "userid", $USER->id);
600 }
601
602 return record_exists("user_coursecreators", "userid", $userid);
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
ebc3bd2b 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 }
da5c172a 650 return ($USER->username == "guest");
651 }
652
9fa49e22 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') {
698 return "$user->firstname $user->lastname";
699
700 } else if ($CFG->fullnamedisplay == 'lastname firstname') {
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
7185e073 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])) {
736 return "";
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
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
faebaf0f 786 if (insert_record("user", $newuser)) {
d35757eb 787 $user = get_user_info_from_db("username", $newuser->username);
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 }
812 return get_user_info_from_db("username", $username);
813}
0609562b 814
815function guest_user() {
816 global $CFG;
817
818 if ($newuser = get_record("user", "username", "guest")) {
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
27286aeb 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)) {
847 $CFG->auth = "manual"; // Default authentication module
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
71f9abf9 864 if (!file_exists("$CFG->dirroot/auth/$auth/lib.php")) {
865 $auth = "manual"; // Can't find auth module, default to internal
466558e3 866 }
867
71f9abf9 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)) {
39a5a35d 888 if (! record_exists("user_coursecreators", "userid", $user->id)) {
889 $cdata->userid = $user->id;
890 if (! insert_record("user_coursecreators", $cdata)) {
891 error("Cannot add user to course creators.");
892 }
893 }
e582b65e 894 } else {
39a5a35d 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.");
898 }
899 }
e582b65e 900 }
39a5a35d 901 }
e582b65e 902 return $user;
9d3c795c 903
e582b65e 904 } else {
9d3c795c 905 add_to_log(0, "login", "error", $_SERVER['HTTP_REFERER'], $username);
906 $date = date('Y-m-d H:i:s');
59619427 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
631cf796 915 if (!$course = get_record("course", "id", $courseid)) { // Check course
3041b0f8 916 return false;
4d312bbe 917 }
631cf796 918 if (!$user = get_record("user", "id", $userid)) { // Check user
919 return false;
920 }
921 if ($student = get_record("user_students", "userid", $userid, "course", $courseid)) {
922 $student->timestart = $timestart;
923 $student->timeend = $timeend;
924 $student->time = time();
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();
933 return insert_record("user_students", $student);
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
9fa62805 942 if ($forums = get_records("forum", "course", $courseid)) {
9fa49e22 943 foreach ($forums as $forum) {
9fa62805 944 delete_records("forum_subscriptions", "forum", $forum->id, "userid", $userid);
945 }
946 }
947 if ($groups = get_groups($courseid, $userid)) {
948 foreach ($groups as $group) {
949 delete_records("groups_members", "groupid", $group->id, "userid", $userid);
bb09fb11 950 }
f9903ed0 951 }
9fa62805 952 return delete_records("user_students", "userid", $userid, "course", $courseid);
9fa49e22 953
f9903ed0 954 } else {
9fa62805 955 delete_records("forum_subscriptions", "userid", $userid);
84bbca53 956 delete_records("groups_members", "userid", $userid);
9fa62805 957 return delete_records("user_students", "userid", $userid);
f9903ed0 958 }
959}
960
b40bc478 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
981 if (!record_exists("user", "id", $userid)) {
982 return false; // no such user
983 }
984
985 if (!record_exists("course", "id", $courseid)) {
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;
997 if ($student = get_record("user_students", "userid", $userid, "course", $courseid)) {
998 $teacher->timestart = $student->timestart;
999 $teacher->timeend = $student->timeend;
1000 $teacher->timeaccess = $student->timeaccess;
1001 }
61451a36 1002
1003 if (record_exists("user_teachers", "course", $courseid)) {
1004 $teacher->authority = 2;
1005 } else {
1006 $teacher->authority = 1;
1007 }
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
1014 return insert_record("user_teachers", $teacher);
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
3041b0f8 1023 if ($forums = get_records("forum", "course", $courseid)) {
9fa49e22 1024 foreach ($forums as $forum) {
3041b0f8 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) {
1034 delete_records("groups_members", "groupid", $group->id, "userid", $userid);
1035 }
1036 }
1037 }
1038
3041b0f8 1039 return delete_records("user_teachers", "userid", $userid, "course", $courseid);
57507290 1040 } else {
3041b0f8 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
1050 if (!record_exists("user_admins", "userid", $userid)) {
1051 if (record_exists("user", "id", $userid)) {
1052 $creator->userid = $userid;
1053 return insert_record("user_coursecreators", $creator);
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
1064 return delete_records("user_coursecreators", "userid", $userid);
1065}
1066
1067function add_admin($userid) {
1068/// Add an admin to the site
1069
1070 if (!record_exists("user_admins", "userid", $userid)) {
1071 if (record_exists("user", "id", $userid)) {
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
3041b0f8 1081 return insert_record("user_admins", $admin);
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
3041b0f8 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
1107 if (! $course = get_record("course", "id", $courseid)) {
1108 error("Course ID was incorrect (can't find it)");
1109 }
1110
1111 $strdeleted = get_string("deleted");
1112
1113 // First delete every instance of every module
d8ba183c 1114
07aeb7b0 1115 if ($allmods = get_records("modules") ) {
1116 foreach ($allmods as $mod) {
1117 $modname = $mod->name;
1118 $modfile = "$CFG->dirroot/mod/$modname/lib.php";
ca952b03 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)) {
1125 if ($instances = get_records($modname, "course", $course->id)) {
1126 foreach ($instances as $instance) {
1127 if ($moddelete($instance->id)) {
1128 $count++;
1129 } else {
1130 notify("Could not delete $modname instance $instance->id ($instance->name)");
1131 $result = false;
1132 }
1133 }
1134 }
1135 } else {
1136 notify("Function $moddelete() doesn't exist!");
1137 $result = false;
1138 }
1139
ca952b03 1140 if (function_exists($moddeletecourse)) {
1141 $moddeletecourse($course);
1142 }
07aeb7b0 1143 }
1144 if ($showfeedback) {
1145 notify("$strdeleted $count x $modname");
1146 }
1147 }
1148 } else {
1149 error("No modules are installed!");
1150 }
1151
1152 // Delete any user stuff
1153
1154 if (delete_records("user_students", "course", $course->id)) {
1155 if ($showfeedback) {
1156 notify("$strdeleted user_students");
1157 }
1158 } else {
1159 $result = false;
1160 }
1161
1162 if (delete_records("user_teachers", "course", $course->id)) {
1163 if ($showfeedback) {
1164 notify("$strdeleted user_teachers");
1165 }
1166 } else {
1167 $result = false;
1168 }
1169
082e3ebc 1170 // Delete any groups
1171
1172 if ($groups = get_records("groups", "courseid", $course->id)) {
1173 foreach ($groups as $group) {
1174 if (delete_records("groups_members", "groupid", $group->id)) {
1175 if ($showfeedback) {
1176 notify("$strdeleted groups_members");
1177 }
1178 } else {
1179 $result = false;
1180 }
1181 if (delete_records("groups", "id", $group->id)) {
1182 if ($showfeedback) {
1183 notify("$strdeleted groups");
1184 }
1185 } else {
1186 $result = false;
1187 }
1188 }
1189 }
1190
1191 // Delete events
1192
1193 if (delete_records("event", "courseid", $course->id)) {
1194 if ($showfeedback) {
1195 notify("$strdeleted event");
1196 }
1197 } else {
1198 $result = false;
1199 }
1200
07aeb7b0 1201 // Delete logs
1202
1203 if (delete_records("log", "course", $course->id)) {
1204 if ($showfeedback) {
1205 notify("$strdeleted log");
1206 }
1207 } else {
1208 $result = false;
1209 }
1210
1211 // Delete any course stuff
1212
1213 if (delete_records("course_sections", "course", $course->id)) {
1214 if ($showfeedback) {
1215 notify("$strdeleted course_sections");
1216 }
1217 } else {
1218 $result = false;
1219 }
1220
1221 if (delete_records("course_modules", "course", $course->id)) {
1222 if ($showfeedback) {
1223 notify("$strdeleted course_modules");
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
1244 if (! $course = get_record("course", "id", $courseid)) {
1245 error("Course ID was incorrect (can't find it)");
1246 }
1247
1248 $strdeleted = get_string("deleted");
1249
1250 // Look in every instance of every module for data to delete
1251
1252 if ($allmods = get_records("modules") ) {
1253 foreach ($allmods as $mod) {
1254 $modname = $mod->name;
1255 $modfile = "$CFG->dirroot/mod/$modname/lib.php";
1256 $moddeleteuserdata = $modname."_delete_userdata"; // Function to delete user data
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 {
1266 error("No modules are installed!");
1267 }
1268
1269 // Delete other stuff
1270
1271 if ($removestudents) {
1272 /// Delete student enrolments
1273 if (delete_records("user_students", "course", $course->id)) {
1274 if ($showfeedback) {
1275 notify("$strdeleted user_students");
1276 }
1277 } else {
1278 $result = false;
1279 }
1280 /// Delete group members (but keep the groups)
1281 if ($groups = get_records("groups", "courseid", $course->id)) {
1282 foreach ($groups as $group) {
1283 if (delete_records("groups_members", "groupid", $group->id)) {
1284 if ($showfeedback) {
1285 notify("$strdeleted groups_members");
1286 }
1287 } else {
1288 $result = false;
1289 }
1290 }
1291 }
1292 }
1293
1294 if ($removeteachers) {
1295 if (delete_records("user_teachers", "course", $course->id)) {
1296 if ($showfeedback) {
1297 notify("$strdeleted user_teachers");
1298 }
1299 } else {
1300 $result = false;
1301 }
1302 }
1303
1304 if ($removegroups) {
1305 if ($groups = get_records("groups", "courseid", $course->id)) {
1306 foreach ($groups as $group) {
1307 if (delete_records("groups", "id", $group->id)) {
1308 if ($showfeedback) {
1309 notify("$strdeleted groups");
1310 }
1311 } else {
1312 $result = false;
1313 }
1314 }
1315 }
1316 }
1317
1318 if ($removeevents) {
1319 if (delete_records("event", "courseid", $course->id)) {
1320 if ($showfeedback) {
1321 notify("$strdeleted event");
1322 }
1323 } else {
1324 $result = false;
1325 }
1326 }
1327
1328 if ($removelogs) {
1329 if (delete_records("log", "course", $course->id)) {
1330 if ($showfeedback) {
1331 notify("$strdeleted log");
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
0da33e07 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))) {
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
6e506bf9 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
136dabd8 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
d8ba183c 1561 $mail->Version = "Moodle $CFG->version"; // mailer version
136dabd8 1562 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
562bbe90 1563
98c4eae3 1564
d483bcd3 1565 if (current_language() != "en") {
1566 $mail->CharSet = get_string("thischarset");
98c4eae3 1567 }
1568
62740736 1569 if ($CFG->smtphosts == "qmail") {
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) {
1578 echo "<pre>\n";
1579 $mail->SMTPDebug = true;
1580 }
1e411ffc 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
1592 $mail->Sender = "$adminuser->email";
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) {
6e506bf9 1598 $mail->From = "$from->email";
1599 $mail->FromName = fullname($from);
1600 } else {
1601 $mail->From = "$CFG->noreplyaddress";
0d8a590a 1602 $mail->FromName = fullname($from);
6e506bf9 1603 }
136dabd8 1604 $mail->Subject = stripslashes($subject);
f9903ed0 1605
d8ba183c 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);
125898af 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
0b4c5822 1632 $mail->AddAddress("$adminuser->email", fullname($adminuser) );
4216daa6 1633 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
136dabd8 1634 } else {
1635 include_once("$CFG->dirroot/files/mimetypes.php");
1636 $mimetype = mimeinfo("type", $attachname);
1637 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
1638 }
f9903ed0 1639 }
1640
136dabd8 1641 if ($mail->Send()) {
1642 return true;
1643 } else {
90e736bd 1644 mtrace("ERROR: $mail->ErrorInfo");
222ac91b 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
1659 if (! set_field("user", "password", md5($newpassword), "id", $user->id) ) {
1660 error("Could not set user password!");
1661 }
1662
1663 $a->firstname = $user->firstname;
1664 $a->sitename = $site->fullname;
1665 $a->username = $user->username;
1666 $a->newpassword = $newpassword;
1667 $a->link = "$CFG->wwwroot/login/change_password.php";
0b4c5822 1668 $a->signoff = fullname($from, true)." ($from->email)";
1d881d92 1669
1670 $message = get_string("newpasswordtext", "", $a);
1671
1672 $subject = "$site->fullname: ".get_string("changedpassword");
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;
839f2456 1687 $data->link = "$CFG->wwwroot/login/confirm.php?p=$user->secret&amp;s=$user->username";
0b4c5822 1688 $data->admin = fullname($from)." ($from->email)";
1d881d92 1689
1690 $message = get_string("emailconfirmation", "", $data);
eb347b6b 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;
839f2456 1708 $data->link = "$CFG->wwwroot/login/forgot_password.php?p=$user->secret&amp;s=$user->username";
0b4c5822 1709 $data->admin = fullname($from)." ($from->email)";
eb347b6b 1710
1711 $message = get_string("emailpasswordconfirmation", "", $data);
1712 $subject = get_string("emailpasswordconfirmationsubject", "", $site->fullname);
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 }
1736 return get_string("emailonlyallowed", '', $CFG->allowemailaddresses);
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!
1746 return get_string("emailnotallowed", '', $CFG->denyemailaddresses);
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) {
1772 notify("ERROR: You need to create the directory $currdir with web server write access");
1773 }
6b174680 1774 return false;
1775 }
1776 }
1777
1e03c552 1778 $dirarray = explode("/", $directory);
6b174680 1779
1780 foreach ($dirarray as $dir) {
1781 $currdir = "$currdir/$dir";
1782 if (! file_exists($currdir)) {
2e6d4273 1783 if (! mkdir($currdir, $CFG->directorypermissions)) {
66f9a82c 1784 if ($shownotices) {
1785 notify("ERROR: Could not find or create a directory ($currdir)");
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
1801 if (! $moddata = make_upload_directory("$courseid/$CFG->moddata")) {
1802 return false;
1803 }
1804
1805 $strreadme = get_string("readme");
1806
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");
1809 } else {
1810 copy("$CFG->dirroot/lang/en/docs/module_files.txt", "$moddata/$strreadme.txt");
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)) {
1819 return "";
1820 }
44e2d2bb 1821 if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
1822 return $newfile['tmp_name'];
1823 } else {
1824 return "";
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
44e2d2bb 1844 if (! $filesize = ini_get("upload_max_filesize")) {
1845 $filesize = "5M";
1846 }
4909e176 1847 $minimumsize = get_real_size($filesize);
1848
316ebf78 1849 if ($postsize = ini_get("post_max_size")) {
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
1953
1954
1955
16a5602c 1956function get_directory_list($rootdir, $excludefile="", $descend=true, $getdirs=false, $getfiles=true) {
d8ba183c 1957/// Returns an array with all the filenames in
9fa49e22 1958/// all subdirectories, relative to the given rootdir.
1959/// If excludefile is defined, then that file/directory is ignored
16a5602c 1960/// If getdirs is true, then (sub)directories are included in the output
1961/// If getfiles is true, then files are included in the output
1962/// (at least one of these must be true!)
f9903ed0 1963
1964 $dirs = array();
f9903ed0 1965
16a5602c 1966 if (!$getdirs and !$getfiles) { // Nothing to show
12407705 1967 return $dirs;
1968 }
1969
16a5602c 1970 if (!is_dir($rootdir)) { // Must be a directory
1971 return $dirs;
1972 }
1973
1974 if (!$dir = opendir($rootdir)) { // Can't open it for some reason
d897cae4 1975 return $dirs;
1976 }
1977
81fcd0f0 1978 while (false !== ($file = readdir($dir))) {
b35e8568 1979 $firstchar = substr($file, 0, 1);
1980 if ($firstchar == "." or $file == "CVS" or $file == $excludefile) {
1981 continue;
1982 }
55fd8177 1983 $fullfile = "$rootdir/$file";
bf5c2e84 1984 if (filetype($fullfile) == "dir") {
16a5602c 1985 if ($getdirs) {
55fd8177 1986 $dirs[] = $file;
1987 }
bf5c2e84 1988 if ($descend) {
16a5602c 1989 $subdirs = get_directory_list($fullfile, $excludefile, $descend, $getdirs, $getfiles);
bf5c2e84 1990 foreach ($subdirs as $subdir) {
1991 $dirs[] = "$file/$subdir";
1992 }
f9903ed0 1993 }
16a5602c 1994 } else if ($getfiles) {
b35e8568 1995 $dirs[] = $file;
f9903ed0 1996 }
1997 }
44e2d2bb 1998 closedir($dir);
f9903ed0 1999
774ab660 2000 asort($dirs);
2001
f9903ed0 2002 return $dirs;
2003}
2004
16a5602c 2005function get_directory_size($rootdir, $excludefile="") {
2006/// Adds up all the files in a directory and works out the size
2007
2008 $size = 0;
2009
2010 if (!is_dir($rootdir)) { // Must be a directory
2011 return $dirs;
2012 }
2013
b5b90f26 2014 if (!$dir = @opendir($rootdir)) { // Can't open it for some reason
16a5602c 2015 return $dirs;
2016 }
2017
2018 while (false !== ($file = readdir($dir))) {
2019 $firstchar = substr($file, 0, 1);
2020 if ($firstchar == "." or $file == "CVS" or $file == $excludefile) {
2021 continue;
2022 }
2023 $fullfile = "$rootdir/$file";
2024 if (filetype($fullfile) == "dir") {
2025 $size += get_directory_size($fullfile, $excludefile);
2026 } else {
2027 $size += filesize($fullfile);
2028 }
2029 }
2030 closedir($dir);
2031
2032 return $size;
2033}
2034
989bfa9d 2035function get_real_size($size=0) {
9fa49e22 2036/// Converts numbers like 10M into bytes
989bfa9d 2037 if (!$size) {
d8ba183c 2038 return 0;
989bfa9d 2039 }
2040 $scan['MB'] = 1048576;
64efda84 2041 $scan['Mb'] = 1048576;
989bfa9d 2042 $scan['M'] = 1048576;
266a416e 2043 $scan['m'] = 1048576;
989bfa9d 2044 $scan['KB'] = 1024;
64efda84 2045 $scan['Kb'] = 1024;
989bfa9d 2046 $scan['K'] = 1024;
266a416e 2047 $scan['k'] = 1024;
989bfa9d 2048
2049 while (list($key) = each($scan)) {
2050 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
2051 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
2052 break;
2053 }
2054 }
2055 return $size;
2056}
2057
44e2d2bb 2058function display_size($size) {
9fa49e22 2059/// Converts bytes into display form
4909e176 2060
2061 static $gb,$mb,$kb,$b;
2062
2063 if (empty($gb)) {
2064 $gb = get_string('sizegb');
2065 $mb = get_string('sizemb');
2066 $kb = get_string('sizekb');
2067 $b = get_string('sizeb');
2068 }
2069
44e2d2bb 2070 if ($size >= 1073741824) {
4909e176 2071 $size = round($size / 1073741824 * 10) / 10 . $gb;
44e2d2bb 2072 } else if ($size >= 1048576) {
4909e176 2073 $size = round($size / 1048576 * 10) / 10 . $mb;
44e2d2bb 2074 } else if ($size >= 1024) {
4909e176 2075 $size = round($size / 1024 * 10) / 10 . $kb;
d8ba183c 2076 } else {
4909e176 2077 $size = $size ." $b";
44e2d2bb 2078 }
2079 return $size;
2080}
2081
6b174680 2082function clean_filename($string) {
9fa49e22 2083/// Cleans a given filename by removing suspicious or troublesome characters
bbf4d8e6 2084/// Only these are allowed:
a402bdcb 2085/// alphanumeric _ - .
bbf4d8e6 2086
2087 $string = eregi_replace("\.\.+", "", $string);
8644437d 2088 $string = preg_replace('/[^\.a-zA-Z\d\_-]/','_', $string ); // only allowed chars
bbf4d8e6 2089 $string = eregi_replace("_+", "_", $string);
2090 return $string;
6b174680 2091}
2092
2093
1180c6dc 2094/// STRING TRANSLATION ////////////////////////////////////////
2095
4bfa92e7 2096function current_language() {
9fa49e22 2097/// Returns the code for the current language
3db3acfb 2098 global $CFG, $USER, $SESSION;
4bfa92e7 2099
e5415d58 2100 if (!empty($CFG->courselang)) { // Course language can override all other settings for this page
b3153e4b 2101 return $CFG->courselang;
2102
e5415d58 2103 } else if (!empty($SESSION->lang)) { // Session language can override other settings
3db3acfb 2104 return $SESSION->lang;
2105
e5415d58 2106 } else if (!empty($USER->lang)) { // User language can override site language
4bfa92e7 2107 return $USER->lang;
3db3acfb 2108
4bfa92e7 2109 } else {
2110 return $CFG->lang;
2111 }
2112}
bcc83c41 2113
9fa49e22 2114function print_string($identifier, $module="", $a=NULL) {
2115/// Given a string to translate - prints it out.
2116 echo get_string($identifier, $module, $a);
2117}
2118
a83fded1 2119function get_string($identifier, $module="", $a=NULL) {
d8ba183c 2120/// Return the translated string specified by $identifier as
9fa49e22 2121/// for $module. Uses the same format files as STphp.
2122/// $a is an object, string or number that can be used
2123/// within translation strings
2124///
2125/// eg "hello \$a->firstname \$a->lastname"
2126/// or "hello \$a"
1180c6dc 2127
4bfa92e7 2128 global $CFG;
1180c6dc 2129
e11dc9b6 2130 global $course; /// Not a nice hack, but quick
ac8abb5f 2131 if (empty($CFG->courselang)) {
2132 if (!empty($course->lang)) {
2133 $CFG->courselang = $course->lang;
2134 }
e11dc9b6 2135 }
2136
4bfa92e7 2137 $lang = current_language();
1180c6dc 2138
058eec18 2139 if ($module == "") {
2140 $module = "moodle";
1180c6dc 2141 }
2142
058eec18 2143 $langpath = "$CFG->dirroot/lang";
2144 $langfile = "$langpath/$lang/$module.php";
1180c6dc 2145
b947c69a 2146 // Look for the string - if found then return it
2147
2148 if (file_exists($langfile)) {
2149 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2150 eval($result);
2151 return $resultstring;
1180c6dc 2152 }
2153 }
2154
cdac797c 2155 // If it's a module, then look within the module pack itself mod/xxxx/lang/en/module.php
2156
2157 if ($module != "moodle") {
2158 $modlangpath = "$CFG->dirroot/mod/$module/lang";
2159 $langfile = "$modlangpath/$lang/$module.php";
2160 if (file_exists($langfile)) {
2161 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2162 eval($result);
2163 return $resultstring;
2164 }
2165 }
2166 }
1180c6dc 2167
cdac797c 2168 // If the preferred language was English we can abort now
d8ba183c 2169 if ($lang == "en") {
b947c69a 2170 return "[[$identifier]]";
2171 }
1180c6dc 2172
b947c69a 2173 // Is a parent language defined? If so, try it.
d8ba183c 2174
b947c69a 2175 if ($result = get_string_from_file("parentlanguage", "$langpath/$lang/moodle.php", "\$parentlang")) {
2176 eval($result);
2177 if (!empty($parentlang)) {
2178 $langfile = "$langpath/$parentlang/$module.php";
2179 if (file_exists($langfile)) {
2180 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2181 eval($result);
2182 return $resultstring;
2183 }
1180c6dc 2184 }
2185 }
2186 }
b947c69a 2187
2188 // Our only remaining option is to try English
2189
2190 $langfile = "$langpath/en/$module.php";
2191 if (!file_exists($langfile)) {
2192 return "ERROR: No lang file ($langpath/en/$module.php)!";
2193 }
2194 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2195 eval($result);
2196 return $resultstring;
2197 }
2198
cdac797c 2199 // If it's a module, then look within the module pack itself mod/xxxx/lang/en/module.php
2200
2201 if ($module != "moodle") {
2202 $langfile = "$modlangpath/en/$module.php";
2203 if (file_exists($langfile)) {
2204 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
2205 eval($result);
2206 return $resultstring;
2207 }
2208 }
2209 }
2210
b947c69a 2211 return "[[$identifier]]"; // Last resort
1180c6dc 2212}
2213
2214
1180c6dc 2215function get_string_from_file($identifier, $langfile, $destination) {
9fa49e22 2216/// This function is only used from get_string().
2b32bddd 2217
2218 static $strings; // Keep the strings cached in memory.
2219
2220 if (empty($strings[$langfile])) {
a32c99e2 2221 $string = array();
2b32bddd 2222 include ($langfile);
2223 $strings[$langfile] = $string;
2224 } else {
2225 $string = &$strings[$langfile];
2226 }
1180c6dc 2227
2228 if (!isset ($string[$identifier])) {
2229 return false;
2230 }
2231
a83fded1 2232 return "$destination = sprintf(\"".$string[$identifier]."\");";
1180c6dc 2233}
f9903ed0 2234
9d3c795c 2235function get_strings($array, $module='') {
2236/// Converts an array of strings
2237
2238 $string = NULL;
2239 foreach ($array as $item) {
2240 $string->$item = get_string($item, $module);
2241 }
2242 return $string;
2243}
f9903ed0 2244
1a72314d 2245function get_list_of_languages() {
2246/// Returns a list of language codes and their full names
2247 global $CFG;
2248
984a8bf3 2249 $languages = array();
2250
2251 if (!empty($CFG->langlist)) { // use admin's list of languages
2252 $langlist = explode(',', $CFG->langlist);
2253 foreach ($langlist as $lang) {
2254 if (file_exists("$CFG->dirroot/lang/$lang/moodle.php")) {
2255 include("$CFG->dirroot/lang/$lang/moodle.php");
2256 $languages[$lang] = $string["thislanguage"]." ($lang)";
2257 unset($string);
2258 }
2259 }
2260 } else {
2261 if (!$langdirs = get_list_of_plugins("lang")) {
2262 return false;
2263 }
2264 foreach ($langdirs as $lang) {
2265 include("$CFG->dirroot/lang/$lang/moodle.php");
2266 $languages[$lang] = $string["thislanguage"]." ($lang)";
2267 unset($string);
2268 }
1a72314d 2269 }
2270
1a72314d 2271 return $languages;
2272}
2273
5833a6c8 2274function get_list_of_countries() {
2275/// Returns a list of country names in the current language
2276 global $CFG, $USER;
2277
2278 $lang = current_language();
2279
2280 if (!file_exists("$CFG->dirroot/lang/$lang/countries.php")) {
aa3eb050 2281 if ($parentlang = get_string("parentlanguage")) {
2282 if (file_exists("$CFG->dirroot/lang/$parentlang/countries.php")) {
2283 $lang = $parentlang;
2284 } else {
2285 $lang = "en"; // countries.php must exist in this pack
2286 }
2287 } else {
2288 $lang = "en"; // countries.php must exist in this pack
2289 }
5833a6c8 2290 }
2291
d8ba183c 2292 include("$CFG->dirroot/lang/$lang/countries.php");
5833a6c8 2293
f8dbffb1 2294 if (!empty($string)) {
2295 asort($string);
2296 }
5833a6c8 2297
2298 return $string;
2299}
2300
82196932 2301function get_list_of_pixnames() {
2302/// Returns a list of picture names in the current language
2303 global $CFG;
2304
2305 $lang = current_language();
2306
2307 if (!file_exists("$CFG->dirroot/lang/$lang/pix.php")) {
2308 if ($parentlang = get_string("parentlanguage")) {
2309 if (file_exists("$CFG->dirroot/lang/$parentlang/pix.php")) {
2310 $lang = $parentlang;
2311 } else {
2312 $lang = "en"; // countries.php must exist in this pack
2313 }
2314 } else {
2315 $lang = "en"; // countries.php must exist in this pack
2316 }
2317 }
2318
d8ba183c 2319 include_once("$CFG->dirroot/lang/$lang/pix.php");
82196932 2320
2321 return $string;
2322}
2323
9bd2c874 2324function document_file($file, $include=true) {
2325/// Can include a given document file (depends on second
2326/// parameter) or just return info about it
2327
c9d4e6da 2328 global $CFG;
9bd2c874 2329
db356340 2330 $file = clean_filename($file);
2331
9bd2c874 2332 if (empty($file)) {
9bd2c874 2333 return false;
2334 }
2335
db356340 2336 $langs = array(current_language(), get_string("parentlanguage"), "en");
9bd2c874 2337
db356340 2338 foreach ($langs as $lang) {
2339 $info->filepath = "$CFG->dirroot/lang/$lang/docs/$file";
2340 $info->urlpath = "$CFG->wwwroot/lang/$lang/docs/$file";
9bd2c874 2341
db356340 2342 if (file_exists($info->filepath)) {
2343 if ($include) {
2344 include($info->filepath);
2345 }
2346 return $info;
0c106cd3 2347 }
9bd2c874 2348 }
2349
db356340 2350 return false;
9bd2c874 2351}
2352
1a72314d 2353
f9903ed0 2354/// ENCRYPTION ////////////////////////////////////////////////
2355
2356function rc4encrypt($data) {
2357 $password = "nfgjeingjk";
2358 return endecrypt($password, $data, "");
2359}
2360
2361function rc4decrypt($data) {
2362 $password = "nfgjeingjk";
2363 return endecrypt($password, $data, "de");
2364}
2365
2366function endecrypt ($pwd, $data, $case) {
9fa49e22 2367/// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
f9903ed0 2368
2369 if ($case == 'de') {
2370 $data = urldecode($data);
2371 }
2372
2373 $key[] = "";
2374 $box[] = "";
2375 $temp_swap = "";
2376 $pwd_length = 0;
2377
2378 $pwd_length = strlen($pwd);
2379
2380 for ($i = 0; $i <= 255; $i++) {
2381 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
2382 $box[$i] = $i;
2383 }
2384
2385 $x = 0;
2386
2387 for ($i = 0; $i <= 255; $i++) {
2388 $x = ($x + $box[$i] + $key[$i]) % 256;
2389 $temp_swap = $box[$i];
2390 $box[$i] = $box[$x];
2391 $box[$x] = $temp_swap;
2392 }
2393
2394 $temp = "";
2395 $k = "";
2396
2397 $cipherby = "";
2398 $cipher = "";
2399
2400 $a = 0;
2401 $j = 0;
2402
2403 for ($i = 0; $i < strlen($data); $i++) {
2404 $a = ($a + 1) % 256;
2405 $j = ($j + $box[$a]) % 256;
2406 $temp = $box[$a];
2407 $box[$a] = $box[$j];
2408 $box[$j] = $temp;
2409 $k = $box[(($box[$a] + $box[$j]) % 256)];
2410 $cipherby = ord(substr($data, $i, 1)) ^ $k;
2411 $cipher .= chr($cipherby);
2412 }
2413
2414 if ($case == 'de') {
2415 $cipher = urldecode(urlencode($cipher));
2416 } else {
2417 $cipher = urlencode($cipher);
2418 }
2419
2420 return $cipher;
2421}
2422
2423
5fba04fb 2424/// CALENDAR MANAGEMENT ////////////////////////////////////////////////////////////////
2425
2426
2427function add_event($event) {
2428/// call this function to add an event to the calendar table
2429/// and to call any calendar plugins
2430/// The function returns the id number of the resulting record
2431/// The object event should include the following:
2432/// $event->name Name for the event
2433/// $event->description Description of the event (defaults to '')
2434/// $event->courseid The id of the course this event belongs to (0 = all courses)
2435/// $event->groupid The id of the group this event belongs to (0 = no group)
2436/// $event->userid The id of the user this event belongs to (0 = no user)
2437/// $event->modulename Name of the module that creates this event
2438/// $event->instance Instance of the module that owns this event
2439/// $event->eventtype The type info together with the module info could
2440/// be used by calendar plugins to decide how to display event
2441/// $event->timestart Timestamp for start of event
2442/// $event->timeduration Duration (defaults to zero)
2443
2444 global $CFG;
2445
2446 $event->timemodified = time();
d8ba183c 2447
5fba04fb 2448 if (!$event->id = insert_record("event", $event)) {
2449 return false;
2450 }
d8ba183c 2451
5fba04fb 2452 if (!empty($CFG->calendar)) { // call the add_event function of the selected calendar
2453 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
2454 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
2455 $calendar_add_event = $CFG->calendar.'_add_event';
2456 if (function_exists($calendar_add_event)) {
2457 $calendar_add_event($event);
2458 }
2459 }
2460 }
d8ba183c 2461
5fba04fb 2462 return $event->id;
2463}
2464
2465
2466function update_event($event) {
2467/// call this function to update an event in the calendar table
2468/// the event will be identified by the id field of the $event object
2469
2470 global $CFG;
2471
2472 $event->timemodified = time();
d8ba183c 2473
5fba04fb 2474 if (!empty($CFG->calendar)) { // call the update_event function of the selected calendar
2475 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
2476 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
2477 $calendar_update_event = $CFG->calendar.'_update_event';
2478 if (function_exists($calendar_update_event)) {
2479 $calendar_update_event($event);
2480 }
2481 }
2482 }
2483 return update_record("event", $event);
2484}
2485
2486
2487function delete_event($id) {
2488/// call this function to delete the event with id $id from calendar table
2489
2490 global $CFG;
2491
2492 if (!empty($CFG->calendar)) { // call the delete_event function of the selected calendar
2493 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
2494 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
2495 $calendar_delete_event = $CFG->calendar.'_delete_event';
2496 if (function_exists($calendar_delete_event)) {
2497 $calendar_delete_event($id);
2498 }
2499 }
2500 }
2501 return delete_records("event", 'id', $id);
2502}
2503
2504
dcd338ff 2505function hide_event($event) {
2506/// call this function to hide an event in the calendar table
2507/// the event will be identified by the id field of the $event object
2508
2509 global $CFG;
2510
2511 if (!empty($CFG->calendar)) { // call the update_event function of the selected calendar
2512 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
2513 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
2514 $calendar_hide_event = $CFG->calendar.'_hide_event';
2515 if (function_exists($calendar_hide_event)) {
2516 $calendar_hide_event($event);
2517 }
2518 }
2519 }
2520 return set_field('event', 'visible', 0, 'id', $event->id);
2521}
2522
2523
2524function show_event($event) {
2525/// call this function to unhide an event in the calendar table
2526/// the event will be identified by the id field of the $event object
2527
2528 global $CFG;
2529
2530 if (!empty($CFG->calendar)) { // call the update_event function of the selected calendar
2531 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
2532 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
2533 $calendar_show_event = $CFG->calendar.'_show_event';
2534 if (function_exists($calendar_show_event)) {
2535 $calendar_show_event($event);
2536 }
2537 }
2538 }
2539 return set_field('event', 'visible', 1, 'id', $event->id);
2540}
5fba04fb 2541
2542
9fa49e22 2543/// ENVIRONMENT CHECKING ////////////////////////////////////////////////////////////
1e3e716f 2544
0cb77f5a 2545function get_list_of_plugins($plugin="mod", $exclude="") {
1d881d92 2546/// Lists plugin directories within some directory
2547
2548 global $CFG;
2549
2550 $basedir = opendir("$CFG->dirroot/$plugin");
2551 while ($dir = readdir($basedir)) {
b35e8568 2552 $firstchar = substr($dir, 0, 1);
0cb77f5a 2553 if ($firstchar == "." or $dir == "CVS" or $dir == "_vti_cnf" or $dir == $exclude) {
1d881d92 2554 continue;
2555 }
2556 if (filetype("$CFG->dirroot/$plugin/$dir") != "dir") {
2557 continue;
2558 }
2559 $plugins[] = $dir;
2560 }
2561 if ($plugins) {
2562 asort($plugins);
2563 }
2564 return $plugins;
2565}
2566
b0cb5e22 2567function check_php_version($version="4.1.0") {
9fa49e22 2568/// Returns true is the current version of PHP is greater that the specified one
b0cb5e22 2569 $minversion = intval(str_replace(".", "", $version));
2570 $curversion = intval(str_replace(".", "", phpversion()));
2571 return ($curversion >= $minversion);
2572}
2573
0095d5cd 2574function check_browser_version($brand="MSIE", $version=5.5) {
9fa49e22 2575/// Checks to see if is a browser matches the specified
2576/// brand and is equal or better version.
0095d5cd 2577
4c46c425 2578 $agent = $_SERVER["HTTP_USER_AGENT"];
2579
2580 if (empty($agent)) {
0095d5cd 2581 return false;
2582 }
4c46c425 2583
2584 switch ($brand) {
2585
2586 case "Gecko": /// Gecko based browsers
2587
2588 if (substr_count($agent, "Camino")) { // MacOS X Camino not supported.
2589 return false;
2590 }
2591
2592 // the proper string - Gecko/CCYYMMDD Vendor/Version
2593 if (ereg("^([a-zA-Z]+)/([0-9]+\.[0-9]+) \((.*)\) (.*)$", $agent, $match)) {
2594 if (ereg("^([Gecko]+)/([0-9]+)",$match[4], $reldate)) {
2595 if ($reldate[2] > $version) {
2596 return true;
2597 }
2598 }
2599 }
2600 break;
2601
2602
2603 case "MSIE": /// Internet Explorer
2604
0e2585ac 2605 if (strpos($agent, 'Opera')) { // Reject Opera
2606 return false;
2607 }
4c46c425 2608 $string = explode(";", $agent);
2609 if (!isset($string[1])) {
2610 return false;
2611 }
2612 $string = explode(" ", trim($string[1]));
2613 if (!isset($string[0]) and !isset($string[1])) {
2614 return false;
2615 }
2616 if ($string[0] == $brand and (float)$string[1] >= $version ) {
2617 return true;
2618 }
2619 break;
2620
0095d5cd 2621 }
4c46c425 2622
0095d5cd 2623 return false;
2624}
2625
c39c66a5 2626function ini_get_bool($ini_get_arg) {
2627/// This function makes the return value of ini_get consistent if you are
2628/// setting server directives through the .htaccess file in apache.
2629/// Current behavior for value set from php.ini On = 1, Off = [blank]
2630/// Current behavior for value set from .htaccess On = On, Off = Off
2631/// Contributed by jdell@unr.edu
2632
2633 $temp = ini_get($ini_get_arg);
2634
2635 if ($temp == "1" or strtolower($temp) == "on") {
2636 return true;
2637 }
2638 return false;
2639}
2640
0095d5cd 2641function can_use_richtext_editor() {
47037513 2642/// Compatibility stub to provide backward compatibility
2643 return can_use_html_editor();
2644}
2645
2646function can_use_html_editor() {
4c46c425 2647/// Is the HTML editor enabled? This depends on site and user
2648/// settings, as well as the current browser being used.
47037513 2649/// Returns false is editor is not being used, otherwise
2650/// returns "MSIE" or "Gecko"
4c46c425 2651
0095d5cd 2652 global $USER, $CFG;
4c46c425 2653
ce78926d 2654 if (!empty($USER->htmleditor) and !empty($CFG->htmleditor)) {
4c46c425 2655 if (check_browser_version("MSIE", 5.5)) {
47037513 2656 return "MSIE";
2657 } else if (check_browser_version("Gecko", 20030516)) {
2658 return "Gecko";
4c46c425 2659 }
7ce20f09 2660 }
2661 return false;
0095d5cd 2662}
2663
47037513 2664
74944b73 2665function check_gd_version() {
9fa49e22 2666/// Hack to find out the GD version by parsing phpinfo output
aa095969 2667 $gdversion = 0;
74944b73 2668
aa095969 2669 if (function_exists('gd_info')){
2670 $gd_info = gd_info();
3ee23682 2671 if (substr_count($gd_info['GD Version'], "2.")) {
aa095969 2672 $gdversion = 2;
3ee23682 2673 } else if (substr_count($gd_info['GD Version'], "1.")) {
2674 $gdversion = 1;
aa095969 2675 }
3ee23682 2676
aa095969 2677 } else {
2678 ob_start();
2679 phpinfo(8);
2680 $phpinfo = ob_get_contents();
2681 ob_end_clean();
74944b73 2682
aa095969 2683 $phpinfo = explode("\n",$phpinfo);
74944b73 2684
92a4b0f1 2685
aa095969 2686 foreach ($phpinfo as $text) {
2687 $parts = explode('</td>',$text);
2688 foreach ($parts as $key => $val) {
2689 $parts[$key] = trim(strip_tags($val));
2690 }
2691 if ($parts[0] == "GD Version") {
2692 if (substr_count($parts[1], "2.0")) {
2693 $parts[1] = "2.0";
2694 }
2695 $gdversion = intval($parts[1]);
92a4b0f1 2696 }
74944b73 2697 }
2698 }
2699
2700 return $gdversion; // 1, 2 or 0
2701}
f9903ed0 2702
0095d5cd 2703
9fa49e22 2704function moodle_needs_upgrading() {
2705/// Checks version numbers of Main code and all modules to see
2706/// if there are any mismatches ... returns true or false
2707 global $CFG;
2708
2709 include_once("$CFG->dirroot/version.php"); # defines $version and upgrades
d8ba183c 2710 if ($CFG->version) {
9fa49e22 2711 if ($version > $CFG->version) {
2712 return true;
2713 }
2714 if ($mods = get_list_of_plugins("mod")) {
2715 foreach ($mods as $mod) {
2716 $fullmod = "$CFG->dirroot/mod/$mod";
2717 unset($module);
1079c8a8 2718 if (!is_readable("$fullmod/version.php")) {
2719 notify("Module '$mod' is not readable - check permissions");
2720 continue;
2721 }
9fa49e22 2722 include_once("$fullmod/version.php"); # defines $module with version etc
2723 if ($currmodule = get_record("modules", "name", $mod)) {
2724 if ($module->version > $currmodule->version) {
2725 return true;
2726 }
2727 }
2728 }
2729 }
2730 } else {
2731 return true;
2732 }
2733 return false;
2734}
2735
2736
2737/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
2738
9d3c795c 2739function notify_login_failures() {
b40bc478 2740 global $CFG, $db;
9d3c795c 2741
2742 // notify admin users or admin user of any failed logins (since last notification).
2743 switch ($CFG->notifyloginfailures) {
2744 case 'mainadmin' :
2745 $recip = array(get_admin());
2746 break;
2747 case 'alladmins':
2748 $recip = get_admins();
2749 break;
2750 }
8f0cd6ef 2751
9d3c795c 2752 if (empty($CFG->lastnotifyfailure)) {
2753 $CFG->lastnotifyfailure=0;
2754 }
8f0cd6ef 2755
2756 // we need to deal with the threshold stuff first.
27106bac 2757 if (empty($CFG->notifyloginthreshold)) {
2758 $CFG->notifyloginthreshold = 10; // default to something sensible.
9d3c795c 2759 }
2760
8f0cd6ef 2761 $notifyipsrs = $db->Execute("SELECT ip FROM {$CFG->prefix}log WHERE time > {$CFG->lastnotifyfailure}
27106bac 2762 AND module='login' AND action='error' GROUP BY ip HAVING count(*) > $CFG->notifyloginthreshold");
9d3c795c 2763
8f0cd6ef 2764 $notifyusersrs = $db->Execute("SELECT info FROM {$CFG->prefix}log WHERE time > {$CFG->lastnotifyfailure}
27106bac 2765 AND module='login' AND action='error' GROUP BY info HAVING count(*) > $CFG->notifyloginthreshold");
8f0cd6ef 2766
9d3c795c 2767 if ($notifyipsrs) {
b40bc478 2768 $ipstr = '';
9d3c795c 2769 while ($row = $notifyipsrs->FetchRow()) {
2770 $ipstr .= "'".$row['ip']."',";
2771 }
2772 $ipstr = substr($ipstr,0,strlen($ipstr)-1);
2773 }
2774 if ($notifyusersrs) {
b40bc478 2775 $userstr = '';
9d3c795c 2776 while ($row = $notifyusersrs->FetchRow()) {
2777 $userstr .= "'".$row['info']."',";
2778 }
2779 $userstr = substr($userstr,0,strlen($userstr)-1);
2780 }
2781
2782 if (strlen($userstr) > 0 || strlen($ipstr) > 0) {
2783 $count = 0;
2784 $logs = get_logs("time > {$CFG->lastnotifyfailure} AND module='login' AND action='error' "
2785 .((strlen($ipstr) > 0 && strlen($userstr) > 0) ? " AND ( ip IN ($ipstr) OR info IN ($userstr) ) "
2786 : ((strlen($ipstr) != 0) ? " AND ip IN ($ipstr) " : " AND info IN ($userstr) ")),"l.time DESC","","",$count);
8f0cd6ef 2787
9d3c795c 2788 // 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 2789 if (is_array($recip) and count($recip) > 0 and ((time() - (60 * 60)) > $CFG->lastnotifyfailure)
9d3c795c 2790 and is_array($logs) and count($logs) > 0) {
8f0cd6ef 2791
b40bc478 2792 $message = '';
9d3c795c 2793 $site = get_site();
2794 $subject = get_string('notifyloginfailuressubject','',$site->fullname);
2795 $message .= get_string('notifyloginfailuresmessagestart','',$CFG->wwwroot)
2796 .(($CFG->lastnotifyfailure != 0) ? '('.userdate($CFG->lastnotifyfailure).')' : '')."\n\n";
2797 foreach ($logs as $log) {
780dd11c 2798 $log->time = userdate($log->time);
2799 $message .= get_string('notifyloginfailuresmessage','',$log)."\n";
9d3c795c 2800 }
2801 $message .= "\n\n".get_string('notifyloginfailuresmessageend','',$CFG->wwwroot)."\n\n";
2802 foreach ($recip as $admin) {
1284a926 2803 mtrace("Emailing $admin->username about ".count($logs)." failed login attempts");
9d3c795c 2804 email_to_user($admin,get_admin(),$subject,$message);
2805 }
2806 $conf->name = "lastnotifyfailure";
2807 $conf->value = time();
2808 if ($current = get_record("config", "name", "lastnotifyfailure")) {
2809 $conf->id = $current->id;
2810 if (! update_record("config", $conf)) {
1284a926 2811 mtrace("Could not update last notify time");
9d3c795c 2812 }
2813
2814 } else if (! insert_record("config", $conf)) {
1284a926 2815 mtrace("Could not set last notify time");
9d3c795c 2816 }
2817 }
2818 }
2819}
2820
a2fa19d8 2821function moodle_setlocale($locale='') {
2822
2823 global $SESSION, $USER, $CFG;
2824
2825 if ($locale) {
2826 $CFG->locale = $locale;
2827 } else if (!empty($CFG->courselang) and ($CFG->courselang != $CFG->lang) ) {
2828 $CFG->locale = get_string('locale');
2829 } else if (!empty($SESSION->lang) and ($SESSION->lang != $CFG->lang) ) {
2830 $CFG->locale = get_string('locale');
2831 } else if (!empty($USER->lang) and ($USER->lang != $CFG->lang) ) {
2832 $CFG->locale = get_string('locale');
2833 } else if (empty($CFG->locale)) {
2834 $CFG->locale = get_string('locale');
2835 set_config('locale', $CFG->locale); // cache it to save lookups in future
2836 }
2837 setlocale (LC_TIME, $CFG->locale);
2838 setlocale (LC_COLLATE, $CFG->locale);
2839
2840 if ($CFG->locale != 'tr_TR') { // To workaround a well-known PHP bug with Turkish
2841 setlocale (LC_CTYPE, $CFG->locale);
2842 }
2843}
2844
7d6cac54 2845function moodle_strtolower ($string, $encoding='') {
2846/// Converts string to lowercase using most compatible function available
2847 if (function_exists('mb_strtolower')) {
2848 if($encoding===''){
2849 return mb_strtolower($string); //use multibyte support with default encoding
2850 } else {
dbe0be00 2851 return mb_strtolower($string,$encoding); //use given encoding
d8ba183c 2852 }
7d6cac54 2853 } else {
2854 return strtolower($string); // use common function what rely on current locale setting
d8ba183c 2855 }
7d6cac54 2856}
2857
9fa49e22 2858function count_words($string) {
2859/// Words are defined as things between whitespace
2860 $string = strip_tags($string);
2861 return count(preg_split("/\w\b/", $string)) - 1;
2862}
2863
1d881d92 2864function random_string ($length=15) {
2865 $pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2866 $pool .= "abcdefghijklmnopqrstuvwxyz";
2867 $pool .= "0123456789";
2868 $poollen = strlen($pool);
2869 mt_srand ((double) microtime() * 1000000);
2870 $string = "";
2871 for ($i = 0; $i < $length; $i++) {
2872 $string .= substr($pool, (mt_rand()%($poollen)), 1);
2873 }
2874 return $string;
2875}
2876
2877
9fa49e22 2878function getweek ($startdate, $thedate) {
2879/// Given dates in seconds, how many weeks is the date from startdate
d8ba183c 2880/// The first week is 1, the second 2 etc ...
2881
9fa49e22 2882 if ($thedate < $startdate) { // error
d8ba183c 2883 return 0;
9fa49e22 2884 }
2885
2886 return floor(($thedate - $startdate) / 604800.0) + 1;
2887}
2888
2889function generate_password($maxlen=10) {
2890/// returns a randomly generated password of length $maxlen. inspired by
d8ba183c 2891/// http://www.phpbuilder.com/columns/jesus19990502.php3
9fa49e22 2892
2893 global $CFG;
2894
2895 $fillers = "1234567890!$-+";
2896 $wordlist = file($CFG->wordlist);
2897
2898 srand((double) microtime() * 1000000);
2899 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2900 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2901 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
2902
2903 return substr($word1 . $filler1 . $word2, 0, $maxlen);
2904}
2905
12659521 2906function format_float($num, $places=1) {
9fa49e22 2907/// Given a float, prints it nicely
2908 return sprintf("%.$places"."f", $num);
2909}
2910
ee0e5d57 2911function swapshuffle($array) {
2912/// Given a simple array, this shuffles it up just like shuffle()
2913/// Unlike PHP's shuffle() ihis function works on any machine.
2914
2915 srand ((double) microtime() * 10000000);
2916 $last = count($array) - 1;
2917 for ($i=0;$i<=$last;$i++) {
2918 $from = rand(0,$last);
2919 $curr = $array[$i];
2920 $array[$i] = $array[$from];
2921 $array[$from] = $curr;
d8ba183c 2922 }
ee0e5d57 2923 return $array;
2924}
2925
bc700e65 2926function swapshuffle_assoc($array) {
2927/// Like swapshuffle, but works on associative arrays
2928
2929 $newkeys = swapshuffle(array_keys($array));
2930 foreach ($newkeys as $newkey) {
2931 $newarray[$newkey] = $array[$newkey];
2932 }
2933 return $newarray;
2934}
2935
ee0e5d57 2936function draw_rand_array($array, $draws) {
d8ba183c 2937/// Given an arbitrary array, and a number of draws,
2938/// this function returns an array with that amount
ee0e5d57 2939/// of items. The indexes are retained.
2940
2941 srand ((double) microtime() * 10000000);
2942
2943 $return = array();
2944
2945 $last = count($array);
2946
2947 if ($draws > $last) {
2948 $draws = $last;
2949 }
2950
2951 while ($draws > 0) {
2952 $last--;
2953
2954 $keys = array_keys($array);
2955 $rand = rand(0, $last);
2956
2957 $return[$keys[$rand]] = $array[$keys[$rand]];
2958 unset($array[$keys[$rand]]);
d8ba183c 2959
ee0e5d57 2960 $draws--;
2961 }
2962
2963 return $return;
d8ba183c 2964}
9fa49e22 2965
f5e82bc7 2966function microtime_diff($a, $b) {
2967 list($a_dec, $a_sec) = explode(" ", $a);
2968 list($b_dec, $b_sec) = explode(" ", $b);
2969 return $b_sec - $a_sec + $b_dec - $a_dec;
2970}
2971
02ebf404 2972function make_menu_from_list($list, $separator=",") {
d8ba183c 2973/// Given a list (eg a,b,c,d,e) this function returns
02ebf404 2974/// an array of 1->a, 2->b, 3->c etc
2975
2976 $array = array_reverse(explode($separator, $list), true);
2977 foreach ($array as $key => $item) {
2978 $outarray[$key+1] = trim($item);
2979 }
2980 return $outarray;
2981}
2982
fdc47ee6 2983function make_grades_menu($gradingtype) {
2984/// Creates an array that represents all the current grades that
2985/// can be chosen using the given grading type. Negative numbers
2986/// are scales, zero is no grade, and positive numbers are maximum
2987/// grades.
2988
2989 $grades = array();
2990 if ($gradingtype < 0) {
2991 if ($scale = get_record("scale", "id", - $gradingtype)) {
2992 return make_menu_from_list($scale->scale);
2993 }
2994 } else if ($gradingtype > 0) {
2995 for ($i=$gradingtype; $i>=0; $i--) {
62ca135d 2996 $grades[$i] = "$i / $gradingtype";
fdc47ee6 2997 }
2998 return $grades;
2999 }
3000 return $grades;
3001}
3002
2127fedd 3003function course_scale_used($courseid,$scaleid) {
3004////This function returns the nummber of activities
3005////using scaleid in a courseid
3006
3007 global $CFG;
a402bdcb 3008
2127fedd 3009 $return = 0;
3010
3011 if (!empty($scaleid)) {
3012 if ($cms = get_course_mods($courseid)) {
3013 foreach ($cms as $cm) {
3014 //Check cm->name/lib.php exists
3015 if (file_exists($CFG->dirroot.'/mod/'.$cm->modname.'/lib.php')) {
3016 include_once($CFG->dirroot.'/mod/'.$cm->modname.'/lib.php');
3017 $function_name = $cm->modname.'_scale_used';
3018 if (function_exists($function_name)) {
3019 if ($function_name($cm->instance,$scaleid)) {
3020 $return++;
3021 }
3022 }
3023 }
3024 }
3025 }
3026 }
3027 return $return;
3028}
3029
3030function site_scale_used($scaleid) {
a402bdcb 3031////This function returns the nummber of activities
2127fedd 3032////using scaleid in the entire site
3033
3034 global $CFG;
3035
3036 $return = 0;
3037
3038 if (!empty($scaleid)) {
3039 if ($courses = get_courses()) {
3040 foreach ($courses as $course) {
3041 $return += course_scale_used($course->id,$scaleid);
3042 }
3043 }
3044 }
3045 return $return;
3046}
3047
757a0abd 3048function make_unique_id_code($extra="") {
280faf9f 3049
3050 $hostname = "unknownhost";
3051 if (!empty($_SERVER["HTTP_HOST"])) {
3052 $hostname = $_SERVER["HTTP_HOST"];
3053 } else if (!empty($_ENV["HTTP_HOST"])) {
3054 $hostname = $_ENV["HTTP_HOST"];
3055 } else if (!empty($_SERVER["SERVER_NAME"])) {
3056 $hostname = $_SERVER["SERVER_NAME"];
3057 } else if (!empty($_ENV["SERVER_NAME"])) {
3058 $hostname = $_ENV["SERVER_NAME"];
3059 }
3060
1ccc73ac 3061 $date = gmdate("ymdHis");
280faf9f 3062
3063 $random = random_string(6);
3064
757a0abd 3065 if ($extra) {
3066 return "$hostname+$date+$random+$extra";
3067 } else {
3068 return "$hostname+$date+$random";
3069 }
280faf9f 3070}
3071
0095d5cd 3072
47efbb04 3073/**
3074* Function to check the passed address is within the passed subnet
3075*
3076* The parameter is a comma separated string of subnet definitions.
3077* Subnet strings can be in one of two formats:
3078* 1: xxx.xxx.xxx.xxx/xx
3079* 2: xxx.xxx
3080* Return boolean
3081* Code for type 1 modified from user posted comments by mediator at
3082* http://au.php.net/manual/en/function.ip2long.php
3083*
3084* @param addr the address you are checking
3085* @param subnetstr the string of subnet addresses
3086*/
3087
3088function address_in_subnet($addr, $subnetstr) {
3089
3090 $subnets = explode(",", $subnetstr);
3091 $found = false;
3092 $addr = trim($addr);
3093
3094 foreach ($subnets as $subnet) {
3095 $subnet = trim($subnet);
3096 if (strpos($subnet, "/") !== false) { /// type 1
3097
3098 list($ip, $mask) = explode('/', $subnet);
3099 $mask = 0xffffffff << (32 - $mask);
3100 $found = ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
3101
3102 } else { /// type 2
3103 $found = (strpos($addr, $subnet) === 0);
3104 }
3105
3106 if ($found) {
3107 continue;
3108 }
3109 }
3110
3111 return $found;
3112}
3113
defaac4c 3114function mtrace($string, $eol="\n") {
8f0cd6ef 3115// For outputting debugging info
622ebc6a 3116
3117 if (defined('STDOUT')) {
3118 fwrite(STDOUT, $string.$eol);
3119 } else {
3120 echo "$string$eol";
3121 }
3122
defaac4c 3123 flush();
3124}
3125
f97ab1ec 3126function getremoteaddr() {
3127//Returns most reliable client address
3128 if (getenv("HTTP_CLIENT_IP")) $ip = getenv("HTTP_CLIENT_IP");
3129 else if(getenv("HTTP_X_FORWARDED_FOR")) $ip = getenv("HTTP_X_FORWARDED_FOR");
3130 else if(getenv("REMOTE_ADDR")) $ip = getenv("REMOTE_ADDR");
3131 else $ip = false; //just in case
3132 return $ip;
3133}
defaac4c 3134
8f0cd6ef 3135if(!function_exists('html_entity_decode')) {
3136// html_entity_decode is only supported by php 4.3.0 and higher
3137// so if it is not predefined, define it here
3138 function html_entity_decode($string) {
3139 $trans_tbl = get_html_translation_table(HTML_ENTITIES);
3140 $trans_tbl = array_flip($trans_tbl);
3141 return strtr($string, $trans_tbl);
3142 }
3143}
3144
9d5b689c 3145// vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140:
d35757eb 3146?>