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