/modules/main/lib/engine/response/redirect.php

https://gitlab.com/alexprowars/bitrix · PHP · 157 lines · 108 code · 29 blank · 20 comment · 13 complexity · d13d9c168dcc52698c0059dbf0e8d9c6 MD5 · raw file

  1. <?php
  2. namespace Bitrix\Main\Engine\Response;
  3. use Bitrix\Main;
  4. use Bitrix\Main\Context;
  5. use Bitrix\Main\Text\Encoding;
  6. class Redirect extends Main\HttpResponse
  7. {
  8. /** @var string|Main\Web\Uri $url */
  9. private $url;
  10. /** @var bool */
  11. private $skipSecurity;
  12. public function __construct($url, bool $skipSecurity = false)
  13. {
  14. parent::__construct();
  15. $this
  16. ->setStatus('302 Found')
  17. ->setSkipSecurity($skipSecurity)
  18. ->setUrl($url)
  19. ;
  20. }
  21. /**
  22. * @return Main\Web\Uri|string
  23. */
  24. public function getUrl()
  25. {
  26. return $this->url;
  27. }
  28. /**
  29. * @param Main\Web\Uri|string $url
  30. * @return $this
  31. */
  32. public function setUrl($url)
  33. {
  34. $this->url = $url;
  35. return $this;
  36. }
  37. /**
  38. * @return bool
  39. */
  40. public function isSkippedSecurity(): bool
  41. {
  42. return $this->skipSecurity;
  43. }
  44. /**
  45. * @param bool $skipSecurity
  46. * @return $this
  47. */
  48. public function setSkipSecurity(bool $skipSecurity)
  49. {
  50. $this->skipSecurity = $skipSecurity;
  51. return $this;
  52. }
  53. private function checkTrial(): bool
  54. {
  55. $isTrial =
  56. defined("DEMO") && DEMO === "Y" &&
  57. (
  58. !defined("SITEEXPIREDATE") ||
  59. !defined("OLDSITEEXPIREDATE") ||
  60. SITEEXPIREDATE == '' ||
  61. SITEEXPIREDATE != OLDSITEEXPIREDATE
  62. )
  63. ;
  64. return $isTrial;
  65. }
  66. private function isExternalUrl($url): bool
  67. {
  68. return preg_match("'^(http://|https://|ftp://)'i", $url);
  69. }
  70. private function modifyBySecurity($url)
  71. {
  72. /** @global \CMain $APPLICATION */
  73. global $APPLICATION;
  74. $isExternal = $this->isExternalUrl($url);
  75. if(!$isExternal && strpos($url, "/") !== 0)
  76. {
  77. $url = $APPLICATION->GetCurDir() . $url;
  78. }
  79. //doubtful about &amp; and http response splitting defence
  80. $url = str_replace(["&amp;", "\r", "\n"], ["&", "", ""], $url);
  81. if (!defined("BX_UTF") && defined("LANG_CHARSET"))
  82. {
  83. $url = Encoding::convertEncoding($url, LANG_CHARSET, "UTF-8");
  84. }
  85. return $url;
  86. }
  87. private function processInternalUrl($url)
  88. {
  89. /** @global \CMain $APPLICATION */
  90. global $APPLICATION;
  91. //store cookies for next hit (see CMain::GetSpreadCookieHTML())
  92. $APPLICATION->StoreCookies();
  93. $server = Context::getCurrent()->getServer();
  94. $protocol = Context::getCurrent()->getRequest()->isHttps() ? "https" : "http";
  95. $host = $server->getHttpHost();
  96. $port = (int)$server->getServerPort();
  97. if ($port !== 80 && $port !== 443 && $port > 0 && strpos($host, ":") === false)
  98. {
  99. $host .= ":" . $port;
  100. }
  101. return "{$protocol}://{$host}{$url}";
  102. }
  103. public function send()
  104. {
  105. if ($this->checkTrial())
  106. {
  107. die(Main\Localization\Loc::getMessage('MAIN_ENGINE_REDIRECT_TRIAL_EXPIRED'));
  108. }
  109. $url = $this->getUrl();
  110. $isExternal = $this->isExternalUrl($url);
  111. $url = $this->modifyBySecurity($url);
  112. foreach (GetModuleEvents("main", "OnBeforeLocalRedirect", true) as $event)
  113. {
  114. ExecuteModuleEventEx($event, [&$url, $this->isSkippedSecurity(), &$isExternal, $this]);
  115. }
  116. if (!$isExternal)
  117. {
  118. $url = $this->processInternalUrl($url);
  119. }
  120. $this->addHeader('Location', $url);
  121. foreach (GetModuleEvents("main", "OnLocalRedirect", true) as $event)
  122. {
  123. ExecuteModuleEventEx($event);
  124. }
  125. Main\Application::getInstance()->getKernelSession()["BX_REDIRECT_TIME"] = time();
  126. parent::send();
  127. }
  128. }