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