From b2b2ebbac4e816c2b0f393124b62d62d4f4ef5f2 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Thu, 28 Jun 2012 17:36:11 -0400
Subject: [PATCH] Live migrate the PHP session to database

Migrate the PHP session from disk to database live. To pull this off, the
session contents are written to database under the current session id. When
the `ostversion` column is dropped from the %config table, the system will
automatically switch to database-backed sessions in osTicket 1.7 mode.

This is sort-of hacked together by carefully calling a instance method of
the osTicketSession class statically, and modify the instance method to
support static invocation.
---
 include/class.ostsession.php |  5 ++++-
 include/class.upgrader.php   | 27 +++++++++++++++++++++++----
 scp/logout.php               |  1 -
 scp/upgrade.php              |  5 +++--
 4 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/include/class.ostsession.php b/include/class.ostsession.php
index 0bcd9449f..08cac02ce 100644
--- a/include/class.ostsession.php
+++ b/include/class.ostsession.php
@@ -67,10 +67,13 @@ class osTicketSession {
     function write($id, $data){
         global $thisstaff;
 
+        $ttl = ($this && get_class($this) == 'osTicketSession') 
+            ? $this->getTTL() : SESSION_TTL;
+
         $sql='REPLACE INTO '.SESSION_TABLE.' SET session_updated=NOW() '.
              ',session_id='.db_input($id).
              ',session_data='.db_input($data).
-             ',session_expire=(NOW() + INTERVAL '.$this->getTTL().' SECOND)'.
+             ',session_expire=(NOW() + INTERVAL '.$ttl.' SECOND)'.
              ',user_id='.db_input($thisstaff?$thisstaff->getId():0).
              ',user_ip='.db_input($_SERVER['REMOTE_ADDR']).
              ',user_agent='.db_input($_SERVER['HTTP_USER_AGENT']);
diff --git a/include/class.upgrader.php b/include/class.upgrader.php
index 69dd760fd..de11aee3a 100644
--- a/include/class.upgrader.php
+++ b/include/class.upgrader.php
@@ -181,9 +181,11 @@ class Upgrader extends SetupWizard {
 
     function doTasks() {
 
+        global $ost;
         if(!($tasks=$this->getPendingTasks()))
             return true; //Nothing to do.
 
+        $ost->logDebug('Upgrader', sprintf('There are %d pending upgrade tasks', count($tasks)));
         $start_time = Misc::micro_time();
         foreach($tasks as $k => $task) {
             //TODO: check time used vs. max execution - break if need be
@@ -238,6 +240,9 @@ class Upgrader extends SetupWizard {
             $shash = substr($phash, 9, 8);
             $_SESSION['ost_upgrader'][$shash]['tasks'] = $tasks;
             $_SESSION['ost_upgrader'][$shash]['state'] = 'upgrade';
+            
+            $ost->logDebug('Upgrader', sprintf('Found %d tasks to be executed for %s',
+                            count($tasks), $shash));
             break;
 
         }
@@ -253,13 +258,16 @@ class Upgrader extends SetupWizard {
             case 'c00511c7-7be60a84': //V1.6 ST- 1.7 * {{MD5('1.6 ST') -> c00511c7c1db65c0cfad04b4842afc57}}
                 $tasks[] = array('func' => 'migrateAttachments2DB',
                                  'desc' => 'Migrating attachments to database, it might take a while depending on the number of files.');
+                $tasks[] = array('func' => 'migrateSessionFile2DB',
+                                 'desc' => 'Transitioning to db-backed sessions');
                 break;
         }
 
         //Check IF SQL cleanup is exists. 
         $file=$this->getSQLDir().$phash.'.cleanup.sql';
         if(file_exists($file)) 
-            $tasks[] = array('func' => 'cleanup', 'desc' => 'Post-upgrade cleanup!');
+            $tasks[] = array('func' => 'cleanup', 'desc' => 'Post-upgrade cleanup!',
+                        'phash' => $phash);
 
 
         return $tasks;
@@ -267,8 +275,11 @@ class Upgrader extends SetupWizard {
 
     /************* TASKS **********************/
     function cleanup($taskId) {
+        global $ost;
+
+        $phash = $this->tasks[$taskId]['phash'];
+        $file=$this->getSQLDir().$phash.'.cleanup.sql';
 
-        $file=$this->getSQLDir().$this->getShash().'-cleanup.sql';
         if(!file_exists($file)) //No cleanup script.
             return 0;
 
@@ -276,11 +287,13 @@ class Upgrader extends SetupWizard {
         if($this->load_sql_file($file, $this->getTablePrefix(), false, true))
             return 0;
 
-        //XXX: ???
-        return false;
+        $ost->logDebug('Upgrader', sprintf("%s: Unable to process cleanup file",
+                        $phash));
+        return 0;
     }
 
     function migrateAttachments2DB($taskId) {
+        global $ost;
         
         if(!($max_time = ini_get('max_execution_time')))
             $max_time = 30; //Default to 30 sec batches.
@@ -291,5 +304,11 @@ class Upgrader extends SetupWizard {
 
         return $att_migrater->getQueueLength();
     }
+
+    function migrateSessionFile2DB($taskId) {
+        # How about 'dis for a hack?
+        osTicketSession::write(session_id(), session_encode()); 
+        return 0;
+    }
 }
 ?>
diff --git a/scp/logout.php b/scp/logout.php
index 32d62d14a..f167d5a87 100644
--- a/scp/logout.php
+++ b/scp/logout.php
@@ -21,7 +21,6 @@ $ost->logDebug('Staff logout',
 $_SESSION['_staff']=array();
 session_unset();
 session_destroy();
-session_write_close();
 @header('Location: login.php');
 require('login.php');
 ?>
diff --git a/scp/upgrade.php b/scp/upgrade.php
index d13dc4c33..c441bd5b7 100644
--- a/scp/upgrade.php
+++ b/scp/upgrade.php
@@ -27,9 +27,10 @@ if($_POST && $_POST['s'] && !$upgrader->isAborted()) {
                 $errors['err']=' Nothing to do! System already upgraded to the current version';
             elseif(!$upgrader->isUpgradable())
                 $errors['err']='The upgrader does NOT support upgrading from the current vesion!';
-            elseif($upgrader->check_prereq())
+            elseif($upgrader->check_prereq()) {
                 $upgrader->setState('upgrade');
-            else
+                $_SESSION['ost_upgrader'] = null;
+            } else
                 $errors['prereq']='Minimum requirements not met!';
             break;
         case 'upgrade': //Manual upgrade.... when JS (ajax) is not supported.
-- 
GitLab