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