Index: chatd.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/chat/chatd.php,v
retrieving revision 1.32.4.2
diff -c -r1.32.4.2 chatd.php
*** chatd.php	1 May 2008 08:31:20 -0000	1.32.4.2
--- chatd.php	6 May 2008 05:31:06 -0000
***************
*** 1,9 ****
  #!/usr/bin/php -q
  <?php
  
  // Browser quirks
  define('QUIRK_CHUNK_UPDATE', 0x0001);
! 
  // Connection telltale
  define('CHAT_CONNECTION',           0x10);
  // Connections: Incrementing sequence, 0x10 to 0x1f
--- 1,12 ----
  #!/usr/bin/php -q
  <?php
+ error_reporting(E_ALL);
+ @set_time_limit (0);
+ set_magic_quotes_runtime(0);
  
  // Browser quirks
  define('QUIRK_CHUNK_UPDATE', 0x0001);
! define('QUIRK_CONTINUOUS_UPDATE', 0x0010);
  // Connection telltale
  define('CHAT_CONNECTION',           0x10);
  // Connections: Incrementing sequence, 0x10 to 0x1f
***************
*** 17,38 ****
  define('CHAT_SIDEKICK_BEEP',        0x23);
  
  $phpversion = phpversion();
  echo 'Moodle chat daemon v1.0 on PHP '.$phpversion." (\$Id: chatd.php,v 1.32.4.2 2008/05/01 08:31:20 dongsheng Exp $)\n\n";
  
  /// Set up all the variables we need   /////////////////////////////////////
  
  /// $CFG variables are now defined in database by chat/lib.php
- 
- $_SERVER['PHP_SELF']        = 'dummy';
  $_SERVER['SERVER_NAME']     = 'dummy';
  $_SERVER['HTTP_USER_AGENT'] = 'dummy';
  
  $nomoodlecookie = true;
  
  include('../../config.php');
  include('lib.php');
  
! $_SERVER['SERVER_NAME'] = $CFG->chat_serverhost;
  $_SERVER['PHP_SELF']    = "http://$CFG->chat_serverhost:$CFG->chat_serverport/mod/chat/chatd.php";
  
  $safemode = ini_get('safe_mode');
--- 20,45 ----
  define('CHAT_SIDEKICK_BEEP',        0x23);
  
  $phpversion = phpversion();
+ 
  echo 'Moodle chat daemon v1.0 on PHP '.$phpversion." (\$Id: chatd.php,v 1.32.4.2 2008/05/01 08:31:20 dongsheng Exp $)\n\n";
  
  /// Set up all the variables we need   /////////////////////////////////////
  
  /// $CFG variables are now defined in database by chat/lib.php
  $_SERVER['SERVER_NAME']     = 'dummy';
  $_SERVER['HTTP_USER_AGENT'] = 'dummy';
+ $_SERVER['SERVER_NAME'] = $CFG->chat_serverhost;
+ unset($argv[0]);
+ $params = getCommandlineParameters();
+ if(isset($params['servername']))
+     $_SERVER['SERVER_NAME'] = $params['servername'];
  
  $nomoodlecookie = true;
  
  include('../../config.php');
  include('lib.php');
  
! $CFG->inchat = true;
  $_SERVER['PHP_SELF']    = "http://$CFG->chat_serverhost:$CFG->chat_serverport/mod/chat/chatd.php";
  
  $safemode = ini_get('safe_mode');
***************
*** 49,58 ****
      die("Error: Cannot run with PHP allow_call_time_pass_reference = Off. Turn on allow_call_time_pass_reference in php.ini.\n");
  }
  
- @set_time_limit (0);
- set_magic_quotes_runtime(0);
- error_reporting(E_ALL);
- 
  function chat_empty_connection() {
      return array('sid' => NULL, 'handle' => NULL, 'ip' => NULL, 'port' => NULL, 'groupid' => NULL);
  }
--- 56,61 ----
***************
*** 72,78 ****
  
      function ChatConnection($resource) {
          $this->handle = $resource;
!         @socket_getpeername($this->handle, &$this->ip, &$this->port);
      }
  }
  
