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