2 /************************************************************************
3 * Mailer v0.2.1-FINAL Start: 06/24/2012 *
4 * =================== Last change: 06/24/2012 *
6 * -------------------------------------------------------------------- *
7 * File : ajax_installer.php *
8 * -------------------------------------------------------------------- *
9 * Short description : AJAX-related functions for installer *
10 * -------------------------------------------------------------------- *
11 * Kurzbeschreibung : AJAX-bezogene Funktionen fuer Installer *
12 * -------------------------------------------------------------------- *
15 * $Tag:: 0.2.1-FINAL $ *
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 *
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. *
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. *
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, *
36 ************************************************************************/
38 // Some security stuff...
39 if (!defined('__SECURITY')) {
41 } elseif ((!isAjaxOutputMode()) || (!isInstaller())) {
42 header('HTTP/1.1 403 Forbidden');
43 die(json_encode(array('reply_content' => 'Access forbidden'), JSON_FORCE_OBJECT));
46 //-----------------------------------------------------------------------------
47 // Generic call-back functions, they all rely on session data
48 //-----------------------------------------------------------------------------
50 // Establish a database link
51 function establishAjaxInstallerDatabaseLink () {
52 // This requires some session data
53 if (!isSessionDataSet(array('mysql_host', 'mysql_dbase', 'mysql_prefix', 'mysql_login', 'mysql_password1', 'mysql_password2', 'mysql_engine'))) {
54 // Some required session data is not set
55 reportBug(__FUNCTION__, __LINE__, 'Required session data for this step not found.');
58 // Remove any previous flag
59 unsetSqlLinkUp(__FUNCTION__, __LINE__);
62 $linkResource = sqlConnectToDatabase(getSession('mysql_host'), getSession('mysql_login'), getSession('mysql_password1'), __FUNCTION__, __LINE__);
64 // Is this a link resource?
65 if (!isValidSqlLink($linkResource)) {
67 reportBug(__FUNCTION__, __LINE__, 'linkResource[]=' . gettype($linkResource) . ', expected: link resource');
68 } elseif (!isSqlLinkUp()) {
70 reportBug(__FUNCTION__, __LINE__, 'Could not bring up SQL link.');
73 // Does selecting the database work?
74 if (!sqlSelectDatabase(getSession('mysql_dbase'), __FUNCTION__, __LINE__)) {
75 // Could not be selected
76 reportBug(__FUNCTION__, __LINE__, 'Could not select database ' . getSession('mysql_dbase'));
77 } elseif (!isInstallerSqlsReadable(getSession('base_path'))) {
78 // Installation area not found
79 reportBug(__FUNCTION__, __LINE__, 'SQL dumps not found. Please extract ALL files from the archive or checkout all files out from SVN.');
80 } elseif (ifFatalErrorsDetected()) {
81 // Some other fatal error occured
82 reportBug(__FUNCTION__, __LINE__, 'Some fatal error detected, please check debug.log for details.');
85 // Set type, prefix from POST data and database name for later queries
86 setConfigEntry('_TABLE_TYPE' , getSession('mysql_engine'));
87 setConfigEntry('_MYSQL_PREFIX', getSession('mysql_prefix'));
88 setConfigEntry('__DB_NAME' , getSession('mysql_dbase'));
91 //-----------------------------------------------------------------------------
92 // Call-back functions for processing AJAX requests
93 //-----------------------------------------------------------------------------
95 // Processes AJAX requests for installer
96 function doAjaxProcessInstall () {
97 // 'do' must always be set and installation phase must be true
99 // This shall not happen
100 reportBug(__FUNCTION__, __LINE__, 'This AJAX request handler was called outside the installer.');
101 } elseif (!isPostRequestElementSet('do')) {
102 // This shall not happen
103 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "do" which is fatal.');
106 // Notify all modules that we are installing
107 $GLOBALS['__mailer_installing'] = TRUE;
109 // Again we do a call-back, so generate a function name depending on 'do'
110 $callbackName = 'doAjaxInstaller' . capitalizeUnderscoreString(postRequestElement('do'));
111 $GLOBALS['ajax_callback_function'] = $callbackName;
113 // Is the call-back function there?
114 if (!function_exists($callbackName)) {
115 // This shall not happen
116 reportBug(__FUNCTION__, __LINE__, 'AJAX call-back ' . $callbackName . ' does not exist.');
120 call_user_func($callbackName);
122 // Is the status fine or template not found (404)?
126 // Processes installer request for testing
127 function doAjaxInstallerTest () {
128 // Load the "test passed" template
129 setAjaxReplyContent(loadTemplate('ajax_test_passed', TRUE));
131 // All okay if we reach this point
132 setHttpStatus('200 OK');
135 // Processes installer requests for footer navigation
136 function doAjaxInstallerFooterNavigation () {
137 // 'tab' must always be set to determine which navigation buttons shall be visible
138 if (!isPostRequestElementSet('tab')) {
139 // This shall not happen
140 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
143 // Init array for footer navigation
144 $enabledNavigations = array();
146 // "Detect" the 'tab' value
147 switch (postRequestElement('tab')) {
148 case 'base_data': // Also 'previous' is valid
149 case 'database_config':
154 array_push($enabledNavigations, 'previous');
155 case 'welcome': // Only 'next' works for welcome page
156 array_push($enabledNavigations, 'next');
159 case 'overview': // Enable only 'previous'
160 array_push($enabledNavigations, 'previous');
161 if (isInstallationDataCompleted()) {
163 array_push($enabledNavigations, 'finish');
167 default: // Unsupported value
168 // This shall not happen
169 reportBug(__FUNCTION__, __LINE__, 'Unsupported "tab" value ' . postRequestElement('tab') . ' detected.');
171 // This will never be reached
175 // Output the array for JSON reply
176 setAjaxReplyContent(encodeJson($enabledNavigations));
178 // All okay if we reach this point
179 setHttpStatus('200 OK');
182 // Processes installer AJAX calls for content-requests
183 function doAjaxInstallerDoStep () {
184 // 'step' must be there
185 if (!isPostRequestElementSet('step')) {
186 // This shall not happen
187 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "step" which is fatal.');
190 // Construct call-back name
191 $callbackName = 'doAjaxInstallerStep' . capitalizeUnderscoreString(postRequestElement('step'));
193 // Is the function there?
194 if (function_exists($callbackName)) {
195 // Call it for setting values in session
196 $status = call_user_func($callbackName);
198 // Log missing functions
199 reportBug(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' does not exist.');
202 // Did the installation step went fine?
203 if ($status === TRUE) {
205 setAjaxReplyContent(encodeJson(postRequestElement('step') . '=OK'));
207 // All okay if we reach this point
208 setHttpStatus('200 OK');
212 // Processes installer AJAX calls for content-requests
213 function doAjaxInstallerRequestContent () {
214 // 'tab' must be there
215 if (!isPostRequestElementSet('tab')) {
216 // This shall not happen
217 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
220 // Construct call-back name for value-preset
221 $callbackName = 'doAjaxPrepareInstaller' . capitalizeUnderscoreString(postRequestElement('tab'));
223 // Is the function there?
224 if (function_exists($callbackName)) {
225 // Call it for setting values in session
226 call_user_func($callbackName);
228 // Log missing functions
229 reportBug(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' does not exist.');
232 // Is the HTTP status still the same? (204 No Content)
233 if (getHttpStatus() == '204 No Content') {
234 // We use the current access level 'install' as prefix and construct a template name
235 setAjaxReplyContent(loadTemplate('install_page_' . trim(postRequestElement('tab')), TRUE));
237 // Has the template been loaded?
238 if (isset($GLOBALS['template_content']['html']['install_page_' . trim(postRequestElement('tab'))])) {
239 // All okay if we reach this point
240 setHttpStatus('200 OK');
243 setHttpStatus('404 Not Found');
248 // Process installer AJAX call for change-warning
249 function doAjaxInstallerChangeWarning () {
250 // 'elements' and 'button' must be there
251 if ((!isPostRequestElementSet('elements')) || (!isPostRequestElementSet('button'))) {
252 // This shall not happen
253 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "elements" and/or "button" which is fatal.');
256 // "Walk" through all elements
258 foreach (explode(':', postRequestElement('elements')) as $element) {
259 // Is it an extension?
260 if (substr($element, 0, 4) == 'ext_') {
261 // Add row for extension
262 $OUT .= '<li>{%message,INSTALLER_CHANGED_ELEMENT_EXTENSION=' . str_replace('_', '-', $element) . '%}</li>';
265 $OUT .= '<li>{--INSTALLER_CHANGED_ELEMENT_' . strtoupper($element) . '--}</li>';
273 'button' => postRequestElement('button'),
274 'message' => '{--INSTALLER_TAB_NAVIGATION_' . strtoupper(postRequestElement('button')) . '_LINK--}',
277 if (in_array(postRequestElement('button'), array('previous', 'next'))) {
278 // Load 'prefixed' template
279 setAjaxReplyContent(loadTemplate('install_warning_' . postRequestElement('button'), TRUE, $content));
281 // Load 'tab' template
282 setAjaxReplyContent(loadTemplate('install_warning_tab', TRUE, $content));
285 // All okay if we reach this point
286 setHttpStatus('200 OK');
289 // Process installer AJAC call for saving changes
290 function doAjaxInstallerSaveChanges () {
291 // 'tab' must always be set to create a post-check-callback
292 if (!isPostRequestElementSet('tab')) {
293 // This shall not happen
294 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
297 // Save the tab for pre-"filtering"
298 $currentTab = postRequestElement('tab');
300 // Remove some elements which should not be saved
301 foreach (array('tab', 'do', 'level') as $removedElement) {
302 // Remove this element from POST data
303 unsetPostRequestElement($removedElement);
306 // Default is failed save attempt (e.g. nothing to save)
308 'status' => 'failed',
309 'message' => '{--INSTALLER_SAVE_CHANGES_FAILED--}',
310 // Don't set this to false, or else it will be returned as 'failed' but is saved
312 'failed_fields' => array()
315 // Init overall status
318 // Now set all remaining data in session
319 foreach (postRequestArray() as $key => $value) {
320 // Set it, if it is valid, else it will be added to $saveStatus (call-by-reference)
321 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value[' . gettype($value) . '=' . $value);
322 $saveStatus['is_saved'] = (
323 // Is the data valid?
324 (isInstallerDataValid($saveStatus, $key, $value))
326 // And can it be stored in session?
327 (setSession($key, $value))
330 // Save the overall status for below final check
331 $isAllSaved = (($isAllSaved === TRUE) && ($saveStatus['is_saved'] === TRUE));
332 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value[' . gettype($value) . '=' . $value . ',is_saved=' . intval($saveStatus['is_saved']) . ',isAllSaved=' . intval($isAllSaved));
335 // 'is_saved' is still true?
336 if ($isAllSaved === TRUE) {
337 // Set 'done' and message
338 $saveStatus['status'] = 'done';
339 $saveStatus['message'] = '{--INSTALLER_SAVE_CHANGES_DONE--}';
341 // Then do the post-check
342 doInstallerPostCheck($currentTab, $saveStatus);
345 // Output the status array for JSON reply
346 setAjaxReplyContent(encodeJson($saveStatus));
348 // All okay if we reach this point
349 setHttpStatus('200 OK');
352 // ----------------------------------------------------------------------------
353 // Call-back functions for preparing installer page requests
354 // ----------------------------------------------------------------------------
356 // Prepare AJAX request 'welcome'
357 function doAjaxPrepareInstallerWelcome () {
358 // Kept empty to prevent logfile entry
361 // Prepare AJAX request 'base_data'
362 function doAjaxPrepareInstallerBaseData () {
363 // Is 'base_path' not set?
364 if (!isSessionVariableSet('base_path')) {
365 // Then set it from PATH
366 setSession('base_path', getPath());
369 // Is 'base_url' not set?
370 if (!isSessionVariableSet('base_url')) {
371 // Then set it from URL
372 setSession('base_url', getUrl());
375 // Is 'main_title' not set?
376 if (!isSessionVariableSet('main_title')) {
377 // Then set it from default main title
378 setSession('main_title', compileRawCode(getMessage('DEFAULT_MAIN_TITLE')));
381 // Is 'slogan' not set?
382 if (!isSessionVariableSet('slogan')) {
383 // Then set it from default slogan
384 setSession('slogan', compileRawCode(getMessage('DEFAULT_SLOGAN')));
387 // Is 'webmaster' not set?
388 if (!isSessionVariableSet('webmaster')) {
389 // Then set it from default webmaster email address
390 setSession('webmaster', '{--DEFAULT_WEBMASTER--}');
394 // Prepare AJAX request 'database_config'
395 function doAjaxPrepareInstallerDatabaseConfig () {
396 // Is 'mysql_host' not set?
397 if (!isSessionVariableSet('mysql_host')) {
398 // Then set it directly
399 setSession('mysql_host', 'localhost');
402 // Is 'mysql_dbase' not set?
403 if (!isSessionVariableSet('mysql_dbase')) {
404 // Then set it directly
405 setSession('mysql_dbase', 'your_database');
408 // Is 'mysql_prefix' not set?
409 if (!isSessionVariableSet('mysql_prefix')) {
410 // Then set it directly
411 setSession('mysql_prefix', 'mailer');
414 // Is 'mysql_login' not set?
415 if (!isSessionVariableSet('mysql_login')) {
416 // Then set it directly
417 setSession('mysql_login', 'your_login');
420 // Is 'mysql_dbase' not set?
421 if (!isSessionVariableSet('mysql_password1')) {
422 // Then set it directly
423 setSession('mysql_password1', '');
426 // Is 'mysql_password2' not set?
427 if (!isSessionVariableSet('mysql_password2')) {
428 // Then set it directly
429 setSession('mysql_password2', '');
432 // Is 'mysql_engine' not set?
433 if (!isSessionVariableSet('mysql_engine')) {
434 // Then set it directly
435 setSession('mysql_engine', 'MyISAM');
439 // Prepare AJAX request 'smtp_config'
440 function doAjaxPrepareInstallerSmtpConfig () {
441 // Kept empty to prevent logfile entry because SMTP settings are optional
444 // Prepare AJAX request 'other_config'
445 function doAjaxPrepareInstallerOtherConfig () {
446 // Is 'output_mode' not set?
447 if (!isSessionVariableSet('output_mode')) {
448 // Then set it directly
449 setSession('output_mode', 'render');
452 // Is 'warn_no_pass' not set?
453 if (!isSessionVariableSet('warn_no_pass')) {
454 // Then set it directly
455 setSession('warn_no_pass', 'Y');
458 // Is 'write_footer' not set?
459 if (!isSessionVariableSet('write_footer')) {
460 // Then set it directly
461 setSession('write_footer', 'Y');
464 // Is 'enable_backlink' not set?
465 if (!isSessionVariableSet('enable_backlink')) {
466 // Then set it directly
467 setSession('enable_backlink', 'Y');
471 // Prepare AJAX request 'extensions'
472 function doAjaxPrepareInstallerExtensions () {
473 // Is 'extensions' set?
474 if (!isSessionVariableSet('extensions')) {
476 * At least ext-admins, ext-sql_patches and ext-task should be installed
477 * (ext-sql_patches is a must!)
479 setSession('extensions', 'admins:sql_patches:task');
480 } elseif (strpos(getSession('extensions'), 'sql_patches') === FALSE) {
481 // Add missing ext-sql_patches
482 setSession('extensions', getSession('extensions') . ':sql_patches');
486 // Prepare AJAX request 'first_admin'
487 function doAjaxPrepareInstallerFirstAdmin () {
488 // Is 'admin_login' set?
489 if (!isSessionVariableSet('admin_login')) {
491 setSession('admin_login', 'admin');
494 // Is 'admin_email' set?
495 if (!isSessionVariableSet('admin_email')) {
497 setSession('admin_email', getSession('webmaster'));
500 // Is 'admin_password1' set?
501 if (!isSessionVariableSet('admin_password1')) {
503 setSession('admin_password1', '');
506 // Is 'admin_password2' set?
507 if (!isSessionVariableSet('admin_password2')) {
509 setSession('admin_password2', '');
513 // Prepare AJAX request 'overview'
514 function doAjaxPrepareInstallerOverview () {
515 // 'tab' must always be set to create a post-check-callback
516 if (!isPostRequestElementSet('tab')) {
517 // This shall not happen
518 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
521 // Save the tab for pre-"filtering"
522 $currentTab = postRequestElement('tab');
524 // Default is failed save attempt (e.g. nothing to save)
525 $verificationStatus = array(
526 // Status code, can be 'failed' or 'done'
527 'status' => 'failed',
528 // Status message (e.g. for output)
529 'message' => '{--INSTALLER_OVERVIEW_FINAL_CHECK_FAILED--}',
530 // Don't set this to false, or else it will be returned as 'failed' but is saved
533 'failed_fields' => array()
536 // Init overall status and final output
540 // Check all data in session
541 foreach (array_keys($GLOBALS['installer_groups']) as $key) {
542 // Get values from session
543 $value = getSession($key);
545 // Is the data valid?
546 $verificationStatus['is_valid'] = (isInstallerDataValid($verificationStatus, $key, $value));
548 // Is this step okay?
549 if ($verificationStatus['is_valid'] === TRUE) {
550 // Add this key/value pair to a overview group
551 addKeyValueToInstallerOverviewGroup($key, $value);
554 // Save the overall status for below final check
555 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ',is_valid=' . intval($verificationStatus['is_valid']) . ',isAllValid=' . intval($isAllValid));
556 $isAllValid = (($isAllValid === TRUE) && ($verificationStatus['is_valid'] === TRUE));
560 if ((isInstallationDataCompleted()) && ($isAllValid === TRUE)) {
561 // Set 'done' and message
562 $verificationStatus['status'] = 'done';
563 $verificationStatus['message'] = '{--INSTALLER_OVERVIEW_FINAL_CHECK_DONE--}';
565 // Then do the post-check
566 doInstallerPostCheck($currentTab, $verificationStatus);
569 // Is it still valid?
570 if ($verificationStatus['status'] != 'done') {
572 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Final check on all stored data failed. message=' . $verificationStatus['message']);
574 // Process failed fields
575 $verificationStatus['failed_fields'] = handleInstallerFailedFields($verificationStatus['failed_fields']);
577 // Output the array for JSON reply
578 setAjaxReplyContent(loadTemplate('install_overview_failed', TRUE, $verificationStatus));
581 * Something went wrong, this might happen when e.g. the user has tried
582 * to save invalid database login data but hit reload button on error
585 setHttpStatus('200 OK');
592 // ----------------------------------------------------------------------------
593 // Call-back functions for doing installation steps
594 // ----------------------------------------------------------------------------
596 // Call-back function to import first tables.sql file
597 function doAjaxInstallerStepImportTablesSql () {
598 // Establish database link
599 establishAjaxInstallerDatabaseLink();
605 importInstallSqlDump('tables');
607 // Are some SQLs found?
608 if (countSqls() == 0) {
610 reportBug(__FUNCTION__, __LINE__, '{--INSTALLER_SQL_IMPORT_FAILED--}');
613 // Now run all queries through
614 runFilterChain('run_sqls');
617 sqlCloseLink(__FUNCTION__, __LINE__);
623 // Call-back function to import menu SQL file
624 function doAjaxInstallerStepImportMenuSql () {
625 // Establish database link
626 establishAjaxInstallerDatabaseLink();
632 importInstallSqlDump('menu-' . getLanguage());
634 // Are some SQLs found?
635 if (countSqls() == 0) {
637 reportBug(__FUNCTION__, __LINE__, '{--INSTALLER_SQL_IMPORT_FAILED--}');
640 // Now run all queries through
641 runFilterChain('run_sqls');
644 sqlCloseLink(__FUNCTION__, __LINE__);
650 // Call-back function to install some important extensions
651 function doAjaxInstallerStepInstallExtensions () {
652 // Only one element is required
653 if (!isSessionVariableSet('extensions')) {
654 // Some required session data is not set
655 reportBug(__FUNCTION__, __LINE__, 'Required session data for this step not found.');
658 // Establish database link
659 establishAjaxInstallerDatabaseLink();
661 // Get all extensions
662 $extensions = explode(':', getSession('extensions'));
664 // Make sure ext-sql_patches is first
665 array_unshift($extensions, 'sql_patches');
667 // "Walk" through all extensions
668 foreach ($extensions as $key => $ext_name) {
669 // Is ext-sql_patches not at key=0?
670 if (($key == 0) && ($ext_name == 'sql_patches')) {
671 // Then skip this entry
673 } elseif ((!loadExtension($ext_name, 'test', '0.0.0', TRUE)) || (!registerExtension($ext_name, NULL))) {
675 reportBug(__FUNCTION__, __LINE__, 'Cannot load/register extension ' . $ext_name . '.');
683 // Call-back function to write local configuration file
684 function doAjaxInstallerStepWriteLocalConfig () {
686 if (!isSessionDataSet(array('base_path', 'base_url', 'main_title', 'slogan', 'webmaster', 'mysql_host', 'mysql_dbase', 'mysql_prefix', 'mysql_login', 'mysql_password1', 'mysql_password2', 'mysql_engine', 'output_mode', 'warn_no_pass', 'write_footer', 'enable_backlink'))) {
687 // Some required session data is not set
688 reportBug(__FUNCTION__, __LINE__, 'Required session data for this step not found.');
689 } elseif (isInstalled()) {
690 // Is already installed = local config written
691 reportBug(__FUNCTION__, __LINE__, 'Local config file is already written.');
692 } elseif (isAdminRegistered()) {
693 // Admin is already registered
694 reportBug(__FUNCTION__, __LINE__, 'First administrator account is already registered.');
697 // Establish database link
698 establishAjaxInstallerDatabaseLink();
701 if (!doInstallWriteLocalConfigurationFile(
702 getSession('base_path'),
703 getSession('base_url'),
704 getSession('main_title'),
705 getSession('slogan'),
706 getSession('webmaster'),
707 getSession('warn_no_pass'),
708 getSession('write_footer'),
709 getSession('enable_backlink'),
710 getSession('mysql_host'),
711 getSession('mysql_dbase'),
712 getSession('mysql_login'),
713 getSession('mysql_password1'),
714 getSession('mysql_prefix'),
715 getSession('mysql_engine'),
716 getSession('smtp_host'),
717 getSession('smtp_user'),
718 getSession('smtp_password1')
720 // Something bad went wrong
721 removeFile(getSession('base_path') . getCachePath() . 'config-local.php');
722 reportBug(__FUNCTION__, __LINE__, 'Did not fully write config-local.php .');
725 // Change ADMIN_REGISTERED flag
726 $done = changeDataInLocalConfigurationFile('ADMIN-SETUP', "setConfigEntry('ADMIN_REGISTERED', '", "');", 'Y', 0);
732 // Call-back function to register first admin
733 function doAjaxInstallerStepRegisterFirstAdmin () {
735 if (!isSessionDataSet(array('admin_login', 'admin_email', 'admin_password1', 'admin_password2'))) {
736 // Some required session data is not set
737 reportBug(__FUNCTION__, __LINE__, 'Required session data for this step not found.');
738 } elseif (isAdminRegistered()) {
739 // First admin is already registered
740 reportBug(__FUNCTION__, __LINE__, 'First administrator is already registered.');
743 // Establish database link
744 establishAjaxInstallerDatabaseLink();
746 // Load admin include
747 loadIncludeOnce('inc/modules/admin/admin-inc.php');
749 // Register first admin
750 $ret = addAdminAccount(getSession('admin_login'), md5(getSession('admin_password1')), getSession('admin_email'), 'allow');
753 return ($ret == 'done');