File Manager

Current Path : /webspace/www.babilon.be/html/lib/classes/
Upload File :
Current File : //webspace/www.babilon.be/html/lib/classes/class.moduleoperations.inc.php

<?php // -*- mode:php; tab-width:4; indent-tabs-mode:t; c-basic-offset:4; -*-
#CMS - CMS Made Simple
#(c)2004-2010 by Ted Kulp (ted@cmsmadesimple.org)
#This project's homepage is: http://cmsmadesimple.org
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
#This program 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 General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#$Id$

/**
 * @package CMS 
 */

/**
 * @ignore
 */
define( "MODULE_DTD_VERSION", "1.3" );

/**
 * A singleton utility class to allow for working with modules.
 *
 * @since		0.9
 * @package		CMS
 */
final class ModuleOperations
{
	/**
	 * System Modules - a list (hardcoded) of all system modules
	 *
	 * @access private
	 * @internal
	 * @ignore
	 */
	protected $cmssystemmodules =  array( 'FileManager','MenuManager','ModuleManager','Search','CMSMailer','News','MicroTiny','CMSPrinting','ThemeManager' );

	static private $_instance = null;
	private $_modules = null;
	private $_moduleinfo;
	private $_moduledeps;
	private $_errors = null;
	
	private $xml_exclude_files = array('^\.svn' , '^CVS$' , '^\#.*\#$' , '~$', '\.bak$', '^\.git');
	private $xmldtd = '
<!DOCTYPE module [
  <!ELEMENT module (dtdversion,name,version,description*,help*,about*,requires*,file+)>
  <!ELEMENT dtdversion (#PCDATA)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT version (#PCDATA)>
  <!ELEMENT mincmsversion (#PCDATA)>
  <!ELEMENT description (#PCDATA)>
  <!ELEMENT help (#PCDATA)>
  <!ELEMENT about (#PCDATA)>
  <!ELEMENT requires (requiredname,requiredversion)>
  <!ELEMENT requiredname (#PCDATA)>
  <!ELEMENT requiredversion (#PCDATA)>
  <!ELEMENT file (filename,isdir,data)>
  <!ELEMENT filename (#PCDATA)>
  <!ELEMENT isdir (#PCDATA)>
  <!ELEMENT data (#PCDATA)>
]>';

  /**
   * ------------------------------------------------------------------
   * Error Functions
   * ------------------------------------------------------------------
   */
  private function __construct() {}


  /**
   * Get the only permitted instance of this object.  It will be created if necessary
   *
   * @return object
   */
  public static function &get_instance()
  {
	  if( !isset(self::$_instance) ) {
		  $c = __CLASS__;
		  self::$_instance = new $c;
	  }
	  return self::$_instance;
  }


  /**
   * Set an error condition
   *
   * @ignore
   * @deprecated
   * @param string $str The string to set for the error
   * @return void
   */
  protected function SetError($str = '')
  {
	  $this->_errors = $str;
  }


  /**
   * Return the last error
   *
   * @ignore
   * @deprecated
   * @return string The last error, if any
   */
  public function GetLastError()
  {
	  return $this->_errors;
  }


  /**
   * Creates an xml data package from the module directory.
   *
   * @param mixed $modinstance The instance of the module object
   * @param string $message Reference to a string which will be filled with the message 
   *                        created by the run of the method
   * @param integer $filecount Reference to an interger which will be filled with the 
   *                           total # of files in the package
   * @return string an XML string comprising the module and its files
   */
  function CreateXMLPackage( &$modinstance, &$message, &$filecount )
  {
	  // get a file list
	  $filecount = 0;
	  $dir = dirname(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR."modules".DIRECTORY_SEPARATOR.$modinstance->GetName();
	  $files = get_recursive_file_list( $dir, $this->xml_exclude_files );

	  $xmltxt  = '<?xml version="1.0" encoding="ISO-8859-1"?>';
	  $xmltxt .= $this->xmldtd."\n";
	  $xmltxt .= "<module>\n";
	  $xmltxt .= "	<dtdversion>".MODULE_DTD_VERSION."</dtdversion>\n";
	  $xmltxt .= "	<name>".$modinstance->GetName()."</name>\n";
	  $xmltxt .= "	<version>".$modinstance->GetVersion()."</version>\n";
	  $xmltxt .= "  <mincmsversion>".$modinstance->MinimumCMSVersion()."</mincmsversion>\n";
	  $xmltxt .= "	<help><![CDATA[".base64_encode($modinstance->GetHelpPage())."]]></help>\n";
	  $xmltxt .= "	<about><![CDATA[".base64_encode($modinstance->GetAbout())."]]></about>\n";
	  $desc = $modinstance->GetAdminDescription();
	  if( $desc != '' )
		  {
			  $xmltxt .= "	<description><![CDATA[".$desc."]]></description>\n";
		  }
	  $depends = $modinstance->GetDependencies();
	  foreach( $depends as $key=>$val )
		  {
			  $xmltxt .= "	<requires>\n";
			  $xmltxt .= "	  <requiredname>$key</requiredname>\n";
			  $xmltxt .= "	  <requiredversion>$val</requiredversion>\n";
			  $xmltxt .= "	</requires>\n";
		  }
	  foreach( $files as $file )
		  {
			  // strip off the beginning
			  if (substr($file,0,strlen($dir)) == $dir)
				  {
					  $file = substr($file,strlen($dir));
				  }
			  if( $file == '' ) continue;

			  $xmltxt .= "	<file>\n";
			  $filespec = $dir.DIRECTORY_SEPARATOR.$file;
			  $xmltxt .= "	  <filename>$file</filename>\n";
			  if( @is_dir( $filespec ) )
				  {
					  $xmltxt .= "	  <isdir>1</isdir>\n";
				  }
			  else
				  {
					  $xmltxt .= "	  <isdir>0</isdir>\n";
					  $data = base64_encode(file_get_contents($filespec));
					  $xmltxt .= "	  <data><![CDATA[".$data."]]></data>\n";
				  }

			  $xmltxt .= "	</file>\n";
			  ++$filecount;
		  }
	  $xmltxt .= "</module>\n";
	  $message = 'XML package of '.strlen($xmltxt).' bytes created for '.$modinstance->GetName();
	  $message .= ' including '.$filecount.' files';
	  return $xmltxt;
  }


/**
 * Unpackage a module from an xml string
 * does not touch the database
 *
 * @param string $xml The xml data for the package
 * @param boolean $overwrite Should we overwrite files if they exist?
 * @param boolean $brief If set to true, less checking is done and no errors are returned
 * @return array A hash of details about the installed module
 */
  function ExpandXMLPackage( $xmluri, $overwrite = 0, $brief = 0 )
  {
	$gCms = cmsms();
	$this->SetError('');

	// first make sure that we can actually write to the module directory
	$dir = dirname(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR."modules";

	if( !is_writable( $dir ) && $brief == 0 ) {
		// directory not writable
		$this->SetError( lang( 'errordirectorynotwritable' ) );
		return false;
	}

	$reader = new XMLReader();
	$ret = $reader->open($xmluri);
	if( $ret == 0 ) {
		$this->SetError( lang( 'errorcouldnotparsexml' ) );
		return false;
	}

	$this->SetError('');
	$havedtdversion = false;
	$moduledetails = array();
	if( is_file($xmluri) ) $moduledetails['size'] = filesize($xmluri);
	$required = array();
	while( $reader->read() ) {
		switch($reader->nodeType) {
		case XMLREADER::ELEMENT:
			switch( strtoupper($reader->localName) ) {
			case 'NAME':
				$reader->read();
				$moduledetails['name'] = $reader->value;
				// check if this module is already installed
				if( isset( $this->_modules[$moduledetails['name']] ) && $overwrite == 0 && $brief == 0 ) {
					$this->SetError( lang( 'moduleinstalled' ) );
					return TRUE;
				}
				break;

			case 'DTDVERSION':
				$reader->read();
				if( $reader->value != MODULE_DTD_VERSION ) {
					$this->SetError( lang( 'errordtdmismatch' ) );
					return false;
				}
				$havedtdversion = true;
				break;

			case 'VERSION':
				$reader->read();
				$moduledetails['version'] = $reader->value;
				$tmpinst = $this->get_module_instance($moduledetails['name']);
				if( $tmpinst && $brief == 0 ) {
					$version = $tmpinst->GetVersion();
					if( version_compare($moduledetails['version'],$version) < 0 ) {
						$this->SetError( lang('errorattempteddowngrade') );
						return false;
					}
					else if (version_compare($moduledetails['version'],$version) == 0 ) {
						$this->SetError( lang('moduleinstalled') );
						return TRUE;
					}
				}
				break;
		
			case 'MINCMSVERSION':
			case 'MAXCMSVERSION':
			case 'DESCRIPTION':
			case 'FILENAME':
			case 'ISDIR':
				$name = $reader->localName;
				$reader->read();
				$moduledetails[$name] = $reader->value;
				break;

			case 'HELP':
			case 'ABOUT':
				$name = $reader->localName;
				$reader->read();
				$moduledetails[$name] = base64_decode($reader->value);
				break;

			case 'REQUIREDNAME':
				$reader->read();
				$requires['name'] = $reader->value;
				break;

			case 'REQUIREDVERSION':
				$reader->read();
				$requires['version'] = $reader->value;
				break;

			case 'DATA':
				$reader->read();
				$moduledetails['filedata'] = $reader->value;
				break;
			}
			break;

		case XMLReader::END_ELEMENT:
			switch( strtoupper($reader->localName) ) {
			case 'REQUIRES':
				if( count($requires) != 2 ) continue;
				if( !isset( $moduledetails['requires'] ) ) $moduledetails['requires'] = array();
				$moduledetails['requires'][] = $requires;
				$requires = array();
				break;

			case 'FILE':
				if( $brief != 0 ) continue;

				// finished a first file
				if( !isset( $moduledetails['name'] )	   || !isset( $moduledetails['version'] ) ||
					!isset( $moduledetails['filename'] ) || !isset( $moduledetails['isdir'] ) ) {
					$this->SetError( lang('errorincompletexml') );
					return false;
				}

				// ready to go
				$moduledir=$dir.DIRECTORY_SEPARATOR.$moduledetails['name'];
				$filename=$moduledir.$moduledetails['filename'];
				if( !file_exists( $moduledir ) ) {
					if( !@mkdir( $moduledir ) && !is_dir( $moduledir ) ) {
						$this->SetError(lang('errorcantcreatefile').' '.$moduledir);
						break;
					}
				}
				else if( $moduledetails['isdir'] ) {
					if( !@mkdir( $filename ) && !is_dir( $filename ) ) {
						$this->SetError(lang('errorcantcreatefile').' '.$filename);
						break;
					}
				}
				else {
					$data = $moduledetails['filedata'];
					if( strlen( $data ) ) $data = base64_decode( $data );
					$fp = @fopen( $filename, "w" );
					if( !$fp ) $this->SetError(lang('errorcantcreatefile').' '.$filename);
					if( strlen( $data ) ) @fwrite( $fp, $data );
					@fclose( $fp );
				}
				unset( $moduledetails['filedata'] );
				unset( $moduledetails['filename'] );
				unset( $moduledetails['isdir'] );
				break;
			}
			break;
		}
	} // while

	$reader->close();
	if( $havedtdversion == false ) {
		$this->SetError( lang( 'errordtdmismatch' ) );
		return false;
	}

	// we've created the module's directory
	unset( $moduledetails['filedata'] );
	unset( $moduledetails['filename'] );
	unset( $moduledetails['isdir'] );

	if( $this->GetLastError() != "" ) return false;
	if( !$brief ) audit('','Module', 'Expanded module: '.$moduledetails['name'].' version '.$moduledetails['version']);

	return $moduledetails;
  }


 private function _install_module(CmsModule& $module_obj)
 {
	 debug_buffer('install_module '.$module_obj->GetName());

	 $gCms = cmsms(); // preserve the global.
	 $db = $gCms->GetDb();

	 // todo, check to make sure the module isn't already installed.

	 $result = $module_obj->Install();
	 if( !isset($result) || $result === FALSE) {
		 // install returned nothing, or FALSE
		 $query = 'DELETE FROM '.cms_db_prefix().'modules WHERE module_name = ?';
		 $dbr = $db->Execute($query,array($module_obj->GetName()));

		 $lazyload_fe    = (method_exists($module_obj,'LazyLoadFrontend') && $module_obj->LazyLoadFrontend())?1:0;
		 $lazyload_admin = (method_exists($module_obj,'LazyLoadAdmin') && $module_obj->LazyLoadAdmin())?1:0;
		 $query = 'INSERT INTO '.cms_db_prefix().'modules 
                   (module_name,version,status,admin_only,active,allow_fe_lazyload,allow_admin_lazyload)
                   VALUES (?,?,?,?,?,?,?)';
		 $dbr = $db->Execute($query,array($module_obj->GetName(),$module_obj->GetVersion(),'installed',
										  ($module_obj->IsAdminOnly()==true)?1:0,
										  1,$lazyload_fe,$lazyload_admin));

		 $deps = $module_obj->GetDependencies();
		 if( is_array($deps) && count($deps) ) {
			 $query = 'INSERT INTO '.cms_db_prefix().'module_deps
                       (parent_module,child_module,minimum_version,create_date,modified_date)
                       VALUES (?,?,?,NOW(),NOW())';
			 foreach( $deps as $depname => $depversion ) {
				 if( !$depname || !$depversion ) continue;
				 $dbr = $db->Execute($query,array($depname,$module_obj->GetName(),$depversion));
			 }
		 }

		 $this->_moduleinfo[$module_obj->GetName()] = array('module_name'=>$module_obj->GetName(),
															'version'=>$module_obj->GetVersion(),
															'status'=>'installed',
															'active'=>1,
															'admn_only'=>($module_obj->IsAdminOnly()==true)?1:0,
															'allow_fe_lazyload'=>($module_obj->LazyLoadFrontend()==TRUE)?1:0,
															'allow_admin_lazyload'=>($module_obj->LazyLoadAdmin()==TRUE)?1:0);

		 Events::SendEvent('Core', 'ModuleInstalled', array('name' => $module_obj->GetName(), 'version' => $module_obj->GetVersion()));
		 audit('',$module_obj->GetName(), 'Installed version '.$module_obj->GetVersion());
		 $gCms->clear_cached_files();

		 return array(TRUE,$module_obj->InstallPostMessage());
	 }

	 return array(FALSE,$result);
 }


  /**
   * Install a module into the database
   *
   * @internal
   * @param string $module The name of the module to install
   * @param boolean $loadifnecessary If true, loads the module before trying to install it
   * @return array Returns a tuple of whether the install was successful and a message if applicable
   */
  public function InstallModule($module, $loadifnecessary = false)
  {
	  // get an instance of the object (force it).
	  $modinstance = $this->get_module_instance($module,'',TRUE);
	  if( !$modinstance ) return array(false,lang('errormodulenotloaded'));

	  // check for dependencies
	  $deps = $modinstance->GetDependencies();
	  if( is_array($deps) && count($deps) ) {
		  foreach( $deps as $mname => $mversion ) {
			  if( $mname == '' || $mversion == '' ) continue; // invalid entry.
			  $newmod = $this->get_module_instance($mname);
			  if( !is_object($newmod) || version_compare($newmod->GetVersion(),$mversion) < 0 ) {
				  return array(false,lang('missingdependency').': '.$mname);
			  }
		  }
	  }

	  // do the actual installation stuff.
	  $res = $this->_install_module($modinstance);
	  if( $res[0] == FALSE && $res[1] == '') $res[1] = lang('errorinstallfailed');
	  return $res;
  }


  private function &_get_module_info()
  {
	  if( !is_array($this->_moduleinfo) || count($this->_moduleinfo) == 0 ) {
		  $query = 'SELECT * FROM '.cms_db_prefix().'modules ORDER BY module_name';
		  $db = cmsms()->GetDb();
		  $tmp = $db->GetArray($query);
		  if( is_array($tmp) ) {
			  $config = cmsms()->GetConfig();
			  $dir = $config['root_path'].'/modules';
			  $this->_moduleinfo = array();
			  for( $i = 0; $i < count($tmp); $i++ ) {
				  $name = $tmp[$i]['module_name'];
				  if( is_file($dir."/$name/$name.module.php") ) {
					  if( !isset($this->_moduleinfo[$name]) ) $this->_moduleinfo[$name] = $tmp[$i];
				  }
			  }
		  }
	  }

	  return $this->_moduleinfo;
  }



  private function _load_module($module_name,$force_load = FALSE,$dependents = TRUE)
  {
	  $config = cmsms()->GetConfig();
	  $dir = $config['root_path'].'/modules';

	  $info = $this->_get_module_info();
	  if( !isset($info[$module_name]) && !$force_load ) {
		  debug_buffer("Nothing is known about $module_name... cant load it");
		  return FALSE;
	  }
	  if( (!isset($info[$module_name]['active']) || $info[$module_name]['active'] == 0) && !$force_load ) {
		  debug_buffer('Requested deactivated module '.$module_name);
		  return FALSE;
	  }

	  global $CMS_INSTALL_PAGE;
	  global $CMS_VERSION;
	  global $CMS_PREVENT_AUTOINSTALL;
	  global $CMS_FORCE_MODULE_LOAD;
	  $allow_auto = (isset($CMS_PREVENT_AUTOINSTALL) && $CMS_PREVENT_AUTOINSTALL)?0:1;

	  $gCms = cmsms(); // backwards compatibility... set the global.
	  if( !class_exists($module_name) ) {
		  $fname = $dir."/$module_name/$module_name.module.php";
		  if( !is_file($fname) ) {
			  debug_buffer("Cannot load $module_name because the module file does not exist");
			  return FALSE;
		  }

		  debug_buffer('loading module '.$module_name);
		  require_once($fname); 
	  }

	  // load dependencies.
	  if( !isset($config['modules_noloaddependants']) && $dependents == TRUE ) {
		  $deps = $this->get_module_dependencies($module_name);
		  if( is_array($deps) && count($deps) ) {
			  $res = true;
			  foreach( $deps as $name => $ver ) {
				  // this is the start of a recursive routine.
				  // get_module_instance may call _load_module.
				  $obj2 = $this->get_module_instance($name,$ver);
				  if( !is_object($obj2) ) {
					  $res = false;
					  break;
				  }
			  }
			  if( !$res && !isset($CMS_FORCE_MODULE_LOAD)) {
				  audit('','Core',"Cannot load module $module_name ... Problem loading dependent module $name version $ver");
				  debug_buffer("Cannot load $module_name... cannot load it's dependants.");
				  unset($obj);
				  return FALSE;
			  }
		  }
	  }

	  $obj = new $module_name;
	  if( !is_object($obj) ) {
		  // oops, some problem loading.
		  audit('','Core',"Cannot load module $module_name ... some problem instantiating the class");
		  debug_buffer("Cannot load $module_name ... some problem instantiating the class");
		  return FALSE;
	  }

	  if (version_compare($obj->MinimumCMSVersion(),$CMS_VERSION) == 1 ) {
		  // oops, not compatible.... can't load.
		  audit('','Core','Cannot load module '.$module_name.' it is not compatible wth this version of CMSMS');
		  debug_buffer("Cannot load $module_name... It is not compatible with this version of CMSMS");
		  unset($obj);
		  return FALSE;
	  }

	  if( isset($info[$module_name]) && $info[$module_name]['status'] != 'installed' && 
		  (isset($CMS_INSTALL_PAGE) || $this->_is_queued_for_install($module_name)) ) {
		  // not installed, can we auto-install it?
		  if( (in_array($module_name,$this->cmssystemmodules) || $obj->AllowAutoInstall() == true ||
			   $this->_is_queued_for_install($module_name)) && $allow_auto ) {
			  $res = $this->_install_module($obj);
			  if( !isset($_SESSION['moduleoperations_result']) )  $_SESSION['moduleoperations_result'] = array();
			  $_SESSION['moduleoperations_result'][$module_name] = $res;
		  }
		  else if( !isset($CMS_FORCE_MODULE_LOAD) ) {
			  // nope, can't auto install...
			  unset($obj);
			  return FALSE;
		  }
	  }

	  // check to see if an upgrade is needed.
	  allow_admin_lang(TRUE); // isn't this ugly.
	  if( isset($info[$module_name]) && $info[$module_name]['status'] == 'installed' ) {
		  $dbversion = $info[$module_name]['version'];
		  if( version_compare($dbversion, $obj->GetVersion()) == -1 ) {
			  // upgrade is needed
			  if( ($obj->AllowAutoUpgrade() == TRUE || $this->_is_queued_for_install($module_name)) && $allow_auto ) {
				  // we're allowed to upgrade
				  $res = $this->_upgrade_module($obj);
				  if( !isset($_SESSION['moduleoperations_result']) ) $_SESSION['moduleoperations_result'] = array();
				  if( $res ) {
					  $res2 = array(TRUE,lang('moduleupgraded'));
					  $_SESSION['moduleoperations_result'][$module_name] = $res2;
					  return TRUE;
				  }
				  else {
					  $res2 = array(FALSE,lang('moduleupgradeerror'));
					  $_SESSION['moduleoperations_result'][$module_name] = $res2;
					  return FALSE;
				  }
				  if( !$res ) {
					  // upgrade failed
					  allow_admin_lang(FALSE); // isn't this ugly.
					  debug_buffer("Automatic upgrade of $module_name failed");
					  unset($obj);
					  return FALSE;
				  }
			  }
			  else if( !isset($CMS_FORCE_MODULE_LOAD) ) {
				  // nope, can't auto upgrade either
				  allow_admin_lang(FALSE); // isn't this ugly.
				  unset($obj);
				  return FALSE;
			  }
		  }
	  }

	  if( (isset($info[$module_name]) && $info[$module_name]['status'] == 'installed') || 
		  $force_load ) {
		  if( is_object($obj) ) $this->_modules[$module_name] = $obj;
		  return TRUE;
	  }

	  return FALSE;
  }


  /**
   * A function to return a list of all modules that appear to exist properly in the modules directory.
   *
   * @internal
   * @return array of complete specifications to module files
   */
  public function FindAllModules()
  {
	$dir = dirname(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR."modules";
	
	$result = array();
	if( $handle = @opendir($dir) ) {
		while( ($file = readdir($handle)) !== false ) {
			$fn = "$dir/$file/$file.module.php";
			if( @is_file($fn) )	$result[] = $file;
		}
	}
	
	sort($result);
	return $result;
  }


  /**
   * Finds all modules in the filesystem, and builds a database about them
   * 
   * @since 1.10
   * @access private
   * @internal
   */
  private function _load_all_modules()
  {
	  $this->_moduleinfo = array();
	  $info = $this->_get_module_info();
	  $names = $this->FindAllModules();
	  foreach( $names as $name ) {
		  if( isset($this->_moduleinfo[$name]) ) continue; // already know about this module.

		  // this module isn't in the database, but is in the filesystem... make up some dummy info.
		  $rec = array('module_name'=>$name,'status'=>'not installed','version'=>'0.0',
					   'admin_only'=>0,'active'=>0,'allow_fe_lazyload'=>0,'allow_admin_lazyload'=>0);
		  $this->_moduleinfo[$name] = $rec;
	  }
	  ksort($this->_moduleinfo);
  }


  /**
   * Finds all modules that are available to be loaded...
   * this method uses the information in the database to load the modules that are necessary to load
   * it also, will go through any queued installs/upgrades and force those modules to load, which 
   * will in turn do the upgrading and installing if necessary.
   *
   * @access public
   * @internal
   * @param loadall boolean indicates wether ALL modules in the filesystem should be loaded, default is false
   * @param noadmin boolean indicates that modules marked as admin_only in the database should not be loaded, default is false
   * @param no_lazyload boolean indicates that modules marked as lazy_loadable should be loaded anywayz, default is falze
   * @return void
   */
  public function LoadModules($loadall = false,$noadmin = false, $no_lazyload = false)
  {
	  if( $loadall ) $this->_load_all_modules();
	  global $CMS_ADMIN_PAGE;
	  global $CMS_STYLESHEET;
	  $config = cmsms()->GetConfig();

	  $allinfo = $this->_get_module_info();
	  if( !is_array($allinfo) ) return; // no modules installed, probably an empty database... edge case.
	  foreach( $allinfo as $module_name => $info ) {
		  if( $info['status'] != 'installed' ) continue;
		  if( !$info['active'] ) continue;
		  if( ($info['admin_only'] || (isset($info['allow_fe_lazyload']) && $info['allow_fe_lazyload'])) && !isset($CMS_ADMIN_PAGE) ) continue;
		  if( isset($config['admin_loadnomodules']) && isset($CMS_ADMIN_PAGE) ) continue;
		  if( isset($info['allow_admin_lazyload']) && $info['allow_admin_lazyload'] && isset($CMS_ADMIN_PAGE) ) continue;
		  if( isset($CMS_STYLESHEET) && !isset($CMS_STYLESHEET) ) continue;
		  $this->get_module_instance($module_name);
	  }
	  if( isset($_SESSION['moduleoperations']) && is_array($_SESSION['moduleoperations']) && count($_SESSION['moduleoperations']) ) {
		  // there are modules queued for install/upgrade that may not have been loaded.
		  foreach($_SESSION['moduleoperations'] as $module_name => $info ) {
			  if( !isset($allinfo[$module_name]) ) {
				  // we don't know about this module yet...
				  $rec = array('module_name'=>$module_name,'status'=>'not installed','version'=>'0.0',
							   'admin_only'=>0,'active'=>0,'allow_fe_lazyload'=>0,'allow_admin_lazyload'=>0);
				  $this->_moduleinfo[$module_name] = $rec;
			  }
			  $this->get_module_instance($module_name,'',TRUE);
			  unset($_SESSION['moduleiperations'][$module_name]);
		  }
		  // by here... we should not have anything left queued
		  unset($_SESSION['moduleoperations']);
	  }
	  return;
  }


  private function _upgrade_module( &$module_obj, $to_version = '' )
  {
	  // we can't upgrade a module if the schema is not up to date.
	  $db = cmsms()->GetDb();
	  $tmp = $db->GetOne('SELECT version FROM '.cms_db_prefix().'version');
	  if( $tmp && $tmp < CMS_SCHEMA_VERSION ) return FALSE;

	  $info = $this->_get_module_info();
	  $module_name = $module_obj->GetName();
	  $dbversion = $info[$module_name]['version'];

	  if( $to_version == '' ) $to_version = $module_obj->GetVersion();

	  $result = $module_obj->Upgrade($dbversion,$to_version);
	  if( $result !== FALSE ) {
		  $db = cmsms()->GetDb();
		  $lazyload_fe    = (method_exists($module_obj,'LazyLoadFrontend') && $module_obj->LazyLoadFrontend())?1:0;
		  $lazyload_admin = (method_exists($module_obj,'LazyLoadAdmin') && $module_obj->LazyLoadAdmin())?1:0;

		  $query = 'UPDATE '.cms_db_prefix().'modules SET version = ?, allow_fe_lazyload = ?,allow_admin_lazyload = ? WHERE module_name = ?';
		  $dbr = $db->Execute($query,array($module_obj->GetVersion(),$lazyload_fe,$lazyload_admin,$module_obj->GetName()));

		  $info[$module_obj->GetName()]['version'] = $module_obj->GetVersion();
		  audit('','Module', 'Upgraded module '.$module_obj->GetName().' to version '.$module_obj->GetVersion());
		  Events::SendEvent('Core', 'ModuleUpgraded', array('name' => $module_obj->GetName(), 'oldversion' => $dbversion, 'newversion' => $module_obj->GetVersion()));
		  cmsms()->clear_cached_files();
		  return TRUE;
	  }
	  return FALSE;
  }


  /**
   * Upgrade a module
   *
   * This is an internal method, subject to change in later releases.  It should never be called for upgrading arbitrary modules.
   * Any use of this function by third party code will not be supported.  Use at your own risk and do not report bugs or issues
   * related to your use of this module.
   *
   * @param string $module The name of the module to upgrade
   * @return boolean Whether or not the upgrade was successful
   */
  public function UpgradeModule( $module_name, $to_version = '')
  {
	  $module_obj = $this->get_module_instance($module_name);
	  if( !is_object($module_obj) ) return FALSE;
	  return $this->_upgrade_module($module_obj,$to_version);
  }


  /**
   * Uninstall a module
   *
   * @param string $module The name of the module to upgrade
   * @return boolean Whether or not the upgrade was successful
   * @internal
   */
  public function UninstallModule( $module)
  {
	  $gCms = cmsms();
	  $db = $gCms->GetDb();

	  $modinstance = cms_utils::get_module($module);
	  if( !$modinstance ) return FALSE;

	  $cleanup = $modinstance->AllowUninstallCleanup();
	  $result = $modinstance->Uninstall();

	  if (!isset($result) || $result === FALSE) {
		  // now delete the record
		  $query = "DELETE FROM ".cms_db_prefix()."modules WHERE module_name = ?";
		  $db->Execute($query, array($module));

		  // delete any dependencies
		  $query = "DELETE FROM ".cms_db_prefix()."module_deps WHERE child_module = ?";
		  $db->Execute($query, array($module));

		  // clean up, if permitted
		  if ($cleanup) {
			  $db->Execute('DELETE FROM '.cms_db_prefix().'module_templates where module_name=?',array($module));
			  $db->Execute('DELETE FROM '.cms_db_prefix().'event_handlers where module_name=?',array($module));
			  $db->Execute('DELETE FROM '.cms_db_prefix().'events where originator=?',array($module));
			  $db->Execute('DELETE FROM '.cms_db_prefix().'module_smarty_plugins where module=?',array($module));
			  $db->Execute('DELETE FROM '.cms_db_prefix().
						   "siteprefs WHERE sitepref_name LIKE '".
						   str_replace("'",'',$db->qstr($module)).
						   "_mapi_pref%'");
			  $db->Execute('DELETE FROM '.cms_db_prefix().'routes WHERE dest = ?',array($module));
			  $db->Execute('DELETE FROM '.cms_db_prefix().'module_smarty_plugins WHERE module = ?',array($module));
		  }

		  // clear the cache.
		  $gCms->clear_cached_files();

		  // Removing module from info
		  unset($this->_moduleinfo[$module]);

		  Events::SendEvent('Core', 'ModuleUninstalled', array('name' => $module));
		  audit('','Module','Uninstalled module '.$module);
	  }
	  else {
		  $this->setError($result);
		  return false;
	  }
	  return true;
  }


  /**
   * Test if a module is active
   */
  public function IsModuleActive($module_name)
  {
	  if( !$module_name ) return FALSE;
	  $info = $this->_get_module_info();
	  if( !isset($info[$module_name]) ) return FALSE;

	  return (bool)$info[$module_name]['active'];
  }


  /**
   * Activate a module
   *
   * @param string module name
   * @param boolean flag indicating wether to activate or deactivate the module
   * @return boolean
   */
  public function ActivateModule($module_name,$activate = true)
  {
	  if( !$module_name ) return FALSE;
	  $info = $this->_get_module_info();
	  if( !isset($info[$module_name]) ) return FALSE;

	  $o_state = $info['module_name']['active'];
	  if( $activate ) {
		  $info['module_name']['active'] = 1;
	  }
	  else {
		  $info['module_name']['active'] = 0;
	  }
	  if( $info['module_name']['active'] != $o_state ) {
		  $db = cmsms()->GetDb();
		  $query = 'UPDATE '.cms_db_prefix.' SET active = ? WHERE module_name = ?';
		  $dbr = $db->Execute($query,array($info['module_name']['active'],$module_name));
	  }
	  return TRUE;
  }


  /**
   * Returns a hash of all loaded modules.  This will include all
   * modules loaded into memory at the current time
   *
   * @return array The hash of all loaded modules
   */
  public function &GetLoadedModules()
  {
	  return $this->_modules;
  }


  /**
   * Return an array of the names of all modules that we currently know about
   */
  public function GetAllModuleNames()
  {
	  return array_keys($this->_get_module_info());
  }

  /**
   * Returns an array of the names of all installed modules.
   *
   * @return array of strings
   */
  public function GetInstalledModules($include_all = FALSE)
  {
	  $result = array();
	  $info = $this->_get_module_info();
	  if( is_array($info) ) {
		  foreach( $info as $name => $rec ) {
			  if( $rec['status'] != 'installed' ) continue;
			  if( !$rec['active'] && $include_all == FALSE ) continue;
			  $result[] = $name;
		  }
	  }
	  return $result;
  }


  /**
   * Returns an array of installed modules that have a certain capabilies
   * This method will force the loading of all modules regardless of the module settings.
   * 
   * @param string $capability The capability name
   * @param mixed $args Capability arguments
   * @return array List of all the module objects with that capability
   */
  public static function get_modules_with_capability($capability, $args= '')
  {
	  if( !is_array($args) ) {
		  if( !empty($args) ) {
			  $args = array($args);
		  }
		  else {
			  $args = array();
		  }
	  }
	  return module_meta::get_instance()->module_list_by_capability($capability,$args);
  }

  /**
   * A function to return a list of dependencies from a module.
   * this method works by reading the dependencies from the database.
   *
   * @since 1.11.8
   * @author Robert Campbell
   * @param string The module name
   * @return mixed.  Null if there are no dependencies.  Otherwise, a hash of dependent module names, and their versions.
   */
  public function get_module_dependencies($module_name)
  {
	  if( !$module_name ) return;

	  if( !is_array($this->_moduledeps) ) {
		  $fn = TMP_CACHE_LOCATION.'/f'.md5(__FILE__.'deps').'.dat';
		  if( file_exists($fn) ) {
			  $data = file_get_contents($fn);
			  $this->_moduledeps = unserialize($data);
		  }
		  else {
			  $this->_moduledeps = array();
			  $db = cmsms()->GetDb();
			  $query = 'SELECT parent_module,child_module,minimum_version FROM '.cms_db_prefix().'module_deps';
			  $dbr = $db->GetArray($query);
			  if( is_array($dbr) && count($dbr) ) {
				  foreach( $dbr as $row ) {
					  if( !isset($this->_moduledeps[$row['child_module']]) ) $this->_moduledeps[$row['child_module']] = array();
					  $this->_moduledeps[$row['child_module']][$row['parent_module']] = $row['minimum_version'];
				  }
			  }
			  file_put_contents($fn,serialize($this->_moduledeps));
		  }
	  }

	  if( isset($this->_moduledeps[$module_name]) ) return $this->_moduledeps[$module_name];
  }

  /**
   * A function to return the object reference to the module object
   * if the module is not already loaded, it will be loaded.  Version checks are done
   * with the module to allow only loading versions of modules that are greater than the 
   * specified value.
   *
   * @param string The module name
   * @param string an optional version string.
   * @param boolean an optional flag to indicate wether the module should be force loaded if necesary.
   * @return mixed  Null on failure, or an object of type CmsModule on success.
   */
  public function &get_module_instance($module_name,$version = '',$force = FALSE)
  {
	  if( empty($module_name) && isset($this->variables['module'])) {
		  $module_name = $this->variables['module'];
	  }

	  $obj = null;
	  if( isset($this->_modules[$module_name]) ) {
		  $obj =& $this->_modules[$module_name];
	  }
	  if( !is_object($obj) ) {
		  // gotta load it.
		  $res = $this->_load_module($module_name,$force);
		  if( $res ) {
			  $obj =& $this->_modules[$module_name];
		  }
	  }

	  if( is_object($obj) && !empty($version) ) {
		  $res = version_compare($obj->GetVersion(),$version);
		  if( $res < 0 OR $res === FALSE ) $obj = null;
	  }
	  return $obj;
  }


  /**
   * Test if the specified module name is a system module
   *
   * @param string The module name
   * @return boolean
   */
  public function IsSystemModule($module_name)
  {
	  return in_array($module_name,$this->cmssystemmodules);
  }



  /**
   * Return the current syntax highlighter module object
   * 
   * This method retrieves the specified syntax highlighter module, or uses the current current user preference for the syntax hightlighter module
   * for a name.
   *
   * @param string allows bypassing the automatic detection process and specifying a wysiwyg module.
   * @return null on failure, an object of type CmsModule On success.
   * @since 1.10
   */
  public function &GetSyntaxHighlighter($module_name = '')
  {
	  $obj = null;
	  if( !$module_name ) {
		  global $CMS_ADMIN_PAGE;
		  if( isset($CMS_ADMIN_PAGE) ) $module_name = get_preference(get_userid(FALSE),'syntaxhighlighter');
	  }

	  if( !$module_name ) return $obj;

	  $obj = $this->get_module_instance($module_name);
	  if( !$obj ) return $obj;
	  if( !$obj->IsSyntaxHighlighter() ) return $obj;

	  return $obj;
  }


  /**
   * Return the current wysiwyg module object
   * 
   * This method makes an attempt to find the appropriate wysiwyg module given the current request context
   * and admin user preference.
   *
   * @param string allows bypassing the automatic detection process and specifying a wysiwyg module.
   * @return null on failure, an object of type CmsModule On success.
   * @since 1.10
   * @deprecated
   */
  public function &GetWYSIWYGModule($module_name = '')
  {
	  global $CMS_ADMIN_PAGE;
	  $obj = null;
	  if( !$module_name ) {
		  if( !isset($CMS_ADMIN_PAGE) ) {
			  $module_name = get_site_preference('frontendwysiwyg');
		  }
		  else {
			  $module_name = get_preference(get_userid(FALSE),'wysiwyg');
		  }
	  }

	  if( !$module_name || $module_name == -1 ) return $obj;

	  $obj = $this->get_module_instance($module_name);
	  if( !$obj ) return $obj;
	  if( $obj->IsWYSIWYG() ) return $obj;

	  $obj = null;
	  return $obj;
  }


  /**
   * Return the current search module object
   *
   * This method returns module object for the currently selected search module.  
   *
   * @return null on failure, an object of type CmsModule on success
   * @since 1.10
   */
  public function &GetSearchModule()
  {
	  $obj = null;
	  $module_name = get_site_preference('searchmodule','Search');
	  if( $module_name && $module_name != 'none' && $module_name != '-1' ) {
		  $obj = $this->get_module_instance($module_name);
	  }
	  return $obj;
  }


  /**
   * Alias for the GetSyntaxHiglighter method.
   * 
   * @see GetSyntaxHighlighter
   * @deprecated
   * @since 1.10
   */
  public function &GetSyntaxModule($module_name = '')
  {
	  return $this->GetSyntaxHighlighter($module_name);
  }


  private function _is_queued_for_install($module_name)
  {
	  if( !isset($_SESSION['moduleoperations']) ) return FALSE;
	  if( !isset($_SESSION['moduleoperations'][$module_name]) ) return FALSE;
	  return TRUE;
  }


  /**
   * Queue a module for install
   * 
   * @internal
   * @since 1.10
   * @param string module name
   * @return void
   */
  public function QueueForInstall($module_name)
  {
	  if( !$module_name ) return;
	  if( !isset($_SESSION['moduleoperations']) ) $_SESSION['moduleoperations'] = array();

	  if( !isset($_SESSION['moduleoperations'][$module_name]) ) $_SESSION['moduleoperations'][$module_name] = 1;
  }


  /**
   * Get list of modules queued for install.
   * 
   * @internal
   * @since 1.10
   * @param string module name
   * @return void
   */
  public function GetQueueResults()
  {
	  if( isset($_SESSION['moduleoperations_result']) ) {
		  $data = $_SESSION['moduleoperations_result'];
		  unset($_SESSION['moduleoperations_result']);
		  return $data;
	  }
  }


  /**
   * Unload a module from memory
   *
   * @internal
   * @since 1.10
   * @param string module name
   * @return void
   */
  public function unload_module($module_name)
  {
	  if( !isset($this->_modules[$module_name]) || !is_object($this->_modules[$module_name]) )  return;
	  unset($this->_modules[$module_name]);
  }

} // end of class

# vim:ts=4 sw=4 noet
?>

File Manager Version 1.0, Coded By Lucas
Email: hehe@yahoo.com