13b3f88a870427c54fa01eac641ea79110f0f4c9
[moodle.git] / lib / weblib.php
1 <?PHP // $Id$
3 ///////////////////////////////////////////////////////////////////////////
4 // weblib.php - functions for web output
5 //
6 // Library of all general-purpose Moodle PHP functions and constants
7 // that produce HTML output
8 //
9 ///////////////////////////////////////////////////////////////////////////
10 //                                                                       //
11 // NOTICE OF COPYRIGHT                                                   //
12 //                                                                       //
13 // Moodle - Modular Object-Oriented Dynamic Learning Environment         //
14 //          http://moodle.com                                            //
15 //                                                                       //
16 // Copyright (C) 2001-2003  Martin Dougiamas  http://dougiamas.com       //
17 //                                                                       //
18 // This program is free software; you can redistribute it and/or modify  //
19 // it under the terms of the GNU General Public License as published by  //
20 // the Free Software Foundation; either version 2 of the License, or     //
21 // (at your option) any later version.                                   //
22 //                                                                       //
23 // This program is distributed in the hope that it will be useful,       //
24 // but WITHOUT ANY WARRANTY; without even the implied warranty of        //
25 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
26 // GNU General Public License for more details:                          //
27 //                                                                       //
28 //          http://www.gnu.org/copyleft/gpl.html                         //
29 //                                                                       //
30 ///////////////////////////////////////////////////////////////////////////
32 /// Constants
34 /// Define text formatting types ... eventually we can add Wiki, BBcode etc
35 define("FORMAT_MOODLE", "0");   // Does all sorts of transformations and filtering
36 define("FORMAT_HTML",   "1");   // Plain HTML (with some tags stripped)
37 define("FORMAT_PLAIN",  "2");   // Plain text (even tags are printed in full)
38 define("FORMAT_WIKI",   "3");   // Wiki-formatted text
40 $ALLOWED_TAGS =
41 "<p><br><b><i><u><font><table><tbody><span><div><tr><td><ol><ul><dl><li><dt><dd><h1><h2><h3><h4><h5><h6><hr><img><a><strong><emphasis><em><sup><sub><address><cite><blockquote><pre><strike><embed><object><param><acronym><nolink><style><lang><tex><algebra><math><mi><mn><mo><mtext><mspace><ms><mrow><mfrac><msqrt><mroot><mstyle><merror><mpadded><mphantom><mfenced><msub><msup><msubsup><munder><mover><munderover><mmultiscripts><mtable><mtr><mtd><maligngroup><malignmark><maction><cn><ci><apply><reln><fn><interval><inverse><sep><condition><declare><lambda><compose><ident><quotient><exp><factorial><divide><max><min><minus><plus><power><rem><times><root><gcd><and><or><xor><not><implies><forall><exists><abs><conjugate><eq><neq><gt><lt><geq><leq><ln><log><int><diff><partialdiff><lowlimit><uplimit><bvar><degree><set><list><union><intersect><in><notin><subset><prsubset><notsubset><notprsubset><setdiff><sum><product><limit><tendsto><mean><sdev><variance><median><mode><moment><vector><matrix><matrixrow><determinant><transpose><selector><annotation><semantics><annotation-xml>";
44 /// Functions
46 function s($var) {
47 /// returns $var with HTML characters (like "<", ">", etc.) properly quoted,
49     if (empty($var)) {
50         return "";
51     }
52     return htmlSpecialChars(stripslashes_safe($var));
53 }
55 function p($var) {
56 /// prints $var with HTML characters (like "<", ">", etc.) properly quoted,
58     if (empty($var)) {
59         echo "";
60     }
61     echo htmlSpecialChars(stripslashes_safe($var));
62 }
64 function nvl(&$var, $default="") {
65 /// if $var is undefined, return $default, otherwise return $var 
67     return isset($var) ? $var : $default;
68 }
70 function strip_querystring($url) {
71 /// takes a URL and returns it without the querystring portion 
73     if ($commapos = strpos($url, '?')) {
74         return substr($url, 0, $commapos);
75     } else {
76         return $url;
77     }
78 }
80 function get_referer() {
81 /// returns the URL of the HTTP_REFERER, less the querystring portion 
83     return strip_querystring(nvl($_SERVER["HTTP_REFERER"]));
84 }
87 function me() {
88 /// returns the name of the current script, WITH the querystring portion.
89 /// this function is necessary because PHP_SELF and REQUEST_URI and SCRIPT_NAME
90 /// return different things depending on a lot of things like your OS, Web
91 /// server, and the way PHP is compiled (ie. as a CGI, module, ISAPI, etc.) 
93     if (!empty($_SERVER["REQUEST_URI"])) {
94         return $_SERVER["REQUEST_URI"];
96     } else if (!empty($_SERVER["PHP_SELF"])) {
97         if (!empty($_SERVER["QUERY_STRING"])) {
98             return $_SERVER["PHP_SELF"]."?".$_SERVER["QUERY_STRING"];
99         }
100         return $_SERVER["PHP_SELF"];
102     } else if (!empty($_SERVER["SCRIPT_NAME"])) {
103         if (!empty($_SERVER["QUERY_STRING"])) {
104             return $_SERVER["SCRIPT_NAME"]."?".$_SERVER["QUERY_STRING"];
105         }
106         return $_SERVER["SCRIPT_NAME"];
108     } else {
109         notify("Warning: Could not find any of these web server variables: \$REQUEST_URI, \$PHP_SELF or \$SCRIPT_NAME");
110         return false;
111     }
115 function qualified_me() {
116 /// like me() but returns a full URL 
118     if (!empty($_SERVER["HTTP_HOST"])) {
119         $hostname = $_SERVER["HTTP_HOST"];
120     } else if (!empty($_ENV["HTTP_HOST"])) {
121         $hostname = $_ENV["HTTP_HOST"];
122     } else if (!empty($_SERVER["SERVER_NAME"])) {
123         $hostname = $_SERVER["SERVER_NAME"];
124     } else if (!empty($_ENV["SERVER_NAME"])) {
125         $hostname = $_ENV["SERVER_NAME"];
126     } else {
127         notify("Warning: could not find the name of this server!");
128         return false;
129     }
131     $protocol = (isset($_SERVER["HTTPS"]) and $_SERVER["HTTPS"] == "on") ? "https://" : "http://";
132     $url_prefix = $protocol.$hostname;
133     return $url_prefix . me();
137 function match_referer($goodreferer = "") {
138 /// returns true if the referer is the same as the goodreferer.  If
139 /// goodreferer is not specified, use qualified_me as the goodreferer 
140     global $CFG;
142     if (empty($CFG->secureforms)) {    // Don't bother checking referer
143         return true;
144     }
146     if ($goodreferer == "nomatch") {   // Don't bother checking referer
147         return true;
148     }
150     if (empty($goodreferer)) { 
151         $goodreferer = qualified_me(); 
152     }
153     return $goodreferer == get_referer();
156 function data_submitted($url="") {
157 /// Used on most forms in Moodle to check for data
158 /// Returns the data as an object, if it's found.
159 /// This object can be used in foreach loops without
160 /// casting because it's cast to (array) automatically
161 /// 
162 /// Checks that submitted POST data exists, and also 
163 /// checks the referer against the given url (it uses 
164 /// the current page if none was specified.
166     global $CFG;
168     if (empty($_POST)) {
169         return false;
171     } else {
172         if (match_referer($url)) {
173             return (object)$_POST;
174         } else {
175             if ($CFG->debug > 10) {
176                 notice("The form did not come from this page! (referer = ".get_referer().")");
177             }
178             return false;
179         }
180     }
183 function stripslashes_safe($string) {
184 /// stripslashes() removes ALL backslashes even from strings 
185 /// so  C:\temp becomes C:temp  ... this isn't good.
186 /// The following should work as a fairly safe replacement 
187 /// to be called on quoted AND unquoted strings (to be sure)
189     $string = str_replace("\\'", "'", $string);
190     $string = str_replace('\\"', '"', $string);
191     $string = str_replace('\\\\', '\\', $string);
192     return $string;
195 if (!function_exists('str_ireplace')) {    /// Only exists in PHP 5
196     function str_ireplace($find, $replace, $string) {
197     /// This does a search and replace, ignoring case
198     /// This function is only used for versions of PHP older than version 5
199     /// which do not have a native version of this function.
200     /// Taken from the PHP manual, by bradhuizenga @ softhome.net
202         if (!is_array($find)) {
203             $find = array($find);
204         }
206         if(!is_array($replace)) {
207             if (!is_array($find)) {
208                 $replace = array($replace);
209             } else {
210                 // this will duplicate the string into an array the size of $find
211                 $c = count($find);
212                 $rString = $replace;
213                 unset($replace);
214                 for ($i = 0; $i < $c; $i++) {
215                     $replace[$i] = $rString;
216                 }
217             }
218         }
220         foreach ($find as $fKey => $fItem) {
221             $between = explode(strtolower($fItem),strtolower($string));
222             $pos = 0;
223             foreach($between as $bKey => $bItem) {
224                 $between[$bKey] = substr($string,$pos,strlen($bItem));
225                 $pos += strlen($bItem) + strlen($fItem);
226             }
227             $string = implode($replace[$fKey],$between);
228         }
229         return ($string);
230     }
233 if (!function_exists('stripos')) {    /// Only exists in PHP 5
234     function stripos($haystack, $needle, $offset=0) {
235     /// This function is only used for versions of PHP older than version 5
236     /// which do not have a native version of this function.
237     /// Taken from the PHP manual, by dmarsh @ spscc.ctc.edu
238         return strpos(strtoupper($haystack), strtoupper($needle), $offset);
239     }
242 function read_template($filename, &$var) {
243 /// return a (big) string containing the contents of a template file with all
244 /// the variables interpolated.  all the variables must be in the $var[] array or
245 /// object (whatever you decide to use).
246 ///
247 /// WARNING: do not use this on big files!! 
249     $temp = str_replace("\\", "\\\\", implode(file($filename), ""));
250     $temp = str_replace('"', '\"', $temp);
251     eval("\$template = \"$temp\";");
252     return $template;
255 function checked(&$var, $set_value = 1, $unset_value = 0) {
256 /// if variable is set, set it to the set_value otherwise set it to the
257 /// unset_value.  used to handle checkboxes when you are expecting them from
258 /// a form 
260     if (empty($var)) {
261         $var = $unset_value;
262     } else {
263         $var = $set_value;
264     }
267 function frmchecked(&$var, $true_value = "checked", $false_value = "") {
268 /// prints the word "checked" if a variable is true, otherwise prints nothing,
269 /// used for printing the word "checked" in a checkbox form input 
271     if ($var) {
272         echo $true_value;
273     } else {
274         echo $false_value;
275     }
279 function link_to_popup_window ($url, $name="popup", $linkname="click here", 
280                                $height=400, $width=500, $title="Popup window", $options="none") {
281 /// This will create a HTML link that will work on both 
282 /// Javascript and non-javascript browsers.
283 /// Relies on the Javascript function openpopup in javascript.php
284 /// $url must be relative to home page  eg /mod/survey/stuff.php
286     global $CFG;
288     if ($options == "none") {
289         $options = "menubar=0,location=0,scrollbars,resizable,width=$width,height=$height";
290     }
291     $fullscreen = 0;
293     echo "<a target=\"$name\" title=\"$title\" href=\"$CFG->wwwroot$url\" ".
294          "onClick=\"return openpopup('$url', '$name', '$options', $fullscreen);\">$linkname</a>\n";
298 function button_to_popup_window ($url, $name="popup", $linkname="click here", 
299                                  $height=400, $width=500, $title="Popup window", $options="none") {
300 /// This will create a HTML link that will work on both 
301 /// Javascript and non-javascript browsers.
302 /// Relies on the Javascript function openpopup in javascript.php
303 /// $url must be relative to home page  eg /mod/survey/stuff.php
305     global $CFG;
307     if ($options == "none") {
308         $options = "menubar=0,location=0,scrollbars,resizable,width=$width,height=$height";
309     }
310     $fullscreen = 0;
312     echo "<input type=\"button\" name=\"popupwindow\" title=\"$title\" value=\"$linkname ...\" ".
313          "onClick=\"return openpopup('$url', '$name', '$options', $fullscreen);\">\n";
317 function close_window_button() {
318 /// Prints a simple button to close a window
320     echo "<center>\n";
321     echo "<script>\n";
322     echo "<!--\n";
323     echo "document.write('<form>');\n";
324     echo "document.write('<input type=\"button\" onClick=\"self.close();\" value=\"".get_string("closewindow")."\" />');\n";
325     echo "document.write('</form>');\n";
326     echo "-->\n";
327     echo "</script>\n";
328     echo "<noscript>\n";
329     echo "<a href=\"".$_SERVER['HTTP_REFERER']."\"><---</a>\n";
330     echo "</noscript>\n";
331     echo "</center>\n";
335 function choose_from_menu ($options, $name, $selected="", $nothing="choose", $script="", $nothingvalue="0", $return=false) {
336 /// Given an array of value, creates a popup menu to be part of a form
337 /// $options["value"]["label"]
338     
339     if ($nothing == "choose") {
340         $nothing = get_string("choose")."...";
341     }
343     if ($script) {
344         $javascript = "onChange=\"$script\"";
345     } else {
346         $javascript = "";
347     }
349     $output = "<select name=\"$name\" $javascript>\n";
350     if ($nothing) {
351         $output .= "   <option value=\"$nothingvalue\"\n";
352         if ($nothingvalue == $selected) {
353             $output .= " selected=\"true\"";
354         }
355         $output .= ">$nothing</option>\n";
356     }
357     if (!empty($options)) {
358         foreach ($options as $value => $label) {
359             $output .= "   <option value=\"$value\"";
360             if ($value == $selected) {
361                 $output .= " selected=\"true\"";
362             }
363             if ($label === "") {
364                 $output .= ">$value</option>\n";
365             } else {
366                 $output .= ">$label</option>\n";
367             }
368         }
369     }
370     $output .= "</select>\n";
372     if ($return) {
373         return $output;
374     } else {
375         echo $output;
376     }
377 }   
379 function popup_form ($common, $options, $formname, $selected="", $nothing="choose", $help="", $helptext="", $return=false, $targetwindow="self") {
380 ///  Implements a complete little popup form
381 ///  $common   = the URL up to the point of the variable that changes
382 ///  $options  = A list of value-label pairs for the popup list
383 ///  $formname = name must be unique on the page
384 ///  $selected = the option that is already selected
385 ///  $nothing  = The label for the "no choice" option
386 ///  $help     = The name of a help page if help is required
387 ///  $helptext  = The name of the label for the help button
388 ///  $return   = Boolean indicating whether the function should return the text 
389 ///    as a string or echo it directly to the page being rendered
391     global $CFG;
393     if ($nothing == "choose") {
394         $nothing = get_string("choose")."...";
395     }
397     $startoutput = "<form target=\"{$CFG->framename}\" name=\"$formname\">";
398     $output = "<select name=\"popup\" onchange=\"$targetwindow.location=document.$formname.popup.options[document.$formname.popup.selectedIndex].value\">\n";
400     if ($nothing != "") {
401         $output .= "   <option value=\"javascript:void(0)\">$nothing</option>\n";
402     }
404     foreach ($options as $value => $label) {
405         if (substr($label,0,1) == "-") {
406             $output .= "   <option value=\"\"";
407         } else {
408             $output .= "   <option value=\"$common$value\"";
409             if ($value == $selected) {
410                 $output .= " selected=\"true\"";
411             }
412         }
413         if ($label) {
414             $output .= ">$label</option>\n";
415         } else {
416             $output .= ">$value</option>\n";
417         }
418     }
419     $output .= "</select>";
420     $output .= "</form>\n";
422     if ($return) {
423         return $startoutput.$output;
424     } else {
425         echo $startoutput;
426         if ($help) {
427             helpbutton($help, $helptext);
428         }
429         echo $output;
430     }
435 function formerr($error) {
436 /// Prints some red text
437     if (!empty($error)) {
438         echo "<font color=\"#ff0000\">$error</font>";
439     }
443 function validate_email ($address) {
444 /// Validates an email to make sure it makes sense.
445     return (ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'.
446                   '@'.
447                   '[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'.
448                   '[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$',
449                   $address));
452 function detect_munged_arguments($string) {
453     if (ereg('\.\.', $string)) { // check for parent URLs
454         return true;
455     }
456     if (ereg('[\|\`]', $string)) {  // check for other bad characters
457         return true;
458     }
459     return false;
462 function get_slash_arguments($file="file.php") {
463 /// Searches the current environment variables for some slash arguments
465     if (!$string = me()) {
466         return false;
467     }
469     $pathinfo = explode($file, $string);
470     
471     if (!empty($pathinfo[1])) {
472         return $pathinfo[1];
473     } else {
474         return false;
475     }
478 function parse_slash_arguments($string, $i=0) {
479 /// Extracts arguments from "/foo/bar/something"
480 /// eg http://mysite.com/script.php/foo/bar/something
482     if (detect_munged_arguments($string)) {
483         return false;
484     }
485     $args = explode("/", $string);
487     if ($i) {     // return just the required argument
488         return $args[$i];
490     } else {      // return the whole array
491         array_shift($args);  // get rid of the empty first one
492         return $args;
493     }
496 function format_text_menu() {
497 /// Just returns an array of formats suitable for a popup menu
498     return array (FORMAT_MOODLE => get_string("formattext"), 
499                   FORMAT_HTML   => get_string("formathtml"),
500                   FORMAT_PLAIN  => get_string("formatplain"),
501                   FORMAT_WIKI   => get_string("formatwiki"));
504 function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL ) {
505 /// Given text in a variety of format codings, this function returns 
506 /// the text as safe HTML.
507 ///
508 /// $text is raw text (originally from a user)
509 /// $format is one of the format constants, defined above
511     global $CFG, $course; 
513     if (!empty($CFG->cachetext)) {
514         $time = time() - $CFG->cachetext;
515         $md5key = md5($text);
516         if ($cacheitem = get_record_select('cache_text', "md5key = '$md5key' AND timemodified > '$time'")) {
517             return $cacheitem->formattedtext;
518         }
519     }
521     if (empty($courseid)) {
522         if (!empty($course->id)) {         // An ugly hack for better compatibility
523             $courseid = $course->id;
524         }
525     }
527     $CFG->currenttextiscacheable = true;   // Default status - can be changed by any filter
529     switch ($format) {
530         case FORMAT_HTML:
531             replace_smilies($text);
532             $text = filter_text($text, $courseid);
533             break;
535         case FORMAT_PLAIN:
536             $text = htmlentities($text);
537             $text = str_replace("  ", "&nbsp; ", $text);
538             replace_smilies($text);
539             $text = nl2br($text);
540             break;
542         case FORMAT_WIKI:
543             $text = wiki_to_html($text);
544             $text = filter_text($text, $courseid);
545             break;
547         default:  // FORMAT_MOODLE or anything else
548             if (!isset($options->smiley)) {
549                 $options->smiley=true;
550             }
551             if (!isset($options->para)) {
552                 $options->para=true;
553             }
554             $text = text_to_html($text, $options->smiley, $options->para);
555             $text = filter_text($text, $courseid);
556             break;
557     }
559     if (!empty($CFG->cachetext) and $CFG->currenttextiscacheable) {
560         $newrecord->md5key = $md5key;
561         $newrecord->formattedtext = addslashes($text);
562         $newrecord->timemodified = time();
563         insert_record('cache_text', $newrecord);
564     }
566     return $text;
569 function format_text_email($text, $format) {
570 /// Given text in a variety of format codings, this function returns 
571 /// the text as plain text suitable for plain email.
572 ///
573 /// $text is raw text (originally from a user)
574 /// $format is one of the format constants, defined above
576     switch ($format) {
578         case FORMAT_PLAIN:
579             return $text;
580             break;
582         case FORMAT_WIKI:
583             $text = wiki_to_html($text);
584         /// This expression turns links into something nice in a text format. (Russell Jungwirth)
585         /// From: http://php.net/manual/en/function.eregi-replace.php and simplified
586             $text = eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)','\\3 [\\2]', $text);
587             return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES)));
588             break;
590         case FORMAT_HTML:
591             return html_to_text($text);
592             break;
594         default:  // FORMAT_MOODLE or anything else
595             $text = eregi_replace('(<a [^<]*href=["|\']?([^ "\']*)["|\']?[^>]*>([^<]*)</a>)','\\3 [\\2]', $text);
596             return strtr(strip_tags($text), array_flip(get_html_translation_table(HTML_ENTITIES)));
597             break;
598     }
602 function filter_text($text, $courseid=NULL) {
603 /// Given some text in HTML format, this function will pass it 
604 /// through any filters that have been defined in $CFG->textfilterx
605 /// The variable defines a filepath to a file containing the 
606 /// filter function.  The file must contain a variable called 
607 /// $textfilter_function which contains the name of the function
608 /// with $courseid and $text parameters
610     global $CFG;
612     if (!empty($CFG->textfilters)) {
613         $textfilters = explode(',', $CFG->textfilters);
614         foreach ($textfilters as $textfilter) {
615             if (is_readable("$CFG->dirroot/$textfilter/filter.php")) {
616                 include("$CFG->dirroot/$textfilter/filter.php");
617                 $text = $textfilter_function($courseid, $text);
618             }
619         }
620     }
622     return $text;
626 function clean_text($text, $format=FORMAT_MOODLE) {
627 /// Given raw text (eg typed in by a user), this function cleans it up 
628 /// and removes any nasty tags that could mess up Moodle pages.
630     global $ALLOWED_TAGS;
632     switch ($format) { 
633         case FORMAT_MOODLE:
634         case FORMAT_HTML:
635         case FORMAT_WIKI:
636         /// Remove javascript: label
637             $text = strip_tags($text, $ALLOWED_TAGS);
638         /// Remove javascript/VBScript
639             $text = str_ireplace("javascript:", "xxx", $text);           
640         /// Remove script events
641             $text = eregi_replace("([^a-z])language([[:space:]]*)=", "xxx", $text);    
642             $text = eregi_replace("([^a-z])on([a-z]+)([[:space:]]*)=", "xxx", $text);  
643             return $text;
645         case FORMAT_PLAIN:
646             return $text;
647     }
650 function replace_smilies(&$text) {
651 /// Replaces all known smileys in the text with image equivalents
652     global $CFG;
654 /// this builds the mapping array only once
655     static $runonce = false;
656     static $e = array();
657     static $img = array();
658     static $emoticons = array(
659         ':-)'  => 'smiley',
660         ':)'   => 'smiley',
661         ':-D'  => 'biggrin',
662         ';-)'  => 'wink',
663         ':-/'  => 'mixed',
664         'V-.'  => 'thoughtful',
665         ':-P'  => 'tongueout',
666         'B-)'  => 'cool',
667         '^-)'  => 'approve',
668         '8-)'  => 'wideeyes',
669         ':o)'  => 'clown',
670         ':-('  => 'sad',
671         ':('   => 'sad',
672         '8-.'  => 'shy',
673         ':-I'  => 'blush',
674         ':-X'  => 'kiss',
675         '8-o'  => 'surprise',
676         'P-|'  => 'blackeye',
677         '8-['  => 'angry',
678         'xx-P' => 'dead',
679         '|-.'  => 'sleepy',
680         '}-]'  => 'evil',
681         );
683     if ($runonce == false) {  /// After the first time this is not run again
684         foreach ($emoticons as $emoticon => $image){
685             $alttext = get_string($image, 'pix');
687             $e[] = $emoticon;
688             $img[] = "<img alt=\"$alttext\" width=\"15\" height=\"15\" src=\"$CFG->pixpath/s/$image.gif\" />";
689         }
690         $runonce = true;
691     }
693 /// this is the meat of the code - this is run every time
694     $text = str_replace($e, $img, $text);
697 function text_to_html($text, $smiley=true, $para=true) {
698 /// Given plain text, makes it into HTML as nicely as possible.
699 /// May contain HTML tags already
701     global $CFG;
703 /// Remove any whitespace that may be between HTML tags
704     $text = eregi_replace(">([[:space:]]+)<", "><", $text);
706 /// Remove any returns that precede or follow HTML tags
707     $text = eregi_replace("([\n\r])<", " <", $text);
708     $text = eregi_replace(">([\n\r])", "> ", $text);
710     convert_urls_into_links($text);
712 /// Make returns into HTML newlines.
713     $text = nl2br($text);
715 /// Turn smileys into images.
716     if ($smiley) {
717         replace_smilies($text);
718     }
720 /// Wrap the whole thing in a paragraph tag if required
721     if ($para) {
722         return "<p>".$text."</p>";
723     } else {
724         return $text;
725     }
728 function wiki_to_html($text) {
729 /// Given Wiki formatted text, make it into XHTML using external function
730     global $CFG;
732     require_once("$CFG->libdir/wiki.php");
734     $wiki = new Wiki;
735     return $wiki->format($text);
738 function html_to_text($html) {
739 /// Given HTML text, make it into plain text using external function
740     global $CFG;
742     require_once("$CFG->libdir/html2text.php");
744     return html2text($html);
748 function convert_urls_into_links(&$text) {
749 /// Given some text, it converts any URLs it finds into HTML links.
751 /// Make lone URLs into links.   eg http://moodle.com/
752     $text = eregi_replace("([[:space:]]|^|\(|\[)([[:alnum:]]+)://([^[:space:]]*)([[:alnum:]#?/&=])",
753                           "\\1<a href=\"\\2://\\3\\4\" target=\"newpage\">\\2://\\3\\4</a>", $text);
755 /// eg www.moodle.com
756     $text = eregi_replace("([[:space:]]|^|\(|\[)www\.([^[:space:]]*)([[:alnum:]#?/&=])", 
757                           "\\1<a href=\"http://www.\\2\\3\" target=\"newpage\">www.\\2\\3</a>", $text);
760 function highlight($needle, $haystack, $case=0, 
761                     $left_string="<span class=\"highlight\">", $right_string="</span>") {
762 /// This function will highlight search words in a given string
763 /// It cares about HTML and will not ruin links.  It's best to use
764 /// this function after performing any conversions to HTML.
765 /// Function found here: http://forums.devshed.com/t67822/scdaa2d1c3d4bacb4671d075ad41f0854.html
767     if (empty($needle)) {
768         return $haystack;
769     }
771     $list_of_words = eregi_replace("[^-a-zA-Z0-9&']", " ", $needle);
772     $list_array = explode(" ", $list_of_words);
773     for ($i=0; $i<sizeof($list_array); $i++) {
774         if (strlen($list_array[$i]) == 1) {
775             $list_array[$i] = "";
776         }
777     }
778     $list_of_words = implode(" ", $list_array);
779     $list_of_words_cp = $list_of_words;
780     $final = array();
781     preg_match_all('/<(.+?)>/is',$haystack,$list_of_words);
783     foreach (array_unique($list_of_words[0]) as $key=>$value) {
784         $final['<|'.$key.'|>'] = $value;
785     }
787     $haystack = str_replace($final,array_keys($final),$haystack);
788     $list_of_words_cp = eregi_replace(" +", "|", $list_of_words_cp);
790     if ($list_of_words_cp{0}=="|") {
791         $list_of_words_cp{0} = "";
792     }
793     if ($list_of_words_cp{strlen($list_of_words_cp)-1}=="|") {
794         $list_of_words_cp{strlen($list_of_words_cp)-1}="";
795     }
796     $list_of_words_cp = "(".trim($list_of_words_cp).")";
798     if (!$case){
799         $haystack = eregi_replace("$list_of_words_cp", "$left_string"."\\1"."$right_string", $haystack);
800     } else {
801         $haystack = ereg_replace("$list_of_words_cp", "$left_string"."\\1"."$right_string", $haystack);
802     }
803     $haystack = str_replace(array_keys($final),$final,$haystack);
805     return stripslashes($haystack);
808 function highlightfast($needle, $haystack) {
809 /// This function will highlight instances of $needle in $haystack
810 /// It's faster that the above function and doesn't care about 
811 /// HTML or anything.
813     $parts = explode(strtolower($needle), strtolower($haystack));
815     $pos = 0;
817     foreach ($parts as $key => $part) {
818         $parts[$key] = substr($haystack, $pos, strlen($part));
819         $pos += strlen($part);
821         $parts[$key] .= "<span class=\"highlight\">".substr($haystack, $pos, strlen($needle))."</span>";
822         $pos += strlen($needle);
823     }   
825     return (join('', $parts));
829 /// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
831 function print_header ($title="", $heading="", $navigation="", $focus="", $meta="",  
832                        $cache=true, $button="&nbsp;", $menu="", $usexml=false) {
833 // $title - appears top of window
834 // $heading - appears top of page
835 // $navigation - premade navigation string
836 // $focus - indicates form element eg  inputform.password
837 // $meta - meta tags in the header
838 // $cache - should this page be cacheable?
839 // $button - HTML code for a button (usually for module editing)
840 // $menu - HTML code for a popup menu
841 // $usexml - use XML for this page
842     global $USER, $CFG, $THEME, $SESSION;
844     global $course;                // This is a bit of an ugly hack to be gotten rid of later
845     if (!empty($course->lang)) {
846         $CFG->courselang = $course->lang;
847     }
849     if (file_exists("$CFG->dirroot/theme/$CFG->theme/styles.php")) {
850         $styles = $CFG->stylesheet;
851     } else {
852         $styles = "$CFG->wwwroot/theme/standard/styles.php";
853     }
855     if ($navigation == "home") {
856         $home = true;
857         $navigation = "";
858     } else {
859         $home = false;
860     }
862     if ($button == "") {
863         $button = "&nbsp;";
864     }
866     if (!$menu and $navigation) {
867         if (isset($USER->id)) {
868             $menu = "<font size=\"2\"><a target=\"$CFG->framename\" href=\"$CFG->wwwroot/login/logout.php\">".get_string("logout")."</a></font>";
869         } else {
870             $menu = "<font size=\"2\"><a target=\"$CFG->framename\" href=\"$CFG->wwwroot/login/index.php\">".get_string("login")."</a></font>";
871         }
872     }
874     // Add a stylesheet for the HTML editor
875     $meta = "<style type=\"text/css\">@import url($CFG->wwwroot/lib/editor/htmlarea.css);</style>\n$meta\n";
877     // Specify character set ... default is iso-8859-1 but some languages might need something else
878     // Could be optimised by carrying the charset variable around in $USER
879     if (current_language() == "en") {
880         $meta = "<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\" />\n$meta\n";
881     } else {
882         $meta = "<meta http-equiv=\"content-type\" content=\"text/html; charset=".get_string("thischarset")."\" />\n$meta\n";
883     }
885     if ( get_string("thisdirection") == "rtl" ) {
886         $direction = " dir=\"rtl\"";
887     } else {
888         $direction = " dir=\"ltr\"";
889     }
890  
891     if (!$cache) {   // Do everything we can to prevent clients and proxies caching
892         @header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
893         @header("Pragma: no-cache");
894         $meta .= "\n<meta http-equiv=\"pragma\" content=\"no-cache\" />";
895         $meta .= "\n<meta http-equiv=\"expires\" content=\"0\" />";
896     }
898     if ($usexml) {       // Added by Gustav Delius / Mad Alex for MathML output
899         $currentlanguage = current_language();
901         @header("Content-type: text/xml");
902         echo "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n";
903         if (!empty($CFG->xml_stylesheets)) {
904             $stylesheets = explode(";", $CFG->xml_stylesheets);
905             foreach ($stylesheets as $stylesheet) {
906                 echo "<?xml-stylesheet type=\"text/xsl\" href=\"$CFG->wwwroot/$stylesheet\" ?>\n";
907             }
908         }
909         echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1";
910         if (!empty($CFG->xml_doctype_extra)) {
911             echo " plus $CFG->xml_doctype_extra";
912         }
913         echo "//" . strtoupper($currentlanguage) . "\" \"$CFG->xml_dtd\">\n";
914         $direction = " xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"$currentlanguage\" $direction";
915     }
917     $title = str_replace('"', '&quot;', $title);
918     $title = strip_tags($title);
920     include ("$CFG->dirroot/theme/$CFG->theme/header.html");
923 function print_footer ($course=NULL) {
924 // Can provide a course object to make the footer contain a link to 
925 // to the course home page, otherwise the link will go to the site home
926     global $USER, $CFG, $THEME;
929 /// Course links
930     if ($course) {
931         if ($course == "home") {   // special case for site home page - please do not remove
932             $homelink  = "<p align=\"center\"><a title=\"moodle $CFG->release ($CFG->version)\" href=\"http://moodle.org/\" target=\"_blank\">";
933             $homelink .= "<br /><img width=\"130\" height=\"19\" src=\"pix/madewithmoodle.gif\" border=\"0\" /></a></p>";
934             $course = get_site();
935             $homepage = true;
936         } else {
937             $homelink = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a>";
938         }
939     } else {
940         $homelink = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/\">".get_string("home")."</a>";
941         $course = get_site();
942     }
944 /// User links
945     $loggedinas = user_login_string($course, $USER);
947     include ("$CFG->dirroot/theme/$CFG->theme/footer.html");
950 function style_sheet_setup($lastmodified=0, $lifetime=300, $themename="") {
951 /// This function is called by stylesheets to set up the header
952 /// approriately as well as the current path
954     global $CFG;
955     
956     if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {   // May not need to send stylesheet
957         // Following lines from Wolfram Kriesing and John Dell
958         $months = array_flip(array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'));
959         preg_match('~[^,]*,\s(\d+)\s(\w+)\s(\d+)\s(\d+):(\d+):(\d+).*~',
960                    $_SERVER['HTTP_IF_MODIFIED_SINCE'], $splitDate);
961         $timestamp = gmmktime($splitDate[4], $splitDate[5], $splitDate[6], $months[$splitDate[2]]+1, 
962                               $splitDate[1], $splitDate[3]);
963         if ($lastmodified <= $timestamp) {
964             header('HTTP/1.x 304 Not Modified');
965             exit;
966         }
967     }
969     header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastmodified) . " GMT");
970     header("Expires: " . gmdate("D, d M Y H:i:s", time() + $lifetime) . " GMT");
971     header("Cache-control: max_age = $lifetime"); 
972     header("Pragma: ");
973     header("Content-type: text/css");  // Correct MIME type
975     if (!empty($themename)) {
976         $CFG->theme = $themename;
977     }
979     return "$CFG->wwwroot/theme/$CFG->theme";
984 function user_login_string($course, $user=NULL) {
985     global $USER, $CFG;
987     if (empty($user)) {
988         $user = $USER;
989     }
991     if (isset($user->realuser)) {
992         if ($realuser = get_record("user", "id", $user->realuser)) {
993             $fullname = fullname($realuser, true);
994             $realuserinfo = " [<a target=\"{$CFG->framename}\"
995             href=\"$CFG->wwwroot/course/loginas.php?id=$course->id&amp;return=$realuser->id\">$fullname</a>] ";
996         }
997     } else {
998         $realuserinfo = "";
999     }
1001     if (isset($user->id) and $user->id) {
1002         $fullname = fullname($user, true);
1003         $username = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/user/view.php?id=$user->id&amp;course=$course->id\">$fullname</a>";
1004         $loggedinas = $realuserinfo.get_string("loggedinas", "moodle", "$username").
1005                       " (<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/login/logout.php\">".get_string("logout")."</a>)";
1006     } else {
1007         $loggedinas = get_string("loggedinnot", "moodle").
1008                       " (<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/login/index.php\">".get_string("login")."</a>)";
1009     }
1010     return $loggedinas;
1014 function print_navigation ($navigation) {
1015    global $CFG;
1017    if ($navigation) {
1018        if (! $site = get_site()) {
1019            $site->shortname = get_string("home");;
1020        }
1021        echo "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/\">$site->shortname</a> -> $navigation";
1022    }
1025 function print_headline($text, $size=2) {
1026     echo "<b><font size=\"$size\">$text</font></b><br />\n";
1029 function print_heading($text, $align="center", $size=3) {
1030     echo "<p align=\"$align\"><font size=\"$size\"><b>".stripslashes_safe($text)."</b></font></p>";
1033 function print_heading_with_help($text, $helppage, $module="moodle", $icon="") {
1034 // Centered heading with attached help button (same title text)
1035 // and optional icon attached
1036     echo "<p align=\"center\"><font size=\"3\">$icon<b>".stripslashes_safe($text);
1037     helpbutton($helppage, $text, $module);
1038     echo "</b></font></p>";
1040     
1041 function print_continue($link) {
1043     if (!$link) {
1044         $link = $_SERVER["HTTP_REFERER"];
1045     }
1047     print_heading("<a href=\"$link\">".get_string("continue")."</a>");
1051 function print_simple_box($message, $align="", $width="", $color="#FFFFFF", $padding=5, $class="generalbox") {
1052     print_simple_box_start($align, $width, $color, $padding, $class);
1053     echo stripslashes_safe($message);
1054     print_simple_box_end();
1057 function print_simple_box_start($align="", $width="", $color="#FFFFFF", $padding=5, $class="generalbox") {
1058     global $THEME;
1060     if ($align) {
1061         $align = "align=\"$align\"";
1062     }
1063     if ($width) {
1064         $width = "width=\"$width\"";
1065     }
1066     echo "<table $align $width class=\"$class\" border=\"0\" cellpadding=\"$padding\" cellspacing=\"0\"><tr><td bgcolor=\"$color\" class=\"$class"."content\">";
1069 function print_simple_box_end() {
1070     echo "</td></tr></table>";
1073 function print_single_button($link, $options, $label="OK", $method="get") {
1074     echo "<form action=\"$link\" method=\"$method\">";
1075     if ($options) {
1076         foreach ($options as $name => $value) {
1077             echo "<input type=\"hidden\" name=\"$name\" value=\"$value\" />";
1078         }
1079     }
1080     echo "<input type=\"submit\" value=\"$label\" /></form>";
1083 function print_spacer($height=1, $width=1, $br=true) {
1084     global $CFG;
1085     echo "<img height=\"$height\" width=\"$width\" src=\"$CFG->wwwroot/pix/spacer.gif\" alt=\"\" />";
1086     if ($br) {
1087         echo "<br />\n";
1088     }
1091 function print_file_picture($path, $courseid=0, $height="", $width="", $link="") {
1092 // Given the path to a picture file in a course, or a URL,
1093 // this function includes the picture in the page.
1094     global $CFG;
1096     if ($height) {
1097         $height = "height=\"$height\"";
1098     }
1099     if ($width) {
1100         $width = "width=\"$width\"";
1101     }
1102     if ($link) {
1103         echo "<a href=\"$link\">";
1104     }
1105     if (substr(strtolower($path), 0, 7) == "http://") {
1106         echo "<img border=\"0\" $height $width src=\"$path\" />";
1108     } else if ($courseid) {
1109         echo "<img border=\"0\" $height $width src=\"";
1110         if ($CFG->slasharguments) {        // Use this method if possible for better caching
1111             echo "$CFG->wwwroot/file.php/$courseid/$path";
1112         } else {
1113             echo "$CFG->wwwroot/file.php?file=/$courseid/$path";
1114         }
1115         echo "\" />";
1116     } else {
1117         echo "Error: must pass URL or course";
1118     }
1119     if ($link) {
1120         echo "</a>";
1121     }
1124 function print_user_picture($userid, $courseid, $picture, $large=false, $returnstring=false, $link=true) {
1125     global $CFG;
1127     if ($link) {
1128         $output = "<a href=\"$CFG->wwwroot/user/view.php?id=$userid&amp;course=$courseid\">";
1129     } else {
1130         $output = "";
1131     }
1132     if ($large) {
1133         $file = "f1";
1134         $size = 100;
1135     } else {
1136         $file = "f2";
1137         $size = 35;
1138     }
1139     if ($picture) {  // Print custom user picture
1140         if ($CFG->slasharguments) {        // Use this method if possible for better caching
1141             $output .= "<img align=\"absmiddle\" src=\"$CFG->wwwroot/user/pix.php/$userid/$file.jpg\"".
1142                        " border=\"0\" width=\"$size\" height=\"$size\" alt=\"\" />";
1143         } else {
1144             $output .= "<img align=\"absmiddle\" src=\"$CFG->wwwroot/user/pix.php?file=/$userid/$file.jpg\"".
1145                        " border=\"0\" width=\"$size\" height=\"$size\" alt=\"\" />";
1146         }
1147     } else {         // Print default user pictures (use theme version if available)
1148         $output .= "<img align=\"absmiddle\" src=\"$CFG->pixpath/u/$file.png\"".
1149                    " border=\"0\" width=\"$size\" height=\"$size\" alt=\"\" />";
1150     }
1151     if ($link) {
1152         $output .= "</a>";
1153     }
1155     if ($returnstring) {
1156         return $output;
1157     } else {
1158         echo $output;
1159     }
1162 function print_user($user, $course) {
1163 /// Prints a summary of a user in a nice little box
1165     global $CFG;
1167     static $string;
1168     static $datestring;
1169     static $countries;
1170     static $isteacher;
1172     if (empty($string)) {     // Cache all the strings for the rest of the page
1174         $string->email       = get_string("email");
1175         $string->location    = get_string("location");
1176         $string->lastaccess  = get_string("lastaccess");
1177         $string->activity    = get_string("activity");
1178         $string->unenrol     = get_string("unenrol");
1179         $string->loginas     = get_string("loginas");
1180         $string->fullprofile = get_string("fullprofile");
1181         $string->role        = get_string("role");
1182         $string->name        = get_string("name");
1183         $string->never       = get_string("never");
1185         $datestring->day     = get_string("day");
1186         $datestring->days    = get_string("days");
1187         $datestring->hour    = get_string("hour");
1188         $datestring->hours   = get_string("hours");
1189         $datestring->min     = get_string("min");
1190         $datestring->mins    = get_string("mins");
1191         $datestring->sec     = get_string("sec");
1192         $datestring->secs    = get_string("secs");
1194         $countries = get_list_of_countries();
1196         $isteacher = isteacher($course->id);
1197     }
1199     echo '<table width="80%" align="center" border="0" cellpadding="10" cellspacing="0" class="userinfobox">';
1200     echo '<tr>';
1201     echo '<td width="100" bgcolor="#ffffff" valign="top" class="userinfoboxside">';
1202     print_user_picture($user->id, $course->id, $user->picture, true);
1203     echo '</td>';
1204     echo '<td width="100%" bgcolor="#ffffff" valign="top" class="userinfoboxsummary">';
1205     echo '<font size="-1">';
1206     echo '<font size="3"><b>'.fullname($user, $isteacher).'</b></font>';
1207     echo '<p>';
1208     if (!empty($user->role) and ($user->role <> $course->teacher)) {
1209         echo "$string->role: $user->role<br />";
1210     }
1211     if ($user->maildisplay == 1 or ($user->maildisplay == 2 and $course->category) or $isteacher) {
1212         echo "$string->email: <a href=\"mailto:$user->email\">$user->email</a><br />";
1213     }
1214     if ($user->city or $user->country) {
1215         echo "$string->location: $user->city, ".$countries["$user->country"]."<br />";
1216     }
1217     if ($user->lastaccess) {
1218         echo "$string->lastaccess: ".userdate($user->lastaccess);
1219         echo "&nbsp (".format_time(time() - $user->lastaccess, $datestring).")";
1220     } else {
1221         echo "$string->lastaccess: $string->never";
1222     }
1223     echo '</td><td valign="bottom" bgcolor="#ffffff" nowrap="nowrap" class="userinfoboxlinkcontent">';
1225     echo '<font size="1">';
1226     if ($isteacher) {
1227         $timemidnight = usergetmidnight(time());
1228         echo "<a href=\"$CFG->wwwroot/course/user.php?id=$course->id&user=$user->id\">$string->activity</a><br>";
1229         if (isstudent($course->id, $user->id) and !iscreator($user->id)) {  // Includes admins
1230             echo "<a href=\"$CFG->wwwroot/course/unenrol.php?id=$course->id&user=$user->id\">$string->unenrol</a><br />";
1231             echo "<a href=\"$CFG->wwwroot/course/loginas.php?id=$course->id&user=$user->id\">$string->loginas</a><br />";
1232         }
1233     } 
1234     echo "<a href=\"$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id\">$string->fullprofile...</a>";
1235     echo '</font>';
1237     echo '</td></tr></table>';
1241 function print_group_picture($group, $courseid, $large=false, $returnstring=false, $link=true) {
1242     global $CFG;
1244     static $isteacheredit;
1246     if (!isset($isteacheredit)) {
1247         $isteacheredit = isteacheredit($courseid);
1248     }
1250     if ($group->hidepicture and !$isteacheredit) {
1251         return '';
1252     }
1254     if ($link or $isteacheredit) {
1255         $output = "<a href=\"$CFG->wwwroot/course/group.php?id=$courseid&amp;group=$group->id\">";
1256     } else {
1257         $output = '';
1258     }
1259     if ($large) {
1260         $file = "f1";
1261         $size = 100;
1262     } else {
1263         $file = "f2";
1264         $size = 35;
1265     }
1266     if ($group->picture) {  // Print custom group picture
1267         if ($CFG->slasharguments) {        // Use this method if possible for better caching
1268             $output .= "<img align=\"absmiddle\" src=\"$CFG->wwwroot/user/pixgroup.php/$group->id/$file.jpg\"".
1269                        " border=\"0\" width=\"$size\" height=\"$size\" alt=\"\" title=\"$group->name\"/>";
1270         } else {
1271             $output .= "<img align=\"absmiddle\" src=\"$CFG->wwwroot/user/pixgroup.php?file=/$group->id/$file.jpg\"".
1272                        " border=\"0\" width=\"$size\" height=\"$size\" alt=\"\" title=\"$group->name\"/>";
1273         }
1274     }
1275     if ($link or $isteacheredit) {
1276         $output .= "</a>";
1277     }
1279     if ($returnstring) {
1280         return $output;
1281     } else {
1282         echo $output;
1283     }
1287 function print_png($url, $sizex, $sizey, $returnstring, $parameters='alt=""') {
1288     global $CFG;
1289     static $recentIE;
1291     if (!isset($recentIE)) {
1292         $recentIE = check_browser_version('MSIE', '5.0');
1293     }
1295     if ($recentIE) {  // work around the HORRIBLE bug IE has with alpha transparencies
1296         $output .= "<img src=\"$CFG->pixpath/spacer.gif\" width=\"$sizex\" height=\"$sizey\"".
1297                    " border=\"0\" style=\"width: {$sizex}px; height: {$sizey}px; ".
1298                    " filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='$url', sizingMethod='scale') ".
1299                    " $parameters />";
1300     } else {
1301         $output .= "<img src=\"$url\" border=\"0\" width=\"$sizex\" height=\"$sizey\" ".
1302                    " $parameters />";
1303     }
1305     if ($returnstring) {
1306         return $output;
1307     } else {
1308         echo $output;
1309     }
1313 function print_table($table) {
1314 // Prints a nicely formatted table.
1315 // $table is an object with several properties.
1316 //     $table->head      is an array of heading names.
1317 //     $table->align     is an array of column alignments
1318 //     $table->size      is an array of column sizes
1319 //     $table->wrap      is an array of "nowrap"s or nothing
1320 //     $table->data[]    is an array of arrays containing the data.
1321 //     $table->width     is an percentage of the page
1322 //     $table->cellpadding    padding on each cell
1323 //     $table->cellspacing    spacing between cells
1325     global $THEME;
1327     if (isset($table->align)) {
1328         foreach ($table->align as $key => $aa) {
1329             if ($aa) {
1330                 $align[$key] = " align=\"$aa\"";
1331             } else {
1332                 $align[$key] = "";
1333             }
1334         }
1335     }
1336     if (isset($table->size)) {
1337         foreach ($table->size as $key => $ss) {
1338             if ($ss) {
1339                 $size[$key] = " width=\"$ss\"";
1340             } else {
1341                 $size[$key] = "";
1342             }
1343         }
1344     }
1345     if (isset($table->wrap)) {
1346         foreach ($table->wrap as $key => $ww) {
1347             if ($ww) {
1348                 $wrap[$key] = " nowrap=\"nowrap\" ";
1349             } else {
1350                 $wrap[$key] = "";
1351             }
1352         }
1353     }
1355     if (empty($table->width)) {
1356         $table->width = "80%";
1357     }
1359     if (empty($table->cellpadding)) {
1360         $table->cellpadding = "5";
1361     }
1363     if (empty($table->cellspacing)) {
1364         $table->cellspacing = "1";
1365     }
1367     print_simple_box_start("center", "$table->width", "#ffffff", 0);
1368     echo "<table width=\"100%\" border=\"0\" valign=\"top\" align=\"center\" ";
1369     echo " cellpadding=\"$table->cellpadding\" cellspacing=\"$table->cellspacing\" class=\"generaltable\">\n";
1371     $countcols = 0;
1373     if (!empty($table->head)) {
1374         $countcols = count($table->head);;
1375         echo "<tr>";
1376         foreach ($table->head as $key => $heading) {
1377             
1378             if (!isset($size[$key])) {
1379                 $size[$key] = "";
1380             } 
1381             if (!isset($align[$key])) {
1382                 $align[$key] = "";
1383             } 
1384             echo "<th valign=\"top\" ".$align[$key].$size[$key]." nowrap=\"nowrap\" class=\"generaltableheader\">$heading</th>";
1385         }
1386         echo "</tr>\n";
1387     }
1389     if (!empty($table->data)) {
1390         foreach ($table->data as $row) {
1391             echo "<tr valign=\"top\">";
1392             if ($row == "hr" and $countcols) {
1393                 echo "<td colspan=\"$countcols\"><div class=\"tabledivider\"></div></td>";
1394             } else {  /// it's a normal row of data
1395                 foreach ($row as $key => $item) {
1396                     if (!isset($size[$key])) {
1397                         $size[$key] = "";
1398                     } 
1399                     if (!isset($align[$key])) {
1400                         $align[$key] = "";
1401                     } 
1402                     if (!isset($wrap[$key])) {
1403                         $wrap[$key] = "";
1404                     } 
1405                     echo "<td ".$align[$key].$size[$key].$wrap[$key]." class=\"generaltablecell\">$item</td>";
1406                 }
1407             }
1408             echo "</tr>\n";
1409         }
1410     }
1411     echo "</table>\n";
1412     print_simple_box_end();
1414     return true;
1417 function make_table($table) {
1418 // Creates  a nicely formatted table and returns it
1419 // $table is an object with several properties.
1420 //     $table->head      is an array of heading names.
1421 //     $table->align     is an array of column alignments
1422 //     $table->size      is an array of column sizes
1423 //     $table->wrap      is an array of "nowrap"s or nothing
1424 //     $table->data[]    is an array of arrays containing the data.
1425 //     $table->width     is an percentage of the page
1426 //     $table->class     is a class
1427 //     $table->fontsize  is the size of all the text
1428 //     $table->tablealign     align the whole table
1429 //     $table->cellpadding    padding on each cell
1430 //     $table->cellspacing    spacing between cells
1432     if (isset($table->align)) {
1433         foreach ($table->align as $key => $aa) {
1434             if ($aa) {
1435                 $align[$key] = " align=\"$aa\"";
1436             } else {
1437                 $align[$key] = "";
1438             }
1439         }
1440     }
1441     if (isset($table->size)) {
1442         foreach ($table->size as $key => $ss) {
1443             if ($ss) {
1444                 $size[$key] = " width=\"$ss\"";
1445             } else {
1446                 $size[$key] = "";
1447             }
1448         }
1449     }
1450     if (isset($table->wrap)) {
1451         foreach ($table->wrap as $key => $ww) {
1452             if ($ww) {
1453                 $wrap[$key] = " nowrap=\"nowrap\" ";
1454             } else {
1455                 $wrap[$key] = "";
1456             }
1457         }
1458     }
1460     if (empty($table->width)) {
1461         $table->width = "80%";
1462     }
1464     if (empty($table->tablealign)) {
1465         $table->tablealign = "center";
1466     }
1468     if (empty($table->cellpadding)) {
1469         $table->cellpadding = "5";
1470     }
1472     if (empty($table->cellspacing)) {
1473         $table->cellspacing = "1";
1474     }
1476     if (empty($table->class)) {
1477         $table->class = "generaltable";
1478     }
1480     if (empty($table->fontsize)) {
1481         $fontsize = "";
1482     } else {
1483         $fontsize = "<font size=\"$table->fontsize\">";
1484     }
1486     $output =  "<table width=\"$table->width\" valign=\"top\" align=\"$table->tablealign\" ";
1487     $output .= " cellpadding=\"$table->cellpadding\" cellspacing=\"$table->cellspacing\" class=\"$table->class\">\n";
1489     if (!empty($table->head)) {
1490         $output .= "<tr>";
1491         foreach ($table->head as $key => $heading) {
1492             if (!isset($size[$key])) {
1493                 $size[$key] = "";
1494             } 
1495             if (!isset($align[$key])) {
1496                 $align[$key] = "";
1497             } 
1498             $output .= "<th valign=\"top\" ".$align[$key].$size[$key]." nowrap=\"nowrap\" class=\"{$table->class}header\">$fontsize$heading</th>";
1499         }
1500         $output .= "</tr>\n";
1501     }
1503     foreach ($table->data as $row) {
1504         $output .= "<tr valign=\"top\">";
1505         foreach ($row as $key => $item) {
1506             if (!isset($size[$key])) {
1507                 $size[$key] = "";
1508             } 
1509             if (!isset($align[$key])) {
1510                 $align[$key] = "";
1511             } 
1512             if (!isset($wrap[$key])) {
1513                 $wrap[$key] = "";
1514             } 
1515             $output .= "<td ".$align[$key].$size[$key].$wrap[$key]." class=\"{$table->class}cell\">$fontsize$item</td>";
1516         }
1517         $output .= "</tr>\n";
1518     }
1519     $output .= "</table>\n";
1521     return $output;
1524 function print_textarea($usehtmleditor, $rows, $cols, $width, $height, $name, $value="", $courseid=0) {
1525 /// Prints a basic textarea field
1526 /// $width and height are legacy fields and no longer used
1528     global $CFG, $course;
1530     if (empty($courseid)) {
1531         if (!empty($course->id)) {  // search for it in global context
1532             $courseid = $course->id;
1533         }
1534     }
1536     if ($usehtmleditor) {
1537         if (!empty($courseid) and isteacher($courseid)) {
1538             echo "<script type=\"text/javascript\" src=\"$CFG->wwwroot/lib/editor/htmlarea.php?id=$courseid\"></script>\n";
1539         } else {
1540             echo "<script type=\"text/javascript\" src=\"$CFG->wwwroot/lib/editor/htmlarea.php\"></script>\n";
1541         }
1542         echo "<script type=\"text/javascript\" src=\"$CFG->wwwroot/lib/editor/dialog.js\"></script>\n";
1543         echo "<script type=\"text/javascript\" src=\"$CFG->wwwroot/lib/editor/lang/en.php\"></script>\n";
1544         echo "<script type=\"text/javascript\" src=\"$CFG->wwwroot/lib/editor/popupwin.js\"></script>\n";
1546         if ($rows < 20) {
1547             $rows = 20;
1548         }
1549         if ($cols < 65) {
1550             $cols = 65;
1551         }
1552     }
1554     echo "<textarea id=\"$name\" name=\"$name\" rows=\"$rows\" cols=\"$cols\" wrap=\"virtual\">";
1555     p($value);
1556     echo "</textarea>\n";
1559 function print_richedit_javascript($form, $name, $source="no") {
1560 /// Legacy function, provided for backward compatability
1561     use_html_editor($name);
1564 function use_html_editor($name="") {
1565 /// Sets up the HTML editor on textareas in the current page.
1566 /// If a field name is provided, then it will only be
1567 /// applied to that field - otherwise it will be used
1568 /// on every textarea in the page.
1569 ///
1570 /// In most cases no arguments need to be supplied
1572     echo "<script language=\"javascript\" type=\"text/javascript\" defer=\"1\">\n";
1573     if (empty($name)) {
1574         echo "HTMLArea.replaceAll();";
1575     } else {
1576         echo "HTMLArea.replace('$name')";
1577     }
1578     echo "</script>";
1582 function update_course_icon($courseid) {
1583 // Used to be an icon, but it's now a simple form button
1584     global $CFG, $USER;
1586     if (isteacheredit($courseid)) {
1587         if (!empty($USER->editing)) {
1588             $string = get_string("turneditingoff");
1589             $edit = "off";
1590         } else {
1591             $string = get_string("turneditingon");
1592             $edit = "on";
1593         }
1594         return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/view.php\">".
1595                "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
1596                "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
1597                "<input type=\"submit\" value=\"$string\" /></form>";
1598     }
1601 function update_module_button($moduleid, $courseid, $string) {
1602 // Prints the editing button on a module "view" page
1603     global $CFG;
1605     if (isteacheredit($courseid)) {
1606         $string = get_string("updatethis", "", $string);
1607         return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/mod.php\">".
1608                "<input type=\"hidden\" name=\"update\" value=\"$moduleid\" />".
1609                "<input type=\"hidden\" name=\"return\" value=\"true\" />".
1610                "<input type=\"submit\" value=\"$string\" /></form>";
1611     } else {
1612         return "";
1613     }
1616 function update_category_button($categoryid) {
1617 // Prints the editing button on a category page
1618     global $CFG, $USER;
1620     if (iscreator()) {
1621         if (!empty($USER->categoryediting)) {
1622             $string = get_string("turneditingoff");
1623             $edit = "off";
1624         } else {
1625             $string = get_string("turneditingon");
1626             $edit = "on";
1627         } 
1628         return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/category.php\">".
1629                "<input type=\"hidden\" name=\"id\" value=\"$categoryid\" />".
1630                "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
1631                "<input type=\"submit\" value=\"$string\" /></form>";
1632     }
1635 function update_categories_button() {
1636 // Prints the editing button on categories listing
1637     global $CFG, $USER;
1639     if (isadmin()) {
1640         if (!empty($USER->categoriesediting)) {
1641             $string = get_string("turneditingoff");
1642             $edit = "off";
1643         } else {
1644             $string = get_string("turneditingon");
1645             $edit = "on";
1646         }
1647         return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/index.php\">".
1648                "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
1649                "<input type=\"submit\" value=\"$string\" /></form>";
1650     }
1653 function update_group_button($courseid, $groupid) {
1654 // Prints the editing button on group page
1655     global $CFG, $USER;
1657     if (isteacheredit($courseid)) {
1658         $string = get_string('editgroupprofile');
1659         return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/group.php\">".
1660                "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
1661                "<input type=\"hidden\" name=\"group\" value=\"$groupid\" />".
1662                "<input type=\"hidden\" name=\"edit\" value=\"on\" />".
1663                "<input type=\"submit\" value=\"$string\" /></form>";
1664     }
1667 function update_groups_button($courseid) {
1668 // Prints the editing button on groups page
1669     global $CFG, $USER;
1671     if (isteacheredit($courseid)) {
1672         if (!empty($USER->groupsediting)) {
1673             $string = get_string("turneditingoff");
1674             $edit = "off";
1675         } else {
1676             $string = get_string("turneditingon");
1677             $edit = "on";
1678         }
1679         return "<form target=\"$CFG->framename\" method=\"get\" action=\"$CFG->wwwroot/course/groups.php\">".
1680                "<input type=\"hidden\" name=\"id\" value=\"$courseid\" />".
1681                "<input type=\"hidden\" name=\"edit\" value=\"$edit\" />".
1682                "<input type=\"submit\" value=\"$string\" /></form>";
1683     }
1686 function print_group_menu($groups, $groupmode, $currentgroup, $urlroot) {
1687 /// Prints an appropriate group selection menu
1689 /// Add an "All groups" to the start of the menu
1690     $groupsmenu[0] = get_string("allgroups");
1691     foreach ($groups as $key => $groupname) {
1692         $groupsmenu[$key] = $groupname;
1693     }
1695     echo '<table><tr><td>';
1696     if ($groupmode == VISIBLEGROUPS) {
1697         print_string('groupsvisible');
1698     } else {
1699         print_string('groupsseparate');
1700     }
1701     echo ':';
1702     echo '</td><td nowrap="nowrap" align="left" width="50%">';
1703     popup_form($urlroot.'&group=', $groupsmenu, 'selectgroup', $currentgroup, "", "", "", false, "self");
1704     echo '</tr></table>';
1709 function navmenu($course, $cm=NULL, $targetwindow="self") {
1710 // Given a course and a (current) coursemodule
1711 // This function returns a small popup menu with all the
1712 // course activity modules in it, as a navigation menu
1713 // The data is taken from the serialised array stored in
1714 // the course record
1716     global $CFG;
1718     if ($cm) {
1719         $cm = $cm->id;
1720     }
1722     if ($course->format == 'weeks') {
1723         $strsection = get_string("week");
1724     } else {
1725         $strsection = get_string("topic");
1726     }
1728     if (!$modinfo = unserialize($course->modinfo)) {
1729         return "";
1730     }
1731     $isteacher = isteacher($course->id);
1732     $section = -1;
1733     $selected = "";
1734     $url = "";
1735     $previousmod = NULL;
1736     $backmod = NULL;
1737     $nextmod = NULL;
1738     $selectmod = NULL;
1739     $logslink = NULL;
1740     $flag = false;
1742     foreach ($modinfo as $mod) {
1743         if ($mod->mod == "label") {
1744             continue;
1745         }
1746         if ($mod->section > 0 and $section <> $mod->section) {
1747             $menu[] = "-------------- $strsection $mod->section --------------";
1748         }
1749         $section = $mod->section;
1750         //Only add visible or teacher mods to jumpmenu
1751         if ($mod->visible or $isteacher) {
1752             $url = "$mod->mod/view.php?id=$mod->cm";
1753             if ($flag) { // the current mod is the "next" mod
1754                 $nextmod = $mod;
1755                 $flag = false;
1756             }
1757             if ($cm == $mod->cm) {
1758                 $selected = $url;
1759                 $selectmod = $mod;
1760                 $backmod = $previousmod;
1761                 $flag = true; // set flag so we know to use next mod for "next"
1762             }
1763             $mod->name = urldecode($mod->name);
1764             if (strlen($mod->name) > 55) {
1765                 $mod->name = substr($mod->name, 0, 50)."...";
1766             }
1767             if (!$mod->visible) {
1768                 $mod->name = "(".$mod->name.")";
1769             }
1770             $menu[$url] = $mod->name;
1771             $previousmod = $mod;
1772         }
1773     }
1774     if ($selectmod and $isteacher) {
1775         $logslink = "<td><a target=\"$CFG->framename\" href=".
1776                     "\"$CFG->wwwroot/course/log.php?chooselog=1&user=0&date=0&id=$course->id&modid=$selectmod->cm\">".
1777                     "<img border=\"0\" height=\"16\" width=\"16\" src=\"$CFG->pixpath/i/log.gif\"></a></td>";
1778         
1779     }
1780     if ($backmod) {
1781         $backmod = "<form action=\"$CFG->wwwroot/mod/$backmod->mod/view.php\" target=\"$CFG->framename\">".
1782                    "<input type=\"hidden\" name=\"id\" value=\"$backmod->cm\">".
1783                    "<input type=\"submit\" value=\"&lt;\"></form>";
1784     }
1785     if ($nextmod) {
1786         $nextmod = "<form action=\"$CFG->wwwroot/mod/$nextmod->mod/view.php\" target=\"$CFG->framename\">".
1787                    "<input type=\"hidden\" name=\"id\" value=\"$nextmod->cm\">".
1788                    "<input type=\"submit\" value=\"&gt;\"></form>";
1789     }
1790     return "<table><tr>$logslink<td>$backmod</td><td>" .
1791             popup_form("$CFG->wwwroot/mod/", $menu, "navmenu", $selected, get_string("jumpto"),
1792                        "", "", true, $targetwindow).
1793             "</td><td>$nextmod</td></tr></table>";
1797 function print_date_selector($day, $month, $year, $currenttime=0) {
1798 // Currenttime is a default timestamp in GMT
1799 // Prints form items with the names $day, $month and $year
1801     if (!$currenttime) {
1802         $currenttime = time();
1803     }
1804     $currentdate = usergetdate($currenttime);
1806     for ($i=1; $i<=31; $i++) {
1807         $days[$i] = "$i";
1808     }
1809     for ($i=1; $i<=12; $i++) {
1810         $months[$i] = userdate(gmmktime(12,0,0,$i,1,2000), "%B");
1811     }
1812     for ($i=2000; $i<=2010; $i++) {
1813         $years[$i] = $i;
1814     }
1815     choose_from_menu($days,   $day,   $currentdate['mday'], "");
1816     choose_from_menu($months, $month, $currentdate['mon'],  "");
1817     choose_from_menu($years,  $year,  $currentdate['year'], "");
1820 function print_time_selector($hour, $minute, $currenttime=0, $step=5) {
1821 // Currenttime is a default timestamp in GMT
1822 // Prints form items with the names $hour and $minute
1824     if (!$currenttime) {
1825         $currenttime = time();
1826     }
1827     $currentdate = usergetdate($currenttime);
1828     if ($step != 1) {
1829         $currentdate['minutes'] = ceil($currentdate['minutes']/$step)*$step;
1830     }
1831     for ($i=0; $i<=23; $i++) {
1832         $hours[$i] = sprintf("%02d",$i);
1833     }
1834     for ($i=0; $i<=59; $i+=$step) {
1835         $minutes[$i] = sprintf("%02d",$i);
1836     }
1837     choose_from_menu($hours,   $hour,   $currentdate['hours'],   "");
1838     choose_from_menu($minutes, $minute, $currentdate['minutes'], "");
1841 function print_grade_menu($courseid, $name, $current, $includenograde=true) {
1842 /// Prints a grade menu (as part of an existing form) with help
1843 /// Showing all possible numerical grades and scales
1845     global $CFG;
1847     $strscale = get_string("scale");
1848     $strscales = get_string("scales");
1850     $scales = get_scales_menu($courseid);
1851     foreach ($scales as $i => $scalename) {
1852         $grades[-$i] = "$strscale: $scalename";
1853     }
1854     if ($includenograde) {
1855         $grades[0] = get_string("nograde");
1856     }
1857     for ($i=100; $i>=1; $i--) {
1858         $grades[$i] = $i;
1859     }
1860     choose_from_menu($grades, "$name", "$current", "");
1862     $helpicon = "$CFG->pixpath/help.gif";
1863     $linkobject = "<img align=\"absmiddle\" border=\"0\" height=\"17\" width=\"22\" alt=\"$strscales\" src=\"$helpicon\" />";
1864     link_to_popup_window ("/course/scales.php?id=$courseid&amp;list=true", "ratingscales", 
1865                           $linkobject, 400, 500, $strscales);
1868 function print_scale_menu($courseid, $name, $current) {
1869 /// Prints a scale menu (as part of an existing form) including help button
1870 /// Just like print_grade_menu but without the numerical grades
1872     global $CFG;
1874     $strscales = get_string("scales");
1875     choose_from_menu(get_scales_menu($courseid), "$name", $current, "");
1876     $helpicon = "$CFG->pixpath/help.gif";
1877     $linkobject = "<img align=\"absmiddle\" border=\"0\" height=\"17\" width=\"22\" alt=\"$strscales\" src=\"$helpicon\" />";
1878     link_to_popup_window ("/course/scales.php?id=$courseid&amp;list=true", "ratingscales", 
1879                           $linkobject, 400, 500, $strscales);
1883 function print_scale_menu_helpbutton($courseid, $scale) {
1884 /// Prints a help button about a scale
1885 /// scale is an object
1887     global $CFG;
1889     $strscales = get_string("scales");
1890     $helpicon = "$CFG->pixpath/help.gif";
1891     $linkobject = "<img align=\"absmiddle\" border=\"0\" height=\"17\" width=\"22\" alt=\"$scale->name\" src=\"$helpicon\" />";
1892     link_to_popup_window ("/course/scales.php?id=$courseid&amp;list=true&amp;scale=$scale->id", "ratingscale", 
1893                           $linkobject, 400, 500, $scale->name);
1897 function error ($message, $link="") {
1898     global $CFG, $SESSION;
1900     print_header(get_string("error"));
1901     echo "<br />";
1902     print_simple_box($message, "center", "", "#FFBBBB");
1903    
1904     if (!$link) {
1905         if ( !empty($SESSION->fromurl) ) {
1906             $link = "$SESSION->fromurl";
1907             unset($SESSION->fromurl);
1908         } else {
1909             $link = "$CFG->wwwroot/";
1910         }
1911     }
1912     print_continue($link);
1913     print_footer();
1914     die;
1917 function helpbutton ($page, $title="", $module="moodle", $image=true, $linktext=false, $text="") {
1918     // $page = the keyword that defines a help page
1919     // $title = the title of links, rollover tips, alt tags etc
1920     // $module = which module is the page defined in
1921     // $image = use a help image for the link?  (true/false/"both")
1922     // $text = if defined then this text is used in the page, and 
1923     //         the $page variable is ignored.
1924     global $CFG, $THEME;
1926     if ($module == "") {
1927         $module = "moodle";
1928     }
1930     if ($image) {
1931         $icon = "$CFG->pixpath/help.gif";
1932         if ($linktext) {
1933             $linkobject = "<span style=\"cursor:help;\">$title<img align=\"absmiddle\" border=\"0\" ".
1934                           " height=\"17\" width=\"22\" alt=\"\" src=\"$icon\" /></span>";
1935         } else {
1936             $linkobject = "<img align=\"absmiddle\" border=\"0\" height=\"17\" width=\"22\" ".
1937                           " alt=\"$title\" style=\"cursor:help;\" src=\"$icon\" />";
1938         }
1939     } else {
1940         $linkobject = "<span style=\"cursor:help;\">$title</span>";
1941     }
1942     if ($text) {
1943         $url = "/help.php?module=$module&amp;text=".htmlentities(urlencode($text));
1944     } else {
1945         $url = "/help.php?module=$module&amp;file=$page.html";
1946     }
1947     link_to_popup_window ($url, "popup", $linkobject, 400, 500, $title);
1950 function emoticonhelpbutton($form, $field) {
1951 /// Prints a special help button that is a link to the "live" emoticon popup
1952     global $CFG, $SESSION;
1954     $SESSION->inserttextform = $form;
1955     $SESSION->inserttextfield = $field;
1956     helpbutton("emoticons", get_string("helpemoticons"), "moodle", false, true);
1957     echo "&nbsp;";
1958     link_to_popup_window ("/help.php?module=moodle&amp;file=emoticons.html", "popup", 
1959                           "<img src=\"$CFG->pixpath/s/smiley.gif\" border=\"0\" align=\"absmiddle\" width=\"15\" height=\"15\" />", 
1960                            400, 500, get_string("helpemoticons"));
1961     echo "<br />";
1964 function notice ($message, $link="") {
1965     global $CFG, $THEME;
1967     if (!$link) {
1968         if (!empty($_SERVER["HTTP_REFERER"])) {
1969             $link = $_SERVER["HTTP_REFERER"];
1970         } else {
1971             $link = "$CFG->wwwroot/";
1972         }
1973     }
1975     echo "<br />";
1976     print_simple_box($message, "center", "50%", "$THEME->cellheading", "20", "noticebox");
1977     print_heading("<a href=\"$link\">".get_string("continue")."</a>");
1978     print_footer(get_site());
1979     die;
1982 function notice_yesno ($message, $linkyes, $linkno) {
1983     global $THEME;
1985     print_simple_box_start("center", "60%", "$THEME->cellheading");
1986     echo "<p align=\"center\"><font size=\"3\">$message</font></p>";
1987     echo "<p align=\"center\"><font size=\"3\"><b>";
1988     echo "<a href=\"$linkyes\">".get_string("yes")."</a>";
1989     echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
1990     echo "<a href=\"$linkno\">".get_string("no")."</a>";
1991     echo "</b></font></p>";
1992     print_simple_box_end();
1995 function redirect($url, $message="", $delay="0") {
1996 // Redirects the user to another page, after printing a notice
1998     if (empty($message)) {
1999         echo "<meta http-equiv=\"refresh\" content=\"$delay; url=$url\" />";
2000         echo "<script>location.replace('$url');</script>";   // To cope with Mozilla bug
2001     } else {
2002         if (empty($delay)) {  
2003             $delay = 3;  // There's no point having a message with no delay
2004         }
2005         print_header("", "", "", "", "<meta http-equiv=\"refresh\" content=\"$delay; url=$url\" />");
2006         echo "<center>";
2007         echo "<p>$message</p>";
2008         echo "<p>( <a href=\"$url\">".get_string("continue")."</a> )</p>";
2009         echo "</center>";
2010         flush();
2011         sleep($delay);
2012         echo "<script>location.replace('$url');</script>";   // To cope with Mozilla bug
2013     }
2014     die; 
2017 function notify ($message, $color="red", $align="center") {
2018     echo "<p align=\"$align\"><b><font color=\"$color\">$message</font></b></p>\n";
2021 function obfuscate_email($email) {
2022 /// Given an email address, this function will return an obfuscated version of it
2023     $i = 0;
2024     $length = strlen($email);
2025     $obfuscated = "";
2026     while ($i < $length) {
2027         if (rand(0,2)) {
2028             $obfuscated.='%'.dechex(ord($email{$i}));
2029         } else {
2030             $obfuscated.=$email{$i};
2031         }
2032         $i++;
2033     }
2034     return $obfuscated;
2037 function obfuscate_text($plaintext) {
2038 /// This function takes some text and replaces about half of the characters
2039 /// with HTML entity equivalents.   Return string is obviously longer.
2040     $i=0;
2041     $length = strlen($plaintext);
2042     $obfuscated="";
2043     $prev_obfuscated = false;
2044     while ($i < $length) {
2045         $c = ord($plaintext{$i});
2046         $numerical = ($c >= ord('0')) && ($c <= ord('9'));
2047         if ($prev_obfuscated and $numerical ) {
2048             $obfuscated.='&#'.ord($plaintext{$i});
2049         } else if (rand(0,2)) {
2050             $obfuscated.='&#'.ord($plaintext{$i});
2051             $prev_obfuscated = true;
2052         } else {
2053             $obfuscated.=$plaintext{$i};
2054             $prev_obfuscated = false;
2055         }
2056       $i++;
2057     }
2058     return $obfuscated;
2061 function obfuscate_mailto($email, $label="", $dimmed=false) {
2062 /// This function uses the above two functions to generate a fully
2063 /// obfuscated email link, ready to use.
2065     if (empty($label)) {
2066         $label = $email;
2067     }
2068     if ($dimmed) {
2069         $title = get_string('emaildisable');
2070         $dimmed = ' class="dimmed"';
2071     } else {
2072         $title = '';
2073         $dimmed = '';
2074     }
2075     return sprintf("<a href=\"%s:%s\" $dimmed title=\"$title\">%s</a>", 
2076                     obfuscate_text('mailto'), obfuscate_email($email),
2077                     obfuscate_text($label));
2080 function print_paging_bar($totalcount, $page, $perpage, $baseurl) {
2081 /// Prints a single paging bar to provide access to other pages  (usually in a search)
2083     $maxdisplay = 18;
2085     if ($totalcount > $perpage) {
2086         echo "<center>";
2087         echo "<p>".get_string("page").":";
2088         if ($page > 0) {
2089             $pagenum=$page-1;
2090             echo "&nbsp;(<a  href=\"{$baseurl}page=$pagenum\">".get_string("previous")."</a>)&nbsp;";
2091         }
2092         $lastpage = ceil($totalcount / $perpage);
2093         if ($page > 15) {
2094             $startpage = $page - 10;
2095             echo "&nbsp<a href=\"{$baseurl}page=0\">1</a>&nbsp;...";
2096         } else {
2097             $startpage = 0;
2098         }
2099         $currpage = $startpage;
2100         $displaycount = 0;
2101         while ($displaycount < $maxdisplay and $currpage < $lastpage) {
2102             $displaypage = $currpage+1;
2103             if ($page == $currpage) {
2104                 echo "&nbsp;&nbsp;$displaypage";
2105             } else {
2106                 echo "&nbsp;&nbsp;<a href=\"{$baseurl}page=$currpage\">$displaypage</a>";
2107             }
2108             $displaycount++;
2109             $currpage++;
2110         }
2111         if ($currpage < $lastpage) {
2112             $lastpageactual = $lastpage - 1;
2113             echo "&nbsp;...<a href=\"{$baseurl}page=$lastpageactual\">$lastpage</a>&nbsp;";
2114         }
2115         $pagenum = $page + 1;
2116         if ($pagenum != $displaypage) {
2117             echo "&nbsp;&nbsp;(<a href=\"{$baseurl}page=$pagenum\">".get_string("next")."</a>)";
2118         }
2119         echo "</p>";
2120         echo "</center>";
2121     }
2124 // vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140:
2125 ?>