fix(Calendar/Packets): add additional validation when creating events (#2799)

This commit is contained in:
Nefertumm
2020-03-28 18:47:53 -03:00
committed by GitHub
parent 1411336dcb
commit bb6047248a
8 changed files with 250 additions and 63 deletions

View File

@@ -14,7 +14,9 @@
CalendarInvite::~CalendarInvite() CalendarInvite::~CalendarInvite()
{ {
sCalendarMgr->FreeInviteId(_inviteId); // Free _inviteId only if it's a real invite and not just a pre-invite or guild announcement
if (_inviteId != 0 && _eventId != 0)
sCalendarMgr->FreeInviteId(_inviteId);
} }
CalendarEvent::~CalendarEvent() CalendarEvent::~CalendarEvent()
@@ -141,15 +143,25 @@ void CalendarMgr::AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite
} }
} }
CalendarEventStore::iterator CalendarMgr::RemoveEvent(uint64 eventId, uint64 remover) void CalendarMgr::RemoveEvent(uint64 eventId, uint64 remover)
{ {
CalendarEventStore::iterator current; CalendarEvent* calendarEvent = GetEvent(eventId);
CalendarEvent* calendarEvent = GetEvent(eventId, &current);
if (!calendarEvent) if (!calendarEvent)
{ {
SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID); SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID);
return _events.end(); return;
}
RemoveEvent(calendarEvent, remover);
}
void CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, uint64 remover)
{
if (!calendarEvent)
{
SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID);
return;
} }
SendCalendarEventRemovedAlert(*calendarEvent); SendCalendarEventRemovedAlert(*calendarEvent);
@@ -158,7 +170,7 @@ CalendarEventStore::iterator CalendarMgr::RemoveEvent(uint64 eventId, uint64 rem
PreparedStatement* stmt; PreparedStatement* stmt;
MailDraft mail(calendarEvent->BuildCalendarMailSubject(remover), calendarEvent->BuildCalendarMailBody()); MailDraft mail(calendarEvent->BuildCalendarMailSubject(remover), calendarEvent->BuildCalendarMailBody());
CalendarInviteStore& eventInvites = _invites[eventId]; CalendarInviteStore& eventInvites = _invites[calendarEvent->GetEventId()];
for (size_t i = 0; i < eventInvites.size(); ++i) for (size_t i = 0; i < eventInvites.size(); ++i)
{ {
CalendarInvite* invite = eventInvites[i]; CalendarInvite* invite = eventInvites[i];
@@ -174,16 +186,16 @@ CalendarEventStore::iterator CalendarMgr::RemoveEvent(uint64 eventId, uint64 rem
delete invite; delete invite;
} }
_invites.erase(eventId); _invites.erase(calendarEvent->GetEventId());
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CALENDAR_EVENT); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CALENDAR_EVENT);
stmt->setUInt64(0, eventId); stmt->setUInt64(0, calendarEvent->GetEventId());
trans->Append(stmt); trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans); CharacterDatabase.CommitTransaction(trans);
delete calendarEvent; delete calendarEvent;
current = _events.erase(current); _events.erase(calendarEvent);
return current; return;
} }
void CalendarMgr::RemoveInvite(uint64 inviteId, uint64 eventId, uint64 /*remover*/) void CalendarMgr::RemoveInvite(uint64 inviteId, uint64 eventId, uint64 /*remover*/)
@@ -260,12 +272,13 @@ void CalendarMgr::RemoveAllPlayerEventsAndInvites(uint64 guid)
{ {
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();)
{ {
if ((*itr)->GetCreatorGUID() == guid) CalendarEvent* event = *itr;
++itr;
if (event->GetCreatorGUID() == guid)
{ {
itr = RemoveEvent((*itr)->GetEventId(), 0); // don't send mail if removing a character RemoveEvent(event, 0);
continue; continue;
} }
++itr;
} }
CalendarInviteStore playerInvites = GetPlayerInvites(guid); CalendarInviteStore playerInvites = GetPlayerInvites(guid);
@@ -275,15 +288,9 @@ void CalendarMgr::RemoveAllPlayerEventsAndInvites(uint64 guid)
void CalendarMgr::RemovePlayerGuildEventsAndSignups(uint64 guid, uint32 guildId) void CalendarMgr::RemovePlayerGuildEventsAndSignups(uint64 guid, uint32 guildId)
{ {
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr)
{
if ((*itr)->GetCreatorGUID() == guid && ((*itr)->IsGuildEvent() || (*itr)->IsGuildAnnouncement())) if ((*itr)->GetCreatorGUID() == guid && ((*itr)->IsGuildEvent() || (*itr)->IsGuildAnnouncement()))
{ RemoveEvent((*itr)->GetEventId(), guid);
itr = RemoveEvent((*itr)->GetEventId(), guid);
continue;
}
++itr;
}
CalendarInviteStore playerInvites = GetPlayerInvites(guid); CalendarInviteStore playerInvites = GetPlayerInvites(guid);
for (CalendarInviteStore::const_iterator itr = playerInvites.begin(); itr != playerInvites.end(); ++itr) for (CalendarInviteStore::const_iterator itr = playerInvites.begin(); itr != playerInvites.end(); ++itr)
@@ -292,17 +299,13 @@ void CalendarMgr::RemovePlayerGuildEventsAndSignups(uint64 guid, uint32 guildId)
RemoveInvite((*itr)->GetInviteId(), (*itr)->GetEventId(), guid); RemoveInvite((*itr)->GetInviteId(), (*itr)->GetEventId(), guid);
} }
CalendarEvent* CalendarMgr::GetEvent(uint64 eventId, CalendarEventStore::iterator* it) CalendarEvent* CalendarMgr::GetEvent(uint64 eventId)
{ {
for (CalendarEventStore::iterator itr = _events.begin(); itr != _events.end(); ++itr) for (CalendarEventStore::iterator itr = _events.begin(); itr != _events.end(); ++itr)
if ((*itr)->GetEventId() == eventId) if ((*itr)->GetEventId() == eventId)
{
if (it)
*it = itr;
return *itr; return *itr;
}
return NULL; return nullptr;
} }
CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId) const CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId) const
@@ -315,7 +318,7 @@ CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId) const
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
sLog->outDebug(LOG_FILTER_UNITS, "CalendarMgr::GetInvite: [" UI64FMTD "] not found!", inviteId); sLog->outDebug(LOG_FILTER_UNITS, "CalendarMgr::GetInvite: [" UI64FMTD "] not found!", inviteId);
#endif #endif
return NULL; return nullptr;
} }
void CalendarMgr::FreeEventId(uint64 id) void CalendarMgr::FreeEventId(uint64 id)
@@ -354,6 +357,44 @@ uint64 CalendarMgr::GetFreeInviteId()
return inviteId; return inviteId;
} }
void CalendarMgr::DeleteOldEvents()
{
time_t oldEventsTime = time(nullptr) - CALENDAR_OLD_EVENTS_DELETION_TIME;
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();)
{
CalendarEvent* event = *itr;
++itr;
if (event->GetEventTime() < oldEventsTime)
RemoveEvent(event, 0);
}
}
CalendarEventStore CalendarMgr::GetEventsCreatedBy(uint64 guid, bool includeGuildEvents)
{
CalendarEventStore result;
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr)
if ((*itr)->GetCreatorGUID() == guid && (includeGuildEvents || (!(*itr)->IsGuildEvent() && !(*itr)->IsGuildAnnouncement())))
result.insert(*itr);
return result;
}
CalendarEventStore CalendarMgr::GetGuildEvents(uint32 guildId)
{
CalendarEventStore result;
if (!guildId)
return result;
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr)
if ((*itr)->IsGuildEvent() || (*itr)->IsGuildAnnouncement())
if ((*itr)->GetGuildId() == guildId)
result.insert(*itr);
return result;
}
CalendarEventStore CalendarMgr::GetPlayerEvents(uint64 guid) CalendarEventStore CalendarMgr::GetPlayerEvents(uint64 guid)
{ {
CalendarEventStore events; CalendarEventStore events;
@@ -365,9 +406,10 @@ CalendarEventStore CalendarMgr::GetPlayerEvents(uint64 guid)
events.insert(event); events.insert(event);
if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(guid)) if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(guid))
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) if (player->GetGuildId())
if ((*itr)->GetGuildId() == player->GetGuildId()) for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr)
events.insert(*itr); if ((*itr)->GetGuildId() == player->GetGuildId())
events.insert(*itr);
return events; return events;
} }

