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