Allow STRIKE tag
[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
dfc9ba9b 57
9fa49e22 58 if (get_field("config", "name", "name", $name)) {
59 return set_field("config", "value", $value, "name", $name);
d897cae4 60 } else {
9fa49e22 61 $config->name = $name;
62 $config->value = $value;
63 return insert_record("config", $config);
39917a09 64 }
39917a09 65}
66
39917a09 67
9fa49e22 68/// FUNCTIONS FOR HANDLING TIME ////////////////////////////////////////////
39917a09 69
70function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0) {
9fa49e22 71/// Given date parts in user time, produce a GMT timestamp
39917a09 72
9fa49e22 73 return mktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
39917a09 74}
75
8dbed6be 76function format_time($totalsecs, $str=NULL) {
9fa49e22 77/// Given an amount of time in seconds, returns string
78/// formatted nicely as months, days, hours etc as needed
c7e3ac2a 79
6b174680 80 $totalsecs = abs($totalsecs);
c7e3ac2a 81
8dbed6be 82 if (!$str) { // Create the str structure the slow way
83 $str->day = get_string("day");
84 $str->days = get_string("days");
85 $str->hour = get_string("hour");
86 $str->hours = get_string("hours");
87 $str->min = get_string("min");
88 $str->mins = get_string("mins");
89 $str->sec = get_string("sec");
90 $str->secs = get_string("secs");
91 }
92
93 $days = floor($totalsecs/86400);
6b174680 94 $remainder = $totalsecs - ($days*86400);
8dbed6be 95 $hours = floor($remainder/3600);
6b174680 96 $remainder = $remainder - ($hours*3600);
8dbed6be 97 $mins = floor($remainder/60);
98 $secs = $remainder - ($mins*60);
99
100 $ss = ($secs == 1) ? $str->sec : $str->secs;
101 $sm = ($mins == 1) ? $str->min : $str->mins;
102 $sh = ($hours == 1) ? $str->hour : $str->hours;
103 $sd = ($days == 1) ? $str->day : $str->days;
104
9c9f7d77 105 $odays = "";
106 $ohours = "";
107 $omins = "";
108 $osecs = "";
109
8dbed6be 110 if ($days) $odays = "$days $sd";
111 if ($hours) $ohours = "$hours $sh";
112 if ($mins) $omins = "$mins $sm";
113 if ($secs) $osecs = "$secs $ss";
6b174680 114
115 if ($days) return "$odays $ohours";
116 if ($hours) return "$ohours $omins";
117 if ($mins) return "$omins $osecs";
118 if ($secs) return "$osecs";
119 return get_string("now");
120}
f9903ed0 121
5fa51a39 122function userdate($date, $format="", $timezone=99) {
9fa49e22 123/// Returns a formatted string that represents a date in user time
124/// WARNING: note that the format is for strftime(), not date().
125/// Because of a bug in most Windows time libraries, we can't use
126/// the nicer %e, so we have to use %d which has leading zeroes.
127/// A lot of the fuss below is just getting rid of these leading
128/// zeroes as efficiently as possible.
7a302afc 129
873960de 130 global $USER;
131
5fa51a39 132 if ($format == "") {
035cdbff 133 $format = "%A, %d %B %Y, %I:%M %p";
134 $formatnoday = "%A, DD %B %Y, %I:%M %p";
135 $fixday = true;
136 } else {
137 $formatnoday = str_replace("%d", "DD", $format);
138 $fixday = ($formatnoday != $format);
5fa51a39 139 }
035cdbff 140
5fa51a39 141 if ($timezone == 99) {
ab247495 142 if (isset($USER->timezone)) {
143 $timezone = (float)$USER->timezone;
144 }
5fa51a39 145 }
0431bd7c 146 if (abs($timezone) > 13) {
035cdbff 147 if ($fixday) {
148 $datestring = strftime($formatnoday, $date);
149 $daystring = str_replace(" 0", "", strftime(" %d", $date));
150 $datestring = str_replace("DD", $daystring, $datestring);
151 } else {
152 $datestring = strftime($format, $date);
153 }
bea7a51e 154 } else {
035cdbff 155 if ($fixday) {
156 $datestring = gmstrftime($formatnoday, $date + (int)($timezone * 3600));
9fa49e22 157 $daystring = str_replace(" 0", "", gmstrftime(" %d", $date));
035cdbff 158 $datestring = str_replace("DD", $daystring, $datestring);
159 } else {
160 $datestring = gmstrftime($format, $date + (int)($timezone * 3600));
161 }
873960de 162 }
bea7a51e 163
035cdbff 164 return $datestring;
873960de 165}
166
5fa51a39 167function usergetdate($date, $timezone=99) {
9fa49e22 168/// Given a $date timestamp in GMT, returns an array
169/// that represents the date in user time
6b174680 170
873960de 171 global $USER;
172
5fa51a39 173 if ($timezone == 99) {
174 $timezone = (float)$USER->timezone;
175 }
0431bd7c 176 if (abs($timezone) > 13) {
873960de 177 return getdate($date);
178 }
d2d6171f 179 //There is no gmgetdate so I have to fake it...
180 $date = $date + (int)($timezone * 3600);
181 $getdate["seconds"] = gmstrftime("%S", $date);
182 $getdate["minutes"] = gmstrftime("%M", $date);
183 $getdate["hours"] = gmstrftime("%H", $date);
184 $getdate["mday"] = gmstrftime("%d", $date);
185 $getdate["wday"] = gmstrftime("%u", $date);
186 $getdate["mon"] = gmstrftime("%m", $date);
187 $getdate["year"] = gmstrftime("%Y", $date);
188 $getdate["yday"] = gmstrftime("%j", $date);
189 $getdate["weekday"] = gmstrftime("%A", $date);
190 $getdate["month"] = gmstrftime("%B", $date);
191 return $getdate;
d552ead0 192}
193
194function usertime($date, $timezone=99) {
9fa49e22 195/// Given a GMT timestamp (seconds since epoch), offsets it by
196/// the timezone. eg 3pm in India is 3pm GMT - 7 * 3600 seconds
d552ead0 197 global $USER;
198
199 if ($timezone == 99) {
200 $timezone = (float)$USER->timezone;
201 }
0431bd7c 202 if (abs($timezone) > 13) {
d552ead0 203 return $date;
204 }
205 return $date - (int)($timezone * 3600);
206}
207
edf7fe8c 208function usergetmidnight($date, $timezone=99) {
9fa49e22 209/// Given a time, return the GMT timestamp of the most recent midnight
210/// for the current user.
edf7fe8c 211 global $USER;
212
4606d9bb 213 if ($timezone == 99) {
214 $timezone = (float)$USER->timezone;
215 }
216
edf7fe8c 217 $userdate = usergetdate($date, $timezone);
4606d9bb 218
0431bd7c 219 if (abs($timezone) > 13) {
4606d9bb 220 return mktime(0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
221 }
222
edf7fe8c 223 $timemidnight = gmmktime (0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
224 return usertime($timemidnight, $timezone); // Time of midnight of this user's day, in GMT
225
226}
227
d552ead0 228function usertimezone($timezone=99) {
9fa49e22 229/// Returns a string that prints the user's timezone
d552ead0 230 global $USER;
231
232 if ($timezone == 99) {
233 $timezone = (float)$USER->timezone;
234 }
0431bd7c 235 if (abs($timezone) > 13) {
d552ead0 236 return "server time";
237 }
238 if (abs($timezone) < 0.5) {
239 return "GMT";
240 }
241 if ($timezone > 0) {
242 return "GMT+$timezone";
243 } else {
244 return "GMT$timezone";
245 }
f9903ed0 246}
247
248
9fa49e22 249/// USER AUTHENTICATION AND LOGIN ////////////////////////////////////////
f9903ed0 250
da5c172a 251function require_login($courseid=0) {
9fa49e22 252/// This function checks that the current user is logged in, and optionally
253/// whether they are "logged in" or allowed to be in a particular course.
254/// If not, then it redirects them to the site login or course enrolment.
f9903ed0 255
256 global $CFG, $SESSION, $USER, $FULLME, $HTTP_REFERER, $PHPSESSID;
257
da5c172a 258 // First check that the user is logged in to the site.
7363ff91 259
c21c671d 260 if (! (isset($USER->loggedin) and $USER->confirmed and ($USER->site == $CFG->wwwroot)) ) { // They're not
f9903ed0 261 $SESSION->wantsurl = $FULLME;
7363ff91 262 $SESSION->fromurl = $HTTP_REFERER;
8223d271 263 save_session("SESSION");
c21c671d 264 $USER = NULL;
265 save_session("USER");
f9903ed0 266 if ($PHPSESSID) { // Cookies not enabled.
a7b9e8bc 267 redirect("$CFG->wwwroot/login/index.php?PHPSESSID=$PHPSESSID");
f9903ed0 268 } else {
a7b9e8bc 269 redirect("$CFG->wwwroot/login/index.php");
f9903ed0 270 }
271 die;
f9903ed0 272 }
da5c172a 273
274 // Next, check if the user can be in a particular course
275 if ($courseid) {
9c9f7d77 276 if (!empty($USER->student[$courseid]) or !empty($USER->teacher[$courseid]) or !empty($USER->admin)) {
cb909d74 277 if (isset($USER->realuser)) { // Make sure the REAL person can also access this course
278 if (!isteacher($courseid, $USER->realuser)) {
279 print_header();
5ebe27e2 280 notice(get_string("studentnotallowed", "", "$USER->firstname $USER->lastname"), $CFG->wwwroot);
cb909d74 281 }
282
283 } else { // just update their last login time
3ce2f1e0 284 update_user_in_db();
285 }
ab998e5d 286 if (!$USER->email) { // User logged in, but has not set up profile!
287 // This can occur with external authentication
ab998e5d 288 redirect("$CFG->wwwroot/user/edit.php?id=$USER->id&course=$courseid");
289 die;
290 }
da5c172a 291 return; // user is a member of this course.
292 }
293 if (! $course = get_record("course", "id", $courseid)) {
294 error("That course doesn't exist");
295 }
7363ff91 296 if ($USER->username == "guest") {
297 switch ($course->guest) {
298 case 0: // Guests not allowed
299 print_header();
300 notice(get_string("guestsnotallowed", "", $course->fullname));
301 break;
302 case 1: // Guests allowed
303 update_user_in_db();
304 return;
305 case 2: // Guests allowed with key (drop through)
306 break;
307 }
da5c172a 308 }
f9903ed0 309
7363ff91 310 // Currently not enrolled in the course, so see if they want to enrol
da5c172a 311 $SESSION->wantsurl = $FULLME;
8223d271 312 save_session("SESSION");
da5c172a 313 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
314 die;
315 }
f9903ed0 316}
317
1d881d92 318function update_user_login_times() {
319 global $USER;
320
321 $USER->lastlogin = $user->lastlogin = $USER->currentlogin;
322 $USER->currentlogin = $user->currentlogin = time();
323 save_session("USER");
324
325 $user->id = $USER->id;
326
327 return update_record("user", $user);
328}
329
f9903ed0 330
f9903ed0 331function update_login_count() {
9fa49e22 332/// Keeps track of login attempts
333
f9903ed0 334 global $SESSION;
335
336 $max_logins = 10;
337
338 if (empty($SESSION->logincount)) {
339 $SESSION->logincount = 1;
340 } else {
341 $SESSION->logincount++;
342 }
8223d271 343 save_session("SESSION");
f9903ed0 344
345 if ($SESSION->logincount > $max_logins) {
9fa49e22 346 unset($SESSION->wantsurl);
347 save_session("SESSION");
1d881d92 348 error(get_string("errortoomanylogins"));
d578afc8 349 }
350}
351
9fa49e22 352function reset_login_count() {
353/// Resets login attempts
354 global $SESSION;
d578afc8 355
9fa49e22 356 $SESSION->logincount = 0;
357 save_session("SESSION");
d578afc8 358}
359
d578afc8 360
f9903ed0 361function isadmin($userid=0) {
9fa49e22 362/// Is the user an admin?
f9903ed0 363 global $USER;
364
9bd2c874 365 if (empty($USER)) {
366 return false;
367 }
368
369 if (empty($userid)) {
ebc3bd2b 370 return record_exists("user_admins", "userid", $USER->id);
f9903ed0 371 }
372
ebc3bd2b 373 return record_exists("user_admins", "userid", $userid);
f9903ed0 374}
375
9fa49e22 376
8a9e3fd7 377function isteacher($courseid, $userid=0) {
9fa49e22 378/// Is the user a teacher or admin?
f9903ed0 379 global $USER;
380
d115a57f 381 if (isadmin($userid)) { // admins can do anything the teacher can
382 return true;
383 }
384
f9903ed0 385 if (!$userid) {
9bd2c874 386 return !empty($USER->teacher[$courseid]);
f9903ed0 387 }
388
ebc3bd2b 389 return record_exists("user_teachers", "userid", $userid, "course", $courseid);
f9903ed0 390}
391
392
8a9e3fd7 393function isstudent($courseid, $userid=0) {
9fa49e22 394/// Is the user a student in this course?
f9903ed0 395 global $USER;
396
397 if (!$userid) {
8a9e3fd7 398 return $USER->student[$courseid];
f9903ed0 399 }
400
ebc3bd2b 401 // $timenow = time(); // todo: add time check below
f9903ed0 402
ebc3bd2b 403 return record_exists("user_students", "userid", $userid, "course", $courseid);
f9903ed0 404}
405
da5c172a 406function isguest($userid=0) {
9fa49e22 407/// Is the user a guest?
da5c172a 408 global $USER;
409
410 if (!$userid) {
411 return ($USER->username == "guest");
412 }
413
9fa49e22 414 return record_exists("user", "id", $userid, "username", "guest");
da5c172a 415}
416
9fa49e22 417
2c309dc2 418function isediting($courseid, $user=NULL) {
9fa49e22 419/// Is the current user in editing mode?
2c309dc2 420 global $USER;
421 if (!$user){
422 $user = $USER;
423 }
9c9f7d77 424 if (empty($user->editing)) {
425 return false;
426 }
2c309dc2 427 return ($user->editing and isteacher($courseid, $user->id));
428}
429
f9903ed0 430
431function set_moodle_cookie($thing) {
9fa49e22 432/// Sets a moodle cookie with an encrypted string
7185e073 433 global $CFG;
434
435 $cookiename = "MOODLEID{$CFG->prefix}";
f9903ed0 436
437 $days = 60;
438 $seconds = 60*60*24*$days;
439
7185e073 440 setCookie($cookiename, "", time() - 3600, "/");
441 setCookie($cookiename, rc4encrypt($thing), time()+$seconds, "/");
f9903ed0 442}
443
444
445function get_moodle_cookie() {
9fa49e22 446/// Gets a moodle cookie with an encrypted string
7185e073 447 global $CFG;
448
4fe04be0 449 $cookiename = "MOODLEID{$CFG->prefix}";
7185e073 450
451 global $$cookiename;
452
453 return rc4decrypt($$cookiename);
f9903ed0 454}
455
456
8223d271 457function save_session($VAR) {
9fa49e22 458/// Copies temporary session variable to permanent session variable
459/// eg $_SESSION["USER"] = $USER;
8223d271 460 global $$VAR;
461 $_SESSION[$VAR] = $$VAR;
462}
463
f9903ed0 464
faebaf0f 465function create_user_record($username, $password) {
9fa49e22 466/// Creates a bare-bones user record
e858f9da 467 global $REMOTE_ADDR, $CFG;
468
6ae24de0 469 if (function_exists(auth_get_userinfo)) {
e858f9da 470 if ($newinfo = auth_get_userinfo($username)) {
34daec9b 471 foreach ($newinfo as $key => $value){
e858f9da 472 $newuser->$key = $value;
473 }
474 }
475 }
f9903ed0 476
faebaf0f 477 $newuser->username = $username;
478 $newuser->password = md5($password);
a0bac19d 479 $newuser->lang = $CFG->lang;
faebaf0f 480 $newuser->confirmed = 1;
481 $newuser->lastIP = $REMOTE_ADDR;
482 $newuser->timemodified = time();
f9903ed0 483
faebaf0f 484 if (insert_record("user", $newuser)) {
485 return get_user_info_from_db("username", $username);
486 }
487 return false;
488}
489
490function authenticate_user_login($username, $password) {
9fa49e22 491/// Given a username and password, this function looks them
492/// up using the currently selected authentication mechanism,
493/// and if the authentication is successful, it returns a
494/// valid $user object from the 'user' table.
495///
496/// Uses auth_ functions from the currently active auth module
faebaf0f 497
498 global $CFG;
499
466558e3 500 $md5password = md5($password);
501
faebaf0f 502 if (!isset($CFG->auth)) {
503 $CFG->auth = "email"; // Default authentication module
504 }
505
466558e3 506 if ($username == "guest") {
507 $CFG->auth = "none"; // Guest account always internal
508 }
509
510 // If this is the admin, then just use internal methods
92710226 511 // Doing this first (even though it's less efficient) because
512 // the chosen authentication method might hang and lock the
513 // admin out.
9fa49e22 514 if (adminlogin($username, $md5password)) {
466558e3 515 return get_user_info_from_db("username", $username);
516 }
517
92710226 518 // OK, the user is a normal user, so try and authenticate them
e858f9da 519 require_once("$CFG->dirroot/auth/$CFG->auth/lib.php");
faebaf0f 520
521 if (auth_user_login($username, $password)) { // Successful authentication
522
523 if ($user = get_user_info_from_db("username", $username)) {
92710226 524 if ($md5password <> $user->password) { // Update local copy of password for reference
466558e3 525 set_field("user", "password", $md5password, "username", $username);
faebaf0f 526 }
527 return $user;
528
529 } else {
530 return create_user_record($username, $password);
531 }
f9903ed0 532 }
89b54325 533
faebaf0f 534 return false;
f9903ed0 535}
536
faebaf0f 537
9fa49e22 538function enrol_student($user, $course) {
539/// Enrols a student in a given course
540 global $db;
f9903ed0 541
ebc3bd2b 542 $record->userid = $user;
9fa49e22 543 $record->course = $course;
544 $record->start = 0;
545 $record->end = 0;
546 $record->time = time();
f9903ed0 547
ebc3bd2b 548 return insert_record("user_students", $record);
d7facad8 549}
550
9fa49e22 551function unenrol_student($user, $course=0) {
552/// Unenrols a student from a given course
553 global $db;
d7facad8 554
9fa49e22 555 if ($course) {
556 /// First delete any crucial stuff that might still send mail
557 if ($forums = get_records("forum", "course", $course)) {
558 foreach ($forums as $forum) {
ebc3bd2b 559 delete_records("forum_subscriptions", "forum", $forum->id, "userid", $user);
bb09fb11 560 }
f9903ed0 561 }
ebc3bd2b 562 return delete_records("user_students", "userid", $user, "course", $course);
9fa49e22 563
f9903ed0 564 } else {
ebc3bd2b 565 delete_records("forum_subscriptions", "userid", $user);
566 return delete_records("user_students", "userid", $user);
f9903ed0 567 }
568}
569
9fa49e22 570function remove_teacher($user, $course=0) {
571/// Removes a teacher from a given course (or ALL courses)
572/// Does not delete the user account
573 global $db;
57507290 574
9fa49e22 575 if ($course) {
576 /// First delete any crucial stuff that might still send mail
577 if ($forums = get_records("forum", "course", $course)) {
578 foreach ($forums as $forum) {
ebc3bd2b 579 delete_records("forum_subscriptions", "forum", $forum->id, "userid", $user);
9fa49e22 580 }
581 }
ebc3bd2b 582 return delete_records("user_teachers", "userid", $user, "course", $course);
57507290 583 } else {
ebc3bd2b 584 delete_records("forum_subscriptions", "userid", $user);
585 return delete_records("user_teachers", "userid", $user);
57507290 586 }
f9903ed0 587}
588
9fa49e22 589function remove_admin($user) {
590/// Removes an admin from a site
591 global $db;
f9903ed0 592
ebc3bd2b 593 return delete_records("user_admins", "userid", $user);
f9903ed0 594}
595
f9903ed0 596
597
f9903ed0 598/// CORRESPONDENCE ////////////////////////////////////////////////
599
5fa51a39 600function email_to_user($user, $from, $subject, $messagetext, $messagehtml="", $attachment="", $attachname="") {
9fa49e22 601/// user - a user record as an object
602/// from - a user record as an object
603/// subject - plain text subject line of the email
604/// messagetext - plain text version of the message
605/// messagehtml - complete html version of the message (optional)
606/// attachment - a file on the filesystem, relative to $CFG->dataroot
607/// attachname - the name of the file (extension indicates MIME)
f9903ed0 608
4216daa6 609 global $CFG, $_SERVER;
f9903ed0 610
136dabd8 611 include_once("$CFG->libdir/phpmailer/class.phpmailer.php");
f9903ed0 612
5fa51a39 613 if (!$user) {
f9903ed0 614 return false;
615 }
616
f9903ed0 617 $mail = new phpmailer;
618
72c578ca 619 $mail->Version = "Moodle $CFG->version"; // mailer version
136dabd8 620 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
562bbe90 621
98c4eae3 622
d483bcd3 623 if (current_language() != "en") {
624 $mail->CharSet = get_string("thischarset");
98c4eae3 625 }
626
7f86ce17 627 if ($CFG->smtphosts) {
1e411ffc 628 $mail->IsSMTP(); // use SMTP directly
629 $mail->Host = "$CFG->smtphosts"; // specify main and backup servers
9f58537a 630
631 if ($CFG->smtpuser) { // Use SMTP authentication
632 $mail->SMTPAuth = true;
633 $mail->Username = $CFG->smtpuser;
634 $mail->Password = $CFG->smtppass;
635 }
7f86ce17 636 } else {
1e411ffc 637 $mail->IsMail(); // use PHP mail() = sendmail
7f86ce17 638 }
f9903ed0 639
136dabd8 640 $mail->From = "$from->email";
641 $mail->FromName = "$from->firstname $from->lastname";
642 $mail->Subject = stripslashes($subject);
f9903ed0 643
6b174680 644 $mail->AddAddress("$user->email", "$user->firstname $user->lastname");
f9903ed0 645
f9903ed0 646 $mail->WordWrap = 70; // set word wrap
f9903ed0 647
136dabd8 648 if ($messagehtml) {
649 $mail->IsHTML(true);
650 $mail->Body = $messagehtml;
78681899 651 $mail->AltBody = "\n$messagetext\n";
136dabd8 652 } else {
653 $mail->IsHTML(false);
78681899 654 $mail->Body = "\n$messagetext\n";
f9903ed0 655 }
656
136dabd8 657 if ($attachment && $attachname) {
658 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
4216daa6 659 $adminuser = get_admin();
660 $mail->AddAddress("$adminuser->email", "$adminuser->firstname $adminuser->lastname");
661 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
136dabd8 662 } else {
663 include_once("$CFG->dirroot/files/mimetypes.php");
664 $mimetype = mimeinfo("type", $attachname);
665 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
666 }
f9903ed0 667 }
668
136dabd8 669 if ($mail->Send()) {
670 return true;
671 } else {
4216daa6 672 echo "ERROR: $mail->ErrorInfo\n";
673 $site = get_site();
674 add_to_log($site->id, "library", "mailer", $_SERVER["REQUEST_URI"], "ERROR: $mail->ErrorInfo");
f9903ed0 675 return false;
676 }
f9903ed0 677}
678
1d881d92 679function reset_password_and_mail($user) {
680
681 global $CFG;
682
683 $site = get_site();
684 $from = get_admin();
685
686 $newpassword = generate_password();
687
688 if (! set_field("user", "password", md5($newpassword), "id", $user->id) ) {
689 error("Could not set user password!");
690 }
691
692 $a->firstname = $user->firstname;
693 $a->sitename = $site->fullname;
694 $a->username = $user->username;
695 $a->newpassword = $newpassword;
696 $a->link = "$CFG->wwwroot/login/change_password.php";
697 $a->signoff = "$from->firstname $from->lastname ($from->email)";
698
699 $message = get_string("newpasswordtext", "", $a);
700
701 $subject = "$site->fullname: ".get_string("changedpassword");
702
703 return email_to_user($user, $from, $subject, $message);
704
705}
706
707function send_confirmation_email($user) {
708
709 global $CFG;
710
711 $site = get_site();
712 $from = get_admin();
713
714 $data->firstname = $user->firstname;
715 $data->sitename = $site->fullname;
716 $data->link = "$CFG->wwwroot/login/confirm.php?p=$user->secret&s=$user->username";
717 $data->admin = "$from->firstname $from->lastname ($from->email)";
718
719 $message = get_string("emailconfirmation", "", $data);
720 $subject = "$site->fullname account confirmation";
721
722 return email_to_user($user, $from, $subject, $message);
723
724}
725
726
136dabd8 727
f9903ed0 728/// FILE HANDLING /////////////////////////////////////////////
729
6b174680 730function make_upload_directory($directory) {
9fa49e22 731/// $directory = a string of directory names under $CFG->dataroot
732/// eg stuff/assignment/1
733/// Returns full directory if successful, false if not
6b174680 734
735 global $CFG;
736
737 $currdir = $CFG->dataroot;
738 if (!file_exists($currdir)) {
739 if (! mkdir($currdir, 0750)) {
740 notify("ERROR: You need to create the directory $currdir with web server write access");
741 return false;
742 }
743 }
744
745 $dirarray = explode("/", $directory);
746
747 foreach ($dirarray as $dir) {
748 $currdir = "$currdir/$dir";
749 if (! file_exists($currdir)) {
750 if (! mkdir($currdir, 0750)) {
751 notify("ERROR: Could not find or create a directory ($currdir)");
752 return false;
753 }
754 }
755 }
756
757 return $currdir;
758}
759
ca4f8eb8 760function make_mod_upload_directory($courseid) {
9fa49e22 761/// Makes an upload directory for a particular module
ca4f8eb8 762 global $CFG;
763
764 if (! $moddata = make_upload_directory("$courseid/$CFG->moddata")) {
765 return false;
766 }
767
768 $strreadme = get_string("readme");
769
770 if (file_exists("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt")) {
771 copy("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt", "$moddata/$strreadme.txt");
772 } else {
773 copy("$CFG->dirroot/lang/en/docs/module_files.txt", "$moddata/$strreadme.txt");
774 }
775 return $moddata;
776}
777
6b174680 778
44e2d2bb 779function valid_uploaded_file($newfile) {
9fa49e22 780/// Returns current name of file on disk if true
9c9f7d77 781 if (empty($newfile)) {
782 return "";
783 }
44e2d2bb 784 if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
785 return $newfile['tmp_name'];
786 } else {
787 return "";
788 }
789}
790
791function get_max_upload_file_size() {
9fa49e22 792/// Returns the maximum size for uploading files
44e2d2bb 793 if (! $filesize = ini_get("upload_max_filesize")) {
794 $filesize = "5M";
795 }
796 return get_real_size($filesize);
797}
798
774ab660 799function get_directory_list($rootdir, $excludefile="", $descend=true) {
9fa49e22 800/// Returns an array with all the filenames in
801/// all subdirectories, relative to the given rootdir.
802/// If excludefile is defined, then that file/directory is ignored
f9903ed0 803
804 $dirs = array();
805
44e2d2bb 806 $dir = opendir($rootdir);
f9903ed0 807
d897cae4 808 if (!$dir) {
809 notify("Error: unable to read this directory! : $rootdir");
810 return $dirs;
811 }
812
ca4f8eb8 813 while ($file = readdir($dir)) {
774ab660 814 if ($file != "." and $file != ".." and $file != "CVS" and $file != $excludefile) {
ca4f8eb8 815 $fullfile = $rootdir."/".$file;
774ab660 816 if ($descend and filetype($fullfile) == "dir") {
817 $subdirs = get_directory_list($fullfile, $excludefile, $descend);
f9903ed0 818 foreach ($subdirs as $subdir) {
819 $dirs[] = $file."/".$subdir;
820 }
821 } else {
822 $dirs[] = $file;
823 }
824 }
825 }
44e2d2bb 826 closedir($dir);
f9903ed0 827
774ab660 828 asort($dirs);
829
f9903ed0 830 return $dirs;
831}
832
989bfa9d 833function get_real_size($size=0) {
9fa49e22 834/// Converts numbers like 10M into bytes
989bfa9d 835 if (!$size) {
836 return 0;
837 }
838 $scan['MB'] = 1048576;
64efda84 839 $scan['Mb'] = 1048576;
989bfa9d 840 $scan['M'] = 1048576;
841 $scan['KB'] = 1024;
64efda84 842 $scan['Kb'] = 1024;
989bfa9d 843 $scan['K'] = 1024;
844
845 while (list($key) = each($scan)) {
846 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
847 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
848 break;
849 }
850 }
851 return $size;
852}
853
44e2d2bb 854function display_size($size) {
9fa49e22 855/// Converts bytes into display form
44e2d2bb 856 if ($size >= 1073741824) {
857 $size = round($size / 1073741824 * 10) / 10 . "Gb";
858 } else if ($size >= 1048576) {
859 $size = round($size / 1048576 * 10) / 10 . "Mb";
860 } else if ($size >= 1024) {
861 $size = round($size / 1024 * 10) / 10 . "Kb";
862 } else {
863 $size = $size . "b";
864 }
865 return $size;
866}
867
6b174680 868function clean_filename($string) {
9fa49e22 869/// Cleans a given filename by removing suspicious or troublesome characters
fc05fccb 870 $string = stripslashes($string);
6b174680 871 $string = eregi_replace("\.\.", "", $string);
872 $string = eregi_replace("[^([:alnum:]|\.)]", "_", $string);
873 return eregi_replace("_+", "_", $string);
874}
875
876
1180c6dc 877/// STRING TRANSLATION ////////////////////////////////////////
878
4bfa92e7 879function current_language() {
9fa49e22 880/// Returns the code for the current language
4bfa92e7 881 global $CFG, $USER;
882
883 if (isset($USER->lang)) { // User language can override site language
884 return $USER->lang;
885 } else {
886 return $CFG->lang;
887 }
888}
bcc83c41 889
9fa49e22 890function print_string($identifier, $module="", $a=NULL) {
891/// Given a string to translate - prints it out.
892 echo get_string($identifier, $module, $a);
893}
894
a83fded1 895function get_string($identifier, $module="", $a=NULL) {
9fa49e22 896/// Return the translated string specified by $identifier as
897/// for $module. Uses the same format files as STphp.
898/// $a is an object, string or number that can be used
899/// within translation strings
900///
901/// eg "hello \$a->firstname \$a->lastname"
902/// or "hello \$a"
1180c6dc 903
4bfa92e7 904 global $CFG;
1180c6dc 905
4bfa92e7 906 $lang = current_language();
1180c6dc 907
058eec18 908 if ($module == "") {
909 $module = "moodle";
1180c6dc 910 }
911
058eec18 912 $langpath = "$CFG->dirroot/lang";
913 $langfile = "$langpath/$lang/$module.php";
1180c6dc 914
915 if (!file_exists($langfile)) { // try English instead
058eec18 916 $langfile = "$langpath/en/$module.php";
1180c6dc 917 if (!file_exists($langfile)) {
058eec18 918 return "ERROR: No lang file ($langpath/en/$module.php)!";
1180c6dc 919 }
920 }
921
922 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
923
924 eval($result);
925 return $resultstring;
926
927 } else {
928 if ($lang == "en") {
44e2d2bb 929 return "[['$identifier']]";
1180c6dc 930
931 } else { // Try looking in the english file.
058eec18 932 $langfile = "$langpath/en/$module.php";
1180c6dc 933 if (!file_exists($langfile)) {
058eec18 934 return "ERROR: No lang file ($langpath/en/$module.php)!";
1180c6dc 935 }
936 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
937 eval($result);
938 return $resultstring;
939 } else {
44e2d2bb 940 return "[['$identifier']]";
1180c6dc 941 }
942 }
943 }
944}
945
946
1180c6dc 947function get_string_from_file($identifier, $langfile, $destination) {
9fa49e22 948/// This function is only used from get_string().
1180c6dc 949 include ($langfile);
950
951 if (!isset ($string[$identifier])) {
952 return false;
953 }
954
a83fded1 955 return "$destination = sprintf(\"".$string[$identifier]."\");";
1180c6dc 956}
f9903ed0 957
958
1a72314d 959function get_list_of_languages() {
960/// Returns a list of language codes and their full names
961 global $CFG;
962
963 if (!$langdirs = get_list_of_plugins("lang")) {
964 return false;
965 }
966
967 foreach ($langdirs as $lang) {
968 include("$CFG->dirroot/lang/$lang/moodle.php");
969 $languages[$lang] = $string["thislanguage"]." ($lang)";
970 unset($string);
971 }
972 return $languages;
973}
974
9bd2c874 975function document_file($file, $include=true) {
976/// Can include a given document file (depends on second
977/// parameter) or just return info about it
978
cae74366 979 global $CFG, $SESSION;
9bd2c874 980
981 if (empty($file)) {
982 echo "Error 404";
983 return false;
984 }
985
cae74366 986 if (!empty($SESSION->doclang)) {
987 $lang = $SESSION->doclang;
988 } else {
989 $lang = current_language();
990 }
991
9bd2c874 992 $file = clean_filename($file);
993
994 $info->filepath = "$CFG->dirroot/lang/$lang/docs/$file";
995 $info->urlpath = "$CFG->wwwroot/lang/$lang/docs/$file";
996
997 if (!file_exists($info->filepath)) {
998 $info->filepath = "$CFG->dirroot/lang/en/docs/$file";
999 $info->urlpath = "$CFG->wwwroot/lang/en/docs/$file";
1000 }
1001
1002 if ($include) {
1003 include($info->filepath);
1004 }
1005
1006 return $info;
1007}
1008
1a72314d 1009
f9903ed0 1010/// ENCRYPTION ////////////////////////////////////////////////
1011
1012function rc4encrypt($data) {
1013 $password = "nfgjeingjk";
1014 return endecrypt($password, $data, "");
1015}
1016
1017function rc4decrypt($data) {
1018 $password = "nfgjeingjk";
1019 return endecrypt($password, $data, "de");
1020}
1021
1022function endecrypt ($pwd, $data, $case) {
9fa49e22 1023/// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
f9903ed0 1024
1025 if ($case == 'de') {
1026 $data = urldecode($data);
1027 }
1028
1029 $key[] = "";
1030 $box[] = "";
1031 $temp_swap = "";
1032 $pwd_length = 0;
1033
1034 $pwd_length = strlen($pwd);
1035
1036 for ($i = 0; $i <= 255; $i++) {
1037 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
1038 $box[$i] = $i;
1039 }
1040
1041 $x = 0;
1042
1043 for ($i = 0; $i <= 255; $i++) {
1044 $x = ($x + $box[$i] + $key[$i]) % 256;
1045 $temp_swap = $box[$i];
1046 $box[$i] = $box[$x];
1047 $box[$x] = $temp_swap;
1048 }
1049
1050 $temp = "";
1051 $k = "";
1052
1053 $cipherby = "";
1054 $cipher = "";
1055
1056 $a = 0;
1057 $j = 0;
1058
1059 for ($i = 0; $i < strlen($data); $i++) {
1060 $a = ($a + 1) % 256;
1061 $j = ($j + $box[$a]) % 256;
1062 $temp = $box[$a];
1063 $box[$a] = $box[$j];
1064 $box[$j] = $temp;
1065 $k = $box[(($box[$a] + $box[$j]) % 256)];
1066 $cipherby = ord(substr($data, $i, 1)) ^ $k;
1067 $cipher .= chr($cipherby);
1068 }
1069
1070 if ($case == 'de') {
1071 $cipher = urldecode(urlencode($cipher));
1072 } else {
1073 $cipher = urlencode($cipher);
1074 }
1075
1076 return $cipher;
1077}
1078
1079
9fa49e22 1080/// ENVIRONMENT CHECKING ////////////////////////////////////////////////////////////
1e3e716f 1081
1d881d92 1082function get_list_of_plugins($plugin="mod") {
1083/// Lists plugin directories within some directory
1084
1085 global $CFG;
1086
1087 $basedir = opendir("$CFG->dirroot/$plugin");
1088 while ($dir = readdir($basedir)) {
1089 if ($dir == "." || $dir == ".." || $dir == "CVS") {
1090 continue;
1091 }
1092 if (filetype("$CFG->dirroot/$plugin/$dir") != "dir") {
1093 continue;
1094 }
1095 $plugins[] = $dir;
1096 }
1097 if ($plugins) {
1098 asort($plugins);
1099 }
1100 return $plugins;
1101}
1102
b0cb5e22 1103function check_php_version($version="4.1.0") {
9fa49e22 1104/// Returns true is the current version of PHP is greater that the specified one
b0cb5e22 1105 $minversion = intval(str_replace(".", "", $version));
1106 $curversion = intval(str_replace(".", "", phpversion()));
1107 return ($curversion >= $minversion);
1108}
1109
0095d5cd 1110function check_browser_version($brand="MSIE", $version=5.5) {
9fa49e22 1111/// Checks to see if is a browser matches the specified
1112/// brand and is equal or better version.
0095d5cd 1113 global $HTTP_USER_AGENT;
1114
1115 if (!$HTTP_USER_AGENT) {
1116 return false;
1117 }
1118 $string = explode(";", $HTTP_USER_AGENT);
1119 if (!isset($string[1])) {
1120 return false;
1121 }
1122 $string = explode(" ", trim($string[1]));
1123 if (!isset($string[0]) and !isset($string[1])) {
1124 return false;
1125 }
1126 if ($string[0] == $brand and (float)$string[1] >= $version ) {
1127 return true;
1128 }
1129 return false;
1130}
1131
1132function can_use_richtext_editor() {
9fa49e22 1133/// Is the richedit editor enabled?
0095d5cd 1134 global $USER, $CFG;
7ce20f09 1135 if ($USER->htmleditor and $CFG->htmleditor) {
1136 return check_browser_version("MSIE", 5.5);
1137 }
1138 return false;
0095d5cd 1139}
1140
74944b73 1141function check_gd_version() {
9fa49e22 1142/// Hack to find out the GD version by parsing phpinfo output
74944b73 1143 ob_start();
a3e175ee 1144 phpinfo(8);
74944b73 1145 $phpinfo = ob_get_contents();
1146 ob_end_clean();
1147
1148 $phpinfo = explode("\n",$phpinfo);
1149
1150 $gdversion = 0;
1151
92a4b0f1 1152
74944b73 1153 foreach ($phpinfo as $text) {
92a4b0f1 1154 $parts = explode('</td>',$text);
74944b73 1155 foreach ($parts as $key => $val) {
92a4b0f1 1156 $parts[$key] = trim(strip_tags($val));
74944b73 1157 }
92a4b0f1 1158 if ($parts[0] == "GD Version") {
1159 if (substr_count($parts[1], "2.0")) {
1160 $parts[1] = "2.0";
1161 }
74944b73 1162 $gdversion = intval($parts[1]);
1163 }
1164 }
1165
1166 return $gdversion; // 1, 2 or 0
1167}
f9903ed0 1168
0095d5cd 1169
9fa49e22 1170function moodle_needs_upgrading() {
1171/// Checks version numbers of Main code and all modules to see
1172/// if there are any mismatches ... returns true or false
1173 global $CFG;
1174
1175 include_once("$CFG->dirroot/version.php"); # defines $version and upgrades
1176 if ($CFG->version) {
1177 if ($version > $CFG->version) {
1178 return true;
1179 }
1180 if ($mods = get_list_of_plugins("mod")) {
1181 foreach ($mods as $mod) {
1182 $fullmod = "$CFG->dirroot/mod/$mod";
1183 unset($module);
1184 include_once("$fullmod/version.php"); # defines $module with version etc
1185 if ($currmodule = get_record("modules", "name", $mod)) {
1186 if ($module->version > $currmodule->version) {
1187 return true;
1188 }
1189 }
1190 }
1191 }
1192 } else {
1193 return true;
1194 }
1195 return false;
1196}
1197
1198
1199/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
1200
1201function count_words($string) {
1202/// Words are defined as things between whitespace
1203 $string = strip_tags($string);
1204 return count(preg_split("/\w\b/", $string)) - 1;
1205}
1206
1d881d92 1207function random_string ($length=15) {
1208 $pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1209 $pool .= "abcdefghijklmnopqrstuvwxyz";
1210 $pool .= "0123456789";
1211 $poollen = strlen($pool);
1212 mt_srand ((double) microtime() * 1000000);
1213 $string = "";
1214 for ($i = 0; $i < $length; $i++) {
1215 $string .= substr($pool, (mt_rand()%($poollen)), 1);
1216 }
1217 return $string;
1218}
1219
1220
9fa49e22 1221function getweek ($startdate, $thedate) {
1222/// Given dates in seconds, how many weeks is the date from startdate
1223/// The first week is 1, the second 2 etc ...
1224
1225 if ($thedate < $startdate) { // error
1226 return 0;
1227 }
1228
1229 return floor(($thedate - $startdate) / 604800.0) + 1;
1230}
1231
1232function generate_password($maxlen=10) {
1233/// returns a randomly generated password of length $maxlen. inspired by
1234/// http://www.phpbuilder.com/columns/jesus19990502.php3
1235
1236 global $CFG;
1237
1238 $fillers = "1234567890!$-+";
1239 $wordlist = file($CFG->wordlist);
1240
1241 srand((double) microtime() * 1000000);
1242 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1243 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1244 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
1245
1246 return substr($word1 . $filler1 . $word2, 0, $maxlen);
1247}
1248
1249function format_float($num, $places=0) {
1250/// Given a float, prints it nicely
1251 return sprintf("%.$places"."f", $num);
1252}
1253
1254
0095d5cd 1255
f9903ed0 1256?>