View File

@@ -110,9 +110,14 @@ enum CalendarError
CALENDAR_ERROR_NO_MODERATOR = 40 CALENDAR_ERROR_NO_MODERATOR = 40
}; };
#define CALENDAR_MAX_EVENTS 30 enum CalendarLimits
#define CALENDAR_MAX_GUILD_EVENTS 100 {
#define CALENDAR_MAX_INVITES 100 CALENDAR_MAX_EVENTS = 30,
CALENDAR_MAX_GUILD_EVENTS = 100,
CALENDAR_MAX_INVITES = 100,
CALENDAR_CREATE_EVENT_COOLDOWN = 5,
CALENDAR_OLD_EVENTS_DELETION_TIME = 1 * MONTH,
};
struct CalendarInvite struct CalendarInvite
{ {
@@ -235,6 +240,9 @@ struct CalendarEvent
bool IsGuildEvent() const { return _flags & CALENDAR_FLAG_GUILD_EVENT; } bool IsGuildEvent() const { return _flags & CALENDAR_FLAG_GUILD_EVENT; }
bool IsGuildAnnouncement() const { return _flags & CALENDAR_FLAG_WITHOUT_INVITES; } bool IsGuildAnnouncement() const { return _flags & CALENDAR_FLAG_WITHOUT_INVITES; }
static bool IsGuildEvent(uint32 flags) { return (flags & CALENDAR_FLAG_GUILD_EVENT) != 0; }
static bool IsGuildAnnouncement(uint32 flags) { return (flags & CALENDAR_FLAG_WITHOUT_INVITES) != 0; }
std::string BuildCalendarMailSubject(uint64 remover) const; std::string BuildCalendarMailSubject(uint64 remover) const;
std::string BuildCalendarMailBody() const; std::string BuildCalendarMailBody() const;
@@ -273,9 +281,11 @@ class CalendarMgr
void LoadFromDB(); void LoadFromDB();
CalendarEvent* GetEvent(uint64 eventId, CalendarEventStore::iterator* it = NULL); CalendarEvent* GetEvent(uint64 eventId);
CalendarEventStore const& GetEvents() const { return _events; } CalendarEventStore const& GetEvents() const { return _events; }
CalendarEventStore GetEventsCreatedBy(uint64 guid, bool includeGuildEvents = false);
CalendarEventStore GetPlayerEvents(uint64 guid); CalendarEventStore GetPlayerEvents(uint64 guid);
CalendarEventStore GetGuildEvents(uint32 guildId);
CalendarInvite* GetInvite(uint64 inviteId) const; CalendarInvite* GetInvite(uint64 inviteId) const;
CalendarEventInviteStore const& GetInvites() const { return _invites; } CalendarEventInviteStore const& GetInvites() const { return _invites; }
@@ -287,10 +297,13 @@ class CalendarMgr
void FreeInviteId(uint64 id); void FreeInviteId(uint64 id);
uint64 GetFreeInviteId(); uint64 GetFreeInviteId();
void DeleteOldEvents();
uint32 GetPlayerNumPending(uint64 guid); uint32 GetPlayerNumPending(uint64 guid);
void AddEvent(CalendarEvent* calendarEvent, CalendarSendEventType sendType); void AddEvent(CalendarEvent* calendarEvent, CalendarSendEventType sendType);
CalendarEventStore::iterator RemoveEvent(uint64 eventId, uint64 remover); void RemoveEvent(uint64 eventId, uint64 remover);
void RemoveEvent(CalendarEvent* calendarEvent, uint64 remover);
void UpdateEvent(CalendarEvent* calendarEvent); void UpdateEvent(CalendarEvent* calendarEvent);
void AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite); void AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite);

