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 - 2012 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')) || (!isAjaxOutputMode()) || (!isInstallationPhase())) {
43 //-----------------------------------------------------------------------------
44 // Generic call-back functions, they all rely on session data
45 //-----------------------------------------------------------------------------
47 // Establish a database link
48 function establishAjaxInstallerDatabaseLink () {
49 // This requires some session data
50 if (!isSessionDataSet(array('mysql_host', 'mysql_dbase', 'mysql_prefix', 'mysql_login', 'mysql_password1', 'mysql_password2', 'mysql_engine'))) {
51 // Some required session data is not set
52 reportBug(__FUNCTION__, __LINE__, 'Required session data for this step not found.');
56 $linkResource = SQL_CONNECT(getSession('mysql_host'), getSession('mysql_login'), getSession('mysql_password1'), __FUNCTION__, __LINE__);
58 // Is this a link resource?
59 if (!is_resource($linkResource)) {
61 reportBug(__FUNCTION__, __LINE__, 'linkResource[]=' . gettype($linkResource) . ', expected: link resource');
64 // Does selecting the database work?
65 if (!SQL_SELECT_DB(getSession('mysql_dbase'), __FUNCTION__, __LINE__)) {
66 // Could not be selected
67 reportBug(__FUNCTION__, __LINE__, 'Could not select database ' . getSession('mysql_dbase'));
68 } elseif ((!isFileReadable(getPath() . 'install/tables.sql')) || (!isFileReadable(getPath() . 'install/menu-'.getLanguage().'.sql'))) {
69 // Installation area not found
70 reportBug(__FUNCTION__, __LINE__, 'SQL dumps not found. Please extract ALL files from the archive or checkout all files out from SVN.');
71 } elseif (ifFatalErrorsDetected()) {
72 // Some other fatal error occured
73 reportBug(__FUNCTION__, __LINE__, 'Some fatal error detected, please check debug.log for details.');
76 // Set type, prefix from POST data and database name for later queries
77 setConfigEntry('_TABLE_TYPE' , getSession('mysql_engine'));
78 setConfigEntry('_MYSQL_PREFIX', getSession('mysql_prefix'));
79 setConfigEntry('__DB_NAME' , getSession('mysql_dbase'));
82 //-----------------------------------------------------------------------------
83 // Call-back functions for processing AJAX requests
84 //-----------------------------------------------------------------------------
86 // Processes AJAX requests for installer
87 function doAjaxProcessInstall () {
88 // 'do' must always be set and installation phase must be true
89 if (!isInstallationPhase()) {
90 // This shall not happen
91 reportBug(__FUNCTION__, __LINE__, 'This AJAX request handler was called outside the installer.');
92 } elseif (!isPostRequestElementSet('do')) {
93 // This shall not happen
94 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "do" which is fatal.');
97 // Notify all modules that we are installing
98 $GLOBALS['__mailer_installing'] = TRUE;
100 // Again we do a call-back, so generate a function name depending on 'do'
101 $callbackName = 'doAjaxInstaller' . capitalizeUnderscoreString(postRequestElement('do'));
103 // Is the call-back function there?
104 if (!function_exists($callbackName)) {
105 // This shall not happen
106 reportBug(__FUNCTION__, __LINE__, 'AJAX call-back ' . $callbackName . ' does not exist.');
110 call_user_func($callbackName);
112 // Is the status fine or template not found (404)?
116 // Processes installer request for testing
117 function doAjaxInstallerTest () {
118 // Load the "test passed" template
119 setAjaxReplyContent(encodeJson(postRequestElement('step').'=OK'));
121 // All okay if we reach this point
122 setHttpStatus('200 OK');
125 // Processes installer requests for footer navigation
126 function doAjaxInstallerFooterNavigation () {
127 // 'tab' must always be set to determine which navigation buttons shall be visible
128 if (!isPostRequestElementSet('tab')) {
129 // This shall not happen
130 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
133 // Init array for footer navigation
134 $enabledNavigations = array();
136 // "Detect" the 'tab' value
137 switch (postRequestElement('tab')) {
138 case 'base_data': // Also 'previous' is valid
139 case 'database_config':
142 array_push($enabledNavigations, 'previous');
143 case 'welcome': // Only 'next' works for welcome page
144 array_push($enabledNavigations, 'next');
147 case 'overview': // Enable only 'previous'
148 array_push($enabledNavigations, 'previous');
149 if (isInstallationDataCompleted()) {
151 array_push($enabledNavigations, 'finish');
155 default: // Unsupported value
156 // This shall not happen
157 reportBug(__FUNCTION__, __LINE__, 'Unsupported "tab" value ' . postRequestElement('tab') . ' detected.');
159 // This will never be reached
163 // Output the array for JSON reply
164 setAjaxReplyContent(encodeJson($enabledNavigations));
166 // All okay if we reach this point
167 setHttpStatus('200 OK');
170 // Processes installer AJAX calls for content-requests
171 function doAjaxInstallerDoStep () {
172 // 'step' must be there
173 if (!isPostRequestElementSet('step')) {
174 // This shall not happen
175 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "step" which is fatal.');
178 // Construct call-back name
179 $callbackName = 'doAjaxInstallerStep' . capitalizeUnderscoreString(postRequestElement('step'));
181 // Is the function there?
182 if (function_exists($callbackName)) {
183 // Call it for setting values in session
184 call_user_func($callbackName);
186 // Log missing functions
187 reportBug(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' does not exist.');
191 setAjaxReplyContent(loadTemplate('install_step_passed', TRUE, postRequestElement('step')));
193 // All okay if we reach this point
194 setHttpStatus('200 OK');
197 // Processes installer AJAX calls for content-requests
198 function doAjaxInstallerRequestContent () {
199 // 'tab' must be there
200 if (!isPostRequestElementSet('tab')) {
201 // This shall not happen
202 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
205 // Construct call-back name for value-preset
206 $callbackName = 'doAjaxPrepareInstaller' . capitalizeUnderscoreString(postRequestElement('tab'));
208 // Is the function there?
209 if (function_exists($callbackName)) {
210 // Call it for setting values in session
211 call_user_func($callbackName);
213 // Log missing functions
214 reportBug(__FUNCTION__, __LINE__, 'Call-back function ' . $callbackName . ' does not exist.');
217 // Is the HTTP status still the same? (204 No Content)
218 if (getHttpStatus() == '204 No Content') {
219 // We use the current access level 'install' as prefix and construct a template name
220 setAjaxReplyContent(loadTemplate('install_page_' . trim(postRequestElement('tab')), TRUE));
222 // Has the template been loaded?
223 if (isset($GLOBALS['template_content']['html']['install_page_' . trim(postRequestElement('tab'))])) {
224 // All okay if we reach this point
225 setHttpStatus('200 OK');
228 setHttpStatus('404 NOT FOUND');
233 // Process installer AJAX call for change-warning
234 function doAjaxInstallerChangeWarning () {
235 // 'elements' and 'button' must be there
236 if ((!isPostRequestElementSet('elements')) || (!isPostRequestElementSet('button'))) {
237 // This shall not happen
238 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "elements" and/or "button" which is fatal.');
241 // "Walk" through all elements
243 foreach (explode(':', postRequestElement('elements')) as $element) {
245 $OUT .= '<li>{--INSTALLER_CHANGED_ELEMENT_' . strtoupper($element) . '--}</li>';
252 'button' => postRequestElement('button'),
253 'message' => '{--INSTALLER_TAB_NAVIGATION_' . strtoupper(postRequestElement('button')) . '_LINK--}',
256 if (in_array(postRequestElement('button'), array('previous', 'next'))) {
257 // Load 'prefixed' template
258 setAjaxReplyContent(loadTemplate('install_warning_' . postRequestElement('button'), TRUE, $content));
260 // Load 'tab' template
261 setAjaxReplyContent(loadTemplate('install_warning_tab', TRUE, $content));
264 // All okay if we reach this point
265 setHttpStatus('200 OK');
268 // Process installer AJAC call for saving changes
269 function doAjaxInstallerSaveChanges () {
270 // 'tab' must always be set to create a post-check-callback
271 if (!isPostRequestElementSet('tab')) {
272 // This shall not happen
273 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
276 // Save the tab for pre-"filtering"
277 $currentTab = postRequestElement('tab');
279 // Remove some elements which should not be saved
280 foreach (array('do', 'level') as $removedElement) {
281 // Remove this element from POST data
282 unsetPostRequestElement($removedElement);
285 // Default is failed save attempt (e.g. nothing to save)
287 'status' => 'failed',
288 'message' => '{--INSTALLER_SAVE_CHANGES_FAILED--}',
289 // Don't set this to false, or else it will be returned as 'failed' but is saved
291 'failed_fields' => array()
294 // Init overall status
297 // Now set all remaining data in session
298 foreach (postRequestArray() as $key => $value) {
299 // Set it, if it is valid, else it will be added to $saveStatus (call-by-reference)
300 $saveStatus['is_saved'] = (
301 // Is the data valid?
302 (isInstallerDataValid($saveStatus, $key, $value))
304 // And can it be stored in session?
305 (setSession($key, $value))
308 // Save the overall status for below final check
309 $isAllSaved = (($isAllSaved === TRUE) && ($saveStatus['is_saved'] === TRUE));
310 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ',is_saved=' . intval($saveStatus['is_saved']) . ',isAllSaved=' . intval($isAllSaved));
313 // 'is_saved' is still true?
314 if ($isAllSaved === TRUE) {
315 // Set 'done' and message
316 $saveStatus['status'] = 'done';
317 $saveStatus['message'] = '{--INSTALLER_SAVE_CHANGES_DONE--}';
319 // Then do the post-check
320 doInstallerPostCheck($currentTab, $saveStatus);
323 // Output the status array for JSON reply
324 setAjaxReplyContent(encodeJson($saveStatus));
326 // All okay if we reach this point
327 setHttpStatus('200 OK');
330 // ----------------------------------------------------------------------------
331 // Call-back functions for preparing installer page requests
332 // ----------------------------------------------------------------------------
334 // Prepare AJAX request 'welcome'
335 function doAjaxPrepareInstallerWelcome () {
336 // Kept empty to prevent logfile entry
339 // Prepare AJAX request 'base_data'
340 function doAjaxPrepareInstallerBaseData () {
341 // Is 'base_path' not set?
342 if (!isSessionVariableSet('base_path')) {
343 // Then set it from PATH
344 setSession('base_path', getPath());
347 // Is 'base_url' not set?
348 if (!isSessionVariableSet('base_url')) {
349 // Then set it from URL
350 setSession('base_url', getUrl());
353 // Is 'main_title' not set?
354 if (!isSessionVariableSet('main_title')) {
355 // Then set it from default main title
356 setSession('main_title', '{--DEFAULT_MAIN_TITLE--}');
359 // Is 'slogan' not set?
360 if (!isSessionVariableSet('slogan')) {
361 // Then set it from default slogan
362 setSession('slogan', '{--DEFAULT_SLOGAN--}');
365 // Is 'webmaster' not set?
366 if (!isSessionVariableSet('webmaster')) {
367 // Then set it from default webmaster email address
368 setSession('webmaster', '{--DEFAULT_WEBMASTER--}');
372 // Prepare AJAX request 'database_config'
373 function doAjaxPrepareInstallerDatabaseConfig () {
374 // Is 'mysql_host' not set?
375 if (!isSessionVariableSet('mysql_host')) {
376 // Then set it directly
377 setSession('mysql_host', 'localhost');
380 // Is 'mysql_dbase' not set?
381 if (!isSessionVariableSet('mysql_dbase')) {
382 // Then set it directly
383 setSession('mysql_dbase', 'your_database');
386 // Is 'mysql_prefix' not set?
387 if (!isSessionVariableSet('mysql_prefix')) {
388 // Then set it directly
389 setSession('mysql_prefix', 'mailer');
392 // Is 'mysql_login' not set?
393 if (!isSessionVariableSet('mysql_login')) {
394 // Then set it directly
395 setSession('mysql_login', 'your_login');
398 // Is 'mysql_dbase' not set?
399 if (!isSessionVariableSet('mysql_password1')) {
400 // Then set it directly
401 setSession('mysql_password1', '');
404 // Is 'mysql_password2' not set?
405 if (!isSessionVariableSet('mysql_password2')) {
406 // Then set it directly
407 setSession('mysql_password2', '');
410 // Is 'mysql_engine' not set?
411 if (!isSessionVariableSet('mysql_engine')) {
412 // Then set it directly
413 setSession('mysql_engine', 'MyISAM');
417 // Prepare AJAX request 'smtp_config'
418 function doAjaxPrepareInstallerSmtpConfig () {
419 // Kept empty to prevent logfile entry because SMTP settings are optional
422 // Prepare AJAX request 'other_config'
423 function doAjaxPrepareInstallerOtherConfig () {
424 // Is 'output_mode' not set?
425 if (!isSessionVariableSet('output_mode')) {
426 // Then set it directly
427 setSession('output_mode', 'render');
430 // Is 'warn_no_pass' not set?
431 if (!isSessionVariableSet('warn_no_pass')) {
432 // Then set it directly
433 setSession('warn_no_pass', 'Y');
436 // Is 'write_footer' not set?
437 if (!isSessionVariableSet('write_footer')) {
438 // Then set it directly
439 setSession('write_footer', 'Y');
442 // Is 'enable_backlink' not set?
443 if (!isSessionVariableSet('enable_backlink')) {
444 // Then set it directly
445 setSession('enable_backlink', 'Y');
449 // Prepare AJAX request 'overview'
450 function doAjaxPrepareInstallerOverview () {
451 // 'tab' must always be set to create a post-check-callback
452 if (!isPostRequestElementSet('tab')) {
453 // This shall not happen
454 reportBug(__FUNCTION__, __LINE__, 'The JavaScript did not send "tab" which is fatal.');
457 // Save the tab for pre-"filtering"
458 $currentTab = postRequestElement('tab');
460 // Default is failed save attempt (e.g. nothing to save)
461 $verificationStatus = array(
462 // Status code, can be 'failed' or 'done'
463 'status' => 'failed',
464 // Status message (e.g. for output)
465 'message' => '{--INSTALLER_OVERVIEW_FINAL_CHECK_FAILED--}',
466 // Don't set this to false, or else it will be returned as 'failed' but is saved
469 'failed_fields' => array()
472 // Init overall status and final output
476 // Check all data in session
477 foreach (array_keys($GLOBALS['installer_groups']) as $key) {
478 // Get values from session
479 $value = getSession($key);
481 // Is the data valid?
482 $verificationStatus['is_valid'] = (isInstallerDataValid($verificationStatus, $key, $value));
484 // Is this step okay?
485 if ($verificationStatus['is_valid'] === TRUE) {
486 // Add this key/value pair to a overview group
487 addKeyValueToInstallerOverviewGroup($key, $value);
490 // Save the overall status for below final check
491 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',value=' . $value . ',is_valid=' . intval($verificationStatus['is_valid']) . ',isAllValid=' . intval($isAllValid));
492 $isAllValid = (($isAllValid === TRUE) && ($verificationStatus['is_valid'] === TRUE));
496 if ((isInstallationDataCompleted()) && ($isAllValid === TRUE)) {
497 // Set 'done' and message
498 $verificationStatus['status'] = 'done';
499 $verificationStatus['message'] = '{--INSTALLER_OVERVIEW_FINAL_CHECK_DONE--}';
501 // Then do the post-check
502 doInstallerPostCheck($currentTab, $verificationStatus);
505 // Is it still valid?
506 if ($verificationStatus['status'] != 'done') {
508 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Final check on all stored data failed. message=' . $verificationStatus['message']);
510 // Process failed fields
511 $verificationStatus['failed_fields'] = handleInstallerFailedFields($verificationStatus['failed_fields']);
513 // Output the array for JSON reply
514 setAjaxReplyContent(loadTemplate('install_overview_failed', TRUE, $verificationStatus));
517 * Something went wrong, this might happen when e.g. the user has tried
518 * to save invalid database login data but hit reload button on error
521 setHttpStatus('200 OK');
528 // ----------------------------------------------------------------------------
529 // Call-back functions for doing installation steps
530 // ----------------------------------------------------------------------------
532 // Call-back function to import first tables.sql file
533 function doAjaxInstallerStepImportTablesSql () {
534 // Establish database link
535 establishAjaxInstallerDatabaseLink();
541 importInstallSqlDump('tables');
543 // Are some SQLs found?
544 if (countSqls() == 0) {
546 reportBug(__FUNCTION__, __LINE__, '{--INSTALLER_SQL_IMPORT_FAILED--}');
549 // Now run all queries through
550 runFilterChain('run_sqls');