--- 75,81 ----
  
      function ChatConnection($resource) {
          $this->handle = $resource;
!         @socket_getpeername($this->handle, $this->ip, $this->port);
      }
  }
  
***************
*** 96,108 ****
      //            Pay extra attention when you write code that affects any of them!
  
      function ChatDaemon() {
!         $this->_trace_level         = E_ALL ^ E_USER_NOTICE;
          $this->_pcntl_exists        = function_exists('pcntl_fork');
          $this->_time_rest_socket    = 20;
!         $this->_beepsoundsrc        = $GLOBALS['CFG']->wwwroot.'/mod/chat/beep.wav';
          $this->_freq_update_records = 20;
!         $this->_freq_poll_idle_chat = $GLOBALS['CFG']->chat_old_ping;
          $this->_stdout = fopen('php://stdout', 'w');
          if($this->_stdout) {
              // Avoid double traces for everything
              $this->_trace_to_console = false;
--- 99,127 ----
      //            Pay extra attention when you write code that affects any of them!
  
      function ChatDaemon() {
!         global $CFG;
!         $this->_trace_level         = E_ALL;
          $this->_pcntl_exists        = function_exists('pcntl_fork');
          $this->_time_rest_socket    = 20;
!         $this->_beepsoundsrc        = $CFG->wwwroot.'/mod/chat/beep.wav';
          $this->_freq_update_records = 20;
!         $this->_freq_poll_idle_chat = $CFG->chat_old_ping;
!         $this->_freq_poll_db_users = 10;
!         $this->_last_poll_db_users = 0;
!         $this->_freq_poll_db_messages = 1;
!         $this->_last_poll_db_messages = 0;
!         $this->_freq_poll_db_messages_nousers = 5;
!         $this->MAX_SOCKET_READ_DATA = 20480;
!         $this->CHAT_DUMMY_DATA_CONTINUOUS = "\n";
!         $this->MAX_CONTINUOUS_DUMMY_UPDATES = 5; //firefox fix.
!         $this->MAX_CONTINUOUS_DUMMY_BYTES = 1024;
!         $this->_freq_continuous_dummy_updates = 100; //number of main loops (~ $this->_time_rest_socket each)
!         $this->_timer_continuous_dummy_updates = 0;
!         $this->_logfile_name = $CFG->dataroot.'/chatd.log';
! 
          $this->_stdout = fopen('php://stdout', 'w');
+         $this->db_users = array();
+ 
          if($this->_stdout) {
              // Avoid double traces for everything
              $this->_trace_to_console = false;
***************
*** 112,118 ****
      function error_handler ($errno, $errmsg, $filename, $linenum, $vars) {
          // Checks if an error needs to be suppressed due to @
          if(error_reporting() != 0) {
!             $this->trace($errmsg.' on line '.$linenum, $errno);
          }
          return true;
      }
--- 131,137 ----
      function error_handler ($errno, $errmsg, $filename, $linenum, $vars) {
          // Checks if an error needs to be suppressed due to @
          if(error_reporting() != 0) {
!             $this->trace("$errmsg on $filename line $linenum", $errno);
          }
          return true;
      }
***************
*** 221,231 ****
          }
          return true;
      }
! 
      function get_user_window($sessionid) {
- 
          global $CFG;
- 
          static $str;
  
          $info = &$this->sets_info[$sessionid];
--- 240,248 ----
          }
          return true;
      }
!     // This function return the code of user list
      function get_user_window($sessionid) {
          global $CFG;
          static $str;
  
          $info = &$this->sets_info[$sessionid];
***************
*** 253,273 ****
          echo "//<![CDATA[\n";
  
          echo 'function openpopup(url,name,options,fullscreen) {';
!         echo 'fullurl = "'.$CFG->wwwroot.'" + url;';
!         echo 'windowobj = window.open(fullurl,name,options);';
!         echo 'if (fullscreen) {';
!         echo '  windowobj.moveTo(0,0);';
!         echo '  windowobj.resizeTo(screen.availWidth,screen.availHeight); ';
!         echo '}';
!         echo 'windowobj.focus();';
!         echo 'return false;';
          echo "}\n//]]>\n";
!         echo '</script></head><body style="font-face: serif;" bgcolor="#FFFFFF">';
! 
!         echo '<table style="width: 100%;"><tbody>';
  
          // Get the users from that chatroom
          $users = $this->chatrooms[$info['chatid']]['users'];
  
          foreach ($users as $usersessionid => $userid) {
              // Fetch each user's sessionid and then the rest of his data from $this->sets_info
--- 270,292 ----
          echo "//<![CDATA[\n";
  
          echo 'function openpopup(url,name,options,fullscreen) {';
!         echo '  fullurl = "'.$CFG->wwwroot.'" + url;';
!         echo '  windowobj = window.open(fullurl,name,options);';
!         echo '  if (fullscreen) {';
!         echo '    windowobj.moveTo(0,0);';
!         echo '    windowobj.resizeTo(screen.availWidth,screen.availHeight); ';
!         echo '  }';
!         echo '  windowobj.focus();';
!         echo '  return false;';
          echo "}\n//]]>\n";
!         echo '</script></head><body>';
  
          // Get the users from that chatroom
          $users = $this->chatrooms[$info['chatid']]['users'];
+         $users = array_merge($this->chatrooms[$info['chatid']]['users'], $this->db_users[$info['chatid']]);
+         echo '<div>'.sizeof($users).get_string('activeusers').'</div>';
+ 
+         echo '<table style="width: 100%;"><tbody>';
  
          foreach ($users as $usersessionid => $userid) {
              // Fetch each user's sessionid and then the rest of his data from $this->sets_info
***************
*** 279,290 ****
              echo '<a target="_new" onclick="return openpopup('.$popuppar.');" href="'.$CFG->wwwroot.'/user/view.php?id='.$userinfo['chatuser']->id.'&amp;course='.$userinfo['courseid'].'">';
              print_user_picture($userinfo['user']->id, 0, $userinfo['user']->picture, false, false, false);
              echo "</a></td><td valign=\"center\">";
!             echo "<p><font size=\"1\">";
!             echo fullname($userinfo['user'])."<br />";
!             echo "<font color=\"#888888\">$str->idle: ".format_time($lastping, $str)."</font> ";
              echo '<a target="empty" href="http://'.$CFG->chat_serverhost.':'.$CFG->chat_serverport.'/?win=beep&amp;beep='.$userinfo['user']->id.
                   '&chat_sid='.$sessionid.'">'.$str->beep."</a>\n";
!             echo "</font></p>";
              echo "<td></tr>";
          }
  
--- 298,309 ----
              echo '<a target="_new" onclick="return openpopup('.$popuppar.');" href="'.$CFG->wwwroot.'/user/view.php?id='.$userinfo['chatuser']->id.'&amp;course='.$userinfo['courseid'].'">';
              print_user_picture($userinfo['user']->id, 0, $userinfo['user']->picture, false, false, false);
              echo "</a></td><td valign=\"center\">";
!             echo "<p>";
!             echo "<p>".fullname($userinfo['user'])."</p>";
!             echo "<span class='chat_username'>$str->idle: ".format_time($lastping, $str)."</span> ";
              echo '<a target="empty" href="http://'.$CFG->chat_serverhost.':'.$CFG->chat_serverport.'/?win=beep&amp;beep='.$userinfo['user']->id.
                   '&chat_sid='.$sessionid.'">'.$str->beep."</a>\n";
!             echo "</p>";
              echo "<td></tr>";
          }
  
***************
*** 324,331 ****
  
          switch($type) {
              case CHAT_SIDEKICK_BEEP:
                  // Incoming beep
!                 $msg = &New stdClass;
                  $msg->chatid    = $this->sets_info[$sessionid]['chatid'];
                  $msg->userid    = $this->sets_info[$sessionid]['userid'];
                  $msg->groupid   = $this->sets_info[$sessionid]['groupid'];
--- 343,352 ----
  
          switch($type) {
              case CHAT_SIDEKICK_BEEP:
+                 if(!isset($this->sets_info[$sessionid]))
+                     return;
                  // Incoming beep
!                 $msg = &new stdClass;
                  $msg->chatid    = $this->sets_info[$sessionid]['chatid'];
                  $msg->userid    = $this->sets_info[$sessionid]['userid'];
                  $msg->groupid   = $this->sets_info[$sessionid]['groupid'];
***************
*** 424,437 ****
                  }
  
                  // A slight hack to prevent malformed SQL inserts
!                 $origmsg = $msg->message;
!                 $msg->message = addslashes($msg->message);
  
                  // Commit to DB
                  insert_record('chat_messages', $msg, false);
  
                  // Undo the hack
!                 $msg->message = $origmsg;
  
                  // OK, now push it out to all users
                  $this->message_broadcast($msg, $this->sets_info[$sessionid]['user']);
--- 445,458 ----
                  }
  
                  // A slight hack to prevent malformed SQL inserts
!                 // $origmsg = $msg->message;
!                 // $msg->message = addslashes($msg->message);
  
                  // Commit to DB
                  insert_record('chat_messages', $msg, false);
  
                  // Undo the hack
!                 // $msg->message = $origmsg;
  
                  // OK, now push it out to all users
                  $this->message_broadcast($msg, $this->sets_info[$sessionid]['user']);
***************
*** 457,462 ****
--- 478,485 ----
  
                  // That's enough headers for one lousy dummy response
                  $this->write_data($handle, $header);
+                 $this->sets_info[$sessionid]['numDummyBytes'] = 0;
+                 $this->sets_info[$sessionid]['numDummyUpdates'] = 0;
  
                  // All done
              break;
***************
*** 467,472 ****
--- 490,497 ----
      }
  
      function promote_final($sessionid, $customdata) {
+         global $CHAT_HTMLHEAD_JS, $CFG;
+ 
          if(isset($this->conn_sets[$sessionid])) {
              $this->trace('Set cannot be finalized: Session '.$sessionid.' is already active');
              return false;
***************
*** 487,500 ****
              $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, $CFG;
  
          $this->conn_sets[$sessionid] = $this->conn_half[$sessionid];
  
--- 512,531 ----
              $this->dismiss_half($sessionid);
              return false;
          }
+         
+         // get user picture here
+         $user->chat_show_pictures =
+             get_user_preferences('chat_show_pictures', 'yes', $user->id);
+         $user->chat_show_enterexit =
+             get_user_preferences('chat_show_enterexit', 'yes', $user->id);
+ 
          $course = get_record('course', 'id', $chat->course); {
!         if($course === false) {
              $this->dismiss_half($sessionid);
              return false;
              }
          }
  
  
          $this->conn_sets[$sessionid] = $this->conn_half[$sessionid];
  
***************
*** 511,522 ****
              'userid'    => $user->id,
              'groupid'   => $chatuser->groupid,
              'lang'      => $chatuser->lang,
!             'quirks'    => $customdata['quirks']
          );
  
          // If we know nothing about this chatroom, initialize it and add the user
          if(!isset($this->chatrooms[$chat->id]['users'])) {
              $this->chatrooms[$chat->id]['users'] = array($sessionid => $user->id);
          }
          else {
              // Otherwise just add the user
--- 542,557 ----
              'userid'    => $user->id,
              'groupid'   => $chatuser->groupid,
              'lang'      => $chatuser->lang,
!             'quirks'    => $customdata['quirks'],
!             'numDummyBytes' => 0,
!             'numDummyUpdates' => 0
          );
  
          // If we know nothing about this chatroom, initialize it and add the user
          if(!isset($this->chatrooms[$chat->id]['users'])) {
              $this->chatrooms[$chat->id]['users'] = array($sessionid => $user->id);
+             $this->db_users[$chat->id] = array();
+             $this->poll_db_users();
          }
          else {
              // Otherwise just add the user
***************
*** 691,698 ****
--- 726,753 ----
  
          return $retval;
      }
+     function continuous_dummy_broadcast(){
+         if(empty($this->conn_sets)) {
+             return true;
+         }
+         foreach($this->sets_info as $sessionid => $info) {
+             // We need to get handles from users that are in the same chatroom, same group
+             if(($info['quirks'] & QUIRK_CONTINUOUS_UPDATE) && $info['numDummyBytes'] < $this->MAX_CONTINUOUS_DUMMY_BYTES && $info['numDummyUpdates'] < $this->MAX_CONTINUOUS_DUMMY_UPDATES)
+             {
+                 $this->sets_info[$sessionid]['numDummyBytes'] += strlen($this->CHAT_DUMMY_DATA_CONTINUOUS);
+                 $this->sets_info[$sessionid]['numDummyUpdates'] += 1;
+ 
+                 if(!$this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $this->CHAT_DUMMY_DATA_CONTINUOUS)) {
+                     $this->disconnect_session($sessionid);
+                 }
+                 else
+                     $this->trace('Sent to UID '.$this->sets_info[$sessionid]['userid'].': {{CHAT_DUMMY_DATA_CONTINUOUS}}', E_USER_NOTICE);
+             }
+         }
+     }
  
      function message_broadcast($message, $sender) {
+         global $CFG;
          if(empty($this->conn_sets)) {
              return true;
          }
***************
*** 700,706 ****
          $now = time();
  
          // First of all, mark this chatroom as having had activity now
!         $this->chatrooms[$message->chatid]['lastactivity'] = $now;
  
          foreach($this->sets_info as $sessionid => $info) {
              // We need to get handles from users that are in the same chatroom, same group
--- 755,765 ----
          $now = time();
  
          // First of all, mark this chatroom as having had activity now
!         if(!isset($this->chatrooms[$message->chatid]['lastactivity']))
!             $this->chatrooms[$message->chatid]['lastactivity'] = $now;
!         else
!             $this->chatrooms[$message->chatid]['lastactivity'] = 
!                 max($now,$this->chatrooms[$message->chatid]['lastactivity']);
  
          foreach($this->sets_info as $sessionid => $info) {
              // We need to get handles from users that are in the same chatroom, same group
***************
*** 710,730 ****
  
                  // Simply give them the message
                  course_setup($info['course'], $info['user']);
                  $output = chat_format_message_manually($message, $info['courseid'], $sender, $info['user']);
                  $this->trace('Delivering message "'.$output->text.'" to '.$this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL]);
  
                  if($output->beep) {
                      $this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], '<embed src="'.$this->_beepsoundsrc.'" autostart="true" hidden="true" />');
                  }