View File

@@ -239,7 +239,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
recvData >> flags; recvData >> flags;
// prevent attacks with non-utf8 chars -> with multiple packets it will hang up the db due to errors. // prevent attacks with non-utf8 chars -> with multiple packets it will hang up the db due to errors.
if (!validUtf8String(recvData, title, "create", guid) || !validUtf8String(recvData, description, "create", guid)) if (!validUtf8String(recvData, title, "create", guid) || title.size() > 31 || !validUtf8String(recvData, description, "create", guid) || description.size() > 255)
return; return;
// prevent events in the past // prevent events in the past
@@ -247,9 +247,49 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
if (time_t(eventPackedTime) < (time(NULL) - time_t(86400L))) if (time_t(eventPackedTime) < (time(NULL) - time_t(86400L)))
{ {
recvData.rfinish(); recvData.rfinish();
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_PASSED);
return; return;
} }
// If the event is a guild event, check if the player is in a guild
if (CalendarEvent::IsGuildEvent(flags) || CalendarEvent::IsGuildAnnouncement(flags))
{
if (!_player->GetGuildId())
{
recvData.rfinish();
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_GUILD_PLAYER_NOT_IN_GUILD);
return;
}
}
// Check if the player reached the max number of events allowed to create
if (CalendarEvent::IsGuildEvent(flags) || CalendarEvent::IsGuildAnnouncement(flags))
{
if (sCalendarMgr->GetGuildEvents(_player->GetGuildId()).size() >= CALENDAR_MAX_GUILD_EVENTS)
{
recvData.rfinish();
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_GUILD_EVENTS_EXCEEDED);
return;
}
}
else
{
if (sCalendarMgr->GetEventsCreatedBy(guid).size() >= CALENDAR_MAX_EVENTS)
{
recvData.rfinish();
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENTS_EXCEEDED);
return;
}
}
if (GetCalendarEventCreationCooldown() > time(nullptr))
{
recvData.rfinish();
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_INTERNAL);
return;
}
SetCalendarEventCreationCooldown(time(nullptr) + CALENDAR_CREATE_EVENT_COOLDOWN);
CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId,
time_t(eventPackedTime), flags, time_t(unkPackedTime), title, description); time_t(eventPackedTime), flags, time_t(unkPackedTime), title, description);
@@ -265,13 +305,10 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
} }
else else
{ {
// client limits the amount of players to be invited to 100
const uint32 MaxPlayerInvites = 100;
uint32 inviteCount; uint32 inviteCount;
uint64 invitee[MaxPlayerInvites]; uint64 invitee[CALENDAR_MAX_INVITES];
uint8 status[MaxPlayerInvites]; uint8 status[CALENDAR_MAX_INVITES];
uint8 rank[MaxPlayerInvites]; uint8 rank[CALENDAR_MAX_INVITES];
memset(invitee, 0, sizeof(invitee)); memset(invitee, 0, sizeof(invitee));
memset(status, 0, sizeof(status)); memset(status, 0, sizeof(status));
@@ -281,7 +318,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
{ {
recvData >> inviteCount; recvData >> inviteCount;
for (uint32 i = 0; i < inviteCount && i < MaxPlayerInvites; ++i) for (uint32 i = 0; i < inviteCount && i < CALENDAR_MAX_INVITES; ++i)
{ {
recvData.readPackGUID(invitee[i]); recvData.readPackGUID(invitee[i]);
recvData >> status[i] >> rank[i]; recvData >> status[i] >> rank[i];
@@ -298,7 +335,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
if (inviteCount > 1) if (inviteCount > 1)
trans = CharacterDatabase.BeginTransaction(); trans = CharacterDatabase.BeginTransaction();
for (uint32 i = 0; i < inviteCount && i < MaxPlayerInvites; ++i) for (uint32 i = 0; i < inviteCount && i < CALENDAR_MAX_INVITES; ++i)
{ {
// 946684800 is 01/01/2000 00:00:00 - default response time // 946684800 is 01/01/2000 00:00:00 - default response time
CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent->GetEventId(), invitee[i], guid, 946684800, CalendarInviteStatus(status[i]), CalendarModerationRank(rank[i]), ""); CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent->GetEventId(), invitee[i], guid, 946684800, CalendarInviteStatus(status[i]), CalendarModerationRank(rank[i]), "");
@@ -335,7 +372,7 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recvData)
recvData >> flags; recvData >> flags;
// prevent attacks with non-utf8 chars -> with multiple packets it will hang up the db due to errors. // prevent attacks with non-utf8 chars -> with multiple packets it will hang up the db due to errors.
if (!validUtf8String(recvData, title, "update", guid) || !validUtf8String(recvData, description, "update", guid)) if (!validUtf8String(recvData, title, "update", guid) || title.size() > 31 || !validUtf8String(recvData, description, "update", guid) || description.size() > 255)
return; return;
// prevent events in the past // prevent events in the past
@@ -400,11 +437,55 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket& recvData)
if (time_t(eventTime) < (time(NULL) - time_t(86400L))) if (time_t(eventTime) < (time(NULL) - time_t(86400L)))
{ {
recvData.rfinish(); recvData.rfinish();
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_PASSED);
return; return;
} }
if (CalendarEvent* oldEvent = sCalendarMgr->GetEvent(eventId)) if (CalendarEvent* oldEvent = sCalendarMgr->GetEvent(eventId))
{ {
// Ensure that the player has access to the event
if (oldEvent->IsGuildEvent() || oldEvent->IsGuildAnnouncement())
{
if (oldEvent->GetGuildId() != _player->GetGuildId())
{
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_INVALID);
return;
}
}
else
{
if (oldEvent->GetCreatorGUID() != guid)
{
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_INVALID);
return;
}
}
// Check if the player reached the max number of events allowed to create
if (oldEvent->IsGuildEvent() || oldEvent->IsGuildAnnouncement())
{
if (sCalendarMgr->GetGuildEvents(_player->GetGuildId()).size() >= CALENDAR_MAX_GUILD_EVENTS)
{
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_GUILD_EVENTS_EXCEEDED);
return;
}
}
else
{
if (sCalendarMgr->GetEventsCreatedBy(guid).size() >= CALENDAR_MAX_EVENTS)
{
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENTS_EXCEEDED);
return;
}
}
if (GetCalendarEventCreationCooldown() > time(nullptr))
{
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_INTERNAL);
return;
}
SetCalendarEventCreationCooldown(time(nullptr) + CALENDAR_CREATE_EVENT_COOLDOWN);
CalendarEvent* newEvent = new CalendarEvent(*oldEvent, sCalendarMgr->GetFreeEventId()); CalendarEvent* newEvent = new CalendarEvent(*oldEvent, sCalendarMgr->GetFreeEventId());
newEvent->SetEventTime(time_t(eventTime)); newEvent->SetEventTime(time_t(eventTime));
sCalendarMgr->AddEvent(newEvent, CALENDAR_SENDTYPE_COPY); sCalendarMgr->AddEvent(newEvent, CALENDAR_SENDTYPE_COPY);

