|
<? |
|
|
|
namespace XTT\ReAuth; |
|
|
|
use Bitrix\Main; |
|
use Bitrix\Main\Page; |
|
|
|
/* |
|
Disable standart spread |
|
\COption::SetOptionString("main", "ALLOW_SPREAD_COOKIE", "N"); |
|
*/ |
|
|
|
class ReAuth |
|
{ |
|
const SESSION_COOKIE_NAME = 'PIXELIZER_SPREAD_COOKIE'; |
|
|
|
protected static /* string */ $PIXEL_PATH = '/x-dev/reauth/pixel.php'; |
|
|
|
public static function init() |
|
{ |
|
AddEventHandler("main", "OnBeforeLocalRedirect", ['XTT\ReAuth\ReAuth', 'OnBeforeLocalRedirect']); |
|
AddEventHandler("main", "OnBeforeEndBufferContent", ['XTT\ReAuth\ReAuth', 'OnBeforeEndBufferContent']); |
|
AddEventHandler("main", "OnAfterUserAuthorize", ['XTT\ReAuth\ReAuth', 'OnAfterUserAuthorize']); |
|
|
|
// \COption::SetOptionString("main", "ALLOW_SPREAD_COOKIE", "N"); |
|
} |
|
|
|
// ! Event (main) |
|
public function OnBeforeEndBufferContent() |
|
{ |
|
$reAuth = new ReAuth(); |
|
$asset = Page\Asset::getInstance(); |
|
$asset->addString($reAuth->GetSpreadCookieHTML(), false, Page\AssetLocation::AFTER_JS, Page\AssetMode::STANDARD); |
|
} |
|
|
|
// ! Event (main) |
|
public function OnBeforeLocalRedirect() |
|
{ |
|
// Store cookies for next hit (see \XTT\ReAuth\ReAuth::GetSpreadCookieHTML()) |
|
$reAuth = new ReAuth(); |
|
$reAuth->StoreCookies(); |
|
} |
|
|
|
// ! Event (main) |
|
public function OnAfterUserAuthorize($arParams) |
|
{ |
|
if (!defined('ADMIN_SECTION') || ADMIN_SECTION !== true) { |
|
return; |
|
} |
|
|
|
// Store cookies for next hit (see \XTT\ReAuth\ReAuth::GetSpreadCookieHTML()) |
|
$reAuth = new ReAuth(); |
|
$reAuth->StoreCookies(); |
|
} |
|
|
|
public function isActive() |
|
{ |
|
return true; |
|
} |
|
|
|
/** |
|
* Вызывается после успешной авторизации (юзера или редиректе) |
|
*/ |
|
public function StoreCookies() |
|
{ |
|
$application = Main\Application::getInstance(); |
|
$response = Main\Context::getCurrent()->getResponse(); |
|
|
|
// Установка прошлых кук из сохраненной сессиии |
|
if (is_array($application->getSession()[self::SESSION_COOKIE_NAME])) { |
|
foreach ($application->getSession()[self::SESSION_COOKIE_NAME] as $cookie) { |
|
if ($cookie instanceof Main\Web\Cookie) { |
|
$response->addCookie($cookie, false); |
|
} |
|
} |
|
} |
|
$application->getSession()[self::SESSION_COOKIE_NAME] = $response->getCookies(); |
|
|
|
$this->HoldSpreadCookieHTML(true); |
|
} |
|
|
|
/** |
|
* Если передано значение `$set`, то устанавливает это состояние и возвращает прошлое.\ |
|
* Иначе просто возвращает состояние держателя печенек (был ли показ "пикселя"). |
|
*/ |
|
public function HoldSpreadCookieHTML(bool $set = false) |
|
{ |
|
static $showed_already = false; |
|
$result = $showed_already; |
|
if ($set) { |
|
$showed_already = true; |
|
} |
|
return $result; |
|
} |
|
|
|
/** |
|
* Возвращает строку с "пикселями" для распространения печенек |
|
*/ |
|
public function GetSpreadCookieHTML() |
|
{ |
|
$res = ''; |
|
$request = Main\Context::getCurrent()->getRequest(); |
|
|
|
if ( |
|
$request->isHttps() |
|
// Если распространения еще не было |
|
&& !$this->HoldSpreadCookieHTML() |
|
&& $this->isActive() |
|
// && \COption::GetOptionString("main", "ALLOW_SPREAD_COOKIE", "Y") == "Y" |
|
) { |
|
foreach ($this->GetSpreadCookieUrls() as $url) { |
|
$res .= "new Image().src='" . \CUtil::JSEscape($url) . "';\n"; |
|
$this->HoldSpreadCookieHTML(true); |
|
} |
|
} |
|
|
|
if ($res) { |
|
return '<script>' . $res . '</script>'; |
|
} |
|
return ''; |
|
} |
|
|
|
/** |
|
* Возвращает массив URL-адресов, содержащих подписанные междоменные печеньки |
|
* |
|
* @return array |
|
*/ |
|
public function GetSpreadCookieUrls() |
|
{ |
|
if (!$this->isActive()/* \COption::GetOptionString("main", "ALLOW_SPREAD_COOKIE", "Y") !== "Y" */) { |
|
return []; |
|
} |
|
|
|
$application = Main\Application::getInstance(); |
|
$response = Main\Context::getCurrent()->getResponse(); |
|
$request = Main\Context::getCurrent()->getRequest(); |
|
|
|
if ( |
|
isset($application->getSession()[self::SESSION_COOKIE_NAME]) |
|
&& is_array($application->getSession()[self::SESSION_COOKIE_NAME]) |
|
) { |
|
foreach ($application->getSession()[self::SESSION_COOKIE_NAME] as $cookie) { |
|
if ($cookie instanceof Main\Web\Cookie) { |
|
$response->addCookie($cookie, false); |
|
} |
|
} |
|
// ! Очищаем, т.к. будем считать, что печеньем уже поделилсь |
|
unset($application->getSession()[self::SESSION_COOKIE_NAME]); |
|
} |
|
|
|
$cookies = $response->getCookies(); |
|
|
|
if (empty($cookies)) { |
|
return []; |
|
} |
|
|
|
$params = ""; |
|
foreach ($cookies as $cookie) { |
|
if ($cookie->getSpread() & Main\Web\Cookie::SPREAD_SITES) { |
|
$params .= join(chr(1), [ |
|
$cookie->getName(), |
|
$cookie->getValue(), |
|
$cookie->getExpires(), |
|
$cookie->getPath(), |
|
'', //domain is empty |
|
$cookie->getSecure(), |
|
$cookie->getHttpOnly(), |
|
chr(2), |
|
]); |
|
} |
|
} |
|
|
|
$salt = $_SERVER["REMOTE_ADDR"] . "|" . @filemtime($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/classes/general/version.php") . "|" . LICENSE_KEY; |
|
$params = "s=" . urlencode(base64_encode($params)) . "&k=" . urlencode(md5($params . $salt)); |
|
|
|
$arrDomain = []; |
|
$arrDomain[] = $request->getHttpHost(); |
|
|
|
$rs = \CSite::GetList('', '', ["ACTIVE" => "Y"]); |
|
while ($ar = $rs->Fetch()) { |
|
$arD = explode("\n", str_replace("\r", "\n", $ar["DOMAINS"])); |
|
if (is_array($arD) && count($arD) > 0) { |
|
foreach ($arD as $d) { |
|
if (trim($d) <> '') { |
|
$arrDomain[] = $d; |
|
} |
|
} |
|
} |
|
} |
|
|
|
if (empty($arrDomain)) { |
|
return []; |
|
} |
|
|
|
$arUniqDomains = []; |
|
$arrDomain = array_unique($arrDomain); |
|
$arrDomain2 = array_unique($arrDomain); |
|
// Уникализация по поддоменам |
|
foreach ($arrDomain as $domain1) { |
|
$bGood = true; |
|
foreach ($arrDomain2 as $domain2) { |
|
if ( |
|
mb_strlen($domain1) > mb_strlen($domain2) |
|
&& mb_substr($domain1, - (mb_strlen($domain2) + 1)) == "." . $domain2 |
|
) { |
|
$bGood = false; |
|
break; |
|
} |
|
} |
|
if ($bGood) { |
|
$arUniqDomains[] = $domain1; |
|
} |
|
} |
|
|
|
$arUrl = []; |
|
$protocol = ($request->isHttps() ? "https://" : "http://"); |
|
$arrCurUrl = parse_url($protocol . $request->getHttpHost() . "/"); |
|
foreach ($arUniqDomains as $domain) { |
|
if (trim($domain) <> '') { |
|
$url = $protocol . $domain . self::$PIXEL_PATH . "?" . $params; |
|
$arrUrl = parse_url($url); |
|
if ($arrUrl["host"] != $arrCurUrl["host"]) { |
|
$arUrl[] = $url; |
|
} |
|
} |
|
} |
|
|
|
return $arUrl; |
|
} |
|
} |