! 
!                 if($info['quirks'] & QUIRK_CHUNK_UPDATE) {
!                     $output->html .= $GLOBALS['CHAT_DUMMY_DATA'];
!                     $output->html .= $GLOBALS['CHAT_DUMMY_DATA'];
!                     $output->html .= $GLOBALS['CHAT_DUMMY_DATA'];
                  }
  
!                 if(!$this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $output->html)) {
                      $this->disconnect_session($sessionid);
                  }
                  //$this->trace('Sent to UID '.$this->sets_info[$sessionid]['userid'].': '.$message->text_);
              }
--- 769,798 ----
  
                  // Simply give them the message
                  course_setup($info['course'], $info['user']);
+                 $CFG->chat_showpictures =
+                     $info['user']->chat_show_pictures;
                  $output = chat_format_message_manually($message, $info['courseid'], $sender, $info['user']);
+                 if($message->system &&
+                         $info['user']->chat_show_enterexit != 'yes')
+                     continue;
                  $this->trace('Delivering message "'.$output->text.'" to '.$this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL]);
  
                  if($output->beep) {
                      $this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], '<embed src="'.$this->_beepsoundsrc.'" autostart="true" hidden="true" />');
                  }
!  
!                 if($info['quirks'] &  QUIRK_CHUNK_UPDATE) {
!                     global $CHAT_DUMMY_DATA;
!                     $output->html .= $CHAT_DUMMY_DATA;
                  }
