86 // using symlinks to reference the original files so as to segregate unique files from non-unique |
86 // using symlinks to reference the original files so as to segregate unique files from non-unique |
87 // and distribution-standard ones. Enano will pivot its root directory accordingly if the file |
87 // and distribution-standard ones. Enano will pivot its root directory accordingly if the file |
88 // .enanodev is found in the Enano root (not /repo/). |
88 // .enanodev is found in the Enano root (not /repo/). |
89 if ( strpos(__FILE__, '/repo/') && file_exists(dirname(__FILE__) . '/../../.enanodev') ) |
89 if ( strpos(__FILE__, '/repo/') && file_exists(dirname(__FILE__) . '/../../.enanodev') ) |
90 { |
90 { |
91 // We have a development directory. Remove /repo/ from the picture. |
91 // We have a development directory. Remove /repo/ from the picture. |
92 $filename = str_replace('/repo/', '/', __FILE__); |
92 $filename = str_replace('/repo/', '/', __FILE__); |
93 } |
93 } |
94 else |
94 else |
95 { |
95 { |
96 // Standard Enano installation |
96 // Standard Enano installation |
97 $filename = __FILE__; |
97 $filename = __FILE__; |
98 } |
98 } |
99 |
99 |
100 // ENANO_ROOT is sometimes defined by plugins like AjIM that need the constant before the Enano API is initialized |
100 // ENANO_ROOT is sometimes defined by plugins like AjIM that need the constant before the Enano API is initialized |
101 if ( !defined('ENANO_ROOT') ) |
101 if ( !defined('ENANO_ROOT') ) |
102 define('ENANO_ROOT', dirname(dirname($filename))); |
102 define('ENANO_ROOT', dirname(dirname($filename))); |
103 |
103 |
104 // We deprecated debugConsole in 1.0.2 because it was never used and there were a lot of unneeded debugging points in the code. |
104 // We deprecated debugConsole in 1.0.2 because it was never used and there were a lot of unneeded debugging points in the code. |
105 |
105 |
106 // _nightly.php is used to tag non-Mercurial-generated nightly builds |
106 // _nightly.php is used to tag non-Mercurial-generated nightly builds |
107 if ( file_exists( ENANO_ROOT . '/_nightly.php') ) |
107 if ( file_exists( ENANO_ROOT . '/_nightly.php') ) |
108 require(ENANO_ROOT.'/_nightly.php'); |
108 require(ENANO_ROOT.'/_nightly.php'); |
109 |
109 |
110 // List of scheduled tasks (don't change this manually, use register_cron_task()) |
110 // List of scheduled tasks (don't change this manually, use register_cron_task()) |
111 $cron_tasks = array(); |
111 $cron_tasks = array(); |
112 |
112 |
113 } // check for ENANO_COMMON_ROOT_LOADED |
113 } // check for ENANO_COMMON_ROOT_LOADED |
114 else |
114 else |
115 { |
115 { |
116 // loading a second time |
116 // loading a second time |
117 if ( !defined('ENANO_COMMON_ROOT_LOADED_MULTI') ) |
117 if ( !defined('ENANO_COMMON_ROOT_LOADED_MULTI') ) |
118 { |
118 { |
119 define('ENANO_COMMON_ROOT_LOADED_MULTI', 1); |
119 define('ENANO_COMMON_ROOT_LOADED_MULTI', 1); |
120 } |
120 } |
121 } |
121 } |
122 |
122 |
123 // If all we really need is the root directory, just leave now |
123 // If all we really need is the root directory, just leave now |
124 // checking for ENANO_COMMON_ROOT_LOADED_MULTI here means that if common |
124 // checking for ENANO_COMMON_ROOT_LOADED_MULTI here means that if common |
125 // is included a second time, the rest of Enano will load. |
125 // is included a second time, the rest of Enano will load. |
126 if ( defined('ENANO_COMMON_ROOTONLY') && !defined('ENANO_COMMON_ROOT_LOADED_MULTI') ) |
126 if ( defined('ENANO_COMMON_ROOTONLY') && !defined('ENANO_COMMON_ROOT_LOADED_MULTI') ) |
127 { |
127 { |
128 return true; |
128 return true; |
129 } |
129 } |
130 |
130 |
131 // Start including files. LOTS of files. Yeah! |
131 // Start including files. LOTS of files. Yeah! |
132 require_once(ENANO_ROOT.'/includes/constants.php'); |
132 require_once(ENANO_ROOT.'/includes/constants.php'); |
133 require_once(ENANO_ROOT.'/includes/functions.php'); |
133 require_once(ENANO_ROOT.'/includes/functions.php'); |
227 unset($sep); // save 10 bytes of memory... |
227 unset($sep); // save 10 bytes of memory... |
228 |
228 |
229 // Build the list of system tables (this is mostly done in constants.php, but that's before table_prefix is known) |
229 // Build the list of system tables (this is mostly done in constants.php, but that's before table_prefix is known) |
230 if ( defined('table_prefix') && !defined('ENANO_TABLELIST_PREFIXED') ) |
230 if ( defined('table_prefix') && !defined('ENANO_TABLELIST_PREFIXED') ) |
231 { |
231 { |
232 define('ENANO_TABLELIST_PREFIXED', 1); |
232 define('ENANO_TABLELIST_PREFIXED', 1); |
233 foreach ( $system_table_list as $i => $_ ) |
233 foreach ( $system_table_list as $i => $_ ) |
234 { |
234 { |
235 $system_table_list[$i] = table_prefix . $system_table_list[$i]; |
235 $system_table_list[$i] = table_prefix . $system_table_list[$i]; |
236 } |
236 } |
237 } |
237 } |
238 |
238 |
239 // Select and fetch the site configuration |
239 // Select and fetch the site configuration |
240 $e = $db->sql_query('SELECT config_name, config_value FROM '.table_prefix.'config;'); |
240 $e = $db->sql_query('SELECT config_name, config_value FROM '.table_prefix.'config;'); |
241 if ( !$e ) |
241 if ( !$e ) |
242 { |
242 { |
243 $db->_die('Some critical configuration information could not be selected.'); |
243 $db->_die('Some critical configuration information could not be selected.'); |
244 } |
244 } |
245 // Used in die_semicritical to figure out whether to call getConfig() or not |
245 // Used in die_semicritical to figure out whether to call getConfig() or not |
246 define('ENANO_CONFIG_FETCHED', ''); |
246 define('ENANO_CONFIG_FETCHED', ''); |
247 |
247 |
248 // Initialize and fetch the site configuration array, which is used to cache the config |
248 // Initialize and fetch the site configuration array, which is used to cache the config |
249 $enano_config = Array(); |
249 $enano_config = Array(); |
250 while($r = $db->fetchrow()) |
250 while($r = $db->fetchrow()) |
251 { |
251 { |
252 $enano_config[$r['config_name']] = $r['config_value']; |
252 $enano_config[$r['config_name']] = $r['config_value']; |
253 } |
253 } |
254 |
254 |
255 $db->free_result(); |
255 $db->free_result(); |
256 |
256 |
257 profiler_log('Config fetched'); |
257 profiler_log('Config fetched'); |
258 |
258 |
259 if ( defined('ENANO_EXIT_AFTER_CONFIG') ) |
259 if ( defined('ENANO_EXIT_AFTER_CONFIG') ) |
260 { |
260 { |
261 return true; |
261 return true; |
262 } |
262 } |
263 |
263 |
264 // Now that we have the config, check the Enano version. |
264 // Now that we have the config, check the Enano version. |
265 if ( enano_version(false, true) != $version && !defined('IN_ENANO_UPGRADE') ) |
265 if ( enano_version(false, true) != $version && !defined('IN_ENANO_UPGRADE') ) |
266 { |
266 { |
267 grinding_halt('Version mismatch', '<p>It seems that the Enano release we\'re trying to run ('.$version.') is different from the version specified in your database ('.enano_version().'). Perhaps you need to <a href="'.scriptPath.'/install/index.php">upgrade</a>?</p>'); |
267 grinding_halt('Version mismatch', '<p>It seems that the Enano release we\'re trying to run ('.$version.') is different from the version specified in your database ('.enano_version().'). Perhaps you need to <a href="'.scriptPath.'/install/index.php">upgrade</a>?</p>'); |
268 } |
268 } |
269 |
269 |
270 // Set our CDN path |
270 // Set our CDN path |
271 if ( !defined('cdnPath') ) |
271 if ( !defined('cdnPath') ) |
272 { |
272 { |
273 $cdnpath = getConfig('cdn_path', scriptPath); |
273 $cdnpath = getConfig('cdn_path', scriptPath); |
274 if ( empty($cdnpath) ) |
274 if ( empty($cdnpath) ) |
275 $cdnpath = scriptPath; |
275 $cdnpath = scriptPath; |
276 define('cdnPath', $cdnpath); |
276 define('cdnPath', $cdnpath); |
277 } |
277 } |
278 |
278 |
279 // |
279 // |
280 // Low level maintenance |
280 // Low level maintenance |
281 // |
281 // |
282 |
282 |
283 // If the AES key size has been changed, bail out and fast |
283 // If the AES key size has been changed, bail out and fast |
284 if ( !getConfig('aes_key_size') ) |
284 if ( !getConfig('aes_key_size') ) |
285 { |
285 { |
286 setConfig('aes_key_size', AES_BITS); |
286 setConfig('aes_key_size', AES_BITS); |
287 } |
287 } |
288 else if ( $ks = getConfig('aes_key_size') ) |
288 else if ( $ks = getConfig('aes_key_size') ) |
289 { |
289 { |
290 if ( intval($ks) != AES_BITS ) |
290 if ( intval($ks) != AES_BITS ) |
291 { |
291 { |
292 grinding_halt('AES key size changed', '<p>Enano has detected that the AES key size in constants.php has been changed. This change cannot be performed after installation, otherwise the private key would have to be re-generated and all passwords would have to be re-encrypted.</p><p>Please change the key size back to ' . $ks . ' bits and reload this page.</p>'); |
292 grinding_halt('AES key size changed', '<p>Enano has detected that the AES key size in constants.php has been changed. This change cannot be performed after installation, otherwise the private key would have to be re-generated and all passwords would have to be re-encrypted.</p><p>Please change the key size back to ' . $ks . ' bits and reload this page.</p>'); |
293 } |
293 } |
294 } |
294 } |
295 |
295 |
296 // Same for AES block size |
296 // Same for AES block size |
297 if ( !getConfig('aes_block_size') ) |
297 if ( !getConfig('aes_block_size') ) |
298 { |
298 { |
299 setConfig('aes_block_size', AES_BLOCKSIZE); |
299 setConfig('aes_block_size', AES_BLOCKSIZE); |
300 } |
300 } |
301 else if ( $ks = getConfig('aes_block_size') ) |
301 else if ( $ks = getConfig('aes_block_size') ) |
302 { |
302 { |
303 if ( intval($ks) != AES_BLOCKSIZE ) |
303 if ( intval($ks) != AES_BLOCKSIZE ) |
304 { |
304 { |
305 grinding_halt('AES block size changed', '<p>Enano has detected that the AES block size in constants.php has been changed. This change cannot be performed after installation, otherwise all passwords would have to be re-encrypted.</p><p>Please change the block size back to ' . $ks . ' bits and reload this page.</p>'); |
305 grinding_halt('AES block size changed', '<p>Enano has detected that the AES block size in constants.php has been changed. This change cannot be performed after installation, otherwise all passwords would have to be re-encrypted.</p><p>Please change the block size back to ' . $ks . ' bits and reload this page.</p>'); |
306 } |
306 } |
307 } |
307 } |
308 |
308 |
309 // Is there no default language? |
309 // Is there no default language? |
310 if ( getConfig('default_language') === false && !defined('IN_ENANO_MIGRATION') ) |
310 if ( getConfig('default_language') === false && !defined('IN_ENANO_MIGRATION') ) |
311 { |
311 { |
312 $q = $db->sql_query('SELECT lang_id FROM '.table_prefix.'language LIMIT 1;'); |
312 $q = $db->sql_query('SELECT lang_id FROM '.table_prefix.'language LIMIT 1;'); |
313 if ( !$q ) |
313 if ( !$q ) |
314 $db->_die('common.php - setting default language'); |
314 $db->_die('common.php - setting default language'); |
315 if ( $db->numrows() < 1 && !defined('ENANO_ALLOW_LOAD_NOLANG') ) |
315 if ( $db->numrows() < 1 && !defined('ENANO_ALLOW_LOAD_NOLANG') ) |
316 { |
316 { |
317 grinding_halt('No languages', '<p>There are no languages installed on this site.</p> |
317 grinding_halt('No languages', '<p>There are no languages installed on this site.</p> |
318 <p>If you are the website administrator, you may install a language by writing and executing a simple PHP script to install it:</p> |
318 <p>If you are the website administrator, you may install a language by writing and executing a simple PHP script to install it:</p> |
319 <pre> |
319 <pre> |
320 <?php |
320 <?php |
321 define("ENANO_ALLOW_LOAD_NOLANG", 1); |
321 define("ENANO_ALLOW_LOAD_NOLANG", 1); |
322 require("includes/common.php"); |
322 require("includes/common.php"); |
323 install_language("eng", "English", "English", ENANO_ROOT . "/language/english/enano.json");</pre>'); |
323 install_language("eng", "English", "English", ENANO_ROOT . "/language/english/enano.json");</pre>'); |
324 } |
324 } |
325 $row = $db->fetchrow(); |
325 $row = $db->fetchrow(); |
326 setConfig('default_language', $row['lang_id']); |
326 setConfig('default_language', $row['lang_id']); |
327 } |
327 } |
328 |
328 |
329 profiler_log('Ran checks'); |
329 profiler_log('Ran checks'); |
330 |
330 |
331 // Init cache |
331 // Init cache |
369 // Once $paths->init() is called, we could be redirected to the main page, so we don't want |
369 // Once $paths->init() is called, we could be redirected to the main page, so we don't want |
370 // that if the installer's running. Don't just go and define IN_ENANO_INSTALL from your |
370 // that if the installer's running. Don't just go and define IN_ENANO_INSTALL from your |
371 // script though, because that will make the DBAL look in the wrong place for the config file. |
371 // script though, because that will make the DBAL look in the wrong place for the config file. |
372 if ( !defined('IN_ENANO_INSTALL') ) |
372 if ( !defined('IN_ENANO_INSTALL') ) |
373 { |
373 { |
374 // And here you have it, the de facto way to place a hook. Plugins can place hooks and hook |
374 // And here you have it, the de facto way to place a hook. Plugins can place hooks and hook |
375 // into other plugins. You just never know. |
375 // into other plugins. You just never know. |
376 $code = $plugins->setHook('base_classes_initted'); |
376 $code = $plugins->setHook('base_classes_initted'); |
377 foreach ( $code as $cmd ) |
377 foreach ( $code as $cmd ) |
378 { |
378 { |
379 eval($cmd); |
379 eval($cmd); |
380 } |
380 } |
381 |
381 |
382 profiler_log('Finished base_classes_initted hook'); |
382 profiler_log('Finished base_classes_initted hook'); |
383 |
383 |
384 // One quick security check... |
384 // One quick security check... |
385 if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) ) |
385 if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) ) |
386 { |
386 { |
387 die('SECURITY: spoofed IP address: ' . htmlspecialchars($_SERVER['REMOTE_ADDR'])); |
387 die('SECURITY: spoofed IP address: ' . htmlspecialchars($_SERVER['REMOTE_ADDR'])); |
388 } |
388 } |
389 |
389 |
390 // For special and administration pages, sometimes there is a "preloader" function that must be run |
390 // For special and administration pages, sometimes there is a "preloader" function that must be run |
391 // before the session manager and/or path manager get the init signal. Call it here. |
391 // before the session manager and/or path manager get the init signal. Call it here. |
392 $urlname = get_title(true); |
392 $urlname = get_title(true); |
393 list($page_id, $namespace) = RenderMan::strToPageID($urlname); |
393 list($page_id, $namespace) = RenderMan::strToPageID($urlname); |
394 list($page_id_top) = explode('/', $page_id); |
394 list($page_id_top) = explode('/', $page_id); |
395 $fname = "page_{$namespace}_{$page_id_top}_preloader"; |
395 $fname = "page_{$namespace}_{$page_id_top}_preloader"; |
396 if( ( $namespace == 'Admin' || $namespace == 'Special' ) && function_exists($fname)) |
396 if( ( $namespace == 'Admin' || $namespace == 'Special' ) && function_exists($fname)) |
397 { |
397 { |
398 call_user_func($fname); |
398 call_user_func($fname); |
399 } |
399 } |
400 |
400 |
401 profiler_log('Checked for (and ran, if applicable) preloader'); |
401 profiler_log('Checked for (and ran, if applicable) preloader'); |
402 |
402 |
403 // Add all of our built in special pages |
403 // Add all of our built in special pages |
404 foreach ( array('SpecialUserFuncs', 'SpecialPageFuncs', 'SpecialAdmin', 'SpecialCSS', 'SpecialUpDownload', 'SpecialSearch', 'PrivateMessages', 'SpecialGroups', 'SpecialLog') as $plugin ) |
404 foreach ( array('SpecialUserFuncs', 'SpecialPageFuncs', 'SpecialAdmin', 'SpecialCSS', 'SpecialUpDownload', 'SpecialSearch', 'PrivateMessages', 'SpecialGroups', 'SpecialLog') as $plugin ) |
405 { |
405 { |
406 $funcname = "{$plugin}_paths_init"; |
406 $funcname = "{$plugin}_paths_init"; |
407 if ( function_exists($funcname) ) |
407 if ( function_exists($funcname) ) |
408 { |
408 { |
409 $funcname(); |
409 $funcname(); |
410 } |
410 } |
411 } |
411 } |
412 profiler_log('Added special pages'); |
412 profiler_log('Added special pages'); |
413 |
413 |
414 // All checks passed! Start the main components up. |
414 // All checks passed! Start the main components up. |
415 $session->start(); |
415 $session->start(); |
416 |
416 |
417 // This is where plugins will want to add pages from 1.1.x on out. You can still add |
417 // This is where plugins will want to add pages from 1.1.x on out. You can still add |
418 // pages at base_classes_initted but the titles won't be localized. This is because |
418 // pages at base_classes_initted but the titles won't be localized. This is because |
419 // the session manager has to be started before localization will work in the user's |
419 // the session manager has to be started before localization will work in the user's |
420 // preferred language. |
420 // preferred language. |
421 $code = $plugins->setHook('session_started'); |
421 $code = $plugins->setHook('session_started'); |
422 foreach ( $code as $cmd ) |
422 foreach ( $code as $cmd ) |
423 { |
423 { |
424 eval($cmd); |
424 eval($cmd); |
425 } |
425 } |
426 |
426 |
427 profiler_log('Ran session_started hook'); |
427 profiler_log('Ran session_started hook'); |
428 |
428 |
429 $paths->init($urlname); |
429 $paths->init($urlname); |
430 |
430 |
431 // setup output format |
431 // setup output format |
432 if ( defined('ENANO_OUTPUT_FORMAT') ) |
432 if ( defined('ENANO_OUTPUT_FORMAT') ) |
433 $class = 'Output_' . ENANO_OUTPUT_FORMAT; |
433 $class = 'Output_' . ENANO_OUTPUT_FORMAT; |
434 else |
434 else |
435 $class = ( isset($_GET['noheaders']) ) ? 'Output_Naked' : 'Output_HTML'; |
435 $class = ( isset($_GET['noheaders']) ) ? 'Output_Naked' : 'Output_HTML'; |
436 |
436 |
437 $output = new $class(); |
437 $output = new $class(); |
438 |
438 |
439 // Are we running from the API? If so, did the page set a title? |
439 // Are we running from the API? If so, did the page set a title? |
440 if ( !defined('ENANO_INTERFACE_INDEX') && !defined('ENANO_INTERFACE_AJAX') && isset($title) ) |
440 if ( !defined('ENANO_INTERFACE_INDEX') && !defined('ENANO_INTERFACE_AJAX') && isset($title) ) |
441 { |
441 { |
442 $output->set_title($title); |
442 $output->set_title($title); |
443 } |
443 } |
444 |
444 |
445 // We're ready for whatever life throws us now, at least from an API point of view. |
445 // We're ready for whatever life throws us now, at least from an API point of view. |
446 define('ENANO_MAINSTREAM', ''); |
446 define('ENANO_MAINSTREAM', ''); |
447 |
447 |
448 // If the site is disabled, bail out, unless we're trying to log in or administer the site |
448 // If the site is disabled, bail out, unless we're trying to log in or administer the site |
449 if(getConfig('site_disabled') == '1' && $session->user_level < USER_LEVEL_ADMIN) |
449 if(getConfig('site_disabled') == '1' && $session->user_level < USER_LEVEL_ADMIN) |
450 { |
450 { |
451 // is this one of the more critical special pages? |
451 // is this one of the more critical special pages? |
452 if ( $paths->namespace == 'Admin' || ( $paths->namespace == 'Special' && ( $paths->page_id == 'CSS' || $paths->page_id == 'Administration' || $paths->page_id == 'Login' ) ) ) |
452 if ( $paths->namespace == 'Admin' || ( $paths->namespace == 'Special' && ( $paths->page_id == 'CSS' || $paths->page_id == 'Administration' || $paths->page_id == 'Login' ) ) ) |
453 { |
453 { |
454 // yeah, we need to keep this page available. do nothing; allow execution to continue |
454 // yeah, we need to keep this page available. do nothing; allow execution to continue |
455 } |
455 } |
456 else |
456 else |
457 { |
457 { |
458 if(!$n = getConfig('site_disabled_notice')) |
458 if(!$n = getConfig('site_disabled_notice')) |
459 { |
459 { |
460 $n = 'The administrator has disabled the site. Please check back later.'; |
460 $n = 'The administrator has disabled the site. Please check back later.'; |
461 } |
461 } |
462 |
462 |
463 $text = RenderMan::render($n) . ' |
463 $text = RenderMan::render($n) . ' |
464 <div class="info-box"> |
464 <div class="info-box"> |
465 If you have an administrative account, you may <a href="'.makeUrlNS('Special', 'Login').'">log in</a> to the site. |
465 If you have an administrative account, you may <a href="'.makeUrlNS('Special', 'Login').'">log in</a> to the site. |
466 </div>'; |
466 </div>'; |
467 $paths->wiki_mode = 0; |
467 $paths->wiki_mode = 0; |
468 die_semicritical('Site disabled', $text); |
468 die_semicritical('Site disabled', $text); |
469 } |
469 } |
470 } |
470 } |
471 else if ( getConfig('site_disabled') == '1' && $session->user_level >= USER_LEVEL_ADMIN ) |
471 else if ( getConfig('site_disabled') == '1' && $session->user_level >= USER_LEVEL_ADMIN ) |
472 { |
472 { |
473 // If the site is disabled but the user has admin rights, allow browsing |
473 // If the site is disabled but the user has admin rights, allow browsing |
474 // and stuff, but display the orange box notifying the admin. |
474 // and stuff, but display the orange box notifying the admin. |
475 $template->site_disabled = true; |
475 $template->site_disabled = true; |
476 } |
476 } |
477 |
477 |
478 // At this point all of Enano is fully initialized and running and you're ready to do whatever you want. |
478 // At this point all of Enano is fully initialized and running and you're ready to do whatever you want. |
479 $code = $plugins->setHook('common_post'); |
479 $code = $plugins->setHook('common_post'); |
480 foreach ( $code as $cmd ) |
480 foreach ( $code as $cmd ) |
481 { |
481 { |
482 eval($cmd); |
482 eval($cmd); |
483 } |
483 } |
484 |
484 |
485 profiler_log('Ran disabled-site checks and common_post'); |
485 profiler_log('Ran disabled-site checks and common_post'); |
486 |
486 |
487 load_rank_data(); |
487 load_rank_data(); |
488 |
488 |
489 profiler_log('Loaded user rank data'); |
489 profiler_log('Loaded user rank data'); |
490 |
490 |
491 if ( isset($_GET['noheaders']) ) |
491 if ( isset($_GET['noheaders']) ) |
492 $template->no_headers = true; |
492 $template->no_headers = true; |
493 } |
493 } |
494 |
494 |
495 profiler_log('common finished'); |
495 profiler_log('common finished'); |
496 |
496 |
497 // That's the end. Enano should be loaded now :-) |
497 // That's the end. Enano should be loaded now :-) |