diff --git a/ajax.php b/ajax.php
index 5210b628be577f830648e34a7f4d4a9a4c4fb3a1..a629af6392e312f35f02a5dc387b380fddf737eb 100644
--- a/ajax.php
+++ b/ajax.php
@@ -30,5 +30,5 @@ $dispatcher = patterns('',
         url_get('^client', 'client')
     ))
 );
-print $dispatcher->resolve($_SERVER['PATH_INFO']);
+print $dispatcher->resolve($ost->get_path_info());
 ?>
diff --git a/api/http.php b/api/http.php
index 0fc32444aebbc2640a93359de39265c961873f6e..90926d1e5b531771c057ca82276711520c305b9e 100644
--- a/api/http.php
+++ b/api/http.php
@@ -26,5 +26,5 @@ $dispatcher = patterns('',
         );
 
 # Call the respective function
-print $dispatcher->resolve($_SERVER['PATH_INFO']);
+print $dispatcher->resolve($ost->get_path_info());
 ?>
diff --git a/include/class.osticket.php b/include/class.osticket.php
index a65c2799507433c342b3e9103dcb2832c69de0b8..512d390e284bdd64b7587f523f71c2ec75712fe4 100644
--- a/include/class.osticket.php
+++ b/include/class.osticket.php
@@ -325,6 +325,43 @@ class osTicket {
 
         return true;
     }
+    /*
+     * Util functions
+     *
+     */
+
+    function get_var($index, $vars, $default='', $type=null) {
+
+        if(is_array($vars)
+                && array_key_exists($index, $vars)
+                && (!$type || gettype($vars[$index])==$type))
+            return $vars[$index];
+
+        return $default;
+    }
+
+    function get_db_input($index, $vars, $quote=true) {
+        return db_input($this->get_var($index, $vars), $quote);
+    }
+
+    function get_path_info() {
+        if(isset($_SERVER['PATH_INFO']))
+            return $_SERVER['PATH_INFO'];
+
+        if(isset($_SERVER['ORIG_PATH_INFO']))
+            return $_SERVER['ORIG_PATH_INFO'];
+
+        //TODO: conruct possible path info.
+
+        return null;
+    }
+
+    /* returns true if script is being executed via commandline */
+    function is_cli() {
+        return (!strcasecmp(substr(php_sapi_name(), 0, 3), 'cli')
+                || (!$_SERVER['REQUEST_METHOD'] && !$_SERVER['HTTP_HOST']) //Fallback when php-cgi binary is used via cli
+                );
+    }
 
     /**** static functions ****/
     function start($configId) {
@@ -338,13 +375,6 @@ class osTicket {
 
         return $ost;
     }
-
-    /* is_cli */
-    function is_cli() {
-        return (!strcasecmp(substr(php_sapi_name(), 0, 3), 'cli')
-                || (!$_SERVER['REQUEST_METHOD'] && !$_SERVER['HTTP_HOST']) //Fallback when php-cgi binary is used via cli
-                );
-    }
 }
 
 ?>
