[10353] Avoid access to DB at view GM tickets by chat commands.

Also
* Show response text if added at view.
* Show tickets amount at console .ticket use instead unexpected no player error.
* Allow use ticket number in .ticket respond case.
* Some code cleanups.
This commit is contained in:
VladimirMangos 2010-08-13 03:56:53 +04:00
parent 12aa1bc606
commit 7e70bba865
11 changed files with 155 additions and 80 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0',
`required_10350_02_mangos_command` bit(1) default NULL
`required_10353_02_mangos_command` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -766,7 +766,7 @@ INSERT INTO `command` VALUES
('tele del',3,'Syntax: .tele del $name\r\n\r\nRemove location with name $name for .tele command locations list.'),
('tele group',1,'Syntax: .tele group#location\r\n\r\nTeleport a selected player and his group members to a given location.'),
('tele name',1,'Syntax: .tele name [#playername] #location\r\n\r\nTeleport the given character to a given location. Character can be offline.'),
('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.'),
('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n .ticket respond #num $response\r\n .ticket respond $character_name $response\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.'),
('titles add',2,'Syntax: .titles add #title\r\nAdd title #title (id or shift-link) to known titles list for selected player.'),
('titles current',2,'Syntax: .titles current #title\r\nSet title #title (id or shift-link) as current selected titl for selected player. If title not in known title list for player then it will be added to list.'),
('titles remove',2,'Syntax: .titles remove #title\r\nRemove title #title (id or shift-link) from known titles list for selected player.'),
@ -3297,6 +3297,9 @@ INSERT INTO `mangos_string` VALUES
(370,'Required heroic keys:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(371,'Required quest (heroic difficulty):',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(372,'No achievement!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(373,'Response:\n%s ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(374,'Tickets count: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(375,'Player %s not have tickets.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),

View file

@ -0,0 +1,8 @@
ALTER TABLE db_version CHANGE COLUMN required_10350_02_mangos_command required_10353_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN (373, 374, 375);
INSERT INTO mangos_string VALUES
(373,'Response:\n%s ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(374,'Tickets count: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(375,'Player %s not have tickets.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_10353_01_mangos_mangos_string required_10353_02_mangos_command bit;
DELETE FROM command WHERE name IN ('ticket');
INSERT INTO command (name, security, help) VALUES
('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n .ticket respond #num $response\r\n .ticket respond $character_name $response\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.');

View file

@ -78,6 +78,8 @@ pkgdata_DATA = \
10342_02_mangos_command.sql \
10349_01_mangos_spell_proc_event.sql \
10350_02_mangos_command.sql \
10353_01_mangos_mangos_string.sql \
10353_02_mangos_command.sql \
README
## Additional files to include when running 'make dist'
@ -136,4 +138,6 @@ EXTRA_DIST = \
10342_02_mangos_command.sql \
10349_01_mangos_spell_proc_event.sql \
10350_02_mangos_command.sql \
10353_01_mangos_mangos_string.sql \
10353_02_mangos_command.sql \
README

View file

@ -31,6 +31,7 @@ struct GameTele;
class ChatHandler;
class WorldSession;
class GMTicket;
class Creature;
class Player;
class Unit;
@ -608,7 +609,7 @@ class ChatHandler
void ShowQuestListHelper(uint32 questId, int32 loc_idx, Player* target = NULL);
bool ShowPlayerListHelper(QueryResult* result, uint32* limit = NULL, bool title = true, bool error = true);
void ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc);
void ShowTicket(uint64 guid, char const* text, char const* time);
void ShowTicket(GMTicket const* ticket);
void ShowTriggerListHelper(AreaTriggerEntry const * atEntry);
void ShowTriggerTargetListHelper(uint32 id, AreaTrigger const* at, bool subpart = false);
bool LookupPlayerSearchCommand(QueryResult* result, uint32* limit = NULL);

View file

@ -33,8 +33,8 @@ void GMTicketMgr::LoadGMTickets()
m_GMTicketMap.clear(); // For reload case
QueryResult *result = CharacterDatabase.Query(
// 0 1 2 3
"SELECT guid, ticket_text, response_text, UNIX_TIMESTAMP(ticket_lastchange) FROM character_ticket");
// 0 1 2 3 4
"SELECT guid, ticket_text, response_text, UNIX_TIMESTAMP(ticket_lastchange), ticket_id FROM character_ticket ORDER BY ticket_id ASC");
if( !result )
{
@ -49,8 +49,6 @@ void GMTicketMgr::LoadGMTickets()
barGoLink bar( (int)result->GetRowCount() );
uint32 count = 0;
do
{
bar.step();
@ -58,14 +56,25 @@ void GMTicketMgr::LoadGMTickets()
Field* fields = result->Fetch();
uint32 guid = fields[0].GetUInt32();
m_GMTicketMap[guid] = GMTicket(guid, fields[1].GetCppString(), fields[2].GetCppString(), time_t(fields[3].GetUInt64()));
++count;
if (!guid)
continue;
GMTicket& ticket = m_GMTicketMap[guid];
if (ticket.GetPlayerLowGuid() != 0) // already exist
{
CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE ticket_id = '%u'", fields[4].GetUInt32());
continue;
}
ticket.Init(guid, fields[1].GetCppString(), fields[2].GetCppString(), time_t(fields[3].GetUInt64()));
m_GMTicketListByCreatingOrder.push_back(&ticket);
} while (result->NextRow());
delete result;
sLog.outString();
sLog.outString( ">> Loaded %d GM tickets", count );
sLog.outString(">> Loaded %d GM tickets", GetTicketCount());
}
void GMTicketMgr::DeleteAll()
@ -76,5 +85,6 @@ void GMTicketMgr::DeleteAll()
owner->GetSession()->SendGMTicketGetTicket(0x0A, 0);
}
CharacterDatabase.Execute("DELETE FROM character_ticket");
m_GMTicketListByCreatingOrder.clear();
m_GMTicketMap.clear();
}

View file

@ -27,13 +27,21 @@
class GMTicket
{
public:
explicit GMTicket()
explicit GMTicket() : m_guid(0), m_lastUpdate(0)
{
}
GMTicket(uint32 guid, const std::string& text, const std::string& responsetext, time_t update) : m_guid(guid), m_text(text), m_responseText(responsetext), m_lastUpdate(update)
void Init(uint32 guid, const std::string& text, const std::string& responsetext, time_t update)
{
m_guid = guid;
m_text = text;
m_responseText = responsetext;
m_lastUpdate =update;
}
uint32 GetPlayerLowGuid() const
{
return m_guid;
}
const char* GetText() const
@ -99,6 +107,7 @@ class GMTicket
time_t m_lastUpdate;
};
typedef std::map<uint32, GMTicket> GMTicketMap;
typedef std::list<GMTicket*> GMTicketList; // for creating order access
class GMTicketMgr
{
@ -121,12 +130,26 @@ class GMTicketMgr
return m_GMTicketMap.size();
}
GMTicket* GetGMTicketByOrderPos(uint32 pos)
{
if (pos >= GetTicketCount())
return NULL;
GMTicketList::iterator itr = m_GMTicketListByCreatingOrder.begin();
std::advance(itr, pos);
if(itr == m_GMTicketListByCreatingOrder.end())
return NULL;
return *itr;
}
void Delete(uint32 guid)
{
GMTicketMap::iterator itr = m_GMTicketMap.find(guid);
if(itr == m_GMTicketMap.end())
return;
itr->second.DeleteFromDB();
m_GMTicketListByCreatingOrder.remove(&itr->second);
m_GMTicketMap.erase(itr);
}
@ -134,12 +157,20 @@ class GMTicketMgr
void Create(uint32 guid, const char* text)
{
GMTicket t = GMTicket(guid, text, "", time(NULL));
t.SaveToDB();
m_GMTicketMap[guid] = t;
GMTicket& ticket = m_GMTicketMap[guid];
if (ticket.GetPlayerLowGuid() != 0) // overwrite ticket
{
ticket.DeleteFromDB();
m_GMTicketListByCreatingOrder.remove(&ticket);
}
ticket.Init(guid, text, "", time(NULL));
ticket.SaveToDB();
m_GMTicketListByCreatingOrder.push_back(&ticket);
}
private:
GMTicketMap m_GMTicketMap;
GMTicketList m_GMTicketListByCreatingOrder;
};
#define sTicketMgr MaNGOS::Singleton<GMTicketMgr>::Instance()

