Index: branches/RC/core/install.php =================================================================== diff -u -N --- branches/RC/core/install.php (revision 11892) +++ branches/RC/core/install.php (revision 0) @@ -1,1340 +0,0 @@ -Init(); - $install_engine->Run(); - $install_engine->Done(); - - class kInstallator { - - /** - * Reference to kApplication class object - * - * @var kApplication - */ - var $Application = null; - - /** - * Connection to database - * - * @var kDBConnection - */ - var $Conn = null; - - /** - * XML file containing steps information - * - * @var string - */ - var $StepDBFile = ''; - - /** - * Step name, that currently being processed - * - * @var string - */ - var $currentStep = ''; - - /** - * Steps list (preset) to use for current installation - * - * @var string - */ - var $stepsPreset = ''; - - /** - * Installtion steps to be done - * - * @var Array - */ - var $steps = Array ( - 'fresh_install' => Array ('check_paths', 'db_config', 'select_license', 'download_license', 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'finish'), - 'clean_reinstall' => Array ('check_paths', 'clean_db', 'db_config', 'select_license', 'download_license', 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'finish'), - 'already_installed' => Array ('check_paths', 'install_setup'), - - 'upgrade' => Array ('check_paths', 'install_setup', 'upgrade_modules', 'finish'), - 'update_license' => Array ('check_paths', 'install_setup', 'select_license', 'download_license', 'select_domain', 'finish'), - 'db_reconfig' => Array ('check_paths', 'install_setup', 'db_reconfig', 'finish'), - 'fix_paths' => Array ('check_paths', 'install_setup', 'fix_paths', 'finish'), - ); - - /** - * Steps, that doesn't required admin to be logged-in to proceed - * - * @var Array - */ - var $skipLoginSteps = Array ('check_paths', 'select_license', 'download_license', 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'finish', -1); - - /** - * Steps, on which kApplication should not be initialized, because of missing correct db table structure - * - * @var Array - */ - var $skipApplicationSteps = Array ('check_paths', 'clean_db', 'db_config', 'db_reconfig' /*, 'install_setup'*/); // remove install_setup when application will work separately from install - - /** - * Folders that should be writeable to continue installation. $1 - main writeable folder from config.php ("/system" by default) - * - * @var Array - */ - var $writeableFolders = Array ( - '$1', - '$1/images', - '$1/images/resized', - '$1/images/pending', - '$1/images/pending/resized', - '$1/images/emoticons', // for "In-Bulletin" - '$1/images/manufacturers', // for "In-Commerce" - '$1/images/manufacturers/resized', // for "In-Commerce" - '$1/backupdata', - '$1/export', - '$1/stylesheets', - '$1/user_files', - '$1/cache', - '/themes', - ); - - /** - * Contains last error message text - * - * @var string - */ - var $errorMessage = ''; - - /** - * Base path for includes in templates - * - * @var string - */ - var $baseURL = ''; - - /** - * Holds number of last executed query in the SQL - * - * @var int - */ - var $LastQueryNum = 0; - - /** - * Common tools required for installation process - * - * @var kInstallToolkit - */ - var $toolkit = null; - - function Init() - { - include_once(FULL_PATH . REL_PATH . '/kernel/utility/multibyte.php'); // emulating multi-byte php extension - require_once(FULL_PATH . REL_PATH . '/install/install_toolkit.php'); // toolkit required for module installations to installator - $this->toolkit = new kInstallToolkit(); - $this->toolkit->setInstallator($this); - - $this->StepDBFile = FULL_PATH.'/'.REL_PATH.'/install/steps_db.xml'; - - $base_path = rtrim(preg_replace('/'.preg_quote(rtrim(REL_PATH, '/'), '/').'$/', '', str_replace('\\', '/', dirname($_SERVER['PHP_SELF']))), '/'); - $this->baseURL = 'http://'.$_SERVER['HTTP_HOST'].$base_path.'/core/install/'; - - set_error_handler( Array(&$this, 'ErrorHandler') ); - - if (file_exists($this->toolkit->INIFile)) { - // if config.php found, then check his write permission too - $this->writeableFolders[] = '/config.php'; - } - else { - $this->writeableFolders[] = '/'; - } - - if (!$this->toolkit->getSystemConfig('Misc', 'WriteablePath')) { - // set global writable folder when such setting is missing - $this->toolkit->setSystemConfig('Misc', 'WriteablePath', DIRECTORY_SEPARATOR . 'system'); - $this->toolkit->SaveConfig(true); // immediately save, because this path will be used in Application later - } - - $this->currentStep = $this->GetVar('step'); - - // can't check login on steps where no application present anyways :) - $this->skipLoginSteps = array_unique(array_merge($this->skipLoginSteps, $this->skipApplicationSteps)); - - $this->SelectPreset(); - - if (!$this->currentStep) { - $this->SetFirstStep(); // sets first step of current preset - } - - $this->InitStep(); - } - - function SetFirstStep() - { - reset($this->steps[$this->stepsPreset]); - $this->currentStep = current($this->steps[$this->stepsPreset]); - } - - /** - * Selects preset to proceed based on various criteria - * - */ - function SelectPreset() - { - $preset = $this->GetVar('preset'); - if ($this->toolkit->systemConfigFound()) { - // only at installation first step - $status = $this->CheckDatabase(false); - if ($status && $this->AlreadyInstalled()) { - // if already installed, then all future actions need login to work - $this->skipLoginSteps = Array ('check_paths', -1); - if (!$preset) { - $preset = 'already_installed'; - $this->currentStep = ''; - } - } - } - if ($preset === false) { - $preset = 'fresh_install'; // default preset - } - - $this->stepsPreset = $preset; - } - - function GetVar($name) - { - return array_key_exists($name, $_REQUEST) ? $_REQUEST[$name] : false; - } - - function SetVar($name, $value) - { - $_REQUEST[$name] = $value; - } - - /** - * Performs needed intialization of data, that step requires - * - */ - function InitStep() - { - $require_login = !in_array($this->currentStep, $this->skipLoginSteps); - $this->InitApplication($require_login); - - if ($require_login) { - // step require login to proceed - if (!$this->Application->LoggedIn()) { - $this->stepsPreset = 'already_installed'; - $this->currentStep = 'install_setup'; // manually set 2nd step, because 'check_paths' step doesn't contain login form -// $this->SetFirstStep(); - } - } - - switch ($this->currentStep) { - case 'check_paths': - $writeable_base = $this->toolkit->getSystemConfig('Misc', 'WriteablePath'); - foreach ($this->writeableFolders as $folder_path) { - $file_path = FULL_PATH . str_replace('$1', $writeable_base, $folder_path); - if (file_exists($file_path) && !is_writable($file_path)) { - $this->errorMessage = 'Install cannot write to specified folder in the root directory of your installation'; - break; - } - } - break; - - case 'clean_db': - // don't use Application, because all tables will be erased and it will crash - $sql = 'SELECT Path - FROM ' . TABLE_PREFIX . 'Modules'; - $modules = $this->Conn->GetCol($sql); - - foreach ($modules as $module_folder) { - $remove_file = '/' . $module_folder . 'install/remove_schema.sql'; - if (file_exists(FULL_PATH . $remove_file)) { - $this->toolkit->RunSQL($remove_file); - } - } - - $this->currentStep = $this->GetNextStep(); - break; - - case 'db_config': - case 'db_reconfig': - $fields = Array ( - 'DBType', 'DBHost', 'DBName', 'DBUser', - 'DBUserPassword', 'DBCollation', 'TablePrefix' - ); - - // set fields - foreach ($fields as $field_name) { - $submit_value = $this->GetVar($field_name); - - if ($submit_value !== false) { - $this->toolkit->setSystemConfig('Database', $field_name, $submit_value); - } - /*else { - $this->toolkit->setSystemConfig('Database', $field_name, ''); - }*/ - } - break; - - case 'download_license': - $license_source = $this->GetVar('license_source'); - if ($license_source !== false && $license_source != 1) { - // previous step was "Select License" and not "Download from Intechnic" option was selected - $this->currentStep = $this->GetNextStep(); - } - break; - - case 'choose_modules': - // if no modules found, then proceed to next step - $modules = $this->ScanModules(); - if (!$modules) { - $this->currentStep = $this->GetNextStep(); - } - break; - - case 'select_theme': - if (count($this->toolkit->getThemes(true)) == 1) { - // only one theme -> set it as primary - $sql = 'UPDATE ' . $this->Application->getUnitOption('theme', 'TableName') . ' - SET Enabled = 1, PrimaryTheme = 1 - LIMIT 1'; - $this->Conn->Query($sql); - - $this->toolkit->rebuildThemes(); // rescan theme to create structure after theme is enabled !!! - - $this->currentStep = $this->GetNextStep(); - } - break; - - case 'upgrade_modules': - // get installed modules from db and compare their versions to upgrade script - $modules = $this->GetUpgradableModules(); - if (!$modules) { - $this->currentStep = $this->GetNextStep(); - } - break; - - case 'install_setup': - $next_preset = $this->Application->GetVar('next_preset'); - if ($next_preset !== false) { - if ($this->Application->GetVar('login') == 'root') { - // verify "root" user using configuration settings - $login_event = new kEvent('u.current:OnLogin'); - $this->Application->HandleEvent($login_event); - - if ($login_event->status != erSUCCESS) { - $user =& $this->Application->recallObject('u.current'); - /* @var $user UsersItem */ - - $this->errorMessage = $user->GetErrorMsg('ValidateLogin') . '. If you don\'t know your username or password, contact Intechnic Support'; - } - } - else { - // non "root" user -> verify using licensing server - $url_params = Array ( - 'login=' . md5( $this->GetVar('login') ), - 'password=' . md5( $this->GetVar('password') ), - 'action=check', - 'license_code=' . base64_encode( $this->toolkit->getSystemConfig('Intechnic', 'LicenseCode') ), - 'version=' . '4.3.0',//$this->toolkit->GetMaxModuleVersion('In-Portal'), - 'domain=' . base64_encode($_SERVER['HTTP_HOST']), - ); - - $license_url = GET_LICENSE_URL . '?' . implode('&', $url_params); - $file_data = curl_post($license_url, '', null, 'GET'); - - if (substr($file_data, 0, 5) == 'Error') { - $this->errorMessage = substr($file_data, 6) . ' If you don\'t know your username or password, contact Intechnic Support'; - } - - if ($this->errorMessage == '') { - $user_id = -1; - $session =& $this->Application->recallObject('Session'); - $session->SetField('PortalUserId', $user_id); - $this->Application->SetVar('u.current_id', $user_id); - $this->Application->StoreVar('user_id', $user_id); - } - } - - if ($this->errorMessage == '') { - // processed with redirect to selected step preset - if (!isset($this->steps[$next_preset])) { - $this->errorMessage = 'Preset "'.$next_preset.'" not yet implemented'; - } - else { - $this->stepsPreset = $next_preset; - } - } - } - else { - // if preset was not choosen, then raise error - $this->errorMessage = 'Please select action to perform'; - } - break; - } - - $this->PerformValidation(); // returns validation status (just in case) - } - - /** - * Validates data entered by user - * - * @return bool - */ - function PerformValidation() - { - if ($this->GetVar('step') != $this->currentStep) { - // just redirect from previous step, don't validate - return true; - } - - $status = true; - - switch ($this->currentStep) { - case 'db_config': - case 'db_reconfig': - // 1. check if required fields are filled - $section_name = 'Database'; - $required_fields = Array ('DBType', 'DBHost', 'DBName', 'DBUser', 'DBCollation'); - foreach ($required_fields as $required_field) { - if (!$this->toolkit->getSystemConfig($section_name, $required_field)) { - $status = false; - $this->errorMessage = 'Please fill all required fields'; - break; - } - } - if (!$status) break; - - // 2. check permissions, that use have in this database - $status = $this->CheckDatabase(($this->currentStep == 'db_config') && !$this->GetVar('UseExistingSetup')); - break; - - case 'select_license': - $license_source = $this->GetVar('license_source'); - if ($license_source == 2) { - // license from file -> file must be uploaded - $upload_error = $_FILES['license_file']['error']; - if ($upload_error != UPLOAD_ERR_OK) { - $this->errorMessage = 'Missing License File'; - } - } - elseif (!is_numeric($license_source)) { - $this->errorMessage = 'Please select license'; - } - - $status = $this->errorMessage == ''; - break; - - case 'root_password': - // check, that password & verify password match - $password = $this->Application->GetVar('root_password'); - $password_verify = $this->Application->GetVar('root_password_verify'); - - if ($password != $password_verify) { - $this->errorMessage = 'Passwords does not match'; - } - elseif (mb_strlen($password) < 4) { - $this->errorMessage = 'Root Password must be at least 4 characters'; - } - - $status = $this->errorMessage == ''; - break; - - case 'choose_modules': - case 'upgrade_modules': - $modules = $this->Application->GetVar('modules'); - if (!$modules) { - $modules = Array (); - $this->errorMessage = 'Please select module(-s) to ' . ($this->currentStep == 'choose_modules' ? 'install' : 'upgrade'); - } - - if ($this->currentStep == 'choose_modules') { - // don't check interface modules during install, only for during upgrade - break; - } - - // check interface module - if (!in_array('core', $modules)) { - $this->errorMessage = 'Please select "Core" as interface module'; - } - - $status = $this->errorMessage == ''; - break; - } - - return $status; - } - - /** - * Perform installation step actions - * - */ - function Run() - { - if ($this->errorMessage) { - // was error during data validation stage - return ; - } - - switch ($this->currentStep) { - case 'db_config': - case 'db_reconfig': - // store db configuration - $sql = 'SHOW COLLATION - LIKE \''.$this->toolkit->getSystemConfig('Database', 'DBCollation').'\''; - $collation_info = $this->Conn->Query($sql); - if ($collation_info) { - $this->toolkit->setSystemConfig('Database', 'DBCharset', $collation_info[0]['Charset']); - - // database is already connected, that's why set collation on the fly - $this->Conn->Query('SET NAMES \''.$this->toolkit->getSystemConfig('Database', 'DBCharset').'\' COLLATE \''.$this->toolkit->getSystemConfig('Database', 'DBCollation').'\''); - } - - $this->toolkit->SaveConfig(); - - if ($this->currentStep == 'db_config') { - if ($this->GetVar('UseExistingSetup')) { - // abort clean install and redirect to already_installed - $this->stepsPreset = 'already_installed'; - break; - } - - // import base data into new database, not for db_reconfig - $this->toolkit->RunSQL('/core/install/install_schema.sql'); - $this->toolkit->RunSQL('/core/install/install_data.sql'); - - // create category using sql, because Application is not available here - $fields_hash = Array ( - 'l1_Name' => 'Content', 'Filename' => 'Content', 'AutomaticFilename' => 0, - 'l1_Description' => 'Content', 'Status' => 4, - ); - - $this->Conn->doInsert($fields_hash, $this->toolkit->getSystemConfig('Database', 'TablePrefix') . 'Category'); - - $this->toolkit->SetModuleRootCategory('Core', $this->Conn->getInsertID()); - - // set module "Core" version after install (based on upgrade scripts) - $this->toolkit->SetModuleVersion('Core'); - } - break; - - case 'select_license': - $license_source = $this->GetVar('license_source'); - switch ($license_source) { - case 1: // Download from Intechnic - - break; - - case 2: // Upload License File - $file_data = array_map('trim', file($_FILES['license_file']['tmp_name'])); - if ((count($file_data) == 3) && $file_data[1]) { - $modules_helper =& $this->Application->recallObject('ModulesHelper'); - /* @var $modules_helper kModulesHelper */ - - if ($modules_helper->verifyLicense($file_data[1])) { - $this->toolkit->setSystemConfig('Intechnic', 'License', $file_data[1]); - $this->toolkit->setSystemConfig('Intechnic', 'LicenseCode', $file_data[2]); - $this->toolkit->SaveConfig(); - } - else { - $this->errorMessage = 'Invalid License File'; - } - } - else { - $this->errorMessage = 'Invalid License File'; - } - break; - - case 3: // Use Existing License - $license_hash = $this->toolkit->getSystemConfig('Intechnic', 'License'); - if ($license_hash) { - $modules_helper =& $this->Application->recallObject('ModulesHelper'); - /* @var $modules_helper kModulesHelper */ - - if (!$modules_helper->verifyLicense($license_hash)) { - $this->errorMessage = 'Invalid or corrupt license detected'; - } - } - else { - // happens, when browser's "Back" button is used - $this->errorMessage = 'Missing License File'; - } - break; - - case 4: // Skip License (Local Domain Installation) - if ($this->toolkit->sectionFound('Intechnic')) { - // remove any previous license information - $this->toolkit->setSystemConfig('Intechnic', 'License'); - $this->toolkit->setSystemConfig('Intechnic', 'LicenseCode'); - $this->toolkit->SaveConfig(); - } - break; - } - break; - - case 'download_license': - $license_login = $this->GetVar('login'); - $license_password = $this->GetVar('password'); - $license_id = $this->GetVar('licenses'); - - if (strlen($license_login) && strlen($license_password) && !$license_id) { - // Here we determine weather login is ok & check available licenses - $url_params = Array ( - 'login=' . md5($license_login), - 'password=' . md5($license_password), - 'version=' . $this->toolkit->GetMaxModuleVersion('In-Portal'), - 'domain=' . base64_encode($_SERVER['HTTP_HOST']), - ); - - $license_url = GET_LICENSE_URL . '?' . implode('&', $url_params); - $file_data = curl_post($license_url, '', null, 'GET'); - if (!$file_data) { - // error connecting to licensing server - $this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!'; - } - else { - if (substr($file_data, 0, 5) == 'Error') { - // after processing data server returned error - $this->errorMessage = substr($file_data, 6); - } - else { - // license received - if (substr($file_data, 0, 3) == 'SEL') { - // we have more, then one license -> let user choose - $this->SetVar('license_selection', base64_encode( substr($file_data, 4) )); // we received html with radio buttons with names "licenses" - $this->errorMessage = 'Please select which license to use'; - } - else { - // we have one license - $this->toolkit->processLicense($file_data); - } - } - } - } - else if (!$license_id) { - // licenses were not queried AND user/password missing - $this->errorMessage = 'Incorrect Username or Password. If you don\'t know your username or password, contact Intechnic Support'; - } - else { - // Here we download license - $url_params = Array ( - 'license_id=' . md5($license_id), - 'dlog=' . md5($license_login), - 'dpass=' . md5($license_password), - 'version=' . $this->toolkit->GetMaxModuleVersion('In-Portal'), - 'domain=' . base64_encode($_SERVER['HTTP_HOST']), - ); - - $license_url = GET_LICENSE_URL . '?' . implode('&', $url_params); - $file_data = curl_post($license_url, '', null, 'GET'); - - if (!$file_data) { - // error connecting to licensing server - $this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!'; - } - else { - if (substr($file_data, 0, 5) == 'Error') { - // after processing data server returned error - $this->errorMessage = substr($file_data, 6); - } - else { - $this->toolkit->processLicense($file_data); - } - } - } - break; - - case 'select_domain': - $modules_helper =& $this->Application->recallObject('ModulesHelper'); - /* @var $modules_helper kModulesHelper */ - - $license_hash = $this->toolkit->getSystemConfig('Intechnic', 'License'); - if ($license_hash) { - // when license present, then extract domain from it - $license_hash = base64_decode($license_hash); - list ( , , $license_keys) = $modules_helper->_ParseLicense($license_hash); - $license_domain = $license_keys[0]['domain']; - } - else { - // when license missing, then use current domain - $license_domain = $_SERVER['HTTP_HOST']; - } - - $domain = $this->GetVar('domain') == 1 ? $_SERVER['HTTP_HOST'] : str_replace(' ', '', $this->GetVar('other')); - - if ($domain != '') { - if (strstr($domain, $license_domain) || $modules_helper->_IsLocalSite($domain)) { - $this->toolkit->setSystemConfig('Intechnic', 'Domain', $domain); - $this->toolkit->SaveConfig(); - } - else { - $this->errorMessage = 'Domain name entered does not match domain name in the license!'; - } - } - else { - $this->errorMessage = 'Please enter valid domain!'; - } - break; - - case 'root_password': - // update root password in database - $password = md5( md5($this->Application->GetVar('root_password')) . 'b38'); - - $config_values = Array ( - 'RootPass' => $password, - 'Site_Path' => BASE_PATH.'/', // set Site_Path (for SSL & old in-portal code) - 'Backup_Path' => FULL_PATH . $this->toolkit->getSystemConfig('Misc', 'WriteablePath') . DIRECTORY_SEPARATOR . 'backupdata', - 'Smtp_AdminMailFrom' => 'portal@' . $this->toolkit->getSystemConfig('Intechnic', 'Domain') - ); - - $this->toolkit->saveConfigValues($config_values); - - // import base language for core (english) - $this->toolkit->ImportLanguage('/core/install/english'); - - // set imported language as primary - $lang =& $this->Application->recallObject('lang.-item', null, Array('skip_autoload' => true)); - /* @var $lang LanguagesItem */ - - $lang->Load(1); // fresh install => ID=1 - $lang->setPrimary(true); // for Front-End - break; - - case 'choose_modules': - // run module install scripts - $modules = $this->Application->GetVar('modules'); - if ($modules) { - foreach ($modules as $module) { - $install_file = MODULES_PATH.'/'.$module.'/install.php'; - if (file_exists($install_file)) { - include_once($install_file); - - // set module version after install (based on upgrade scripts) - $this->toolkit->SetModuleVersion($module); - } - } - } - - // update category cache - $updater =& $this->Application->recallObject('kPermCacheUpdater'); - /* @var $updater kPermCacheUpdater */ - - $updater->OneStepRun(); - break; - - case 'post_config': - $this->toolkit->saveConfigValues( $this->GetVar('config') ); - break; - - case 'select_theme': - // 1. mark theme, that user is selected - $theme_id = $this->GetVar('theme'); - $theme_table = $this->Application->getUnitOption('theme', 'TableName'); - $theme_idfield = $this->Application->getUnitOption('theme', 'IDField'); - - $sql = 'UPDATE ' . $theme_table . ' - SET Enabled = 1, PrimaryTheme = 1 - WHERE ' . $theme_idfield . ' = ' . $theme_id; - $this->Conn->Query($sql); - - $this->toolkit->rebuildThemes(); // rescan theme to create structure after theme is enabled !!! - - if ($this->Application->isModuleEnabled('In-Portal')) { - // 2. compile theme stylesheets (only In-Portal uses them) - $css_table = $this->Application->getUnitOption('css', 'TableName'); - $css_idfield = $this->Application->getUnitOption('css', 'IDField'); - - $sql = 'SELECT LOWER(Name) AS Name, ' . $css_idfield . ' - FROM ' . $css_table; - $css_hash = $this->Conn->GetCol($sql, $css_idfield); - - $css_item =& $this->Application->recallObject('css', null, Array('skip_autoload' => true)); - /* @var $css_item StyleshetsItem */ - - foreach ($css_hash as $stylesheet_id => $theme_name) { - $css_item->Load($stylesheet_id); - $css_item->Compile(); - - $sql = 'UPDATE ' . $theme_table . ' - SET StylesheetId = ' . $stylesheet_id . ' - WHERE LOWER(Name) = ' . $this->Conn->qstr($theme_name); - $this->Conn->Query($sql); - } - } - break; - - case 'upgrade_modules': - // get installed modules from db and compare their versions to upgrade script - $modules = $this->Application->GetVar('modules'); - if ($modules) { - $upgrade_data = $this->GetUpgradableModules(); - - $start_from_module = $this->GetVar('continue_from_module'); - $start_from_query = $this->GetVar('continue_from_query'); - if (!$start_from_query) $start_from_query = 0; - foreach ($modules as $module_name) { - if ($start_from_module && $module_name != $start_from_module) { - continue; - } - else { - $start_from_module = false; //otherwise it will skip all modules after the one we start with! - } - $module_info = $upgrade_data[$module_name]; - $upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path'], 'sql'); - - $sqls = file_get_contents($upgrades_file); - $version_mark = preg_replace('/(\(.*?\))/', $module_info['FromVersion'], VERSION_MARK); - - // get only sqls from next (relative to current) version to end of file - $start_pos = strpos($sqls, $version_mark); - $sqls = substr($sqls, $start_pos); - - preg_match_all('/'.VERSION_MARK.'/s', $sqls, $regs); - - if (!$start_from_module) { - $this->RunUpgrades($module_info['Path'], $regs[1], 'before'); - } - if (!$this->toolkit->RunSQLText($sqls, null, null, $start_from_query)) { - $this->errorMessage .= ''; - $this->errorMessage .= ''; - $this->errorMessage .= '
Click Continue button below to skip this query and go further
'; - $this->Done(); - } - $start_from_query = 0; // so that next module start from the beggining - - $this->toolkit->ImportLanguage('/' . $module_info['Path'] . 'install/english', true); - $this->RunUpgrades($module_info['Path'], $regs[1], 'after'); // upgrade script could operate resulting language pack - - // after upgrade sqls are executed update version and upgrade language pack - $this->toolkit->SetModuleVersion($module_name, $module_info['ToVersion']); - } - } - break; - - case 'fix_paths': - $this->toolkit->saveConfigValues( $this->Application->GetVar('config') ); - break; - - case 'finish': - // delete cache - $this->toolkit->deleteCache(); - - // set installation finished mark - if ($this->Application->ConfigValue('InstallFinished') === false) { - $fields_hash = Array ( - 'VariableName' => 'InstallFinished', - 'VariableValue' => 1, - ); - $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ConfigurationValues'); - } - break; - } - - if ($this->errorMessage) { - // was error during run stage - return ; - } - - $this->currentStep = $this->GetNextStep(); - $this->InitStep(); // init next step (that will be shown now) - - $this->InitApplication(); - - if ($this->currentStep == -1) { - // step after last step -> redirect to admin - $this->Application->Redirect('index', null, '', 'index.php'); - } - } - - /** - * Run upgrade PHP scripts for module with specified path - * - * @param string $module_path - * @param Array $versions - * @param string $mode upgrade mode = {before,after} - */ - function RunUpgrades($module_path, $versions, $mode) - { - static $upgrade_classes = Array (); - - $upgrades_file = sprintf(UPGRADES_FILE, $module_path, 'php'); - if (!file_exists($upgrades_file) || !$versions) { - return ; - } - - if (!isset($upgrade_classes[$module_path])) { - // save class name, because 2nd time - // (in after call $upgrade_class variable will not be present) - include_once $upgrades_file; - $upgrade_classes[$module_path] = $upgrade_class; - } - - $upgrade_object = new $upgrade_classes[$module_path](); - if (method_exists($upgrade_object, 'setToolkit')) { - $upgrade_object->setToolkit($this->toolkit); - } - - foreach ($versions as $version) { - $upgrade_method = 'Upgrade_'.str_replace('.', '_', $version); - if (method_exists($upgrade_object, $upgrade_method)) { - $upgrade_object->$upgrade_method($mode); - } - } - } - - /** - * Initialize kApplication - * - * @param bool $force initialize in any case - */ - function InitApplication($force = false) - { - if (($force || !in_array($this->currentStep, $this->skipApplicationSteps)) && !isset($this->Application)) { - // step is allowed for application usage & it was not initialized in previous step - global $start, $debugger, $dbg_options; - include_once(FULL_PATH.'/core/kernel/startup.php'); - - $this->Application =& kApplication::Instance(); - $this->toolkit->Application =& kApplication::Instance(); - - $this->Application->Init(); - - $this->Conn =& $this->Application->GetADODBConnection(); - $this->toolkit->Conn =& $this->Application->GetADODBConnection(); - } - } - - /** - * Show next step screen - * - */ - function Done($error_message = null) - { - if (isset($error_message)) { - $this->errorMessage = $error_message; - } - - include_once (FULL_PATH.'/'.REL_PATH.'/install/incs/install.tpl'); - - if (isset($this->Application)) { - $this->Application->Done(); - } - - exit; - } - - function ConnectToDatabase() - { - include_once FULL_PATH . '/core/kernel/db/db_connection.php'; - - $required_keys = Array ('DBType', 'DBUser', 'DBName'); - foreach ($required_keys as $required_key) { - if (!$this->toolkit->getSystemConfig('Database', $required_key)) { - // one of required db connection settings missing -> abort connection - return false; - } - } - - $this->Conn = new kDBConnection($this->toolkit->getSystemConfig('Database', 'DBType'), Array(&$this, 'DBErrorHandler')); - $this->Conn->Connect( - $this->toolkit->getSystemConfig('Database', 'DBHost'), - $this->toolkit->getSystemConfig('Database', 'DBUser'), - $this->toolkit->getSystemConfig('Database', 'DBUserPassword'), - $this->toolkit->getSystemConfig('Database', 'DBName') - ); - - // setup toolkit too - $this->toolkit->Conn =& $this->Conn; - - return $this->Conn->errorCode == 0; - } - - /** - * Checks if core is already installed - * - * @return bool - */ - function AlreadyInstalled() - { - $table_prefix = $this->toolkit->getSystemConfig('Database', 'TablePrefix'); - - $sql = 'SELECT VariableValue - FROM ' . $table_prefix . 'ConfigurationValues - WHERE VariableName = "InstallFinished"'; - - return $this->TableExists('ConfigurationValues') && $this->Conn->GetOne($sql); - } - - function CheckDatabase($check_installed = true) - { - // perform various check type to database specified - // 1. user is allowed to connect to database - // 2. user has all types of permissions in database - - - if (mb_strlen($this->toolkit->getSystemConfig('Database', 'TablePrefix')) > 7) { - $this->errorMessage = 'Table prefix should not be longer than 7 characters'; - return false; - } - - // connect to database - $status = $this->ConnectToDatabase(); - if ($status) { - // if connected, then check if all sql statements work - $sql_tests[] = 'DROP TABLE IF EXISTS test_table'; - $sql_tests[] = 'CREATE TABLE test_table(test_col mediumint(6))'; - $sql_tests[] = 'LOCK TABLES test_table WRITE'; - $sql_tests[] = 'INSERT INTO test_table(test_col) VALUES (5)'; - $sql_tests[] = 'UPDATE test_table SET test_col = 12'; - $sql_tests[] = 'UNLOCK TABLES'; - $sql_tests[] = 'ALTER TABLE test_table ADD COLUMN new_col varchar(10)'; - $sql_tests[] = 'SELECT * FROM test_table'; - $sql_tests[] = 'DELETE FROM test_table'; - $sql_tests[] = 'DROP TABLE IF EXISTS test_table'; - - foreach ($sql_tests as $sql_test) { - $this->Conn->Query($sql_test); - if ($this->Conn->getErrorCode() != 0) { - $status = false; - break; - } - } - - if ($status) { - // if statements work & connection made, then check table existance - if ($check_installed && $this->AlreadyInstalled()) { - $this->errorMessage = 'An In-Portal Database already exists at this location'; - return false; - } - } - else { - // user has insufficient permissions in database specified - $this->errorMessage = 'Permission Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg(); - return false; - } - } - else { - // was error while connecting - if (!$this->Conn) return false; - $this->errorMessage = 'Connection Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg(); - return false; - } - - return true; - } - - /** - * Checks if all passed tables exists - * - * @param string $tables comma separated tables list - * @return bool - */ - function TableExists($tables) - { - $prefix = $this->toolkit->getSystemConfig('Database', 'TablePrefix'); - - $all_found = true; - $tables = explode(',', $tables); - foreach ($tables as $table_name) { - $sql = 'SHOW TABLES LIKE "'.$prefix.$table_name.'"'; - if (count($this->Conn->Query($sql)) == 0) { - $all_found = false; - break; - } - } - - return $all_found; - } - - /** - * Returns modules list found in modules folder - * - * @return Array - */ - function ScanModules() - { - static $modules = null; - - if (!isset($modules)) { - $modules = Array(); - $fh = opendir(MODULES_PATH); - while (($sub_folder = readdir($fh))) { - $folder_path = MODULES_PATH.'/'.$sub_folder; - if ($sub_folder != '.' && $sub_folder != '..' && is_dir($folder_path)) { - if ($sub_folder == 'core') { - // skip modules here - continue; - } - // this is folder in MODULES_PATH directory - if (file_exists($folder_path.'/install.php') && file_exists($folder_path.'/install/install_schema.sql')) { - $install_order = trim( file_get_contents($folder_path . '/install/install_order.txt') ); - $modules[$install_order] = $sub_folder; - } - } - } - } - - // allows to control module install order - ksort($modules, SORT_NUMERIC); - return $modules; - } - - /** - * Returns list of modules, that can be upgraded - * - */ - function GetUpgradableModules() - { - $ret = Array (); - - foreach ($this->Application->ModuleInfo as $module_name => $module_info) { - if ($module_name == 'In-Portal') { - // don't show In-Portal, because it shares upgrade scripts with Core module - continue; - } - - $upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path'], 'sql'); - if (!file_exists($upgrades_file)) { - // no upgrade file - continue; - } - - $sqls = file_get_contents($upgrades_file); - $versions_found = preg_match_all('/'.VERSION_MARK.'/s', $sqls, $regs); - if (!$versions_found) { - // upgrades file doesn't contain version definitions - continue; - } - - $to_version = end($regs[1]); - $this_version = $this->toolkit->ConvertModuleVersion($module_info['Version']); - if ($this->toolkit->ConvertModuleVersion($to_version) > $this_version) { - // destination version is greather then current - foreach ($regs[1] as $version) { - if ($this->toolkit->ConvertModuleVersion($version) > $this_version) { - $from_version = $version; - break; - } - } - - $version_info = Array ( - 'FromVersion' => $from_version, - 'ToVersion' => $to_version, - ); - - $ret[ strtolower($module_name) ] = array_merge_recursive2($module_info, $version_info); - } - } - - return $ret; - } - - /** - * Returns content to show for current step - * - * @return string - */ - function GetStepBody() - { - $step_template = FULL_PATH.'/core/install/step_templates/'.$this->currentStep.'.tpl'; - if (file_exists($step_template)) { - ob_start(); - include_once ($step_template); - return ob_get_clean(); - } - - return '{step template "'.$this->currentStep.'" missing}'; - } - - /** - * Parses step information file, cache result for current step ONLY & return it - * - * @return Array - */ - function &_getStepInfo() - { - static $info = Array('help_title' => null, 'step_title' => null, 'help_body' => null, 'queried' => false); - - if (!$info['queried']) { - $fdata = file_get_contents($this->StepDBFile); - - $parser = xml_parser_create(); - xml_parse_into_struct($parser, $fdata, $values, $index); - xml_parser_free($parser); - - foreach ($index['STEP'] as $section_index) { - $step_data =& $values[$section_index]; - - if ($step_data['attributes']['NAME'] == $this->currentStep) { - $info['step_title'] = $step_data['attributes']['TITLE']; - if (isset($step_data['attributes']['HELP_TITLE'])) { - $info['help_title'] = $step_data['attributes']['HELP_TITLE']; - } - else { - // if help title not set, then use step title - $info['help_title'] = $step_data['attributes']['TITLE']; - } - $info['help_body'] = trim($step_data['value']); - break; - } - } - - $info['queried'] = true; - } - - return $info; - } - - /** - * Returns particular information abou current step - * - * @param string $info_type - * @return string - */ - function GetStepInfo($info_type) - { - $step_info =& $this->_getStepInfo(); - - if (isset($step_info[$info_type])) { - return $step_info[$info_type]; - } - - return '{step "'.$this->currentStep.'"; param "'.$info_type.'" missing}'; - } - - /** - * Returns passed steps titles - * - * @param Array $steps - * @return Array - * @see kInstaller:PrintSteps - */ - function _getStepTitles($steps) - { - $fdata = file_get_contents($this->StepDBFile); - - $parser = xml_parser_create(); - xml_parse_into_struct($parser, $fdata, $values, $index); - xml_parser_free($parser); - - $ret = Array (); - foreach ($index['STEP'] as $section_index) { - $step_data =& $values[$section_index]; - if (in_array($step_data['attributes']['NAME'], $steps)) { - $ret[ $step_data['attributes']['NAME'] ] = $step_data['attributes']['TITLE']; - } - } - - return $ret; - } - - /** - * Returns current step number in active steps_preset. - * Value can't be cached, because same step can have different number in different presets - * - * @return int - */ - function GetStepNumber() - { - return array_search($this->currentStep, $this->steps[$this->stepsPreset]) + 1; - } - - /** - * Returns step name to process next - * - * @return string - */ - function GetNextStep() - { - $next_index = $this->GetStepNumber(); - if ($next_index > count($this->steps[$this->stepsPreset]) - 1) { - return -1; - } - - return $this->steps[$this->stepsPreset][$next_index]; - } - - /** - * Returns step name, that was processed before this step - * - * @return string - */ - function GetPreviousStep() - { - $next_index = $this->GetStepNumber() - 1; - if ($next_index < 0) { - $next_index = 0; - } - - return $this->steps[$this->stepsPreset][$next_index]; - } - - /** - * Prints all steps from active steps preset and highlights current step - * - * @param string $active_tpl - * @param string $passive_tpl - * @return string - */ - function PrintSteps($active_tpl, $passive_tpl) - { - $ret = ''; - $step_titles = $this->_getStepTitles($this->steps[$this->stepsPreset]); - - foreach ($this->steps[$this->stepsPreset] as $step_name) { - $template = $step_name == $this->currentStep ? $active_tpl : $passive_tpl; - $ret .= sprintf($template, $step_titles[$step_name]); - } - - return $ret; - } - - /** - * Installation error handler for sql errors - * - * @param int $code - * @param string $msg - * @param string $sql - * @return bool - * @access private - */ - function DBErrorHandler($code, $msg, $sql) - { - $this->errorMessage = 'Query:
'.htmlspecialchars($sql).'
execution result is error:
['.$code.'] '.$msg; - return true; - } - - /** - * Installation error handler - * - * @param int $errno - * @param string $errstr - * @param string $errfile - * @param int $errline - * @param Array $errcontext - */ - function ErrorHandler($errno, $errstr, $errfile = '', $errline = '', $errcontext = '') - { - if ($errno == E_USER_ERROR) { - // only react on user fatal errors - $this->Done($errstr); - } - } - } -?> \ No newline at end of file