+                 $this->sets_info[$sessionid]['numDummyBytes'] = 0;
+                 $this->sets_info[$sessionid]['numDummyUpdates'] = 0;
  
!                 if(!$this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL],
!                             stripslashes($output->html))) {
                      $this->disconnect_session($sessionid);
+                 }else{
+                     $this->trace('Sent to UID '.$this->sets_info[$sessionid]['userid'].': '.$output->text, E_USER_NOTICE); 
                  }
                  //$this->trace('Sent to UID '.$this->sets_info[$sessionid]['userid'].': '.$message->text_);
              }
***************
*** 802,807 ****
--- 870,877 ----
  
      function cli_switch($switch, $param = NULL) {
          switch($switch) { //LOL
+             case 'servername':
+                 return false;
              case 'reset':
                  // Reset sockets
                  $this->_resetsocket = true;
***************
*** 833,886 ****
          }
          return false;
      }
  
  }
  
  $DAEMON = New ChatDaemon;
  set_error_handler(array($DAEMON, 'error_handler'));
  
  /// Check the parameters //////////////////////////////////////////////////////
! 
! unset($argv[0]);
! $commandline = implode(' ', $argv);
! if(strpos($commandline, '-') === false) {
!     if(!empty($commandline)) {
!         // We cannot have received any meaningful parameters
!         $DAEMON->fatal('Garbage in command line');
      }
! }
! else {
!     // Parse command line
!     $switches = preg_split('/(-{1,2}[a-zA-Z]+) */', $commandline, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
! 
!     // Taking advantage of the fact that $switches is indexed with incrementing numeric keys
!     // We will be using that to pass additional information to those switches who need it
!     $numswitches = count($switches);
! 
!     // Fancy way to give a "hyphen" boolean flag to each "switch"
!     $switches = array_map(create_function('$x', 'return array("str" => $x, "hyphen" => (substr($x, 0, 1) == "-"));'), $switches);
! 
!     for($i = 0; $i < $numswitches; ++$i) {
! 
!         $switch = $switches[$i]['str'];
!         $params = ($i == $numswitches - 1 ? NULL :
!                                             ($switches[$i + 1]['hyphen'] ? NULL : trim($switches[$i + 1]['str']))
!                   );
! 
!         if(substr($switch, 0, 2) == '--') {
!             // Double-hyphen switch
!             $DAEMON->cli_switch(strtolower(substr($switch, 2)), $params);
!         }
!         else if(substr($switch, 0, 1) == '-') {
!             // Single-hyphen switch(es), may be more than one run together
!             $switch = substr($switch, 1); // Get rid of the -
!             $len = strlen($switch);
!             for($j = 0; $j < $len; ++$j) {
!                 $DAEMON->cli_switch(strtolower(substr($switch, $j, 1)), $params);
              }
          }
      }
  }
  
  if(!$DAEMON->query_start()) {
      // For some reason we didn't start, so print out some info
--- 903,1031 ----
          }
          return false;
      }
