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