Your IP : 18.119.109.229


Current Path : /home/bitrix/ext_www/dev.ballu.in.ua/bitrix/modules/security/lib/
Upload File :
Current File : /home/bitrix/ext_www/dev.ballu.in.ua/bitrix/modules/security/lib/session.php

<?php
namespace Bitrix\Security;


use Bitrix\Main\DB;
use Bitrix\Main\Entity;
use Bitrix\Main\Type;

/*
CREATE TABLE b_sec_session
(
	SESSION_ID VARCHAR(250) NOT NULL,
	TIMESTAMP_X TIMESTAMP NOT NULL,
	SESSION_DATA LONGTEXT,
	PRIMARY KEY(SESSION_ID)
);
 */

/**
 * Class SessionTable
 * @since 16.0.0
 */
class SessionTable
	extends Entity\DataManager
{
	/** @var string Connection name used for SQL queries */
	const CONNECTION_NAME = 'user_session';

	/**
	 * {@inheritdoc}
	 *
	 * @return string
	 */
	public static function getTableName()
	{
		return 'b_sec_session';
	}

	/**
	 * Returns connection name for entity
	 * Have side affect, keep it in mind!
	 * Clone default database connection if connection {@link SessionTable::CONNECTION_NAME} doesn't exists
	 *
	 * @return string
	 */
	public static function getConnectionName()
	{
		$pool = \Bitrix\Main\Application::getInstance()->getConnectionPool();
		$isConnectionExists = $pool->getConnection(static::CONNECTION_NAME) !== null;
		if (!$isConnectionExists)
		{
			$pool->cloneConnection(
				$pool::DEFAULT_CONNECTION_NAME,
				static::CONNECTION_NAME
			);
		}
		return static::CONNECTION_NAME;
	}

	/**
	 * {@inheritdoc}
	 *
	 * @return array
	 */
	public static function getMap()
	{
		return array(
			new Entity\StringField('SESSION_ID', array(
				'primary' => true,
				'format' => '#^[0-9a-z\-,]{6,250}$#iD'
			)),
			new Entity\DatetimeField('TIMESTAMP_X', array(
				'default_value' => new Type\DateTime
			)),
			new Entity\TextField('SESSION_DATA', array(
				'default_value' => '',
				'save_data_modification' => function()
				{
					return array(function($data)
					{
						return base64_encode($data);
					});
				},
				'fetch_data_modification' => function()
				{
					return array(function($data)
					{
						return base64_decode($data);
					});
				},
			))
		);
	}

	/**
	 * Locks specified session id
	 * Supports Mysql, MSSQL and Oracle so far.
	 *
	 * @param string $id Session id.
	 * @param int $timeout Lock timeout.
	 * @return bool Returns true if lock occurred.
	 */
	public static function lock($id, $timeout = 60)
	{
		$result = true;
		$connection = static::getEntity()->getConnection();
		if ($connection instanceof \Bitrix\Main\DB\MysqlCommonConnection)
		{
			$lock = $connection->queryScalar(
				sprintf('SELECT GET_LOCK("%s", %d)', md5($id), (int) $timeout)
			);
			$result = $lock != '0';
		}
		elseif ($connection instanceof \Bitrix\Main\DB\MssqlConnection)
		{
			$id = $connection->getSqlHelper()->forSql($id);
			$timeout = (int) $timeout;
			$connection->startTransaction();
			try
			{
				$connection->queryExecute(sprintf('SET LOCK_TIMEOUT %d', $timeout * 1000));
				$queryResult = static::update($id, array(
					'TIMESTAMP_X' => new Type\DateTime
				));
				if ($queryResult->isSuccess())
				{
					if ($queryResult->getAffectedRowsCount())
					{
						$result = true;
					}
					else
					{
						$queryResult = static::add(array(
							'SESSION_ID' => $id
						));
						$result = $queryResult->isSuccess();
					}
				}
				else
				{
					$result = false;
				}
			}
			catch (\Bitrix\Main\DB\SqlQueryException $e)
			{
				$result = false;
			}
		}
		elseif ($connection instanceof \Bitrix\Main\DB\OracleConnection)
		{
			$id = $connection->getSqlHelper()->forSql($id);
			$timeout = (int) $timeout;
			$connection->startTransaction();
			$result = null;
			while ($result === null)
			{
				try
				{
					$lock = $connection->query("
						select *
						from b_sec_session
							where SESSION_ID = '${id}'
						for update wait ${timeout}
					");

					if ($lock->fetch())
					{
						$result = true;
					}
					else
					{
						static::add(array(
							'SESSION_ID' => $id
						));
					}
				}
				catch (\Bitrix\Main\DB\SqlQueryException $e)
				{
					$result = false;
				}
			}
		}
		else
		{
			trigger_error(sprintf('SessionTable::lock not supported for connection of type "%s"', get_class($connection)), E_USER_WARNING);
		}

		return $result;
	}

	/**
	 * Unlock specified session id
	 * Supports Mysql, MSSQL and Oracle so far.
	 *
	 * @param string $id Session id.
	 * @return bool Returns true if lock released.
	 */
	public static function unlock($id)
	{
		$connection = static::getEntity()->getConnection();
		if ($connection instanceof \Bitrix\Main\DB\MysqlCommonConnection)
		{
			$connection->queryExecute(
				sprintf('DO RELEASE_LOCK("%s")', md5($id))
			);
		}
		elseif ($connection instanceof \Bitrix\Main\DB\MssqlConnection)
		{
			$connection->queryExecute("SET LOCK_TIMEOUT -1");
			$connection->commitTransaction();
		}
		elseif ($connection instanceof \Bitrix\Main\DB\OracleConnection)
		{
			$connection->commitTransaction();
		}
		else
		{
			trigger_error(sprintf('SessionTable::unlock not supported for connection of type "%s"', get_class($connection)), E_USER_WARNING);
		}

		return true;
	}

	/**
	 * Deletes old sessions
	 *
	 * @param int $sec Seconds.
	 * @return void
	 */
	public static function deleteOlderThan($sec)
	{
		$connection = static::getEntity()->getConnection();
		$connection->queryExecute(
			sprintf('delete from b_sec_session where TIMESTAMP_X < %s',
				$connection->getSqlHelper()->addSecondsToDateTime('-'.$sec))
		);
	}
}