Display tweaks
[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 }
29
30 if (!$cache) { // Do everything we can to prevent clients and proxies caching
31 @header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
32 @header("Pragma: no-cache");
33 $meta .= "\n<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">";
34 $meta .= "\n<META HTTP-EQUIV=\"Expires\" CONTENT=\"0\">";
35 }
36
37 include ("$CFG->dirroot/theme/$CFG->theme/header.html");
38}
39
40function print_footer ($course=NULL) {
41// Can provide a course object to make the footer contain a link to
42// to the course home page, otherwise the link will go to the site home
43 global $USER, $CFG, $THEME;
44
45 if ($course) {
46 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</A>";
47 } else {
48 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot\">Home</A>";
49 }
50 include ("$CFG->dirroot/theme/$CFG->theme/footer.html");
51}
52
53function print_navigation ($navigation) {
54 global $CFG;
55
a2eaeb91 56 if (! $site = get_record("course", "category", 0)) {
57 $site->shortname = "Home";
58 }
f9903ed0 59 if ($navigation) {
a2eaeb91 60 echo "<A TARGET=_top HREF=\"$CFG->wwwroot/\">$site->shortname</A> -> $navigation";
f9903ed0 61 }
62}
63
2a46a71b 64function print_heading($text, $align="CENTER", $size=3) {
65 echo "<P ALIGN=\"$align\"><FONT SIZE=\"$size\"><B>$text</B></FONT></P>";
f9903ed0 66}
67
4216daa6 68function print_simple_box($message, $align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
69 print_simple_box_start($align, $width, $color, $padding, $border);
f9903ed0 70 echo "<P>$message</P>";
71 print_simple_box_end();
72}
73
4216daa6 74function print_simple_box_start($align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
f9903ed0 75 global $THEME;
76
77 if ($align) {
78 $tablealign = "ALIGN=\"$align\"";
79 }
80 if ($width) {
81 $tablewidth = "WIDTH=\"$width\"";
82 $innertablewidth = "WIDTH=\"100%\"";
83 }
4216daa6 84 echo "<TABLE $tablealign $tablewidth BORDER=0 CELLPADDING=\"$border\" CELLSPACING=0>";
f9903ed0 85 echo "<TR><TD BGCOLOR=\"$THEME->borders\">\n";
86 echo "<TABLE $innertablewidth BORDER=0 CELLPADDING=\"$padding\" CELLSPACING=0><TR><TD BGCOLOR=\"$color\">";
87}
88
89function print_simple_box_end() {
90 echo "</TD></TR></TABLE>";
91 echo "</TD></TR></TABLE>";
92}
93
94function print_single_button($link, $options, $label="OK") {
95 echo "<FORM ACTION=\"$link\" METHOD=GET>";
96 foreach ($options as $name => $value) {
97 echo "<INPUT TYPE=hidden NAME=\"$name\" VALUE=\"$value\">";
98 }
99 echo "<INPUT TYPE=submit VALUE=\"$label\"></FORM>";
100}
101
136dabd8 102function print_user_picture($userid, $courseid, $picture, $large=false, $returnstring=false) {
f9903ed0 103 global $CFG;
104
136dabd8 105 $output = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$userid&course=$courseid\">";
f9903ed0 106 if ($large) {
107 $file = "f1.jpg";
108 $size = 100;
109 } else {
110 $file = "f2.jpg";
111 $size = 35;
112 }
113 if ($picture) {
136dabd8 114 $output .= "<IMG SRC=\"$CFG->wwwroot/user/pix.php/$userid/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
f9903ed0 115 } else {
136dabd8 116 $output .= "<IMG SRC=\"$CFG->wwwroot/user/default/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
117 }
118 $output .= "</A>";
119
120 if ($returnstring) {
121 return $output;
122 } else {
123 echo $output;
f9903ed0 124 }
f9903ed0 125}
126
127function print_table($table) {
128// Prints a nicely formatted table.
129// $table is an object with three properties.
130// $table->head is an array of heading names.
131// $table->align is an array of column alignments
132// $table->data[] is an array of arrays containing the data.
133
134 if ( $table->align) {
135 foreach ($table->align as $key => $aa) {
136 if ($aa) {
137 $align[$key] = "ALIGN=\"$aa\"";
138 } else {
139 $align[$key] = "";
140 }
141 }
142 }
143
144 echo "<BR>";
145
146 print_simple_box_start("CENTER","","#FFFFFF",0);
147 echo "<TABLE BORDER=0 valign=top align=center cellpadding=10 cellspacing=1>\n";
148
149 if ($table->head) {
150 echo "<TR>";
151 foreach ($table->head as $heading) {
152 echo "<TH>$heading</TH>";
153 }
154 echo "</TR>\n";
155 }
156
157 foreach ($table->data as $row) {
158 echo "<TR VALIGN=TOP>";
159 foreach ($row as $key => $item) {
160 echo "<TD ".$align[$key].">$item</TD>";
161 }
162 echo "</TR>\n";
163 }
164 echo "</TABLE>\n";
165 print_simple_box_end();
166
167 return true;
168}
169
21ddaf60 170function print_editing_switch($courseid) {
171 global $CFG, $USER;
172
c7e3ac2a 173 if (isteacher($courseid)) {
21ddaf60 174 if ($USER->editing) {
175 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=off\">Turn editing off</A>";
176 } else {
177 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=on\">Turn editing on</A>";
178 }
179 }
180}
181
c7e3ac2a 182function update_course_icon($courseid) {
183 global $CFG, $USER;
184
185 if (isteacher($courseid)) {
186 if ($USER->editing) {
187 return "<A TITLE=\"Turn editing OFF\" HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=off\"
188 TARGET=_top><IMG SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
189 } else {
190 return "<A TITLE=\"Turn editing ON\" HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=on\"
191 TARGET=_top><IMG SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
192 }
193 }
194}
195
196function update_module_icon($moduleid) {
197 global $CFG;
198
199 if (isteacher($courseid)) {
200 return "<A TITLE=\"Edit this activity\" HREF=\"$CFG->wwwroot/course/mod.php?update=$moduleid\" TARGET=_top><IMG
201 SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
202 }
203}
204
f9903ed0 205
5fa51a39 206function userdate($date, $format="", $timezone=99) {
873960de 207 global $USER;
208
5fa51a39 209 if ($format == "") {
210 $format = "l, j F Y, g:i A";
211 }
212 if ($timezone == 99) {
213 $timezone = (float)$USER->timezone;
214 }
215 if (abs($timezone) > 12) {
873960de 216 return date("$format T", $date);
217 }
5fa51a39 218 return gmdate($format, $date + (int)($timezone * 3600));
873960de 219}
220
5fa51a39 221function usergetdate($date, $timezone=99) {
873960de 222 global $USER;
223
5fa51a39 224 if ($timezone == 99) {
225 $timezone = (float)$USER->timezone;
226 }
227 if (abs($timezone) > 12) {
873960de 228 return getdate($date);
229 }
5fa51a39 230 return getdate($date + (int)($timezone * 3600));
f9903ed0 231}
232
233
234function error ($message, $link="") {
235 global $CFG, $SESSION;
236
237 print_header("Error");
238 echo "<BR>";
239 print_simple_box($message, "center", "", "#FFBBBB");
240
241 if (!$link) {
242 if ( !empty($SESSION->fromurl) ) {
243 $link = "$SESSION->fromurl";
244 unset($SESSION->fromurl);
245 } else {
246 $link = "$CFG->wwwroot";
247 }
248 }
249 print_heading("<A HREF=\"$link\">Continue</A>");
250 print_footer();
251 die;
252}
253
34c8915d 254function helpbutton ($info, $type="file") {
255 global $CFG;
256 $url = "/help.php?$type=help.$info.php";
257 $image = "<IMG BORDER=0 ALT=help SRC=\"$CFG->wwwroot/pix/help.gif\">";
258 link_to_popup_window ($url, "popup", $image, $height=400, $width=500);
259}
260
f9903ed0 261function notice ($message, $link="") {
262 global $THEME, $HTTP_REFERER;
263
264 if (!$link) {
265 $link = $HTTP_REFERER;
266 }
267
268 echo "<BR>";
269 print_simple_box($message, "center", "", "$THEME->cellheading");
270 print_heading("<A HREF=\"$link\">Continue</A>");
271 print_footer();
272 die;
273}
274
275function notice_yesno ($message, $linkyes, $linkno) {
276 global $THEME;
277
278 print_simple_box_start("center", "", "$THEME->cellheading");
279 echo "<P ALIGN=CENTER><FONT SIZE=3>$message</FONT></P>";
280 echo "<P ALIGN=CENTER><FONT SIZE=3><B>";
281 echo "<A HREF=\"$linkyes\">Yes</A>";
282 echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
283 echo "<A HREF=\"$linkno\">No</A>";
284 echo "</B></FONT></P>";
285 print_simple_box_end();
286}
287
288function redirect($url, $message="", $delay=0) {
289// Uses META tags to redirect the user, after printing a notice
290 global $THEME;
291
292 echo "<META HTTP-EQUIV='Refresh' CONTENT='$delay; URL=$url'>";
293
294 if (!empty($message)) {
295 print_header();
296 echo "<CENTER>";
297 echo "<P>$message</P>";
298 echo "<P>( <A HREF=\"$url\">Continue</A> )</P>";
299 echo "</CENTER>";
300 }
301 die;
302}
303
304function notify ($message) {
305 echo "<P align=center><B><FONT COLOR=#FF0000>$message</FONT></B></P>\n";
306}
307
308
309
310/// PARAMETER HANDLING ////////////////////////////////////////////////////
311
312function require_variable($var) {
313
314 if (! isset($var)) {
315 error("A required parameter was missing");
316 }
317}
318
319function optional_variable(&$var, $default=0) {
320 if (! isset($var)) {
321 $var = $default;
322 }
323}
324
325
326
327
328/// DATABASE HANDLING ////////////////////////////////////////////////
329
330function execute_sql($command) {
331// Completely general
332
333 global $db;
334
335 $result = $db->Execute("$command");
336
337 if ($result) {
338 echo "<P><FONT COLOR=green>SUCCESS: $command</FONT></P>";
339 return true;
340 } else {
341 echo "<P><FONT COLOR=red>ERROR: $command </FONT></P>";
342 return false;
343 }
344}
345
346function modify_database($sqlfile) {
347// Assumes that the input text file consists of a number
348// of SQL statements ENDING WITH SEMICOLONS. The semicolons
349// MUST be the last character in a line.
350// Lines that are blank or that start with "#" are ignored.
351// Only tested with mysql dump files (mysqldump -p -d moodle)
352
353
354 if (file_exists($sqlfile)) {
355 $success = true;
356 $lines = file($sqlfile);
357 $command = "";
358
359 while ( list($i, $line) = each($lines) ) {
360 $line = chop($line);
361 $length = strlen($line);
362
363 if ($length && substr($line, 0, 1) <> "#") {
364 if (substr($line, $length-1, 1) == ";") {
365 $line = substr($line, 0, $length-1); // strip ;
366 $command .= $line;
367 if (! execute_sql($command)) {
368 $success = false;
369 }
370 $command = "";
371 } else {
372 $command .= $line;
373 }
374 }
375 }
376
377 } else {
378 $success = false;
379 echo "<P>Tried to modify database, but \"$sqlfile\" doesn't exist!</P>";
380 }
381
382 return $success;
383}
384
385
386function record_exists($table, $field, $value) {
387 global $db;
388
389 $rs = $db->Execute("SELECT * FROM $table WHERE $field = '$value' LIMIT 1");
390 if (!$rs) return false;
391
392 if ( $rs->RecordCount() ) {
393 return true;
394 } else {
395 return false;
396 }
397}
398
399function record_exists_sql($sql) {
400 global $db;
401
402 $rs = $db->Execute($sql);
403 if (!$rs) return false;
404
405 if ( $rs->RecordCount() ) {
406 return true;
407 } else {
408 return false;
409 }
410}
411
412
413function count_records($table, $selector, $value) {
414// Get all the records and count them
415 global $db;
416
417 $rs = $db->Execute("SELECT COUNT(*) FROM $table WHERE $selector = '$value'");
418 if (!$rs) return 0;
419
420 return $rs->fields[0];
421}
422
423function count_records_sql($sql) {
424// Get all the records and count them
425 global $db;
426
427 $rs = $db->Execute("$sql");
428 if (!$rs) return 0;
429
430 return $rs->fields[0];
431}
432
433function get_record($table, $selector, $value) {
434// Get a single record as an object
435 global $db;
436
437 $rs = $db->Execute("SELECT * FROM $table WHERE $selector = '$value'");
438 if (!$rs) return false;
439
440 if ( $rs->RecordCount() == 1 ) {
441 return (object)$rs->fields;
442 } else {
443 return false;
444 }
445}
446
447function get_record_sql($sql) {
448// Get a single record as an object
449// The sql statement is provided as a string.
450
451 global $db;
452
453 $rs = $db->Execute("$sql");
454 if (!$rs) return false;
455
456 if ( $rs->RecordCount() == 1 ) {
457 return (object)$rs->fields;
458 } else {
459 return false;
460 }
461}
462
463function get_records($table, $selector, $value, $sort="") {
464// Get a number of records as an array of objects
465// Can optionally be sorted eg "time ASC" or "time DESC"
466// The "key" is the first column returned, eg usually "id"
467 global $db;
468
469 if ($sort) {
470 $sortorder = "ORDER BY $sort";
471 }
472 $sql = "SELECT * FROM $table WHERE $selector = '$value' $sortorder";
473
474 return get_records_sql($sql);
475}
476
477function get_records_sql($sql) {
478// Get a number of records as an array of objects
479// The "key" is the first column returned, eg usually "id"
480// The sql statement is provided as a string.
481
482 global $db;
483
484 $rs = $db->Execute("$sql");
485 if (!$rs) return false;
486
487 if ( $rs->RecordCount() > 0 ) {
5c0bef5d 488 if ($records = $rs->GetAssoc(true)) {
489 foreach ($records as $key => $record) {
490 $objects[$key] = (object) $record;
491 }
492 return $objects;
493 } else {
494 return false;
f9903ed0 495 }
f9903ed0 496 } else {
497 return false;
498 }
499}
500
501function get_records_sql_menu($sql) {
502// Given an SQL select, this function returns an associative
503// array of the first two columns. This is most useful in
504// combination with the choose_from_menu function to create
505// a form menu.
506
507 global $db;
508
509 $rs = $db->Execute("$sql");
510 if (!$rs) return false;
511
512 if ( $rs->RecordCount() > 0 ) {
513 while (!$rs->EOF) {
514 $menu[$rs->fields[0]] = $rs->fields[1];
515 $rs->MoveNext();
516 }
517 return $menu;
518
519 } else {
520 return false;
521 }
522}
523
524function get_field($table, $field, $selector, $value) {
525 global $db;
526
527 $rs = $db->Execute("SELECT $field FROM $table WHERE $selector = '$value'");
528 if (!$rs) return false;
529
530 if ( $rs->RecordCount() == 1 ) {
531 return $rs->fields["$field"];
532 } else {
533 return false;
534 }
535}
536
537function set_field($table, $field, $newvalue, $selector, $value) {
538 global $db;
539
540 return $db->Execute("UPDATE $table SET $field = '$newvalue' WHERE $selector = '$value'");
541}
542
543
544function delete_records($table, $selector, $value) {
545// Delete one or more records from a table
546 global $db;
547
548 return $db->Execute("DELETE FROM $table WHERE $selector = '$value'");
549}
550
551function insert_record($table, $dataobject) {
552// Insert a record into a table and return the "id" field
553// $dataobject is an object containing needed data
554
555 global $db;
556
557 // Determine all the fields needed
558 if (! $columns = $db->MetaColumns("$table")) {
559 return false;
560 }
561
562 $data = (array)$dataobject;
563
564 // Pull out data matching these fields
565 foreach ($columns as $column) {
566 if ($column->name <> "id" && $data[$column->name] ) {
567 $ddd[$column->name] = $data[$column->name];
568 }
569 }
570
571 // Construct SQL queries
572 if (! $numddd = count($ddd)) {
573 return 0;
574 }
575
576 $count = 0;
577 $insert = "";
578 $select = "";
579
580 foreach ($ddd as $key => $value) {
581 $count++;
582 $insert .= "$key = '$value'";
583 $select .= "$key = '$value'";
584 if ($count < $numddd) {
585 $insert .= ", ";
586 $select .= " AND ";
587 }
588 }
589
590 if (! $rs = $db->Execute("INSERT INTO $table SET $insert")) {
591 return false;
592 }
593
594 // Pull it out again to find the id. This is the most cross-platform method.
595 if ($rs = $db->Execute("SELECT id FROM $table WHERE $select")) {
596 return $rs->fields[0];
597 } else {
598 return false;
599 }
600}
601
602
603function update_record($table, $dataobject) {
604// Update a record in a table
605// $dataobject is an object containing needed data
606
607 global $db;
608
5c0bef5d 609 if (! isset($dataobject->id) ) {
f9903ed0 610 return false;
611 }
612
613 // Determine all the fields in the table
614 $columns = $db->MetaColumns($table);
615 $data = (array)$dataobject;
616
617 // Pull out data matching these fields
618 foreach ($columns as $column) {
5c0bef5d 619 if ($column->name <> "id" && isset($data[$column->name]) ) {
f9903ed0 620 $ddd[$column->name] = $data[$column->name];
621 }
622 }
623
624 // Construct SQL queries
625 $numddd = count($ddd);
626 $count = 0;
627 $update = "";
628
629 foreach ($ddd as $key => $value) {
630 $count++;
631 $update .= "$key = '$value'";
632 if ($count < $numddd) {
633 $update .= ", ";
634 }
635 }
636
637 if ($rs = $db->Execute("UPDATE $table SET $update WHERE id = '$dataobject->id'")) {
638 return true;
639 } else {
640 return false;
641 }
642}
643
644
645
646/// USER DATABASE ////////////////////////////////////////////////
647
648function get_user_info_from_db($field, $value) {
649
650 global $db;
651
652 if (!$field || !$value)
653 return false;
654
655 $result = $db->Execute("SELECT * FROM user WHERE $field = '$value'");
656
657 if ( $result->RecordCount() == 1 ) {
658 $user = (object)$result->fields;
659
660 $rs = $db->Execute("SELECT course FROM user_students WHERE user = '$user->id' ");
661 while (!$rs->EOF) {
662 $course = $rs->fields["course"];
663 $user->student["$course"] = true;
664 $rs->MoveNext();
665 }
666
667 $rs = $db->Execute("SELECT course FROM user_teachers WHERE user = '$user->id' ");
668 while (!$rs->EOF) {
669 $course = $rs->fields["course"];
670 $user->teacher["$course"] = true;
671 $rs->MoveNext();
672 }
673
674 $rs = $db->Execute("SELECT * FROM user_admins WHERE user = '$user->id' ");
675 while (!$rs->EOF) {
676 $user->admin = true;
677 $rs->MoveNext();
678 }
679
680 if ($course = get_record("course", "category", 0)) {
681 // Everyone is always a member of the top course
682 $user->student["$course->id"] = true;
683 }
684
685 return $user;
686
687 } else {
688 return false;
689 }
690}
691
692function update_user_in_db() {
693
694 global $db, $USER, $REMOTE_ADDR;
695
696 if (!isset($USER->id))
697 return false;
698
699 $timenow = time();
700 if ($db->Execute("UPDATE LOW_PRIORITY user SET lastIP='$REMOTE_ADDR', lastaccess='$timenow'
701 WHERE id = '$USER->id' ")) {
702 return true;
703 } else {
704 return false;
705 }
706}
707
da5c172a 708function require_login($courseid=0) {
709// This function checks that the current user is logged in, and optionally
710// whether they are "logged in" or allowed to be in a particular course.
711// If not, then it redirects them to the site login or course enrolment.
f9903ed0 712
713 global $CFG, $SESSION, $USER, $FULLME, $HTTP_REFERER, $PHPSESSID;
714
da5c172a 715 // First check that the user is logged in to the site.
f9903ed0 716 if (! (isset( $USER->loggedin ) && $USER->confirmed) ) {
717 $SESSION->wantsurl = $FULLME;
718 $SESSION->fromurl = $HTTP_REFERER;
719 if ($PHPSESSID) { // Cookies not enabled.
720 redirect("$CFG->wwwroot/login/?PHPSESSID=$PHPSESSID");
721 } else {
722 redirect("$CFG->wwwroot/login/");
723 }
724 die;
f9903ed0 725 }
da5c172a 726
727 // Next, check if the user can be in a particular course
728 if ($courseid) {
729 if ($USER->student[$courseid] || $USER->teacher[$courseid] || $USER->admin) {
730 update_user_in_db();
731 return; // user is a member of this course.
732 }
733 if (! $course = get_record("course", "id", $courseid)) {
734 error("That course doesn't exist");
735 }
736 if ($course->guest && ($USER->username == "guest")) {
737 update_user_in_db();
738 return; // user is a guest and this course allows guests
739 }
f9903ed0 740
da5c172a 741 // Not allowed in the course, so see if they want to enrol
742
743 $SESSION->wantsurl = $FULLME;
744 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
745 die;
746 }
f9903ed0 747}
748
749
750
751function update_login_count() {
752 global $SESSION;
753
754 $max_logins = 10;
755
756 if (empty($SESSION->logincount)) {
757 $SESSION->logincount = 1;
758 } else {
759 $SESSION->logincount++;
760 }
761
762 if ($SESSION->logincount > $max_logins) {
763 unset($SESSION->wantsurl);
764 error("Sorry, you have exceeded the allowed number of login attempts. Restart your browser.");
765 }
766}
767
768
769function isadmin($userid=0) {
770 global $USER;
771
772 if (!$userid) {
773 return $USER->admin;
774 }
775
776 return record_exists_sql("SELECT * FROM user_admins WHERE user='$userid'");
777}
778
779function isteacher($course, $userid=0) {
780 global $USER;
781
d115a57f 782 if (isadmin($userid)) { // admins can do anything the teacher can
783 return true;
784 }
785
f9903ed0 786 if (!$userid) {
787 return $USER->teacher[$course];
788 }
789
790 return record_exists_sql("SELECT * FROM user_teachers WHERE user='$userid' AND course='$course'");
791}
792
793
794function isstudent($course, $userid=0) {
795 global $USER;
796
797 if (!$userid) {
798 return $USER->student[$course];
799 }
800
801 $timenow = time(); // todo: add time check below
802
803 return record_exists_sql("SELECT * FROM user_students WHERE user='$userid' AND course='$course'");
804}
805
da5c172a 806function isguest($userid=0) {
807 global $USER;
808
809 if (!$userid) {
810 return ($USER->username == "guest");
811 }
812
813 return record_exists_sql("SELECT * FROM user WHERE user='$userid' AND username = 'guest' ");
814}
815
f9903ed0 816
817function reset_login_count() {
818 global $SESSION;
819
820 $SESSION->logincount = 0;
821}
822
823
824function set_moodle_cookie($thing) {
825
826 $days = 60;
827 $seconds = 60*60*24*$days;
828
d115a57f 829 setCookie ('MOODLEID', "", time() - 3600, "/");
f9903ed0 830 setCookie ('MOODLEID', rc4encrypt($thing), time()+$seconds, "/");
831}
832
833
834function get_moodle_cookie() {
835 global $MOODLEID;
836 return rc4decrypt($MOODLEID);
837}
838
839
840
841function verify_login($username, $password) {
842
843 $user = get_user_info_from_db("username", $username);
844
845 if (! $user) {
846 return false;
847 } else if ( $user->password == md5($password) ) {
848 return $user;
849 } else {
850 return false;
851 }
852}
853
854function get_site () {
855// Returns $course object of the top-level site.
856 if ( $course = get_record("course", "category", 0)) {
857 return $course;
858 } else {
859 return false;
860 }
861}
862
863function get_admin () {
864// Returns $user object of the main admin user
865
866 if ( $admins = get_records_sql("SELECT u.* FROM user u, user_admins a WHERE a.user = u.id ORDER BY u.id ASC")) {
867 foreach ($admins as $admin) {
868 return $admin; // ie the first one (yeah I know it's bodgy)
869 }
870 } else {
871 return false;
872 }
873}
874
875function get_teacher($courseid) {
876// Returns $user object of the main teacher for a course
877 if ( $teachers = get_records_sql("SELECT u.* FROM user u, user_teachers t
878 WHERE t.user = u.id AND t.course = '$courseid'
879 ORDER BY t.authority ASC")) {
880 foreach ($teachers as $teacher) {
881 return $teacher; // ie the first one (yeah I know it's bodgy)
882 }
883 } else {
884 return false;
885 }
886}
887
888
889
890/// MODULE FUNCTIONS /////////////////////////////////////////////////
891
892function get_coursemodule_from_instance($modulename, $instance, $course) {
893// Given an instance of a module, finds the coursemodule description
894
895 return get_record_sql("SELECT cm.*, m.name
896 FROM course_modules cm, modules md, $modulename m
897 WHERE cm.course = '$course' AND
898 cm.deleted = '0' AND
899 cm.instance = m.id AND
900 md.name = '$modulename' AND
901 md.id = cm.module AND
902 m.id = '$instance'");
903
904}
905
906function get_all_instances_in_course($modulename, $course, $sort="cw.week") {
907// Returns an array of all the active instances of a particular
908// module in a given course. Returns false on any errors.
909
910 return get_records_sql("SELECT m.*,cw.week,cm.id as coursemodule
911 FROM course_modules cm, course_weeks cw, modules md, $modulename m
912 WHERE cm.course = '$course' AND
913 cm.instance = m.id AND
914 cm.deleted = '0' AND
915 cm.week = cw.id AND
916 md.name = '$modulename' AND
917 md.id = cm.module
918 ORDER BY $sort");
919
920}
921
f9903ed0 922
923
924
925
926/// CORRESPONDENCE ////////////////////////////////////////////////
927
5fa51a39 928function email_to_user($user, $from, $subject, $messagetext, $messagehtml="", $attachment="", $attachname="") {
929// user - a user record as an object
930// from - a user record as an object
931// subject - plain text subject line of the email
136dabd8 932// messagetext - plain text version of the message
933// messagehtml - complete html version of the message (optional)
934// attachment - a file on the filesystem, relative to $CFG->dataroot
935// attachname - the name of the file (extension indicates MIME)
f9903ed0 936
4216daa6 937 global $CFG, $_SERVER;
f9903ed0 938
136dabd8 939 include_once("$CFG->libdir/phpmailer/class.phpmailer.php");
f9903ed0 940
5fa51a39 941 if (!$user) {
f9903ed0 942 return false;
943 }
944
f9903ed0 945 $mail = new phpmailer;
946
1e411ffc 947 $mail->Version = "Moodle $CFG->moodleversion"; // mailer version
136dabd8 948 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
7f86ce17 949 if ($CFG->smtphosts) {
1e411ffc 950 $mail->IsSMTP(); // use SMTP directly
951 $mail->Host = "$CFG->smtphosts"; // specify main and backup servers
7f86ce17 952 } else {
1e411ffc 953 $mail->IsMail(); // use PHP mail() = sendmail
7f86ce17 954 }
f9903ed0 955
136dabd8 956 $mail->From = "$from->email";
957 $mail->FromName = "$from->firstname $from->lastname";
958 $mail->Subject = stripslashes($subject);
f9903ed0 959
5fa51a39 960 $mail->AddBCC("$user->email","$user->firstname $user->lastname");
f9903ed0 961
f9903ed0 962 $mail->WordWrap = 70; // set word wrap
f9903ed0 963
136dabd8 964 if ($messagehtml) {
965 $mail->IsHTML(true);
966 $mail->Body = $messagehtml;
78681899 967 $mail->AltBody = "\n$messagetext\n";
136dabd8 968 } else {
969 $mail->IsHTML(false);
78681899 970 $mail->Body = "\n$messagetext\n";
f9903ed0 971 }
972
136dabd8 973 if ($attachment && $attachname) {
974 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
4216daa6 975 $adminuser = get_admin();
976 $mail->AddAddress("$adminuser->email", "$adminuser->firstname $adminuser->lastname");
977 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
136dabd8 978 } else {
979 include_once("$CFG->dirroot/files/mimetypes.php");
980 $mimetype = mimeinfo("type", $attachname);
981 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
982 }
f9903ed0 983 }
984
136dabd8 985 if ($mail->Send()) {
986 return true;
987 } else {
4216daa6 988 echo "ERROR: $mail->ErrorInfo\n";
989 $site = get_site();
990 add_to_log($site->id, "library", "mailer", $_SERVER["REQUEST_URI"], "ERROR: $mail->ErrorInfo");
f9903ed0 991 return false;
992 }
f9903ed0 993}
994
136dabd8 995
f9903ed0 996/// FILE HANDLING /////////////////////////////////////////////
997
998function get_directory_list( $rootdir ) {
999// Returns an array with all the filenames in
1000// all subdirectories, relative to the given rootdir.
1001
1002 $dirs = array();
1003
1004 $dir = opendir( $rootdir );
1005
1006 while( $file = readdir( $dir ) ) {
1007 $fullfile = $rootdir."/".$file;
1008 if ($file != "." and $file != "..") {
1009 if (filetype($fullfile) == "dir") {
1010 $subdirs = get_directory_list($fullfile);
1011 foreach ($subdirs as $subdir) {
1012 $dirs[] = $file."/".$subdir;
1013 }
1014 } else {
1015 $dirs[] = $file;
1016 }
1017 }
1018 }
1019
1020 return $dirs;
1021}
1022
1023
1024
1025/// ENCRYPTION ////////////////////////////////////////////////
1026
1027function rc4encrypt($data) {
1028 $password = "nfgjeingjk";
1029 return endecrypt($password, $data, "");
1030}
1031
1032function rc4decrypt($data) {
1033 $password = "nfgjeingjk";
1034 return endecrypt($password, $data, "de");
1035}
1036
1037function endecrypt ($pwd, $data, $case) {
1038// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
1039
1040 if ($case == 'de') {
1041 $data = urldecode($data);
1042 }
1043
1044 $key[] = "";
1045 $box[] = "";
1046 $temp_swap = "";
1047 $pwd_length = 0;
1048
1049 $pwd_length = strlen($pwd);
1050
1051 for ($i = 0; $i <= 255; $i++) {
1052 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
1053 $box[$i] = $i;
1054 }
1055
1056 $x = 0;
1057
1058 for ($i = 0; $i <= 255; $i++) {
1059 $x = ($x + $box[$i] + $key[$i]) % 256;
1060 $temp_swap = $box[$i];
1061 $box[$i] = $box[$x];
1062 $box[$x] = $temp_swap;
1063 }
1064
1065 $temp = "";
1066 $k = "";
1067
1068 $cipherby = "";
1069 $cipher = "";
1070
1071 $a = 0;
1072 $j = 0;
1073
1074 for ($i = 0; $i < strlen($data); $i++) {
1075 $a = ($a + 1) % 256;
1076 $j = ($j + $box[$a]) % 256;
1077 $temp = $box[$a];
1078 $box[$a] = $box[$j];
1079 $box[$j] = $temp;
1080 $k = $box[(($box[$a] + $box[$j]) % 256)];
1081 $cipherby = ord(substr($data, $i, 1)) ^ $k;
1082 $cipher .= chr($cipherby);
1083 }
1084
1085 if ($case == 'de') {
1086 $cipher = urldecode(urlencode($cipher));
1087 } else {
1088 $cipher = urlencode($cipher);
1089 }
1090
1091 return $cipher;
1092}
1093
1094
1095/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
1096
1097function getweek ($startdate, $thedate) {
1098// Given dates in seconds, how many weeks is the date from startdate
1099// The first week is 1, the second 2 etc ...
1100
1101 if ($thedate < $startdate) { // error
1102 return 0;
1103 }
1104
1105 return floor(($thedate - $startdate) / 604800.0) + 1;
1106}
1107
4216daa6 1108function add_to_log($course, $module, $action, $url="", $info="") {
1109// Add an entry to the log table. These are "action" focussed rather
1110// than web server hits, and provide a way to easily reconstruct what
1111// any particular student has been doing.
1112//
1113// course = the course id
1114// module = discuss, journal, reading, course, user etc
1115// action = view, edit, post (often but not always the same as the file.php)
1116// url = the file and parameters used to see the results of the action
1117// info = additional description information
1118
1119
f9903ed0 1120 global $db, $USER, $REMOTE_ADDR;
1121
1122 $timenow = time();
4216daa6 1123 $info = addslashes($info);
1124
1125 $result = $db->Execute("INSERT INTO log
1126 SET time = '$timenow',
1127 user = '$USER->id',
1128 course = '$course',
1129 ip = '$REMOTE_ADDR',
1130 module = '$module',
1131 action = '$action',
1132 url = '$url',
1133 info = '$info'");
f9903ed0 1134 if (!$result) {
4216daa6 1135 echo "<P>Error: Could not insert a new entry to the Moodle log</P>"; // Don't throw an error
f9903ed0 1136 }
1137}
1138
1139function generate_password($maxlen=10) {
1140/* returns a randomly generated password of length $maxlen. inspired by
1141 * http://www.phpbuilder.com/columns/jesus19990502.php3 */
1142
1143 global $CFG;
1144
1145 $fillers = "1234567890!$-+";
1146 $wordlist = file($CFG->wordlist);
1147
1148 srand((double) microtime() * 1000000);
1149 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1150 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1151 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
1152
1153 return substr($word1 . $filler1 . $word2, 0, $maxlen);
1154}
1155
1156
1157function format_time($totalsecs) {
1158
1159 $days = floor($totalsecs/86400);
1160 $remainder = $totalsecs - ($days*86400);
1161 $hours = floor($remainder/3600);
1162 $remainder = $remainder - ($hours*3600);
1163 $mins = floor($remainder/60);
1164 $secs = $remainder - ($mins*60);
1165
1166 if ($secs != 1) $ss = "s";
1167 if ($mins != 1) $ms = "s";
1168 if ($hours != 1) $hs = "s";
1169 if ($days != 1) $ds = "s";
1170
1171 if ($days) $odays = "$days day$ds";
1172 if ($hours) $ohours = "$hours hr$hs";
1173 if ($mins) $omins = "$mins min$ms";
1174 if ($secs) $osecs = "$secs sec$ss";
1175
1176 if ($days) return "$odays $ohours";
1177 if ($hours) return "$ohours $omins";
1178 if ($mins) return "$omins $osecs";
1179 if ($secs) return "$osecs";
1180 return "now";
1181}
1182
1183
1184?>