DOKU_SESSION_LIFETIME,
261 'path' => DOKU_SESSION_PATH,
262 'domain' => DOKU_SESSION_DOMAIN,
263 'secure' => ($conf['securecookie'] && is_ssl()),
264 'httponly' => true,
265 'samesite' => 'Lax',
266 ]);
267
268 // make sure the session cookie contains a valid session ID
269 if (isset($_COOKIE[DOKU_SESSION_NAME]) && !preg_match('/^[-,a-zA-Z0-9]{22,256}$/', $_COOKIE[DOKU_SESSION_NAME])) {
270 unset($_COOKIE[DOKU_SESSION_NAME]);
271 }
272
273 session_start();
274 }
275
276
277 /**
278 * Проверяет пути из файла конфигурации
279 */
280 function init_paths()
281 {
282 global $conf;
283
284 $paths = [
285 'datadir' => 'pages',
286 'olddir' => 'attic',
287 'mediadir' => 'media',
288 'mediaolddir' => 'media_attic',
289 'metadir' => 'meta',
290 'mediametadir' => 'media_meta',
291 'cachedir' => 'cache',
292 'indexdir' => 'index',
293 'lockdir' => 'locks',
294 'tmpdir' => 'tmp',
295 'logdir' => 'log',
296 ];
297
298 foreach ($paths as $c => $p) {
299 $path = empty($conf[$c]) ? $conf['savedir'] . '/' . $p : $conf[$c];
300 $conf[$c] = init_path($path);
301 if (empty($conf[$c])) {
302 $path = fullpath($path);
303 nice_die("The $c ('$p') at $path is not found, isn't accessible or writable.
304 You should check your config and permission settings.
305 Or maybe you want to run the
306 installer?");
307 }
308 }
309
310 // путь к старому списку изменений нужен только для обновления
311 $conf['changelog_old'] = init_path(
312 $conf['changelog'] ?? $conf['savedir'] . '/changes.log'
313 );
314 if ($conf['changelog_old'] == '') {
315 unset($conf['changelog_old']);
316 }
317 // жестко запрограммирован журнал изменений, поскольку теперь это кэш, который находится в метаданных
318 $conf['changelog'] = $conf['metadir'] . '/_dokuwiki.changes';
319 $conf['media_changelog'] = $conf['metadir'] . '/_media.changes';
320 }
321
322 /**
323 * Загрузить языковые строки
324 *
325 * @param string $langCode код языка, переданный обработчиком событий
326 */
327 function init_lang($langCode)
328 {
329 //подготовить языковой массив
330 global $lang, $config_cascade;
331 $lang = [];
332
333 //загрузить языковые файлы
334 require(DOKU_INC . 'inc/lang/en/lang.php');
335 foreach ($config_cascade['lang']['core'] as $config_file) {
336 if (file_exists($config_file . 'en/lang.php')) {
337 include($config_file . 'en/lang.php');
338 }
339 }
340
341 if ($langCode && $langCode != 'en') {
342 if (file_exists(DOKU_INC . "inc/lang/$langCode/lang.php")) {
343 require(DOKU_INC . "inc/lang/$langCode/lang.php");
344 }
345 foreach ($config_cascade['lang']['core'] as $config_file) {
346 if (file_exists($config_file . "$langCode/lang.php")) {
347 include($config_file . "$langCode/lang.php");
348 }
349 }
350 }
351 }
352
353 /**
354 * Проверяет наличие определенных файлов и создает их, если они отсутствуют.
355 */
356 function init_files()
357 {
358 global $conf;
359
360 $files = [$conf['indexdir'] . '/page.idx'];
361
362 foreach ($files as $file) {
363 if (!file_exists($file)) {
364 $fh = @fopen($file, 'a');
365 if ($fh) {
366 fclose($fh);
367 if ($conf['fperm']) chmod($file, $conf['fperm']);
368 } else {
369 nice_die("$file is not writable. Check your permissions settings!");
370 }
371 }
372 }
373 }
374
375 /**
376 * Возвращает абсолютный путь
377 *
378 * Сначала проверяется указанный путь, затем DOKU_INC.
379 * Проверьте также доступность каталогов.
380 *
381 * @автор Андреас Гор
382 *
383 * @param string $ path
384 *
385 * @return bool | строка
386 */
387 function init_path($path)
388 {
389 // проверка существования
390 $p = fullpath($path);
391 if (!file_exists($p)) {
392 $p = fullpath(DOKU_INC . $path);
393 if (!file_exists($p)) {
394 return '';
395 }
396 }
397
398 // проверка возможности записи
399 if (!@is_writable($p)) {
400 return '';
401 }
402
403 // проверка доступности (бит выполнения) для каталогов
404 if (@is_dir($p) && !file_exists("$p/.")) {
405 return '';
406 }
407
408 return $p;
409 }
410
411 /**
412 * Устанавливает внутренние значения конфигурации fperm и dperm, которые, если установлены,
413 * будет использоваться для изменения разрешения вновь созданного каталога или
414 * файл с chmod. Учитывает влияние umask системы
415 * установка значений только при необходимости.
416 */
417 function init_creationmodes()
418 {
419 global $conf;
420
421 // Устаревшая поддержка старой схемы umask / dmask
422 unset($conf['dmask']);
423 unset($conf['fmask']);
424 unset($conf['umask']);
425
426 $conf['fperm'] = false;
427 $conf['dperm'] = false;
428
429 // получить системную маску umask, вернуться к 0, если она недоступна
430 $umask = @umask();
431 if (!$umask) $umask = 0000;
432
433 // проверка того, что автоматически устанавливается системой при создании файлаn
434 // и устанавливаем параметр fperm, если это не то, что нам нужно
435 $auto_fmode = 0666 & ~$umask;
436 if ($auto_fmode != $conf['fmode']) $conf['fperm'] = $conf['fmode'];
437
438 // проверка того, что автоматически устанавливается системой при создании каталога
439 // и устанавливаем параметр dperm, если это не то, что нам нужно.
440 $auto_dmode = 0777 & ~$umask;
441 if ($auto_dmode != $conf['dmode']) $conf['dperm'] = $conf['dmode'];
442 }
443
444 /**
445 * Возвращает полный абсолютный URL-адрес каталога, где
446 * DokuWiki установлен в (включая завершающий слеш)
447 *
448 * !! Невозможно получить доступ к значениям $_SERVER через $INPUT
449 * !! здесь, поскольку эта функция вызывается до $INPUT
450 * !! инициализировано.
451 *
452 * @автор Андреас Гор
453 *
454 * @param null | bool $ abs Вернуть абсолютный URL? (по умолчанию null — $conf['canonical'])
455 *
456 * @возвращаемая строка
457 */
458 function getBaseURL($abs = null)
459 {
460 global $conf;
461
462 $abs ??= $conf['canonical'];
463
464 if (!empty($conf['basedir'])) {
465 $dir = $conf['basedir'];
466 } elseif (substr($_SERVER['SCRIPT_NAME'], -4) == '.php') {
467 $dir = dirname($_SERVER['SCRIPT_NAME']);
468 } elseif (substr($_SERVER['PHP_SELF'], -4) == '.php') {
469 $dir = dirname($_SERVER['PHP_SELF']);
470 } elseif ($_SERVER['DOCUMENT_ROOT'] && $_SERVER['SCRIPT_FILENAME']) {
471 $dir = preg_replace(
472 '/^' . preg_quote($_SERVER['DOCUMENT_ROOT'], '/') . '/',
473 '',
474 $_SERVER['SCRIPT_FILENAME']
475 );
476 $dir = dirname('/' . $dir);
477 } else {
478 $dir = ''; //возможно, это неверно, но мы предполагаем, что он в корне
479 }
480
481 $dir = str_replace('\\', '/', $dir); // исправление странного поведения WIN
482 $dir = preg_replace('#//+#', '/', "/$dir/"); // гарантируем начальные и конечные слеши
483
484 //handle script in lib/exe dir
485 $dir = preg_replace('!lib/exe/$!', '', $dir);
486
487 //handle script in lib/plugins dir
488 $dir = preg_replace('!lib/plugins/.*$!', '', $dir);
489
490 //завершить здесь для относительных URL-адресов
491 if (!$abs) return $dir;
492
493 //используйте конфигурацию, если она доступна, обрежьте все слеши в конце baseurl, чтобы избежать нескольких последовательных слешей в пути
494 if (!empty($conf['baseurl'])) return rtrim($conf['baseurl'], '/') . $dir;
495
496 //разделить заголовок хоста на хост и порт
497 if (isset($_SERVER['HTTP_HOST'])) {
498 if (
499 (!empty($conf['trustedproxy'])) && isset($_SERVER['HTTP_X_FORWARDED_HOST'])
500 && preg_match('/' . $conf['trustedproxy'] . '/', $_SERVER['REMOTE_ADDR'])
501 ) {
502 $cur_host = $_SERVER['HTTP_X_FORWARDED_HOST'];
503 } else {
504 $cur_host = $_SERVER['HTTP_HOST'];
505 }
506 $parsed_host = parse_url('http://' . $cur_host);
507 $host = $parsed_host['host'] ?? '';
508 $port = $parsed_host['port'] ?? '';
509 } elseif (isset($_SERVER['SERVER_NAME'])) {
510 $parsed_host = parse_url('http://' . $_SERVER['SERVER_NAME']);
511 $host = $parsed_host['host'] ?? '';
512 $port = $parsed_host['port'] ?? '';
513 } else {
514 $host = php_uname('n');
515 $port = '';
516 }
517
518 if (!is_ssl()) {
519 $proto = 'http://';
520 if ($port == '80') {
521 $port = '';
522 }
523 } else {
524 $proto = 'https://';
525 if ($port == '443') {
526 $port = '';
527 }
528 }
529
530 if ($port !== '') $port = ':' . $port;
531
532 return $proto . $host . $port . $dir;
533 }
534
535 /**
536 * Проверьте, доступен ли сайт через HTTPS
537 *
538 * Apache оставляет ,$_SERVER['HTTPS'] пустым, когда он недоступен, IIS устанавливает его в значение «выкл.».
539 * «ложь» и «отключено» — это всего лишь предположения
540 *
541 * @returns bool true, когда SSL активен
542 */
543 function is_ssl()
544 {
545 global $conf;
546
547 // проверяем, находимся ли мы за обратным прокси-сервером
548 if (
549 (!empty($conf['trustedproxy'])) && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
550 && preg_match('/' . $conf['trustedproxy'] . '/', $_SERVER['REMOTE_ADDR'])
551 && ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
552 ) {
553 return true;
554 }
555
556 if (preg_match('/^(|off|false|disabled)$/i', $_SERVER['HTTPS'] ?? 'off')) {
557 return false;
558 }
559
560 return true;
561 }
562
563 /**
564 * проверяет, что это ОС Windows
565 * @return bool
566 */
567 function isWindows()
568 {
569 return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
570 }
571
572 /**
573 * вывести приятное сообщение, даже если ни один стили еще не загружен.
574 * @param целое число | строка $ сообщение
575 * @param integer|string $msg
576 */
577 function nice_die($msg)
578 {
579 echo<<
581
582 DokuWiki Setup Error
583
584
586
DokuWiki Setup Error
587
$msg
588
589
590
591 EOT;
592 if (defined('DOKU_UNITTEST')) {
593 throw new RuntimeException('nice_die: ' . $msg);
594 }
595 exit(1);
596 }
597
598 /**
599 * Замена realpath()
600 *
601 * Эта функция ведет себя аналогично функции realpath() в PHP, но не разрешает
602 * символические ссылки или доступ к верхним каталогам
603 *
604 * @автор Андреас Гор
605 * @author
606 * @ссылка http://php.net/manual/en/function.realpath.php#75992
607 *
608 * @param string $ path
609 * @param bool $ существует
610 *
611 * @return bool | строка
612 */
613 function fullpath($path, $exists = false)
614 {
615 static $run = 0;
616 $root = '';
617 $iswin = (isWindows() || !empty($GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']));
618
619 // найти (неразрушаемый) корень пути - сохраняет содержимое Windows нетронутым
620 if ($path[0] == '/') {
621 $root = '/';
622 } elseif ($iswin) {
623 // сопоставить букву диска и пути UNC
624 if (preg_match('!^([a-zA-z]:)(.*)!', $path, $match)) {
625 $root = $match[1] . '/';
626 $path = $match[2];
627 } elseif (preg_match('!^(\\\\\\\\[^\\\\/]+\\\\[^\\\\/]+[\\\\/])(.*)!', $path, $match)) {
628 $root = $match[1];
629 $path = $match[2];
630 }
631 }
632 $path = str_replace('\\', '/', $path);
633
634 // если указанный путь еще не был абсолютным, добавьте путь к скрипту и повторите попытку
635 if (!$root) {
636 $base = dirname($_SERVER['SCRIPT_FILENAME']);
637 $path = $base . '/' . $path;
638 if ($run == 0) { // избегаем бесконечной рекурсии, когда база по какой-то причине не является абсолютной
639 $run++;
640 return fullpath($path, $exists);
641 }
642 }
643 $run = 0;
644
645 // канонизировать
646 $path = explode('/', $path);
647 $newpath = [];
648 foreach ($path as $p) {
649 if ($p === '' || $p === '.') continue;
650 if ($p === '..') {
651 array_pop($newpath);
652 continue;
653 }
654 $newpath[] = $p;
655 }
656 $finalpath = $root . implode('/', $newpath);
657
658 // проверка существования при необходимости (кроме случаев модульного тестирования)
659 if ($exists && !defined('DOKU_UNITTEST') && !file_exists($finalpath)) {
660 return false;
661 }
662 return $finalpath;
663 }
664