View File

@@ -113,7 +113,8 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
recruiterId(recruiter), recruiterId(recruiter),
isRecruiter(isARecruiter), isRecruiter(isARecruiter),
m_currentBankerGUID(0), m_currentBankerGUID(0),
timeWhoCommandAllowed(0) timeWhoCommandAllowed(0),
_calendarEventCreationCooldown(0)
{ {
memset(m_Tutorials, 0, sizeof(m_Tutorials)); memset(m_Tutorials, 0, sizeof(m_Tutorials));

View File

@@ -317,8 +317,6 @@ class WorldSession
m_TutorialsChanged = true; m_TutorialsChanged = true;
} }
} }
//used with item_page table
bool SendItemInfo(uint32 itemid, WorldPacket data);
//auction //auction
void SendAuctionHello(uint64 guid, Creature* unit); void SendAuctionHello(uint64 guid, Creature* unit);
void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0); void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
@@ -381,6 +379,10 @@ class WorldSession
uint32 GetRecruiterId() const { return recruiterId; } uint32 GetRecruiterId() const { return recruiterId; }
bool IsARecruiter() const { return isRecruiter; } bool IsARecruiter() const { return isRecruiter; }
// Packets cooldown
time_t GetCalendarEventCreationCooldown() const { return _calendarEventCreationCooldown; }
void SetCalendarEventCreationCooldown(time_t cooldown) { _calendarEventCreationCooldown = cooldown; }
public: // opcodes handlers public: // opcodes handlers
void Handle_NULL(WorldPacket& recvPacket); // not used void Handle_NULL(WorldPacket& recvPacket); // not used
@@ -405,7 +407,6 @@ class WorldSession
// new // new
void HandleMoveUnRootAck(WorldPacket& recvPacket); void HandleMoveUnRootAck(WorldPacket& recvPacket);
void HandleMoveRootAck(WorldPacket& recvPacket); void HandleMoveRootAck(WorldPacket& recvPacket);
void HandleLookingForGroup(WorldPacket& recvPacket);
// new inspect // new inspect
void HandleInspectOpcode(WorldPacket& recvPacket); void HandleInspectOpcode(WorldPacket& recvPacket);
@@ -433,8 +434,6 @@ class WorldSession
void HandleMoveTeleportAck(WorldPacket& recvPacket); void HandleMoveTeleportAck(WorldPacket& recvPacket);
void HandleForceSpeedChangeAck(WorldPacket& recvData); void HandleForceSpeedChangeAck(WorldPacket& recvData);
void HandlePingOpcode(WorldPacket& recvPacket);
void HandleAuthSessionOpcode(WorldPacket& recvPacket);
void HandleRepopRequestOpcode(WorldPacket& recvPacket); void HandleRepopRequestOpcode(WorldPacket& recvPacket);
void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket); void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket);
void HandleLootMoneyOpcode(WorldPacket& recvPacket); void HandleLootMoneyOpcode(WorldPacket& recvPacket);
@@ -484,7 +483,6 @@ class WorldSession
void HandleSetActionButtonOpcode(WorldPacket& recvPacket); void HandleSetActionButtonOpcode(WorldPacket& recvPacket);
void HandleGameObjectUseOpcode(WorldPacket& recPacket); void HandleGameObjectUseOpcode(WorldPacket& recPacket);
void HandleMeetingStoneInfo(WorldPacket& recPacket);
void HandleGameobjectReportUse(WorldPacket& recvPacket); void HandleGameobjectReportUse(WorldPacket& recvPacket);
void HandleNameQueryOpcode(WorldPacket& recvPacket); void HandleNameQueryOpcode(WorldPacket& recvPacket);
@@ -511,7 +509,6 @@ class WorldSession
void HandleBattlefieldStatusOpcode(WorldPacket& recvData); void HandleBattlefieldStatusOpcode(WorldPacket& recvData);
void HandleGroupInviteOpcode(WorldPacket& recvPacket); void HandleGroupInviteOpcode(WorldPacket& recvPacket);
//void HandleGroupCancelOpcode(WorldPacket& recvPacket);
void HandleGroupAcceptOpcode(WorldPacket& recvPacket); void HandleGroupAcceptOpcode(WorldPacket& recvPacket);
void HandleGroupDeclineOpcode(WorldPacket& recvPacket); void HandleGroupDeclineOpcode(WorldPacket& recvPacket);
void HandleGroupUninviteOpcode(WorldPacket& recvPacket); void HandleGroupUninviteOpcode(WorldPacket& recvPacket);
@@ -631,7 +628,6 @@ class WorldSession
void HandleQueryNextMailTime(WorldPacket& recvData); void HandleQueryNextMailTime(WorldPacket& recvData);
void HandleCancelChanneling(WorldPacket& recvData); void HandleCancelChanneling(WorldPacket& recvData);
void SendItemPageInfo(ItemTemplate* itemProto);
void HandleSplitItemOpcode(WorldPacket& recvPacket); void HandleSplitItemOpcode(WorldPacket& recvPacket);
void HandleSwapInvItemOpcode(WorldPacket& recvPacket); void HandleSwapInvItemOpcode(WorldPacket& recvPacket);
void HandleDestroyItemOpcode(WorldPacket& recvPacket); void HandleDestroyItemOpcode(WorldPacket& recvPacket);
@@ -713,7 +709,6 @@ class WorldSession
void HandleChannelBan(WorldPacket& recvPacket); void HandleChannelBan(WorldPacket& recvPacket);
void HandleChannelUnban(WorldPacket& recvPacket); void HandleChannelUnban(WorldPacket& recvPacket);
void HandleChannelAnnouncements(WorldPacket& recvPacket); void HandleChannelAnnouncements(WorldPacket& recvPacket);
void HandleChannelModerate(WorldPacket& recvPacket);
void HandleChannelDeclineInvite(WorldPacket& recvPacket); void HandleChannelDeclineInvite(WorldPacket& recvPacket);
void HandleChannelDisplayListQuery(WorldPacket& recvPacket); void HandleChannelDisplayListQuery(WorldPacket& recvPacket);
void HandleGetChannelMemberCount(WorldPacket& recvPacket); void HandleGetChannelMemberCount(WorldPacket& recvPacket);
@@ -1041,6 +1036,8 @@ class WorldSession
uint32 _offlineTime; uint32 _offlineTime;
bool _kicked; bool _kicked;
bool _shouldSetOfflineInDB; bool _shouldSetOfflineInDB;
// Packets cooldown
time_t _calendarEventCreationCooldown;
}; };
#endif #endif
/// @} /// @}

