Tweaks
[moodle.git] / lib / moodlelib.php
CommitLineData
f9903ed0 1<?PHP // $Id$
2
9fa49e22 3///////////////////////////////////////////////////////////////////////////
4// //
5// moodlelib.php //
6// //
7// Main library file of miscellaneous general-purpose Moodle functions //
8// //
9// Other main libraries: //
10// //
11// weblib.php - functions that produce web output //
12// datalib.php - functions that access the database //
13// //
14///////////////////////////////////////////////////////////////////////////
15// //
16// NOTICE OF COPYRIGHT //
17// //
18// Moodle - Modular Object-Oriented Dynamic Learning Environment //
19// http://moodle.com //
20// //
21// Copyright (C) 2001-2003 Martin Dougiamas http://dougiamas.com //
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
f9903ed0 37
9fa49e22 38/// PARAMETER HANDLING ////////////////////////////////////////////////////
6b174680 39
9fa49e22 40function require_variable($var) {
41/// Variable must be present
42 if (! isset($var)) {
43 error("A required parameter was missing");
6b174680 44 }
45}
46
9fa49e22 47function optional_variable(&$var, $default=0) {
48/// Variable may be present, if not then set a default
49 if (! isset($var)) {
50 $var = $default;
6b174680 51 }
52}
53
54
9fa49e22 55function set_config($name, $value) {
56/// No need for get_config because they are usually always available in $CFG
42282810 57 global $CFG;
58
59 $CFG->$name = $value; // So it's defined for this invocation at least
dfc9ba9b 60
9fa49e22 61 if (get_field("config", "name", "name", $name)) {
62 return set_field("config", "value", $value, "name", $name);
d897cae4 63 } else {
9fa49e22 64 $config->name = $name;
65 $config->value = $value;
66 return insert_record("config", $config);
39917a09 67 }
39917a09 68}
69
39917a09 70
9fa49e22 71/// FUNCTIONS FOR HANDLING TIME ////////////////////////////////////////////
39917a09 72
3db75c62 73function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99) {
9fa49e22 74/// Given date parts in user time, produce a GMT timestamp
39917a09 75
94e34118 76 global $USER;
77
03c17ddf 78 if ($timezone == 99) {
94e34118 79 $timezone = (float)$USER->timezone;
80 }
81
82 if (abs($timezone) > 13) {
03c17ddf 83 return mktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
84 } else {
85 $time = gmmktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
86 return usertime($time, $timezone); // This is GMT
87 }
39917a09 88}
89
8dbed6be 90function format_time($totalsecs, $str=NULL) {
9fa49e22 91/// Given an amount of time in seconds, returns string
92/// formatted nicely as months, days, hours etc as needed
c7e3ac2a 93
6b174680 94 $totalsecs = abs($totalsecs);
c7e3ac2a 95
8dbed6be 96 if (!$str) { // Create the str structure the slow way
97 $str->day = get_string("day");
98 $str->days = get_string("days");
99 $str->hour = get_string("hour");
100 $str->hours = get_string("hours");
101 $str->min = get_string("min");
102 $str->mins = get_string("mins");
103 $str->sec = get_string("sec");
104 $str->secs = get_string("secs");
105 }
106
107 $days = floor($totalsecs/86400);
6b174680 108 $remainder = $totalsecs - ($days*86400);
8dbed6be 109 $hours = floor($remainder/3600);
6b174680 110 $remainder = $remainder - ($hours*3600);
8dbed6be 111 $mins = floor($remainder/60);
112 $secs = $remainder - ($mins*60);
113
114 $ss = ($secs == 1) ? $str->sec : $str->secs;
115 $sm = ($mins == 1) ? $str->min : $str->mins;
116 $sh = ($hours == 1) ? $str->hour : $str->hours;
117 $sd = ($days == 1) ? $str->day : $str->days;
118
9c9f7d77 119 $odays = "";
120 $ohours = "";
121 $omins = "";
122 $osecs = "";
123
8dbed6be 124 if ($days) $odays = "$days $sd";
125 if ($hours) $ohours = "$hours $sh";
126 if ($mins) $omins = "$mins $sm";
127 if ($secs) $osecs = "$secs $ss";
6b174680 128
129 if ($days) return "$odays $ohours";
130 if ($hours) return "$ohours $omins";
131 if ($mins) return "$omins $osecs";
132 if ($secs) return "$osecs";
133 return get_string("now");
134}
f9903ed0 135
61ae5d36 136function userdate($date, $format="", $timezone=99, $fixday = true) {
9fa49e22 137/// Returns a formatted string that represents a date in user time
138/// WARNING: note that the format is for strftime(), not date().
139/// Because of a bug in most Windows time libraries, we can't use
140/// the nicer %e, so we have to use %d which has leading zeroes.
141/// A lot of the fuss below is just getting rid of these leading
142/// zeroes as efficiently as possible.
61ae5d36 143///
144/// If parammeter fixday = true (default), then take off leading
145/// zero from %d, else mantain it.
7a302afc 146
873960de 147 global $USER;
148
5fa51a39 149 if ($format == "") {
dcde9f02 150 $format = get_string("strftimedaydatetime");
5fa51a39 151 }
035cdbff 152
dcde9f02 153 $formatnoday = str_replace("%d", "DD", $format);
61ae5d36 154 if ($fixday) {
155 $fixday = ($formatnoday != $format);
156 }
dcde9f02 157
5fa51a39 158 if ($timezone == 99) {
ab247495 159 if (isset($USER->timezone)) {
160 $timezone = (float)$USER->timezone;
161 }
5fa51a39 162 }
0431bd7c 163 if (abs($timezone) > 13) {
035cdbff 164 if ($fixday) {
165 $datestring = strftime($formatnoday, $date);
166 $daystring = str_replace(" 0", "", strftime(" %d", $date));
167 $datestring = str_replace("DD", $daystring, $datestring);
168 } else {
169 $datestring = strftime($format, $date);
170 }
bea7a51e 171 } else {
70d4cf82 172 $date = $date + (int)($timezone * 3600);
035cdbff 173 if ($fixday) {
70d4cf82 174 $datestring = gmstrftime($formatnoday, $date);
9fa49e22 175 $daystring = str_replace(" 0", "", gmstrftime(" %d", $date));
035cdbff 176 $datestring = str_replace("DD", $daystring, $datestring);
177 } else {
70d4cf82 178 $datestring = gmstrftime($format, $date);
035cdbff 179 }
873960de 180 }
bea7a51e 181
035cdbff 182 return $datestring;
873960de 183}
184
5fa51a39 185function usergetdate($date, $timezone=99) {
9fa49e22 186/// Given a $date timestamp in GMT, returns an array
187/// that represents the date in user time
6b174680 188
873960de 189 global $USER;
190
5fa51a39 191 if ($timezone == 99) {
192 $timezone = (float)$USER->timezone;
193 }
0431bd7c 194 if (abs($timezone) > 13) {
873960de 195 return getdate($date);
196 }
d2d6171f 197 //There is no gmgetdate so I have to fake it...
198 $date = $date + (int)($timezone * 3600);
199 $getdate["seconds"] = gmstrftime("%S", $date);
200 $getdate["minutes"] = gmstrftime("%M", $date);
201 $getdate["hours"] = gmstrftime("%H", $date);
202 $getdate["mday"] = gmstrftime("%d", $date);
203 $getdate["wday"] = gmstrftime("%u", $date);
204 $getdate["mon"] = gmstrftime("%m", $date);
205 $getdate["year"] = gmstrftime("%Y", $date);
206 $getdate["yday"] = gmstrftime("%j", $date);
207 $getdate["weekday"] = gmstrftime("%A", $date);
208 $getdate["month"] = gmstrftime("%B", $date);
209 return $getdate;
d552ead0 210}
211
212function usertime($date, $timezone=99) {
9fa49e22 213/// Given a GMT timestamp (seconds since epoch), offsets it by
214/// the timezone. eg 3pm in India is 3pm GMT - 7 * 3600 seconds
d552ead0 215 global $USER;
216
217 if ($timezone == 99) {
218 $timezone = (float)$USER->timezone;
219 }
0431bd7c 220 if (abs($timezone) > 13) {
d552ead0 221 return $date;
222 }
223 return $date - (int)($timezone * 3600);
224}
225
edf7fe8c 226function usergetmidnight($date, $timezone=99) {
9fa49e22 227/// Given a time, return the GMT timestamp of the most recent midnight
228/// for the current user.
edf7fe8c 229 global $USER;
230
4606d9bb 231 if ($timezone == 99) {
232 $timezone = (float)$USER->timezone;
233 }
234
edf7fe8c 235 $userdate = usergetdate($date, $timezone);
4606d9bb 236
0431bd7c 237 if (abs($timezone) > 13) {
4606d9bb 238 return mktime(0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
239 }
240
edf7fe8c 241 $timemidnight = gmmktime (0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
242 return usertime($timemidnight, $timezone); // Time of midnight of this user's day, in GMT
243
244}
245
d552ead0 246function usertimezone($timezone=99) {
9fa49e22 247/// Returns a string that prints the user's timezone
d552ead0 248 global $USER;
249
250 if ($timezone == 99) {
251 $timezone = (float)$USER->timezone;
252 }
0431bd7c 253 if (abs($timezone) > 13) {
d552ead0 254 return "server time";
255 }
256 if (abs($timezone) < 0.5) {
257 return "GMT";
258 }
259 if ($timezone > 0) {
260 return "GMT+$timezone";
261 } else {
262 return "GMT$timezone";
263 }
f9903ed0 264}
265
266
9fa49e22 267/// USER AUTHENTICATION AND LOGIN ////////////////////////////////////////
f9903ed0 268
da5c172a 269function require_login($courseid=0) {
9fa49e22 270/// This function checks that the current user is logged in, and optionally
271/// whether they are "logged in" or allowed to be in a particular course.
272/// If not, then it redirects them to the site login or course enrolment.
f9903ed0 273
73047f2f 274 global $CFG, $SESSION, $USER, $FULLME, $MoodleSession;
f9903ed0 275
da5c172a 276 // First check that the user is logged in to the site.
c21c671d 277 if (! (isset($USER->loggedin) and $USER->confirmed and ($USER->site == $CFG->wwwroot)) ) { // They're not
f9903ed0 278 $SESSION->wantsurl = $FULLME;
9f44d972 279 if (!empty($_SERVER["HTTP_REFERER"])) {
280 $SESSION->fromurl = $_SERVER["HTTP_REFERER"];
281 }
c21c671d 282 $USER = NULL;
73047f2f 283 redirect("$CFG->wwwroot/login/index.php");
f9903ed0 284 die;
f9903ed0 285 }
808a3baa 286
287 // Check that the user account is properly set up
288 if (user_not_fully_set_up($USER)) {
289 $site = get_site();
290 redirect("$CFG->wwwroot/user/edit.php?id=$USER->id&course=$site->id");
291 die;
292 }
da5c172a 293
294 // Next, check if the user can be in a particular course
295 if ($courseid) {
9c9f7d77 296 if (!empty($USER->student[$courseid]) or !empty($USER->teacher[$courseid]) or !empty($USER->admin)) {
cb909d74 297 if (isset($USER->realuser)) { // Make sure the REAL person can also access this course
298 if (!isteacher($courseid, $USER->realuser)) {
299 print_header();
0b4c5822 300 notice(get_string("studentnotallowed", "", fullname($USER, true)), $CFG->wwwroot);
cb909d74 301 }
302
303 } else { // just update their last login time
3ce2f1e0 304 update_user_in_db();
305 }
da5c172a 306 return; // user is a member of this course.
307 }
308 if (! $course = get_record("course", "id", $courseid)) {
309 error("That course doesn't exist");
310 }
1efa27fd 311 if (!$course->visible) {
312 print_header();
0b4c5822 313 notice(get_string("studentnotallowed", "", fullname($USER, true)), $CFG->wwwroot);
1efa27fd 314 }
7363ff91 315 if ($USER->username == "guest") {
316 switch ($course->guest) {
317 case 0: // Guests not allowed
318 print_header();
319 notice(get_string("guestsnotallowed", "", $course->fullname));
320 break;
321 case 1: // Guests allowed
322 update_user_in_db();
323 return;
324 case 2: // Guests allowed with key (drop through)
325 break;
326 }
da5c172a 327 }
f9903ed0 328
7363ff91 329 // Currently not enrolled in the course, so see if they want to enrol
da5c172a 330 $SESSION->wantsurl = $FULLME;
331 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
332 die;
333 }
f9903ed0 334}
335
1d881d92 336function update_user_login_times() {
337 global $USER;
338
339 $USER->lastlogin = $user->lastlogin = $USER->currentlogin;
340 $USER->currentlogin = $user->currentlogin = time();
1d881d92 341
342 $user->id = $USER->id;
343
344 return update_record("user", $user);
345}
346
808a3baa 347function user_not_fully_set_up($user) {
ac5d88eb 348 return ($user->username != "guest" and (empty($user->firstname) or empty($user->lastname) or empty($user->email)));
808a3baa 349}
f9903ed0 350
f9903ed0 351function update_login_count() {
9fa49e22 352/// Keeps track of login attempts
353
f9903ed0 354 global $SESSION;
355
356 $max_logins = 10;
357
358 if (empty($SESSION->logincount)) {
359 $SESSION->logincount = 1;
360 } else {
361 $SESSION->logincount++;
362 }
363
364 if ($SESSION->logincount > $max_logins) {
9fa49e22 365 unset($SESSION->wantsurl);
1d881d92 366 error(get_string("errortoomanylogins"));
d578afc8 367 }
368}
369
9fa49e22 370function reset_login_count() {
371/// Resets login attempts
372 global $SESSION;
d578afc8 373
9fa49e22 374 $SESSION->logincount = 0;
d578afc8 375}
376
581d7b49 377function isadmin($userid=0) {
9fa49e22 378/// Is the user an admin?
f9903ed0 379 global $USER;
aa095969 380 static $admins = array();
381 static $nonadmins = array();
f9903ed0 382
581d7b49 383 if (!$userid){
384 if (empty($USER->id)) {
385 return false;
386 }
387 $userid = $USER->id;
9bd2c874 388 }
389
581d7b49 390 if (in_array($userid, $admins)) {
aa095969 391 return true;
581d7b49 392 } else if (in_array($userid, $nonadmins)) {
aa095969 393 return false;
581d7b49 394 } else if (record_exists("user_admins", "userid", $userid)){
395 $admins[] = $userid;
aa095969 396 return true;
397 } else {
581d7b49 398 $nonadmins[] = $userid;
aa095969 399 return false;
f9903ed0 400 }
f9903ed0 401}
402
9788367b 403function isteacher($courseid, $userid=0, $includeadmin=true) {
9fa49e22 404/// Is the user a teacher or admin?
f9903ed0 405 global $USER;
406
9788367b 407 if ($includeadmin and isadmin($userid)) { // admins can do anything the teacher can
d115a57f 408 return true;
409 }
410
f9903ed0 411 if (!$userid) {
9bd2c874 412 return !empty($USER->teacher[$courseid]);
f9903ed0 413 }
414
ebc3bd2b 415 return record_exists("user_teachers", "userid", $userid, "course", $courseid);
f9903ed0 416}
417
73047f2f 418function isteacheredit($courseid, $userid=0) {
419/// Is the user allowed to edit this course?
420 global $USER;
421
422 if (isadmin($userid)) { // admins can do anything
423 return true;
424 }
425
426 if (!$userid) {
427 return !empty($USER->teacheredit[$courseid]);
428 }
429
430 return get_field("user_teachers", "editall", "userid", $userid, "course", $courseid);
431}
432
1924074c 433function iscreator ($userid=0) {
434/// Can user create new courses?
435 global $USER;
8a205861 436 if (empty($USER->id)) {
437 return false;
438 }
1924074c 439 if (isadmin($userid)) { // admins can do anything
440 return true;
441 }
8a205861 442 if (empty($userid)) {
1924074c 443 return record_exists("user_coursecreators", "userid", $USER->id);
444 }
445
446 return record_exists("user_coursecreators", "userid", $userid);
447}
448
8a9e3fd7 449function isstudent($courseid, $userid=0) {
9fa49e22 450/// Is the user a student in this course?
f9903ed0 451 global $USER;
452
453 if (!$userid) {
346b1a24 454 return !empty($USER->student[$courseid]);
f9903ed0 455 }
456
ebc3bd2b 457 // $timenow = time(); // todo: add time check below
f9903ed0 458
ebc3bd2b 459 return record_exists("user_students", "userid", $userid, "course", $courseid);
f9903ed0 460}
461
da5c172a 462function isguest($userid=0) {
9fa49e22 463/// Is the user a guest?
da5c172a 464 global $USER;
465
466 if (!$userid) {
b35e8568 467 if (empty($USER->username)) {
468 return false;
469 }
da5c172a 470 return ($USER->username == "guest");
471 }
472
9fa49e22 473 return record_exists("user", "id", $userid, "username", "guest");
da5c172a 474}
475
9fa49e22 476
2c309dc2 477function isediting($courseid, $user=NULL) {
9fa49e22 478/// Is the current user in editing mode?
2c309dc2 479 global $USER;
480 if (!$user){
481 $user = $USER;
482 }
9c9f7d77 483 if (empty($user->editing)) {
484 return false;
485 }
2c309dc2 486 return ($user->editing and isteacher($courseid, $user->id));
487}
488
7977cffd 489function ismoving($courseid) {
490/// Is the current user currently moving an activity?
491 global $USER;
492
493 if (!empty($USER->activitycopy)) {
494 return ($USER->activitycopycourse == $courseid);
495 }
496 return false;
497}
498
e2cd5065 499function fullname($user, $override=false) {
500/// Given a user object, this function returns a
501/// string with the full name of the person.
502/// The result may depend on system settings
503/// or language. Override will force both names
504/// to be used even if system settings specify one.
505 global $CFG;
506
507 /// XXX
508 /// XXX this function is not finished yet!
509 /// XXX
510
511 return "$user->firstname $user->lastname";
512
513}
514
f9903ed0 515
516function set_moodle_cookie($thing) {
9fa49e22 517/// Sets a moodle cookie with an encrypted string
7185e073 518 global $CFG;
482b6e6e 519
520 $cookiename = 'MOODLEID_'.$CFG->sessioncookie;
f9903ed0 521
522 $days = 60;
523 $seconds = 60*60*24*$days;
524
7185e073 525 setCookie($cookiename, "", time() - 3600, "/");
526 setCookie($cookiename, rc4encrypt($thing), time()+$seconds, "/");
f9903ed0 527}
528
529
530function get_moodle_cookie() {
9fa49e22 531/// Gets a moodle cookie with an encrypted string
7185e073 532 global $CFG;
533
482b6e6e 534 $cookiename = 'MOODLEID_'.$CFG->sessioncookie;
7185e073 535
1079c8a8 536 if (empty($_COOKIE[$cookiename])) {
537 return "";
538 } else {
539 return rc4decrypt($_COOKIE[$cookiename]);
540 }
f9903ed0 541}
542
ba7166c3 543function is_internal_auth() {
544/// Returns true if an internal authentication method is being used.
545
546 global $CFG;
547
548 return ($CFG->auth == "email" || $CFG->auth == "none" || $CFG->auth == "manual");
549}
f9903ed0 550
faebaf0f 551function create_user_record($username, $password) {
9fa49e22 552/// Creates a bare-bones user record
e858f9da 553 global $REMOTE_ADDR, $CFG;
1e22bc9c 554 //just in case check text case
555 $username = trim(moodle_strtolower($username));
6ae24de0 556 if (function_exists(auth_get_userinfo)) {
e858f9da 557 if ($newinfo = auth_get_userinfo($username)) {
34daec9b 558 foreach ($newinfo as $key => $value){
9f44d972 559 $newuser->$key = addslashes(stripslashes($value)); // Just in case
e858f9da 560 }
561 }
562 }
f9903ed0 563
faebaf0f 564 $newuser->username = $username;
565 $newuser->password = md5($password);
a0bac19d 566 $newuser->lang = $CFG->lang;
faebaf0f 567 $newuser->confirmed = 1;
568 $newuser->lastIP = $REMOTE_ADDR;
569 $newuser->timemodified = time();
f9903ed0 570
faebaf0f 571 if (insert_record("user", $newuser)) {
572 return get_user_info_from_db("username", $username);
573 }
574 return false;
575}
576
577function authenticate_user_login($username, $password) {
9fa49e22 578/// Given a username and password, this function looks them
579/// up using the currently selected authentication mechanism,
580/// and if the authentication is successful, it returns a
581/// valid $user object from the 'user' table.
582///
583/// Uses auth_ functions from the currently active auth module
faebaf0f 584
585 global $CFG;
586
466558e3 587 $md5password = md5($password);
588
14217044 589 if (empty($CFG->auth)) {
faebaf0f 590 $CFG->auth = "email"; // Default authentication module
591 }
592
466558e3 593 if ($username == "guest") {
594 $CFG->auth = "none"; // Guest account always internal
595 }
596
597 // If this is the admin, then just use internal methods
92710226 598 // Doing this first (even though it's less efficient) because
599 // the chosen authentication method might hang and lock the
600 // admin out.
9fa49e22 601 if (adminlogin($username, $md5password)) {
466558e3 602 return get_user_info_from_db("username", $username);
603 }
604
92710226 605 // OK, the user is a normal user, so try and authenticate them
e858f9da 606 require_once("$CFG->dirroot/auth/$CFG->auth/lib.php");
faebaf0f 607
608 if (auth_user_login($username, $password)) { // Successful authentication
faebaf0f 609 if ($user = get_user_info_from_db("username", $username)) {
92710226 610 if ($md5password <> $user->password) { // Update local copy of password for reference
466558e3 611 set_field("user", "password", $md5password, "username", $username);
faebaf0f 612 }
faebaf0f 613 } else {
e582b65e 614 $user = create_user_record($username, $password);
faebaf0f 615 }
89b54325 616
e582b65e 617 if (function_exists('auth_iscreator')) { // Check if the user is a creator
618 if (auth_iscreator($username)) {
619 if (! record_exists("user_coursecreators", "userid", $user->id)) {
620 $cdata['userid']=$user->id;
621 $creator = insert_record("user_coursecreators",$cdata);
622 if (! $creator) {
623 error("Cannot add user to course creators.");
624 }
625 }
626 } else {
627 if ( record_exists("user_coursecreators", "userid", $user->id)) {
f5cdd4d1 628 $creator = delete_records("user_coursecreators", "userid", $user->id);
e582b65e 629 if (! $creator) {
630 error("Cannot remove user from course creators.");
631 }
632 }
633 }
634 }
635
636 return $user;
637 } else {
638 return false;
639 }
f9903ed0 640}
641
4d312bbe 642function enrol_student($userid, $courseid) {
9fa49e22 643/// Enrols a student in a given course
f9903ed0 644
4d312bbe 645 if (!record_exists("user_students", "userid", $userid, "course", $courseid)) {
3041b0f8 646 if (record_exists("user", "id", $userid)) {
647 $student->userid = $userid;
648 $student->course = $courseid;
649 $student->start = 0;
650 $student->end = 0;
651 $student->time = time();
652 return insert_record("user_students", $student);
653 }
654 return false;
4d312bbe 655 }
656 return true;
d7facad8 657}
658
9fa49e22 659function unenrol_student($user, $course=0) {
660/// Unenrols a student from a given course
d7facad8 661
9fa49e22 662 if ($course) {
663 /// First delete any crucial stuff that might still send mail
664 if ($forums = get_records("forum", "course", $course)) {
665 foreach ($forums as $forum) {
ebc3bd2b 666 delete_records("forum_subscriptions", "forum", $forum->id, "userid", $user);
bb09fb11 667 }
f9903ed0 668 }
ebc3bd2b 669 return delete_records("user_students", "userid", $user, "course", $course);
9fa49e22 670
f9903ed0 671 } else {
ebc3bd2b 672 delete_records("forum_subscriptions", "userid", $user);
673 return delete_records("user_students", "userid", $user);
f9903ed0 674 }
675}
676
3041b0f8 677function add_teacher($userid, $courseid) {
678/// Add a teacher to a given course
679
680 if (!record_exists("user_teachers", "userid", $userid, "course", $courseid)) {
681 if (record_exists("user", "id", $userid)) {
682 $teacher->userid = $userid;
683 $teacher->course = $courseid;
684 $teacher->editall = 1;
685 $teacher->role = "";
686 if (record_exists("user_teachers", "course", $courseid)) {
687 $teacher->authority = 2;
688 } else {
689 $teacher->authority = 1;
690 }
691 return insert_record("user_teachers", $teacher);
692 }
693 return false;
694 }
695 return true;
696}
697
698function remove_teacher($userid, $courseid=0) {
9fa49e22 699/// Removes a teacher from a given course (or ALL courses)
700/// Does not delete the user account
3041b0f8 701 if ($courseid) {
9fa49e22 702 /// First delete any crucial stuff that might still send mail
3041b0f8 703 if ($forums = get_records("forum", "course", $courseid)) {
9fa49e22 704 foreach ($forums as $forum) {
3041b0f8 705 delete_records("forum_subscriptions", "forum", $forum->id, "userid", $userid);
9fa49e22 706 }
707 }
3041b0f8 708 return delete_records("user_teachers", "userid", $userid, "course", $courseid);
57507290 709 } else {
3041b0f8 710 delete_records("forum_subscriptions", "userid", $userid);
711 return delete_records("user_teachers", "userid", $userid);
57507290 712 }
f9903ed0 713}
714
3041b0f8 715
716function add_creator($userid) {
717/// Add a creator to the site
718
719 if (!record_exists("user_admins", "userid", $userid)) {
720 if (record_exists("user", "id", $userid)) {
721 $creator->userid = $userid;
722 return insert_record("user_coursecreators", $creator);
723 }
724 return false;
725 }
726 return true;
727}
728
729function remove_creator($userid) {
730/// Removes a creator from a site
731 global $db;
732
733 return delete_records("user_coursecreators", "userid", $userid);
734}
735
736function add_admin($userid) {
737/// Add an admin to the site
738
739 if (!record_exists("user_admins", "userid", $userid)) {
740 if (record_exists("user", "id", $userid)) {
741 $admin->userid = $userid;
742 return insert_record("user_admins", $admin);
743 }
744 return false;
745 }
746 return true;
747}
748
749function remove_admin($userid) {
9fa49e22 750/// Removes an admin from a site
751 global $db;
f9903ed0 752
3041b0f8 753 return delete_records("user_admins", "userid", $userid);
f9903ed0 754}
755
f9903ed0 756
07aeb7b0 757function remove_course_contents($courseid, $showfeedback=true) {
758/// Clear a course out completely, deleting all content
759/// but don't delete the course itself
760
ee23f384 761 global $CFG, $THEME, $USER, $SESSION;
07aeb7b0 762
763 $result = true;
764
765 if (! $course = get_record("course", "id", $courseid)) {
766 error("Course ID was incorrect (can't find it)");
767 }
768
769 $strdeleted = get_string("deleted");
770
771 // First delete every instance of every module
772
773 if ($allmods = get_records("modules") ) {
774 foreach ($allmods as $mod) {
775 $modname = $mod->name;
776 $modfile = "$CFG->dirroot/mod/$modname/lib.php";
777 $moddelete = $modname."_delete_instance";
778 $count=0;
779 if (file_exists($modfile)) {
780 include_once($modfile);
781 if (function_exists($moddelete)) {
782 if ($instances = get_records($modname, "course", $course->id)) {
783 foreach ($instances as $instance) {
784 if ($moddelete($instance->id)) {
785 $count++;
786 } else {
787 notify("Could not delete $modname instance $instance->id ($instance->name)");
788 $result = false;
789 }
790 }
791 }
792 } else {
793 notify("Function $moddelete() doesn't exist!");
794 $result = false;
795 }
796
797 }
798 if ($showfeedback) {
799 notify("$strdeleted $count x $modname");
800 }
801 }
802 } else {
803 error("No modules are installed!");
804 }
805
806 // Delete any user stuff
807
808 if (delete_records("user_students", "course", $course->id)) {
809 if ($showfeedback) {
810 notify("$strdeleted user_students");
811 }
812 } else {
813 $result = false;
814 }
815
816 if (delete_records("user_teachers", "course", $course->id)) {
817 if ($showfeedback) {
818 notify("$strdeleted user_teachers");
819 }
820 } else {
821 $result = false;
822 }
823
824 // Delete logs
825
826 if (delete_records("log", "course", $course->id)) {
827 if ($showfeedback) {
828 notify("$strdeleted log");
829 }
830 } else {
831 $result = false;
832 }
833
834 // Delete any course stuff
835
836 if (delete_records("course_sections", "course", $course->id)) {
837 if ($showfeedback) {
838 notify("$strdeleted course_sections");
839 }
840 } else {
841 $result = false;
842 }
843
844 if (delete_records("course_modules", "course", $course->id)) {
845 if ($showfeedback) {
846 notify("$strdeleted course_modules");
847 }
848 } else {
849 $result = false;
850 }
851
852 return $result;
853
854}
855
f9903ed0 856
f9903ed0 857/// CORRESPONDENCE ////////////////////////////////////////////////
858
5fa51a39 859function email_to_user($user, $from, $subject, $messagetext, $messagehtml="", $attachment="", $attachname="") {
9fa49e22 860/// user - a user record as an object
861/// from - a user record as an object
862/// subject - plain text subject line of the email
863/// messagetext - plain text version of the message
864/// messagehtml - complete html version of the message (optional)
865/// attachment - a file on the filesystem, relative to $CFG->dataroot
866/// attachname - the name of the file (extension indicates MIME)
f9903ed0 867
4216daa6 868 global $CFG, $_SERVER;
f9903ed0 869
136dabd8 870 include_once("$CFG->libdir/phpmailer/class.phpmailer.php");
f9903ed0 871
5fa51a39 872 if (!$user) {
f9903ed0 873 return false;
874 }
875
f9903ed0 876 $mail = new phpmailer;
877
72c578ca 878 $mail->Version = "Moodle $CFG->version"; // mailer version
136dabd8 879 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
562bbe90 880
98c4eae3 881
d483bcd3 882 if (current_language() != "en") {
883 $mail->CharSet = get_string("thischarset");
98c4eae3 884 }
885
62740736 886 if ($CFG->smtphosts == "qmail") {
887 $mail->IsQmail(); // use Qmail system
888
889 } else if (empty($CFG->smtphosts)) {
890 $mail->IsMail(); // use PHP mail() = sendmail
891
892 } else {
1e411ffc 893 $mail->IsSMTP(); // use SMTP directly
57ef3480 894 if ($CFG->debug > 7) {
895 echo "<pre>\n";
896 $mail->SMTPDebug = true;
897 }
1e411ffc 898 $mail->Host = "$CFG->smtphosts"; // specify main and backup servers
9f58537a 899
900 if ($CFG->smtpuser) { // Use SMTP authentication
901 $mail->SMTPAuth = true;
902 $mail->Username = $CFG->smtpuser;
903 $mail->Password = $CFG->smtppass;
904 }
7f86ce17 905 }
f9903ed0 906
2b97bd71 907 $adminuser = get_admin();
908
909 $mail->Sender = "$adminuser->email";
910
136dabd8 911 $mail->From = "$from->email";
0b4c5822 912 $mail->FromName = fullname($from);
136dabd8 913 $mail->Subject = stripslashes($subject);
f9903ed0 914
0b4c5822 915 $mail->AddAddress("$user->email", fullname($user) );
f9903ed0 916
f9903ed0 917 $mail->WordWrap = 70; // set word wrap
f9903ed0 918
136dabd8 919 if ($messagehtml) {
920 $mail->IsHTML(true);
125898af 921 $mail->Encoding = "quoted-printable"; // Encoding to use
136dabd8 922 $mail->Body = $messagehtml;
78681899 923 $mail->AltBody = "\n$messagetext\n";
136dabd8 924 } else {
925 $mail->IsHTML(false);
78681899 926 $mail->Body = "\n$messagetext\n";
f9903ed0 927 }
928
136dabd8 929 if ($attachment && $attachname) {
930 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
0b4c5822 931 $mail->AddAddress("$adminuser->email", fullname($adminuser) );
4216daa6 932 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
136dabd8 933 } else {
934 include_once("$CFG->dirroot/files/mimetypes.php");
935 $mimetype = mimeinfo("type", $attachname);
936 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
937 }
f9903ed0 938 }
939
136dabd8 940 if ($mail->Send()) {
941 return true;
942 } else {
4216daa6 943 echo "ERROR: $mail->ErrorInfo\n";
944 $site = get_site();
945 add_to_log($site->id, "library", "mailer", $_SERVER["REQUEST_URI"], "ERROR: $mail->ErrorInfo");
f9903ed0 946 return false;
947 }
f9903ed0 948}
949
1d881d92 950function reset_password_and_mail($user) {
951
952 global $CFG;
953
954 $site = get_site();
955 $from = get_admin();
956
957 $newpassword = generate_password();
958
959 if (! set_field("user", "password", md5($newpassword), "id", $user->id) ) {
960 error("Could not set user password!");
961 }
962
963 $a->firstname = $user->firstname;
964 $a->sitename = $site->fullname;
965 $a->username = $user->username;
966 $a->newpassword = $newpassword;
967 $a->link = "$CFG->wwwroot/login/change_password.php";
0b4c5822 968 $a->signoff = fullname($from, true)." ($from->email)";
1d881d92 969
970 $message = get_string("newpasswordtext", "", $a);
971
972 $subject = "$site->fullname: ".get_string("changedpassword");
973
974 return email_to_user($user, $from, $subject, $message);
975
976}
977
978function send_confirmation_email($user) {
979
980 global $CFG;
981
982 $site = get_site();
983 $from = get_admin();
984
985 $data->firstname = $user->firstname;
986 $data->sitename = $site->fullname;
987 $data->link = "$CFG->wwwroot/login/confirm.php?p=$user->secret&s=$user->username";
0b4c5822 988 $data->admin = fullname($from)." ($from->email)";
1d881d92 989
990 $message = get_string("emailconfirmation", "", $data);
eb347b6b 991 $subject = get_string("emailconfirmationsubject", "", $site->fullname);
1d881d92 992
993 return email_to_user($user, $from, $subject, $message);
994
995}
996
eb347b6b 997function send_password_change_confirmation_email($user) {
998
999 global $CFG;
1000
1001 $site = get_site();
1002 $from = get_admin();
1003
1004 $data->firstname = $user->firstname;
1005 $data->sitename = $site->fullname;
1006 $data->link = "$CFG->wwwroot/login/forgot_password.php?p=$user->secret&s=$user->username";
0b4c5822 1007 $data->admin = fullname($from)." ($from->email)";
eb347b6b 1008
1009 $message = get_string("emailpasswordconfirmation", "", $data);
1010 $subject = get_string("emailpasswordconfirmationsubject", "", $site->fullname);
1011
1012 return email_to_user($user, $from, $subject, $message);
1013
1014}
1015
1016
1d881d92 1017
136dabd8 1018
f9903ed0 1019/// FILE HANDLING /////////////////////////////////////////////
1020
6b174680 1021function make_upload_directory($directory) {
9fa49e22 1022/// $directory = a string of directory names under $CFG->dataroot
1023/// eg stuff/assignment/1
1024/// Returns full directory if successful, false if not
6b174680 1025
1026 global $CFG;
1027
1028 $currdir = $CFG->dataroot;
fe287429 1029
2e6d4273 1030 umask(0000);
1031
6b174680 1032 if (!file_exists($currdir)) {
2e6d4273 1033 if (! mkdir($currdir, $CFG->directorypermissions)) {
6b174680 1034 notify("ERROR: You need to create the directory $currdir with web server write access");
1035 return false;
1036 }
1037 }
1038
1039 $dirarray = explode("/", $directory);
1040
1041 foreach ($dirarray as $dir) {
1042 $currdir = "$currdir/$dir";
1043 if (! file_exists($currdir)) {
2e6d4273 1044 if (! mkdir($currdir, $CFG->directorypermissions)) {
6b174680 1045 notify("ERROR: Could not find or create a directory ($currdir)");
1046 return false;
1047 }
feffa4e6 1048 @chmod($currdir, $CFG->directorypermissions); // Just in case mkdir didn't do it
6b174680 1049 }
1050 }
1051
1052 return $currdir;
1053}
1054
ca4f8eb8 1055function make_mod_upload_directory($courseid) {
9fa49e22 1056/// Makes an upload directory for a particular module
ca4f8eb8 1057 global $CFG;
1058
1059 if (! $moddata = make_upload_directory("$courseid/$CFG->moddata")) {
1060 return false;
1061 }
1062
1063 $strreadme = get_string("readme");
1064
1065 if (file_exists("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt")) {
1066 copy("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt", "$moddata/$strreadme.txt");
1067 } else {
1068 copy("$CFG->dirroot/lang/en/docs/module_files.txt", "$moddata/$strreadme.txt");
1069 }
1070 return $moddata;
1071}
1072
6b174680 1073
44e2d2bb 1074function valid_uploaded_file($newfile) {
9fa49e22 1075/// Returns current name of file on disk if true
9c9f7d77 1076 if (empty($newfile)) {
1077 return "";
1078 }
44e2d2bb 1079 if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
1080 return $newfile['tmp_name'];
1081 } else {
1082 return "";
1083 }
1084}
1085
4909e176 1086function get_max_upload_file_size($sitebytes=0, $coursebytes=0, $modulebytes=0) {
9fa49e22 1087/// Returns the maximum size for uploading files
4909e176 1088/// There are six possible upload limits:
1089///
1090/// 1) in Apache using LimitRequestBody (no way of checking or changing this)
1091/// 2) in php.ini for 'upload_max_filesize' (can not be changed inside PHP)
1092/// 3) in .htaccess for 'upload_max_filesize' (can not be changed inside PHP)
1093/// 4) by the Moodle admin in $CFG->maxbytes
1094/// 5) by the teacher in the current course $course->maxbytes
1095/// 6) by the teacher for the current module, eg $assignment->maxbytes
1096///
1097/// These last two are passed to this function as arguments (in bytes).
1098/// Anything defined as 0 is ignored.
1099/// The smallest of all the non-zero numbers is returned.
1100
44e2d2bb 1101 if (! $filesize = ini_get("upload_max_filesize")) {
1102 $filesize = "5M";
1103 }
4909e176 1104 $minimumsize = get_real_size($filesize);
1105
1106 if ($sitebytes and $sitebytes < $minimumsize) {
1107 $minimumsize = $sitebytes;
1108 }
1109
1110 if ($coursebytes and $coursebytes < $minimumsize) {
1111 $minimumsize = $coursebytes;
1112 }
1113
1114 if ($modulebytes and $modulebytes < $minimumsize) {
1115 $minimumsize = $modulebytes;
1116 }
1117
1118 return $minimumsize;
1119}
1120
1121function get_max_upload_sizes($sitebytes=0, $coursebytes=0, $modulebytes=0) {
1122/// Related to the above function - this function returns an
1123/// array of possible sizes in an array, translated to the
1124/// local language.
1125
1126 if (!$maxsize = get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes)) {
1127 return array();
1128 }
1129
1130 $filesize[$maxsize] = display_size($maxsize);
1131
1132 $sizelist = array(10240, 51200, 102400, 512000, 1048576, 2097152,
1133 5242880, 10485760, 20971520, 52428800, 104857600);
1134
1135 foreach ($sizelist as $sizebytes) {
1136 if ($sizebytes < $maxsize) {
1137 $filesize[$sizebytes] = display_size($sizebytes);
1138 }
1139 }
1140
1141 krsort($filesize, SORT_NUMERIC);
1142
1143 return $filesize;
44e2d2bb 1144}
1145
774ab660 1146function get_directory_list($rootdir, $excludefile="", $descend=true) {
9fa49e22 1147/// Returns an array with all the filenames in
1148/// all subdirectories, relative to the given rootdir.
1149/// If excludefile is defined, then that file/directory is ignored
f9903ed0 1150
1151 $dirs = array();
f9903ed0 1152
12407705 1153 if (!is_dir($rootdir)) {
1154 return $dirs;
1155 }
1156
487c1711 1157 if (!$dir = opendir($rootdir)) {
d897cae4 1158 return $dirs;
1159 }
1160
ca4f8eb8 1161 while ($file = readdir($dir)) {
b35e8568 1162 $firstchar = substr($file, 0, 1);
1163 if ($firstchar == "." or $file == "CVS" or $file == $excludefile) {
1164 continue;
1165 }
1166 $fullfile = $rootdir."/".$file;
1167 if ($descend and filetype($fullfile) == "dir") {
1168 $subdirs = get_directory_list($fullfile, $excludefile, $descend);
1169 foreach ($subdirs as $subdir) {
1170 $dirs[] = $file."/".$subdir;
f9903ed0 1171 }
b35e8568 1172 } else {
1173 $dirs[] = $file;
f9903ed0 1174 }
1175 }
44e2d2bb 1176 closedir($dir);
f9903ed0 1177
774ab660 1178 asort($dirs);
1179
f9903ed0 1180 return $dirs;
1181}
1182
989bfa9d 1183function get_real_size($size=0) {
9fa49e22 1184/// Converts numbers like 10M into bytes
989bfa9d 1185 if (!$size) {
1186 return 0;
1187 }
1188 $scan['MB'] = 1048576;
64efda84 1189 $scan['Mb'] = 1048576;
989bfa9d 1190 $scan['M'] = 1048576;
266a416e 1191 $scan['m'] = 1048576;
989bfa9d 1192 $scan['KB'] = 1024;
64efda84 1193 $scan['Kb'] = 1024;
989bfa9d 1194 $scan['K'] = 1024;
266a416e 1195 $scan['k'] = 1024;
989bfa9d 1196
1197 while (list($key) = each($scan)) {
1198 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
1199 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
1200 break;
1201 }
1202 }
1203 return $size;
1204}
1205
44e2d2bb 1206function display_size($size) {
9fa49e22 1207/// Converts bytes into display form
4909e176 1208
1209 static $gb,$mb,$kb,$b;
1210
1211 if (empty($gb)) {
1212 $gb = get_string('sizegb');
1213 $mb = get_string('sizemb');
1214 $kb = get_string('sizekb');
1215 $b = get_string('sizeb');
1216 }
1217
44e2d2bb 1218 if ($size >= 1073741824) {
4909e176 1219 $size = round($size / 1073741824 * 10) / 10 . $gb;
44e2d2bb 1220 } else if ($size >= 1048576) {
4909e176 1221 $size = round($size / 1048576 * 10) / 10 . $mb;
44e2d2bb 1222 } else if ($size >= 1024) {
4909e176 1223 $size = round($size / 1024 * 10) / 10 . $kb;
44e2d2bb 1224 } else {
4909e176 1225 $size = $size ." $b";
44e2d2bb 1226 }
1227 return $size;
1228}
1229
6b174680 1230function clean_filename($string) {
9fa49e22 1231/// Cleans a given filename by removing suspicious or troublesome characters
fc05fccb 1232 $string = stripslashes($string);
6b174680 1233 $string = eregi_replace("\.\.", "", $string);
5c219ea4 1234 $string = eregi_replace("[^(-|[:alnum:]|\.)]", "_", $string);
6b174680 1235 return eregi_replace("_+", "_", $string);
1236}
1237
1238
1180c6dc 1239/// STRING TRANSLATION ////////////////////////////////////////
1240
4bfa92e7 1241function current_language() {
9fa49e22 1242/// Returns the code for the current language
3db3acfb 1243 global $CFG, $USER, $SESSION;
4bfa92e7 1244
3db3acfb 1245 if (isset($SESSION->lang)) { // Session language can override other settings
1246 return $SESSION->lang;
1247
1248 } else if (isset($USER->lang)) { // User language can override site language
4bfa92e7 1249 return $USER->lang;
3db3acfb 1250
4bfa92e7 1251 } else {
1252 return $CFG->lang;
1253 }
1254}
bcc83c41 1255
9fa49e22 1256function print_string($identifier, $module="", $a=NULL) {
1257/// Given a string to translate - prints it out.
1258 echo get_string($identifier, $module, $a);
1259}
1260
a83fded1 1261function get_string($identifier, $module="", $a=NULL) {
9fa49e22 1262/// Return the translated string specified by $identifier as
1263/// for $module. Uses the same format files as STphp.
1264/// $a is an object, string or number that can be used
1265/// within translation strings
1266///
1267/// eg "hello \$a->firstname \$a->lastname"
1268/// or "hello \$a"
1180c6dc 1269
4bfa92e7 1270 global $CFG;
1180c6dc 1271
4bfa92e7 1272 $lang = current_language();
1180c6dc 1273
058eec18 1274 if ($module == "") {
1275 $module = "moodle";
1180c6dc 1276 }
1277
058eec18 1278 $langpath = "$CFG->dirroot/lang";
1279 $langfile = "$langpath/$lang/$module.php";
1180c6dc 1280
b947c69a 1281 // Look for the string - if found then return it
1282
1283 if (file_exists($langfile)) {
1284 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1285 eval($result);
1286 return $resultstring;
1180c6dc 1287 }
1288 }
1289
b947c69a 1290 // If the preferred language was English we can abort now
1180c6dc 1291
b947c69a 1292 if ($lang == "en") {
1293 return "[[$identifier]]";
1294 }
1180c6dc 1295
b947c69a 1296 // Is a parent language defined? If so, try it.
1297
1298 if ($result = get_string_from_file("parentlanguage", "$langpath/$lang/moodle.php", "\$parentlang")) {
1299 eval($result);
1300 if (!empty($parentlang)) {
1301 $langfile = "$langpath/$parentlang/$module.php";
1302 if (file_exists($langfile)) {
1303 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1304 eval($result);
1305 return $resultstring;
1306 }
1180c6dc 1307 }
1308 }
1309 }
b947c69a 1310
1311 // Our only remaining option is to try English
1312
1313 $langfile = "$langpath/en/$module.php";
1314 if (!file_exists($langfile)) {
1315 return "ERROR: No lang file ($langpath/en/$module.php)!";
1316 }
1317 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1318 eval($result);
1319 return $resultstring;
1320 }
1321
1322 return "[[$identifier]]"; // Last resort
1180c6dc 1323}
1324
1325
1180c6dc 1326function get_string_from_file($identifier, $langfile, $destination) {
9fa49e22 1327/// This function is only used from get_string().
2b32bddd 1328
1329 static $strings; // Keep the strings cached in memory.
1330
1331 if (empty($strings[$langfile])) {
1332 include ($langfile);
1333 $strings[$langfile] = $string;
1334 } else {
1335 $string = &$strings[$langfile];
1336 }
1180c6dc 1337
1338 if (!isset ($string[$identifier])) {
1339 return false;
1340 }
1341
a83fded1 1342 return "$destination = sprintf(\"".$string[$identifier]."\");";
1180c6dc 1343}
f9903ed0 1344
1345
1a72314d 1346function get_list_of_languages() {
1347/// Returns a list of language codes and their full names
1348 global $CFG;
1349
984a8bf3 1350 $languages = array();
1351
1352 if (!empty($CFG->langlist)) { // use admin's list of languages
1353 $langlist = explode(',', $CFG->langlist);
1354 foreach ($langlist as $lang) {
1355 if (file_exists("$CFG->dirroot/lang/$lang/moodle.php")) {
1356 include("$CFG->dirroot/lang/$lang/moodle.php");
1357 $languages[$lang] = $string["thislanguage"]." ($lang)";
1358 unset($string);
1359 }
1360 }
1361 } else {
1362 if (!$langdirs = get_list_of_plugins("lang")) {
1363 return false;
1364 }
1365 foreach ($langdirs as $lang) {
1366 include("$CFG->dirroot/lang/$lang/moodle.php");
1367 $languages[$lang] = $string["thislanguage"]." ($lang)";
1368 unset($string);
1369 }
1a72314d 1370 }
1371
1a72314d 1372 return $languages;
1373}
1374
5833a6c8 1375function get_list_of_countries() {
1376/// Returns a list of country names in the current language
1377 global $CFG, $USER;
1378
1379 $lang = current_language();
1380
1381 if (!file_exists("$CFG->dirroot/lang/$lang/countries.php")) {
aa3eb050 1382 if ($parentlang = get_string("parentlanguage")) {
1383 if (file_exists("$CFG->dirroot/lang/$parentlang/countries.php")) {
1384 $lang = $parentlang;
1385 } else {
1386 $lang = "en"; // countries.php must exist in this pack
1387 }
1388 } else {
1389 $lang = "en"; // countries.php must exist in this pack
1390 }
5833a6c8 1391 }
1392
82196932 1393 include_once("$CFG->dirroot/lang/$lang/countries.php");
5833a6c8 1394
f8dbffb1 1395 if (!empty($string)) {
1396 asort($string);
1397 }
5833a6c8 1398
1399 return $string;
1400}
1401
82196932 1402function get_list_of_pixnames() {
1403/// Returns a list of picture names in the current language
1404 global $CFG;
1405
1406 $lang = current_language();
1407
1408 if (!file_exists("$CFG->dirroot/lang/$lang/pix.php")) {
1409 if ($parentlang = get_string("parentlanguage")) {
1410 if (file_exists("$CFG->dirroot/lang/$parentlang/pix.php")) {
1411 $lang = $parentlang;
1412 } else {
1413 $lang = "en"; // countries.php must exist in this pack
1414 }
1415 } else {
1416 $lang = "en"; // countries.php must exist in this pack
1417 }
1418 }
1419
1420 include_once("$CFG->dirroot/lang/$lang/pix.php");
1421
1422 return $string;
1423}
1424
9bd2c874 1425function document_file($file, $include=true) {
1426/// Can include a given document file (depends on second
1427/// parameter) or just return info about it
1428
c9d4e6da 1429 global $CFG;
9bd2c874 1430
db356340 1431 $file = clean_filename($file);
1432
9bd2c874 1433 if (empty($file)) {
9bd2c874 1434 return false;
1435 }
1436
db356340 1437 $langs = array(current_language(), get_string("parentlanguage"), "en");
9bd2c874 1438
db356340 1439 foreach ($langs as $lang) {
1440 $info->filepath = "$CFG->dirroot/lang/$lang/docs/$file";
1441 $info->urlpath = "$CFG->wwwroot/lang/$lang/docs/$file";
9bd2c874 1442
db356340 1443 if (file_exists($info->filepath)) {
1444 if ($include) {
1445 include($info->filepath);
1446 }
1447 return $info;
0c106cd3 1448 }
9bd2c874 1449 }
1450
db356340 1451 return false;
9bd2c874 1452}
1453
1a72314d 1454
f9903ed0 1455/// ENCRYPTION ////////////////////////////////////////////////
1456
1457function rc4encrypt($data) {
1458 $password = "nfgjeingjk";
1459 return endecrypt($password, $data, "");
1460}
1461
1462function rc4decrypt($data) {
1463 $password = "nfgjeingjk";
1464 return endecrypt($password, $data, "de");
1465}
1466
1467function endecrypt ($pwd, $data, $case) {
9fa49e22 1468/// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
f9903ed0 1469
1470 if ($case == 'de') {
1471 $data = urldecode($data);
1472 }
1473
1474 $key[] = "";
1475 $box[] = "";
1476 $temp_swap = "";
1477 $pwd_length = 0;
1478
1479 $pwd_length = strlen($pwd);
1480
1481 for ($i = 0; $i <= 255; $i++) {
1482 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
1483 $box[$i] = $i;
1484 }
1485
1486 $x = 0;
1487
1488 for ($i = 0; $i <= 255; $i++) {
1489 $x = ($x + $box[$i] + $key[$i]) % 256;
1490 $temp_swap = $box[$i];
1491 $box[$i] = $box[$x];
1492 $box[$x] = $temp_swap;
1493 }
1494
1495 $temp = "";
1496 $k = "";
1497
1498 $cipherby = "";
1499 $cipher = "";
1500
1501 $a = 0;
1502 $j = 0;
1503
1504 for ($i = 0; $i < strlen($data); $i++) {
1505 $a = ($a + 1) % 256;
1506 $j = ($j + $box[$a]) % 256;
1507 $temp = $box[$a];
1508 $box[$a] = $box[$j];
1509 $box[$j] = $temp;
1510 $k = $box[(($box[$a] + $box[$j]) % 256)];
1511 $cipherby = ord(substr($data, $i, 1)) ^ $k;
1512 $cipher .= chr($cipherby);
1513 }
1514
1515 if ($case == 'de') {
1516 $cipher = urldecode(urlencode($cipher));
1517 } else {
1518 $cipher = urlencode($cipher);
1519 }
1520
1521 return $cipher;
1522}
1523
1524
9fa49e22 1525/// ENVIRONMENT CHECKING ////////////////////////////////////////////////////////////
1e3e716f 1526
1d881d92 1527function get_list_of_plugins($plugin="mod") {
1528/// Lists plugin directories within some directory
1529
1530 global $CFG;
1531
1532 $basedir = opendir("$CFG->dirroot/$plugin");
1533 while ($dir = readdir($basedir)) {
b35e8568 1534 $firstchar = substr($dir, 0, 1);
bb9cf93d 1535 if ($firstchar == "." or $dir == "CVS" or $dir == "_vti_cnf") {
1d881d92 1536 continue;
1537 }
1538 if (filetype("$CFG->dirroot/$plugin/$dir") != "dir") {
1539 continue;
1540 }
1541 $plugins[] = $dir;
1542 }
1543 if ($plugins) {
1544 asort($plugins);
1545 }
1546 return $plugins;
1547}
1548
b0cb5e22 1549function check_php_version($version="4.1.0") {
9fa49e22 1550/// Returns true is the current version of PHP is greater that the specified one
b0cb5e22 1551 $minversion = intval(str_replace(".", "", $version));
1552 $curversion = intval(str_replace(".", "", phpversion()));
1553 return ($curversion >= $minversion);
1554}
1555
0095d5cd 1556function check_browser_version($brand="MSIE", $version=5.5) {
9fa49e22 1557/// Checks to see if is a browser matches the specified
1558/// brand and is equal or better version.
0095d5cd 1559
4c46c425 1560 $agent = $_SERVER["HTTP_USER_AGENT"];
1561
1562 if (empty($agent)) {
0095d5cd 1563 return false;
1564 }
4c46c425 1565
1566 switch ($brand) {
1567
1568 case "Gecko": /// Gecko based browsers
1569
1570 if (substr_count($agent, "Camino")) { // MacOS X Camino not supported.
1571 return false;
1572 }
1573
1574 // the proper string - Gecko/CCYYMMDD Vendor/Version
1575 if (ereg("^([a-zA-Z]+)/([0-9]+\.[0-9]+) \((.*)\) (.*)$", $agent, $match)) {
1576 if (ereg("^([Gecko]+)/([0-9]+)",$match[4], $reldate)) {
1577 if ($reldate[2] > $version) {
1578 return true;
1579 }
1580 }
1581 }
1582 break;
1583
1584
1585 case "MSIE": /// Internet Explorer
1586
1587 $string = explode(";", $agent);
1588 if (!isset($string[1])) {
1589 return false;
1590 }
1591 $string = explode(" ", trim($string[1]));
1592 if (!isset($string[0]) and !isset($string[1])) {
1593 return false;
1594 }
1595 if ($string[0] == $brand and (float)$string[1] >= $version ) {
1596 return true;
1597 }
1598 break;
1599
0095d5cd 1600 }
4c46c425 1601
0095d5cd 1602 return false;
1603}
1604
4c46c425 1605
c39c66a5 1606function ini_get_bool($ini_get_arg) {
1607/// This function makes the return value of ini_get consistent if you are
1608/// setting server directives through the .htaccess file in apache.
1609/// Current behavior for value set from php.ini On = 1, Off = [blank]
1610/// Current behavior for value set from .htaccess On = On, Off = Off
1611/// Contributed by jdell@unr.edu
1612
1613 $temp = ini_get($ini_get_arg);
1614
1615 if ($temp == "1" or strtolower($temp) == "on") {
1616 return true;
1617 }
1618 return false;
1619}
1620
0095d5cd 1621function can_use_richtext_editor() {
47037513 1622/// Compatibility stub to provide backward compatibility
1623 return can_use_html_editor();
1624}
1625
1626function can_use_html_editor() {
4c46c425 1627/// Is the HTML editor enabled? This depends on site and user
1628/// settings, as well as the current browser being used.
47037513 1629/// Returns false is editor is not being used, otherwise
1630/// returns "MSIE" or "Gecko"
4c46c425 1631
0095d5cd 1632 global $USER, $CFG;
4c46c425 1633
ce78926d 1634 if (!empty($USER->htmleditor) and !empty($CFG->htmleditor)) {
4c46c425 1635 if (check_browser_version("MSIE", 5.5)) {
47037513 1636 return "MSIE";
1637 } else if (check_browser_version("Gecko", 20030516)) {
1638 return "Gecko";
4c46c425 1639 }
7ce20f09 1640 }
1641 return false;
0095d5cd 1642}
1643
47037513 1644
74944b73 1645function check_gd_version() {
9fa49e22 1646/// Hack to find out the GD version by parsing phpinfo output
aa095969 1647 $gdversion = 0;
74944b73 1648
aa095969 1649 if (function_exists('gd_info')){
1650 $gd_info = gd_info();
3ee23682 1651 if (substr_count($gd_info['GD Version'], "2.")) {
aa095969 1652 $gdversion = 2;
3ee23682 1653 } else if (substr_count($gd_info['GD Version'], "1.")) {
1654 $gdversion = 1;
aa095969 1655 }
3ee23682 1656
aa095969 1657 } else {
1658 ob_start();
1659 phpinfo(8);
1660 $phpinfo = ob_get_contents();
1661 ob_end_clean();
74944b73 1662
aa095969 1663 $phpinfo = explode("\n",$phpinfo);
74944b73 1664
92a4b0f1 1665
aa095969 1666 foreach ($phpinfo as $text) {
1667 $parts = explode('</td>',$text);
1668 foreach ($parts as $key => $val) {
1669 $parts[$key] = trim(strip_tags($val));
1670 }
1671 if ($parts[0] == "GD Version") {
1672 if (substr_count($parts[1], "2.0")) {
1673 $parts[1] = "2.0";
1674 }
1675 $gdversion = intval($parts[1]);
92a4b0f1 1676 }
74944b73 1677 }
1678 }
1679
1680 return $gdversion; // 1, 2 or 0
1681}
f9903ed0 1682
0095d5cd 1683
9fa49e22 1684function moodle_needs_upgrading() {
1685/// Checks version numbers of Main code and all modules to see
1686/// if there are any mismatches ... returns true or false
1687 global $CFG;
1688
1689 include_once("$CFG->dirroot/version.php"); # defines $version and upgrades
1690 if ($CFG->version) {
1691 if ($version > $CFG->version) {
1692 return true;
1693 }
1694 if ($mods = get_list_of_plugins("mod")) {
1695 foreach ($mods as $mod) {
1696 $fullmod = "$CFG->dirroot/mod/$mod";
1697 unset($module);
1079c8a8 1698 if (!is_readable("$fullmod/version.php")) {
1699 notify("Module '$mod' is not readable - check permissions");
1700 continue;
1701 }
9fa49e22 1702 include_once("$fullmod/version.php"); # defines $module with version etc
1703 if ($currmodule = get_record("modules", "name", $mod)) {
1704 if ($module->version > $currmodule->version) {
1705 return true;
1706 }
1707 }
1708 }
1709 }
1710 } else {
1711 return true;
1712 }
1713 return false;
1714}
1715
1716
1717/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
1718
7d6cac54 1719function moodle_strtolower ($string, $encoding='') {
1720/// Converts string to lowercase using most compatible function available
1721 if (function_exists('mb_strtolower')) {
1722 if($encoding===''){
1723 return mb_strtolower($string); //use multibyte support with default encoding
1724 } else {
dbe0be00 1725 return mb_strtolower($string,$encoding); //use given encoding
7d6cac54 1726 }
1727 } else {
1728 return strtolower($string); // use common function what rely on current locale setting
1729 }
1730}
1731
9fa49e22 1732function count_words($string) {
1733/// Words are defined as things between whitespace
1734 $string = strip_tags($string);
1735 return count(preg_split("/\w\b/", $string)) - 1;
1736}
1737
1d881d92 1738function random_string ($length=15) {
1739 $pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1740 $pool .= "abcdefghijklmnopqrstuvwxyz";
1741 $pool .= "0123456789";
1742 $poollen = strlen($pool);
1743 mt_srand ((double) microtime() * 1000000);
1744 $string = "";
1745 for ($i = 0; $i < $length; $i++) {
1746 $string .= substr($pool, (mt_rand()%($poollen)), 1);
1747 }
1748 return $string;
1749}
1750
1751
9fa49e22 1752function getweek ($startdate, $thedate) {
1753/// Given dates in seconds, how many weeks is the date from startdate
1754/// The first week is 1, the second 2 etc ...
1755
1756 if ($thedate < $startdate) { // error
1757 return 0;
1758 }
1759
1760 return floor(($thedate - $startdate) / 604800.0) + 1;
1761}
1762
1763function generate_password($maxlen=10) {
1764/// returns a randomly generated password of length $maxlen. inspired by
1765/// http://www.phpbuilder.com/columns/jesus19990502.php3
1766
1767 global $CFG;
1768
1769 $fillers = "1234567890!$-+";
1770 $wordlist = file($CFG->wordlist);
1771
1772 srand((double) microtime() * 1000000);
1773 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1774 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1775 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
1776
1777 return substr($word1 . $filler1 . $word2, 0, $maxlen);
1778}
1779
1780function format_float($num, $places=0) {
1781/// Given a float, prints it nicely
1782 return sprintf("%.$places"."f", $num);
1783}
1784
ee0e5d57 1785function swapshuffle($array) {
1786/// Given a simple array, this shuffles it up just like shuffle()
1787/// Unlike PHP's shuffle() ihis function works on any machine.
1788
1789 srand ((double) microtime() * 10000000);
1790 $last = count($array) - 1;
1791 for ($i=0;$i<=$last;$i++) {
1792 $from = rand(0,$last);
1793 $curr = $array[$i];
1794 $array[$i] = $array[$from];
1795 $array[$from] = $curr;
1796 }
1797 return $array;
1798}
1799
bc700e65 1800function swapshuffle_assoc($array) {
1801/// Like swapshuffle, but works on associative arrays
1802
1803 $newkeys = swapshuffle(array_keys($array));
1804 foreach ($newkeys as $newkey) {
1805 $newarray[$newkey] = $array[$newkey];
1806 }
1807 return $newarray;
1808}
1809
ee0e5d57 1810function draw_rand_array($array, $draws) {
1811/// Given an arbitrary array, and a number of draws,
1812/// this function returns an array with that amount
1813/// of items. The indexes are retained.
1814
1815 srand ((double) microtime() * 10000000);
1816
1817 $return = array();
1818
1819 $last = count($array);
1820
1821 if ($draws > $last) {
1822 $draws = $last;
1823 }
1824
1825 while ($draws > 0) {
1826 $last--;
1827
1828 $keys = array_keys($array);
1829 $rand = rand(0, $last);
1830
1831 $return[$keys[$rand]] = $array[$keys[$rand]];
1832 unset($array[$keys[$rand]]);
1833
1834 $draws--;
1835 }
1836
1837 return $return;
1838}
9fa49e22 1839
f5e82bc7 1840function microtime_diff($a, $b) {
1841 list($a_dec, $a_sec) = explode(" ", $a);
1842 list($b_dec, $b_sec) = explode(" ", $b);
1843 return $b_sec - $a_sec + $b_dec - $a_dec;
1844}
1845
02ebf404 1846function make_menu_from_list($list, $separator=",") {
1847/// Given a list (eg a,b,c,d,e) this function returns
1848/// an array of 1->a, 2->b, 3->c etc
1849
1850 $array = array_reverse(explode($separator, $list), true);
1851 foreach ($array as $key => $item) {
1852 $outarray[$key+1] = trim($item);
1853 }
1854 return $outarray;
1855}
1856
fdc47ee6 1857function make_grades_menu($gradingtype) {
1858/// Creates an array that represents all the current grades that
1859/// can be chosen using the given grading type. Negative numbers
1860/// are scales, zero is no grade, and positive numbers are maximum
1861/// grades.
1862
1863 $grades = array();
1864 if ($gradingtype < 0) {
1865 if ($scale = get_record("scale", "id", - $gradingtype)) {
1866 return make_menu_from_list($scale->scale);
1867 }
1868 } else if ($gradingtype > 0) {
1869 for ($i=$gradingtype; $i>=0; $i--) {
62ca135d 1870 $grades[$i] = "$i / $gradingtype";
fdc47ee6 1871 }
1872 return $grades;
1873 }
1874 return $grades;
1875}
1876
757a0abd 1877function make_unique_id_code($extra="") {
280faf9f 1878
1879 $hostname = "unknownhost";
1880 if (!empty($_SERVER["HTTP_HOST"])) {
1881 $hostname = $_SERVER["HTTP_HOST"];
1882 } else if (!empty($_ENV["HTTP_HOST"])) {
1883 $hostname = $_ENV["HTTP_HOST"];
1884 } else if (!empty($_SERVER["SERVER_NAME"])) {
1885 $hostname = $_SERVER["SERVER_NAME"];
1886 } else if (!empty($_ENV["SERVER_NAME"])) {
1887 $hostname = $_ENV["SERVER_NAME"];
1888 }
1889
1ccc73ac 1890 $date = gmdate("ymdHis");
280faf9f 1891
1892 $random = random_string(6);
1893
757a0abd 1894 if ($extra) {
1895 return "$hostname+$date+$random+$extra";
1896 } else {
1897 return "$hostname+$date+$random";
1898 }
280faf9f 1899}
1900
0095d5cd 1901
9d5b689c 1902// vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140:
f9903ed0 1903?>