+     
+     function poll_db_messages($now){
+         foreach($this->chatrooms as $roomid=>$room){
+             if(!isset($this->chatrooms[$roomid]['lastactivity']))
+                 $this->chatrooms[$roomid]['lastactivity'] = 0;
+             if(!sizeof($room['users']))
+                 continue;
+             if(!sizeof($this->db_users[$roomid]) && ($now - $this->_last_poll_db_users < $this->_freq_poll_db_messages_nousers))
+                 continue;
+ //            echo "."; fflush($this->_stdout);
+             $sessionids = array_keys($room['users']);
+             $set = $this->sets_info[$sessionids[0]];
+             if(!isset($room['lastactivity']))
+                 $room['lastactivity'] = 0;
+             $messages = get_records_select('chat_messages', "timestamp>$room[lastactivity] AND chatid='$set[chatid]'"/* AND groupid=$set[groupid]"*/, "timestamp asc");
+             if($messages && sizeof($messages)){
+                 $messageids = array_keys($messages);
+                 $lastmessageid = $messageids[sizeof($messageids)-1];
+                 $this->chatrooms[$roomid]['lastactivity'] = max($this->chatrooms[$roomid]['lastactivity'],$messages[$lastmessageid]->timestamp);
+                 foreach($messages as $m){
+                     //if($m->system)
+                     //    return;
+                     // OK, now push it out to all users
+                     $this->message_broadcast($m, get_record('user','id',$m->userid));
+ //                    echo "broadcasting message $m->message...\n";
+                 }
+             }
+         }
+     }
  
