%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/bitrix/www/bitrix/modules/pull/classes/general/
Upload File :
Create Path :
Current File : /home/bitrix/www/bitrix/modules/pull/classes/general/pull_channel.php

<?
use Bitrix\Main\Security\Sign;
IncludeModuleLangFile(__FILE__);

class CPullChannel
{
	const TYPE_PRIVATE = 'private';
	const TYPE_SHARED = 'shared';

	public static function GetNewChannelId()
	{
		global $APPLICATION;
		return md5(uniqid().$_SERVER["REMOTE_ADDR"].$_SERVER["SERVER_NAME"].(is_object($APPLICATION)? $APPLICATION->GetServerUniqID(): ''));
	}

	public static function GetChannelShared($channelType = self::TYPE_SHARED, $cache = true, $reOpen = false)
	{
		return self::GetShared($cache, $reOpen, $channelType);
	}

	public static function GetShared($cache = true, $reOpen = false, $channelType = self::TYPE_SHARED)
	{
		return self::Get(0, $cache, $reOpen, $channelType);
	}

	public static function GetChannel($userId, $channelType = self::TYPE_PRIVATE, $cache = true, $reOpen = false)
	{
		return self::Get($userId, $cache, $reOpen, $channelType);
	}

	public static function Get($userId, $cache = true, $reOpen = false, $channelType = self::TYPE_PRIVATE)
	{
		global $DB, $CACHE_MANAGER;

		$nginxStatus = CPullOptions::GetQueueServerStatus();

		$arResult = false;
		$userId = intval($userId);
		$cache_id="b_pchc_".$userId.'_'.$channelType;

		if ($nginxStatus && $cache)
		{
			$res = $CACHE_MANAGER->Read(43200, $cache_id, "b_pull_channel");
			if ($res)
				$arResult = $CACHE_MANAGER->Get($cache_id);
		}
		if(!is_array($arResult) || !isset($arResult['CHANNEL_ID']))
		{
			$arResult = Array();
			CTimeZone::Disable();
			$strSql = "
					SELECT C.CHANNEL_ID, C.CHANNEL_TYPE, ".$DB->DatetimeToTimestampFunction('C.DATE_CREATE')." DATE_CREATE, C.LAST_ID
					FROM b_pull_channel C
					WHERE C.USER_ID = ".$userId." AND C.CHANNEL_TYPE = '".$DB->ForSQL($channelType)."'
			";
			CTimeZone::Enable();
			$res = $DB->Query($strSql);
			if ($arResult = $res->Fetch())
			{
				if ($nginxStatus)
				{
					self::SaveToCache($cache_id, $arResult);
				}
			}
		}
		if (empty($arResult) || intval($arResult['DATE_CREATE'])+43200 < time())
		{
			$arChannel = Array(
				'CHANNEL_ID' => self::GetNewChannelId(),
				'CHANNEL_TYPE' => $channelType,
				'DATE_CREATE' => time(),
				'LAST_ID' => 0,
			);
			self::SaveToCache($cache_id, $arChannel);

			if (isset($arResult['CHANNEL_ID']))
			{
				$strSql = "DELETE FROM b_pull_channel WHERE CHANNEL_ID = '".$DB->ForSQL($arResult['CHANNEL_ID'])."'";
				$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
			}

			$channelId = self::Add($userId, $arChannel['CHANNEL_ID'], $arChannel['CHANNEL_TYPE']);

			if (isset($arResult['CHANNEL_ID']) && $channelId != $arResult['CHANNEL_ID'])
			{
				$params = Array(
					'action' => $channelType != self::TYPE_PRIVATE? 'reconnect': 'get_config',
					'channel' => Array(
						'id' => self::SignChannel($arResult['CHANNEL_ID']),
						'type' => $channelType,
					),
				);
				if ($channelType != self::TYPE_PRIVATE)
				{
					$params['new_channel'] = Array(
						'id' => self::SignChannel($channelId),
						'start' => date('c', time()),
						'end' => date('c', time()+43205),
						'type' => $channelType,
					);
				}
				$arMessage = Array(
					'module_id' => 'pull',
					'command' => 'channel_expire',
					'params' => $params
				);
				CPullStack::AddByChannel($arResult['CHANNEL_ID'], $arMessage);
			}

			return $channelId? Array(
				'CHANNEL_ID' => $channelId,
				'CHANNEL_TYPE' => $channelType,
				'CHANNEL_DT' => time(),
				'LAST_ID' => 0,
			): false;
		}
		else
		{
			if ($nginxStatus && $reOpen && CPullOptions::GetQueueServerVersion() < 3)
			{
				self::Send($arResult['CHANNEL_ID'], \Bitrix\Pull\Common::jsonEncode(Array(
					'module_id' => 'pull',
					'command' => 'reopen',
					'expiry' => 1,
					'params' => Array(),
					'extra' => Array(
						'server_time' => date('c'),
						'server_name' => COption::GetOptionString('main', 'server_name', $_SERVER['SERVER_NAME']),
						'revision_web' => PULL_REVISION_WEB,
						'revision_mobile' => PULL_REVISION_MOBILE,
					),
				)));
			}
			return Array(
				'CHANNEL_ID' => $arResult['CHANNEL_ID'],
				'CHANNEL_TYPE' => $arResult['CHANNEL_TYPE'],
				'CHANNEL_DT' => $arResult['DATE_CREATE'],
				'LAST_ID' => $arResult['LAST_ID'],
			);
		}
	}

