Location: PHPKode > projects > ZZ/OSS Installer > zic-1.1.0dev1/installer/lib/ZZOSS_Installer/Registry.php
<?php
    /*
    Copyright (C) 2001-2004 ZZOSS GbR, http://www.zzoss.com

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    */
    
    /**
    @version $Id: Registry.php,v 1.33 2004/04/07 14:21:53 ordnas Exp $
    @copyright Copyright &copy; 2001-2004 ZZ/OSS GbR, http://www.zzoss.com
    @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
    */
    
    // Include utility functions
    require_once 'ZZOSS_Installer/Utils.php';
    
    // the following classes are only included
    // if we are not in the plugins runtime environment
    if(ZI_INIT_MODE != 'RE'){
        require_once 'PEAR.php';
        // Include package handling.
        require_once 'ZZOSS_Package/Package.php';
        require_once 'ZZOSS_Config/Config.php';
        require_once 'ZZOSS_Debug/Debug.php';
    }
    
class ZZOSS_InstallerRegistry
{
    var $dir                    = '';
    
    var $distribution           = NULL;
    var $distribution_path      = NULL;
    var $distributions          = array();
    var $distributions_resolve  = array();
    var $no_distribution        = true;
    var $application;
    var $applications           = array();
    var $applications_resolve   = array();
    var $has_applications       = false;
    var $no_application         = true;
    var $application_path;
    var $packages_specified     = array();
    var $package_type           = 'package';
    var $log                    = '';
    
    /**
    * Those packages that have been specified in the application XML.
    */
    var $packages_specified = array();
    
    function ZZOSS_InstallerRegistry($dir = NULL)
    {
        $this->dir = $dir;
        $this->dir_installer                = $this->dir.'installer'.DIRECTORY_SEPARATOR;
        $this->dir_distributions_rel        = 'distributions'.DIRECTORY_SEPARATOR;
        $this->dir_distributions            = $this->dir.$this->dir_distributions_rel;
        $this->reg_distributions            = $this->dir_installer.'distributions.reg';
        $this->reg_distributions_resolve    = $this->dir_installer.'distributions_resolve.reg';
        $this->reg_current_distribution     = $this->dir_installer.'current_distribution.reg';
        $this->reg_current_application      = $this->dir_installer.'current_application.reg';
        $this->lock_distributions           = $this->dir_installer.'distributions.lock';
    }
    
    function setDir($dir)
    {
        $this->ZZOSS_InstallerRegistry($dir);
    }
    
    function setInitDir($init_dir)
    {
        $this->init_dir = $init_dir;
    }
    
    function getDir()
    {
        return $this->dir;
    }
    
    function getLog()
    {
        $log = $this->log;
        $this->log = '';
        return $log;
    }
    
    function setDistribution($distribution)
    {
        if(!strlen($distribution)){
            return trigger_error('Empty distribution.');
        }
        // test if "-" for version is contained
        
        $this->distribution = $distribution;
        $this->distribution_path_rel = $this->dir_distributions_rel.$this->distribution.DIRECTORY_SEPARATOR;
        $this->distribution_path = $this->dir_distributions.$this->distribution.DIRECTORY_SEPARATOR;
        
        // Unset previous settings
        unset($this->application_path);
        /*
        if(!is_writeable($this->distribution_path)){
            return trigger_error('Cannot write to '.$this->distribution_path);
        }
        */
        return true;
    }
    
    function setApplication($application)
    {
        if(!strlen($this->distribution_path)){
            return trigger_error('Empty distribution path.');
        }
        
        if(!strlen($application)){
            return trigger_error('Empty application.');
        }
        // test if "-" for version is contained
        $this->application = $application;
        $this->application_path_rel = $this->distribution_path_rel.'applications'.DIRECTORY_SEPARATOR.$this->application.DIRECTORY_SEPARATOR;
        $this->application_path = $this->distribution_path.'applications'.DIRECTORY_SEPARATOR.$this->application.DIRECTORY_SEPARATOR;
        
        /*
        if(!is_writeable($this->application_path)){
            return trigger_error('Cannot write to '.$this->application_path);
        }
        */
        return true;
    }
    
    function getDistributionPath()
    {
        return $this->distribution_path;
    }
    
    function getApplicationPath()
    {
        return $this->application_path;
    }
    
    function getApplicationPathRel()
    {
        return $this->application_path_rel;
    }

    // following function refreshes distributions array and
    // updates serialized disk dump
    function refreshDistributions()
    {
        if(!(
            !$this->areRegisteredDistributions() ||
            $this->areLockedDistributions()
            )) {
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'No need to refresh Distributions.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            return false;
        }
        
        $distributions = array();
        $distributions_resolve = array();
        $count = 0;
        
        // parse distribution.xml file from all available distributions
        if($dp = @opendir($this->dir_distributions)) {
            while (false !== ($entry = readdir($dp))) { 
                $dir = $this->dir_distributions.$entry;
                $file = $dir.DIRECTORY_SEPARATOR.'distribution.xml';
                if(is_dir($dir)&&($entry != '.')&&($entry != '..')&&(file_exists($file))) {
                    $config = new ZZOSS_Config();
                    $config->setFile($file);
                    //$config->setCacheDir($dir);
                    //$config->writeCacheUnique();
                    $xml = $config->query('/distribution');
                    $xml["install"]["path"] = $this->dir_distributions.$entry.DIRECTORY_SEPARATOR;
                    $xml["id"] = $count;
                    $key = $xml["name"].'-'.$xml['release']['version'];
                    $distributions[$key] = $xml;
                    $distributions_resolve[$count] = $key;
                    $count++;
                }
            }
            closedir($dp);
            
            // sort array
            if(is_array($distributions)) {
                ksort($distributions);
                reset($distributions);
            }
            
        }
        // dump arrays to file
        $this->setDistributions( $distributions );
        $this->setDistributionsResolve($distributions_resolve );
        
        // remove possible flag
        $this->unlockDistributions();
    }
    
    /**
    * @see refreshDistributions()
    */
    function areRegisteredDistributions()
    {
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Checking file '.$this->reg_distributions, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        return file_exists($this->reg_distributions);
    }
    
    /**
    * @see refreshDistributions()
    */
    function areLockedDistributions()
    {
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Checking file '.$this->lock_distributions, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        return file_exists($this->lock_distributions);
    }
    
    /**
    * @see refreshDistributions()
    */
    function setDistributions($distributions)
    {
        $this->distributions = $distributions;
        ZZOSS_InstallerUtils::serializeToFile( $this->reg_distributions, $distributions);
    }
    
