MINOR: Small code improvements
[mailer.git] / inc / install-functions.php
1 <?php
2 /************************************************************************
3  * Mailer v0.2.1-FINAL                                Start: 10/22/2009 *
4  * ===================                          Last change: 10/22/2009 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : install-functions.php                            *
8  * -------------------------------------------------------------------- *
9  * Short description : Functions for installation procedure             *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Funktionen fuer die Installationsroutine         *
12  * -------------------------------------------------------------------- *
13  * $Revision::                                                        $ *
14  * $Date::                                                            $ *
15  * $Tag:: 0.2.1-FINAL                                                 $ *
16  * $Author::                                                          $ *
17  * -------------------------------------------------------------------- *
18  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
19  * Copyright (c) 2009 - 2012 by Mailer Developer Team                   *
20  * For more information visit: http://mxchange.org                      *
21  *                                                                      *
22  * This program is free software; you can redistribute it and/or modify *
23  * it under the terms of the GNU General Public License as published by *
24  * the Free Software Foundation; either version 2 of the License, or    *
25  * (at your option) any later version.                                  *
26  *                                                                      *
27  * This program is distributed in the hope that it will be useful,      *
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
30  * GNU General Public License for more details.                         *
31  *                                                                      *
32  * You should have received a copy of the GNU General Public License    *
33  * along with this program; if not, write to the Free Software          *
34  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
35  * MA  02110-1301  USA                                                  *
36  ************************************************************************/
37
38 // Some security stuff...
39 if ((!defined('__SECURITY')) || (!isInstallationPhase())) {
40         die();
41 } // END - if
42
43 // Init installer
44 function initInstaller () {
45         // Initialize installer group array
46         $GLOBALS['installer_groups'] = array(
47                 // base_data
48                 'base_path'       => 'base_data',
49                 'base_url'        => 'base_data',
50                 'main_title'      => 'base_data',
51                 'slogan'          => 'base_data',
52                 'webmaster'       => 'base_data',
53                 // database_config
54                 'mysql_host'      => 'database_config',
55                 'mysql_dbase'     => 'database_config',
56                 'mysql_prefix'    => 'database_config',
57                 'mysql_engine'    => 'database_config',
58                 'mysql_login'     => 'database_config',
59                 'mysql_password1' => 'database_config',
60                 'mysql_password2' => 'database_config',
61                 // smtp_config
62                 'smtp_host'       => 'smtp_config',
63                 'smtp_user'       => 'smtp_config',
64                 'smtp_password1'  => 'smtp_config',
65                 'smtp_password2'  => 'smtp_config',
66                 // other_config
67                 'output_mode'     => 'other_config',
68                 'warn_no_pass'    => 'other_config',
69                 'write_footer'    => 'other_config',
70                 'enable_backlink' => 'other_config',
71         );
72 }
73
74 // Write the local config-local.php file from "template"
75 function doInstallWriteLocalConfigurationFile ($path, $url, $title, $slogan, $email, $noPassword, $writeFooter, $backLink, $databaseHost, $databaseName, $databaseLogin, $databasePassword, $databasePrefix, $databaseType, $smtpHost, $smtpUser, $smtpPassword) {
76         // Copy the config template and verify it
77         copyFileVerified($path . 'inc/config-local.php.dist', $path . getCachePath() . 'config-local.php', 0644);
78
79         /*
80          * Ok, all done. So we can write the config data to the php files. Do only
81          * write these if they differ from auto-detected values.
82          */
83         if ($path != getPath()) {
84                 changeDataInLocalConfigurationFile('SERVER-PATH', "setConfigEntry('PATH', '", "');", $path, 0);
85         } // END - if
86         if ($url != getUrl()) {
87                 changeDataInLocalConfigurationFile('HOST-URL', "setConfigEntry('URL', '", "');", $url, 0);
88         } // END - if
89
90         // Write more data
91         changeDataInLocalConfigurationFile('MAIN-TITLE', "setConfigEntry('MAIN_TITLE', '", "');", $title, 0);
92         changeDataInLocalConfigurationFile('SLOGAN', "setConfigEntry('SLOGAN', '", "');", $slogan, 0);
93         changeDataInLocalConfigurationFile('WEBMASTER', "setConfigEntry('WEBMASTER', '", "');", $email, 0);
94         changeDataInLocalConfigurationFile('NULLPASS-WARNING', "setConfigEntry('WARN_NO_PASS', '", "');", $noPassword, 0);
95         changeDataInLocalConfigurationFile('WRITE-FOOTER', "setConfigEntry('WRITE_FOOTER', '", "');", $writeFooter, 0);
96         changeDataInLocalConfigurationFile('BACKLINK', "setConfigEntry('ENABLE_BACKLINK', '", "');", $backLink, 0);
97         // @TODO DEACTIVATED: changeDataInLocalConfigurationFile('OUTPUT-MODE', "setConfigEntry('OUTPUT_MODE', '", "');", postRequestElement('omode'), 0);
98         changeDataInLocalConfigurationFile('MYSQL-HOST', "      'host'     => '", "',", $databaseHost, 0);
99         changeDataInLocalConfigurationFile('MYSQL-DBASE', "     'dbase'    => '", "',", $databaseName, 0);
100         changeDataInLocalConfigurationFile('MYSQL-LOGIN', "     'login'    => '", "',", $databaseLogin, 0);
101         changeDataInLocalConfigurationFile('MYSQL-PASSWORD', "  'password' => '", "',", $databasePassword, 0);
102         changeDataInLocalConfigurationFile('MYSQL-PREFIX', "setConfigEntry('_MYSQL_PREFIX', '", "');", $databasePrefix, 0);
103         changeDataInLocalConfigurationFile('TABLE-TYPE', "setConfigEntry('_TABLE_TYPE', '", "');", $databaseType, 0);
104         changeDataInLocalConfigurationFile('SMTP-HOSTNAME', "setConfigEntry('SMTP_HOSTNAME', '", "');", $smtpHost, 0);
105         changeDataInLocalConfigurationFile('SMTP-USER', "setConfigEntry('SMTP_USER', '", "');", $smtpUser, 0);
106         changeDataInLocalConfigurationFile('SMTP-PASSWORD', "setConfigEntry('SMTP_PASSWORD', '", "');", $smtpPassword, 0);
107
108         // Generate a long site-key and write it
109         changeDataInLocalConfigurationFile('SITE-KEY', "setConfigEntry('SITE_KEY', '", "');", generatePassword(50), 0);
110
111         // Script is now installed
112         return changeDataInLocalConfigurationFile('INSTALLED', "setConfigEntry('MAILER_INSTALLED', '", "');", 'Y', 0);
113 }
114
115 // Adds a given template with content to install output stream
116 function addTemplateToInstallContent ($template, $content = array()) {
117         // Load the template
118         $out = loadTemplate($template, TRUE, $content);
119
120         // Add it to output
121         addToInstallContent($out);
122 }
123
124 // Add it to install content
125 function addToInstallContent ($out) {
126         // Set or add it...
127         if (!isset($GLOBALS['install_content'])) {
128                 // Set it
129                 $GLOBALS['install_content'] = $out;
130         } else {
131                 // Add it
132                 $GLOBALS['install_content'] .= $out;
133         } // END - if
134 }
135
136 // Somewhat getter for installer content
137 function getInstallerContent () {
138         // Is it here?
139         if (isset($GLOBALS['install_content'])) {
140                 // Yes, then use it
141                 $content = $GLOBALS['install_content'];
142         } else {
143                 // Nothing found, this needs fixing
144                 $content = displayMessage('{--INSTALLER_CONTENT_404--}', TRUE);
145         }
146
147         // Return content
148         return $content;
149 }
150
151 // Read a given SQL dump
152 function readSqlDump ($FQFN) {
153         // Load the file
154         $content = readFromFile($FQFN);
155
156         // Remove some unwanted chars
157         $content = str_replace(chr(13), '', $content);
158         $content = str_replace(PHP_EOL . PHP_EOL, PHP_EOL, $content);
159
160         // Return the content
161         return $content;
162 }
163
164 // Generates the installer menu by simply loading another template
165 function generateInstallerMenu () {
166         // Load installer menu template
167         $OUT = loadTemplate('install_menu', TRUE);
168
169         // Return loaded content
170         return $OUT;
171 }
172
173 // Generate the install footer navigation by simply loading another template
174 function generateInstallerFooterNavigation () {
175         // Load installer menu template
176         $OUT = loadTemplate('install_footer', TRUE);
177
178         // Return loaded content
179         return $OUT;
180 }
181
182 // Generate an option list for database types for given default value
183 function generateInstallerDatabaseTypeOptions () {
184         return generateOptions(
185                 '/ARRAY/',
186                 array('MyISAM', 'InnoDB'),
187                 array('{--INSTALLER_TABLE_TYPE_MYISAM--}', '{--INSTALLER_TABLE_TYPE_INNODB--}'),
188                 getSession('mysql_engine')
189         );
190 }
191
192 // Generate an option list for output mode types for given default value
193 function generateInstallerOutputModeOptions ($defaultValue) {
194         return generateOptions(
195                 '/ARRAY/',
196                 array('render', 'direct'),
197                 array('{--INSTALLER_MODE_RENDER--}', '{--INSTALLER_MODE_DIRECT--}'),
198                 $defaultValue
199         );
200 }
201
202 // Checks whether we have an AJAX-enabled installer which defaults to red pill
203 function isAjaxInstaller () {
204         // Get the session data and compare it against 'ajax'
205         $isAjaxInstaller = (getSession('installer') == 'ajax');
206
207         // Return it
208         return $isAjaxInstaller;
209 }
210
211 // Checks whether we have an plain installer which defaults to red pill
212 function isPlainInstaller () {
213         // Get the session data and compare it against 'plain'
214         $isPlainInstaller = (getSession('installer') == 'plain');
215
216         // Return it
217         return $isPlainInstaller;
218 }
219
220 // Handle all given failed fields
221 function handleInstallerFailedFields ($failedFields) {
222         // Don't do anything with no array or no entries
223         if ((!is_array($failedFields)) || (count($failedFields) == 0)) {
224                 // Abort here
225                 reportBug(__FUNCTION__, __LINE__, 'failedFields[]=' . gettype($failedFields) . ' verification failed');
226         } // END - if
227
228         // Handle all
229         $out = '<ol>';
230         foreach ($failedFields as $key => $field) {
231                 // "Translate" it
232                 $out .= '<li>{--INSTALLER_FIELD_FAILED_' . strtoupper($field) . '--}</li>';
233         } // END - foreach
234         $out .= '</ol>';
235
236         // Return it
237         return $out;
238 }
239
240 // Checks given key/value pair if it is valid by a call-back
241 function isInstallerDataValid (&$saveStatus, $key, $value) {
242         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ' - ENTERED!');
243         // Generate call-back function based on given key
244         $callbackName = 'isInstaller' . capitalizeUnderscoreString($key) . 'Valid';
245
246         // Is the function there?
247         if (!function_exists($callbackName)) {
248                 // Not found, which is not bad, but it means this data is always valid
249                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' not found. saveStatus[status]=' . $saveStatus['status'] . ', key=' . $key . ', value=' . $value);
250
251                 // All fine (CAREFULL!)
252                 return TRUE;
253         } // END - if
254
255         // Then call it back
256         $isValid = (bool) call_user_func($callbackName, $value);
257
258         // Is it not valid?
259         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ',isValid=' . intval($isValid));
260         if ($isValid === FALSE) {
261                 // Then add it to saveStatus
262                 array_push($saveStatus['failed_fields'], $key);
263         } // END - if
264
265         // Return status
266         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT!');
267         return $isValid;
268 }
269
270 // Post-check on installer data
271 function doInstallerPostCheck ($currentTab, &$saveStatus) {
272         // Debug message
273         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentTab=' . $currentTab . ',saveStatus[status]=' . $saveStatus['status'] . ' - ENTERED!');
274
275         // Create the call-back function on 'tab'
276         $callbackName = 'isInstallerPost' . capitalizeUnderscoreString($currentTab) . 'Valid';
277
278         // Is the function there?
279         if (!function_exists($callbackName)) {
280                 // Not found, which is not bad, but it means the post-check won't be run
281                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' not found. saveStatus[status]=' . $saveStatus['status'] . ', currentTab=' . $currentTab);
282
283                 // Abort here
284                 return;
285         } // END - if
286
287         // Init 'tab-specific error message'
288         $GLOBALS['installer_post_error'][$currentTab]    = '';
289         $GLOBALS['installer_failed_fields'][$currentTab] = array();
290
291         // Debug message
292         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Calling function ' . $callbackName . ',currentTab=' . $currentTab . ',saveStatus[status]=' . $saveStatus['status']);
293
294         // Then call it back
295         $isValid = (bool) call_user_func($callbackName, $currentTab);
296
297         // Is it not valid?
298         if (($isValid === FALSE) || (count($GLOBALS['installer_failed_fields'][$currentTab]) > 0)) {
299                 // Then change status and message
300                 $saveStatus['status']  = 'failed';
301                 $saveStatus['message'] = '{%message,INSTALLER_POST_CHECK_' . strtoupper($currentTab) . '_FAILED=' . $GLOBALS['installer_post_error'][$currentTab] . '%}';
302
303                 // Is there failed fields?
304                 if (count($GLOBALS['installer_failed_fields'][$currentTab]) > 0) {
305                         // Then merge both
306                         $saveStatus['failed_fields'] = merge_array($saveStatus['failed_fields'], $GLOBALS['installer_failed_fields'][$currentTab]);
307                 } // END - if
308         } // END - if
309
310         // Debug message
311         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentTab=' . $currentTab . ',saveStatus[status]=' . $saveStatus['status'] . ' - EXIT!');
312 }
313
314 // Determines an installer group by given key
315 function determineInstallerGroupByKey ($key) {
316         // Try to look it up
317         if (!isset($GLOBALS['installer_groups'][$key])) {
318                 // Log missing entry
319                 logDebugMessage(__FUNCTION__, __LINE__, 'Cannot determine installer group, returning dummy group. key=' . $key);
320
321                 // Return dummy group
322                 return 'dummy';
323         } // END - if
324
325         // Return it
326         return $GLOBALS['installer_groups'][$key];
327 }
328
329 // Adds given key/value pair to an overview group
330 function addKeyValueToInstallerOverviewGroup ($key, $value) {
331         // First determine the group by given key
332         $group = determineInstallerGroupByKey($key);
333
334         // Depending on the group, add it for later usage (to render the overview page)
335         $GLOBALS['installer_overview'][$group][$key] = $value;
336 }
337
338 //-----------------------------------------------------------------------------
339 //                        Template call-back functions
340 //-----------------------------------------------------------------------------
341
342 // ----------------- Extensions -----------------
343
344 // Generates (and returns) a table from all extensions
345 function generateInstallerExtensionTable () {
346         // Generate extension list
347         $extensions = loadAllExtensionsByTemplate();
348
349         // "Walk" through all
350         $OUT = '';
351         foreach ($extensions as $extension) {
352                 // Remove prefix + suffix
353                 $ext_name = substr(basename($extension), 4, -4);
354
355                 // Is the extension not in development and not admintheme* ?
356                 if ((loadExtension($ext_name, 'test', '0.0.0', TRUE)) && (isExtensionProductive($ext_name)) && (substr($ext_name, 0, 10) != 'admintheme')) {
357                         // Default is not disabled
358                         $disabled = '';
359                         if ($ext_name == 'sql_patches') {
360                                 // Always keep this enabled
361                                 $disabled = ' disabled="disabled"';
362                         } // END - if
363
364                         // Initialize content array
365                         $content = array(
366                                 'ext_name'    => $ext_name,
367                                 'ext_version' => getExtensionVersion($ext_name),
368                                 'checked'     => getExtensionSelectedFromSession($ext_name, 'extensions'),
369                                 'disabled'    => $disabled,
370                                 'description' => loadTemplate('ext_' . $ext_name, TRUE),
371                         );
372
373                         // Load row template
374                         $OUT .= loadTemplate('install_list_extensions_row', TRUE, $content);
375                 } // END - if
376         } // END - foreach
377
378         // Load main template
379         return loadTemplate('install_list_extensions', TRUE, $OUT);
380 }
381
382 //-----------------------------------------------------------------------------
383 //                   Call-back functions to check validity
384 //-----------------------------------------------------------------------------
385
386 // ----------------- Base data -----------------
387
388 // Call-back function to check validity of 'base_path'
389 function isInstallerBasePathValid ($value) {
390         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - ENTERED!');
391         // Is it a directory and if some typical files could be found
392         $isValid = (
393                 // Is it a directory?
394                 (isDirectory($value))
395         &&
396                 // Doesn't contain dots
397                 (strpos($value, '..') === FALSE)
398         &&
399                 // Is there a trailing slash?
400                 (substr($value, -1, 1) == '/')
401         &&
402                 // Is mysql-manager.php there?
403                 (isFileReadable($value . 'inc/mysql-manager.php'))
404         &&
405                 // What about gen_sql_patches.php?
406                 (isFileReadable($value . 'inc/gen_sql_patches.php'))
407         &&
408                 // And how about referral-functions.php?
409                 (isFileReadable($value . 'inc/referral-functions.php'))
410         );
411
412         // Return it
413         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT');
414         return $isValid;
415 }
416
417 // Call-back function to check validity of 'base_url'
418 function isInstallerBaseUrlValid ($value) {
419         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - ENTERED!');
420         // Is it same as URL
421         $isValid = (
422                 // Same as URL?
423                 ($value == getUrl())
424         || (
425                 // Starts with http:// or https:// ?
426                 ((substr($value, 0, 7) == 'http://') || (substr($value, 0, 8) == 'https://'))
427         &&
428                 // Has no trailing slash?
429                 (substr($value, -1, 1) != '/')
430         &&
431                 // And total length is at least 6+8=14 chars long? (https://foo.ba)
432                 (strlen($value) >= 14)
433         &&
434                 // Is the URL valid?
435                 (isUrlValid($value))
436         ));
437
438         // Return it
439         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT');
440         return $isValid;
441 }
442
443 // Call-back function to checl validity of 'main_title'
444 function isInstallerMainTitleValid ($value) {
445         // Is it valid?
446         // @TODO Comparing with DEFAULT_MAIN_TITLE doesn't work
447         $isValid = ((strlen($value) >= 4) && ($value != getMessage('DEFAULT_MAIN_TITLE')));
448
449         // Return it
450         return $isValid;
451 }
452
453 // Call-back function to checl validity of 'slogan'
454 function isInstallerSloganValid ($value) {
455         // Is it valid?
456         $isValid = ((strlen($value) >= 4) && ($value != getMessage('DEFAULT_SLOGAN')));
457
458         // Return it
459         return $isValid;
460 }
461
462 // Call-back function to check validity of 'webmaster'
463 function isInstallerWebmasterValid ($value) {
464         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - ENTERED!');
465         // Is it a valid email address?
466         $isValid = ((
467                 // Is it a valid email address?
468                 (isEmailValid($value))
469         ||
470                 // Or is there 'localhost/127.0.0.1' as hostname? Then don't check email address (e.g. you@localhost)
471                 (in_array(detectServerName(), array('localhost', '127.0.0.1')))
472         ) && (
473                 // Is not default "email address"
474                 $value != getMessage('DEFAULT_WEBMASTER')
475         ));
476
477         // Return it
478         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ',isValid=' . intval($isValid) . ' - EXIT');
479         return $isValid;
480 }
481
482 // ----------------- Database configuration -----------------
483
484 // Call-back function to check validity of 'mysql_host'
485 function isInstallerMysqlHostValid ($value) {
486         // This value must match a hostname or IP address
487         $isValid = (
488                 // Shall not be empty
489                 (!empty($value)) && (
490                 // Is localhost/127.0.0.1? (mostly the case)
491                 (in_array($value, array('localhost', '127.0.0.1')))
492         ||
493                 // IP number match (this regex was taken from www.regexlib.com)
494                 (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))
495         ||
496                 // Host name match
497                 (preg_match('/([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}/', $value))
498         ));
499
500         // Return it
501         return $isValid;
502 }
503
504 // Call-back function to check validity of 'mysql_engine'
505 function isInstallerMysqlEngineValid ($value) {
506         // This value must be 'MyISAM' or 'InnoDB'
507         $isValid = in_array($value, array('MyISAM', 'InnoDB'));
508
509         // Return it
510         return $isValid;
511 }
512
513 // Call-back function to check validity of 'mysql_dbase'
514 function isInstallerMysqlDbaseValid ($value) {
515         // This value must not be empty
516         $isValid = ((!empty($value)) && ($value != 'your_database'));
517
518         // Return it
519         return $isValid;
520 }
521
522 // Call-back function to check validity of 'mysql_login'
523 function isInstallerMysqlLoginValid ($value) {
524         // This value must not be empty
525         $isValid = ((!empty($value)) && ($value != 'your_login'));
526
527         // Return it
528         return $isValid;
529 }
530
531 // Call-back function to check validity of 'mysql_prefix'
532 function isInstallerMysqlPrefixValid ($value) {
533         // This value must not be empty
534         $isValid = !empty($value);
535
536         // Return it
537         return $isValid;
538 }
539
540 // ----------------- SMTP configuration -----------------
541
542 // ----------------- Other configuration -----------------
543
544 // ----------------- Extensions -----------------
545
546 // Call-back function to check 'sel' (array!)
547 function isInstallerSelValid ($value) {
548         // $value is not an array, is really bad.
549         if (!is_array($value)) {
550                 // Is no array
551                 reportBug(__FUNCTION__, __LINE__, 'sel,value[]=' . gettype($value) . '!=array');
552         } // END - if
553
554         // Add always missing ext-sql_patches
555         $value['sql_patches'] = '1';
556
557         // Default is fine
558         $isValid = TRUE;
559
560         // "Walk" through all extensions
561         foreach ($value as $ext_name => $sel) {
562                 // Is this extension choosen?
563                 if ($sel != '1') {
564                         // Skip this
565                         continue;
566                 } // END - if
567
568                 // Can it be loaded?
569                 $isValid = (($isValid) && (loadExtension($ext_name, 'test', '0.0.0', TRUE)));
570         } // END - foreach
571
572         // Remove 'sel' from POST data as it cannot be saved
573         unsetPostRequestElement('sel');
574
575         // Save it in session (sorry to do that here :( )
576         setSession('extensions', implode(':', array_keys($value)));
577
578         // Return result
579         return $isValid;
580 }
581
582 //-----------------------------------------------------------------------------
583 //                 Call-back functions to post-check validity
584 //-----------------------------------------------------------------------------
585
586 // Call-back function to check if base data is valid
587 function isInstallerPostBaseDataValid ($currentTab) {
588         // By default it is not valid
589         $isValid = FALSE;
590
591         // Is the base path valid?
592         if (!isInstallerBasePathValid(postRequestElement('base_path'))) {
593                 // Then mark it
594                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_BASE_PATH_INVALID--}';
595                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'base_path');
596                 return FALSE;
597         } elseif (!isInstallerBaseUrlValid(postRequestElement('base_url'))) {
598                 // Then mark it
599                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_BASE_URL_INVALID--}';
600                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'base_url');
601                 return FALSE;
602         } elseif (strlen(postRequestElement('main_title')) < 3) {
603                 // To short
604                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_MAIN_TITLE_INVALID--}';
605                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'main_title');
606                 return FALSE;
607         } elseif (strlen(postRequestElement('slogan')) < 3) {
608                 // To short
609                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_SLOGAN_INVALID--}';
610                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'slogan');
611                 return FALSE;
612         } elseif (!isInstallerWebmasterValid(postRequestElement('webmaster'))) {
613                 // Then mark it
614                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_WEBMASTER_INVALID--}';
615                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'webmaster');
616                 return FALSE;
617         } else {
618                 // All fine
619                 $isValid = TRUE;
620
621                 // Remember this tab in session
622                 installTabOkay($currentTab);
623         }
624
625         // Return it
626         return $isValid;
627 }
628
629 // Call-back function to check if database configuration in POST is valid
630 function isInstallerPostDatabaseConfigValid ($currentTab) {
631         // By default nothing is valid
632         $isValid       = FALSE;
633         $engineValid   = FALSE;
634         $missingTables = 0;
635
636         // Do both passwords match?
637         if ((!isPostRequestElementSet('mysql_password1')) && (isPostRequestElementSet('mysql_password2'))) {
638                 // Password 1 not set
639                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_PASSWORD1_EMPTY--}';
640                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_password1');
641                 return FALSE;
642         } elseif ((isPostRequestElementSet('mysql_password1')) && (!isPostRequestElementSet('mysql_password2'))) {
643                 // Password 2 not set
644                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_PASSWORD2_EMPTY--}';
645                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_password2');
646                 return FALSE;
647         } elseif (postRequestElement('mysql_password1') != postRequestElement('mysql_password2')) {
648                 // Passwords mismatch
649                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_PASSWORDS_MISMATCH--}';
650                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_password1', 'mysql_password2');
651                 return FALSE;
652         } // END - if
653
654         // Remove any previous flag
655         unsetSqlLinkUp(__FUNCTION__, __LINE__);
656
657         // Try to connect to the database
658         SQL_CONNECT(postRequestElement('mysql_host'), postRequestElement('mysql_login'), postRequestElement('mysql_password1'), __FUNCTION__, __LINE__);
659
660         // Is the link up
661         if (!SQL_IS_LINK_UP()) {
662                 // Cannot connect to database
663                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_CONNECT_ERROR--}';
664                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_login', 'mysql_password1', 'mysql_password2');
665                 return FALSE;
666         } // END - if
667
668         // Then attempt to select the database
669         if (!SQL_SELECT_DB(postRequestElement('mysql_dbase'), __FUNCTION__, __LINE__)) {
670                 // Could not find database
671                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_SELECT_FAILED--}';
672                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_dbase');
673
674                 // Disconnect here, we don't need idle database connections laying around
675                 SQL_CLOSE(__FUNCTION__, __LINE__);
676
677                 // Abort here
678                 return FALSE;
679         } // END - if
680
681         // Set database name and prefix
682         setConfigEntry('__DB_NAME'    , postRequestElement('mysql_dbase'));
683         setConfigEntry('_MYSQL_PREFIX', postRequestElement('mysql_prefix'));
684
685         // Get an array of all supported engines
686         $engines = getArrayFromSupportedSqlEngines(postRequestElement('mysql_engine'));
687
688         // Is this an array?
689         if (!is_array($engines)) {
690                 // Something bad happened
691                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_ENGINES_SQL_ERROR--}';
692                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_engine');
693
694                 // Disconnect here, we don't need idle database connections laying around
695                 SQL_CLOSE(__FUNCTION__, __LINE__);
696
697                 // Abort here
698                 return FALSE;
699         } elseif (count($engines) == 0) {
700                 // No engine is active
701                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_NO_ENGINES_ACTIVE--}';
702                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_engine');
703
704                 // Disconnect here, we don't need idle database connections laying around
705                 SQL_CLOSE(__FUNCTION__, __LINE__);
706
707                 // Abort here
708                 return FALSE;
709         }
710
711         // Then check all, if the requested is working
712         foreach ($engines as $engineArray) {
713                 // By default the selected engine is not valid
714                 $engineValid = FALSE;
715
716                 // Is the engine there?
717                 if (strtolower($engineArray['Engine']) == strtolower(postRequestElement('mysql_engine'))) {
718                         // Okay, engine is found
719                         $engineValid = TRUE;
720                         break;
721                 } // END - if
722         } // END - foreach
723
724         // So, is the engine found?
725         if ($engineValid === FALSE) {
726                 // Requested engine is not active
727                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_ENGINE_UNSUPPORTED--}';
728                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_engine');
729
730                 // Disconnect here, we don't need idle database connections laying around
731                 SQL_CLOSE(__FUNCTION__, __LINE__);
732
733                 // Abort here
734                 return FALSE;
735         } // END - if
736
737         // Init some known tables
738         $tables = array(
739                 // Admins
740                 'admins'      => TRUE,
741                 // Admin menu
742                 'admin_menu'  => TRUE,
743                 // Categories
744                 'cats'        => TRUE,
745                 // Configuration
746                 'config'      => TRUE,
747                 // Extensions
748                 'extensions'  => TRUE,
749                 // Guest menu
750                 'guest_menu'  => TRUE,
751                 // Max receive
752                 'max_receive' => TRUE,
753                 // Member menu
754                 'member_menu' => TRUE,
755                 // Module registry
756                 'mod_reg'     => TRUE,
757                 // Payments
758                 'payments'    => TRUE,
759                 // Sending pool
760                 'pool'        => TRUE,
761                 // Referral banner
762                 'refbanner'   => TRUE,
763                 // Referral levels
764                 'refdepths'   => TRUE,
765                 // Referral system
766                 'refsystem'   => TRUE,
767                 // Task system
768                 'task_system' => TRUE,
769         );
770
771         // So check if all tables are not there
772         foreach ($tables as $tableName => $isFound) {
773                 // Check it out
774                 $tables[$tableName] = ifSqlTableExists($tableName);
775
776                 // Is it (hopefully not) there?
777                 if ($tables[$tableName] === FALSE) {
778                         // This does not exist
779                         $missingTables++;
780                 } // END - if
781         } // END - foreach
782
783         // Determine final status (simply compare both counts
784         $isValid = (count($tables) == $missingTables);
785
786         // Disconnect here, we don't need idle database connections laying around
787         SQL_CLOSE(__FUNCTION__, __LINE__);
788
789         // If the status is true, disconnect the database
790         if ($isValid === FALSE) {
791                 // Still something bad happened (e.g. tables found)
792                 $GLOBALS['installer_post_error'][$currentTab] = '{--INSTALLER_POST_DATABASE_IN_USE--}';
793                 array_push($GLOBALS['installer_failed_fields'][$currentTab], 'mysql_dbase');
794         } else {
795                 // Remember this tab in session
796                 installTabOkay($currentTab);
797         }
798
799         // Return status
800         return $isValid;
801 }
802
803 // Store given tab in session
804 function installTabOkay ($currentTab) {
805         // Is it set?
806         if (isSessionVariableSet('installer_okay')) {
807                 // Is this tab already found?
808                 if (strpos(getSession('installer_okay'), $currentTab) === FALSE) {
809                         // Then extend it
810                         setSession('installer_okay', getSession('installer_okay') . ';' . $currentTab);
811                 } // END - if
812         } else {
813                 // Initially set it
814                 setSession('installer_okay', $currentTab);
815         }
816 }
817
818 // Checks whether at least the required tabs are completed
819 function isInstallationDataCompleted () {
820         // Check both
821         $isCompleted = (
822                 (isSessionVariableSet('installer_okay')) &&
823                 (strpos(getSession('installer_okay'), 'base_data') !== FALSE) &&
824                 (strpos(getSession('installer_okay'), 'database_config') !== FALSE)
825         );
826
827         // Return it
828         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isCompleted=' . intval($isCompleted) . ',installer_okay=' . getSession('installer_okay'));
829         return $isCompleted;
830 }
831
832 // Call-back function to check if enable_backlink is Y/N
833 function isInstallerEnableBacklinkValid ($currentTab) {
834         // Check and return it
835         return in_array($currentTab, array('Y', 'N'));
836 }
837
838 // Call-back function to check if warn_no_pass is Y/N
839 function isInstallerWarnNoPassValid ($currentTab) {
840         // Check and return it
841         return in_array($currentTab, array('Y', 'N'));
842 }
843
844 // Call-back function to check if write_footer is Y/N
845 function isInstallerWriteFooterValid ($currentTab) {
846         // Check and return it
847         return in_array($currentTab, array('Y', 'N'));
848 }
849
850 // Call-back function to check if output_mode is Y/N
851 function isInstallerOutputModeValid ($currentTab) {
852         // Check and return it
853         return in_array($currentTab, array('render', 'direct'));
854 }
855
856 // Wrapper to import given installation SQL dump
857 function importInstallSqlDump ($dumpName) {
858         // Import the file
859         importSqlDump('install', $dumpName, 'install');
860 }
861
862 // [EOF]
863 ?>