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