a removeChild block opera on iframe stream, removed
[brisk.git] / web / Obj / brisk.phh
index 000722b..f38b504 100644 (file)
@@ -2,7 +2,7 @@
 /*
  *  brisk - brisk.phh
  *
- *  Copyright (C) 2006-2011 Matteo Nastasi
+ *  Copyright (C) 2006-2012 Matteo Nastasi
  *                          mailto: nastasi@alternativeoutput.it 
  *                                  matteo.nastasi@milug.org
  *                          web: http://www.alternativeoutput.it
@@ -45,9 +45,13 @@ define('COMM_GEN_N', 50);
 
 define('CHAT_N', 3);
 define('CHAT_ILL_TIME', 6);
+define('CHAT_ENABLED', TRUE);
 
 define('SESS_LEN', 13);
 define('STREAM_TIMEOUT', 60);
+/* FIXME: move to sac-a-push .phh */
+/* TIME_RD define the server-side timeout, after half of it a ping request
+   is sent to client, after this time the client is log out */
 define('EXPIRE_TIME_RD', 180);
 define('EXPIRE_TIME_SMAMMA', 360);
 define('EXPIRE_TIME_WAG', 10);
@@ -136,10 +140,10 @@ $mlang_brisk = array( 'btn_backstand'=> array( 'it' => 'torna in piedi',
 $G_lng = langtolng($G_lang);
 
 $G_all_points = array( 11,10,4,3,2, 0,0,0,0,0 );
-$G_brisk_version = "3.6.3";
+$G_brisk_version = "4.3.0";
 
 /* MLANG: ALL THE INFO STRINGS IN brisk.phh */
-$root_wellarr = array( 'it' => array ( 'Brisk (Ver. '.$G_brisk_version.'), <b>NOVITA\'</b>: nuovo sistema di evidenziazione degli utenti registrati.',
+$root_wellarr = array( 'it' => array ( 'Brisk (Ver. '.$G_brisk_version.'), <b>NOVITA\'</b>: adottato sac-a-push come motore per l\'invio dei dati in tempo reale, nuovo trasporto httpfile per explorer, tanti bug fixati, freeze su disco, fix del calcolo dei punti, nuovo stream dati xhr.',
                                        'Se vuoi iscriverti alla <a target="_blank" href="mailto:ml-briscola+subscribe@milug.org">Mailing List</a>, cliccala!' ),
                        'en' => array ( 'Brisk (Ver. '.$G_brisk_version.'), <b>NEWS</b>: usage of reader/writer locking instead of generic exclusive locking.',
                                        'If you want to subscribe our <a target="_blank" href="ml-briscola+subscribe@milug.org">Mailing List</a>, click it!' ) );
@@ -282,7 +286,7 @@ Copyright 2006-2012 <a href=\\"mailto:brisk@alternativeoutput.it\\">Matteo Nasta
   declaration briscola in ajax sauce <b>(Beta)</b>
 </div>
 <br><b>version '.$G_brisk_version.'</b><br><br>
-Copyright 2006-2009 <a href=\\"mailto:brisk@alternativeoutput.it\\">Matteo Nastasi</a> (aka mop)<br><br>');
+Copyright 2006-2012 <a href=\\"mailto:brisk@alternativeoutput.it\\">Matteo Nastasi</a> (aka mop)<br><br>');
 
 function mop_flush()
 {
@@ -292,6 +296,13 @@ function mop_flush()
     flush();
 }
 
+function force_no_cache(&$header_out)
+{
+    $header_out['Pragma'] = 'no-cache, must-revalidate';
+    $header_out['Cache-Control'] = 'no-cache';
+    $header_out['Expires'] = '-1';
+}
+
 function file_lock($fname, $is_exclusive)
 {
     if (($res = @fopen($fname, "r+")) == FALSE) {
@@ -661,45 +672,49 @@ class Table {
 
 
 
-class Room {
+class Room
+{
     static $delta_t;
-
-  var $user;
-  var $table;
-  var $comm; // commands for many people
-  var $step; // current step of the comm array
-  // externalized var $garbage_timeout;
-  var $shm_sz;
-
-  function Room () {
-    $this->user = array();
-    $this->table = array();
-
-    for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
-        $this->user[$i] = User::create($this, $i, "", "");
-    }
-
-    for ($i = 0 ; $i < TABLES_N ; $i++) {
-      $this->table[$i] = Table::create($i);
-      /* OLD METHOD
-      if ($i < 12) {
-        $row = ( (((int)($i / 4)) % 2) == 0 );
-        $col = ($i % 2 == 0);
-        $this->table[$i]->auth_only = (($row && $col) || (!$row && !$col));
-      }
-      else {
-        $this->table[$i]->auth_only = FALSE;
-      }
-      */
-      if ($i < TABLES_AUTH_N) 
-        $this->table[$i]->auth_only = TRUE;
-      else
-        $this->table[$i]->auth_only = FALSE;
+    
+    var $crystal_filename;
+    var $user;
+    var $table;
+    var $match;
+    var $comm; // commands for many people
+    var $step; // current step of the comm array
+    var $garbage_timeout;
+    var $shm_sz;
+    
+    function Room ($crystal_filename) {
+        $this->crystal_filename = $crystal_filename;
+        $this->user  = array();
+        $this->table = array();
+        $this->match = array();
+        
+        for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
+            $this->user[$i] = User::create($this, $i, "", "");
+        }
+        
+        for ($i = 0 ; $i < TABLES_N ; $i++) {
+            $this->table[$i] = Table::create($i);
+            /* OLD METHOD
+               if ($i < 12) {
+               $row = ( (((int)($i / 4)) % 2) == 0 );
+               $col = ($i % 2 == 0);
+               $this->table[$i]->auth_only = (($row && $col) || (!$row && !$col));
+               }
+               else {
+               $this->table[$i]->auth_only = FALSE;
+               }
+            */
+            if ($i < TABLES_AUTH_N) 
+                $this->table[$i]->auth_only = TRUE;
+            else
+                $this->table[$i]->auth_only = FALSE;
+        }
+        $this->garbage_timeout = 0;
+        $this->shm_sz = SHM_DIMS_MIN;
     }
-    // externalized $this->garbage_timeout = 0;
-    Room::garbage_time_expire_set(0);
-    $this->shm_sz = SHM_DIMS_MIN;
-  }
 
   function garbage_manager($force)
   {
@@ -712,163 +727,156 @@ class Room {
     /* Garbage collector degli utenti in timeout */
     $curtime = time();
 
-    // externalized if ($force || $this->garbage_timeout < $curtime) {
-    if (!$force && !Room::garbage_time_is_expired($curtime)) {
+    if (!$force && !($this->garbage_timeout < $curtime)) {
         return ($ismod);
     }
       
     webservers_check();
-      // FIXME BRISK4: include for each kind of table
-      require_once("${G_base}briskin5/Obj/briskin5.phh");
-
-      // Before all align times with table timeout
-      for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
+    
+    // Before all align times with table timeout
+    for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
        $table_cur = $this->table[$table_idx];
        // if the table is complete and exists its shared mem we get the info about users lacc
-
+        
        if ($table_cur->player_n == PLAYERS_N) {
-         log_main("PLAYERS == N TABLE ".$table_idx);
-         
-         if (($sem = Bin5::lock_data(TRUE, $table_idx)) != FALSE) { 
-           log_main("bin5 lock data success");
-           
-           $no_recovery = FALSE;
-           if (($bri = Bin5::load_data($table_idx)) != FALSE) {
-             if ($table_cur->table_token != $bri->table_token) {
-               log_main("ERROR: not matching table_token. Room: ".$table_cur->table_token."  Table: ".$bri->table_token);
-               log_main("ERROR: not matching table_start. Room: ".$table_cur->table_start."  Table: ".$bri->table_start);
-               $no_recovery = TRUE;
-               $bri = FALSE;
-             }
-           }
-           
-           if ($bri != FALSE) {
-             //
-             //  SPAWN: JOIN
-             //
-             log_main("garbage_manager: bri loaded successfully.");
-             $bri->garbage_manager(TRUE);
-             
-             $bri_table = $bri->table[0];
-
-             // is the end of the table
-             if ($bri->the_end == TRUE) {
-                  /*
-                *  DESTROY OF FINISHED TABLE && MOVE PLAYER TO ROOM AGAIN
-                */
-               log_main("garbage_manager: INSIDE THE END.");
-
-                $plist = "$table_cur->table_token|$table_cur->idx|$table_cur->player_n";
-                for ($i = 0 ; $i < $table_cur->player_n ; $i++) {
-                  $plist .= '|'.$this->user[$table_cur->player[$i]]->sess;
+            log_main("PLAYERS == N TABLE ".$table_idx);
+            
+            
+            $no_recovery = FALSE;
+            if (isset($this->match[$table_idx])) {
+                $bri = $this->match[$table_idx];
+
+                if ($table_cur->table_token != $bri->table_token) {
+                    log_main("ERROR: not matching table_token. Room: ".$table_cur->table_token."  Table: ".$bri->table_token);
+                    log_main("ERROR: not matching table_start. Room: ".$table_cur->table_start."  Table: ".$bri->table_start);
+                    $no_recovery = TRUE;
+                    $bri = FALSE;
                 }
 
-               for ($i = 0 ; $i < $bri_table->player_n ; $i++) {
-                 // stat must be "table" by definition
-                 $user_cur = $this->user[$table_cur->player[$i]];
-                 $bri_user = $bri->user[$i];
-                 
-                 $user_cur->subst      = $bri_user->subst;
-                 $user_cur->step       = $bri_user->step;
-                 $user_cur->lacc       = $bri_user->lacc;
-                 $user_cur->laccwr     = $bri_user->lacc;
-                 $user_cur->bantime    = $bri_user->bantime;
-               }
-
-                log_legal($curtime, 'xxx', $user_cur, "STAT:DESTROY_GAME", $plist);
-
-               $this->room_join_wakeup($user_cur, FALSE, 0); 
-               $table_cur->table_token = "";
-                $table_cur->wakeup_time = $curtime + WAKEUP_TIME;
-                        
-                        $bri->destroy_data($table_idx);
-             }
-             else {
-               log_main("gm:: save_data");
-
-               for ($i = 0 ; $i < $bri_table->player_n ; $i++) {
-                 $this->user[$table_cur->player[$i]]->lacc = $bri->user[$i]->lacc;
-               }
-             
-               Bin5::save_data($bri);
-             }
-           } // else if (($bri = Bin5::load_data($table_idx)) != FALSE) {
-           else if ($no_recovery == FALSE) {
-             log_crit("ERROR: table ".$table_idx." unrecoverable join");
-
-             for ($i = 0 ; $i < $table_cur->player_n ; $i++) {
-               $user_cur = $this->user[$table_cur->player[$i]];
-               $user_cur->subst = "shutdowner";
-               $user_cur->step_inc();
-               
-               $ret = sprintf('stat = "%s"; subst = "%s";',  $user_cur->stat, $user_cur->subst);
-               $ret .= "gst.st = ".($user_cur->step+1)."; ";
-                // MLANG <br>I dati del tavolo n&deg; ".$user_cur->table." sono inconsistenti, verranno resettati.<br><br>Torni in piedi.<br><br>
-                $prestr = sprintf($mlang_brisk['tabincon'][$G_lang], $user_cur->table);
-               $ret .= show_notify($prestr, 2000, $mlang_brisk['btn_close'][$G_lang], 400, 110);
-               $user_cur->comm[$user_cur->step % COMM_N] = $ret;
-               $user_cur->step_inc();
-             }
-
-              $plist = "$table_cur->table_token|$user_cur->table|$table_cur->player_n";
-              for ($i = 0 ; $i < $table_cur->player_n ; $i++) {
-                $plist .= '|'.$this->user[$table_cur->player[$i]]->sess;
-              }
-              log_legal($curtime, 'xxx', $user_cur, "STAT:DESTROY_GAME(RECOVERY)", $plist);
-              
-             $this->room_join_wakeup($user_cur, TRUE, -2); 
-             $table_cur->table_token = "";
-           }
 
-           Bin5::unlock_data($sem);
-         } // bri::lock_data
-       } //  if ($table_cur->player_n == PLAYERS_N) {
-      } //  for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
+                if ($bri != FALSE) {
+                    //
+                    //  SPAWN: JOIN
+                    //
+                    log_main("garbage_manager: bri loaded successfully.");
+                    $bri->garbage_manager(TRUE);
+                    
+                    $bri_table = $bri->table[0];
+                    
+                    // is the end of the table
+                    
+                    if ($bri->the_end == TRUE) {
+                        /*
+                         *  DESTROY OF FINISHED TABLE && MOVE PLAYER TO ROOM AGAIN
+                         */
+                        log_main("garbage_manager: INSIDE THE END.");
+                        
+                        $plist = "$table_cur->table_token|$table_cur->idx|$table_cur->player_n";
+                        for ($i = 0 ; $i < $table_cur->player_n ; $i++) {
+                            $plist .= '|'.$this->user[$table_cur->player[$i]]->sess;
+                        }
+                        
+                        for ($i = 0 ; $i < $bri_table->player_n ; $i++) {
+                            // stat must be "table" by definition
+                            $user_cur = $this->user[$table_cur->player[$i]];
+                            $bri_user = $bri->user[$i];
+                            
+                            $user_cur->subst      = $bri_user->subst;
+                            $user_cur->step       = $bri_user->step;
+                            $user_cur->lacc       = $bri_user->lacc;
+                            $user_cur->laccwr     = $bri_user->lacc;
+                            $user_cur->bantime    = $bri_user->bantime;
+                        }
+                        
+                        log_legal($curtime, 'xxx', $user_cur, "STAT:DESTROY_GAME", $plist);
+                        
+                        $this->room_join_wakeup($user_cur, FALSE, 0); 
+                        $table_cur->table_token = "";
+                        $table_cur->wakeup_time = $curtime + WAKEUP_TIME;
+                        
+                        $this->match_del($table_idx);
+                    }
+                    else {
+                        log_main("gm:: save_data");
+                        
+                        for ($i = 0 ; $i < $bri_table->player_n ; $i++) {
+                            $this->user[$table_cur->player[$i]]->lacc = $bri->user[$i]->lacc;
+                        }
+                    }
+                } // if ($bri == FALSE
+                else if ($no_recovery == FALSE) {
+                    log_crit("ERROR: table ".$table_idx." unrecoverable join");
+                    
+                    for ($i = 0 ; $i < $table_cur->player_n ; $i++) {
+                        $user_cur = $this->user[$table_cur->player[$i]];
+                        $user_cur->subst = "shutdowner";
+                        $user_cur->step_inc();
+                        
+                        $ret = sprintf('stat = "%s"; subst = "%s";',  $user_cur->stat, $user_cur->subst);
+                        $ret .= "gst.st = ".($user_cur->step+1)."; ";
+                        // MLANG <br>I dati del tavolo n&deg; ".$user_cur->table." sono inconsistenti, verranno resettati.<br><br>Torni in piedi.<br><br>
+                        $prestr = sprintf($mlang_brisk['tabincon'][$G_lang], $user_cur->table);
+                        $ret .= show_notify($prestr, 2000, $mlang_brisk['btn_close'][$G_lang], 400, 110);
+                        $user_cur->comm[$user_cur->step % COMM_N] = $ret;
+                        $user_cur->step_inc();
+                    }
+                    
+                    $plist = "$table_cur->table_token|$user_cur->table|$table_cur->player_n";
+                    for ($i = 0 ; $i < $table_cur->player_n ; $i++) {
+                        $plist .= '|'.$this->user[$table_cur->player[$i]]->sess;
+                    }
+                    log_legal($curtime, 'xxx', $user_cur, "STAT:DESTROY_GAME(RECOVERY)", $plist);
+                    
+                    $this->room_join_wakeup($user_cur, TRUE, -2); 
+                    $table_cur->table_token = "";
+                }
+            }
+        } //  if ($table_cur->player_n == PLAYERS_N) {
+    } //  for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
     
-      log_rd2("out new loop.");
-               
-      for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
+    log_rd2("out new loop.");
+    
+    for ($i = 0 ; $i < MAX_PLAYERS ; $i++) {
        $user_cur = $this->user[$i];
        
        log_rd2("User: ".$user_cur->name."  stat: ".$user_cur->stat."  subst: ".$user_cur->subst);
-         
+       
        if ($user_cur->sess == "") 
-         continue;
+            continue;
        
        if ($user_cur->lacc + EXPIRE_TIME_RD < $curtime) {
-         // Auto logout dell'utente
-         log_rd2("AUTO LOGOUT.".($user_cur->lacc + EXPIRE_TIME_RD)." curtime ".$curtime);
-         
-         if ($user_cur->stat == 'table' || $user_cur->stat == 'room') {
-           log_auth($user_cur->sess, "Autologout session.");
-           
-           $user_cur->reset();
+            // Auto logout dell'utente
+            log_rd2("AUTO LOGOUT.".($user_cur->lacc + EXPIRE_TIME_RD)." curtime ".$curtime);
+            
+            if ($user_cur->stat == 'table' || $user_cur->stat == 'room') {
+                log_auth($user_cur->sess, "Autologout session.");
+                
+                $user_cur->reset();
            
-           log_rd2("AUTO LOGOUT.");
-           if ($user_cur->subst == 'sitdown' || $user_cur->stat == 'table')
-             $this->room_wakeup($user_cur);
-           else if ($user_cur->subst == 'standup')
-             $this->room_outstandup($user_cur);
-           else
-             log_rd2("LOGOUT FROM WHAT ???");
-         }
+                log_rd2("AUTO LOGOUT.");
+                if ($user_cur->subst == 'sitdown' || $user_cur->stat == 'table')
+                    $this->room_wakeup($user_cur);
+                else if ($user_cur->subst == 'standup')
+                    $this->room_outstandup($user_cur);
+                else
+                    log_rd2("LOGOUT FROM WHAT ???");
+            }
        }
 
        if ($user_cur->laccwr + EXPIRE_TIME_SMAMMA < $curtime) { // lo rimettiamo in piedi
-         if ($user_cur->stat == 'room' && $user_cur->subst == 'sitdown') {
-           $this->room_wakeup($user_cur);
-           $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
-            /* MLANG: <br>Sei stato inattivo per ".(EXPIRE_TIME_SMAMMA/60.0)." minuti. <br><br>Quindi ritorni tra i <b>Giocatori in piedi</b>.", "torna ai tavoli" */
-           $user_cur->comm[$user_cur->step % COMM_N] .=  show_notify($mlang_brisk['tabtout_a'][$G_lang].(EXPIRE_TIME_SMAMMA/60.0).$mlang_brisk['tabtout_b'][$G_lang], 0, $mlang_brisk['btn_backstand'][$G_lang], 400, 100);
-           $user_cur->step_inc();
-         }
+            if ($user_cur->stat == 'room' && $user_cur->subst == 'sitdown') {
+                $this->room_wakeup($user_cur);
+                $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
+                /* MLANG: <br>Sei stato inattivo per ".(EXPIRE_TIME_SMAMMA/60.0)." minuti. <br><br>Quindi ritorni tra i <b>Giocatori in piedi</b>.", "torna ai tavoli" */
+                $user_cur->comm[$user_cur->step % COMM_N] .=  show_notify($mlang_brisk['tabtout_a'][$G_lang].(EXPIRE_TIME_SMAMMA/60.0).$mlang_brisk['tabtout_b'][$G_lang], 0, $mlang_brisk['btn_backstand'][$G_lang], 400, 100);
+                $user_cur->step_inc();
+            }
        }
-      }
-      log_rd2("GARBAGE UPDATED!");
-      
-      // externalized $this->garbage_timeout = time() + GARBAGE_TIMEOUT;
-      Room::garbage_time_expire_set($curtime + GARBAGE_TIMEOUT);
-      $ismod = TRUE;
+    }
+    log_rd2("GARBAGE UPDATED!");
+    
+    $this->garbage_timeout = $curtime + GARBAGE_TIMEOUT;
+    $ismod = TRUE;
 
     return ($ismod);
   }
@@ -918,7 +926,8 @@ class Room {
         $ret .= sprintf('tra.rem(%d); ', $i);
     }
     $ret .= $this->standup_content($user);
-    
+    $ret .= "setTimeout(preload_images, 0, g_preload_img_arr, g_imgct); ";
+
     return ($ret);
   }
   
@@ -978,7 +987,7 @@ class Room {
 
       $ret = "gst.st = ".($user_cur->step+1)."; ".($remove_wagon ? sprintf("tra.rem(%d);",$table_idx) : "");
       if ($from_table && ($user_cur->table == $table_idx || $user->idx_get() == $i)) {
-       $ret .= 'gst.st_loc++; hstm.stop(); window.onunload = null; window.onbeforeunload = null; document.location.assign("index.php");|';
+       $ret .= 'gst.st_loc++; xstm.stop(); window.onunload = null; window.onbeforeunload = null; document.location.assign("index.php");|';
        // $ret .= 'gst.st_loc++; document.location.assign("index.php");|';
        log_main("DOCUMENT.index.php: from table");
       }
@@ -1213,7 +1222,7 @@ class Room {
     $only_you = FALSE;
     
     // common settings
-    $msg = substr($mesg, 6, 128);
+    $msg = mb_substr($mesg, 6, 128, "UTF-8");
     $curtime = time();
     $dt = date("H:i ", $curtime);
     $target = "";
@@ -1473,7 +1482,7 @@ class Room {
 
     else { // normal chat line
       $is_normchat = TRUE;
-      if ($curtime < ($user->chat_ban + $user->chat_dlt)) {
+      if (CHAT_ENABLED && $curtime < ($user->chat_ban + $user->chat_dlt)) {
         $only_you = TRUE;
         $user->chat_dlt = $user->chat_dlt * 2; 
         if ($user->chat_dlt > 120)
@@ -1481,7 +1490,7 @@ class Room {
       }
       else if ($user->chat_lst == $msg)
         $only_you = TRUE;
-      else if ($curtime - $user->chattime[($user->chat_cur + 1) % CHAT_N] < CHAT_ILL_TIME) {
+      else if (CHAT_ENABLED && $curtime - $user->chattime[($user->chat_cur + 1) % CHAT_N] < CHAT_ILL_TIME) {
         $user->chat_ban = $curtime;
         $user->chat_dlt = 5;
         $only_you = TRUE;
@@ -1555,46 +1564,27 @@ class Room {
     }
     
     if ($to_tabl) {
-      // FIXME BRISK4: include for each kind of table
-      require_once("${G_base}briskin5/Obj/briskin5.phh");
-      // Before all align times with table timeout
-      for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
-        $table_cur = $this->table[$table_idx];
-        // if the table is complete and exists its shared mem we get the info about users lacc
-        
-        if ($table_cur->player_n == PLAYERS_N) {
-          log_main("PLAYERS == N TABLE ".$table_idx);
-        
-          if (($sem = Bin5::lock_data(TRUE, $table_idx)) != FALSE) { 
-            log_main("bin5 lock data success");
-            
-            $no_recovery = FALSE;
-            if (($bri = Bin5::load_data($table_idx)) != FALSE) {
-              if ($table_cur->table_token != $bri->table_token) {
-                log_main("ERROR: not matching table_token. Room: ".$table_cur->table_token."  Table: ".$bri->table_token);
-                $bri = FALSE;
-              }
-            }
-            
-            if ($bri != FALSE) {
-              $bri_table = $bri->table[0];
-              for ($i = 0 ; $i < $bri_table->player_n ; $i++) {
-                // stat must be "table" by definition
-                $bri_user = $bri->user[$i];
+        // FIXME BRISK4: include for each kind of table
+        require_once("${G_base}briskin5/Obj/briskin5.phh");
+        // Before all align times with table timeout
+        for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
+            if (isset($this->match[$table_idx])) {
+                $bri = $this->match[$table_idx];
+
+                $bri_table = $bri->table[0];
+                for ($i = 0 ; $i < $bri_table->player_n ; $i++) {
+                    // stat must be "table" by definition
+                    $bri_user = $bri->user[$i];
               
-                if ($target != "" && $bri_user->name != $target)
-                  continue;
-                log_main("writa: ".$user_mesg);
-                $bri_user->comm[$bri_user->step % COMM_N] = "gst.st = ".($bri_user->step+1)."; ";
-                $bri_user->comm[$bri_user->step % COMM_N] .= $to_tabl;
-                $bri_user->step_inc();
-              }
-              Bin5::save_data($bri);
-            }
-            Bin5::unlock_data($sem);
-          } // bri::lock_data
-        } //  if ($table_cur->player_n == PLAYERS_N) {
-      } //  for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
+                    if ($target != "" && $bri_user->name != $target)
+                        continue;
+                    log_main("writa: ".$user_mesg);
+                    $bri_user->comm[$bri_user->step % COMM_N] = "gst.st = ".($bri_user->step+1)."; ";
+                    $bri_user->comm[$bri_user->step % COMM_N] .= $to_tabl;
+                    $bri_user->step_inc();
+                }
+            } // if (isset($this->match
+        } //  for ($table_idx = 0 ; $table_idx < TABLES_N ; $table_idx++) {
     } // if ($to_tabl == true ...
 
     if ($update_room) {
@@ -1647,9 +1637,9 @@ class Room {
    *   if ($idx == -$idx && ret == user)   =>  SUCCESS (but the login exists in the auth db)
    */
 
-  function add_user(&$sess, &$idx, $name, $pass, $ip)
+  function add_user(&$sess, &$idx, $name, $pass, $ip, $cookie)
   {
-    GLOBAL $G_base, $CO_list;
+    GLOBAL $G_base;
 
     $idx = 0;
 
@@ -1730,6 +1720,7 @@ class Room {
 
       $ghost_user = $this->user[$ghost];
       $curtime = time();
+      $ghost_user->comm[$ghost_user->step % COMM_N] = "";
       $ghost_user->step_inc();
       if ($sess == "") {
         $sess = uniqid(""); 
@@ -1742,18 +1733,16 @@ class Room {
       // If user at the table we need to update the table data too
       $table_idx = $ghost_user->table;
       if ($ghost_user->stat == "table" && $this->table[$table_idx]->player_n == PLAYERS_N) {
-        // FIXME BRISK4: include for each kind of table
-        require_once("${G_base}briskin5/Obj/briskin5.phh");
-        if (($brisem = Bin5::lock_data(TRUE, $table_idx)) != FALSE) { 
-          if (($bri = Bin5::load_data($table_idx)) != FALSE) {
-            if ($bri->the_end != TRUE) {
-              $bri->user[$ghost_user->table_pos]->step_inc();
-              $bri->user[$ghost_user->table_pos]->sess = $sess;
-              Bin5::save_data($bri);
-            }
+          require_once("${G_base}briskin5/Obj/briskin5.phh");
+          if (isset($this->match[$table_idx])) {
+              $bri = $this->match[$table_idx];
+
+              if ($bri->the_end != TRUE) {
+                  $bri->user[$ghost_user->table_pos]->comm[$bri->user[$ghost_user->table_pos]->step % COMM_N] = "";
+                  $bri->user[$ghost_user->table_pos]->step_inc();
+                  $bri->user[$ghost_user->table_pos]->sess = $sess;
+              }
           }
-          Bin5::unlock_data($brisem);
-        }
       }
 
       $idx = $ghost;
@@ -1789,12 +1778,12 @@ class Room {
         $this->user[$idx]->code = $authenticate->code_get();
         $this->user[$idx]->flags |= USER_FLAG_LISTAUTH;
 
-        if (isset($CO_list)) {
-          if (strcmp($CO_list, "auth") == 0) {
+        if (isset($cookie['CO_list'])) {
+          if (strcmp($cookie['CO_list'], "auth") == 0) {
             $this->user[$idx]->flags &= ~USER_FLAG_MAP_AUTH;
             $this->user[$idx]->flags |= USER_FLAG_LISTAUTH;
           }
-          if (strcmp($CO_list, "isolation") == 0) {
+          if (strcmp($cookie['CO_list'], "isolation") == 0) {
             $this->user[$idx]->flags &= ~USER_FLAG_MAP_AUTH;
             $this->user[$idx]->flags |= USER_FLAG_ISOLAUTH;
           }
@@ -1877,10 +1866,17 @@ class Room {
   }
 
   // Static functions
-  static function create()
+  static function create($crystal_filename)
   {
-    $room = new Room();
-    
+      if (($room_ser = @file_get_contents($crystal_filename)) == FALSE ||
+          ($room = unserialize($room_ser)) == FALSE) {
+          fprintf(STDERR, "NEW ROOM\n");
+          $room = new Room($crystal_filename);
+      }
+      else {
+          fprintf(STDERR, "ROOM FROM FILE\n");
+      }
+
     return $room;
   }
   
@@ -1890,7 +1886,7 @@ class Room {
     GLOBAL $sess;
 
     do {
-      if (($tok = @ftok(FTOK_PATH."/main", "B")) == -1) {
+      if (($tok = @ftok(FTOK_PATH."/main", "C")) == -1) {
        log_main("ftok failed");
        break;
       }
@@ -1955,7 +1951,7 @@ class Room {
     
     // var_dump($room);
     
-    if (($tok = @ftok(FTOK_PATH."/main", "B")) == -1) 
+    if (($tok = @ftok(FTOK_PATH."/main", "C")) == -1) 
       return (FALSE);
     
     while ($room->shm_sz < SHM_DIMS_MAX) {
@@ -1980,7 +1976,16 @@ class Room {
     
     return (FALSE);
   }
-
+  function dump_data()
+  {
+      $room_ser = serialize($this);
+      $room_ser_len = mb_strlen($room_ser, "ASCII");
+      if (file_put_contents($this->crystal_filename, $room_ser) == $room_ser_len) {
+          return (TRUE);
+      }
+      
+      return (FALSE);
+  }
 
   function save_data($room) 
   {
@@ -1989,7 +1994,7 @@ class Room {
       $ret =   FALSE;
       $shm =   FALSE;
     
-      if (($tok = @ftok(FTOK_PATH."/main", "B")) == -1) 
+      if (($tok = @ftok(FTOK_PATH."/main", "C")) == -1) 
           return (FALSE);
     
       // SHSPLIT: before save the $room you must save users, 
@@ -2127,81 +2132,48 @@ class Room {
     return ($ret);
   }
 
-  static function garbage_time_is_expired($tm) 
-  {
-      $ret = TRUE;
-      $fp = FALSE;
-      do {
-          if (file_exists(PROXY_PATH) == FALSE)
-              mkdir(PROXY_PATH, 0775, TRUE);
-          if (($fp = @fopen(PROXY_PATH."/garbage_time.expired", 'rb')) == FALSE)
-              break;
-          if (($s = fread($fp, 4)) == FALSE)
-              break;
-          if (mb_strlen($s, "ASCII") != 4)
-              break;
-          $arr = unpack('Le', $s);
-          if ($arr['e'] > $tm)
-              $ret = FALSE;
-      } while (0);
-      
-      if ($fp != FALSE)
-          fclose($fp);
-      
-      log_rd2("END: return ".($ret ? "TRUE" : "FALSE"));
-      
-      return ($ret);
-  }
-
-  static function garbage_time_expire_set($tm) 
-  {
-      do {
-          if (file_exists(PROXY_PATH) == FALSE)
-              mkdir(PROXY_PATH, 0775, TRUE);
-          if (($fp = @fopen(PROXY_PATH."/garbage_time.expired", 'wb')) == FALSE)
-              break;
-          fwrite($fp, pack("L",$tm));
-          fclose($fp);
-          
-          return (TRUE);
-      } while (0);
-      
-      return (FALSE);
-  }
-
-  function request_mgr(&$s_a_p, &$header_out, &$new_socket, $path, $addr, $get, $post, $cookie)
+  function request_mgr(&$s_a_p, $header, &$header_out, &$new_socket, $path, $addr, $get, $post, $cookie)
   {
       printf("NEW_SOCKET (root): %d\n", intval($new_socket));
 
+      $enc = get_encoding($header);
+      if (isset($header['User-Agent']) && strstr($header['User-Agent'], "MSIE")) {
+          $transp_type = "htmlfile";
+      }
+      else {
+          $transp_type = "iframe";
+      }
+      force_no_cache($header_out);
+
       switch ($path) {
-      case SITE_PREFIX:
-      case SITE_PREFIX."index.php":
+      case "":
+      case "index.php":
           ob_start();
-      index_main($this, $header_out, $addr, $get, $post, $cookie);
-      $content = ob_get_contents();
-      ob_end_clean();
+          index_main($this, $transp_type, $header_out, $addr, $get, $post, $cookie);
+          $content = ob_get_contents();
+          ob_end_clean();
 
-      $s_a_p->pgflush_try_add($new_socket, 20, $header_out, $content);
-      return TRUE;
+          $s_a_p->pgflush_try_add($enc, $new_socket, 20, $header_out, $content);
+          return TRUE;
 
-      break;
-      case SITE_PREFIX."index_wr.php":
+          break;
+      case "index_wr.php":
           ob_start();
           index_wr_main($this, $addr, $get, $post, $cookie);
           $content = ob_get_contents();
           ob_end_clean();
-
-          $s_a_p->pgflush_try_add($new_socket, 20, $header_out, $content);
+          
+          $s_a_p->pgflush_try_add($enc, $new_socket, 20, $header_out, $content);
           return TRUE;
 
           break;
-      case SITE_PREFIX."index_rd_ifra.php":
+      case "index_rd_ifra.php":
           do {
               if (!isset($cookie['sess'])
                   || (($user = $this->get_user($cookie['sess'], $idx)) == FALSE)) {
-                  $content = User::stream_fini(TRUE);
+                  $content = User::stream_fini($s_a_p->rndstr, TRUE);
                   
-                  $s_a_p->pgflush_try_add($new_socket, 20, $header_out, $content);
+                  $s_a_p->pgflush_try_add($enc, $new_socket, 20, $header_out, $content);
                   return TRUE;
 
                   break;
@@ -2213,11 +2185,11 @@ class Room {
                   printf("CLOSE AND OPEN AGAIN ON IFRA2\n");
                   $user->rd_socket_set(NULL);
               }
-              
+
               $content = "";
-              $user->stream_init($header_out, $content, $get, $post, $cookie);
+              $user->stream_init($s_a_p->rndstr, $enc, $header_out, $content, $get, $post, $cookie);
               
-              $response = headers_render($header_out, -1).chunked_content($content);
+              $response = headers_render($header_out, -1).chunked_content($user->rd_zls_get(), $content);
               $response_l = mb_strlen($response, "ASCII");
               
               $wret = @fwrite($new_socket, $response, $response_l);
@@ -2239,11 +2211,42 @@ class Room {
           
           return FALSE;
           break;
+
+      default:
+          /* FAR TODO: move all into an array of registered sub-apps */
+          $subs = "briskin5/";
+          $subs_l = strlen($subs);
+          if (!strncmp($path, $subs, $subs_l)) {
+              $ret = Bin5::request_mgr(&$s_a_p, $header, &$header_out, &$new_socket, substr($path, $subs_l) , $addr, $get, $post, $cookie);
+              return ($ret);
+          }
+          break;
       }
 
       return (FALSE);
   }
 
+  function match_add($idx, $match)
+  {
+      $this->match[$idx] = $match;
+  }
+
+  function match_del($idx)
+  {
+      unset($this->match[$idx]);
+  }
+
+  function match_get($idx, $token)
+  {
+      if (isset($this->match[$idx])) {
+          if (   $token == NULL 
+              || $token == $this->match[$idx]->table_token) {
+              return ($this->match[$idx]);
+          }
+      }
+      return NULL;
+  }
+
 } // end class Room
 
 function make_seed()
@@ -2680,7 +2683,7 @@ function validate_sess($sess)
 
 function validate_name($name) 
 {
-  $name_new = str_replace(' ', '_', substr(trim($name),0,12));
+    $name_new = str_replace(' ', '_', mb_substr(trim($name),0,12, "UTF-8"));
 
   for ($i = 0 ; $i < strlen($name_new) ; $i++) {
     $c = $name_new[$i];