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