diff --git a/client.inc.php b/client.inc.php
index b714e93b44bd587f4d10a2f292b2d4890bc63a3f..3b450e9e2491653ec44c65f346ef79758cc1d1a8 100644
--- a/client.inc.php
+++ b/client.inc.php
@@ -28,21 +28,12 @@ define('OSTCLIENTINC',TRUE);
 
 define('ASSETS_PATH',ROOT_PATH.'assets/default/');
 
-
 //Check the status of the HelpDesk.
-if(!is_object($cfg) || !$cfg->getId() || $cfg->isHelpDeskOffline()) {
+if(!is_object($cfg) || !$cfg->getId() || $cfg->isHelpDeskOffline() || $cfg->isUpgradePending()) {
     include('./offline.php');
     exit;
 }
 
-//Forced upgrade? Version mismatch.
-if(defined('THIS_VERSION') && strcasecmp($cfg->getVersion(),THIS_VERSION)) {
-    die('System is offline for an upgrade.');
-    exit;
-}
-
-
-
 /* include what is needed on client stuff */
 require_once(INCLUDE_DIR.'class.client.php');
 require_once(INCLUDE_DIR.'class.ticket.php');
diff --git a/include/class.config.php b/include/class.config.php
index c51814bebc73aef1ae3a9052db364d2702798c04..e54c0d7392d8268c9b273ed2f802a562dcaf20b3 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -67,22 +67,35 @@ class Config {
         return !$this->isSystemOnline();
     }
 
+    function isHelpDeskOnline() {
+        return $this->isSystemOnline();
+    }
+
     function isSystemOnline() {
-        return ($this->config['isonline']);
+        return ($this->config['isonline'] && !$this->isUpgradePending());
     }
 
-    function isKnowledgebaseEnabled() {
+    function isUpgradePending() {
+        return (defined('SCHEMA_SIGNATURE') && strcasecmp($this->getSchemaSignature(), SCHEMA_SIGNATURE));
+    }
 
+    function isKnowledgebaseEnabled() {
         require_once(INCLUDE_DIR.'class.faq.php');
         return ($this->config['enable_kb'] && FAQ::countPublishedFAQs());
     }
 
     function getVersion() {
-        return '1.7-DPR2';
+        return THIS_VERSION;
     }
 
     function getSchemaSignature() {
-        return $this->config['schema_signature'];
+
+        if($this->config['schema_signature'])
+            return $this->config['schema_signature'];
+        elseif($this->config['ostversion']) //old version 1.6 st.
+            return md5($this->config['ostversion']);
+
+        return null;
     }
 
     function setMysqlTZ($tz) {
diff --git a/scp/admin.inc.php b/scp/admin.inc.php
index a580fa6986b87661b039419bcf178e5ae46ad12e..8b3da09e6e6fbd55eeb81f9a93f9216fb6fe183e 100644
--- a/scp/admin.inc.php
+++ b/scp/admin.inc.php
@@ -15,34 +15,29 @@
 **********************************************************************/
 require('staff.inc.php');
 //Make sure config is loaded and the staff is set and of admin type
-if(!$cfg or !$thisstaff or !$thisstaff->isadmin()){
+if(!$cfg or !$thisstaff or !$thisstaff->isadmin()) {
     header('Location: index.php');
     require('index.php'); // just in case!
     exit;
 }
 
 //Some security related warnings - bitch until fixed!!! :)
-if(defined('THIS_VERSION') && strcasecmp($cfg->getVersion(),THIS_VERSION)) {
-    $sysnotice=sprintf('The script is version %s while the database is version %s.',THIS_VERSION,$cfg->getVersion());
-    if(file_exists('../setup/'))
-        $sysnotice.=' Possibly caused by incomplete <a href="../setup/upgrade.php">upgrade</a>.';
-    $errors['err']=$sysnotice; 
-}elseif(!$cfg->isHelpDeskOffline()) {
-    if(file_exists('../setup/')){
-        $sysnotice='Please take a minute to delete <strong>setup/install</strong> directory for security reasons.';
-    }else{
-
-        if(CONFIG_FILE && file_exists(CONFIG_FILE) && is_writable(CONFIG_FILE)) {
+if($cfg->isUpgradePending()) {
+    $errors['err']=$sysnotice='System upgrade is pending <a href="../setup/upgrade.php">Upgrade Now</a>';
+} elseif(!$cfg->isHelpDeskOffline()) {
+    
+    if(file_exists('../setup/')) {
+        $sysnotice='Please take a minute to delete <strong>setup/install</strong> directory (../setup/) for security reasons.';
+    } elseif(CONFIG_FILE && file_exists(CONFIG_FILE) && is_writable(CONFIG_FILE)) {
             //Confirm for real that the file is writable by group or world.
             clearstatcache(); //clear the cache!
             $perms = @fileperms(CONFIG_FILE);
             if(($perms & 0x0002) || ($perms & 0x0010)) { 
                 $sysnotice=sprintf('Please change permission of config file (%s) to remove write access. e.g <i>chmod 644 %s</i>',
-                                basename(CONFIG_FILE),basename(CONFIG_FILE));
+                                basename(CONFIG_FILE), basename(CONFIG_FILE));
             }
-        }
-
     }
+
     if(!$sysnotice && ini_get('register_globals'))
         $sysnotice='Please consider turning off register globals if possible';
 }
diff --git a/scp/staff.inc.php b/scp/staff.inc.php
index b3ee30a4ec3a555c2fd8c3c86ed6e72b2c6517ca..bddf874cf976f4a170b3782330b7fdc3b8a87732 100644
--- a/scp/staff.inc.php
+++ b/scp/staff.inc.php
@@ -63,19 +63,19 @@ if(!$thisstaff || !is_object($thisstaff) || !$thisstaff->getId() || !$thisstaff-
     exit;
 }
 //2) if not super admin..check system status and group status
-if(!$thisstaff->isadmin()){
-    //Staff are not allowed to login in offline mode!!
-    if($cfg->isHelpDeskOffline()){
-        staffLoginPage('System Offline');
-        exit;
-    }
+if(!$thisstaff->isadmin()) {
     //Check for disabled staff or group!
     if(!$thisstaff->isactive() || !$thisstaff->isGroupActive()) {
         staffLoginPage('Access Denied. Contact Admin');
         exit;
     }
-}
 
+    //Staff are not allowed to login in offline mode!!
+    if($cfg->isHelpDeskOffline() || $cfg->isUpgradePending()) {
+        staffLoginPage('System Offline');
+        exit;
+    }
+}
 
 //Keep the session activity alive
 $thisstaff->refreshSession();
@@ -93,10 +93,9 @@ $errors=array();
 $msg=$warn=$sysnotice='';
 $tabs=array();
 $submenu=array();
-
-if(defined('THIS_VERSION') && strcasecmp($cfg->getVersion(),THIS_VERSION)) {
-    $errors['err']=$sysnotice=sprintf('The script is version %s while the database is version %s',THIS_VERSION,$cfg->getVersion());
-}elseif($cfg->isHelpDeskOffline()){
+if($cfg->isUpgradePending()) {
+    $errors['err']=$sysnotice='System upgrade is pending <a href="../setup/upgrade.php">Upgrade Now</a>';
+} elseif($cfg->isHelpDeskOffline()) {
     $sysnotice='<strong>System is set to offline mode</strong> - Client interface is disabled and ONLY admins can access staff control panel.';
     $sysnotice.=' <a href="settings.php">Enable</a>.';
 }
diff --git a/setup/cleanup.php b/setup/cleanup.php
deleted file mode 100644
index 1309228eb6c64eaaee6f16926ec98b06d91d0221..0000000000000000000000000000000000000000
--- a/setup/cleanup.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/*********************************************************************
-    cleanup.php
-
-    Cleanup script called via ajax to migrate attachments.
-
-    Peter Rotich <peter@osticket.com>
-    Copyright (c)  2006-2012 osTicket
-    http://www.osticket.com
-
-    Released under the GNU General Public License WITHOUT ANY WARRANTY.
-    See LICENSE.TXT for details.
-
-    vim: expandtab sw=4 ts=4 sts=4:
-**********************************************************************/
-session_start();
-if($_GET['c']>10) { //When Done send 304 - nothing else to do.
-    $_SESSION['s']='done';
-    session_write_close();
-    header("HTTP/1.1 304 Not Modified"); 
-    exit;
-}
-echo "Cleaning up...".time(); 
-?>
diff --git a/setup/css/wizard.css b/setup/css/wizard.css
index 6fd18e17854f65a30a2947460a955ca4c403541c..c92b05447a6acb9992ea21be3ce13581840784a9 100644
--- a/setup/css/wizard.css
+++ b/setup/css/wizard.css
@@ -70,7 +70,7 @@ form .row span { width: 600px; color: #666666; }
 
 #overlay { display: none; position: fixed; background: #000; z-index: 2000; }
 
-#loading { padding: 10px 10px 10px 60px; width: 300px; height: 100px; background: url('../images/ajax-loader.gif?1312925608') 10px 50% no-repeat white; position: fixed; display: none; z-index: 3000; }
+#loading { padding: 10px 10px 10px 60px; width: 400px; height: 150px; background: url('../images/ajax-loader.gif?1312925608') 10px 50% no-repeat white; position: fixed; display: none; z-index: 3000; }
 #loading h4 { margin: 3px 0 0 0; padding: 0; color: #d80; }
 
 .tip { display: inline-block; width: 16px; height: 16px; outline: none; text-decoration: none; color: #d80; }
diff --git a/setup/inc/class.setup.php b/setup/inc/class.setup.php
index 21b4f33ee6b51a23a1459575e164e0fcfe673c1f..4662c2333738bdba6c221d4ace0caca2639bcc48 100644
--- a/setup/inc/class.setup.php
+++ b/setup/inc/class.setup.php
@@ -21,8 +21,8 @@ Class SetupWizard {
                         'mysql' => '4.4');
 
     //Version info - same as the latest version.
-    var $version ='1.7-rc1';
-    var $version_verbose='1.7 RC 1';
+    var $version ='1.7-dpr2';
+    var $version_verbose='1.7 DPR 2';
 
     //Errors
     var $errors=array();
@@ -31,18 +31,18 @@ Class SetupWizard {
         $this->errors=array();
     }
 
-    function load_sql_file($file, $prefix, $debug=false) {
+    function load_sql_file($file, $prefix, $abort=true, $debug=false) {
         
         if(!file_exists($file) || !($schema=file_get_contents($file)))
-            return $this->abort('Error accessing SQL file');
+            return $this->abort('Error accessing SQL file '.basename($file));
 
-        return $this->load_sql($schema, $prefix, $debug);
+        return $this->load_sql($schema, $prefix, $abort, $debug);
     }
 
     /*
         load SQL schema - assumes MySQL && existing connection
         */
-    function load_sql($schema, $prefix, $debug=false) {
+    function load_sql($schema, $prefix, $abort=true, $debug=false) {
 
         # Strip comments and remarks
         $schema=preg_replace('%^\s*(#|--).*$%m','',$schema);
@@ -57,7 +57,8 @@ Class SetupWizard {
         foreach($statements as $k=>$sql) {
             if(!mysql_query($sql)) {
                 if($debug) echo "[$sql]=>".mysql_error();
-                return $this->abort("[$sql] - ".mysql_error());
+                if($abort)
+                    return $this->abort("[$sql] - ".mysql_error());
             }
         }
 
@@ -96,15 +97,18 @@ Class SetupWizard {
         @error is a mixed var.
     */
     function abort($error) {
-        
+       
+        $this->onError($error);
+
+        return false; // Always false... It's an abort.
+    }
 
+    function setError($error) {
+    
         if($error && is_array($error))
             $this->errors = array_merge($this->errors,$error);
         elseif($error)
             $this->errors[] = $error;
-
-        //Always returns FALSE.
-        return false;
     }
 
     function getErrors(){
@@ -112,91 +116,271 @@ Class SetupWizard {
         return $this->errors;
     }
 
-    /* Access and user validation*/
-
-    function getThisUser() {
-
-
+    function onError($error) {
+       return $this->setError($error);
     }
 }
 
 class Upgrader extends SetupWizard {
 
     var $prefix;
+    var $sqldir;
+    var $signature;
 
-    function Upgrader($prefix) {
+    function Upgrader($signature, $prefix, $sqldir) {
+
+        $this->signature = $signature;
+        $this->shash = substr($signature, 0, 8);
         $this->prefix = $prefix;
+        $this->sqldir = $sqldir;
         $this->errors = array();
+
+        //Init persistent state of upgrade.
+        $this->state = &$_SESSION['ost_upgrader'][$this->getShash()]['state'];
+
+        //Init the task Manager.
+        if(!isset($_SESSION['ost_upgrader'][$this->getShash()]))
+            $_SESSION['ost_upgrader'][$this->getShash()]['tasks']=array();
+
+        //Tasks to perform - saved on the session.
+        $this->tasks = &$_SESSION['ost_upgrader'][$this->getShash()]['tasks'];
+    }
+
+    function onError($error) {
+        $this->setError($error);
+        $this->setState('aborted');
+    }
+
+    function isUpgradable() {
+        return (!$this->isAborted() && $this->getNextPatch());
+    }
+
+    function isAborted() {
+        return !strcasecmp($this->getState(), 'aborted');
+    }
+
+    function getSchemaSignature() {
+        return $this->signature;
+    }
+
+    function getShash() {
+        return $this->shash;
     }
 
     function getTablePrefix() {
         return $this->prefix;
     }
 
-    /* upgrade magic related to the given version */
-    function upgradeTo($version) {
+    function getSQLDir() {
+        return $this->sqldir;
+    }
 
-        $errors = array();
-        switch($version) {
-            case '1.7-RC1':
-                //TODO: latest upgrade logic.
-                break;
-            case '1.6 ST':
-                //TODO: refactor code from 1.6 ST.
-                break;
-            case '1.6 RC5':
-                //TODO: refactor code from 1.6 ST.
+    function getState() {
+        return $this->state;
+    }
+
+    function setState($state) {
+        $this->state = $state;
+    }
+
+    function getNextPatch() {
+
+        if(!($patch=glob($this->getSQLDir().$this->getShash().'-*.patch.sql')))
+            return null;
+
+        return $patch[0];
+    }
+
+    function getThisPatch() {
+                
+        if(!($patch=glob($this->getSQLDir().'*-'.$this->getShash().'.patch.sql')))
+            return null;
+
+        return $patch[0];
+
+    }
+
+    function getNextVersion() {
+        if(!$patch=$this->getNextPatch())
+            return '(Latest)';
+
+        if(preg_match('/\*(.*)\*/', file_get_contents($patch), $matches))
+            $info=$matches[0];
+        else
+            $info=substr(basename($patch), 9, 8);
+
+        return $info;
+    }
+
+    function getNextAction() {
+
+        $action='Upgrade osTicket to '.$this->getVersion();
+        if($this->getNumPendingTasks() && ($task=$this->getNextTask())) {
+            $action = $task['desc'];
+            if($task['status']) //Progress report... 
+                $action.=' ('.$task['status'].')';
+        } elseif($this->isUpgradable() && ($nextversion = $this->getNextVersion())) {
+            $action = "Upgrade to $nextversion";
+        }
+
+        return $action;
+    }
+
+    function getNextStepInfo() {
+
+        if(($patches=$this->getPatches()))
+            return $patches[0];
+        
+        if(($hooks=$this->getScriptedHooks()))
+            return $hooks[0]['desc'];
+
+        return null;
+    }
+
+    function getPatches($ToSignature) {
+     
+        $signature = $this->getSignature();
+        $patches = array();
+        while(($patch=glob($this->getSQLDir().substr($signature,0,8).'-*.patch.sql')) && $i++) {
+            $patches = array_merge($patches, $patch);
+            if(!($signature=substr(basename($patch[0]), 10, 8)) || !strncasecmp($signature, $ToSignature, 8))
                 break;
-            default:
-                //XXX: escape version 
-                return $this->abort('Trying to upgrade unknown version '.$version);
         }
 
-        if($errors)
-            return $this->abort($errors);
+        return $patches;
+    }
 
-        return true;
+    function getNumPendingTasks() {
+
+        return count($this->getPendingTasks());
     }
 
-    /*
-       Do base upgrade
-       Does fall-through upgrade until we reach the current version.
-       We're assumming the user - is upgrading upgradable version of osTicket!
-        @version - version number to upgrade from!
-       */
-    function upgradeFrom($version) {
-
-        if(!$version || $this->getErrors())
+    function getPendingTasks() {
+
+        $pending=array();
+        if(($tasks=$this->getTasks())) {
+            foreach($tasks as $k => $task) {
+                if(!$task['done'])
+                    $pending[$k] = $task;
+            }  
+        }
+        
+        return $pending;
+    }
+
+    function getTasks() {
+       return $this->tasks;
+    }
+
+    function getNextTask() {
+
+        if(!($tasks=$this->getPendingTasks()))
+            return null;
+
+        return current($tasks);
+    }
+
+    function removeTask($tId) {
+
+        if(isset($this->tasks[$tId]))
+            unset($this->tasks[$tId]);
+
+        return (!$this->tasks[$tId]);
+    }
+
+    function setTaskStatus($tId, $status) {
+        if(isset($this->tasks[$tId]))
+            $this->tasks[$tId]['status'] = $status;
+    }
+
+    function doTasks() {
+
+        if(!($tasks=$this->getPendingTasks()))
+            return true; //Nothing to do.
+
+        foreach($tasks as $k => $task) {
+            if(call_user_func(array($this, $task['func']), $k)===0) {
+                $this->tasks[$k]['done'] = true;
+            } else { //Task has pending items to process.
+                break;
+            }
+        }
+
+        return (!$this->getPendingTasks());
+    }
+    
+    function upgrade() {
+
+        if($this->getPendingTasks() || !($patch=$this->getNextPatch()))
+            return false;
+
+        if(!$this->load_sql_file($patch, $this->getTablePrefix()))
             return false;
+
+        //TODO: Log the upgrade
+
+        //Load up post install tasks.
+        $shash = substr(basename($patch), 9, 8); 
+        $phash = substr(basename($patch), 0, 17); 
         
-        if(!strcasecmp($version,$this->getVersion()))
-            return true;
-
-        //XXX: Note FALLTHROUGH (we only break on error) and uppercase cases.
-        switch(strtoupper($version)) {
-            case 'OLD': //Upgrade old versions to 1.6 ST.
-                if(!$this->upgradeTo('1.6 RC5')) break;
-                /* FALLTHROUGH */
-            case '1.6 RC5': //Upgrade 1.6 RC5 to 1.6 ST
-                if(!$this->upgradeTo('1.6 ST')) break;
-                /* FALLTHROUGH */
-            case '1.6 ST': //Upgrade 1.6 ST to to 1.7 RC1
-                if(!$this->upgradeTo('1.7-RC1')) break;
-                /* LAST CASE IS NOT FALLTHROUGH */
+        $tasks=array();
+        $tasks[] = array('func' => 'sometask',
+                         'desc' => 'Some Task.... blah');
+        switch($phash) { //Add  patch specific scripted tasks.
+            case 'xxxx': //V1.6 ST- 1.7 *
+                $tasks[] = array('func' => 'migrateAttachments2DB',
+                                 'desc' => 'Migrating attachments to database, it might take a while depending on the number of files.');
                 break;
-            default: //Catch all - Upgrading older versions 1.3+ 
-                return $this->upgradeFrom('OLD');
         }
-        //XXX: Set errors???
-       
-        return (!$this->getErrors());
+        
+        $tasks[] = array('func' => 'cleanup',
+                         'desc' => 'Post-upgrade cleanup!');
+        
+        
+        
+        //Load up tasks - NOTE: writing directly to the session - back to the future majic.
+        $_SESSION['ost_upgrader'][$shash]['tasks'] = $tasks;
+        $_SESSION['ost_upgrader'][$shash]['state'] = 'upgrade';
+
+        //clear previous patch info - 
+        unset($_SESSION['ost_upgrader'][$this->getSHash()]);
+
+        return true;
     }
 
-    function cleanup() {
-        //FIXME: cleanup logic here.
+    /************* TASKS **********************/
+    function sometask($tId) {
+        
+        $this->setTaskStatus($tId, 'Doing... '.time(). ' #'.$_SESSION['sometask']);
+
         sleep(2);
+        $_SESSION['sometask']+=1;
+        if($_SESSION['sometask']<4)
+            return 22;
 
-        return true;
+        $_SESSION['sometask']=0;
+
+        return 0;  //Change to 1 for testing...
+    }
+
+    function cleanup($tId=0) {
+
+        $file=$this->getSQLDir().$this->getSchemaSignature().'-cleanup.sql';
+        if(!file_exists($file)) //No cleanup script.
+            return 0;
+
+        //We have a cleanup script  ::XXX: Don't abort on error? 
+        if($this->load_sql_file($file, $this->getTablePrefix(), false, true))
+            return 0;
+
+        //XXX: ???
+        return false;
+    }
+    
+
+    function migrateAttachments2DB($tId=0) {
+        echo "Process attachments here - $tId";
+        return 0;
     }
 }
 
@@ -297,7 +481,7 @@ class Installer extends SetupWizard {
             $this->errors['err']='Unable to read config file. Permission denied! (#2)';
         elseif(!($fp = @fopen($this->getConfigFile(),'r+')))
             $this->errors['err']='Unable to open config file for writing. Permission denied! (#3)';
-        elseif(!$this->load_sql_file($schemaFile,$vars['prefix'],$debug))
+        elseif(!$this->load_sql_file($schemaFile,$vars['prefix'], true, $debug))
             $this->errors['err']='Error parsing SQL schema! Get help from developers (#4)';
               
         if(!$this->errors) {
diff --git a/setup/inc/sql/patches/02decaa2-60fcbee1.patch.sql b/setup/inc/sql/02decaa2-60fcbee1.patch.sql
similarity index 100%
rename from setup/inc/sql/patches/02decaa2-60fcbee1.patch.sql
rename to setup/inc/sql/02decaa2-60fcbee1.patch.sql
diff --git a/setup/inc/sql/patches/522e5b78-02decaa2.patch.sql b/setup/inc/sql/522e5b78-02decaa2.patch.sql
similarity index 91%
rename from setup/inc/sql/patches/522e5b78-02decaa2.patch.sql
rename to setup/inc/sql/522e5b78-02decaa2.patch.sql
index 6dc1f3a8afdb8fe83f75a7f10e9852284432725e..a6d9a6e09cc1c16aac70dc6a9b4a0f03987a6c9b 100644
--- a/setup/inc/sql/patches/522e5b78-02decaa2.patch.sql
+++ b/setup/inc/sql/522e5b78-02decaa2.patch.sql
@@ -1,3 +1,4 @@
+/* v1.7-DPR2-P2 */
 UPDATE `%TABLE_PREFIX%sla`
     SET `created` = NOW(),
         `updated` = NOW()
diff --git a/setup/inc/sql/patches/60fcbee1-f8856d56.patch.sql b/setup/inc/sql/60fcbee1-f8856d56.patch.sql
similarity index 100%
rename from setup/inc/sql/patches/60fcbee1-f8856d56.patch.sql
rename to setup/inc/sql/60fcbee1-f8856d56.patch.sql
diff --git a/setup/inc/sql/patches/7be60a84-522e5b78.patch.sql b/setup/inc/sql/7be60a84-522e5b78.patch.sql
similarity index 91%
rename from setup/inc/sql/patches/7be60a84-522e5b78.patch.sql
rename to setup/inc/sql/7be60a84-522e5b78.patch.sql
index 17ab3e07bd82c42df9b5cf7b2a73107afffbb499..35e744566d50f8a5e8d37d56c3fe3b795db2e1e5 100644
--- a/setup/inc/sql/patches/7be60a84-522e5b78.patch.sql
+++ b/setup/inc/sql/7be60a84-522e5b78.patch.sql
@@ -1,3 +1,4 @@
+/* v1.7-DPR1 (P1) */ 
 UPDATE `%TABLE_PREFIX%email_template`
     SET `ticket_overlimit_subj` = 'Open Tickets Limit Reached'
     WHERE `tpl_id` = 1 AND `cfg_id` = 1;
diff --git a/setup/inc/upgrade-aborted.inc.php b/setup/inc/upgrade-aborted.inc.php
index 8d8f64aa831841dd9431f017c7289760ba18448e..8624590d35710a42906952afab82b2688f028315 100644
--- a/setup/inc/upgrade-aborted.inc.php
+++ b/setup/inc/upgrade-aborted.inc.php
@@ -6,17 +6,18 @@ if(!defined('SETUPINC')) die('Kwaheri!');
     <div id="intro">
         <p>Upgrade aborted due to errors. Any errors at this stage are fatal. Please note the error(s), if any, when contacting us.<p>
         <?php
-        if($_SESSION['upgrader']['errors']) {
-            $errors=$_SESSION['upgrader']['errors'];
+        if($upgrader && ($errors=$upgrader->getErrors())) {
             if($errors['err'])
                 echo sprintf('<b><font color="red">%s</font></b>',$errors['err']);
-                
             echo '<ul class="error">';
             unset($errors['err']);
-            foreach($errors as $k=>$error)
+            foreach($errors as $k => $error)
                 echo sprintf('<li>%s</li>',$error);
             echo '</ul>';
-        } ?>
+        } else {
+            echo '<b><font color="red">Internal error occurred - get technical help.</font></b>';
+        }
+        ?>
         <p>Please, refer to the <a target="_blank" href="http://osticket.com/wiki/Upgrade_and_Migration">Upgrade Guide</a> on the wiki for more information.</p>
     </div>
     <p><strong>Need Help?</strong> We provide <a target="_blank" href="http://osticket.com/support/professional_services.php"><u>professional upgrade services</u></a> and commercial support. <a target="_blank" href="http://osticket.com/support/">Contact us</a> today for expedited help.</p>
diff --git a/setup/inc/upgrade-attachments.inc.php b/setup/inc/upgrade-attachments.inc.php
deleted file mode 100644
index c8155d32c672e358cb068d79720a076327a88706..0000000000000000000000000000000000000000
--- a/setup/inc/upgrade-attachments.inc.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-if(!defined('SETUPINC')) die('Kwaheri!');
-$msg = $_SESSION['ost_upgrader']['msg'];
-?>    
-<div id="main">
-    <h1>Attachments Migration</h1>
-    <p>We're almost done! We're now migrating attachments to the database, it might take a while dending on the number of files in your database.<p>
-    <p style="color:#FF7700;font-weight:bold;">We have to migrate files in batches for technical reasons.</p>
-    <p>Please don't cancel or close the browser.</p>
-            
-    <div id="bar">
-        <form method="post" action="upgrade.php" id="attachments">
-            <input type="hidden" name="s" value="cleanup">
-            <input class="btn"  type="submit" name="submit" value="Next Batch">
-        </form>
-        
-    </div>
-</div>
-<div id="sidebar">
-    <h3>Upgrade Tips</h3>
-    <p>1. Be patient the process will take a few minutes.</p>
-    <p>2. If you experience any problems, you can always restore your files/dabase backup.</p>
-    <p>3. We can help, feel free to <a href="http://osticket.com/support/" target="_blank">contact us </a> for professional help.</p>    
-</div>    
-<div id="overlay"></div>
-    <div id="loading">
-        <h4>Moving attachments</h4>
-        <br>
-        Please wait... while we migrate attachments!
-        <br><br>
-        <div id="msg" style="font-weight: bold;"><?php echo Format::htmlchars($msg); ?></div>
-    </div>
diff --git a/setup/inc/upgrade-cleanup.inc.php b/setup/inc/upgrade-cleanup.inc.php
deleted file mode 100644
index f8406ae533a9efbce73e864239d749b586e8f66e..0000000000000000000000000000000000000000
--- a/setup/inc/upgrade-cleanup.inc.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-if(!defined('SETUPINC')) die('Kwaheri!');
-
-?>
-    <div id="main">
-            <h1>osTicket Upgrade</h1>
-            <div id="intro">
-             <p>We're almost done! Please don't cancel or close the browser, any errors at this stage will be fatal.</p>
-            </div>
-            <h2>Cleanup: Step 2 of 2</h2>
-            <p>The upgrade wizard will now attempt to do post upgrade cleanup. It might take a while dending on the size of your database. </p>
-            <ul>
-                <li>Setting Changes</li>
-                <li>Attachment Migration</li>
-                <li>Database Optimization</li>
-            </ul>
-            <div id="bar">
-                <form method="post" action="upgrade.php" id="cleanup">
-                    <input type="hidden" name="s" value="cleanup">
-                    <input class="btn"  type="submit" name="submit" value="Do It Now!">
-                </form>
-            </div>
-    </div>
-    <div id="sidebar">
-            <h3>Upgrade Tips</h3>
-            <p>1. Be patient the process will take a couple of seconds.</p>
-            <p>2. If you experience any problems, you can always restore your files/dabase backup.</p>
-            <p>3. We can help, feel free to <a href="http://osticket.com/support/" target="_blank">contact us </a> for professional help.</p>
-    </div>
-
-    <div id="overlay"></div>
-    <div id="loading">
-        <h4>Doing serious stuff!</h4>
-        <br>
-        Please wait... while we do post-upgrade cleanup!
-        <br><br>
-        <div id="msg" style="font-weight: bold;"></div>
-    </div>
diff --git a/setup/inc/upgrade-core.inc.php b/setup/inc/upgrade-core.inc.php
deleted file mode 100644
index ec42e50437537ea01931484a18e86c902ba909b1..0000000000000000000000000000000000000000
--- a/setup/inc/upgrade-core.inc.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-if(!defined('SETUPINC')) die('Kwaheri!');
-
-?>
-    <div id="main">
-            <h1>osTicket Upgrade</h1>
-            <div id="intro">
-             <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>Base upgrade: Step 1 of 2</h2>
-            <p>The upgrade wizard will now attempt to upgrade your database and core settings!</p>
-            <ul>
-                <li>Database enhancements</li>
-                <li>New and updated features</li>
-                <li>Enhance settings and security</li>
-            </ul>
-            <div id="bar">
-                <form method="post" action="upgrade.php" id="upgrade">
-                    <input type="hidden" name="s" value="upgrade">
-                    <input class="btn"  type="submit" name="submit" value="Do It Now!">
-                </form>
-            </div>
-    </div>
-    <div id="sidebar">
-            <h3>Upgrade Tips</h3>
-            <p>1. Be patient the process will take a couple of seconds.</p>
-            <p>2. If you experience any problems, you can always restore your files/dabase backup.</p>
-            <p>3. We can help, feel free to <a href="http://osticket.com/support/" target="_blank">contact us </a> for professional help.</p>
-    </div>
-
-    <div id="overlay"></div>
-    <div id="loading">
-        <h4>Doing serious stuff!</h4>
-        Please wait... while we upgrade your osTicket installation!
-        <div id="udb"><br><b>Smile!</b></div>
-    </div>
diff --git a/setup/inc/upgrade-prereq.inc.php b/setup/inc/upgrade-prereq.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..5f60cece25500679de83b01981ea05ac634949e9
--- /dev/null
+++ b/setup/inc/upgrade-prereq.inc.php
@@ -0,0 +1,50 @@
+<?php
+if(!defined('SETUPINC')) die('Kwaheri!');
+
+?>
+    <div id="main">
+            <h1>osTicket Upgrade!</h1>
+            <font color="red"><b><?php echo $errors['err']; ?></b></font>
+            <div id="intro">
+             <p>Thank you for being a loyal osTicket user!</p>
+             <p>The upgrade wizard will guide you every step of the way in the upgrade process. While we try to ensure that the upgrade process is straightforward and painless, we can't guarantee it will be the case for every user.</p>
+            </div>
+            <h2>Getting ready!</h2>
+            <p>Before we begin, we'll check your server configuration to make sure you meet the minimum requirements to run the latest version of osTicket.</p>
+            <h3>Prerequisites: <font color="red"><?php echo $errors['prereq']; ?></font></h3>
+            These items are necessary in order to use osTicket the latest version of osTicket.
+            <ul class="progress">
+                <li class="<? echo $upgrader->check_php()?'yes':'no'; ?>">
+                PHP v4.3 or greater - (<small><b><?php echo PHP_VERSION; ?></b></small>)</li>
+                <li class="<? echo $upgrader->check_mysql()?'yes':'no'; ?>">
+                MySQL v4.4 or greater - (<small><b><?php echo extension_loaded('mysql')?'module loaded':'missing!'; ?></b></small>)</li>
+            </ul>
+            <h3>Higly Recommended:</h3>
+            We hightly recommend that you follow the steps below.
+            <ul>
+                <li>Take osTicket offline momentarily during upgrade.</li>
+                <li>Backup the current database, if you haven't done so already.</li>
+                <li>Be patient the upgrade process will take a couple of seconds.</li>
+            </ul>
+            <div id="bar">
+                <form method="post" action="upgrade.php" id="prereq">
+                    <input type="hidden" name="s" value="prereq">
+                    <input class="btn"  type="submit" name="submit" value="Start Upgrade Now &raquo;">
+                </form>
+            </div>
+    </div>
+    <div id="sidebar">
+            <h3>Upgrade Tips</h3>
+            <p>1. Remember to backup your osTicket database</p>
+            <p>2. Take osTicket offline momentarily</p>
+            <p>3. If you experience any problems, you can always restore your files/dabase backup.</p>
+            <p>4. We can help, feel free to <a href="http://osticket.com/support/" target="_blank">contact us </a> for professional help.</p>
+
+    </div>
+
+    <div id="overlay"></div>
+    <div id="loading">
+        <h4>Doing stuff!</h4>
+        Please wait... while we upgrade your osTicket installation!
+        <div id="udb"></div>
+    </div>
diff --git a/setup/inc/upgrade.inc.php b/setup/inc/upgrade.inc.php
index e5b8ba77bef7da18c547820031d1ca294b2b4dea..6f05cd169c66d49163908d8a6c6bef9d5b9a1a18 100644
--- a/setup/inc/upgrade.inc.php
+++ b/setup/inc/upgrade.inc.php
@@ -1,50 +1,40 @@
 <?php
-if(!defined('SETUPINC')) die('Kwaheri!');
+if(!defined('SETUPINC') || !$upgrader)  die('Kwaheri!');
+$action=$upgrader->getNextAction();
 
 ?>
     <div id="main">
-            <h1>osTicket Upgrade!</h1>
-            <font color="red"><b><?php echo $errors['err']; ?></b></font>
+            <h1>osTicket Upgrade</h1>
             <div id="intro">
-             <p>Thank you for being a loyal osTicket user!</p>
-             <p>The upgrade wizard will guide you every step of the way in the upgrade process. While we try to ensure that the upgrade process is straightforward and painless, we can't guarantee it will be the case for every user.</p>
+             <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>Getting ready!</h2>
-            <p>Before we begin, we'll check your server configuration to make sure you meet the minimum requirements to run the latest version of osTicket.</p>
-            <h3>Prerequisites: <font color="red"><?php echo $errors['prereq']; ?></font></h3>
-            These items are necessary in order to use osTicket the latest version of osTicket.
-            <ul class="progress">
-                <li class="<? echo $upgrader->check_php()?'yes':'no'; ?>">
-                PHP v4.3 or greater - (<small><b><?php echo PHP_VERSION; ?></b></small>)</li>
-                <li class="<? echo $upgrader->check_mysql()?'yes':'no'; ?>">
-                MySQL v4.4 or greater - (<small><b><?php echo extension_loaded('mysql')?'module loaded':'missing!'; ?></b></small>)</li>
-            </ul>
-            <h3>Higly Recommended:</h3>
-            We hightly recommend that you follow the steps below.
+            <h2><?php echo $action ?></h2>
+            <p>The upgrade wizard will now attempt to upgrade your database and core settings!</p>
             <ul>
-                <li>Take osTicket offline momentarily during upgrade.</li>
-                <li>Backup the current database, if you haven't done so already.</li>
-                <li>Be patient the upgrade process will take a couple of seconds.</li>
+                <li>Database enhancements</li>
+                <li>New and updated features</li>
+                <li>Enhance settings and security</li>
             </ul>
             <div id="bar">
                 <form method="post" action="upgrade.php" id="upgrade">
-                    <input type="hidden" name="s" value="prereq">
-                    <input class="btn"  type="submit" name="submit" value="Start Upgrade Now &raquo;">
+                    <input type="hidden" name="s" value="upgrade">
+                    <input type="hidden" name="sh" value="<?php echo $upgrader->getSchemaSignature(); ?>">
+                    <input class="btn"  type="submit" name="submit" value="Do It Now!">
                 </form>
             </div>
     </div>
     <div id="sidebar">
             <h3>Upgrade Tips</h3>
-            <p>1. Remember to backup your osTicket database</p>
-            <p>2. Take osTicket offline momentarily</p>
-            <p>3. If you experience any problems, you can always restore your files/dabase backup.</p>
-            <p>4. We can help, feel free to <a href="http://osticket.com/support/" target="_blank">contact us </a> for professional help.</p>
-
+            <p>1. Be patient the process will take a couple of seconds.</p>
+            <p>2. If you experience any problems, you can always restore your files/dabase backup.</p>
+            <p>3. We can help, feel free to <a href="http://osticket.com/support/" target="_blank">contact us </a> for professional help.</p>
     </div>
 
     <div id="overlay"></div>
     <div id="loading">
-        <h4>Doing stuff!</h4>
+        <h4><?php echo $action; ?></h4>
         Please wait... while we upgrade your osTicket installation!
-        <div id="udb"></div>
+        <div id="msg" style="font-weight: bold;padding-top:10px;">Smile!</div>
     </div>
diff --git a/setup/js/setup.js b/setup/js/setup.js
index 5d274ea3198bbec310c20abef16ac68df51ee270..b1f8e08c3aa48397206c43ad854fc3bf4815473c 100644
--- a/setup/js/setup.js
+++ b/setup/js/setup.js
@@ -13,30 +13,30 @@ jQuery(function($) {
         left : ($(window).width() / 2 - 160)
         });
         
-    $('form#install, form#upgrade, form#attachments').submit(function(e) {
+    $('form#install').submit(function(e) {
         $('input[type=submit]', this).attr('disabled', 'disabled');
         $('#overlay, #loading').show();
         return true;
         });
 
-    $('form#cleanup').submit(function(e) {
+    $('form#upgrade').submit(function(e) {
         e.preventDefault();
         var form = $(this);
         $('input[type=submit]', this).attr('disabled', 'disabled');
         $('#overlay, #loading').show();
-        doCleanup('upgrade',form.attr('action'));
+        doTasks('upgrade.php',form.serialize());
+
         return false;
         });
 
-
-    function doCleanup(type,url) {
+    function doTasks(url, data) {
         function _lp(count) {
             $.ajax({
                 type: 'GET',
-                url: 'cleanup.php',
+                url: 'p.php',
                 async: true,
                 cache: false,
-                data: {c:count,type:type},
+                data: data,
                 dataType: 'text',
                 success: function(res) {
                     if (res) { 
@@ -45,16 +45,17 @@ jQuery(function($) {
                 },
                 statusCode: {
                     200: function() {
-                        setTimeout(function() { _lp(count+1); },2);
+                        setTimeout(function() { _lp(count+1); }, 2);
                     },
 
                     304: function() {
-                        $('#loading #msg').html("We're done... ");
-                        setTimeout(function() { location.href =url;},1000);
+                        $('#loading #msg').html("We're done... cleaning up!");
+                        setTimeout(function() { location.href =url;}, 3000);
                     }
                 },
-                error: function(){
-                    alert("Something went wrong");
+                error: function() {
+                    $('#loading #msg').html("Something went wrong");
+                    setTimeout(function() { location.href =url;}, 1000);
                 }
             });
         };
diff --git a/setup/p.php b/setup/p.php
new file mode 100644
index 0000000000000000000000000000000000000000..b508c9303f1b33a951b15e7dbafc8e0047c3ff3a
--- /dev/null
+++ b/setup/p.php
@@ -0,0 +1,68 @@
+<?php
+/*********************************************************************
+    upgrader.php
+
+    osTicket Upgrader Helper - called via ajax.
+
+    Peter Rotich <peter@osticket.com>
+    Copyright (c)  2006-2012 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+function staffLoginPage($msg) {
+    Http::response(403, $msg?$msg:'Access Denied');
+    exit;
+}
+
+require '../scp/staff.inc.php';
+if(!$thisstaff or !$thisstaff->isadmin()) {
+    staffLoginPage('Admin Access Required!');
+    exit;
+}
+
+define('SETUPINC', true);
+define('INC_DIR', './inc/');
+define('SQL_DIR', INC_DIR.'sql/');
+require_once INC_DIR.'class.setup.php';
+
+
+$upgrader = new Upgrader($cfg->getSchemaSignature(), TABLE_PREFIX, SQL_DIR);
+
+//Just report the next action on the first call.
+if(!$_SESSION['ost_upgrader'][$upgrader->getSHash()]['progress']) {
+    $_SESSION['ost_upgrader'][$upgrader->getSHash()]['progress'] = $upgrader->getNextAction();
+    Http::response(200, $upgrader->getNextAction());
+    exit;
+}
+
+if($upgrader->getNumPendingTasks()) {
+    if($upgrader->doTasks() && !$upgrader->getNumPendingTasks() && $cfg->isUpgradePending()) {
+        //Just reporting done...with tasks - break in between patches!
+        header("HTTP/1.1 304 Not Modified");
+        exit;
+    }
+} elseif($cfg->isUpgradePending() && $upgrader->isUpgradable()) {
+    $version = $upgrader->getNextVersion();
+    if($upgrader->upgrade()) {
+        //We're simply reporting progress here - call back will report next action'
+        Http::response(200, "Upgraded to $version ... post-upgrade checks!");
+        exit;
+    }
+} elseif(!$cfg->isUpgradePending()) {
+    $upgrader->setState('done');
+    session_write_close();
+    header("HTTP/1.1 304 Not Modified");
+    exit;
+}
+
+if($upgrader->isAborted() || $upgrader->getErrors()) {
+    Http::response(416, "We have a problem ... wait a sec.");
+    exit;
+}
+
+Http::response(200, $upgrader->getNextAction());
+?>
diff --git a/setup/setup.inc.php b/setup/setup.inc.php
index f2af40af61e1b7e94b9ae915eb1e81e103560594..d8108e079c5a0df0411ff57cce4d1ecb97eb9e87 100644
--- a/setup/setup.inc.php
+++ b/setup/setup.inc.php
@@ -57,5 +57,4 @@ require_once(INCLUDE_DIR.'class.validator.php');
 require_once(INCLUDE_DIR.'class.format.php');
 require_once(INCLUDE_DIR.'class.misc.php');
 require_once(INCLUDE_DIR.'mysql.php');
-
 ?>
diff --git a/setup/upgrade.php b/setup/upgrade.php
index 6fc34cfd307cfcc9df319deb25101ec159f52d75..c70d183ffe290de4a09ade74b1ff7ec47bd4acde 100644
--- a/setup/upgrade.php
+++ b/setup/upgrade.php
@@ -13,5 +13,84 @@
 
     vim: expandtab sw=4 ts=4 sts=4:
 **********************************************************************/
-die('Upgrade NOT supported for v1.7 DPR.');
+function staffLoginPage($msg) {
+        
+    $_SESSION['_staff']['auth']['dest']=THISPAGE;
+    $_SESSION['_staff']['auth']['msg']=$msg;
+    header('Location: ../scp/login.php');
+    exit;
+}
+
+require '../scp/staff.inc.php';
+if(!$thisstaff or !$thisstaff->isadmin()) {
+    staffLoginPage('Admin Access Required!');
+    exit;
+}
+
+define('SETUPINC', true);
+define('INC_DIR', './inc/');
+define('SQL_DIR', INC_DIR.'sql/');
+require_once INC_DIR.'class.setup.php';
+
+//$_SESSION['ost_upgrader']=null;
+$upgrader = new Upgrader($cfg->getSchemaSignature(), TABLE_PREFIX, SQL_DIR);
+
+
+$wizard=array();
+$wizard['title']='osTicket Upgrade Wizard';
+$wizard['tagline']='Upgrading osTicket to v'.$upgrader->getVersionVerbose();
+$wizard['logo']='logo-upgrade.png';
+$wizard['menu']=array('Upgrade Guide'=>'http://osticket.com/wiki/Upgrade_and_Migration',
+                      'Get Professional Help'=>'http://osticket.com/support');
+$errors=array();
+if($_POST && $_POST['s'] && !$upgrader->isAborted()) {
+    switch(strtolower($_POST['s'])) {
+        case 'prereq':
+            //XXX: check if it's upgradable version??
+            if(!$cfg->isUpgradePending())
+                $errors['err']=' Nothing to do! System already upgraded to the current version'; 
+            elseif($upgrader->check_prereq())
+                $upgrader->setState('upgrade');
+            else
+                $errors['prereq']='Minimum requirements not met!';
+            break;
+        case 'upgrade': //Manual upgrade.... when JS (ajax) is not supported.
+            if($upgrader->getNumPendingTasks()) {
+                $upgrader->doTasks();
+            } elseif($cfg->isUpgradePending() && $upgrader->isUpgradable()) {
+                $upgrader->upgrade();
+            } elseif(!$cfg->isUpgradePending()) {
+                $upgrader->setState('done');
+            }
+
+            if(($errors=$upgrader->getErrors()))  {
+                $upgrader->setState('aborted');
+            }
+            break;
+        default:
+            $errors['err']='Unknown action!';
+    }
+}
+
+switch(strtolower($upgrader->getState())) {
+    case 'aborted':
+        $inc='upgrade-aborted.inc.php';
+        break;
+    case 'upgrade':
+        $inc='upgrade.inc.php';
+        break;
+    case 'done':
+        $inc='upgrade-done.inc.php';
+        break;
+    default:
+        $inc='upgrade-prereq.inc.php';
+        if($upgrader->isAborted())
+            $inc='upgrade-aborted.inc.php';
+        elseif(!$cfg->isUpgradePending())
+            $errors['err']='Nothing to do! System already upgraded to the latest version';
+}
+
+require(INC_DIR.'header.inc.php');
+require(INC_DIR.$inc);
+require(INC_DIR.'footer.inc.php');
 ?>