%PDF- %PDF-
| Direktori : /home/bitrix/www/bitrix/modules/main/classes/general/ |
| Current File : //home/bitrix/www/bitrix/modules/main/classes/general/user.php |
<?php
/**
* Bitrix Framework
* @package bitrix
* @subpackage main
* @copyright 2001-2013 Bitrix
*/
use Bitrix\Main;
use Bitrix\Main\Authentication\ApplicationPasswordTable;
IncludeModuleLangFile(__FILE__);
global $BX_GROUP_POLICY;
$BX_GROUP_POLICY = array(
"SESSION_TIMEOUT" => 0, //minutes
"SESSION_IP_MASK" => "0.0.0.0",
"MAX_STORE_NUM" => 10,
"STORE_IP_MASK" => "0.0.0.0",
"STORE_TIMEOUT" => 60*24*365, //minutes
"CHECKWORD_TIMEOUT" => 60*24*365, //minutes
"PASSWORD_LENGTH" => false,
"PASSWORD_UPPERCASE" => "N",
"PASSWORD_LOWERCASE" => "N",
"PASSWORD_DIGITS" => "N",
"PASSWORD_PUNCTUATION" => "N",
"LOGIN_ATTEMPTS" => 0,
);
abstract class CAllUser extends CDBResult
{
var $LAST_ERROR = "";
var $bLoginByHash = false;
protected $admin = null;
protected static $CURRENT_USER = false;
protected $justAuthorized = false;
protected static $userGroupCache = array();
const STATUS_ONLINE = 'online';
const STATUS_OFFLINE = 'offline';
abstract public function Add($arFields);
public function GetParam($name)
{
if(isset($_SESSION["SESS_AUTH"][$name]))
return $_SESSION["SESS_AUTH"][$name];
else
return null;
}
public function GetSecurityPolicy()
{
if(!is_set($_SESSION["SESS_AUTH"], "POLICY"))
$_SESSION["SESS_AUTH"]["POLICY"] = CUser::GetGroupPolicy($_SESSION["SESS_AUTH"]["USER_ID"]);
return $_SESSION["SESS_AUTH"]["POLICY"];
}
public function SetParam($name, $value)
{
$_SESSION["SESS_AUTH"][$name] = $value;
}
public function GetID()
{
if(isset($_SESSION["SESS_AUTH"]["USER_ID"]))
return $_SESSION["SESS_AUTH"]["USER_ID"];
else
return null;
}
public function GetLogin()
{
return $_SESSION["SESS_AUTH"]["LOGIN"];
}
public function GetEmail()
{
return $_SESSION["SESS_AUTH"]["EMAIL"];
}
public function GetFullName()
{
return $_SESSION["SESS_AUTH"]["NAME"];
}
public function GetFirstName()
{
return $_SESSION["SESS_AUTH"]["FIRST_NAME"];
}
public function GetLastName()
{
return $_SESSION["SESS_AUTH"]["LAST_NAME"];
}
public function GetSecondName()
{
return $_SESSION["SESS_AUTH"]["SECOND_NAME"];
}
public function GetFormattedName($bUseBreaks = true, $bHTMLSpec = true)
{
return CUser::FormatName(CSite::GetNameFormat($bUseBreaks),
array(
"TITLE" => $this->GetParam("TITLE"),
"NAME" => $this->GetFirstName(),
"SECOND_NAME" => $this->GetSecondName(),
"LAST_NAME" => $this->GetLastName(),
"LOGIN" => $this->GetLogin(),
),
true,
$bHTMLSpec
);
}
public function GetUserGroupArray()
{
if(
!isset($_SESSION["SESS_AUTH"]["GROUPS"])
|| !is_array($_SESSION["SESS_AUTH"]["GROUPS"])
|| empty($_SESSION["SESS_AUTH"]["GROUPS"])
)
return array(2);
//always unique and sorted, containing group ID=2
return $_SESSION["SESS_AUTH"]["GROUPS"];
}
public function SetUserGroupArray($arr)
{
$arr = array_map("intval", $arr);
$arr = array_filter($arr);
$arr[] = 2;
$arr = array_values(array_unique($arr));
sort($arr);
$_SESSION["SESS_AUTH"]["GROUPS"] = $arr;
}
public function GetUserGroupString()
{
return $this->GetGroups();
}
public function GetGroups()
{
return implode(",", $this->GetUserGroupArray());
}
public function RequiredHTTPAuthBasic($Realm = "Bitrix")
{
header("WWW-Authenticate: Basic realm=\"{$Realm}\"");
if(stristr(php_sapi_name(), "cgi") !== false)
header("Status: 401 Unauthorized");
else
header($_SERVER["SERVER_PROTOCOL"]." 401 Unauthorized");
return false;
}
public function LoginByCookies()
{
global $USER;
if(COption::GetOptionString("main", "store_password", "Y") == "Y")
{
$bLogout = isset($_REQUEST["logout"]) && (strtolower($_REQUEST["logout"]) == "yes");
$cookie_prefix = COption::GetOptionString('main', 'cookie_name', 'BITRIX_SM');
$cookie_login = strval($_COOKIE[$cookie_prefix.'_UIDL']);
if($cookie_login == '')
{
//compatibility reasons
$cookie_login = strval($_COOKIE[$cookie_prefix.'_LOGIN']);
}
$cookie_md5pass = strval($_COOKIE[$cookie_prefix.'_UIDH']);
if($cookie_login <> '' && $cookie_md5pass <> '' && !$bLogout)
{
if($_SESSION["SESS_PWD_HASH_TESTED"] != md5($cookie_login."|".$cookie_md5pass))
{
$USER->LoginByHash($cookie_login, $cookie_md5pass);
$_SESSION["SESS_PWD_HASH_TESTED"] = md5($cookie_login."|".$cookie_md5pass);
}
}
}
}
public function LoginByHash($login, $hash)
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$result_message = true;
$user_id = 0;
$arParams = array(
"LOGIN" => $login,
"HASH" => $hash,
);
$APPLICATION->ResetException();
$bOk = true;
foreach(GetModuleEvents("main", "OnBeforeUserLoginByHash", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false)
{
if($err = $APPLICATION->GetException())
$result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
else
{
$APPLICATION->ThrowException("Unknown error");
$result_message = array("MESSAGE"=>"Unknown error"."<br>", "TYPE"=>"ERROR");
}
$bOk = false;
break;
}
}
if($bOk && $arParams['HASH'] <> '')
{
$strSql =
"SELECT U.ID, U.ACTIVE, U.STORED_HASH, U.EXTERNAL_AUTH_ID ".
"FROM b_user U ".
"WHERE U.LOGIN='".$DB->ForSQL($arParams['LOGIN'], 50)."' ";
$result = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$bFound = false;
$bHashFound = false;
while(($arUser = $result->Fetch()))
{
$bFound = true;
//there is no stored auth for external authorization, but domain spread auth should work
$bExternal = ($arUser["EXTERNAL_AUTH_ID"] <> '');
if(
// if old method (STORED_HASH <> '') and exact match
($arUser["STORED_HASH"] <> '' && $arUser["STORED_HASH"] == $arParams['HASH'])
|| // or new method
(CUser::CheckStoredHash($arUser["ID"], $arParams['HASH'], $bExternal))
)
{
$bHashFound = true;
if($arUser["ACTIVE"] == "Y")
{
$user_id = $arUser["ID"];
$_SESSION["SESS_AUTH"]["SESSION_HASH"] = $arParams['HASH'];
$this->bLoginByHash = true;
$this->Authorize($arUser["ID"], !$bExternal);
}
else
{
$APPLICATION->ThrowException(GetMessage("LOGIN_BLOCK"));
$result_message = array("MESSAGE"=>GetMessage("LOGIN_BLOCK")."<br>", "TYPE"=>"ERROR");
}
break;
}
else
{
//Delete invalid stored auth cookie
$spread = (COption::GetOptionString("main", "auth_multisite", "N") == "Y"? (Main\Web\Cookie::SPREAD_SITES | Main\Web\Cookie::SPREAD_DOMAIN) : Main\Web\Cookie::SPREAD_DOMAIN);
$cookie = new Main\Web\Cookie("UIDH", "", 0);
$cookie->setSpread($spread);
$cookie->setHttpOnly(true);
Main\Context::getCurrent()->getResponse()->addCookie($cookie);
}
}
if(!$bFound)
{
$APPLICATION->ThrowException(GetMessage("WRONG_LOGIN"));
$result_message = array("MESSAGE"=>GetMessage("WRONG_LOGIN")."<br>", "TYPE"=>"ERROR");
}
elseif(!$bHashFound)
{
$APPLICATION->ThrowException(GetMessage("USER_WRONG_HASH"));
$result_message = array("MESSAGE"=>GetMessage("USER_WRONG_HASH")."<br>", "TYPE"=>"ERROR");
}
}
$arParams["USER_ID"] = $user_id;
$arParams["RESULT_MESSAGE"] = $result_message;
foreach (GetModuleEvents("main", "OnAfterUserLoginByHash", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arParams));
if(($result_message !== true) && (COption::GetOptionString("main", "event_log_login_fail", "N") === "Y"))
CEventLog::Log("SECURITY", "USER_LOGINBYHASH", "main", $login, $result_message["MESSAGE"]);
return $arParams["RESULT_MESSAGE"];
}
public function LoginByHttpAuth()
{
$arAuth = CHTTP::ParseAuthRequest();
foreach(GetModuleEvents("main", "onBeforeUserLoginByHttpAuth", true) as $arEvent)
{
$res = ExecuteModuleEventEx($arEvent, array(&$arAuth));
if($res !== null)
{
return $res;
}
}
if(isset($arAuth["basic"]) && $arAuth["basic"]["username"] <> '' && $arAuth["basic"]["password"] <> '')
{
// Authorize user, if it is http basic authorization, with no remembering
if(!$this->IsAuthorized() || $this->GetLogin() <> $arAuth["basic"]["username"])
{
return $this->Login($arAuth["basic"]["username"], $arAuth["basic"]["password"], "N");
}
}
elseif(isset($arAuth["digest"]) && $arAuth["digest"]["username"] <> '' && COption::GetOptionString('main', 'use_digest_auth', 'N') == 'Y')
{
// Authorize user by http digest authorization
if(!$this->IsAuthorized() || $this->GetLogin() <> $arAuth["digest"]["username"])
{
return $this->LoginByDigest($arAuth["digest"]);
}
}
return null;
}
public function LoginByDigest($arDigest)
{
//array("username"=>"", "nonce"=>"", "uri"=>"", "response"=>"")
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$APPLICATION->ResetException();
$strSql =
"SELECT U.ID, U.PASSWORD, UD.DIGEST_HA1, U.EXTERNAL_AUTH_ID ".
"FROM b_user U LEFT JOIN b_user_digest UD ON UD.USER_ID=U.ID ".
"WHERE U.LOGIN='".$DB->ForSQL($arDigest["username"])."' ";
$res = $DB->Query($strSql);
if($arUser = $res->Fetch())
{
$method = (isset($_SERVER['REDIRECT_REQUEST_METHOD']) ? $_SERVER['REDIRECT_REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']);
$HA2 = md5($method.':'.$arDigest['uri']);
if($arUser["EXTERNAL_AUTH_ID"] == '' && $arUser["DIGEST_HA1"] <> '')
{
//digest is for internal authentication only
$_SESSION["BX_HTTP_DIGEST_ABSENT"] = false;
$HA1 = $arUser["DIGEST_HA1"];
$valid_response = md5($HA1.':'.$arDigest['nonce'].':'.$HA2);
if($arDigest["response"] === $valid_response)
{
//regular user password
return $this->Login($arDigest["username"], $arUser["PASSWORD"], "N", "N");
}
}
//check for an application password, including external users
if(($appPassword = \Bitrix\Main\Authentication\ApplicationPasswordTable::findDigestPassword($arUser["ID"], $arDigest)) !== false)
{
return $this->Login($arDigest["username"], $appPassword["PASSWORD"], "N", "N");
}
if($arUser["DIGEST_HA1"] == '')
{
//this indicates that we still have no user digest hash
$_SESSION["BX_HTTP_DIGEST_ABSENT"] = true;
}
}
$APPLICATION->ThrowException(GetMessage("USER_AUTH_DIGEST_ERR"));
return array("MESSAGE"=>GetMessage("USER_AUTH_DIGEST_ERR")."<br>", "TYPE"=>"ERROR");
}
public static function UpdateDigest($ID, $pass)
{
global $DB;
$ID = intval($ID);
$res = $DB->Query("
SELECT U.LOGIN, UD.DIGEST_HA1
FROM b_user U LEFT JOIN b_user_digest UD on UD.USER_ID=U.ID
WHERE U.ID=".$ID
);
if($arRes = $res->Fetch())
{
if(defined('BX_HTTP_AUTH_REALM'))
$realm = BX_HTTP_AUTH_REALM;
else
$realm = "Bitrix Site Manager";
$digest = md5($arRes["LOGIN"].':'.$realm.':'.$pass);
if($arRes["DIGEST_HA1"] == '')
{
//new digest
$DB->Query("insert into b_user_digest (user_id, digest_ha1) values('".$ID."', '".$DB->ForSQL($digest)."')");
}
else
{
//update digest (login, password or realm were changed)
if($arRes["DIGEST_HA1"] !== $digest)
$DB->Query("update b_user_digest set digest_ha1='".$DB->ForSQL($digest)."' where user_id=".$ID);
}
}
}
public function LoginHitByHash()
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$hash = trim($_REQUEST["bx_hit_hash"]);
if ($hash == '')
return false;
$APPLICATION->ResetException();
$strSql =
"SELECT UH.USER_ID AS USER_ID ".
"FROM b_user_hit_auth UH ".
"INNER JOIN b_user U ON U.ID = UH.USER_ID AND U.ACTIVE ='Y' ".
"WHERE UH.HASH = '".$DB->ForSQL($hash, 32)."' ".
" AND '".$DB->ForSqlLike($APPLICATION->GetCurPageParam("", array(), true), 500)."' LIKE ".$DB->Concat("UH.URL", "'%'");
if(!defined("ADMIN_SECTION") || ADMIN_SECTION !== true)
$strSql .= " AND UH.SITE_ID = '".SITE_ID."'";
$result = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
if($arUser = $result->Fetch())
{
setSessionExpired(true);
$this->Authorize($arUser["USER_ID"], false);
$DB->Query("UPDATE b_user_hit_auth SET TIMESTAMP_X = ".$DB->GetNowFunction()." WHERE HASH='".$DB->ForSQL($hash, 32)."'");
return true;
}
else
return false;
}
public static function AddHitAuthHash($url, $user_id = false, $site_id = false)
{
global $USER, $DB;
if ($url == '')
return false;
if (!$user_id)
$user_id = $USER->GetID();
if (!$site_id && (!defined("ADMIN_SECTION") || ADMIN_SECTION !== true))
$site_id = SITE_ID;
$hash = false;
if ($user_id)
{
$hash = md5(uniqid(rand(), true));
$arFields = array(
'USER_ID' => $user_id,
'URL' => $DB->ForSqlLike(trim($url), 500),
'HASH' => $hash,
'SITE_ID' => $DB->ForSQL(trim($site_id), 2),
'~TIMESTAMP_X'=>$DB->CurrentTimeFunction()
);
$DB->Add("b_user_hit_auth", $arFields);
}
return $hash;
}
public static function GetHitAuthHash($url_mask, $userID = false)
{
global $USER, $DB;
$url_mask = trim($url_mask);
if ($url_mask == '')
return false;
if (!$userID)
{
if (!$USER->IsAuthorized())
return false;
else
$userID = $USER->GetID();
}
$strSql =
"SELECT ID, HASH ".
"FROM b_user_hit_auth ".
"WHERE URL = '".$DB->ForSqlLike($url_mask, 500)."' AND USER_ID = ".intval($userID);
$result = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
if($arTmp = $result->Fetch())
return $arTmp["HASH"];
else
return false;
}
public static function CleanUpHitAuthAgent()
{
global $DB;
$cleanup_days = COption::GetOptionInt("main", "hit_auth_cleanup_days", 30);
if($cleanup_days > 0)
{
$arDate = localtime(time());
$date = mktime(0, 0, 0, $arDate[4]+1, $arDate[3]-$cleanup_days, 1900+$arDate[5]);
$DB->Query("DELETE FROM b_user_hit_auth WHERE TIMESTAMP_X <= ".$DB->CharToDateFunction(ConvertTimeStamp($date, "FULL")));
}
return "CUser::CleanUpHitAuthAgent();";
}
protected function UpdateSessionData($id, $applicationId = null)
{
global $DB;
unset($_SESSION["SESS_OPERATIONS"]);
unset($_SESSION["MODULE_PERMISSIONS"]);
$_SESSION["BX_LOGIN_NEED_CAPTCHA"] = false;
$strSql =
"SELECT U.* ".
"FROM b_user U ".
"WHERE U.ID='".intval($id)."' ";
$result = $DB->Query($strSql);
if($arUser = $result->Fetch())
{
$_SESSION["SESS_AUTH"]["AUTHORIZED"] = "Y";
$_SESSION["SESS_AUTH"]["USER_ID"] = $arUser["ID"];
$_SESSION["SESS_AUTH"]["LOGIN"] = $arUser["LOGIN"];
$_SESSION["SESS_AUTH"]["LOGIN_COOKIES"] = $arUser["LOGIN"];
$_SESSION["SESS_AUTH"]["EMAIL"] = $arUser["EMAIL"];
$_SESSION["SESS_AUTH"]["PASSWORD_HASH"] = $arUser["PASSWORD"];
$_SESSION["SESS_AUTH"]["TITLE"] = $arUser["TITLE"];
$_SESSION["SESS_AUTH"]["NAME"] = $arUser["NAME"].($arUser["NAME"] == '' || $arUser["LAST_NAME"] == ''? "":" ").$arUser["LAST_NAME"];
$_SESSION["SESS_AUTH"]["FIRST_NAME"] = $arUser["NAME"];
$_SESSION["SESS_AUTH"]["SECOND_NAME"] = $arUser["SECOND_NAME"];
$_SESSION["SESS_AUTH"]["LAST_NAME"] = $arUser["LAST_NAME"];
$_SESSION["SESS_AUTH"]["PERSONAL_PHOTO"] = $arUser["PERSONAL_PHOTO"];
$_SESSION["SESS_AUTH"]["PERSONAL_GENDER"] = $arUser["PERSONAL_GENDER"];
$_SESSION["SESS_AUTH"]["PERSONAL_WWW"] = $arUser["PERSONAL_WWW"];
$_SESSION["SESS_AUTH"]["EXTERNAL_AUTH_ID"] = $arUser["EXTERNAL_AUTH_ID"];
$_SESSION["SESS_AUTH"]["XML_ID"] = $arUser["XML_ID"];
$_SESSION["SESS_AUTH"]["ADMIN"] = false;
$_SESSION["SESS_AUTH"]["POLICY"] = CUser::GetGroupPolicy($arUser["ID"]);
$_SESSION["SESS_AUTH"]["AUTO_TIME_ZONE"] = trim($arUser["AUTO_TIME_ZONE"]);
$_SESSION["SESS_AUTH"]["TIME_ZONE"] = $arUser["TIME_ZONE"];
$_SESSION["SESS_AUTH"]["TIME_ZONE_OFFSET"] = $arUser["TIME_ZONE_OFFSET"];
$_SESSION["SESS_AUTH"]["APPLICATION_ID"] = $applicationId;
$_SESSION["SESS_AUTH"]["BX_USER_ID"] = $arUser["BX_USER_ID"];
// groups
$_SESSION["SESS_AUTH"]["GROUPS"] = Main\UserTable::getUserGroupIds($arUser["ID"]);
foreach ($_SESSION["SESS_AUTH"]["GROUPS"] as $groupId)
{
if ($groupId == 1)
{
$_SESSION["SESS_AUTH"]["ADMIN"] = true;
break;
}
}
return $arUser;
}
return false;
}
/**
* Performs the user authorization:
* fills session parameters;
* remembers auth;
* spreads auth through sites.
* @param int $id An user ID.
* @param bool $bSave Save authorization in cookies.
* @param bool $bUpdate Update last login information in DB.
* @param string|null $applicationId An application password ID.
* @return bool
*/
public function Authorize($id, $bSave = false, $bUpdate = true, $applicationId = null)
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$arUser = $this->UpdateSessionData($id, $applicationId);
if($arUser !== false)
{
self::$CURRENT_USER = false;
$this->justAuthorized = true;
$this->SetControllerAdmin(false);
//sometimes we don't need to update db (REST)
if($bUpdate)
{
$tz = '';
if(CTimeZone::Enabled())
{
if(!CTimeZone::IsAutoTimeZone(trim($arUser["AUTO_TIME_ZONE"])) || CTimeZone::GetCookieValue() !== null)
{
$offset = CTimeZone::GetOffset();
$tz = ', TIME_ZONE_OFFSET = '.$offset;
$_SESSION["SESS_AUTH"]["TIME_ZONE_OFFSET"] = $offset;
}
}
$bxUid = '';
if (!empty($_COOKIE['BX_USER_ID']) && preg_match('/^[0-9a-f]{32}$/', $_COOKIE['BX_USER_ID']))
{
if ($_COOKIE['BX_USER_ID'] != $arUser['BX_USER_ID'])
{
// save new bxuid value
$bxUid = ", BX_USER_ID = '".$_COOKIE['BX_USER_ID']."'";
$arUser['BX_USER_ID'] = $_COOKIE['BX_USER_ID'];
$_SESSION["SESS_AUTH"]["BX_USER_ID"] = $_COOKIE['BX_USER_ID'];
}
}
$DB->Query("
UPDATE b_user SET
STORED_HASH = NULL,
LAST_LOGIN = ".$DB->GetNowFunction().",
TIMESTAMP_X = TIMESTAMP_X,
LOGIN_ATTEMPTS = 0
".$tz."
".$bxUid."
WHERE
ID=".$arUser["ID"]
);
if($applicationId === null && ($bSave || COption::GetOptionString("main", "auth_multisite", "N") == "Y"))
{
$response = Main\Context::getCurrent()->getResponse();
$hash = $this->GetSessionHash();
$secure = (COption::GetOptionString("main", "use_secure_password_cookies", "N")=="Y" && CMain::IsHTTPS());
if($bSave)
{
$period = time()+60*60*24*30*60;
$spread = Main\Web\Cookie::SPREAD_SITES | Main\Web\Cookie::SPREAD_DOMAIN;
}
else
{
$period = 0;
$spread = Main\Web\Cookie::SPREAD_SITES;
}
$cookie = new Bitrix\Main\Web\Cookie("UIDH", $hash, $period);
$cookie->setSecure($secure)
->setSpread($spread)
->setHttpOnly(true);
$response->addCookie($cookie);
$cookie = new Bitrix\Main\Web\Cookie("UIDL", $arUser["LOGIN"], $period);
$cookie->setSecure($secure)
->setSpread($spread)
->setHttpOnly(true);
$response->addCookie($cookie);
$stored_id = CUser::CheckStoredHash($arUser["ID"], $hash);
if($stored_id)
{
$DB->Query(
"UPDATE b_user_stored_auth SET
LAST_AUTH=".$DB->CurrentTimeFunction().",
".($this->bLoginByHash?"":"TEMP_HASH='".($bSave?"N":"Y")."', ")."
IP_ADDR='".sprintf("%u", ip2long($_SERVER["REMOTE_ADDR"]))."'
WHERE ID=".$stored_id
);
}
else
{
$arFields = array(
'USER_ID'=>$arUser["ID"],
'~DATE_REG'=>$DB->CurrentTimeFunction(),
'~LAST_AUTH'=>$DB->CurrentTimeFunction(),
'TEMP_HASH'=>($bSave?"N":"Y"),
'~IP_ADDR'=>sprintf("%u", ip2long($_SERVER["REMOTE_ADDR"])),
'STORED_HASH'=>$hash
);
$stored_id = $DB->Add("b_user_stored_auth", $arFields);
}
$_SESSION["SESS_AUTH"]["STORED_AUTH_ID"] = $stored_id;
}
if(COption::GetOptionString("main", "event_log_login_success", "N") === "Y")
CEventLog::Log("SECURITY", "USER_AUTHORIZE", "main", $arUser["ID"], $applicationId);
}
$this->admin = null;
$arParams = array(
"user_fields" => $arUser,
"save" => $bSave,
"update" => $bUpdate,
"applicationId" => $applicationId,
);
foreach (GetModuleEvents("main", "OnAfterUserAuthorize", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($arParams));
foreach (GetModuleEvents("main", "OnUserLogin", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($_SESSION["SESS_AUTH"]["USER_ID"], $arParams));
Main\Composite\Engine::onUserLogin();
return true;
}
return false;
}
public function GetSessionHash()
{
if($_SESSION["SESS_AUTH"]["SESSION_HASH"] == '')
{
$_SESSION["SESS_AUTH"]["SESSION_HASH"] = md5(CMain::GetServerUniqID().uniqid("", true));
}
return $_SESSION["SESS_AUTH"]["SESSION_HASH"];
}
/** @deprecated */
public function GetPasswordHash($PASSWORD_HASH)
{
$add = COption::GetOptionString("main", "pwdhashadd", "");
if($add == '')
{
$add = md5(uniqid(rand(), true));
COption::SetOptionString("main", "pwdhashadd", $add);
}
return md5($add.$PASSWORD_HASH);
}
/** @deprecated */
public function SavePasswordHash()
{
/** @global CMain $APPLICATION */
global $APPLICATION;
$hash = $this->GetSessionHash();
$time = time()+60*60*24*30*60;
$secure = (COption::GetOptionString("main", "use_secure_password_cookies", "N")=="Y" && CMain::IsHTTPS());
$spread = (COption::GetOptionString("main", "auth_multisite", "N") == "Y"? (Main\Web\Cookie::SPREAD_SITES | Main\Web\Cookie::SPREAD_DOMAIN) : Main\Web\Cookie::SPREAD_DOMAIN);
$cookie = new Main\Web\Cookie("UIDH", $hash, $time);
$cookie->setSpread($spread)
->setSecure($secure)
->setHttpOnly(true);
Main\Context::getCurrent()->getResponse()->addCookie($cookie);
}
/**
* Authenticates the user and then authorizes him
* @param string $login
* @param string $password
* @param string $remember
* @param string $password_original
* @return array|bool
*/
public function Login($login, $password, $remember="N", $password_original="Y")
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$result_message = true;
$user_id = 0;
$applicationId = null;
$applicationPassId = null;
$arParams = array(
"LOGIN" => &$login,
"PASSWORD" => &$password,
"REMEMBER" => &$remember,
"PASSWORD_ORIGINAL" => &$password_original,
);
unset($_SESSION["SESS_OPERATIONS"]);
unset($_SESSION["MODULE_PERMISSIONS"]);
$_SESSION["BX_LOGIN_NEED_CAPTCHA"] = false;
$bOk = true;
$APPLICATION->ResetException();
foreach(GetModuleEvents("main", "OnBeforeUserLogin", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false)
{
if($err = $APPLICATION->GetException())
{
$result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
}
else
{
$APPLICATION->ThrowException("Unknown login error");
$result_message = array("MESSAGE"=>"Unknown login error"."<br>", "TYPE"=>"ERROR");
}
$bOk = false;
break;
}
}
if($bOk)
{
//external authentication
foreach(GetModuleEvents("main", "OnUserLoginExternal", true) as $arEvent)
{
$user_id = ExecuteModuleEventEx($arEvent, array(&$arParams));
if(isset($arParams["RESULT_MESSAGE"]))
{
$result_message = $arParams["RESULT_MESSAGE"];
}
if($user_id > 0)
{
break;
}
}
if($user_id <= 0)
{
//internal authentication OR application password for external user
$user_id = self::LoginInternal($arParams, $result_message, $applicationId, $applicationPassId);
if($user_id <= 0)
{
//no user found by login - try to find an external user
foreach(GetModuleEvents("main", "OnFindExternalUser", true) as $arEvent)
{
if(($external_user_id = intval(ExecuteModuleEventEx($arEvent, array($arParams["LOGIN"])))) > 0)
{
//external user authentication
//let's try to find application password for the external user
if(($appPassword = ApplicationPasswordTable::findPassword($external_user_id, $arParams["PASSWORD"], ($arParams["PASSWORD_ORIGINAL"] == "Y"))) !== false)
{
//bingo, the user has the application password
$user_id = $external_user_id;
$applicationId = $appPassword["APPLICATION_ID"];
$applicationPassId = $appPassword["ID"];
}
break;
}
}
}
if($user_id <= 0 && $result_message === true)
{
$APPLICATION->ThrowException(GetMessage("WRONG_LOGIN"));
$result_message = array("MESSAGE"=>GetMessage("WRONG_LOGIN")."<br>", "TYPE"=>"ERROR", "ERROR_TYPE" => "LOGIN");
}
}
}
// All except Admin
if ($user_id > 1 && $arParams["CONTROLLER_ADMIN"] !== "Y")
{
if(!static::CheckUsersCount($user_id))
{
$user_id = 0;
$APPLICATION->ThrowException(GetMessage("LIMIT_USERS_COUNT"));
$result_message = array(
"MESSAGE" => GetMessage("LIMIT_USERS_COUNT")."<br>",
"TYPE" => "ERROR",
);
}
}
$arParams["USER_ID"] = $user_id;
$doAuthorize = true;
if($user_id > 0)
{
if($applicationId === null && CModule::IncludeModule("security"))
{
/*
MFA can allow or disallow authorization.
Allowed if:
- OTP is not active for the user;
- correct "OTP" in the $arParams (filled by the OnBeforeUserLogin event handler).
Disallowed if:
- OTP is not provided;
- OTP is not correct.
When authorization is disallowed the OTP form will be shown on the next hit.
Note: there is no MFA check for an application password.
*/
$arParams["CAPTCHA_WORD"] = $_REQUEST["captcha_word"];
$arParams["CAPTCHA_SID"] = $_REQUEST["captcha_sid"];
$doAuthorize = \Bitrix\Security\Mfa\Otp::verifyUser($arParams);
}
if($doAuthorize)
{
$this->Authorize($user_id, ($arParams["REMEMBER"] == "Y"), true, $applicationId);
if($applicationPassId !== null)
{
//update usage statistics for the application
Main\Authentication\ApplicationPasswordTable::update($applicationPassId, array(
'DATE_LOGIN' => new Main\Type\DateTime(),
'LAST_IP' => $_SERVER["REMOTE_ADDR"],
));
}
}
else
{
$result_message = false;
}
if($applicationId === null && $arParams["LOGIN"] <> '')
{
//the cookie is for authentication forms mostly, does not make sense for applications
$cookie = new Bitrix\Main\Web\Cookie("LOGIN", $arParams["LOGIN"], time()+60*60*24*30*60);
Main\Context::getCurrent()->getResponse()->addCookie($cookie);
}
}
$arParams["RESULT_MESSAGE"] = $result_message;
$APPLICATION->ResetException();
foreach(GetModuleEvents("main", "OnAfterUserLogin", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arParams));
if($doAuthorize == true && $result_message !== true && (COption::GetOptionString("main", "event_log_login_fail", "N") === "Y"))
CEventLog::Log("SECURITY", "USER_LOGIN", "main", $login, $result_message["MESSAGE"]);
return $arParams["RESULT_MESSAGE"];
}
/**
* Internal authentication by login and password.
* @param array $arParams
* @param array|bool $result_message
* @param string|null $applicationId
* @param string|null $applicationPassId
* @return int User ID on success or 0 on failure. Additionally, $result_message will hold an error.
*/
public static function LoginInternal(&$arParams, &$result_message = true, &$applicationId = null, &$applicationPassId = null)
{
global $DB, $APPLICATION;
$user_id = 0;
$strSql =
"SELECT U.ID, U.LOGIN, U.ACTIVE, U.PASSWORD, U.LOGIN_ATTEMPTS, U.CONFIRM_CODE, U.EMAIL ".
"FROM b_user U ".
"WHERE U.LOGIN='".$DB->ForSQL($arParams["LOGIN"])."' ";
if(isset($arParams["EXTERNAL_AUTH_ID"]) && $arParams["EXTERNAL_AUTH_ID"] <> '')
{
//external user
$strSql .= " AND EXTERNAL_AUTH_ID='".$DB->ForSql($arParams["EXTERNAL_AUTH_ID"])."'";
}
else
{
//internal user (by default)
$strSql .= " AND (EXTERNAL_AUTH_ID IS NULL OR EXTERNAL_AUTH_ID='') ";
}
$result = $DB->Query($strSql);
if(($arUser = $result->Fetch()))
{
if(strlen($arUser["PASSWORD"]) > 32)
{
$salt = substr($arUser["PASSWORD"], 0, strlen($arUser["PASSWORD"]) - 32);
$db_password = substr($arUser["PASSWORD"], -32);
}
else
{
$salt = "";
$db_password = $arUser["PASSWORD"];
}
$user_password_no_otp = "";
if($arParams["PASSWORD_ORIGINAL"] == "Y")
{
$user_password = md5($salt.$arParams["PASSWORD"]);
if($arParams["OTP"] <> '')
{
$user_password_no_otp = md5($salt.substr($arParams["PASSWORD"], 0, -6));
}
}
else
{
if(strlen($arParams["PASSWORD"]) > 32)
{
$user_password = substr($arParams["PASSWORD"], -32);
}
else
{
$user_password = $arParams["PASSWORD"];
}
}
$passwordCorrect = ($db_password === $user_password || ($arParams["OTP"] <> '' && $db_password === $user_password_no_otp));
if($db_password === $user_password)
{
//this password has no added otp for sure
$arParams["OTP"] = '';
}
if(!$passwordCorrect)
{
//let's try to find application password
if(($appPassword = ApplicationPasswordTable::findPassword($arUser["ID"], $arParams["PASSWORD"], ($arParams["PASSWORD_ORIGINAL"] == "Y"))) !== false)
{
$passwordCorrect = true;
$applicationId = $appPassword["APPLICATION_ID"];
$applicationPassId = $appPassword["ID"];
}
}
$arPolicy = CUser::GetGroupPolicy($arUser["ID"]);
$pol_login_attempts = intval($arPolicy["LOGIN_ATTEMPTS"]);
$usr_login_attempts = intval($arUser["LOGIN_ATTEMPTS"]) + 1;
if($pol_login_attempts > 0 && $usr_login_attempts > $pol_login_attempts)
{
$_SESSION["BX_LOGIN_NEED_CAPTCHA"] = true;
if(!$APPLICATION->CaptchaCheckCode($_REQUEST["captcha_word"], $_REQUEST["captcha_sid"]))
{
$passwordCorrect = false;
}
}
if($passwordCorrect)
{
if($salt == '' && $arParams["PASSWORD_ORIGINAL"] == "Y" && $applicationId === null)
{
$salt = randString(8, array(
"abcdefghijklnmopqrstuvwxyz",
"ABCDEFGHIJKLNMOPQRSTUVWXYZ",
"0123456789",
",.<>/?;:[]{}\\|~!@#\$%^&*()-_+=",
));
$new_password = $salt.md5($salt.$arParams["PASSWORD"]);
$DB->Query("UPDATE b_user SET PASSWORD='".$DB->ForSQL($new_password)."', TIMESTAMP_X = TIMESTAMP_X WHERE ID = ".intval($arUser["ID"]));
}
if($arUser["ACTIVE"] == "Y")
{
$user_id = $arUser["ID"];
//update digest hash for http digest authorization
if($arParams["PASSWORD_ORIGINAL"] == "Y" && $applicationId === null && COption::GetOptionString('main', 'use_digest_auth', 'N') == 'Y')
{
CUser::UpdateDigest($arUser["ID"], $arParams["PASSWORD"]);
}
}
elseif($arUser["CONFIRM_CODE"] <> '')
{
//unconfirmed registration
$message = GetMessage("MAIN_LOGIN_EMAIL_CONFIRM", array("#EMAIL#" => $arUser["EMAIL"]));
$APPLICATION->ThrowException($message);
$result_message = array("MESSAGE" => $message."<br>", "TYPE" => "ERROR");
}
else
{
$APPLICATION->ThrowException(GetMessage("LOGIN_BLOCK"));
$result_message = array("MESSAGE" => GetMessage("LOGIN_BLOCK")."<br>", "TYPE" => "ERROR");
}
}
else
{
$DB->Query("UPDATE b_user SET LOGIN_ATTEMPTS = ".$usr_login_attempts.", TIMESTAMP_X = TIMESTAMP_X WHERE ID = ".intval($arUser["ID"]));
$APPLICATION->ThrowException(GetMessage("WRONG_LOGIN"));
$result_message = array("MESSAGE" => GetMessage("WRONG_LOGIN")."<br>", "TYPE" => "ERROR", "ERROR_TYPE" => "LOGIN");
}
}
return $user_id;
}
protected static function CheckUsersCount($user_id)
{
$limitUsersCount = intval(COption::GetOptionInt("main", "PARAM_MAX_USERS", 0));
if ($limitUsersCount > 0)
{
$by = "ID";
$order = "ASC";
$arFilter = array("LAST_LOGIN_1" => ConvertTimeStamp());
//Intranet users only
$intranet = IsModuleInstalled("intranet");
if ($intranet)
{
$arFilter["!=UF_DEPARTMENT"] = false;
}
$rsUsers = CUser::GetList($by, $order, $arFilter, array("FIELDS" => array("ID")));
while ($user = $rsUsers->fetch())
{
if ($user["ID"] == $user_id)
{
$limitUsersCount = 1;
break;
}
$limitUsersCount--;
}
if ($limitUsersCount <= 0)
{
if($intranet)
{
//only intranet users are NOT allowed
$currUserRs = CUser::GetByID($user_id);
if($currUser = $currUserRs->Fetch())
{
if(!empty($currUser["UF_DEPARTMENT"]))
{
return false;
}
}
}
else
{
return false;
}
}
}
return true;
}
public function LoginByOtp($otp, $remember_otp = "N", $captcha_word = "", $captcha_sid = "")
{
if(!CModule::IncludeModule("security") || !\Bitrix\Security\Mfa\Otp::isOtpRequired())
{
return array("MESSAGE" => GetMessage("USER_LOGIN_OTP_ERROR")."<br>", "TYPE" => "ERROR");
}
$userParams = \Bitrix\Security\Mfa\Otp::getDeferredParams();
$userParams["OTP"] = $otp;
$userParams["OTP_REMEMBER"] = ($remember_otp === "Y");
$userParams["CAPTCHA_WORD"] = $captcha_word;
$userParams["CAPTCHA_SID"] = $captcha_sid;
if(!\Bitrix\Security\Mfa\Otp::verifyUser($userParams))
{
return array("MESSAGE" => GetMessage("USER_LOGIN_OTP_INCORRECT")."<br>", "TYPE" => "ERROR");
}
$this->Authorize($userParams["USER_ID"], ($userParams["REMEMBER"] == "Y"));
return true;
}
public function AuthorizeWithOtp($user_id)
{
$doAuthorize = true;
if(CModule::IncludeModule("security"))
{
/*
MFA can allow or disallow authorization.
Allowed only if:
- OTP is not active for the user;
When authorization is disallowed the OTP form will be shown on the next hit.
*/
$doAuthorize = \Bitrix\Security\Mfa\Otp::verifyUser(array("USER_ID" => $user_id));
}
if($doAuthorize)
{
return $this->Authorize($user_id);
}
return false;
}
public function ChangePassword($LOGIN, $CHECKWORD, $PASSWORD, $CONFIRM_PASSWORD, $SITE_ID=false, $captcha_word = "", $captcha_sid = 0, $authActions = true)
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$result_message = array("MESSAGE"=>GetMessage('PASSWORD_CHANGE_OK')."<br>", "TYPE"=>"OK");
$arParams = array(
"LOGIN" => &$LOGIN,
"CHECKWORD" => &$CHECKWORD,
"PASSWORD" => &$PASSWORD,
"CONFIRM_PASSWORD" => &$CONFIRM_PASSWORD,
"SITE_ID" => &$SITE_ID
);
$APPLICATION->ResetException();
$bOk = true;
foreach(GetModuleEvents("main", "OnBeforeUserChangePassword", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false)
{
if($err = $APPLICATION->GetException())
$result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
$bOk = false;
break;
}
}
if($bOk && COption::GetOptionString("main", "captcha_restoring_password", "N") == "Y")
{
if (!($APPLICATION->CaptchaCheckCode($captcha_word, $captcha_sid)))
{
$result_message = array("MESSAGE"=>GetMessage("main_user_captcha_error")."<br>", "TYPE"=>"ERROR");
$bOk = false;
}
}
if($bOk)
{
$strAuthError = "";
if(strlen($arParams["LOGIN"])<3)
$strAuthError .= GetMessage('MIN_LOGIN')."<br>";
if($arParams["PASSWORD"]<>$arParams["CONFIRM_PASSWORD"])
$strAuthError .= GetMessage('WRONG_CONFIRMATION')."<br>";
if($strAuthError <> '')
return array("MESSAGE"=>$strAuthError, "TYPE"=>"ERROR");
CTimeZone::Disable();
$db_check = $DB->Query(
"SELECT ID, LID, CHECKWORD, ".$DB->DateToCharFunction("CHECKWORD_TIME", "FULL")." as CHECKWORD_TIME ".
"FROM b_user ".
"WHERE LOGIN='".$DB->ForSql($arParams["LOGIN"], 0)."' AND (EXTERNAL_AUTH_ID IS NULL OR EXTERNAL_AUTH_ID='')");
CTimeZone::Enable();
if(!($res = $db_check->Fetch()))
return array("MESSAGE"=>preg_replace("/#LOGIN#/i", htmlspecialcharsbx($arParams["LOGIN"]), GetMessage('LOGIN_NOT_FOUND')), "TYPE"=>"ERROR", "FIELD" => "LOGIN");
$salt = substr($res["CHECKWORD"], 0, 8);
if($res["CHECKWORD"] == '' || $res["CHECKWORD"] != $salt.md5($salt.$arParams["CHECKWORD"]))
return array("MESSAGE"=>preg_replace("/#LOGIN#/i", htmlspecialcharsbx($arParams["LOGIN"]), GetMessage("CHECKWORD_INCORRECT"))."<br>", "TYPE"=>"ERROR", "FIELD"=>"CHECKWORD");
$arPolicy = CUser::GetGroupPolicy($res["ID"]);
$passwordErrors = self::CheckPasswordAgainstPolicy($arParams["PASSWORD"], $arPolicy);
if (!empty($passwordErrors))
{
return array(
"MESSAGE" => implode("<br>", $passwordErrors)."<br>",
"TYPE" => "ERROR"
);
}
$site_format = CSite::GetDateFormat();
if(time()-$arPolicy["CHECKWORD_TIMEOUT"]*60 > MakeTimeStamp($res["CHECKWORD_TIME"], $site_format))
return array("MESSAGE"=>preg_replace("/#LOGIN#/i", htmlspecialcharsbx($arParams["LOGIN"]), GetMessage("CHECKWORD_EXPIRE"))."<br>", "TYPE"=>"ERROR", "FIELD"=>"CHECKWORD_EXPIRE");
if($arParams["SITE_ID"] === false)
{
if(defined("ADMIN_SECTION") && ADMIN_SECTION===true)
$arParams["SITE_ID"] = CSite::GetDefSite($res["LID"]);
else
$arParams["SITE_ID"] = SITE_ID;
}
// change the password
$ID = $res["ID"];
$obUser = new CUser;
$res = $obUser->Update($ID, array("PASSWORD"=>$arParams["PASSWORD"]), $authActions);
if(!$res && $obUser->LAST_ERROR <> '')
return array("MESSAGE"=>$obUser->LAST_ERROR."<br>", "TYPE"=>"ERROR");
CUser::SendUserInfo($ID, $arParams["SITE_ID"], GetMessage('CHANGE_PASS_SUCC'), true, 'USER_PASS_CHANGED');
}
return $result_message;
}
public static function CheckPasswordAgainstPolicy($password, $arPolicy)
{
$errors = array();
$password_min_length = intval($arPolicy["PASSWORD_LENGTH"]);
if($password_min_length <= 0)
$password_min_length = 6;
if(strlen($password) < $password_min_length)
$errors[] = GetMessage("MAIN_FUNCTION_REGISTER_PASSWORD_LENGTH", array("#LENGTH#" => $arPolicy["PASSWORD_LENGTH"]));
if(($arPolicy["PASSWORD_UPPERCASE"] === "Y") && !preg_match("/[A-Z]/", $password))
$errors[] = GetMessage("MAIN_FUNCTION_REGISTER_PASSWORD_UPPERCASE");
if(($arPolicy["PASSWORD_LOWERCASE"] === "Y") && !preg_match("/[a-z]/", $password))
$errors[] = GetMessage("MAIN_FUNCTION_REGISTER_PASSWORD_LOWERCASE");
if(($arPolicy["PASSWORD_DIGITS"] === "Y") && !preg_match("/[0-9]/", $password))
$errors[] = GetMessage("MAIN_FUNCTION_REGISTER_PASSWORD_DIGITS");
if(($arPolicy["PASSWORD_PUNCTUATION"] === "Y") && !preg_match("/[,.<>\\/?;:'\"[\\]\\{\\}\\\\|`~!@#\$%^&*()_+=-]/", $password))
$errors[] = GetMessage("MAIN_FUNCTION_REGISTER_PASSWORD_PUNCTUATION");
return $errors;
}
/**
* Sends a profile information to email
*/
public static function SendUserInfo($ID, $SITE_ID, $MSG, $bImmediate=false, $eventName="USER_INFO")
{
global $DB;
// change CHECKWORD
$ID = intval($ID);
$salt = randString(8);
$checkword = md5(CMain::GetServerUniqID().uniqid());
$strSql = "UPDATE b_user SET ".
" CHECKWORD = '".$salt.md5($salt.$checkword)."', ".
" CHECKWORD_TIME = ".$DB->CurrentTimeFunction().", ".
" LID = '".$DB->ForSql($SITE_ID, 2)."', ".
" TIMESTAMP_X = TIMESTAMP_X ".
"WHERE ID = '".$ID."'".
" AND (EXTERNAL_AUTH_ID IS NULL OR EXTERNAL_AUTH_ID='') ";
$DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$res = $DB->Query(
"SELECT u.* ".
"FROM b_user u ".
"WHERE ID='".$ID."'".
" AND (EXTERNAL_AUTH_ID IS NULL OR EXTERNAL_AUTH_ID='') "
);
if($res_array = $res->Fetch())
{
$event = new CEvent;
$arFields = array(
"USER_ID"=>$res_array["ID"],
"STATUS"=>($res_array["ACTIVE"]=="Y"?GetMessage("STATUS_ACTIVE"):GetMessage("STATUS_BLOCKED")),
"MESSAGE"=>$MSG,
"LOGIN"=>$res_array["LOGIN"],
"URL_LOGIN"=>urlencode($res_array["LOGIN"]),
"CHECKWORD"=>$checkword,
"NAME"=>$res_array["NAME"],
"LAST_NAME"=>$res_array["LAST_NAME"],
"EMAIL"=>$res_array["EMAIL"]
);
$arParams = array(
"FIELDS" => &$arFields,
"USER_FIELDS" => $res_array,
"SITE_ID" => &$SITE_ID,
"EVENT_NAME" => &$eventName,
);
foreach (GetModuleEvents("main", "OnSendUserInfo", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arParams));
if (!$bImmediate)
$event->Send($eventName, $SITE_ID, $arFields, "Y", "", array(), $res_array["LANGUAGE_ID"]);
else
$event->SendImmediate($eventName, $SITE_ID, $arFields, "Y", "", array(), $res_array["LANGUAGE_ID"]);
}
}
public static function SendPassword($LOGIN, $EMAIL, $SITE_ID = false, $captcha_word = "", $captcha_sid = 0)
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$arParams = array(
"LOGIN" => $LOGIN,
"EMAIL" => $EMAIL,
"SITE_ID" => $SITE_ID
);
$result_message = array("MESSAGE"=>GetMessage('ACCOUNT_INFO_SENT')."<br>", "TYPE"=>"OK");
$APPLICATION->ResetException();
$bOk = true;
foreach(GetModuleEvents("main", "OnBeforeUserSendPassword", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false)
{
if($err = $APPLICATION->GetException())
$result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
$bOk = false;
break;
}
}
if($bOk && COption::GetOptionString("main", "captcha_restoring_password", "N") == "Y")
{
if (!($APPLICATION->CaptchaCheckCode($captcha_word, $captcha_sid)))
{
$result_message = array("MESSAGE"=>GetMessage("main_user_captcha_error")."<br>", "TYPE"=>"ERROR");
$bOk = false;
}
}
if($bOk)
{
$f = false;
if($arParams["LOGIN"] <> '' || $arParams["EMAIL"] <> '')
{
$confirmation = (COption::GetOptionString("main", "new_user_registration_email_confirmation", "N") == "Y");
$strSql = "";
if($arParams["LOGIN"] <> '')
{
$strSql =
"SELECT ID, LID, ACTIVE, CONFIRM_CODE, LOGIN, EMAIL, NAME, LAST_NAME, LANGUAGE_ID ".
"FROM b_user u ".
"WHERE LOGIN='".$DB->ForSQL($arParams["LOGIN"])."' ".
" AND (ACTIVE='Y' OR NOT(CONFIRM_CODE IS NULL OR CONFIRM_CODE='')) ".
" AND (EXTERNAL_AUTH_ID IS NULL OR EXTERNAL_AUTH_ID='') ";
}
if($arParams["EMAIL"] <> '')
{
if($strSql <> '')
{
$strSql .= "\nUNION\n";
}
$strSql .=
"SELECT ID, LID, ACTIVE, CONFIRM_CODE, LOGIN, EMAIL, NAME, LAST_NAME, LANGUAGE_ID ".
"FROM b_user u ".
"WHERE EMAIL='".$DB->ForSQL($arParams["EMAIL"])."' ".
" AND (ACTIVE='Y' OR NOT(CONFIRM_CODE IS NULL OR CONFIRM_CODE='')) ".
" AND (EXTERNAL_AUTH_ID IS NULL OR EXTERNAL_AUTH_ID='') ";
}
$res = $DB->Query($strSql);
while($arUser = $res->Fetch())
{
if($arParams["SITE_ID"]===false)
{
if(defined("ADMIN_SECTION") && ADMIN_SECTION===true)
$arParams["SITE_ID"] = CSite::GetDefSite($arUser["LID"]);
else
$arParams["SITE_ID"] = SITE_ID;
}
if($arUser["ACTIVE"] == "Y")
{
CUser::SendUserInfo($arUser["ID"], $arParams["SITE_ID"], GetMessage("INFO_REQ"), true, 'USER_PASS_REQUEST');
$f = true;
}
elseif($confirmation)
{
//unconfirmed registration - resend confirmation email
$arFields = array(
"USER_ID" => $arUser["ID"],
"LOGIN" => $arUser["LOGIN"],
"EMAIL" => $arUser["EMAIL"],
"NAME" => $arUser["NAME"],
"LAST_NAME" => $arUser["LAST_NAME"],
"CONFIRM_CODE" => $arUser["CONFIRM_CODE"],
"USER_IP" => $_SERVER["REMOTE_ADDR"],
"USER_HOST" => @gethostbyaddr($_SERVER["REMOTE_ADDR"]),
);
$event = new CEvent;
$event->SendImmediate("NEW_USER_CONFIRM", $arParams["SITE_ID"], $arFields, "Y", "", array(), $arUser["LANGUAGE_ID"]);
$result_message = array("MESSAGE"=>GetMessage("MAIN_SEND_PASS_CONFIRM")."<br>", "TYPE"=>"OK");
$f = true;
}
if(COption::GetOptionString("main", "event_log_password_request", "N") === "Y")
{
CEventLog::Log("SECURITY", "USER_INFO", "main", $arUser["ID"]);
}
}
}
if(!$f)
{
return array("MESSAGE"=>GetMessage('DATA_NOT_FOUND')."<br>", "TYPE"=>"ERROR");
}
}
return $result_message;
}
public function Register($USER_LOGIN, $USER_NAME, $USER_LAST_NAME, $USER_PASSWORD, $USER_CONFIRM_PASSWORD, $USER_EMAIL, $SITE_ID = false, $captcha_word = "", $captcha_sid = 0, $bSkipConfirm = false)
{
/**
* @global CMain $APPLICATION
* @global CUserTypeManager $USER_FIELD_MANAGER
*/
global $APPLICATION, $DB, $USER_FIELD_MANAGER;
$APPLICATION->ResetException();
if(defined("ADMIN_SECTION") && ADMIN_SECTION===true && $SITE_ID!==false)
{
$APPLICATION->ThrowException(GetMessage("MAIN_FUNCTION_REGISTER_NA_INADMIN"));
return array("MESSAGE"=>GetMessage("MAIN_FUNCTION_REGISTER_NA_INADMIN"), "TYPE"=>"ERROR");
}
$strError = "";
if (COption::GetOptionString("main", "captcha_registration", "N") == "Y")
{
if (!($APPLICATION->CaptchaCheckCode($captcha_word, $captcha_sid)))
{
$strError .= GetMessage("MAIN_FUNCTION_REGISTER_CAPTCHA")."<br>";
}
}
if($strError)
{
if(COption::GetOptionString("main", "event_log_register_fail", "N") === "Y")
{
CEventLog::Log("SECURITY", "USER_REGISTER_FAIL", "main", false, $strError);
}
$APPLICATION->ThrowException($strError);
return array("MESSAGE"=>$strError, "TYPE"=>"ERROR");
}
if($SITE_ID===false)
$SITE_ID = SITE_ID;
$checkword = md5(CMain::GetServerUniqID().uniqid());
$bConfirmReq = !$bSkipConfirm && (COption::GetOptionString("main", "new_user_registration_email_confirmation", "N") == "Y" && COption::GetOptionString("main", "new_user_email_required", "Y") <> "N");
$arFields = array(
"LOGIN" => $USER_LOGIN,
"NAME" => $USER_NAME,
"LAST_NAME" => $USER_LAST_NAME,
"PASSWORD" => $USER_PASSWORD,
"CHECKWORD" => $checkword,
"~CHECKWORD_TIME" => $DB->CurrentTimeFunction(),
"CONFIRM_PASSWORD" => $USER_CONFIRM_PASSWORD,
"EMAIL" => $USER_EMAIL,
"ACTIVE" => $bConfirmReq? "N": "Y",
"CONFIRM_CODE" => $bConfirmReq? randString(8): "",
"SITE_ID" => $SITE_ID,
"LANGUAGE_ID" => LANGUAGE_ID,
"USER_IP" => $_SERVER["REMOTE_ADDR"],
"USER_HOST" => @gethostbyaddr($_SERVER["REMOTE_ADDR"]),
);
$USER_FIELD_MANAGER->EditFormAddFields("USER", $arFields);
$def_group = COption::GetOptionString("main", "new_user_registration_def_group", "");
if($def_group!="")
$arFields["GROUP_ID"] = explode(",", $def_group);
$bOk = true;
$result_message = true;
foreach(GetModuleEvents("main", "OnBeforeUserRegister", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arFields)) === false)
{
if($err = $APPLICATION->GetException())
$result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
else
{
$APPLICATION->ThrowException("Unknown error");
$result_message = array("MESSAGE"=>"Unknown error"."<br>", "TYPE"=>"ERROR");
}
$bOk = false;
break;
}
}
$ID = false;
if($bOk)
{
$arFields["LID"] = $arFields["SITE_ID"];
if($ID = $this->Add($arFields))
{
$arFields["USER_ID"] = $ID;
$arEventFields = $arFields;
unset($arEventFields["PASSWORD"]);
unset($arEventFields["CONFIRM_PASSWORD"]);
unset($arEventFields["~CHECKWORD_TIME"]);
$event = new CEvent;
$event->SendImmediate("NEW_USER", $arEventFields["SITE_ID"], $arEventFields);
if($bConfirmReq)
$event->SendImmediate("NEW_USER_CONFIRM", $arEventFields["SITE_ID"], $arEventFields);
$result_message = array("MESSAGE"=>GetMessage("USER_REGISTER_OK"), "TYPE"=>"OK", "ID"=>$ID);
}
else
{
$APPLICATION->ThrowException($this->LAST_ERROR);
$result_message = array("MESSAGE"=>$this->LAST_ERROR, "TYPE"=>"ERROR");
}
}
if(is_array($result_message))
{
if($result_message["TYPE"] == "OK")
{
if(COption::GetOptionString("main", "event_log_register", "N") === "Y")
{
$res_log["user"] = ($USER_NAME != "" || $USER_LAST_NAME != "") ? trim($USER_NAME." ".$USER_LAST_NAME) : $USER_LOGIN;
CEventLog::Log("SECURITY", "USER_REGISTER", "main", $ID, serialize($res_log));
}
}
else
{
if(COption::GetOptionString("main", "event_log_register_fail", "N") === "Y")
{
CEventLog::Log("SECURITY", "USER_REGISTER_FAIL", "main", $ID, $result_message["MESSAGE"]);
}
}
}
//authorize succesfully registered user
$isAuthorize = false;
if($ID !== false && $arFields["ACTIVE"] === "Y")
$isAuthorize = $this->Authorize($ID);
$agreementId = intval(COption::getOptionString("main", "new_user_agreement", ""));
if ($agreementId && $isAuthorize)
{
$agreementObject = new \Bitrix\Main\UserConsent\Agreement($agreementId);
if ($agreementObject->isExist() && $agreementObject->isActive() && $_REQUEST["USER_AGREEMENT"] == "Y")
{
\Bitrix\Main\UserConsent\Consent::addByContext($agreementId, "main/reg", "register");
}
}
$arFields["RESULT_MESSAGE"] = $result_message;
foreach (GetModuleEvents("main", "OnAfterUserRegister", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arFields));
return $arFields["RESULT_MESSAGE"];
}
public function SimpleRegister($USER_EMAIL, $SITE_ID = false)
{
/** @global CMain $APPLICATION */
global $APPLICATION, $DB;
$APPLICATION->ResetException();
if(defined("ADMIN_SECTION") && ADMIN_SECTION===true && $SITE_ID===false)
{
$APPLICATION->ThrowException(GetMessage("MAIN_FUNCTION_SIMPLEREGISTER_NA_INADMIN"));
return array("MESSAGE"=>GetMessage("MAIN_FUNCTION_SIMPLEREGISTER_NA_INADMIN"), "TYPE"=>"ERROR");
}
if($SITE_ID===false)
$SITE_ID = SITE_ID;
global $REMOTE_ADDR;
$checkword = md5(CMain::GetServerUniqID().uniqid());
$arFields = array(
"CHECKWORD" => $checkword,
"~CHECKWORD_TIME" => $DB->CurrentTimeFunction(),
"EMAIL" => $USER_EMAIL,
"ACTIVE" => "Y",
"NAME"=>"",
"LAST_NAME"=>"",
"USER_IP"=>$REMOTE_ADDR,
"USER_HOST"=>@gethostbyaddr($REMOTE_ADDR),
"SITE_ID" => $SITE_ID,
"LANGUAGE_ID" => LANGUAGE_ID,
);
$def_group = COption::GetOptionString("main", "new_user_registration_def_group", "");
if($def_group!="")
{
$arFields["GROUP_ID"] = explode(",", $def_group);
$arPolicy = $this->GetGroupPolicy($arFields["GROUP_ID"]);
}
else
{
$arPolicy = $this->GetGroupPolicy(array());
}
$password_min_length = intval($arPolicy["PASSWORD_LENGTH"]);
if($password_min_length <= 0)
$password_min_length = 6;
$password_chars = array(
"abcdefghijklnmopqrstuvwxyz",
"ABCDEFGHIJKLNMOPQRSTUVWXYZ",
"0123456789",
);
if($arPolicy["PASSWORD_PUNCTUATION"] === "Y")
$password_chars[] = ",.<>/?;:'\"[]{}\\|`~!@#\$%^&*()-_+=";
$arFields["PASSWORD"] = $arFields["CONFIRM_PASSWORD"] = randString($password_min_length, $password_chars);
$bOk = true;
$result_message = false;
foreach(GetModuleEvents("main", "OnBeforeUserSimpleRegister", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arFields)) === false)
{
if($err = $APPLICATION->GetException())
$result_message = array("MESSAGE"=>$err->GetString()."<br>", "TYPE"=>"ERROR");
else
{
$APPLICATION->ThrowException("Unknown error");
$result_message = array("MESSAGE"=>"Unknown error"."<br>", "TYPE"=>"ERROR");
}
$bOk = false;
break;
}
}
$bRandLogin = false;
if(!is_set($arFields, "LOGIN"))
{
$arFields["LOGIN"] = randString(50);
$bRandLogin = true;
}
$ID = 0;
if($bOk)
{
$arFields["LID"] = $arFields["SITE_ID"];
$arFields["CHECKWORD"] = $checkword;
if($ID = $this->Add($arFields))
{
if($bRandLogin)
{
$this->Update($ID, array("LOGIN"=>"user".$ID));
$arFields["LOGIN"] = "user".$ID;
}
$this->Authorize($ID);
$event = new CEvent;
$arFields["USER_ID"] = $ID;
$arEventFields = $arFields;
unset($arEventFields["PASSWORD"]);
unset($arEventFields["CONFIRM_PASSWORD"]);
$event->SendImmediate("NEW_USER", $arEventFields["SITE_ID"], $arEventFields);
CUser::SendUserInfo($ID, $arEventFields["SITE_ID"], GetMessage("USER_REGISTERED_SIMPLE"), true);
$result_message = array("MESSAGE"=>GetMessage("USER_REGISTER_OK"), "TYPE"=>"OK");
}
else
$result_message = array("MESSAGE"=>$this->LAST_ERROR, "TYPE"=>"ERROR");
}
if(is_array($result_message))
{
if($result_message["TYPE"] == "OK")
{
if(COption::GetOptionString("main", "event_log_register", "N") === "Y")
{
$res_log["user"] = $arFields["LOGIN"];
CEventLog::Log("SECURITY", "USER_REGISTER", "main", $ID, serialize($res_log));
}
}
else
{
if(COption::GetOptionString("main", "event_log_register_fail", "N") === "Y")
{
CEventLog::Log("SECURITY", "USER_REGISTER_FAIL", "main", $ID, $result_message["MESSAGE"]);
}
}
}
$arFields["RESULT_MESSAGE"] = $result_message;
foreach(GetModuleEvents("main", "OnAfterUserSimpleRegister", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arFields));
return $arFields["RESULT_MESSAGE"];
}
public function IsAuthorized()
{
return ($_SESSION["SESS_AUTH"]["AUTHORIZED"]=="Y");
}
public function HasNoAccess()
{
if (!$this->IsAuthorized())
{
return true;
}
$filePath = \Bitrix\Main\Context::getCurrent()->getRequest()->getScriptFile();
return !$this->CanDoFileOperation('fm_view_file', [SITE_ID, $filePath]);
}
public function IsJustAuthorized()
{
return $this->justAuthorized;
}
public function IsJustBecameOnline()
{
if(!$_SESSION['SESS_AUTH']['PREV_LAST_ACTIVITY'])
{
return true;
}
else
{
return ($_SESSION['SESS_AUTH']['SET_LAST_ACTIVITY'] - $_SESSION['SESS_AUTH']['PREV_LAST_ACTIVITY']) > Main\UserTable::getSecondsForLimitOnline();
}
}
public function IsAdmin()
{
if ($this->admin === null)
{
if(
COption::GetOptionString("main", "controller_member", "N") == "Y"
&& COption::GetOptionString("main", "~controller_limited_admin", "N") == "Y"
)
{
if(
isset($_SESSION["SESS_AUTH"])
&& is_array($_SESSION["SESS_AUTH"])
&& isset($_SESSION["SESS_AUTH"]["CONTROLLER_ADMIN"])
)
$this->admin = ($_SESSION["SESS_AUTH"]["CONTROLLER_ADMIN"] === true);
else
$this->admin = false;
}
else
{
if(
isset($_SESSION["SESS_AUTH"])
&& is_array($_SESSION["SESS_AUTH"])
&& isset($_SESSION["SESS_AUTH"]["ADMIN"])
)
$this->admin = ($_SESSION["SESS_AUTH"]["ADMIN"] === true);
else
$this->admin = false;
}
}
return $this->admin;
}
public function SetControllerAdmin($isAdmin=true)
{
$_SESSION["SESS_AUTH"]["CONTROLLER_ADMIN"] = $isAdmin;
}
public function Logout()
{
/** @global CMain $APPLICATION */
global $APPLICATION, $DB;
$USER_ID = $_SESSION["SESS_AUTH"]["USER_ID"];
$arParams = array(
"USER_ID" => &$USER_ID
);
$APPLICATION->ResetException();
$bOk = true;
foreach(GetModuleEvents("main", "OnBeforeUserLogout", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false)
{
if(!($APPLICATION->GetException()))
{
$APPLICATION->ThrowException("Unknown logout error");
}
$bOk = false;
break;
}
}
if($bOk)
{
foreach(GetModuleEvents("main", "OnUserLogout", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($USER_ID));
if($_SESSION["SESS_AUTH"]["STORED_AUTH_ID"]>0)
$DB->Query("DELETE FROM b_user_stored_auth WHERE ID=".intval($_SESSION["SESS_AUTH"]["STORED_AUTH_ID"]));
$this->justAuthorized = false;
$this->admin = null;
$_SESSION["SESS_AUTH"] = array();
unset($_SESSION["SESS_AUTH"]);
unset($_SESSION["SESS_OPERATIONS"]);
unset($_SESSION["MODULE_PERMISSIONS"]);
unset($_SESSION["SESS_PWD_HASH_TESTED"]);
//change session id for security reason after logout
if(COption::GetOptionString("security", "session", "N") === "Y" && CModule::IncludeModule("security"))
CSecuritySession::UpdateSessID();
else
session_regenerate_id(true);
$response = Main\Context::getCurrent()->getResponse();
$spread = (COption::GetOptionString("main", "auth_multisite", "N") == "Y"? (Main\Web\Cookie::SPREAD_SITES | Main\Web\Cookie::SPREAD_DOMAIN) : Main\Web\Cookie::SPREAD_DOMAIN);
$cookie = new Main\Web\Cookie("UIDH", "", 0);
$cookie->setSpread($spread);
$cookie->setHttpOnly(true);
$response->addCookie($cookie);
$cookie = new Main\Web\Cookie("UIDL", "", 0);
$cookie->setSpread($spread);
$cookie->setHttpOnly(true);
$response->addCookie($cookie);
Main\Composite\Engine::onUserLogout();
}
$arParams["SUCCESS"] = $bOk;
foreach(GetModuleEvents("main", "OnAfterUserLogout", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arParams));
if(COption::GetOptionString("main", "event_log_logout", "N") === "Y")
CEventLog::Log("SECURITY", "USER_LOGOUT", "main", $USER_ID);
}
public static function GetUserGroup($ID)
{
$ID = (int)$ID;
if (!isset(self::$userGroupCache[$ID]))
{
$arr = array();
$res = static::GetUserGroupEx($ID);
while ($r = $res->Fetch())
$arr[] = $r["GROUP_ID"];
self::$userGroupCache[$ID] = $arr;
}
return self::$userGroupCache[$ID];
}
public static function GetUserGroupEx($ID)
{
global $DB;
$strSql = "
SELECT UG.GROUP_ID, G.STRING_ID,
".$DB->DateToCharFunction("UG.DATE_ACTIVE_FROM", "FULL")." as DATE_ACTIVE_FROM,
".$DB->DateToCharFunction("UG.DATE_ACTIVE_TO", "FULL")." as DATE_ACTIVE_TO
FROM b_user_group UG INNER JOIN b_group G ON G.ID=UG.GROUP_ID
WHERE UG.USER_ID = ".intval($ID)."
and ((UG.DATE_ACTIVE_FROM IS NULL) OR (UG.DATE_ACTIVE_FROM <= ".$DB->CurrentTimeFunction()."))
and ((UG.DATE_ACTIVE_TO IS NULL) OR (UG.DATE_ACTIVE_TO >= ".$DB->CurrentTimeFunction()."))
and G.ACTIVE = 'Y'
UNION SELECT 2, 'everyone', NULL, NULL ".(strtoupper($DB->type) == "ORACLE"? " FROM dual " : "");
$res = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
return $res;
}
public static function GetUserGroupList($ID)
{
global $DB;
$strSql = "
SELECT
UG.GROUP_ID,
".$DB->DateToCharFunction("UG.DATE_ACTIVE_FROM", "FULL")." as DATE_ACTIVE_FROM,
".$DB->DateToCharFunction("UG.DATE_ACTIVE_TO", "FULL")." as DATE_ACTIVE_TO
FROM
b_user_group UG
WHERE
UG.USER_ID = ".intval($ID)."
UNION SELECT 2, NULL, NULL ".(strtoupper($DB->type) == "ORACLE"? " FROM dual " : "");
$res = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
return $res;
}
public function CheckFields(&$arFields, $ID=false)
{
/**
* @global CMain $APPLICATION
* @global CUserTypeManager $USER_FIELD_MANAGER
*/
global $DB, $APPLICATION, $USER_FIELD_MANAGER;
$this->LAST_ERROR = "";
$bInternal = true;
if(is_set($arFields, "EXTERNAL_AUTH_ID"))
{
if(trim($arFields["EXTERNAL_AUTH_ID"]) <> '')
{
$bInternal = false;
}
}
else
{
if($ID > 0)
{
$dbr = $DB->Query("SELECT EXTERNAL_AUTH_ID FROM b_user WHERE ID=".intval($ID));
if(($ar = $dbr->Fetch()))
{
if($ar['EXTERNAL_AUTH_ID'] <> '')
{
$bInternal = false;
}
}
}
}
if($bInternal)
{
$this->LAST_ERROR .= self::CheckInternalFields($arFields, $ID);
}
else
{
if(is_set($arFields, "EMAIL"))
{
if($arFields["EMAIL"] <> '' && !check_email($arFields["EMAIL"], true))
{
$this->LAST_ERROR .= GetMessage("WRONG_EMAIL")."<br>";
}
}
}
if(is_set($arFields, "PERSONAL_PHOTO") && $arFields["PERSONAL_PHOTO"]["name"] == '' && $arFields["PERSONAL_PHOTO"]["del"] == '')
unset($arFields["PERSONAL_PHOTO"]);
$maxWidth = COption::GetOptionInt("main", "profile_image_width", 0);
$maxHeight = COption::GetOptionInt("main", "profile_image_height", 0);
$maxSize = COption::GetOptionInt("main", "profile_image_size", 0);
if(is_set($arFields, "PERSONAL_PHOTO"))
{
$res = CFile::CheckImageFile($arFields["PERSONAL_PHOTO"], $maxSize, $maxWidth, $maxHeight);
if($res <> '')
$this->LAST_ERROR .= $res."<br>";
}
if(is_set($arFields, "PERSONAL_BIRTHDAY") && $arFields["PERSONAL_BIRTHDAY"] <> '' && !CheckDateTime($arFields["PERSONAL_BIRTHDAY"]))
$this->LAST_ERROR .= GetMessage("WRONG_PERSONAL_BIRTHDAY")."<br>";
if(is_set($arFields, "WORK_LOGO") && $arFields["WORK_LOGO"]["name"] == '' && $arFields["WORK_LOGO"]["del"] == '')
unset($arFields["WORK_LOGO"]);
if(is_set($arFields, "WORK_LOGO"))
{
$res = CFile::CheckImageFile($arFields["WORK_LOGO"], $maxSize, $maxWidth, $maxHeight);
if($res <> '')
$this->LAST_ERROR .= $res."<br>";
}
if(is_set($arFields, "LOGIN"))
{
$res = $DB->Query(
"SELECT 'x' ".
"FROM b_user ".
"WHERE LOGIN='".$DB->ForSql($arFields["LOGIN"], 50)."' ".
" ".($ID===false ? "" : " AND ID<>".intval($ID)).
" ".(!$bInternal ? " AND EXTERNAL_AUTH_ID='".$DB->ForSql($arFields["EXTERNAL_AUTH_ID"])."' " : " AND (EXTERNAL_AUTH_ID IS NULL OR ".$DB->Length("EXTERNAL_AUTH_ID")."<=0)")
);
if($res->Fetch())
$this->LAST_ERROR .= str_replace("#LOGIN#", htmlspecialcharsbx($arFields["LOGIN"]), GetMessage("USER_EXIST"))."<br>";
}
if(is_object($APPLICATION))
{
$APPLICATION->ResetException();
if($ID===false)
$events = GetModuleEvents("main", "OnBeforeUserAdd", true);
else
{
$arFields["ID"] = $ID;
$events = GetModuleEvents("main", "OnBeforeUserUpdate", true);
}
foreach($events as $arEvent)
{
$bEventRes = ExecuteModuleEventEx($arEvent, array(&$arFields));
if($bEventRes===false)
{
if($err = $APPLICATION->GetException())
$this->LAST_ERROR .= $err->GetString()." ";
else
{
$APPLICATION->ThrowException("Unknown error");
$this->LAST_ERROR .= "Unknown error. ";
}
break;
}
}
}
if(is_object($APPLICATION))
$APPLICATION->ResetException();
if (!$USER_FIELD_MANAGER->CheckFields("USER", $ID, $arFields))
{
if(is_object($APPLICATION) && $APPLICATION->GetException())
{
$e = $APPLICATION->GetException();
$this->LAST_ERROR .= $e->GetString();
$APPLICATION->ResetException();
}
else
{
$this->LAST_ERROR .= "Unknown error. ";
}
}
if($this->LAST_ERROR <> '')
return false;
return true;
}
/**
* @param array $arFields
* @param int|bool $ID
* @return string
*/
public static function CheckInternalFields($arFields, $ID = false)
{
global $DB;
$resultError = '';
$emailRequired = (COption::GetOptionString("main", "new_user_email_required", "Y") <> "N");
if($ID === false)
{
if(!isset($arFields["LOGIN"]))
{
$resultError .= GetMessage("user_login_not_set")."<br>";
}
if(!isset($arFields["PASSWORD"]))
{
$resultError .= GetMessage("user_pass_not_set")."<br>";
}
if($emailRequired && !isset($arFields["EMAIL"]))
{
$resultError .= GetMessage("user_email_not_set")."<br>";
}
}
if(is_set($arFields, "LOGIN") && $arFields["LOGIN"] <> trim($arFields["LOGIN"]))
{
$resultError .= GetMessage("LOGIN_WHITESPACE")."<br>";
}
if(is_set($arFields, "LOGIN") && strlen($arFields["LOGIN"]) < 3)
{
$resultError .= GetMessage("MIN_LOGIN")."<br>";
}
if(is_set($arFields, "PASSWORD"))
{
if(array_key_exists("GROUP_ID", $arFields))
{
$arGroups = array();
if(is_array($arFields["GROUP_ID"]))
{
foreach($arFields["GROUP_ID"] as $arGroup)
{
if(is_array($arGroup))
{
$arGroups[] = $arGroup["GROUP_ID"];
}
else
{
$arGroups[] = $arGroup;
}
}
}
$arPolicy = self::GetGroupPolicy($arGroups);
}
elseif($ID !== false)
{
$arPolicy = self::GetGroupPolicy($ID);
}
else
{
$arPolicy = self::GetGroupPolicy(array());
}
$passwordErrors = self::CheckPasswordAgainstPolicy($arFields["PASSWORD"], $arPolicy);
if(!empty($passwordErrors))
{
$resultError .= implode("<br>", $passwordErrors)."<br>";
}
}
if(is_set($arFields, "EMAIL"))
{
if(($emailRequired && strlen($arFields["EMAIL"]) < 3) || ($arFields["EMAIL"] <> '' && !check_email($arFields["EMAIL"], true)))
{
$resultError .= GetMessage("WRONG_EMAIL")."<br>";
}
elseif(COption::GetOptionString("main", "new_user_email_uniq_check", "N") === "Y")
{
if($arFields["EMAIL"] <> '')
{
$oldEmail = '';
if($ID > 0)
{
//the option 'new_user_email_uniq_check' might have been switched on after the DB already contained identical emails
//so we let a user to have the old email, but not the existing new one
$dbr = $DB->Query("SELECT EMAIL FROM b_user WHERE ID=".intval($ID));
if(($ar = $dbr->Fetch()))
{
$oldEmail = $ar['EMAIL'];
}
}
if($ID == false || $arFields["EMAIL"] <> $oldEmail)
{
$b = $o = "";
$res = CUser::GetList($b, $o,
array(
"=EMAIL" => $arFields["EMAIL"],
"EXTERNAL_AUTH_ID" => $arFields["EXTERNAL_AUTH_ID"]
),
array(
"FIELDS" => array("ID")
)
);
while($ar = $res->Fetch())
{
if(intval($ar["ID"]) !== intval($ID))
{
$resultError .= GetMessage("USER_WITH_EMAIL_EXIST", array("#EMAIL#" => htmlspecialcharsbx($arFields["EMAIL"])))."<br>";
}
}
}
}
}
}
if(is_set($arFields, "PASSWORD") && is_set($arFields, "CONFIRM_PASSWORD") && $arFields["PASSWORD"] !== $arFields["CONFIRM_PASSWORD"])
{
$resultError .= GetMessage("WRONG_CONFIRMATION")."<br>";
}
if(is_array($arFields["GROUP_ID"]) && count($arFields["GROUP_ID"]) > 0)
{
if(is_array($arFields["GROUP_ID"][0]) && count($arFields["GROUP_ID"][0]) > 0)
{
foreach($arFields["GROUP_ID"] as $arGroup)
{
if($arGroup["DATE_ACTIVE_FROM"] <> '' && !CheckDateTime($arGroup["DATE_ACTIVE_FROM"]))
{
$error = str_replace("#GROUP_ID#", $arGroup["GROUP_ID"], GetMessage("WRONG_DATE_ACTIVE_FROM"));
$resultError .= $error."<br>";
}
if($arGroup["DATE_ACTIVE_TO"] <> '' && !CheckDateTime($arGroup["DATE_ACTIVE_TO"]))
{
$error = str_replace("#GROUP_ID#", $arGroup["GROUP_ID"], GetMessage("WRONG_DATE_ACTIVE_TO"));
$resultError .= $error."<br>";
}
}
}
}
return $resultError;
}
public static function GetByID($ID)
{
global $USER;
$userID = (is_object($USER)? intval($USER->GetID()): 0);
$ID = intval($ID);
if($userID > 0 && $ID == $userID && is_array(self::$CURRENT_USER))
{
$rs = new CDBResult;
$rs->InitFromArray(self::$CURRENT_USER);
}
else
{
$rs = CUser::GetList(($by="id"), ($order="asc"), array("ID_EQUAL_EXACT"=>intval($ID)), array("SELECT"=>array("UF_*")));
if($userID > 0 && $ID == $userID)
{
self::$CURRENT_USER = array($rs->Fetch());
$rs = new CDBResult;
$rs->InitFromArray(self::$CURRENT_USER);
}
}
return $rs;
}
public static function GetByLogin($LOGIN)
{
$rs = CUser::GetList(($by="id"), ($order="asc"), array("LOGIN_EQUAL_EXACT"=>$LOGIN), array("SELECT"=>array("UF_*")));
return $rs;
}
public function Update($ID, $arFields, $authActions = true)
{
/** @global CUserTypeManager $USER_FIELD_MANAGER */
global $DB, $USER_FIELD_MANAGER, $CACHE_MANAGER, $USER;
$ID = intval($ID);
if(!$this->CheckFields($arFields, $ID))
{
$result = false;
$arFields["RESULT_MESSAGE"] = &$this->LAST_ERROR;
}
else
{
unset($arFields["ID"]);
if(is_set($arFields, "ACTIVE") && $arFields["ACTIVE"]!="Y")
$arFields["ACTIVE"]="N";
if(is_set($arFields, "PERSONAL_GENDER") && ($arFields["PERSONAL_GENDER"]!="M" && $arFields["PERSONAL_GENDER"]!="F"))
$arFields["PERSONAL_GENDER"] = "";
$saveHistory = (Main\Config\Option::get("main", "user_profile_history") === "Y");
//we need old values for some actions
$arUser = null;
if((isset($arFields["ACTIVE"]) && $arFields["ACTIVE"] == "N") || isset($arFields["PASSWORD"]) || $saveHistory)
{
$rUser = CUser::GetByID($ID);
$arUser = $rUser->Fetch();
}
$newPassword = "";
if(is_set($arFields, "PASSWORD"))
{
$original_pass = $arFields["PASSWORD"];
$salt = randString(8, array(
"abcdefghijklnmopqrstuvwxyz",
"ABCDEFGHIJKLNMOPQRSTUVWXYZ",
"0123456789",
",.<>/?;:[]{}\\|~!@#\$%^&*()-_+=",
));
$arFields["PASSWORD"] = $salt.md5($salt.$arFields["PASSWORD"]);
if($arUser)
{
$oldSalt = substr($arUser["PASSWORD"], 0, 8);
$newPassword = $oldSalt.md5($oldSalt.$original_pass);
if($newPassword <> $arUser["PASSWORD"])
{
$DB->Query("DELETE FROM b_user_stored_auth WHERE USER_ID=".$ID);
}
}
if(COption::GetOptionString("main", "event_log_password_change", "N") === "Y")
CEventLog::Log("SECURITY", "USER_PASSWORD_CHANGED", "main", $ID);
}
unset($arFields["STORED_HASH"]);
$checkword = '';
if(!is_set($arFields, "CHECKWORD"))
{
if(is_set($arFields, "PASSWORD") || is_set($arFields, "EMAIL") || is_set($arFields, "LOGIN") || is_set($arFields, "ACTIVE"))
{
$salt = randString(8);
$checkword = md5(CMain::GetServerUniqID().uniqid());
$arFields["CHECKWORD"] = $salt.md5($salt.$checkword);
}
}
else
{
$salt = randString(8);
$checkword = $arFields["CHECKWORD"];
$arFields["CHECKWORD"] = $salt.md5($salt.$checkword);
}
if(is_set($arFields, "CHECKWORD") && !is_set($arFields, "CHECKWORD_TIME"))
$arFields["~CHECKWORD_TIME"] = $DB->CurrentTimeFunction();
if(is_set($arFields, "WORK_COUNTRY"))
$arFields["WORK_COUNTRY"] = intval($arFields["WORK_COUNTRY"]);
if(is_set($arFields, "PERSONAL_COUNTRY"))
$arFields["PERSONAL_COUNTRY"] = intval($arFields["PERSONAL_COUNTRY"]);
if (
array_key_exists("PERSONAL_PHOTO", $arFields)
&& is_array($arFields["PERSONAL_PHOTO"])
&& (
!array_key_exists("MODULE_ID", $arFields["PERSONAL_PHOTO"])
|| $arFields["PERSONAL_PHOTO"]["MODULE_ID"] == ''
)
)
{
$arFields["PERSONAL_PHOTO"]["MODULE_ID"] = "main";
}
CFile::SaveForDB($arFields, "PERSONAL_PHOTO", "main");
if (
array_key_exists("WORK_LOGO", $arFields)
&& is_array($arFields["WORK_LOGO"])
&& (
!array_key_exists("MODULE_ID", $arFields["WORK_LOGO"])
|| $arFields["WORK_LOGO"]["MODULE_ID"] == ''
)
)
{
$arFields["WORK_LOGO"]["MODULE_ID"] = "main";
}
CFile::SaveForDB($arFields, "WORK_LOGO", "main");
$strUpdate = $DB->PrepareUpdate("b_user", $arFields);
if(!is_set($arFields, "TIMESTAMP_X"))
$strUpdate .= ($strUpdate <> ""? ",":"")." TIMESTAMP_X = ".$DB->GetNowFunction();
$strSql = "UPDATE b_user SET ".$strUpdate." WHERE ID=".$ID;
$DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$USER_FIELD_MANAGER->Update("USER", $ID, $arFields);
if(COption::GetOptionString("main", "event_log_user_edit", "N") === "Y")
{
$res_log["user"] = ($arFields["NAME"] != "" || $arFields["LAST_NAME"] != "") ? trim($arFields["NAME"]." ".$arFields["LAST_NAME"]) : $arFields["LOGIN"];
CEventLog::Log("SECURITY", "USER_EDIT", "main", $ID, serialize($res_log));
}
if(is_set($arFields, "GROUP_ID"))
CUser::SetUserGroup($ID, $arFields["GROUP_ID"]);
//update digest hash for http digest authorization
if(isset($arUser["ID"]) && is_set($arFields, "PASSWORD") && COption::GetOptionString('main', 'use_digest_auth', 'N') == 'Y')
{
/** @noinspection PhpUndefinedVariableInspection */
CUser::UpdateDigest($arUser["ID"], $original_pass);
}
if($arUser && $authActions == true)
{
$authAction = false;
if(isset($arFields["ACTIVE"]) && $arUser["ACTIVE"] == "Y" && $arFields["ACTIVE"] == "N")
{
$authAction = true;
}
$internalUser = true;
if(isset($arFields["EXTERNAL_AUTH_ID"]))
{
if($arFields["EXTERNAL_AUTH_ID"] <> '')
{
$internalUser = false;
}
}
elseif($arUser["EXTERNAL_AUTH_ID"] <> '')
{
$internalUser = false;
}
if($internalUser == true && isset($arFields["PASSWORD"]) && $newPassword <> $arUser["PASSWORD"])
{
$authAction = true;
if(is_object($USER) && $USER->GetID() == $ID)
{
//changed password by himself
$USER->SetParam("SELF_CHANGED_PASSWORD", true);
}
}
if($authAction)
{
Main\UserAuthActionTable::add(array(
'USER_ID' => $ID,
'PRIORITY' => Main\UserAuthActionTable::PRIORITY_HIGH,
'ACTION' => Main\UserAuthActionTable::ACTION_LOGOUT,
'ACTION_DATE' => new Main\Type\DateTime(),
));
}
}
$result = true;
$arFields["CHECKWORD"] = $checkword;
//update session information and cache for current user
if(is_object($USER) && $USER->GetID() == $ID)
{
static $arSessFields = array(
'LOGIN'=>'LOGIN', 'EMAIL'=>'EMAIL', 'TITLE'=>'TITLE', 'FIRST_NAME'=>'NAME', 'SECOND_NAME'=>'SECOND_NAME', 'LAST_NAME'=>'LAST_NAME',
'PERSONAL_PHOTO'=>'PERSONAL_PHOTO', 'PERSONAL_GENDER'=>'PERSONAL_GENDER', 'AUTO_TIME_ZONE'=>'AUTO_TIME_ZONE', 'TIME_ZONE'=>'TIME_ZONE');
foreach($arSessFields as $key => $val)
if(isset($arFields[$val]))
$USER->SetParam($key, $arFields[$val]);
$name = $USER->GetParam("FIRST_NAME");
$last_name = $USER->GetParam("LAST_NAME");
$USER->SetParam("NAME", $name.($name == '' || $last_name == ''? "":" ").$last_name);
//cache for GetByID()
self::$CURRENT_USER = false;
}
if($saveHistory && $arUser)
{
$rUser = CUser::GetByID($ID);
$newUser = $rUser->Fetch();
Main\UserProfileHistoryTable::addHistory($ID, Main\UserProfileHistoryTable::TYPE_UPDATE, $arUser, $newUser);
}
}
$arFields["ID"] = $ID;
$arFields["RESULT"] = &$result;
foreach (GetModuleEvents("main", "OnAfterUserUpdate", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array(&$arFields));
if($arFields["RESULT"] == true)
{
\Bitrix\Main\UserTable::indexRecord($ID);
if(defined("BX_COMP_MANAGED_CACHE"))
{
$userData = \Bitrix\Main\UserTable::getById($ID)->fetch();
$isRealUser = !$userData['EXTERNAL_AUTH_ID'] || !in_array($userData['EXTERNAL_AUTH_ID'], \Bitrix\Main\UserTable::getExternalUserTypes());
$CACHE_MANAGER->ClearByTag("USER_CARD_".intval($ID / TAGGED_user_card_size));
$CACHE_MANAGER->ClearByTag($isRealUser? "USER_CARD": "EXTERNAL_USER_CARD");
static $arNameFields = array("NAME", "LAST_NAME", "SECOND_NAME", "LOGIN", "EMAIL", "PERSONAL_GENDER", "PERSONAL_PHOTO", "WORK_POSITION", "PERSONAL_PROFESSION", "PERSONAL_WWW", "PERSONAL_BIRTHDAY", "TITLE", "EXTERNAL_AUTH_ID", "UF_DEPARTMENT");
$bClear = false;
foreach($arNameFields as $val)
{
if(isset($arFields[$val]))
{
$bClear = true;
break;
}
}
if ($bClear)
{
$CACHE_MANAGER->ClearByTag("USER_NAME_".$ID);
$CACHE_MANAGER->ClearByTag($isRealUser? "USER_NAME": "EXTERNAL_USER_NAME");
}
}
}
return $result;
}
public static function SetUserGroup($USER_ID, $arGroups, $newUser = false)
{
global $DB;
$USER_ID = intval($USER_ID);
if ($USER_ID === 0)
{
return false;
}
//remember previous groups of the user
$aPrevGroups = array();
$res = CUser::GetUserGroupList($USER_ID);
while($res_arr = $res->Fetch())
if($res_arr["GROUP_ID"] <> 2)
$aPrevGroups[$res_arr["GROUP_ID"]] = $res_arr;
$DB->Query("DELETE FROM b_user_group WHERE USER_ID=".$USER_ID, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$inserted = array();
if(is_array($arGroups))
{
foreach($arGroups as $group)
{
if(!is_array($group))
{
$group = array("GROUP_ID" => $group);
}
$group_id = intval($group["GROUP_ID"]);
if($group_id > 0 && $group_id <> 2 && !isset($inserted[$group_id]))
{
$arInsert = $DB->PrepareInsert("b_user_group", $group);
$strSql = "
INSERT INTO b_user_group (
USER_ID, ".$arInsert[0]."
) VALUES (
".$USER_ID.",
".$arInsert[1]."
)
";
$DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$inserted[$group_id] = $group;
}
}
}
self::clearUserGroupCache($USER_ID);
foreach (GetModuleEvents("main", "OnAfterSetUserGroup", true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, array("USER_ID"=>$USER_ID, "GROUPS"=>$inserted));
}
if($aPrevGroups <> $inserted)
{
if($newUser == false)
{
$authActionCommon = false;
$now = new Main\Type\DateTime();
foreach($inserted as $group)
{
foreach(array("DATE_ACTIVE_FROM", "DATE_ACTIVE_TO") as $field)
{
if($group[$field] <> '')
{
$date = Main\Type\DateTime::createFromUserTime($group[$field]);
if($date > $now)
{
//group membership is in the future, we need separate records for each group
Main\UserAuthActionTable::add(array(
'USER_ID' => $USER_ID,
'PRIORITY' => Main\UserAuthActionTable::PRIORITY_LOW,
'ACTION' => Main\UserAuthActionTable::ACTION_UPDATE,
'ACTION_DATE' => $date,
));
}
else
{
$authActionCommon = true;
}
}
else
{
$authActionCommon = true;
}
}
}
if($authActionCommon == true)
{
//one action for all groups without dates in the future
Main\UserAuthActionTable::add(array(
'USER_ID' => $USER_ID,
'PRIORITY' => Main\UserAuthActionTable::PRIORITY_LOW,
'ACTION' => Main\UserAuthActionTable::ACTION_UPDATE,
'ACTION_DATE' => new Main\Type\DateTime(),
));
}
}
if(COption::GetOptionString("main", "event_log_user_groups", "N") === "Y")
{
$UserName = '';
$rsUser = CUser::GetByID($USER_ID);
if($arUser = $rsUser->GetNext())
$UserName = ($arUser["NAME"] != "" || $arUser["LAST_NAME"] != "") ? trim($arUser["NAME"]." ".$arUser["LAST_NAME"]) : $arUser["LOGIN"];
$res_log = array(
"groups" => serialize($aPrevGroups)." => ".serialize($inserted),
"user" => $UserName
);
CEventLog::Log("SECURITY", "USER_GROUP_CHANGED", "main", $USER_ID, serialize($res_log));
}
}
return null;
}
/**
* Appends groups to the list of existing user's groups.
*
* @param int $user_id
* @param array|int $groups A single number, or an array of numbers, or an array of arrays("GROUP_ID"=>$val, "DATE_ACTIVE_FROM"=>$val, "DATE_ACTIVE_TO"=>$val)
*/
public static function AppendUserGroup($user_id, $groups)
{
$arGroups = array();
$res = CUser::GetUserGroupList($user_id);
while($res_arr = $res->Fetch())
{
$arGroups[] = array(
"GROUP_ID" => $res_arr["GROUP_ID"],
"DATE_ACTIVE_FROM" => $res_arr["DATE_ACTIVE_FROM"],
"DATE_ACTIVE_TO" => $res_arr["DATE_ACTIVE_TO"],
);
}
if(!is_array($groups))
{
$groups = array($groups);
}
foreach($groups as $group)
{
if(!is_array($group))
{
$group = array("GROUP_ID" => $group);
}
$arGroups[] = $group;
}
CUser::SetUserGroup($user_id, $arGroups);
}
public static function GetCount()
{
global $DB;
$r = $DB->Query("SELECT COUNT('x') as C FROM b_user");
$r = $r->Fetch();
return Intval($r["C"]);
}
public static function Delete($ID)
{
/** @global CMain $APPLICATION */
/** @global CUserTypeManager $USER_FIELD_MANAGER */
global $DB, $APPLICATION, $USER_FIELD_MANAGER, $CACHE_MANAGER;
$ID = intval($ID);
@set_time_limit(600);
$rsUser = $DB->Query("SELECT ID, LOGIN, NAME, LAST_NAME, EXTERNAL_AUTH_ID FROM b_user WHERE ID=".$ID." AND ID<>1");
$arUser = $rsUser->Fetch();
if(!$arUser)
return false;
foreach(GetModuleEvents("main", "OnBeforeUserDelete", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array($ID))===false)
{
$err = GetMessage("MAIN_BEFORE_DEL_ERR").' '.$arEvent['TO_NAME'];
if($ex = $APPLICATION->GetException())
$err .= ': '.$ex->GetString();
$APPLICATION->throwException($err);
if(COption::GetOptionString("main", "event_log_user_delete", "N") === "Y")
{
$UserName = ($arUser["NAME"] != "" || $arUser["LAST_NAME"] != "") ? trim($arUser["NAME"]." ".$arUser["LAST_NAME"]) : $arUser["LOGIN"];
$res_log = array(
"user" => $UserName,
"err" => $err
);
CEventLog::Log("SECURITY", "USER_DELETE", "main", $ID, serialize($res_log));
}
return false;
}
}
foreach(GetModuleEvents("main", "OnUserDelete", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array($ID))===false)
{
$err = GetMessage("MAIN_BEFORE_DEL_ERR").' '.$arEvent['TO_NAME'];
if($ex = $APPLICATION->GetException())
$err .= ': '.$ex->GetString();
$APPLICATION->throwException($err);
if(COption::GetOptionString("main", "event_log_user_delete", "N") === "Y")
{
$UserName = ($arUser["NAME"] != "" || $arUser["LAST_NAME"] != "") ? trim($arUser["NAME"]." ".$arUser["LAST_NAME"]) : $arUser["LOGIN"];
$res_log = array(
"user" => $UserName,
"err" => $err
);
CEventLog::Log("SECURITY", "USER_DELETE", "main", $ID, serialize($res_log));
}
return false;
}
}
$strSql = "SELECT F.ID FROM b_user U, b_file F WHERE U.ID='$ID' and (F.ID=U.PERSONAL_PHOTO or F.ID=U.WORK_LOGO)";
$z = $DB->Query($strSql, false, "FILE: ".__FILE__." LINE:".__LINE__);
while ($zr = $z->Fetch())
CFile::Delete($zr["ID"]);
if(!$DB->Query("DELETE FROM b_user_group WHERE USER_ID=".$ID))
return false;
if(!$DB->Query("DELETE FROM b_user_digest WHERE USER_ID=".$ID))
return false;
if(!$DB->Query("DELETE FROM b_app_password WHERE USER_ID=".$ID))
return false;
$USER_FIELD_MANAGER->Delete("USER", $ID);
if(COption::GetOptionString("main", "event_log_user_delete", "N") === "Y")
{
$res_log["user"] = ($arUser["NAME"] != "" || $arUser["LAST_NAME"] != "") ? trim($arUser["NAME"]." ".$arUser["LAST_NAME"]) : $arUser["LOGIN"];
CEventLog::Log("SECURITY", "USER_DELETE", "main", $arUser["LOGIN"], serialize($res_log));
}
if(!$DB->Query("DELETE FROM b_user WHERE ID=".$ID." AND ID<>1"))
return false;
if(defined("BX_COMP_MANAGED_CACHE"))
{
$isRealUser = !$arUser['EXTERNAL_AUTH_ID'] || !in_array($arUser['EXTERNAL_AUTH_ID'], \Bitrix\Main\UserTable::getExternalUserTypes());
$CACHE_MANAGER->ClearByTag("USER_CARD_".intval($ID / TAGGED_user_card_size));
$CACHE_MANAGER->ClearByTag($isRealUser? "USER_CARD": "EXTERNAL_USER_CARD");
$CACHE_MANAGER->ClearByTag("USER_NAME_".$ID);
$CACHE_MANAGER->ClearByTag($isRealUser? "USER_NAME": "EXTERNAL_USER_CARD");
}
self::clearUserGroupCache($ID);
Main\UserAuthActionTable::add(array(
'USER_ID' => $ID,
'PRIORITY' => Main\UserAuthActionTable::PRIORITY_HIGH,
'ACTION' => Main\UserAuthActionTable::ACTION_LOGOUT,
'ACTION_DATE' => new Main\Type\DateTime(),
));
if(Main\Config\Option::get("main", "user_profile_history") === "Y")
{
Main\UserProfileHistoryTable::deleteByUser($ID);
Main\UserProfileHistoryTable::addHistory($ID, Main\UserProfileHistoryTable::TYPE_DELETE);
}
\Bitrix\Main\UserTable::deleteIndexRecord($ID);
foreach(GetModuleEvents("main", "OnAfterUserDelete", true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, array($ID));
}
return true;
}
public static function GetExternalAuthList()
{
$arAll = array();
foreach(GetModuleEvents("main", "OnExternalAuthList", true) as $arEvent)
{
$arRes = ExecuteModuleEventEx($arEvent);
if(is_array($arRes))
{
foreach($arRes as $v)
{
$arAll[] = $v;
}
}
}
$result = new CDBResult;
$result->InitFromArray($arAll);
return $result;
}
public static function GetGroupPolicy($iUserId)
{
global $DB;
static $arPOLICY_CACHE;
if(!is_array($arPOLICY_CACHE))
$arPOLICY_CACHE = array();
$CACHE_ID = md5(serialize($iUserId));
if(array_key_exists($CACHE_ID, $arPOLICY_CACHE))
return $arPOLICY_CACHE[$CACHE_ID];
global $BX_GROUP_POLICY;
$arPolicy = $BX_GROUP_POLICY;
if($arPolicy["SESSION_TIMEOUT"]<=0)
$arPolicy["SESSION_TIMEOUT"] = ini_get("session.gc_maxlifetime")/60;
$arSql = array();
$arSql[] =
"SELECT G.SECURITY_POLICY ".
"FROM b_group G ".
"WHERE G.ID=2";
if(is_array($iUserId))
{
$arGroups = array();
foreach($iUserId as $value)
{
$value = intval($value);
if($value > 0 && $value != 2)
$arGroups[$value] = $value;
}
if(count($arGroups) > 0)
{
$arSql[] =
"SELECT G.ID GROUP_ID, G.SECURITY_POLICY ".
"FROM b_group G ".
"WHERE G.ID in (".implode(", ", $arGroups).")";
}
}
elseif(intval($iUserId) > 0)
{
$arSql[] =
"SELECT UG.GROUP_ID, G.SECURITY_POLICY ".
"FROM b_user_group UG, b_group G ".
"WHERE UG.USER_ID = ".intval($iUserId)." ".
" AND UG.GROUP_ID = G.ID ".
" AND ((UG.DATE_ACTIVE_FROM IS NULL) OR (UG.DATE_ACTIVE_FROM <= ".$DB->CurrentTimeFunction().")) ".
" AND ((UG.DATE_ACTIVE_TO IS NULL) OR (UG.DATE_ACTIVE_TO >= ".$DB->CurrentTimeFunction().")) ";
}
foreach($arSql as $strSql)
{
$res = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
while($ar = $res->Fetch())
{
if($ar["SECURITY_POLICY"])
$arGroupPolicy = unserialize($ar["SECURITY_POLICY"]);
else
continue;
if(!is_array($arGroupPolicy))
continue;
foreach($arGroupPolicy as $key=>$val)
{
switch($key)
{
case "STORE_IP_MASK":
case "SESSION_IP_MASK":
if($arPolicy[$key]<$val)
$arPolicy[$key] = $val;
break;
case "SESSION_TIMEOUT":
if($arPolicy[$key]<=0 || $arPolicy[$key]>$val)
$arPolicy[$key] = $val;
break;
case "PASSWORD_LENGTH":
if($arPolicy[$key]<=0 || $arPolicy[$key] < $val)
$arPolicy[$key] = $val;
break;
case "PASSWORD_UPPERCASE":
case "PASSWORD_LOWERCASE":
case "PASSWORD_DIGITS":
case "PASSWORD_PUNCTUATION":
if($val === "Y")
$arPolicy[$key] = "Y";
break;
case "LOGIN_ATTEMPTS":
if($val > 0 && ($arPolicy[$key] <= 0 || $arPolicy[$key] > $val))
$arPolicy[$key] = $val;
break;
default:
if($arPolicy[$key]>$val)
$arPolicy[$key] = $val;
}
}
}
if($arPolicy["PASSWORD_LENGTH"] === false)
$arPolicy["PASSWORD_LENGTH"] = 6;
}
$ar = array(
GetMessage("MAIN_GP_PASSWORD_LENGTH", array("#LENGTH#" => intval($arPolicy["PASSWORD_LENGTH"])))
);
if($arPolicy["PASSWORD_UPPERCASE"] === "Y")
$ar[] = GetMessage("MAIN_GP_PASSWORD_UPPERCASE");
if($arPolicy["PASSWORD_LOWERCASE"] === "Y")
$ar[] = GetMessage("MAIN_GP_PASSWORD_LOWERCASE");
if($arPolicy["PASSWORD_DIGITS"] === "Y")
$ar[] = GetMessage("MAIN_GP_PASSWORD_DIGITS");
if($arPolicy["PASSWORD_PUNCTUATION"] === "Y")
$ar[] = GetMessage("MAIN_GP_PASSWORD_PUNCTUATION");
$arPolicy["PASSWORD_REQUIREMENTS"] = implode(", ", $ar).".";
if(count($arPOLICY_CACHE)<=10)
$arPOLICY_CACHE[$CACHE_ID] = $arPolicy;
return $arPolicy;
}
public static function CheckStoredHash($iUserId, $sHash, $bTempHashOnly=false)
{
global $DB;
$arPolicy = CUser::GetGroupPolicy($iUserId);
$cnt = 0;
$auth_id = false;
$site_format = CSite::GetDateFormat();
CTimeZone::Disable();
$strSql =
"SELECT A.*, ".
" ".$DB->DateToCharFunction("A.DATE_REG", "FULL")." as DATE_REG, ".
" ".$DB->DateToCharFunction("A.LAST_AUTH", "FULL")." as LAST_AUTH ".
"FROM b_user_stored_auth A ".
"WHERE A.USER_ID = ".intval($iUserId)." ".
"ORDER BY A.LAST_AUTH DESC";
$res = $DB->Query($strSql);
CTimeZone::Enable();
while($ar = $res->Fetch())
{
if($ar["TEMP_HASH"]=="N")
$cnt++;
if($arPolicy["MAX_STORE_NUM"] < $cnt
|| ($ar["TEMP_HASH"]=="N" && time()-$arPolicy["STORE_TIMEOUT"]*60 > MakeTimeStamp($ar["LAST_AUTH"], $site_format))
|| ($ar["TEMP_HASH"]=="Y" && time()-$arPolicy["SESSION_TIMEOUT"]*60 > MakeTimeStamp($ar["LAST_AUTH"], $site_format))
)
{
$DB->Query("DELETE FROM b_user_stored_auth WHERE ID=".$ar["ID"]);
}
elseif(!$auth_id)
{
//for domain spreaded external auth we should check only temporary hashes
if($bTempHashOnly == false || $ar["TEMP_HASH"] == "Y")
{
$remote_net = ip2long($arPolicy["STORE_IP_MASK"]) & ip2long($_SERVER["REMOTE_ADDR"]);
$stored_net = ip2long($arPolicy["STORE_IP_MASK"]) & (float)$ar["IP_ADDR"];
if($sHash == $ar["STORED_HASH"] && $remote_net == $stored_net)
$auth_id = $ar["ID"];
}
}
}
return $auth_id;
}
public function GetAllOperations($arGroups = false)
{
global $DB;
if ($arGroups)
{
$userGroups = "2,".implode(",", array_map("intval", $arGroups));
}
else
{
$userGroups = $this->GetGroups();
}
$sql_str = "
SELECT O.NAME OPERATION_NAME
FROM b_group_task GT
INNER JOIN b_task_operation T_O ON T_O.TASK_ID=GT.TASK_ID
INNER JOIN b_operation O ON O.ID=T_O.OPERATION_ID
WHERE GT.GROUP_ID IN(".$userGroups.")
UNION
SELECT O.NAME OPERATION_NAME
FROM b_option OP
INNER JOIN b_task_operation T_O ON T_O.TASK_ID=".$DB->ToChar("OP.VALUE", 18)."
INNER JOIN b_operation O ON O.ID=T_O.OPERATION_ID
WHERE OP.NAME='GROUP_DEFAULT_TASK'
UNION
SELECT O.NAME OPERATION_NAME
FROM b_option OP
INNER JOIN b_task T ON T.MODULE_ID=OP.MODULE_ID AND T.BINDING='module' AND T.LETTER=".$DB->ToChar("OP.VALUE", 1)." AND T.SYS='Y'
INNER JOIN b_task_operation T_O ON T_O.TASK_ID=T.ID
INNER JOIN b_operation O ON O.ID=T_O.OPERATION_ID
WHERE OP.NAME='GROUP_DEFAULT_RIGHT'
";
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$arr = array();
while($r = $z->Fetch())
$arr[$r['OPERATION_NAME']] = $r['OPERATION_NAME'];
return $arr;
}
public function CanDoOperation($op_name, $user_id = 0)
{
if ($user_id > 0)
{
$arGroups = array();
$rsGroups = $this->GetUserGroupEx($user_id);
while ($group = $rsGroups->Fetch())
{
$arGroups[] = $group["GROUP_ID"];
}
if (!$arGroups)
return false;
$op = $this->GetAllOperations($arGroups);
return isset($op[$op_name]);
}
else
{
if ($this->IsAdmin())
return true;
if(!isset($_SESSION["SESS_OPERATIONS"]))
$_SESSION["SESS_OPERATIONS"] = $this->GetAllOperations();
return isset($_SESSION["SESS_OPERATIONS"][$op_name]);
}
}
public static function GetFileOperations($arPath, $arGroups=false)
{
/** @global CMain $APPLICATION */
global $APPLICATION;
$ar = $APPLICATION->GetFileAccessPermission($arPath, $arGroups, true);
$arFileOperations = array();
for ($i = 0, $len = count($ar); $i < $len; $i++)
$arFileOperations = array_merge($arFileOperations, CTask::GetOperations($ar[$i], true));
$arFileOperations = array_values(array_unique($arFileOperations));
return $arFileOperations;
}
public function CanDoFileOperation($op_name, $arPath)
{
global $APPLICATION, $USER;
if ($this->IsAdmin())
return true;
if(!isset($APPLICATION->FILEMAN_OPERATION_CACHE))
$APPLICATION->FILEMAN_OPERATION_CACHE = array();
$k = addslashes($arPath[0].'|'.$arPath[1]);
if(array_key_exists($k, $APPLICATION->FILEMAN_OPERATION_CACHE))
{
$arFileOperations = $APPLICATION->FILEMAN_OPERATION_CACHE[$k];
}
else
{
$arFileOperations = $this->GetFileOperations($arPath);
$APPLICATION->FILEMAN_OPERATION_CACHE[$k] = $arFileOperations;
}
$arAlowedOperations = array('fm_delete_file','fm_rename_folder','fm_view_permission');
if(substr($arPath[1], -10)=="/.htaccess" && !$USER->CanDoOperation('edit_php') && !in_array($op_name,$arAlowedOperations))
return false;
if(substr($arPath[1], -12)=="/.access.php")
return false;
return in_array($op_name, $arFileOperations);
}
public static function UserTypeRightsCheck($entity_id)
{
global $USER;
if($entity_id == "USER" && $USER->CanDoOperation('edit_other_settings'))
{
return "W";
}
else
return "D";
}
public function CanAccess($arCodes)
{
if(!is_array($arCodes) || empty($arCodes))
return false;
if(in_array('G2', $arCodes))
return true;
if($this->IsAuthorized() && in_array('AU', $arCodes))
return true;
$bEmpty = true;
foreach($arCodes as $code)
{
if(trim($code) <> '')
{
$bEmpty = false;
break;
}
}
if($bEmpty)
return false;
$res = CAccess::GetUserCodes($this->GetID(), array("ACCESS_CODE"=>$arCodes));
if($res->Fetch())
return true;
return false;
}
public function GetAccessCodes()
{
if(!$this->IsAuthorized())
return array('G2');
static $arCodes = array();
$USER_ID = intval($this->GetID());
if(!array_key_exists($USER_ID, $arCodes))
{
$arCodes[$USER_ID] = CAccess::GetUserCodesArray($USER_ID);
if($this->IsAuthorized())
$arCodes[$USER_ID][] = "AU";
}
return $arCodes[$USER_ID];
}
public static function CleanUpAgent()
{
$bTmpUser = false;
if (!isset($GLOBALS["USER"]) || !is_object($GLOBALS["USER"]))
{
$bTmpUser = true;
$GLOBALS["USER"] = new CUser;
}
$cleanup_days = COption::GetOptionInt("main", "new_user_registration_cleanup_days", 7);
if($cleanup_days > 0 && COption::GetOptionString("main", "new_user_registration_email_confirmation", "N") === "Y")
{
$arDate = localtime(time());
$date = mktime(0, 0, 0, $arDate[4]+1, $arDate[3]-$cleanup_days, 1900+$arDate[5]);
$arFilter = array(
"!CONFIRM_CODE" => false,
"ACTIVE" => "N",
"DATE_REGISTER_2" => ConvertTimeStamp($date),
);
$rsUsers = CUser::GetList(($by=""), ($order=""), $arFilter);
while($arUser = $rsUsers->Fetch())
{
CUser::Delete($arUser["ID"]);
}
}
if ($bTmpUser)
{
unset($GLOBALS["USER"]);
}
return "CUser::CleanUpAgent();";
}
public static function GetActiveUsersCount()
{
global $DB;
$q = "SELECT COUNT(ID) as C FROM b_user WHERE ACTIVE = 'Y' AND LAST_LOGIN IS NOT NULL";
if (IsModuleInstalled("intranet"))
$q = "SELECT COUNT(U.ID) as C FROM b_user U WHERE U.ACTIVE = 'Y' AND U.LAST_LOGIN IS NOT NULL AND EXISTS(SELECT 'x' FROM b_utm_user UF, b_user_field F WHERE F.ENTITY_ID = 'USER' AND F.FIELD_NAME = 'UF_DEPARTMENT' AND UF.FIELD_ID = F.ID AND UF.VALUE_ID = U.ID AND UF.VALUE_INT IS NOT NULL AND UF.VALUE_INT <> 0)";
$dbRes = $DB->Query($q, true);
if ($dbRes && ($arRes = $dbRes->Fetch()))
return $arRes["C"];
else
return 0;
}
public static function SetLastActivityDate($userId = null, $cache = false)
{
global $USER;
if (is_null($userId))
{
$userId = $USER->GetId();
}
$userId = intval($userId);
if ($userId <= 0)
{
return false;
}
if($userId == $USER->GetId())
{
$_SESSION['SESS_AUTH']['PREV_LAST_ACTIVITY'] = $_SESSION['SESS_AUTH']['SET_LAST_ACTIVITY'];
if ($cache)
{
if (
isset($_SESSION['SESS_AUTH']['SET_LAST_ACTIVITY'])
&& intval($_SESSION['SESS_AUTH']['SET_LAST_ACTIVITY'])+60 > time()
)
{
return false;
}
}
$_SESSION['SESS_AUTH']['SET_LAST_ACTIVITY'] = time();
}
self::SetLastActivityDateByArray(array($userId), $_SERVER['REMOTE_ADDR']);
return true;
}
public static function SetLastActivityDateByArray($arUsers, $ip = null)
{
global $DB;
if (!is_array($arUsers) || count($arUsers) <= 0)
return false;
$strSqlPrefix = "UPDATE b_user SET ".
"TIMESTAMP_X = ".(strtoupper($DB->type) == "ORACLE"? "NULL":"TIMESTAMP_X").", ".
"LAST_ACTIVITY_DATE = ".$DB->CurrentTimeFunction()." WHERE ID IN (";
$strSqlPostfix = ")";
$maxValuesLen = 2048;
$strSqlValues = "";
$arUsers = array_map("intval", $arUsers);
foreach($arUsers as $userId)
{
$strSqlValues .= ",$userId";
if(strlen($strSqlValues) > $maxValuesLen)
{
$DB->Query($strSqlPrefix.substr($strSqlValues, 1).$strSqlPostfix, false, "", array("ignore_dml"=>true));
$strSqlValues = "";
}
}
if(strlen($strSqlValues) > 0)
{
$DB->Query($strSqlPrefix.substr($strSqlValues, 1).$strSqlPostfix, false, "", array("ignore_dml"=>true));
}
$event = new \Bitrix\Main\Event("main", "OnUserSetLastActivityDate", array($arUsers, $ip));
$event->send();
return true;
}
public static function GetSecondsForLimitOnline()
{
return \Bitrix\Main\UserTable::getSecondsForLimitOnline();
}
public static function GetExternalUserTypes()
{
return Main\UserTable::getExternalUserTypes();
}
public static function GetOnlineStatus($userId, $lastseen, $now = false)
{
$userId = intval($userId);
if ($lastseen instanceof \Bitrix\Main\Type\DateTime)
{
$lastseen = $lastseen->getTimestamp();
}
else if (is_int($lastseen))
{
$lastseen = intval($lastseen);
}
else
{
$lastseen = 0;
}
if ($now === false)
{
$now = time();
}
else if ($now instanceof \Bitrix\Main\Type\DateTime)
{
$now = $now->getTimestamp();
}
else
{
$now = intval($now);
}
$result = Array(
'IS_ONLINE' => false,
'STATUS' => self::STATUS_OFFLINE,
'STATUS_TEXT' => GetMessage('USER_STATUS_OFFLINE'),
'LAST_SEEN' => $lastseen,
'LAST_SEEN_TEXT' => "",
'NOW' => $now,
);
if ($lastseen === false)
{
return $result;
}
$result['IS_ONLINE'] = $now - $lastseen <= self::GetSecondsForLimitOnline();
$result['STATUS'] = $result['IS_ONLINE']? self::STATUS_ONLINE: self::STATUS_OFFLINE;
$result['STATUS_TEXT'] = GetMessage('USER_STATUS_'.strtoupper($result['STATUS']));
if ($lastseen && $now - $lastseen > 300)
{
$result['LAST_SEEN_TEXT'] = self::FormatLastActivityDate($lastseen, $now);
}
if ($userId > 0)
{
if ($result['IS_ONLINE'])
{
foreach(GetModuleEvents("main", "OnUserOnlineStatusGetCustomOnlineStatus", true) as $arEvent)
{
$customStatus = ExecuteModuleEventEx($arEvent, array($userId, $lastseen, $now, self::STATUS_ONLINE));
if (is_array($customStatus))
{
if (!empty($customStatus['STATUS']) && !empty($customStatus['STATUS_TEXT']))
{
$result['STATUS'] = strtolower($customStatus['STATUS']);
$result['STATUS_TEXT'] = $customStatus['STATUS_TEXT'];
}
if (isset($customStatus['LAST_SEEN']) && intval($customStatus['LAST_SEEN']) > 0)
{
$result['LAST_SEEN'] = intval($customStatus['LAST_SEEN']);
}
if (isset($customStatus['LAST_SEEN_TEXT']))
{
$result['LAST_SEEN_TEXT'] = $customStatus['LAST_SEEN_TEXT'];
}
}
}
}
else
{
foreach(GetModuleEvents("main", "OnUserOnlineStatusGetCustomOfflineStatus", true) as $arEvent)
{
$customStatus = ExecuteModuleEventEx($arEvent, array($userId, $lastseen, $now, self::STATUS_OFFLINE));
if (is_array($customStatus))
{
if (!empty($customStatus['STATUS']) && !empty($customStatus['STATUS_TEXT']))
{
$result['STATUS'] = strtolower($customStatus['STATUS']);
$result['STATUS_TEXT'] = $customStatus['STATUS_TEXT'];
}
if (isset($customStatus['LAST_SEEN']) && intval($customStatus['LAST_SEEN']) > 0)
{
$result['LAST_SEEN'] = intval($customStatus['LAST_SEEN']);
}
if (isset($customStatus['LAST_SEEN_TEXT']))
{
$result['LAST_SEEN_TEXT'] = $customStatus['LAST_SEEN_TEXT'];
}
}
}
}
}
return $result;
}
/**
* @param int|bool|\Bitrix\Main\Type\DateTime $timestamp
* @param int|bool|\Bitrix\Main\Type\DateTime $now
*
* @return string
*/
public static function FormatLastActivityDate($timestamp, $now = false)
{
global $DB;
if ($timestamp instanceof \Bitrix\Main\Type\DateTime)
{
$timestamp = $timestamp->getTimestamp();
}
else if (is_int($timestamp))
{
$timestamp = intval($timestamp);
}
else
{
return "";
}
if ($now === false)
{
$now = time();
}
else if ($now instanceof \Bitrix\Main\Type\DateTime)
{
$now = $now->getTimestamp();
}
else
{
$now = intval($now);
}
$ampm = IsAmPmMode(true);
$timeFormat = ($ampm === AM_PM_LOWER? "g:i a" : ($ampm === AM_PM_UPPER? "g:i A" : "H:i"));
$formattedDate = FormatDate(array(
"tomorrow" => "#01#{$timeFormat}",
"now" => "#02#",
"todayFuture" => "#03#{$timeFormat}",
"yesterday" => "#04#{$timeFormat}",
"-" => preg_replace('/:s$/', '', $DB->DateFormatToPHP(CSite::GetDateFormat("FULL"))),
"s60" => "sago",
"i60" => "iago",
"H5" => "Hago",
"H24" => "#03#{$timeFormat}",
"d31" => "dago",
"m12>1" => "mago",
"m12>0" => "dago",
"" => "#05#",
), $timestamp, $now);
if (preg_match('/^#(\d+)#(.*)/', $formattedDate, $match))
{
switch($match[1])
{
case "01":
$formattedDate = str_replace("#TIME#", $match[2], GetMessage('USER_LAST_SEEN_TOMORROW'));
break;
case "02":
$formattedDate = GetMessage('USER_LAST_SEEN_NOW');
break;
case "03":
$formattedDate = str_replace("#TIME#", $match[2], GetMessage('USER_LAST_SEEN_TODAY'));
break;
case "04":
$formattedDate = str_replace("#TIME#", $match[2], GetMessage('USER_LAST_SEEN_YESTERDAY'));
break;
case "05":
$formattedDate = GetMessage('USER_LAST_SEEN_MORE_YEAR');
break;
default:
$formattedDate = $match[2];
break;
}
}
return $formattedDate;
}
public static function SearchUserByName($arName, $email = "", $bLoginMode = false)
{
global $DB;
$arNameReady = array();
foreach ($arName as $s)
{
$s = Trim($s);
if (StrLen($s) > 0)
$arNameReady[] = $s;
}
if (Count($arNameReady) <= 0)
return false;
$strSqlWhereEMail = ((StrLen($email) > 0) ? " AND upper(U.EMAIL) = upper('".$DB->ForSql($email)."') " : "");
if ($bLoginMode)
{
if (count($arNameReady) > 3)
{
$strSql =
"SELECT U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.EMAIL ".
"FROM b_user U ".
"WHERE (";
$bFirst = true;
for ($i = 0; $i < 4; $i++)
{
for ($j = 0; $j < 4; $j++)
{
if ($i == $j)
continue;
for ($k = 0; $k < 4; $k++)
{
if ($i == $k || $j == $k)
continue;
for ($l = 0; $l < 4; $l++)
{
if ($i == $l || $j == $l || $k == $l)
continue;
if (!$bFirst)
$strSql .= " OR ";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$j])."%') ".
"AND U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[$k])."%') ".
"AND U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[$l])."%'))";
$bFirst = false;
}
}
}
}
$strSql .= ")";
}
elseif (Count($arNameReady) == 3)
{
$strSql =
"SELECT U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.EMAIL ".
"FROM b_user U ".
"WHERE (";
$bFirst = true;
for ($i = 0; $i < 3; $i++)
{
for ($j = 0; $j < 3; $j++)
{
if ($i == $j)
continue;
for ($k = 0; $k < 3; $k++)
{
if ($i == $k || $j == $k)
continue;
if (!$bFirst)
$strSql .= " OR ";
$strSql .= "(";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$j])."%') ".
"AND U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[$k])."%'))";
$strSql .= " OR ";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$j])."%') ".
"AND U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[$k])."%'))";
$strSql .= " OR ";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[$j])."%') ".
"AND U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[$k])."%'))";
$strSql .= " OR ";
$strSql .= "(U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[$j])."%') ".
"AND U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[$k])."%'))";
$strSql .= ")";
$bFirst = false;
}
}
}
$strSql .= ")";
}
elseif (Count($arNameReady) == 2)
{
$strSql =
"SELECT U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.EMAIL ".
"FROM b_user U ".
"WHERE (";
$bFirst = true;
for ($i = 0; $i < 2; $i++)
{
for ($j = 0; $j < 2; $j++)
{
if ($i == $j)
continue;
if (!$bFirst)
$strSql .= " OR ";
$strSql .= "(";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$j])."%'))";
$strSql .= " OR ";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[$j])."%'))";
$strSql .= " OR ";
$strSql .= "(U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[$j])."%'))";
$strSql .= " OR ";
$strSql .= "(U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[$j])."%'))";
$strSql .= " OR ";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[$j])."%'))";
$strSql .= " OR ";
$strSql .= "(U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[$j])."%'))";
$strSql .= ")";
$bFirst = false;
}
}
$strSql .= ")";
}
else
{
$strSql =
"SELECT U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.EMAIL ".
"FROM b_user U ".
"WHERE (U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[0])."%') ".
" OR U.LOGIN IS NOT NULL AND upper(U.LOGIN) LIKE upper('".$DB->ForSql($arNameReady[0])."%') ".
" OR U.EMAIL IS NOT NULL AND upper(U.EMAIL) LIKE upper('".$DB->ForSql($arNameReady[0])."%') ".
" OR U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[0])."%')) ";
}
$strSql .= $strSqlWhereEMail;
}
else
{
if (Count($arNameReady) >= 3)
{
$strSql =
"SELECT U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.EMAIL ".
"FROM b_user U ".
"WHERE ";
$bFirst = true;
for ($i = 0; $i < 3; $i++)
{
for ($j = 0; $j < 3; $j++)
{
if ($i == $j)
continue;
for ($k = 0; $k < 3; $k++)
{
if ($i == $k || $j == $k)
continue;
if (!$bFirst)
$strSql .= " OR ";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$j])."%') ".
"AND U.SECOND_NAME IS NOT NULL AND upper(U.SECOND_NAME) LIKE upper('".$DB->ForSql($arNameReady[$k])."%')".$strSqlWhereEMail.")";
$bFirst = false;
}
}
}
}
elseif (Count($arNameReady) == 2)
{
$strSql =
"SELECT U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.EMAIL ".
"FROM b_user U ".
"WHERE ";
$bFirst = true;
for ($i = 0; $i < 2; $i++)
{
for ($j = 0; $j < 2; $j++)
{
if ($i == $j)
continue;
if (!$bFirst)
$strSql .= " OR ";
$strSql .= "(U.NAME IS NOT NULL AND upper(U.NAME) LIKE upper('".$DB->ForSql($arNameReady[$i])."%') ".
"AND U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[$j])."%')".$strSqlWhereEMail.")";
$bFirst = false;
}
}
}
else
{
$strSql =
"SELECT U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.EMAIL ".
"FROM b_user U ".
"WHERE U.LAST_NAME IS NOT NULL AND upper(U.LAST_NAME) LIKE upper('".$DB->ForSql($arNameReady[0])."%') ".
$strSqlWhereEMail;
}
}
$dbRes = $DB->Query($strSql);
return $dbRes;
}
public static function FormatName($NAME_TEMPLATE, $arUser, $bUseLogin = false, $bHTMLSpec = true)
{
if (isset($arUser["ID"]))
$ID = intval($arUser['ID']);
else
$ID = '';
$NAME_SHORT = ($arUser['NAME'] <> ''? substr($arUser['NAME'], 0, 1).'.' : '');
$LAST_NAME_SHORT = ($arUser['LAST_NAME'] <> ''? substr($arUser['LAST_NAME'], 0, 1).'.' : '');
$SECOND_NAME_SHORT = ($arUser['SECOND_NAME'] <> ''? substr($arUser['SECOND_NAME'], 0, 1).'.' : '');
$res = str_replace(
array('#TITLE#', '#NAME#', '#LAST_NAME#', '#SECOND_NAME#', '#NAME_SHORT#', '#LAST_NAME_SHORT#', '#SECOND_NAME_SHORT#', '#EMAIL#', '#ID#'),
array($arUser['TITLE'], $arUser['NAME'], $arUser['LAST_NAME'], $arUser['SECOND_NAME'], $NAME_SHORT, $LAST_NAME_SHORT, $SECOND_NAME_SHORT, $arUser['EMAIL'], $ID),
$NAME_TEMPLATE
);
while(strpos($res, " ") !== false)
{
$res = str_replace(" ", " ", $res);
}
$res = trim($res);
$res_check = "";
if (strpos($NAME_TEMPLATE, '#NAME#') !== false || strpos($NAME_TEMPLATE, '#NAME_SHORT#') !== false)
$res_check .= $arUser['NAME'];
if (strpos($NAME_TEMPLATE, '#LAST_NAME#') !== false || strpos($NAME_TEMPLATE, '#LAST_NAME_SHORT#') !== false)
$res_check .= $arUser['LAST_NAME'];
if (strpos($NAME_TEMPLATE, '#SECOND_NAME#') !== false || strpos($NAME_TEMPLATE, '#SECOND_NAME_SHORT#') !== false)
$res_check .= $arUser['SECOND_NAME'];
if (trim($res_check) == '')
{
if ($bUseLogin && $arUser['LOGIN'] <> '')
$res = $arUser['LOGIN'];
else
$res = GetMessage('FORMATNAME_NONAME');
if (strpos($NAME_TEMPLATE, '[#ID#]') !== false)
$res .= " [".$ID."]";
}
if ($bHTMLSpec)
$res = htmlspecialcharsbx($res);
$res = str_replace(array('#NOBR#', '#/NOBR#'), '', $res);
return $res;
}
public static function clearUserGroupCache($ID = false)
{
if ($ID === false)
{
self::$userGroupCache = array();
}
else
{
$ID = (int)$ID;
if (isset(self::$userGroupCache[$ID]))
unset(self::$userGroupCache[$ID]);
}
}
public function CheckAuthActions()
{
if(!$this->IsAuthorized())
{
return;
}
if(!is_array($_SESSION["AUTH_ACTIONS_PERFORMED"]))
{
$_SESSION["AUTH_ACTIONS_PERFORMED"] = array();
}
$user_id = $this->GetID();
//calculate a session lifetime
$policy = $this->GetSecurityPolicy();
$phpSessTimeout = ini_get("session.gc_maxlifetime");
if($policy["SESSION_TIMEOUT"] > 0)
{
$interval = min($policy["SESSION_TIMEOUT"]*60, $phpSessTimeout);
}
else
{
$interval = $phpSessTimeout;
}
$now = new Main\Type\DateTime();
$date = new Main\Type\DateTime();
$date->add("-T".$interval."S");
$actions = Main\UserAuthActionTable::getList(array(
"filter" => array("=USER_ID" => $user_id),
"order" => array("USER_ID" => "ASC", "PRIORITY" => "ASC", "ID" => "DESC"),
"cache" => array("ttl" => 3600),
));
$deleted = false;
while($action = $actions->fetch())
{
if($deleted == false)
{
//clear expired records for the user
Main\UserAuthActionTable::deleteByFilter(array(
"=USER_ID" => $user_id,
"<ACTION_DATE" => $date,
));
$deleted = true;
}
if(isset($_SESSION["AUTH_ACTIONS_PERFORMED"][$action["ID"]]))
{
//already processed the action in this session
continue;
}
/** @var Main\Type\DateTime() $actionDate */
$actionDate = $action["ACTION_DATE"];
if($actionDate >= $date && $actionDate <= $now)
{
//remember that we already did the action
$_SESSION["AUTH_ACTIONS_PERFORMED"][$action["ID"]] = true;
if($this->IsJustAuthorized())
{
//no need to update the session
continue;
}
switch($action["ACTION"])
{
case Main\UserAuthActionTable::ACTION_LOGOUT:
if($this->GetParam("SELF_CHANGED_PASSWORD") == true)
{
//user's changed password by himself, skip logout
$this->SetParam("SELF_CHANGED_PASSWORD", false);
break;
}
//redirect is possible
$this->Logout();
break;
case Main\UserAuthActionTable::ACTION_UPDATE:
$this->UpdateSessionData($user_id, $this->GetParam("APPLICATION_ID"));
break;
}
//we need to process only the first action by proirity
break;
}
}
}
public static function AuthActionsCleanUpAgent()
{
$date = new Main\Type\DateTime();
$date->add("-1D");
Main\UserAuthActionTable::deleteByFilter(array("<ACTION_DATE" => $date));
return 'CUser::AuthActionsCleanUpAgent();';
}
}
class CAllGroup
{
var $LAST_ERROR;
public static function err_mess()
{
return "<br>Class: CAllGroup<br>File: ".__FILE__;
}
public function CheckFields($arFields, $ID=false)
{
global $DB;
$this->LAST_ERROR = "";
if(is_set($arFields, "NAME") && $arFields["NAME"] == '')
$this->LAST_ERROR .= GetMessage("BAD_GROUP_NAME")."<br>";
if (is_array($arFields["USER_ID"]) && count($arFields["USER_ID"]) > 0)
{
if (is_array($arFields["USER_ID"][0]) && count($arFields["USER_ID"][0]) > 0)
{
foreach($arFields["USER_ID"] as $arUser)
{
if($arUser["DATE_ACTIVE_FROM"] <> '' && !CheckDateTime($arUser["DATE_ACTIVE_FROM"]))
{
$error = str_replace("#USER_ID#", $arUser["USER_ID"], GetMessage("WRONG_USER_DATE_ACTIVE_FROM"));
$this->LAST_ERROR .= $error."<br>";
}
if($arUser["DATE_ACTIVE_TO"] <> '' && !CheckDateTime($arUser["DATE_ACTIVE_TO"]))
{
$error = str_replace("#USER_ID#", $arUser["USER_ID"], GetMessage("WRONG_USER_DATE_ACTIVE_TO"));
$this->LAST_ERROR .= $error."<br>";
}
}
}
}
if (isset($arFields['STRING_ID']) && $arFields['STRING_ID'] <> '')
{
$sql_str = "SELECT G.ID
FROM b_group G
WHERE G.STRING_ID='".$DB->ForSql($arFields['STRING_ID'])."'";
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
if ($r = $z->Fetch())
{
if ($ID === false || $ID != $r['ID'])
$this->LAST_ERROR .= GetMessage('MAIN_ERROR_STRING_ID')."<br>";
}
}
if($this->LAST_ERROR <> '')
return false;
return true;
}
public function Update($ID, $arFields)
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
$ID = intval($ID);
if(!$this->CheckFields($arFields, $ID))
return false;
foreach(GetModuleEvents("main", "OnBeforeGroupUpdate", true) as $arEvent)
{
$bEventRes = ExecuteModuleEventEx($arEvent, array($ID, &$arFields));
if($bEventRes===false)
{
if($err = $APPLICATION->GetException())
$this->LAST_ERROR .= $err->GetString()."<br>";
else
$this->LAST_ERROR .= "Unknown error in OnBeforeGroupUpdate handler."."<br>";
return false;
}
}
if($ID<=2)
unset($arFields["ACTIVE"]);
if(is_set($arFields, "ACTIVE") && $arFields["ACTIVE"]!="Y")
$arFields["ACTIVE"]="N";
$strUpdate = $DB->PrepareUpdate("b_group", $arFields);
if(!is_set($arFields, "TIMESTAMP_X"))
$strUpdate .= ", TIMESTAMP_X = ".$DB->GetNowFunction();
$strSql = "UPDATE b_group SET $strUpdate WHERE ID=".$ID;
if(is_set($arFields, "SECURITY_POLICY"))
{
if(COption::GetOptionString("main", "event_log_group_policy", "N") === "Y")
{
//get old security policy
$aPrevPolicy = array();
$res = $DB->Query("SELECT SECURITY_POLICY FROM b_group WHERE ID=".$ID);
if(($res_arr = $res->Fetch()) && $res_arr["SECURITY_POLICY"] <> '')
$aPrevPolicy = unserialize($res_arr["SECURITY_POLICY"]);
//compare with new one
$aNewPolicy = array();
if($arFields["SECURITY_POLICY"] <> '')
$aNewPolicy = unserialize($arFields["SECURITY_POLICY"]);
$aDiff = array_diff_assoc($aNewPolicy, $aPrevPolicy);
if(empty($aDiff))
$aDiff = array_diff_assoc($aPrevPolicy, $aNewPolicy);
if(!empty($aDiff))
CEventLog::Log("SECURITY", "GROUP_POLICY_CHANGED", "main", $ID, print_r($aPrevPolicy, true)." => ".print_r($aNewPolicy, true));
}
$DB->QueryBind($strSql, array("SECURITY_POLICY"=>$arFields["SECURITY_POLICY"]), false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
}
else
{
$DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
}
if(is_set($arFields, "USER_ID") && is_array($arFields["USER_ID"]))
{
$log = (COption::GetOptionString("main", "event_log_user_groups", "N") === "Y");
if($log)
{
//remember users in the group
$aPrevUsers = array();
$res = $DB->Query("SELECT USER_ID FROM b_user_group WHERE GROUP_ID=".$ID.($ID=="1"?" AND USER_ID<>1":""));
while($res_arr = $res->Fetch())
$aPrevUsers[] = $res_arr["USER_ID"];
}
$DB->Query("DELETE FROM b_user_group WHERE GROUP_ID=".$ID.($ID=="1"?" AND USER_ID<>1":""));
$arUsers = $arFields["USER_ID"];
$arTmp = array();
foreach($arUsers as $user)
{
if(!is_array($user))
$user = array("USER_ID" => $user);
$user_id = intval($user["USER_ID"]);
if(
$user_id > 0
&& !isset($arTmp[$user_id])
&& ($ID != 1 || $user_id != 1)
)
{
$arInsert = $DB->PrepareInsert("b_user_group", $user);
$strSql = "
INSERT INTO b_user_group (
GROUP_ID, ".$arInsert[0]."
) VALUES (
".$ID.", ".$arInsert[1]."
)
";
$DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$arTmp[$user_id] = true;
}
}
$aNewUsers = array_keys($arTmp);
CUser::clearUserGroupCache();
if($log)
{
/** @noinspection PhpUndefinedVariableInspection */
foreach($aPrevUsers as $user_id)
{
if(!in_array($user_id, $aNewUsers))
{
$UserName = '';
$rsUser = CUser::GetByID($user_id);
if($arUser = $rsUser->GetNext())
$UserName = ($arUser["NAME"] != "" || $arUser["LAST_NAME"] != "") ? trim($arUser["NAME"]." ".$arUser["LAST_NAME"]) : $arUser["LOGIN"];
$res_log = array(
"groups" => "-(".$ID.")",
"user" => $UserName
);
CEventLog::Log("SECURITY", "USER_GROUP_CHANGED", "main", $user_id, serialize($res_log));
}
}
foreach($aNewUsers as $user_id)
{
if(!in_array($user_id, $aPrevUsers))
{
$UserName = '';
$rsUser = CUser::GetByID($user_id);
if($arUser = $rsUser->GetNext())
$UserName = ($arUser["NAME"] != "" || $arUser["LAST_NAME"] != "") ? trim($arUser["NAME"]." ".$arUser["LAST_NAME"]) : $arUser["LOGIN"];
$res_log = array(
"groups" => "+(".$ID.")",
"user" => $UserName
);
CEventLog::Log("SECURITY", "USER_GROUP_CHANGED", "main", $user_id, serialize($res_log));
}
}
}
}
foreach (GetModuleEvents("main", "OnAfterGroupUpdate", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($ID, &$arFields));
return true;
}
public static function Delete($ID)
{
/** @global CMain $APPLICATION */
global $APPLICATION, $DB;
$ID = intval($ID);
if($ID<=2)
return false;
@set_time_limit(600);
foreach(GetModuleEvents("main", "OnBeforeGroupDelete", true) as $arEvent)
{
if(ExecuteModuleEventEx($arEvent, array($ID))===false)
{
$err = GetMessage("MAIN_BEFORE_DEL_ERR").' '.$arEvent['TO_NAME'];
if($ex = $APPLICATION->GetException())
$err .= ': '.$ex->GetString();
$APPLICATION->throwException($err);
return false;
}
}
foreach(GetModuleEvents("main", "OnGroupDelete", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($ID));
CMain::DelGroupRight("",array($ID));
if(!$DB->Query("DELETE FROM b_user_group WHERE GROUP_ID=".$ID." AND GROUP_ID>2", true))
return false;
CUser::clearUserGroupCache();
return $DB->Query("DELETE FROM b_group WHERE ID=".$ID." AND ID>2", true);
}
public static function GetGroupUser($ID)
{
global $DB;
$ID = intval($ID);
if ($ID == 2)
{
$strSql = "SELECT U.ID as USER_ID FROM b_user U ";
}
else
{
$strSql =
"SELECT UG.USER_ID ".
"FROM b_user_group UG ".
"WHERE UG.GROUP_ID = ".$ID." ".
" AND ((UG.DATE_ACTIVE_FROM IS NULL) OR (UG.DATE_ACTIVE_FROM <= ".$DB->CurrentTimeFunction().")) ".
" AND ((UG.DATE_ACTIVE_TO IS NULL) OR (UG.DATE_ACTIVE_TO >= ".$DB->CurrentTimeFunction().")) ";
}
$res = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$arr = array();
while($r = $res->Fetch())
$arr[]=$r["USER_ID"];
return $arr;
}
public static function GetGroupUserEx($ID)
{
global $DB;
$ID = intval($ID);
if ($ID == 2)
{
$strSql = "SELECT U.ID as USER_ID, NULL as DATE_ACTIVE_FROM, NULL as DATE_ACTIVE_TO FROM b_user U ";
}
else
{
$strSql =
"SELECT UG.USER_ID, ".
" ".$DB->DateToCharFunction("UG.DATE_ACTIVE_FROM", "FULL")." as DATE_ACTIVE_FROM, ".
" ".$DB->DateToCharFunction("UG.DATE_ACTIVE_TO", "FULL")." as DATE_ACTIVE_TO ".
"FROM b_user_group UG ".
"WHERE UG.GROUP_ID = ".$ID." ".
" AND ((UG.DATE_ACTIVE_FROM IS NULL) OR (UG.DATE_ACTIVE_FROM <= ".$DB->CurrentTimeFunction().")) ".
" AND ((UG.DATE_ACTIVE_TO IS NULL) OR (UG.DATE_ACTIVE_TO >= ".$DB->CurrentTimeFunction().")) ";
}
$res = $DB->Query($strSql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
return $res;
}
public static function GetMaxSort()
{
global $DB;
$err_mess = (CAllGroup::err_mess())."<br>Function: GetMaxSort<br>Line: ";
$z = $DB->Query("SELECT max(C_SORT) M FROM b_group", false, $err_mess.__LINE__);
$zr = $z->Fetch();
return intval($zr["M"])+100;
}
public static function GetSubordinateGroups($grId)
{
global $DB, $CACHE_MANAGER;
$groupFilter = array();
if (is_array($grId))
{
foreach ($grId as $id)
{
$id = intval($id);
if ($id > 0)
$groupFilter[$id] = $id;
}
}
else
{
$id = intval($grId);
if ($id > 0)
$groupFilter[$id] = $id;
}
$result = array(2);
if (!empty($groupFilter))
{
if (CACHED_b_group_subordinate === false)
{
$z = $DB->Query("SELECT AR_SUBGROUP_ID FROM b_group_subordinate WHERE ID in (".implode(", ", $groupFilter).")");
while ($zr = $z->Fetch())
{
$subordinateGroups = explode(",", $zr['AR_SUBGROUP_ID']);
if (count($subordinateGroups) == 1 && !$subordinateGroups[0])
continue;
$result = array_merge($result, $subordinateGroups);
}
}
else
{
if ($CACHE_MANAGER->Read(CACHED_b_group_subordinate, "b_group_subordinate"))
{
$cache = $CACHE_MANAGER->Get("b_group_subordinate");
}
else
{
$cache = array();
$z = $DB->Query("SELECT ID, AR_SUBGROUP_ID FROM b_group_subordinate");
while ($zr = $z->Fetch())
{
$subordinateGroups = explode(",", $zr['AR_SUBGROUP_ID']);
if (count($subordinateGroups) == 1 && !$subordinateGroups[0])
continue;
$cache[$zr["ID"]] = $subordinateGroups;
}
$CACHE_MANAGER->Set("b_group_subordinate", $cache);
}
foreach ($cache as $groupId => $subordinateGroups)
{
if (isset($groupFilter[$groupId]))
{
$result = array_merge($result, $subordinateGroups);
}
}
}
}
return array_unique($result);
}
public static function SetSubordinateGroups($grId, $arSubGroups=false)
{
global $DB, $CACHE_MANAGER;
$grId = intval($grId);
$DB->Query("DELETE FROM b_group_subordinate WHERE ID = ".$grId);
if(is_array($arSubGroups))
{
$arInsert = $DB->PrepareInsert("b_group_subordinate", array(
"ID" => $grId,
"AR_SUBGROUP_ID" => implode(",", $arSubGroups),
));
$DB->Query("INSERT INTO b_group_subordinate(".$arInsert[0].") VALUES (".$arInsert[1].")");
}
$CACHE_MANAGER->Clean("b_group_subordinate");
}
public static function GetTasks($ID, $onlyMainTasks=true, $module_id=false)
{
global $DB;
$sql_str = 'SELECT GT.TASK_ID,T.MODULE_ID,GT.EXTERNAL_ID
FROM b_group_task GT
INNER JOIN b_task T ON (T.ID=GT.TASK_ID)
WHERE GT.GROUP_ID='.intval($ID);
if ($module_id !== false)
$sql_str .= ' AND T.MODULE_ID="'.$DB->ForSQL($module_id).'"';
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$arr = array();
$ex_arr = array();
while($r = $z->Fetch())
{
if (!$r['EXTERNAL_ID'])
$arr[$r['MODULE_ID']] = $r['TASK_ID'];
else
$ex_arr[] = $r;
}
if ($onlyMainTasks)
return $arr;
else
return array($arr,$ex_arr);
}
public static function SetTasks($ID, $arr)
{
global $DB;
$ID = intval($ID);
if(COption::GetOptionString("main", "event_log_module_access", "N") === "Y")
{
//get old values
$arOldTasks = array();
$rsTask = $DB->Query("SELECT TASK_ID FROM b_group_task WHERE GROUP_ID=".$ID);
while($arTask = $rsTask->Fetch())
$arOldTasks[] = $arTask["TASK_ID"];
//compare with new ones
$aNewTasks = array();
foreach($arr as $task_id)
if($task_id > 0)
$aNewTasks[] = $task_id;
$aDiff = array_diff($arOldTasks, $aNewTasks);
if(empty($aDiff))
$aDiff = array_diff($aNewTasks, $arOldTasks);
if(!empty($aDiff))
CEventLog::Log("SECURITY", "MODULE_RIGHTS_CHANGED", "main", $ID, "(".implode(", ", $arOldTasks).") => (".implode(", ", $aNewTasks).")");
}
$sql_str = "DELETE FROM b_group_task WHERE GROUP_ID=".$ID.
" AND (EXTERNAL_ID IS NULL OR EXTERNAL_ID = '')";
$DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$sID = "0";
if(is_array($arr))
foreach($arr as $task_id)
$sID .= ",".intval($task_id);
$DB->Query(
"INSERT INTO b_group_task (GROUP_ID, TASK_ID, EXTERNAL_ID) ".
"SELECT '".$ID."', ID, '' ".
"FROM b_task ".
"WHERE ID IN (".$sID.") "
, false, "File: ".__FILE__."<br>Line: ".__LINE__
);
}
public static function GetTasksForModule($module_id, $onlyMainTasks = true)
{
global $DB;
$sql_str = "SELECT GT.TASK_ID,GT.GROUP_ID,GT.EXTERNAL_ID,T.NAME
FROM b_group_task GT
INNER JOIN b_task T ON (T.ID=GT.TASK_ID)
WHERE T.MODULE_ID='".$DB->ForSQL($module_id)."'";
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$main_arr = array();
$ext_arr = array();
while($r = $z->Fetch())
{
if (!$r['EXTERNAL_ID'])
{
$main_arr[$r['GROUP_ID']] = array('ID'=>$r['TASK_ID'],'NAME'=>$r['NAME']);
}
elseif(!$onlyMainTasks)
{
if (!isset($ext_arr[$r['GROUP_ID']]))
$ext_arr[$r['GROUP_ID']] = array();
$ext_arr[$r['GROUP_ID']][] = array('ID'=>$r['TASK_ID'],'NAME'=>$r['NAME'],'EXTERNAL_ID'=>$r['EXTERNAL_ID']);
}
}
if ($onlyMainTasks)
return $main_arr;
else
return array($main_arr,$ext_arr);
}
public static function SetTasksForModule($module_id, $arGroupTask)
{
global $DB;
$module_id = $DB->ForSql($module_id);
$sql_str = "SELECT T.ID
FROM b_task T
WHERE T.MODULE_ID='".$module_id."'";
$r = $DB->Query($sql_str, false, "File: ".__FILE__."<br>Line: ".__LINE__);
$arIds = array();
while($arR = $r->Fetch())
$arIds[] = $arR['ID'];
if(COption::GetOptionString("main", "event_log_module_access", "N") === "Y")
{
//get old values
$arOldTasks = array();
if(!empty($arIds))
{
$rsTask = $DB->Query("SELECT GROUP_ID, TASK_ID FROM b_group_task WHERE TASK_ID IN (".implode(",", $arIds).")");
while($arTask = $rsTask->Fetch())
$arOldTasks[$arTask["GROUP_ID"]] = $arTask["TASK_ID"];
}
//compare with new ones
foreach($arOldTasks as $gr_id=>$task_id)
if($task_id <> $arGroupTask[$gr_id]['ID'])
CEventLog::Log("SECURITY", "MODULE_RIGHTS_CHANGED", "main", $gr_id, $module_id.": (".$task_id.") => (".$arGroupTask[$gr_id]['ID'].")");
foreach($arGroupTask as $gr_id => $oTask)
if(intval($oTask['ID']) > 0 && !array_key_exists($gr_id, $arOldTasks))
CEventLog::Log("SECURITY", "MODULE_RIGHTS_CHANGED", "main", $gr_id, $module_id.": () => (".$oTask['ID'].")");
}
if(!empty($arIds))
{
$sql_str = "DELETE FROM b_group_task WHERE TASK_ID IN (".implode(",", $arIds).")";
$DB->Query($sql_str, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
foreach($arGroupTask as $gr_id => $oTask)
{
if(intval($oTask['ID']) > 0)
{
$DB->Query(
"INSERT INTO b_group_task (GROUP_ID, TASK_ID, EXTERNAL_ID) ".
"SELECT G.ID, T.ID, '' ".
"FROM b_group G, b_task T ".
"WHERE G.ID = ".intval($gr_id)." AND
T.ID = ".intval($oTask['ID']),
false, "File: ".__FILE__."<br>Line: ".__LINE__
);
}
}
}
public static function GetModulePermission($group_id, $module_id)
{
/** @global CMain $APPLICATION */
global $APPLICATION, $DB;
// check module permissions mode
$strSql = "SELECT T.ID, GT.TASK_ID FROM b_task T LEFT JOIN b_group_task GT ON T.ID=GT.TASK_ID AND GT.GROUP_ID=".intval($group_id)." WHERE T.MODULE_ID='".$DB->ForSql($module_id)."'";
$dbr_tasks = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
if($ar_task = $dbr_tasks->Fetch())
{
do
{
if($ar_task["TASK_ID"]>0)
return $ar_task["TASK_ID"];
}
while ($ar_task = $dbr_tasks->Fetch());
return false;
}
return $APPLICATION->GetGroupRight($module_id, array($group_id), "N", "N");
}
public static function SetModulePermission($group_id, $module_id, $permission)
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
if(intval($permission)<=0 && $permission != false)
{
$strSql = "SELECT T.ID FROM b_task T WHERE T.MODULE_ID='".$DB->ForSql($module_id)."' AND NAME='".$DB->ForSql($permission)."'";
$db_task = $DB->Query($strSql);
if($ar_task=$db_task->Fetch())
$permission = $ar_task['ID'];
}
$permission_letter = '';
if(intval($permission)>0 || $permission === false)
{
$strSql = "SELECT T.ID FROM b_task T WHERE T.MODULE_ID='".$DB->ForSql($module_id)."'";
$dbr_tasks = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
$arIds = array();
while($arTask = $dbr_tasks->Fetch())
$arIds[] = $arTask['ID'];
if(!empty($arIds))
{
$strSql = "DELETE FROM b_group_task WHERE GROUP_ID=".intval($group_id)." AND TASK_ID IN (".implode(",", $arIds).")";
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
if(intval($permission)>0)
{
$DB->Query(
"INSERT INTO b_group_task (GROUP_ID, TASK_ID, EXTERNAL_ID) ".
"SELECT G.ID, T.ID, '' ".
"FROM b_group G, b_task T ".
"WHERE G.ID = ".intval($group_id)." AND T.ID = ".intval($permission),
false,
"File: ".__FILE__."<br>Line: ".__LINE__
);
$permission_letter = CTask::GetLetter($permission);
}
}
else
{
$permission_letter = $permission;
}
if($permission_letter <> '')
$APPLICATION->SetGroupRight($module_id, $group_id, $permission_letter);
else
$APPLICATION->DelGroupRight($module_id, array($group_id));
}
public static function GetIDByCode($code)
{
if(strval(intval($code)) == $code && $code > 0)
return $code;
if(strtolower($code) == 'administrators')
return 1;
if(strtolower($code) == 'everyone')
return 2;
global $DB;
$strSql = "SELECT G.ID FROM b_group G WHERE G.STRING_ID='".$DB->ForSQL($code)."'";
$db_res = $DB->Query($strSql);
if($ar_res = $db_res->Fetch())
return $ar_res["ID"];
return false;
}
}
class CAllTask
{
public static function err_mess()
{
return "<br>Class: CAllTask<br>File: ".__FILE__;
}
public static function CheckFields(&$arFields, $ID = false)
{
/** @global CMain $APPLICATION */
global $DB, $APPLICATION;
if($ID>0)
unset($arFields["ID"]);
$arMsg = array();
if(($ID===false || is_set($arFields, "NAME")) && $arFields["NAME"] == '')
$arMsg[] = array("id"=>"NAME", "text"=> GetMessage('MAIN_ERROR_STRING_ID_EMPTY'));
$sql_str = "SELECT T.ID
FROM b_task T
WHERE T.NAME='".$DB->ForSQL($arFields['NAME'])."'";
if ($ID !== false)
$sql_str .= " AND T.ID <> ".intval($ID);
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
if ($r = $z->Fetch())
$arMsg[] = array("id"=>"NAME", "text"=> GetMessage('MAIN_ERROR_STRING_ID_DOUBLE'));
if (isset($arFields['LETTER']))
{
if (preg_match("/[^A-Z]/i", $arFields['LETTER']) || strlen($arFields['LETTER']) > 1)
$arMsg[] = array("id"=>"LETTER", "text"=> GetMessage('MAIN_TASK_WRONG_LETTER'));
$arFields['LETTER'] = strtoupper($arFields['LETTER']);
}
else
{
$arFields['LETTER'] = '';
}
if(count($arMsg)>0)
{
$e = new CAdminException($arMsg);
$APPLICATION->ThrowException($e);
return false;
}
if (!isset($arFields['SYS']) || $arFields['SYS'] != "Y")
$arFields['SYS'] = "N";
if (!isset($arFields['BINDING']))
$arFields['BINDING'] = 'module';
return true;
}
public static function Add($arFields)
{
global $CACHE_MANAGER, $DB;
if(!CTask::CheckFields($arFields))
return false;
if(CACHED_b_task !== false)
$CACHE_MANAGER->CleanDir("b_task");
$ID = $DB->Add("b_task", $arFields);
return $ID;
}
public static function Update($arFields,$ID)
{
global $DB, $CACHE_MANAGER;
if(!CTask::CheckFields($arFields,$ID))
return false;
$strUpdate = $DB->PrepareUpdate("b_task", $arFields);
if($strUpdate)
{
if(CACHED_b_task !== false)
$CACHE_MANAGER->CleanDir("b_task");
$strSql =
"UPDATE b_task SET ".
$strUpdate.
" WHERE ID=".intval($ID);
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
return true;
}
public static function UpdateModuleRights($id, $moduleId, $letter, $site_id = false)
{
global $DB;
if (!isset($id, $moduleId))
return false;
$sql = "SELECT GT.GROUP_ID
FROM b_group_task GT
WHERE GT.TASK_ID=".intval($id);
$z = $DB->Query($sql, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$arGroups = array();
while($r = $z->Fetch())
{
$g = intval($r['GROUP_ID']);
if ($g > 0)
$arGroups[] = $g;
}
if (count($arGroups) == 0)
return false;
$str_groups = implode(',', $arGroups);
$moduleId = $DB->ForSQL($moduleId);
$DB->Query(
"DELETE FROM b_module_group
WHERE
MODULE_ID = '".$moduleId."' AND
SITE_ID ".($site_id ? "='".$site_id."'" : "IS NULL")." AND
GROUP_ID IN (".$str_groups.")",
false, "FILE: ".__FILE__."<br> LINE: ".__LINE__
);
if ($letter == '')
return false;
$letter = $DB->ForSQL($letter);
$DB->Query(
"INSERT INTO b_module_group (MODULE_ID, GROUP_ID, G_ACCESS, SITE_ID) ".
"SELECT '".$moduleId."', G.ID, '".$letter."', ".($site_id ? "'".$site_id."'" : "NULL")." ".
"FROM b_group G ".
"WHERE G.ID IN (".$str_groups.")"
, false, "File: ".__FILE__."<br>Line: ".__LINE__
);
return true;
}
public static function Delete($ID, $protect = true)
{
global $DB, $CACHE_MANAGER;
$ID = intval($ID);
if(CACHED_b_task !== false)
$CACHE_MANAGER->CleanDir("b_task");
$sql_str = "DELETE FROM b_task WHERE ID=".$ID;
if ($protect)
$sql_str .= " AND SYS='N'";
$DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
if (!$protect)
{
if(CACHED_b_task_operation !== false)
$CACHE_MANAGER->CleanDir("b_task_operation");
$DB->Query("DELETE FROM b_task_operation WHERE TASK_ID=".$ID, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
}
}
public static function GetList($arOrder = array('MODULE_ID'=>'asc','LETTER'=>'asc'), $arFilter = array())
{
global $DB, $CACHE_MANAGER;;
if(CACHED_b_task !== false)
{
$context = Main\Context::getCurrent();
$cacheId = "b_task".md5(serialize($arOrder).".".serialize($arFilter).".".$context->getLanguage());
if($CACHE_MANAGER->Read(CACHED_b_task, $cacheId, "b_task"))
{
$arResult = $CACHE_MANAGER->Get($cacheId);
$res = new CDBResult;
$res->InitFromArray($arResult);
return $res;
}
}
static $arFields = array(
"ID" => array("FIELD_NAME" => "T.ID", "FIELD_TYPE" => "int"),
"NAME" => array("FIELD_NAME" => "T.NAME", "FIELD_TYPE" => "string"),
"LETTER" => array("FIELD_NAME" => "T.LETTER", "FIELD_TYPE" => "string"),
"MODULE_ID" => array("FIELD_NAME" => "T.MODULE_ID", "FIELD_TYPE" => "string"),
"SYS" => array("FIELD_NAME" => "T.SYS", "FIELD_TYPE" => "string"),
"BINDING" => array("FIELD_NAME" => "T.BINDING", "FIELD_TYPE" => "string")
);
$err_mess = (CAllTask::err_mess())."<br>Function: GetList<br>Line: ";
$arSqlSearch = array();
if(is_array($arFilter))
{
foreach($arFilter as $n => $val)
{
$n = strtoupper($n);
if(strlen($val) <= 0 || strval($val) == "NOT_REF")
continue;
if(isset($arFields[$n]))
{
$arSqlSearch[] = GetFilterQuery($arFields[$n]["FIELD_NAME"], $val, ($n == 'NAME'? "Y" : "N"));
}
}
}
$strOrderBy = '';
foreach($arOrder as $by=>$order)
if(isset($arFields[strtoupper($by)]))
$strOrderBy .= $arFields[strtoupper($by)]["FIELD_NAME"].' '.(strtolower($order)=='desc'?'desc'.(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""):'asc'.(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":"")).',';
if($strOrderBy <> '')
$strOrderBy = "ORDER BY ".rtrim($strOrderBy, ",");
$strSqlSearch = GetFilterSqlSearch($arSqlSearch);
$strSql = "
SELECT
T.ID, T.NAME, T.DESCRIPTION, T.MODULE_ID, T.LETTER, T.SYS, T.BINDING
FROM
b_task T
WHERE
".$strSqlSearch."
".$strOrderBy;
$res = $DB->Query($strSql, false, $err_mess.__LINE__);
$arResult = array();
while($arRes = $res->Fetch())
{
$arRes['TITLE'] = CTask::GetLangTitle($arRes['NAME'], $arRes['MODULE_ID']);
$arRes['DESC'] = CTask::GetLangDescription($arRes['NAME'], $arRes['DESCRIPTION'], $arRes['MODULE_ID']);
$arResult[] = $arRes;
}
$res->InitFromArray($arResult);
if(CACHED_b_task !== false)
{
/** @noinspection PhpUndefinedVariableInspection */
$CACHE_MANAGER->Set($cacheId, $arResult);
}
return $res;
}
public static function GetOperations($ID, $return_names = false)
{
global $DB, $CACHE_MANAGER;
static $TASK_OPERATIONS_CACHE = array();
$ID = intval($ID);
if (!isset($TASK_OPERATIONS_CACHE[$ID]))
{
if(CACHED_b_task_operation !== false)
{
$cacheId = "b_task_operation_".$ID;
if($CACHE_MANAGER->Read(CACHED_b_task_operation, $cacheId, "b_task_operation"))
{
$TASK_OPERATIONS_CACHE[$ID] = $CACHE_MANAGER->Get($cacheId);
}
}
}
if (!isset($TASK_OPERATIONS_CACHE[$ID]))
{
$sql_str = '
SELECT T_O.OPERATION_ID, O.NAME
FROM b_task_operation T_O
INNER JOIN b_operation O ON T_O.OPERATION_ID = O.ID
WHERE T_O.TASK_ID = '.$ID.'
';
$TASK_OPERATIONS_CACHE[$ID] = array(
'names' => array(),
'ids' => array(),
);
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
while($r = $z->Fetch())
{
$TASK_OPERATIONS_CACHE[$ID]['names'][] = $r['NAME'];
$TASK_OPERATIONS_CACHE[$ID]['ids'][] = $r['OPERATION_ID'];
}
if(CACHED_b_task_operation !== false)
{
/** @noinspection PhpUndefinedVariableInspection */
$CACHE_MANAGER->Set($cacheId, $TASK_OPERATIONS_CACHE[$ID]);
}
}
return $TASK_OPERATIONS_CACHE[$ID][$return_names ? 'names' : 'ids'];
}
public static function SetOperations($ID, $arr, $bOpNames=false)
{
global $DB, $CACHE_MANAGER;
$ID = intval($ID);
//get old operations
$aPrevOp = array();
$res = $DB->Query("
SELECT O.NAME
FROM b_operation O
INNER JOIN b_task_operation T_OP ON O.ID = T_OP.OPERATION_ID
WHERE T_OP.TASK_ID = ".$ID."
ORDER BY O.ID
");
while(($res_arr = $res->Fetch()))
$aPrevOp[] = $res_arr["NAME"];
$sql_str = 'DELETE FROM b_task_operation WHERE TASK_ID='.$ID;
$DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
if(is_array($arr) && count($arr)>0)
{
if($bOpNames)
{
$sID = "";
foreach($arr as $op_id)
$sID .= ",'".$DB->ForSQL($op_id)."'";
$sID = LTrim($sID, ",");
$DB->Query(
"INSERT INTO b_task_operation (TASK_ID, OPERATION_ID) ".
"SELECT '".$ID."', O.ID ".
"FROM b_operation O, b_task T ".
"WHERE O.NAME IN (".$sID.") AND T.MODULE_ID=O.MODULE_ID AND T.ID=".$ID." "
, false, "File: ".__FILE__."<br>Line: ".__LINE__
);
}
else
{
$sID = "0";
foreach($arr as $op_id)
$sID .= ",".intval($op_id);
$DB->Query(
"INSERT INTO b_task_operation (TASK_ID, OPERATION_ID) ".
"SELECT '".$ID."', ID ".
"FROM b_operation ".
"WHERE ID IN (".$sID.") "
, false, "File: ".__FILE__."<br>Line: ".__LINE__
);
}
}
if(CACHED_b_task_operation !== false)
$CACHE_MANAGER->CleanDir("b_task_operation");
//get new operations
$aNewOp = array();
$res = $DB->Query("
SELECT O.NAME
FROM b_operation O
INNER JOIN b_task_operation T_OP ON O.ID = T_OP.OPERATION_ID
WHERE T_OP.TASK_ID = ".$ID."
ORDER BY O.ID
");
while(($res_arr = $res->Fetch()))
$aNewOp[] = $res_arr["NAME"];
//compare with old one
$aDiff = array_diff($aNewOp, $aPrevOp);
if(empty($aDiff))
$aDiff = array_diff($aPrevOp, $aNewOp);
if(!empty($aDiff))
{
if(COption::GetOptionString("main", "event_log_task", "N") === "Y")
CEventLog::Log("SECURITY", "TASK_CHANGED", "main", $ID, "(".implode(", ", $aPrevOp).") => (".implode(", ", $aNewOp).")");
foreach(GetModuleEvents("main", "OnTaskOperationsChanged", true) as $arEvent)
ExecuteModuleEventEx($arEvent, array($ID, $aPrevOp, $aNewOp));
}
}
public static function GetTasksInModules($mode=false, $module_id=false, $binding = false)
{
$arFilter = array();
if ($module_id !== false)
$arFilter["MODULE_ID"] = $module_id;
if ($binding !== false)
$arFilter["BINDING"] = $binding;
$z = CTask::GetList(
array(
"MODULE_ID" => "asc",
"LETTER" => "asc"
),
$arFilter
);
$arr = array();
if ($mode)
{
while($r = $z->Fetch())
{
if (!is_array($arr[$r['MODULE_ID']]))
$arr[$r['MODULE_ID']] = array('reference_id'=>array(),'reference'=>array());
$arr[$r['MODULE_ID']]['reference_id'][] = $r['ID'];
$arr[$r['MODULE_ID']]['reference'][] = '['.($r['LETTER'] ? $r['LETTER'] : '..').'] '.CTask::GetLangTitle($r['NAME'], $r['MODULE_ID']);
}
}
else
{
while($r = $z->Fetch())
{
if (!is_array($arr[$r['MODULE_ID']]))
$arr[$r['MODULE_ID']] = array();
$arr[$r['MODULE_ID']][] = $r;
}
}
return $arr;
}
public static function GetByID($ID)
{
return CTask::GetList(array(), array("ID" => intval($ID)));
}
protected static function GetDescriptions($module)
{
static $descriptions = array();
if(preg_match("/[^a-z0-9._]/i", $module))
{
return array();
}
if(!isset($descriptions[$module]))
{
if(($path = getLocalPath("modules/".$module."/admin/task_description.php")) !== false)
{
$descriptions[$module] = include($_SERVER["DOCUMENT_ROOT"].$path);
}
else
{
$descriptions[$module] = array();
}
}
return $descriptions[$module];
}
public static function GetLangTitle($name, $module = "main")
{
$descriptions = static::GetDescriptions($module);
$nameUpper = strtoupper($name);
if(isset($descriptions[$nameUpper]["title"]))
{
return $descriptions[$nameUpper]["title"];
}
return $name;
}
public static function GetLangDescription($name, $desc, $module = "main")
{
$descriptions = static::GetDescriptions($module);
$nameUpper = strtoupper($name);
if(isset($descriptions[$nameUpper]["description"]))
{
return $descriptions[$nameUpper]["description"];
}
return $desc;
}
public static function GetLetter($ID)
{
$z = CTask::GetById($ID);
if ($r = $z->Fetch())
if ($r['LETTER'])
return $r['LETTER'];
return false;
}
public static function GetIdByLetter($letter, $module, $binding='module')
{
static $TASK_LETTER_CACHE = array();
if (!$letter)
return false;
if (!isset($TASK_LETTER_CACHE))
$TASK_LETTER_CACHE = array();
$k = strtoupper($letter.'_'.$module.'_'.$binding);
if (isset($TASK_LETTER_CACHE[$k]))
return $TASK_LETTER_CACHE[$k];
$z = CTask::GetList(
array(),
array(
"LETTER" => $letter,
"MODULE_ID" => $module,
"BINDING" => $binding,
"SYS"=>"Y"
)
);
if ($r = $z->Fetch())
{
$TASK_LETTER_CACHE[$k] = $r['ID'];
if ($r['ID'])
return $r['ID'];
}
return false;
}
}
class CAllOperation
{
public static function err_mess()
{
return "<br>Class: CAllOperation<br>File: ".__FILE__;
}
public static function GetList($arOrder = array('MODULE_ID'=>'asc'),$arFilter=array())
{
global $DB;
static $arFields = array(
"ID" => array("FIELD_NAME" => "O.ID", "FIELD_TYPE" => "int"),
"NAME" => array("FIELD_NAME" => "O.NAME", "FIELD_TYPE" => "string"),
"MODULE_ID" => array("FIELD_NAME" => "O.MODULE_ID", "FIELD_TYPE" => "string"),
"BINDING" => array("FIELD_NAME" => "O.BINDING", "FIELD_TYPE" => "string")
);
$err_mess = (CAllOperation::err_mess())."<br>Function: GetList<br>Line: ";
$arSqlSearch = array();
if(is_array($arFilter))
{
foreach($arFilter as $n => $val)
{
$n = strtoupper($n);
if($val == '' || strval($val)=="NOT_REF")
continue;
if ($n == 'ID' || $n == 'MODULE_ID' || $n == 'BINDING')
$arSqlSearch[] = GetFilterQuery($arFields[$n]["FIELD_NAME"], $val, 'N');
elseif(isset($arFields[$n]))
$arSqlSearch[] = GetFilterQuery($arFields[$n]["FIELD_NAME"], $val);
}
}
$strOrderBy = '';
foreach($arOrder as $by=>$order)
if(isset($arFields[strtoupper($by)]))
$strOrderBy .= $arFields[strtoupper($by)]["FIELD_NAME"].' '.(strtolower($order)=='desc'?'desc'.(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""):'asc'.(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":"")).',';
if($strOrderBy <> '')
$strOrderBy = "ORDER BY ".rtrim($strOrderBy, ",");
$strSqlSearch = GetFilterSqlSearch($arSqlSearch);
$strSql = "
SELECT *
FROM
b_operation O
WHERE
".$strSqlSearch."
".$strOrderBy;
$res = $DB->Query($strSql, false, $err_mess.__LINE__);
return $res;
}
public static function GetAllowedModules()
{
global $DB;
$sql_str = 'SELECT DISTINCT O.MODULE_ID FROM b_operation O';
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$arr = array();
while($r = $z->Fetch())
$arr[] = $r['MODULE_ID'];
return $arr;
}
public static function GetBindingList()
{
global $DB;
$sql_str = 'SELECT DISTINCT O.MODULE_ID, O.BINDING FROM b_operation O';
$z = $DB->Query($sql_str, false, "FILE: ".__FILE__."<br> LINE: ".__LINE__);
$arr = array();
while($r = $z->Fetch())
$arr[] = $r;
return $arr;
}
public static function GetIDByName($name)
{
$z = COperation::GetList(array('MODULE_ID' => 'asc'), array("NAME" => $name));
if ($r = $z->Fetch())
return $r['ID'];
return false;
}
protected static function GetDescriptions($module)
{
static $descriptions = array();
if(preg_match("/[^a-z0-9._]/i", $module))
{
return array();
}
if(!isset($descriptions[$module]))
{
if(($path = getLocalPath("modules/".$module."/admin/operation_description.php")) !== false)
{
$descriptions[$module] = include($_SERVER["DOCUMENT_ROOT"].$path);
}
else
{
$descriptions[$module] = array();
}
}
return $descriptions[$module];
}
public static function GetLangTitle($name, $module = "main")
{
$descriptions = static::GetDescriptions($module);
$nameUpper = strtoupper($name);
if(isset($descriptions[$nameUpper]["title"]))
{
return $descriptions[$nameUpper]["title"];
}
return $name;
}
public static function GetLangDescription($name, $desc, $module = "main")
{
$descriptions = static::GetDescriptions($module);
$nameUpper = strtoupper($name);
if(isset($descriptions[$nameUpper]["description"]))
{
return $descriptions[$nameUpper]["description"];
}
return $desc;
}
}