	public static function SignChannel($channelId)
	{
		$signatureKey = \CPullOptions::GetSignatureKey();
		if ($signatureKey === "" || !is_string($channelId))
		{
			return $channelId;
		}

		$signatureAlgo = \CPullOptions::GetSignatureAlgorithm();
		$hmac = new Sign\HmacAlgorithm();
		$hmac->setHashAlgorithm($signatureAlgo);
		$signer = new Sign\Signer($hmac);
		$signer->setKey($signatureKey);

		return $signer->sign($channelId);
	}

	// create a channel for the user
	public static function Add($userId, $channelId = null, $channelType = self::TYPE_PRIVATE)
	{
		global $DB;

		$userId = intval($userId);
		$cache_id="b_pchc_".$userId."_".$channelType;

		if ($userId)
		{
			$user = \Bitrix\Main\UserTable::getById($userId)->fetch();
			if ($user['ACTIVE'] == 'N')
			{
				return false;
			}
		}

		$channelId = is_null($channelId)? self::GetNewChannelId(): $channelId;
		$arParams = Array(
			'USER_ID' => intval($userId),
			'CHANNEL_ID' => $channelId,
			'CHANNEL_TYPE' => $channelType,
			'LAST_ID' => 0,
			'~DATE_CREATE' => $DB->CurrentTimeFunction(),
		);
		$result = intval($DB->Add("b_pull_channel", $arParams, Array(), "", true));
		if ($result > 0)
		{
			$arChannel = Array(
				'CHANNEL_ID' => $channelId,
				'CHANNEL_TYPE' => $channelType,
				'DATE_CREATE' => time(),
				'LAST_ID' => 0,
			);
			self::SaveToCache($cache_id, $arChannel);

			if (CPullOptions::GetQueueServerStatus() && CPullOptions::GetQueueServerVersion() < 3)
			{
				self::Send($channelId, \Bitrix\Pull\Common::jsonEncode(Array(
					'module_id' => 'pull',
					'command' => 'open',
					'expiry' => 1,
					'params' => Array(),
					'extra' => Array(
						'server_time' => date('c'),
						'server_time_unix' => microtime(true),
						'server_name' => COption::GetOptionString('main', 'server_name', $_SERVER['SERVER_NAME']),
						'revision_web' => PULL_REVISION_WEB,
						'revision_mobile' => PULL_REVISION_MOBILE,
					),
				)));
			}
		}
		else
		{
			CTimeZone::Disable();
			$strSql = "
					SELECT CHANNEL_ID, ".$DB->DatetimeToTimestampFunction('DATE_CREATE')." DATE_CREATE, LAST_ID
					FROM b_pull_channel
					WHERE USER_ID = ".$userId." AND CHANNEL_TYPE = '".$DB->ForSQL($channelType)."'
			";
			CTimeZone::Enable();
			$res = $DB->Query($strSql);
			$arChannel = $res->Fetch();
			$channelId = $arChannel['CHANNEL_ID'];
			self::SaveToCache($cache_id, $arChannel);

			if (CPullOptions::GetQueueServerStatus() && CPullOptions::GetQueueServerVersion() < 3)
			{
				self::Send($channelId, \Bitrix\Pull\Common::jsonEncode(Array(
					'module_id' => 'pull',
					'command' => 'open_exists',
					'expiry' => 1,
					'params' => Array(),
					'extra' => Array(
						'server_time' => date('c'),
						'server_time_unix' => microtime(true),
						'server_name' => COption::GetOptionString('main', 'server_name', $_SERVER['SERVER_NAME']),
						'revision_web' => PULL_REVISION_WEB,
						'revision_mobile' => PULL_REVISION_MOBILE,
					),
				)));
			}
		}

		return $channelId;
	}

