Files
ROSS/Src/Login Server/loginpackets.cpp
T
2025-08-11 11:09:09 -05:00

241 lines
8.1 KiB
C++

/*
Rose Online Server Emulator
Copyright (C) 2006,2007 OSRose Team http://osroseon.to.md
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
developed with Main erose/hrose source server + some change from the original eich source
*/
#include "loginserver.h"
// Send Server encryption
bool CLoginServer::pakEncryptionRequest( CLoginClient* thisclient, CPacket* P )
{
try
{
thisclient->CryptStatus.CurAddValue = rand( ) | (rand( )<<16);
STARTPACKET( pak, 0x7FF, 11 );
SETBYTE ( pak, 0x00, 0x02 );
SETDWORD ( pak, 0x01, thisclient->CryptStatus.CurAddValue );
thisclient->SendPacket( &pak );
return true;
}
catch(...)
{
Log(MSG_ERROR, "pakEncryptionRequest");
}
}
// Packet when user login (chck user and pass)
bool CLoginServer::pakUserLogin( CLoginClient* thisclient, CPacket* P )
{
Log(MSG_DEBUG,"User Login request received");
try
{
if ( thisclient->isLoggedIn ) return false;
MYSQL_ROW row;
thisclient->username.assign( (const char*)&P->Buffer, 32, (P->Size-6-32)>16?16:P->Size-6-32 );
thisclient->password.assign( (const char*)&P->Buffer, 0, 32 );
BEGINPACKET( pak, 0x708 );
MYSQL_RES *result = DB->QStore( "SELECT id,password,accesslevel,online FROM accounts WHERE username='%s'", thisclient->username.c_str() );
if(result == NULL)
{
Log(MSG_WARNING,"DB Query returned a NULL result");
return false;
}
if( mysql_num_rows( result ) == 1 )
{
row = mysql_fetch_row(result);
int res = 0;
#ifdef _WIN32
res = _stricmp( row[1], thisclient->password.c_str() );
#else
res = strcasecmp( row[1], thisclient->password.c_str() );
#endif
if ( res == 0 )
{
if(atoi(row[3])==1)
{ // characters is already logged
Log(MSG_WARNING, "Account %s try re-login", thisclient->username.c_str() );
ADDBYTE( pak, 4 );
ADDDWORD( pak, 0 );
thisclient->SendPacket( &pak );
DB->QFree( );
DB->QExecute( "update accounts set login_count=1 WHERE username='%s'", thisclient->username.c_str());
return true;
}
thisclient->accesslevel = atoi(row[2]);
if( thisclient->accesslevel < Config.MinimumAccessLevel )
{ //The server are under inspection
Log(MSG_WARNING,"User accesslevel %i is lower than minimum %i",thisclient->accesslevel,Config.MinimumAccessLevel);
ADDBYTE( pak, 0 );
ADDDWORD( pak, 0 );
thisclient->SendPacket( &pak );
DB->QFree( );
return true;
}
if ( thisclient->accesslevel > 0 )
{
thisclient->userid = atoi(row[0]);
thisclient->isLoggedIn = true;
DB->QFree( );
//OK!
Log(MSG_WARNING,"User %s passed to charserver",thisclient->username.c_str());
ADDDWORD( pak, 0x0c000000 );//ADDDWORD( pak, 0x6f000000 );
ADDBYTE( pak, 0 );
result = DB->QStore( "SELECT id,name FROM channels WHERE owner=0" );
if(result==NULL) return false;
while( row = mysql_fetch_row(result) )
{
if (Config.Testserver){ADDBYTE( pak, 63 + atoi( row[0] ) );}
else{
ADDBYTE( pak, 48 + atoi( row[0] ) );}
ADDSTRING( pak, row[1] );
ADDBYTE( pak, 0 );
ADDDWORD(pak, atoi( row[0] ) );
}
DB->QFree( );
}
else
{
//BANNED
Log(MSG_WARNING,"User %s banned",thisclient->username.c_str());
ADDBYTE( pak, 5 );
ADDDWORD( pak, 0 );
DB->QFree( );
}
}
else
{
//BAD PASSWORD
Log(MSG_WARNING,"User %s attempted to log in with invalid password",thisclient->username.c_str());
ADDBYTE( pak, 3 );
ADDDWORD( pak, 0 );
DB->QFree( );
}
}
else
{
DB->QFree( );
if(Config.CreateLoginAccount)
{
if(!DB->QExecute("INSERT into accounts (username,password,accesslevel) values ('%s','%s',100)",thisclient->username.c_str(),thisclient->password.c_str()))
return true;
Log( MSG_INFO, "New Account created '%s'", thisclient->username.c_str() );
}
//BAD USERNAME
ADDBYTE( pak, 2 );
ADDDWORD( pak, 0 );
}
/*
1 - general error | 4 - your account is already logged
6 - topup account | 7 - cannot connect to server please try again
8 - server exceeded | 9 - account have not been verified
10 - login failed | 11 - ip capacity is full
*/
thisclient->SendPacket ( &pak );
return true;
}
catch(...)
{
Log(MSG_ERROR, "Error in pakUserLogin");
}
}
// Send server list
bool CLoginServer::pakGetServers( CLoginClient* thisclient, CPacket* P )
{
try
{
if( !thisclient->isLoggedIn ) return false;
MYSQL_ROW row;
unsigned servernum = GETDWORD( (*P), 0 );
MYSQL_RES *result = DB->QStore( "SELECT id,name,connected,maxconnections FROM channels WHERE owner=%i", servernum );
if(result==NULL) return false;
BEGINPACKET( pak, 0x704 );
ADDDWORD ( pak, servernum );
ADDBYTE ( pak, (BYTE)mysql_num_rows( result ) ); //old function
while(row = mysql_fetch_row(result))
{
UINT connected = atoi(row[2]);
UINT maxconnections = atoi(row[3]);
BYTE id = atoi( row[0] );
BYTE status = ((100 * connected) / (maxconnections == 0 ? 1 : maxconnections)) & 0xff;
ADDWORD( pak, id );
ADDBYTE( pak, 0 );
ADDWORD( pak, status );
ADDSTRING( pak, row[1] ); // Name
ADDBYTE( pak, 0 );
}
DB->QFree( );
thisclient->SendPacket ( &pak );
return true;
}
catch(...)
{
Log(MSG_ERROR, "Error in pakGetServers");
}
}
// Send server IP
bool CLoginServer::pakGetIP( CLoginClient* thisclient, CPacket* P )
{
try
{
if (!thisclient->isLoggedIn) return false;
MYSQL_ROW row;
DWORD servernum = GETDWORD( (*P), 0 );
BYTE channelnum = GETBYTE( (*P), 4 );
BEGINPACKET( pak, 0x70a );
if(!DB->QExecute( "UPDATE accounts SET lastsvr=%i,lastip='%s' WHERE id=%i", channelnum, inet_ntoa( thisclient->clientinfo.sin_addr ), thisclient->userid))
return false;
MYSQL_RES *result = DB->QStore( "SELECT host,port,connected,maxconnections FROM channels WHERE id=%i", servernum );
if(result==NULL) return false;
if(mysql_num_rows(result)!=1)
{
Log(MSG_WARNING, "Player selected a invalid channel or channel offline" );
DB->QFree( );
return true;
}
row = mysql_fetch_row(result);
UINT connected = atoi(row[2]);
UINT maxconnections = atoi(row[3]);
Log(MSG_DEBUG, "IP from database. Sent to client: %s ",row[0] );
ADDBYTE( pak, 0 ); //atoi(row[0]) ); // What is status? It's NULL in tables - Drakia
ADDDWORD( pak, thisclient->userid );
ADDDWORD( pak, 0x87654321 );
ADDSTRING( pak, row[0] );
ADDBYTE( pak, 0 );
ADDWORD( pak, atoi(row[1]) );
DB->QFree( );
thisclient->SendPacket ( &pak );
return true;
}
catch(...)
{
Log(MSG_ERROR, "Error in pakGetIP");
}
}