AAAA.htaccess000066600000000177151372702060006356 0ustar00 Order allow,deny Deny from all index.html000066600000000037151372702060006550 0ustar00 template.php000066600000042426151372702060007107 0ustar00parent->getPath('source'); if (!$source) { $this->parent ->setPath( 'source', ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/templates/' . $this->parent->extension->element ); } $clientId = isset($this->parent->extension) ? $this->parent->extension->client_id : 0; $this->manifest = $this->parent->getManifest(); $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); $client = (string) $this->manifest->attributes()->client; // Load administrator language if not set. if (!$client) { $client = 'ADMINISTRATOR'; } $extension = "tpl_$name"; $lang = JFactory::getLanguage(); $source = $path ? $path : ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/templates/' . $name; $lang->load($extension . '.sys', $source, null, false, true) || $lang->load($extension . '.sys', constant('JPATH_' . strtoupper($client)), null, false, true); } /** * Custom install method * * @return boolean True on success * * @since 11.1 */ public function install() { // Get a database connector object $db = $this->parent->getDbo(); $lang = JFactory::getLanguage(); $xml = $this->parent->getManifest(); // Get the client application target if ($cname = (string) $xml->attributes()->client) { // Attempt to map the client to a base path $client = JApplicationHelper::getClientInfo($cname, true); if ($client === false) { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_UNKNOWN_CLIENT', $cname)); return false; } $basePath = $client->path; $clientId = $client->id; } else { // No client attribute was found so we assume the site as the client $cname = 'site'; $basePath = JPATH_SITE; $clientId = 0; } // Set the extension's name $name = JFilterInput::getInstance()->clean((string) $xml->name, 'cmd'); $element = strtolower(str_replace(" ", "_", $name)); $this->set('name', $name); $this->set('element', $element); // Check to see if a template by the same name is already installed. $query = $db->getQuery(true); $query->select($query->qn('extension_id'))->from($query->qn('#__extensions')); $query->where($query->qn('type') . ' = ' . $query->q('template')); $query->where($query->qn('element') . ' = ' . $query->q($element)); $db->setQuery($query); try { $id = $db->loadResult(); } catch (RuntimeException $e) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_ROLLBACK'), $e->getMessage()); return false; } // Legacy error handling switch based on the JError::$legacy switch. // @deprecated 12.1 if (JError::$legacy && $db->getErrorNum()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_ROLLBACK', $db->stderr(true))); return false; } // Set the template root path $this->parent->setPath('extension_root', $basePath . '/templates/' . $element); // if it's on the fs... if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite() || $this->parent->isUpgrade())) { $updateElement = $xml->update; // Upgrade manually set or // Update function available or // Update tag detected if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) || $updateElement) { // Force this one $this->parent->setOverwrite(true); $this->parent->setUpgrade(true); if ($id) { // if there is a matching extension mark this as an update; semantics really $this->route = 'update'; } } elseif (!$this->parent->isOverwrite()) { // Overwrite is not set // If we didn't have overwrite set, find an update function or find an update tag so let's call it safe $this->parent ->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT_TPL_INSTALL_ANOTHER_TEMPLATE_USING_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route), $this->parent->getPath('extension_root') ) ); return false; } } /* * If the template directory already exists, then we will assume that the template is already * installed or another template is using that directory. */ if (file_exists($this->parent->getPath('extension_root')) && !$this->parent->isOverwrite()) { JError::raiseWarning( 100, JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_ANOTHER_TEMPLATE_USING_DIRECTORY', $this->parent->getPath('extension_root')) ); return false; } // If the template directory does not exist, let's create it $created = false; if (!file_exists($this->parent->getPath('extension_root'))) { if (!$created = JFolder::create($this->parent->getPath('extension_root'))) { $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_FAILED_CREATE_DIRECTORY', $this->parent->getPath('extension_root'))); return false; } } // If we created the template directory and will want to remove it if we have to roll back // the installation, let's add it to the installation step stack if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root'))); } // Copy all the necessary files if ($this->parent->parseFiles($xml->files, -1) === false) { // Install failed, rollback changes $this->parent->abort(); return false; } if ($this->parent->parseFiles($xml->images, -1) === false) { // Install failed, rollback changes $this->parent->abort(); return false; } if ($this->parent->parseFiles($xml->css, -1) === false) { // Install failed, rollback changes $this->parent->abort(); return false; } // Parse optional tags $this->parent->parseMedia($xml->media); $this->parent->parseLanguages($xml->languages, $clientId); // Get the template description $this->parent->set('message', JText::_((string) $xml->description)); // Lastly, we will copy the manifest file to its appropriate place. if (!$this->parent->copyManifest(-1)) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_TPL_INSTALL_COPY_SETUP')); return false; } // Extension Registration $row = JTable::getInstance('extension'); if ($this->route == 'update' && $id) { $row->load($id); } else { $row->type = 'template'; $row->element = $this->get('element'); // There is no folder for templates $row->folder = ''; $row->enabled = 1; $row->protected = 0; $row->access = 1; $row->client_id = $clientId; $row->params = $this->parent->getParams(); $row->custom_data = ''; // custom data } $row->name = $this->get('name'); // name might change in an update $row->manifest_cache = $this->parent->generateManifestCache(); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_ROLLBACK', $db->stderr(true))); return false; } if ($this->route == 'install') { //insert record in #__template_styles $query = $db->getQuery(true); $query->insert($db->quoteName('#__template_styles')); $debug = $lang->setDebug(false); $columns = array($db->quoteName('template'), $db->quoteName('client_id'), $db->quoteName('home'), $db->quoteName('title'), $db->quoteName('params') ); $query->columns($columns); $query->values( $db->Quote($row->element) . ',' . $db->Quote($clientId) . ',' . $db->Quote(0) . ',' . $db->Quote(JText::sprintf('JLIB_INSTALLER_DEFAULT_STYLE', JText::_($this->get('name')))) . ',' . $db->Quote($row->params) ); $lang->setDebug($debug); $db->setQuery($query); // There is a chance this could fail but we don't care... $db->execute(); } return $row->get('extension_id'); } /** * Custom update method for components * * @return boolean True on success * * @since 11.1 */ public function update() { return $this->install(); } /** * Custom uninstall method * * @param integer $id The extension ID * * @return boolean True on success * * @since 11.1 */ public function uninstall($id) { // Initialise variables. $retval = true; // First order of business will be to load the template object table from the database. // This should give us the necessary information to proceed. $row = JTable::getInstance('extension'); if (!$row->load((int) $id) || !strlen($row->element)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_ERRORUNKOWNEXTENSION')); return false; } // Is the template we are trying to uninstall a core one? // Because that is not a good idea... if ($row->protected) { JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_WARNCORETEMPLATE', $row->name)); return false; } $name = $row->element; $clientId = $row->client_id; // For a template the id will be the template name which represents the subfolder of the templates folder that the template resides in. if (!$name) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_ID_EMPTY')); return false; } // Deny remove default template $db = $this->parent->getDbo(); $query = 'SELECT COUNT(*) FROM #__template_styles' . ' WHERE home = 1 AND template = ' . $db->Quote($name); $db->setQuery($query); if ($db->loadResult() != 0) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_DEFAULT')); return false; } // Get the template root path $client = JApplicationHelper::getClientInfo($clientId); if (!$client) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_INVALID_CLIENT')); return false; } $this->parent->setPath('extension_root', $client->path . '/templates/' . strtolower($name)); $this->parent->setPath('source', $this->parent->getPath('extension_root')); // We do findManifest to avoid problem when uninstalling a list of extensions: getManifest cache its manifest file $this->parent->findManifest(); $manifest = $this->parent->getManifest(); if (!($manifest instanceof SimpleXMLElement)) { // Kill the extension entry $row->delete($row->extension_id); unset($row); // Make sure we delete the folders JFolder::delete($this->parent->getPath('extension_root')); JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_INVALID_NOTFOUND_MANIFEST')); return false; } // Remove files $this->parent->removeFiles($manifest->media); $this->parent->removeFiles($manifest->languages, $clientId); // Delete the template directory if (JFolder::exists($this->parent->getPath('extension_root'))) { $retval = JFolder::delete($this->parent->getPath('extension_root')); } else { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_DIRECTORY')); $retval = false; } // Set menu that assigned to the template back to default template $query = 'UPDATE #__menu INNER JOIN #__template_styles' . ' ON #__template_styles.id = #__menu.template_style_id' . ' SET #__menu.template_style_id = 0' . ' WHERE #__template_styles.template = ' . $db->Quote(strtolower($name)) . ' AND #__template_styles.client_id = ' . $db->Quote($clientId); $db->setQuery($query); $db->execute(); $query = 'DELETE FROM #__template_styles' . ' WHERE template = ' . $db->Quote($name) . ' AND client_id = ' . $db->Quote($clientId); $db->setQuery($query); $db->execute(); $row->delete($row->extension_id); unset($row); return $retval; } /** * Discover existing but uninstalled templates * * @return array JExtensionTable list */ public function discover() { $results = array(); $site_list = JFolder::folders(JPATH_SITE . '/templates'); $admin_list = JFolder::folders(JPATH_ADMINISTRATOR . '/templates'); $site_info = JApplicationHelper::getClientInfo('site', true); $admin_info = JApplicationHelper::getClientInfo('administrator', true); foreach ($site_list as $template) { if ($template == 'system') { continue; // Ignore special system template } $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_SITE . "/templates/$template/templateDetails.xml"); $extension = JTable::getInstance('extension'); $extension->set('type', 'template'); $extension->set('client_id', $site_info->id); $extension->set('element', $template); $extension->set('name', $template); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } foreach ($admin_list as $template) { if ($template == 'system') { continue; // Ignore special system template } $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_ADMINISTRATOR . "/templates/$template/templateDetails.xml"); $extension = JTable::getInstance('extension'); $extension->set('type', 'template'); $extension->set('client_id', $admin_info->id); $extension->set('element', $template); $extension->set('name', $template); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } return $results; } /** * Discover_install * Perform an install for a discovered extension * * @return boolean * * @since 11.1 */ public function discover_install() { // Templates are one of the easiest // If its not in the extensions table we just add it $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $lang = JFactory::getLanguage(); $manifestPath = $client->path . '/templates/' . $this->parent->extension->element . '/templateDetails.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $description = (string) $this->parent->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->state = 0; $this->parent->extension->name = $manifest_details['name']; $this->parent->extension->enabled = 1; $data = new JObject; foreach ($manifest_details as $key => $value) { $data->set($key, $value); } $this->parent->extension->params = $this->parent->getParams(); if ($this->parent->extension->store()) { //insert record in #__template_styles $db = $this->parent->getDbo(); $query = $db->getQuery(true); $query->insert($db->quoteName('#__template_styles')); $debug = $lang->setDebug(false); $columns = array($db->quoteName('template'), $db->quoteName('client_id'), $db->quoteName('home'), $db->quoteName('title'), $db->quoteName('params') ); $query->columns($columns); $query->values( $db->Quote($this->parent->extension->element) . ',' . $db->Quote($this->parent->extension->client_id) . ',' . $db->Quote(0) . ',' . $db->Quote(JText::sprintf('JLIB_INSTALLER_DEFAULT_STYLE', $this->parent->extension->name)) . ',' . $db->Quote($this->parent->extension->params) ); $lang->setDebug($debug); $db->setQuery($query); $db->execute(); return $this->parent->extension->get('extension_id'); } else { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_TPL_DISCOVER_STORE_DETAILS')); return false; } } /** * Refreshes the extension table cache * * @return boolean Result of operation, true if updated, false on failure * * @since 11.1 */ public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally. $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $manifestPath = $client->path . '/templates/' . $this->parent->extension->element . '/templateDetails.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; try { return $this->parent->extension->store(); } catch (JException $e) { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_TPL_REFRESH_MANIFEST_CACHE')); return false; } } } component.php000066600000166374151372702060007307 0ustar00parent->getPath('source'); if (!$source) { $this->parent ->setPath( 'source', ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/components/' . $this->parent->extension->element ); } $this->manifest = $this->parent->getManifest(); $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); if (substr($name, 0, 4) == "com_") { $extension = $name; } else { $extension = "com_$name"; } $lang = JFactory::getLanguage(); $source = $path ? $path : ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/components/' . $extension; if ($this->manifest->administration->files) { $element = $this->manifest->administration->files; } elseif ($this->manifest->files) { $element = $this->manifest->files; } else { $element = null; } if ($element) { $folder = (string) $element->attributes()->folder; if ($folder && file_exists("$path/$folder")) { $source = "$path/$folder"; } } $lang->load($extension . '.sys', $source, null, false, true) || $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, null, false, true); } /** * Custom install method for components * * @return boolean True on success * * @since 11.1 */ public function install() { // Get a database connector object $db = $this->parent->getDbo(); // Get the extension manifest object $this->manifest = $this->parent->getManifest(); // Manifest Document Setup Section // Set the extension's name $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); if (substr($name, 0, 4) == "com_") { $element = $name; } else { $element = "com_$name"; } $this->set('name', $name); $this->set('element', $element); // Get the component description $this->parent->set('message', JText::_((string) $this->manifest->description)); // Set the installation target paths $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->get('element'))); $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->get('element'))); // copy this as its used as a common base $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // Basic Checks Section // Make sure that we have an admin element if (!$this->manifest->administration) { JError::raiseWarning(1, JText::_('JLIB_INSTALLER_ERROR_COMP_INSTALL_ADMIN_ELEMENT')); return false; } // Filesystem Processing Section // If the component site or admin directory already exists, then we will assume that the component is already // installed or another component is using that directory. if (file_exists($this->parent->getPath('extension_site')) || file_exists($this->parent->getPath('extension_administrator'))) { // Look for an update function or update tag $updateElement = $this->manifest->update; // Upgrade manually set or // Update function available or // Update tag detected if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) || $updateElement) { return $this->update(); // transfer control to the update function } elseif (!$this->parent->isOverwrite()) { // Overwrite is set. // We didn't have overwrite set, find an update function or find an update tag so lets call it safe if (file_exists($this->parent->getPath('extension_site'))) { // If the site exists say so. JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_SITE', $this->parent->getPath('extension_site'))); } else { // If the admin exists say so JError::raiseWarning( 1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_ADMIN', $this->parent->getPath('extension_administrator')) ); } return false; } } // Installer Trigger Loading // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // Set the class name $classname = $this->get('element') . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } // Run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight('install', $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Create msg object; first use here $msg = ob_get_contents(); ob_end_clean(); // If the component directory does not exist, let's create it $created = false; if (!file_exists($this->parent->getPath('extension_site'))) { if (!$created = JFolder::create($this->parent->getPath('extension_site'))) { JError::raiseWarning( 1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_FAILED_TO_CREATE_DIRECTORY_SITE', $this->parent->getPath('extension_site')) ); return false; } } // Since we created the component directory and will want to remove it if we have to roll back // the installation, let's add it to the installation step stack if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_site'))); } // If the component admin directory does not exist, let's create it $created = false; if (!file_exists($this->parent->getPath('extension_administrator'))) { if (!$created = JFolder::create($this->parent->getPath('extension_administrator'))) { JError::raiseWarning( 1, JText::sprintf( 'JLIB_INSTALLER_ERROR_COMP_INSTALL_FAILED_TO_CREATE_DIRECTORY_ADMIN', $this->parent->getPath('extension_administrator') ) ); // Install failed, rollback any changes $this->parent->abort(); return false; } } /* * Since we created the component admin directory and we will want to remove it if we have to roll * back the installation, let's add it to the installation step stack */ if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_administrator'))); } // Copy site files if ($this->manifest->files) { if ($this->parent->parseFiles($this->manifest->files) === false) { // Install failed, rollback any changes $this->parent->abort(); return false; } } // Copy admin files if ($this->manifest->administration->files) { if ($this->parent->parseFiles($this->manifest->administration->files, 1) === false) { // Install failed, rollback any changes $this->parent->abort(); return false; } } // Parse optional tags $this->parent->parseMedia($this->manifest->media); $this->parent->parseLanguages($this->manifest->languages); $this->parent->parseLanguages($this->manifest->administration->languages, 1); // Deprecated install, remove after 1.6 // If there is an install file, lets copy it. $installFile = (string) $this->manifest->installfile; if ($installFile) { // Make sure it hasn't already been copied (this would be an error in the XML install file) if (!file_exists($this->parent->getPath('extension_administrator') . '/' . $installFile) || $this->parent->isOverwrite()) { $path['src'] = $this->parent->getPath('source') . '/' . $installFile; $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $installFile; if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_PHP_INSTALL')); return false; } } $this->set('install_script', $installFile); } // Deprecated uninstall, remove after 1.6 // If there is an uninstall file, let's copy it. $uninstallFile = (string) $this->manifest->uninstallfile; if ($uninstallFile) { // Make sure it hasn't already been copied (this would be an error in the XML install file) if (!file_exists($this->parent->getPath('extension_administrator') . '/' . $uninstallFile) || $this->parent->isOverwrite()) { $path['src'] = $this->parent->getPath('source') . '/' . $uninstallFile; $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $uninstallFile; if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_PHP_UNINSTALL')); return false; } } } // If there is a manifest script, let's copy it. if ($this->get('manifest_script')) { $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $this->get('manifest_script'); if (!file_exists($path['dest']) || $this->parent->isOverwrite()) { if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_MANIFEST')); return false; } } } /** * --------------------------------------------------------------------------------------------- * Database Processing Section * --------------------------------------------------------------------------------------------- */ /* * Let's run the install queries for the component * If Joomla 1.5 compatible, with discreet sql files - execute appropriate * file for utf-8 support or non-utf-8 support */ // Try for Joomla 1.5 type queries // Second argument is the utf compatible version attribute if (isset($this->manifest->install->sql)) { $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); if ($utfresult === false) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_SQL_ERROR', $db->stderr(true))); return false; } } /** * --------------------------------------------------------------------------------------------- * Custom Installation Script Section * --------------------------------------------------------------------------------------------- */ /* * If we have an install script, let's include it, execute the custom * install method, and append the return value from the custom install * method to the installation message. */ // Start legacy support if ($this->get('install_script')) { if (is_file($this->parent->getPath('extension_administrator') . '/' . $this->get('install_script')) || $this->parent->isOverwrite()) { $notdef = false; $ranwell = false; ob_start(); ob_implicit_flush(false); require_once $this->parent->getPath('extension_administrator') . '/' . $this->get('install_script'); if (function_exists('com_install')) { if (com_install() === false) { $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg .= ob_get_contents(); // append messages ob_end_clean(); } } // End legacy support // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'install')) { if ($this->parent->manifestClass->install($this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Append messages $msg .= ob_get_contents(); ob_end_clean(); /** * --------------------------------------------------------------------------------------------- * Finalization and Cleanup Section * --------------------------------------------------------------------------------------------- */ // Add an entry to the extension table with a whole heap of defaults $row = JTable::getInstance('extension'); $row->set('name', $this->get('name')); $row->set('type', 'component'); $row->set('element', $this->get('element')); $row->set('folder', ''); // There is no folder for components $row->set('enabled', 1); $row->set('protected', 0); $row->set('access', 0); $row->set('client_id', 1); $row->set('params', $this->parent->getParams()); $row->set('manifest_cache', $this->parent->generateManifestCache()); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); return false; } $eid = $db->insertid(); // Clobber any possible pending updates $update = JTable::getInstance('update'); $uid = $update->find(array('element' => $this->get('element'), 'type' => 'component', 'client_id' => '', 'folder' => '')); if ($uid) { $update->delete($uid); } // We will copy the manifest file to its appropriate place. if (!$this->parent->copyManifest()) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_COPY_SETUP')); return false; } // Time to build the admin menus if (!$this->_buildAdminMenus($row->extension_id)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED')); //$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); //return false; } // Set the schema version to be the latest update version if ($this->manifest->update) { $this->parent->setSchemaVersion($this->manifest->update->schemas, $eid); } // Register the component container just under root in the assets table. $asset = JTable::getInstance('Asset'); $asset->name = $row->element; $asset->parent_id = 1; $asset->rules = '{}'; $asset->title = $row->name; $asset->setLocation(1, 'last-child'); if (!$asset->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); return false; } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight('install', $this); } // Append messages $msg .= ob_get_contents(); ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $row->extension_id; } /** * Custom update method for components * * @return boolean True on success * * @since 11.1 */ public function update() { // Get a database connector object $db = $this->parent->getDbo(); // Set the overwrite setting $this->parent->setOverwrite(true); // Get the extension manifest object $this->manifest = $this->parent->getManifest(); /** * --------------------------------------------------------------------------------------------- * Manifest Document Setup Section * --------------------------------------------------------------------------------------------- */ // Set the extension's name $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); if (substr($name, 0, 4) == "com_") { $element = $name; } else { $element = "com_$name"; } $this->set('name', $name); $this->set('element', $element); // Get the component description $description = (string) $this->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } // Set the installation target paths $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->get('element'))); $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->get('element'))); $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // copy this as its used as a common base /** * Hunt for the original XML file */ $old_manifest = null; // Create a new installer because findManifest sets stuff // Look in the administrator first $tmpInstaller = new JInstaller; $tmpInstaller->setPath('source', $this->parent->getPath('extension_administrator')); if (!$tmpInstaller->findManifest()) { // Then the site $tmpInstaller->setPath('source', $this->parent->getPath('extension_site')); if ($tmpInstaller->findManifest()) { $old_manifest = $tmpInstaller->getManifest(); } } else { $old_manifest = $tmpInstaller->getManifest(); } // Should do this above perhaps? if ($old_manifest) { $this->oldAdminFiles = $old_manifest->administration->files; $this->oldFiles = $old_manifest->files; } else { $this->oldAdminFiles = null; $this->oldFiles = null; } /** * --------------------------------------------------------------------------------------------- * Basic Checks Section * --------------------------------------------------------------------------------------------- */ // Make sure that we have an admin element if (!$this->manifest->administration) { JError::raiseWarning(1, JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_ADMIN_ELEMENT')); return false; } /** * --------------------------------------------------------------------------------------------- * Installer Trigger Loading * --------------------------------------------------------------------------------------------- */ // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // Set the class name $classname = $element . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } // Run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight('update', $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Create msg object; first use here $msg = ob_get_contents(); ob_end_clean(); /** * --------------------------------------------------------------------------------------------- * Filesystem Processing Section * --------------------------------------------------------------------------------------------- */ // If the component directory does not exist, let's create it $created = false; if (!file_exists($this->parent->getPath('extension_site'))) { if (!$created = JFolder::create($this->parent->getPath('extension_site'))) { JError::raiseWarning( 1, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UPDATE_FAILED_TO_CREATE_DIRECTORY_SITE', $this->parent->getPath('extension_site')) ); return false; } } /* * Since we created the component directory and will want to remove it if we have to roll back * the installation, lets add it to the installation step stack */ if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_site'))); } // If the component admin directory does not exist, let's create it $created = false; if (!file_exists($this->parent->getPath('extension_administrator'))) { if (!$created = JFolder::create($this->parent->getPath('extension_administrator'))) { JError::raiseWarning( 1, JText::sprintf( 'JLIB_INSTALLER_ERROR_COMP_UPDATE_FAILED_TO_CREATE_DIRECTORY_ADMIN', $this->parent->getPath('extension_administrator') ) ); // Install failed, rollback any changes $this->parent->abort(); return false; } } /* * Since we created the component admin directory and we will want to remove it if we have to roll * back the installation, let's add it to the installation step stack */ if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_administrator'))); } // Find files to copy if ($this->manifest->files) { if ($this->parent->parseFiles($this->manifest->files, 0, $this->oldFiles) === false) { // Install failed, rollback any changes $this->parent->abort(); return false; } } if ($this->manifest->administration->files) { if ($this->parent->parseFiles($this->manifest->administration->files, 1, $this->oldAdminFiles) === false) { // Install failed, rollback any changes $this->parent->abort(); return false; } } // Parse optional tags $this->parent->parseMedia($this->manifest->media); $this->parent->parseLanguages($this->manifest->languages); $this->parent->parseLanguages($this->manifest->administration->languages, 1); // Deprecated install, remove after 1.6 // If there is an install file, lets copy it. $installFile = (string) $this->manifest->installfile; if ($installFile) { // Make sure it hasn't already been copied (this would be an error in the XML install file) if (!file_exists($this->parent->getPath('extension_administrator') . '/' . $installFile) || $this->parent->isOverwrite()) { $path['src'] = $this->parent->getPath('source') . '/' . $installFile; $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $installFile; if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_PHP_INSTALL')); return false; } } $this->set('install_script', $installFile); } // Deprecated uninstall, remove after 1.6 // If there is an uninstall file, lets copy it. $uninstallFile = (string) $this->manifest->uninstallfile; if ($uninstallFile) { // Make sure it hasn't already been copied (this would be an error in the XML install file) if (!file_exists($this->parent->getPath('extension_administrator') . '/' . $uninstallFile) || $this->parent->isOverwrite()) { $path['src'] = $this->parent->getPath('source') . '/' . $uninstallFile; $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $uninstallFile; if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_PHP_UNINSTALL')); return false; } } } // If there is a manifest script, let's copy it. if ($this->get('manifest_script')) { $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $this->get('manifest_script'); if (!file_exists($path['dest']) || $this->parent->isOverwrite()) { if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_MANIFEST')); return false; } } } /** * --------------------------------------------------------------------------------------------- * Database Processing Section * --------------------------------------------------------------------------------------------- */ /* * Let's run the update queries for the component */ $row = JTable::getInstance('extension'); $eid = $row->find(array('element' => strtolower($this->get('element')), 'type' => 'component')); if ($this->manifest->update) { $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $eid); if ($result === false) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_UPDATE_SQL_ERROR', $db->stderr(true))); return false; } } // Time to build the admin menus if (!$this->_buildAdminMenus($eid)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED')); // $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); // Return false; } /** * --------------------------------------------------------------------------------------------- * Custom Installation Script Section * --------------------------------------------------------------------------------------------- */ /* * If we have an install script, let's include it, execute the custom * install method, and append the return value from the custom install * method to the installation message. */ // Start legacy support if ($this->get('install_script')) { if (is_file($this->parent->getPath('extension_administrator') . '/' . $this->get('install_script')) || $this->parent->isOverwrite()) { $notdef = false; $ranwell = false; ob_start(); ob_implicit_flush(false); require_once $this->parent->getPath('extension_administrator') . '/' . $this->get('install_script'); if (function_exists('com_install')) { if (com_install() === false) { $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg .= ob_get_contents(); // append messages ob_end_clean(); } } /* * If we have an update script, let's include it, execute the custom * update method, and append the return value from the custom update * method to the installation message. */ // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) { if ($this->parent->manifestClass->update($this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Append messages $msg .= ob_get_contents(); ob_end_clean(); /** * --------------------------------------------------------------------------------------------- * Finalization and Cleanup Section * --------------------------------------------------------------------------------------------- */ // Clobber any possible pending updates $update = JTable::getInstance('update'); $uid = $update->find(array('element' => $this->get('element'), 'type' => 'component', 'client_id' => '', 'folder' => '')); if ($uid) { $update->delete($uid); } // Update an entry to the extension table if ($eid) { $row->load($eid); } else { // Set the defaults // There is no folder for components $row->folder = ''; $row->enabled = 1; $row->protected = 0; $row->access = 1; $row->client_id = 1; $row->params = $this->parent->getParams(); } $row->name = $this->get('name'); $row->type = 'component'; $row->element = $this->get('element'); $row->manifest_cache = $this->parent->generateManifestCache(); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_UPDATE_ROLLBACK', $db->stderr(true))); return false; } // We will copy the manifest file to its appropriate place. if (!$this->parent->copyManifest()) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_COPY_SETUP')); return false; } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight('update', $this); } // Append messages $msg .= ob_get_contents(); ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $row->extension_id; } /** * Custom uninstall method for components * * @param integer $id The unique extension id of the component to uninstall * * @return mixed Return value for uninstall method in component uninstall file * * @since 11.1 */ public function uninstall($id) { // Initialise variables. $db = $this->parent->getDbo(); $row = null; $retval = true; // First order of business will be to load the component object table from the database. // This should give us the necessary information to proceed. $row = JTable::getInstance('extension'); if (!$row->load((int) $id)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORUNKOWNEXTENSION')); return false; } // Is the component we are trying to uninstall a core one? // Because that is not a good idea... if ($row->protected) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_WARNCORECOMPONENT')); return false; } // Get the admin and site paths for the component $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $row->element)); $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $row->element)); $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // copy this as its used as a common base /** * --------------------------------------------------------------------------------------------- * Manifest Document Setup Section * --------------------------------------------------------------------------------------------- */ // Find and load the XML install file for the component $this->parent->setPath('source', $this->parent->getPath('extension_administrator')); // Get the package manifest object // We do findManifest to avoid problem when uninstalling a list of extension: getManifest cache its manifest file $this->parent->findManifest(); $this->manifest = $this->parent->getManifest(); if (!$this->manifest) { // Make sure we delete the folders if no manifest exists JFolder::delete($this->parent->getPath('extension_administrator')); JFolder::delete($this->parent->getPath('extension_site')); // Remove the menu $this->_removeAdminMenus($row); // Raise a warning JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORREMOVEMANUALLY')); // Return return false; } // Set the extensions name $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); if (substr($name, 0, 4) == "com_") { $element = $name; } else { $element = "com_$name"; } $this->set('name', $name); $this->set('element', $element); // Attempt to load the admin language file; might have uninstall strings $this->loadLanguage(JPATH_ADMINISTRATOR . '/components/' . $element); /** * --------------------------------------------------------------------------------------------- * Installer Trigger Loading and Uninstall * --------------------------------------------------------------------------------------------- */ // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) $scriptFile = (string) $this->manifest->scriptfile; if ($scriptFile) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $scriptFile; if (is_file($manifestScriptFile)) { // load the file include_once $manifestScriptFile; } // Set the class name $classname = $row->element . 'InstallerScript'; if (class_exists($classname)) { // create a new instance $this->parent->manifestClass = new $classname($this); // and set this so we can copy it later $this->set('manifest_script', $scriptFile); // Note: if we don't find the class, don't bother to copy the file } } ob_start(); ob_implicit_flush(false); // run uninstall if possible if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) { $this->parent->manifestClass->uninstall($this); } $msg = ob_get_contents(); ob_end_clean(); /** * --------------------------------------------------------------------------------------------- * Custom Uninstallation Script Section; Legacy CMS 1.5 Support * --------------------------------------------------------------------------------------------- */ // Now let's load the uninstall file if there is one and execute the uninstall function if it exists. $uninstallFile = (string) $this->manifest->uninstallfile; if ($uninstallFile) { // Element exists, does the file exist? if (is_file($this->parent->getPath('extension_administrator') . '/' . $uninstallFile)) { ob_start(); ob_implicit_flush(false); require_once $this->parent->getPath('extension_administrator') . '/' . $uninstallFile; if (function_exists('com_uninstall')) { if (com_uninstall() === false) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_CUSTOM')); $retval = false; } } // append this in case there was something else $msg .= ob_get_contents(); ob_end_clean(); } } if ($msg != '') { $this->parent->set('extension_message', $msg); } /** * --------------------------------------------------------------------------------------------- * Database Processing Section * --------------------------------------------------------------------------------------------- */ /* * Let's run the uninstall queries for the component * If Joomla CMS 1.5 compatible, with discrete sql files - execute appropriate * file for utf-8 support or non-utf support */ // Try for Joomla 1.5 type queries // Second argument is the utf compatible version attribute if (isset($this->manifest->uninstall->sql)) { $utfresult = $this->parent->parseSQLFiles($this->manifest->uninstall->sql); if ($utfresult === false) { // Install failed, rollback changes JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_SQL_ERROR', $db->stderr(true))); $retval = false; } } $this->_removeAdminMenus($row); /** * --------------------------------------------------------------------------------------------- * Filesystem Processing Section * --------------------------------------------------------------------------------------------- */ // Let's remove those language files and media in the JROOT/images/ folder that are // associated with the component we are uninstalling $this->parent->removeFiles($this->manifest->media); $this->parent->removeFiles($this->manifest->languages); $this->parent->removeFiles($this->manifest->administration->languages, 1); // Remove the schema version $query = $db->getQuery(true); $query->delete()->from('#__schemas')->where('extension_id = ' . $id); $db->setQuery($query); $db->execute(); // Remove the component container in the assets table. $asset = JTable::getInstance('Asset'); if ($asset->loadByName($element)) { $asset->delete(); } // Remove categories for this component $query = $db->getQuery(true); $query->delete()->from('#__categories')->where('extension=' . $db->quote($element), 'OR') ->where('extension LIKE ' . $db->quote($element . '.%')); $db->setQuery($query); $db->execute(); // Check for errors. if ($db->getErrorNum()) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_DELETE_CATEGORIES')); $this->setError($db->getErrorMsg()); $retval = false; } // Clobber any possible pending updates $update = JTable::getInstance('update'); $uid = $update->find(array('element' => $row->element, 'type' => 'component', 'client_id' => '', 'folder' => '')); if ($uid) { $update->delete($uid); } // Now we need to delete the installation directories. This is the final step in uninstalling the component. if (trim($row->element)) { // Delete the component site directory if (is_dir($this->parent->getPath('extension_site'))) { if (!JFolder::delete($this->parent->getPath('extension_site'))) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_SITE')); $retval = false; } } // Delete the component admin directory if (is_dir($this->parent->getPath('extension_administrator'))) { if (!JFolder::delete($this->parent->getPath('extension_administrator'))) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_ADMIN')); $retval = false; } } // Now we will no longer need the extension object, so let's delete it and free up memory $row->delete($row->extension_id); unset($row); return $retval; } else { // No component option defined... cannot delete what we don't know about JError::raiseWarning(100, 'JLIB_INSTALLER_ERROR_COMP_UNINSTALL_NO_OPTION'); return false; } } /** * Method to build menu database entries for a component * * @return boolean True if successful * * @since 11.1 */ protected function _buildAdminMenus() { // Initialise variables. $db = $this->parent->getDbo(); $table = JTable::getInstance('menu'); $option = $this->get('element'); // If a component exists with this option in the table then we don't need to add menus $query = $db->getQuery(true); $query->select('m.id, e.extension_id'); $query->from('#__menu AS m'); $query->leftJoin('#__extensions AS e ON m.component_id = e.extension_id'); $query->where('m.parent_id = 1'); $query->where("m.client_id = 1"); $query->where('e.element = ' . $db->quote($option)); $db->setQuery($query); $componentrow = $db->loadObject(); // Check if menu items exist if ($componentrow) { // Don't do anything if overwrite has not been enabled if (!$this->parent->isOverwrite()) { return true; } // Remove existing menu items if overwrite has been enabled if ($option) { $this->_removeAdminMenus($componentrow); // If something goes wrong, theres no way to rollback TODO: Search for better solution } $component_id = $componentrow->extension_id; } else { // Lets Find the extension id $query->clear(); $query->select('e.extension_id'); $query->from('#__extensions AS e'); $query->where('e.element = ' . $db->quote($option)); $db->setQuery($query); $component_id = $db->loadResult(); // TODO Find Some better way to discover the component_id } // Ok, now its time to handle the menus. Start with the component root menu, then handle submenus. $menuElement = $this->manifest->administration->menu; if ($menuElement) { $data = array(); $data['menutype'] = 'main'; $data['client_id'] = 1; $data['title'] = (string) $menuElement; $data['alias'] = (string) $menuElement; $data['link'] = 'index.php?option=' . $option; $data['type'] = 'component'; $data['published'] = 0; $data['parent_id'] = 1; $data['component_id'] = $component_id; $data['img'] = ((string) $menuElement->attributes()->img) ? (string) $menuElement->attributes()->img : 'class:component'; $data['home'] = 0; if (!$table->setLocation(1, 'last-child') || !$table->bind($data) || !$table->check() || !$table->store()) { // The menu item already exists. Delete it and retry instead of throwing an error. $query = $db->getQuery(true); $query->select('id'); $query->from('#__menu'); $query->where('menutype = '.$db->quote('main')); $query->where('client_id = 1'); $query->where('link = '.$db->quote('index.php?option='.$option)); $query->where('type = '.$db->quote('component')); $query->where('parent_id = 1'); $query->where('home = 0'); $db->setQuery($query); $menu_id = $db->loadResult(); if(!$menu_id) { // Oops! Could not get the menu ID. Go back and rollback changes. JError::raiseWarning(1, $table->getError()); return false; } else { // Remove the old menu item $query = $db->getQuery(true); $query->delete('#__menu'); $query->where('id = '.(int)$menu_id); $db->setQuery($query); $db->query(); // Retry creating the menu item if (!$table->setLocation(1, 'last-child') || !$table->bind($data) || !$table->check() || !$table->store()) { // Install failed, rollback changes return false; } } } /* * Since we have created a menu item, we add it to the installation step stack * so that if we have to rollback the changes we can undo it. */ $this->parent->pushStep(array('type' => 'menu', 'id' => $component_id)); } // No menu element was specified, Let's make a generic menu item else { $data = array(); $data['menutype'] = 'main'; $data['client_id'] = 1; $data['title'] = $option; $data['alias'] = $option; $data['link'] = 'index.php?option=' . $option; $data['type'] = 'component'; $data['published'] = 0; $data['parent_id'] = 1; $data['component_id'] = $component_id; $data['img'] = 'class:component'; $data['home'] = 0; if (!$table->setLocation(1, 'last-child') || !$table->bind($data) || !$table->check() || !$table->store()) { // Install failed, warn user and rollback changes JError::raiseWarning(1, $table->getError()); return false; } /* * Since we have created a menu item, we add it to the installation step stack * so that if we have to rollback the changes we can undo it. */ $this->parent->pushStep(array('type' => 'menu', 'id' => $component_id)); } $parent_id = $table->id; /* * Process SubMenus */ if (!$this->manifest->administration->submenu) { return true; } $parent_id = $table->id; foreach ($this->manifest->administration->submenu->menu as $child) { $data = array(); $data['menutype'] = 'main'; $data['client_id'] = 1; $data['title'] = (string) $child; $data['alias'] = (string) $child; $data['type'] = 'component'; $data['published'] = 0; $data['parent_id'] = $parent_id; $data['component_id'] = $component_id; $data['img'] = ((string) $child->attributes()->img) ? (string) $child->attributes()->img : 'class:component'; $data['home'] = 0; // Set the sub menu link if ((string) $child->attributes()->link) { $data['link'] = 'index.php?' . $child->attributes()->link; } else { $request = array(); if ((string) $child->attributes()->act) { $request[] = 'act=' . $child->attributes()->act; } if ((string) $child->attributes()->task) { $request[] = 'task=' . $child->attributes()->task; } if ((string) $child->attributes()->controller) { $request[] = 'controller=' . $child->attributes()->controller; } if ((string) $child->attributes()->view) { $request[] = 'view=' . $child->attributes()->view; } if ((string) $child->attributes()->layout) { $request[] = 'layout=' . $child->attributes()->layout; } if ((string) $child->attributes()->sub) { $request[] = 'sub=' . $child->attributes()->sub; } $qstring = (count($request)) ? '&' . implode('&', $request) : ''; $data['link'] = 'index.php?option=' . $option . $qstring; } $table = JTable::getInstance('menu'); if (!$table->setLocation($parent_id, 'last-child') || !$table->bind($data) || !$table->check() || !$table->store()) { // Install failed, rollback changes return false; } /* * Since we have created a menu item, we add it to the installation step stack * so that if we have to rollback the changes we can undo it. */ $this->parent->pushStep(array('type' => 'menu', 'id' => $component_id)); } return true; } /** * Method to remove admin menu references to a component * * @param object &$row Component table object. * * @return boolean True if successful. * * @since 11.1 */ protected function _removeAdminMenus(&$row) { // Initialise Variables $db = $this->parent->getDbo(); $table = JTable::getInstance('menu'); $id = $row->extension_id; // Get the ids of the menu items $query = $db->getQuery(true); $query->select('id'); $query->from('#__menu'); $query->where($query->qn('client_id') . ' = 1'); $query->where($query->qn('component_id') . ' = ' . (int) $id); $db->setQuery($query); $ids = $db->loadColumn(); // Check for error if ($error = $db->getErrorMsg()) { JError::raiseWarning('', JText::_('JLIB_INSTALLER_ERROR_COMP_REMOVING_ADMIN_MENUS_FAILED')); if ($error && $error != 1) { JError::raiseWarning(100, $error); } return false; } elseif (!empty($ids)) { // Iterate the items to delete each one. foreach ($ids as $menuid) { if (!$table->delete((int) $menuid)) { $this->setError($table->getError()); return false; } } // Rebuild the whole tree $table->rebuild(); } return true; } /** * Custom rollback method * - Roll back the component menu item * * @param array $step Installation step to rollback. * * @return boolean True on success * * @since 11.1 */ protected function _rollback_menu($step) { return $this->_removeAdminMenus((object) array('extension_id' => $step['id'])); } /** * Discover unregistered extensions. * * @return array A list of extensions. * * @since 11.1 */ public function discover() { $results = array(); $site_components = JFolder::folders(JPATH_SITE . '/components'); $admin_components = JFolder::folders(JPATH_ADMINISTRATOR . '/components'); foreach ($site_components as $component) { if (file_exists(JPATH_SITE . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml')) { $manifest_details = JApplicationHelper::parseXMLInstallFile( JPATH_SITE . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml' ); $extension = JTable::getInstance('extension'); $extension->set('type', 'component'); $extension->set('client_id', 0); $extension->set('element', $component); $extension->set('name', $component); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } } foreach ($admin_components as $component) { if (file_exists(JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml')) { $manifest_details = JApplicationHelper::parseXMLInstallFile( JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml' ); $extension = JTable::getInstance('extension'); $extension->set('type', 'component'); $extension->set('client_id', 1); $extension->set('element', $component); $extension->set('name', $component); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } } return $results; } /** * Install unregistered extensions that have been discovered. * * @return mixed * * @since 11.1 */ public function discover_install() { // Need to find to find where the XML file is since we don't store this normally $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $short_element = str_replace('com_', '', $this->parent->extension->element); $manifestPath = $client->path . '/components/' . $this->parent->extension->element . '/' . $short_element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $this->parent->setPath('source', $client->path . '/components/' . $this->parent->extension->element); $this->parent->setPath('extension_root', $this->parent->getPath('source')); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->state = 0; $this->parent->extension->name = $manifest_details['name']; $this->parent->extension->enabled = 1; $this->parent->extension->params = $this->parent->getParams(); try { $this->parent->extension->store(); } catch (JException $e) { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_COMP_DISCOVER_STORE_DETAILS')); return false; } // now we need to run any SQL it has, languages, media or menu stuff // Get a database connector object $db = $this->parent->getDbo(); // Get the extension manifest object $this->manifest = $this->parent->getManifest(); /** * --------------------------------------------------------------------------------------------- * Manifest Document Setup Section * --------------------------------------------------------------------------------------------- */ // Set the extensions name $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); if (substr($name, 0, 4) == "com_") { $element = $name; } else { $element = "com_$name"; } $this->set('name', $name); $this->set('element', $element); // Get the component description $description = (string) $this->manifest->description; if ($description) { $this->parent->set('message', JText::_((string) $description)); } else { $this->parent->set('message', ''); } // Set the installation target paths $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->get('element'))); $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->get('element'))); $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); // copy this as its used as a common base /** * --------------------------------------------------------------------------------------------- * Basic Checks Section * --------------------------------------------------------------------------------------------- */ // Make sure that we have an admin element if (!$this->manifest->administration) { JError::raiseWarning(1, JText::_('JLIB_INSTALLER_ERROR_COMP_INSTALL_ADMIN_ELEMENT')); return false; } /** * --------------------------------------------------------------------------------------------- * Installer Trigger Loading * --------------------------------------------------------------------------------------------- */ // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // load the file include_once $manifestScriptFile; } // Set the class name $classname = $element . 'InstallerScript'; if (class_exists($classname)) { // create a new instance $this->parent->manifestClass = new $classname($this); // and set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } // Run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight('discover_install', $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg = ob_get_contents(); // create msg object; first use here ob_end_clean(); // Normally we would copy files and create directories, lets skip to the optional files // Note: need to dereference things! // Parse optional tags //$this->parent->parseMedia($this->manifest->media); // We don't do language because 1.6 suggests moving to extension based languages //$this->parent->parseLanguages($this->manifest->languages); //$this->parent->parseLanguages($this->manifest->administration->languages, 1); /** * --------------------------------------------------------------------------------------------- * Database Processing Section * --------------------------------------------------------------------------------------------- */ /* * Let's run the install queries for the component * If Joomla 1.5 compatible, with discreet sql files - execute appropriate * file for utf-8 support or non-utf-8 support */ // Try for Joomla 1.5 type queries // second argument is the utf compatible version attribute if (isset($this->manifest->install->sql)) { $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); if ($utfresult === false) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_SQL_ERROR', $db->stderr(true))); return false; } } // Time to build the admin menus if (!$this->_buildAdminMenus($this->parent->extension->extension_id)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED')); //$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); //return false; } /** * --------------------------------------------------------------------------------------------- * Custom Installation Script Section * --------------------------------------------------------------------------------------------- */ /* * If we have an install script, lets include it, execute the custom * install method, and append the return value from the custom install * method to the installation message. */ // start legacy support if ($this->get('install_script')) { if (is_file($this->parent->getPath('extension_administrator') . '/' . $this->get('install_script'))) { ob_start(); ob_implicit_flush(false); require_once $this->parent->getPath('extension_administrator') . '/' . $this->get('install_script'); if (function_exists('com_install')) { if (com_install() === false) { $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Append messages $msg .= ob_get_contents(); ob_end_clean(); } } // End legacy support // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'install')) { if ($this->parent->manifestClass->install($this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg .= ob_get_contents(); // append messages ob_end_clean(); /** * --------------------------------------------------------------------------------------------- * Finalization and Cleanup Section * --------------------------------------------------------------------------------------------- */ // Clobber any possible pending updates $update = JTable::getInstance('update'); $uid = $update->find(array('element' => $this->get('element'), 'type' => 'component', 'client_id' => '', 'folder' => '')); if ($uid) { $update->delete($uid); } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight('discover_install', $this); } $msg .= ob_get_contents(); // append messages ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $this->parent->extension->extension_id; } /** * Refreshes the extension table cache * * @return boolean Result of operation, true if updated, false on failure * * @since 11.1 */ public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $short_element = str_replace('com_', '', $this->parent->extension->element); $manifestPath = $client->path . '/components/' . $this->parent->extension->element . '/' . $short_element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; try { return $this->parent->extension->store(); } catch (JException $e) { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_COMP_REFRESH_MANIFEST_CACHE')); return false; } } } language.php000066600000047303151372702060007056 0ustar00parent->getPath('source'); if (!$source) { $this->parent ->setPath( 'source', ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/language/' . $this->parent->extension->element ); } $this->manifest = $this->parent->getManifest(); $root = $this->manifest->document; // Get the client application target if ((string) $this->manifest->attributes()->client == 'both') { JError::raiseWarning(42, JText::_('JLIB_INSTALLER_ERROR_DEPRECATED_FORMAT')); $element = $this->manifest->site->files; if (!$this->_install('site', JPATH_SITE, 0, $element)) { return false; } $element = $this->manifest->administration->files; if (!$this->_install('administrator', JPATH_ADMINISTRATOR, 1, $element)) { return false; } // This causes an issue because we have two eid's, *sigh* nasty hacks! return true; } elseif ($cname = (string) $this->manifest->attributes()->client) { // Attempt to map the client to a base path $client = JApplicationHelper::getClientInfo($cname, true); if ($client === null) { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_UNKNOWN_CLIENT_TYPE', $cname))); return false; } $basePath = $client->path; $clientId = $client->id; $element = $this->manifest->files; return $this->_install($cname, $basePath, $clientId, $element); } else { // No client attribute was found so we assume the site as the client $cname = 'site'; $basePath = JPATH_SITE; $clientId = 0; $element = $this->manifest->files; return $this->_install($cname, $basePath, $clientId, $element); } } /** * Install function that is designed to handle individual clients * * @param string $cname Cname @todo: not used * @param string $basePath The base name. * @param integer $clientId The client id. * @param object &$element The XML element. * * @return boolean * * @since 11.1 */ protected function _install($cname, $basePath, $clientId, &$element) { $this->manifest = $this->parent->getManifest(); // Get the language name // Set the extensions name $name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd'); $this->set('name', $name); // Get the Language tag [ISO tag, eg. en-GB] $tag = (string) $this->manifest->tag; // Check if we found the tag - if we didn't, we may be trying to install from an older language package if (!$tag) { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::_('JLIB_INSTALLER_ERROR_NO_LANGUAGE_TAG'))); return false; } $this->set('tag', $tag); // Set the language installation path $this->parent->setPath('extension_site', $basePath . '/language/' . $tag); // Do we have a meta file in the file list? In other words... is this a core language pack? if ($element && count($element->children())) { $files = $element->children(); foreach ($files as $file) { if ((string) $file->attributes()->file == 'meta') { $this->_core = true; break; } } } // Either we are installing a core pack or a core pack must exist for the language we are installing. if (!$this->_core) { if (!JFile::exists($this->parent->getPath('extension_site') . '/' . $this->get('tag') . '.xml')) { $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_NO_CORE_LANGUAGE', $this->get('tag')))); return false; } } // If the language directory does not exist, let's create it $created = false; if (!file_exists($this->parent->getPath('extension_site'))) { if (!$created = JFolder::create($this->parent->getPath('extension_site'))) { $this->parent ->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_CREATE_FOLDER_FAILED', $this->parent->getPath('extension_site')) ) ); return false; } } else { // Look for an update function or update tag $updateElement = $this->manifest->update; // Upgrade manually set or // Update function available or // Update tag detected if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) || $updateElement) { return $this->update(); // transfer control to the update function } elseif (!$this->parent->isOverwrite()) { // Overwrite is set // We didn't have overwrite set, find an update function or find an update tag so lets call it safe if (file_exists($this->parent->getPath('extension_site'))) { // If the site exists say so. JError::raiseWarning( 1, JText::sprintf( 'JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_FOLDER_IN_USE', $this->parent->getPath('extension_site')) ) ); } else { // If the admin exists say so. JError::raiseWarning( 1, JText::sprintf( 'JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_FOLDER_IN_USE', $this->parent->getPath('extension_administrator')) ) ); } return false; } } /* * If we created the language directory we will want to remove it if we * have to roll back the installation, so let's add it to the installation * step stack */ if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_site'))); } // Copy all the necessary files if ($this->parent->parseFiles($element) === false) { // Install failed, rollback changes $this->parent->abort(); return false; } // Parse optional tags $this->parent->parseMedia($this->manifest->media); // Copy all the necessary font files to the common pdf_fonts directory $this->parent->setPath('extension_site', $basePath . '/language/pdf_fonts'); $overwrite = $this->parent->setOverwrite(true); if ($this->parent->parseFiles($this->manifest->fonts) === false) { // Install failed, rollback changes $this->parent->abort(); return false; } $this->parent->setOverwrite($overwrite); // Get the language description $description = (string) $this->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } // Add an entry to the extension table with a whole heap of defaults $row = JTable::getInstance('extension'); $row->set('name', $this->get('name')); $row->set('type', 'language'); $row->set('element', $this->get('tag')); // There is no folder for languages $row->set('folder', ''); $row->set('enabled', 1); $row->set('protected', 0); $row->set('access', 0); $row->set('client_id', $clientId); $row->set('params', $this->parent->getParams()); $row->set('manifest_cache', $this->parent->generateManifestCache()); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', $row->getError())); return false; } // Clobber any possible pending updates $update = JTable::getInstance('update'); $uid = $update->find(array('element' => $this->get('tag'), 'type' => 'language', 'client_id' => '', 'folder' => '')); if ($uid) { $update->delete($uid); } return $row->get('extension_id'); } /** * Custom update method * * @return boolean True on success, false on failure * * @since 11.1 */ public function update() { $xml = $this->parent->getManifest(); $this->manifest = $xml; $cname = $xml->attributes()->client; // Attempt to map the client to a base path $client = JApplicationHelper::getClientInfo($cname, true); if ($client === null || (empty($cname) && $cname !== 0)) { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_UNKNOWN_CLIENT_TYPE', $cname))); return false; } $basePath = $client->path; $clientId = $client->id; // Get the language name // Set the extensions name $name = (string) $this->manifest->name; $name = JFilterInput::getInstance()->clean($name, 'cmd'); $this->set('name', $name); // Get the Language tag [ISO tag, eg. en-GB] $tag = (string) $xml->tag; // Check if we found the tag - if we didn't, we may be trying to install from an older language package if (!$tag) { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::_('JLIB_INSTALLER_ERROR_NO_LANGUAGE_TAG'))); return false; } $this->set('tag', $tag); $folder = $tag; // Set the language installation path $this->parent->setPath('extension_site', $basePath . '/language/' . $this->get('tag')); // Do we have a meta file in the file list? In other words... is this a core language pack? if (count($xml->files->children())) { foreach ($xml->files->children() as $file) { if ((string) $file->attributes()->file == 'meta') { $this->_core = true; break; } } } // Either we are installing a core pack or a core pack must exist for the language we are installing. if (!$this->_core) { if (!JFile::exists($this->parent->getPath('extension_site') . '/' . $this->get('tag') . '.xml')) { $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_NO_CORE_LANGUAGE', $this->get('tag')))); return false; } } // Copy all the necessary files if ($this->parent->parseFiles($xml->files) === false) { // Install failed, rollback changes $this->parent->abort(); return false; } // Parse optional tags $this->parent->parseMedia($xml->media); // Copy all the necessary font files to the common pdf_fonts directory $this->parent->setPath('extension_site', $basePath . '/language/pdf_fonts'); $overwrite = $this->parent->setOverwrite(true); if ($this->parent->parseFiles($xml->fonts) === false) { // Install failed, rollback changes $this->parent->abort(); return false; } $this->parent->setOverwrite($overwrite); // Get the language description and set it as message $this->parent->set('message', (string) $xml->description); // Finalization and Cleanup Section // Clobber any possible pending updates $update = JTable::getInstance('update'); $uid = $update->find(array('element' => $this->get('tag'), 'type' => 'language', 'client_id' => $clientId)); if ($uid) { $update->delete($uid); } // Update an entry to the extension table $row = JTable::getInstance('extension'); $eid = $row->find(array('element' => strtolower($this->get('tag')), 'type' => 'language', 'client_id' => $clientId)); if ($eid) { $row->load($eid); } else { // set the defaults $row->set('folder', ''); // There is no folder for language $row->set('enabled', 1); $row->set('protected', 0); $row->set('access', 0); $row->set('client_id', $clientId); $row->set('params', $this->parent->getParams()); } $row->set('name', $this->get('name')); $row->set('type', 'language'); $row->set('element', $this->get('tag')); $row->set('manifest_cache', $this->parent->generateManifestCache()); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', $row->getError())); return false; } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight('update', $this); } $msg = ob_get_contents(); // append messages ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $row->get('extension_id'); } /** * Custom uninstall method * * @param string $eid The tag of the language to uninstall * * @return mixed Return value for uninstall method in component uninstall file * * @since 11.1 */ public function uninstall($eid) { // Load up the extension details $extension = JTable::getInstance('extension'); $extension->load($eid); // Grab a copy of the client details $client = JApplicationHelper::getClientInfo($extension->get('client_id')); // Check the element isn't blank to prevent nuking the languages directory...just in case $element = $extension->get('element'); if (empty($element)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_ELEMENT_EMPTY')); return false; } // Check that the language is not protected, Normally en-GB. $protected = $extension->get('protected'); if ($protected == 1) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_PROTECTED')); return false; } // Verify that it's not the default language for that client $params = JComponentHelper::getParams('com_languages'); if ($params->get($client->name) == $element) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_DEFAULT')); return false; } // Construct the path from the client, the language and the extension element name $path = $client->path . '/language/' . $element; // Get the package manifest object and remove media $this->parent->setPath('source', $path); // We do findManifest to avoid problem when uninstalling a list of extension: getManifest cache its manifest file $this->parent->findManifest(); $this->manifest = $this->parent->getManifest(); $this->parent->removeFiles($this->manifest->media); // Check it exists if (!JFolder::exists($path)) { // If the folder doesn't exist lets just nuke the row as well and presume the user killed it for us $extension->delete(); JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_PATH_EMPTY')); return false; } if (!JFolder::delete($path)) { // If deleting failed we'll leave the extension entry in tact just in case JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_DIRECTORY')); return false; } // Remove the extension table entry $extension->delete(); // Setting the language of users which have this language as the default language $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->from('#__users'); $query->select('*'); $db->setQuery($query); $users = $db->loadObjectList(); if ($client->name == 'administrator') { $param_name = 'admin_language'; } else { $param_name = 'language'; } $count = 0; foreach ($users as $user) { $registry = new JRegistry; $registry->loadString($user->params); if ($registry->get($param_name) == $element) { $registry->set($param_name, ''); $query = $db->getQuery(true); $query->update('#__users'); $query->set('params=' . $db->quote($registry)); $query->where('id=' . (int) $user->id); $db->setQuery($query); $db->execute(); $count = $count + 1; } } if (!empty($count)) { JError::raiseNotice(500, JText::plural('JLIB_INSTALLER_NOTICE_LANG_RESET_USERS', $count)); } // All done! return true; } /** * Custom discover method * Finds language files * * @return boolean True on success * * @since 11.1 */ public function discover() { $results = array(); $site_languages = JFolder::folders(JPATH_SITE . '/language'); $admin_languages = JFolder::folders(JPATH_ADMINISTRATOR . '/language'); foreach ($site_languages as $language) { if (file_exists(JPATH_SITE . '/language/' . $language . '/' . $language . '.xml')) { $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_SITE . '/language/' . $language . '/' . $language . '.xml'); $extension = JTable::getInstance('extension'); $extension->set('type', 'language'); $extension->set('client_id', 0); $extension->set('element', $language); $extension->set('name', $language); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } } foreach ($admin_languages as $language) { if (file_exists(JPATH_ADMINISTRATOR . '/language/' . $language . '/' . $language . '.xml')) { $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_ADMINISTRATOR . '/language/' . $language . '/' . $language . '.xml'); $extension = JTable::getInstance('extension'); $extension->set('type', 'language'); $extension->set('client_id', 1); $extension->set('element', $language); $extension->set('name', $language); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } } return $results; } /** * Custom discover install method * Basically updates the manifest cache and leaves everything alone * * @return integer The extension id * * @since 11.1 */ public function discover_install() { // Need to find to find where the XML file is since we don't store this normally $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $short_element = $this->parent->extension->element; $manifestPath = $client->path . '/language/' . $short_element . '/' . $short_element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $this->parent->setPath('source', $client->path . '/language/' . $short_element); $this->parent->setPath('extension_root', $this->parent->getPath('source')); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->state = 0; $this->parent->extension->name = $manifest_details['name']; $this->parent->extension->enabled = 1; //$this->parent->extension->params = $this->parent->getParams(); try { $this->parent->extension->store(); } catch (JException $e) { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_LANG_DISCOVER_STORE_DETAILS')); return false; } return $this->parent->extension->get('extension_id'); } /** * Refreshes the extension table cache * * @return boolean result of operation, true if updated, false on failure * * @since 11.1 */ public function refreshManifestCache() { $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $manifestPath = $client->path . '/language/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; if ($this->parent->extension->store()) { return true; } else { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE')); return false; } } } module.php000066600000062441151372702060006560 0ustar00parent->getPath('source'); if (!$source) { $this->parent ->setPath( 'source', ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $this->parent->extension->element ); } $this->manifest = $this->parent->getManifest(); if ($this->manifest->files) { $element = $this->manifest->files; $extension = ''; if (count($element->children())) { foreach ($element->children() as $file) { if ((string) $file->attributes()->module) { $extension = strtolower((string) $file->attributes()->module); break; } } } if ($extension) { $lang = JFactory::getLanguage(); $source = $path ? $path : ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $extension; $folder = (string) $element->attributes()->folder; if ($folder && file_exists("$path/$folder")) { $source = "$path/$folder"; } $client = (string) $this->manifest->attributes()->client; $lang->load($extension . '.sys', $source, null, false, true) || $lang->load($extension . '.sys', constant('JPATH_' . strtoupper($client)), null, false, true); } } } /** * Custom install method * * @return boolean True on success * * @since 11.1 */ public function install() { // Get a database connector object $db = $this->parent->getDbo(); // Get the extension manifest object $this->manifest = $this->parent->getManifest(); // Manifest Document Setup Section // Set the extensions name $name = (string) $this->manifest->name; $name = JFilterInput::getInstance()->clean($name, 'string'); $this->set('name', $name); // Get the component description $description = (string) $this->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } // Target Application Section // Get the target application if ($cname = (string) $this->manifest->attributes()->client) { // Attempt to map the client to a base path $client = JApplicationHelper::getClientInfo($cname, true); if ($client === false) { $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_UNKNOWN_CLIENT', JText::_('JLIB_INSTALLER_' . $this->route), $client->name)); return false; } $basePath = $client->path; $clientId = $client->id; } else { // No client attribute was found so we assume the site as the client $cname = 'site'; $basePath = JPATH_SITE; $clientId = 0; } // Set the installation path $element = ''; if (count($this->manifest->files->children())) { foreach ($this->manifest->files->children() as $file) { if ((string) $file->attributes()->module) { $element = (string) $file->attributes()->module; $this->set('element', $element); break; } } } if (!empty($element)) { $this->parent->setPath('extension_root', $basePath . '/modules/' . $element); } else { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_NOFILE', JText::_('JLIB_INSTALLER_' . $this->route))); return false; } // Check to see if a module by the same name is already installed // If it is, then update the table because if the files aren't there // we can assume that it was (badly) uninstalled // If it isn't, add an entry to extensions $query = $db->getQuery(true); $query->select($query->qn('extension_id'))->from($query->qn('#__extensions')); $query->where($query->qn('element') . ' = ' . $query->q($element))->where($query->qn('client_id') . ' = ' . (int) $clientId); $db->setQuery($query); try { $db->execute(); } catch (JException $e) { // Install failed, roll back changes $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))); return false; } $id = $db->loadResult(); // If the module directory already exists, then we will assume that the // module is already installed or another module is using that // directory. // Check that this is either an issue where its not overwriting or it is // set to upgrade anyway if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite() || $this->parent->isUpgrade())) { // Look for an update function or update tag $updateElement = $this->manifest->update; // Upgrade manually set or // Update function available or // Update tag detected if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) || $updateElement) { // Force this one $this->parent->setOverwrite(true); $this->parent->setUpgrade(true); if ($id) { // If there is a matching extension mark this as an update; semantics really $this->route = 'Update'; } } elseif (!$this->parent->isOverwrite()) { // Overwrite is set // We didn't have overwrite set, find an update function or find an update tag so lets call it safe $this->parent ->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT_MOD_INSTALL_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route), $this->parent->getPath('extension_root') ) ); return false; } } // Installer Trigger Loading // If there is an manifest class file, let's load it; we'll copy it later (don't have destination yet) $this->scriptElement = $this->manifest->scriptfile; $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // Set the class name $classname = $element . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance. $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later. $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file. } } // Run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight($this->route, $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Create msg object; first use here $msg = ob_get_contents(); ob_end_clean(); // Filesystem Processing Section // If the module directory does not exist, lets create it $created = false; if (!file_exists($this->parent->getPath('extension_root'))) { if (!$created = JFolder::create($this->parent->getPath('extension_root'))) { $this->parent ->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT_MOD_INSTALL_CREATE_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route), $this->parent->getPath('extension_root') ) ); return false; } } // Since we created the module directory and will want to remove it if // we have to roll back the installation, let's add it to the // installation step stack if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root'))); } // Copy all necessary files if ($this->parent->parseFiles($this->manifest->files, -1) === false) { // Install failed, roll back changes $this->parent->abort(); return false; } // If there is a manifest script, let's copy it. if ($this->get('manifest_script')) { $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script'); if (!file_exists($path['dest']) || $this->parent->isOverwrite()) { if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_MANIFEST')); return false; } } } // Parse optional tags $this->parent->parseMedia($this->manifest->media, $clientId); $this->parent->parseLanguages($this->manifest->languages, $clientId); // Parse deprecated tags $this->parent->parseFiles($this->manifest->images, -1); // Database Processing Section $row = JTable::getInstance('extension'); // Was there a module already installed with the same name? if ($id) { // Load the entry and update the manifest_cache $row->load($id); $row->name = $this->get('name'); // update name $row->manifest_cache = $this->parent->generateManifestCache(); // update manifest if (!$row->store()) { // Install failed, roll back changes $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))); return false; } } else { $row->set('name', $this->get('name')); $row->set('type', 'module'); $row->set('element', $this->get('element')); $row->set('folder', ''); // There is no folder for modules $row->set('enabled', 1); $row->set('protected', 0); $row->set('access', $clientId == 1 ? 2 : 0); $row->set('client_id', $clientId); $row->set('params', $this->parent->getParams()); $row->set('custom_data', ''); // custom data $row->set('manifest_cache', $this->parent->generateManifestCache()); if (!$row->store()) { // Install failed, roll back changes $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))); return false; } // Set the insert id $row->extension_id = $db->insertid(); // Since we have created a module item, we add it to the installation step stack // so that if we have to rollback the changes we can undo it. $this->parent->pushStep(array('type' => 'extension', 'extension_id' => $row->extension_id)); // Create unpublished module in jos_modules $name = preg_replace('#[\*?]#', '', JText::_($this->get('name'))); $module = JTable::getInstance('module'); $module->set('title', $name); $module->set('module', $this->get('element')); $module->set('access', '1'); $module->set('showtitle', '1'); $module->set('client_id', $clientId); $module->set('language', '*'); $module->store(); } // Let's run the queries for the module // If Joomla 1.5 compatible, with discrete sql files, execute appropriate // file for utf-8 support or non-utf-8 support // Try for Joomla 1.5 type queries // Second argument is the utf compatible version attribute if (strtolower($this->route) == 'install') { $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); if ($utfresult === false) { // Install failed, rollback changes $this->parent ->abort( JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) ); return false; } // Set the schema version to be the latest update version if ($this->manifest->update) { $this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id); } } elseif (strtolower($this->route) == 'update') { if ($this->manifest->update) { $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id); if ($result === false) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_UPDATE_SQL_ERROR', $db->stderr(true))); return false; } } } // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route)) { if ($this->parent->manifestClass->{$this->route}($this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Append messages $msg .= ob_get_contents(); ob_end_clean(); // Finalization and Cleanup Section // Lastly, we will copy the manifest file to its appropriate place. if (!$this->parent->copyManifest(-1)) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_COPY_SETUP')); return false; } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight($this->route, $this); } // Append messages $msg .= ob_get_contents(); ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $row->get('extension_id'); } /** * Custom update method * * This is really a shell for the install system * * @return boolean True on success. * * @since 11.1 */ public function update() { // Set the overwrite setting $this->parent->setOverwrite(true); $this->parent->setUpgrade(true); // Set the route for the install $this->route = 'Update'; // Go to install which handles updates properly return $this->install(); } /** * Custom discover method * * @return array JExtension list of extensions available * * @since 11.1 */ public function discover() { $results = array(); $site_list = JFolder::folders(JPATH_SITE . '/modules'); $admin_list = JFolder::folders(JPATH_ADMINISTRATOR . '/modules'); $site_info = JApplicationHelper::getClientInfo('site', true); $admin_info = JApplicationHelper::getClientInfo('administrator', true); foreach ($site_list as $module) { $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_SITE . "/modules/$module/$module.xml"); $extension = JTable::getInstance('extension'); $extension->set('type', 'module'); $extension->set('client_id', $site_info->id); $extension->set('element', $module); $extension->set('name', $module); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = clone $extension; } foreach ($admin_list as $module) { $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_ADMINISTRATOR . "/modules/$module/$module.xml"); $extension = JTable::getInstance('extension'); $extension->set('type', 'module'); $extension->set('client_id', $admin_info->id); $extension->set('element', $module); $extension->set('name', $module); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = clone $extension; } return $results; } /** * Custom discover_install method * * @return mixed Extension ID on success, boolean false on failure * * @since 11.1 */ public function discover_install() { // Modules are like templates, and are one of the easiest // If its not in the extensions table we just add it $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $manifestPath = $client->path . '/modules/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $description = (string) $this->parent->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); // TODO: Re-evaluate this; should we run installation triggers? postflight perhaps? $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->state = 0; $this->parent->extension->name = $manifest_details['name']; $this->parent->extension->enabled = 1; $this->parent->extension->params = $this->parent->getParams(); if ($this->parent->extension->store()) { return $this->parent->extension->get('extension_id'); } else { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_MOD_DISCOVER_STORE_DETAILS')); return false; } } /** * Refreshes the extension table cache * * @return boolean Result of operation, true if updated, false on failure. * * @since 11.1 */ public function refreshManifestCache() { $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $manifestPath = $client->path . '/modules/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; if ($this->parent->extension->store()) { return true; } else { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE')); return false; } } /** * Custom uninstall method * * @param integer $id The id of the module to uninstall * * @return boolean True on success * * @since 11.1 */ public function uninstall($id) { // Initialise variables. $row = null; $retval = true; $db = $this->parent->getDbo(); // First order of business will be to load the module object table from the database. // This should give us the necessary information to proceed. $row = JTable::getInstance('extension'); if (!$row->load((int) $id) || !strlen($row->element)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_ERRORUNKOWNEXTENSION')); return false; } // Is the module we are trying to uninstall a core one? // Because that is not a good idea... if ($row->protected) { JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_WARNCOREMODULE', $row->name)); return false; } // Get the extension root path $element = $row->element; $client = JApplicationHelper::getClientInfo($row->client_id); if ($client === false) { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_UNKNOWN_CLIENT', $row->client_id)); return false; } $this->parent->setPath('extension_root', $client->path . '/modules/' . $element); $this->parent->setPath('source', $this->parent->getPath('extension_root')); // Get the package manifest objecct // We do findManifest to avoid problem when uninstalling a list of extensions: getManifest cache its manifest file. $this->parent->findManifest(); $this->manifest = $this->parent->getManifest(); // Attempt to load the language file; might have uninstall strings $this->loadLanguage(($row->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $element); // If there is an manifest class file, let's load it $this->scriptElement = $this->manifest->scriptfile; $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // Set the class name $classname = $element . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } ob_start(); ob_implicit_flush(false); // Run uninstall if possible if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) { $this->parent->manifestClass->uninstall($this); } $msg = ob_get_contents(); ob_end_clean(); if (!($this->manifest instanceof SimpleXMLElement)) { // Make sure we delete the folders JFolder::delete($this->parent->getPath('extension_root')); JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_INVALID_NOTFOUND_MANIFEST')); return false; } /* * Let's run the uninstall queries for the component * If Joomla 1.5 compatible, with discreet sql files - execute appropriate * file for utf-8 support or non-utf support */ // Try for Joomla 1.5 type queries // Second argument is the utf compatible version attribute $utfresult = $this->parent->parseSQLFiles($this->manifest->uninstall->sql); if ($utfresult === false) { // Install failed, rollback changes JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_SQL_ERROR', $db->stderr(true))); $retval = false; } // Remove the schema version $query = $db->getQuery(true); $query->delete()->from('#__schemas')->where('extension_id = ' . $row->extension_id); $db->setQuery($query); $db->execute(); // Remove other files $this->parent->removeFiles($this->manifest->media); $this->parent->removeFiles($this->manifest->languages, $row->client_id); // Let's delete all the module copies for the type we are uninstalling $query = $db->getQuery(true); $query->select($query->qn('id'))->from($query->qn('#__modules')); $query->where($query->qn('module') . ' = ' . $query->q($row->element)); $query->where($query->qn('client_id') . ' = ' . (int) $row->client_id); $db->setQuery($query); try { $modules = $db->loadColumn(); } catch (JException $e) { $modules = array(); } // Do we have any module copies? if (count($modules)) { // Ensure the list is sane JArrayHelper::toInteger($modules); $modID = implode(',', $modules); // Wipe out any items assigned to menus $query = 'DELETE' . ' FROM #__modules_menu' . ' WHERE moduleid IN (' . $modID . ')'; $db->setQuery($query); try { $db->execute(); } catch (JException $e) { JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION', $db->stderr(true))); $retval = false; } // Wipe out any instances in the modules table $query = 'DELETE' . ' FROM #__modules' . ' WHERE id IN (' . $modID . ')'; $db->setQuery($query); try { $db->execute(); } catch (JException $e) { JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION', $db->stderr(true))); $retval = false; } } // Now we will no longer need the module object, so let's delete it and free up memory $row->delete($row->extension_id); $query = 'DELETE FROM #__modules WHERE module = ' . $db->Quote($row->element) . ' AND client_id = ' . $row->client_id; $db->setQuery($query); try { // Clean up any other ones that might exist as well $db->execute(); } catch (JException $e) { // Ignore the error... } unset($row); // Remove the installation folder if (!JFolder::delete($this->parent->getPath('extension_root'))) { // JFolder should raise an error $retval = false; } return $retval; } /** * Custom rollback method * - Roll back the menu item * * @param array $arg Installation step to rollback * * @return boolean True on success * * @since 11.1 */ protected function _rollback_menu($arg) { // Get database connector object $db = $this->parent->getDbo(); // Remove the entry from the #__modules_menu table $query = 'DELETE' . ' FROM #__modules_menu' . ' WHERE moduleid=' . (int) $arg['id']; $db->setQuery($query); try { return $db->execute(); } catch (JException $e) { return false; } } /** * Custom rollback method * - Roll back the module item * * @param array $arg Installation step to rollback * * @return boolean True on success * * @since 11.1 */ protected function _rollback_module($arg) { // Get database connector object $db = $this->parent->getDbo(); // Remove the entry from the #__modules table $query = 'DELETE' . ' FROM #__modules' . ' WHERE id=' . (int) $arg['id']; $db->setQuery($query); try { return $db->execute(); } catch (JException $e) { return false; } } } library.php000066600000031073151372702060006734 0ustar00parent->getPath('source'); if (!$source) { $this->parent->setPath('source', JPATH_PLATFORM . '/' . $this->parent->extension->element); } $this->manifest = $this->parent->getManifest(); $extension = 'lib_' . strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); $name = strtolower((string) $this->manifest->libraryname); $lang = JFactory::getLanguage(); $source = $path ? $path : JPATH_PLATFORM . "/$name"; $lang->load($extension . '.sys', $source, null, false, true) || $lang->load($extension . '.sys', JPATH_SITE, null, false, true); } /** * Custom install method * * @return boolean True on success * * @since 11.1 */ public function install() { // Get the extension manifest object $this->manifest = $this->parent->getManifest(); // Manifest Document Setup Section // Set the extensions name $name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'string'); $element = str_replace('.xml', '', basename($this->parent->getPath('manifest'))); $this->set('name', $name); $this->set('element', $element); $db = $this->parent->getDbo(); $query = $db->getQuery(true); $query->select($db->quoteName('extension_id')); $query->from($db->quoteName('#__extensions')); $query->where($db->quoteName('type') . ' = ' . $db->quote('library')); $query->where($db->quoteName('element') . ' = ' . $db->quote($element)); $db->setQuery($query); $result = $db->loadResult(); if ($result) { // Already installed, can we upgrade? if ($this->parent->isOverwrite() || $this->parent->isUpgrade()) { // We can upgrade, so uninstall the old one $installer = new JInstaller; // we don't want to compromise this instance! $installer->uninstall('library', $result); } else { // Abort the install, no upgrade possible $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_ALREADY_INSTALLED')); return false; } } // Get the libraries description $description = (string) $this->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } // Set the installation path $group = (string) $this->manifest->libraryname; if (!$group) { $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_NOFILE')); return false; } else { $this->parent->setPath('extension_root', JPATH_PLATFORM . '/' . implode(DIRECTORY_SEPARATOR, explode('/', $group))); } // Filesystem Processing Section // If the plugin directory does not exist, let's create it $created = false; if (!file_exists($this->parent->getPath('extension_root'))) { if (!$created = JFolder::create($this->parent->getPath('extension_root'))) { $this->parent->abort( JText::sprintf('JLIB_INSTALLER_ABORT_LIB_INSTALL_FAILED_TO_CREATE_DIRECTORY', $this->parent->getPath('extension_root')) ); return false; } } // If we created the plugin directory and will want to remove it if we // have to roll back the installation, let's add it to the installation // step stack if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root'))); } // Copy all necessary files if ($this->parent->parseFiles($this->manifest->files, -1) === false) { // Install failed, roll back changes $this->parent->abort(); return false; } // Parse optional tags $this->parent->parseLanguages($this->manifest->languages); $this->parent->parseMedia($this->manifest->media); // Extension Registration $row = JTable::getInstance('extension'); $row->name = $this->get('name'); $row->type = 'library'; $row->element = $this->get('element'); $row->folder = ''; // There is no folder for modules $row->enabled = 1; $row->protected = 0; $row->access = 1; $row->client_id = 0; $row->params = $this->parent->getParams(); $row->custom_data = ''; // custom data $row->manifest_cache = $this->parent->generateManifestCache(); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_LIB_INSTALL_ROLLBACK', $db->stderr(true))); return false; } // Finalization and Cleanup Section // Lastly, we will copy the manifest file to its appropriate place. $manifest = array(); $manifest['src'] = $this->parent->getPath('manifest'); $manifest['dest'] = JPATH_MANIFESTS . '/libraries/' . basename($this->parent->getPath('manifest')); if (!$this->parent->copyFiles(array($manifest), true)) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_COPY_SETUP')); return false; } return $row->get('extension_id'); } /** * Custom update method * * @return boolean True on success * * @since 11.1 */ public function update() { // Since this is just files, an update removes old files // Get the extension manifest object $this->manifest = $this->parent->getManifest(); // Manifest Document Setup Section // Set the extensions name $name = (string) $this->manifest->name; $name = JFilterInput::getInstance()->clean($name, 'string'); $element = str_replace('.xml', '', basename($this->parent->getPath('manifest'))); $this->set('name', $name); $this->set('element', $element); $installer = new JInstaller; // we don't want to compromise this instance! $db = $this->parent->getDbo(); $query = $db->getQuery(true); $query->select($db->quoteName('extension_id')); $query->from($db->quoteName('#__extensions')); $query->where($db->quoteName('type') . ' = ' . $db->quote('library')); $query->where($db->quoteName('element') . ' = ' . $db->quote($element)); $db->setQuery($query); $result = $db->loadResult(); if ($result) { // Already installed, which would make sense $installer->uninstall('library', $result); } // Now create the new files return $this->install(); } /** * Custom uninstall method * * @param string $id The id of the library to uninstall. * * @return boolean True on success * * @since 11.1 */ public function uninstall($id) { // Initialise variables. $retval = true; // First order of business will be to load the module object table from the database. // This should give us the necessary information to proceed. $row = JTable::getInstance('extension'); if (!$row->load((int) $id) || !strlen($row->element)) { JError::raiseWarning(100, JText::_('ERRORUNKOWNEXTENSION')); return false; } // Is the library we are trying to uninstall a core one? // Because that is not a good idea... if ($row->protected) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_WARNCORELIBRARY')); return false; } $manifestFile = JPATH_MANIFESTS . '/libraries/' . $row->element . '.xml'; // Because libraries may not have their own folders we cannot use the standard method of finding an installation manifest if (file_exists($manifestFile)) { $manifest = new JLibraryManifest($manifestFile); // Set the plugin root path $this->parent->setPath('extension_root', JPATH_PLATFORM . '/' . $manifest->libraryname); $xml = JFactory::getXML($manifestFile); // If we cannot load the XML file return null if (!$xml) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_LOAD_MANIFEST')); return false; } // Check for a valid XML root tag. // TODO: Remove backwards compatibility in a future version // Should be 'extension', but for backward compatibility we will accept 'install'. if ($xml->getName() != 'install' && $xml->getName() != 'extension') { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_INVALID_MANIFEST')); return false; } $this->parent->removeFiles($xml->files, -1); JFile::delete($manifestFile); } else { // Remove this row entry since its invalid $row->delete($row->extension_id); unset($row); JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_INVALID_NOTFOUND_MANIFEST')); return false; } // TODO: Change this so it walked up the path backwards so we clobber multiple empties // If the folder is empty, let's delete it if (JFolder::exists($this->parent->getPath('extension_root'))) { if (is_dir($this->parent->getPath('extension_root'))) { $files = JFolder::files($this->parent->getPath('extension_root')); if (!count($files)) { JFolder::delete($this->parent->getPath('extension_root')); } } } $this->parent->removeFiles($xml->media); $this->parent->removeFiles($xml->languages); $row->delete($row->extension_id); unset($row); return $retval; } /** * Custom discover method * * @return array JExtension list of extensions available * * @since 11.1 */ public function discover() { $results = array(); $file_list = JFolder::files(JPATH_MANIFESTS . '/libraries', '\.xml$'); foreach ($file_list as $file) { $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_MANIFESTS . '/libraries/' . $file); $file = JFile::stripExt($file); $extension = JTable::getInstance('extension'); $extension->set('type', 'library'); $extension->set('client_id', 0); $extension->set('element', $file); $extension->set('name', $file); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } return $results; } /** * Custom discover_install method * * @return boolean True on success * * @since 11.1 */ public function discover_install() { /* Libraries are a strange beast; they are actually references to files * There are two parts to a library which are disjunct in their locations * 1) The manifest file (stored in /JPATH_MANIFESTS/libraries) * 2) The actual files (stored in /JPATH_PLATFORM/libraryname) * Thus installation of a library is the process of dumping files * in two different places. As such it is impossible to perform * any operation beyond mere registration of a library under the presumption * that the files exist in the appropriate location so that come uninstall * time they can be adequately removed. */ $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->state = 0; $this->parent->extension->name = $manifest_details['name']; $this->parent->extension->enabled = 1; $this->parent->extension->params = $this->parent->getParams(); if ($this->parent->extension->store()) { return true; } else { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_LIB_DISCOVER_STORE_DETAILS')); return false; } } /** * Refreshes the extension table cache * * @return boolean Result of operation, true if updated, false on failure * * @since 11.1 */ public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; try { return $this->parent->extension->store(); } catch (JException $e) { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_LIB_REFRESH_MANIFEST_CACHE')); return false; } } } plugin.php000066600000061064151372702060006571 0ustar00parent->getPath('source'); if (!$source) { $this->parent->setPath('source', JPATH_PLUGINS . '/' . $this->parent->extension->folder . '/' . $this->parent->extension->element); } $this->manifest = $this->parent->getManifest(); $element = $this->manifest->files; if ($element) { $group = strtolower((string) $this->manifest->attributes()->group); $name = ''; if (count($element->children())) { foreach ($element->children() as $file) { if ((string) $file->attributes()->plugin) { $name = strtolower((string) $file->attributes()->plugin); break; } } } if ($name) { $extension = "plg_${group}_${name}"; $lang = JFactory::getLanguage(); $source = $path ? $path : JPATH_PLUGINS . "/$group/$name"; $folder = (string) $element->attributes()->folder; if ($folder && file_exists("$path/$folder")) { $source = "$path/$folder"; } $lang->load($extension . '.sys', $source, null, false, true) || $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, null, false, true); } } } /** * Custom install method * * @return boolean True on success * * @since 11.1 */ public function install() { // Get a database connector object $db = $this->parent->getDbo(); // Get the extension manifest object $this->manifest = $this->parent->getManifest(); $xml = $this->manifest; // Manifest Document Setup Section // Set the extension name $name = (string) $xml->name; $name = JFilterInput::getInstance()->clean($name, 'string'); $this->set('name', $name); // Get the component description $description = (string) $xml->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } /* * Backward Compatibility * @todo Deprecate in future version */ $type = (string) $xml->attributes()->type; // Set the installation path if (count($xml->files->children())) { foreach ($xml->files->children() as $file) { if ((string) $file->attributes()->$type) { $element = (string) $file->attributes()->$type; break; } } } $group = (string) $xml->attributes()->group; if (!empty($element) && !empty($group)) { $this->parent->setPath('extension_root', JPATH_PLUGINS . '/' . $group . '/' . $element); } else { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_NO_FILE', JText::_('JLIB_INSTALLER_' . $this->route))); return false; } // Check if we should enable overwrite settings // Check to see if a plugin by the same name is already installed. $query = $db->getQuery(true); $query->select($query->qn('extension_id'))->from($query->qn('#__extensions')); $query->where($query->qn('folder') . ' = ' . $query->q($group)); $query->where($query->qn('element') . ' = ' . $query->q($element)); $db->setQuery($query); try { $db->execute(); } catch (JException $e) { // Install failed, roll back changes $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))); return false; } $id = $db->loadResult(); // If it's on the fs... if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite() || $this->parent->isUpgrade())) { $updateElement = $xml->update; // Upgrade manually set or // Update function available or // Update tag detected if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) || $updateElement) { // Force this one $this->parent->setOverwrite(true); $this->parent->setUpgrade(true); if ($id) { // If there is a matching extension mark this as an update; semantics really $this->route = 'update'; } } elseif (!$this->parent->isOverwrite()) { // Overwrite is set // We didn't have overwrite set, find an update function or find an update tag so lets call it safe $this->parent ->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT_PLG_INSTALL_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route), $this->parent->getPath('extension_root') ) ); return false; } } // Installer Trigger Loading // If there is an manifest class file, let's load it; we'll copy it later (don't have destination yet). if ((string) $xml->scriptfile) { $manifestScript = (string) $xml->scriptfile; $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // If a dash is present in the group name, remove it $groupClass = str_replace('-', '', $group); // Set the class name $classname = 'plg' . $groupClass . $element . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } // Run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight($this->route, $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg = ob_get_contents(); // create msg object; first use here ob_end_clean(); // Filesystem Processing Section // If the plugin directory does not exist, lets create it $created = false; if (!file_exists($this->parent->getPath('extension_root'))) { if (!$created = JFolder::create($this->parent->getPath('extension_root'))) { $this->parent ->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT_PLG_INSTALL_CREATE_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route), $this->parent->getPath('extension_root') ) ); return false; } } // If we're updating at this point when there is always going to be an extension_root find the old XML files if ($this->route == 'update') { // Hunt for the original XML file $old_manifest = null; $tmpInstaller = new JInstaller; // create a new installer because findManifest sets stuff; side effects! // Look in the extension root $tmpInstaller->setPath('source', $this->parent->getPath('extension_root')); if ($tmpInstaller->findManifest()) { $old_manifest = $tmpInstaller->getManifest(); $this->oldFiles = $old_manifest->files; } } // If we created the plugin directory and will want to remove it if we // have to roll back the installation, let's add it to the installation // step stack if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root'))); } // Copy all necessary files if ($this->parent->parseFiles($xml->files, -1, $this->oldFiles) === false) { // Install failed, roll back changes $this->parent->abort(); return false; } // Parse optional tags -- media and language files for plugins go in admin app $this->parent->parseMedia($xml->media, 1); $this->parent->parseLanguages($xml->languages, 1); // If there is a manifest script, lets copy it. if ($this->get('manifest_script')) { $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script'); if (!file_exists($path['dest'])) { if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_MANIFEST', JText::_('JLIB_INSTALLER_' . $this->route))); return false; } } } // Database Processing Section $row = JTable::getInstance('extension'); // Was there a plugin with the same name already installed? if ($id) { if (!$this->parent->isOverwrite()) { // Install failed, roll back changes $this->parent ->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT_PLG_INSTALL_ALLREADY_EXISTS', JText::_('JLIB_INSTALLER_' . $this->route), $this->get('name') ) ); return false; } $row->load($id); $row->name = $this->get('name'); $row->manifest_cache = $this->parent->generateManifestCache(); $row->store(); // update the manifest cache and name } else { // Store in the extensions table (1.6) $row->name = $this->get('name'); $row->type = 'plugin'; $row->ordering = 0; $row->element = $element; $row->folder = $group; $row->enabled = 0; $row->protected = 0; $row->access = 1; $row->client_id = 0; $row->params = $this->parent->getParams(); // Custom data $row->custom_data = ''; // System data $row->system_data = ''; $row->manifest_cache = $this->parent->generateManifestCache(); // Editor plugins are published by default if ($group == 'editors') { $row->enabled = 1; } if (!$row->store()) { // Install failed, roll back changes $this->parent ->abort( JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) ); return false; } // Since we have created a plugin item, we add it to the installation step stack // so that if we have to rollback the changes we can undo it. $this->parent->pushStep(array('type' => 'extension', 'id' => $row->extension_id)); $id = $row->extension_id; } // Let's run the queries for the module // If Joomla 1.5 compatible, with discreet sql files - execute appropriate // file for utf-8 support or non-utf-8 support // Try for Joomla 1.5 type queries // Second argument is the utf compatible version attribute if (strtolower($this->route) == 'install') { $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); if ($utfresult === false) { // Install failed, rollback changes $this->parent ->abort( JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) ); return false; } // Set the schema version to be the latest update version if ($this->manifest->update) { $this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id); } } elseif (strtolower($this->route) == 'update') { if ($this->manifest->update) { $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id); if ($result === false) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_UPDATE_SQL_ERROR', $db->stderr(true))); return false; } } } // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route)) { if ($this->parent->manifestClass->{$this->route}($this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Append messages $msg .= ob_get_contents(); ob_end_clean(); // Finalization and Cleanup Section // Lastly, we will copy the manifest file to its appropriate place. if (!$this->parent->copyManifest(-1)) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_COPY_SETUP', JText::_('JLIB_INSTALLER_' . $this->route))); return false; } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight($this->route, $this); } // Append messages $msg .= ob_get_contents(); ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $id; } /** * Custom update method * * @return boolean True on success * * @since 11.1 */ public function update() { // Set the overwrite setting $this->parent->setOverwrite(true); $this->parent->setUpgrade(true); // Set the route for the install $this->route = 'update'; // Go to install which handles updates properly return $this->install(); } /** * Custom uninstall method * * @param integer $id The id of the plugin to uninstall * * @return boolean True on success * * @since 11.1 */ public function uninstall($id) { $this->route = 'uninstall'; // Initialise variables. $row = null; $retval = true; $db = $this->parent->getDbo(); // First order of business will be to load the plugin object table from the database. // This should give us the necessary information to proceed. $row = JTable::getInstance('extension'); if (!$row->load((int) $id)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_ERRORUNKOWNEXTENSION')); return false; } // Is the plugin we are trying to uninstall a core one? // Because that is not a good idea... if ($row->protected) { JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_WARNCOREPLUGIN', $row->name)); return false; } // Get the plugin folder so we can properly build the plugin path if (trim($row->folder) == '') { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_FOLDER_FIELD_EMPTY')); return false; } // Set the plugin root path if (is_dir(JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element)) { // Use 1.6 plugins $this->parent->setPath('extension_root', JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element); } else { // Use Legacy 1.5 plugins $this->parent->setPath('extension_root', JPATH_PLUGINS . '/' . $row->folder); } // Because 1.5 plugins don't have their own folders we cannot use the standard method of finding an installation manifest // Since 1.6 they do, however until we move to 1.7 and remove 1.6 legacy we still need to use this method. // When we get there it'll be something like "$this->parent->findManifest();$manifest = $this->parent->getManifest();" $manifestFile = $this->parent->getPath('extension_root') . '/' . $row->element . '.xml'; if (!file_exists($manifestFile)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_INVALID_NOTFOUND_MANIFEST')); return false; } $xml = JFactory::getXML($manifestFile); $this->manifest = $xml; // If we cannot load the XML file return null if (!$xml) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_LOAD_MANIFEST')); return false; } /* * Check for a valid XML root tag. * @todo: Remove backwards compatibility in a future version * Should be 'extension', but for backward compatibility we will accept 'install'. */ if ($xml->getName() != 'install' && $xml->getName() != 'extension') { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_INVALID_MANIFEST')); return false; } // Attempt to load the language file; might have uninstall strings $this->parent->setPath('source', JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element); $this->loadLanguage(JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element); // Installer Trigger Loading // If there is an manifest class file, let's load it; we'll copy it later (don't have dest yet) $manifestScript = (string) $xml->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // If a dash is present in the folder, remove it $folderClass = str_replace('-', '', $row->folder); // Set the class name $classname = 'plg' . $folderClass . $row->element . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } // Run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight($this->route, $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } // Create msg object; first use here $msg = ob_get_contents(); ob_end_clean(); // Let's run the queries for the module // If Joomla 1.5 compatible, with discreet sql files - execute appropriate // file for utf-8 support or non-utf-8 support // Try for Joomla 1.5 type queries // Second argument is the utf compatible version attribute $utfresult = $this->parent->parseSQLFiles($xml->{strtolower($this->route)}->sql); if ($utfresult === false) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_UNINSTALL_SQL_ERROR', $db->stderr(true))); return false; } // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) { $this->parent->manifestClass->uninstall($this); } // Append messages $msg = ob_get_contents(); ob_end_clean(); // Remove the plugin files $this->parent->removeFiles($xml->images, -1); $this->parent->removeFiles($xml->files, -1); JFile::delete($manifestFile); // Remove all media and languages as well $this->parent->removeFiles($xml->media); $this->parent->removeFiles($xml->languages, 1); // Remove the schema version $query = $db->getQuery(true); $query->delete()->from('#__schemas')->where('extension_id = ' . $row->extension_id); $db->setQuery($query); $db->execute(); // Now we will no longer need the plugin object, so let's delete it $row->delete($row->extension_id); unset($row); // If the folder is empty, let's delete it $files = JFolder::files($this->parent->getPath('extension_root')); JFolder::delete($this->parent->getPath('extension_root')); if ($msg) { $this->parent->set('extension_message', $msg); } return $retval; } /** * Custom discover method * * @return array JExtension) list of extensions available * * @since 11.1 */ public function discover() { $results = array(); $folder_list = JFolder::folders(JPATH_SITE . '/plugins'); foreach ($folder_list as $folder) { $file_list = JFolder::files(JPATH_SITE . '/plugins/' . $folder, '\.xml$'); foreach ($file_list as $file) { $manifest_details = JApplicationHelper::parseXMLInstallFile(JPATH_SITE . '/plugins/' . $folder . '/' . $file); $file = JFile::stripExt($file); // Ignore example plugins if ($file == 'example') { continue; } $extension = JTable::getInstance('extension'); $extension->set('type', 'plugin'); $extension->set('client_id', 0); $extension->set('element', $file); $extension->set('folder', $folder); $extension->set('name', $file); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } $folder_list = JFolder::folders(JPATH_SITE . '/plugins/' . $folder); foreach ($folder_list as $plugin_folder) { $file_list = JFolder::files(JPATH_SITE . '/plugins/' . $folder . '/' . $plugin_folder, '\.xml$'); foreach ($file_list as $file) { $manifest_details = JApplicationHelper::parseXMLInstallFile( JPATH_SITE . '/plugins/' . $folder . '/' . $plugin_folder . '/' . $file ); $file = JFile::stripExt($file); if ($file == 'example') { continue; } // ignore example plugins $extension = JTable::getInstance('extension'); $extension->set('type', 'plugin'); $extension->set('client_id', 0); $extension->set('element', $file); $extension->set('folder', $folder); $extension->set('name', $file); $extension->set('state', -1); $extension->set('manifest_cache', json_encode($manifest_details)); $results[] = $extension; } } } return $results; } /** * Custom discover_install method. * * @return mixed * * @since 11.1 */ public function discover_install() { // Plugins use the extensions table as their primary store // Similar to modules and templates, rather easy // If it's not in the extensions table we just add it $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); if (is_dir($client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element)) { $manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml'; } else { $manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '.xml'; } $this->parent->manifest = $this->parent->isManifest($manifestPath); $description = (string) $this->parent->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($manifestPath); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->state = 0; $this->parent->extension->name = $manifest_details['name']; $this->parent->extension->enabled = ('editors' == $this->parent->extension->folder) ? 1 : 0; $this->parent->extension->params = $this->parent->getParams(); if ($this->parent->extension->store()) { return $this->parent->extension->get('extension_id'); } else { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PLG_DISCOVER_STORE_DETAILS')); return false; } } /** * Refreshes the extension table cache. * * @return boolean Result of operation, true if updated, false on failure. * * @since 11.1 */ public function refreshManifestCache() { // Plugins use the extensions table as their primary store // Similar to modules and templates, rather easy // If it's not in the extensions table we just add it $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); $manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; if ($this->parent->extension->store()) { return true; } else { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PLG_REFRESH_MANIFEST_CACHE')); return false; } } } file.php000066600000046525151372702060006217 0ustar00manifest = $this->parent->getManifest(); $extension = 'files_' . str_replace('files_', '', strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd'))); $lang = JFactory::getLanguage(); $source = $path; $lang->load($extension . '.sys', $source, null, false, true) || $lang->load($extension . '.sys', JPATH_SITE, null, false, true); } /** * Custom install method * * @return boolean True on success * * @since 11.1 */ public function install() { // Get the extension manifest object $this->manifest = $this->parent->getManifest(); // Manifest Document Setup Section // Set the extension's name $name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'string'); $this->set('name', $name); // Set element $manifestPath = JPath::clean($this->parent->getPath('manifest')); $element = preg_replace('/\.xml/', '', basename($manifestPath)); $this->set('element', $element); // Get the component description $description = (string) $this->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } //Check if the extension by the same name is already installed if ($this->extensionExistsInSystem($element)) { // Package with same name already exists if (!$this->parent->isOverwrite()) { // we're not overwriting so abort $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_SAME_NAME')); return false; } else { // swap to the update route $this->route = 'update'; } } // Set the file root path $this->parent->setPath('extension_root', JPATH_ROOT); /** * --------------------------------------------------------------------------------------------- * Installer Trigger Loading * --------------------------------------------------------------------------------------------- */ // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) $this->scriptElement = $this->manifest->scriptfile; $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // load the file include_once $manifestScriptFile; } // Set the class name $classname = $element . 'InstallerScript'; if (class_exists($classname)) { // create a new instance $this->parent->manifestClass = new $classname($this); // and set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } // run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight($this->route, $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg = ob_get_contents(); // create msg object; first use here ob_end_clean(); // Populate File and Folder List to copy $this->populateFilesAndFolderList(); // Filesystem Processing Section // Now that we have folder list, lets start creating them foreach ($this->folderList as $folder) { if (!JFolder::exists($folder)) { if (!$created = JFolder::create($folder)) { JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $folder)); // If installation fails, rollback $this->parent->abort(); return false; } // Since we created a directory and will want to remove it if we have to roll back. // the installation due to some errors, let's add it to the installation step stack. if ($created) { $this->parent->pushStep(array('type' => 'folder', 'path' => $folder)); } } } // Now that we have file list, let's start copying them $this->parent->copyFiles($this->fileList); // Parse optional tags $this->parent->parseLanguages($this->manifest->languages); // Finalization and Cleanup Section // Get a database connector object $db = $this->parent->getDbo(); // Check to see if a module by the same name is already installed // If it is, then update the table because if the files aren't there // we can assume that it was (badly) uninstalled // If it isn't, add an entry to extensions $query = $db->getQuery(true); $query->select($query->qn('extension_id')) ->from($query->qn('#__extensions')); $query->where($query->qn('type') . ' = ' . $query->q('file')) ->where($query->qn('element') . ' = ' . $query->q($element)); $db->setQuery($query); try { $db->execute(); } catch (JException $e) { // Install failed, roll back changes $this->parent->abort( JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) ); return false; } $id = $db->loadResult(); $row = JTable::getInstance('extension'); if ($id) { // Load the entry and update the manifest_cache $row->load($id); // Update name $row->set('name', $this->get('name')); // Update manifest $row->manifest_cache = $this->parent->generateManifestCache(); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort( JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) ); return false; } } else { // Add an entry to the extension table with a whole heap of defaults $row->set('name', $this->get('name')); $row->set('type', 'file'); $row->set('element', $this->get('element')); // There is no folder for files so leave it blank $row->set('folder', ''); $row->set('enabled', 1); $row->set('protected', 0); $row->set('access', 0); $row->set('client_id', 0); $row->set('params', ''); $row->set('system_data', ''); $row->set('manifest_cache', $this->parent->generateManifestCache()); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_ROLLBACK', $db->stderr(true))); return false; } // Set the insert id $row->set('extension_id', $db->insertid()); // Since we have created a module item, we add it to the installation step stack // so that if we have to rollback the changes we can undo it. $this->parent->pushStep(array('type' => 'extension', 'extension_id' => $row->extension_id)); } /* * Let's run the queries for the file */ // second argument is the utf compatible version attribute if (strtolower($this->route) == 'install') { $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); if ($utfresult === false) { // Install failed, rollback changes $this->parent->abort( JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) ); return false; } // Set the schema version to be the latest update version if ($this->manifest->update) { $this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id); } } elseif (strtolower($this->route) == 'update') { if ($this->manifest->update) { $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id); if ($result === false) { // Install failed, rollback changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_UPDATE_SQL_ERROR', $db->stderr(true))); return false; } } } // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route)) { if ($this->parent->manifestClass->{$this->route}($this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg .= ob_get_contents(); // append messages ob_end_clean(); // Lastly, we will copy the manifest file to its appropriate place. $manifest = array(); $manifest['src'] = $this->parent->getPath('manifest'); $manifest['dest'] = JPATH_MANIFESTS . '/files/' . basename($this->parent->getPath('manifest')); if (!$this->parent->copyFiles(array($manifest), true)) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_COPY_SETUP')); return false; } // Clobber any possible pending updates $update = JTable::getInstance('update'); $uid = $update->find( array('element' => $this->get('element'), 'type' => 'file', 'client_id' => '', 'folder' => '') ); if ($uid) { $update->delete($uid); } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight($this->route, $this); } $msg .= ob_get_contents(); // append messages ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $row->get('extension_id'); } /** * Custom update method * * @return boolean True on success * * @since 11.1 */ public function update() { // Set the overwrite setting $this->parent->setOverwrite(true); $this->parent->setUpgrade(true); $this->route = 'update'; // ...and adds new files return $this->install(); } /** * Custom uninstall method * * @param string $id The id of the file to uninstall * * @return boolean True on success * * @since 11.1 */ public function uninstall($id) { // Initialise variables. $row = JTable::getInstance('extension'); if (!$row->load($id)) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_ENTRY')); return false; } if ($row->protected) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_WARNCOREFILE')); return false; } $retval = true; $manifestFile = JPATH_MANIFESTS . '/files/' . $row->element . '.xml'; // Because files may not have their own folders we cannot use the standard method of finding an installation manifest if (file_exists($manifestFile)) { // Set the plugin root path $this->parent->setPath('extension_root', JPATH_ROOT); // . '/files/' . $manifest->filename); $xml = JFactory::getXML($manifestFile); // If we cannot load the XML file return null if (!$xml) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_MANIFEST')); return false; } /* * Check for a valid XML root tag. */ if ($xml->getName() != 'extension') { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_MANIFEST')); return false; } $this->manifest = $xml; // If there is an manifest class file, let's load it $this->scriptElement = $this->manifest->scriptfile; $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // Set the class name $classname = $row->element . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } ob_start(); ob_implicit_flush(false); // Run uninstall if possible if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) { $this->parent->manifestClass->uninstall($this); } $msg = ob_get_contents(); ob_end_clean(); /* * Let's run the uninstall queries for the component * If Joomla 1.5 compatible, with discreet sql files - execute appropriate * file for utf-8 support or non-utf support */ // Try for Joomla 1.5 type queries // Second argument is the utf compatible version attribute $utfresult = $this->parent->parseSQLFiles($this->manifest->uninstall->sql); $db = JFactory::getDbo(); if ($utfresult === false) { // Install failed, rollback changes JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_SQL_ERROR', $db->stderr(true))); $retval = false; } // Remove the schema version $query = $db->getQuery(true); $query->delete() ->from('#__schemas') ->where('extension_id = ' . $row->extension_id); $db->setQuery($query); $db->execute(); // Set root folder names $packagePath = $this->parent->getPath('source'); $jRootPath = JPath::clean(JPATH_ROOT); // Loop through all elements and get list of files and folders foreach ($xml->fileset->files as $eFiles) { $folder = (string) $eFiles->attributes()->folder; $target = (string) $eFiles->attributes()->target; // Create folder path if (empty($target)) { $targetFolder = JPATH_ROOT; } else { $targetFolder = JPATH_ROOT . '/' . $target; } $folderList = array(); // Check if all children exists if (count($eFiles->children()) > 0) { // Loop through all filenames elements foreach ($eFiles->children() as $eFileName) { if ($eFileName->getName() == 'folder') { $folderList[] = $targetFolder . '/' . $eFileName; } else { $fileName = $targetFolder . '/' . $eFileName; JFile::delete($fileName); } } } // Delete any folders that don't have any content in them. foreach ($folderList as $folder) { $files = JFolder::files($folder); if (!count($files)) { JFolder::delete($folder); } } } JFile::delete($manifestFile); } else { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_NOTFOUND_MANIFEST')); // Delete the row because its broken $row->delete(); return false; } $this->parent->removeFiles($xml->languages); $row->delete(); return $retval; } /** * Function used to check if extension is already installed * * @param string $extension The element name of the extension to install * * @return boolean True if extension exists * * @since 11.1 */ protected function extensionExistsInSystem($extension = null) { // Get a database connector object $db = $this->parent->getDBO(); $query = $db->getQuery(true); $query->select($query->qn('extension_id')) ->from($query->qn('#__extensions')); $query->where($query->qn('type') . ' = ' . $query->q('file')) ->where($query->qn('element') . ' = ' . $query->q($extension)); $db->setQuery($query); try { $db->execute(); } catch (JException $e) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', $db->stderr(true))); return false; } $id = $db->loadResult(); if (empty($id)) { return false; } return true; } /** * Function used to populate files and folder list * * @return boolean none * * @since 11.1 */ protected function populateFilesAndFolderList() { // Initialise variable $this->folderList = array(); $this->fileList = array(); // Get fileset $eFileset = $this->manifest->fileset->files; // Set root folder names $packagePath = $this->parent->getPath('source'); $jRootPath = JPath::clean(JPATH_ROOT); // Loop through all elements and get list of files and folders foreach ($this->manifest->fileset->files as $eFiles) { // Check if the element is files element $folder = (string) $eFiles->attributes()->folder; $target = (string) $eFiles->attributes()->target; //Split folder names into array to get folder names. This will // help in creating folders $arrList = preg_split("#/|\\/#", $target); $folderName = $jRootPath; foreach ($arrList as $dir) { if (empty($dir)) { continue; } $folderName .= '/' . $dir; // Check if folder exists, if not then add to the array for folder creation if (!JFolder::exists($folderName)) { array_push($this->folderList, $folderName); } } // Create folder path $sourceFolder = empty($folder) ? $packagePath : $packagePath . '/' . $folder; $targetFolder = empty($target) ? $jRootPath : $jRootPath . '/' . $target; // Check if source folder exists if (!JFolder::exists($sourceFolder)) { JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $sourceFolder)); // If installation fails, rollback $this->parent->abort(); return false; } // Check if all children exists if (count($eFiles->children())) { // Loop through all filenames elements foreach ($eFiles->children() as $eFileName) { $path['src'] = $sourceFolder . '/' . $eFileName; $path['dest'] = $targetFolder . '/' . $eFileName; $path['type'] = 'file'; if ($eFileName->getName() == 'folder') { $folderName = $targetFolder . '/' . $eFileName; array_push($this->folderList, $folderName); $path['type'] = 'folder'; } array_push($this->fileList, $path); } } else { $files = JFolder::files($sourceFolder); foreach ($files as $file) { $path['src'] = $sourceFolder . '/' . $file; $path['dest'] = $targetFolder . '/' . $file; array_push($this->fileList, $path); } } } } /** * Refreshes the extension table cache * * @return boolean result of operation, true if updated, false on failure * * @since 11.1 */ public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally $manifestPath = JPATH_MANIFESTS . '/files/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; try { return $this->parent->extension->store(); } catch (JException $e) { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE')); return false; } } } package.php000066600000035574151372702060006675 0ustar00manifest = $this->parent->getManifest(); $extension = 'pkg_' . strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->packagename, 'cmd')); $lang = JFactory::getLanguage(); $source = $path; $lang->load($extension . '.sys', $source, null, false, true) || $lang->load($extension . '.sys', JPATH_SITE, null, false, true); } /** * Custom install method * * @return int The extension id * * @since 11.1 */ public function install() { // Get the extension manifest object $this->manifest = $this->parent->getManifest(); // Manifest Document Setup Section // Set the extensions name $filter = JFilterInput::getInstance(); $name = (string) $this->manifest->packagename; $name = $filter->clean($name, 'cmd'); $this->set('name', $name); $element = 'pkg_' . $filter->clean($this->manifest->packagename, 'cmd'); $this->set('element', $element); // Get the component description $description = (string) $this->manifest->description; if ($description) { $this->parent->set('message', JText::_($description)); } else { $this->parent->set('message', ''); } // Set the installation path $files = $this->manifest->files; $group = (string) $this->manifest->packagename; if (!empty($group)) { $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . implode(DIRECTORY_SEPARATOR, explode('/', $group))); } else { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_PACK', JText::_('JLIB_INSTALLER_' . strtoupper($this->route)))); return false; } /** * --------------------------------------------------------------------------------------------- * Installer Trigger Loading * --------------------------------------------------------------------------------------------- */ // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) $this->scriptElement = $this->manifest->scriptfile; $manifestScript = (string) $this->manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // load the file include_once $manifestScriptFile; } // Set the class name $classname = $element . 'InstallerScript'; if (class_exists($classname)) { // create a new instance $this->parent->manifestClass = new $classname($this); // and set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } // run preflight if possible (since we know we're not an update) ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) { if ($this->parent->manifestClass->preflight($this->route, $this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg = ob_get_contents(); // create msg object; first use here ob_end_clean(); // Filesystem Processing Section if ($folder = $files->attributes()->folder) { $source = $this->parent->getPath('source') . '/' . $folder; } else { $source = $this->parent->getPath('source'); } // Install all necessary files if (count($this->manifest->files->children())) { $i = 0; foreach ($this->manifest->files->children() as $child) { $file = $source . '/' . $child; if (is_dir($file)) { // If it's actually a directory then fill it up $package = array(); $package['dir'] = $file; $package['type'] = JInstallerHelper::detectType($file); } else { // If it's an archive $package = JInstallerHelper::unpack($file); } $tmpInstaller = new JInstaller; $installResult = $tmpInstaller->install($package['dir']); if (!$installResult) { $this->parent->abort( JText::sprintf( 'JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION', JText::_('JLIB_INSTALLER_' . strtoupper($this->route)), basename($file) ) ); return false; } else { $results[$i] = array( 'name' => $tmpInstaller->manifest->name, 'result' => $installResult ); } $i++; } } else { $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES', JText::_('JLIB_INSTALLER_' . strtoupper($this->route)))); return false; } // Parse optional tags $this->parent->parseLanguages($this->manifest->languages); // Extension Registration $row = JTable::getInstance('extension'); $eid = $row->find(array('element' => strtolower($this->get('element')), 'type' => 'package')); if ($eid) { $row->load($eid); } else { $row->name = $this->get('name'); $row->type = 'package'; $row->element = $this->get('element'); // There is no folder for modules $row->folder = ''; $row->enabled = 1; $row->protected = 0; $row->access = 1; $row->client_id = 0; // custom data $row->custom_data = ''; $row->params = $this->parent->getParams(); } // Update the manifest cache for the entry $row->manifest_cache = $this->parent->generateManifestCache(); if (!$row->store()) { // Install failed, roll back changes $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_ROLLBACK', $row->getError())); return false; } // Finalization and Cleanup Section // Start Joomla! 1.6 ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route)) { if ($this->parent->manifestClass->{$this->route}($this) === false) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE')); return false; } } $msg .= ob_get_contents(); // append messages ob_end_clean(); // Lastly, we will copy the manifest file to its appropriate place. $manifest = array(); $manifest['src'] = $this->parent->getPath('manifest'); $manifest['dest'] = JPATH_MANIFESTS . '/packages/' . basename($this->parent->getPath('manifest')); if (!$this->parent->copyFiles(array($manifest), true)) { // Install failed, rollback changes $this->parent->abort( JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_COPY_SETUP', JText::_('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES')) ); return false; } // If there is a manifest script, let's copy it. if ($this->get('manifest_script')) { // First, we have to create a folder for the script if one isn't present $created = false; if (!file_exists($this->parent->getPath('extension_root'))) { JFolder::create($this->parent->getPath('extension_root')); } $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script'); if (!file_exists($path['dest']) || $this->parent->isOverwrite()) { if (!$this->parent->copyFiles(array($path))) { // Install failed, rollback changes $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST')); return false; } } } // And now we run the postflight ob_start(); ob_implicit_flush(false); if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) { $this->parent->manifestClass->postflight($this->route, $this, $results); } $msg .= ob_get_contents(); // append messages ob_end_clean(); if ($msg != '') { $this->parent->set('extension_message', $msg); } return $row->extension_id; } /** * Updates a package * * The only difference between an update and a full install * is how we handle the database * * @return void * * @since 11.1 */ public function update() { $this->route = 'update'; $this->install(); } /** * Custom uninstall method * * @param integer $id The id of the package to uninstall. * * @return boolean True on success * * @since 11.1 */ public function uninstall($id) { // Initialise variables. $row = null; $retval = true; $row = JTable::getInstance('extension'); $row->load($id); if ($row->protected) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_WARNCOREPACK')); return false; } $manifestFile = JPATH_MANIFESTS . '/packages/' . $row->get('element') . '.xml'; $manifest = new JPackageManifest($manifestFile); // Set the package root path $this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . $manifest->packagename); // Because packages may not have their own folders we cannot use the standard method of finding an installation manifest if (!file_exists($manifestFile)) { // TODO: Fail? JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSINGMANIFEST')); return false; } $xml = JFactory::getXML($manifestFile); // If we cannot load the XML file return false if (!$xml) { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_LOAD_MANIFEST')); return false; } /* * Check for a valid XML root tag. * @todo: Remove backwards compatibility in a future version * Should be 'extension', but for backward compatibility we will accept 'install'. */ if ($xml->getName() != 'install' && $xml->getName() != 'extension') { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_INVALID_MANIFEST')); return false; } // If there is an manifest class file, let's load it $this->scriptElement = $manifest->scriptfile; $manifestScript = (string) $manifest->scriptfile; if ($manifestScript) { $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript; if (is_file($manifestScriptFile)) { // Load the file include_once $manifestScriptFile; } // Set the class name $classname = $row->element . 'InstallerScript'; if (class_exists($classname)) { // Create a new instance $this->parent->manifestClass = new $classname($this); // And set this so we can copy it later $this->set('manifest_script', $manifestScript); // Note: if we don't find the class, don't bother to copy the file } } ob_start(); ob_implicit_flush(false); // Run uninstall if possible if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) { $this->parent->manifestClass->uninstall($this); } $msg = ob_get_contents(); ob_end_clean(); $error = false; foreach ($manifest->filelist as $extension) { $tmpInstaller = new JInstaller; $id = $this->_getExtensionID($extension->type, $extension->id, $extension->client, $extension->group); $client = JApplicationHelper::getClientInfo($extension->client, true); if ($id) { if (!$tmpInstaller->uninstall($extension->type, $id, $client->id)) { $error = true; JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_NOT_PROPER', basename($extension->filename))); } } else { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_UNKNOWN_EXTENSION')); } } // Remove any language files $this->parent->removeFiles($xml->languages); // clean up manifest file after we're done if there were no errors if (!$error) { JFile::delete($manifestFile); $folder = $this->parent->getPath('extension_root'); if (JFolder::exists($folder)) { JFolder::delete($folder); } $row->delete(); } else { JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MANIFEST_NOT_REMOVED')); } // Return the result up the line return $retval; } /** * Gets the extension id. * * @param string $type The extension type. * @param string $id The name of the extension (the element field). * @param integer $client The application id (0: Joomla CMS site; 1: Joomla CMS administrator). * @param string $group The extension group (mainly for plugins). * * @return integer * * @since 11.1 */ protected function _getExtensionID($type, $id, $client, $group) { $db = $this->parent->getDbo(); $result = $id; $query = $db->getQuery(true); $query->select('extension_id'); $query->from('#__extensions'); $query->where('type = ' . $db->Quote($type)); $query->where('element = ' . $db->Quote($id)); switch ($type) { case 'plugin': // Plugins have a folder but not a client $query->where('folder = ' . $db->Quote($group)); break; case 'library': case 'package': case 'component': // Components, packages and libraries don't have a folder or client. // Included for completeness. break; case 'language': case 'module': case 'template': // Languages, modules and templates have a client but not a folder $client = JApplicationHelper::getClientInfo($client, true); $query->where('client_id = ' . (int) $client->id); break; } $db->setQuery($query); $result = $db->loadResult(); // Note: For templates, libraries and packages their unique name is their key. // This means they come out the same way they came in. return $result; } /** * Refreshes the extension table cache * * @return boolean Result of operation, true if updated, false on failure * * @since 11.1 */ public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally $manifestPath = JPATH_MANIFESTS . '/packages/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); $this->parent->extension->name = $manifest_details['name']; try { return $this->parent->extension->store(); } catch (JException $e) { JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE')); return false; } } } extension.php000066600000015606151372722710007314 0ustar00_stack, $name); $tag = $this->_getStackLocation(); // Reset the data if (isset($this->$tag)) { $this->$tag->_data = ""; } switch ($name) { case 'UPDATE': $this->current_update = JTable::getInstance('update'); $this->current_update->update_site_id = $this->_update_site_id; $this->current_update->detailsurl = $this->_url; $this->current_update->folder = ""; $this->current_update->client_id = 1; break; // Don't do anything case 'UPDATES': // Store compatibility info per updates block (usually one per file) $this->compatibility = array(); break; default: if (in_array($name, $this->_updatecols)) { $name = strtolower($name); $this->current_update->$name = ''; } if ($name == 'TARGETPLATFORM') { $this->current_update->targetplatform = $attrs; if (isset($attrs['NAME']) && ($attrs['NAME'] == 'joomla') && !empty($attrs['VERSION'])) { $this->current_update->compatibility = $attrs['VERSION']; } } if ($name == 'PHP_MINIMUM') { $this->current_update->php_minimum = ''; } break; } } /** * Character Parser Function * * @param object $parser Parser object. * @param object $name The name of the element. * * @return void * * @since 11.1 */ protected function _endElement($parser, $name) { array_pop($this->_stack); //echo 'Closing: '. $name .'
'; switch ($name) { case 'UPDATE': $ver = new JVersion; $product = strtolower(JFilterInput::getInstance()->clean($ver->PRODUCT, 'cmd')); // lower case and remove the exclamation mark // Keep compatibility information in class property if (isset($this->current_update->compatibility)) { $this->compatibility[$this->current_update->version][] = $this->current_update->compatibility; unset($this->current_update->compatibility); } // Check that the product matches and that the version matches (optionally a regexp) if ($product == $this->current_update->targetplatform['NAME'] && preg_match('/' . $this->current_update->targetplatform['VERSION'] . '/', $ver->RELEASE)) { // Check if PHP version supported via tag, assume true if tag isn't present if (!isset($this->current_update->php_minimum) || version_compare(PHP_VERSION, $this->current_update->php_minimum, '>=')) { $phpMatch = true; } else { // Notify the user of the potential update $msg = JText::sprintf( 'JLIB_INSTALLER_AVAILABLE_UPDATE_PHP_VERSION', $this->current_update->name, $this->current_update->version, $this->current_update->php_minimum, PHP_VERSION ); JFactory::getApplication()->enqueueMessage($msg, 'warning'); $phpMatch = false; } // Target platform and php_minimum aren't valid fields in the update table so unset them to prevent J! from trying to store them unset($this->current_update->targetplatform); unset($this->current_update->php_minimum); if ($phpMatch) { if (isset($this->latest)) { if (version_compare($this->current_update->version, $this->latest->version, '>') == 1) { $this->latest = $this->current_update; } } else { $this->latest = $this->current_update; } } } break; case 'UPDATES': // :D break; } } /** * Character Parser Function * * @param object $parser Parser object. * @param object $data The data. * * @return void * * @note This is public because its called externally. * @since 11.1 */ protected function _characterData($parser, $data) { $tag = $this->_getLastTag(); //if(!isset($this->$tag->_data)) $this->$tag->_data = ''; //$this->$tag->_data .= $data; if (in_array($tag, $this->_updatecols)) { $tag = strtolower($tag); $this->current_update->$tag .= $data; } if ($tag == 'PHP_MINIMUM') { $this->current_update->php_minimum = $data; } } /** * Finds an update. * * @param array $options Update options. * * @return array Array containing the array of update sites and array of updates * * @since 11.1 */ public function findUpdate($options) { $url = trim($options['location']); $this->_url = &$url; $this->_update_site_id = $options['update_site_id']; if (substr($url, -4) != '.xml') { if (substr($url, -1) != '/') { $url .= '/'; } $url .= 'extension.xml'; } $dbo = $this->parent->getDBO(); $http = JHttpFactory::getHttp(); try { $response = $http->get($url); } catch (Exception $exc) { $response = null; } if (is_null($response) || ($response->code != 200)) { $query = $dbo->getQuery(true); $query->update('#__update_sites'); $query->set('enabled = 0'); $query->where('update_site_id = ' . $this->_update_site_id); $dbo->setQuery($query); $dbo->execute(); JLog::add("Error opening url: " . $url, JLog::WARNING, 'updater'); $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_EXTENSION_OPEN_URL', $url), 'warning'); return false; } $this->xml_parser = xml_parser_create(''); xml_set_object($this->xml_parser, $this); xml_set_element_handler($this->xml_parser, '_startElement', '_endElement'); xml_set_character_data_handler($this->xml_parser, '_characterData'); if (!xml_parse($this->xml_parser, $response->body)) { JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater'); $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_EXTENSION_PARSE_URL', $url), 'warning'); return false; } xml_parser_free($this->xml_parser); if (isset($this->latest)) { if (isset($this->latest->client) && strlen($this->latest->client)) { $this->latest->client_id = JApplicationHelper::getClientInfo($this->latest->client, 1)->id; unset($this->latest->client); } $updates = array($this->latest); } else { $updates = array(); } return array('update_sites' => array(), 'updates' => $updates, 'compatibility' => $this->compatibility); } } collection.php000066600000014714151372722710007432 0ustar00', $this->_stack); } /** * Get the parent tag * * @return string parent * * @since 11.1 */ protected function _getParent() { return end($this->parent); } /** * Opening an XML element * * @param object $parser Parser object * @param string $name Name of element that is opened * @param array $attrs Array of attributes for the element * * @return void * * @since 11.1 */ public function _startElement($parser, $name, $attrs = array()) { array_push($this->_stack, $name); $tag = $this->_getStackLocation(); // Reset the data if (isset($this->$tag)) { $this->$tag->_data = ""; } switch ($name) { case 'CATEGORY': if (isset($attrs['REF'])) { $this->update_sites[] = array('type' => 'collection', 'location' => $attrs['REF'], 'update_site_id' => $this->_update_site_id); } else { // This item will have children, so prepare to attach them $this->pop_parent = 1; } break; case 'EXTENSION': $update = JTable::getInstance('update'); $update->set('update_site_id', $this->_update_site_id); foreach ($this->_updatecols as $col) { // Reset the values if it doesn't exist if (!array_key_exists($col, $attrs)) { $attrs[$col] = ''; if ($col == 'CLIENT') { $attrs[$col] = 'site'; } } } $client = JApplicationHelper::getClientInfo($attrs['CLIENT'], 1); $attrs['CLIENT_ID'] = $client->id; // Lower case all of the fields foreach ($attrs as $key => $attr) { $values[strtolower($key)] = $attr; } // Only add the update if it is on the same platform and release as we are $ver = new JVersion; $product = strtolower(JFilterInput::getInstance()->clean($ver->PRODUCT, 'cmd')); // lower case and remove the exclamation mark // Set defaults, the extension file should clarify in case but it may be only available in one version // This allows an update site to specify a targetplatform // targetplatformversion can be a regexp, so 1.[56] would be valid for an extension that supports 1.5 and 1.6 // Note: Whilst the version is a regexp here, the targetplatform is not (new extension per platform) // Additionally, the version is a regexp here and it may also be in an extension file if the extension is // compatible against multiple versions of the same platform (e.g. a library) if (!isset($values['targetplatform'])) { $values['targetplatform'] = $product; } // set this to ourself as a default if (!isset($values['targetplatformversion'])) { $values['targetplatformversion'] = $ver->RELEASE; } // set this to ourself as a default // validate that we can install the extension if ($product == $values['targetplatform'] && preg_match('/' . $values['targetplatformversion'] . '/', $ver->RELEASE)) { $update->bind($values); $this->updates[] = $update; } break; } } /** * Closing an XML element * Note: This is a protected function though has to be exposed externally as a callback * * @param object $parser Parser object * @param string $name Name of the element closing * * @return void * * @since 11.1 */ protected function _endElement($parser, $name) { $lastcell = array_pop($this->_stack); switch ($name) { case 'CATEGORY': if ($this->pop_parent) { $this->pop_parent = 0; array_pop($this->parent); } break; } } // Note: we don't care about char data in collection because there should be none /** * Finds an update * * @param array $options Options to use: update_site_id: the unique ID of the update site to look at * * @return array Update_sites and updates discovered * * @since 11.1 */ public function findUpdate($options) { $url = trim($options['location']); $this->_update_site_id = $options['update_site_id']; if (substr($url, -4) != '.xml') { if (substr($url, -1) != '/') { $url .= '/'; } $url .= 'update.xml'; } $this->base = new stdClass; $this->update_sites = array(); $this->updates = array(); $dbo = $this->parent->getDBO(); $http = JHttpFactory::getHttp(); try { $response = $http->get($url); } catch (Exception $exc) { $response = null; } if (is_null($response) || ($response->code != 200)) { $query = $dbo->getQuery(true); $query->update('#__update_sites'); $query->set('enabled = 0'); $query->where('update_site_id = ' . $this->_update_site_id); $dbo->setQuery($query); $dbo->execute(); JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater'); $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL', $url), 'warning'); return false; } $this->xml_parser = xml_parser_create(''); xml_set_object($this->xml_parser, $this); xml_set_element_handler($this->xml_parser, '_startElement', '_endElement'); if (!xml_parse($this->xml_parser, $response->body)) { JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater'); $app = JFactory::getApplication(); $app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL', $url), 'warning'); return false; } // TODO: Decrement the bad counter if non-zero return array('update_sites' => $this->update_sites, 'updates' => $this->updates); } }