	// remove channel by identifier
	// before removing need to send a message to change channel
	public static function Delete($channelId)
	{
		global $DB, $CACHE_MANAGER;

		$strSql = "SELECT ID, USER_ID, CHANNEL_TYPE FROM b_pull_channel WHERE CHANNEL_ID = '".$DB->ForSQL($channelId)."'";
		$res = $DB->Query($strSql);
		if ($arRes = $res->Fetch())
		{
			$strSql = "DELETE FROM b_pull_channel WHERE USER_ID = ".$arRes['USER_ID']." AND CHANNEL_TYPE = '".$DB->ForSql($arRes['CHANNEL_TYPE'])."'";
			$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);

			$CACHE_MANAGER->Clean("b_pchc_".$arRes['USER_ID']."_".$arRes['CHANNEL_TYPE'], "b_pull_channel");

			$channelType = $arRes['CHANNEL_TYPE'];

			$params = Array(
				'action' => $channelType != self::TYPE_PRIVATE? 'reconnect': 'get_config',
				'channel' => Array(
					'id' => self::SignChannel($channelId),
					'type' => $channelType,
				),
			);
			if ($channelType != self::TYPE_PRIVATE)
			{
				$result = self::GetShared(false);
				$params['new_channel'] = Array(
					'id' => self::SignChannel($result['CHANNEL_ID']),
					'start' => $result['CHANNEL_DT'],
					'end' => date('c', $result['CHANNEL_DT']+43205),
					'type' => $channelType,
				);
			}
			$arMessage = Array(
				'module_id' => 'pull',
				'command' => 'channel_expire',
				'params' => $params
			);
			CPullStack::AddByChannel($channelId, $arMessage);
		}