    /**
    * @see refreshDistributions()
    */
    function setDistributionsResolve($distributions_resolve)
    {
        $this->distributions_resolve = $distributions_resolve;
        ZZOSS_InstallerUtils::serializeToFile( $this->reg_distributions_resolve, $distributions_resolve);
    }
    
    /**
    * @see getDistribution()
    */
    function getDistributions()
    {
        /*
        if(count($this->distributions)){
            return $this->distributions;
        }
        */
        if(file_exists($this->reg_distributions)){
            return $this->distributions = ZZOSS_InstallerUtils::unserializeFromFile($this->reg_distributions);
        }
        return false;
    }

    function getDistribution($distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        if(!$distributions = $this->getDistributions()){
            return false;
        }
        
        if(!is_null($distribution) && isset($distributions[$distribution])) {
            //$this->saveDistributionCurrent($distribution);
            return  $distributions[$distribution];
        }
        
        if($distribution = ZZOSS_InstallerUtils::unserializeFromFile($this->reg_current_distribution)) {
            //$this->saveDistributionCurrent($distribution);
            return $distributions[$distribution];
        }
        
        if(is_array($distributions)) {
            $first = false;
            reset($distributions);
            while(!$first && (list($key,$record) = each($distributions))) {
                $first = $record;
            }
            if(is_array($first)) {
                //$this->saveDistributionCurrent($first['name'].'-'.$first['release']['version']);
                return $first;
            }
        }
        
        return false;
    }
    
    /**
    * @see refreshDistributions()
    */
    function unlockDistributions()
    {
        if(file_exists($this->lock_distributions)){
            unlink($this->lock_distributions);
        }
    }
    
    /**
    * @see removeDistribution();
    */
    function lockDistributions($dir_installer = NULL)
    {
        if(is_null($dir_installer)){
            $dir_installer = $this->dir_installer;
        }
        $fp = fopen($dir_installer."distributions.lock","w");
        fputs($fp,'dummy');
        fclose($fp);
        return true;
    }
    
    function removeDistribution($distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        if(is_dir($this->distribution_path) && System::rm(array('-rf', $this->distribution_path))){
            // set rebuild applications flag
            return $this->lockDistributions();
        }
    }

    function noApplication()
    {
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'No application? '.var_export($this->no_application, true), __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        return $this->no_application;
    }
    
    function setApplicationInstalledById($id, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Distribution: '.$distribution, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        $application = $this->getApplicationById($id);
		$config = new ZZOSS_Config(array('cache' => true, 'numeric' => array('package', 'plugin', 'holder', 'license', 'maintainer')));
		$config->setFile($application['install']['path'].'application.xml');
		ZZOSS_InstallerUtils::serializeToFile(
            $application['install']['path'].'installer'.DIRECTORY_SEPARATOR.'application_installed.reg',
			$config->query('/application')
			);
    }
    
    function getApplicationNameById($id, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Distribution: '.$distribution, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        $application = $this->getApplicationById($id);
        return $application['name'].'-'.$application['release']['version'];
    }
    
    /**
    * @see registerPackages()
    */
    function hasPatches($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        // check for patches
        if(
            file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.'patches.tgz') && 
            filesize($this->application_path.'installer'.DIRECTORY_SEPARATOR.'patches.tgz') > 0
            ) {
            return true;
        }
        
