void Corpse::EndLoot(Client* client, const EQApplicationPacket* app) { EQApplicationPacket* outapp = new EQApplicationPacket; outapp->SetOpcode(OP_LootComplete); outapp->size = 0; client->QueuePacket(outapp); safe_delete(outapp); this->being_looted_by = 0xFFFFFFFF; if (this->IsEmpty()) Delete(); else Save(); }
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account"); return false; } snprintf(char_name, 64, "%s", (char*)app->pBuffer); uchar race = app->pBuffer[64]; uchar clas = app->pBuffer[68]; clog(WORLD__CLIENT, "Name approval request. Name=%s, race=%s, class=%s", char_name, GetRaceName(race), GetEQClassName(clas)); EQApplicationPacket *outapp; outapp = new EQApplicationPacket; outapp->SetOpcode(OP_ApproveName); outapp->pBuffer = new uchar[1]; outapp->size = 1; clog(WORLD__CLIENT, "common/client.cpp line 292 pass"); bool valid = false; if (!database.CheckNameFilter(char_name)) { clog(WORLD__CLIENT, "Invalid name"); valid = false; } /* Name must begin with an upper-case letter. */ else if (islower(char_name[0])) { clog(WORLD__CLIENT, "Must begin with uppercase"); valid = false; } else if (database.ReserveName(GetAccountID(), char_name)) { clog(WORLD__CLIENT, "common/client.cpp line 304 pass"); valid = true; } else { clog(WORLD__CLIENT, "common/client.cpp line 308 pass"); valid = false; } clog(WORLD__CLIENT, "common/client.cpp line 312 pass"); outapp->pBuffer[0] = valid? 1 : 0; QueuePacket(outapp); safe_delete(outapp); clog(WORLD__CLIENT, "common/client.cpp line 316 pass"); if (!valid) memset(char_name, 0, sizeof(char_name)); clog(WORLD__CLIENT, "common/client.cpp line 320 pass"); return true; }
void StructStrategy::ErrorEncoder(EQApplicationPacket **in_p, EQStreamInterface *dest, bool ack_req) { EQApplicationPacket *p = *in_p; *in_p = nullptr; Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Error encoding opcode %s: no encoder provided. Dropping.", OpcodeManager::EmuToName(p->GetOpcode())); delete p; }
void StructStrategy::ErrorEncoder(EQApplicationPacket **in_p, EQStream *dest, bool ack_req) { EQApplicationPacket *p = *in_p; *in_p = nullptr; _log(NET__STRUCTS, "Error encoding opcode %s: no encoder provided. Dropping.", OpcodeManager::EmuToName(p->GetOpcode())); delete p; }
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account"); return false; } snprintf(char_name, 64, "%s", (char*)app->pBuffer); uchar race = app->pBuffer[64]; uchar clas = app->pBuffer[68]; clog(WORLD__CLIENT,"Name approval request. Name=%s, race=%s, class=%s",char_name,GetRaceName(race),GetEQClassName(clas)); EQApplicationPacket *outapp; outapp = new EQApplicationPacket; outapp->SetOpcode(OP_ApproveName); outapp->pBuffer = new uchar[1]; outapp->size = 1; bool valid; if(!database.CheckNameFilter(char_name)) { valid = false; } else if(char_name[0] < 'A' && char_name[0] > 'Z') { //name must begin with an upper-case letter. valid = false; } else if (database.ReserveName(GetAccountID(), char_name)) { valid = true; } else { valid = false; } outapp->pBuffer[0] = valid? 1 : 0; QueuePacket(outapp); safe_delete(outapp); if(!valid) { memset(char_name, 0, sizeof(char_name)); } return true; }
void Client::SendGuildMOTD(bool GetGuildMOTDReply) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMOTD, sizeof(GuildMOTD_Struct)); // When the Client gets an OP_GuildMOTD, it compares the text to the version it has previously stored. // If the text in the OP_GuildMOTD packet is the same, it does nothing. If not the same, it displays // the new MOTD and then stores the new text. // // When the Client receives an OP_GetGuildMOTDReply, it displays the text in the packet. // // So OP_GuildMOTD should be sent on zone entry and when an Officer changes the MOTD, and OP_GetGuildMOTDReply // should be sent when the client issues the /getguildmotd command. // if(GetGuildMOTDReply) outapp->SetOpcode(OP_GetGuildMOTDReply); GuildMOTD_Struct *motd = (GuildMOTD_Struct *) outapp->pBuffer; motd->unknown0 = 0; strn0cpy(motd->name, m_pp.name, 64); if(IsInAGuild()) { if(!guild_mgr.GetGuildMOTD(GuildID(), motd->motd, motd->setby_name)) { motd->setby_name[0] = '\0'; strcpy(motd->motd, "ERROR GETTING MOTD!"); } } else { //we have to send them an empty MOTD anywyas. motd->motd[0] = '\0'; //just to be sure motd->setby_name[0] = '\0'; //just to be sure } mlog(GUILDS__OUT_PACKETS, "Sending OP_GuildMOTD of length %d", outapp->size); mpkt(GUILDS__OUT_PACKET_TRACE, outapp); FastQueuePacket(&outapp); }
void Clientlist::Process() { EQStream *eqs; while((eqs = mailsf->Pop())) { struct in_addr in; in.s_addr = eqs->GetRemoteIP(); _log(MAIL__CLIENT, "New Client UDP Mail connection from %s:%d", inet_ntoa(in), ntohs(eqs->GetRemotePort())); eqs->SetOpcodeManager(&MailOpMgr); Client *c = new Client(eqs); ClientMailConnections.push_back(c); } list<Client*>::iterator Iterator; for(Iterator = ClientMailConnections.begin(); Iterator != ClientMailConnections.end(); Iterator++) { if((*Iterator)->ClientStream->CheckClosed()) { struct in_addr in; in.s_addr = (*Iterator)->ClientStream->GetRemoteIP(); _log(MAIL__CLIENT, "Client connection from %s:%d closed.", inet_ntoa(in), ntohs((*Iterator)->ClientStream->GetRemotePort())); safe_delete((*Iterator)); Iterator = ClientMailConnections.erase(Iterator); if(Iterator == ClientMailConnections.end()) break; continue; } EQApplicationPacket *app = 0; bool KeyValid = true; while( KeyValid && (app = (EQApplicationPacket *)(*Iterator)->ClientStream->PopPacket())) { _pkt(MAIL__PACKETS, app); EmuOpcode opcode = app->GetOpcode(); switch(opcode) { case OP_MailLogin: { char *PacketBuffer = (char *)app->pBuffer; char MailBox[64]; char Key[64]; VARSTRUCT_DECODE_STRING(MailBox, PacketBuffer); // Check to see if we are running with a version of world that inserts a Connection Type // indicator at the start of the mailkey, and skip past it if so. if(strlen(PacketBuffer) == 9) PacketBuffer++; VARSTRUCT_DECODE_STRING(Key, PacketBuffer); string MailBoxString = MailBox, CharacterName; // Strip off the SOE.EQ.<shortname>. // string::size_type LastPeriod = MailBoxString.find_last_of("."); if(LastPeriod == string::npos) CharacterName = MailBoxString; else CharacterName = MailBoxString.substr(LastPeriod + 1); _log(MAIL__TRACE, "Received login for mailbox %s with key %s", MailBox, Key); if(!database.VerifyMailKey(CharacterName, (*Iterator)->ClientStream->GetRemoteIP(), Key)) { _log(MAIL__ERROR, "Mail Key for %s does not match, closing connection.", MailBox); KeyValid = false; break; } database.FindAccount(CharacterName.c_str(), (*Iterator)); (*Iterator)->SendMailBoxes(); CheckForStaleConnections((*Iterator)); break; } case OP_Mail: { const char *inbuf = (const char*)app->pBuffer; if((app->size >= 11) && !strncmp(inbuf, "getheaders", 10)) { // getheaders database.SendHeaders((*Iterator)); } else if((app->size >= 8) && !strncmp(inbuf, "getbody", 7)) { string GetBodyCommand = inbuf; database.SendBody((*Iterator), atoi(GetBodyCommand.substr(8).c_str())); } else if((app->size >= 7) && !strncmp(inbuf, "mailto", 6)) { ProcessMailTo((*Iterator), inbuf); } else if((app->size >= 17) && !strncmp(inbuf, "setmessagestatus", 16)) { int MessageNumber; int Status; string SetMessageCommand = inbuf; switch(SetMessageCommand[17]) { case 'R': // READ Status = 3; break; case 'T': // TRASH Status = 4; break; default: // DELETE Status = 0; } string::size_type NumStart = SetMessageCommand.find_first_of("123456789", 18); while(NumStart != string::npos) { string::size_type NumEnd = SetMessageCommand.find_first_of(" ", NumStart); if(NumEnd == string::npos) { MessageNumber = atoi(SetMessageCommand.substr(NumStart).c_str()); database.SetMessageStatus(MessageNumber, Status); break; } MessageNumber = atoi(SetMessageCommand.substr(NumStart, NumEnd-NumStart).c_str()); database.SetMessageStatus(MessageNumber, Status); NumStart = SetMessageCommand.find_first_of("123456789", NumEnd); } } else if((app->size >= 14) && !strncmp(inbuf, "selectmailbox", 13)) { string SelectMailBoxCommand = inbuf; string::size_type NumStart = SelectMailBoxCommand.find_first_of("0123456789", 13); int MailBoxNumber = atoi(SelectMailBoxCommand.substr(NumStart).c_str()); _log(MAIL__TRACE, "%s Change to mailbox %i", (*Iterator)->MailBoxName().c_str(), MailBoxNumber); (*Iterator)->SetMailBox(MailBoxNumber); _log(MAIL__TRACE, "New mailbox is %s", (*Iterator)->MailBoxName().c_str()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_MailboxChange, 2); char *buf = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_INTSTRING(buf, MailBoxNumber); _pkt(MAIL__PACKETS, outapp); (*Iterator)->QueuePacket(outapp); safe_delete(outapp); } else if((app->size >= 18) && !strncmp(inbuf, "setmailforwarding", 17)) { // This is sent to turn mail forwarding to your Station email account on/off // Not implemented. _log(MAIL__TRACE, "Unimplemented command: %s", inbuf); } else _log(MAIL__ERROR, "Unhandled OP_Mail command: %s", inbuf); break; } default: { _log(MAIL__ERROR, "Unhandled mail opcode %8X", opcode); break; } } safe_delete(app); } if(!KeyValid) { (*Iterator)->ClientStream->Close(); safe_delete((*Iterator)); Iterator = ClientMailConnections.erase(Iterator); if(Iterator == ClientMailConnections.end()) break; } } }
bool Client::Process() { EQApplicationPacket *app = connection->PopPacket(); while(app) { if(server.options.IsTraceOn()) { server_log->Log(log_network, "Application packet recieved from client (size %u)", app->Size()); } if(server.options.IsDumpInPacketsOn()) { DumpPacket(app); } switch(app->GetOpcode()) { case OP_SessionReady: { if(server.options.IsTraceOn()) { server_log->Log(log_network, "Session ready recieved from client."); } Handle_SessionReady((const char*)app->pBuffer, app->Size()); break; } case OP_Login: { if(app->Size() < 20) { server_log->Log(log_network_error, "Login recieved but it is too small, discarding."); break; } if(server.options.IsTraceOn()) { server_log->Log(log_network, "Login recieved from client."); } Handle_Login((const char*)app->pBuffer, app->Size()); break; } case OP_ServerListRequest: { if(server.options.IsTraceOn()) { server_log->Log(log_network, "Server list request recieved from client."); } SendServerListPacket(); break; } case OP_PlayEverquestRequest: { if(app->Size() < sizeof(PlayEverquestRequest_Struct)) { server_log->Log(log_network_error, "Play recieved but it is too small, discarding."); break; } Handle_Play((const char*)app->pBuffer); break; } default: { char dump[64]; app->build_header_dump(dump); server_log->Log(log_network_error, "Recieved unhandled application packet from the client: %s.", dump); } } delete app; app = connection->PopPacket(); } return true; }
void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!zone) return; auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_id, level); auto ability = ability_rank.first; auto rank = ability_rank.second; if(!ability) { return; } if(!(ability->classes & (1 << GetClass()))) { return; } if(!CanUseAlternateAdvancementRank(rank)) { return; } int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * rank->effects.size()) + (sizeof(AARankPrereq_Struct) * rank->prereqs.size()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); AARankInfo_Struct *aai = (AARankInfo_Struct*)outapp->pBuffer; aai->id = rank->id; aai->upper_hotkey_sid = rank->upper_hotkey_sid; aai->lower_hotkey_sid = rank->lower_hotkey_sid; aai->title_sid = rank->title_sid; aai->desc_sid = rank->desc_sid; aai->cost = rank->cost; aai->seq = aa_id; aai->type = ability->type; aai->spell = rank->spell; aai->spell_type = rank->spell_type; aai->spell_refresh = rank->recast_time; aai->classes = ability->classes; aai->level_req = rank->level_req; aai->current_level = level; aai->max_level = ability->GetMaxLevel(this); aai->prev_id = rank->prev_id; if(rank->next && !CanUseAlternateAdvancementRank(rank->next) || ability->charges > 0) { aai->next_id = -1; } else { aai->next_id = rank->next_id; } aai->total_cost = rank->total_cost; aai->expansion = rank->expansion; aai->category = ability->category; aai->charges = ability->charges; aai->grant_only = ability->grant_only; aai->total_effects = rank->effects.size(); aai->total_prereqs = rank->prereqs.size(); outapp->SetWritePosition(sizeof(AARankInfo_Struct)); for(auto &effect : rank->effects) { outapp->WriteSInt32(effect.effect_id); outapp->WriteSInt32(effect.base1); outapp->WriteSInt32(effect.base2); outapp->WriteSInt32(effect.slot); } for(auto &prereq : rank->prereqs) { outapp->WriteSInt32(prereq.first); outapp->WriteSInt32(prereq.second); } QueuePacket(outapp); safe_delete(outapp); }