Issues (1369)

includes/init.php (1 issue)

1
<?php
2
3
version_compare(PHP_VERSION, '5.6') < 0 ? die('FATAL ERROR: SuperNova REQUIRE PHP version >= 5.6') : false;
4
5
use Common\Tools\VersionCheckerDeprecated;
6
use Core\Autoloader;
7
use Core\SnBootstrap;
8
use Fleet\TaskDispatchFleets;
9
use Player\playerTimeDiff;
10
11
// Защита от двойного инита
12
if(defined('INIT')) {
13
  return;
14
}
15
16
const INIT = true;
17
18
// Initial time and mem params
19
define('SN_TIME_MICRO', microtime(true));
20
define('SN_MEM_START', memory_get_usage());
21
22
// Basic constants
23
!defined('INSIDE') && define('INSIDE', true);
24
!defined('INSTALL') && define('INSTALL', false);
25
!defined('IN_PHPBB') && define('IN_PHPBB', true);
26
27
call_user_func(function () {
28
  if (file_exists($fileName = realpath(__DIR__ . '/../.env.ini'))) {
29
    define('SN_ENV_PROD', 'production');
30
    define('SN_ENV_DEV', 'development');
31
32
    if (($ini = @parse_ini_file($fileName)) !== false) {
33
      if (!empty($ini['SN_ENV']) && in_array($envName = $ini['SN_ENV'], [SN_ENV_DEV, SN_ENV_PROD,])) {
34
        define('SN_ENV', $envName);
35
      } else {
36
        define('SN_ENV', SN_ENV_PROD);
37
      }
38
    }
39
  }
40
});
41
42
// Config file name
43
const SN_CONFIG_NAME = 'config.php';
44
45
// Calculating physical root path to SN
46
define('SN_ROOT_PHYSICAL', str_replace('\\', '/', realpath(dirname(__DIR__))) . '/');
47
define('SN_ROOT_PHYSICAL_STR_LEN', strlen(SN_ROOT_PHYSICAL));
48
49
// Getting relative HTTP root to game resources and executable pages (.php)
50
// I.e. in https://server.com/supernova/index.php SN_ROOT_RELATIVE will become '/supernova/'
51
// It needed to make game work on sub-folders and do not mess with cookies
52
// Not very accurate - heavily relies on filesystem paths and may fail on complicate web server setups
53
$sn_root_relative = str_replace(['\\', '//'], '/', getcwd() . '/');
54
$sn_root_relative = str_replace(SN_ROOT_PHYSICAL, '', $sn_root_relative);
55
$sn_root_relative = $sn_root_relative . basename($_SERVER['SCRIPT_NAME']);
56
// Removing script name to obtain HTTP root
57
define('SN_ROOT_RELATIVE', str_replace($sn_root_relative, '', $_SERVER['SCRIPT_NAME']));
58
59
// Path to modules
60
const SN_ROOT_MODULES = SN_ROOT_PHYSICAL . 'modules/';
61
const SN_MODULE_CONFIG_NAME = SN_CONFIG_NAME;
62
63
// Detecting if we are under Google's eye - domain is prefixed with `google.`
64
$_server_server_name =
65
  isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] :