+     function poll_db_users(){
+         chat_delete_old_users();
+         foreach($this->chatrooms as $roomid=>$room){
+             if(!sizeof($room['users']))
+                 continue;
+             $sessionids = array_keys($room['users']);
+             $set = $this->sets_info[$sessionids[0]];
+             $users = get_records_select('chat_users', "chatid='$set[chatid]'"/* AND groupid=$set[groupid]"*/, "lastmessageping desc");
+             $nondaemonusers = array();
+             $nondaemonsids = array();
+             if($users && sizeof($users)){
+                 $userids = array_keys($users);
+                 foreach($users as $u){
+                     if(!in_array($u->sid, $sessionids)){
+                         $nondaemonusers[] = $u;
+                         $nondaemonsids[] = $u->sid;
+                     }
+                 }
+             }
+             //remove users no longer in db.
+             if(isset($this->db_users[$roomid])){
+                 foreach($this->db_users[$roomid] as $sid=>$u){
+                     if(!in_array($sid,$nondaemonsids))
+                         unset($this->db_users[$roomid][$sid]);
+                 }
+             }
+             foreach($nondaemonusers as $u){
+                 if(!isset($this->db_users[$roomid][$u->sid]))
+                     $this->db_users[$roomid][$u->sid]['user'] = get_record('user','id',$u->userid);
+                 $this->db_users[$roomid][$u->sid]['chatuser'] = $u;
+             }
+         }
+     }
  }
  
  $DAEMON = New ChatDaemon;
  set_error_handler(array($DAEMON, 'error_handler'));
  
  /// Check the parameters //////////////////////////////////////////////////////
