Just making this more relevant for the CVS update junkies :-)
[moodle.git] / lib / moodlelib.php
CommitLineData
f9903ed0 1<?PHP // $Id$
2
3//
4// moodlelib.php
5//
6// Large collection of useful functions used by many parts of Moodle.
7//
8// Martin Dougiamas, 2000
9//
10
11
12/// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
13
c7e3ac2a 14function print_header ($title="", $heading="", $navigation="", $focus="", $meta="", $cache=true, $button="") {
f9903ed0 15// $title - appears top of window
16// $heading - appears top of page
17// $navigation - premade navigation string
18// $focus - indicates form element eg inputform.password
19// $meta - meta tags in the header
c7e3ac2a 20// $cache - should this page be cacheable?
21// $button - code for a button in the top-right
f9903ed0 22 global $USER, $CFG, $THEME;
23
24 if (file_exists("$CFG->dirroot/theme/$CFG->theme/styles.css")) {
25 $styles = "$CFG->wwwroot/theme/$CFG->theme/styles.css";
26 } else {
27 $styles = "$CFG->wwwroot/theme/standard/styles.css";
28 }
4efeb8c3 29
a28af1fe 30 if ($navigation == "home") {
31 $home = true;
32 $navigation = "";
33 }
34
4efeb8c3 35 if (!$button and $navigation) {
36 if (isset($USER->id)) {
37 $button = "<FONT SIZE=2><A HREF=\"$CFG->wwwroot/login/logout.php\">".get_string("logout")."</A></FONT>";
38 } else {
a7b9e8bc 39 $button = "<FONT SIZE=2><A HREF=\"$CFG->wwwroot/login/index.php\">".get_string("login")."</A></FONT>";
4efeb8c3 40 }
41 }
4bfa92e7 42
43 // Specify character set ... default is iso-8859-1 but some languages might need something else
44 // Could be optimised by carrying the charset variable around in $USER
45 if (current_language() == "en") {
46 $meta .= "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=iso-8859-1\">\n";
47 } else {
48 $meta .= "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=".get_string("thischarset")."\">\n";
49 }
f9903ed0 50
51 if (!$cache) { // Do everything we can to prevent clients and proxies caching
52 @header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
53 @header("Pragma: no-cache");
54 $meta .= "\n<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">";
55 $meta .= "\n<META HTTP-EQUIV=\"Expires\" CONTENT=\"0\">";
56 }
4bfa92e7 57
f9903ed0 58 include ("$CFG->dirroot/theme/$CFG->theme/header.html");
59}
60
61function print_footer ($course=NULL) {
62// Can provide a course object to make the footer contain a link to
63// to the course home page, otherwise the link will go to the site home
64 global $USER, $CFG, $THEME;
65
66 if ($course) {
28b1e3ec 67 if ($course == "home") { // special case for site home page - please do not remove
a28af1fe 68 $homelink = "<P ALIGN=center><A TITLE=\"Moodle $CFG->release ($CFG->version)\" HREF=\"http://moodle.com/\">";
a3cbb753 69 $homelink .= "<BR><IMG WIDTH=130 HEIGHT=19 SRC=\"pix/madewithmoodle2.gif\" BORDER=0></A></P>";
d82c8545 70 } else {
71 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</A>";
72 }
f9903ed0 73 } else {
d82c8545 74 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot\">".get_string("home")."</A>";
f9903ed0 75 }
3ce2f1e0 76 if ($USER->realuser) {
77 if ($realuser = get_record("user", "id", $USER->realuser)) {
78 $realuserinfo = " [$realuser->firstname $realuser->lastname] ";
79 }
80 }
81 if ($USER->id) {
82 $loggedinas = $realuserinfo.get_string("loggedinas", "moodle", "$USER->firstname $USER->lastname").
83 " (<A HREF=\"$CFG->wwwroot/login/logout.php\">".get_string("logout")."</A>)";
84 } else {
85 $loggedinas = get_string("loggedinnot", "moodle").
a7b9e8bc 86 " (<A HREF=\"$CFG->wwwroot/login/index.php\">".get_string("login")."</A>)";
3ce2f1e0 87 }
88
f9903ed0 89 include ("$CFG->dirroot/theme/$CFG->theme/footer.html");
90}
91
92function print_navigation ($navigation) {
93 global $CFG;
94
95 if ($navigation) {
a83fded1 96 if (! $site = get_site()) {
bcc83c41 97 $site->shortname = get_string("home");;
98 }
a2eaeb91 99 echo "<A TARGET=_top HREF=\"$CFG->wwwroot/\">$site->shortname</A> -> $navigation";
f9903ed0 100 }
101}
102
2a46a71b 103function print_heading($text, $align="CENTER", $size=3) {
104 echo "<P ALIGN=\"$align\"><FONT SIZE=\"$size\"><B>$text</B></FONT></P>";
f9903ed0 105}
106
dbcb136a 107function print_continue($link) {
108 global $HTTP_REFERER;
109
110 if (!$link) {
111 $link = $HTTP_REFERER;
112 }
113
114 print_heading("<A HREF=\"$link\">".get_string("continue")."</A>");
115}
116
117
4216daa6 118function print_simple_box($message, $align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
119 print_simple_box_start($align, $width, $color, $padding, $border);
f9903ed0 120 echo "<P>$message</P>";
121 print_simple_box_end();
122}
123
4216daa6 124function print_simple_box_start($align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
f9903ed0 125 global $THEME;
126
127 if ($align) {
128 $tablealign = "ALIGN=\"$align\"";
129 }
130 if ($width) {
131 $tablewidth = "WIDTH=\"$width\"";
132 $innertablewidth = "WIDTH=\"100%\"";
133 }
4216daa6 134 echo "<TABLE $tablealign $tablewidth BORDER=0 CELLPADDING=\"$border\" CELLSPACING=0>";
f9903ed0 135 echo "<TR><TD BGCOLOR=\"$THEME->borders\">\n";
136 echo "<TABLE $innertablewidth BORDER=0 CELLPADDING=\"$padding\" CELLSPACING=0><TR><TD BGCOLOR=\"$color\">";
137}
138
139function print_simple_box_end() {
140 echo "</TD></TR></TABLE>";
141 echo "</TD></TR></TABLE>";
142}
143
144function print_single_button($link, $options, $label="OK") {
145 echo "<FORM ACTION=\"$link\" METHOD=GET>";
dbcb136a 146 if ($options) {
147 foreach ($options as $name => $value) {
148 echo "<INPUT TYPE=hidden NAME=\"$name\" VALUE=\"$value\">";
149 }
f9903ed0 150 }
151 echo "<INPUT TYPE=submit VALUE=\"$label\"></FORM>";
152}
153
19a55d67 154function print_spacer($height=1, $width=1, $br=true) {
155 global $CFG;
156 echo "<IMG HEIGHT=\"$height\" WIDTH=\"$width\" SRC=\"$CFG->wwwroot/pix/spacer.gif\" ALT=\"\">";
157 if ($br) {
158 echo "<BR>\n";
159 }
160}
161
136dabd8 162function print_user_picture($userid, $courseid, $picture, $large=false, $returnstring=false) {
f9903ed0 163 global $CFG;
164
136dabd8 165 $output = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$userid&course=$courseid\">";
f9903ed0 166 if ($large) {
167 $file = "f1.jpg";
168 $size = 100;
169 } else {
170 $file = "f2.jpg";
171 $size = 35;
172 }
173 if ($picture) {
3f8247c2 174 if ($CFG->slasharguments) { // Use this method if possible for better caching
2447921f 175 $output .= "<IMG SRC=\"$CFG->wwwroot/user/pix.php/$userid/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
3f8247c2 176 } else {
177 $output .= "<IMG SRC=\"$CFG->wwwroot/user/pix.php?file=/$userid/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
2447921f 178 }
f9903ed0 179 } else {
136dabd8 180 $output .= "<IMG SRC=\"$CFG->wwwroot/user/default/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
181 }
182 $output .= "</A>";
183
184 if ($returnstring) {
185 return $output;
186 } else {
187 echo $output;
f9903ed0 188 }
f9903ed0 189}
190
274f62e6 191function print_table($table) {
f9903ed0 192// Prints a nicely formatted table.
5b54db6e 193// $table is an object with several properties.
f9903ed0 194// $table->head is an array of heading names.
195// $table->align is an array of column alignments
5b54db6e 196// $table->size is an array of column sizes
f9903ed0 197// $table->data[] is an array of arrays containing the data.
1e3e716f 198// $table->width is an percentage of the page
274f62e6 199// $table->cellpadding padding on each cell
200// $table->cellspacing spacing between cells
f9903ed0 201
5b54db6e 202 if (isset($table->align)) {
f9903ed0 203 foreach ($table->align as $key => $aa) {
204 if ($aa) {
5b54db6e 205 $align[$key] = " ALIGN=\"$aa\"";
f9903ed0 206 } else {
207 $align[$key] = "";
208 }
209 }
210 }
5b54db6e 211 if (isset($table->size)) {
212 foreach ($table->size as $key => $ss) {
213 if ($ss) {
214 $size[$key] = " WIDTH=\"$ss\"";
215 } else {
216 $size[$key] = "";
217 }
218 }
219 }
f9903ed0 220
1e3e716f 221 if (!$table->width) {
222 $table->width = "80%";
223 }
224
1e22462d 225 if (!$table->cellpadding) {
226 $table->cellpadding = "5";
227 }
228
229 if (!$table->cellspacing) {
230 $table->cellspacing = "1";
231 }
232
1e3e716f 233 print_simple_box_start("CENTER", "$table->width", "#FFFFFF", 0);
dccd1671 234 echo "<TABLE WIDTH=100% BORDER=0 valign=top align=center ";
1e22462d 235 echo " cellpadding=\"$table->cellpadding\" cellspacing=\"$table->cellspacing\">\n";
f9903ed0 236
237 if ($table->head) {
238 echo "<TR>";
909f539d 239 foreach ($table->head as $key => $heading) {
5b54db6e 240 echo "<TH ".$align[$key].$size[$key].">$heading</TH>";
f9903ed0 241 }
242 echo "</TR>\n";
243 }
244
245 foreach ($table->data as $row) {
246 echo "<TR VALIGN=TOP>";
247 foreach ($row as $key => $item) {
5b54db6e 248 echo "<TD ".$align[$key].$size[$key].">$item</TD>";
f9903ed0 249 }
250 echo "</TR>\n";
251 }
252 echo "</TABLE>\n";
253 print_simple_box_end();
254
255 return true;
256}
257
21ddaf60 258function print_editing_switch($courseid) {
259 global $CFG, $USER;
260
c7e3ac2a 261 if (isteacher($courseid)) {
21ddaf60 262 if ($USER->editing) {
263 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=off\">Turn editing off</A>";
264 } else {
265 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=on\">Turn editing on</A>";
266 }
267 }
268}
269
6b174680 270function update_course_icon($courseid) {
271 global $CFG, $USER;
272
273 if (isteacher($courseid)) {
274 if ($USER->editing) {
2c0411e2 275 return "<A TITLE=\"".get_string("turneditingoff")."\"
276 HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=off\"
6b174680 277 TARGET=_top><IMG SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
278 } else {
2c0411e2 279 return "<A TITLE=\"".get_string("turneditingon")."\"
280 HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=on\"
6b174680 281 TARGET=_top><IMG SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
282 }
283 }
284}
285
286function update_module_icon($moduleid, $courseid) {
287 global $CFG;
288
289 if (isteacher($courseid)) {
2c0411e2 290 return "<A TITLE=\"".get_string("editthisactivity")."\" HREF=\"$CFG->wwwroot/course/mod.php?update=$moduleid&return=true\" TARGET=_top><IMG SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
6b174680 291 }
292}
293
294
39917a09 295function print_date_selector($day, $month, $year, $currenttime=0) {
296// Currenttime is a default timestamp in GMT
297// Prints form items with the names $day, $month and $year
298
299 if (!$currenttime) {
300 $currenttime = time();
301 }
302 $currentdate = usergetdate($currenttime);
303
304 for ($i=1; $i<=31; $i++) {
305 $days[$i] = "$i";
306 }
307 for ($i=1; $i<=12; $i++) {
308 $months[$i] = date("F", mktime(0,0,0,$i,1,2000));
309 }
310 for ($i=2000; $i<=2010; $i++) {
311 $years[$i] = $i;
312 }
313 choose_from_menu($days, $day, $currentdate[mday], "");
314 choose_from_menu($months, $month, $currentdate[mon], "");
315 choose_from_menu($years, $year, $currentdate[year], "");
316}
317
318function print_time_selector($hour, $minute, $currenttime=0) {
319// Currenttime is a default timestamp in GMT
320// Prints form items with the names $hour and $minute
321
322 if (!$currenttime) {
323 $currenttime = time();
324 }
325 $currentdate = usergetdate($currenttime);
326 for ($i=0; $i<=23; $i++) {
327 $hours[$i] = sprintf("%02d",$i);
328 }
329 for ($i=0; $i<=59; $i++) {
330 $minutes[$i] = sprintf("%02d",$i);
331 }
332 choose_from_menu($hours, $hour, $currentdate[hours], "");
333 choose_from_menu($minutes, $minute, $currentdate[minutes], "");
334}
335
336function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0) {
337// Given date parts in user time, produce a GMT timestamp
338
339 return mktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
340}
341
6b174680 342function format_time($totalsecs) {
343// Given an amount of time in seconds, prints it
344// nicely as months, days, hours etc as needed
c7e3ac2a 345
6b174680 346 $totalsecs = abs($totalsecs);
c7e3ac2a 347
6b174680 348 $days = floor($totalsecs/86400);
349 $remainder = $totalsecs - ($days*86400);
350 $hours = floor($remainder/3600);
351 $remainder = $remainder - ($hours*3600);
352 $mins = floor($remainder/60);
353 $secs = $remainder - ($mins*60);
c7e3ac2a 354
6b174680 355 if ($secs != 1) $ss = "s";
356 if ($mins != 1) $ms = "s";
357 if ($hours != 1) $hs = "s";
358 if ($days != 1) $ds = "s";
c7e3ac2a 359
6b174680 360 if ($days) $odays = "$days day$ds";
361 if ($hours) $ohours = "$hours hr$hs";
362 if ($mins) $omins = "$mins min$ms";
363 if ($secs) $osecs = "$secs sec$ss";
364
365 if ($days) return "$odays $ohours";
366 if ($hours) return "$ohours $omins";
367 if ($mins) return "$omins $osecs";
368 if ($secs) return "$osecs";
369 return get_string("now");
370}
f9903ed0 371
5fa51a39 372function userdate($date, $format="", $timezone=99) {
d552ead0 373// Returns a formatted string that represents a date in user time
7a302afc 374// WARNING: note that the format is for strftime(), not date().
375
873960de 376 global $USER;
377
5fa51a39 378 if ($format == "") {
7a302afc 379 $format = "%A, %e %B %Y, %I:%M %p";
5fa51a39 380 }
381 if ($timezone == 99) {
ab247495 382 if (isset($USER->timezone)) {
383 $timezone = (float)$USER->timezone;
384 }
5fa51a39 385 }
386 if (abs($timezone) > 12) {
6d9d8344 387 return strftime("$format", $date);
873960de 388 }
7a302afc 389 return gmstrftime($format, $date + (int)($timezone * 3600));
873960de 390}
391
5fa51a39 392function usergetdate($date, $timezone=99) {
6b174680 393// Given a $date timestamp in GMT, returns an array
394// that represents the date in user time
395
873960de 396 global $USER;
397
5fa51a39 398 if ($timezone == 99) {
399 $timezone = (float)$USER->timezone;
400 }
401 if (abs($timezone) > 12) {
873960de 402 return getdate($date);
403 }
d2d6171f 404 //There is no gmgetdate so I have to fake it...
405 $date = $date + (int)($timezone * 3600);
406 $getdate["seconds"] = gmstrftime("%S", $date);
407 $getdate["minutes"] = gmstrftime("%M", $date);
408 $getdate["hours"] = gmstrftime("%H", $date);
409 $getdate["mday"] = gmstrftime("%d", $date);
410 $getdate["wday"] = gmstrftime("%u", $date);
411 $getdate["mon"] = gmstrftime("%m", $date);
412 $getdate["year"] = gmstrftime("%Y", $date);
413 $getdate["yday"] = gmstrftime("%j", $date);
414 $getdate["weekday"] = gmstrftime("%A", $date);
415 $getdate["month"] = gmstrftime("%B", $date);
416 return $getdate;
d552ead0 417}
418
419function usertime($date, $timezone=99) {
420// Given a GMT timestamp (seconds since epoch), offsets it by
421// the timezone. eg 3pm in India is 3pm GMT - 7 * 3600 seconds
422 global $USER;
423
424 if ($timezone == 99) {
425 $timezone = (float)$USER->timezone;
426 }
427 if (abs($timezone) > 12) {
428 return $date;
429 }
430 return $date - (int)($timezone * 3600);
431}
432
edf7fe8c 433function usergetmidnight($date, $timezone=99) {
434// Given a time, return the GMT timestamp of the most recent midnight
435// for the current user.
edf7fe8c 436 global $USER;
437
4606d9bb 438 if ($timezone == 99) {
439 $timezone = (float)$USER->timezone;
440 }
441
edf7fe8c 442 $userdate = usergetdate($date, $timezone);
4606d9bb 443
444 if (abs($timezone) > 12) {
445 return mktime(0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
446 }
447
edf7fe8c 448 $timemidnight = gmmktime (0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
449 return usertime($timemidnight, $timezone); // Time of midnight of this user's day, in GMT
450
451}
452
d552ead0 453function usertimezone($timezone=99) {
454// returns a string that prints the user's timezone
455 global $USER;
456
457 if ($timezone == 99) {
458 $timezone = (float)$USER->timezone;
459 }
460 if (abs($timezone) > 12) {
461 return "server time";
462 }
463 if (abs($timezone) < 0.5) {
464 return "GMT";
465 }
466 if ($timezone > 0) {
467 return "GMT+$timezone";
468 } else {
469 return "GMT$timezone";
470 }
f9903ed0 471}
472
473
474function error ($message, $link="") {
475 global $CFG, $SESSION;
476
ae350059 477 print_header(get_string("error"));
f9903ed0 478 echo "<BR>";
479 print_simple_box($message, "center", "", "#FFBBBB");
480
481 if (!$link) {
482 if ( !empty($SESSION->fromurl) ) {
483 $link = "$SESSION->fromurl";
484 unset($SESSION->fromurl);
8223d271 485 save_session("SESSION");
f9903ed0 486 } else {
487 $link = "$CFG->wwwroot";
488 }
489 }
dbcb136a 490 print_continue($link);
f9903ed0 491 print_footer();
492 die;
493}
494
65cf9fc3 495function helpbutton ($page, $title="", $module="moodle", $image=true, $text="") {
496 // $page = the keyword that defines a help page
497 // $title = the title of links, rollover tips, alt tags etc
498 // $module = which module is the page defined in
499 // $image = use a help image for the link? (otherwise uses text)
500 // $text = if defined then this text is used in the page, and
501 // the $page variable is ignored.
34c8915d 502 global $CFG;
65cf9fc3 503 if ($module == "") {
504 $module = "moodle";
505 }
506 if ($image) {
507 $linkobject = "<IMG BORDER=0 ALT=\"$title\" SRC=\"$CFG->wwwroot/pix/help.gif\">";
508 } else {
509 $linkobject = $title;
510 }
511 if ($text) {
512 $url = "/help.php?module=$module&text=$text";
513 } else {
6ee45796 514 $url = "/help.php?module=$module&file=$page.html";
65cf9fc3 515 }
516 link_to_popup_window ($url, "popup", $linkobject, 400, 500, $title);
34c8915d 517}
518
f9903ed0 519function notice ($message, $link="") {
520 global $THEME, $HTTP_REFERER;
521
522 if (!$link) {
523 $link = $HTTP_REFERER;
524 }
525
526 echo "<BR>";
527 print_simple_box($message, "center", "", "$THEME->cellheading");
ae350059 528 print_heading("<A HREF=\"$link\">".get_string("continue")."</A>");
f9903ed0 529 print_footer();
530 die;
531}
532
533function notice_yesno ($message, $linkyes, $linkno) {
534 global $THEME;
535
536 print_simple_box_start("center", "", "$THEME->cellheading");
537 echo "<P ALIGN=CENTER><FONT SIZE=3>$message</FONT></P>";
538 echo "<P ALIGN=CENTER><FONT SIZE=3><B>";
ae350059 539 echo "<A HREF=\"$linkyes\">".get_string("yes")."</A>";
f9903ed0 540 echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
ae350059 541 echo "<A HREF=\"$linkno\">".get_string("no")."</A>";
f9903ed0 542 echo "</B></FONT></P>";
543 print_simple_box_end();
544}
545
546function redirect($url, $message="", $delay=0) {
547// Uses META tags to redirect the user, after printing a notice
f9903ed0 548
549 echo "<META HTTP-EQUIV='Refresh' CONTENT='$delay; URL=$url'>";
550
551 if (!empty($message)) {
552 print_header();
553 echo "<CENTER>";
554 echo "<P>$message</P>";
ae350059 555 echo "<P>( <A HREF=\"$url\">".get_string("continue")."</A> )</P>";
f9903ed0 556 echo "</CENTER>";
557 }
558 die;
559}
560
561function notify ($message) {
562 echo "<P align=center><B><FONT COLOR=#FF0000>$message</FONT></B></P>\n";
563}
564
565
566
567/// PARAMETER HANDLING ////////////////////////////////////////////////////
568
569function require_variable($var) {
f9903ed0 570 if (! isset($var)) {
571 error("A required parameter was missing");
572 }
573}
574
575function optional_variable(&$var, $default=0) {
576 if (! isset($var)) {
577 $var = $default;
578 }
579}
580
581
582
583
584/// DATABASE HANDLING ////////////////////////////////////////////////
585
586function execute_sql($command) {
587// Completely general
588
589 global $db;
590
591 $result = $db->Execute("$command");
592
593 if ($result) {
ae350059 594 echo "<P><FONT COLOR=green><B>".get_string("success")."</B></FONT></P>";
f9903ed0 595 return true;
596 } else {
ae350059 597 echo "<P><FONT COLOR=red><B>".get_string("error")."</B></FONT></P>";
f9903ed0 598 return false;
599 }
600}
601
602function modify_database($sqlfile) {
603// Assumes that the input text file consists of a number
604// of SQL statements ENDING WITH SEMICOLONS. The semicolons
605// MUST be the last character in a line.
606// Lines that are blank or that start with "#" are ignored.
607// Only tested with mysql dump files (mysqldump -p -d moodle)
608
609
610 if (file_exists($sqlfile)) {
611 $success = true;
612 $lines = file($sqlfile);
613 $command = "";
614
615 while ( list($i, $line) = each($lines) ) {
616 $line = chop($line);
617 $length = strlen($line);
618
619 if ($length && substr($line, 0, 1) <> "#") {
620 if (substr($line, $length-1, 1) == ";") {
621 $line = substr($line, 0, $length-1); // strip ;
622 $command .= $line;
623 if (! execute_sql($command)) {
624 $success = false;
625 }
626 $command = "";
627 } else {
628 $command .= $line;
629 }
630 }
631 }
632
633 } else {
634 $success = false;
635 echo "<P>Tried to modify database, but \"$sqlfile\" doesn't exist!</P>";
636 }
637
638 return $success;
639}
640
641
642function record_exists($table, $field, $value) {
643 global $db;
644
645 $rs = $db->Execute("SELECT * FROM $table WHERE $field = '$value' LIMIT 1");
646 if (!$rs) return false;
647
648 if ( $rs->RecordCount() ) {
649 return true;
650 } else {
651 return false;
652 }
653}
654
655function record_exists_sql($sql) {
656 global $db;
657
658 $rs = $db->Execute($sql);
659 if (!$rs) return false;
660
661 if ( $rs->RecordCount() ) {
662 return true;
663 } else {
664 return false;
665 }
666}
667
668
669function count_records($table, $selector, $value) {
670// Get all the records and count them
671 global $db;
672
673 $rs = $db->Execute("SELECT COUNT(*) FROM $table WHERE $selector = '$value'");
674 if (!$rs) return 0;
675
676 return $rs->fields[0];
677}
678
679function count_records_sql($sql) {
680// Get all the records and count them
681 global $db;
682
683 $rs = $db->Execute("$sql");
684 if (!$rs) return 0;
685
686 return $rs->fields[0];
687}
688
689function get_record($table, $selector, $value) {
690// Get a single record as an object
691 global $db;
692
693 $rs = $db->Execute("SELECT * FROM $table WHERE $selector = '$value'");
694 if (!$rs) return false;
695
696 if ( $rs->RecordCount() == 1 ) {
697 return (object)$rs->fields;
698 } else {
699 return false;
700 }
701}
702
703function get_record_sql($sql) {
704// Get a single record as an object
705// The sql statement is provided as a string.
706
707 global $db;
708
709 $rs = $db->Execute("$sql");
710 if (!$rs) return false;
711
712 if ( $rs->RecordCount() == 1 ) {
713 return (object)$rs->fields;
714 } else {
715 return false;
716 }
717}
718
719function get_records($table, $selector, $value, $sort="") {
720// Get a number of records as an array of objects
721// Can optionally be sorted eg "time ASC" or "time DESC"
722// The "key" is the first column returned, eg usually "id"
723 global $db;
724
725 if ($sort) {
726 $sortorder = "ORDER BY $sort";
727 }
728 $sql = "SELECT * FROM $table WHERE $selector = '$value' $sortorder";
729
730 return get_records_sql($sql);
731}
732
733function get_records_sql($sql) {
734// Get a number of records as an array of objects
735// The "key" is the first column returned, eg usually "id"
736// The sql statement is provided as a string.
737
738 global $db;
739
740 $rs = $db->Execute("$sql");
741 if (!$rs) return false;
742
743 if ( $rs->RecordCount() > 0 ) {
5c0bef5d 744 if ($records = $rs->GetAssoc(true)) {
745 foreach ($records as $key => $record) {
746 $objects[$key] = (object) $record;
747 }
748 return $objects;
749 } else {
750 return false;
f9903ed0 751 }
f9903ed0 752 } else {
753 return false;
754 }
755}
756
757function get_records_sql_menu($sql) {
758// Given an SQL select, this function returns an associative
759// array of the first two columns. This is most useful in
760// combination with the choose_from_menu function to create
761// a form menu.
762
763 global $db;
764
765 $rs = $db->Execute("$sql");
766 if (!$rs) return false;
767
768 if ( $rs->RecordCount() > 0 ) {
769 while (!$rs->EOF) {
770 $menu[$rs->fields[0]] = $rs->fields[1];
771 $rs->MoveNext();
772 }
773 return $menu;
774
775 } else {
776 return false;
777 }
778}
779
780function get_field($table, $field, $selector, $value) {
781 global $db;
782
783 $rs = $db->Execute("SELECT $field FROM $table WHERE $selector = '$value'");
784 if (!$rs) return false;
785
786 if ( $rs->RecordCount() == 1 ) {
787 return $rs->fields["$field"];
788 } else {
789 return false;
790 }
791}
792
793function set_field($table, $field, $newvalue, $selector, $value) {
794 global $db;
795
796 return $db->Execute("UPDATE $table SET $field = '$newvalue' WHERE $selector = '$value'");
797}
798
a28af1fe 799function set_config($name, $value) {
800// No need for get_config because they are usually always available in $CFG
801
802 if (get_field("config", "value", "name", $name)) {
803 return set_field("config", "value", $value, "name", $name);
804 } else {
805 $config->name = $name;
806 $config->value = $value;
807 return insert_record("config", $config);
808 }
809}
f9903ed0 810
811function delete_records($table, $selector, $value) {
812// Delete one or more records from a table
813 global $db;
814
815 return $db->Execute("DELETE FROM $table WHERE $selector = '$value'");
816}
817
818function insert_record($table, $dataobject) {
819// Insert a record into a table and return the "id" field
820// $dataobject is an object containing needed data
821
822 global $db;
823
824 // Determine all the fields needed
825 if (! $columns = $db->MetaColumns("$table")) {
826 return false;
827 }
828
829 $data = (array)$dataobject;
830
831 // Pull out data matching these fields
832 foreach ($columns as $column) {
e5a57e85 833 if ($column->name <> "id" && isset($data[$column->name]) ) {
f9903ed0 834 $ddd[$column->name] = $data[$column->name];
835 }
836 }
837
838 // Construct SQL queries
839 if (! $numddd = count($ddd)) {
840 return 0;
841 }
842
843 $count = 0;
844 $insert = "";
845 $select = "";
846
847 foreach ($ddd as $key => $value) {
848 $count++;
849 $insert .= "$key = '$value'";
850 $select .= "$key = '$value'";
851 if ($count < $numddd) {
852 $insert .= ", ";
853 $select .= " AND ";
854 }
855 }
856
857 if (! $rs = $db->Execute("INSERT INTO $table SET $insert")) {
858 return false;
859 }
860
861 // Pull it out again to find the id. This is the most cross-platform method.
862 if ($rs = $db->Execute("SELECT id FROM $table WHERE $select")) {
863 return $rs->fields[0];
864 } else {
865 return false;
866 }
867}
868
869
870function update_record($table, $dataobject) {
871// Update a record in a table
872// $dataobject is an object containing needed data
873
874 global $db;
875
5c0bef5d 876 if (! isset($dataobject->id) ) {
f9903ed0 877 return false;
878 }
879
880 // Determine all the fields in the table
1afd014e 881 if (!$columns = $db->MetaColumns($table)) {
882 return false;
883 }
f9903ed0 884 $data = (array)$dataobject;
885
886 // Pull out data matching these fields
887 foreach ($columns as $column) {
5c0bef5d 888 if ($column->name <> "id" && isset($data[$column->name]) ) {
f9903ed0 889 $ddd[$column->name] = $data[$column->name];
890 }
891 }
892
893 // Construct SQL queries
894 $numddd = count($ddd);
895 $count = 0;
896 $update = "";
897
898 foreach ($ddd as $key => $value) {
899 $count++;
900 $update .= "$key = '$value'";
901 if ($count < $numddd) {
902 $update .= ", ";
903 }
904 }
905
906 if ($rs = $db->Execute("UPDATE $table SET $update WHERE id = '$dataobject->id'")) {
907 return true;
908 } else {
909 return false;
910 }
911}
912
913
f93f848a 914function print_object($object) {
915// Mostly just for debugging
916
917 $array = (array)$object;
918 foreach ($array as $key => $item) {
919 echo "$key -> $item <BR>";
920 }
921}
922
923
f9903ed0 924
925/// USER DATABASE ////////////////////////////////////////////////
926
927function get_user_info_from_db($field, $value) {
928
929 global $db;
930
931 if (!$field || !$value)
932 return false;
933
91ac0405 934 if (! $result = $db->Execute("SELECT * FROM user WHERE $field = '$value' AND deleted <> '1'")) {
935 error("Could not find any active users!");
936 }
f9903ed0 937
938 if ( $result->RecordCount() == 1 ) {
939 $user = (object)$result->fields;
940
941 $rs = $db->Execute("SELECT course FROM user_students WHERE user = '$user->id' ");
942 while (!$rs->EOF) {
943 $course = $rs->fields["course"];
944 $user->student["$course"] = true;
945 $rs->MoveNext();
946 }
947
948 $rs = $db->Execute("SELECT course FROM user_teachers WHERE user = '$user->id' ");
949 while (!$rs->EOF) {
950 $course = $rs->fields["course"];
951 $user->teacher["$course"] = true;
952 $rs->MoveNext();
953 }
954
955 $rs = $db->Execute("SELECT * FROM user_admins WHERE user = '$user->id' ");
956 while (!$rs->EOF) {
957 $user->admin = true;
958 $rs->MoveNext();
959 }
960
a83fded1 961 if ($course = get_site()) {
f9903ed0 962 // Everyone is always a member of the top course
963 $user->student["$course->id"] = true;
964 }
965
966 return $user;
967
968 } else {
969 return false;
970 }
971}
972
973function update_user_in_db() {
974
975 global $db, $USER, $REMOTE_ADDR;
976
977 if (!isset($USER->id))
978 return false;
979
980 $timenow = time();
faebaf0f 981 if ($db->Execute("UPDATE user SET lastIP='$REMOTE_ADDR', lastaccess='$timenow' WHERE id = '$USER->id' ")) {
f9903ed0 982 return true;
983 } else {
984 return false;
985 }
986}
987
da5c172a 988function require_login($courseid=0) {
989// This function checks that the current user is logged in, and optionally
990// whether they are "logged in" or allowed to be in a particular course.
991// If not, then it redirects them to the site login or course enrolment.
f9903ed0 992
993 global $CFG, $SESSION, $USER, $FULLME, $HTTP_REFERER, $PHPSESSID;
994
da5c172a 995 // First check that the user is logged in to the site.
7363ff91 996
c21c671d 997 if (! (isset($USER->loggedin) and $USER->confirmed and ($USER->site == $CFG->wwwroot)) ) { // They're not
f9903ed0 998 $SESSION->wantsurl = $FULLME;
7363ff91 999 $SESSION->fromurl = $HTTP_REFERER;
8223d271 1000 save_session("SESSION");
c21c671d 1001 $USER = NULL;
1002 save_session("USER");
f9903ed0 1003 if ($PHPSESSID) { // Cookies not enabled.
a7b9e8bc 1004 redirect("$CFG->wwwroot/login/index.php?PHPSESSID=$PHPSESSID");
f9903ed0 1005 } else {
a7b9e8bc 1006 redirect("$CFG->wwwroot/login/index.php");
f9903ed0 1007 }
1008 die;
f9903ed0 1009 }
da5c172a 1010
1011 // Next, check if the user can be in a particular course
1012 if ($courseid) {
1013 if ($USER->student[$courseid] || $USER->teacher[$courseid] || $USER->admin) {
7363ff91 1014 if (!isset($USER->realuser)) { // Don't update if this isn't a realuser
3ce2f1e0 1015 update_user_in_db();
1016 }
ab998e5d 1017 if (!$USER->email) { // User logged in, but has not set up profile!
1018 // This can occur with external authentication
ab998e5d 1019 redirect("$CFG->wwwroot/user/edit.php?id=$USER->id&course=$courseid");
1020 die;
1021 }
da5c172a 1022 return; // user is a member of this course.
1023 }
1024 if (! $course = get_record("course", "id", $courseid)) {
1025 error("That course doesn't exist");
1026 }
7363ff91 1027 if ($USER->username == "guest") {
1028 switch ($course->guest) {
1029 case 0: // Guests not allowed
1030 print_header();
1031 notice(get_string("guestsnotallowed", "", $course->fullname));
1032 break;
1033 case 1: // Guests allowed
1034 update_user_in_db();
1035 return;
1036 case 2: // Guests allowed with key (drop through)
1037 break;
1038 }
da5c172a 1039 }
f9903ed0 1040
7363ff91 1041 // Currently not enrolled in the course, so see if they want to enrol
da5c172a 1042 $SESSION->wantsurl = $FULLME;
8223d271 1043 save_session("SESSION");
da5c172a 1044 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
1045 die;
1046 }
f9903ed0 1047}
1048
1049
1050
1051function update_login_count() {
1052 global $SESSION;
1053
1054 $max_logins = 10;
1055
1056 if (empty($SESSION->logincount)) {
1057 $SESSION->logincount = 1;
1058 } else {
1059 $SESSION->logincount++;
1060 }
8223d271 1061 save_session("SESSION");
f9903ed0 1062
1063 if ($SESSION->logincount > $max_logins) {
1064 unset($SESSION->wantsurl);
8223d271 1065 save_session("SESSION");
f9903ed0 1066 error("Sorry, you have exceeded the allowed number of login attempts. Restart your browser.");
1067 }
1068}
1069
d578afc8 1070function remove_admin($user) {
1071 global $db;
1072
1073 return $db->Execute("DELETE FROM user_admins WHERE user = '$user'");
1074}
1075
1076function remove_teacher($user, $course=0) {
1077 global $db;
1078
1079 if ($course) {
45aa6d56 1080 /// First delete any crucial stuff that might still send mail
1081 if ($forums = get_records("forum", "course", $course)) {
1082 foreach ($forums as $forum) {
1083 $db->Execute("DELETE FROM forum_subscriptions WHERE forum = '$forum->id' AND user = '$user'");
1084 }
1085 }
d578afc8 1086 return $db->Execute("DELETE FROM user_teachers WHERE user = '$user' AND course = '$course'");
1087 } else {
45aa6d56 1088 delete_records("forum_subscriptions", "user", $user);
1089 return delete_records("user_teachers", "user", $user);
d578afc8 1090 }
1091}
1092
1093
1094function enrol_student($user, $course) {
1095 global $db;
1096
1097 $timenow = time();
1098
1099 $rs = $db->Execute("INSERT INTO user_students (user, course, start, end, time)
1100 VALUES ($user, $course, 0, 0, $timenow)");
1101 if ($rs) {
1102 return true;
1103 } else {
1104 return false;
1105 }
1106}
1107
1108function unenrol_student($user, $course=0) {
1109 global $db;
1110
1111 if ($course) {
45aa6d56 1112 /// First delete any crucial stuff that might still send mail
1113 if ($forums = get_records("forum", "course", $course)) {
1114 foreach ($forums as $forum) {
1115 $db->Execute("DELETE FROM forum_subscriptions WHERE forum = '$forum->id' AND user = '$user'");
1116 }
1117 }
d578afc8 1118 return $db->Execute("DELETE FROM user_students WHERE user = '$user' AND course = '$course'");
45aa6d56 1119
d578afc8 1120 } else {
45aa6d56 1121 delete_records("forum_subscriptions", "user", $user);
1122 return delete_records("user_students", "user", $user);
d578afc8 1123 }
1124}
1125
f9903ed0 1126
1127function isadmin($userid=0) {
1128 global $USER;
1129
1130 if (!$userid) {
1131 return $USER->admin;
1132 }
1133
1134 return record_exists_sql("SELECT * FROM user_admins WHERE user='$userid'");
1135}
1136
8a9e3fd7 1137function isteacher($courseid, $userid=0) {
f9903ed0 1138 global $USER;
1139
d115a57f 1140 if (isadmin($userid)) { // admins can do anything the teacher can
1141 return true;
1142 }
1143
f9903ed0 1144 if (!$userid) {
8a9e3fd7 1145 return $USER->teacher[$courseid];
f9903ed0 1146 }
1147
8a9e3fd7 1148 return record_exists_sql("SELECT * FROM user_teachers WHERE user='$userid' AND course='$courseid'");
f9903ed0 1149}
1150
1151
8a9e3fd7 1152function isstudent($courseid, $userid=0) {
f9903ed0 1153 global $USER;
1154
1155 if (!$userid) {
8a9e3fd7 1156 return $USER->student[$courseid];
f9903ed0 1157 }
1158
1159 $timenow = time(); // todo: add time check below
1160
8a9e3fd7 1161 return record_exists_sql("SELECT * FROM user_students WHERE user='$userid' AND course='$courseid'");
f9903ed0 1162}
1163
da5c172a 1164function isguest($userid=0) {
1165 global $USER;
1166
1167 if (!$userid) {
1168 return ($USER->username == "guest");
1169 }
1170
a3447e10 1171 return record_exists_sql("SELECT * FROM user WHERE id='$userid' AND username = 'guest' ");
da5c172a 1172}
1173
2c309dc2 1174function isediting($courseid, $user=NULL) {
1175 global $USER;
1176 if (!$user){
1177 $user = $USER;
1178 }
1179 return ($user->editing and isteacher($courseid, $user->id));
1180}
1181
f9903ed0 1182function reset_login_count() {
1183 global $SESSION;
1184
1185 $SESSION->logincount = 0;
8223d271 1186 save_session("SESSION");
f9903ed0 1187}
1188
1189
1190function set_moodle_cookie($thing) {
1191
1192 $days = 60;
1193 $seconds = 60*60*24*$days;
1194
d115a57f 1195 setCookie ('MOODLEID', "", time() - 3600, "/");
f9903ed0 1196 setCookie ('MOODLEID', rc4encrypt($thing), time()+$seconds, "/");
1197}
1198
1199
1200function get_moodle_cookie() {
1201 global $MOODLEID;
1202 return rc4decrypt($MOODLEID);
1203}
1204
1205
8223d271 1206function save_session($VAR) {
1207// Copies temporary session variable to permanent sesson variable
1208// eg $_SESSION["USER"] = $USER;
1209 global $$VAR;
1210 $_SESSION[$VAR] = $$VAR;
1211}
1212
f9903ed0 1213
faebaf0f 1214function create_user_record($username, $password) {
1215// Creates a bare-bones user record
1216 global $REMOTE_ADDR;
f9903ed0 1217
faebaf0f 1218 $newuser->username = $username;
1219 $newuser->password = md5($password);
1220 $newuser->confirmed = 1;
1221 $newuser->lastIP = $REMOTE_ADDR;
1222 $newuser->timemodified = time();
f9903ed0 1223
faebaf0f 1224 if (insert_record("user", $newuser)) {
1225 return get_user_info_from_db("username", $username);
1226 }
1227 return false;
1228}
1229
1230function authenticate_user_login($username, $password) {
1231// Given a username and password, this function looks them
1232// up using the currently selected authentication mechanism,
1233// and if the authentication is successful, it returns a
1234// valid $user object from the 'user' table.
1235//
1236// Uses auth_ functions from the currently active auth module
1237
1238 global $CFG;
1239
1240 if (!isset($CFG->auth)) {
1241 $CFG->auth = "email"; // Default authentication module
1242 }
1243
1244 require("$CFG->dirroot/auth/$CFG->auth/lib.php");
1245
1246 if (auth_user_login($username, $password)) { // Successful authentication
1247
1248 if ($user = get_user_info_from_db("username", $username)) {
1249 if (md5($password) <> $user->password) {
1250 set_field("user", "password", md5($password), "username", $username);
1251 }
1252 return $user;
1253
1254 } else {
1255 return create_user_record($username, $password);
1256 }
f9903ed0 1257 }
faebaf0f 1258 return false;
f9903ed0 1259}
1260
faebaf0f 1261
f9903ed0 1262function get_site () {
1263// Returns $course object of the top-level site.
1264 if ( $course = get_record("course", "category", 0)) {
1265 return $course;
1266 } else {
1267 return false;
1268 }
1269}
1270
1271function get_admin () {
1272// Returns $user object of the main admin user
1273
1274 if ( $admins = get_records_sql("SELECT u.* FROM user u, user_admins a WHERE a.user = u.id ORDER BY u.id ASC")) {
1275 foreach ($admins as $admin) {
bb09fb11 1276 return $admin; // ie the first one
f9903ed0 1277 }
1278 } else {
1279 return false;
1280 }
1281}
1282
1283function get_teacher($courseid) {
1284// Returns $user object of the main teacher for a course
1285 if ( $teachers = get_records_sql("SELECT u.* FROM user u, user_teachers t
1286 WHERE t.user = u.id AND t.course = '$courseid'
1287 ORDER BY t.authority ASC")) {
1288 foreach ($teachers as $teacher) {
bb09fb11 1289 if ($teacher->authority) {
1290 return $teacher; // the highest authority teacher
1291 }
f9903ed0 1292 }
1293 } else {
1294 return false;
1295 }
1296}
1297
3c720cce 1298function get_course_students($courseid, $sort="u.lastaccess DESC") {
1299 return get_records_sql("SELECT u.* FROM user u, user_students s
bb09fb11 1300 WHERE s.course = '$courseid' AND s.user = u.id AND u.deleted = '0'
3c720cce 1301 ORDER BY $sort");
1302}
1303
1304function get_course_teachers($courseid, $sort="t.authority ASC") {
b4d7002e 1305 return get_records_sql("SELECT u.*,t.authority,t.role FROM user u, user_teachers t
bb09fb11 1306 WHERE t.course = '$courseid' AND t.user = u.id AND u.deleted = '0'
3c720cce 1307 ORDER BY $sort");
1308}
1309
1310function get_course_users($courseid, $sort="u.lastaccess DESC") {
57507290 1311// Using this method because the direct SQL just would not always work!
1312
1313 $teachers = get_course_teachers($courseid, $sort);
1314 $students = get_course_students($courseid, $sort);
1315
1316 if ($teachers and $students) {
1317 return array_merge($teachers, $students);
1318 } else if ($teachers) {
1319 return $teachers;
1320 } else {
1321 return $students;
1322 }
1323
1324// return get_records_sql("SELECT u.* FROM user u, user_students s, user_teachers t
1325// WHERE (s.course = '$courseid' AND s.user = u.id) OR
1326// (t.course = '$courseid' AND t.user = u.id)
1327// ORDER BY $sort");
3c720cce 1328}
1329
f9903ed0 1330
1331
1332/// MODULE FUNCTIONS /////////////////////////////////////////////////
1333
1ea8303c 1334function get_coursemodule_from_instance($modulename, $instance, $courseid) {
f9903ed0 1335// Given an instance of a module, finds the coursemodule description
1336
1337 return get_record_sql("SELECT cm.*, m.name
1338 FROM course_modules cm, modules md, $modulename m
1ea8303c 1339 WHERE cm.course = '$courseid' AND
f9903ed0 1340 cm.deleted = '0' AND
1341 cm.instance = m.id AND
1342 md.name = '$modulename' AND
1343 md.id = cm.module AND
1344 m.id = '$instance'");
1345
1346}
1347
1ea8303c 1348function get_all_instances_in_course($modulename, $courseid, $sort="cw.section") {
f9903ed0 1349// Returns an array of all the active instances of a particular
1350// module in a given course. Returns false on any errors.
1351
9ccbad71 1352 return get_records_sql("SELECT m.*,cw.section,cm.id as coursemodule
1353 FROM course_modules cm, course_sections cw, modules md, $modulename m
1ea8303c 1354 WHERE cm.course = '$courseid' AND
f9903ed0 1355 cm.instance = m.id AND
1356 cm.deleted = '0' AND
9ccbad71 1357 cm.section = cw.id AND
f9903ed0 1358 md.name = '$modulename' AND
1359 md.id = cm.module
1360 ORDER BY $sort");
1361
1362}
1363
f9903ed0 1364
1365
1366
f9903ed0 1367/// CORRESPONDENCE ////////////////////////////////////////////////
1368
5fa51a39 1369function email_to_user($user, $from, $subject, $messagetext, $messagehtml="", $attachment="", $attachname="") {
1370// user - a user record as an object
1371// from - a user record as an object
1372// subject - plain text subject line of the email
136dabd8 1373// messagetext - plain text version of the message
1374// messagehtml - complete html version of the message (optional)
1375// attachment - a file on the filesystem, relative to $CFG->dataroot
1376// attachname - the name of the file (extension indicates MIME)
f9903ed0 1377
4216daa6 1378 global $CFG, $_SERVER;
f9903ed0 1379
136dabd8 1380 include_once("$CFG->libdir/phpmailer/class.phpmailer.php");
f9903ed0 1381
5fa51a39 1382 if (!$user) {
f9903ed0 1383 return false;
1384 }
1385
f9903ed0 1386 $mail = new phpmailer;
1387
1e411ffc 1388 $mail->Version = "Moodle $CFG->moodleversion"; // mailer version
136dabd8 1389 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
562bbe90 1390
7f86ce17 1391 if ($CFG->smtphosts) {
1e411ffc 1392 $mail->IsSMTP(); // use SMTP directly
1393 $mail->Host = "$CFG->smtphosts"; // specify main and backup servers
7f86ce17 1394 } else {
1e411ffc 1395 $mail->IsMail(); // use PHP mail() = sendmail
7f86ce17 1396 }
f9903ed0 1397
136dabd8 1398 $mail->From = "$from->email";
1399 $mail->FromName = "$from->firstname $from->lastname";
1400 $mail->Subject = stripslashes($subject);
f9903ed0 1401
6b174680 1402 $mail->AddAddress("$user->email", "$user->firstname $user->lastname");
f9903ed0 1403
f9903ed0 1404 $mail->WordWrap = 70; // set word wrap
f9903ed0 1405
136dabd8 1406 if ($messagehtml) {
1407 $mail->IsHTML(true);
1408 $mail->Body = $messagehtml;
78681899 1409 $mail->AltBody = "\n$messagetext\n";
136dabd8 1410 } else {
1411 $mail->IsHTML(false);
78681899 1412 $mail->Body = "\n$messagetext\n";
f9903ed0 1413 }
1414
136dabd8 1415 if ($attachment && $attachname) {
1416 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
4216daa6 1417 $adminuser = get_admin();
1418 $mail->AddAddress("$adminuser->email", "$adminuser->firstname $adminuser->lastname");
1419 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
136dabd8 1420 } else {
1421 include_once("$CFG->dirroot/files/mimetypes.php");
1422 $mimetype = mimeinfo("type", $attachname);
1423 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
1424 }
f9903ed0 1425 }
1426
136dabd8 1427 if ($mail->Send()) {
1428 return true;
1429 } else {
4216daa6 1430 echo "ERROR: $mail->ErrorInfo\n";
1431 $site = get_site();
1432 add_to_log($site->id, "library", "mailer", $_SERVER["REQUEST_URI"], "ERROR: $mail->ErrorInfo");
f9903ed0 1433 return false;
1434 }
f9903ed0 1435}
1436
136dabd8 1437
f9903ed0 1438/// FILE HANDLING /////////////////////////////////////////////
1439
6b174680 1440function make_upload_directory($directory) {
1441// $directory = a string of directory names under $CFG->dataroot
1442// eg stuff/assignment/1
1443// Returns full directory if successful, false if not
1444
1445 global $CFG;
1446
1447 $currdir = $CFG->dataroot;
1448 if (!file_exists($currdir)) {
1449 if (! mkdir($currdir, 0750)) {
1450 notify("ERROR: You need to create the directory $currdir with web server write access");
1451 return false;
1452 }
1453 }
1454
1455 $dirarray = explode("/", $directory);
1456
1457 foreach ($dirarray as $dir) {
1458 $currdir = "$currdir/$dir";
1459 if (! file_exists($currdir)) {
1460 if (! mkdir($currdir, 0750)) {
1461 notify("ERROR: Could not find or create a directory ($currdir)");
1462 return false;
1463 }
1464 }
1465 }
1466
1467 return $currdir;
1468}
1469
ca4f8eb8 1470function make_mod_upload_directory($courseid) {
1471 global $CFG;
1472
1473 if (! $moddata = make_upload_directory("$courseid/$CFG->moddata")) {
1474 return false;
1475 }
1476
1477 $strreadme = get_string("readme");
1478
1479 if (file_exists("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt")) {
1480 copy("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt", "$moddata/$strreadme.txt");
1481 } else {
1482 copy("$CFG->dirroot/lang/en/docs/module_files.txt", "$moddata/$strreadme.txt");
1483 }
1484 return $moddata;
1485}
1486
6b174680 1487
44e2d2bb 1488function valid_uploaded_file($newfile) {
1489// Returns current name of file on disk if true
1490 if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
1491 return $newfile['tmp_name'];
1492 } else {
1493 return "";
1494 }
1495}
1496
1497function get_max_upload_file_size() {
1498 if (! $filesize = ini_get("upload_max_filesize")) {
1499 $filesize = "5M";
1500 }
1501 return get_real_size($filesize);
1502}
1503
1504
774ab660 1505function get_directory_list($rootdir, $excludefile="", $descend=true) {
f9903ed0 1506// Returns an array with all the filenames in
1507// all subdirectories, relative to the given rootdir.
ca4f8eb8 1508// If excludefile is defined, then that file/directory is ignored
f9903ed0 1509
1510 $dirs = array();
1511
44e2d2bb 1512 $dir = opendir($rootdir);
f9903ed0 1513
ca4f8eb8 1514 while ($file = readdir($dir)) {
774ab660 1515 if ($file != "." and $file != ".." and $file != "CVS" and $file != $excludefile) {
ca4f8eb8 1516 $fullfile = $rootdir."/".$file;
774ab660 1517 if ($descend and filetype($fullfile) == "dir") {
1518 $subdirs = get_directory_list($fullfile, $excludefile, $descend);
f9903ed0 1519 foreach ($subdirs as $subdir) {
1520 $dirs[] = $file."/".$subdir;
1521 }
1522 } else {
1523 $dirs[] = $file;
1524 }
1525 }
1526 }
44e2d2bb 1527 closedir($dir);
f9903ed0 1528
774ab660 1529 asort($dirs);
1530
f9903ed0 1531 return $dirs;
1532}
1533
989bfa9d 1534function get_real_size($size=0) {
1535// Converts numbers like 10M into bytes
1536 if (!$size) {
1537 return 0;
1538 }
1539 $scan['MB'] = 1048576;
1540 $scan['M'] = 1048576;
1541 $scan['KB'] = 1024;
1542 $scan['K'] = 1024;
1543
1544 while (list($key) = each($scan)) {
1545 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
1546 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
1547 break;
1548 }
1549 }
1550 return $size;
1551}
1552
44e2d2bb 1553function display_size($size) {
1554// Converts bytes into display form
1555 if ($size >= 1073741824) {
1556 $size = round($size / 1073741824 * 10) / 10 . "Gb";
1557 } else if ($size >= 1048576) {
1558 $size = round($size / 1048576 * 10) / 10 . "Mb";
1559 } else if ($size >= 1024) {
1560 $size = round($size / 1024 * 10) / 10 . "Kb";
1561 } else {
1562 $size = $size . "b";
1563 }
1564 return $size;
1565}
1566
6b174680 1567function clean_filename($string) {
1568 $string = eregi_replace("\.\.", "", $string);
1569 $string = eregi_replace("[^([:alnum:]|\.)]", "_", $string);
1570 return eregi_replace("_+", "_", $string);
1571}
1572
1573
1180c6dc 1574/// STRING TRANSLATION ////////////////////////////////////////
1575
a83fded1 1576function print_string($identifier, $module="", $a=NULL) {
1577 echo get_string($identifier, $module, $a);
bcc83c41 1578}
1579
4bfa92e7 1580function current_language() {
1581// Returns the code for the current language
1582 global $CFG, $USER;
1583
1584 if (isset($USER->lang)) { // User language can override site language
1585 return $USER->lang;
1586 } else {
1587 return $CFG->lang;
1588 }
1589}
bcc83c41 1590
a83fded1 1591function get_string($identifier, $module="", $a=NULL) {
1180c6dc 1592// Return the translated string specified by $identifier as
1593// for $module. Uses the same format files as STphp.
a83fded1 1594// $a is an object, string or number that can be used
1180c6dc 1595// within translation strings
a83fded1 1596//
1597// eg "hello \$a->firstname \$a->lastname"
1598// or "hello \$a"
1180c6dc 1599
4bfa92e7 1600 global $CFG;
1180c6dc 1601
4bfa92e7 1602 $lang = current_language();
1180c6dc 1603
058eec18 1604 if ($module == "") {
1605 $module = "moodle";
1180c6dc 1606 }
1607
058eec18 1608 $langpath = "$CFG->dirroot/lang";
1609 $langfile = "$langpath/$lang/$module.php";
1180c6dc 1610
1611 if (!file_exists($langfile)) { // try English instead
058eec18 1612 $langfile = "$langpath/en/$module.php";
1180c6dc 1613 if (!file_exists($langfile)) {
058eec18 1614 return "ERROR: No lang file ($langpath/en/$module.php)!";
1180c6dc 1615 }
1616 }
1617
1618 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1619
1620 eval($result);
1621 return $resultstring;
1622
1623 } else {
1624 if ($lang == "en") {
44e2d2bb 1625 return "[['$identifier']]";
1180c6dc 1626
1627 } else { // Try looking in the english file.
058eec18 1628 $langfile = "$langpath/en/$module.php";
1180c6dc 1629 if (!file_exists($langfile)) {
058eec18 1630 return "ERROR: No lang file ($langpath/en/$module.php)!";
1180c6dc 1631 }
1632 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1633 eval($result);
1634 return $resultstring;
1635 } else {
44e2d2bb 1636 return "[['$identifier']]";
1180c6dc 1637 }
1638 }
1639 }
1640}
1641
1642
1180c6dc 1643function get_string_from_file($identifier, $langfile, $destination) {
1644// This function is only used from get_string().
1645 include ($langfile);
1646
1647 if (!isset ($string[$identifier])) {
1648 return false;
1649 }
1650
a83fded1 1651 return "$destination = sprintf(\"".$string[$identifier]."\");";
1180c6dc 1652}
f9903ed0 1653
1654
1a72314d 1655function get_list_of_languages() {
1656/// Returns a list of language codes and their full names
1657 global $CFG;
1658
1659 if (!$langdirs = get_list_of_plugins("lang")) {
1660 return false;
1661 }
1662
1663 foreach ($langdirs as $lang) {
1664 include("$CFG->dirroot/lang/$lang/moodle.php");
1665 $languages[$lang] = $string["thislanguage"]." ($lang)";
1666 unset($string);
1667 }
1668 return $languages;
1669}
1670
1671
f9903ed0 1672/// ENCRYPTION ////////////////////////////////////////////////
1673
1674function rc4encrypt($data) {
1675 $password = "nfgjeingjk";
1676 return endecrypt($password, $data, "");
1677}
1678
1679function rc4decrypt($data) {
1680 $password = "nfgjeingjk";
1681 return endecrypt($password, $data, "de");
1682}
1683
1684function endecrypt ($pwd, $data, $case) {
1685// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
1686
1687 if ($case == 'de') {
1688 $data = urldecode($data);
1689 }
1690
1691 $key[] = "";
1692 $box[] = "";
1693 $temp_swap = "";
1694 $pwd_length = 0;
1695
1696 $pwd_length = strlen($pwd);
1697
1698 for ($i = 0; $i <= 255; $i++) {
1699 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
1700 $box[$i] = $i;
1701 }
1702
1703 $x = 0;
1704
1705 for ($i = 0; $i <= 255; $i++) {
1706 $x = ($x + $box[$i] + $key[$i]) % 256;
1707 $temp_swap = $box[$i];
1708 $box[$i] = $box[$x];
1709 $box[$x] = $temp_swap;
1710 }
1711
1712 $temp = "";
1713 $k = "";
1714
1715 $cipherby = "";
1716 $cipher = "";
1717
1718 $a = 0;
1719 $j = 0;
1720
1721 for ($i = 0; $i < strlen($data); $i++) {
1722 $a = ($a + 1) % 256;
1723 $j = ($j + $box[$a]) % 256;
1724 $temp = $box[$a];
1725 $box[$a] = $box[$j];
1726 $box[$j] = $temp;
1727 $k = $box[(($box[$a] + $box[$j]) % 256)];
1728 $cipherby = ord(substr($data, $i, 1)) ^ $k;
1729 $cipher .= chr($cipherby);
1730 }
1731
1732 if ($case == 'de') {
1733 $cipher = urldecode(urlencode($cipher));
1734 } else {
1735 $cipher = urlencode($cipher);
1736 }
1737
1738 return $cipher;
1739}
1740
1741
1742/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
1743
39917a09 1744function count_words($string) {
1745 $string = strip_tags($string);
1746 return count(preg_split("/\w\b/", $string)) - 1;
1747}
1748
f9903ed0 1749function getweek ($startdate, $thedate) {
1750// Given dates in seconds, how many weeks is the date from startdate
1751// The first week is 1, the second 2 etc ...
1752
1753 if ($thedate < $startdate) { // error
1754 return 0;
1755 }
1756
1757 return floor(($thedate - $startdate) / 604800.0) + 1;
1758}
1759
4216daa6 1760function add_to_log($course, $module, $action, $url="", $info="") {
1761// Add an entry to the log table. These are "action" focussed rather
1762// than web server hits, and provide a way to easily reconstruct what
1763// any particular student has been doing.
1764//
1765// course = the course id
501cdbd8 1766// module = forum, journal, reading, course, user etc
4216daa6 1767// action = view, edit, post (often but not always the same as the file.php)
1768// url = the file and parameters used to see the results of the action
1769// info = additional description information
1770
1771
f9903ed0 1772 global $db, $USER, $REMOTE_ADDR;
1773
9132e866 1774 if (isset($USER->realuser)) { // Don't log
1775 return;
1776 }
1777
f9903ed0 1778 $timenow = time();
4216daa6 1779 $info = addslashes($info);
1780
1781 $result = $db->Execute("INSERT INTO log
1782 SET time = '$timenow',
1783 user = '$USER->id',
1784 course = '$course',
1785 ip = '$REMOTE_ADDR',
1786 module = '$module',
1787 action = '$action',
1788 url = '$url',
1789 info = '$info'");
f9903ed0 1790 if (!$result) {
4216daa6 1791 echo "<P>Error: Could not insert a new entry to the Moodle log</P>"; // Don't throw an error
f9903ed0 1792 }
1793}
1794
1795function generate_password($maxlen=10) {
53bfe78c 1796// returns a randomly generated password of length $maxlen. inspired by
1797// http://www.phpbuilder.com/columns/jesus19990502.php3
f9903ed0 1798
1799 global $CFG;
1800
1801 $fillers = "1234567890!$-+";
1802 $wordlist = file($CFG->wordlist);
1803
1804 srand((double) microtime() * 1000000);
1805 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1806 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1807 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
1808
1809 return substr($word1 . $filler1 . $word2, 0, $maxlen);
1810}
1811
53bfe78c 1812function moodle_needs_upgrading() {
1813// Checks version numbers of Main code and all modules to see
1814// if there are any mismatches ... returns true or false
1815 global $CFG;
1816
1817 include_once("$CFG->dirroot/version.php"); # defines $version and upgrades
a28af1fe 1818 if ($CFG->version) {
1819 if ($version > $CFG->version) {
53bfe78c 1820 return true;
1821 }
1e3e716f 1822 if ($mods = get_list_of_plugins("mod")) {
53bfe78c 1823 foreach ($mods as $mod) {
1824 $fullmod = "$CFG->dirroot/mod/$mod";
1825 unset($module);
1826 include_once("$fullmod/version.php"); # defines $module with version etc
1827 if ($currmodule = get_record("modules", "name", $mod)) {
1828 if ($module->version > $currmodule->version) {
1829 return true;
1830 }
1831 }
1832 }
1833 }
1834 } else {
1835 return true;
1836 }
1837 return false;
53bfe78c 1838}
1839
1840
1e3e716f 1841function get_list_of_plugins($plugin="mod") {
1842// Lists plugin directories within some directory
1843
53bfe78c 1844 global $CFG;
1845
1e3e716f 1846 $basedir = opendir("$CFG->dirroot/$plugin");
1847 while ($dir = readdir($basedir)) {
1848 if ($dir == "." || $dir == ".." || $dir == "CVS") {
53bfe78c 1849 continue;
1850 }
1e3e716f 1851 if (filetype("$CFG->dirroot/$plugin/$dir") != "dir") {
53bfe78c 1852 continue;
1853 }
1e3e716f 1854 $plugins[] = $dir;
53bfe78c 1855 }
1e3e716f 1856 if ($plugins) {
1857 asort($plugins);
1858 }
1859 return $plugins;
53bfe78c 1860}
1861
1e3e716f 1862
b0cb5e22 1863function check_php_version($version="4.1.0") {
1864// Returns true is the current version of PHP is greater that the specified one
1865 $minversion = intval(str_replace(".", "", $version));
1866 $curversion = intval(str_replace(".", "", phpversion()));
1867 return ($curversion >= $minversion);
1868}
1869
f9903ed0 1870
74944b73 1871function check_gd_version() {
1872 ob_start();
1873 phpinfo();
1874 $phpinfo = ob_get_contents();
1875 ob_end_clean();
1876
1877 $phpinfo = explode("\n",$phpinfo);
1878
1879 $gdversion = 0;
1880
1881 foreach ($phpinfo as $text) {
1882 $parts = explode('</b>',$text);
1883 foreach ($parts as $key => $val) {
1884 $parts[$key] = strip_tags($val);
1885 }
1886 if ($parts[0]=="GD Version") {
1887 $gdversion = intval($parts[1]);
1888 }
1889 }
1890
1891 return $gdversion; // 1, 2 or 0
1892}
f9903ed0 1893
f9903ed0 1894?>