[pLog-svn] r5990 - plog/branches/lifetype-1.2

reto at devel.lifetype.net reto at devel.lifetype.net
Fri Oct 19 16:49:08 EDT 2007


Author: reto
Date: 2007-10-19 16:49:07 -0400 (Fri, 19 Oct 2007)
New Revision: 5990

Added:
   plog/branches/lifetype-1.2/wizard.php
Log:
hmmm, somehow the wizard lost its file extension (php).
strange...



Copied: plog/branches/lifetype-1.2/wizard.php (from rev 5989, plog/branches/lifetype-1.2/wizard)
===================================================================
--- plog/branches/lifetype-1.2/wizard.php	                        (rev 0)
+++ plog/branches/lifetype-1.2/wizard.php	2007-10-19 20:49:07 UTC (rev 5990)
@@ -0,0 +1,2367 @@
+|<?php
+
+    if (!defined( "PLOG_CLASS_PATH" )) {
+        define( "PLOG_CLASS_PATH", dirname(__FILE__)."/");
+    }
+
+    set_time_limit (5 * 3600);
+
+    //
+    // enable this for debugging purposes
+    //
+    define( "DB_WIZARD_DEBUG", false );
+
+    //
+    // in case you're having problems with time outs while upgrading (probably too
+    // many records) lower this figure
+    //
+    define( "WIZARD_MAX_RECORDS_PER_STEP", 75 );
+    
+    //
+    // minimum php version required
+    //
+    define( "MIN_PHP_VERSION", "4.2.0" );
+    
+    //
+    // whether data transformers should fail on error by default
+    // It might be convenient to set this to 'false' if we're running
+    // the wizard on top of an already updated installation
+    //
+    define( "DATABASE_DATA_TRANSFORMER_FAIL_ON_ERROR_DEFAULT", true );
+
+    // many hosts don't have this enabled and we, for the time being, need it...
+    ini_set("arg_seperator.output", "&amp;");
+
+    include_once( PLOG_CLASS_PATH."class/bootstrap.php" );
+    lt_include( PLOG_CLASS_PATH."class/controller/controller.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/template/templateservice.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/action/action.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/database/db.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/template/template.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/view/view.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/data/validator/usernamevalidator.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/data/validator/stringvalidator.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/data/validator/integervalidator.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/data/validator/emailvalidator.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/data/validator/passwordvalidator.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/data/timestamp.class.php" );    
+    lt_include( PLOG_CLASS_PATH."class/net/http/httpvars.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/misc/version.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/file/file.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/file/finder/filefinder.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/gallery/resizers/gddetector.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/config/configfilestorage.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/data/textfilter.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/locale/locales.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/locale/localefinder.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesets.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/bloginfo.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/users.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/blogs.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/articlecategories.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/articles.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/mylinkscategories.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/userpermissions.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/blogcategories.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/dao/globalarticlecategories.class.php" );
+    lt_include( PLOG_CLASS_PATH."class/gallery/dao/galleryalbums.class.php" );     
+	lt_include( PLOG_CLASS_PATH."class/dao/permissions.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/dao/userpermissions.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/dao/permission.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/dao/userpermission.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/dao/userinfo.class.php" );
+	lt_include( PLOG_CLASS_PATH."class/misc/integritychecker.class.php" );
+    
+    // table schemas
+    include( PLOG_CLASS_PATH."install/dbschemas.properties.php" );
+    // default configuration values for 1.1
+    include( PLOG_CLASS_PATH."install/defaultconfig.properties.php" );
+
+    define( "TEMP_FOLDER", "./tmp" );
+
+    // maps used to map requests with actions
+    $_actionMap["Checks"] = "WizardChecks";
+    $_actionMap["Default"] = "WizardChecks";
+    $_actionMap["Intro"] = "WizardIntro";
+    $_actionMap["Step1"] = "WizardStepOne";
+    $_actionMap["Step2"] = "WizardStepTwo";
+    $_actionMap["Step3"] = "WizardStepThree";
+    $_actionMap["Step4"] = "WizardStepFour";
+    $_actionMap["Step5"] = "WizardStepFive";
+    $_actionMap["Update1"] = "UpdateStepOne";
+    $_actionMap["Update2"] = "UpdateStepTwo";
+    $_actionMap["Update3"] = "UpdateStepThree";
+    $_actionMap["Fix120"] = "Fix120StepOne";
+
+
+    /**
+     * Open a connection to the database
+     */
+     function connectDb( $ignoreError = false , $selectDatabase = true )
+     {
+        $config = new ConfigFileStorage();
+        // open a connection to the database
+        //$db = NewADOConnection('mysql');
+        $db = PDb::getDriver('mysql');
+        
+        if ( $selectDatabase ) {
+            $res = $db->Connect($config->getValue( "db_host" ), $config->getValue( "db_username" ), $config->getValue( "db_password" ), $config->getValue( "db_database" ), $config->getValue( "db_character_set" ));
+        } else {
+            $res = $db->Connect($config->getValue( "db_host" ), $config->getValue( "db_username" ), $config->getValue( "db_password" ), null, $config->getValue( "db_character_set" ));
+        }
+
+        if( DB_WIZARD_DEBUG )
+            $db->debug = true;
+
+        // return error
+        if( $ignoreError )
+            return $db;
+
+        if( !$res )
+            return false;
+
+        return $db;
+    }
+
+    /**
+     * Returns the database prefix
+     */
+    function getDbPrefix()
+    {
+        $config = new ConfigFileStorage();
+        return $config->getValue( "db_prefix" );
+    }
+
+    /**
+     * some useful little functions
+     */
+    class WizardTools
+    {
+       /**
+        * returns true if plog has already been installed before or
+        * false otherwise
+        */
+       function isNewInstallation()
+       {
+           $configFile = new ConfigFileStorage();
+           // if plog hasn't been installed, this file will have empty settings
+           if( $configFile->getValue( "db_host") == "" && $configFile->getValue( "db_username") == "" &&
+               $configFile->getValue( "db_database") == "" && $configFile->getValue( "db_prefix" ) == "" &&
+               $configFile->getValue( "db_password" ) == "" )
+               $isNew = true;
+           else
+               $isNew = false;
+
+           return( $isNew );
+       }
+
+		/**
+		 * Clean up the default temporary folder
+		 */
+		function cleanTmpFolder()
+		{
+			// remove the files recursively, but only files, do not do anything to directories
+			File::deleteDir( TEMP_FOLDER, true, true, array(".svn", ".htaccess") );
+		}
+    }
+
+    /**
+     * Renders a template file.
+     */
+    class WizardView extends View
+    {
+
+        var $_templateName;
+
+        function WizardView( $templateName )
+        {
+            $this->View();
+            $this->_templateName = $templateName;
+        }
+
+        function render()
+        {
+            // build the file name
+            $templateFileName = "wizard/".$this->_templateName.".template";
+
+            //$t = new Template( $templateFileName, "" );
+            $t = new Smarty();
+            $v = new Version();
+            $this->_params->setValue( "version", $v->getVersion());
+            $this->_params->setValue( "projectPage", $v->getProjectPage());
+            $this->_params->setValue( "safeMode", ini_get("safe_mode"));
+            $t->assign( $this->_params->getAsArray());
+            $t->template_dir    = "./templates";
+            $t->compile_dir     = TEMP_FOLDER;
+            $t->cache_dir       = TEMP_FOLDER;
+            $t->use_sub_dirs    = false;
+            $t->caching = false;
+
+            print $t->fetch( $templateFileName );
+        }
+    }
+    
+    class WizardAction extends Action
+    {
+        function WizardAction( $actionInfo, $request )
+        {
+            $this->Action( $actionInfo, $request );
+        }
+    }    
+    
+    class WizardValidator
+    {
+        var $_desc;
+        var $_critical;
+        var $_valid;
+        var $_solution;
+    
+        function WizardValidator( $desc = "", $solution = "", $critical = true )
+        {            
+            $this->_desc = $desc;
+            $this->_critical = $critical;
+            $this->_valid = false;
+            $this->_solution = $solution;
+        }
+        
+        function isCritical()
+        {
+            return( $this->_critical );
+        }
+        
+        function getDesc()
+        {
+            return( $this->_desc );
+        }
+        
+        function isValid()
+        {
+            return( $this->_valid );
+        }
+        
+        function getSolution()
+        {
+            return( $this->_solution );
+        }
+        
+        function validate() 
+        {
+            return( $this->_valid );
+        }        
+    }
+    
+    class WizardPhpVersionValidator extends WizardValidator
+    {
+        function WizardPhpVersionValidator( $minVersion = MIN_PHP_VERSION )
+        {
+            $this->WizardValidator( "Checking if the installed <b>PHP</b> version is at least $minVersion", 
+                                    "Please upgrade your version of PHP to $minVersion or newer",
+                                    true );
+            $this->_minVersion = $minVersion;
+        }
+    
+        function validate()
+        {
+            $this->_valid = version_compare( phpversion(), $this->_minVersion ) >= 0;
+            return( parent::validate());
+        }
+    }
+    
+    class WizardWritableFileValidator extends WizardValidator
+    {
+        var $_file;
+        
+        function WizardWritableFileValidator( $file )
+        {
+            $this->WizardValidator( "Checking if file/folder <b>$file</b> is writable", 
+                                    "Please make sure that the file is writable by the web server",
+                                    true );
+            $this->_file = $file;
+        }
+    
+        function validate()
+        {
+            $this->_valid = File::isWritable( $this->_file );
+            return( parent::validate());
+        }
+    }
+    
+    class WizardSessionFunctionsAvailableValidator extends WizardValidator
+    {
+        function WizardSessionFunctionsAvailableValidator()
+        {
+            $this->WizardValidator( "Checking if <b>session</b> functions are available", 
+                                    "LifeType requires support for sessions to be part of your PHP installation",
+                                    true );
+        }
+    
+        function validate()
+        {
+            $this->_valid = function_exists( "session_start" ) &&
+                            function_exists( "session_destroy" ) &&
+                            function_exists( "session_cache_limiter" ) &&
+                            function_exists( "session_name" ) &&
+                            function_exists( "session_set_cookie_params" ) &&
+                            function_exists( "session_save_path" );
+            return( parent::validate());            
+        }
+    }
+
+    class WizardSessionSettingsValidator extends WizardValidator
+    {
+        function WizardSessionSettingsValidator()
+        {
+            $this->WizardValidator( "Checking if <b>session.auto_start</b> is disabled", 
+                                    "LifeType can only run when session.auto_start is disabled.",           
+                                    true );
+        }    
+    
+        function validate()
+        {
+            $this->_valid = (ini_get( "session.auto_start" ) == "0");
+            return( parent::validate());    
+        }
+    }
+       
+    class WizardMySQLFunctionsAvailableValidator extends WizardValidator
+    {
+        function WizardMySQLFunctionsAvailableValidator()
+        {
+            $this->WizardValidator( "Checking if <b>MySQL</b> functions are available", 
+                                    "LifeType requires support for MySQL to be part of your PHP installation",
+                                    true );
+        }
+    
+        function validate()
+        {
+            $this->_valid = function_exists( "mysql_select_db" ) &&
+                            function_exists( "mysql_query" ) &&
+                            function_exists( "mysql_connect" ) &&
+                            function_exists( "mysql_fetch_assoc" ) &&
+                            function_exists( "mysql_num_rows" ) &&
+                            function_exists( "mysql_free_result" );
+            return( parent::validate());                            
+        }        
+    }
+    
+    class WizardXmlFunctionsAvailableValidator extends WizardValidator
+    {
+        function WizardXmlFunctionsAvailableValidator()
+        {
+            $this->WizardValidator( "Checking if <b>XML</b> functions are available", 
+                                    "LifeType requires support for XML to be part of your PHP installation",
+                                    true );
+        }    
+    
+        function validate()
+        {
+            $this->_valid = function_exists( "xml_set_object" ) &&
+                            function_exists( "xml_set_element_handler" ) &&
+                            function_exists( "xml_parser_create" ) &&
+                            function_exists( "xml_parser_set_option" ) &&
+                            function_exists( "xml_parse" ) &&
+                            function_exists( "xml_parser_free" );
+            return( parent::validate());                            
+        }        
+    }
+    
+    class WizardSafeModeValidator extends WizardValidator
+    {
+        function WizardSafeModeValidator()
+        {
+            $this->WizardValidator( "Checking if <b>safe mode</b> is disabled", 
+                                    "LifeType can run when PHP's safe mode is enabled, but it may cause some problems.",           
+                                    false );
+        }    
+    
+        function validate()
+        {
+            $this->_valid = (ini_get( "safe_mode" ) == "");
+            return( parent::validate());    
+        }
+    }
+
+    class WizardIconvFunctionsAvailableValidator extends WizardValidator
+    {
+        function WizardIconvFunctionsAvailableValidator()
+        {
+            $this->WizardValidator( "Checking if <b>iconv</b> functions are available", 
+                                    "LifeType requires support for some resource metadata conversion and some LifeType plugins requires support for multi-byte language encoding/decoding.",
+                                    false );
+        }
+    
+        function validate()
+        {
+            $this->_valid = function_exists( "iconv" );
+            return( parent::validate());                            
+        }        
+    }
+
+    class WizardMbstringFunctionsAvailableValidator extends WizardValidator
+    {
+        function WizardMbstringFunctionsAvailableValidator()
+        {
+            $this->WizardValidator( "Checking if <b>mbstring</b> functions are available", 
+                                    "Some LifeType plugins requires support for multi-byte language encoding/decoding.",
+                                    false );
+        }
+    
+        function validate()
+        {
+            $this->_valid = function_exists( "mb_convert_encoding" );
+            return( parent::validate());                            
+        }        
+    }
+
+    class WizardGdFunctionsAvailableValidator extends WizardValidator
+    {
+        function WizardGdFunctionsAvailableValidator()
+        {
+            $this->WizardValidator( "Checking if <b>gd</b> or <b>gd2</b> functions are available", 
+                                    "LifeType requires support for generating image thumbnail.",
+                                    false );
+        }
+    
+        function validate()
+        {
+            $this->_valid = function_exists( "imagecopyresampled" ) &&
+            				function_exists( "imagecopyresized" );
+            return( parent::validate());                            
+        }        
+    }
+    
+    class WizardFileUploadsValidator extends WizardValidator
+    {
+        function WizardFileUploadsValidator()
+        {
+            $this->WizardValidator( "Checking if <b>file_uploads</b> is enabled", 
+                                    "LifeType requires support for uploading resources.",
+                                    true );
+        }    
+    
+        function validate()
+        {
+            $this->_valid = (ini_get( "file_uploads" ) == 1);
+            return( parent::validate());    
+        }
+    }
+
+    class WizardFileIntegrityValidator extends WizardValidator
+    {
+        function WizardFileIntegrityValidator()
+        {
+            $this->WizardValidator( "Checking that all files have been correctly uploaded", 
+                                    "will be set later on...",
+                                    false );
+        }    
+    
+        function validate()
+        {
+			include( PLOG_CLASS_PATH."install/files.properties.php");
+			
+			$result = IntegrityChecker::checkIntegrity( 
+				$data
+			);	
+	
+		
+            $this->_valid = ( count( $result ) == 0 );
+			if( !$this->_valid ) {
+				/* let's modify a private attribute... */
+				$fileList = implode( "<br/>", array_keys( $result ));
+				$this->_solution = "The current version of the following is not the expected one. Installation can proceed but please make sure that all files were uploaded correctly:"."<br/>".$fileList;				
+			}
+
+            return( parent::validate());
+        }
+    }
+    
+    class WizardCtypeFunctionsAvailableValidator extends WizardValidator
+    {
+        function WizardCtypeFunctionsAvailableValidator()
+        {
+            $this->WizardValidator( "Checking if <b>ctype</b> functions are available", 
+                                    "Some LifeType plugins requires support for variable type validation.",
+                                    false );
+        }
+    
+        function validate()
+        {
+            $this->_valid = function_exists( "ctype_digit" );
+            return( parent::validate());                            
+        }        
+    }               
+    
+    class WizardChecks extends WizardAction
+    {        
+        function perform()
+        {
+            // build the array with checks
+            $checkGroups['File checks'] = Array(
+               "writeConfigFile" => new WizardWritableFileValidator( "config/config.properties.php" ),
+               "writeTmpFolder" => new WizardWritableFileValidator( "tmp" ),
+               "writeGalleryFolder" => new WizardWritableFileValidator( "gallery" ),
+			   "fileVersionCheck" => new WizardFileIntegrityValidator()
+            );
+            
+            $checkGroups['PHP version checking'] = Array(
+               "php" => new WizardPhpVersionValidator()
+            );
+
+            $checkGroups['PHP configuration checking'] = Array(
+               "sessionSettings" => new WizardSessionSettingsValidator(),
+               "safemode" => new WizardSafeModeValidator(),
+               "fileUploads" => new WizardFileUploadsValidator()
+            );
+            
+            $checkGroups['PHP functions availability checking'] = Array(
+               "sessions" => new WizardSessionFunctionsAvailableValidator(),
+               "mysql" => new WizardMySQLFunctionsAvailableValidator(),
+               "xml" => new WizardXmlFunctionsAvailableValidator(),
+               "iconv" => new WizardIconvFunctionsAvailableValidator(),
+               "mbstring" => new WizardMbstringFunctionsAvailableValidator(),
+               "gd" => new WizardGdFunctionsAvailableValidator(),
+               "ctype" => new WizardCtypeFunctionsAvailableValidator()
+            );                                    
+            
+            // run the checks
+            $ok = true;
+            foreach( $checkGroups as $checkGroup => $checks ) {
+	            foreach( $checks as $id => $check ) {
+	                $valid = $checkGroups[$checkGroup][$id]->validate();
+	                // if it doesn't validate but it's not critical, then we can proced too
+	                if( !$checkGroups[$checkGroup][$id]->isCritical())
+	                    $valid = true;  
+	                $ok = ($ok && $valid);
+	            }
+	        }
+            
+            // create the view and pass the results
+            $this->_view = new WizardView( "checks" );
+            $this->_view->setValue( "ok", $ok );
+            $this->_view->setValue( "checkGroups", $checkGroups );
+            
+            if( WizardTools::isNewInstallation())
+                $this->_view->setValue( "mode", "install" );
+            else
+                $this->_view->setValue( "mode", "update" );
+
+            return true;
+        }
+    }
+    
+    class WizardPagedAction extends WizardAction
+    {
+        var $willRefresh;
+    
+        function WizardPagedAction( $actionInfo, $request ) 
+        {
+            $this->WizardAction( $actionInfo, $request );
+            
+            $this->willRefresh = false;
+        }
+        
+        /**
+         * @private
+         */
+        function getPageFromRequest()
+        {
+            lt_include( PLOG_CLASS_PATH."class/data/validator/integervalidator.class.php");    	
+			// get the value from the request
+			$page = HttpVars::getRequestValue( "page" );
+			// but first of all, validate it
+			$val = new IntegerValidator();
+			if( !$val->validate( $page ))
+				$page = 1;			
+							
+			return $page;        
+        }
+        
+        /**
+         * @private
+         */
+        function willRefresh()
+        {
+            return( $this->willRefresh );
+        }
+    }
+
+    /**
+     * Gets the information about the database from the user.
+     */
+    class WizardIntro extends WizardAction
+    {
+        function WizardIntro( $actionInfo, $request )
+        {
+            $this->WizardAction( $actionInfo, $request );
+        }
+
+        function perform()
+        {
+            // we can detect whether plog is already installed or not and direct users to the right
+            // place
+            if( WizardTools::isNewInstallation())
+                $this->_view = new WizardView( "intro" );
+            else {
+                Controller::setForwardAction( "Update1" );
+                return false;
+            }
+
+            $this->setCommonData();
+            return true;
+        }
+    }
+
+    /**
+     *
+     * Saves data to the configuration file
+     *
+     */
+    class WizardStepOne extends WizardAction
+    {
+
+        var $_dbServer;
+        var $_dbUser;
+        var $_dbPassword;
+        var $_dbName;
+        var $_dbPrefix;
+        var $_connection;
+
+        function WizardStepOne( $actionInfo, $request )
+        {
+            $this->WizardAction( $actionInfo, $request );
+
+            // data validation
+            $this->registerFieldValidator( "dbServer", new StringValidator());
+            $this->registerFieldValidator( "dbUser", new StringValidator());
+            $this->registerFieldValidator( "dbPassword",  new StringValidator(), true );
+            $this->registerFieldValidator( "dbName", new StringValidator());
+            $this->registerFieldValidator( "dbPrefix", new StringValidator(), true );
+            $errorView = new WizardView( "intro" );
+            $errorView->setErrorMessage( "Some data was incorrect or missing." );
+            $this->setValidationErrorView( $errorView );
+        }
+
+        function perform()
+        {
+            // fetch the data needed from the request
+            $this->_dbServer   = $this->_request->getValue( "dbServer" );
+            $this->_dbUser     = $this->_request->getValue( "dbUser" );
+            $this->_dbPassword = $this->_request->getValue( "dbPassword" );
+            $this->_dbName     = $this->_request->getValue( "dbName" );
+            $this->_skipThis   = $this->_request->getValue( "skipDbInfo" );
+            $this->_dbPrefix   = $this->_request->getValue( "dbPrefix", DEFAULT_DB_PREFIX );
+
+            // we should now save the data to the configuration file, just before
+            // we read it
+            $configFile = new ConfigFileStorage();
+
+            // we expect everything to be fine
+            $errors = false;
+
+            // before doing anything, we should check of the configuration file is
+            // writable by this script, or else, throw an error and bail out gracefully
+            $configFileName = $configFile->getConfigFileName();
+            if( !File::exists( $configFileName )) {
+                if (! File::touch( $configFileName ) ) {
+                    $this->_view = new WizardView( "intro" );
+                    $message = "Could not create the LifeType configuration file $configFileName. Please make sure
+                                that the file can be created by the user running the webserver. It is needed to
+                                store the database configuration settings.";
+                    $this->_view->setErrorMessage( $message );
+                    $this->setCommonData( true );
+                    return false;
+                } else {
+                    ConfigFileStorage::createConfigFile( $configFileName );
+                }
+            }
+            if( File::exists( $configFileName ) && !File::isWritable( $configFileName )) {
+                $this->_view = new WizardView( "intro" );
+                $message = "Please make sure that the file $configFileName can be written by this script during
+                            the installation process. It is needed to store the database configuration settings. Once the
+                            installation is complete, please revert the permissions to no writing possible.";
+                $this->_view->setErrorMessage( $message );
+                $this->setCommonData( true );
+                return false;
+            }
+
+            // continue if everything went fine
+            if( !$configFile->saveValue( "db_username", $this->_dbUser ) ||
+                !$configFile->saveValue( "db_password", $this->_dbPassword ) ||
+                !$configFile->saveValue( "db_host", $this->_dbServer ) ||
+                !$configFile->saveValue( "db_database", $this->_dbName ) ||
+                !$configFile->saveValue( "db_prefix", $this->_dbPrefix )) {
+                $errors = true;
+            }
+
+            if( $errors ) {
+                $message = "Could not save values to the configuration file. Please make sure it is available and
+                            that has write permissions for the user under your web server is running.";
+                $this->_view = new WizardView( "intro" );
+                $this->_view->setErrorMessage( $message );
+
+                return( false );
+            }
+            else {
+                $connectionEsablished = false;
+
+                $this->_connection = @mysql_connect( $this->_dbServer, $this->_dbUser, $this->_dbPassword );
+                if( $this->_connection ) {
+                    $connectionEsablished = true;
+                } else {
+                    $connectionEsablished = false;
+                    $message = "There was an error connecting to the database. Please check your settings.";
+                }
+
+                if ( !$connectionEsablished ) {
+                    $this->_view = new WizardView( "step1" );
+                    $this->_view->setErrorMessage( $message );
+                    $this->setCommonData( true );
+                    return false;
+                } else {
+                	$this->_view = new WizardView( "step1" );
+	                $availableCharacterSets = $this->getAvailableCharacterSets();
+	                $defaultCharacterSet = $this->getDatabaseCharacterSet();
+	                $createDatabase = false;
+	                if( empty( $defaultCharacterSet ) )
+	                {
+	                	$defaultCharacterSet = $this->getServerCharacterSet();
+	                	$createDatabase = true;
+	                }
+	                $this->_view->setValue( "availableCharacterSets", $availableCharacterSets );
+	                $this->_view->setValue( "defaultCharacterSet", $defaultCharacterSet );
+	                $this->_view->setValue( "createDatabase", $createDatabase );
+	                // now we better read the information from the config file to make sure that
+	                // it has been correctly saved
+	                $this->setCommonData( true );
+	                return true;
+	            }
+            }
+        }
+
+	    function getAvailableCharacterSets()
+	    {
+	        // check mysql version first. Version lower than 4.1 doesn't support utf8
+	        $serverVersion = mysql_get_server_info( $this->_connection );
+	        $version = explode( '.', $serverVersion );
+	        if ( $version[0] < 4 ) return false;
+	        if ( ( $version[0] == 4 ) && ( $version[1] == 0 ) ) return false;
+	        
+	        // check if utf8 support was compiled in
+	        $result = mysql_query( "SHOW CHARACTER SET", $this->_connection );
+	        if( $result )
+	        {
+		        if( mysql_num_rows($result) > 0 ) {
+		            // iterate through resultset
+		            $availableCharacterSets = array();
+		            while( $row = mysql_fetch_array( $result, MYSQL_ASSOC ) )
+		            {
+						array_push( $availableCharacterSets, $row['Charset'] );
+		            }
+		            return $availableCharacterSets;
+		        }
+		    }
+	        return false;
+	    }
+	    
+	    function getDatabaseCharacterSet()
+	    {
+			if( !@mysql_select_db( $this->_dbName, $this->_connection ) ) {
+				return false;
+			}
+	        
+	        // We use a SHOW CREATE DATABASE command to show the original
+	        // SQL character set when DB was created.
+	        $result = mysql_query( "SHOW CREATE DATABASE `".$this->_dbName."`", $this->_connection );
+	        if( $result )
+	        {
+		        if( mysql_num_rows( $result ) < 0 ) {
+		            // The specified db name is wrong!
+		            return false;
+		        }
+		        $dbInfo = mysql_fetch_row( $result );
+		        $pattern = '/40100 DEFAULT CHARACTER SET (\w+) /';
+		        if( ( preg_match( $pattern, $dbInfo[1], $match ) > 0 ) ) {
+		            return $match[1];
+		        }
+		    }
+	        return false;
+	    }
+	
+	    function getServerCharacterSet(){
+	        // We use a SHOW CREATE DATABASE command to show the original
+	        // SQL character set when DB was created.
+	        $result = mysql_query( "SHOW VARIABLES LIKE 'character_set_server'", $this->_connection );
+	        if( $result )
+	        {
+		        if( mysql_num_rows( $result ) > 0 ) {
+		            $row = mysql_fetch_array( $result, MYSQL_ASSOC );
+		            return $row['Value'];
+		        }
+			}
+	        return false;
+	    }
+    }
+
+    /**
+     *
+     * Second step where we connect to the database and create the tables.
+     *
+     */
+    class WizardStepTwo extends WizardAction
+    {
+
+        var $_db;
+        var $_database;
+        var $_dbCharacterSet;
+        var $_createDatabase;
+
+        function setDbConfigValues( &$view )
+        {
+            $configFile = new ConfigFileStorage();
+            $configFile->reload();
+            $view->setValue( "dbUser", $configFile->getValue( "db_username" ));
+            $view->setValue( "dbPassword", $configFile->getValue( "db_password" ));
+            $view->setValue( "dbServer", $configFile->getValue( "db_host" ));
+            $view->setValue( "dbName", $configFile->getValue( "db_database" ));
+            $view->setValue( "dbPrefix", $configFile->getValue( "db_prefix" ));
+            $view->setValue( "dbCharacterSet", $configFile->getValue( "db_character_set" ));
+            return true;
+        }
+
+        function perform()
+        {
+            global $Tables;
+            global $Inserts;
+
+			$this->_dbCharacterSet = $this->_request->getValue( "dbCharacterSet" );
+            $configFile = new ConfigFileStorage();
+			$configFileName = $configFile->getConfigFileName();
+            
+            if( File::exists( $configFileName ) && !File::isWritable( $configFileName )) {
+                $this->_view = new WizardView( "step1" );
+                $message = "Please make sure that the file $configFileName can be written by this script during
+                            the installation process. It is needed to store the database configuration settings. Once the
+                            installation is complete, please revert the permissions to no writing possible.";
+                $this->_view->setErrorMessage( $message );
+                $this->setCommonData( true );
+                return false;
+            }
+
+            // continue if everything went fine
+            if( !$configFile->saveValue( "db_character_set", $this->_dbCharacterSet ) ) {
+                $message = "Could not save values to the configuration file. Please make sure it is available and
+                            that has write permissions for the user under your web server is running.";
+                $this->_view = new WizardView( "step1" );
+                $this->_view->setErrorMessage( $message );
+
+                return false;
+            }
+            
+            $createDb = $this->_request->getValue( "createDatabase" );
+            $message = '';
+
+            // only check for errors in case the database table should already exist!
+            if( !$createDb ) {
+                $connectionEsablished = false;
+
+                // Lets check the 'everything is fine' case first..
+                $this->_db = connectDb();
+                if( $this->_db ) {
+                     $connectionEsablished = true;
+                } else {
+                     $connectionEsablished = false;
+                     $message = "There was an error selecting the database. Please verify the database was already created or check the 'Create database' checkbox.";
+                }
+
+                // We were unable to connect to the db and select the right db.. lets try
+                // just to connect.. maybe the database needs to be created (even though the
+                // user did not check the appropriate box).
+                if ( !$connectionEsablished ) {
+                    $this->_db = connectDb( true, false );
+                    if( !$this->_db ) {
+                         $message = "There was an error connecting to the database. Please check your settings.";
+                    }
+                }
+
+                if ( !$connectionEsablished ) {
+                    $this->_view = new WizardView( "step1" );
+                    $this->setDbConfigValues( $this->_view );
+                    $this->_view->setErrorMessage( $message );
+                    $this->setCommonData( true );
+                    return false;
+                }
+            }
+
+            $config = new ConfigFileStorage();
+            $this->_database = $config->getValue( "db_database" );
+            $this->_dbPrefix = $config->getValue( "db_prefix" );
+
+            // create the database
+            if( $createDb ) {
+                $this->_db = connectDb( false, false );
+				if( !$this->_db ) {
+                    $this->_view = new WizardView( "step1" );
+                    $this->setDbConfigValues( $this->_view );
+                    $this->_view->setErrorMessage( $message );
+                    $this->setCommonData( true );
+                    return false;					
+				}
+                if( !$this->_db->Execute( "CREATE DATABASE ".$this->_database )) {
+                    $message = "Error creating the database: ".$this->_db->ErrorMsg();
+					$message .= "<br/><br/>If the database already exists, go back to Step 2 and use a new database name.";
+                    $this->_view = new WizardView( "step1" );
+                    $this->setDbConfigValues( $this->_view );
+                    $this->_view->setErrorMessage( $message );
+                    $this->setCommonData( true );
+                    return false;
+                } else {
+                    $message = "Database created successfully.<br/>";
+                }
+            }
+
+            // reconnect using the new database.
+            $config = new ConfigFileStorage();
+            $this->_db->Connect( $config->getValue( "db_host" ), 
+                                 $config->getValue( "db_username" ), 
+                                 $config->getValue( "db_password" ), 
+                                 $config->getValue( "db_database" ));
+                                 
+            // create a data dictionary to give us the right sql code needed to create the tables
+            $dict = NewPDbDataDictionary( $this->_db );
+
+           // create the tables
+            $errors = false;            
+            
+            foreach( $Tables as $name => $table ) {
+            	$upperName = $dict->upperName;
+            	$tableSchema = $table["schema"];
+            	if ( isset( $table["options"] ) )
+            	{
+            		$tableOptions = $table["options"];
+            		$options = array ( $upperName => $tableOptions );
+            	} else {
+            		$options = array ();
+                }
+                $sqlarray = $dict->CreateTableSQL( $this->_dbPrefix.$name, $tableSchema, $options );
+
+                // each table may need more than one sql query because of indexes, triggers, etc...
+                $ok = true;
+                foreach( $sqlarray as $sql ) {
+                    $ok = ( $ok && $this->_db->Execute( $sql ));
+                }
+                
+                if( $ok )
+                    $message .= "Table <strong>$name</strong> created successfully.<br/>";
+                else {
+                    $message .= "Error creating table $name: ".$this->_db->ErrorMsg()."<br/>";
+                    $errors = true;
+                }                    
+            }
+
+            if( $errors ) {
+                $message = "There was an error creating the tables in the database. Please make sure that the user chosen to connect to the database has enough permissions to create tables.<br/><br/>$message";
+                $this->_view = new WizardView( "step1" );
+                $this->_view->setErrorMessage( $message );
+                $this->setDbConfigValues( $this->_view );
+                $this->setCommonData();
+                return false;
+            }
+
+             // try to guess the url where plog is running
+             $httpProtocol = (array_key_exists("HTTPS", $_SERVER) && $_SERVER["HTTPS"] == "on") ? "https://" : "http://";
+             $httpHost = $_SERVER["HTTP_HOST"];
+             $requestUrl = $_SERVER["REQUEST_URI"];
+             $requestUrl = str_replace( "/wizard.php", "", $requestUrl );
+             $plogUrl = $httpProtocol.$httpHost.$requestUrl;
+
+            // Find some of the tools we are going to need (last one is for os x, with fink installed)
+            // TBD: support for Windows specific directories
+            $folders = Array( "/bin/", "/usr/bin/", "/usr/local/bin/", "/sw/bin/" );
+            $finder = new FileFinder();
+            $pathToUnzip = $finder->findBinary( "unzip", $folders );
+            $pathToTar = $finder->findBinary( "tar", $folders);
+            $pathToGzip = $finder->findBinary( "gzip", $folders);
+            $pathToBzip2 = $finder->findBinary( "bzip2", $folders);
+            $pathToConvert = $finder->findBinary( "convert", $folders);
+
+            // and execute some insert's
+            foreach( $Inserts as $insert ) {
+                $query = str_replace( "{dbprefix}", $this->_dbPrefix, $insert );
+                $query = str_replace( "{plog_base_url}", $plogUrl, $query );
+                // replace also the placeholders for the paths to the tools
+                $query = str_replace( "{path_to_tar}", $pathToTar, $query );
+                $query = str_replace( "{path_to_unzip}", $pathToUnzip, $query );
+                $query = str_replace( "{path_to_bz2}", $pathToBzip2, $query );
+                $query = str_replace( "{path_to_gzip}", $pathToGzip, $query );
+                $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+                $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+                if( !$this->_db->Execute( $query )) {
+                    $message .= "Error executing code: ".$this->_db->ErrorMsg()."<br/>";
+                    $errors = true;
+                }
+            }
+
+            //
+            // show some information regarding the helper tools we're going to need
+            // and wether they were found or not
+            //
+            $message .= "<br/><b>-- Helper tools --</b><br/>";
+            if( $pathToTar == "" )
+                $message .= "The helper tool 'tar' was not found<br/>";
+            else
+                $message .= "The helper tool 'tar' was found in $pathToTar<br/>";
+            if( $pathToGzip == "" )
+                $message .= "The helper tool 'gzip' was not found<br/>";
+            else
+                $message .= "The helper tool 'gzip' was found in $pathToGzip<br/>";
+            if( $pathToUnzip == "" )
+                $message .= "The helper tool 'unzip' was not found<br/>";
+            else
+                $message .= "The helper tool 'unzip' was found in $pathToUnzip<br/>";
+            if( $pathToBzip2 == "" )
+                $message .= "The helper tool 'bzip2' was not found<br/>";
+            else
+                $message .= "The helper tool 'bzip2' was found in $pathToTar<br/>";
+            if( $pathToConvert == "" )
+                $message .= "The helper tool 'convert' (from the ImageMagick package) was not found<br/>";
+            else
+                $message .= "The helper tool 'convert' (from the ImageMagick package) was found in $pathToConvert<br/>";
+
+            // Scan for locales
+            $locales = new Locales();
+            // find all the new locales that we have not yet stored
+            $f = new LocaleFinder();
+            $newLocaleCodes = $f->find();
+
+            foreach( $newLocaleCodes as $newLocaleCode ) {
+                $res = $locales->addLocale( $newLocaleCode );
+            }
+
+			// load the core permissions
+		    include( PLOG_CLASS_PATH."install/corepermissions.properties.php" );
+
+		    // process permissions
+		    $total = 0;		
+		    foreach( $permissions as $perm ) {
+			    // check if it already exists
+			    $query = "SELECT * FROM ".Db::getPrefix()."permissions WHERE permission = '".$perm[0]."'";
+			    $result = $this->_db->Execute( $query );
+			    if( !$result || $result->RowCount() < 1 ) {
+				   	// permission needs to be added
+					$corePerm = ( $perm[2] == true ? 1 : 0 );
+					$adminOnly = ( $perm[3] == true ? 1 : 0 );
+
+					$query = "INSERT INTO ".Db::getPrefix()."permissions (permission,description,core_perm,admin_only) ".
+					          "VALUES ('".$perm[0]."','".$perm[1]."','".$corePerm."','".$adminOnly."')";
+
+					$this->_db->Execute( $query );
+					$total++;
+			    }
+		    }
+
+			// show some feedback
+            if( $errors ) {
+                $this->_view = new WizardView( "step1" );
+                $this->setDbConfigValues( $this->_view );
+                $message = "There was an error initializing some of the tables. Please make sure that the user chosen to connect to the database has enough permissions to add records to the database.<br/><br/>$message";
+                $this->_view->setErrorMessage( $message );
+                $this->setCommonData();
+            }
+            else {
+                $this->_view = new WizardView( "step2" );
+                $this->_view->setValue( "message", $message );
+            }
+        }
+    }
+
+    /**
+     *
+     * this action only shows some feedback
+     *
+     */
+    class WizardStepThree extends WizardAction
+    {
+        function perform()
+        {
+            $this->_view = new WizardView( "step3" );
+            $this->setCommonData();
+        }
+    }
+
+    /**
+     *
+     * Create the first user in the database
+     *
+     */
+    class WizardStepFour extends WizardAction
+    {
+
+        var $_userName;
+        var $_userPassword;
+        var $_confirmPassword;
+        var $_userEmail;
+        var $_userFullName;
+
+        function WizardStepFour( $actionInfo, $request )
+        {
+            $this->WizardAction( $actionInfo, $request );
+
+            $this->registerFieldValidator( "userName", new UsernameValidator());
+            $this->registerFieldValidator( "userPassword", new PasswordValidator());
+            $this->registerFieldValidator( "userPasswordCheck", new PasswordValidator());
+            $this->registerFieldValidator( "userEmail", new EmailValidator());
+            $this->registerField( "userFullName" );
+            $view = new WizardView( "step3" );
+            $view->setErrorMessage( "Some data is missing or incorrect" );
+            $this->setValidationErrorView( $view );
+        }
+
+        // creates the user
+        function perform()
+        {
+            $this->_userName = $this->_request->getValue( "userName" );
+            $this->_userPassword = $this->_request->getValue( "userPassword" );
+            $this->_confirmPassword = $this->_request->getValue( "userPasswordCheck" );
+            $this->_userEmail = $this->_request->getValue( "userEmail" );
+            $this->_userFullName = $this->_request->getValue( "userFullName" );
+
+            $db = connectDb();
+
+            if( !$db ) {
+                $this->_view = new WizardView( "step3" );
+                $this->_view->setErrorMessage( "There was an error connecting to the database. Please check your settings." );
+                $this->setCommonData();
+                return false;
+            }
+
+            if( $this->_confirmPassword != $this->_userPassword ) {
+                $this->_view = new WizardView( "step3" );
+                $this->_form->setFieldValidationStatus( "userPasswordCheck", false );
+                $this->setCommonData( true );
+                return false;
+            }
+
+            $dbPrefix = Db::getPrefix();
+
+            $users = new Users();
+            $user = new UserInfo( $this->_userName,
+                                  $this->_userPassword,
+                                  $this->_userEmail,
+                                  "",
+                                  $this->_userFullName);
+			// set the user as an administrator
+			$user->setSiteAdmin( true );
+			// and add this record to the db
+            $userId = $users->addUser( $user );
+            if( !$userId ) {
+                $this->_view = new WizardView( "step3" );
+				$db =& Db::getDb();
+                $message = "There was an error adding the user. Make sure that the user does not already exist in the database (".$db->ErrorMsg().")";
+                $this->_view->setErrorMessage( $message );
+                $this->setCommonData();
+                return false;
+            }
+
+			// since this user is an administrator, he must be granted all the administrator
+			// permissions available
+			$perms = new Permissions();
+			$userPerms = new UserPermissions();
+			foreach( $perms->getAllPermissions() as $perm ) {
+				if( $perm->isAdminOnlyPermission()) {
+					// if it's an admin permission, add it
+					$p = new UserPermission( $userId, 0, $perm->getId());
+					$userPerms->grantPermission( $p );
+					//print("granting permission: ".$perm->getName()."<br/>");
+				}
+			}
+
+            $this->_view = new Wizardview( "step4" );
+            $this->_view->setValue( "ownerid", $userId );
+            $this->_view->setValue( "siteLocales", Locales::getLocales());
+            $this->_view->setValue( "defaultLocale", Locales::getDefaultLocale());
+            $ts = new TemplateSets();
+            $this->_view->setValue( "siteTemplates", $ts->getGlobalTemplateSets());
+            $this->setCommonData();
+            return true;
+        }
+
+    }
+
+    class WizardStepFive extends WizardAction
+    {
+
+        var $_blogName;
+        var $_ownerId;
+        var $_blogProperties;
+
+        function WizardStepFive( $actionInfo, $request )
+        {
+              $this->WizardAction( $actionInfo, $request );
+
+              $this->registerFieldValidator( "blogName", new StringValidator());
+              $this->registerFieldValidator( "ownerid", new IntegerValidator());
+              $this->registerFieldValidator( "blogTemplate", new StringValidator());
+              $this->registerFieldValidator( "blogLocale", new StringValidator());			  
+              $view = new WizardView( "step4" );
+              $view->setErrorMessage( "Some data is missing or incorrect" );
+              $view->setValue( "siteLocales", Locales::getLocales());
+			  $view->setValue( "defaultLocale", Locales::getDefaultLocale());
+              $ts = new TemplateSets();
+              $view->setValue( "siteTemplates", $ts->getGlobalTemplateSets());
+              $this->setValidationErrorView( $view );
+        }
+
+        function perform()
+        {
+            // Before we add a new blog, we need to add blog category and global article category first
+            // add blog category
+            $blogCategories = new BlogCategories();
+            $blogCategory = new BlogCategory( "General", "General" );
+            $blogCategoryId = $blogCategories->addBlogCategory( $blogCategory );
+
+            // add global article category
+            $globalArticleCategories = new GlobalArticleCategories();
+            $globalArticleCategory = new GlobalArticleCategory( "General", "General" );
+            $globalArticleCategoryId = $globalArticleCategories->addGlobalArticleCategory( $globalArticleCategory );
+            
+            // retrieve the values from the view
+            $this->_blogName = $this->_request->getValue( "blogName" );
+            $this->_ownerId  = $this->_request->getValue( "ownerid" );
+            $this->_blogProperties = $this->_request->getValue( "properties" );
+            $this->_blogTemplate = $this->_request->getValue( "blogTemplate" );
+            $this->_blogLocale = $this->_request->getValue( "blogLocale" );
+
+            // configure the blog
+            $blogs = new Blogs();
+            $blog = new BlogInfo( $this->_blogName, $this->_ownerId, "", "" );
+            // set the default BlogCategory id to blog
+            $blog->setBlogCategoryId( $blogCategoryId );
+            $blog->setProperties( $this->_blogProperties );
+            $blog->setStatus( BLOG_STATUS_ACTIVE );
+            $blogSettings = $blog->getSettings();
+            $blogSettings->setValue( "locale", $this->_blogLocale );
+            $blogSettings->setValue( "template", $this->_blogTemplate );
+            $blog->setSettings( $blogSettings );
+
+            // and now save it to the database
+            $newblogId = $blogs->addBlog( $blog );
+            if( !$newblogId ) {
+                $this->_view = new WizardView( "step4" );
+                $this->_view->setValue( "siteLocales", Locales::getLocales());
+                $ts = new TemplateSets();
+                $this->_view->setValue( "siteTemplates", $ts->getGlobalTemplateSets());
+                $this->_view->setErrorMessage( "There was an error creating the new blog" );
+                $this->setCommonData( true );
+                return false;
+            }
+
+            // if the blog was created, we can add some basic information
+            // add a category
+            $articleCategories = new ArticleCategories();
+            $articleCategory = new ArticleCategory( "General", "General", $newblogId, true );
+            $catId = $articleCategories->addArticleCategory( $articleCategory );
+
+            // load the right locale
+            $locale =& Locales::getLocale( $this->_blogLocale );
+            // and load the right text
+            $articleTopic = $locale->tr( "register_default_article_topic" );
+            $articleText  = $locale->tr( "register_default_article_text" );
+            $article = new Article( $articleTopic, $articleText, Array( $catId ), $this->_ownerId, $newblogId, POST_STATUS_PUBLISHED, 0, Array(), "welcome" );
+            // set the default ArticleGlobalCategory id to article
+            $article->setGlobalCategoryId( $globalArticleCategoryId );
+            // set the current time to article
+            $t = new Timestamp();
+            $article->setDateObject( $t );
+            $articles = new Articles();
+            $articles->addArticle( $article );
+
+            // add a new first album so that users can start uploading stuff right away
+            $t = new Timestamp();
+            $album = new GalleryAlbum( $newblogId,
+                                       "General",
+                                       "General",
+                                       GALLERY_RESOURCE_PREVIEW_AVAILABLE,
+                                       0,
+                                       $t->getTimestamp(),
+                                       Array(),
+                                       true );
+            $albums = new GalleryAlbums();
+            $albums->addAlbum( $album );
+            
+            // add a new default mylinkscategory
+            $linksCategory = new MyLinksCategory( "General", $newblogId );
+            $linksCategories = new MyLinksCategories();
+            $linksCategories->addMyLinksCategory( $linksCategory );         
+
+            // save a few things in the default configuration
+            $config =& Config::getConfig();
+            // default blog id
+            $config->saveValue( "default_blog_id", (int)$newblogId );
+            // default locale
+            $config->saveValue( "default_locale", $this->_blogLocale );
+            // and finally, the default template
+            $config->saveValue( "default_template", $this->_blogTemplate );
+
+            //
+            // detect wether we have GD available and set the blog to use it
+            //
+            if( GdDetector::detectGd()) {
+                $config->saveValue( "thumbnail_method", "gd" );
+                $message = "GD has been detected and set as the backend for dealing with images.";
+            }
+            else {
+                $pathToConvert = $config->getValue( "path_to_convert" );
+                if( $pathToConvert ) {
+                    $config->saveValue( "thumbnail_method", "imagemagick" );
+                    $message = "ImageMagick has been detected and set as the backend for dealing with images.";
+                }
+                else {
+                    // nothing was found, so we'll have to do away with the 'null' resizer...
+                    $config->saveValue( "thumbnail_method", "null" );
+                    $message = "Neither GD nor ImageMagick have been detected in this host so it will not be possible to generate thumbnails from images.";
+                }
+            }
+            
+            // clean the data cache to avoid problems when we're done
+            lt_include( PLOG_CLASS_PATH."class/cache/cachemanager.class.php" );
+            $cache =& CacheManager::getCache();
+            $cache->clearCache();
+
+            WizardTools::cleanTmpFolder();
+
+            $this->_view = new WizardView( "step5" );
+            $this->_view->setValue( "message", $message );
+            return true;
+        }
+    }
+
+    class UpdateStepOne extends WizardAction
+    {
+
+        function perform()
+        {
+            $this->_view = new WizardView( "update1" );
+            WizardStepTwo::setDbConfigValues( $this->_view );
+            $this->setCommonData();
+        }
+    }
+
+    class UpdateStepTwo extends WizardAction
+    {
+        function perform()
+        {
+			lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
+			$config =& Config::getConfig();
+			$resourcesNamingRule = $config->getValue( "resources_naming_rule", "original_file_name" );
+			
+            $this->_view = new WizardView( "update2" );
+            $this->_view->setValue( "resourcesNamingRule", $resourcesNamingRule );
+            $this->setCommonData();
+        }
+    }
+    
+    /**
+     * Generic class that performs data updates on the database
+     */
+    class DatabaseDataTransformer extends Model
+    {
+        /**
+         * @public
+         * Public fields, may be accessed by other classes
+         */
+        var $updatedRecords;
+        var $message;
+        var $errorRecords;
+        var $notModifiedRecords;
+        var $failOnError;
+        var $page;
+        var $itemsPerPage;
+        var $dbPrefix;
+    
+        function DatabaseDataTransformer( $page = -1, $itemsPerPage = WIZARD_MAX_RECORDS_PER_STEP )
+        {
+            $this->Model();
+            
+            $this->updatedRecords = 0;
+            $this->errorRecords   = 0;
+            $this->notModifiedRecords = 0;
+            $this->addedRecords = 0;
+            $this->deletedRecords = 0;
+            $this->failOnError = DATABASE_DATA_TRANSFORMER_FAIL_ON_ERROR_DEFAULT;
+            $this->message = "";
+            
+            $this->page = $page;
+            $this->itemsPerPage = $itemsPerPage;
+            
+            $this->dbPrefix = $this->getPrefix();
+        }
+        
+        /**
+         * Rerforms the transformation. Returns true if the step was successful or false otherwise.
+         * Upon finalization, please check the $message string to get more information. Use the $updatedRecords,
+         * $errorRecords, $notModifiedRecords, $addedRecords and $deletedRecords for some figures regarding the 
+         * previous step
+         */
+        function perform()
+        {
+            // must be implemented by child classes
+            return true;        
+        }
+        
+        /**
+         * Returns true if there is no more data for this transformer to upgrade, or false otherwise
+         *
+         * @return True if ready or false if not
+         */
+        function isComplete()
+        {
+            return( $this->getNumSteps() <= $this->page );
+        }
+        
+        /**
+         * returns the number of steps needed to process this data
+         */
+        function getNumSteps( $table = "" )
+        {
+            // if there is a table name, we can take a shortcut or else we expect child
+            // classes to reimplement this method
+            if( $table ) {
+                $numItems = $this->getNumItems( $this->getPrefix().$table );
+                
+                $numSteps = ceil( $numItems / $this->itemsPerPage );
+            }
+            else {
+                $numSteps = 0;
+            }
+            
+            return( $numSteps );
+        }
+        
+        /**
+         * returns the total number of records processed so far based on the current page and the
+         * number of items per page
+         */
+        function getTotalProcessedRecords()
+        {
+            return( $this->page * $this->itemsPerPage );
+        }
+        
+        /**
+         * returns an approximate percentage of records processed so far
+         */
+        function getPercentProcessed()
+        {
+            $processed = $this->getTotalProcessedRecords();
+            return((int)($processed / ( $this->getNumSteps() * $this->itemsPerPage ) * 100 ));
+        }
+    }
+
+	/**
+	 * This step takes care of transforming the database schema, one
+	 * table at a time.
+	 */
+	class DatabaseSchemaDataTransformer extends DatabaseDataTransformer
+	{		
+		function getNumSteps()
+		{
+			global $Tables;			
+			return( count( $Tables ) - 1);
+		}
+		
+		function perform()
+		{
+			global $Tables;
+			
+			$tablesArray = array_keys( $Tables );
+			$curTable = $tablesArray[$this->page-1];
+						
+			$db =& Db::getDb();
+            $dict = NewPDbDataDictionary( $db );
+            $errors = false;
+
+			$this->message = "Performing changes to the dabase schema, please wait (step %s of %s)<br/>";
+
+			$errorMessage = "";
+			$table_errors = false;
+			$upperName = $dict->upperName;
+			$tableSchema = $Tables[$curTable]["schema"];
+			if ( isset( $Tables[$curTable]["options"] )) {
+				$tableOptions = $Tables[$curTable]["options"];
+				$options = array ( $upperName => $tableOptions );
+			} 
+			else {
+				$options = array ();
+			}
+
+			// generate the code with the changes for the table
+			$sqlarray = $dict->ChangeTableSQL( $this->getPrefix().$curTable, $tableSchema, $options );
+
+			foreach( $sqlarray as $sql ) {
+				// and run the query
+				//print( "sql: ".$sql."<br/>" );
+				if( !$this->Execute( $sql )) {
+					$table_errors = true;
+					$errors = true;
+					$errorMessage .= $this->_db->ErrorMsg()."<br/>";
+				}
+			}
+
+			if( !$table_errors ) {
+				$this->message .= "Changes to table <strong>$curTable</strong> executed successfully.<br/>";
+				$result = true;
+			}
+			else {
+				$this->message .= "Error modifying table $curTable: ".$errorMessage;
+				$result = false;
+			}
+
+			return( $result ); 
+		}
+	}
+    
+    /**
+	 * Processes all users and grants the appropriate permissions
+     */
+    class UserPermissionsDataTransformer extends DatabaseDataTransformer
+    {        
+        function getNumSteps()
+        {
+            return( parent::getNumSteps( "tmp_users_permissions" ));
+        }
+    
+        function perform()
+        {
+            $this->message = "Updating user permissions (step %s of %s)<br/>";        
+        
+            $query3 = "SELECT * FROM ".Db::getPrefix()."tmp_users_permissions";
+            $res3 = $this->Execute( $query3, $this->page, $this->itemsPerPage );
+            if( $res3->RecordCount() == 0 ) {
+				$this->message .= "No more records to process";
+				return( true );
+			}
+			
+			$permissions = new Permissions();
+			$userPermissions = new UserPermissions();
+			$allPerms = $permissions->getAllPermissions();
+			$blogOwnerOnlyPerms = Array( "update_blog", 
+			                             "add_blog_user", 
+			                             "update_blog_user", 
+			                             "view_blog_users", 
+			                             "view_blog_stats", 
+			                             "add_blog_template",
+										 "view_blog_templates",
+										 "view_blog_stats" );
+			
+            while( $row = $res3->FetchRow()) {
+            	// grant all the non-admin permissions so that users can still access the blogs to where they still had permissions
+				if( $row["permission_id"] != 3) {
+					foreach( $allPerms as $perm ) {
+						if( !$perm->isAdminOnlyPermission() && !in_array( $perm->getName(), $blogOwnerOnlyPerms )) {
+							//print( "granting perm: ".$perm->getName()." - user: ".$row["user_id"]." - blog id: ".$row["blog_id"]."<br/>");							
+							$perm = new UserPermission( $row["user_id"], $row["blog_id"], $perm->getId());
+							$userPermissions->grantPermission( $perm );
+						}
+					}
+				}
+            }
+      
+            $this->message .= "{$this->updatedRecords} users updated (".$this->getPercentProcessed()."%%)<br/>";
+
+            $this->Execute("DROP TABLE ".Db::getPrefix()."tmp_users_permissions");
+
+            return true;
+        }
+    }
+
+	class PermissionLoader extends DatabaseDataTransformer
+	{
+		
+		//
+		// load the new list of permissions
+		//		
+		function getNumSteps()
+		{
+			return( 0 );
+		}
+		
+		function perform()
+		{
+			// initial message, no errors yet
+            $this->message = "Loading new permissions (step %s of %s)<br/>";			
+			$errors = false;
+			
+			// load the core permissions
+		    include( PLOG_CLASS_PATH."install/corepermissions.properties.php" );	
+
+		    // process permissions
+		    $total = 0;		
+		    foreach( $permissions as $perm ) {
+			    // check if it already exists
+			    $query = "SELECT * FROM ".$this->dbPrefix."permissions WHERE permission = '".$perm[0]."'";
+			    $result = $this->Execute( $query );
+			    if( !$result || $result->RowCount() < 1 ) {				
+				   	// permission needs to be added
+					$corePerm = ( $perm[2] == true ? 1 : 0 );
+					$adminOnly = ( $perm[3] == true ? 1 : 0 );
+					$query = "INSERT INTO ".$this->dbPrefix."permissions (permission,description,core_perm,admin_only) ".
+					          "VALUES ('".$perm[0]."','".$perm[1]."','".$corePerm."','".$adminOnly."')";
+					$this->_db->Execute( $query );
+					$total++;
+			    }
+		    }
+		
+			//
+			// prepare the users_permissions table for the next step
+			//
+
+            // make sure we are starting with an empty table
+            $this->Execute("DELETE FROM ".Db::getPrefix()."tmp_users_permissions");
+            
+			if( !$this->Execute( "INSERT INTO ".$this->dbPrefix."tmp_users_permissions SELECT * FROM ".$this->dbPrefix."users_permissions WHERE blog_id != 0 AND permission_id != 1" )) {
+				$this->message .= "Error preparing the users_permissions table for transformation";
+				$errors = true;
+			}
+			else {
+				$this->Execute( "DELETE FROM ".$this->dbPrefix."users_permissions" );
+				$this->message .= count($permissions)." permissions successfully loaded";
+				$errors = false;
+			}				
+			
+			return( !$errors );			
+		}	
+	}
+
+	class ConfigDataTransformer extends DatabaseDataTransformer
+	{
+		function getNumSteps()
+		{
+			return( 0 );
+		}
+		
+		function perform()
+		{
+		    global $Inserts;	
+			
+            $this->message = "Adding new configuration parameters (step %s of %s)<br/>";
+			$errors = false;
+			
+            // Find some of the tools we are going to need (last one is for os x, with fink installed), this will be needed later on
+            $folders = Array( "/bin/", "/usr/bin/", "/usr/local/bin/", "/sw/bin/" );
+            $finder = new FileFinder();
+            $pathToUnzip = $finder->findBinary( "unzip", $folders );
+            $pathToTar = $finder->findBinary( "tar", $folders);
+            $pathToGzip = $finder->findBinary( "gzip", $folders);
+            $pathToBzip2 = $finder->findBinary( "bzip2", $folders);
+            $pathToConvert = $finder->findBinary( "convert", $folders);
+
+            // check the configuration and add the new configuration settings that were added for 1.2
+            foreach( $Inserts as $key => $insert ) {
+				$checkKeyQuery = "SELECT * FROM ".$this->dbPrefix."config WHERE config_key ='".$key."';";
+				$result = $this->Execute($checkKeyQuery);
+                if(!$result){
+                    $this->message .= "Error executing code: ".$this->_db->ErrorMsg()."<br/>";
+                    $errors = true;
+                }
+				else{
+                    if ($result->RecordCount() == 0) {	
+                        // replace the prefix
+                        $query = str_replace( "{dbprefix}", $this->dbPrefix, $insert );
+                        // replace also the placeholders for the paths to the tools
+                        $query = str_replace( "{path_to_tar}", $pathToTar, $query );
+                        $query = str_replace( "{path_to_unzip}", $pathToUnzip, $query );
+                        $query = str_replace( "{path_to_bz2}", $pathToBzip2, $query );
+                        $query = str_replace( "{path_to_gzip}", $pathToGzip, $query );
+                        $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+                        $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+                        if( !$this->Execute( $query )) {
+                            $this->message .= "Error executing code: ".$this->_db->ErrorMsg()."<br/>";
+                            $errors = true;
+                        }
+                    }
+                    $result->Close();
+                }
+            }
+                // check to see if we need to remove duplicates and the id index
+            $query = "SELECT id FROM ".$this->dbPrefix."config LIMIT 1";
+            $result = $this->Execute($query);
+                // if $result is false, id column has already been removed
+            if($result){
+                $result->Close();           
+                    // remove all duplicates in plog_config table
+                    
+                    // first create temp table without the duplicates
+                $query = "CREATE TEMPORARY TABLE tmptable ".
+                         "SELECT * FROM ".$this->dbPrefix."config WHERE 1 GROUP BY config_key";
+                $result = $this->Execute($query);
+                if($result){
+                    //$result->Close();
+                        // Now delete the old table
+                    $query = "DELETE FROM ".$this->dbPrefix."config";
+                    $result = $this->Execute($query);
+                    if($result) {
+                        //$result->Close();
+                        // Insert the unique rows into the old table
+                        $query = "INSERT INTO ".$this->dbPrefix."config SELECT * FROM tmptable";
+                        $result = $this->Execute($query);
+                    }
+                }
+                /*if(!$result){
+                    $this->message .= "Error removing duplicates in config table<br/>";
+                    $errors = true;
+                }*/
+
+                if($result){
+
+                    // remove index id field, we don't need it any more!
+                    $query = "ALTER TABLE ".$this->dbPrefix."config DROP COLUMN id";
+                    $result = $this->Execute($query);
+                    if(!$result){
+                        $this->message .= "Error removing old id column from config table: ".$this->_db->ErrorMsg()."<br/>";
+                        $errors = true;
+                    }
+                }
+            }			
+
+			if( !$errors ) {
+				$this->message .= "Configuration settings updated successfully";
+			}
+			
+			return( !$errors );
+		}		
+	}
+
+    /**
+	 * Processes all admin users and grants the appropriate permissions
+     */
+    class AdminUserPermissionsDataTransformer extends DatabaseDataTransformer
+    {        
+        function getNumSteps()
+        {
+            return( parent::getNumSteps( "users" ));
+        }
+    
+        function perform()
+        {
+            $this->message = "Updating admin user permissions (step %s of %s)<br/>";        
+        
+            // load each one of the categories and update them
+            // list of categories
+            /*$query3 = "SELECT id, site_admin FROM ".$this->dbPrefix."users";
+            $res3 = $this->Execute( $query3, $this->page, $this->itemsPerPage );
+            if( $res3->RecordCount() == 0 ) {
+				$this->message .= "No more records to process";
+				return( true );
+			}*/
+			
+			$users = new Users();
+			$allUsers = $users->getAllUsers( USER_STATUS_ALL, "", "", $this->page, $this->itemsPerPage );
+			
+			$permissions = new Permissions();
+			$userPermissions = new UserPermissions();
+			$loginPerm = $permissions->getPermissionByName( "login_perm" );
+			$allPerms = $permissions->getAllPermissions();
+			
+            //while( $row = $res3->FetchRow()) {
+			foreach( $allUsers as $user ) {
+				//print("Processing user: ".$user->getUsername()."<br/>");
+            	//if( $row["site_admin"] > 0 ) {
+				if( $user->isSiteAdmin()) {
+					// it's an admin, let's grant all the appropriate permissions
+					foreach( $allPerms as $perm ) {
+						if( $perm->isAdminOnlyPermission() && $perm->getName() != "login_perm" ) {
+							//$userPerm = new UserPermission( $row["id"], 0, $perm->getId());
+							$userPerm = new UserPermission( $user->getId(), 0, $perm->getId());
+							$userPermissions->grantPermission( $userPerm );
+						}
+					}
+				}
+				// grant the login_perm permission or else users won't be able to log in
+				$newPerm = new UserPermission( $user->getId(), 0, $loginPerm->getId());
+				$userPermissions->grantPermission( $newPerm );
+				
+				$this->updatedRecords++;
+            }
+        
+            $this->message .= "{$this->updatedRecords} users updated (".$this->getPercentProcessed()."%%)<br/>";
+            return true;        
+        }
+    }
+    
+    /**
+     * processes all resource files and renames the files to their "real" names
+     */
+    class ResourcesOriginalFileNameDataTransformer extends DatabaseDataTransformer
+    {
+        function getNumSteps()
+        {
+            return( parent::getNumSteps( "gallery_resources" ));
+        }
+    
+        function perform()
+        {
+            $this->message = "Updating resource files with original file naming rule (step %s of %s)<br/>";        
+        
+            $query1 = "SELECT id, owner_id, file_name, resource_type, thumbnail_format FROM ".$this->dbPrefix."gallery_resources";
+
+			$config =& Config::getConfig();
+			$galleryFolder = $config->getValue( "resources_folder" );
+
+            // total number of comments
+            $res1 = $this->Execute( $query1, $this->page, $this->itemsPerPage );
+            if( !$res1 ) {
+                $this->message .= "Error performing loading resource data";
+                return false;
+            }
+            if( $res1->RecordCount() == 0 ) {
+				$this->message .= "No more records to process";
+				return( true );            
+            }
+            $numComments = Array();
+            while( $row = $res1->FetchRow()) {
+				//
+				// process each one of the rows and rename the main file
+				//
+				
+				// get the file extension
+				if(( $extPos = strrpos( $row["file_name"], "." )) !== false ) {					
+					$fileExt = substr( $row["file_name"], $extPos+1, strlen( $row["file_name"] ));
+				}
+				else {
+					$fileExt = "";
+				}
+								
+				$fileName = $galleryFolder.$row["owner_id"]."/".$row["owner_id"]."-".$row["id"].".".$fileExt;
+				$destFileName = $galleryFolder.$row["owner_id"]."/".$row["file_name"];
+				
+                    //print( "Renaming file: $fileName --- $destFileName<br/>" );
+
+                    // skip the rename if we already did it
+				if( File::exists( $fileName )) {
+	                if( !File::exists( $destFileName)) {
+	                    if( !File::rename( $fileName, $destFileName )) {
+	                        $this->message .= "Error updating resource file with id ".$row["id"].", while attempting to rename file from $fileName to $destFileName<br/>";
+	                    }
+					}
+				}
+				
+				// if it's an image, we also need to process the previews
+				if( $row["resource_type"] == "1" ) {
+					// calculate the extension of the preview file, depending on how it was saved
+					if( $row["thumbnail_format"] == "same" ) {
+						$previewExt = strtolower( $fileExt );
+						$destFileName = $row["file_name"];
+					}
+					else {
+						$previewExt = $row["thumbnail_format"];
+						// remove the old extension and put the new one in place
+						//print("file name = ".$row["file_name"]." - file ext = $fileExt - previewExt = $previewExt" );
+						$destFileName = str_replace( $fileExt, $previewExt, $row["file_name"] );
+					}
+						
+					// file names for the preview and medium preview
+					$previewFileName = $galleryFolder.$row["owner_id"]."/previews/".$row["owner_id"]."-".$row["id"].".".$previewExt;
+					$medPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$row["owner_id"]."-".$row["id"].".".$previewExt;					
+					// destination file names for the preview and medium preview
+					$destPreviewFileName = $galleryFolder.$row["owner_id"]."/previews/".$destFileName;
+					$destMedPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$destFileName;
+					
+					//print(" -- renaming preview: $previewFileName -- $destPreviewFileName<br/>");
+					//print(" -- renaming medium preview: $medPreviewFileName -- $destMedPreviewFileName<br/>");					
+					
+					if( File::exists( $previewFileName )) {
+                    	if( !File::exists( $destPreviewFileName)) {
+                        	File::rename( $previewFileName, $destPreviewFileName );
+                    	}
+					}
+					if( File::exists( $medPreviewFileName )) {
+	                    if( !File::exists( $destMedPreviewFileName)) {
+	                        File::rename( $medPreviewFileName, $destMedPreviewFileName );
+	                    }
+					}
+				}
+
+                $this->updatedRecords++;
+            }
+            $res1->Close();
+            $this->message .= "{$this->updatedRecords} resource files updated, ".$this->getTotalProcessedRecords()." processed so far (".$this->getPercentProcessed()."%%)<br/>";
+            return true;        
+        }        
+    }
+
+    /**
+     * processes all resource files and renames the files to their "encoded" names
+     */
+    class ResourcesEncodedFileNameDataTransformer extends DatabaseDataTransformer
+    {
+        function getNumSteps()
+        {
+            return( parent::getNumSteps( "gallery_resources" ));
+        }
+    
+        function perform()
+        {
+            $this->message = "Updating resource files with encoded file naming rule (step %s of %s)<br/>";        
+        
+            $query1 = "SELECT id, owner_id, file_name, resource_type, thumbnail_format FROM ".$this->dbPrefix."gallery_resources";
+
+			$config =& Config::getConfig();
+			$galleryFolder = $config->getValue( "resources_folder" );
+
+            // total number of comments
+            $res1 = $this->Execute( $query1, $this->page, $this->itemsPerPage );
+            if( !$res1 ) {
+                $this->message .= "Error performing loading resource data";
+                return false;
+            }
+            if( $res1->RecordCount() == 0 ) {
+				$this->message .= "No more records to process";
+				return( true );            
+            }
+            $numComments = Array();
+            while( $row = $res1->FetchRow()) {
+				//
+				// process each one of the rows and rename the main file
+				//
+				
+				// get the file extension
+				if(( $extPos = strrpos( $row["file_name"], "." )) !== false ) {					
+					$fileExt = substr( $row["file_name"], $extPos+1, strlen( $row["file_name"] ));
+				}
+				else {
+					$fileExt = "";
+				}
+								
+				$fileName = $galleryFolder.$row["owner_id"]."/".$row["owner_id"]."-".$row["id"].".".$fileExt;
+				$destFileName = $galleryFolder.$row["owner_id"]."/".$row["owner_id"]."-".$row["id"].".".strtolower($fileExt);
+				
+				if( $fileName != $destFileName ) {
+					if( File::exists( $fileName )) {
+		                if( !File::exists( $destFileName)) {
+		                    if( !File::rename( $fileName, $destFileName )) {
+		                        $this->message .= "Error updating resource file with id ".$row["id"].", while attempting to rename file from $fileName to $destFileName<br/>";
+		                    }
+						}
+					}
+				}	
+
+                $this->updatedRecords++;
+            }
+            $res1->Close();
+            $this->message .= "{$this->updatedRecords} resource files updated, ".$this->getTotalProcessedRecords()." processed so far (".$this->getPercentProcessed()."%%)<br/>";
+            return true;        
+        }        
+    }
+
+    /**
+     * processes all resource files that we did not convert correctly in 1.2.0
+     */
+    class ResourcesFix120FileNameDataTransformer extends DatabaseDataTransformer
+    {
+        function getNumSteps()
+        {
+            return( parent::getNumSteps( "gallery_resources" ));
+        }
+    
+        function perform()
+        {
+            $this->message = "Fixing resource files with original file naming rule (step %s of %s)<br/>";        
+        
+            $query1 = "SELECT id, owner_id, file_name, resource_type, thumbnail_format FROM ".$this->dbPrefix."gallery_resources";
+
+			$config =& Config::getConfig();
+			$galleryFolder = $config->getValue( "resources_folder" );
+
+            // total number of comments
+            $res1 = $this->Execute( $query1, $this->page, $this->itemsPerPage );
+            if( !$res1 ) {
+                $this->message .= "Error performing loading resource data";
+                return false;
+            }
+            if( $res1->RecordCount() == 0 ) {
+				$this->message .= "No more records to process";
+				return( true );            
+            }
+            $numComments = Array();
+            while( $row = $res1->FetchRow()) {
+				//
+				// process each one of the rows and rename the main file
+				//
+				
+				// get the file extension
+				if(( $extPos = strrpos( $row["file_name"], "." )) !== false ) {					
+					$fileExt = substr( $row["file_name"], $extPos+1, strlen( $row["file_name"] ));
+				}
+				else {
+					$fileExt = "";
+				}
+
+				// Only convert the preview file name if the file extension does not lower case
+				if( strtolower( $fileExt ) != $fileExt ) {
+					// if it's an image, we also need to process the previews
+					if( $row["resource_type"] == "1" ) {
+						// calculate the extension of the preview file, depending on how it was saved
+						if( $row["thumbnail_format"] == "same" ) {
+							$previewExt = strtolower( $fileExt );
+							$destFileName = $row["file_name"];
+						}
+						else {
+							$previewExt = $row["thumbnail_format"];
+							// remove the old extension and put the new one in place
+							//print("file name = ".$row["file_name"]." - file ext = $fileExt - previewExt = $previewExt" );
+							$destFileName = str_replace( $fileExt, $previewExt, $row["file_name"] );
+						}
+							
+						// file names for the preview and medium preview
+						$previewFileName = $galleryFolder.$row["owner_id"]."/previews/".$row["owner_id"]."-".$row["id"].".".$previewExt;
+						$medPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$row["owner_id"]."-".$row["id"].".".$previewExt;					
+						// destination file names for the preview and medium preview
+						$destPreviewFileName = $galleryFolder.$row["owner_id"]."/previews/".$destFileName;
+						$destMedPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$destFileName;
+						
+						//print(" -- renaming preview: $previewFileName -- $destPreviewFileName<br/>");
+						//print(" -- renaming medium preview: $medPreviewFileName -- $destMedPreviewFileName<br/>");					
+						
+						if( File::exists( $previewFileName )) {
+	                    	if( !File::exists( $destPreviewFileName)) {
+	                        	File::rename( $previewFileName, $destPreviewFileName );
+	                    	}
+						}
+						if( File::exists( $medPreviewFileName )) {
+		                    if( !File::exists( $destMedPreviewFileName)) {
+		                        File::rename( $medPreviewFileName, $destMedPreviewFileName );
+		                    }
+						}
+					}
+				}
+
+                $this->updatedRecords++;
+            }
+            $res1->Close();
+            $this->message .= "{$this->updatedRecords} resource files updated, ".$this->getTotalProcessedRecords()." processed so far (".$this->getPercentProcessed()."%%)<br/>";
+            return true;        
+        }        
+    }    
+
+	// Dummy Transformer
+	class DummyDataTransformer extends DatabaseDataTransformer
+	{
+		function getNumSteps()
+		{
+			return( 0 );
+		}
+		
+		function perform()
+		{
+			return true;
+		}
+	}
+    
+    /**
+     * This class is basically now a "data transformer runner", because now it works
+     * like class that executes data transformers, collects their results and refreshes
+     * the page to execute the next step of the transformer. If the current transformer
+     * reported that its processing is complete, this class will continue with the next
+     * transformer unless there are no more transformer to run.
+     *
+     * In order to coordinate the current step and the current transformer, two parameters
+     * are needed in each request:
+     *
+     * - page
+     * - transformerId
+     *
+     * The 'page' parameter holds the current page, while 'transformerId' is the index of 
+     * the current transformer in the $this->transformers array.
+     *
+     * In order to add new transformers, follow these steps:
+     *
+     * - Create your own transfomer class by extending DatabaseDataTransformer and implementing
+     * the methods DatabaseDataTransformer::perform() and DatabaseDataTransformer::getNumSteps(). The
+     * first does the data processing while the second one returns the number of needed steps to the
+     * class running the transformer.
+     * - Add the name of the transformer class to the the UpdateStepThree::transformers array,
+     * and the class will take care of everything else. 
+     */
+    class UpdateStepThree extends WizardPagedAction
+    {
+        var $resourcesNamingRule;
+        var $message;  
+        var $currentTransformerId;
+        var $totalTransformers;
+    
+        function UpdateStepThree( $actionInfo, $httpRequest )
+        {
+            $this->WizardPagedAction( $actionInfo, $httpRequest );
+            // data validation
+            $this->registerFieldValidator( "resourcesNamingRule", new StringValidator());
+			$errorView = new WizardView( "update2" );
+            $errorView->setErrorMessage( "Some data was incorrect or missing." );
+            $this->setValidationErrorView( $errorView );
+            
+            /**
+             * array with the data transformers that will be run
+             */
+			$this->resourcesNamingRule = $this->_request->getValue( "resourcesNamingRule" );
+			if( $this->resourcesNamingRule == 'encoded_file_name' ) {
+	            $this->transformers = Array(
+					"DatabaseSchemaDataTransformer",
+					"PermissionLoader",
+					"AdminUserPermissionsDataTransformer",
+					"UserPermissionsDataTransformer",
+					"ConfigDataTransformer",
+					"ResourcesEncodedFileNameDataTransformer",
+					"DummyDataTransformer"
+	            );
+	        }
+	        else {
+	            $this->transformers = Array(
+					"DatabaseSchemaDataTransformer",
+					"PermissionLoader",
+					"AdminUserPermissionsDataTransformer",
+					"UserPermissionsDataTransformer",
+					"ConfigDataTransformer",
+					"ResourcesOriginalFileNameDataTransformer",
+					"DummyDataTransformer"
+	            );
+	    	}
+
+            $this->currentTransformerId = $this->getTransformerIdFromRequest();
+            $this->totalTransformers = count( $this->transformers ) - 1;
+        }
+        
+        /**
+         * gets the id of the transformer from the request. If it is not available, it
+         * will return the id of the first transformer available (which is '0')
+         *
+         * @private
+         */
+        function getTransformerIdFromRequest()
+        {    	
+			$id = HttpVars::getRequestValue( "transformerId" );
+			$val = new IntegerValidator();
+			if( !$val->validate( $id ))
+				$id = 0;
+							
+			return $id;        
+        }        
+
+       function perform()
+       {
+            $step = $this->getPageFromRequest();
+            
+            // get the current transformer class so that we can continue where we left
+            $transformerClass = $this->transformers[$this->currentTransformerId];
+            $transformer = new $transformerClass( $step );
+            $result = $transformer->perform();
+            $complete = $transformer->isComplete();
+            $message = $transformer->message;
+            $message = sprintf( $message, $this->currentTransformerId + 1, $this->totalTransformers );
+            
+            //print("transformer = $transformerClass<br/>");
+             
+            // error during processing and the processor is configured
+            // to fail on error   
+            if( !$result && $transformer->failOnError ) {
+                //print("Error in step = $step<br/>");
+                $this->_view = new WizardView( "update3" );
+                $this->_view->setValue( "resourcesNamingRule", $this->resourcesNamingRule );
+                // current and next step
+                $this->_view->setValue( "currentStep", $step );
+                $this->_view->setValue( "nextStep", $step+1 );                
+                // whether this transformer is ready
+                $this->_view->setValue( "complete", $complete );
+                // transformer id
+                $this->_view->setValue( "transformerId", $this->currentTransformerId );            
+                $this->_view->setValue( "error", true );
+                if( $transformer->DbError() != "" ) {
+                    $message .= "<br/>The database error message was: ".$transformer->DbError()."<br/>";
+                }
+
+                $this->_view->setErrorMessage( $message );
+            }                
+            else {
+                if( !$complete ) {
+                    //print("it's not complete! step = $step<br/>");
+                    $this->_view = new WizardView( "update3" );
+                    $this->_view->setValue( "resourcesNamingRule", $this->resourcesNamingRule );
+                    // current and next step
+                    $this->_view->setValue( "currentStep", $step );
+                    $this->_view->setValue( "nextStep", $step+1 );                
+                    // whether this transformer is ready
+                    $this->_view->setValue( "complete", $complete );
+                    // transformer id
+                    $this->_view->setValue( "transformerId", $this->currentTransformerId );
+                }            
+                else {
+                    // have we already been through all transformers?
+                    //print("transformer complete! - num transformers = ".count($this->transformers)."<br/>");
+                    $moreTransformers = ( $this->currentTransformerId+1 < count( $this->transformers ));
+                    if( $moreTransformers ) {
+                        //print("Starting new transformer!<br/>");
+                        $this->_view = new WizardView( "update3" );
+                        $this->_view->setValue( "resourcesNamingRule", $this->resourcesNamingRule );
+                        // current and next step
+                        $this->_view->setValue( "currentStep", 0 );
+                        $this->_view->setValue( "nextStep", 1 );  
+                        // whether this transformer is ready
+                        $this->_view->setValue( "complete", false );
+                        // transformer id
+                        $this->_view->setValue( "transformerId", $this->currentTransformerId+1 );
+                    }
+                    else {
+                        // no more data to transform, we can finalize the installation!
+						// delete the contents of the temporary folder
+						lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
+						$config =& Config::getConfig();
+						$tmpFolder = $config->getValue( "temp_folder", TEMP_FOLDER );
+                        WizardTools::cleanTmpFolder();
+                        
+                        // save the resources naming rule to config table
+						$config->saveValue( "resources_naming_rule", $this->resourcesNamingRule );
+
+                        $this->_view = new WizardView( "update4" );
+                    }
+                }
+            }
+
+            $this->_view->setValue( "message", $message );            
+
+            return true;
+        }
+    }
+
+	// Fix those resources that we did not convert correctly in 1.2.0
+    class Fix120StepOne extends WizardPagedAction
+    {
+        var $message;  
+        var $currentTransformerId;
+        var $totalTransformers;
+    
+        function Fix120StepOne( $actionInfo, $httpRequest )
+        {
+            $this->WizardPagedAction( $actionInfo, $httpRequest );
+            
+            /**
+             * array with the data transformers that will be run
+             */
+            $this->transformers = Array(
+				"ResourcesFix120FileNameDataTransformer",
+				"DummyDataTransformer"
+            );
+
+            $this->currentTransformerId = $this->getTransformerIdFromRequest();
+            $this->totalTransformers = count( $this->transformers ) - 1;
+        }
+        
+        /**
+         * gets the id of the transformer from the request. If it is not available, it
+         * will return the id of the first transformer available (which is '0')
+         *
+         * @private
+         */
+        function getTransformerIdFromRequest()
+        {    	
+			$id = HttpVars::getRequestValue( "transformerId" );
+			$val = new IntegerValidator();
+			if( !$val->validate( $id ))
+				$id = 0;
+							
+			return $id;        
+        }        
+
+       function perform()
+       {
+            $step = $this->getPageFromRequest();
+            
+            // get the current transformer class so that we can continue where we left
+            $transformerClass = $this->transformers[$this->currentTransformerId];
+            $transformer = new $transformerClass( $step );
+            $result = $transformer->perform();
+            $complete = $transformer->isComplete();
+            $message = $transformer->message;
+            $message = sprintf( $message, $this->currentTransformerId + 1, $this->totalTransformers );
+            
+            //print("transformer = $transformerClass<br/>");
+             
+            // error during processing and the processor is configured
+            // to fail on error   
+            if( !$result && $transformer->failOnError ) {
+                //print("Error in step = $step<br/>");
+                $this->_view = new WizardView( "update3" );
+                // current and next step
+                $this->_view->setValue( "currentStep", $step );
+                $this->_view->setValue( "nextStep", $step+1 );                
+                // whether this transformer is ready
+                $this->_view->setValue( "complete", $complete );
+                // transformer id
+                $this->_view->setValue( "transformerId", $this->currentTransformerId );            
+                $this->_view->setValue( "error", true );
+                if( $transformer->DbError() != "" ) {
+                    $message .= "<br/>The database error message was: ".$transformer->DbError()."<br/>";
+                }
+
+                $this->_view->setErrorMessage( $message );
+            }                
+            else {
+                if( !$complete ) {
+                    //print("it's not complete! step = $step<br/>");
+                    $this->_view = new WizardView( "fix120" );
+                    // current and next step
+                    $this->_view->setValue( "currentStep", $step );
+                    $this->_view->setValue( "nextStep", $step+1 );                
+                    // whether this transformer is ready
+                    $this->_view->setValue( "complete", $complete );
+                    // transformer id
+                    $this->_view->setValue( "transformerId", $this->currentTransformerId );
+                }            
+                else {
+                    // have we already been through all transformers?
+                    //print("transformer complete! - num transformers = ".count($this->transformers)."<br/>");
+                    $moreTransformers = ( $this->currentTransformerId+1 < count( $this->transformers ));
+                    if( $moreTransformers ) {
+                        //print("Starting new transformer!<br/>");
+                        $this->_view = new WizardView( "fix120" );
+                        // current and next step
+                        $this->_view->setValue( "currentStep", 0 );
+                        $this->_view->setValue( "nextStep", 1 );  
+                        // whether this transformer is ready
+                        $this->_view->setValue( "complete", false );
+                        // transformer id
+                        $this->_view->setValue( "transformerId", $this->currentTransformerId+1 );
+                    }
+                    else {
+                        // no more data to transform, we can finalize the installation!
+						// delete the contents of the temporary folder
+						lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
+						$config =& Config::getConfig();
+						$tmpFolder = $config->getValue( "temp_folder", TEMP_FOLDER );
+                        WizardTools::cleanTmpFolder();
+
+                        // User upgrade LifeType from 1.1.x to 1.2.0, they have to use "original_file_name",
+                        // becasue there is no option for user to choose he want to use encoded file name
+                        // or original file name.
+                        // save the resources naming rule to config table
+						$config->saveValue( "resources_naming_rule", "original_file_name" );
+
+                        $this->_view = new WizardView( "update4" );
+                    }
+                }
+            }
+
+            $this->_view->setValue( "message", $message );            
+
+            return true;
+        }
+    }
+
+    // check if the "./tmp" folder is writable by us, otherwise
+    // throw an error before the user gets countless errors
+    // from Smarty
+    if( !File::isWritable( TEMP_FOLDER ) || !File::isDir( TEMP_FOLDER )) {
+        print("<span style=\"color:red; font-size: 14px;\">Error</span><br/><br/>This wizard needs the ".TEMP_FOLDER." folder to be writable by the web server user.<br/><br/>Please correct it and try again.");
+        die();
+    }
+
+    //// main part ////
+    $controller = new Controller( $_actionMap, "nextStep" );
+    $controller->process( HttpVars::getRequest());
+?>



More information about the pLog-svn mailing list