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