Changeset 2467 in subversion


Ignore:
Timestamp:
May 12, 2009 9:26:07 AM (4 years ago)
Author:
robin
Message:

Minimize chance of race condition in session handling (#1485659, #1484678)

Location:
trunk/roundcubemail
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/roundcubemail/CHANGELOG

    r2463 r2467  
    22=========================== 
    33 
     4- Minimize chance of race condition in session handling (#1485659, #1484678) 
    45- Fix session handling on non-session SQL query error (#1485734) 
    56- Fix html editor mode setting when reopening draft message (#1485834) 
  • trunk/roundcubemail/program/include/rcmail.php

    r2427 r2467  
    125125    // reset some session parameters when changing task 
    126126    if ($_SESSION['task'] != $this->task) 
    127       unset($_SESSION['page']); 
     127      rcube_sess_unset('page'); 
    128128 
    129129    // set current task to session 
  • trunk/roundcubemail/program/include/session.inc

    r2463 r2467  
    6363  $DB = rcmail::get_instance()->get_dbh(); 
    6464   
    65   $sql_result = $DB->query( 
    66     "SELECT 1 FROM " . get_table_name('session') . " 
    67      WHERE  sess_id=?", 
    68     $key); 
    69  
    7065  $now = $DB->fromunixtime(time()); 
    7166 
    72   if ($DB->num_rows($sql_result)) { 
     67  if ($oldvars = rcube_sess_read($key)) { 
    7368    $DB->query( 
    7469      "UPDATE " . get_table_name('session') . " 
    7570       SET    vars=?, changed= " . $now . " 
    7671       WHERE  sess_id=?", 
    77       $vars, 
     72      rcube_sess_serialize(array_merge(rcube_sess_unserialize($oldvars), rcube_sess_unserialize($vars))), 
    7873      $key); 
    7974  } 
     
    9287 
    9388 
     89// unset session variable 
     90function rcube_sess_unset($var) 
     91{ 
     92  $DB = rcmail::get_instance()->get_dbh(); 
     93 
     94  if ($DB->is_error()) { 
     95    return false; 
     96  } 
     97 
     98  $now = $DB->fromunixtime(time()); 
     99 
     100  $sql_result = $DB->query( 
     101    "SELECT vars 
     102     FROM " . get_table_name('session') . " 
     103     WHERE  sess_id=?", 
     104     session_id()); 
     105 
     106  if ($sql_arr = $DB->fetch_assoc($sql_result)) { 
     107    $vars = rcube_sess_unserialize($sql_arr['vars']); 
     108    if (isset($vars[$var])) { 
     109      unset($vars[$var]); 
     110      $DB->query( 
     111        "UPDATE " . get_table_name('session') . " 
     112         SET    vars=?, changed= " . $now . " 
     113         WHERE  sess_id=?", 
     114         rcube_sess_serialize($vars), 
     115         session_id()); 
     116    } 
     117  }    
     118 
     119  return true; 
     120} 
     121 
     122 
     123// serialize session data 
     124function rcube_sess_serialize($vars) 
     125{ 
     126  $data = ''; 
     127  if (is_array($vars)) 
     128    foreach ($vars as $var=>$value) 
     129      $data .= $var.'|'.serialize($value); 
     130  else 
     131    $data = 'b:0;'; 
     132  return $data; 
     133} 
     134 
     135 
     136// unserialize session data 
     137// http://www.php.net/manual/en/function.session-decode.php#56106 
     138function rcube_sess_unserialize($str) 
     139{ 
     140  $str = (string)$str; 
     141  $endptr = strlen($str); 
     142  $p = 0; 
     143 
     144  $serialized = ''; 
     145  $items = 0; 
     146  $level = 0; 
     147 
     148  while ($p < $endptr) { 
     149    $q = $p; 
     150    while ($str[$q] != '|') 
     151      if (++$q >= $endptr) break 2; 
     152 
     153    if ($str[$p] == '!') { 
     154      $p++; 
     155      $has_value = false; 
     156    } else { 
     157      $has_value = true; 
     158    } 
     159 
     160    $name = substr($str, $p, $q - $p); 
     161    $q++; 
     162 
     163    $serialized .= 's:' . strlen($name) . ':"' . $name . '";'; 
     164 
     165    if ($has_value) { 
     166      for (;;) { 
     167        $p = $q; 
     168        switch (strtolower($str[$q])) { 
     169          case 'n': /* null */ 
     170          case 'b': /* boolean */ 
     171          case 'i': /* integer */ 
     172          case 'd': /* decimal */ 
     173            do $q++; 
     174            while ( ($q < $endptr) && ($str[$q] != ';') ); 
     175            $q++; 
     176            $serialized .= substr($str, $p, $q - $p); 
     177            if ($level == 0) break 2; 
     178            break; 
     179          case 'r': /* reference  */ 
     180            $q+= 2; 
     181            for ($id = ''; ($q < $endptr) && ($str[$q] != ';'); $q++) $id .= $str[$q]; 
     182            $q++; 
     183            $serialized .= 'R:' . ($id + 1) . ';'; /* increment pointer because of outer array */ 
     184            if ($level == 0) break 2; 
     185            break; 
     186          case 's': /* string */ 
     187            $q+=2; 
     188            for ($length=''; ($q < $endptr) && ($str[$q] != ':'); $q++) $length .= $str[$q]; 
     189            $q+=2; 
     190            $q+= (int)$length + 2; 
     191            $serialized .= substr($str, $p, $q - $p); 
     192            if ($level == 0) break 2; 
     193            break; 
     194          case 'a': /* array */ 
     195          case 'o': /* object */ 
     196            do $q++; 
     197            while ( ($q < $endptr) && ($str[$q] != '{') ); 
     198            $q++; 
     199            $level++; 
     200            $serialized .= substr($str, $p, $q - $p); 
     201            break; 
     202          case '}': /* end of array|object */ 
     203            $q++; 
     204            $serialized .= substr($str, $p, $q - $p); 
     205            if (--$level == 0) break 2; 
     206            break; 
     207          default: 
     208            return false; 
     209        } 
     210      } 
     211    } else { 
     212      $serialized .= 'N;'; 
     213      $q+= 2; 
     214    } 
     215    $items++; 
     216    $p = $q; 
     217  } 
     218 
     219  return unserialize( 'a:' . $items . ':{' . $serialized . '}' ); 
     220} 
     221 
     222 
    94223// handler for session_destroy() 
    95224function rcube_sess_destroy($key) 
  • trunk/roundcubemail/program/steps/mail/func.inc

    r2446 r2467  
    12791279  rcmail::get_instance()->plugins->exec_hook('cleanup_attachments',array()); 
    12801280   
    1281   unset($_SESSION['compose']); 
     1281  rcube_sess_unset('compose'); 
    12821282  } 
    12831283   
Note: See TracChangeset for help on using the changeset viewer.