]> git.mjollnir.org Git - moodle.git/commitdiff
Latest fixes from Jon ... it's much more stable now!
authormoodler <moodler>
Tue, 10 Aug 2004 13:50:58 +0000 (13:50 +0000)
committermoodler <moodler>
Tue, 10 Aug 2004 13:50:58 +0000 (13:50 +0000)
... the only thing remaining is that the user window is
still done old-style, and not yet converted over to the
new -style daemon

mod/chat/chatd.php
mod/chat/lib.php

index b90e57b66a140478497016b8e3345af0b6ae3a7e..5c6a43500a6117fccbbc789589384b2909564f14 100755 (executable)
@@ -67,6 +67,34 @@ class ChatDaemon {
 
     var $message_queue = array(); // Holds messages that we haven't committed to the DB yet
 
+    function get_user_window($sessionid) {
+        ob_start();
+        echo "<html>\n<head>\n";
+
+        // <head>
+        /*
+        echo "<script type='text/javascript'>\n";
+        echo "   function reloadme() {\n";
+        //echo "       return false;\n";
+        echo "       window.location.reload();\n";
+        echo "   }\n";
+        echo "</script>";
+        */
+        // </head>
+
+        //echo "</head>\n<body onload='window.setTimeout(\"reloadme()\", 2000);'>\n";
+        echo "</head>\n<body>\n";
+
+        // <body>
+        echo '<p style="font-size: 0.75em;">User window for session '.$sessionid.'</p>';
+        echo '<p style="font-size: 0.75em;">The time is '.time().'</p>';
+        // </body>
+
+        echo "</body>\n</html>\n";
+        return ob_get_clean();
+
+    }
+
     function new_ufo_id() {
         static $id = 0;
         if($id++ === 0x1000000) { // Cycling very very slowly to prevent overflow
@@ -91,7 +119,8 @@ class ChatDaemon {
 
         switch($type) {
             case CHAT_SIDEKICK_USERS:
-                $x = pusers($this->sets_info[$sessionid]['chat'], $this->sets_info[$sessionid]['groupid']);
+            /*
+                //$x = pusers($this->sets_info[$sessionid]['chatid'], $this->sets_info[$sessionid]['groupid']);
                 //$x = "<html>Lalalala! ".time()."</html>";
 
                 $header  = "HTTP/1.1 200 OK\n";
@@ -102,16 +131,38 @@ class ChatDaemon {
                 $header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n";
                 $header .= "Cache-Control: no-cache, must-revalidate\n";
                 $header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n";
-                $header .= "Refresh: 3; url=http://$CFG->chat_serverhost:$CFG->chat_serverport?win=users&".
-                           "chat_sid=".$sessionid."&groupid=".$this->sets_info[$sessionid]['groupid']."\n";
+                //$header .= "Refresh: 3; url=http://$CFG->chat_serverhost:$CFG->chat_serverport?win=users&".
+                //           "chat_sid=".$sessionid."&groupid=".$this->sets_info[$sessionid]['groupid']."\n";
                 $header .= "\n";
 
                 $x = $header.$x;
+*/
 
+/*
                 trace('Outputting user list('.strlen($x).' chars)');
                 //trace($x);
 
                 chat_socket_write($handle, $x);
+*/
+
+                $content = $this->get_user_window($sessionid);
+
+                $header  = "HTTP/1.1 200 OK\n";
+                $header .= "Connection: close\n";
+                $header .= "Date: ".date('r')."\n";
+                $header .= "Server: Moodle\n";
+                $header .= "Content-Type: text/html\n";
+                $header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n";
+                $header .= "Cache-Control: no-cache, must-revalidate\n";
+                $header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n";
+                $header .= "Content-Length: ".strlen($content)."\n";
+                $header .= "Refresh: 3; url=http://$CFG->chat_serverhost:$CFG->chat_serverport/?win=users&".
+                           "chat_sid=".$sessionid."&groupid=".$this->sets_info[$sessionid]['groupid']."\n";
+                $header .= "\n";
+
+                // That's enough headers for one lousy dummy response
+                chat_socket_write($handle, $header . $content);
+
             break;
             case CHAT_SIDEKICK_MESSAGE:
                 // Incoming message
@@ -128,21 +179,11 @@ class ChatDaemon {
                     break;
                 }
 
-                // Format the message object here
-                $output = chat_format_message($msg);
-
-                $msg->message = $output->text; // This is for writing into the DB
-                $msg->text_ = $output->text;
-                $msg->html_ = $output->html;
-                $msg->beep_ = $output->beep;
+                // Commit to DB
+                insert_record('chat_messages', $msg);
 
                 // OK, now push it out to all users
-                $this->message_broadcast($msg);
-
-                // Put it on the uncommitted queue
-                // TODO: error checking!!!
-                //$message_queue[] = $msg;
-                insert_record('chat_messages', $msg);
+                $this->message_broadcast($msg, $this->sets_info[$sessionid]['user']);
 
                 // Update that user's lastmessageping
                 // TODO: this can and should be written as a single UPDATE query
@@ -152,6 +193,23 @@ class ChatDaemon {
                     update_record('chat_users', $user);
                 }
 
+                // We did our work, but before slamming the door on the poor browser
+                // show the courtesy of responding to the HTTP request. Otherwise, some
+                // browsers decide to get vengeance by flooding us with repeat requests.
+
+                $header  = "HTTP/1.1 200 OK\n";
+                $header .= "Connection: close\n";
+                $header .= "Date: ".date('r')."\n";
+                $header .= "Server: Moodle\n";
+                $header .= "Content-Type: text/html\n";
+                $header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n";
+                $header .= "Cache-Control: no-cache, must-revalidate\n";
+                $header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n";
+                $header .= "\n";
+
+                // That's enough headers for one lousy dummy response
+                chat_socket_write($handle, $header);
+
                 // All done
             break;
         }
@@ -176,11 +234,41 @@ class ChatDaemon {
             $this->dismiss_half($sessionid);
             return false;
         }
+        $user = get_record('user', 'id', $chatuser->userid);
+        if($user === false) {
+            $this->dismiss_half($sessionid);
+            return false;
+        }
+        $course = get_record('course', 'id', $chat->course); {
+        if($course === false) {
+            $this->dismiss_half($sessionid);
+            return false;
+            }
+        }
 
-        global $CHAT_HTMLHEAD_JS;
+        global $CHAT_HTMLHEAD_JS, $CFG;
+
+        // A really sad thing, to have to do this by hand.... :-(
+        $lang = NULL;
+        if(empty($lang) && !empty($course->lang)) {
+            $lang = $course->lang;
+        }
+        if(empty($lang) && !empty($user->lang)) {
+            $lang = $user->lang;
+        }
+        if(empty($lang)) {
+            $lang = $CFG->lang;
+        }
 
         $this->conn_sets[$sessionid] = $this->conn_half[$sessionid];
-        $this->sets_info[$sessionid] = array('chatid' => $chatuser->chatid, 'userid' => $chatuser->userid, 'groupid' => $groupid, 'lastmessages' => array(), 'lastmsgindex' => 0);
+        $this->sets_info[$sessionid] = array(
+            'chatid'    => $chatuser->chatid,
+            'user'      => $user,
+            'userid'    => $chatuser->userid,
+            'groupid'   => $groupid,
+            'lang'      => $lang
+        );
+
         $this->dismiss_half($sessionid, false);
         chat_socket_write($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $CHAT_HTMLHEAD_JS);
         trace('Finalized client: sid: '.$sessionid.' uid: '.$chatuser->userid.' gid: '.intval($groupid));
@@ -196,16 +284,7 @@ class ChatDaemon {
         $msg->timestamp = time();
 
         insert_record('chat_messages', $msg);
-
-        // Format the message object here
-        $output = chat_format_message($msg);
-
-        $msg->message = $output->text; // This is for writing into the DB
-        $msg->text_ = $output->text;
-        $msg->html_ = $output->html;
-        $msg->beep_ = $output->beep;
-
-        $this->message_broadcast($msg);
+        $this->message_broadcast($msg, $this->sets_info[$sessionid]['user']);
 
         return true;
     }
@@ -293,8 +372,9 @@ class ChatDaemon {
             return false;
         }
         foreach($this->conn_sets[$sessionid] as $handle) {
-            socket_shutdown($handle);
-            socket_close($handle);
+            // Since we want to dismiss this, don't generate any errors if it's dead already
+            @socket_shutdown($handle);
+            @socket_close($handle);
         }
         unset($this->conn_sets[$sessionid]);
         unset($this->sets_info[$sessionid]);
@@ -355,12 +435,11 @@ class ChatDaemon {
         return $retval;
     }
 
-    function message_broadcast($message) {
+    function message_broadcast($message, $sender) {
         if(empty($this->conn_sets)) {
             return true;
         }
 
-        //trace('Broadcasting message');
         foreach($this->sets_info as $sessionid => $info) {
             // We need to get handles from users that are in the same chatroom, same group
             if($info['chatid'] == $message->chatid &&
@@ -368,8 +447,13 @@ class ChatDaemon {
             {
 
                 // Simply give them the message
+                $output = chat_format_message_manually($message, 0, $sender, $info['userid'], $info['lang']);
 
-                if(!chat_socket_write($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $message->html_)) {
+                if($output->beep) {
+                    chat_socket_write($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], '<embed src="'.$this->beepsoundsrc.'" autostart="true" hidden="true" />');
+                }
+
+                if(!chat_socket_write($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $output->html)) {
 
                     // Send failed! We must now disconnect/forget about the user FIRST
                     // and THEN broadcast a message to all others... otherwise, infinite recursion.
@@ -386,17 +470,14 @@ class ChatDaemon {
                     trace('Client socket write failed, destroying uid '.$info['userid'].' with SID '.$sessionid);
                     insert_record('chat_messages', $msg);
 
-                    // Format the message object here
-                    $output = chat_format_message($msg);
-
-                    $msg->message = $output->text; // This is for writing into the DB
-                    $msg->text_ = $output->text;
-                    $msg->html_ = $output->html;
-                    $msg->beep_ = $output->beep;
-
-                    // Kill him before broadcasting!!
+                    // *************************** IMPORTANT
+                    //
+                    // Kill him BEFORE broadcasting, otherwise we 'll get infinite recursion!
+                    //
+                    // **********************************************************************
+                    $latesender = $this->sets_info[$sessionid]['user'];
                     $this->dismiss_set($sessionid);
-                    $this->message_broadcast($msg);
+                    $this->message_broadcast($msg, $latesender);
                 }
                 //trace('Sent to UID '.$this->sets_info[$sessionid]['userid'].': '.$message->text_);
             }
@@ -426,9 +507,7 @@ $DAEMON->trace_level = E_ALL;
 $DAEMON->socketserver_refresh = 10;
 $DAEMON->rememberlast = 10;
 $DAEMON->can_daemonize = function_exists('pcntl_fork');
-
-$logfile = fopen('chatd.log', 'a+');
-
+$DAEMON->beepsoundsrc = $CFG->wwwroot.'/mod/chat/beep.wav';
 
 /// Check the parameters //////////////////////////////////////////////////////
 
@@ -448,6 +527,7 @@ $logfile = fopen('chatd.log', 'a+');
     }
 
 
+$logfile = fopen('chatd.log', 'a+');
 
 /// Try to set up all the sockets ////////////////////////////////////////////////
 
@@ -482,6 +562,13 @@ if(!socket_bind($DAEMON->listen_socket, $CFG->chat_serverip, $CFG->chat_serverpo
     // Failed to bind socket
     $DAEMON->last_error = socket_last_error();
     echo "Error: socket_bind() failed: ". socket_strerror(socket_last_error($DAEMON->last_error)).' ['.$DAEMON->last_error."]\n";
+
+    // If $DAEMON->last_error == 98 (Success), maybe we need to try cleaning up a bit before dying
+    // This is EXPERIMENTAL code!
+    if($DAEMON->last_error == 98) {
+        trace('experimental fix kicks in');
+        socket_close($DAEMON->listen_socket);
+    }
     die();
 }
 if(!socket_listen($DAEMON->listen_socket, $CFG->chat_servermax)) {
@@ -653,17 +740,21 @@ function chat_socket_write($connection, $text) {
     $check_socket = array($connection);
     $socket_changed = socket_select($read = NULL, $check_socket, $except = NULL, 0, 0);
     if($socket_changed > 0) {
-        socket_write($connection, $text, strlen($text));
+        $written = socket_write($connection, $text, strlen($text));
+        //trace('socket_write wrote '.$written.' of '.strlen($text).' bytes');
         return true;
     }
     return false;
 }
 
-function pusers($chat, $groupid) {
+function pusers($chatid, $groupid) {
 /// Delete users who are using text version and are old
 
 global $CFG, $str;
 
+static $lastupdate  = 0;
+static $outputcache = NULL;
+
 //chat_delete_old_users();
 
 
@@ -674,60 +765,77 @@ ob_start();
 
 $timenow = time();
 
-if (empty($str)) {
-    $str->idle   = get_string("idle", "chat");
-    $str->beep   = get_string("beep", "chat");
-    $str->day   = get_string("day");
-    $str->days  = get_string("days");
-    $str->hour  = get_string("hour");
-    $str->hours = get_string("hours");
-    $str->min   = get_string("min");
-    $str->mins  = get_string("mins");
-    $str->sec   = get_string("sec");
-    $str->secs  = get_string("secs");
-}
 
-/// Get list of users
+// WARNING!!!! THESE ARE HERE TO REMOVE NOTICES!!!
+// THEY SHOULD BE FIXED!
+$chat_sid = 0;
+$chat->course = 0;
+
+// Keep the results cached for 5 seconds
+if($timenow - 5 > $lastupdate || empty($outputcache)) {
+
+    if (empty($str)) {
+        $str->idle   = get_string("idle", "chat");
+        $str->beep   = get_string("beep", "chat");
+        $str->day   = get_string("day");
+        $str->days  = get_string("days");
+        $str->hour  = get_string("hour");
+        $str->hours = get_string("hours");
+        $str->min   = get_string("min");
+        $str->mins  = get_string("mins");
+        $str->sec   = get_string("sec");
+        $str->secs  = get_string("secs");
+    }
+
+    /// Get list of users
 
-if (!$chatusers = chat_get_users($chat->id, $groupid)) {
-    print_string("errornousers", "chat");
-    die('no users');
-    //return ob_get_clean();
-    //exit;
-}
+    if (!$chatusers = chat_get_users($chatid, $groupid)) {
+        print_string("errornousers", "chat");
+        die('no users');
+        //return ob_get_clean();
+        //exit;
+    }
 
-echo "<html>\n";
-echo "<head>\n";
-echo "<script lang=\"Javascript\">\n";
-echo "   function reloadme() {\n";
-echo "       return false;\n";
-echo "       window.location.reload();\n";
-echo "   }\n";
-echo "</script></head>\n";
-echo '<body onload="setTimeout(\'reloadme()\', 5000);">'."\n\n";
-for ($i = 0; $i < 100; ++$i) {
-    echo "<!-- nix -->\n";
-}
+    echo "<html>\n";
+    echo "<head>\n";
+    echo "<script lang=\"Javascript\">\n";
+    echo "   function reloadme() {\n";
+    echo "       return false;\n";
+    echo "       window.location.reload();\n";
+    echo "   }\n";
+    echo "</script></head>\n";
+    //echo '<body onload="setTimeout(\'reloadme()\', 5000);">'."\n\n";
+    //for ($i = 0; $i < 100; ++$i) {
+    //    echo "<!-- nix -->\n";
+    //}
+
+    echo "<body>\n<table width=\"100%\">\n";
+    foreach ($chatusers as $chatuser) {
+        $lastping = $timenow - $chatuser->lastmessageping;
+        echo "<tr>\n<td width=35>";
+        echo "<a target=\"_new\" onClick=\"return openpopup('/user/view.php?id=$chatuser->id&course=$chat->course','user$chatuser->id','');\" href=\"$CFG->wwwroot/user/view.php?id=$chatuser->id&course=$chat->course\">";
+        print_user_picture($chatuser->id, 0, $chatuser->picture, false, false, false);
+        echo "</a></td><td valign=center>";
+        echo "<p><font size=1>";
+        echo fullname($chatuser)."<br />";
+        echo "<font color=\"#888888\">$str->idle: ".format_time($lastping, $str)."</font>";
+        echo " <a href=\"users.php?chat_sid=$chat_sid&beep=$chatuser->id&groupid=$groupid\">$str->beep</a>";
+        echo "</font></p>";
+        echo "<td>\n</tr>\n";
+    }
+    echo "</table>\n";
 
-echo "<table width=\"100%\">";
-foreach ($chatusers as $chatuser) {
-    $lastping = $timenow - $chatuser->lastmessageping;
-    echo "<tr><td width=35>";
-    echo "<a target=\"_new\" onClick=\"return openpopup('/user/view.php?id=$chatuser->id&course=$chat->course','user$chatuser->id','');\" href=\"$CFG->wwwroot/user/view.php?id=$chatuser->id&course=$chat->course\">";
-    print_user_picture($chatuser->id, 0, $chatuser->picture, false, false, false);
-    echo "</a></td><td valign=center>";
-    echo "<p><font size=1>";
-    echo fullname($chatuser)."<br />";
-    echo "<font color=\"#888888\">$str->idle: ".format_time($lastping, $str)."</font>";
-    echo " <a href=\"users.php?chat_sid=$chat_sid&beep=$chatuser->id&groupid=$groupid\">$str->beep</a>";
-    echo "</font></p>";
-    echo "<td></tr>";
-}
-echo "</table>";
+    //window.setTimeout('reloadme', 1000)
+    echo "</body>\n</html>\n";
 
-//window.setTimeout('reloadme', 1000)
-echo '</body></html>';
-return ob_get_clean();
+    $lastupdate = $timenow;
+    return $outputcache = ob_get_clean();
+}
+else {
+    // Return cached output
+    trace('User window cached return');
+    return $outputcache;
+}
 
 }
 
index 067512476049bbc0679ffbb2c4c39df5957ee2e5..40e158cdfb344a547f458ac82e22a68b5eff386b 100644 (file)
@@ -4,28 +4,28 @@
 
 if (!isset($CFG->chat_refresh_room)) {
     set_config("chat_refresh_room", 5);
-} 
+}
 if (!isset($CFG->chat_refresh_userlist)) {
     set_config("chat_refresh_userlist", 10);
-} 
+}
 if (!isset($CFG->chat_old_ping)) {
     set_config("chat_old_ping", 30);
-} 
+}
 if (!isset($CFG->chat_method)) {
     set_config("chat_method", "header_js");
-} 
+}
 if (!isset($CFG->chat_serverhost)) {
     set_config("chat_serverhost", $_SERVER['HTTP_HOST']);
-} 
+}
 if (!isset($CFG->chat_serverip)) {
     set_config("chat_serverip", $_SERVER['SERVER_ADDR']);
-} 
+}
 if (!isset($CFG->chat_serverport)) {
     set_config("chat_serverport", 9111);
-} 
+}
 if (!isset($CFG->chat_servermax)) {
     set_config("chat_servermax", 100);
-} 
+}
 
 define("CHAT_DRAWBOARD", false);  // Look into this later
 
@@ -47,16 +47,16 @@ $CHAT_HTMLHEAD_MSGINPUT_JS = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Trans
 
 
 function chat_add_instance($chat) {
-/// Given an object containing all the necessary data, 
-/// (defined by the form in mod.html) this function 
-/// will create a new instance and return the id number 
+/// Given an object containing all the necessary data,
+/// (defined by the form in mod.html) this function
+/// will create a new instance and return the id number
 /// of the new instance.
 
     $chat->timemodified = time();
 
-    $chat->chattime = make_timestamp($chat->chatyear, $chat->chatmonth, $chat->chatday, 
+    $chat->chattime = make_timestamp($chat->chatyear, $chat->chatmonth, $chat->chatday,
                                      $chat->chathour, $chat->chatminute);
-    
+
     if ($returnid = insert_record("chat", $chat)) {
 
         $event = NULL;
@@ -79,14 +79,14 @@ function chat_add_instance($chat) {
 
 
 function chat_update_instance($chat) {
-/// Given an object containing all the necessary data, 
-/// (defined by the form in mod.html) this function 
+/// Given an object containing all the necessary data,
+/// (defined by the form in mod.html) this function
 /// will update an existing instance with new data.
 
     $chat->timemodified = time();
     $chat->id = $chat->instance;
 
-    $chat->chattime = make_timestamp($chat->chatyear, $chat->chatmonth, $chat->chatday, 
+    $chat->chattime = make_timestamp($chat->chatyear, $chat->chatmonth, $chat->chatday,
                                      $chat->chathour, $chat->chatminute);
 
     if ($returnid = update_record("chat", $chat)) {
@@ -108,9 +108,9 @@ function chat_update_instance($chat) {
 
 
 function chat_delete_instance($id) {
-/// Given an ID of an instance of this module, 
-/// this function will permanently delete the instance 
-/// and any data that depends on it.  
+/// Given an ID of an instance of this module,
+/// this function will permanently delete the instance
+/// and any data that depends on it.
 
     if (! $chat = get_record("chat", "id", "$id")) {
         return false;
@@ -132,7 +132,7 @@ function chat_delete_instance($id) {
 }
 
 function chat_user_outline($course, $user, $mod, $chat) {
-/// Return a small object with summary information about what a 
+/// Return a small object with summary information about what a
 /// user has done with a given particular instance of this module
 /// Used for user activity reports.
 /// $return->time = the time they did it
@@ -142,7 +142,7 @@ function chat_user_outline($course, $user, $mod, $chat) {
 }
 
 function chat_user_complete($course, $user, $mod, $chat) {
-/// Print a detailed representation of what a  user has done with 
+/// Print a detailed representation of what a  user has done with
 /// a given particular instance of this module, for user activity reports.
 
     return true;
@@ -161,7 +161,7 @@ function chat_print_recent_activity($course, $isteacher, $timestart) {
                                         FROM {$CFG->prefix}chat_users as cu,
                                              {$CFG->prefix}chat as ch,
                                              {$CFG->prefix}user as u
-                                       WHERE cu.userid = u.id 
+                                       WHERE cu.userid = u.id
                                          AND cu.chatid = ch.id
                                          AND cu.lastping > '$timeold'
                                          AND ch.course = '$course->id'
@@ -200,8 +200,8 @@ function chat_print_recent_activity($course, $isteacher, $timestart) {
 
 function chat_cron () {
 /// Function to be run periodically according to the moodle cron
-/// This function searches for things that need to be done, such 
-/// as sending out mail, toggling flags etc ... 
+/// This function searches for things that need to be done, such
+/// as sending out mail, toggling flags etc ...
 
     global $CFG;
 
@@ -281,7 +281,7 @@ function chat_refresh_events($courseid = 0) {
             $event->eventtype   = $chat->schedule;
             $event->timeduration = 0;
             $event->visible     = get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $chat->id);
-            
+
             add_event($event);
         }
     }
@@ -300,7 +300,7 @@ function chat_get_users($chatid, $groupid=0) {
     } else {
         $groupselect = "";
     }
-   
+
     return get_records_sql("SELECT DISTINCT u.id, u.firstname, u.lastname, u.picture, c.lastmessageping, c.firstping
                               FROM {$CFG->prefix}chat_users c,
                                    {$CFG->prefix}user u
@@ -312,7 +312,7 @@ function chat_get_users($chatid, $groupid=0) {
 function chat_get_latest_message($chatid, $groupid=0) {
 /// Efficient way to extract just the latest message
 /// Uses ADOdb directly instead of get_record_sql()
-/// because the LIMIT command causes problems with 
+/// because the LIMIT command causes problems with
 /// the developer debugging in there.
 
     global $db, $CFG;
@@ -324,7 +324,7 @@ function chat_get_latest_message($chatid, $groupid=0) {
     }
 
     if (!$rs = $db->Execute("SELECT *
-                               FROM {$CFG->prefix}chat_messages 
+                               FROM {$CFG->prefix}chat_messages
                               WHERE chatid = '$chatid' $groupselect
                            ORDER BY timestamp DESC LIMIT 1")) {
         return false;
@@ -373,7 +373,7 @@ function chat_delete_old_users() {
             $message->message = "exit";
             $message->system = 1;
             $message->timestamp = time();
-     
+
             if (!insert_record("chat_messages", $message)) {
                 error("Could not insert a chat message!");
             }
@@ -532,7 +532,7 @@ function chat_browser_detect($HTTP_USER_AGENT) {
  {
   $BPlatform = "Unknown";
  }
+
  $return["name"] = $BName;
  $return["version"] = $BVersion;
  $return["platform"] = $BPlatform;
@@ -600,92 +600,125 @@ function chat_display_version($version, $browser)
 }
 
 
-function chat_format_message($message, $courseid=0) {
-/// Given a message object full of information, this function 
-/// formats it appropriately into text and html, then 
-/// returns the formatted data.
-
-    global $CFG, $USER;
+function chat_format_message_manually($message, $courseid, $sender, $currentuserid, $language = NULL) {
+    global $CFG;
 
-    $output = new object;
+    $output = New stdClass;
+    $output->beep = false;   // by default
 
-    if (!$user = get_record("user", "id", $message->userid)) {
-        return "Error finding user id = $message->userid";
+    if(empty($language)) {
+        $language = current_language();
     }
 
-    $picture = print_user_picture($user->id, 0, $user->picture, false, true, false);
+    // Override the highest-ranking language variable from current_language() here
+    // And save it so we can restore it again afterwards
+
+    $oldcfglang = empty($CFG->courselang) ? NULL : $CFG->courselang;
+    $CFG->courselang = $language;
+
+    // Get some additional info now that the language has been correctly set
+
+    // But before that :-) let's override get_user_timezone() for this call... messy stuff...
+    $tz = ($sender->timezone == 99) ? $CFG->timezone : $sender->timezone;
+    $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz);
+
+    $message->picture = print_user_picture($sender->id, 0, $sender->picture, false, true, false);
     if ($courseid) {
-        $picture = "<a target=\"_new\" href=\"$CFG->wwwroot/user/view.php?id=$user->id&course=$courseid\">$picture</a>";
+        $message->picture = "<a target=\"_new\" href=\"$CFG->wwwroot/user/view.php?id=$sender->id&course=$courseid\">$picture</a>";
     }
 
-    $strtime = userdate($message->timestamp, get_string("strftimemessage", "chat"));
-
-    $output->beep = false;   // by default
+    // Start processing the message
 
-    $text = $message->message;
+    if(!empty($message->system)) {
+        // System event
+        $output->text = $message->strtime.': '.get_string('message'.$message->message, 'chat', fullname($sender));
+        $output->html  = '<table><tr><td style="vertical-align: top;">'.$message->picture.'</td><td>';
+        $output->html .= '<font size=2 color="#CCAAAA">'.$output->text.'</font></td></tr></table>';
 
-    if (!empty($message->system)) {             /// It's a system message
-        $output->text = get_string("message$text", "chat", fullname($user));
-        $output->text = "$strtime: $output->text";
-        $output->html  = "<table><tr><td valign=top>$picture</td><td>";
-        $output->html .= "<font size=2 color=\"#CCAAAA\">$output->text</font>";
-        $output->html .= "</td></tr></table>";
+        // Don't forget to reset the language before returning!!!
+        if(!empty($oldcfglang)) {
+            $CFG->courselang = $oldcfglang;
+        }
         return $output;
     }
 
+    // It's not a system event, so format it nicely
+
+    $text = $message->message;
     convert_urls_into_links($text);
     replace_smilies($text);
     $text = filter_text($text, $courseid);
 
-    if (substr($text, 0, 5) == "beep ") {          /// It's a beep!
+    // And now check for special cases
+
+    if (substr($text, 0, 5) == 'beep ') {
+        /// It's a beep!
         $beepwho = trim(substr($text, 5));
 
-        if ($beepwho == "all") {   // everyone
-            $outinfo = "$strtime: ". get_string("messagebeepseveryone", "chat", fullname($user));
-            $outmain = "";
-            $output->beep = true;  // (eventually this should be set to 
+        if ($beepwho == 'all') {   // everyone
+            $outinfo = $message->strtime.': '.get_string('messagebeepseveryone', 'chat', fullname($sender));
+            $outmain = '';
+            $output->beep = true;  // (eventually this should be set to
                                    //  to a filename uploaded by the user)
 
-        } else if ($beepwho == $USER->id) {  // current user
-            $outinfo = "$strtime: ". get_string("messagebeepsyou", "chat", fullname($user));
-            $outmain = "";
+        } else if ($beepwho == $currentuserid) {  // current user
+            $outinfo = $message->strtime.': '.get_string('messagebeepsyou', 'chat', fullname($sender));
+            $outmain = '';
             $output->beep = true;
 
         } else {
             return false;
         }
+    } else if (substr($text, 0, 1) == ':') {              /// It's an MOO emote
+        $outinfo = $message->strtime;
+        $outmain = $sender->firstname.' '.substr($text, 1);
 
-    } else if (substr($text, 0, 1) == ":") {              /// It's an MOO emote
-        $outinfo = $strtime;
-        $outmain = "$user->firstname ".substr($text, 1);
-
-    } else if (substr($text, 0, 1) == "/") {     /// It's a user command
+    } else if (substr($text, 0, 1) == '/') {     /// It's a user command
 
         if (substr($text, 0, 4) == "/me ") {
-            $outinfo = $strtime;
-            $outmain = "$user->firstname ".substr($text, 4);
+            $outinfo = $message->strtime;
+            $outmain = $sender->firstname.' '.substr($text, 4);
         } else {
-            $outinfo = $strtime;
+            $outinfo = $message->strtime;
             $outmain = $text;
         }
 
     } else {                                          /// It's a normal message
-        $outinfo = "$strtime $user->firstname";
+        $outinfo = $message->strtime.' '.$sender->firstname;
         $outmain = $text;
     }
 
     /// Format the message as a small table
 
-    $output->text  = strip_tags("$outinfo: $outmain");
+    $output->text  = strip_tags($outinfo.': '.$outmain);
 
-    $output->html  = "<table><tr><td valign=top>$picture</td><td><font size=2>";
+    $output->html  = "<table><tr><td valign=top>$message->picture</td><td><font size=2>";
     $output->html .= "<font color=\"#888888\">$outinfo</font>";
     if ($outmain) {
         $output->html .= ": $outmain";
     }
     $output->html .= "</font></td></tr></table>";
 
+    // Don't forget to reset the language before returning!!!
+    if(!empty($oldcfglang)) {
+        $CFG->courselang = $oldcfglang;
+    }
+
     return $output;
+}
+
+function chat_format_message($message, $courseid=0) {
+/// Given a message object full of information, this function
+/// formats it appropriately into text and html, then
+/// returns the formatted data.
+
+    global $CFG, $USER;
+
+    if (!$user = get_record("user", "id", $message->userid)) {
+        return "Error finding user id = $message->userid";
+    }
+
+    return chat_format_message_manually($message, $courseid, $user, $USER->id);
 
 }