1043 lines
25 KiB
PHP
1043 lines
25 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Invision Power Services
|
|
* IP.Board v3.0.5
|
|
* Static SETUP Classes for IP.Board 3
|
|
*
|
|
* These classes are not required as objects.
|
|
* Last Updated: $Date: 2009-10-13 17:40:38 -0400 (Tue, 13 Oct 2009) $
|
|
*
|
|
* @author Matt Mecham
|
|
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
|
* @license http://www.iinvisionpower.com/community/board/license.html
|
|
* @package Invision Power Board
|
|
* @link http://www.iinvisionpower.com
|
|
* @since 1st December 2008
|
|
* @version $Revision: 5228 $
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* Collection of methods to aid setup (install/upgrade)
|
|
*
|
|
*
|
|
* @author Matt
|
|
*/
|
|
class IPSSetUp
|
|
{
|
|
/**
|
|
* Min PHP Version
|
|
*
|
|
* @var string
|
|
*/
|
|
const minPhpVersion = '5.1.0';
|
|
|
|
/**
|
|
* Min MySQL Version
|
|
*
|
|
* @var string
|
|
*/
|
|
const minDb_mysql = '4.1.0';
|
|
|
|
/**
|
|
* Min MSSQL Version
|
|
*
|
|
* @var string
|
|
*/
|
|
const minDb_mssql = '10.0.0';
|
|
|
|
/**
|
|
* Min PHP Version
|
|
*
|
|
* @var string
|
|
*/
|
|
const prefPhpVersion = '5.2.1';
|
|
|
|
/**
|
|
* Min MySQL Version
|
|
*
|
|
* @var string
|
|
*/
|
|
const prefDb_mysql = '5.0.0';
|
|
|
|
/**
|
|
* Min MSSQL Version
|
|
*
|
|
* @var string
|
|
*/
|
|
const prefDb_mssql = '10.0.0';
|
|
|
|
|
|
/**
|
|
* Doc Char Set
|
|
*
|
|
* @var string
|
|
*/
|
|
const charSet = 'utf-8';
|
|
|
|
/**
|
|
* Saved data
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $_savedData = array();
|
|
|
|
/**
|
|
* Current version: Is 1.2.0+?
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
static public function is120plus()
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'perm_id', 'forum_perms' ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Current version: Is 1.3.0+?
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
static public function is130plus()
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'sub_id', 'subscriptions' ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Current version: Is 2.0.0+?
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
static public function is200plus()
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'upgrade_id', 'upgrade_history' ) )
|
|
{
|
|
/* Now, this table is created in the first step between 1.3 and 2.0, so check for contents */
|
|
$test = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'MAX(upgrade_version_id) as max',
|
|
'from' => 'upgrade_history' ) );
|
|
|
|
if ( $test['max'] < 20000 )
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Current version: Is 3.0.0+?
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
static public function is300plus()
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'member_id', 'members' ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a MySQL source file for larger boards
|
|
*
|
|
* @access public
|
|
* @param string Output - list of current queries
|
|
* @param int Current Long Version ID
|
|
* @param string Unique bit to append to filename to prevent overwrites, eg 1,2 etc
|
|
* @param mixed File name on success, false on not
|
|
*/
|
|
static public function createSqlSourceFile( $sqlData, $uipLong, $uniqueBit='' )
|
|
{
|
|
$uniqueBit = ( $uniqueBit ) ? '_' . $uniqueBit : '';
|
|
$fileName = IPS_CACHE_PATH . 'cache/sql_source_' . $uipLong . $uniqueBit . '.sql';
|
|
|
|
/* Try and write the file */
|
|
if ( $sqlData AND @file_put_contents( $fileName, str_replace( "\n\n", "\n", $sqlData ) ) )
|
|
{
|
|
@chmod( $fileName, 0777 );
|
|
return $fileName;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clean up source files
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
static public function removeSqlSourceFiles()
|
|
{
|
|
try
|
|
{
|
|
foreach( new DirectoryIterator( IPS_CACHE_PATH . 'cache' ) as $file )
|
|
{
|
|
if ( ! $file->isDot() AND ! $file->isDir() )
|
|
{
|
|
$_name = $file->getFileName();
|
|
|
|
if ( preg_match( "#^sql_source_#", $_name ) )
|
|
{
|
|
@unlink( IPS_CACHE_PATH . 'cache/' . $_name );
|
|
}
|
|
}
|
|
}
|
|
} catch ( Exception $e ) {}
|
|
}
|
|
|
|
/**
|
|
* Add SQL Prefix to Query
|
|
*
|
|
* @access public
|
|
* @param string SQL Query
|
|
* @param string SQL Prefix
|
|
*/
|
|
static public function addPrefixToQuery( $query, $prefix )
|
|
{
|
|
if ( $prefix )
|
|
{
|
|
/* Remove default ibf_ from < 3.0.0 files */
|
|
if ( strstr( $query, 'ibf' ) )
|
|
{
|
|
$query = preg_replace("/\sibf_(\S+?)([\s\.,]|$)/", " \\1\\2", $query);
|
|
}
|
|
|
|
$query = preg_replace( "#^CREATE TABLE(?:\s+?)?(\S+)#is" , "CREATE TABLE " . $prefix."\\1 ", $query );
|
|
$query = preg_replace( "#^RENAME TABLE(?:\s+?)?(\S+)\s+?TO\s+?(\S+?)(\s|$)#i" , "RENAME TABLE " . $prefix."\\1 TO " . $prefix ."\\2", $query );
|
|
$query = preg_replace( "#^DROP TABLE( IF EXISTS)?(?:\s+?)?(\S+)(\s+?)?#i" , "DROP TABLE \\1 " . $prefix."\\2 ", $query );
|
|
$query = preg_replace( "#^TRUNCATE TABLE(?:\s+?)?(\S+)(\s+?)?#i", "TRUNCATE TABLE ". $prefix."\\1 ", $query );
|
|
$query = preg_replace( "#^DELETE FROM(?:\s+?)?(\S+)(\s+?)?#i" , "DELETE FROM " . $prefix."\\1 ", $query );
|
|
$query = preg_replace( "#^INSERT INTO(?:\s+?)?(\S+)\s+?#i" , "INSERT INTO " . $prefix."\\1 ", $query );
|
|
$query = preg_replace( "#^UPDATE(?:\s+?)?(\S+)\s+?#i" , "UPDATE " . $prefix."\\1 ", $query );
|
|
$query = preg_replace( "#^REPLACE INTO(?:\s+?)?(\S+)\s+?#i" , "REPLACE INTO " . $prefix."\\1 ", $query );
|
|
$query = preg_replace( "#^ALTER TABLE(?:\s+?)?(\S+)\s+?#i" , "ALTER TABLE " . $prefix."\\1 ", $query );
|
|
|
|
# MSSQL
|
|
$query = preg_replace( "#select FULLTEXTCATALOGPROPERTY \( '(\S+)', 'PopulateStatus' \)#i", "select FULLTEXTCATALOGPROPERTY ( '" . $prefix . "\\1', 'PopulateStatus' )", $query );
|
|
$query = preg_replace( "#exec sp_fulltext_catalog '(\S+)', 'create'#i", "exec sp_fulltext_catalog '" . $prefix . "\\1', 'create'", $query );
|
|
$query = preg_replace( "#sp_fulltext_table\s{1,}'(\S+)',\s{1,}'(\S+)',\s{1,}'(\S+)',\s{1,}'(\S+)'#i", "sp_fulltext_table '" . $prefix . "\\1', '\\2', '" . $prefix . "\\3', '\\4'", $query );
|
|
$query = preg_replace( "#sp_fulltext_table '(\S+)', '(\S+)'$#i", "sp_fulltext_table '" . $prefix . "\\1', '\\2'", $query );
|
|
$query = preg_replace( "#sp_fulltext_column\s{0,}'(\S+)',\s{0,}'(\S+)',\s{0,}'(\S+)'#i", "sp_fulltext_column '" . $prefix . "\\1', '\\2', '\\3'", $query );
|
|
$query = preg_replace( "#(\s|'|\")PK_(\S+)#", " \\1" . $prefix."PK_\\2", $query );
|
|
$query = preg_replace( "#(\s|'|\")ftcatalog(\s|'|\")#", " \\1" . $prefix."ftcatalog\\2", $query );
|
|
$query = preg_replace( "#^SET IDENTITY_INSERT (?:\s+?)?(\S+)\s+?#i" , "SET IDENTITY_INSERT " . $prefix."\\1 ", $query );
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* Add a message to the upgader log
|
|
*
|
|
* @access public
|
|
* @param string Main error message
|
|
* @param string Upgrade version
|
|
* @param string Upgrade App
|
|
*/
|
|
static public function addLogMessage( $message, $version, $app='core' )
|
|
{
|
|
$file_name = DOC_IPS_ROOT_PATH . 'cache/sql_upgrade_log_'.date('m_d_y').'.cgi';
|
|
|
|
$_error_string = "\n===================================================";
|
|
$_error_string .= "\n Дата: ". date( 'r' );
|
|
$_error_string .= "\n IP адрес: " . $_SERVER['REMOTE_ADDR'];
|
|
$_error_string .= "\n Приложение " . $app;
|
|
$_error_string .= "\n Версия: " . $version;
|
|
$_error_string .= "\n Шаг: " . ipsRegistry::$request['do'];
|
|
$_error_string .= "\n Действие: " . ipsRegistry::$request['workact'];
|
|
$_error_string .= "\n\n\n ".$message;
|
|
|
|
if ( $fh = @fopen( $file_name, "a" ) )
|
|
{
|
|
@fwrite( $fh, $_error_string, strlen( $_error_string ) );
|
|
@fclose( $fh );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch version classes
|
|
*
|
|
* @access public
|
|
* @param string Application Directory
|
|
* @param int Start version number
|
|
* @param int Ending version number
|
|
* @return array
|
|
*/
|
|
static public function fetchVersionClasses( $app, $from, $to )
|
|
{
|
|
/* INIT */
|
|
$classes = array();
|
|
|
|
/* Make sure we have stuff to get.. */
|
|
if ( ! $from OR ! $to )
|
|
{
|
|
return $classes;
|
|
}
|
|
|
|
/* Search for files... */
|
|
$dh = opendir( IPSLib::getAppDir( $app ) . '/setup/versions' );
|
|
|
|
while ( false !== ( $file = readdir( $dh ) ) )
|
|
{
|
|
if ( is_dir( IPSLib::getAppDir( $app ) . '/setup/versions/' . $file ) )
|
|
{
|
|
if ( $file != "." && $file != ".." && $file != 'install' )
|
|
{
|
|
if ( strstr( $file, 'upg_' ) )
|
|
{
|
|
$tmp = intval( str_replace( "upg_", "", $file ) );
|
|
|
|
if ( $tmp > $from AND $tmp <= $to )
|
|
{
|
|
if ( file_exists( IPSLib::getAppDir( $app ) . '/setup/versions/' . $file . '/version_class.php' ) )
|
|
{
|
|
$classes[] = $tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $classes;
|
|
}
|
|
|
|
/**
|
|
* Fetch current and next app versions
|
|
*
|
|
* @access public Application Directory
|
|
* @return array array( 'current' => array( 000000, '1.0.0 Beta1' ), 'next' => array( 000000, '1.0.0 Beta1' ), 'latest' => array( 000000, '1.0.0 Beta1' ) )
|
|
*/
|
|
static public function fetchAppVersionNumbers( $app )
|
|
{
|
|
$return = array( 'current' => array( 0, '' ),
|
|
'next' => array( 0, '' ),
|
|
'latest' => array( 0, '' ) );
|
|
|
|
/* Latest version */
|
|
$XMLVersions = self::fetchXmlAppVersions( $app );
|
|
$tmp = $XMLVersions;
|
|
krsort( $tmp );
|
|
|
|
foreach( $tmp as $long => $human )
|
|
{
|
|
$return['latest'] = array( $long, $human );
|
|
break;
|
|
}
|
|
|
|
/* Current Version */
|
|
$DBVersions = self::fetchDbAppVersions( $app );
|
|
$tmp = $DBVersions;
|
|
$key = array_pop( $tmp );
|
|
|
|
if ( ! $key OR ! count( $DBVersions ) )
|
|
{
|
|
if ( self::is300plus() === TRUE )
|
|
{
|
|
$_version = ipsRegistry::DB()->buildAndFetch( array( 'select' => '*',
|
|
'from' => 'core_applications',
|
|
'where' => 'app_directory=\'' . $app . '\'' ) );
|
|
|
|
$key = intval( $_version['app_long_version'] );
|
|
}
|
|
else
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'upgrade_id', 'upgrade_history' ) )
|
|
{
|
|
/* Now, this table is created in the first step between 1.3 and 2.0, so check for contents */
|
|
$test = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'MAX(upgrade_version_id) as max', 'from' => 'upgrade_history' ) );
|
|
|
|
$key = ( $test['max'] ) ? $test['max'] : '10003';
|
|
}
|
|
else if ( self::is130plus() === TRUE )
|
|
{
|
|
$key = '10003';
|
|
}
|
|
else if ( self::is120plus() === TRUE )
|
|
{
|
|
$key = '10002';
|
|
}
|
|
else
|
|
{
|
|
$key = '10001';
|
|
}
|
|
}
|
|
|
|
/* Blog Version Check */
|
|
if( $app == 'blog' )
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'blog_upgrade_id', 'blog_upgrade_history' ) )
|
|
{
|
|
$test = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'MAX(blog_version_id) as max', 'from' => 'blog_upgrade_history' ) );
|
|
$key = ( $test['max'] ) ? $test['max'] : $key;
|
|
}
|
|
else
|
|
{
|
|
$key = 0;
|
|
}
|
|
}
|
|
/* Gallery Version Check */
|
|
else if( $app == 'gallery' )
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'gallery_upgrade_id', 'gallery_upgrade_history' ) )
|
|
{
|
|
$test = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'MAX(gallery_version_id) as max', 'from' => 'gallery_upgrade_history' ) );
|
|
$key = ( $test['max'] ) ? $test['max'] : $key;
|
|
}
|
|
else
|
|
{
|
|
$key = 0;
|
|
}
|
|
}
|
|
else if( $app == 'downloads' )
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( 'idm_upgrade_id', 'idm_upgrade_history' ) )
|
|
{
|
|
$test = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'MAX(idm_version_id) as max', 'from' => 'idm_upgrade_history' ) );
|
|
$key = ( $test['max'] ) ? $test['max'] : $key;
|
|
}
|
|
else
|
|
{
|
|
$key = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
$return['current'] = ( $key ) ? array( $key, $XMLVersions[ $key ] ) : array( 0, 'install' );
|
|
|
|
/* Next version */
|
|
$nextKey = 0;
|
|
|
|
foreach( $XMLVersions as $long => $human )
|
|
{
|
|
if ( $long > $return['current'][0] )
|
|
{
|
|
$nextKey = $long;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$return['next'] = array( $nextKey, $XMLVersions[ $nextKey ] );
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Fetch directory versions
|
|
*
|
|
* @access public
|
|
* @param string Application directory
|
|
* @return array Array of data
|
|
*/
|
|
static public function fetchAppDirStructure( $app )
|
|
{
|
|
$versions = array();
|
|
|
|
$dh = opendir( IPSLib::getAppDir( $app ) . '/setup/versions' );
|
|
|
|
while ( false !== ( $file = readdir( $dh ) ) )
|
|
{
|
|
if ( is_dir( IPSLib::getAppDir( $app ) . '/setup/versions/' . $file ) )
|
|
{
|
|
if ( $file != "." && $file != ".." && $file != 'install' )
|
|
{
|
|
if ( strstr( $file, 'upg_' ) )
|
|
{
|
|
$tmp = str_replace( "upg_", "", $file );
|
|
$versions[ $tmp ] = $tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
closedir( $dh );
|
|
|
|
sort($versions);
|
|
|
|
return $versions;
|
|
}
|
|
|
|
/**
|
|
* Fetch app DB versions
|
|
*
|
|
* @access public Application Directory
|
|
* @return array
|
|
*/
|
|
static public function fetchDbAppVersions( $app )
|
|
{
|
|
/* INIT */
|
|
$versions = array();
|
|
|
|
/* 2.x+? */
|
|
if ( self::is200plus() === TRUE )
|
|
{
|
|
if ( ipsRegistry::DB()->checkForField( "upgrade_app", "upgrade_history" ) )
|
|
{
|
|
ipsRegistry::DB()->build( array( 'select' => '*',
|
|
'where' => 'upgrade_app=\'' . $app . '\'',
|
|
'from' => 'upgrade_history',
|
|
'order' => 'upgrade_version_id ASC' ) );
|
|
ipsRegistry::DB()->execute();
|
|
|
|
while( $r = ipsRegistry::DB()->fetch() )
|
|
{
|
|
$versions[ $r['upgrade_version_id'] ] = $r['upgrade_version_id'];
|
|
}
|
|
}
|
|
|
|
/* Ok, field is there but there's nothing, so.. */
|
|
if ( ! count( $versions ) )
|
|
{
|
|
if ( $app == 'core' )
|
|
{
|
|
ipsRegistry::DB()->build( array( 'select' => '*',
|
|
'from' => 'upgrade_history',
|
|
'order' => 'upgrade_version_id ASC' ) );
|
|
ipsRegistry::DB()->execute();
|
|
|
|
while( $r = ipsRegistry::DB()->fetch() )
|
|
{
|
|
$versions[ $r['upgrade_version_id'] ] = $r['upgrade_version_id'];
|
|
}
|
|
}
|
|
else if ( $app == 'blog' AND ipsRegistry::DB()->checkForField( "blog_version_id", "blog_upgrade_history" ) )
|
|
{
|
|
ipsRegistry::DB()->build( array( 'select' => '*',
|
|
'from' => 'blog_upgrade_history',
|
|
'order' => 'blog_version_id ASC' ) );
|
|
ipsRegistry::DB()->execute();
|
|
|
|
while( $r = ipsRegistry::DB()->fetch() )
|
|
{
|
|
$versions[ $r['blog_version_id'] ] = $r['blog_version_id'];
|
|
}
|
|
}
|
|
else if ( $app == 'gallery' AND ipsRegistry::DB()->checkForField( "gallery_version_id", "gallery_upgrade_history" ) )
|
|
{
|
|
ipsRegistry::DB()->build( array( 'select' => '*',
|
|
'from' => 'gallery_upgrade_history',
|
|
'order' => 'gallery_version_id ASC' ) );
|
|
ipsRegistry::DB()->execute();
|
|
|
|
while( $r = ipsRegistry::DB()->fetch() )
|
|
{
|
|
$versions[ $r['gallery_version_id'] ] = $r['gallery_version_id'];
|
|
}
|
|
}
|
|
else if ( $app == 'downloads' AND ipsRegistry::DB()->checkForField( "idm_version_id", "downloads_upgrade_history" ) )
|
|
{
|
|
ipsRegistry::DB()->build( array( 'select' => '*',
|
|
'from' => 'downloads_upgrade_history',
|
|
'order' => 'idm_version_id ASC' ) );
|
|
ipsRegistry::DB()->execute();
|
|
|
|
while( $r = ipsRegistry::DB()->fetch() )
|
|
{
|
|
$versions[ $r['idm_version_id'] ] = $r['idm_version_id'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ksort( $versions );
|
|
|
|
return $versions;
|
|
}
|
|
|
|
/**
|
|
* Fetch Apps XML Information File
|
|
*
|
|
* @access public
|
|
* @param string Application Directory
|
|
* @return array ..of data
|
|
*/
|
|
static public function fetchXmlAppVersions( $app )
|
|
{
|
|
/* INIT */
|
|
$versions = array();
|
|
|
|
/* Fetch core writeable files */
|
|
require_once( IPS_KERNEL_PATH . 'classXML.php' );
|
|
$xml = new classXML( IPSSetUp::charSet );
|
|
|
|
try
|
|
{
|
|
$xml->load( IPSLib::getAppDir( $app ) . '/xml/versions.xml' );
|
|
|
|
/* Fetch general information */
|
|
foreach( $xml->fetchElements( 'version' ) as $xmlelement )
|
|
{
|
|
$data = $xml->fetchElementsFromRecord( $xmlelement );
|
|
|
|
$versions[ $data['long'] ] = $data['human'];
|
|
}
|
|
|
|
ksort( $versions );
|
|
|
|
return $versions;
|
|
}
|
|
catch( Exception $error )
|
|
{
|
|
$this->registry->output->addError( IPS_ROOT_PATH . 'applications/' . $app . '/xml/versions.xml' );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Simple method for writing a file
|
|
*
|
|
* @access public
|
|
* @param string $name Full name, including path, of file to write
|
|
* @param string $data Contents of file
|
|
* @return bool True
|
|
*/
|
|
static public function writeFile( $name, $data )
|
|
{
|
|
$fh = @fopen( $name, "w" );
|
|
@fwrite( $fh, $data, strlen( $data ) );
|
|
@fclose( $fh );
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Fetch next application
|
|
*
|
|
* @access public
|
|
* @param string Previous application
|
|
* @param string XML file to search for. If supplied, function will return next app that has the XML file. Use {app} for $app ({app}_settings.xml)
|
|
* @return mixed
|
|
*/
|
|
static public function fetchNextApplication( $previous='', $xmlFileSearch='' )
|
|
{
|
|
//-----------------------------------------
|
|
// INIT
|
|
//-----------------------------------------
|
|
|
|
$apps = explode( ",", IPSSetUp::getSavedData('install_apps') );
|
|
$return = FALSE;
|
|
$flag = ( $previous ) ? 0 : 1;
|
|
$array = array();
|
|
|
|
if ( ! count( $apps ) OR ! count( $apps ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
foreach( $apps as $_app )
|
|
{
|
|
# Looking for an XML file?
|
|
if ( $xmlFileSearch )
|
|
{
|
|
$_xmlFileSearch = str_replace( '{app}', $_app, $xmlFileSearch );
|
|
|
|
if ( ! file_exists( IPSLib::getAppDir( $_app ) . '/xml/' . $_xmlFileSearch ) )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
# Flag raised? Grab it!
|
|
if ( $flag )
|
|
{
|
|
$return = $_app;
|
|
break;
|
|
}
|
|
|
|
# Got this one? Set the flag
|
|
if ( $_app == $previous )
|
|
{
|
|
$flag = 1;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Got something?
|
|
//-----------------------------------------
|
|
|
|
if ( $return )
|
|
{
|
|
return self::fetchXmlAppInformation( $return );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Fetch Apps XML Writeable File information
|
|
*
|
|
* @access public
|
|
* @param string Application Directory
|
|
* @return array ..of data
|
|
*/
|
|
static public function fetchXmlAppWriteableFiles( $app )
|
|
{
|
|
/* INIT */
|
|
$info = array( 'notexist' => array(), 'notwrite' => array(), 'other' => array() );
|
|
$file = IPSLib::getAppDir( $app ) . '/xml/writeablefiles.xml';
|
|
|
|
/**
|
|
* Custom error checker routine...
|
|
*/
|
|
if( file_exists( IPSLib::getAppDir( $app ) . '/setup/versions/install/installCheck.php' ) )
|
|
{
|
|
require_once( IPSLib::getAppDir( $app ) . '/setup/versions/install/installCheck.php' );
|
|
$checkerClass = $app . '_installCheck';
|
|
|
|
if( class_exists($checkerClass) )
|
|
{
|
|
$checker = new $checkerClass;
|
|
$info = $checker->checkForProblems();
|
|
}
|
|
}
|
|
|
|
/* Got a file? */
|
|
if ( ! file_exists( $file ) )
|
|
{
|
|
return $info;
|
|
}
|
|
|
|
/* Fetch app writeable files */
|
|
require_once( IPS_KERNEL_PATH . 'classXML.php' );
|
|
$xml = new classXML( IPSSetUp::charSet );
|
|
|
|
try
|
|
{
|
|
$xml->load( $file );
|
|
|
|
foreach( $xml->fetchElements( 'file' ) as $xmlelement )
|
|
{
|
|
$data = $xml->fetchElementsFromRecord( $xmlelement );
|
|
|
|
if ( $data['path'] )
|
|
{
|
|
$_path = DOC_IPS_ROOT_PATH . $data['path'];
|
|
|
|
if ( ! file_exists( $_path ) )
|
|
{
|
|
if ( $data['dir'] )
|
|
{
|
|
if ( ! @mkdir( $_path, 0777, TRUE ) )
|
|
{
|
|
$info['notexist'][] = $_path;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$info['notexist'][] = $_path;
|
|
}
|
|
}
|
|
else if ( ! is_writeable( $_path ) )
|
|
{
|
|
if ( ! @chmod( $_path, 0777 ) )
|
|
{
|
|
$info['notwrite'][] = $_path;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $info;
|
|
}
|
|
catch( Exception $error )
|
|
{
|
|
$this->registry->output->addError( $file );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch Apps XML Information File
|
|
*
|
|
* @access public
|
|
* @param string Application Directory
|
|
* @return array ..of data
|
|
*/
|
|
static public function fetchXmlAppInformation( $app )
|
|
{
|
|
/* INIT */
|
|
$info = array();
|
|
|
|
/* Fetch core writeable files */
|
|
require_once( IPS_KERNEL_PATH . 'classXML.php' );
|
|
$xml = new classXML( IPSSetUp::charSet );
|
|
|
|
try
|
|
{
|
|
if( file_exists( IPSLib::getAppDir( $app ) . '/xml/information.xml' ) )
|
|
{
|
|
$xml->load( IPSLib::getAppDir( $app ) . '/xml/information.xml' );
|
|
|
|
/* Fetch general information */
|
|
foreach( $xml->fetchElements( 'data' ) as $xmlelement )
|
|
{
|
|
$data = $xml->fetchElementsFromRecord( $xmlelement );
|
|
|
|
$info['name'] = $data['name'];
|
|
$info['title'] = $data['name'];
|
|
$info['author'] = $data['author'];
|
|
$info['description'] = $data['description'];
|
|
$info['public_name'] = $data['public_name'];
|
|
$info['disabledatinstall'] = ( $data['disabledatinstall'] ) ? 1 : 0;
|
|
$info['key'] = $app;
|
|
$info['ipskey'] = $data['ipskey'];
|
|
$info['hide_tab'] = $data['hide_tab'];
|
|
}
|
|
|
|
/* Fetch template information */
|
|
foreach( $xml->fetchElements( 'template' ) as $template )
|
|
{
|
|
$name = $xml->fetchItem( $template );
|
|
$match = $xml->fetchAttribute( $template, 'match' );
|
|
|
|
if ( $name )
|
|
{
|
|
$info['templates'][ $name ] = $match;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $info;
|
|
}
|
|
catch( Exception $error )
|
|
{
|
|
$this->registry->output->addError( IPS_ROOT_PATH . 'applications/' . $app . '/xml/information.xml' );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch Apps XML Modules File
|
|
*
|
|
* @access public
|
|
* @param string Application Directory
|
|
* @return array ..of data
|
|
*/
|
|
static public function fetchXmlAppModules( $app )
|
|
{
|
|
//-----------------------------------------
|
|
// No modules?
|
|
//-----------------------------------------
|
|
|
|
if( !file_exists( IPSLib::getAppDir( $app ) . '/xml/' . $app . '_modules.xml' ) )
|
|
{
|
|
return array();
|
|
}
|
|
|
|
/* INIT */
|
|
$modules = array();
|
|
|
|
/* Fetch core writeable files */
|
|
require_once( IPS_KERNEL_PATH . 'classXML.php' );
|
|
$xml = new classXML( IPSSetUp::charSet );
|
|
|
|
try
|
|
{
|
|
require_once( IPS_KERNEL_PATH . 'classXML.php' );
|
|
$xml = new classXML( IPSSetUp::charSet );
|
|
|
|
$xml->load( IPSLib::getAppDir( $app ) . '/xml/' . $app . '_modules.xml' );
|
|
|
|
/* Fetch info */
|
|
foreach( $xml->fetchElements( 'module' ) as $xmlelement )
|
|
{
|
|
$data = $xml->fetchElementsFromRecord( $xmlelement );
|
|
|
|
if( $data['sys_module_id'] )
|
|
{
|
|
unset($data['sys_module_id']);
|
|
}
|
|
|
|
$modules[ $data['sys_module_key'] . intval($data['sys_module_admin']) ] = $data;
|
|
}
|
|
|
|
return $modules;
|
|
}
|
|
catch( Exception $error )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Saved Data Get
|
|
*
|
|
* @access public
|
|
* @param string Key to return value of
|
|
* @return mixed False, or array of data
|
|
*/
|
|
static function getSavedData( $key )
|
|
{
|
|
return isset( self::$_savedData[ $key ] ) ? self::$_savedData[ $key ] : FALSE;
|
|
}
|
|
|
|
/**
|
|
* Get Saved Data As Array
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
static function getSavedDataAsArray()
|
|
{
|
|
return is_array( self::$_savedData ) ? self::$_savedData : array();
|
|
}
|
|
|
|
/**
|
|
* Saved Data Set
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @param string Value
|
|
* @return void
|
|
*/
|
|
static function setSavedData( $key, $value )
|
|
{
|
|
//-----------------------------------------
|
|
// Driver needs to be lowercased
|
|
//-----------------------------------------
|
|
|
|
if( $key == 'sql_driver' )
|
|
{
|
|
$value = strtolower($value);
|
|
}
|
|
|
|
self::$_savedData[ $key ] = $value;
|
|
}
|
|
|
|
/**
|
|
* Freeze data
|
|
*
|
|
* @access public
|
|
* @return string "Frozed" data for saving
|
|
*/
|
|
static function freezeSavedData()
|
|
{
|
|
/* Encode */
|
|
$data = urlencode( serialize( self::$_savedData ) );
|
|
|
|
/* Write to our cache file */
|
|
if ( is_array( self::$_savedData ) )
|
|
{
|
|
self::_writeFreezerCache( $data );
|
|
}
|
|
|
|
/* Return */
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Thaw Data
|
|
*
|
|
* @access public
|
|
* @param string Raw data for thawing
|
|
* @return void
|
|
*/
|
|
static function thawSavedData( $data='' )
|
|
{
|
|
if ( ! $data )
|
|
{
|
|
/* Check cache file first */
|
|
$data = self::_readFreezerCache();
|
|
|
|
/* Nothing? Try post data */
|
|
if ( ! $data )
|
|
{
|
|
$data = $_POST['_sd'];
|
|
}
|
|
}
|
|
|
|
self::$_savedData = unserialize( urldecode( $data ) );
|
|
}
|
|
|
|
/**
|
|
* Writes the frozen data to a cache
|
|
*
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
private static function _readFreezerCache()
|
|
{
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
$_data = ipsRegistry::DB()->buildAndFetch( array( 'select' => '*',
|
|
'from' => 'upgrade_sessions',
|
|
'where' => 'session_id=\'' . ipsRegistry::$request['s'] . '\'' ) );
|
|
return $_data['session_data'];
|
|
}
|
|
else
|
|
{
|
|
if ( file_exists( DOC_IPS_ROOT_PATH . 'conf_global.php' ) )
|
|
{
|
|
require( DOC_IPS_ROOT_PATH . 'conf_global.php' );
|
|
return trim( $VAR );
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Writes the frozen data to a cache
|
|
*
|
|
* @access private
|
|
* @param string Encoded data to write
|
|
* @return void
|
|
*/
|
|
private static function _writeFreezerCache( $data )
|
|
{
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
ipsRegistry::DB()->update( 'upgrade_sessions', array( 'session_data' => $data ), 'session_id=\'' . ipsRegistry::$request['s'] . '\'' );
|
|
}
|
|
else
|
|
{
|
|
if ( file_exists( DOC_IPS_ROOT_PATH . 'conf_global.php' ) AND is_writeable( DOC_IPS_ROOT_PATH . 'conf_global.php' ) )
|
|
{
|
|
$_data = file_get_contents( DOC_IPS_ROOT_PATH . 'conf_global.php' );
|
|
|
|
if ( $_data )
|
|
{
|
|
$fmt = "/*~~DATA~~*/\n\$VAR = <<<EOF\n" . $data . "\nEOF;\n/**/";
|
|
$_data = preg_replace( "#(\n{1,})?/\*~~DATA~~\*/(.+?)/\*\*/#s", "", $_data );
|
|
|
|
$_data = preg_replace( "#\?\>$#", $fmt . "\n?>", $_data );
|
|
|
|
@file_put_contents( DOC_IPS_ROOT_PATH . 'conf_global.php', $_data );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |