/** * Execute selected method * * @access public * @param object Registry object * @return @e void */ public function doExecute(ipsRegistry $registry) { /* Remove the FURL cache */ @unlink(FURL_CACHE_PATH); /* Got anything to show? */ $apps = explode(',', IPSSetUp::getSavedData('install_apps')); $vNums = IPSSetUp::getSavedData('version_numbers'); $output = array(); if (is_array($apps) and count($apps)) { foreach ($apps as $app) { /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); /* Grab all numbers */ $nums[$app] = IPSSetUp::fetchXmlAppVersions($app); /* Grab app data */ $appData[$app] = IPSSetUp::fetchXmlAppInformation($app, $this->settings['gb_char_set']); $appClasses[$app] = IPSSetUp::fetchVersionClasses($app, $vNums[$app], $numbers['latest'][0]); } /* Got anything? */ if (count($appClasses)) { foreach ($appClasses as $app => $data) { foreach ($data as $num) { if (is_file(IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php')) { $_class = 'version_class_' . $app . '_' . $num; require_once IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php'; /*noLibHook*/ $_tmp = new $_class($this->registry); if (method_exists($_tmp, 'postInstallNotices')) { $_t = $_tmp->postInstallNotices(); if (is_array($_t) and count($_t)) { $output[$app][$num] = array('long' => $nums[$app][$num], 'app' => $appData[$app], 'out' => implode("<br />", $_t)); } } } } } } } /* Remove any SQL source files */ IPSSetUp::removeSqlSourceFiles(); /* Simply return the Done page */ $this->registry->output->setTitle("Complete!"); $this->registry->output->setHideButton(TRUE); $this->registry->output->addContent($this->registry->output->template()->upgrade_complete($output)); $this->registry->output->sendOutput(); }
/** * Execute selected method * * @access public * @param object Registry object * @return @e void */ public function doExecute(ipsRegistry $registry) { /* Delete sessions and continue */ if ($this->request['do'] == 'rsessions') { IPSSetUp::removePreviousSession(); } /* Rebuild from last session and continue */ if ($this->request['do'] == 'rcontinue') { $oldSession = IPSSetUp::checkForPreviousSessions(); if (count($oldSession) and $oldSession['_session_get']['section'] and $oldSession['_sd']['install_apps']) { IPSSetUp::restorePreviousSession($oldSession); exit; } } /* Check for failed upgrade */ if (!$this->request['do'] or $this->request['do'] != 'rsessions') { $oldSession = IPSSetUp::checkForPreviousSessions(); if (count($oldSession) and $oldSession['_session_get']['section'] and $oldSession['_sd']['install_apps']) { /* Page Output */ $this->registry->output->setTitle("Applications"); $this->registry->output->setNextAction('apps&do=rsessions'); //$this->registry->output->setHideButton( TRUE ); $this->registry->output->addContent($this->registry->output->template()->upgrade_previousSession($oldSession)); $this->registry->output->sendOutput(); } } /* Save data */ if ($this->request['do'] == 'save') { $apps = explode(',', IPSSetUp::getSavedData('install_apps')); $toSave = array(); $vNums = array(); if (is_array($apps) and count($apps)) { foreach ($apps as $app) { /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); /* Grab all numbers */ $nums[$app] = IPSSetUp::fetchXmlAppVersions($app); /* Grab app data */ $appData[$app] = IPSSetUp::fetchXmlAppInformation($app, $this->settings['gb_char_set']); $appClasses[$app] = IPSSetUp::fetchVersionClasses($app, $numbers['current'][0], $numbers['latest'][0]); /* Store starting vnums */ $vNums[$app] = $numbers['current'][0]; } /* Got anything? */ if (count($appClasses)) { foreach ($appClasses as $app => $data) { foreach ($data as $num) { if (is_file(IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php')) { $_class = 'version_class_' . $app . '_' . $num; require_once IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php'; /*noLibHook*/ $_tmp = new $_class($this->registry); if (method_exists($_tmp, 'preInstallOptionsSave')) { $_t = $_tmp->preInstallOptionsSave(); if (is_array($_t) and count($_t)) { $toSave[$app][$num] = $_t; } } } } } /* Save it */ if (count($toSave)) { IPSSetUp::setSavedData('custom_options', $toSave); } if (count($vNums)) { IPSSetUp::setSavedData('version_numbers', $vNums); } } } /* Next Action */ $this->registry->autoLoadNextAction('license'); } else { if ($this->request['do'] == 'check') { /* Check Directory */ if (!is_array($_POST['apps']) or !count($_POST['apps'])) { /* We use 'warning' because it has same effect but does not block the 'next' button (which they'll want to use after selecting an app when page reloads) */ $this->registry->output->addWarning('You must select to upgrade at least one application'); } else { /* If it's lower than 3.0.0, then add in the removed apps */ if (IPSSetUp::is300plus() !== TRUE) { $_POST['apps']['forums'] = 1; $_POST['apps']['members'] = 1; $_POST['apps']['calendar'] = 1; $_POST['apps']['chat'] = 1; } else { if ($_POST['apps']['core']) { $_POST['apps']['forums'] = 1; $_POST['apps']['members'] = 1; } } /* Save Form Data */ IPSSetUp::setSavedData('install_apps', implode(',', array_keys($_POST['apps']))); /* Got any app-version classes? */ $appClasses = array(); $output = array(); $nums = array(); $appData = array(); foreach ($_POST['apps'] as $app => $val) { /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); /* Grab all numbers */ $nums[$app] = IPSSetUp::fetchXmlAppVersions($app); /* Grab app data */ $appData[$app] = IPSSetUp::fetchXmlAppInformation($app, $this->settings['gb_char_set']); $appClasses[$app] = IPSSetUp::fetchVersionClasses($app, $numbers['current'][0], $numbers['latest'][0]); } /* Got anything? */ $error = FALSE; if (count($appClasses)) { foreach ($appClasses as $app => $data) { if (is_file(IPSLib::getAppDir($app) . '/setup/upgradeCheck.php')) { $_class = $app . '_upgradeCheck'; require_once IPSLib::getAppDir($app) . '/setup/upgradeCheck.php'; /*noLibHook*/ $requirements_class = new $_class(); if (method_exists($requirements_class, 'checkForProblems')) { $check = $requirements_class->checkForProblems($appClasses); if ($check !== TRUE) { $error = TRUE; $this->registry->output->addError($check); } } } foreach ($data as $num) { if (is_file(IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php')) { $_class = 'version_class_' . $app . '_' . $num; require_once IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php'; /*noLibHook*/ $_tmp = new $_class($this->registry); if (method_exists($_tmp, 'preInstallOptionsForm')) { $_t = $_tmp->preInstallOptionsForm(); if ($_t) { $output[$app][$num] = array('long' => $nums[$app][$num], 'app' => $appData[$app], 'out' => $_t); } } } } } } /* Finally... */ if (count($output) or $error === TRUE) { $this->registry->output->setTitle("Applications"); $this->registry->output->setNextAction('apps&do=save'); //$this->registry->output->setHideButton( TRUE ); if (!$error) { $this->registry->output->addContent($this->registry->output->template()->upgrade_appsOptions($output)); } $this->registry->output->sendOutput(); } else { /* Next Action */ $this->registry->autoLoadNextAction('license'); } } } } /* Generate apps... */ $apps = array('core' => array(), 'ips' => array(), 'other' => array()); foreach (array('applications', 'applications_addon/ips', 'applications_addon/other') as $_pBit) { $path = IPS_ROOT_PATH . $_pBit; $handle = opendir($path); while (($file = readdir($handle)) !== FALSE) { if (!preg_match("#^\\.#", $file)) { if (is_dir($path . '/' . $file)) { //----------------------------------------- // Get it! //----------------------------------------- if (!is_file(IPS_ROOT_PATH . $_pBit . '/' . $file . '/xml/information.xml')) { continue; } $data = IPSSetUp::fetchXmlAppInformation($file, $this->settings['gb_char_set']); switch ($_pBit) { case 'applications': $apps['core'][$file] = $data; break; case 'applications_addon/ips': $apps['ips'][$file] = $data; break; case 'applications_addon/other': $apps['other'][$file] = $data; break; } } } } closedir($handle); } /* Reorder the array so that core is first */ $new_array = array(); $new_array['core'] = $apps['core']['core']; foreach ($apps['core'] as $app => $data) { if ($app == 'core') { continue; } $new_array[$app] = $data; } $apps['core'] = $new_array; /* Now get version numbers */ foreach ($apps as $type => $app) { foreach ($apps[$type] as $app => $data) { if ($type == 'core' and ($app == 'forums' or $app == 'members')) { /* Skip forums and members and just count core for now */ continue; } /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); $appClasses[$app] = IPSSetUp::fetchVersionClasses($app, $numbers['current'][0], $numbers['latest'][0]); $apps[$type][$app]['_vnumbers'] = $numbers; } } /* Any notices? */ $notices = array(); if (count($appClasses)) { foreach ($appClasses as $app => $data) { $notices[$app] = array(); foreach ($data as $num) { if (is_file(IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php')) { $_class = 'version_class_' . $app . '_' . $num; require_once IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php'; /*noLibHook*/ $_tmp = new $_class($this->registry); if (method_exists($_tmp, 'preInstallNotices')) { $_t = $_tmp->preInstallNotices(); if ($_t) { $notices[$app] = array_merge($_t, $notices[$app]); } } } } } } /* If it's lower than 3.0.0, then remove some apps and make them part of 'core' */ if (IPSSetUp::is300plus() !== TRUE) { unset($apps['ips']['calendar']); unset($apps['ips']['chat']); } /* Page Output */ $this->registry->output->setTitle("Applications"); $this->registry->output->setNextAction('apps&do=check'); //$this->registry->output->setHideButton( TRUE ); $this->registry->output->addContent($this->registry->output->template()->upgrade_apps($apps, $notices)); $this->registry->output->sendOutput(); }
/** * Show the redirect screen * * @param string $app_directory * @param string $output * @param string $errors * @param string $next_url * @return @e void */ protected function showRedirectScreen($app_directory, $output, $errors, $next_url) { /* Init Data */ $data = IPSSetUp::fetchXmlAppInformation($app_directory, $this->settings['gb_char_set']); $_numbers = IPSSetUp::fetchAppVersionNumbers($app_directory); /* Grab Data */ $data['app_directory'] = $app_directory; $data['current_version'] = $_numbers['current'][0] ? $_numbers['current'][0] : $this->lang->words['cur_version_none']; $data['latest_version'] = $_numbers['latest'][1]; $data['next_version'] = $_numbers['next'][0]; /* Setup Redirect */ $this->registry->output->html .= $this->html->setup_redirectScreen($output, $errors, $next_url); }
/** * Add Applications * * @return @e void */ public function addApplications() { /* Add applications.. */ $apps = array('core' => array(), 'ips' => array(), 'other' => array()); $components = array(); foreach (array('applications', 'applications_addon/ips', 'applications_addon/other') as $_pBit) { $path = IPS_ROOT_PATH . $_pBit; $handle = opendir($path); while (($file = readdir($handle)) !== FALSE) { if (!preg_match("#^\\.#", $file)) { if (is_dir($path . '/' . $file)) { //----------------------------------------- // Get it! //----------------------------------------- if (!is_file(IPS_ROOT_PATH . $_pBit . '/' . $file . '/xml/information.xml')) { continue; } $data = IPSSetUp::fetchXmlAppInformation($file); switch ($_pBit) { case 'applications': $apps['core'][$file] = $data; break; case 'applications_addon/ips': $apps['ips'][$file] = $data; break; case 'applications_addon/other': $apps['other'][$file] = $data; break; } } } } closedir($handle); } /* Reorder the array so that core is first */ $new_array = array(); $new_array['core'] = $apps['core']['core']; foreach ($apps['core'] as $app => $data) { if ($app == 'core') { continue; } $new_array[$app] = $data; } $apps['core'] = $new_array; /* Fetch data for current 'components' */ $this->DB->build(array('select' => '*', 'from' => 'components')); $this->DB->execute(); while ($row = $this->DB->fetch()) { $components[$row['com_section']] = $row; } /* Got Gallery? */ if ($components['gallery']['com_enabled'] and $this->DB->checkForTable('gallery_upgrade_history')) { /* Fetch current version number */ $version = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'gallery_upgrade_history', 'order' => 'gallery_version_id DESC', 'limit' => array(0, 1))); $apps['ips']['gallery']['_currentLong'] = $version['gallery_version_id']; $apps['ips']['gallery']['_currentHuman'] = $version['gallery_version_human']; } /* Got Blog? */ if ($components['blog']['com_enabled'] and $this->DB->checkForTable('blog_upgrade_history')) { /* Fetch current version number */ $version = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'blog_upgrade_history', 'order' => 'blog_version_id DESC', 'limit' => array(0, 1))); $apps['ips']['blog']['_currentLong'] = $version['blog_version_id']; $apps['ips']['blog']['_currentHuman'] = $version['blog_version_human']; } /* Got Downloads? */ if ($components['downloads']['com_enabled'] and $this->DB->checkForTable('downloads_upgrade_history')) { /* Fetch current version number */ $version = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'downloads_upgrade_history', 'order' => 'idm_version_id DESC', 'limit' => array(0, 1))); $apps['ips']['downloads']['_currentLong'] = $version['idm_version_id']; $apps['ips']['downloads']['_currentHuman'] = $version['idm_version_human']; } /* Others.. */ $apps['core']['forums']['_currentLong'] = '30001'; $apps['core']['forums']['_currentHuman'] = '3.0.0'; $apps['core']['core']['_currentLong'] = '30001'; $apps['core']['core']['_currentHuman'] = '3.0.0'; $apps['core']['members']['_currentLong'] = '30001'; $apps['core']['members']['_currentHuman'] = '3.0.0'; $apps['ips']['portal']['_currentLong'] = '30003'; $apps['ips']['portal']['_currentHuman'] = '3.0.0'; //$apps['ips']['chat']['_currentLong'] = '30003'; //$apps['ips']['chat']['_currentHuman'] = '3.0.0'; /* If we are upgrading from 2.3 and did not upload the calendar files, we still need to insert the applications table entry, otherwise you won't be able to upgrade down the road. We will insert it as disabled, however, as calendar won't function since files are not available @link http://community.invisionpower.com/tracker/issue-33543-ipb2-upgrades */ if (!isset($apps['ips']['calendar']['name'])) { $apps['ips']['calendar'] = array('name' => 'Calendar', 'public_name' => 'Calendar', 'description' => "", 'author' => "Invision Power Services, Inc.", 'hide_tab' => 0, 'key' => 'calendar', 'disabledatinstall' => 1, 'ipskey' => "fa038db69fa627d8e8e034d65f554d1f", '_locationkey' => 'ips'); } $apps['ips']['calendar']['_currentLong'] = '30003'; $apps['ips']['calendar']['_currentHuman'] = '3.0.0'; /* Now install them.. */ $num = 0; foreach ($apps as $where => $data) { foreach ($apps[$where] as $dir => $appData) { //----------------------------------------- // Had Gallery (e.g.) but didn't upload updated files //----------------------------------------- if (!$appData['name']) { continue; } $num++; $_protected = in_array($appData['key'], array('core', 'forums', 'members')) ? 1 : 0; $_enabled = $appData['disabledatinstall'] ? 0 : 1; if (!$appData['_currentLong']) { continue; } $this->registry->output->addMessage("Добавление приложения: {$appData['name']}...."); $this->DB->insert('core_applications', array('app_title' => $appData['name'], 'app_public_title' => $appData['public_name'] ? $appData['public_name'] : '', 'app_description' => $appData['description'], 'app_author' => $appData['author'], 'app_hide_tab' => intval($appData['hide_tab']), 'app_version' => $appData['_currentHuman'], 'app_long_version' => $appData['_currentLong'], 'app_directory' => $appData['key'], 'app_added' => time(), 'app_position' => $num, 'app_protected' => $_protected, 'app_location' => $appData['_locationkey'] ? $appData['_locationkey'] : IPSLib::extractAppLocationKey($appData['key']), 'app_enabled' => $_enabled, 'app_website' => $appData['website'], 'app_update_check' => $appData['update_check'], 'app_global_caches' => $appData['global_caches'])); } } /* Next Page */ $this->request['workact'] = 'settings'; }
/** * Check for previous sessions. * Checks to see if there's an unfinished upgrade. * * @param array * @access public */ public static function restorePreviousSession($session) { /* Delete all previous sessions */ ipsRegistry::DB()->delete('upgrade_sessions', 'session_id != \'' . ipsRegistry::$request['s'] . '\''); /* Update the session */ ipsRegistry::DB()->update('upgrade_sessions', array('session_current_time' => time(), 'session_section' => $session['session_section'], 'session_post' => serialize($session['_session_post']), 'session_get' => serialize($session['_session_get'])), 'session_id=\'' . ipsRegistry::$request['s'] . '\''); /* Set correct app */ $_GET['app'] = 'upgrade'; $_POST['app'] = 'upgrade'; ipsRegistry::$request['app'] = 'upgrade'; ipsRegistry::$current_section = 'upgrade'; /* Set correct section */ $_GET['section'] = $session['_session_get']['section']; $_POST['section'] = $session['_session_get']['section']; ipsRegistry::$request['section'] = $session['_session_get']['section']; ipsRegistry::$current_section = $session['_session_get']['section']; /* Set up the correct do */ $_GET['do'] = $session['_session_get']['do']; $_POST['do'] = $session['_session_get']['do']; ipsRegistry::$request['do'] = $session['_session_get']['do']; /* Set up the correct previous */ $_GET['previous'] = $session['_session_get']['previous']; $_POST['previous'] = $session['_session_get']['previous']; ipsRegistry::$request['previous'] = $session['_session_get']['previous']; /* Set up SD */ $_POST['_sd'] = $session['_sd']; ipsRegistry::$request['_sd'] = $session['_sd']; /* App dir, etc */ ipsRegistry::$request['appdir'] = $session['_sd']['appdir']; ipsRegistry::$request['man'] = $session['_sd']['man']; ipsRegistry::$request['helpfile'] = $session['_sd']['helpfile']; $apps = explode(',', $session['_sd']['install_apps']); $toSave = array(); $vNums = array(); /* set saved data */ if (count($session['_sd'])) { foreach ($session['_sd'] as $k => $v) { if ($k) { IPSSetUp::setSavedData($k, $v); } } } if (is_array($apps) and count($apps)) { /* Grab data */ foreach ($apps as $app) { /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); /* Grab all numbers */ $nums[$app] = IPSSetUp::fetchXmlAppVersions($app); /* Grab app data */ $appData[$app] = IPSSetUp::fetchXmlAppInformation($app); $appClasses[$app] = IPSSetUp::fetchVersionClasses($app, $numbers['current'][0], $numbers['latest'][0]); /* Store starting vnums */ $vNums[$app] = $numbers['current'][0]; } /* Got anything? */ if (count($appClasses)) { foreach ($appClasses as $app => $data) { foreach ($data as $num) { if (is_file(IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php')) { $_class = 'version_class_' . $app . '_' . $num; require_once IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php'; /*noLibHook*/ $_tmp = new $_class(ipsRegistry::instance()); if (method_exists($_tmp, 'preInstallOptionsSave')) { $_t = $_tmp->preInstallOptionsSave(); if (is_array($_t) and count($_t)) { $toSave[$app][$num] = $_t; } } } } } /* Save it */ if (count($toSave)) { IPSSetUp::setSavedData('custom_options', $toSave); } if (count($vNums)) { IPSSetUp::setSavedData('version_numbers', $vNums); } } /* Freeze data */ IPSSetUp::freezeSavedData(); /* Thaw it */ IPSSetUp::thawSavedData(); } /* Re run our controller */ ipsController::run(); }
/** * Execute selected method * * @access public * @param object Registry object * @return @e void */ public function doExecute(ipsRegistry $registry) { /* Check input? */ if ($this->request['do'] == 'check') { /* Check Directory */ if (!is_array($_POST['apps']) or !count($_POST['apps'])) { $this->registry->output->addError('You must select to install at least one application'); } else { /* Save Form Data */ IPSSetUp::setSavedData('install_apps', implode(',', array_keys($_POST['apps']))); /* Check writeable files */ foreach (array_keys($_POST['apps']) as $appDir) { $info = IPSSetUp::fetchXmlAppWriteableFiles($appDir); if (count($info['notexist'])) { foreach ($info['notexist'] as $path) { $this->registry->output->addWarning('File or directory does not exist: "' . $path . '", please create it via FTP'); } } if (count($info['notwrite'])) { foreach ($info['notwrite'] as $path) { $this->registry->output->addWarning('File or directory is not writeable: "' . $path . '", please CHMOD via FTP'); } } /** * Custom errors */ if (count($info['other'])) { foreach ($info['other'] as $error) { $this->registry->output->addWarning($error); } } } /* Do we have errors? */ if (!count($this->registry->output->fetchWarnings())) { /* Next Action */ $this->registry->autoLoadNextAction('address'); } } } /* Generate apps... */ $apps = array('core' => array(), 'ips' => array(), 'other' => array()); foreach (array('applications', 'applications_addon/ips', 'applications_addon/other') as $_pBit) { $path = IPS_ROOT_PATH . $_pBit; $handle = opendir($path); while (($file = readdir($handle)) !== FALSE) { if (!preg_match("#^\\.#", $file)) { if (is_dir($path . '/' . $file)) { //----------------------------------------- // Get it! //----------------------------------------- if (!is_file(IPS_ROOT_PATH . $_pBit . '/' . $file . '/xml/information.xml')) { continue; } $data = IPSSetUp::fetchXmlAppInformation($file, $this->settings['gb_char_set']); switch ($_pBit) { case 'applications': $apps['core'][$file] = $data; break; case 'applications_addon/ips': $apps['ips'][$file] = $data; break; case 'applications_addon/other': $apps['other'][$file] = $data; break; } } } } closedir($handle); } /* We don't want IP.SEO to be installed on future versions. Bad things happen. */ unset($apps['ips']['ipseo']); unset($apps['other']['ipseo']); /* Reorder the array so that core is first */ $new_array = array(); $new_array['core'] = $apps['core']['core']; foreach ($apps['core'] as $app => $data) { if ($app == 'core') { continue; } $new_array[$app] = $data; } $apps['core'] = $new_array; /* Page Output */ $this->registry->output->setTitle("Applications"); $this->registry->output->setNextAction('apps&do=check'); $this->registry->output->addContent($this->registry->output->template()->page_apps($apps)); $this->registry->output->sendOutput(); }
/** * Execute selected method * [ REPEAT FOR APPS: SQL > VERSION UPGRADER / FINISH ] -> SETTINGS > TEMPLATES > TASKS > LANGUAGES > PUBLIC LANGUAGES > BBCODE > ACP HELP OTHER [ Email Templates ] > Build Caches * * @access public * @param object Registry object * @return @e void */ public function doExecute(ipsRegistry $registry) { /* Set Up */ IPSSetUp::setSavedData('man', intval($this->request['man']) ? intval($this->request['man']) : IPSSetUp::getSavedData('man')); IPSSetUp::setSavedData('appdir', $this->request['appdir'] ? $this->request['appdir'] : IPSSetUp::getSavedData('appdir')); IPSSetUp::setSavedData('helpfile', intval($this->request['helpfile']) ? intval($this->request['helpfile']) : IPSSetUp::getSavedData('helpfile')); /* Do we have a current application? */ if (!IPSSetUp::getSavedData('appdir')) { $_app = IPSSetUp::fetchNextApplication('', '', $this->settings['gb_char_set']); IPSSetUp::setSavedData('appdir', $_app['key']); } /* Set current app */ $this->_currentApp = IPSSetUp::getSavedData('appdir'); /* Fetch numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($this->_currentApp); /* Set numbers */ $this->_currentLong = $numbers['current'][0]; $this->_currentHuman = $numbers['current'][1]; $this->_uipLong = $numbers['next'][0]; $this->_uipHuman = $numbers['next'][1]; $this->_latestLong = $numbers['latest'][0]; $this->_latestHuman = $numbers['latest'][1]; $this->_dbDriver = strtolower($this->settings['sql_driver']); if ($this->_currentApp) { $this->_appData = IPSSetUp::fetchXmlAppInformation($this->_currentApp, $this->settings['gb_char_set']); if ($this->_currentApp == 'core') { $this->_appData['name'] = 'IP.Board'; } } /* Fail safe */ if (!$this->_currentApp) { print "No app"; exit; } $this->registry->output->setVersionAndApp($this->_uipHuman, $this->_appData); /* Switch */ switch ($this->request['do']) { case 'sql': $this->_stepCount = 1; $this->install_sql(); break; case 'appclass': $this->_stepCount = 2; $this->install_appclass(); break; case 'checkdb': $this->_stepCount = 3; $this->install_checkdb(); break; case 'modules': $this->_stepCount = 4; $this->install_modules(); break; case 'settings': $this->_stepCount = 5; $this->install_settings(); break; case 'templates': $this->_stepCount = 6; $this->install_templates(); break; case 'tasks': $this->_stepCount = 7; $this->install_tasks(); break; case 'languages': $this->_stepCount = 8; $this->install_languages(); break; case 'clientlanguages': $this->_stepCount = 9; $this->install_client_languages(); break; case 'bbcode': $this->_stepCount = 10; $this->install_bbcode(); break; case 'acphelp': $this->_stepCount = 11; $this->install_acphelp(); break; case 'other': $this->_stepCount = 12; $this->install_other(); break; case 'caches': $this->_stepCount = 13; $this->install_caches(); break; case 'templatecache': $this->_stepCount = 14; $this->install_template_caches(); break; default: $this->_splash(); break; } /* Log errors for support */ if (count($this->_errorMsg) > 0) { IPSSetUp::addLogMessage(implode("\n", $this->_errorMsg), $this->_uipHuman, $this->_currentApp); } }
/** * Install Applications * * @return void */ public function install_applications() { //----------------------------------------- // INIT //----------------------------------------- $previous = $_REQUEST['previous']; $num = intval($_REQUEST['num']) + 1; //----------------------------------------- // Fetch next 'un //----------------------------------------- $next = IPSSetUp::fetchNextApplication($previous, '', $this->settings['gb_char_set']); /* Set up DB driver */ $extra_install = $this->_setUpDBDriver(FALSE); //----------------------------------------- // Install APP Data //----------------------------------------- if ($next['key']) { $output[] = $next['title'] . ": Добавление данных приложений"; $_PATH = IPSLib::getAppDir($next['key']) . '/xml/'; $_protected = in_array($next['key'], array('core', 'forums', 'members')) ? 1 : 0; $version = '1.0.0'; $long_version = '10000'; $_versions = array(); if (is_file($_PATH . 'versions.xml')) { require_once IPS_KERNEL_PATH . 'classXML.php'; /*noLibHook*/ $xml = new classXML(IPSSetUp::charSet); $xml->load($_PATH . 'versions.xml'); foreach ($xml->fetchElements('version') as $xmlelement) { $data = $xml->fetchElementsFromRecord($xmlelement); $_versions[$data['long']] = $data; } krsort($_versions); $_this_version = current($_versions); $version = $_this_version['human']; $long_version = $_this_version['long']; } if (is_file($_PATH . 'information.xml')) { //----------------------------------------- // Adjust the table? //----------------------------------------- if ($extra_install and method_exists($extra_install, 'before_inserts_run')) { $q = $extra_install->before_inserts_run('applications'); } //----------------------------------------- // Continue //----------------------------------------- $appData = IPSSetUp::fetchXmlAppInformation($next['key'], $this->settings['gb_char_set']); //----------------------------------------- // Insert... //----------------------------------------- $this->DB->insert('core_applications', array('app_title' => $appData['name'], 'app_public_title' => $appData['public_name'] ? $appData['public_name'] : '', 'app_description' => $appData['description'], 'app_author' => $appData['author'], 'app_hide_tab' => intval($appData['hide_tab']), 'app_version' => $version, 'app_long_version' => $long_version, 'app_directory' => $next['key'], 'app_added' => time(), 'app_position' => isset($this->forcePositions[$next['key']]) ? $this->forcePositions[$next['key']] : $num, 'app_protected' => $_protected, 'app_location' => IPSLib::extractAppLocationKey($next['key']), 'app_enabled' => $appData['disabledatinstall'] ? 0 : 1, 'app_website' => $appData['website'], 'app_update_check' => $appData['update_check'], 'app_global_caches' => $appData['global_caches'])); $this->DB->insert('upgrade_history', array('upgrade_version_id' => $long_version, 'upgrade_version_human' => $version, 'upgrade_date' => 0, 'upgrade_mid' => 0, 'upgrade_notes' => '', 'upgrade_app' => $next['key'])); //----------------------------------------- // Adjust the table? //----------------------------------------- if ($extra_install and method_exists($extra_install, 'after_inserts_run')) { $q = $extra_install->after_inserts_run('applications'); } } //----------------------------------------- // Done.. so get some more! //----------------------------------------- $this->_finishStep($output, "Установка: Приложения", 'install&do=applications&previous=' . $next['key'] . '&num=' . $num); } else { //----------------------------------------- // Next... //----------------------------------------- $output[] = "Приложения установлены"; $this->_finishStep($output, "Установка: Приложения", 'install&do=modules'); } }
/** * List applications * * @return @e void [Outputs to screen] */ public function applicationsOverview() { /* Init vars */ $folders = array(); $applications = array('enabled' => array('core' => array()), 'disabled' => array()); $_apps = array(); $uninstalled = array(); $checkUpdates = false; $appsUpdates = 0; $message = ''; /* Get the setup class */ require_once IPS_ROOT_PATH . "setup/sources/base/setup.php"; /*noLibHook*/ /* Checking for updates? */ if (!empty($this->request['checkUpdates'])) { $checkUpdates = true; /* Get hooks file for update check */ $classToLoad = IPSLib::loadActionOverloader(IPSLib::getAppDir('core') . '/modules_admin/applications/hooks.php', 'admin_core_applications_hooks'); $hooksClass = new $classToLoad(); $hooksClass->makeRegistryShortcuts($this->registry); } //----------------------------------------- // Get DB applications //----------------------------------------- $this->DB->build(array('select' => '*', 'from' => 'core_applications', 'order' => 'app_position')); $this->DB->execute(); while ($row = $this->DB->fetch()) { /* Got updates? */ if ($row['app_update_check'] && $checkUpdates === true) { $row['app_update_available'] = $hooksClass->_updateAvailable($row['app_update_check'], $row['app_long_version']); if ($row['app_update_available'][0]) { $appsUpdates++; } } else { $row['app_update_available'] = array(0); } $_apps[IPSLib::getAppFolder($row['app_directory']) . '/' . $row['app_directory']] = $row; } //----------------------------------------- // Get folder applications... //----------------------------------------- foreach (array('applications', 'applications_addon/ips', 'applications_addon/other') as $folder) { try { foreach (new DirectoryIterator(IPS_ROOT_PATH . $folder) as $file) { if (!$file->isDot() and $file->isDir()) { $_name = $file->getFileName(); if (substr($_name, 0, 1) != '.') { $folders[$folder . '/' . $_name] = $_name; } } } } catch (Exception $e) { } } //----------------------------------------- // Installed Loop... //----------------------------------------- foreach ($_apps as $_app_path => $row) { $app_dir = $row['app_directory']; /* Version numbers */ $_a = ($app_dir == 'forums' or $app_dir == 'members') ? 'core' : $app_dir; $numbers = IPSSetUp::fetchAppVersionNumbers($_a); $row['_human_version'] = $numbers['latest'][1]; $row['_long_version'] = $numbers['latest'][0]; $row['_human_current'] = $numbers['current'][1]; $row['_long_current'] = $numbers['current'][0]; /* Nexus? */ if ($row['app_directory'] == 'nexus') { $encoding = 'Unencoded'; $file = file_get_contents(IPSLib::getAppDir('nexus') . '/app_class_nexus.php'); if (substr($file, 6, 5) == '@Zend') { $phpVersion = phpversion(); $phpVersion = str_replace(substr($phpVersion, strrpos($phpVersion, '.')), '', $phpVersion); $encoding = "Zend {$phpVersion}"; } elseif (substr($file, 36, 7) == 'ionCube' or substr($file, 37, 7) == 'ionCube') { $encoding = 'Ioncube'; } $row['_human_current'] .= " ({$encoding})"; } if ($row['app_enabled']) { $applications['enabled'][$row['app_directory']] = $row; } else { $applications['disabled'][$row['app_directory']] = $row; } } //----------------------------------------- // Uninstalled //----------------------------------------- foreach ($folders as $filepath => $_file) { if (!in_array($filepath, array_keys($_apps))) { $info = IPSSetUp::fetchXmlAppInformation($_file, $this->settings['gb_char_set']); /* OK, we're making no effort to conceal the secret behind the ipskey. It's an honourable setting - do not abuse it. We only mildly obfuscate it to stop copy and paste mistakes in information.xml */ $okToGo = 0; if (strstr($filepath, 'applications_addon/ips') or strstr($filepath, 'applications/')) { if (md5('ips_' . $_file) == $info['ipskey']) { $okToGo = 1; } } else { if (strstr($filepath, 'applications_addon/other')) { if (!$info['ipskey']) { $okToGo = 1; } } } if ($info['name'] && $info['key'] != "ipseo") { $uninstalled[$_file] = array('title' => $info['name'], 'author' => $info['author'], 'path' => $filepath, 'okToGo' => $okToGo, 'directory' => $_file); } } } /* Got updates to show? */ if ($checkUpdates === true) { $message = $appsUpdates == 1 ? $this->lang->words['updates_string_single'] : sprintf($this->lang->words['updates_string_more'], $appsUpdates); } /* Output */ $this->registry->output->html .= $this->html->applications_list($applications, $uninstalled, $message); }
/** * Execute selected method * * @access public * @param object Registry object * @return void */ public function doExecute(ipsRegistry $registry) { /* Save data */ if ($this->request['do'] == 'save') { $apps = explode(',', IPSSetUp::getSavedData('install_apps')); $toSave = array(); $vNums = array(); if (is_array($apps) and count($apps)) { foreach ($apps as $app) { /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); /* Grab all numbers */ $nums[$app] = IPSSetUp::fetchXmlAppVersions($app); /* Grab app data */ $appData[$app] = IPSSetUp::fetchXmlAppInformation($app); $appClasses[$app] = IPSSetUp::fetchVersionClasses($app, $numbers['current'][0], $numbers['latest'][0]); /* Store starting vnums */ $vNums[$app] = $numbers['current'][0]; } /* Got anything? */ if (count($appClasses)) { foreach ($appClasses as $app => $data) { foreach ($data as $num) { if (file_exists(IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php')) { $_class = 'version_class_' . $num; require_once IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php'; $_tmp = new $_class($this->registry); if (method_exists($_tmp, 'preInstallOptionsSave')) { $_t = $_tmp->preInstallOptionsSave(); if (is_array($_t) and count($_t)) { $toSave[$app][$num] = $_t; } } } } } /* Save it */ if (count($toSave)) { IPSSetUp::setSavedData('custom_options', $toSave); } if (count($vNums)) { IPSSetUp::setSavedData('version_numbers', $vNums); } } } /* Next Action */ $this->registry->autoLoadNextAction('upgrade'); } else { if ($this->request['do'] == 'check') { /* Check Directory */ if (!is_array($_POST['apps']) or !count($_POST['apps'])) { $this->registry->output->addError('You must select to upgrade at least one application'); } else { /* If it's lower than 3.0.0, then add in the removed apps */ if (IPSSetUp::is300plus() !== TRUE) { $_POST['apps']['forums'] = 1; $_POST['apps']['members'] = 1; $_POST['apps']['calendar'] = 1; $_POST['apps']['chat'] = 1; $_POST['apps']['portal'] = 1; //$_POST['apps']['subscriptions'] = 1; } else { if ($_POST['apps']['core']) { $_POST['apps']['forums'] = 1; $_POST['apps']['members'] = 1; } } /* Save Form Data */ IPSSetUp::setSavedData('install_apps', implode(',', array_keys($_POST['apps']))); /* Got any app-version classes? */ $appClasses = array(); $output = array(); $nums = array(); $appData = array(); foreach ($_POST['apps'] as $app => $val) { /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); /* Grab all numbers */ $nums[$app] = IPSSetUp::fetchXmlAppVersions($app); /* Grab app data */ $appData[$app] = IPSSetUp::fetchXmlAppInformation($app); $appClasses[$app] = IPSSetUp::fetchVersionClasses($app, $numbers['current'][0], $numbers['latest'][0]); } /* Got anything? */ if (count($appClasses)) { foreach ($appClasses as $app => $data) { foreach ($data as $num) { if (file_exists(IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php')) { $_class = 'version_class_' . $num; require_once IPSLib::getAppDir($app) . '/setup/versions/upg_' . $num . '/version_class.php'; $_tmp = new $_class($this->registry); if (method_exists($_tmp, 'preInstallOptionsForm')) { $_t = $_tmp->preInstallOptionsForm(); if ($_t) { $output[$app][$num] = array('long' => $nums[$app][$num], 'app' => $appData[$app], 'out' => $_t); } } } } } } /* Finally... */ if (count($output)) { $this->registry->output->setTitle("Applications"); $this->registry->output->setNextAction('apps&do=save'); //$this->registry->output->setHideButton( TRUE ); $this->registry->output->addContent($this->registry->output->template()->upgrade_appsOptions($output)); $this->registry->output->sendOutput(); } else { /* Next Action */ $this->registry->autoLoadNextAction('upgrade'); } } } } /* Generate apps... */ $apps = array('core' => array(), 'ips' => array(), 'other' => array()); foreach (array('applications', 'applications_addon/ips', 'applications_addon/other') as $_pBit) { $path = IPS_ROOT_PATH . $_pBit; $handle = opendir($path); while (($file = readdir($handle)) !== FALSE) { if (!preg_match("#^\\.#", $file)) { if (is_dir($path . '/' . $file)) { //----------------------------------------- // Get it! //----------------------------------------- if (!file_exists(IPS_ROOT_PATH . $_pBit . '/' . $file . '/xml/information.xml')) { continue; } $data = IPSSetUp::fetchXmlAppInformation($file); switch ($_pBit) { case 'applications': $apps['core'][$file] = $data; break; case 'applications_addon/ips': $apps['ips'][$file] = $data; break; case 'applications_addon/other': $apps['other'][$file] = $data; break; } } } } closedir($handle); } /* Reorder the array so that core is first */ $new_array = array(); $new_array['core'] = $apps['core']['core']; foreach ($apps['core'] as $app => $data) { if ($app == 'core') { continue; } $new_array[$app] = $data; } $apps['core'] = $new_array; /* Now get version numbers */ foreach ($apps as $type => $app) { foreach ($apps[$type] as $app => $data) { if ($type == 'core' and ($app == 'forums' or $app == 'members')) { /* Skip forums and members and just count core for now */ continue; } /* Grab version numbers */ $numbers = IPSSetUp::fetchAppVersionNumbers($app); $apps[$type][$app]['_vnumbers'] = $numbers; } } /* If it's lower than 3.0.0, then remove some apps and make them part of 'core' */ if (IPSSetUp::is300plus() !== TRUE) { unset($apps['ips']['calendar']); unset($apps['ips']['chat']); unset($apps['ips']['portal']); unset($apps['other']['subscriptions']); } /* Page Output */ $this->registry->output->setTitle("Applications"); $this->registry->output->setNextAction('apps&do=check'); //$this->registry->output->setHideButton( TRUE ); $this->registry->output->addContent($this->registry->output->template()->upgrade_apps($apps)); $this->registry->output->sendOutput(); }
/** * Add Applications * * @access public * @param int */ public function addApplications() { /* Add applications.. */ $apps = array('core' => array(), 'ips' => array(), 'other' => array()); $components = array(); foreach (array('applications', 'applications_addon/ips', 'applications_addon/other') as $_pBit) { $path = IPS_ROOT_PATH . $_pBit; $handle = opendir($path); while (($file = readdir($handle)) !== FALSE) { if (!preg_match("#^\\.#", $file)) { if (is_dir($path . '/' . $file)) { //----------------------------------------- // Get it! //----------------------------------------- if (!file_exists(IPS_ROOT_PATH . $_pBit . '/' . $file . '/xml/information.xml')) { continue; } $data = IPSSetUp::fetchXmlAppInformation($file); switch ($_pBit) { case 'applications': $apps['core'][$file] = $data; break; case 'applications_addon/ips': $apps['ips'][$file] = $data; break; case 'applications_addon/other': $apps['other'][$file] = $data; break; } } } } closedir($handle); } /* Reorder the array so that core is first */ $new_array = array(); $new_array['core'] = $apps['core']['core']; foreach ($apps['core'] as $app => $data) { if ($app == 'core') { continue; } $new_array[$app] = $data; } $apps['core'] = $new_array; /* Fetch data for current 'components' */ $this->DB->build(array('select' => '*', 'from' => 'components')); $this->DB->execute(); while ($row = $this->DB->fetch()) { $components[$row['com_section']] = $row; } /* Got Gallery? */ if ($components['gallery']['com_enabled'] and $this->DB->checkForTable('gallery_upgrade_history')) { /* Fetch current version number */ $version = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'gallery_upgrade_history', 'order' => 'gallery_version_id DESC', 'limit' => array(0, 1))); $apps['ips']['gallery']['_currentLong'] = $version['gallery_version_id']; $apps['ips']['gallery']['_currentHuman'] = $version['gallery_version_human']; } /* Got Blog? */ if ($components['blog']['com_enabled'] and $this->DB->checkForTable('blog_upgrade_history')) { /* Fetch current version number */ $version = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'blog_upgrade_history', 'order' => 'blog_version_id DESC', 'limit' => array(0, 1))); $apps['ips']['blog']['_currentLong'] = $version['blog_version_id']; $apps['ips']['blog']['_currentHuman'] = $version['blog_version_human']; } /* Got Downloads? */ if ($components['downloads']['com_enabled'] and $this->DB->checkForTable('downloads_upgrade_history')) { /* Fetch current version number */ $version = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'downloads_upgrade_history', 'order' => 'idm_version_id DESC', 'limit' => array(0, 1))); $apps['ips']['downloads']['_currentLong'] = $version['idm_version_id']; $apps['ips']['downloads']['_currentHuman'] = $version['idm_version_human']; } /* Others.. */ $apps['core']['forums']['_currentLong'] = '30001'; $apps['core']['forums']['_currentHuman'] = '3.0.0'; $apps['core']['core']['_currentLong'] = '30001'; $apps['core']['core']['_currentHuman'] = '3.0.0'; $apps['core']['members']['_currentLong'] = '30001'; $apps['core']['members']['_currentHuman'] = '3.0.0'; $apps['ips']['portal']['_currentLong'] = '30003'; $apps['ips']['portal']['_currentHuman'] = '3.0.0'; $apps['ips']['chat']['_currentLong'] = '30003'; $apps['ips']['chat']['_currentHuman'] = '3.0.0'; $apps['ips']['calendar']['_currentLong'] = '30003'; $apps['ips']['calendar']['_currentHuman'] = '3.0.0'; /* Now install them.. */ $num = 0; foreach ($apps as $where => $data) { foreach ($apps[$where] as $dir => $appData) { //----------------------------------------- // Had Gallery (e.g.) but didn't upload updated files //----------------------------------------- if (!$appData['name']) { continue; } $num++; $_protected = in_array($appData['key'], array('core', 'forums', 'members')) ? 1 : 0; $_enabled = $appData['disabledatinstall'] ? 0 : 1; if (!$appData['_currentLong']) { continue; } $this->registry->output->addMessage("Adding application: {$appData['name']}...."); $this->DB->insert('core_applications', array('app_title' => $appData['name'], 'app_public_title' => $appData['public_name'] ? $appData['public_name'] : '', 'app_description' => $appData['description'], 'app_author' => $appData['author'], 'app_hide_tab' => intval($appData['hide_tab']), 'app_version' => $appData['_currentHuman'], 'app_long_version' => $appData['_currentLong'], 'app_directory' => $appData['key'], 'app_added' => time(), 'app_position' => $num, 'app_protected' => $_protected, 'app_location' => IPSLib::extractAppLocationKey($appData['key']), 'app_enabled' => $_enabled)); } } /* Next Page */ $this->request['workact'] = 'settings'; }
/** * List applications * * @access private * @return void [Outputs to screen] */ private function applicationsOverview() { //----------------------------------------- // INIT //----------------------------------------- $folders = array(); $application = array(); $_apps = array(); $seen_count = 0; $total_items = 0; $uninstalled = array(); /* Get the setup class */ require IPS_ROOT_PATH . "setup/sources/base/setup.php"; //----------------------------------------- // Get DB applications //----------------------------------------- $this->DB->build(array('select' => '*', 'from' => 'core_applications', 'order' => 'app_position')); $this->DB->execute(); while ($row = $this->DB->fetch()) { $_apps[IPSLib::getAppFolder($row['app_directory']) . '/' . $row['app_directory']] = $row; $total_items++; } //----------------------------------------- // Get folder applications... //----------------------------------------- foreach (array('applications', 'applications_addon/ips', 'applications_addon/other') as $folder) { try { foreach (new DirectoryIterator(IPS_ROOT_PATH . $folder) as $file) { if (!$file->isDot() and $file->isDir()) { $_name = $file->getFileName(); if (substr($_name, 0, 1) != '.') { $folders[$folder . '/' . $_name] = $_name; } } } } catch (Exception $e) { } } //----------------------------------------- // Installed Loop... //----------------------------------------- foreach ($_apps as $_app_path => $row) { $app_dir = $row['app_directory']; //----------------------------------------- // Enabled? //----------------------------------------- $row['_app_enabled'] = $row['app_enabled'] ? 'tick.png' : 'cross.png'; /* Version numbers */ $_a = ($app_dir == 'forums' or $app_dir == 'members') ? 'core' : $app_dir; $numbers = IPSSetUp::fetchAppVersionNumbers($_a); $row['_human_version'] = $numbers['latest'][1]; $row['_long_version'] = $numbers['latest'][0]; $row['_human_current'] = $numbers['current'][1]; $row['_long_current'] = $numbers['current'][0]; /* Exists? */ if (!file_exists(IPSLib::getAppDir($app_dir))) { $row['_missing'] = 1; } $seen_count++; $application[$row['app_location']][] = $row; } /* Make sure they are in the proper order, hacky but it works :) */ $__apps = array(); $__apps['root'] = $application['root'] ? $application['root'] : array(); $__apps['ips'] = $application['ips'] ? $application['ips'] : array(); $__apps['other'] = $application['other'] ? $application['other'] : array(); $application = $__apps; //----------------------------------------- // Uninstalled //----------------------------------------- foreach ($folders as $filepath => $_file) { if (!in_array($filepath, array_keys($_apps))) { $info = IPSSetUp::fetchXmlAppInformation($_file); /* OK, we're making no effort to conceal the secret behind the ipskey. It's an honourable setting - do not abuse it. We only mildly obfuscate it to stop copy and paste mistakes in information.xml */ $okToGo = 0; if (strstr($filepath, 'applications_addon/ips') or strstr($filepath, 'applications/')) { if (md5('ips_' . $_file) == $info['ipskey']) { $okToGo = 1; } } else { if (strstr($filepath, 'applications_addon/other')) { if (!$info['ipskey']) { $okToGo = 1; } } } $uninstalled[$_file] = array('title' => $info['name'], 'author' => $info['author'], 'path' => $filepath, 'okToGo' => $okToGo, 'directory' => $_file); } } //----------------------------------------- // Show it... //----------------------------------------- $this->registry->output->html .= $this->html->applications_list($application, $uninstalled); }