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