		return true;
	}

	public static function DeleteByUser($userId, $channelId = null, $channelType = self::TYPE_PRIVATE)
	{
		global $DB, $CACHE_MANAGER;

		$userId = intval($userId);
		if ($userId == 0 && $channelType == self::TYPE_PRIVATE)
		{
			$channelType = self::TYPE_SHARED;
		}

		if (is_null($channelId))
		{
			$strSql = "SELECT CHANNEL_ID, CHANNEL_TYPE FROM b_pull_channel WHERE USER_ID = ".$userId." AND CHANNEL_TYPE = '".$DB->ForSQL($channelType)."'";
			$res = $DB->Query($strSql);
			if ($arRes = $res->Fetch())
			{
				$channelId = $arRes['CHANNEL_ID'];
				$channelType = $arRes['CHANNEL_TYPE'];
			}
		}

		if (strlen($channelType) <= 0)
			$channelTypeSql = "(CHANNEL_TYPE = '' OR CHANNEL_TYPE IS NULL)";
		else
			$channelTypeSql = "CHANNEL_TYPE = '".$DB->ForSQL($channelType)."'";

		$strSql = "DELETE FROM b_pull_channel WHERE USER_ID = ".$userId." AND ".$channelTypeSql;
		$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);

		$CACHE_MANAGER->Clean("b_pchc_".$userId."_".$channelType, "b_pull_channel");

		$params = Array(
			'action' => $channelType != self::TYPE_PRIVATE? 'reconnect': 'get_config',
			'channel' => Array(
				'id' => self::SignChannel($channelId),
				'type' => $channelType,
			),
		);
		if ($channelType != self::TYPE_PRIVATE)
		{
			$result = self::GetShared(false);
			$params['new_channel'] = Array(
				'id' => self::SignChannel($result['CHANNEL_ID']),
				'start' => $result['CHANNEL_DT'],
				'end' => date('c', $result['CHANNEL_DT']+43205),
				'type' => $channelType,
			);
		}
		$arMessage = Array(
			'module_id' => 'pull',
			'command' => 'channel_expire',
			'params' => $params
		);

		CPullStack::AddByChannel($channelId, $arMessage);

		return true;
	}

	public static function Send($channelId, $message, $options = array())
	{
		$result_start = '{"infos": ['; $result_end = ']}';
		if (is_array($channelId) && CPullOptions::GetQueueServerVersion() == 1)
		{
			$results = Array();
			foreach ($channelId as $channel)
			{
				$results[] = self::SendCommand($channel, $message, $options);
			}
			$result = json_decode($result_start.implode(',', $results).$result_end);
		}
		else if (is_array($channelId))
		{
			$commandPerHit = CPullOptions::GetCommandPerHit();
			if (count($channelId) > $commandPerHit)
			{
				$arGroup = Array();
				$i = 0;
				foreach($channelId as $channel)
				{
					if (count($arGroup[$i]) == $commandPerHit)
						$i++;

					$arGroup[$i][] = $channel;
				}
				$results = Array();
				foreach($arGroup as $channels)
				{
					$result = self::SendCommand($channels, $message, $options);
					$subresult = json_decode($result);
					if (is_array($subresult->infos))
					{
						$results = array_merge($results, $subresult->infos);
					}
				}
				$result = json_decode('{"infos":'.json_encode($results).'}');
			}
			else
			{
				$result = self::SendCommand($channelId, $message, $options);
				$result = json_decode($result);
			}
		}
		else
		{
			$result = self::SendCommand($channelId, $message, $options);
			$result = json_decode($result_start.$result.$result_end);
		}

		return $result;
	}

	private static function SendCommand($channelId, $message, $options = array())
	{
		if (!is_array($channelId))
			$channelId = Array($channelId);

		$channelId = implode('/', array_unique($channelId));

		if (strlen($channelId) <=0 || strlen($message) <= 0)
			return false;

		$defaultOptions = array(
			"method" => "POST",
			"timeout" => 5,
			"dont_wait_answer" => true
		);

		$options = array_merge($defaultOptions, $options);

		if (!in_array($options["method"], Array('POST', 'GET')))
			return false;

		$nginx_error = COption::GetOptionString("pull", "nginx_error", "N");
		if ($nginx_error != "N")
		{
			$nginx_error = unserialize($nginx_error);
			if (intval($nginx_error['date'])+120 < time())
			{
				COption::SetOptionString("pull", "nginx_error", "N");
				CAdminNotify::DeleteByTag("PULL_ERROR_SEND");
				$nginx_error = "N";
			}
			else if ($nginx_error['count'] >= 10)
			{
				$ar = Array(
					"MESSAGE" => GetMessage('PULL_ERROR_SEND'),
					"TAG" => "PULL_ERROR_SEND",
					"MODULE_ID" => "pull",
				);
				CAdminNotify::Add($ar);
				return false;
			}
		}

		$postdata = CHTTP::PrepareData($message);

		$CHTTP = new CHTTP();
		$CHTTP->http_timeout = intval($options["timeout"]);
		if (isset($options["expiry"]))
		{
			$CHTTP->SetAdditionalHeaders(array("Message-Expiry" => intval($options["expiry"])));
		}

		$arUrl = $CHTTP->ParseURL(CPullOptions::GetPublishUrl($channelId), false);
		try
		{
			$sendResult = $CHTTP->Query($options["method"], $arUrl['host'], $arUrl['port'], $arUrl['path_query'], $postdata, $arUrl['proto'], 'N', $options["dont_wait_answer"]);
		}
		catch(Exception $e)
		{
			$sendResult = false;
		}

		if ($sendResult)
		{
			$result = $options["dont_wait_answer"] ? '{}': $CHTTP->result;
		}
		else
		{
			if ($nginx_error == "N")
			{
				$nginx_error = Array(
					'count' => 1,
					'date' => time(),
					'date_increment' => time(),
				);
			}
			else if (intval($nginx_error['date_increment'])+1 < time())
			{
				$nginx_error['count'] = intval($nginx_error['count'])+1;
				$nginx_error['date_increment'] = time();
			}
			COption::SetOptionString("pull", "nginx_error", serialize($nginx_error));
			$result = false;
		}

		return $result;
	}

	public static function SaveToCache($cacheId, $data)
	{
		global $CACHE_MANAGER;

		$CACHE_MANAGER->Clean($cacheId, "b_pull_channel");
		$CACHE_MANAGER->Read(43200, $cacheId, "b_pull_channel");
		$CACHE_MANAGER->SetImmediate($cacheId, $data);
	}

	public static function UpdateLastId($channelId, $lastId)
	{
		global $DB;

		$strSql = "UPDATE b_pull_channel SET LAST_ID = ".intval($lastId)." WHERE CHANNEL_ID = '".$DB->ForSQL($channelId)."'";
		$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);

		return true;
	}

	// check channels that are older than 12 hours, remove them.
	public static function CheckExpireAgent()
	{
		global $DB;
		$sqlDateFunction = null;
		$dbType = strtolower($DB->type);
		if ($dbType== "mysql")
			$sqlDateFunction = "DATE_SUB(NOW(), INTERVAL 13 HOUR)";
		else if ($dbType == "mssql")
			$sqlDateFunction = "dateadd(HOUR, -13, getdate())";
		else if ($dbType == "oracle")
			$sqlDateFunction = "SYSDATE-1/13";

		if (!is_null($sqlDateFunction))
		{
			$strSql = "
					SELECT USER_ID, CHANNEL_ID, CHANNEL_TYPE
					FROM b_pull_channel
					WHERE DATE_CREATE < ".$sqlDateFunction;
			$dbRes = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
			while ($arRes = $dbRes->Fetch())
			{
				self::DeleteByUser($arRes['USER_ID'], $arRes['CHANNEL_ID'], $arRes['CHANNEL_TYPE']);
			}
		}

		return "CPullChannel::CheckExpireAgent();";
	}

	public static function CheckOnlineChannel()
	{
		if (!CPullOptions::GetQueueServerStatus())
			return "CPullChannel::CheckOnlineChannel();";

		$users = Array();
		$channels = Array();

		$isImInstalled = CModule::IncludeModule('im');
		if ($isImInstalled)
		{
			$orm = \Bitrix\Main\UserTable::getList(array(
				'select' => Array(
					'USER_ID' => 'ID',
					'CHANNEL_ID' =>	'CHANNEL.CHANNEL_ID',
					'STATUS' =>	'ST.STATUS',
					'COLOR' =>	'ST.COLOR',
					'IDLE' => 'ST.IDLE',
					'MOBILE_LAST_DATE' => 'ST.MOBILE_LAST_DATE',
				 ),
				'runtime' => Array(
					new \Bitrix\Main\Entity\ReferenceField(
						'CHANNEL',
						'\Bitrix\Pull\Model\ChannelTable',
						array(
							"=ref.USER_ID" => "this.ID",
							"=ref.CHANNEL_TYPE" => new \Bitrix\Main\DB\SqlExpression('?s', 'private'),
						),
						array("join_type"=>"LEFT")
					),
					new \Bitrix\Main\Entity\ReferenceField(
						'ST',
						'\Bitrix\Im\Model\StatusTable',
						array("=ref.USER_ID" => "this.ID"),
						array("join_type"=>"LEFT")
					),
				),
				'filter' => Array(
					'=IS_ONLINE' => 'Y',
					'=IS_REAL_USER' => 'Y'
				)
			));
		}
		else
		{
			$orm = \Bitrix\Main\UserTable::getList(array(
				'select' => Array(
					'USER_ID' => 'ID',
					'CHANNEL_ID' =>	'CHANNEL.CHANNEL_ID'
				 ),
				'runtime' => Array(
					new \Bitrix\Main\Entity\ReferenceField(
						'CHANNEL',
						'\Bitrix\Pull\Model\ChannelTable',
						array(
							"=ref.USER_ID" => "this.ID",
							"=ref.CHANNEL_TYPE" => new \Bitrix\Main\DB\SqlExpression('?s', 'private'),
						),
						array("join_type"=>"LEFT")
					)
				),
				'filter' => Array(
					'=IS_ONLINE' => 'Y',
					'=IS_REAL_USER' => 'Y'
				)
			));
		}

		while ($res = $orm->fetch())
		{
			$channels[$res['CHANNEL_ID']] = $res['USER_ID'];
			$users[$res['USER_ID']] = $res;
		}

		if (count($users) > 0)
		{
			$arOnline = Array();

			global $USER;
			$agentUserId = 0;
			if (is_object($USER) && $USER->GetId() > 0)
			{
				$agentUserId = $USER->GetId();
				$arOnline[$agentUserId] = $agentUserId;
			}

			$options = array(
				"method" => "GET",
				"dont_wait_answer" => false
			);
			$result = self::Send(array_keys($channels), 'ping', $options);
			if (is_object($result) && isset($result->infos))
			{
				foreach ($result->infos as $info)
				{
					$userId = $channels[$info->channel];
					if ($userId == 0 || $agentUserId == $userId)
						continue;

					if ($info->subscribers > 0)
						$arOnline[$userId] = $userId;
				}
			}

			if (count($arOnline) > 0)
			{
				ksort($arOnline);
				CUser::SetLastActivityDateByArray($arOnline);
			}

			$arSend = Array();
			if ($isImInstalled)
			{
				foreach ($arOnline as $userId)
				{
					$arSend[$userId] = Array(
						'id' => $userId,
						'status' => $users[$userId]['STATUS'],
						'color' => $users[$userId]['COLOR']? \Bitrix\Im\Color::getColor($users[$userId]['COLOR']): \Bitrix\Im\Color::getColorByNumber($userId),
						'idle' => $users[$userId]['IDLE'] instanceof \Bitrix\Main\Type\DateTime? $users[$userId]['IDLE']: false,
						'mobile_last_date' => $users[$userId]['MOBILE_LAST_DATE'] instanceof \Bitrix\Main\Type\DateTime? $users[$userId]['MOBILE_LAST_DATE']: false,
						'last_activity_date' => new \Bitrix\Main\Type\DateTime(),
					);
				}
			}
			else
			{
				foreach ($arOnline as $userId)
				{
					$arSend[$userId] = Array(
						'id' => $userId,
						'status' => 'online',
						'color' => '#556574',
						'idle' => false,
						'mobile_last_date' => false,
						'last_activity_date' => new \Bitrix\Main\Type\DateTime(),
					);
				}
			}

			CPullStack::AddShared(Array(
				'module_id' => 'online',
				'command' => 'list',
				'expiry' => 240,
				'params' => Array(
					'users' => $arSend
				),
			));
		}

		return "CPullChannel::CheckOnlineChannel();";
	}

	public static function GetConfig($userId, $cache = true, $reopen = false, $mobile = false)
	{
		$pullConfig = Array();

		if (defined('BX_PULL_SKIP_LS'))
			$pullConfig['LOCAL_STORAGE'] = 'N';

		if (IsModuleInstalled('bitrix24'))
			$pullConfig['BITRIX24'] = 'Y';

		if (!CPullOptions::GetQueueServerHeaders())
			$pullConfig['HEADERS'] = 'N';

		$arChannel = CPullChannel::Get($userId, $cache, $reopen);
		if (!is_array($arChannel))
		{
			return false;
		}

		$arChannel["CHANNEL_ID"] = self::SignChannel($arChannel["CHANNEL_ID"]);
		$nginxStatus = CPullOptions::GetQueueServerStatus();
		$webSocketStatus = false;

		$arChannels = Array($arChannel['CHANNEL_ID']);
		if ($nginxStatus)
		{
			if (defined('BX_PULL_SKIP_WEBSOCKET'))
			{
				$pullConfig['WEBSOCKET'] = 'N';
			}
			else
			{
				$webSocketStatus = CPullOptions::GetWebSocketStatus();
			}

			if ($userId > 0)
			{
				$arChannelShared = CPullChannel::GetShared($cache, $reopen);
				if (is_array($arChannelShared))
				{
					$arChannelShared["CHANNEL_ID"] = self::SignChannel($arChannelShared["CHANNEL_ID"]);
					$arChannels[] = $arChannelShared['CHANNEL_ID'];
					$arChannel['CHANNEL_DT'] = $arChannel['CHANNEL_DT'].'/'.$arChannelShared['CHANNEL_DT'];
				}
			}
		}

		$pullPath = ($nginxStatus? (CMain::IsHTTPS()? CPullOptions::GetListenSecureUrl($arChannels): CPullOptions::GetListenUrl($arChannels)): '/bitrix/components/bitrix/pull.request/ajax.php?UPDATE_STATE');
		$pullPathWs = ($nginxStatus && $webSocketStatus? (CMain::IsHTTPS()? CPullOptions::GetWebSocketSecureUrl($arChannels): CPullOptions::GetWebSocketUrl($arChannels)): '');

		return $pullConfig+Array(
			'CHANNEL_ID' => implode('/', $arChannels),
			'CHANNEL_DT' => $arChannel['CHANNEL_DT'],
			'USER_ID' => $userId,
			'LAST_ID' => $arChannel['LAST_ID'],
			'PATH' => $pullPath,
			'PATH_WS' => $pullPathWs,
			'PATH_COMMAND' => defined('BX_PULL_COMMAND_PATH')? BX_PULL_COMMAND_PATH: '',
			'METHOD' => ($nginxStatus? 'LONG': 'PULL'),
			'REVISION' => PULL_REVISION_WEB,
			'ERROR' => '',
		);
	}
}
?>

Zerion Mini Shell 1.0