View File

@@ -111,6 +111,7 @@ World::World()
m_NextWeeklyQuestReset = 0; m_NextWeeklyQuestReset = 0;
m_NextMonthlyQuestReset = 0; m_NextMonthlyQuestReset = 0;
m_NextRandomBGReset = 0; m_NextRandomBGReset = 0;
m_NextCalendarOldEventsDeletionTime = 0;
m_NextGuildReset = 0; m_NextGuildReset = 0;
m_defaultDbcLocale = LOCALE_enUS; m_defaultDbcLocale = LOCALE_enUS;
@@ -1071,6 +1072,13 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = 6; m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = 6;
} }
m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] = sConfigMgr->GetIntDefault("Calendar.DeleteOldEventsHour", 6);
if (m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] > 23)
{
sLog->outError("Calendar.DeleteOldEventsHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR]);
m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] = 6;
}
m_int_configs[CONFIG_GUILD_RESET_HOUR] = sConfigMgr->GetIntDefault("Guild.ResetHour", 6); m_int_configs[CONFIG_GUILD_RESET_HOUR] = sConfigMgr->GetIntDefault("Guild.ResetHour", 6);
if (m_int_configs[CONFIG_GUILD_RESET_HOUR] > 23) if (m_int_configs[CONFIG_GUILD_RESET_HOUR] > 23)
{ {
@@ -1964,6 +1972,9 @@ void World::SetInitialWorldSettings()
sLog->outString("Calculate random battleground reset time..." ); sLog->outString("Calculate random battleground reset time..." );
InitRandomBGResetTime(); InitRandomBGResetTime();
sLog->outString("Calculate deletion of old calendar events time...");
InitCalendarOldEventsDeletionTime();
sLog->outString("Calculate Guild cap reset time..."); sLog->outString("Calculate Guild cap reset time...");
InitGuildResetTime(); InitGuildResetTime();
@@ -2165,6 +2176,9 @@ void World::Update(uint32 diff)
if (m_gameTime > m_NextRandomBGReset) if (m_gameTime > m_NextRandomBGReset)
ResetRandomBG(); ResetRandomBG();
if (m_gameTime > m_NextCalendarOldEventsDeletionTime)
CalendarDeleteOldEvents();
if (m_gameTime > m_NextGuildReset) if (m_gameTime > m_NextGuildReset)
ResetGuildCap(); ResetGuildCap();
@@ -2882,6 +2896,23 @@ void World::InitRandomBGResetTime()
sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset)); sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset));
} }
void World::InitCalendarOldEventsDeletionTime()
{
time_t now = time(nullptr);
time_t currentDeletionTime = getWorldState(WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME);
time_t nextDeletionTime = currentDeletionTime ? currentDeletionTime : GetNextTimeWithDayAndHour(-1, getIntConfig(CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR));
// If the reset time saved in the worldstate is before now it means the server was offline when the reset was supposed to occur.
// In this case we set the reset time in the past and next world update will do the reset and schedule next one in the future.
if (currentDeletionTime < now)
m_NextCalendarOldEventsDeletionTime = nextDeletionTime - DAY;
else
m_NextCalendarOldEventsDeletionTime = nextDeletionTime;
if (!currentDeletionTime)
sWorld->setWorldState(WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME, uint64(m_NextCalendarOldEventsDeletionTime));
}
void World::InitGuildResetTime() void World::InitGuildResetTime()
{ {
time_t wstime = time_t(getWorldState(WS_GUILD_DAILY_RESET_TIME)); time_t wstime = time_t(getWorldState(WS_GUILD_DAILY_RESET_TIME));
@@ -2984,6 +3015,15 @@ void World::ResetRandomBG()
sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset)); sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset));
} }
void World::CalendarDeleteOldEvents()
{
sLog->outString("Calendar deletion of old events.");
m_NextCalendarOldEventsDeletionTime = time_t(m_NextCalendarOldEventsDeletionTime + DAY);
sWorld->setWorldState(WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME, uint64(m_NextCalendarOldEventsDeletionTime));
sCalendarMgr->DeleteOldEvents();
}
void World::ResetGuildCap() void World::ResetGuildCap()
{ {
sLog->outString("Guild Daily Cap reset."); sLog->outString("Guild Daily Cap reset.");

View File

@@ -316,6 +316,7 @@ enum WorldIntConfigs
CONFIG_GUILD_BANK_EVENT_LOG_COUNT, CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
CONFIG_MIN_LEVEL_STAT_SAVE, CONFIG_MIN_LEVEL_STAT_SAVE,
CONFIG_RANDOM_BG_RESET_HOUR, CONFIG_RANDOM_BG_RESET_HOUR,
CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR,
CONFIG_GUILD_RESET_HOUR, CONFIG_GUILD_RESET_HOUR,
CONFIG_CHARDELETE_KEEP_DAYS, CONFIG_CHARDELETE_KEEP_DAYS,
CONFIG_CHARDELETE_METHOD, CONFIG_CHARDELETE_METHOD,
@@ -493,13 +494,14 @@ enum RealmZone
enum WorldStates enum WorldStates
{ {
WS_ARENA_DISTRIBUTION_TIME = 20001, // Next arena distribution time WS_ARENA_DISTRIBUTION_TIME = 20001, // Next arena distribution time
WS_WEEKLY_QUEST_RESET_TIME = 20002, // Next weekly reset time WS_WEEKLY_QUEST_RESET_TIME = 20002, // Next weekly reset time
WS_BG_DAILY_RESET_TIME = 20003, // Next daily BG reset time WS_BG_DAILY_RESET_TIME = 20003, // Next daily BG reset time
WS_CLEANING_FLAGS = 20004, // Cleaning Flags WS_CLEANING_FLAGS = 20004, // Cleaning Flags
WS_DAILY_QUEST_RESET_TIME = 20005, // Next daily reset time WS_DAILY_QUEST_RESET_TIME = 20005, // Next daily reset time
WS_GUILD_DAILY_RESET_TIME = 20006, // Next guild cap reset time WS_GUILD_DAILY_RESET_TIME = 20006, // Next guild cap reset time
WS_MONTHLY_QUEST_RESET_TIME = 20007, // Next monthly reset time WS_MONTHLY_QUEST_RESET_TIME = 20007, // Next monthly reset time
WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME = 20008 // Next daily calendar deletions of old events time
}; };
/// Storage class for commands issued for delayed execution /// Storage class for commands issued for delayed execution
@@ -812,11 +814,13 @@ class World
void InitWeeklyQuestResetTime(); void InitWeeklyQuestResetTime();
void InitMonthlyQuestResetTime(); void InitMonthlyQuestResetTime();
void InitRandomBGResetTime(); void InitRandomBGResetTime();
void InitCalendarOldEventsDeletionTime();
void InitGuildResetTime(); void InitGuildResetTime();
void ResetDailyQuests(); void ResetDailyQuests();
void ResetWeeklyQuests(); void ResetWeeklyQuests();
void ResetMonthlyQuests(); void ResetMonthlyQuests();
void ResetRandomBG(); void ResetRandomBG();
void CalendarDeleteOldEvents();
void ResetGuildCap(); void ResetGuildCap();
private: private:
static ACE_Atomic_Op<ACE_Thread_Mutex, bool> m_stopEvent; static ACE_Atomic_Op<ACE_Thread_Mutex, bool> m_stopEvent;
@@ -879,6 +883,7 @@ class World
time_t m_NextWeeklyQuestReset; time_t m_NextWeeklyQuestReset;
time_t m_NextMonthlyQuestReset; time_t m_NextMonthlyQuestReset;
time_t m_NextRandomBGReset; time_t m_NextRandomBGReset;
time_t m_NextCalendarOldEventsDeletionTime;
time_t m_NextGuildReset; time_t m_NextGuildReset;
//Player Queue //Player Queue

View File

@@ -1338,6 +1338,14 @@ Quests.IgnoreAutoAccept = 0
Quests.IgnoreAutoComplete = 0 Quests.IgnoreAutoComplete = 0
#
# Calendar.DeleteOldEventsHour
# Description: Hour of the day when the daily deletion of old calendar events occurs.
# Range: 0-23
# Default: 6 - (06:00 AM)
Calendar.DeleteOldEventsHour = 6
# #
# Guild.EventLogRecordsCount # Guild.EventLogRecordsCount
# Description: Number of log entries for guild events that are stored per guild. Old entries # Description: Number of log entries for guild events that are stored per guild. Old entries