        return false;
    }
    
    function getApplicationSettings($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        // check for settings
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_settings.reg';
        if(!file_exists($file)) {
            return false;
        }
        
        return ZZOSS_InstallerUtils::unserializeFromFile($file);
        return $this->application_settings = $array["ZI_VALUES"];
    }
    
    /**
    * @see refreshPackages()
    */
    function getApplication($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        if(!$applications = $this->getApplications()){
            return false;
        }
        
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Application: '.$this->application, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        //if(strlen($this->application) && isset($applications[$this->application])) {
            //$this->saveApplicationCurrent($application);
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'Returning '.var_export($applications[$this->application], true), __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            if(isset($applications[$this->application])){
                return  $applications[$this->application];
            }
        //}
        return false;
    }
    
    /**
    * following function refreshes packages array and
    * updates serialized disk dump
    *
    * @see getApplications(), getApplicationById()
    */
    function refreshApplications($distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        /*
        // compose array with available applications
        if(!(
            !$this->areRegisteredApplications() ||
            !$this->areRegisteredApplicationsResolve() || 
            $this->areLockedApplications()
            )) {
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'No need to refresh applications.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            return false;
        }
        */
        
        $isModified = false;
        $applications = array();
        $applications_resolve = array();
        $count = 0;
        
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Check if directory exists '.$this->distribution_path.'applications', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        // parse application.xml file from all available applications
        if($dp = @opendir($this->distribution_path.'applications')) {
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'Scanning directory '.$this->distribution_path.'applications', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            
            // remember the current application
            $application = $this->application;
            
            $apps_reg = $this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.reg';
            
            if(file_exists($apps_reg)){
                $reg = $this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.reg';
                $applications = ZZOSS_InstallerUtils::unserializeFromFile($reg);
                $apps_mtime = filemtime($apps_reg);
            } else {
                $apps_mtime = 0;
            }
            
            while (false !== ($entry = readdir($dp))) {
                $dir = $this->distribution_path.'applications'.DIRECTORY_SEPARATOR.$entry;
                $file = $dir.DIRECTORY_SEPARATOR.'application.xml';
                if(is_dir($dir)&&($entry != '.')&&($entry != '..')&&(file_exists($file))) {
                    
                    $this->setApplication($entry);
                    
                    $app_installed_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_installed.reg';
                    $app_hidden_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_hidden.reg';
                    
                    if(file_exists($app_installed_reg)){
                        $installed_mtime = filemtime($app_installed_reg);
                    } else {
                        $installed_mtime = 0;
                    }
                    
                    if(file_exists($app_hidden_reg)){
                        $hidden_mtime = filemtime($app_hidden_reg);
                    } else {
                        $hidden_mtime = 0;
                    }
                    
                    // only update, if applications.reg is older
                    if(
                        filemtime($file) > $apps_mtime ||
                        $installed_mtime > $apps_mtime ||
                        $hidden_mtime > $apps_mtime){
                        
                        $isModified = true;
                        
                        $config = new ZZOSS_Config(array('numeric' => array('maintainer', 'plugin', 'package', 'holder', 'license')));
                        $config->setFile($file);
                        $xml = $config->query('/application');
                        $xml["install"]["path"] = $this->distribution_path.'applications'.DIRECTORY_SEPARATOR.$entry.DIRECTORY_SEPARATOR;
                        //$xml["id"] = $count;
                        // is this application installed ?
                        if($config_installed = $this->isInstalledApplication($entry)){
                            $xml["installed"] = $config_installed["release"]["version"];
                        }
                        // is this application hidden ?
                        $xml["hidden"] = $this->isHiddenApplication($entry);
                        
                        $key = $xml["name"].'-'.$xml['release']['version'];
                        $applications[$key] = $xml;
                        //$applications_resolve[$count] = $key;
                        
                        // check if all necessary directories exist
                        $data_dir = $xml["install"]["path"].'installer';
                        if(!is_dir($data_dir)) {
                            @mkdir($data_dir);
                        }
                    }
                    
                    //$count++;
                }
            }
            closedir($dp);
            
            if($isModified){
                // sort array
                if(is_array($applications)) {
                    ksort($applications);
                    reset($applications);
                }
                // dump arrays to file
                $this->setApplications($applications);
                //$this->setApplicationsResolve( $applications_resolve );
                // remove possible flag
                $this->unlockApplications();
            }
            
            // Set back application
            if(strlen($application)){
                $this->setApplication($application);
            }
        }
    }
    
    function mkDirsApplication($app_path)
    {
        System::mkdir(array('-p',$app_path));
        System::mkdir(array('-p',$app_path.'installer'));
        System::mkdir(array('-p',$app_path.'downloads'));
        System::mkdir(array('-p',$app_path.'packages'));
        System::mkdir(array('-p',$app_path.'packages_installed'));
        System::mkdir(array('-p',$app_path.'cache'));
        System::mkdir(array('-p',$app_path.'plugins'));
    }
    
    function getApplicationById($id, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Distribution: '.$distribution, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
            $this->refreshApplications($distribution);
        }
        
        //if(!count($this->applications)){
            $this->applications = $this->getApplications($distribution);
        //}
        //if(!count($this->applications_resolve)){
            $this->applications_resolve = $this->getApplicationsResolve();
        //}
        return $this->applications[$this->applications_resolve[$id]];
    }
    /*
    function getApplicationName()
    {
        $application = $this->getApplication();
        return $application['name'];
    }
    */
    function isRegisteredApplication($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        return is_dir($this->application_path);
    }
    
    /**
    * @see refreshApplications()
    */
    function isInstalledApplication($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_installed.reg';
        //if(file_exists($file)) {
            return ZZOSS_InstallerUtils::unserializeFromFile($file);
        //}
        
        return false;
    }
    
    /**
    * @see refreshApplications()
    */
    function setInstalledApplication($data, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_installed.reg';
        //if(file_exists($file)) {
            return ZZOSS_InstallerUtils::serializeToFile($file, $data);
        //}
        
        return false;
    }
    
    /**
    * @see refreshApplications()
    */
    function isHiddenApplication($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_hidden.reg';
        return ZZOSS_InstallerUtils::unserializeFromFile($file);
    }
    
    /**
    * @see refreshApplications()
    */
    function setHiddenApplication($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_hidden.reg';
        return ZZOSS_InstallerUtils::serializeToFile($file, true);
        
        return false;
    }
    
    /**
    * Indicates, that this is the very first installation.
    */
    function setApplicationInstalledBy($app_root, $inst_root)
    {
        $file = $this->init_dir.'.installed_by.reg';
        $virgins = ZZOSS_InstallerUtils::unserializeFromFile($file);
        $virgins[$app_root] = $inst_root;
        ZZOSS_InstallerUtils::serializeToFile($file, $virgins);
    }
    
    function getApplicationInstalledBy($app_root)
    {
        $file = $this->init_dir.'.installed_by.reg';
        $virgins = ZZOSS_InstallerUtils::unserializeFromFile($file);
        return $virgins[$app_root];
    }
    
    function unsetApplicationInstalledBy($app_root)
    {
        $file = $this->init_dir.'.installed_by.reg';
        $virgins = ZZOSS_InstallerUtils::unserializeFromFile($file);
        unset($virgins[$app_root]);
        ZZOSS_InstallerUtils::serializeToFile($file, $virgins);
    }
    
    /**
    * @see refreshApplications()
    */
    function unsetHiddenApplication($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_hidden.reg';
        //if(file_exists($file)) {
            return ZZOSS_InstallerUtils::serializeToFile($file, false);
        //}
        
        return false;
    }
    
    function updateApplicationSettingsById($id, $data, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        //$application = $this->getApplicationById($id);
     	$file = $this->getApplicationPath().'installer'.DIRECTORY_SEPARATOR.'application_settings.reg';
		if(file_exists($file)) {
			$old_settings = ZZOSS_InstallerUtils::unserializeFromFile( $file );
			$data = array_merge($old_settings, $data);
		}
		ZZOSS_InstallerUtils::serializeToFile( $file, $data );
        return true;
    }
    
    function updateApplicationSettings($data, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        //$application = $this->getApplication();
     	$file = $this->getApplicationPath().'installer'.DIRECTORY_SEPARATOR.'application_settings.reg';
		if(file_exists($file)) {
			$old_settings = ZZOSS_InstallerUtils::unserializeFromFile( $file );
			$data = array_merge($old_settings, $data);
		}
		ZZOSS_InstallerUtils::serializeToFile( $file, $data );
        return true;
    }
    
    function getApplicationSettingsById($id, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        //$application = $this->getApplicationById($id);
        $file = $this->getApplicationPath().'installer'.DIRECTORY_SEPARATOR.'application_settings.reg';
		if(file_exists($file)){
			return ZZOSS_InstallerUtils::unserializeFromFile( $file );
		}
        
        return false;
    }
    
    /**
    * @see refreshApplications()
    */
    function areRegisteredApplications()
    {
        return file_exists($this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.reg');
    }
    
    /**
    * @see refreshApplications()
    */
    function areRegisteredApplicationsResolve()
    {
        return file_exists($this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications_resolve.reg');
    }
    
    /**
    * @see refreshApplications()
    */
    function areLockedApplications()
    {
        return file_exists($this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.lock');
    }
    
    /**
    * @see removeApplications()
    */
    function lockApplications($distribution = NULL)
    {
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Distribution: '.$distribution, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        $fp = fopen($this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.lock',"w");
        fputs($fp,'dummy');
        fclose($fp);
        return true;
    }
    
    /**
    * @see refreshApplications()
    */
    function setApplications($applications, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        $this->applications = $applications;
        ZZOSS_InstallerUtils::serializeToFile( $this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.reg', $applications );
    }
    
    function unsetApplications($distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        $apps_reg = $this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.reg';
        if(file_exists($apps_reg)){
            unlink($apps_reg);
        }
    }
    
    /**
    * @see refreshApplications()
    */
    function setApplicationsResolve($applications_resolve, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        $this->applications_resolve = $applications_resolve;
        ZZOSS_InstallerUtils::serializeToFile( $this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications_resolve.reg', $applications_resolve );
    }
    
    /**
    * @see getApplicationById()
    */
    function getApplications($distribution = NULL)
    {
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Distribution: '.$distribution, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        $this->refreshApplications();
        
        /*
        if(is_null($distribution) && count($this->applications)){
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'Return existing applications', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            return $this->applications;
        }
        */
        $reg = $this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.reg';
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Read applications from '.$reg, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        $this->applications = ZZOSS_InstallerUtils::unserializeFromFile($reg);
        //print_r($this->applications);
        return $this->applications;
    }
    
    /**
    * @see getApplicationById()
    */
    function getApplicationsResolve($distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        return $this->applications_resolve = ZZOSS_InstallerUtils::unserializeFromFile( $this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications_resolve.reg');
    }
    
    /**
    * @see refreshApplications()
    */
    function unlockApplications($distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        
        if(is_file($this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.lock')){
            @unlink($this->distribution_path.'installer'.DIRECTORY_SEPARATOR.'applications.lock');
        }
    }
    
    function removeApplication($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        if(is_dir($this->application_path)){
            System::rm(array('-rf', $this->application_path));
            $this->unsetApplications();
        }
    }
    
    function setApplicationProfile($profile, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'profile.reg';
	    ZZOSS_InstallerUtils::serializeToFile( $file, $profile );
    }
    
    function getApplicationProfile($application = NULL, $distribution = NULL)
	{
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
	  	// load package selection
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'profile.reg';
		return ZZOSS_InstallerUtils::unserializeFromFile( $file );
	}
    
    function setPackageType($type)
    {
        $this->package_type = $type;
    }
    
    function registerPackages($src = 'downloads', $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $src_pkgs = $this->application_path.$src.DIRECTORY_SEPARATOR;
        
        // Refresh package registry only if something changed
        if(!$this->isOldPkgsReg($src_pkgs)){
            return true;
        }
        
        $packages_specified = $this->getApplicationPackages();
        $this->setPackagesSpecified($packages_specified);
        
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Start registering packages.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        // check for patches
        if($this->hasPatches()) {
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'Extracting patches.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            // extract patches to download folder
            $src_patches = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'patches.tgz';
            $dest_patches = $this->application_path.'downloads'.DIRECTORY_SEPARATOR;
            ZZOSS_Package::extractPatches($src_patches, $dest_patches);
        }
        
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Extracting packages.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        
        $dest_pkgs = $this->application_path.$this->package_type.'s'.DIRECTORY_SEPARATOR;
        
        ZZOSS_Package::extractPackages($src_pkgs, $dest_pkgs, $this->getApplicationPackages());
        
        $this->refreshPackages();
       // $this->refreshPlugins();
       return true;
    }
    
    /**
    * Check if the package registry is old.
    */
    function isOldPkgsReg($pkgs_src_dir)
    {
        /*
		Somehow following code snippet makes installer broken on my system.
		Commenting it seems to help. (czonsius, 25-03-2004)
		
		TODO: Look for real reason of strange processing
        */
        if(!$this->isRegPackages()){
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'Package registry is old, because there is no registry at all.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            return true;
        }
        
        // make sure that file stats are fresh
        clearstatcache();
        
        // get the modified time of the package registry file
        $pkgs_reg_mtime = $this->getPkgsRegMtime();
        
        // have things changed in the source directory where all the package archives reside?
        //echo filemtime($pkgs_src_dir.'.').' (downloads/) > '.$pkgs_reg_mtime.'('.$this->package_type.'_packages.reg)<br/>';
        if(filemtime($pkgs_src_dir.'.') > $pkgs_reg_mtime){
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'Package registry is old; checked filemtime: '.filemtime($pkgs_src_dir.'.').'('.$pkgs_src_dir.') > '.$pkgs_reg_mtime.'?', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            return true;
        }
        
        // has something changed in the directory where we store installed packages?
        $pkgs_installed_dir = $this->application_path.$this->package_type.'s_installed'.DIRECTORY_SEPARATOR;
        /*
        if(is_dir($pkgs_installed_dir)){
            echo filemtime($pkgs_installed_dir.'.').'('.$this->package_type.'_installed/) > '.$pkgs_reg_mtime.'('.$this->package_type.'_packages.reg)<br/>';
        }
        */
        if(is_dir($pkgs_installed_dir) && filemtime($pkgs_installed_dir.'.') > $pkgs_reg_mtime){
            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                ZZOSS_Debug::log('ZZOSS_Registry', 'Package registry is old; checked filemtime: '.filemtime($pkgs_installed_dir.'.').'('.$pkgs_installed_dir.') > '.$pkgs_reg_mtime.'?', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
            }
            return true;
        }
        
        // The package registry is not old, it's up-to-date.
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Packages registry is up-to-date.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        return false;
    }
    
    function getPackageById($id, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        //if(!count($this->packages)){
            $this->packages = $this->getPackages();
        //}
        //if(!count($this->packages_resolve)){
            $this->packages_resolve = $this->getPackagesResolve();
        //}
        return $this->packages[$this->packages_resolve[$id]];
    }
    
    function unsetPackageRemoteInfo($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'remote_package.xml';
        if(file_exists($file)){
            @unlink($file);
        }
    }
    
    function getPackageRemoteInfo($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
		
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'remote_package.xml';
        
        if(file_exists($file)) {
			$package_config = new ZZOSS_Config(array('cache' => true, 'numeric' => array('dep','file', 'build', 'maintainer', 'license', 'holder')));
			$package_config->setFile($file); 
			return $package_config->query('/package');
		}
        
        return false;
    }
    
    function isRegPackages($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $packages_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_packages.reg';
        return file_exists($packages_reg);
    }
    
    function isRegPackagesResolve($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        return file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_resolve.reg');
    }
    
    function isLockedPackages($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        return file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s.lock');
    }
    
    function lockPackagesByApplicationId($id, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $application = $this->getApplicationById($id);
        // set package rebuild flag
        $fp = fopen($application["install"]["path"]."installer".DIRECTORY_SEPARATOR.$this->package_type."s.lock","w");
        fputs($fp,'dummy');
        fclose($fp);
    }
    
    function getPkgsRegMtime($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_packages.reg';
        
        if(!file_exists($file)){
            return false;
        }
        
        return filemtime($file);
    }
    
    function getPackages($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_packages.reg';
        return ZZOSS_InstallerUtils::unserializeFromFile($file);
    }
    
    function hasPkgs($pkg_type = NULL, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        if(is_null($pkg_type)){
            $pkg_type = $this->package_type;
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$pkg_type.'s_packages.reg';
        $pkgs = ZZOSS_InstallerUtils::unserializeFromFile($file);
        if(!is_array($pkgs) || !count($pkgs)){
            return false;
        }
        return true;
    }
    
    function getPackagesResolve($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $file_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_resolve.reg';
        return ZZOSS_InstallerUtils::unserializeFromFile($file_reg);
    }
    
    function getPackageVersions($package, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $versions = ZZOSS_InstallerUtils::unserializeFromFile($this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_versions.reg');
        return $versions[$package];
    }
    
    function getPackagesVersions($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        return ZZOSS_InstallerUtils::unserializeFromFile($this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_versions.reg');
    }
    
    function unlockPackages()
    {
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s.lock';
        if(file_exists($file)){
            @unlink($file);
        }
    }
    
    function getPkgInstalledDir($name)
    {
        return $this->application_path.$this->package_type.'s_installed'.DIRECTORY_SEPARATOR.$name.DIRECTORY_SEPARATOR;
    }
    
    function installPackage($name)
    {
        $pkg_src = $this->application_path.$this->package_type.'s'.DIRECTORY_SEPARATOR.$name.DIRECTORY_SEPARATOR;
        $pkg_installed = $this->getPkgInstalledDir($name);

        if(!is_dir($pkg_src)){
            return trigger_error('Internal Error: Unknow '.$this->package_type.' source path. Seems like the '.$this->package_type.' registry has not been refreshed properly.');
        }
        if(is_dir($pkg_installed)){
            ZZOSS_InstallerUtils::rmdir($pkg_installed);
            $this->log .= '* Removed '.$pkg_installed."\n";
        }
        // Post-processing
        ZZOSS_InstallerUtils::mkdir($pkg_installed);
        $this->log .= '* Created '.$pkg_installed."\n";
        copy(
            $pkg_src.'package.xml', 
            $pkg_installed.'package.xml'
            );
        $this->log .= '* Copied '.$pkg_src.'package.xml to '.$pkg_installed.'package.xml'."\n";
        // remove the extracted package
        // TODO: Do we really have to remove this dir?
        //System::rm(array('-rf',$pkg_src));
        //$this->log .= '* Removed extracted '.$this->package_type.' ('.$pkg_src.')'."\n";
    }
    
    function removePackage($name, $keep_src = true)
    {
        $pkg_src = $this->application_path.$this->package_type.'s'.DIRECTORY_SEPARATOR.$name.DIRECTORY_SEPARATOR;
        $pkg_installed = $this->application_path.$this->package_type.'s_installed'.DIRECTORY_SEPARATOR.$name.DIRECTORY_SEPARATOR;
        
        if(is_dir($pkg_installed)){
            System::rm(array('-rf',$pkg_installed));
            $this->log .= '* Removed installed '.$this->package_type.' "'.$name.'" registry directory ('.$pkg_installed.')'."\n";
        } else {
            $this->log .= '* '.$this->package_type.' "'.$name.'" is not installed'."\n";
        }
        // We remove the src and archive as well if the package has not been specified in application XML
        if(!$keep_src){
            if(is_dir($pkg_src)){
                System::rm(array('-rf',$pkg_src));
                $this->log .= '* Removed '.$this->package_type.' "'.$name.'" src directory ('.$pkg_src.')'."\n";
            }
            $pkg_archive = $this->application_path.'downloads'.DIRECTORY_SEPARATOR.$name.'.tgz';
            if(file_exists($pkg_archive)){
                $this->log .= '* Removed '.$this->package_type.' "'.$name.'" archive ('.$pkg_archive.')'."\n";
                unlink($pkg_archive);
            }
        }
    }
    
    function setPackagesSpecified($specified)
    {
        $this->packages_specified = $specified;
    }
    
    // following function refreshes packages array and
    // updates serialized disk dump
    function refreshPackages($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        /*
        // compose array with available packages
		if(!(
            !$this->isRegPackages() ||
			!$this->isRegPackagesResolve() || 
			$this->isLockedPackages()
            )) {
			return false;
		}
        */
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Start refreshing packages.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        
        $packages = array();
        $packages_resolve = array();
        $packages_versions = array();
        $count = 0;
        $package_sources = array();
        $package_sources[] = $this->application_path.$this->package_type.'s'.DIRECTORY_SEPARATOR;
        
        foreach($package_sources as $sourcedir) {
            // parse package.xml file from all available packages
            if($dp = @opendir($sourcedir)) {
                while (false !== ($entry = readdir($dp))) {
                    if($entry != '.' && $entry != '..'){
                        $dir = $sourcedir.$entry.DIRECTORY_SEPARATOR;
                        $package_xml = $dir.'package.xml';
                        
                        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                            ZZOSS_Debug::log('ZZOSS_Registry', '$entry = '.$entry, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
                            ZZOSS_Debug::log('ZZOSS_Registry', '$dir = '.$dir, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
                            ZZOSS_Debug::log('ZZOSS_Registry', '$file = '.$package_xml, __FILE__, __LINE__, __FUNCTION__, __CLASS__);
                        }
                        if($xml = $this->getPackageDescr($package_xml, $count)) {
                            $key = $xml["name"].'-'.$xml['release']['version'];
                            // already got this package ?
                            if(!isset($packages[$key])) {
                                if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                                    ZZOSS_Debug::log('ZZOSS_Registry', 'Register local package "'.$key.'"', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
                                }
                                $packages[$key] = $xml;
                                $packages_resolve[$count] = $key;
                                $packages_versions[$xml['name']][$xml['release']['version']] = array('installed' => false);
                                $count++;
                            }
                        }
                    }
                }
            }
            //closedir($dp);
        }
        // add remote packages if exist
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'remote_packages.xml';
        if(file_exists($file)) {
            $remote_packages_xml = new ZZOSS_Config( array( 'cache' => true, 
                                                            'numeric' => array('file', 'dir', 'package', 'maintainer', 'holder', 'license')
                                                            ) );
            $remote_packages_xml->setFile($file);
            $remote_packages = $remote_packages_xml->query('/packages/package');
    
            if(is_array($remote_packages)) {
                foreach($remote_packages as $remote_package) {
                    $key = $remote_package["name"].'-'.$remote_package['release']['version'];
                    // only show packages defined in application.xml
                    if(isset($this->packages_specified[$key])){
                        $remote_package["id"] = $count;
                        $remote_package["install"]["type"] = 'remote';
                        if(isset($this->packages_specified[$key]['@']['use']) && $this->packages_specified[$key]['@']['use'] == 'required') {
                            $remote_package["install"]["required"] = true;
                        } else {
                            $remote_package["install"]["required"] = false;
                        }
                        
                        // The package is available locally, but is the specified remote package a newer version?
                        /*if(isset($packages[$key])) {
                            if(ZZOSS_Package::compareRelease($packages[$key]["release"]["version"], $remote_package["release"]["version"])) {
                                if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                                    ZZOSS_Debug::log('ZZOSS_Registry', 'Overwriting existing package "'.$key.'" with remote package which is a newer one.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
                                }
                                $packages[$key] = $remote_package;
                            }
                        } else {*/
                        if(!isset($packages[$key])) {
                            if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
                                ZZOSS_Debug::log('ZZOSS_Registry', 'Package "'.$key.'" not available locally, so assign remote package.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
                            }
                            // The package is not available locally, so we assign the remote package.
                            $packages[$key] = $remote_package;
                            $packages_resolve[$count] = $key;
                            $packages_versions[$remote_package['name']][$remote_package['release']['version']] = array('installed' => false);
                            $count++;
                        }
                    }
                }
            }
        }

        // now check which of the modules are already installed
        if(
            is_dir($this->application_path.$this->package_type.'s_installed') &&
            $dp = @opendir($this->application_path.$this->package_type.'s_installed')
            ) {
            while (false !== ($entry = readdir($dp))) {
                if($entry != '.' && $entry != '..'){
                    $dir = $this->application_path.$this->package_type.'s_installed'.DIRECTORY_SEPARATOR.$entry.DIRECTORY_SEPARATOR;
                    $file = $dir.'package.xml';
                    if($xml = $this->getPackageDescr($file, $count)) {
                        $key = $xml["name"].'-'.$xml['release']['version'];
                        if(!isset($package[$xml["name"].'-'.$xml['release']['version']])) {
                            $key = $xml["name"].'-'.$xml['release']['version'];
                            $package[$key] = $xml;
                            $packages_resolve[$count] = $key;
                            $count++;
                        }
                        $packages[$xml["name"].'-'.$xml["release"]["version"]]["installed"] = $xml["release"]["version"];
                        $packages_versions[$xml['name']][$xml['release']['version']] = array('installed' => true);
                    }
                }
            }
            closedir($dp);
        }

        // sort array
        if(is_array($packages) && (count($packages)>0)) {
            ksort($packages);
            reset($packages);
            reset($packages_versions);
            
            // dump arrays to file
            $this->setPackages($packages);
            $this->setPackagesResolve($packages_resolve);
            $this->setPackagesVersions($packages_versions);
        } else {
            $this->unsetPackages();
            $this->unsetPackagesResolve();
            $this->unsetPackagesVersions();
        }
        
        // remove possible flag
        $this->unlockPackages();
    }
    
    function getPackageDescr($package_xml, $id = NULL)
    {
        if(!file_exists($package_xml)){
            return false;
        }
        
        $package_config = new ZZOSS_Config(array('numeric' => array('dep','file', 'dir', 'build', 'maintainer', 'holder', 'license')));
        $package_config->setFile($package_xml); 
        $xml = array();
        $xml = $package_config->query('/package');
        $xml["install"]["path"] = dirname($package_xml).DIRECTORY_SEPARATOR;
        $xml["install"]["type"] = 'local';
        if(isset($id)){
            $xml["id"] = $id;
        }
        $key = $xml["name"].'-'.$xml['release']['version'];
        if(isset($this->packages_specified[$key]['@']['use']) && $this->packages_specified[$key]['@']['use'] == 'required') {
            $xml["install"]["required"] = true;
        } else {
            $xml["install"]["required"] = false;
        }
        // only show packages defined in application.xml
        if(!isset($this->packages_specified[$key])){
            $xml['_specified'] = false;
        } else {
            $xml['_specified'] = true;
        }
        
        return $xml;
    }
    
    function setPackages($packages)
    {
        ZZOSS_InstallerUtils::serializeToFile( $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_packages.reg', $packages );
    }
    
    function unsetPackages()
    {
        $packages_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_packages.reg';
        if(file_exists($packages_reg)){
            unlink($packages_reg);
        }
    }

    function setPackagesResolve($packages_resolve)
    {
        ZZOSS_InstallerUtils::serializeToFile( $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_resolve.reg', $packages_resolve );
    }
    
    function unsetPackagesResolve()
    {
        $packages_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_resolve.reg';
        if(file_exists($packages_reg)){
            unlink($packages_reg);
        }
    }

    function setPackagesVersions($packages)
    {
        ZZOSS_InstallerUtils::serializeToFile( $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_versions.reg', $packages );
    }
    
    function unsetPackagesVersions()
    {
        $packages_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_versions.reg';
        if(file_exists($packages_reg)){
            unlink($packages_reg);
        }
    }

    function setPackagesActions($packages, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_actions.reg';
	    ZZOSS_InstallerUtils::serializeToFile( $file, $packages );
    }
    
    function setPkgsActionsPreselect($profile)
    {
        // preselect plugins
        $this->setPackageType('plugin');
        $a = array();
        $this->registerPackages();
        $packages = $this->getPackages();
    
        if(is_array($packages) && count($packages)) {
            foreach($packages as $package) {
                if($profile == 'full') {
                    $a[$package["id"]] = 'I';
                } elseif($profile == 'minimum' && $package["install"]["required"]) {
                    $a[$package["id"]] = 'I';
                }
            }
        }
        $this->setPackagesActions($a);
        
        // preselect packages
        $this->setPackageType('package');
        $a = array();
        $this->registerPackages();
        $packages = $this->getPackages();
    
        if(is_array($packages) && count($packages)) {
            foreach($packages as $package) {
                if($profile == 'full') {
                    $a[$package["id"]] = 'I';
                } elseif($profile == 'minimum' && $package["install"]["required"]) {
                    $a[$package["id"]] = 'I';
                }
            }
        }
        $this->setPackagesActions($a);
    }
    
    function updatePackagesActions($packages_new, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $packages_old = $this->getPackagesActions();
        /*
        echo '<pre>';
        print_r($packages_old);
        echo '</pre>';
        */
        $packages = $packages_new + $packages_old;
        /*
        echo '<pre>';
        print_r($packages);
        echo '</pre>';
        */
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_actions.reg';
        @unlink($file);
	    ZZOSS_InstallerUtils::serializeToFile( $file, $packages );
    }

    function getPackagesActions($application = NULL, $distribution = NULL)
	{
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
	  	// load package selection
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_actions.reg';
		return ZZOSS_InstallerUtils::unserializeFromFile( $file );
	}
    
    function setPackagesActionsDeps($packages, $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        $file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_deps.reg';
	    ZZOSS_InstallerUtils::serializeToFile( $file, $packages );
    }
    
    function getPackagesActionsDeps($application = NULL, $distribution = NULL)
	{
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
	  	// load package selection
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_deps.reg';
		return ZZOSS_InstallerUtils::unserializeFromFile( $file );
	}

    function replacePackage( $id, $xml, $dir ) {
        $application = $this->getApplication();
        $packages_application = array();
        if(is_array($application["release"]["packages"]["package"])) {
            foreach($application["release"]["packages"]["package"] as $key => $val) {
                $packages_application[$val["@"]["name"].'-'.$val["@"]["version"]] = $val;
            }
        }
        if(is_dir($dir)&&file_exists($xml)) {
            $package_config = new ZZOSS_Config(array('cache' => true, 'numeric' => array('dep','file', 'build', 'maintainer', 'holder', 'license')));
            $package_config->setFile($xml); 
            $package_config->setCacheDir($this->application_path.'cache'.DIRECTORY_SEPARATOR);
            $xml = $package_config->query('/package');
            $xml["install"]["path"] = $dir;
            $xml["install"]["type"] = 'local';
            $xml["id"] = $id;
            $key = $xml["name"].'-'.$xml['release']['version'];
            if(isset($packages_application[$key]['@']['use']) && $packages_application[$key]['@']['use'] == 'required') {
                $xml["install"]["required"] = true;
            } else {
                $xml["install"]["required"] = false;
            }
            // only register packages defined in application.xml
            if(isset($packages_application[$key])){
                $packages = $this->getPackages();
                $packages[$key] = $xml;
                $this->setPackages($packages);
                $packages_resolve = $this->getPackagesResolve();
                $packages_resolve[$id] = $key;
                $this->setPackagesResolve($packages_resolve);
            }
        }
    }

    function unsetPackagesQueue()
	{
		// save process queue
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_queue.reg';
        if(file_exists($file)){
            return @unlink($file);
        }
        
        return false;
	}
    
    function updatePackagesQueue($queue_new)
	{
		// save process queue
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_queue.reg';
        $queue_old = ZZOSS_InstallerUtils::unserializeFromFile($file);
        if(is_array($queue_old) && count($queue_old)){
            $queue = $queue_new + $queue_old;
            @unlink($file);
        } else {
            $queue = $queue_new;
        }
		ZZOSS_InstallerUtils::serializeToFile( $file, $queue );
	}
    
    function getPackagesQueue()
	{
		// save process queue
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_queue.reg';
		return ZZOSS_InstallerUtils::unserializeFromFile( $file );
	}
    
    function unsetPackagesRemote()
	{
		// save process queue
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_remote.reg';
        if(file_exists($file)){
            return @unlink($file);
        }
        
        return false;
	}
    
    function setPackagesRemote($pkgs)
	{
		// save process queue
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_remote.reg';
		ZZOSS_InstallerUtils::serializeToFile( $file, $pkgs );
	}

    function getPackagesRemote()
	{
		// save process queue
		$file = $this->application_path.'installer'.DIRECTORY_SEPARATOR.$this->package_type.'s_remote.reg';
        return ZZOSS_InstallerUtils::unserializeFromFile($file);
	}

    // prepare package array from application.xml
    function getApplicationPackages()
    {
        if(ZZOSS_INSTALLER_REGISTRY_DEBUG){
            ZZOSS_Debug::log('ZZOSS_Registry', 'Compose application '.$this->package_type.'s.', __FILE__, __LINE__, __FUNCTION__, __CLASS__);
        }
        $packages_application = array();
        $application = $this->getApplication();
        if(
            isset($application["release"][$this->package_type."s"][$this->package_type]) &&
            is_array($application["release"][$this->package_type."s"][$this->package_type])) {
            foreach($application["release"][$this->package_type."s"][$this->package_type] as $package) {
                $packages_application[$package["@"]["name"].'-'.$package["@"]["version"]] = $package;
            }
        }
        return $packages_application;
    }
    
    function isRegPlugins($application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        
        return file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins.reg');
    }
    
    function isLockedPlugins()
    {
        return file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins.lock');
    }
    
    function getPlugins()
    {
        $this->plugins = ZZOSS_InstallerUtils::unserializeFromFile($this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins.reg');
        //print_r($this->plugins);
        return $this->plugins;
    }
    
	function mergePluginArrays($array_1, $array_2, $key) {
		$array = array();
		if(isset($array_1[$key])) {
			if(is_array($array_1[$key])) {
				$array = $array_1[$key];
			}
		}
		if(isset($array_2[$key])) {
			if(is_array($array_2[$key])) {
				$array = array_merge($array, $array_2[$key]);
			}
		}
		return $array;
	}
	
    function composePlugins($installs, $removes = NULL, $plugins_old = NULL)
    {
        // cope with removed plugins
        if(is_array($plugins_old) && count($plugins_old)){
            // we need to take removed plugins into account
            if(is_array($removes) && count($removes)){
                 
                foreach($removes as $role => $vals){
                    foreach($vals as $key_1 => $vals_1){
                        foreach($vals_1 as $key_2 => $vals_2){
                            if(
                                $role == 'install' ||
                                $role == 'update' ||
                                $role == 'remove'
                                ){
                                unset($plugins_old[$role][$key_1][$key_2]);
                            } else {
                                foreach($vals_2 as $plugin_type => $plugins){
                                    foreach($plugins as $plugin => $file){
                                        unset($plugins_old[$role][$key_1][$key_2][$plugin_type][$plugin]);
                                    }
                                    // if there's no more plugin registered, clean up
                                    if(!count($plugins_old[$role][$key_1][$key_2][$plugin_type])){
                                        unset($plugins_old[$role][$key_1][$key_2][$plugin_type]);
                                    }
                                }
                            }
                            // if there's no more plugin registered, clean up
                            if(!count($plugins_old[$role][$key_1][$key_2])){
                                unset($plugins_old[$role][$key_1][$key_2]);
                            }
                        }
                        // if there's no more plugin registered, clean up
                        if(!count($plugins_old[$role][$key_1])){
                            unset($plugins_old[$role][$key_1]);
                        }
                    }
                    // if there's no more plugin registered, clean up
                    if(!count($plugins_old[$role])){
                        unset($plugins_old[$role]);
                    }
                }
            }
        } else {
            $plugins_old = array();
        }
        
        if(isset($installs['_undefined']) && is_array($installs['_undefined']) && count($installs['_undefined'])){
            $undefs = $installs['_undefined'];
            foreach($undefs as $undefs_type => $plugins){
                foreach($plugins as $plugin => $file){
                    // install
                    if(
                        $file == 'exec_install.php' ||
                        $file == 'plugin_install.php'
                        ){
                        $installs['install'][$undefs_type][$plugin] = $file;
                    }
                    // update
                    if(
                        $file == 'exec_update.php' ||
                        $file == 'plugin_update.php'
                        ){
                        $installs['update'][$undefs_type][$plugin] = $file;
                    }
                    // remove
                    if(
                        $file == 'exec_uninstall.php' ||
                        $file == 'plugin_uninstall.php' ||
                        $file == 'exec_remove.php' ||
                        $file == 'plugin_remove.php'
                        ){
                        $installs['remove'][$undefs_type][$plugin] = $file;
                    }
                }
            }
            unset($installs['_undefined']);
        }
        
        if(is_array($installs) && count($installs)){
			  $plugins = array();
			  $plugins['role'] = $this->mergePluginArrays($plugins_old, $installs, 'role');
			  $plugins['install'] = $this->mergePluginArrays($plugins_old, $installs, 'install');
			  $plugins['remove'] = $this->mergePluginArrays($plugins_old, $installs, 'remove');
        }
        return $plugins;
    }
    
    function setPlugins($plugins)
    {
        ZZOSS_InstallerUtils::serializeToFile($this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins.reg', $plugins );
    }
    
    function unsetPlugins()
    {
        $plugins_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins.reg';
        if(file_exists($plugins_reg)){
            return unlink($plugins_reg);
        }
        
        return false;
    }
    
    function unlockPlugins()
    {
        @unlink($this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins.lock');
    }

    function setPluginDev($plugin_dev)
    {
        $plugins_dev_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins_dev.reg';
        $plugins_dev_old = array();
        
        if(file_exists($plugins_dev_reg)){
            $plugins_dev_old = ZZOSS_InstallerUtils::unserializeFromFile($plugins_dev_reg);
        }
        
        if(count($plugins_dev_old)){
            $plugins = $plugin_dev + $plugins_dev_old;
            //@unlink($plugins_dev_reg);
        } else {
            $plugins = $plugin_dev;
        }
        
        ZZOSS_InstallerUtils::serializeToFile($plugins_dev_reg, $plugins);
    }
    
    function getPluginsDev($plugin = NULL)
    {
        $plugins_dev_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'plugins_dev.reg';
        
        if(file_exists($plugins_dev_reg)){
            $plugins_dev = ZZOSS_InstallerUtils::unserializeFromFile($plugins_dev_reg);
            if(!isset($plugin)){
                return $plugins_dev;
            } elseif (isset($plugins_dev[$plugin])){
                return $plugins_dev[$plugin];
            } else {
                return false;
            }
        }
    }
    
    function isConfigured()
    {
        return file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.'application_settings.ser');
    }
    
    function hasPackages()
    {
        return (file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.'packages.ser') && file_exists($this->application_path.'installer'.DIRECTORY_SEPARATOR.'packages_resolve.ser') );
    }
    
    function initDistribution($distribution)
    {
        // Create installer main dir
        if(!is_dir($this->dir_installer)){
            System::mkdir(array('-p',$this->dir_installer));
        }
        
        $this->distribution_path = $this->dir_distributions.$distribution.DIRECTORY_SEPARATOR;
        
        // create directories for distribution if not exists
        System::mkdir(array('-p',$this->distribution_path.'installer'));
        System::mkdir(array('-p',$this->distribution_path.'downloads'));
        System::mkdir(array('-p',$this->distribution_path.'applications'));
        System::mkdir(array('-p',$this->distribution_path.'cache'));
    }
		
    function initApplication($application)
    {
        $this->application_path = $this->distribution_path.'applications'.DIRECTORY_SEPARATOR.$application.DIRECTORY_SEPARATOR;
        
        // create directories
        System::mkdir(array('-p',$this->application_path));
        System::mkdir(array('-p',$this->application_path.'installer'));
        System::mkdir(array('-p',$this->application_path.'downloads'));
        System::mkdir(array('-p',$this->application_path.'packages'));
        System::mkdir(array('-p',$this->application_path.'packages_installed'));
        System::mkdir(array('-p',$this->application_path.'cache'));
        System::mkdir(array('-p',$this->application_path.'plugins'));
    }

    function setProcedures($procedure, $ident = '', $application = NULL, $distribution = NULL)
    {
        if(!is_null($distribution)){
            $this->setDistribution($distribution);
        }
        if(!is_null($application)){
            $this->setApplication($application);
        }
        $procedures_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'procedures'.$ident.'.reg';
        if(file_exists($procedures_reg)){
            unlink($procedures_reg);
        }
        ZZOSS_InstallerUtils::serializeToFile( $procedures_reg, $procedure );
    }

    function setProcedure($procedure, $val = 'on')
    {
        $procedures_new[$procedure] = $val;
        
        $procedures_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'procedures.reg';
		
        $procedures_old = ZZOSS_InstallerUtils::unserializeFromFile($procedures_reg);
        if(is_array($procedures_old) && count($procedures_old)){
            $procedures = $procedures_new + $procedures_old;
            @unlink($procedures_reg);
        } else {
            $procedures = $procedures_new;
        }
		ZZOSS_InstallerUtils::serializeToFile( $procedures_reg, $procedures );
    }

    function isProcedure($type)
    {
        $procedures_reg = $this->application_path.'installer'.DIRECTORY_SEPARATOR.'procedures.reg';
        $procedures = ZZOSS_InstallerUtils::unserializeFromFile($procedures_reg);
        return (isset($procedures[$type]));
    }

    function getProcedures($ident = '')
    {
        return ZZOSS_InstallerUtils::unserializeFromFile( $this->application_path.'installer'.DIRECTORY_SEPARATOR.'procedures'.$ident.'.reg');
    }

    function getProcedure($procedure)
    {
        $procedures = ZZOSS_InstallerUtils::unserializeFromFile( $this->application_path.'installer'.DIRECTORY_SEPARATOR.'procedures.reg');
        return (isset($procedures[$procedure])) ? $procedures[$procedure] : false;
    }
}
?>
Return current item: ZZ/OSS Installer