// Messenger actions (add/remove/invite) bool CCharServer::pakMessengerManager ( CCharClient* thisclient, CPacket* P ) { BYTE action = GETBYTE((*P),0); switch (action) { case 0x01://wanna be my friend? { char* nick = new (nothrow) char[P->Size-7]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory: pakMessengerManager 1" ); return false; } memcpy( nick, &P->Buffer[1], P->Size-7 ); Log(MSG_INFO,"%s Trying to invite %s",nick,thisclient->charname); CCharClient* otherclient = (CCharClient*) GetClientByName (nick); if(otherclient!=NULL) {//Send friend invitation (check this one) BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x01 ); ADDWORD ( pak, 0x0000 ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00 ); otherclient->SendPacket(&pak); Log(MSG_INFO,"%s exists, invite sent to %s",nick,otherclient->charname); } else {//This charname doesnt exist BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x04 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); thisclient->SendPacket(&pak); Log(MSG_INFO,"invite: %s doesn't exist",nick); } delete []nick; } break; case 0x02://yes i want { char* nick = new (nothrow) char[P->Size-9]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory: pakMessengerManager 2" ); return false; } memcpy( nick, &P->Buffer[3], P->Size-9 ); if(!CheckEscapeMySQL(nick,-1,true)) { Log(MSG_WARNING,"A nick (friendlist) contains incorrect caracter (see warnings above)"); return false; } CCharClient* otherclient = (CCharClient*) GetClientByName (nick); if(otherclient!=NULL) { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x02 ); /*ADDWORD ( pak, thisclient->charid ); ADDBYTE ( pak, 0x00 ); ADDWORD ( pak, 0x0000 );*/ ADDDWORD ( pak, thisclient->charid ); ADDBYTE ( pak, 0x00 ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00); otherclient->SendPacket(&pak); //Add friend to my friend list(sql) if(!DB->QExecute("INSERT INTO list_friend (id,idfriend,namefriend) VALUES (%i,%i,'%s')",otherclient->charid,thisclient->charid,thisclient->charname)) { Log(MSG_WARNING,"error addind %s to %s friend list",otherclient->charname,thisclient->charname); return false; } CFriendList * newfriend1 = new (nothrow) CFriendList; if(newfriend1==NULL) return false; newfriend1->id = otherclient->charid; //friendid strcpy(newfriend1->name, otherclient->charname); //friend name thisclient->FriendList.push_back( newfriend1 ); RESETPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x02 ); /*ADDWORD ( pak, otherclient->charid ); ADDBYTE ( pak, 0x00 ); ADDWORD ( pak, 0x0000 );*/ ADDDWORD ( pak, otherclient->charid ); ADDBYTE ( pak, 0x00 ); ADDSTRING ( pak, otherclient->charname ); ADDBYTE ( pak, 0x00); thisclient->SendPacket(&pak); //Add me to his friend list (sql) if(!DB->QExecute("INSERT INTO list_friend (id,idfriend,namefriend) VALUES (%i,%i,'%s')",thisclient->charid,otherclient->charid,otherclient->charname)) return false; CFriendList * newfriend2 = new (nothrow) CFriendList; if(newfriend2==NULL) return false; newfriend2->id = thisclient->charid; //friendid strcpy(newfriend2->name, thisclient->charname); //friend name otherclient->FriendList.push_back( newfriend2 ); Log(MSG_INFO,"accept %s ok",nick); } else//not found { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x04 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); thisclient->SendPacket(&pak); Log(MSG_INFO,"accept: %s doesn't exist",nick); } delete []nick; } break; case 0x03://no, i dont want { char* nick = new (nothrow) char[P->Size-9]; if(nick==NULL) { Log(MSG_ERROR, "Error allocing memory: pakMessengerManager 3" ); return false; } memcpy( nick, &P->Buffer[3], P->Size-9 ); CCharClient* otherclient = (CCharClient*) GetClientByName (nick); if(otherclient!=NULL) { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x03 ); ADDSTRING ( pak, thisclient->charname ); ADDBYTE ( pak, 0x00); otherclient->SendPacket(&pak); Log(MSG_INFO,"refuse: %s ok",nick); } else { BEGINPACKET( pak, 0x7e1 ); ADDBYTE ( pak, 0x04 ); ADDWORD ( pak, 0x0000 ); ADDSTRING ( pak, nick ); ADDBYTE ( pak, 0x00 ); thisclient->SendPacket(&pak); Log(MSG_INFO,"refuse: %s doesn't exist",nick); } } break; case 0x05://delete user. { //WORD id = GETWORD ((*P),1); DWORD id = GETDWORD ((*P),1); if(!DB->QExecute("DELETE FROM list_friend WHERE id=%i and idfriend=%i",thisclient->charid,id)) { Log(MSG_INFO,"user failed to delete friend slot %i",thisclient->charname,id); return false; } Log(MSG_INFO,"user %s deletes friend slot %i",thisclient->charname,id); CCharClient* otherclient = (CCharClient*) GetClientByID(id); if(otherclient!=NULL) { ChangeMessengerStatus ( thisclient, otherclient, 0x08); } } break; case 0xfa://messenger logout { //WORD id = GETWORD ((*P),1); DWORD id = GETDWORD ((*P),1); CCharClient* ctherclient = (CCharClient*) GetClientByID(id); if(ctherclient==NULL) return true; ctherclient->logout = true; for(UINT i=0;i<ctherclient->FriendList.size();i++) { CFriendList* thisfriend = ctherclient->FriendList.at( i ); CCharClient* otherclient = (CCharClient*) GetClientByID( thisfriend->id ); if(otherclient!=NULL) { ChangeMessengerStatus ( ctherclient, otherclient, 0x08); } } //Logout in clan ClanLogout ( ctherclient ); } break; default: Log( MSG_INFO, "Friend action unknown: %i", action ); break; } return true; }
// Send away the world IP bool CCharServer::pakRequestWorld( CCharClient* thisclient, CPacket* P ) { if (!thisclient->isLoggedIn) return false; MYSQL_ROW row; MYSQL_RES *result; memset( &thisclient->charname, '\0', 17 ); memcpy( thisclient->charname, &P->Buffer[3], (P->Size-6-4)>16?16:(P->Size-6-4) ); if(!CheckEscapeMySQL(thisclient->charname,17,true)) { Log(MSG_WARNING,"A charname contains incorrect caracters or incorrect size (see warnings above)"); return false; } Log( MSG_INFO,"User %s(%i) selected char '%s'", thisclient->username, thisclient->userid, thisclient->charname); if(!DB->QExecute("UPDATE accounts SET lastchar='%s' WHERE id=%i", thisclient->charname, thisclient->userid)) return false; result = DB->QStore("SELECT host,port,lanip,lansubmask FROM channels WHERE id=%u and owner=%u and type=2", thisclient->channel, Config.ServerID); if(result==NULL) return false; if(mysql_num_rows( result )!=1 ) { Log( MSG_WARNING, "Invalid Server: %i", thisclient->channel ); DB->QFree( ); return false; } row = mysql_fetch_row( result ); BEGINPACKET( pak, 0x711 ); ADDWORD ( pak, atoi(row[1]) ); // PORT ADDDWORD ( pak, thisclient->userid ); ADDDWORD ( pak, 0x87654321 ); if(strcmp(thisclient->ClientSubNet,row[3])==0)//from lan { ADDSTRING( pak, row[2] ); Log(MSG_INFO, "Sending LanIP" ); } else if(strcmp( thisclient->ClientSubNet ,"127.0.0")==0)//same computer { ADDSTRING( pak, "127.0.0.1" ); Log(MSG_INFO, "Sending Localhost IP" ); } else { ADDSTRING( pak, row[0] ); Log(MSG_INFO, "Sending InetIP"); } ADDBYTE ( pak, 0 ); thisclient->SendPacket( &pak ); DB->QFree( ); //CHAR INFORMATION 0 1 2 3 4 result = DB->QStore("SELECT clanid,clan_rank,id,level,classid,rewardpoints FROM characters WHERE char_name='%s'", thisclient->charname); if(result==NULL) return false; if(mysql_num_rows(result)!=1) { Log( MSG_WARNING, "Number of user with charname '%s' is %i", thisclient->charname,mysql_num_rows(result)); DB->QFree( ); return false; } row = mysql_fetch_row( result ); thisclient->clanid = atoi( row[0] ); thisclient->clan_rank = atoi( row[1] ); thisclient->charid = atoi( row[2] ); thisclient->level = atoi( row[3] ); thisclient->job = atoi( row[4] ); thisclient->reward_points=atoi( row[5] ); //LMA: reward points: DB->QFree( ); //MESSENGER INFORMATION // // 0 1 result = DB->QStore("SELECT idfriend,namefriend FROM list_friend WHERE id=%i", thisclient->charid); if(result==NULL) return false; BYTE nfriends = mysql_num_rows(result) & 0xff; RESETPACKET( pak, 0x7e1 );// Friend list command ADDBYTE ( pak, 0x06 );// Sending Friend List ADDBYTE ( pak, nfriends );// # friends while(row = mysql_fetch_row( result )) { CFriendList * newfriend = new CFriendList; assert(newfriend); newfriend->id = atoi(row[0]); //friendid strcpy(newfriend->name, row[1]); //friend name thisclient->FriendList.push_back( newfriend ); ADDWORD (pak, newfriend->id);// friend id ADDWORD (pak, 0x0000 ); CCharClient* otherclient = (CCharClient*) GetClientByID( newfriend->id ); if(otherclient!=NULL) //is online?? { ADDBYTE (pak, 0x07 ); //online ChangeMessengerStatus ( thisclient, otherclient, 0x07); } else { ADDBYTE (pak, 0x08 );//offline } ADDSTRING (pak, newfriend->name); //friend name ADDBYTE (pak, 0x00 ); } thisclient->SendPacket( &pak ); DB->QFree( ); thisclient->logout = false; //SEND CLAN INFORMATION SendClanInfo (thisclient); return true; }
// delete/resurect character bool CCharServer::pakDeleteChar( CCharClient* thisclient, CPacket* P ) { if(!thisclient->isLoggedIn) return false; char* name = (char*)&P->Buffer[2]; if(!CheckEscapeMySQL(name,-1,true)) { Log(MSG_WARNING,"A name (delete / resurrect) contains incorrect caracter (see warnings above)"); return false; } MYSQL_RES *result; MYSQL_ROW row; result = DB->QStore("SELECT account_name FROM characters WHERE char_name='%s' LIMIT 1", name); if(result==NULL) return false; row = mysql_fetch_row(result); //LMA: no case. //if (strcmp(row[0], thisclient->username)!=0) if (stricmp(row[0], thisclient->username)!=0) { Log(MSG_HACK, "User %s tried deleting another users (%s) character.", thisclient->username, name); DB->QFree( ); return false; } DB->QFree( ); short int action = GETBYTE((*P), 1 ); unsigned long int DeleteTime = 0; switch(action) { case 0x00://Resurrect { DeleteTime = 0; //if(!DB->QExecute(" UPDATE characters SET deletetime=0 WHERE char_name='%s'",(char*)&P->Buffer[2] )) if(!DB->QExecute(" UPDATE characters SET deletetime=0 WHERE char_name='%s'",name)) { return false; } } break; case 0x01://Delete { DeleteTime = GetServerTime( ) + Config.DeleteTime; //if(!DB->QExecute(" UPDATE characters SET deletetime=%i WHERE char_name='%s'",DeleteTime, (char*)&P->Buffer[2] )) if(!DB->QExecute(" UPDATE characters SET deletetime=%i WHERE char_name='%s'",DeleteTime,name)) { return false; } } break; } BEGINPACKET( pak, 0x714 ); if(DeleteTime > 0 ) { ADDDWORD ( pak, Config.DeleteTime ); } else { ADDDWORD ( pak, 0x00000000 ); } ADDSTRING ( pak, (char*)&P->Buffer[2] ); ADDBYTE ( pak, 0x00 ); thisclient->SendPacket( &pak ); return true; }
// Do player identification bool CCharServer::pakDoIdentify( CCharClient* thisclient, CPacket* P ) { if (thisclient->isLoggedIn) return false; MYSQL_RES *result; MYSQL_ROW row; thisclient->userid = GETDWORD((*P), 0x00); memcpy( thisclient->password, &P->Buffer[4], 32 ); //LMA: checking is password is ok. if(!CheckEscapeMySQL(thisclient->password,33,true)) { Log(MSG_WARNING,"A password contains incorrect caracters or is too long (see warnings above)"); return false; } result = DB->QStore("SELECT username,lastsvr,accesslevel,platinum FROM accounts WHERE id=%i AND password='******'", thisclient->userid, thisclient->password); if(result==NULL) return false; if (mysql_num_rows( result ) != 1) { Log( MSG_HACK, "Someone tried to connect to char server with an invalid account" ); DB->QFree( ); return false; } else { row = mysql_fetch_row(result); strncpy(thisclient->username, row[0],16); thisclient->channel = atoi(row[1]); thisclient->accesslevel = atoi(row[2]); thisclient->platinum = atoi(row[3]); DB->QFree( ); if(!CheckEscapeMySQL(thisclient->username,-1,true)) { Log(MSG_WARNING,"A username contains incorrect caracters (see warnings above)"); return false; } } //LMA: Adding a log for admins. Account ids shouldn't be less than 78 if(thisclient->userid<78) { Log(MSG_INFO,"Account ID %i (%s) is < 78, this is NOT advised to have ids too low (<10). You should change the id if it is the case.",thisclient->userid,thisclient->username); } //LMA: We try something here... We tell the worldserver to disconnect every character //from this account to avoid multi client on the same account (let's call this a preemptive strike). if(GetNbUserID(thisclient->userid)>1) { Log(MSG_HACK,"[HACK] User ID %u (%s) has several avatars logged on the same account.",thisclient->userid,thisclient->username); return false; } Log( MSG_INFO,"User '%s'(#%i) logged in", thisclient->username, thisclient->userid ); BEGINPACKET( pak, 0x070c ); ADDBYTE ( pak, 0 ); ADDDWORD ( pak, 0x87654321); ADDDWORD ( pak, 0x00000000 ); thisclient->SendPacket( &pak ); result = DB->QStore( "SELECT online FROM accounts WHERE username='******'", thisclient->username ); if(result==NULL) return false; row = mysql_fetch_row(result); bool online = atoi(row[0]); DB->QFree( ); if(online) return false; if(!DB->QExecute( "UPDATE accounts SET online=1 WHERE username='******'", thisclient->username )) return false; thisclient->isLoggedIn = true; return true; }
// Create a new clan bool CWorldServer::pakCreateClan ( CPlayer* thisclient, CPacket* P ) { if(thisclient->CharInfo->Zulies < 1000000) return true; thisclient->CharInfo->Zulies -= 1000000; //MYSQL_ROW row; int background = GETWORD((*P),1); int icon = GETWORD((*P),3); char*name=(char*)&P->Buffer[5]; char*slogan=(char*)&P->Buffer[strlen(name)+6]; //LMA: Check if name already exists and is short enough. if(!CheckValidName(thisclient,name)) { return true; } //LMA: Checking if it needs to be escaped. if(!CheckEscapeMySQL(name,50,true)) { return true; } //LMA: checking if the name is ok. MYSQL_RES *result = DB->QStore("SELECT name FROM list_clan WHERE name='%s'", name); if(result==NULL) return true; if ( mysql_num_rows( result ) > 0 ) { BEGINPACKET( pak, 0x07e0 ); ADDWORD ( pak, 0x42 ); thisclient->client->SendPacket( &pak ); DB->QFree( ); return true; } DB->QFree( ); //Check if user can create a clan if( thisclient->Clan->clanid != 0 ) { BEGINPACKET( pak, 0x7e0 ); ADDWORD ( pak, 0x44 ); thisclient->client->SendPacket( &pak ); return true; } char * lma_slogan = new char[strlen(slogan) + 1]; strcpy(lma_slogan,slogan); char * new_slogan = new char[strlen(lma_slogan)*3 +1]; mysql_real_escape_string(DB->Mysql, new_slogan,lma_slogan,strlen(lma_slogan)); //mysql_real_escape_string(DB->Mysql, new_slogan,"abcdefghijk",11); Log(MSG_INFO,"[WS] New clan %s created, slogan detected=%s, cleaned=%s ",name,slogan,new_slogan); //LMA: checking slogan's size. if(strlen(new_slogan)>=100) { Log(MSG_HACK,"%s tried to create clan %s with too long slogan %s (%i>=100)",thisclient->CharInfo->charname,name,new_slogan,strlen(new_slogan)); return true; } DB->QExecute( "INSERT into list_clan (logo,back,name,cp,grade,slogan,news) values (%i,%i,'%s',0,1,'%s','')",icon,background,name,new_slogan); thisclient->Clan->clanid = mysql_insert_id(DB->Mysql); thisclient->Clan->clanrank = 6; thisclient->Clan->logo = icon; thisclient->Clan->back = background; strncpy(thisclient->Clan->clanname,name,16); thisclient->Clan->grade = 1; //Update user clan information DB->QExecute( "UPDATE characters set clanid=%i,clan_rank=6 where id=%i", thisclient->Clan->clanid,thisclient->CharInfo->charid); //load clan info in char server BEGINPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0xfa ); //action to update clan informacion (charserver) ADDWORD ( pak, thisclient->Clan->clanid ); //ADDWORD ( pak, thisclient->CharInfo->charid ); ADDDWORD ( pak, thisclient->CharInfo->charid ); ADDWORD ( pak, thisclient->clientid ); cryptPacket( (char*)&pak, cct ); send( csock, (char*)&pak, pak.Size, 0 ); //Send to other players RESETPACKET( pak, 0x7e0 ); ADDBYTE ( pak, 0x35 ); ADDWORD ( pak, thisclient->clientid ); ADDDWORD ( pak, thisclient->Clan->clanid );//clanid ADDWORD ( pak, thisclient->Clan->back ); ADDWORD ( pak, thisclient->Clan->logo ); ADDBYTE ( pak, thisclient->Clan->grade );//clan grade ADDBYTE ( pak, thisclient->Clan->clanrank );//clan rank ADDSTRING ( pak, thisclient->Clan->clanname ); ADDBYTE ( pak, 0x00 ); SendToVisible( &pak, thisclient ); delete[] lma_slogan; delete[] new_slogan; return true; }