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