2020-08-18 20:42:30 +00:00
# include "CNLoginServer.hpp"
# include "CNShared.hpp"
# include "CNStructs.hpp"
2020-09-01 22:37:09 +00:00
# include "Database.hpp"
# include "PlayerManager.hpp"
# include <regex>
2020-09-03 02:25:09 +00:00
# include "contrib/bcrypt/BCrypt.hpp"
2020-08-18 20:42:30 +00:00
# include "settings.hpp"
std : : map < CNSocket * , CNLoginData > CNLoginServer : : loginSessions ;
CNLoginServer : : CNLoginServer ( uint16_t p ) {
port = p ;
pHandler = & CNLoginServer : : handlePacket ;
init ( ) ;
}
void CNLoginServer : : handlePacket ( CNSocket * sock , CNPacketData * data ) {
2020-08-23 21:09:31 +00:00
printPacket ( data , CL2LS ) ;
2020-08-22 17:39:13 +00:00
2020-08-18 20:42:30 +00:00
switch ( data - > type ) {
2020-09-01 22:37:09 +00:00
case P_CL2LS_REQ_LOGIN : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_LOGIN ) )
return ; // ignore the malformed packet
sP_CL2LS_REQ_LOGIN * login = ( sP_CL2LS_REQ_LOGIN * ) data - > buf ;
//TODO: implement better way of sending credentials
2020-09-09 19:07:47 +00:00
std : : string userLogin ( ( char * ) login - > szCookie_TEGid ) ;
std : : string userPassword ( ( char * ) login - > szCookie_authid ) ;
if ( userLogin . length ( ) = = 0 )
userLogin = U16toU8 ( login - > szID ) ;
if ( userPassword . length ( ) = = 0 )
userPassword = U16toU8 ( login - > szPassword ) ;
2020-09-01 22:37:09 +00:00
bool success = false ;
int errorCode = 0 ;
//checking regex
if ( ! CNLoginServer : : isLoginDataGood ( userLogin , userPassword ) )
{
errorCode = ( int ) LOGINERRORID : : login_error ;
}
else
{
std : : unique_ptr < Database : : Account > findUser = Database : : findAccount ( userLogin ) ;
//if account not found, create it
if ( findUser = = nullptr )
{
loginSessions [ sock ] = CNLoginData ( ) ;
loginSessions [ sock ] . userID = Database : : addAccount ( userLogin , userPassword ) ;
loginSessions [ sock ] . slot = 1 ;
success = true ;
}
//if user exists, check if password is correct
else if ( CNLoginServer : : isPasswordCorrect ( findUser - > Password , userPassword ) )
{
//check if account isn't currently in use
if ( CNLoginServer : : isAccountInUse ( findUser - > AccountID ) | |
PlayerManager : : isAccountInUse ( findUser - > AccountID ) )
{
errorCode = ( int ) LOGINERRORID : : id_already_in_use ;
}
//if not, login success
else
{
loginSessions [ sock ] = CNLoginData ( ) ;
loginSessions [ sock ] . userID = findUser - > AccountID ;
loginSessions [ sock ] . slot = findUser - > Selected ;
success = true ;
}
}
else
{
errorCode = ( int ) LOGINERRORID : : id_and_password_do_not_match ;
}
}
2020-08-29 11:14:21 +00:00
2020-09-01 22:37:09 +00:00
if ( success )
{
std : : vector < Player > characters = Database : : getCharacters ( loginSessions [ sock ] . userID ) ;
int charCount = characters . size ( ) ;
INITSTRUCT ( sP_LS2CL_REP_LOGIN_SUCC , resp ) ;
// set username in resp packet
memcpy ( resp . szID , login - > szID , sizeof ( char16_t ) * 33 ) ;
resp . iCharCount = charCount ;
resp . iSlotNum = loginSessions [ sock ] . slot ;
resp . iPaymentFlag = 1 ;
resp . iOpenBetaFlag = 0 ;
resp . uiSvrTime = getTime ( ) ;
// send the resp in with original key
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_LOGIN_SUCC , sizeof ( sP_LS2CL_REP_LOGIN_SUCC ) ) ;
// update keys
sock - > setEKey ( CNSocketEncryption : : createNewKey ( resp . uiSvrTime , resp . iCharCount + 1 , resp . iSlotNum + 1 ) ) ;
sock - > setFEKey ( CNSocketEncryption : : createNewKey ( ( uint64_t ) ( * ( uint64_t * ) & CNSocketEncryption : : defaultKey [ 0 ] ) , login - > iClientVerC , 1 ) ) ;
// now send the characters :)
std : : vector < Player > : : iterator it ;
for ( it = characters . begin ( ) ; it ! = characters . end ( ) ; it + + )
{
2020-08-22 23:31:09 +00:00
sP_LS2CL_REP_CHAR_INFO charInfo = sP_LS2CL_REP_CHAR_INFO ( ) ;
2020-08-18 20:42:30 +00:00
2020-08-29 11:14:21 +00:00
charInfo . iSlot = ( int8_t ) it - > slot ;
charInfo . iLevel = ( int16_t ) it - > level ;
charInfo . sPC_Style = it - > PCStyle ;
charInfo . sPC_Style2 = it - > PCStyle2 ;
// position
charInfo . iX = it - > x ;
charInfo . iY = it - > y ;
charInfo . iZ = it - > z ;
//save character in session (for char select)
2020-09-01 22:37:09 +00:00
int UID = it - > iID ;
loginSessions [ sock ] . characters [ UID ] = Player ( * it ) ;
2020-08-18 20:42:30 +00:00
loginSessions [ sock ] . characters [ UID ] . FEKey = sock - > getFEKey ( ) ;
2020-08-29 11:14:21 +00:00
2020-09-01 22:37:09 +00:00
//temporary inventory stuff
2020-08-29 11:14:21 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
//equip char creation clothes and lightning rifle
charInfo . aEquip [ i ] = it - > Equip [ i ] ;
}
for ( int i = 5 ; i < AEQUIP_COUNT ; i + + ) {
// empty equips
2020-08-22 23:31:09 +00:00
charInfo . aEquip [ i ] . iID = 0 ;
charInfo . aEquip [ i ] . iType = i ;
charInfo . aEquip [ i ] . iOpt = 0 ;
2020-08-21 02:10:14 +00:00
}
2020-08-28 18:02:03 +00:00
2020-08-29 11:14:21 +00:00
// set default to the first character
if ( it = = characters . begin ( ) )
loginSessions [ sock ] . selectedChar = UID ;
2020-08-28 18:02:03 +00:00
2020-09-01 22:37:09 +00:00
sock - > sendPacket ( ( void * ) & charInfo , P_LS2CL_REP_CHAR_INFO , sizeof ( sP_LS2CL_REP_CHAR_INFO ) ) ;
2020-08-29 11:14:21 +00:00
}
2020-09-01 22:37:09 +00:00
}
//Failure
else {
INITSTRUCT ( sP_LS2CL_REP_LOGIN_FAIL , resp ) ;
memcpy ( resp . szID , login - > szID , sizeof ( char16_t ) * 33 ) ;
resp . iErrorCode = errorCode ;
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_LOGIN_FAIL , sizeof ( sP_LS2CL_REP_LOGIN_FAIL ) ) ;
2020-08-18 20:42:30 +00:00
}
2020-08-29 11:14:21 +00:00
2020-09-01 22:37:09 +00:00
break ;
2020-08-18 20:42:30 +00:00
}
2020-09-01 22:37:09 +00:00
case P_CL2LS_REP_LIVE_CHECK : {
// stubbed, the client really doesn't care LOL
break ;
}
case P_CL2LS_REQ_CHECK_CHAR_NAME : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_CHECK_CHAR_NAME ) )
return ;
// naughty words allowed!!!!!!!! (also for some reason, the client will always show 'Player 0' if you manually type a name. It will show up for other connected players though)
sP_CL2LS_REQ_CHECK_CHAR_NAME * nameCheck = ( sP_CL2LS_REQ_CHECK_CHAR_NAME * ) data - > buf ;
//check if name is occupied
if ( Database : : isNameFree ( nameCheck ) )
{
// naughty words allowed!!!!!!!! (also for some reason, the client will always show 'Player + ID' if you manually type a name. It will show up for other connected players though)
INITSTRUCT ( sP_LS2CL_REP_CHECK_CHAR_NAME_SUCC , resp ) ;
DEBUGLOG (
2020-08-29 11:14:21 +00:00
std : : cout < < " P_CL2LS_REQ_CHECK_CHAR_NAME: " < < std : : endl ;
2020-09-01 22:37:09 +00:00
std : : cout < < " \t FirstName: " < < U16toU8 ( nameCheck - > szFirstName ) < < " LastName: " < < U16toU8 ( nameCheck - > szLastName ) < < std : : endl ;
)
2020-08-18 20:42:30 +00:00
2020-08-29 11:14:21 +00:00
memcpy ( resp . szFirstName , nameCheck - > szFirstName , sizeof ( char16_t ) * 9 ) ;
2020-09-01 22:37:09 +00:00
memcpy ( resp . szLastName , nameCheck - > szLastName , sizeof ( char16_t ) * 17 ) ;
// fr*ck allowed!!!
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_CHECK_CHAR_NAME_SUCC , sizeof ( sP_LS2CL_REP_CHECK_CHAR_NAME_SUCC ) ) ;
}
else {
INITSTRUCT ( sP_LS2CL_REP_CHECK_CHAR_NAME_FAIL , resp ) ;
resp . iErrorCode = 1 ;
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_CHECK_CHAR_NAME_FAIL , sizeof ( sP_LS2CL_REP_CHECK_CHAR_NAME_FAIL ) ) ;
}
break ;
2020-08-18 20:42:30 +00:00
2020-08-29 11:14:21 +00:00
}
2020-09-01 22:37:09 +00:00
case P_CL2LS_REQ_SAVE_CHAR_NAME : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_SAVE_CHAR_NAME ) )
return ;
sP_CL2LS_REQ_SAVE_CHAR_NAME * save = ( sP_CL2LS_REQ_SAVE_CHAR_NAME * ) data - > buf ;
INITSTRUCT ( sP_LS2CL_REP_SAVE_CHAR_NAME_SUCC , resp ) ;
DEBUGLOG (
std : : cout < < " P_CL2LS_REQ_SAVE_CHAR_NAME: " < < std : : endl ;
std : : cout < < " \t Slot: " < < ( int ) save - > iSlotNum < < std : : endl ;
std : : cout < < " \t Name: " < < U16toU8 ( save - > szFirstName ) < < " " < < U16toU8 ( save - > szLastName ) < < std : : endl ;
)
2020-08-29 11:14:21 +00:00
resp . iSlotNum = save - > iSlotNum ;
2020-09-01 22:37:09 +00:00
resp . iGender = save - > iGender ;
resp . iPC_UID = Database : : createCharacter ( save , loginSessions [ sock ] . userID ) ;
memcpy ( resp . szFirstName , save - > szFirstName , sizeof ( char16_t ) * 9 ) ;
memcpy ( resp . szLastName , save - > szLastName , sizeof ( char16_t ) * 17 ) ;
2020-08-29 11:14:21 +00:00
2020-09-01 22:37:09 +00:00
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_SAVE_CHAR_NAME_SUCC , sizeof ( sP_LS2CL_REP_SAVE_CHAR_NAME_SUCC ) ) ;
2020-08-29 11:14:21 +00:00
2020-09-01 22:37:09 +00:00
Database : : updateSelected ( loginSessions [ sock ] . userID , save - > iSlotNum ) ;
break ;
}
case P_CL2LS_REQ_CHAR_CREATE : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_CHAR_CREATE ) )
return ;
sP_CL2LS_REQ_CHAR_CREATE * character = ( sP_CL2LS_REQ_CHAR_CREATE * ) data - > buf ;
Database : : finishCharacter ( character ) ;
DEBUGLOG (
std : : cout < < " P_CL2LS_REQ_CHAR_CREATE: " < < std : : endl ;
std : : cout < < " \t PC_UID: " < < character - > PCStyle . iPC_UID < < std : : endl ;
std : : cout < < " \t NameCheck: " < < ( int ) character - > PCStyle . iNameCheck < < std : : endl ;
std : : cout < < " \t Name: " < < U16toU8 ( character - > PCStyle . szFirstName ) < < " " < < U16toU8 ( character - > PCStyle . szLastName ) < < std : : endl ;
std : : cout < < " \t Gender: " < < ( int ) character - > PCStyle . iGender < < std : : endl ;
std : : cout < < " \t Face: " < < ( int ) character - > PCStyle . iFaceStyle < < std : : endl ;
std : : cout < < " \t Hair: " < < ( int ) character - > PCStyle . iHairStyle < < std : : endl ;
std : : cout < < " \t Hair Color: " < < ( int ) character - > PCStyle . iHairColor < < std : : endl ;
std : : cout < < " \t Skin Color: " < < ( int ) character - > PCStyle . iSkinColor < < std : : endl ;
std : : cout < < " \t Eye Color: " < < ( int ) character - > PCStyle . iEyeColor < < std : : endl ;
std : : cout < < " \t Height: " < < ( int ) character - > PCStyle . iHeight < < std : : endl ;
std : : cout < < " \t Body: " < < ( int ) character - > PCStyle . iBody < < std : : endl ;
std : : cout < < " \t Class: " < < ( int ) character - > PCStyle . iClass < < std : : endl ;
std : : cout < < " \t iEquipUBID: " < < ( int ) character - > sOn_Item . iEquipUBID < < std : : endl ;
std : : cout < < " \t iEquipLBID: " < < ( int ) character - > sOn_Item . iEquipLBID < < std : : endl ;
std : : cout < < " \t iEquipFootID: " < < ( int ) character - > sOn_Item . iEquipFootID < < std : : endl ;
)
Player player =
Database : : DbToPlayer (
Database : : getDbPlayerById ( character - > PCStyle . iPC_UID )
) ;
int64_t UID = player . iID ;
INITSTRUCT ( sP_LS2CL_REP_CHAR_CREATE_SUCC , resp ) ;
resp . sPC_Style = player . PCStyle ;
resp . sPC_Style2 = player . PCStyle2 ;
resp . iLevel = player . level ;
resp . sOn_Item = character - > sOn_Item ;
//save player in session
loginSessions [ sock ] . characters [ UID ] = Player ( player ) ;
loginSessions [ sock ] . characters [ UID ] . FEKey = sock - > getFEKey ( ) ;
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_CHAR_CREATE_SUCC , sizeof ( sP_LS2CL_REP_CHAR_CREATE_SUCC ) ) ;
Database : : updateSelected ( loginSessions [ sock ] . userID , player . slot ) ;
break ;
}
case P_CL2LS_REQ_CHAR_DELETE : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_CHAR_DELETE ) )
return ;
2020-08-29 11:14:21 +00:00
2020-09-01 22:37:09 +00:00
sP_CL2LS_REQ_CHAR_DELETE * del = ( sP_CL2LS_REQ_CHAR_DELETE * ) data - > buf ;
int operationResult = Database : : deleteCharacter ( del - > iPC_UID ) ;
2020-08-29 11:14:21 +00:00
INITSTRUCT ( sP_LS2CL_REP_CHAR_DELETE_SUCC , resp ) ;
resp . iSlotNum = operationResult ;
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_CHAR_DELETE_SUCC , sizeof ( sP_LS2CL_REP_CHAR_DELETE_SUCC ) ) ;
2020-08-18 20:42:30 +00:00
2020-09-01 22:37:09 +00:00
break ;
}
case P_CL2LS_REQ_CHAR_SELECT : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_CHAR_SELECT ) )
return ;
// character selected
sP_CL2LS_REQ_CHAR_SELECT * chararacter = ( sP_CL2LS_REQ_CHAR_SELECT * ) data - > buf ;
INITSTRUCT ( sP_LS2CL_REP_CHAR_SELECT_SUCC , resp ) ;
2020-08-18 20:42:30 +00:00
2020-09-01 22:37:09 +00:00
DEBUGLOG (
std : : cout < < " P_CL2LS_REQ_CHAR_SELECT: " < < std : : endl ;
std : : cout < < " \t PC_UID: " < < chararacter - > iPC_UID < < std : : endl ;
)
2020-08-18 20:42:30 +00:00
2020-09-01 22:37:09 +00:00
loginSessions [ sock ] . selectedChar = chararacter - > iPC_UID ;
Database : : updateSelected ( loginSessions [ sock ] . userID , loginSessions [ sock ] . characters [ chararacter - > iPC_UID ] . slot ) ;
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_CHAR_SELECT_SUCC , sizeof ( sP_LS2CL_REP_CHAR_SELECT_SUCC ) ) ;
break ;
}
case P_CL2LS_REQ_SHARD_SELECT : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_SHARD_SELECT ) )
return ;
// tell client to connect to the shard server
sP_CL2LS_REQ_SHARD_SELECT * shard = ( sP_CL2LS_REQ_SHARD_SELECT * ) data - > buf ;
INITSTRUCT ( sP_LS2CL_REP_SHARD_SELECT_SUCC , resp ) ;
2020-08-29 11:14:21 +00:00
2020-09-01 22:37:09 +00:00
DEBUGLOG (
std : : cout < < " P_CL2LS_REQ_SHARD_SELECT: " < < std : : endl ;
std : : cout < < " \t Shard: " < < ( int ) shard - > ShardNum < < std : : endl ;
)
2020-08-18 20:42:30 +00:00
2020-09-01 22:37:09 +00:00
const char * SHARD_IP = settings : : SHARDSERVERIP . c_str ( ) ;
resp . iEnterSerialKey = rand ( ) ;
resp . g_FE_ServerPort = settings : : SHARDPORT ;
2020-08-18 20:42:30 +00:00
2020-09-01 22:37:09 +00:00
// copy IP to resp (this struct uses ASCII encoding so we don't have to goof around converting encodings)
memcpy ( resp . g_FE_ServerIP , SHARD_IP , strlen ( SHARD_IP ) ) ;
resp . g_FE_ServerIP [ strlen ( SHARD_IP ) ] = ' \0 ' ;
2020-08-18 20:42:30 +00:00
2020-09-01 22:37:09 +00:00
// pass player to CNSharedData
CNSharedData : : setPlayer ( resp . iEnterSerialKey , loginSessions [ sock ] . characters [ loginSessions [ sock ] . selectedChar ] ) ;
2020-08-18 20:42:30 +00:00
2020-09-01 22:37:09 +00:00
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_SHARD_SELECT_SUCC , sizeof ( sP_LS2CL_REP_SHARD_SELECT_SUCC ) ) ;
break ;
}
case P_CL2LS_REQ_SAVE_CHAR_TUTOR : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_SAVE_CHAR_TUTOR ) )
return ;
sP_CL2LS_REQ_SAVE_CHAR_TUTOR * save = ( sP_CL2LS_REQ_SAVE_CHAR_TUTOR * ) data - > buf ;
Database : : finishTutorial ( save - > iPC_UID ) ;
loginSessions [ sock ] . characters [ save - > iPC_UID ] . PCStyle2 . iTutorialFlag = 1 ;
loginSessions [ sock ] . characters [ save - > iPC_UID ] . Equip [ 0 ] . iID = 328 ;
loginSessions [ sock ] . characters [ save - > iPC_UID ] . Equip [ 0 ] . iType = 0 ;
loginSessions [ sock ] . characters [ save - > iPC_UID ] . Equip [ 0 ] . iOpt = 1 ;
break ;
}
case P_CL2LS_REQ_CHANGE_CHAR_NAME : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_CHANGE_CHAR_NAME ) )
return ;
sP_CL2LS_REQ_CHANGE_CHAR_NAME * save = ( sP_CL2LS_REQ_CHANGE_CHAR_NAME * ) data - > buf ;
Database : : changeName ( save ) ;
INITSTRUCT ( sP_LS2CL_REP_CHANGE_CHAR_NAME_SUCC , resp ) ;
resp . iPC_UID = save - > iPCUID ;
memcpy ( resp . szFirstName , save - > szFirstName , sizeof ( char16_t ) * 9 ) ;
memcpy ( resp . szLastName , save - > szLastName , sizeof ( char16_t ) * 17 ) ;
resp . iSlotNum = save - > iSlotNum ;
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_CHANGE_CHAR_NAME_SUCC , sizeof ( sP_LS2CL_REP_CHANGE_CHAR_NAME_SUCC ) ) ;
break ;
}
case P_CL2LS_REQ_PC_EXIT_DUPLICATE : {
if ( data - > size ! = sizeof ( sP_CL2LS_REQ_PC_EXIT_DUPLICATE ) )
return ;
2020-09-07 17:23:00 +00:00
2020-09-01 22:37:09 +00:00
sP_CL2LS_REQ_PC_EXIT_DUPLICATE * exit = ( sP_CL2LS_REQ_PC_EXIT_DUPLICATE * ) data - > buf ;
auto account = Database : : findAccount ( U16toU8 ( exit - > szID ) ) ;
if ( account = = nullptr )
break ;
2020-09-07 17:23:00 +00:00
2020-09-01 22:37:09 +00:00
int accountId = account - > AccountID ;
if ( ! exitDuplicate ( accountId ) )
2020-09-07 17:23:00 +00:00
PlayerManager : : exitDuplicate ( accountId ) ;
2020-09-01 22:37:09 +00:00
break ;
}
default :
if ( settings : : VERBOSITY )
std : : cerr < < " OpenFusion: LOGIN UNIMPLM ERR. PacketType: " < < Defines : : p2str ( CL2LS , data - > type ) < < " ( " < < data - > type < < " ) " < < std : : endl ;
break ;
/* Unimplemented CL2LS packets:
P_CL2LS_CHECK_NAME_LIST - unused by the client
P_CL2LS_REQ_SERVER_SELECT
P_CL2LS_REQ_SHARD_LIST_INFO - dev commands , useless as we only run 1 server
*/
2020-08-18 20:42:30 +00:00
}
}
2020-08-22 23:31:09 +00:00
void CNLoginServer : : newConnection ( CNSocket * cns ) {
cns - > setActiveKey ( SOCKETKEY_E ) ; // by default they accept keys encrypted with the default key
}
2020-08-18 20:42:30 +00:00
void CNLoginServer : : killConnection ( CNSocket * cns ) {
loginSessions . erase ( cns ) ;
2020-08-22 17:19:46 +00:00
}
2020-09-01 22:37:09 +00:00
# pragma region helperMethods
bool CNLoginServer : : isAccountInUse ( int accountId ) {
std : : map < CNSocket * , CNLoginData > : : iterator it ;
for ( it = CNLoginServer : : loginSessions . begin ( ) ; it ! = CNLoginServer : : loginSessions . end ( ) ; it + + )
{
if ( it - > second . userID = = accountId )
return true ;
}
return false ;
}
bool CNLoginServer : : exitDuplicate ( int accountId )
{
std : : map < CNSocket * , CNLoginData > : : iterator it ;
for ( it = CNLoginServer : : loginSessions . begin ( ) ; it ! = CNLoginServer : : loginSessions . end ( ) ; it + + )
{
if ( it - > second . userID = = accountId )
{
CNSocket * sock = it - > first ;
INITSTRUCT ( sP_LS2CL_REP_PC_EXIT_DUPLICATE , resp ) ;
resp . iErrorCode = 0 ;
sock - > sendPacket ( ( void * ) & resp , P_LS2CL_REP_PC_EXIT_DUPLICATE , sizeof ( sP_LS2CL_REP_PC_EXIT_DUPLICATE ) ) ;
sock - > kill ( ) ;
return true ;
}
}
return false ;
}
bool CNLoginServer : : isLoginDataGood ( std : : string login , std : : string password )
{
2020-09-06 15:27:53 +00:00
std : : regex loginRegex ( " [a-zA-Z0-9_-]{4,32} " ) ;
std : : regex passwordRegex ( " [a-zA-Z0-9!@#$%^&*()_+]{8,32} " ) ;
2020-09-01 22:37:09 +00:00
return ( std : : regex_match ( login , loginRegex ) & & std : : regex_match ( password , passwordRegex ) ) ;
}
bool CNLoginServer : : isPasswordCorrect ( std : : string actualPassword , std : : string tryPassword )
{
return BCrypt : : validatePassword ( tryPassword , actualPassword ) ;
}
# pragma endregion helperMethods