View file

@ -361,7 +361,10 @@ enum MangosStrings
LANG_TRIGGER_REQ_KEYS_HEROIC = 370,
LANG_TRIGGER_REQ_QUEST_HEROIC = 371,
LANG_COMMAND_ACHIEVEMENT_NOTFOUND = 372,
// Room for more level 2 373-399 not used
LANG_COMMAND_TICKETRESPONSE = 373,
LANG_COMMAND_TICKETCOUNT_CONSOLE = 374,
LANG_COMMAND_TICKETNOTEXIST_NAME = 375,
// Room for more level 2 376-399 not used
// level 3 chat
LANG_SCRIPTS_RELOADED = 400,

View file

@ -2589,15 +2589,21 @@ bool ChatHandler::HandlePInfoCommand(char* args)
}
//show tickets
void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
void ChatHandler::ShowTicket(GMTicket const* ticket)
{
std::string lastupdated = TimeToTimestampStr(ticket->GetLastUpdate());
std::string name;
if (!sObjectMgr.GetPlayerNameByGUID(guid, name))
if (!sObjectMgr.GetPlayerNameByGUID(MAKE_NEW_GUID(ticket->GetPlayerLowGuid(), 0, HIGHGUID_PLAYER), name))
name = GetMangosString(LANG_UNKNOWN);
std::string nameLink = playerLink(name);
PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text);
char const* response = ticket->GetResponse();
PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(), lastupdated.c_str(), ticket->GetText());
if (strlen(response))
PSendSysMessage(LANG_COMMAND_TICKETRESPONSE, ticket->GetResponse());
}
//ticket commands
@ -2608,18 +2614,17 @@ bool ChatHandler::HandleTicketCommand(char* args)
// ticket<end>
if (!px)
{
if (!m_session)
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
return false;
}
size_t count = sTicketMgr.GetTicketCount();
if (m_session)
{
bool accept = m_session->GetPlayer()->isAcceptTickets();
PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
}
else
PSendSysMessage(LANG_COMMAND_TICKETCOUNT_CONSOLE, count);
return true;
}
@ -2656,42 +2661,50 @@ bool ChatHandler::HandleTicketCommand(char* args)
// ticket respond
if (strncmp(px, "respond", 8) == 0)
{
std::string plName = ExtractPlayerNameFromLink(&args);
if (plName.empty())
GMTicket* ticket = NULL;
// ticket respond #num
uint32 num;
if (ExtractUInt32(&args, num))
{
SendSysMessage(LANG_CMD_SYNTAX);
SetSentErrorMessage(true);
if (num == 0)
return false;
}
uint64 guid = sObjectMgr.GetPlayerGUIDByName(plName);
if (!guid)
{
SendSysMessage(LANG_PLAYER_NOT_FOUND);
SetSentErrorMessage(true);
return false;
}
GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(guid));
// mgr numbering tickets start from 0
ticket = sTicketMgr.GetGMTicketByOrderPos(num-1);
if (!ticket)
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, GUID_LOPART(guid));
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num);
SetSentErrorMessage(true);
return false;
}
}
else
{
uint64 target_guid;
std::string target_name;
if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name))
return false;
// ticket respond $char_name
ticket = sTicketMgr.GetGMTicket(GUID_LOPART(target_guid));
if (!ticket)
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str());
SetSentErrorMessage(true);
return false;
}
}
// no response text?
if (!*args)
{
SendSysMessage(LANG_CMD_SYNTAX);
SetSentErrorMessage(true);
return false;
}
ticket->SetResponseText(args);
if (Player* pl = sObjectMgr.GetPlayer(guid))
if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, ticket->GetPlayerLowGuid())))
pl->GetSession()->SendGMResponse(ticket);
return true;
@ -2704,38 +2717,34 @@ bool ChatHandler::HandleTicketCommand(char* args)
if (num == 0)
return false;
QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
if (!result)
// mgr numbering tickets start from 0
GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(num-1);
if (!ticket)
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num);
SetSentErrorMessage(true);
return false;
}
Field* fields = result->Fetch();
uint32 guid = fields[0].GetUInt32();
char const* text = fields[1].GetString();
char const* time = fields[2].GetString();
ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
delete result;
ShowTicket(ticket);
return true;
}
uint64 target_guid;
if (!ExtractPlayerTarget(&px, NULL, &target_guid))
std::string target_name;
if (!ExtractPlayerTarget(&px, NULL, &target_guid, &target_name))
return false;
// ticket $char_name
GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(target_guid));
if (!ticket)
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str());
SetSentErrorMessage(true);
return false;
}
std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
ShowTicket(target_guid, ticket->GetText(), time.c_str());
ShowTicket(ticket);
return true;
}
@ -2763,21 +2772,22 @@ bool ChatHandler::HandleDelTicketCommand(char *args)
if (num ==0)
return false;
QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
if (!result)
// mgr numbering tickets start from 0
GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(num-1);
if (!ticket)
{
PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num);
SetSentErrorMessage(true);
return false;
}
Field* fields = result->Fetch();
uint32 guid = fields[0].GetUInt32();
delete result;
sTicketMgr.Delete(guid);
uint32 lowguid = ticket->GetPlayerLowGuid();
sTicketMgr.Delete(lowguid);
//notify player
if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, guid)))
if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, lowguid)))
{
pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str());

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10352"
#define REVISION_NR "10353"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_10332_02_characters_pet_aura"
#define REVISION_DB_MANGOS "required_10350_02_mangos_command"
#define REVISION_DB_MANGOS "required_10353_02_mangos_command"
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__