diff --git a/include/class.upgrader.php b/include/class.upgrader.php
index 7e45e9e6a0e33933148ac7133b280c2759f09fd4..8b86b9e5724f07ea3fbb4bf3132a554e79ca7586 100644
--- a/include/class.upgrader.php
+++ b/include/class.upgrader.php
@@ -23,13 +23,16 @@ class Upgrader extends SetupWizard {
     var $sqldir;
     var $signature;
 
+    var $state;
+    var $mode;
+
     function Upgrader($signature, $prefix, $sqldir) {
 
         $this->signature = $signature;
-        $this->shash = substr($signature, 0, 8);
         $this->prefix = $prefix;
         $this->sqldir = $sqldir;
         $this->errors = array();
+        $this->mode = 'ajax'; //
 
         //Disable time limit if - safe mode is set.
         if(!ini_get('safe_mode'))
@@ -38,6 +41,8 @@ class Upgrader extends SetupWizard {
         //Init persistent state of upgrade.
         $this->state = &$_SESSION['ost_upgrader']['state'];
 
+        $this->mode = &$_SESSION['ost_upgrader']['mode'];
+
         //Init the task Manager.
         if(!isset($_SESSION['ost_upgrader'][$this->getShash()]))
             $_SESSION['ost_upgrader'][$this->getShash()]['tasks']=array();
@@ -45,8 +50,8 @@ class Upgrader extends SetupWizard {
         //Tasks to perform - saved on the session.
         $this->tasks = &$_SESSION['ost_upgrader'][$this->getShash()]['tasks'];
 
-        //Database migrater 
-        $this->migrater = new DatabaseMigrater($this->signature, SCHEMA_SIGNATURE, $this->sqldir);
+        //Database migrater
+        $this->migrater = null;
     }
 
     function onError($error) {
@@ -87,7 +92,7 @@ class Upgrader extends SetupWizard {
     }
 
     function getShash() {
-        return $this->shash;
+        return  substr($this->getSchemaSignature(), 0, 8);
     }
 
     function getTablePrefix() {
@@ -106,13 +111,31 @@ class Upgrader extends SetupWizard {
         $this->state = $state;
     }
 
+    function getMode() {
+        return $this->mode;
+    }
+
+    function setMode($mode) {
+        $this->mode = $mode;
+    }
+
+    function getMigrater() {
+        if(!$this->migrater)
+            $this->migrater = new DatabaseMigrater($this->signature, SCHEMA_SIGNATURE, $this->sqldir);
+
+        return  $this->migrater;
+    }
+
     function getPatches() {
-        return $this->migrater->getPatches();
+        $patches = array();
+        if($this->getMigrater())
+            $patches = $this->getMigrater()->getPatches();
+
+        return $patches;
     }
 
     function getNextPatch() {
-        $p = $this->getPatches();
-        return (count($p)) ? $p[0] : false;
+        return (($p=$this->getPatches()) && count($p)) ? $p[0] : false;
     }
 
     function getNextVersion() {
@@ -140,7 +163,7 @@ class Upgrader extends SetupWizard {
         $action='Upgrade osTicket to '.$this->getVersion();
         if($this->getNumPendingTasks() && ($task=$this->getNextTask())) {
             $action = $task['desc'];
-            if($task['status']) //Progress report... 
+            if($task['status']) //Progress report...
                 $action.=' ('.$task['status'].')';
         } elseif($this->isUpgradable() && ($nextversion = $this->getNextVersion())) {
             $action = "Upgrade to $nextversion";
@@ -161,9 +184,9 @@ class Upgrader extends SetupWizard {
             foreach($tasks as $k => $task) {
                 if(!$task['done'])
                     $pending[$k] = $task;
-            }  
+            }
         }
-        
+
         return $pending;
     }
 
@@ -198,7 +221,11 @@ class Upgrader extends SetupWizard {
         if(!($tasks=$this->getPendingTasks()))
             return true; //Nothing to do.
 
-        $ost->logDebug('Upgrader', sprintf('There are %d pending upgrade tasks', count($tasks)));
+        $c = count($tasks);
+        $ost->logDebug(
+                sprintf('Upgrader - %s (%d pending tasks).', $this->getShash(), $c),
+                sprintf('There are %d pending upgrade tasks for %s patch', $c, $this->getShash())
+                );
         $start_time = Misc::micro_time();
         foreach($tasks as $k => $task) {
             //TODO: check time used vs. max execution - break if need be
@@ -211,7 +238,7 @@ class Upgrader extends SetupWizard {
 
         return $this->getPendingTasks();
     }
-    
+
     function upgrade() {
         global $ost;
 
@@ -227,18 +254,20 @@ class Upgrader extends SetupWizard {
             if (!$this->load_sql_file($patch, $this->getTablePrefix()))
                 return false;
 
-            //clear previous patch info - 
+            //clear previous patch info -
             unset($_SESSION['ost_upgrader'][$this->getShash()]);
 
             $phash = substr(basename($patch), 0, 17);
+            $shash = substr($phash, 9, 8);
 
             //Log the patch info
-            $logMsg = "Patch $phash applied ";
+            $logMsg = "Patch $phash applied successfully ";
             if(($info = $this->readPatchInfo($patch)) && $info['version'])
                 $logMsg.= ' ('.$info['version'].') ';
 
-            $ost->logDebug('Upgrader - Patch applied', $logMsg);
-            
+            $ost->logDebug("Upgrader - $shash applied", $logMsg);
+            $this->signature = $shash; //Update signature to the *new* HEAD
+
             //Check if the said patch has scripted tasks
             if(!($tasks=$this->getTasksForPatch($phash))) {
                 //Break IF elapsed time is greater than 80% max time allowed.
@@ -250,16 +279,14 @@ class Upgrader extends SetupWizard {
             }
 
             //We have work to do... set the tasks and break.
-            $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;
-
         }
 
+        //Reset the migrater
+        $this->migrater = null;
+
         return true;
 
     }
@@ -286,9 +313,9 @@ class Upgrader extends SetupWizard {
                 break;
         }
 
-        //Check IF SQL cleanup exists. 
+        //Check IF SQL cleanup exists.
         $file=$this->getSQLDir().$phash.'.cleanup.sql';
-        if(file_exists($file)) 
+        if(file_exists($file))
             $tasks[] = array('func' => 'cleanup',
                              'desc' => 'Post-upgrade cleanup!',
                              'phash' => $phash);
@@ -306,7 +333,7 @@ class Upgrader extends SetupWizard {
         if(!file_exists($file)) //No cleanup script.
             return 0;
 
-        //We have a cleanup script  ::XXX: Don't abort on error? 
+        //We have a cleanup script  ::XXX: Don't abort on error?
         if($this->load_sql_file($file, $this->getTablePrefix(), false, true))
             return 0;
 
@@ -317,7 +344,7 @@ class Upgrader extends SetupWizard {
 
     function migrateAttachments2DB($taskId) {
         global $ost;
-        
+
         if(!($max_time = ini_get('max_execution_time')))
             $max_time = 30; //Default to 30 sec batches.
 
@@ -330,7 +357,7 @@ class Upgrader extends SetupWizard {
 
     function migrateSessionFile2DB($taskId) {
         # How about 'dis for a hack?
-        osTicketSession::write(session_id(), session_encode()); 
+        osTicketSession::write(session_id(), session_encode());
         return 0;
     }
 
diff --git a/include/upgrader/upgrade.inc.php b/include/upgrader/upgrade.inc.php
index fae6947d94849c6cfbd4a7df849df708e470f1de..b157b6a030e4e0e23165a4a5720e31fe114ea133 100644
--- a/include/upgrader/upgrade.inc.php
+++ b/include/upgrader/upgrade.inc.php
@@ -1,5 +1,16 @@
 <?php
 if(!defined('OSTSCPINC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
+
+//See if we need to switch the mode of upgrade...e.g from ajax (default) to manual
+if(($mode = $ost->get_var('m', $_GET)) &&  $mode!=$upgrader->getMode()) {
+    //Set Persistent mode/
+    $upgrader->setMode($mode);
+    //Log warning about ajax calls - most likely culprit is AcceptPathInfo directive.
+    if($mode=='manual')
+        $ost->logWarning('Ajax calls are failing',
+                'Make sure your server has AcceptPathInfo directive set to "ON" or get technical help');
+}
+
 $action=$upgrader->getNextAction();
 ?>
 <h2>osTicket Upgrade</h2>
@@ -9,7 +20,7 @@ $action=$upgrader->getNextAction();
              <p>Thank you for taking the time to upgrade your osTicket intallation!</p>
              <p>Please don't cancel or close the browser, any errors at this stage will be fatal.</p>
             </div>
-            <h2><?php echo $action ?></h2>
+            <h2 id="task"><?php echo $action ?></h2>
             <p>The upgrade wizard will now attempt to upgrade your database and core settings!</p>
             <ul>
                 <li>Database enhancements</li>
@@ -20,8 +31,9 @@ $action=$upgrader->getNextAction();
                 <form method="post" action="upgrade.php" id="upgrade">
                     <?php csrf_token(); ?>
                     <input type="hidden" name="s" value="upgrade">
+                    <input type="hidden" id="mode" name="m" value="<?php echo $upgrader->getMode(); ?>">
                     <input type="hidden" name="sh" value="<?php echo $upgrader->getSchemaSignature(); ?>">
-                    <input class="btn"  type="submit" name="submit" value="Do It Now!">
+                    <input class="btn"  type="submit" name="submit" value="Upgrade Now!">
                 </form>
             </div>
     </div>
@@ -33,9 +45,11 @@ $action=$upgrader->getNextAction();
     </div>
     <div class="clear"></div>
     <div id="upgrading">
-        <h4><?php echo $action; ?></h4>
+        <h4 id="action"><?php echo $action; ?></h4>
         Please wait... while we upgrade your osTicket installation!
-        <div id="msg" style="font-weight: bold;padding-top:10px;">Smile!</div>
+        <div id="msg" style="font-weight: bold;padding-top:10px;">
+            <?php echo sprintf("%s - Relax!", $thisstaff->getFirstName()); ?>
+        </div>
     </div>
 </div>
-<div class="clear"></div>`
+<div class="clear"></div>
diff --git a/scp/ajax.php b/scp/ajax.php
index e4100f4e31c4f4028086e4608785df4fcdebba41..0f0771d3742efe983fe325fff52fe937f31e8dc5 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -27,7 +27,7 @@ require('staff.inc.php');
 ini_set('display_errors','0'); //Disable error display
 ini_set('display_startup_errors','0');
 
-//TODO: disable direct access via the browser? i,e All request must have REFER? 
+//TODO: disable direct access via the browser? i,e All request must have REFER?
 if(!defined('INCLUDE_DIR'))	Http::response(500, 'Server configuration error');
 
 require_once INCLUDE_DIR.'/class.dispatcher.php';
@@ -65,5 +65,5 @@ $dispatcher = patterns('',
 );
 
 # Call the respective function
-print $dispatcher->resolve($_SERVER['PATH_INFO']);
+print $dispatcher->resolve($ost->get_path_info());
 ?>
diff --git a/scp/js/upgrader.js b/scp/js/upgrader.js
index 1631ac5cd5a7a156498f44e6f13020dae875dde2..2ac77d99f86c5db1b2a54d36f4afc709e2b9bad5 100644
--- a/scp/js/upgrader.js
+++ b/scp/js/upgrader.js
@@ -1,5 +1,5 @@
 jQuery(function($) {
-            
+
     $("#overlay").css({
         opacity : 0.3,
         top     : 0,
@@ -12,18 +12,21 @@ jQuery(function($) {
         top  : ($(window).height() / 3),
         left : ($(window).width() / 2 - 160)
         });
-        
+
     $('form#upgrade').submit(function(e) {
-        e.preventDefault();
         var form = $(this);
         $('input[type=submit]', this).attr('disabled', 'disabled');
         $('#overlay, #upgrading').show();
-        doTasks('upgrade.php',form.serialize());
-
-        return false;
-        });
+        if($('input#mode', form).val() == 'manual') {
+            return  true;
+        } else {
+            e.preventDefault();
+            autoUpgrade('upgrade.php',form.serialize());
+            return false;
+        }
+      });
 
-    function doTasks(url, data) {
+    function autoUpgrade(url, data) {
         function _lp(count) {
             $.ajax({
                 type: 'POST',
@@ -33,26 +36,34 @@ jQuery(function($) {
                 data: data,
                 dataType: 'text',
                 success: function(res) {
-                    if (res) { 
-                        $('#loading #msg').html(res);
-                    }
+                    $('#main #task').html(res);
+                    $('#upgrading #action').html(res);
+                    $('#upgrading #msg').html('Still busy... smile #'+count);
                 },
                 statusCode: {
                     200: function() {
-                        setTimeout(function() { _lp(count+1); }, 2);
+                        setTimeout(function() { _lp(count+1); }, 200);
                     },
 
                     201: function() {
-                        $('#loading #msg').html("We're done... cleaning up!");
+                        $('#upgrading #msg').html("Cleaning up!...");
                         setTimeout(function() { location.href =url+'?c='+count+'&r='+Math.floor((Math.random()*100)+1); }, 3000);
                     }
                 },
-                error: function() {
-                    $('#loading #msg').html("Something went wrong");
-                    setTimeout(function() { location.href =url+'?c='+count+'&r='+Math.floor((Math.random()*100)+1); }, 1000);
+                error: function(jqXHR, textStatus, errorThrown) {
+                    $('#upgrading #action').html('Error occurred. Aborting...');
+                    switch(jqXHR.status) {
+                        case 404:
+                            $('#upgrading #msg').html("Manual upgrade required (ajax failed)");
+                            setTimeout(function() { location.href =url+'?m=manual&c='+count+'&r='+Math.floor((Math.random()*100)+1); }, 2000);
+                            break;
+                        default:
+                            $('#upgrading #msg').html("Something went wrong");
+                            setTimeout(function() { location.href =url+'?c='+count+'&r='+Math.floor((Math.random()*100)+1); }, 2000);
+                    }
                 }
             });
         };
-        _lp(0);
+        _lp(1);
     }
 });