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