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