#9659
[phpbb.git] / phpBB / install / install_install.php
blob5808b1055756cdfee07db853796a85c6828d7431
1 <?php
2 /**
4 * @package install
5 * @version $Id$
6 * @copyright (c) 2005 phpBB Group
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
9 */
11 /**
13 if (!defined('IN_INSTALL'))
15 // Someone has tried to access the file direct. This is not a good idea, so exit
16 exit;
19 if (!empty($setmodules))
21 // If phpBB is already installed we do not include this module
22 if (@file_exists($phpbb_root_path . 'config.' . $phpEx) && !file_exists($phpbb_root_path . 'cache/install_lock'))
24 include_once($phpbb_root_path . 'config.' . $phpEx);
26 if (defined('PHPBB_INSTALLED'))
28 return;
32 $module[] = array(
33 'module_type' => 'install',
34 'module_title' => 'INSTALL',
35 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
36 'module_order' => 10,
37 'module_subs' => '',
38 'module_stages' => array('INTRO', 'REQUIREMENTS', 'DATABASE', 'ADMINISTRATOR', 'CONFIG_FILE', 'ADVANCED', 'CREATE_TABLE', 'FINAL'),
39 'module_reqs' => ''
43 /**
44 * Installation
45 * @package install
47 class install_install extends module
49 function install_install(&$p_master)
51 $this->p_master = &$p_master;
54 function main($mode, $sub)
56 global $lang, $template, $language, $phpbb_root_path;
58 switch ($sub)
60 case 'intro' :
61 $this->page_title = $lang['SUB_INTRO'];
63 $template->assign_vars(array(
64 'TITLE' => $lang['INSTALL_INTRO'],
65 'BODY' => $lang['INSTALL_INTRO_BODY'],
66 'L_SUBMIT' => $lang['NEXT'],
67 'S_LANG_SELECT' => '<select id="language" name="language">' . $this->p_master->inst_language_select($language) . '</select>',
68 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language",
69 ));
71 break;
73 case 'requirements' :
74 $this->check_server_requirements($mode, $sub);
76 break;
78 case 'database' :
79 $this->obtain_database_settings($mode, $sub);
81 break;
83 case 'administrator' :
84 $this->obtain_admin_settings($mode, $sub);
86 break;
88 case 'config_file' :
89 $this->create_config_file($mode, $sub);
91 break;
93 case 'advanced' :
94 $this->obtain_advanced_settings($mode, $sub);
96 break;
98 case 'create_table':
99 $this->load_schema($mode, $sub);
100 break;
102 case 'final' :
103 $this->add_modules($mode, $sub);
104 $this->add_language($mode, $sub);
105 $this->add_bots($mode, $sub);
106 $this->email_admin($mode, $sub);
108 // Remove the lock file
109 @unlink($phpbb_root_path . 'cache/install_lock');
111 break;
114 $this->tpl_name = 'install_install';
118 * Checks that the server we are installing on meets the requirements for running phpBB
120 function check_server_requirements($mode, $sub)
122 global $lang, $template, $phpbb_root_path, $phpEx, $language;
124 $this->page_title = $lang['STAGE_REQUIREMENTS'];
126 $template->assign_vars(array(
127 'TITLE' => $lang['REQUIREMENTS_TITLE'],
128 'BODY' => $lang['REQUIREMENTS_EXPLAIN'],
131 $passed = array('php' => false, 'db' => false, 'files' => false, 'pcre' => false);
133 // Test for basic PHP settings
134 $template->assign_block_vars('checks', array(
135 'S_LEGEND' => true,
136 'LEGEND' => $lang['PHP_SETTINGS'],
137 'LEGEND_EXPLAIN' => $lang['PHP_SETTINGS_EXPLAIN'],
140 // Test the minimum PHP version
141 $php_version = PHP_VERSION;
143 if (version_compare($php_version, '4.3.3') < 0)
145 $result = '<b style="color:red">' . $lang['NO'] . '</b>';
147 else
149 $passed['php'] = true;
151 // We also give feedback on whether we're running in safe mode
152 $result = '<b style="color:green">' . $lang['YES'];
153 if (@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on')
155 $result .= ', ' . $lang['PHP_SAFE_MODE'];
157 $result .= '</b>';
160 $template->assign_block_vars('checks', array(
161 'TITLE' => $lang['PHP_VERSION_REQD'],
162 'RESULT' => $result,
164 'S_EXPLAIN' => false,
165 'S_LEGEND' => false,
168 // Check for register_globals being enabled
169 if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on')
171 $result = '<b style="color:red">' . $lang['NO'] . '</b>';
173 else
175 $result = '<b style="color:green">' . $lang['YES'] . '</b>';
178 $template->assign_block_vars('checks', array(
179 'TITLE' => $lang['PHP_REGISTER_GLOBALS'],
180 'TITLE_EXPLAIN' => $lang['PHP_REGISTER_GLOBALS_EXPLAIN'],
181 'RESULT' => $result,
183 'S_EXPLAIN' => true,
184 'S_LEGEND' => false,
187 // Check for PCRE UTF-8 support
188 if (@preg_match('//u', ''))
190 $passed['pcre'] = true;
191 $result = '<b style="color:green">' . $lang['YES'] . '</b>';
193 else
195 $result = '<b style="color:red">' . $lang['NO'] . '</b>';
198 $template->assign_block_vars('checks', array(
199 'TITLE' => $lang['PCRE_UTF_SUPPORT'],
200 'TITLE_EXPLAIN' => $lang['PCRE_UTF_SUPPORT_EXPLAIN'],
201 'RESULT' => $result,
203 'S_EXPLAIN' => true,
204 'S_LEGEND' => false,
208 * Better not enabling and adding to the loaded extensions due to the specific requirements needed
209 if (!@extension_loaded('mbstring'))
211 can_load_dll('mbstring');
215 $passed['mbstring'] = true;
216 if (@extension_loaded('mbstring'))
218 // Test for available database modules
219 $template->assign_block_vars('checks', array(
220 'S_LEGEND' => true,
221 'LEGEND' => $lang['MBSTRING_CHECK'],
222 'LEGEND_EXPLAIN' => $lang['MBSTRING_CHECK_EXPLAIN'],
225 $checks = array(
226 array('func_overload', '&', MB_OVERLOAD_MAIL|MB_OVERLOAD_STRING),
227 array('encoding_translation', '!=', 0),
228 array('http_input', '!=', 'pass'),
229 array('http_output', '!=', 'pass')
232 foreach ($checks as $mb_checks)
234 $ini_val = ini_get('mbstring.' . $mb_checks[0]);
235 switch ($mb_checks[1])
237 case '&':
238 if (intval($ini_val) & $mb_checks[2])
240 $result = '<b style="color:red">' . $lang['NO'] . '</b>';
241 $passed['mbstring'] = false;
243 else
245 $result = '<b style="color:green">' . $lang['YES'] . '</b>';
247 break;
249 case '!=':
250 if ($ini_val != $mb_checks[2])
252 $result = '<b style="color:red">' . $lang['NO'] . '</b>';
253 $passed['mbstring'] = false;
255 else
257 $result = '<b style="color:green">' . $lang['YES'] . '</b>';
259 break;
261 $template->assign_block_vars('checks', array(
262 'TITLE' => $lang['MBSTRING_' . strtoupper($mb_checks[0])],
263 'TITLE_EXPLAIN' => $lang['MBSTRING_' . strtoupper($mb_checks[0]) . '_EXPLAIN'],
264 'RESULT' => $result,
266 'S_EXPLAIN' => true,
267 'S_LEGEND' => false,
272 // Test for available database modules
273 $template->assign_block_vars('checks', array(
274 'S_LEGEND' => true,
275 'LEGEND' => $lang['PHP_SUPPORTED_DB'],
276 'LEGEND_EXPLAIN' => $lang['PHP_SUPPORTED_DB_EXPLAIN'],
279 $available_dbms = get_available_dbms(false, true);
280 $passed['db'] = $available_dbms['ANY_DB_SUPPORT'];
281 unset($available_dbms['ANY_DB_SUPPORT']);
283 foreach ($available_dbms as $db_name => $db_ary)
285 if (!$db_ary['AVAILABLE'])
287 $template->assign_block_vars('checks', array(
288 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
289 'RESULT' => '<span style="color:red">' . $lang['UNAVAILABLE'] . '</span>',
291 'S_EXPLAIN' => false,
292 'S_LEGEND' => false,
295 else
297 $template->assign_block_vars('checks', array(
298 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
299 'RESULT' => '<b style="color:green">' . $lang['AVAILABLE'] . '</b>',
301 'S_EXPLAIN' => false,
302 'S_LEGEND' => false,
307 // Test for other modules
308 $template->assign_block_vars('checks', array(
309 'S_LEGEND' => true,
310 'LEGEND' => $lang['PHP_OPTIONAL_MODULE'],
311 'LEGEND_EXPLAIN' => $lang['PHP_OPTIONAL_MODULE_EXPLAIN'],
314 foreach ($this->php_dlls_other as $dll)
316 if (!@extension_loaded($dll))
318 if (!can_load_dll($dll))
320 $template->assign_block_vars('checks', array(
321 'TITLE' => $lang['DLL_' . strtoupper($dll)],
322 'RESULT' => '<b style="color:red">' . $lang['UNAVAILABLE'] . '</b>',
324 'S_EXPLAIN' => false,
325 'S_LEGEND' => false,
327 continue;
331 $template->assign_block_vars('checks', array(
332 'TITLE' => $lang['DLL_' . strtoupper($dll)],
333 'RESULT' => '<b style="color:green">' . $lang['AVAILABLE'] . '</b>',
335 'S_EXPLAIN' => false,
336 'S_LEGEND' => false,
340 // Can we find Imagemagick anywhere on the system?
341 $exe = (defined('PHP_OS') && strpos(strtolower(PHP_OS), 'win') === 0) ? '.exe' : '';
343 $magic_home = getenv('MAGICK_HOME');
344 $img_imagick = '';
345 if (empty($magic_home))
347 $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/');
348 $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH'))));
350 $locations = array_merge($path_locations, $locations);
351 foreach ($locations as $location)
353 // The path might not end properly, fudge it
354 if (substr($location, -1, 1) !== '/')
356 $location .= '/';
359 if (@is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000)
361 $img_imagick = str_replace('\\', '/', $location);
362 continue;
366 else
368 $img_imagick = str_replace('\\', '/', $magic_home);
371 $template->assign_block_vars('checks', array(
372 'TITLE' => $lang['APP_MAGICK'],
373 'RESULT' => ($img_imagick) ? '<b style="color:green">' . $lang['AVAILABLE'] . ', ' . $img_imagick . '</b>' : '<b style="color:blue">' . $lang['NO_LOCATION'] . '</b>',
375 'S_EXPLAIN' => false,
376 'S_LEGEND' => false,
379 // Check permissions on files/directories we need access to
380 $template->assign_block_vars('checks', array(
381 'S_LEGEND' => true,
382 'LEGEND' => $lang['FILES_REQUIRED'],
383 'LEGEND_EXPLAIN' => $lang['FILES_REQUIRED_EXPLAIN'],
386 $directories = array('cache/', 'files/', 'store/');
388 umask(0);
390 $passed['files'] = true;
391 foreach ($directories as $dir)
393 $exists = $write = false;
395 // Try to create the directory if it does not exist
396 if (!file_exists($phpbb_root_path . $dir))
398 @mkdir($phpbb_root_path . $dir, 0777);
399 @chmod($phpbb_root_path . $dir, 0777);
402 // Now really check
403 if (file_exists($phpbb_root_path . $dir) && is_dir($phpbb_root_path . $dir))
405 if (!is_writeable($phpbb_root_path . $dir))
407 @chmod($phpbb_root_path . $dir, 0777);
409 $exists = true;
412 // Now check if it is writeable by storing a simple file
413 $fp = @fopen($phpbb_root_path . $dir . 'test_lock', 'wb');
414 if ($fp !== false)
416 $write = true;
418 @fclose($fp);
420 @unlink($phpbb_root_path . $dir . 'test_lock');
422 $passed['files'] = ($exists && $write && $passed['files']) ? true : false;
424 $exists = ($exists) ? '<b style="color:green">' . $lang['FOUND'] . '</b>' : '<b style="color:red">' . $lang['NOT_FOUND'] . '</b>';
425 $write = ($write) ? ', <b style="color:green">' . $lang['WRITEABLE'] . '</b>' : (($exists) ? ', <b style="color:red">' . $lang['UNWRITEABLE'] . '</b>' : '');
427 $template->assign_block_vars('checks', array(
428 'TITLE' => $dir,
429 'RESULT' => $exists . $write,
431 'S_EXPLAIN' => false,
432 'S_LEGEND' => false,
436 // Check permissions on files/directories it would be useful access to
437 $template->assign_block_vars('checks', array(
438 'S_LEGEND' => true,
439 'LEGEND' => $lang['FILES_OPTIONAL'],
440 'LEGEND_EXPLAIN' => $lang['FILES_OPTIONAL_EXPLAIN'],
443 $directories = array('config.'.$phpEx, 'images/avatars/upload/');
445 foreach ($directories as $dir)
447 $write = $exists = true;
448 if (file_exists($phpbb_root_path . $dir))
450 if (!is_writeable($phpbb_root_path . $dir))
452 $write = false;
455 else
457 $write = $exists = false;
460 $exists_str = ($exists) ? '<b style="color:green">' . $lang['FOUND'] . '</b>' : '<b style="color:red">' . $lang['NOT_FOUND'] . '</b>';
461 $write_str = ($write) ? ', <b style="color:green">' . $lang['WRITEABLE'] . '</b>' : (($exists) ? ', <b style="color:red">' . $lang['UNWRITEABLE'] . '</b>' : '');
463 $template->assign_block_vars('checks', array(
464 'TITLE' => $dir,
465 'RESULT' => $exists_str . $write_str,
467 'S_EXPLAIN' => false,
468 'S_LEGEND' => false,
472 // And finally where do we want to go next (well today is taken isn't it :P)
473 $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
475 $url = ($passed['php'] && $passed['db'] && $passed['files'] && $passed['pcre'] && $passed['mbstring']) ? $this->p_master->module_url . "?mode=$mode&amp;sub=database&amp;language=$language" : $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language ";
476 $submit = ($passed['php'] && $passed['db'] && $passed['files'] && $passed['pcre'] && $passed['mbstring']) ? $lang['INSTALL_START'] : $lang['INSTALL_TEST'];
479 $template->assign_vars(array(
480 'L_SUBMIT' => $submit,
481 'S_HIDDEN' => $s_hidden_fields,
482 'U_ACTION' => $url,
487 * Obtain the information required to connect to the database
489 function obtain_database_settings($mode, $sub)
491 global $lang, $template, $phpEx;
493 $this->page_title = $lang['STAGE_DATABASE'];
495 // Obtain any submitted data
496 foreach ($this->request_vars as $var)
498 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
501 $connect_test = false;
502 $error = array();
503 $available_dbms = get_available_dbms(false, true);
505 // Has the user opted to test the connection?
506 if (isset($_POST['testdb']))
508 if (!isset($available_dbms[$dbms]) || !$available_dbms[$dbms]['AVAILABLE'])
510 $error['db'][] = $lang['INST_ERR_NO_DB'];
511 $connect_test = false;
513 else
515 $dbpasswd = htmlspecialchars_decode($dbpasswd);
516 $connect_test = connect_check_db(true, $error, $available_dbms[$dbms], $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport);
519 $template->assign_block_vars('checks', array(
520 'S_LEGEND' => true,
521 'LEGEND' => $lang['DB_CONNECTION'],
522 'LEGEND_EXPLAIN' => false,
525 if ($connect_test)
527 $template->assign_block_vars('checks', array(
528 'TITLE' => $lang['DB_TEST'],
529 'RESULT' => '<b style="color:green">' . $lang['SUCCESSFUL_CONNECT'] . '</b>',
531 'S_EXPLAIN' => false,
532 'S_LEGEND' => false,
535 else
537 $template->assign_block_vars('checks', array(
538 'TITLE' => $lang['DB_TEST'],
539 'RESULT' => '<b style="color:red">' . implode('<br />', $error) . '</b>',
541 'S_EXPLAIN' => false,
542 'S_LEGEND' => false,
547 if (!$connect_test)
549 // Update the list of available DBMS modules to only contain those which can be used
550 $available_dbms_temp = array();
551 foreach ($available_dbms as $type => $dbms_ary)
553 if (!$dbms_ary['AVAILABLE'])
555 continue;
558 $available_dbms_temp[$type] = $dbms_ary;
561 $available_dbms = &$available_dbms_temp;
563 // And now for the main part of this page
564 $table_prefix = (!empty($table_prefix) ? $table_prefix : 'phpbb_');
566 foreach ($this->db_config_options as $config_key => $vars)
568 if (!is_array($vars) && strpos($config_key, 'legend') === false)
570 continue;
573 if (strpos($config_key, 'legend') !== false)
575 $template->assign_block_vars('options', array(
576 'S_LEGEND' => true,
577 'LEGEND' => $lang[$vars])
580 continue;
583 $options = isset($vars['options']) ? $vars['options'] : '';
585 $template->assign_block_vars('options', array(
586 'KEY' => $config_key,
587 'TITLE' => $lang[$vars['lang']],
588 'S_EXPLAIN' => $vars['explain'],
589 'S_LEGEND' => false,
590 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
591 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $$config_key, $options),
597 // And finally where do we want to go next (well today is taken isn't it :P)
598 $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
599 $s_hidden_fields .= '<input type="hidden" name="language" value="' . $language . '" />';
600 if ($connect_test)
602 foreach ($this->db_config_options as $config_key => $vars)
604 if (!is_array($vars))
606 continue;
608 $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $$config_key . '" />';
612 $url = ($connect_test) ? $this->p_master->module_url . "?mode=$mode&amp;sub=administrator" : $this->p_master->module_url . "?mode=$mode&amp;sub=database";
613 $s_hidden_fields .= ($connect_test) ? '' : '<input type="hidden" name="testdb" value="true" />';
615 $submit = $lang['NEXT_STEP'];
617 $template->assign_vars(array(
618 'L_SUBMIT' => $submit,
619 'S_HIDDEN' => $s_hidden_fields,
620 'U_ACTION' => $url,
625 * Obtain the administrator's name, password and email address
627 function obtain_admin_settings($mode, $sub)
629 global $lang, $template, $phpEx;
631 $this->page_title = $lang['STAGE_ADMINISTRATOR'];
633 // Obtain any submitted data
634 foreach ($this->request_vars as $var)
636 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
639 if ($dbms == '')
641 // Someone's been silly and tried calling this page direct
642 // So we send them back to the start to do it again properly
643 $this->p_master->redirect("index.$phpEx?mode=install");
646 $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
647 $passed = false;
649 $default_lang = ($default_lang !== '') ? $default_lang : $language;
651 $board_email1 = strtolower($board_email1);
652 $board_email2 = strtolower($board_email2);
654 if (isset($_POST['check']))
656 $error = array();
658 // Check the entered email address and password
659 if ($admin_name == '' || $admin_pass1 == '' || $admin_pass2 == '' || $board_email1 == '' || $board_email2 == '')
661 $error[] = $lang['INST_ERR_MISSING_DATA'];
664 if ($admin_pass1 != $admin_pass2 && $admin_pass1 != '')
666 $error[] = $lang['INST_ERR_PASSWORD_MISMATCH'];
669 // Test against the default username rules
670 if ($admin_name != '' && utf8_strlen($admin_name) < 3)
672 $error[] = $lang['INST_ERR_USER_TOO_SHORT'];
675 if ($admin_name != '' && utf8_strlen($admin_name) > 20)
677 $error[] = $lang['INST_ERR_USER_TOO_LONG'];
680 // Test against the default password rules
681 if ($admin_pass1 != '' && utf8_strlen($admin_pass1) < 6)
683 $error[] = $lang['INST_ERR_PASSWORD_TOO_SHORT'];
686 if ($admin_pass1 != '' && utf8_strlen($admin_pass1) > 30)
688 $error[] = $lang['INST_ERR_PASSWORD_TOO_LONG'];
691 if ($board_email1 != $board_email2 && $board_email1 != '')
693 $error[] = $lang['INST_ERR_EMAIL_MISMATCH'];
696 if ($board_email1 != '' && !preg_match('/^' . get_preg_expression('email') . '$/i', $board_email1))
698 $error[] = $lang['INST_ERR_EMAIL_INVALID'];
701 $template->assign_block_vars('checks', array(
702 'S_LEGEND' => true,
703 'LEGEND' => $lang['STAGE_ADMINISTRATOR'],
704 'LEGEND_EXPLAIN' => false,
707 if (!sizeof($error))
709 $passed = true;
710 $template->assign_block_vars('checks', array(
711 'TITLE' => $lang['ADMIN_TEST'],
712 'RESULT' => '<b style="color:green">' . $lang['TESTS_PASSED'] . '</b>',
714 'S_EXPLAIN' => false,
715 'S_LEGEND' => false,
718 else
720 $template->assign_block_vars('checks', array(
721 'TITLE' => $lang['ADMIN_TEST'],
722 'RESULT' => '<b style="color:red">' . implode('<br />', $error) . '</b>',
724 'S_EXPLAIN' => false,
725 'S_LEGEND' => false,
730 if (!$passed)
732 foreach ($this->admin_config_options as $config_key => $vars)
734 if (!is_array($vars) && strpos($config_key, 'legend') === false)
736 continue;
739 if (strpos($config_key, 'legend') !== false)
741 $template->assign_block_vars('options', array(
742 'S_LEGEND' => true,
743 'LEGEND' => $lang[$vars])
746 continue;
749 $options = isset($vars['options']) ? $vars['options'] : '';
751 $template->assign_block_vars('options', array(
752 'KEY' => $config_key,
753 'TITLE' => $lang[$vars['lang']],
754 'S_EXPLAIN' => $vars['explain'],
755 'S_LEGEND' => false,
756 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
757 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $$config_key, $options),
762 else
764 foreach ($this->admin_config_options as $config_key => $vars)
766 if (!is_array($vars))
768 continue;
770 $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $$config_key . '" />';
774 $s_hidden_fields .= ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
775 $s_hidden_fields .= '<input type="hidden" name="language" value="' . $language . '" />';
777 foreach ($this->db_config_options as $config_key => $vars)
779 if (!is_array($vars))
781 continue;
783 $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $$config_key . '" />';
786 $submit = $lang['NEXT_STEP'];
788 $url = ($passed) ? $this->p_master->module_url . "?mode=$mode&amp;sub=config_file" : $this->p_master->module_url . "?mode=$mode&amp;sub=administrator";
789 $s_hidden_fields .= ($passed) ? '' : '<input type="hidden" name="check" value="true" />';
791 $template->assign_vars(array(
792 'L_SUBMIT' => $submit,
793 'S_HIDDEN' => $s_hidden_fields,
794 'U_ACTION' => $url,
799 * Writes the config file to disk, or if unable to do so offers alternative methods
801 function create_config_file($mode, $sub)
803 global $lang, $template, $phpbb_root_path, $phpEx;
805 $this->page_title = $lang['STAGE_CONFIG_FILE'];
807 // Obtain any submitted data
808 foreach ($this->request_vars as $var)
810 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
813 if ($dbms == '')
815 // Someone's been silly and tried calling this page direct
816 // So we send them back to the start to do it again properly
817 $this->p_master->redirect("index.$phpEx?mode=install");
820 $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
821 $s_hidden_fields .= '<input type="hidden" name="language" value="' . $language . '" />';
822 $written = false;
824 // Create a list of any PHP modules we wish to have loaded
825 $load_extensions = array();
826 $available_dbms = get_available_dbms($dbms);
827 $check_exts = array_merge(array($available_dbms[$dbms]['MODULE']), $this->php_dlls_other);
829 $suffix = (defined('PHP_OS') && strpos(strtolower(PHP_OS), 'win') === 0) ? 'dll' : 'so';
831 foreach ($check_exts as $dll)
833 if (!@extension_loaded($dll))
835 if (!can_load_dll($dll))
837 continue;
840 $load_extensions[] = "$dll.$suffix";
844 // Create a lock file to indicate that there is an install in progress
845 $fp = @fopen($phpbb_root_path . 'cache/install_lock', 'wb');
846 if ($fp === false)
848 // We were unable to create the lock file - abort
849 $this->p_master->error($lang['UNABLE_WRITE_LOCK'], __LINE__, __FILE__);
851 @fclose($fp);
853 $dbpasswd = htmlspecialchars_decode($dbpasswd);
854 $load_extensions = implode(',', $load_extensions);
856 // Time to convert the data provided into a config file
857 $config_data = "<?php\n";
858 $config_data .= "// phpBB 3.0.x auto-generated configuration file\n// Do not change anything in this file!\n";
859 $config_data .= "\$dbms = '" . $available_dbms[$dbms]['DRIVER'] . "';\n";
860 $config_data .= "\$dbhost = '$dbhost';\n";
861 $config_data .= "\$dbport = '$dbport';\n";
862 $config_data .= "\$dbname = '$dbname';\n";
863 $config_data .= "\$dbuser = '$dbuser';\n";
864 $config_data .= "\$dbpasswd = '$dbpasswd';\n\n";
865 $config_data .= "\$table_prefix = '$table_prefix';\n";
866 // $config_data .= "\$acm_type = '" . (($acm_type) ? $acm_type : 'file') . "';\n";
867 $config_data .= "\$acm_type = 'file';\n";
868 $config_data .= "\$load_extensions = '$load_extensions';\n\n";
869 $config_data .= "@define('PHPBB_INSTALLED', true);\n";
870 $config_data .= "@define('DEBUG', true);\n"; // @todo Comment out when final
871 $config_data .= "// @define('DEBUG_EXTRA', true);\n";
872 $config_data .= '?' . '>'; // Done this to prevent highlighting editors getting confused!
874 // Attempt to write out the config file directly. If it works, this is the easiest way to do it ...
875 if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && is_writeable($phpbb_root_path . 'config.' . $phpEx)) || is_writable($phpbb_root_path))
877 // Assume it will work ... if nothing goes wrong below
878 $written = true;
880 if (!($fp = @fopen($phpbb_root_path . 'config.'.$phpEx, 'w')))
882 // Something went wrong ... so let's try another method
883 $written = false;
886 if (!(@fwrite($fp, $config_data)))
888 // Something went wrong ... so let's try another method
889 $written = false;
892 @fclose($fp);
895 if (isset($_POST['dldone']))
897 // Do a basic check to make sure that the file has been uploaded
898 // Note that all we check is that the file has _something_ in it
899 // We don't compare the contents exactly - if they can't upload
900 // a single file correctly, it's likely they will have other problems....
901 if (filesize($phpbb_root_path . 'config.'.$phpEx) > 10)
903 $written = true;
907 $config_options = array_merge($this->db_config_options, $this->admin_config_options);
909 foreach ($config_options as $config_key => $vars)
911 if (!is_array($vars))
913 continue;
915 $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $$config_key . '" />';
918 if (!$written)
920 // OK, so it didn't work let's try the alternatives
922 if (isset($_POST['dlconfig']))
924 // They want a copy of the file to download, so send the relevant headers and dump out the data
925 header("Content-Type: text/x-delimtext; name=\"config.$phpEx\"");
926 header("Content-disposition: attachment; filename=config.$phpEx");
927 echo $config_data;
928 exit;
931 // The option to download the config file is always available, so output it here
932 $template->assign_vars(array(
933 'BODY' => $lang['CONFIG_FILE_UNABLE_WRITE'],
934 'L_DL_CONFIG' => $lang['DL_CONFIG'],
935 'L_DL_CONFIG_EXPLAIN' => $lang['DL_CONFIG_EXPLAIN'],
936 'L_DL_DONE' => $lang['DONE'],
937 'L_DL_DOWNLOAD' => $lang['DL_DOWNLOAD'],
938 'S_HIDDEN' => $s_hidden_fields,
939 'S_SHOW_DOWNLOAD' => true,
940 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=config_file",
942 return;
944 else
946 $template->assign_vars(array(
947 'BODY' => $lang['CONFIG_FILE_WRITTEN'],
948 'L_SUBMIT' => $lang['NEXT_STEP'],
949 'S_HIDDEN' => $s_hidden_fields,
950 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=advanced",
952 return;
957 * Provide an opportunity to customise some advanced settings during the install
958 * in case it is necessary for them to be set to access later
960 function obtain_advanced_settings($mode, $sub)
962 global $lang, $template, $phpEx;
964 $this->page_title = $lang['STAGE_ADVANCED'];
966 // Obtain any submitted data
967 foreach ($this->request_vars as $var)
969 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
972 if ($dbms == '')
974 // Someone's been silly and tried calling this page direct
975 // So we send them back to the start to do it again properly
976 $this->p_master->redirect("index.$phpEx?mode=install");
979 $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
980 $s_hidden_fields .= '<input type="hidden" name="language" value="' . $language . '" />';
982 $email_enable = ($email_enable !== '') ? $email_enable : true;
983 $server_name = ($server_name !== '') ? $server_name : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME'));
984 $server_port = ($server_port !== '') ? $server_port : ((!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'));
985 $server_protocol = ($server_protocol !== '') ? $server_protocol : ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://');
986 $cookie_secure = ($cookie_secure !== '') ? $cookie_secure : ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? true : false);
988 if ($script_path === '')
990 $name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF');
991 if (!$name)
993 $name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI');
996 // Replace backslashes and doubled slashes (could happen on some proxy setups)
997 $name = str_replace(array('\\', '//', '/install'), '/', $name);
998 $script_path = trim(dirname($name));
1001 foreach ($this->advanced_config_options as $config_key => $vars)
1003 if (!is_array($vars) && strpos($config_key, 'legend') === false)
1005 continue;
1008 if (strpos($config_key, 'legend') !== false)
1010 $template->assign_block_vars('options', array(
1011 'S_LEGEND' => true,
1012 'LEGEND' => $lang[$vars])
1015 continue;
1018 $options = isset($vars['options']) ? $vars['options'] : '';
1020 $template->assign_block_vars('options', array(
1021 'KEY' => $config_key,
1022 'TITLE' => $lang[$vars['lang']],
1023 'S_EXPLAIN' => $vars['explain'],
1024 'S_LEGEND' => false,
1025 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
1026 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $$config_key, $options),
1031 $config_options = array_merge($this->db_config_options, $this->admin_config_options);
1032 foreach ($config_options as $config_key => $vars)
1034 if (!is_array($vars))
1036 continue;
1038 $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $$config_key . '" />';
1041 $submit = $lang['NEXT_STEP'];
1043 $url = $this->p_master->module_url . "?mode=$mode&amp;sub=create_table";
1045 $template->assign_vars(array(
1046 'BODY' => $lang['STAGE_ADVANCED_EXPLAIN'],
1047 'L_SUBMIT' => $submit,
1048 'S_HIDDEN' => $s_hidden_fields,
1049 'U_ACTION' => $url,
1054 * Load the contents of the schema into the database and then alter it based on what has been input during the installation
1056 function load_schema($mode, $sub)
1058 global $db, $lang, $template, $phpbb_root_path, $phpEx;
1060 $this->page_title = $lang['STAGE_CREATE_TABLE'];
1061 $s_hidden_fields = '';
1063 // Obtain any submitted data
1064 foreach ($this->request_vars as $var)
1066 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
1069 if ($dbms == '')
1071 // Someone's been silly and tried calling this page direct
1072 // So we send them back to the start to do it again properly
1073 $this->p_master->redirect("index.$phpEx?mode=install");
1076 $cookie_domain = ($server_name != '') ? $server_name : (!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME');
1078 // Try to come up with the best solution for cookie domain...
1079 if (strpos($cookie_domain, 'www.') === 0)
1081 $cookie_domain = str_replace('www.', '.', $cookie_domain);
1084 // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
1085 $available_dbms = get_available_dbms($dbms);
1087 $dbpasswd = htmlspecialchars_decode($dbpasswd);
1089 // Load the appropriate database class if not already loaded
1090 include($phpbb_root_path . 'includes/db/' . $available_dbms[$dbms]['DRIVER'] . '.' . $phpEx);
1092 // Instantiate the database
1093 $sql_db = 'dbal_' . $available_dbms[$dbms]['DRIVER'];
1094 $db = new $sql_db();
1095 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
1097 // NOTE: trigger_error does not work here.
1098 $db->return_on_error = true;
1100 // If mysql is chosen, we need to adjust the schema filename slightly to reflect the correct version. ;)
1101 if ($dbms == 'mysql')
1103 if (version_compare($db->mysql_version, '4.1.3', '>='))
1105 $available_dbms[$dbms]['SCHEMA'] .= '_41';
1107 else
1109 $available_dbms[$dbms]['SCHEMA'] .= '_40';
1113 // Ok we have the db info go ahead and read in the relevant schema
1114 // and work on building the table
1115 $dbms_schema = 'schemas/' . $available_dbms[$dbms]['SCHEMA'] . '_schema.sql';
1117 // How should we treat this schema?
1118 $remove_remarks = $available_dbms[$dbms]['COMMENTS'];
1119 $delimiter = $available_dbms[$dbms]['DELIM'];
1121 $sql_query = @file_get_contents($dbms_schema);
1123 $sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query);
1125 $remove_remarks($sql_query);
1127 $sql_query = split_sql_file($sql_query, $delimiter);
1129 foreach ($sql_query as $sql)
1131 //$sql = trim(str_replace('|', ';', $sql));
1132 if (!$db->sql_query($sql))
1134 $error = $db->sql_error();
1135 $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
1138 unset($sql_query);
1140 // Ok tables have been built, let's fill in the basic information
1141 $sql_query = file_get_contents('schemas/schema_data.sql');
1143 // Deal with any special comments
1144 switch ($dbms)
1146 case 'mssql':
1147 case 'mssql_odbc':
1148 $sql_query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $sql_query);
1149 break;
1151 case 'postgres':
1152 $sql_query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $sql_query);
1153 break;
1156 $sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query);
1158 // Since there is only one schema file we know the comment style and are able to remove it directly with remove_remarks
1159 remove_remarks($sql_query);
1160 $sql_query = split_sql_file($sql_query, ';');
1162 foreach ($sql_query as $sql)
1164 //$sql = trim(str_replace('|', ';', $sql));
1165 if (!$db->sql_query($sql))
1167 $error = $db->sql_error();
1168 $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
1171 unset($sql_query);
1173 $current_time = time();
1175 $user_ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
1177 if ($script_path !== '/')
1179 // Adjust destination path (no trailing slash)
1180 if (substr($script_path, -1) == '/')
1182 $script_path = substr($script_path, 0, -1);
1185 $script_path = str_replace(array('../', './'), '', $script_path);
1187 if ($script_path[0] != '/')
1189 $script_path = '/' . $script_path;
1193 // Set default config and post data, this applies to all DB's
1194 $sql_ary = array(
1195 'INSERT INTO ' . $table_prefix . "config (config_name, config_value)
1196 VALUES ('board_startdate', '$current_time')",
1198 'INSERT INTO ' . $table_prefix . "config (config_name, config_value)
1199 VALUES ('default_lang', '" . $db->sql_escape($default_lang) . "')",
1201 'UPDATE ' . $table_prefix . "config
1202 SET config_value = '" . $db->sql_escape($img_imagick) . "'
1203 WHERE config_name = 'img_imagick'",
1205 'UPDATE ' . $table_prefix . "config
1206 SET config_value = '" . $db->sql_escape($server_name) . "'
1207 WHERE config_name = 'server_name'",
1209 'UPDATE ' . $table_prefix . "config
1210 SET config_value = '" . $db->sql_escape($server_port) . "'
1211 WHERE config_name = 'server_port'",
1213 'UPDATE ' . $table_prefix . "config
1214 SET config_value = '" . $db->sql_escape($board_email1) . "'
1215 WHERE config_name = 'board_email'",
1217 'UPDATE ' . $table_prefix . "config
1218 SET config_value = '" . $db->sql_escape($board_email1) . "'
1219 WHERE config_name = 'board_contact'",
1221 'UPDATE ' . $table_prefix . "config
1222 SET config_value = '" . $db->sql_escape($cookie_domain) . "'
1223 WHERE config_name = 'cookie_domain'",
1225 'UPDATE ' . $table_prefix . "config
1226 SET config_value = '" . $db->sql_escape($lang['default_dateformat']) . "'
1227 WHERE config_name = 'default_dateformat'",
1229 'UPDATE ' . $table_prefix . "config
1230 SET config_value = '" . $db->sql_escape($email_enable) . "'
1231 WHERE config_name = 'email_enable'",
1233 'UPDATE ' . $table_prefix . "config
1234 SET config_value = '" . $db->sql_escape($smtp_delivery) . "'
1235 WHERE config_name = 'smtp_delivery'",
1237 'UPDATE ' . $table_prefix . "config
1238 SET config_value = '" . $db->sql_escape($smtp_host) . "'
1239 WHERE config_name = 'smtp_host'",
1241 'UPDATE ' . $table_prefix . "config
1242 SET config_value = '" . $db->sql_escape($smtp_auth) . "'
1243 WHERE config_name = 'smtp_auth_method'",
1245 'UPDATE ' . $table_prefix . "config
1246 SET config_value = '" . $db->sql_escape($smtp_user) . "'
1247 WHERE config_name = 'smtp_username'",
1249 'UPDATE ' . $table_prefix . "config
1250 SET config_value = '" . $db->sql_escape($smtp_pass) . "'
1251 WHERE config_name = 'smtp_password'",
1253 'UPDATE ' . $table_prefix . "config
1254 SET config_value = '" . $db->sql_escape($cookie_secure) . "'
1255 WHERE config_name = 'cookie_secure'",
1257 'UPDATE ' . $table_prefix . "config
1258 SET config_value = '" . $db->sql_escape($force_server_vars) . "'
1259 WHERE config_name = 'force_server_vars'",
1261 'UPDATE ' . $table_prefix . "config
1262 SET config_value = '" . $db->sql_escape($script_path) . "'
1263 WHERE config_name = 'script_path'",
1265 'UPDATE ' . $table_prefix . "config
1266 SET config_value = '" . $db->sql_escape($server_protocol) . "'
1267 WHERE config_name = 'server_protocol'",
1269 'UPDATE ' . $table_prefix . "config
1270 SET config_value = '" . $db->sql_escape($admin_name) . "'
1271 WHERE config_name = 'newest_username'",
1273 'UPDATE ' . $table_prefix . "users
1274 SET username = '" . $db->sql_escape($admin_name) . "', user_password='" . $db->sql_escape(md5($admin_pass1)) . "', user_ip = '" . $db->sql_escape($user_ip) . "', user_lang = '" . $db->sql_escape($default_lang) . "', user_email='" . $db->sql_escape($board_email1) . "', user_dateformat='" . $db->sql_escape($lang['default_dateformat']) . "', user_email_hash = " . (crc32($board_email1) . strlen($board_email1)) . ", username_clean = '" . $db->sql_escape(utf8_clean_string($admin_name)) . "'
1275 WHERE username = 'Admin'",
1277 'UPDATE ' . $table_prefix . "moderator_cache
1278 SET username = '" . $db->sql_escape($admin_name) . "'
1279 WHERE username = 'Admin'",
1281 'UPDATE ' . $table_prefix . "forums
1282 SET forum_last_poster_name = '" . $db->sql_escape($admin_name) . "'
1283 WHERE forum_last_poster_name = 'Admin'",
1285 'UPDATE ' . $table_prefix . "topics
1286 SET topic_first_poster_name = '" . $db->sql_escape($admin_name) . "', topic_last_poster_name = '" . $db->sql_escape($admin_name) . "'
1287 WHERE topic_first_poster_name = 'Admin'
1288 OR topic_last_poster_name = 'Admin'",
1290 'UPDATE ' . $table_prefix . "users
1291 SET user_regdate = $current_time",
1293 'UPDATE ' . $table_prefix . "posts
1294 SET post_time = $current_time, poster_ip = '" . $db->sql_escape($user_ip) . "'",
1296 'UPDATE ' . $table_prefix . "topics
1297 SET topic_time = $current_time, topic_last_post_time = $current_time",
1299 'UPDATE ' . $table_prefix . "forums
1300 SET forum_last_post_time = $current_time",
1303 if (!@extension_loaded('gd'))
1305 can_load_dll('gd');
1308 // This is for people who have TTF and GD
1309 if (@extension_loaded('gd') && function_exists('imagettfbbox') && function_exists('imagettftext'))
1311 $sql_ary[] = 'UPDATE ' . $table_prefix . "config
1312 SET config_value = '1'
1313 WHERE config_name = 'captcha_gd'";
1316 // We set a (semi-)unique cookie name to bypass login issues related to the cookie name.
1317 $cookie_name = 'phpbb3_';
1318 $cookie_name .= strtolower(gen_rand_string(5));
1320 $sql_ary[] = 'UPDATE ' . $table_prefix . "config
1321 SET config_value = '" . $db->sql_escape($cookie_name) . "'
1322 WHERE config_name = 'cookie_name'";
1324 foreach ($sql_ary as $sql)
1326 //$sql = trim(str_replace('|', ';', $sql));
1328 if (!$db->sql_query($sql))
1330 $error = $db->sql_error();
1331 $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
1335 foreach ($this->request_vars as $var)
1337 $s_hidden_fields .= '<input type="hidden" name="' . $var . '" value="' . $$var . '" />';
1340 $submit = $lang['NEXT_STEP'];
1342 $url = $this->p_master->module_url . "?mode=$mode&amp;sub=final";
1344 $template->assign_vars(array(
1345 'BODY' => $lang['STAGE_CREATE_TABLE_EXPLAIN'],
1346 'L_SUBMIT' => $submit,
1347 'S_HIDDEN' => $s_hidden_fields,
1348 'U_ACTION' => $url,
1353 * Populate the module tables
1355 function add_modules($mode, $sub)
1357 global $db, $lang, $phpbb_root_path, $phpEx;
1359 // Obtain any submitted data
1360 foreach ($this->request_vars as $var)
1362 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
1365 $dbpasswd = htmlspecialchars_decode($dbpasswd);
1367 // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
1368 $available_dbms = get_available_dbms($dbms);
1370 // Load the appropriate database class if not already loaded
1371 include($phpbb_root_path . 'includes/db/' . $available_dbms[$dbms]['DRIVER'] . '.' . $phpEx);
1373 // Instantiate the database
1374 $sql_db = 'dbal_' . $available_dbms[$dbms]['DRIVER'];
1375 $db = new $sql_db();
1376 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
1378 // NOTE: trigger_error does not work here.
1379 $db->return_on_error = true;
1381 include_once($phpbb_root_path . 'includes/constants.' . $phpEx);
1382 include_once($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx);
1384 $_module = &new acp_modules();
1385 $module_classes = array('acp', 'mcp', 'ucp');
1387 // Add categories
1388 foreach ($module_classes as $module_class)
1390 $categories = array();
1392 // Set the module class
1393 $_module->module_class = $module_class;
1395 foreach ($this->module_categories[$module_class] as $cat_name => $subs)
1397 $module_data = array(
1398 'module_basename' => '',
1399 'module_enabled' => 1,
1400 'module_display' => 1,
1401 'parent_id' => 0,
1402 'module_class' => $module_class,
1403 'module_langname' => $cat_name,
1404 'module_mode' => '',
1405 'module_auth' => '',
1408 // Add category
1409 $_module->update_module_data($module_data, true);
1411 // Check for last sql error happened
1412 if ($db->sql_error_triggered)
1414 $error = $db->sql_error($db->sql_error_sql);
1415 $this->p_master->db_error($error['message'], $db->sql_error_sql, __LINE__, __FILE__);
1418 $categories[$cat_name]['id'] = (int) $module_data['module_id'];
1419 $categories[$cat_name]['parent_id'] = 0;
1421 // Create sub-categories...
1422 if (is_array($subs))
1424 foreach ($subs as $level2_name)
1426 $module_data = array(
1427 'module_basename' => '',
1428 'module_enabled' => 1,
1429 'module_display' => 1,
1430 'parent_id' => (int) $categories[$cat_name]['id'],
1431 'module_class' => $module_class,
1432 'module_langname' => $level2_name,
1433 'module_mode' => '',
1434 'module_auth' => '',
1437 $_module->update_module_data($module_data, true);
1439 // Check for last sql error happened
1440 if ($db->sql_error_triggered)
1442 $error = $db->sql_error($db->sql_error_sql);
1443 $this->p_master->db_error($error['message'], $db->sql_error_sql, __LINE__, __FILE__);
1446 $categories[$level2_name]['id'] = (int) $module_data['module_id'];
1447 $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id'];
1452 // Get the modules we want to add... returned sorted by name
1453 $module_info = $_module->get_module_infos('', $module_class);
1455 foreach ($module_info as $module_basename => $fileinfo)
1457 foreach ($fileinfo['modes'] as $module_mode => $row)
1459 foreach ($row['cat'] as $cat_name)
1461 if (!isset($categories[$cat_name]))
1463 continue;
1465 $module_data = array(
1466 'module_basename' => $module_basename,
1467 'module_enabled' => 1,
1468 'module_display' => (isset($row['display'])) ? $row['display'] : 1,
1469 'parent_id' => (int) $categories[$cat_name]['id'],
1470 'module_class' => $module_class,
1471 'module_langname' => $row['title'],
1472 'module_mode' => $module_mode,
1473 'module_auth' => $row['auth'],
1476 $_module->update_module_data($module_data, true);
1478 // Check for last sql error happened
1479 if ($db->sql_error_triggered)
1481 $error = $db->sql_error($db->sql_error_sql);
1482 $this->p_master->db_error($error['message'], $db->sql_error_sql, __LINE__, __FILE__);
1488 // Move some of the modules around since the code above will put them in the wrong place
1489 if ($module_class == 'acp')
1491 // Move main module 4 up...
1492 $sql = 'SELECT *
1493 FROM ' . MODULES_TABLE . "
1494 WHERE module_basename = 'main'
1495 AND module_class = 'acp'
1496 AND module_mode = 'main'";
1497 $result = $db->sql_query($sql);
1498 $row = $db->sql_fetchrow($result);
1499 $db->sql_freeresult($result);
1501 $_module->move_module_by($row, 'move_up', 4);
1503 // Move permissions intro screen module 4 up...
1504 $sql = 'SELECT *
1505 FROM ' . MODULES_TABLE . "
1506 WHERE module_basename = 'permissions'
1507 AND module_class = 'acp'
1508 AND module_mode = 'intro'";
1509 $result = $db->sql_query($sql);
1510 $row = $db->sql_fetchrow($result);
1511 $db->sql_freeresult($result);
1513 $_module->move_module_by($row, 'move_up', 4);
1515 // Move manage users screen module 5 up...
1516 $sql = 'SELECT *
1517 FROM ' . MODULES_TABLE . "
1518 WHERE module_basename = 'users'
1519 AND module_class = 'acp'
1520 AND module_mode = 'overview'";
1521 $result = $db->sql_query($sql);
1522 $row = $db->sql_fetchrow($result);
1523 $db->sql_freeresult($result);
1525 $_module->move_module_by($row, 'move_up', 5);
1528 if ($module_class == 'ucp')
1530 // Move attachment module 4 down...
1531 $sql = 'SELECT *
1532 FROM ' . MODULES_TABLE . "
1533 WHERE module_basename = 'attachments'
1534 AND module_class = 'ucp'
1535 AND module_mode = 'attachments'";
1536 $result = $db->sql_query($sql);
1537 $row = $db->sql_fetchrow($result);
1538 $db->sql_freeresult($result);
1540 $_module->move_module_by($row, 'move_down', 4);
1543 // And now for the special ones
1544 // (these are modules which appear in multiple categories and thus get added manually to some for more control)
1545 if (isset($this->module_extras[$module_class]))
1547 foreach ($this->module_extras[$module_class] as $cat_name => $mods)
1549 $sql = 'SELECT module_id, left_id, right_id
1550 FROM ' . MODULES_TABLE . "
1551 WHERE module_langname = '" . $db->sql_escape($cat_name) . "'
1552 AND module_class = '" . $db->sql_escape($module_class) . "'";
1553 $result = $db->sql_query_limit($sql, 1);
1554 $row2 = $db->sql_fetchrow($result);
1555 $db->sql_freeresult($result);
1557 foreach ($mods as $mod_name)
1559 $sql = 'SELECT *
1560 FROM ' . MODULES_TABLE . "
1561 WHERE module_langname = '" . $db->sql_escape($mod_name) . "'
1562 AND module_class = '" . $db->sql_escape($module_class) . "'
1563 AND module_basename <> ''";
1564 $result = $db->sql_query_limit($sql, 1);
1565 $module_data = $db->sql_fetchrow($result);
1566 $db->sql_freeresult($result);
1568 unset($module_data['module_id']);
1569 unset($module_data['left_id']);
1570 unset($module_data['right_id']);
1572 $module_data['parent_id'] = (int) $row2['module_id'];
1574 $_module->update_module_data($module_data, true);
1576 // Check for last sql error happened
1577 if ($db->sql_error_triggered)
1579 $error = $db->sql_error($db->sql_error_sql);
1580 $this->p_master->db_error($error['message'], $db->sql_error_sql, __LINE__, __FILE__);
1586 $_module->remove_cache_file();
1591 * Populate the language tables
1593 function add_language($mode, $sub)
1595 global $db, $lang, $phpbb_root_path, $phpEx;
1597 $dir = @opendir($phpbb_root_path . 'language');
1599 if (!$dir)
1601 $this->error('Unable to access the language directory', __LINE__, __FILE__);
1604 while (($file = readdir($dir)) !== false)
1606 $path = $phpbb_root_path . 'language/' . $file;
1608 if (is_dir($path) && !is_link($path) && file_exists($path . '/iso.txt'))
1610 $lang_pack = file("{$phpbb_root_path}language/$path/iso.txt");
1612 $sql_ary = array(
1613 'lang_iso' => basename($path),
1614 'lang_dir' => basename($path),
1615 'lang_english_name' => trim(htmlspecialchars($lang_pack[0])),
1616 'lang_local_name' => trim(htmlspecialchars($lang_pack[1], ENT_COMPAT, 'UTF-8')),
1617 'lang_author' => trim(htmlspecialchars($lang_pack[2], ENT_COMPAT, 'UTF-8')),
1620 $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1622 if ($db->sql_error_triggered)
1624 $error = $db->sql_error($db->sql_error_sql);
1625 $this->p_master->db_error($error['message'], $db->sql_error_sql, __LINE__, __FILE__);
1629 closedir($dir);
1633 * Add search robots to the database
1635 function add_bots($mode, $sub)
1637 global $db, $lang, $phpbb_root_path, $phpEx, $config;
1639 // Obtain any submitted data
1640 foreach ($this->request_vars as $var)
1642 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
1645 // Fill the config array - it is needed by those functions we call
1646 $sql = 'SELECT *
1647 FROM ' . CONFIG_TABLE;
1648 $result = $db->sql_query($sql);
1650 $config = array();
1651 while ($row = $db->sql_fetchrow($result))
1653 $config[$row['config_name']] = $row['config_value'];
1655 $db->sql_freeresult($result);
1657 $sql = 'SELECT group_id
1658 FROM ' . GROUPS_TABLE . "
1659 WHERE group_name = 'BOTS'";
1660 $result = $db->sql_query($sql);
1661 $group_id = (int) $db->sql_fetchfield('group_id');
1662 $db->sql_freeresult($result);
1664 if (!$group_id)
1666 // If we reach this point then something has gone very wrong
1667 $this->p_master->error($lang['NO_GROUP'], __LINE__, __FILE__);
1670 if (!function_exists('user_add'))
1672 include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
1675 foreach ($this->bot_list as $bot_name => $bot_ary)
1677 $user_row = array(
1678 'user_type' => USER_IGNORE,
1679 'group_id' => $group_id,
1680 'username' => $bot_name,
1681 'user_regdate' => time(),
1682 'user_password' => '',
1683 'user_colour' => '9E8DA7',
1684 'user_email' => '',
1685 'user_lang' => $default_lang,
1686 'user_style' => 1,
1687 'user_timezone' => 0,
1688 'user_dateformat' => $lang['default_dateformat'],
1689 'user_allow_massemail' => 0,
1692 $user_id = user_add($user_row);
1694 if (!$user_id)
1696 // If we can't insert this user then continue to the next one to avoid inconsistant data
1697 $this->p_master->db_error('Unable to insert bot into users table', $db->sql_error_sql, __LINE__, __FILE__, true);
1698 continue;
1701 $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1702 'bot_active' => 1,
1703 'bot_name' => $bot_name,
1704 'user_id' => $user_id,
1705 'bot_agent' => $bot_ary[0],
1706 'bot_ip' => $bot_ary[1],
1709 $result = $db->sql_query($sql);
1714 * Sends an email to the board administrator with their password and some useful links
1716 function email_admin($mode, $sub)
1718 global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpEx;
1720 $this->page_title = $lang['STAGE_FINAL'];
1722 // Obtain any submitted data
1723 foreach ($this->request_vars as $var)
1725 $$var = (in_array($var, array('admin_name', 'dbpasswd', 'admin_pass1', 'admin_pass2'))) ? request_var($var, '', true) : request_var($var, '');
1728 // Load the basic configuration data
1729 include_once($phpbb_root_path . 'includes/constants.' . $phpEx);
1731 $sql = 'SELECT *
1732 FROM ' . CONFIG_TABLE;
1733 $result = $db->sql_query($sql);
1735 $config = array();
1736 while ($row = $db->sql_fetchrow($result))
1738 $config[$row['config_name']] = $row['config_value'];
1740 $db->sql_freeresult($result);
1742 $user->session_begin();
1743 $auth->login($admin_name, $admin_pass1, false, true, true);
1745 // OK, Now that we've reached this point we can be confident that everything
1746 // is installed and working......I hope :)
1747 // So it's time to send an email to the administrator confirming the details
1748 // they entered
1750 if ($config['email_enable'])
1752 include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
1754 $messenger = new messenger(false);
1756 $messenger->template('installed', $language);
1758 $messenger->to($board_email1, $admin_name);
1760 $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']);
1761 $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']);
1762 $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']);
1763 $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
1765 $messenger->assign_vars(array(
1766 'USERNAME' => htmlspecialchars_decode($admin_name),
1767 'PASSWORD' => htmlspecialchars_decode($admin_pass1))
1770 $messenger->send(NOTIFY_EMAIL);
1773 // And finally, add a note to the log
1774 add_log('admin', 'LOG_INSTALL_INSTALLED', $config['version']);
1776 $template->assign_vars(array(
1777 'TITLE' => $lang['INSTALL_CONGRATS'],
1778 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&amp;language=' . $language), '../docs/README.html'),
1779 'L_SUBMIT' => $lang['INSTALL_LOGIN'],
1780 'U_ACTION' => append_sid($phpbb_root_path . 'adm/index.' . $phpEx),
1785 * Generate a list of available mail server authentication methods
1787 function mail_auth_select($selected_method)
1789 global $lang;
1791 $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP');
1792 $s_smtp_auth_options = '';
1794 foreach ($auth_methods as $method)
1796 $s_smtp_auth_options .= '<option value="' . $method . '"' . (($selected_method == $method) ? ' selected="selected"' : '') . '>' . $lang['SMTP_' . str_replace('-', '_', $method)] . '</option>';
1799 return $s_smtp_auth_options;
1804 * The variables that we will be passing between pages
1805 * Used to retrieve data quickly on each page
1807 var $request_vars = array('language', 'dbms', 'dbhost', 'dbport', 'dbuser', 'dbpasswd', 'dbname', 'table_prefix', 'default_lang', 'admin_name', 'admin_pass1', 'admin_pass2', 'board_email1', 'board_email2', 'img_imagick', 'ftp_path', 'ftp_user', 'ftp_pass', 'email_enable', 'smtp_delivery', 'smtp_host', 'smtp_auth', 'smtp_user', 'smtp_pass', 'cookie_secure', 'force_server_vars', 'server_protocol', 'server_name', 'server_port', 'script_path');
1810 * The information below will be used to build the input fields presented to the user
1812 var $db_config_options = array(
1813 'legend1' => 'DB_CONFIG',
1814 'dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\')', 'explain' => false),
1815 'dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true),
1816 'dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true),
1817 'dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false),
1818 'dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false),
1819 'dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false),
1820 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => false),
1822 var $admin_config_options = array(
1823 'legend1' => 'ADMIN_CONFIG',
1824 'default_lang' => array('lang' => 'DEFAULT_LANG', 'type' => 'select', 'options' => '$this->module->inst_language_select(\'{VALUE}\')', 'explain' => false),
1825 'admin_name' => array('lang' => 'ADMIN_USERNAME', 'type' => 'text:25:100', 'explain' => true),
1826 'admin_pass1' => array('lang' => 'ADMIN_PASSWORD', 'type' => 'password:25:100', 'explain' => true),
1827 'admin_pass2' => array('lang' => 'ADMIN_PASSWORD_CONFIRM', 'type' => 'password:25:100', 'explain' => false),
1828 'board_email1' => array('lang' => 'CONTACT_EMAIL', 'type' => 'text:25:100', 'explain' => false),
1829 'board_email2' => array('lang' => 'CONTACT_EMAIL_CONFIRM', 'type' => 'text:25:100', 'explain' => false),
1831 var $advanced_config_options = array(
1832 'legend1' => 'ACP_EMAIL_SETTINGS',
1833 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'type' => 'radio:enabled_disabled', 'explain' => true),
1834 'smtp_delivery' => array('lang' => 'USE_SMTP', 'type' => 'radio:yes_no', 'explain' => true),
1835 'smtp_host' => array('lang' => 'SMTP_SERVER', 'type' => 'text:25:50', 'explain' => false),
1836 'smtp_auth' => array('lang' => 'SMTP_AUTH_METHOD', 'type' => 'select', 'options' => '$this->module->mail_auth_select(\'{VALUE}\')', 'explain' => true),
1837 'smtp_user' => array('lang' => 'SMTP_USERNAME', 'type' => 'text:25:255', 'explain' => true),
1838 'smtp_pass' => array('lang' => 'SMTP_PASSWORD', 'type' => 'password:25:255', 'explain' => true),
1840 'legend2' => 'SERVER_URL_SETTINGS',
1841 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'type' => 'radio:enabled_disabled', 'explain' => true),
1842 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'type' => 'radio:yes_no', 'explain' => true),
1843 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'type' => 'text:10:10', 'explain' => true),
1844 'server_name' => array('lang' => 'SERVER_NAME', 'type' => 'text:40:255', 'explain' => true),
1845 'server_port' => array('lang' => 'SERVER_PORT', 'type' => 'text:5:5', 'explain' => true),
1846 'script_path' => array('lang' => 'SCRIPT_PATH', 'type' => 'text::255', 'explain' => true),
1850 * Specific PHP modules we may require for certain optional or extended features
1852 var $php_dlls_other = array('zlib', 'ftp', 'gd', 'xml');
1855 * A list of the web-crawlers/bots we recognise by default
1857 * Candidates but not included:
1858 * 'Accoona [Bot]' 'Accoona-AI-Agent/'
1859 * 'ASPseek [Crawler]' 'ASPseek/'
1860 * 'Boitho [Crawler]' 'boitho.com-dc/'
1861 * 'Bunnybot [Bot]' 'powered by www.buncat.de'
1862 * 'Cosmix [Bot]' 'cfetch/'
1863 * 'Crawler Search [Crawler]' '.Crawler-Search.de'
1864 * 'Findexa [Crawler]' 'Findexa Crawler ('
1865 * 'GBSpider [Spider]' 'GBSpider v'
1866 * 'genie [Bot]' 'genieBot ('
1867 * 'Hogsearch [Bot]' 'oegp v. 1.3.0'
1868 * 'Insuranco [Bot]' 'InsurancoBot'
1869 * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler'
1870 * 'ISC Systems [Bot]' 'ISC Systems iRc Search'
1871 * 'Jyxobot [Bot]' 'Jyxobot/'
1872 * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/'
1873 * 'LinkWalker' 'LinkWalker'
1874 * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html'
1875 * 'Naver [Bot]' 'nhnbot@naver.com)'
1876 * 'NetResearchServer' 'NetResearchServer/'
1877 * 'Nimble [Crawler]' 'NimbleCrawler'
1878 * 'Ocelli [Bot]' 'Ocelli/'
1879 * 'Onsearch [Bot]' 'onCHECK-Robot'
1880 * 'Orange [Spider]' 'OrangeSpider'
1881 * 'Sproose [Bot]' 'http://www.sproose.com/bot'
1882 * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)'
1883 * 'Tbot [Bot]' 'Tbot/'
1884 * 'Thumbshots [Capture]' 'thumbshots-de-Bot'
1885 * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/'
1886 * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)'
1887 * 'WissenOnline [Bot]' 'WissenOnline-Bot'
1888 * 'WWWeasel [Bot]' 'WWWeasel Robot v'
1889 * 'Xaldon [Spider]' 'Xaldon WebSpider'
1891 var $bot_list = array(
1892 'AdsBot [Google]' => array('AdsBot-Google', ''),
1893 'Alexa [Bot]' => array('ia_archiver', ''),
1894 'Alta Vista [Bot]' => array('Scooter/', ''),
1895 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
1896 'Baidu [Spider]' => array('Baiduspider+(', ''),
1897 'Exabot [Bot]' => array('Exabot/', ''),
1898 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
1899 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
1900 'Francis [Bot]' => array('http://www.neomo.de/', ''),
1901 'Gigabot [Bot]' => array('Gigabot/', ''),
1902 'Google Adsense [Bot]' => array('Mediapartners-Google/', ''),
1903 'Google Desktop' => array('Google Desktop', ''),
1904 'Google Feedfetcher' => array('Feedfetcher-Google', ''),
1905 'Google [Bot]' => array('Googlebot', ''),
1906 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
1907 'Heritrix [Crawler]' => array('heritrix/1.', ''),
1908 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
1909 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
1910 'ichiro [Crawler]' => array('ichiro/2', ''),
1911 'Majestic-12 [Bot]' => array('MJ12bot/', ''),
1912 'Metager [Bot]' => array('MetagerBot/', ''),
1913 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
1914 'MSN [Bot]' => array('msnbot/', ''),
1915 'MSNbot Media' => array('msnbot-media/', ''),
1916 'NG-Search [Bot]' => array('NG-Search/', ''),
1917 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
1918 'Nutch/CVS [Bot]' => array('NutchCVS/', ''),
1919 'OmniExplorer [Bot]' => array('OmniExplorer_Bot/', ''),
1920 'Online link [Validator]' => array('online link validator', ''),
1921 'psbot [Picsearch]' => array('psbot/0', ''),
1922 'Seekport [Bot]' => array('Seekbot/', ''),
1923 'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
1924 'SEO Crawler' => array('SEO search Crawler/', ''),
1925 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
1926 'SEOSearch [Crawler]' => array('SEOsearch/', ''),
1927 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
1928 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
1929 'Synoo [Bot]' => array('SynooBot/', ''),
1930 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
1931 'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
1932 'Voyager [Bot]' => array('voyager/1.0', ''),
1933 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
1934 'W3C [Linkcheck]' => array('W3C-checklink/', ''),
1935 'W3C [Validator]' => array('W3C_*Validator', ''),
1936 'WiseNut [Bot]' => array('http://www.WISEnutbot.com', ''),
1937 'YaCy [Bot]' => array('yacybot', ''),
1938 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
1939 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
1940 'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
1941 'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
1945 * Define the module structure so that we can populate the database without
1946 * needing to hard-code module_id values
1948 var $module_categories = array(
1949 'acp' => array(
1950 'ACP_CAT_GENERAL' => array(
1951 'ACP_QUICK_ACCESS',
1952 'ACP_BOARD_CONFIGURATION',
1953 'ACP_CLIENT_COMMUNICATION',
1954 'ACP_SERVER_CONFIGURATION',
1956 'ACP_CAT_FORUMS' => array(
1957 'ACP_MANAGE_FORUMS',
1958 'ACP_FORUM_BASED_PERMISSIONS',
1960 'ACP_CAT_POSTING' => array(
1961 'ACP_MESSAGES',
1962 'ACP_ATTACHMENTS',
1964 'ACP_CAT_USERGROUP' => array(
1965 'ACP_CAT_USERS',
1966 'ACP_GROUPS',
1967 'ACP_USER_SECURITY',
1969 'ACP_CAT_PERMISSIONS' => array(
1970 'ACP_GLOBAL_PERMISSIONS',
1971 'ACP_FORUM_BASED_PERMISSIONS',
1972 'ACP_PERMISSION_ROLES',
1973 'ACP_PERMISSION_MASKS',
1975 'ACP_CAT_STYLES' => array(
1976 'ACP_STYLE_MANAGEMENT',
1977 'ACP_STYLE_COMPONENTS',
1979 'ACP_CAT_MAINTENANCE' => array(
1980 'ACP_FORUM_LOGS',
1981 'ACP_CAT_DATABASE',
1983 'ACP_CAT_SYSTEM' => array(
1984 'ACP_AUTOMATION',
1985 'ACP_GENERAL_TASKS',
1986 'ACP_MODULE_MANAGEMENT',
1988 'ACP_CAT_DOT_MODS' => null,
1990 'mcp' => array(
1991 'MCP_MAIN' => null,
1992 'MCP_QUEUE' => null,
1993 'MCP_REPORTS' => null,
1994 'MCP_NOTES' => null,
1995 'MCP_WARN' => null,
1996 'MCP_LOGS' => null,
1997 'MCP_BAN' => null,
1999 'ucp' => array(
2000 'UCP_MAIN' => null,
2001 'UCP_PROFILE' => null,
2002 'UCP_PREFS' => null,
2003 'UCP_PM' => null,
2004 'UCP_USERGROUPS' => null,
2005 'UCP_ZEBRA' => null,
2009 var $module_extras = array(
2010 'acp' => array(
2011 'ACP_QUICK_ACCESS' => array(
2012 'ACP_MANAGE_USERS',
2013 'ACP_GROUPS_MANAGE',
2014 'ACP_MANAGE_FORUMS',
2015 'ACP_MOD_LOGS',
2016 'ACP_BOTS',
2017 'ACP_PHP_INFO',
2019 'ACP_FORUM_BASED_PERMISSIONS' => array(
2020 'ACP_FORUM_PERMISSIONS',
2021 'ACP_FORUM_MODERATORS',
2022 'ACP_USERS_FORUM_PERMISSIONS',
2023 'ACP_GROUPS_FORUM_PERMISSIONS',