mailer project continued:
[mailer.git] / inc / install-functions.php
index 51596123fd73586c1cc7e3869ae02440ce1b1f94..003feec90f6457b511c12b33c8dde03ba430b6f6 100644 (file)
@@ -16,7 +16,7 @@
  * $Author::                                                          $ *
  * -------------------------------------------------------------------- *
  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
- * Copyright (c) 2009 - 2011 by Mailer Developer Team                   *
+ * Copyright (c) 2009 - 2012 by Mailer Developer Team                   *
  * For more information visit: http://mxchange.org                      *
  *                                                                      *
  * This program is free software; you can redistribute it and/or modify *
  ************************************************************************/
 
 // Some security stuff...
-if (!defined('__SECURITY')) {
+if ((!defined('__SECURITY')) || (!isInstallationPhase())) {
        die();
 } // END - if
 
+// Init installer
+function initInstaller () {
+       // Initialize installer group array
+       $GLOBALS['installer_groups'] = array(
+               // base_data
+               'base_path'       => 'base_data',
+               'base_url'        => 'base_data',
+               'main_title'      => 'base_data',
+               'slogan'          => 'base_data',
+               'webmaster'       => 'base_data',
+               // database_config
+               'mysql_host'      => 'database_config',
+               'mysql_dbase'     => 'database_config',
+               'mysql_prefix'    => 'database_config',
+               'mysql_type'      => 'database_config',
+               'mysql_login'     => 'database_config',
+               'mysql_password1' => 'database_config',
+               'mysql_password2' => 'database_config',
+               // smtp_config
+               'smtp_host'       => 'smtp_config',
+               'smtp_user'       => 'smtp_config',
+               'smtp_password1'  => 'smtp_config',
+               'smtp_password2'  => 'smtp_config',
+               // other_config
+               'output_mode'     => 'other_config',
+               'warn_no_pass'    => 'other_config',
+               'write_footer'    => 'other_config',
+               'enable_backlink' => 'other_config',
+       );
+}
+
 // Write the local config-local.php file from "template"
-function doInstallWriteLocalConfig () {
+function doInstallWriteLocalConfigurationFile ($path) {
        // Copy the config template and verify it
-       copyFileVerified(postRequestElement('spath') . 'inc/config-local.php.dist', getPath() . getCachePath() . 'config-local.php', 0644);
+       copyFileVerified(postRequestElement('spath') . 'inc/config-local.php.dist', postRequestElement('spath') . getCachePath() . 'config-local.php', 0644);
 
        // Ok, all done. So we can write the config data to the php files
+       // Do only write these if they differ from auto-detected values
        if (postRequestElement('spath') != getPath()) changeDataInLocalConfigurationFile('SERVER-PATH', "setConfigEntry('PATH', '", "');", postRequestElement('spath'), 0);
        if (postRequestElement('burl')  != getUrl())  changeDataInLocalConfigurationFile('HOST-URL', "setConfigEntry('URL', '", "');", postRequestElement('burl'), 0);
+
+       // Write more data
        changeDataInLocalConfigurationFile('MAIN-TITLE', "setConfigEntry('MAIN_TITLE', '", "');", postRequestElement('title'), 0);
        changeDataInLocalConfigurationFile('SLOGAN', "setConfigEntry('SLOGAN', '", "');", postRequestElement('slogan'), 0);
        changeDataInLocalConfigurationFile('WEBMASTER', "setConfigEntry('WEBMASTER', '", "');", postRequestElement('email'), 0);
@@ -65,11 +99,8 @@ function doInstallWriteLocalConfig () {
        changeDataInLocalConfigurationFile('SMTP-USER', "setConfigEntry('SMTP_USER', '", "');", postRequestElement('smtp_user'), 0);
        changeDataInLocalConfigurationFile('SMTP-PASSWORD', "setConfigEntry('SMTP_PASSWORD', '", "');", postRequestElement('smtp_pass1'), 0);
 
-       // Generate a long site key
-       $siteKey = generatePassword(50);
-
-       // And write it
-       changeDataInLocalConfigurationFile('SITE-KEY', "setConfigEntry('SITE_KEY', '", "');", $siteKey, 0);
+       // Generate a long site-key and write it
+       changeDataInLocalConfigurationFile('SITE-KEY', "setConfigEntry('SITE_KEY', '", "');", generatePassword(50), 0);
 
        // Script is now installed
        changeDataInLocalConfigurationFile('INSTALLED', "setConfigEntry('MXCHANGE_INSTALLED', '", "');", 'Y', 0);
@@ -117,12 +148,474 @@ function readSqlDump ($FQFN) {
        $content = readFromFile($FQFN);
 
        // Remove some unwanted chars
-       $content = str_replace("\r", '', $content);
-       $content = str_replace("\n\n", "\n", $content);
+       $content = str_replace(chr(13), '', $content);
+       $content = str_replace("\n\n", chr(10), $content);
 
        // Return the content
        return $content;
 }
 
+// Generates the installer menu by simply loading another template
+function generateInstallerMenu () {
+       // Load installer menu template
+       $OUT = loadTemplate('install_menu', true);
+
+       // Return loaded content
+       return $OUT;
+}
+
+// Generate the install footer navigation by simply loading another template
+function generateInstallerFooterNavigation () {
+       // Load installer menu template
+       $OUT = loadTemplate('install_footer', true);
+
+       // Return loaded content
+       return $OUT;
+}
+
+// Generate an option list for database types for given default value
+function generateInstallerDatabaseTypeOptions () {
+       return generateOptions(
+               '/ARRAY/',
+               array('MyISAM', 'InnoDB'),
+               array('{--INSTALLER_TABLE_TYPE_MYISAM--}', '{--INSTALLER_TABLE_TYPE_INNODB--}'),
+               getSession('mysql_type')
+       );
+}
+
+// Generate an option list for output mode types for given default value
+function generateInstallerOutputModeOptions ($defaultValue) {
+       return generateOptions(
+               '/ARRAY/',
+               array('render', 'direct'),
+               array('{--INSTALLER_MODE_RENDER--}', '{--INSTALLER_MODE_DIRECT--}'),
+               $defaultValue
+       );
+}
+
+// Checks whether we have an AJAX-enabled installer which defaults to red pill
+function isAjaxInstaller () {
+       // Get the session data and compare it against 'ajax'
+       $isAjaxInstaller = (getSession('installer') == 'ajax');
+
+       // Return it
+       return $isAjaxInstaller;
+}
+
+// Checks whether we have an plain installer which defaults to red pill
+function isPlainInstaller () {
+       // Get the session data and compare it against 'plain'
+       $isPlainInstaller = (getSession('installer') == 'plain');
+
+       // Return it
+       return $isPlainInstaller;
+}
+
+// Checks given key/value pair if it is valid by a call-back
+function isInstallerDataValid (&$saveStatus, $key, $value) {
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ' - ENTERED!');
+       // Generate call-back function based on given key
+       $callbackName = 'isInstaller' . capitalizeUnderscoreString($key) . 'Valid';
+
+       // Is the function there?
+       if (!function_exists($callbackName)) {
+               // Not found, which is not bad, but it means this data is always valid
+               //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' not found. saveStatus[status]=' . $saveStatus['status'] . ', key=' . $key . ', value=' . $value);
+
+               // All fine (CAREFULL!)
+               return true;
+       } // END - if
+
+       // Then call it back
+       $isValid = (bool) call_user_func($callbackName, $value);
+
+       // Is it not valid?
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ',isValid=' . intval($isValid));
+       if ($isValid === false) {
+               // Then add it to saveStatus
+               array_push($saveStatus['failed_fields'], $key);
+       } // END - if
+
+       // Return status
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT!');
+       return $isValid;
+}
+
+// Post-check on installer data
+function doInstallerPostCheck ($currentTab, &$saveStatus) {
+       // Debug message
+       //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentTab=' . $currentTab . ',saveStatus[status]=' . $saveStatus['status'] . ' - ENTERED!');
+
+       // Create the call-back function on 'tab'
+       $callbackName = 'isInstallerPost' . capitalizeUnderscoreString($currentTab) . 'Valid';
+
+       // Is the function there?
+       if (!function_exists($callbackName)) {
+               // Not found, which is not bad, but it means the post-check won't be run
+               //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' not found. saveStatus[status]=' . $saveStatus['status'] . ', currentTab=' . $currentTab);
+
+               // Abort here
+               return;
+       } // END - if
+
+       // Init 'tab-specific error message'
+       $GLOBALS['installer_post_error'][$currentTab]    = '';
+       $GLOBALS['installer_failed_fields'][$currentTab] = array();
+
+       // Debug message
+       //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Calling function ' . $callbackName . ',currentTab=' . $currentTab . ',saveStatus[status]=' . $saveStatus['status']);
+
+       // Then call it back
+       $isValid = (bool) call_user_func($callbackName, $currentTab);
+
+       // Is it not valid?
+       if (($isValid === false) || (count($GLOBALS['installer_failed_fields'][$currentTab]) > 0)) {
+               // Then change status and message
+               $saveStatus['status']  = 'failed';
+               $saveStatus['message'] = '{%message,INSTALLER_POST_CHECK_' . strtoupper($currentTab) . '_FAILED=' . $GLOBALS['installer_post_error'][$currentTab] . '%}';
+
+               // Do we have failed fields?
+               if (count($GLOBALS['installer_failed_fields'][$currentTab]) > 0) {
+                       // Then merge both
+                       $saveStatus['failed_fields'] = merge_array($saveStatus['failed_fields'], $GLOBALS['installer_failed_fields'][$currentTab]);
+               } // END - if
+       } // END - if
+
+       // Debug message
+       //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentTab=' . $currentTab . ',saveStatus[status]=' . $saveStatus['status'] . ' - EXIT!');
+}
+
+// Determines an installer group by given key
+function determineInstallerGroupByKey ($key) {
+       // Try to look it up
+       if (!isset($GLOBALS['installer_groups'][$key])) {
+               // Log missing entry
+               logDebugMessage(__FUNCTION__, __LINE__, 'Cannot determine installer group, returning dummy group. key=' . $key);
+
+               // Return dummy group
+               return 'dummy';
+       } // END - if
+
+       // Return it
+       return $GLOBALS['installer_groups'][$key];
+}
+
+// Adds given key/value pair to an overview group
+function addKeyValueToInstallerOverviewGroup ($key, $value) {
+       // First determine the group by given key
+       $group = determineInstallerGroupByKey($key);
+
+       // Depending on the group, add it for later usage (to render the overview page)
+       $GLOBALS['installer_overview'][$group][$key] = $value;
+}
+
+//-----------------------------------------------------------------------------
+//                   Call-back functions to check validity
+//-----------------------------------------------------------------------------
+
+// ----------------- Base data -----------------
+
+// Call-back function to check validity of 'base_path'
+function isInstallerBasePathValid ($value) {
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - ENTERED!');
+       // Is it a directory and if some typical files could be found
+       $isValid = (
+               // Is it a directory?
+               (isDirectory($value))
+       &&
+               // Is there a trailing slash?
+               (substr($value, -1, 1) == '/')
+       &&
+               // Is mysql-manager.php there?
+               (isFileReadable($value . 'inc/mysql-manager.php'))
+       &&
+               // What about gen_sql_patches.php?
+               (isFileReadable($value . 'inc/gen_sql_patches.php'))
+       );
+
+       // Return it
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT');
+       return $isValid;
+}
+
+// Call-back function to check validity of 'base_url'
+function isInstallerBaseUrlValid ($value) {
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - ENTERED!');
+       // Is it same as URL
+       $isValid = (
+               // Same as URL?
+               ($value == getUrl())
+       || (
+               // Starts with http:// or https:// ?
+               ((substr($value, 0, 7) == 'http://') || (substr($value, 0, 8) == 'https://'))
+       &&
+               // Has no trailing slash?
+               (substr($value, -1, 1) != '/')
+       &&
+               // And total length is at least 6+8=14 chars long? (https://foo.ba)
+               (strlen($value) >= 14)
+       &&
+               // Is the URL valid?
+               (isUrlValid($value))
+       ));
+
+       // Return it
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT');
+       return $isValid;
+}
+
+// Call-back function to check validity of 'webmaster'
+function isInstallerWebmasterValid ($value) {
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - ENTERED!');
+       // Is it a valid email address?
+       $isValid = (
+               // Is it a valid email address?
+               (isEmailValid($value))
+       ||
+               // Or do we have 'localhost/127.0.0.1' as hostname? Then don't check email address (e.g. you@localhost)
+               (in_array(detectServerName(), array('localhost', '127.0.0.1')))
+       );
+
+       // Return it
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT');
+       return $isValid;
+}
+
+// ----------------- Database configuration -----------------
+
+// Call-back function to check validity of 'mysql_host'
+function isInstallerMysqlHostValid ($value) {
+       // This value must match a hostname or IP address
+       $isValid = (
+               // Is localhost/127.0.0.1? (mostly the case)
+               (in_array($value, array('localhost', '127.0.0.1')))
+       ||
+               // IP number match (this regex was taken from www.regexlib.com)
+               (preg_match('/((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9]))/', $value))
+       ||
+               // Host name match
+               (preg_match('/([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}/', $value))
+       );
+
+       // Return it
+       return $isValid;
+}
+
+// Call-back function to check validity of 'mysql_type'
+function isInstallerMysqlTypeValid ($value) {
+       // This value must be 'MyISAM' or 'InnoDB'
+       $isValid = in_array($value, array('MyISAM', 'InnoDB'));
+
+       // Return it
+       return $isValid;
+}
+
+// ----------------- SMTP configuration -----------------
+
+// ----------------- Other configuration -----------------
+
+//-----------------------------------------------------------------------------
+//                 Call-back functions to post-check validity
+//-----------------------------------------------------------------------------
+
+// Call-back function to check if database configuration in POST is valid
+function isInstallerPostDatabaseConfigValid ($currentTab) {
+       // By default nothing is valid
+       $isValid       = false;
+       $engineValid   = false;
+       $missingTables = 0;
+
+       // Do both passwords match?
+       if ((!isPostRequestElementSet('mysql_password1')) && (isPostRequestElementSet('mysql_password2'))) {
+               // Password 1 not set
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_PASSWORD1_EMPTY--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_password1');
+               return false;
+       } elseif ((isPostRequestElementSet('mysql_password1')) && (!isPostRequestElementSet('mysql_password2'))) {
+               // Password 2 not set
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_PASSWORD2_EMPTY--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_password2');
+               return false;
+       } elseif (postRequestElement('mysql_password1') != postRequestElement('mysql_password2')) {
+               // Passwords mismatch
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_PASSWORDS_MISMATCH--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_password1', 'mysql_password2');
+               return false;
+       } // END - if
+
+       // Restore PHP's own error handler
+       if (!restore_error_handler()) {
+               // This is fatal
+               reportBug(__FUNCTION__, __LINE__, 'Could not unregister error handler.');
+       } // END - if
+
+       // Try to connect to the database
+       $linkResource = SQL_CONNECT(postRequestElement('mysql_host'), postRequestElement('mysql_login'), postRequestElement('mysql_password1'), __FUNCTION__, __LINE__);
+
+       // Is the link up
+       if (!is_resource($linkResource)) {
+               // Restore own error handler again
+               set_error_handler('__errorHandler');
+
+               // Cannot connect to database
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_CONNECT_ERROR--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_login', 'mysql_password1', 'mysql_password2');
+               return false;
+       } // END - if
+
+       // Then attempt to select the database
+       if (!SQL_SELECT_DB(postRequestElement('mysql_dbase'), __FUNCTION__, __LINE__)) {
+               // Restore own error handler again
+               set_error_handler('__errorHandler');
+
+               // Could not find database
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_SELECT_FAILED--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_dbase');
+               return false;
+       } // END - if
+
+       // Set database name and prefix
+       setConfigEntry('__DB_NAME'    , postRequestElement('mysql_dbase'));
+       setConfigEntry('_MYSQL_PREFIX', postRequestElement('mysql_prefix'));
+
+       // Restore own error handler again
+       set_error_handler('__errorHandler');
+
+       // Get an array of all supported engines
+       $engines = getArrayFromSupportedSqlEngines();
+
+       // Is this an array?
+       if (!is_array($engines)) {
+               // Restore own error handler again
+               set_error_handler('__errorHandler');
+
+               // Something bad happened
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_ENGINES_SQL_ERROR--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_type');
+               return false;
+       } elseif (count($engines) == 0) {
+               // Restore own error handler again
+               set_error_handler('__errorHandler');
+
+               // No engine is active
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_NO_ENGINES_ACTIVE--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_type');
+               return false;
+       }
+
+       // Then check all, if the requested is working
+       foreach ($engines as $engineArray) {
+               // By default the selected engine is not valid
+               $engineValid = false;
+
+               // Is the engine there?
+               if (strtolower($engineArray['Engine']) == strtolower(postRequestElement('mysql_type'))) {
+                       // Okay, engine is found
+                       $engineValid = true;
+                       break;
+               } // END - if
+       } // END - foreach
+
+       // So, is the engine found?
+       if ($engineValid === false) {
+               // Restore own error handler again
+               set_error_handler('__errorHandler');
+
+               // Requested engine is not active
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_ENGINE_UNSUPPORTED--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_type');
+               return false;
+       } // END - if
+
+       // Init some known tables
+       $tables = array(
+               // Admins
+               'admins'      => true,
+               // Admin menu
+               'admin_menu'  => true,
+               // Categories
+               'cats'        => true,
+               // Configuration
+               'config'      => true,
+               // Extensions
+               'extensions'  => true,
+               // Guest menu
+               'guest_menu'  => true,
+               // Max receive
+               'max_receive' => true,
+               // Member menu
+               'member_menu' => true,
+               // Module registry
+               'mod_reg'     => true,
+               // Payments
+               'payments'    => true,
+               // Sending pool
+               'pool'        => true,
+               // Referral banner
+               'refbanner'   => true,
+               // Referral levels
+               'refdepths'   => true,
+               // Referral system
+               'refsystem'   => true,
+               // Task system
+               'task_system' => true,
+       );
+
+       // So check if all tables are not there
+       foreach ($tables as $tableName => $isFound) {
+               // Check it out
+               $tables[$tableName] = isSqlTableCreated($tableName);
+
+               // Is it (hopefully not) there?
+               if ($tables[$tableName] === false) {
+                       // This does not exist
+                       $missingTables++;
+               } // END - if
+       } // END - foreach
+
+       // Determine final status (simply compare both counts
+       $isValid = (count($tables) == $missingTables);
+
+       // Disconnect here, we don't need idle database connections laying around
+       SQL_CLOSE(__FUNCTION__, __LINE__);
+
+       // Restore own error handler again
+       set_error_handler('__errorHandler');
+
+       // If the status is true, disconnect the database
+       if ($isValid === false) {
+               // Still something bad happened (e.g. tables found)
+               $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_IN_USE--}';
+               array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_dbase');
+       } // END - if
+
+       // Return status
+       return $isValid;
+}
+
+// Call-back function to check if enable_backlink is Y/N
+function isInstallerEnableBacklinkValid ($currentTab) {
+       // Check and return it
+       return in_array($currentTab, array('Y', 'N'));
+}
+
+// Call-back function to check if warn_no_pass is Y/N
+function isInstallerWarnNoPassValid ($currentTab) {
+       // Check and return it
+       return in_array($currentTab, array('Y', 'N'));
+}
+
+// Call-back function to check if write_footer is Y/N
+function isInstallerWriteFooterValid ($currentTab) {
+       // Check and return it
+       return in_array($currentTab, array('Y', 'N'));
+}
+
+// Call-back function to check if output_mode is Y/N
+function isInstallerOutputModeValid ($currentTab) {
+       // Check and return it
+       return in_array($currentTab, array('render', 'direct'));
+}
+
 // [EOF]
 ?>