66
    (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
67
if (substr(strtolower($_server_server_name), 0, 7) === 'google.') {
68
  define('SN_GOOGLE', true);
69
} else {
70
  define('SN_GOOGLE', false);
71
}
72
73
// Instancing
74
// If server name contains port - replacing : with _ - servers on different ports are different instances
75
$instanceName = str_replace(':', '_', $_server_server_name);
76
if(SN_GOOGLE) {
77
  $instanceName = substr($instanceName, 7);
78
}
79
$instancePath = 'servers/' . $instanceName . '/';
80
// This would be our relative path to instance-specific files
81
// Instance is propagated only if config file `/servers/(server name with port - if any)/config.php` present
82
define('SN_INSTANCE_PATH_RELATIVE', file_exists(SN_ROOT_PHYSICAL . $instancePath . SN_CONFIG_NAME) ? $instancePath : '');
83
// Absolute path to instance files
84
const SN_INSTANCE_PATH_ABSOLUTE = SN_ROOT_PHYSICAL . SN_INSTANCE_PATH_RELATIVE;
85
// Config for instance
86
const SN_CONFIG_PATH = SN_INSTANCE_PATH_ABSOLUTE . SN_CONFIG_NAME;
87
88
// Now finding what folder we will use for player's avatars
89
$avatarDirs = [
90
  SN_INSTANCE_PATH_RELATIVE . 'avatars',
91
  'avatars',
92
  'images/avatar',
93
];
94
foreach ($avatarDirs as $possibleDir) {
95
  $avatarInstancePath = SN_ROOT_PHYSICAL . $possibleDir . '/';
96
  if (is_dir($avatarInstancePath) && is_writable($avatarInstancePath)) {
97
    define('SN_PATH_AVATAR_RELATIVE', $possibleDir . '/');
98
    define('SN_PATH_AVATAR', $avatarInstancePath);
99
    break;
100
  }
101
}
102
if (!defined('SN_PATH_AVATAR_RELATIVE')) {
103
  die('Can not finding writable folder for player avatars. Check that `/avatars` or `/image/avatar` folder exists and it writable by web-server.');
104
}
105
106
// Detecting root URL aka Virtual Root
107
$_server_http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
108
define('SN_ROOT_VIRTUAL', 'http' . (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '') . '://' . $_server_http_host . SN_ROOT_RELATIVE);
109
// Extra config in case of Google
110
define('SN_ROOT_VIRTUAL_PARENT', str_replace('//google.', '//', SN_ROOT_VIRTUAL));
111
// HTTP path to user avatars
112
define('SN_HTTP_AVATAR', SN_ROOT_VIRTUAL . SN_PATH_AVATAR_RELATIVE);
113
114
115
ini_set('error_reporting', E_ALL ^ E_NOTICE);
116
117
header('Content-type: text/html; charset=utf-8');
118
ob_start();
119
120
// Installing autoloader
121
require_once SN_ROOT_PHYSICAL . 'classes/Core/Autoloader.php';
122
Autoloader::register('classes/');
123
Autoloader::register('classes/UBE/');
124
125
// Propagating other constants
126
require_once SN_ROOT_PHYSICAL . 'includes/constants/constants.php';
127
128
// Initiating benchmark
129
SnBootstrap::install_benchmark();
130
// Loading functions - can't be inserted into function
131
require_once SN_ROOT_PHYSICAL . 'includes/db.php';
132
require_once(SN_ROOT_PHYSICAL . 'includes/general/general.php');
133
sn_sys_load_php_files(SN_ROOT_PHYSICAL . 'includes/functions/', PHP_EX);
134
135
SN::loadFileSettings();
136
SN::init_global_objects();
137
138
// AFTER init global objects 'cause vars.php uses some from config
139
require_once(SN_ROOT_PHYSICAL . 'includes/vars.php');
140
141
// Some time required to start from cold cache
142
set_time_limit(60); // TODO - Optimize
143
144
// Отладка
145
// define('BE_DEBUG', true); // Отладка боевого движка
146
SnBootstrap::init_debug_state();
147
148
SnBootstrap::performUpdate(SN::$config);
149
150
if (BanHammer::checkIpV4($_SERVER["REMOTE_ADDR"])) {
151
  die("Server error. Try to connect later...<br />\nСерверная ошибка. Попробуйте подключиться позже...");
152
}
153
154
// init constants from db
155
// Moved from SnBootstrap for phpStorm autocomplete
156
// TODO - Should be removed someday - there should NOT be constants that depends on configuration!
157
define('SN_COOKIE', (SN::$config->COOKIE_NAME ?: 'SuperNova') . (SN_GOOGLE ? '_G' : ''));
158
define('SN_COOKIE_I', SN_COOKIE . AUTH_COOKIE_IMPERSONATE_SUFFIX);
159
define('SN_COOKIE_D', SN_COOKIE . '_D');
160
define('SN_COOKIE_T', SN_COOKIE . '_T'); // Time measure cookie
161
define('SN_COOKIE_F', SN_COOKIE . '_F'); // Font size cookie
162
define('SN_COOKIE_U', SN_COOKIE . '_U'); // Current user cookie aka user ID
163
define('SN_COOKIE_U_I', SN_COOKIE_U . AUTH_COOKIE_IMPERSONATE_SUFFIX); // Current impersonator user cookie aka impersonator user ID
164
define('SN_COOKIE_WEBP', SN_COOKIE . '_WEBP'); // WebP support cookie
165
166
define('DEFAULT_SKIN_NAME', 'EpicBlue');
167
define('DEFAULT_SKINPATH', SN::$config->game_default_skin ?: 'skins/' . DEFAULT_SKIN_NAME . '/');
168
169
define('DEFAULT_LANG', SN::$config->game_default_language ?: 'ru');
170
171
define('FMT_DATE', SN::$config->int_format_date ?: 'd.m.Y');
172
define('FMT_TIME', SN::$config->int_format_time ?: 'H:i:s');
173
define('FMT_DATE_TIME', FMT_DATE . ' ' . FMT_TIME);
174
175
/**
176
 * @var classCache  $sn_cache
177
 * @var classConfig $config
178
 * @var debug       $debug
179
 */
180
global $sn_cache, $config, $auth, $debug, $lang;
181
182
183
global $sn_page_name;
184
empty($sn_page_name) ? $sn_page_name = INITIAL_PAGE : false;
185
global $template_result;
186
$template_result = ['.' => ['result' => []]];
187
188
SN::$lang = $lang = new classLocale(SN::$config->server_locale_log_usage);
189
190
global $sn_data, $sn_mvc;
191
192
// Including here to allow `AwardConstants` use in MM race festival module
193
@include_once(SN_ROOT_MODULES . 'player_award/classes/AwardConstants.php');
194
195
// Подключаем все модули
196
// По нормальным делам тут надо подключать манифесты
197
// И читать конфиги - вдруг модуль отключен?
198
// Конфиг - часть манифеста?
199
200
// TODO
201
// Здесь - потому что core_auth модуль лежит в другом каталоге и его нужно инициализировать отдельно
202
// И надо инициализировать после загрузки других модулей. Когда-то это казалось отличной идеей, бля...
203
SN::$auth = new \core_auth();
204
SN::$gc->modules->registerModule(SN::$auth->manifest['name'], SN::$auth);
205
//SN::$gc->modules->registerModule(core_auth::$main_provider->manifest['name'], core_auth::$main_provider);
206
207
SN::$gc->modules->loadModules(SN_ROOT_MODULES);
208
SN::$gc->modules->initModules();
209
210
211
// Подключаем дефолтную страницу
212
// По нормальным делам её надо подключать в порядке загрузки обработчиков
213
// Сейчас мы делаем это здесь только для того, что бы содержание дефолтной страницы оказалось вверху. Что не факт, что нужно всегда
214
// Но нужно, пока у нас есть не MVC-страницы
215
$sn_page_data      = $sn_mvc['pages'][$sn_page_name];
216
$sn_page_name_file = 'includes/pages/' . $sn_page_data['filename'] . DOT_PHP_EX;
217
if($sn_page_name) {
218
  // Merging page options to global option pull
219
  if(is_array($sn_page_data['options'])) {
220
    SN::$options = array_merge(SN::$options, $sn_page_data['options']);
221
  }
222
223
  if(isset($sn_page_data) && file_exists($sn_page_name_file)) {
224
    require_once($sn_page_name_file);
225
  }
226
}
227
228
if((defined('IN_AJAX') && IN_AJAX === true) || (defined('IN_ADMIN') && IN_ADMIN === true) || (!empty(SN::$options[PAGE_OPTION_ADMIN]))) {
229
  SN::$options[PAGE_OPTION_FLEET_UPDATE_SKIP] = true;
230
}
231
232
233
// А теперь проверяем - поддерживают ли у нас загруженный код такую страницу
234
// TODO - костыль, что бы работали старые модули. Убрать!
235
if(is_array($sn_data['pages'])) {
236
  $sn_mvc['pages'] = array_merge($sn_mvc['pages'], $sn_data['pages']);
237
}
238
if(!isset($sn_mvc['pages'][$sn_page_name])) {
239
  $sn_page_name = '';
240
}
241
242
$lang->lng_switch(sys_get_param_str('lang'));
243
244
245
if(SN::$config->server_updater_check_auto && SN::$config->server_updater_check_last + SN::$config->server_updater_check_period <= SN_TIME_NOW) {
246
  VersionCheckerDeprecated::performCheckVersion();
247
}
248
249
SN::$gc->watchdog->register(new TaskDispatchFleets(), TaskDispatchFleets::class);
250
SN::$gc->worker->registerWorker('dispatchFleets', function () {
251
  \Core\Worker::detachIncomingRequest();
252
253
  $result = SN::$gc->fleetDispatcher->flt_flying_fleet_handler();
254
255
  return $result + ['message' => 'Fleets dispatched', ];
256
});
257
258
// TODO Check URL timestamp when checking signature
259
if (INITIAL_PAGE === 'worker' && SN::$gc->request->url->isSigned()) {
260
  if (!defined('IN_AJAX')) {
261
    define('IN_AJAX', true);
262
  }
263
264
  $result = [];
265
266
  if (!empty($mode = sys_get_param_str('mode'))) {
267
    $result = SN::$gc->worker->$mode();
268
  }
269
270
  die(json_encode($result));
271
}
272
273
if(SN::$config->user_birthday_gift && SN_TIME_NOW - SN::$config->user_birthday_celebrate > PERIOD_DAY) {
274
  require_once(SN_ROOT_PHYSICAL . 'includes/includes/user_birthday_celebrate.php');
275
  sn_user_birthday_celebrate();
276
}
277
278
if(!SN::$config->var_online_user_count || SN::$config->var_online_user_time + SN::$config->game_users_update_online < SN_TIME_NOW) {
279
  dbUpdateUsersCount(db_user_count());
280
  dbUpdateUsersOnline(db_user_count(true));
281
  SN::$config->pass()->var_online_user_time = SN_TIME_NOW;
282
  if(SN::$config->server_log_online) {
283
    /** @noinspection SqlResolve */
284
    doquery("INSERT IGNORE INTO `{{log_users_online}}` SET online_count = " . SN::$config->var_online_user_count . ";");
285
  }
286
}
287
288
289
290
291
global $user;
292
$result = SN::$auth->login();
293
294
global $account_logged_in;
295
$account_logged_in = !empty(SN::$auth->account) && $result[F_LOGIN_STATUS] == LOGIN_SUCCESS;
296
297
$user = !empty($result[F_USER]) ? $result[F_USER] : false;
298
299
unset($result[F_USER]);
300
$template_result += $result;
301
unset($result);
302
// В этой точке пользователь либо авторизирован - и есть его запись - либо пользователя гарантированно нет в базе
303
304
$template_result[F_ACCOUNT_IS_AUTHORIZED] = SN::$sys_user_logged_in = !empty($user) && isset($user['id']) && $user['id'];
305
306
if(!empty($user['id'])) {
307
  SN::$user_options->user_change($user['id']);
308
}
309
310
// Если сообщение пустое - заполняем его по коду
311
$template_result[F_LOGIN_MESSAGE] =
312
  !empty($template_result[F_LOGIN_MESSAGE])
313
    ? $template_result[F_LOGIN_MESSAGE]
314
    : ($template_result[F_LOGIN_STATUS] != LOGIN_UNDEFINED
315
        ? $lang['sys_login_messages'][$template_result[F_LOGIN_STATUS]]
316
        : false
317
      );
318
319
if($template_result[F_LOGIN_STATUS] == LOGIN_ERROR_USERNAME_RESTRICTED_CHARACTERS) {
320
  $prohibited_characters = array_map(function($value) {
321
    return "'" . htmlentities($value, ENT_QUOTES, 'UTF-8') . "'";
322
  }, str_split(LOGIN_REGISTER_CHARACTERS_PROHIBITED));
323
  $template_result[F_LOGIN_MESSAGE] .= implode(', ', $prohibited_characters);
324
}
325
326
327
if(defined('DEBUG_AUTH') && DEBUG_AUTH && !defined('IN_AJAX')) {
0 ignored issues
show
The constant DEBUG_AUTH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
328
  pdump('Отключи отладку перед продакшном!');
329
}
330
331
332
// Это уже переключаемся на пользовательский язык с откатом до языка в параметрах запроса
333
$lang->lng_switch(sys_get_param_str('lang'));
334
335
SN::$config->db_loadItem('game_disable') == GAME_DISABLE_INSTALL
336
  ? define('INSTALL_MODE', GAME_DISABLE_INSTALL)
337
  : false;
338
339
// TODO - to scheduler
340
StatUpdateLauncher::unlock();
341
342
if(!empty($_GET['admin_http_key']) && $_GET['admin_http_key'] == $config->admin_http_key) {
343
  define('IN_API', true);
344
}
345
346
if($template_result[F_GAME_DISABLE] = SN::$config->game_disable) {
347
  $template_result[F_GAME_DISABLE_REASON] = HelperString::nl2br(
348
    SN::$config->game_disable == GAME_DISABLE_REASON
349
      ? SN::$config->game_disable_reason
350
      : $lang['sys_game_disable_reason'][SN::$config->game_disable]
351
  );
352
353
  // For API - just skipping all checks
354
  // TODO: That is ideologically wrong and should be redone
355
  if(defined('IN_API')) {
356
    return;
357
  }
358
359
  // Actions for install mode
360
  if(defined('INSTALL_MODE') && INSTALL_MODE) {
361
    // Handling log out - should work even in install mode
362
    if(strtolower(INITIAL_PAGE) === 'logout') {
363
      SN::$auth->logout(true);
364
      die();
365
    }
366
367
    // If user not logged in AND we are not on login page - redirect user there
368
    if(!SN::$sys_user_logged_in && !defined('LOGIN_LOGOUT')) {
369
      header('Location: login.php');
370
      die();
371
    }
372
373
    // If user is type of admin AND in user pages - redirecting him to admin interface
374
    // You really shouldn't mess in user interface until game not configured!
375
    if($user['authlevel'] >= 1 && !defined('IN_ADMIN')) {
376
      header('Location: ' . SN_ROOT_VIRTUAL_PARENT . 'admin/overview.php');
377
      die();
378
    }
379
  }
380
381
  if(
382
    ($user['authlevel'] < 1 || !(defined('IN_ADMIN') && IN_ADMIN))
383
    &&
384
    !(defined('INSTALL_MODE') && defined('LOGIN_LOGOUT'))
385
    &&
386
    empty(SN::$options[PAGE_OPTION_ADMIN])
387
  ) {
388
    SnTemplate::messageBox($template_result[F_GAME_DISABLE_REASON], SN::$config->game_name, '', 5, false);
389
    ob_end_flush();
390
    die();
391
  }
392
}
393
394
// TODO ban
395
// TODO $skip_ban_check
396
global $skip_ban_check;
397
if($template_result[F_BANNED_STATUS] && !$skip_ban_check) {
398
  if(defined('IN_API')) {
399
    return;
400
  }
401
402
  $bantime = date(FMT_DATE_TIME, $template_result[F_BANNED_STATUS]);
403
  // TODO: Add ban reason. Add vacation time. Add message window
404
  SnTemplate::messageBox("{$lang['sys_banned_msg']} {$bantime}", $lang['ban_title']);
405
  die("{$lang['sys_banned_msg']} {$bantime}");
406
}
407
408
// TODO !!! Просто $allow_anonymous используется в платежных модулях !!!
409
global $allow_anonymous;
410
$allow_anonymous = $allow_anonymous || (isset($sn_page_data['allow_anonymous']) && $sn_page_data['allow_anonymous']);
411
412
413
if(SN::$sys_user_logged_in && INITIAL_PAGE == 'login') {
414
  sys_redirect(SN_ROOT_VIRTUAL . 'overview.php');
415
} elseif($account_logged_in && !SN::$sys_user_logged_in) { // empty(core_auth::$user['id'])
416
} elseif(!$allow_anonymous && !SN::$sys_user_logged_in && !defined('IN_API')) {
417
  sys_redirect(SN_ROOT_VIRTUAL . 'login.php');
418
}
419
420
playerTimeDiff::defineTimeDiff();
421
422
// TODO: ...to controller
423
!empty($user) && sys_get_param_id('only_hide_news') ? die(nws_mark_read($user)) : false;
424
!empty($user) && sys_get_param_id('survey_vote') ? die(survey_vote($user)) : false;
425
426
!empty($sn_mvc['i18n']['']) ? lng_load_i18n($sn_mvc['i18n']['']) : false;
427
$sn_page_name && !empty($sn_mvc['i18n'][$sn_page_name]) ? lng_load_i18n($sn_mvc['i18n'][$sn_page_name]) : false;
428
429
execute_hooks($sn_mvc['model'][''], $template, 'model', '');
430
431
SN::$gc->watchdog->execute();
432
433
//ini_set('error_reporting', E_ALL);
434
435
//SN::$gc->watchdog->checkConfigTimeDiff(
436
//  'fleet_update_last',
437
//  SN::$config->fleet_update_interval,
438
//  // Promise
439
//  function () {SN::$gc->fleetDispatcher->dispatch();},
440
//  classConfig::DATE_TYPE_SQL_STRING,
441
//  false
442
//);
443
444
StatUpdateLauncher::scheduler_process();
445