i_iswin = (substr(PHP_OS, 0, 3) == 'WIN');
}
/**
* Uploads and unpacks a file
* @param string The uploaded package filename or install directory
* @param boolean True if the file is an archive file
* @return boolean True on success, False on error
*/
function upload($p_filename = null, $p_unpack = true, $p_findinstallfile = true ) {
$this->i_iswin = (substr(PHP_OS, 0, 3) == 'WIN');
$this->installArchive( $p_filename );
if ($p_unpack) {
if ($this->extractArchive()) {
if ( $p_findinstallfile ) {
return $this->findInstallFile();
} else {
return true;
}
} else {
return false;
}
} else {
return false;
}
}
/**
* Extracts the package archive file
* @return boolean True on success, False on error
*/
function extractArchive() {
global $_CB_framework;
$base_Dir = _cbPathName( $_CB_framework->getCfg('tmp_path') );
$archivename = $this->installArchive();
$tmpdir = uniqid( 'install_' );
$extractdir = _cbPathName( $base_Dir . $tmpdir );
$archivename = _cbPathName( $archivename, false );
$this->unpackDir( $extractdir );
if ( preg_match( "/\\.zip\$/i", $archivename ) ) {
// Extract functions
cbimport( 'pcl.pclziplib' );
$zipfile = new PclZip( $archivename );
if($this->isWindows()) {
define('OS_WINDOWS',1);
} else {
define('OS_WINDOWS',0);
}
$ret = $zipfile->extract( PCLZIP_OPT_PATH, $extractdir );
if($ret == 0) {
$this->setError( 1, 'Unrecoverable error "'.$zipfile->errorName(true).'"' );
return false;
}
} else {
cbimport( 'pcl.tar' ); // includes/Archive/Tar.php' );
$archive =& new Archive_Tar( $archivename );
$archive->setErrorHandling( PEAR_ERROR_PRINT );
if ( ! $archive->extractModify( $extractdir, '' ) ) {
$this->setError( 1, 'Extract Error' );
return false;
}
}
$this->installDir( $extractdir );
// Try to find the correct install dir. in case that the package have subdirs
// Save the install dir for later cleanup
$filesindir = cbReadDirectory( $this->installDir(), '' );
if ( count( $filesindir ) == 1 ) {
if ( is_dir( $extractdir . $filesindir[0] ) ) {
$this->installDir( _cbPathName( $extractdir . $filesindir[0] ) );
}
}
return true;
}
/**
* Tries to find the package XML file
* @return boolean True on success, False on error
*/
function findInstallFile() {
$found = false;
// Search the install dir for an xml file
$files = cbReadDirectory( $this->installDir(), '.xml$', true, false );
if (count( $files ) > 0) {
foreach ($files as $file) {
$packagefile =& $this->isPackageFile( $this->installDir() . $file );
if (!is_null( $packagefile ) && !$found ) {
$this->i_xmldocument =& $packagefile;
return true;
}
}
$this->setError( 1, 'ERROR: Could not find a CB XML setup file in the package.' );
return false;
} else {
$this->setError( 1, 'ERROR: Could not find an XML setup file in the package.' );
return false;
}
}
/**
* @param string A file path
* @return object A DOMIT XML document, or null if the file failed to parse
*/
function & isPackageFile( $p_file ) {
$null = null;
if ( ! file_exists( $p_file ) ) {
return $null;
}
cbimport('cb.xml.simplexml');
$xmlString = trim( file_get_contents( $p_file ) );
$element =& new CBSimpleXMLElement( $xmlString );
if ( count( $element->children() ) == 0 ) {
return $null;
}
if ( $element->name() != 'cbinstall' ) {
//echo "didn't find cbinstall";
return $null;
}
// Set the type
//echo "
element->attributes( 'type' )=".$element->attributes( 'type' );
$this->installType( $element->attributes( 'type' ) );
$this->installFilename( $p_file );
return $element;
}
/**
* Loads and parses the XML setup file
* @return boolean True on success, False on error
*/
function readInstallFile() {
if ($this->installFilename() == "") {
$this->setError( 1, 'No filename specified' );
return false;
}
cbimport('cb.xml.simplexml');
if ( file_exists( $this->installFilename() ) ) {
$xmlString = trim( file_get_contents( $this->installFilename() ) );
$this->i_xmldocument =& new CBSimpleXMLElement( $xmlString );
if ( count( $this->i_xmldocument->children() ) == 0 ) {
return false;
}
}
$main_element =& $this->i_xmldocument;
// Check that it's am installation file
if ($main_element->name() != 'cbinstall') {
$this->setError( 1, 'File :"' . $this->installFilename() . '" is not a valid Joomla installation file' );
return false;
}
//echo "
main_element->attributes( 'type' )=".$main_element->attributes( 'type' );
$this->installType( $main_element->attributes( 'type' ) );
return true;
}
/**
* Abstract install method
*/
function install() {
die( 'Method "install" cannot be called by class ' . strtolower(get_class( $this )) );
}
/**
* Abstract uninstall method
*/
function uninstall() {
die( 'Method "uninstall" cannot be called by class ' . strtolower(get_class( $this )) );
}
/**
* return to method
*/
function returnTo( $option, $task ) {
return "index2.php?option=$option&task=$task";
}
/**
* @param string Install from directory
* @param string The install type
* @return boolean
*/
function preInstallCheck( $p_fromdir, $type='plugin' ) {
if (!is_null($p_fromdir)) {
$this->installDir($p_fromdir);
}
if (!$this->installfile()) {
$this->findInstallFile();
}
if (!$this->readInstallFile()) {
$this->setError( 1, 'Installation file not found:
' . $this->installDir() );
return false;
}
//echo "
type=".$type." this->installType()=".$this->installType();
if (trim($this->installType()) != trim($type)) {
//echo "
failing here
";
$this->setError( 1, 'XML setup file is not for a "'.$type.'".' );
return false;
}
// In case there where an error doring reading or extracting the archive
if ($this->errno()) {
return false;
}
return true;
}
/**
* @param string The tag name to parse
* @param string An attribute to search for in a filename element
* @param string The value of the 'special' element if found
* @param boolean True for Administrator components
* @return mixed Number of file or False on error
*/
function parseFiles( $tagName='files', $special='', $specialError='', $adminFiles=0 ) {
global $_CB_framework;
// Find files to copy
$cbInstallXML =& $this->i_xmldocument;
$files_element =& $cbInstallXML->getElementByPath( $tagName );
if ( ! ( $files_element )) {
return 0;
}
if ( count( $files_element->children() ) == 0 ) {
// no files
return 0;
}
$copyfiles = array();
$folder = $files_element->attributes( 'folder' );
if ( $folder ) {
$temp = _cbPathName( $this->unpackDir() . $folder );
if ($temp == $this->installDir()) {
// this must be only an admin component
$installFrom = $this->installDir();
} else {
$installFrom = _cbPathName( $this->installDir() . $folder );
}
} else {
$installFrom = $this->installDir();
}
foreach ( $files_element->children() as $file ) {
if ( basename( $file->data() ) != $file->data() ) {
$newdir = dirname( $file->data() );
if ( $adminFiles ) {
if ( ! $this->mosMakePath( $this->componentAdminDir(), $newdir ) ) {
$this->setError( 1, 'Failed to create directory "' . ($this->componentAdminDir()) . $newdir . '"' );
return false;
}
} else {
if ( ! $this->mosMakePath( $this->elementDir(), $newdir ) ) {
$this->setError( 1, 'Failed to create directory "' . ($this->elementDir()) . $newdir . '"' );
return false;
}
}
}
$copyfiles[] = $file->data();
// check special for attribute
if ( $file->attributes( $special ) ) {
$this->elementSpecial( $file->attributes( $special ) );
}
}
if ( $specialError ) {
if ( $this->elementSpecial() == '' ) {
$this->setError( 1, $specialError );
return false;
}
}
if ( $tagName == 'media' ) {
// media is a special tag
$installTo = _cbPathName( $_CB_framework->getCfg('absolute_path') . '/images/stories' );
} else if ($adminFiles) {
$installTo = $this->componentAdminDir();
} else {
$installTo = $this->elementDir();
}
$result = $this->copyFiles( $installFrom, $installTo, $copyfiles );
return $result;
}
/**
* @param string Source directory
* @param string Destination directory
* @param array array with filenames
* @param boolean True is existing files can be replaced
* @return boolean True on success, False on error
*/
function copyFiles( $p_sourcedir, $p_destdir, $p_files, $overwrite=false ) {
global $_CB_framework;
if (is_array( $p_files ) && count( $p_files ) > 0) {
$adminFS =& cbAdminFileSystem::getInstance();
$filePerms = $_CB_framework->getCfg( 'fileperms' );
$dirPerms = $_CB_framework->getCfg( 'dirperms' );
if ( $filePerms ) {
$filePerms = octdec( $filePerms );
} else {
$filePerms = null;
}
if ( $dirPerms ) {
$dirPerms = octdec( $dirPerms );
} else {
$dirPerms = null;
}
foreach($p_files as $_file) {
$filesource = _cbPathName( _cbPathName( $p_sourcedir ) . $_file, false );
$filedest = _cbPathName( _cbPathName( $p_destdir ) . $_file, false );
if ( ! file_exists( $filesource ) ) {
$this->setError( 1, "File $filesource does not exist!" );
return false;
} else if ( file_exists( $filedest ) && ! $overwrite ) {
$this->setError( 1, "There is already a file called $filedest - Are you trying to install the same Plugin twice?" );
return false;
} else if ( ! $adminFS->copy( $filesource, $filedest ) ) {
$this->setError( 1, "Failed to copy file: $filesource to $filedest" );
return false;
} else {
if ( is_dir( $filesource ) && $dirPerms ) {
$perms = $dirPerms;
} elseif ( is_file( $filesource ) && $filePerms ) {
$perms = $filePerms;
} else {
$perms = null;
}
if ( $perms && ! $adminFS->chmod( $filedest, $perms ) ) {
$this->setError( 1, "Failed to chmod file: $filedest" );
return false;
}
}
}
} else {
return false;
}
return count( $p_files );
}
/**
* Copies the XML setup file to the element Admin directory
* Used by Plugin Installer
* @return boolean True on success, False on error
*/
function copySetupFile( $where='admin' ) {
if ($where == 'admin') {
return $this->copyFiles( $this->installDir(), $this->componentAdminDir(), array( basename( $this->installFilename() ) ), true );
} else if ($where == 'front') {
return $this->copyFiles( $this->installDir(), $this->elementDir(), array( basename( $this->installFilename() ) ), true );
}
return false;
}
/**
* @param int The error number
* @param string The error message
*/
function setError( $p_errno, $p_error ) {
$this->errno( $p_errno );
$this->error( $p_error );
}
/**
* @param boolean True to display both number and message
* @param string The error message
* @return string
*/
function getError($p_full = false) {
if ($p_full) {
return $this->errno() . " " . $this->error();
} else {
return $this->error();
}
}
/**
* @param string The name of the property to set/get
* @param mixed The value of the property to set
* @return The value of the property
*/
function setVar( $name, $value=null ) {
if (!is_null( $value )) {
$this->$name = $value;
}
return $this->$name;
}
function installFilename( $p_filename = null ) {
if(!is_null($p_filename)) {
if($this->isWindows()) {
$this->i_installfilename = str_replace('/','\\',$p_filename);
} else {
$this->i_installfilename = str_replace('\\','/',$p_filename);
}
}
return $this->i_installfilename;
}
function installType( $p_installtype = null ) {
return $this->setVar( 'i_installtype', $p_installtype );
}
function error( $p_error = null ) {
return $this->setVar( 'i_error', $p_error );
}
function installArchive( $p_filename = null ) {
return $this->setVar( 'i_installarchive', $p_filename );
}
function installDir( $p_dirname = null ) {
return $this->setVar( 'i_installdir', $p_dirname );
}
function unpackDir( $p_dirname = null ) {
return $this->setVar( 'i_unpackdir', $p_dirname );
}
function isWindows() {
return $this->i_iswin;
}
function errno( $p_errno = null ) {
return $this->setVar( 'i_errno', $p_errno );
}
function hasInstallfile( $p_hasinstallfile = null ) {
return $this->setVar( 'i_hasinstallfile', $p_hasinstallfile );
}
function installfile( $p_installfile = null ) {
return $this->setVar( 'i_installfile', $p_installfile );
}
function elementDir( $p_dirname = null ) {
return $this->setVar( 'i_elementdir', $p_dirname );
}
function elementName( $p_name = null ) {
return $this->setVar( 'i_elementname', $p_name );
}
function elementSpecial( $p_name = null ) {
return $this->setVar( 'i_elementspecial', $p_name );
}
/**
* Warning: needs cbAdminFileSystem File-system loaded to use
*
* @param string $base An existing base path
* @param string $path A path to create from the base path
* @param int $mode Directory permissions
* @return boolean True if successful
*/
function mosMakePath( $base, $path='', $mode = null ) {
global $_CB_framework;
// convert windows paths
$path = preg_replace( "/(\\/){2,}|(\\\\){1,}/",'/', $path );
// check if dir exists
if ( file_exists( $base . $path ) ) {
return true;
}
// set mode
$origmask = null;
if ( isset( $mode ) ) {
$origmask = @umask(0);
} else {
if ( $_CB_framework->getCfg( 'dirperms' ) == '' ) {
// rely on umask
$mode = 0755; // 0777;
} else {
$origmask = @umask( 0 );
$mode = octdec( $_CB_framework->getCfg( 'dirperms' ) );
}
}
$ret = true;
if ( $path == '' ) {
while ( substr( $base, -1, 1 ) == '/' ) {
$base = substr( $base, 0, -1 );
}
$adminFS =& cbAdminFileSystem::getInstance();
$ret = $adminFS->mkdir( $base, $mode );
} else {
$parts = explode( '/', $path );
$n = count( $parts );
$path = $base;
for ( $i = 0 ; $i < $n ; $i++ ) {
$path .= $parts[$i];
if ( ! file_exists( $path ) ) {
$adminFS =& cbAdminFileSystem::getInstance();
if ( ! $adminFS->mkdir( $path, $mode ) ) {
$ret = false;
break;
}
}
$path .= '/';
}
}
if ( isset( $origmask ) ) {
@umask( $origmask );
}
return $ret;
}
} // end class cbInstaller
function cleanupInstall( $userfile_name, $resultdir) {
if ( file_exists( $resultdir ) ) {
$adminFS =& cbAdminFileSystem::getInstance();
$adminFS->deldir( $resultdir );
if ( $userfile_name ) {
$adminFS->unlink( _cbPathName( $userfile_name, false ) );
}
}
}
class cbInstallerPlugin extends cbInstaller {
/** @var string The element type */
var $elementType = 'plugin';
var $checkdbErrors = null;
var $checkdbLogs = null;
/**
* Constructor
*/
function cbInstallerPlugin() {
$this->cbInstaller();
}
/**
* Custom install method
* @param boolean True if installing from directory
*/
function install( $p_fromdir = null ) {
global $_CB_framework, $_CB_database, $ueConfig, $_PLUGINS;
if (!$this->preInstallCheck( $p_fromdir,$this->elementType )) {
return false;
}
$cbInstallXML =& $this->i_xmldocument;
// Get name
$e = &$cbInstallXML->getElementByPath( 'name' );
$this->elementName( $e->data() );
$cleanedElementName = strtolower(str_replace(array(" ","."),array("","_"),$this->elementName()));
// Get plugin filename
$files_element = &$cbInstallXML->getElementByPath( 'files' );
foreach ( $files_element->children() as $file ) {
if ($file->attributes( "plugin" )) {
$this->elementSpecial( $file->attributes( "plugin" ) );
}
}
$fileNopathNoext = null;
$matches = array();
if ( preg_match("/^.*[\\/\\\\](.*)\\..*$/", $this->installFilename(), $matches ) ) {
$fileNopathNoext = $matches[1];
}
if ( ! ( $fileNopathNoext && ( $this->elementSpecial() == $fileNopathNoext ) ) ) {
$this->setError( 1, 'Installation filename `' . $fileNopathNoext . '` (with .xml) does not match main php file plugin attribute `' . $this->elementSpecial() . '` in the plugin xml file
' );
return false;
}
$cleanedMainFileName = strtolower(str_replace(array(" ","."),array("","_"),$this->elementSpecial()));
// check version
$v = &$cbInstallXML->getElementByPath( 'version' );
$version = $v->data();
if (($version == $ueConfig['version']) || ( $version=="1.2.1" || $version=="1.2" || $version=="1.2 RC 4" || $version=="1.2 RC 3" || $version=="1.2 RC 2" || $version=="1.2 RC" || $version=="1.0 RC 2" || $version=="1.0" || $version=="1.0.1" || $version=="1.0.2" || $version=="1.1")) {
;
} else {
$this->setError( 1, 'Plugin version ('.$version.') different from Community Builder version ('.$ueConfig['version'].')' );
return false;
}
$backendMenu = "";
$adminmenusnode =& $cbInstallXML->getElementByPath( 'adminmenus' );
if ( $adminmenusnode ) {
$menusArr = array();
//cycle through each menu
foreach( $adminmenusnode->children() AS $menu ) {
if ( $menu->name() == "menu" ) {
$action = $menu->attributes('action');
$text = getLangDefinition($menu->data());
$menusArr[] = $text . ":" . $action;
}
}
$backendMenu = implode( ",", $menusArr );
}
$folder = strtolower($cbInstallXML->attributes( 'group' ));
if ( cbStartOfStringMatch( $folder, '/' ) ) {
$this->elementDir( $_CB_framework->getCfg('absolute_path') . $folder . '/' );
$subFolder = $folder;
} else {
$subFolder = ( ( $folder == 'user' ) ? 'plug_' : '' ) . $cleanedElementName;
$this->elementDir( $_CB_framework->getCfg('absolute_path') . '/components/com_comprofiler/plugin/' . $folder . '/' . $subFolder . '/' );
}
if (file_exists($this->elementDir())) {
$this->setError( 1, 'Another plugin is already using directory: "' . $this->elementDir() . '"' );
return false;
}
$parentFolder = preg_replace( '/\/[^\/]*\/?$/', '/', $this->elementDir() );
if ( ! file_exists( $parentFolder ) ) {
$this->setError( 1, sprintf( 'The directory in which the plugin should install does not exist: probably the parent extension is not installed. Install parent extension first. Plugin parent directory missing: "%s" and plugin directory specified by installer for installation "%s"', $parentFolder, $this->elementDir() ) );
return false;
}
if(!file_exists($this->elementDir()) && !$this->mosMakePath($this->elementDir())) {
$this->setError( 1, 'Failed to create directory' .' "' . $this->elementDir() . '"' );
return false;
}
// Copy files from package:
if ($this->parseFiles( 'files', 'plugin', 'No file is marked as plugin file' ) === false) {
cleanupInstall( null, $this->elementDir() ); // try removing directory and content just created successfully
return false;
}
// Copy XML file from package (needed for creating fields of new types and so on):
if ($this->copySetupFile('front') === false) {
cleanupInstall( null, $this->elementDir() ); // try removing directory and content just created successfully
return false;
}
// Check to see if plugin already exists in db
$_CB_database->setQuery( "SELECT id FROM #__comprofiler_plugin WHERE element = '" . $this->elementSpecial() . "' AND folder = '" . $subFolder . "'" );
if (!$_CB_database->query()) {
$this->setError( 1, 'SQL error' .': ' . $_CB_database->stderr( true ) );
cleanupInstall( null, $this->elementDir() ); // try removing directory and content just created successfully
return false;
}
$pluginid = $_CB_database->loadResult();
$pluginRowWasNotExisting = ( ! $pluginid );
$row = new moscomprofilerPlugin( $_CB_database );
$row->id = $pluginid;
if ( ! $pluginid ) {
$row->name = $this->elementName();
$row->ordering = 99;
}
$row->type = $folder;
if ( $row->type == 'language' ) {
$row->published = 1;
}
$row->folder = $subFolder;
$row->backend_menu = $backendMenu;
$row->iscore = 0;
$row->access = 0;
$row->client_id = 0;
$row->element = $this->elementSpecial();
if (!$row->store()) {
$this->setError( 1, 'SQL error' .': ' . $row->getError() );
cleanupInstall( null, $this->elementDir() ); // try removing directory and content just created successfully
return false;
}
if ( ! $pluginid ) {
$pluginid = $_CB_database->insertid();
}
$_PLUGINS->_setLoading( $row, true );
// Are there any Database statements ??
$db =& $cbInstallXML->getElementByPath( 'database' );
if ( ( $db !== false ) && ( count( $db->children() ) > 0 ) ) {
cbimport( 'cb.sql.upgrader' );
$sqlUpgrader = new CBSQLupgrader( $_CB_database, false );
//$sqlUpgrader->setDryRun( true );
$success = $sqlUpgrader->checkXmlDatabaseDescription( $db, $cleanedElementName, true, null );
/*
var_dump( $success );
echo "
\nERRORS: " . $sqlUpgrader->getErrors( "
\n\n", "
\n" );
echo "
\nLOGS: " . $sqlUpgrader->getLogs( "
\n\n", "
\n" );
exit;
*/
if ( ! $success ) {
$this->setError( 1, "Plugin database XML SQL Error " . $sqlUpgrader->getErrors() );
if ( $pluginRowWasNotExisting ) {
$this->deleteTabAndFieldsOfPlugin( $row->id ); // delete tabs and private fields of plugin
$row->delete();
}
cleanupInstall( null, $this->elementDir() ); // try removing directory and content just created successfully
return false;
}
}
$e =& $cbInstallXML->getElementByPath( 'description' );
if ( $e !== false ) {
$desc = $this->elementName() . '