a removeChild block opera on iframe stream, removed
[brisk.git] / web / Obj / brisk.phh
index 60ea624..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,47 +672,49 @@ class Table {
 
 
 
-class Room {
+class Room
+{
     static $delta_t;
-
-  var $user;
-  var $table;
-  var $match;
-  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();
-    $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;
+    
+    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)
   {
@@ -714,8 +727,7 @@ 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);
     }
       
@@ -863,8 +875,7 @@ class Room {
     }
     log_rd2("GARBAGE UPDATED!");
     
-    // externalized $this->garbage_timeout = time() + GARBAGE_TIMEOUT;
-    Room::garbage_time_expire_set($curtime + GARBAGE_TIMEOUT);
+    $this->garbage_timeout = $curtime + GARBAGE_TIMEOUT;
     $ismod = TRUE;
 
     return ($ismod);
@@ -915,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);
   }
   
@@ -975,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");
       }
@@ -1210,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 = "";
@@ -1470,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)
@@ -1478,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;
@@ -1552,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) {
@@ -1644,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;
 
@@ -1727,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(""); 
@@ -1739,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;
@@ -1786,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;
           }
@@ -1874,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;
   }
   
@@ -1887,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;
       }
@@ -1952,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) {
@@ -1977,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) 
   {
@@ -1986,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, 
@@ -2124,71 +2132,38 @@ 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 "":
       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;
+          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;
@@ -2196,9 +2171,9 @@ class Room {
           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;
@@ -2210,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);
@@ -2242,7 +2217,7 @@ class Room {
           $subs = "briskin5/";
           $subs_l = strlen($subs);
           if (!strncmp($path, $subs, $subs_l)) {
-              $ret = Bin5::request_mgr(&$s_a_p, &$header_out, &$new_socket, substr($path, $subs_l) , $addr, $get, $post, $cookie);
+              $ret = Bin5::request_mgr(&$s_a_p, $header, &$header_out, &$new_socket, substr($path, $subs_l) , $addr, $get, $post, $cookie);
               return ($ret);
           }
           break;
@@ -2708,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];