! function getCommandlineParameters($DAEMON=NULL){
!     global $argv;
!     $ret = array();
!     /// Check the parameters //////////////////////////////////////////////////////
!     $commandline = implode(' ', $argv);
!     if(strpos($commandline, '-') === false) {
!         if(!empty($commandline)) {
!             // We cannot have received any meaningful parameters
!             if($DAEMON)
!                 $DAEMON->fatal('Garbage in command line');
!             else
!                 echo 'Garbage in command line';
!         }
      }
!     else {
!         // Parse command line
!         $switches = preg_split('/(-{1,2}[a-zA-Z]+) */', $commandline, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
!         // Taking advantage of the fact that $switches is indexed with incrementing numeric keys
!         // We will be using that to pass additional information to those switches who need it
!         $numswitches = count($switches);
! 
!         // Fancy way to give a "hyphen" boolean flag to each "switch"
!         $switches = array_map(create_function('$x', 'return array("str" => $x, "hyphen" => (substr($x, 0, 1) == "-"));'), $switches);
!         for($i = 0; $i < $numswitches; ++$i) {
!             $switch = $switches[$i]['str'];
!             $params = ($i == $numswitches - 1 ? NULL : 
!                     ($switches[$i + 1]['hyphen'] ? NULL : trim($switches[$i + 1]['str']))
!                 );
!             if(substr($switch, 0, 2) == '--') {
!                 // Double-hyphen switch
!                 if($DAEMON)
!                     $DAEMON->cli_switch(strtolower(substr($switch, 2)), $params);
!                 else
!                     $ret[strtolower(substr($switch, 2))] = $params;
!             }
!             else if(substr($switch, 0, 1) == '-') {
!                 // Single-hyphen switch(es), may be more than one run together
!                 $switch = substr($switch, 1); // Get rid of the -
!                 $len = strlen($switch);
!                 for($j = 0; $j < $len; ++$j) {
!                     if($DAEMON)
!                         $DAEMON->cli_switch(strtolower(substr($switch, $j, 1)), $params);
!                     else
!                         $ret[strtolower(substr($switch, $j, 1))] = $params;
!                 }
              }
          }
      }
+     if(!sizeof($ret) && $DAEMON)
+         $DAEMON->cli_switch('start','');
+     return $ret;
  }
+   
+ getCommandlineParameters($DAEMON);
  
  if(!$DAEMON->query_start()) {
      // For some reason we didn't start, so print out some info
***************
*** 970,982 ****
  
              if($changed > 0) {
                  // Let's see what it has to say
! 
!                 $data = socket_read($handle, 2048); // should be more than 512 to prevent empty pages and repeated messages!!
                  if(empty($data)) {
                      continue;
                  }
  
!                 if (strlen($data) == 2048) { // socket_read has more data, ignore all data
                      $DAEMON->trace('UFO with '.$handle.': Data too long; connection closed', E_USER_WARNING);
                      $DAEMON->dismiss_ufo($handle, true, 'Data too long; connection closed');
                      continue;
--- 1115,1126 ----
  
              if($changed > 0) {
                  // Let's see what it has to say
!                 $data = socket_read($handle, $DAEMON->MAX_SOCKET_READ_DATA); // should be more than 512 to prevent empty pages and repeated messages!!
                  if(empty($data)) {
                      continue;
                  }
  
!                 if (strlen($data) == $DAEMON->MAX_SOCKET_READ_DATA) { // socket_read has more data, ignore all data
                      $DAEMON->trace('UFO with '.$handle.': Data too long; connection closed', E_USER_WARNING);
                      $DAEMON->dismiss_ufo($handle, true, 'Data too long; connection closed');
                      continue;
***************
*** 984,990 ****
  
                  if(!ereg('win=(chat|users|message|beep).*&chat_sid=([a-zA-Z0-9]*) HTTP', $data, $info)) {
                      // Malformed data
!                     $DAEMON->trace('UFO with '.$handle.': Request with malformed data; connection closed', E_USER_WARNING);
                      $DAEMON->dismiss_ufo($handle, true, 'Request with malformed data; connection closed');
                      continue;
                  }
--- 1128,1134 ----
  
                  if(!ereg('win=(chat|users|message|beep).*&chat_sid=([a-zA-Z0-9]*) HTTP', $data, $info)) {
                      // Malformed data
!                     $DAEMON->trace('UFO with '.$handle.": Request with malformed data ($data); connection closed", E_USER_WARNING);
                      $DAEMON->dismiss_ufo($handle, true, 'Request with malformed data; connection closed');
                      continue;
                  }
***************
*** 999,1007 ****
                         $type = CHAT_CONNECTION_CHANNEL;
                          $customdata['quirks'] = 0;
                          if(strpos($data, 'Safari')) {
!                             $DAEMON->trace('Safari identified...', E_USER_WARNING);
                              $customdata['quirks'] += QUIRK_CHUNK_UPDATE;
!                         }
                      break;
                      case 'users':
                          $type = CHAT_SIDEKICK_USERS;
--- 1143,1154 ----
                         $type = CHAT_CONNECTION_CHANNEL;
                          $customdata['quirks'] = 0;
                          if(strpos($data, 'Safari')) {
!                             $DAEMON->trace('Safari identified...');
                              $customdata['quirks'] += QUIRK_CHUNK_UPDATE;
!                         }elseif(strpos($data,'User-Agent: Mozilla')){
!                             $DAEMON->trace('Mozilla identified...');
!                             $customdata['quirks'] += QUIRK_CONTINUOUS_UPDATE;
!                         } 
                      break;
                      case 'users':
                          $type = CHAT_SIDEKICK_USERS;
***************
*** 1043,1053 ****
--- 1190,1214 ----
      }
  
      $now = time();
+     if($now - $DAEMON->_last_poll_db_users >= $DAEMON->_freq_poll_db_users){
+         $DAEMON->poll_db_users();
+         $DAEMON->_last_poll_db_users = $now;
+     }
+     if($now - $DAEMON->_last_poll_db_messages >= $DAEMON->_freq_poll_db_messages){
+         $DAEMON->poll_db_messages($now);
+         $DAEMON->_last_poll_db_messages = $now;
+     }
  
      // Clean up chatrooms with no activity as required
      if($now - $DAEMON->_last_idle_poll >= $DAEMON->_freq_poll_idle_chat) {
          $DAEMON->poll_idle_chats($now);
      }
+     if($DAEMON->_timer_continuous_dummy_updates >= $DAEMON->_freq_continuous_dummy_updates){
+         $DAEMON->continuous_dummy_broadcast();
+         $DAEMON->_timer_continuous_dummy_updates = 0;
+     } else {
+         $DAEMON->_timer_continuous_dummy_updates += 1;
+     }
  
      // Finally, accept new connections
      $DAEMON->conn_accept();

