mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-04 10:26:37 +00:00
svn -> git Migration
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
SET(ucs_sources
|
||||
chatchannel.cpp
|
||||
clientlist.cpp
|
||||
database.cpp
|
||||
ucs.cpp
|
||||
ucsconfig.cpp
|
||||
worldserver.cpp
|
||||
)
|
||||
|
||||
SET(ucs_headers
|
||||
chatchannel.h
|
||||
clientlist.h
|
||||
database.h
|
||||
ucsconfig.h
|
||||
worldserver.h
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(ucs ${ucs_sources} ${ucs_headers})
|
||||
|
||||
ADD_DEFINITIONS(-DUCS)
|
||||
|
||||
TARGET_LINK_LIBRARIES(ucs Common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
|
||||
|
||||
IF(MSVC)
|
||||
|
||||
SET_TARGET_PROPERTIES(ucs PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
|
||||
TARGET_LINK_LIBRARIES(ucs "Ws2_32.lib")
|
||||
ENDIF(MSVC)
|
||||
|
||||
IF(MINGW)
|
||||
TARGET_LINK_LIBRARIES(ucs "WS2_32")
|
||||
ENDIF(MINGW)
|
||||
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(ucs "dl")
|
||||
TARGET_LINK_LIBRARIES(ucs "z")
|
||||
TARGET_LINK_LIBRARIES(ucs "m")
|
||||
TARGET_LINK_LIBRARIES(ucs "rt")
|
||||
TARGET_LINK_LIBRARIES(ucs "pthread")
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ../Bin)
|
||||
@@ -0,0 +1,706 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "chatchannel.h"
|
||||
#include "clientlist.h"
|
||||
#include "database.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include <cstdlib>
|
||||
|
||||
extern Database database;
|
||||
extern uint32 ChatMessagesSent;
|
||||
|
||||
ChatChannel::ChatChannel(string inName, string inOwner, string inPassword, bool inPermanent, int inMinimumStatus) :
|
||||
DeleteTimer(0) {
|
||||
|
||||
Name = inName;
|
||||
|
||||
Owner = inOwner;
|
||||
|
||||
Password = inPassword;
|
||||
|
||||
Permanent = inPermanent;
|
||||
|
||||
MinimumStatus = inMinimumStatus;
|
||||
|
||||
Moderated = false;
|
||||
|
||||
_log(UCS__TRACE, "New ChatChannel created: Name: [%s], Owner: [%s], Password: [%s], MinStatus: %i",
|
||||
Name.c_str(), Owner.c_str(), Password.c_str(), MinimumStatus);
|
||||
|
||||
}
|
||||
|
||||
ChatChannel::~ChatChannel() {
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements())
|
||||
iterator.RemoveCurrent(false);
|
||||
}
|
||||
|
||||
ChatChannel* ChatChannelList::CreateChannel(string Name, string Owner, string Password, bool Permanent, int MinimumStatus) {
|
||||
|
||||
ChatChannel *NewChannel = new ChatChannel(CapitaliseName(Name), Owner, Password, Permanent, MinimumStatus);
|
||||
|
||||
ChatChannels.Insert(NewChannel);
|
||||
|
||||
return NewChannel;
|
||||
}
|
||||
|
||||
ChatChannel* ChatChannelList::FindChannel(string Name) {
|
||||
|
||||
string NormalisedName = CapitaliseName(Name);
|
||||
|
||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
ChatChannel *CurrentChannel = iterator.GetData();
|
||||
|
||||
if(CurrentChannel && (CurrentChannel->Name == NormalisedName))
|
||||
return iterator.GetData();
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ChatChannelList::SendAllChannels(Client *c) {
|
||||
|
||||
if(!c) return;
|
||||
|
||||
if(!c->CanListAllChannels()) {
|
||||
c->GeneralChannelMessage("You do not have permission to list all the channels.");
|
||||
return;
|
||||
}
|
||||
|
||||
c->GeneralChannelMessage("All current channels:");
|
||||
|
||||
int ChannelsInLine = 0;
|
||||
|
||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
string Message;
|
||||
|
||||
char CountString[10];
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
ChatChannel *CurrentChannel = iterator.GetData();
|
||||
|
||||
if(!CurrentChannel || (CurrentChannel->GetMinStatus() > c->GetAccountStatus())) {
|
||||
|
||||
iterator.Advance();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ChannelsInLine > 0)
|
||||
Message += ", ";
|
||||
|
||||
sprintf(CountString, "(%i)", CurrentChannel->MemberCount(c->GetAccountStatus()));
|
||||
|
||||
Message += CurrentChannel->GetName();
|
||||
|
||||
Message += CountString;
|
||||
|
||||
ChannelsInLine++;
|
||||
|
||||
if(ChannelsInLine == 6) {
|
||||
|
||||
c->GeneralChannelMessage(Message);
|
||||
|
||||
ChannelsInLine = 0;
|
||||
|
||||
Message.clear();
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if(ChannelsInLine > 0)
|
||||
c->GeneralChannelMessage(Message);
|
||||
|
||||
}
|
||||
|
||||
void ChatChannelList::RemoveChannel(ChatChannel *Channel) {
|
||||
|
||||
_log(UCS__TRACE, "RemoveChannel(%s)", Channel->GetName().c_str());
|
||||
|
||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
if(iterator.GetData() == Channel) {
|
||||
|
||||
iterator.RemoveCurrent();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatChannelList::RemoveAllChannels() {
|
||||
|
||||
_log(UCS__TRACE, "RemoveAllChannels");
|
||||
|
||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements())
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
|
||||
int ChatChannel::MemberCount(int Status) {
|
||||
|
||||
int Count = 0;
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
Client *ChannelClient = iterator.GetData();
|
||||
|
||||
if(ChannelClient && (!ChannelClient->GetHideMe() || (ChannelClient->GetAccountStatus() < Status)))
|
||||
Count++;
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
void ChatChannel::SetPassword(string inPassword) {
|
||||
|
||||
Password = inPassword;
|
||||
|
||||
if(Permanent)
|
||||
{
|
||||
RemoveApostrophes(Password);
|
||||
database.SetChannelPassword(Name, Password);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatChannel::SetOwner(string inOwner) {
|
||||
|
||||
Owner = inOwner;
|
||||
|
||||
if(Permanent)
|
||||
database.SetChannelOwner(Name, Owner);
|
||||
}
|
||||
|
||||
void ChatChannel::AddClient(Client *c) {
|
||||
|
||||
if(!c) return;
|
||||
|
||||
DeleteTimer.Disable();
|
||||
|
||||
if(IsClientInChannel(c)) {
|
||||
|
||||
_log(UCS__ERROR, "Client %s already in channel %s", c->GetName().c_str(), GetName().c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool HideMe = c->GetHideMe();
|
||||
|
||||
int AccountStatus = c->GetAccountStatus();
|
||||
|
||||
_log(UCS__TRACE, "Adding %s to channel %s", c->GetName().c_str(), Name.c_str());
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
Client *CurrentClient = iterator.GetData();
|
||||
|
||||
if(CurrentClient && CurrentClient->IsAnnounceOn())
|
||||
if(!HideMe || (CurrentClient->GetAccountStatus() > AccountStatus))
|
||||
CurrentClient->AnnounceJoin(this, c);
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
ClientsInChannel.Insert(c);
|
||||
|
||||
}
|
||||
|
||||
bool ChatChannel::RemoveClient(Client *c) {
|
||||
|
||||
if(!c) return false;
|
||||
|
||||
_log(UCS__TRACE, "RemoveClient %s from channel %s", c->GetName().c_str(), GetName().c_str());
|
||||
|
||||
bool HideMe = c->GetHideMe();
|
||||
|
||||
int AccountStatus = c->GetAccountStatus();
|
||||
|
||||
int PlayersInChannel = 0;
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
Client *CurrentClient = iterator.GetData();
|
||||
|
||||
if(CurrentClient == c) {
|
||||
iterator.RemoveCurrent(false);
|
||||
}
|
||||
else if(CurrentClient) {
|
||||
|
||||
PlayersInChannel++;
|
||||
|
||||
if(CurrentClient->IsAnnounceOn())
|
||||
if(!HideMe || (CurrentClient->GetAccountStatus() > AccountStatus))
|
||||
CurrentClient->AnnounceLeave(this, c);
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if((PlayersInChannel == 0) && !Permanent) {
|
||||
|
||||
if((Password.length() == 0) || (RuleI(Channels, DeleteTimer) == 0))
|
||||
return false;
|
||||
|
||||
_log(UCS__TRACE, "Starting delete timer for empty password protected channel %s", Name.c_str());
|
||||
|
||||
DeleteTimer.Start(RuleI(Channels, DeleteTimer) * 60000);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChatChannel::SendOPList(Client *c) {
|
||||
|
||||
if(!c) return;
|
||||
|
||||
c->GeneralChannelMessage("Channel " + Name + " op-list: (Owner=" + Owner + ")");
|
||||
|
||||
list<string>::iterator Iterator;
|
||||
|
||||
for(Iterator = Moderators.begin(); Iterator != Moderators.end(); Iterator++)
|
||||
c->GeneralChannelMessage((*Iterator));
|
||||
|
||||
}
|
||||
|
||||
void ChatChannel::SendChannelMembers(Client *c) {
|
||||
|
||||
if(!c) return;
|
||||
|
||||
char CountString[10];
|
||||
|
||||
sprintf(CountString, "(%i)", MemberCount(c->GetAccountStatus()));
|
||||
|
||||
string Message = "Channel " + GetName();
|
||||
|
||||
Message += CountString;
|
||||
|
||||
Message += " members:";
|
||||
|
||||
c->GeneralChannelMessage(Message);
|
||||
|
||||
int AccountStatus = c->GetAccountStatus();
|
||||
|
||||
Message.clear();
|
||||
|
||||
int MembersInLine = 0;
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
Client *ChannelClient = iterator.GetData();
|
||||
|
||||
// Don't list hidden characters with status higher or equal than the character requesting the list.
|
||||
//
|
||||
if(!ChannelClient || (ChannelClient->GetHideMe() && (ChannelClient->GetAccountStatus() >= AccountStatus))) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(MembersInLine > 0)
|
||||
Message += ", ";
|
||||
|
||||
Message += ChannelClient->GetName();
|
||||
|
||||
MembersInLine++;
|
||||
|
||||
if(MembersInLine == 6) {
|
||||
|
||||
c->GeneralChannelMessage(Message);
|
||||
|
||||
MembersInLine = 0;
|
||||
|
||||
Message.clear();
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
if(MembersInLine > 0)
|
||||
c->GeneralChannelMessage(Message);
|
||||
|
||||
}
|
||||
|
||||
void ChatChannel::SendMessageToChannel(string Message, Client* Sender) {
|
||||
|
||||
if(!Sender) return;
|
||||
|
||||
ChatMessagesSent++;
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
Client *ChannelClient = iterator.GetData();
|
||||
|
||||
if(ChannelClient)
|
||||
{
|
||||
_log(UCS__TRACE, "Sending message to %s from %s",
|
||||
ChannelClient->GetName().c_str(), Sender->GetName().c_str());
|
||||
ChannelClient->SendChannelMessage(Name, Message, Sender);
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatChannel::SetModerated(bool inModerated) {
|
||||
|
||||
Moderated = inModerated;
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
Client *ChannelClient = iterator.GetData();
|
||||
|
||||
if(ChannelClient) {
|
||||
|
||||
if(Moderated)
|
||||
ChannelClient->GeneralChannelMessage("Channel " + Name + " is now moderated.");
|
||||
else
|
||||
ChannelClient->GeneralChannelMessage("Channel " + Name + " is no longer moderated.");
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
}
|
||||
bool ChatChannel::IsClientInChannel(Client *c) {
|
||||
|
||||
if(!c) return false;
|
||||
|
||||
LinkedListIterator<Client*> iterator(ClientsInChannel);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
if(iterator.GetData() == c)
|
||||
return true;
|
||||
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ChatChannel *ChatChannelList::AddClientToChannel(string ChannelName, Client *c) {
|
||||
|
||||
if(!c) return NULL;
|
||||
|
||||
if((ChannelName.length() > 0) && (isdigit(ChannelName[0]))) {
|
||||
|
||||
c->GeneralChannelMessage("The channel name can not begin with a number.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
string NormalisedName, Password;
|
||||
|
||||
string::size_type Colon = ChannelName.find_first_of(":");
|
||||
|
||||
if(Colon == string::npos)
|
||||
NormalisedName = CapitaliseName(ChannelName);
|
||||
else {
|
||||
NormalisedName = CapitaliseName(ChannelName.substr(0, Colon));
|
||||
|
||||
Password = ChannelName.substr(Colon + 1);
|
||||
}
|
||||
|
||||
if((NormalisedName.length() > 64) || (Password.length() > 64)) {
|
||||
|
||||
c->GeneralChannelMessage("The channel name or password cannot exceed 64 characters.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_log(UCS__TRACE, "AddClient to channel [%s] with password [%s]", NormalisedName.c_str(), Password.c_str());
|
||||
|
||||
ChatChannel *RequiredChannel = FindChannel(NormalisedName);
|
||||
|
||||
if(!RequiredChannel)
|
||||
RequiredChannel = CreateChannel(NormalisedName, c->GetName(), Password, false, 0);
|
||||
|
||||
if(RequiredChannel->GetMinStatus() > c->GetAccountStatus()) {
|
||||
|
||||
string Message = "You do not have the required account status to join channel " + NormalisedName;
|
||||
|
||||
c->GeneralChannelMessage(Message);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(RequiredChannel->IsClientInChannel(c))
|
||||
return NULL;
|
||||
|
||||
if(RequiredChannel->IsInvitee(c->GetName())) {
|
||||
|
||||
RequiredChannel->AddClient(c);
|
||||
|
||||
RequiredChannel->RemoveInvitee(c->GetName());
|
||||
|
||||
return RequiredChannel;
|
||||
}
|
||||
|
||||
if(RequiredChannel->CheckPassword(Password) || RequiredChannel->IsOwner(c->GetName()) || RequiredChannel->IsModerator(c->GetName()) ||
|
||||
c->IsChannelAdmin()) {
|
||||
|
||||
RequiredChannel->AddClient(c);
|
||||
|
||||
return RequiredChannel;
|
||||
}
|
||||
|
||||
c->GeneralChannelMessage("Incorrect password for channel " + (NormalisedName));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ChatChannel *ChatChannelList::RemoveClientFromChannel(string inChannelName, Client *c) {
|
||||
|
||||
if(!c) return NULL;
|
||||
|
||||
string ChannelName = inChannelName;
|
||||
|
||||
if((inChannelName.length() > 0) && isdigit(ChannelName[0]))
|
||||
ChannelName = c->ChannelSlotName(atoi(inChannelName.c_str()));
|
||||
|
||||
ChatChannel *RequiredChannel = FindChannel(ChannelName);
|
||||
|
||||
if(!RequiredChannel)
|
||||
return NULL;
|
||||
|
||||
// RemoveClient will return false if there is no-one left in the channel, and the channel is not permanent and has
|
||||
// no password.
|
||||
//
|
||||
if(!RequiredChannel->RemoveClient(c))
|
||||
RemoveChannel(RequiredChannel);
|
||||
|
||||
return RequiredChannel;
|
||||
}
|
||||
|
||||
void ChatChannelList::Process() {
|
||||
|
||||
LinkedListIterator<ChatChannel*> iterator(ChatChannels);
|
||||
|
||||
iterator.Reset();
|
||||
|
||||
while(iterator.MoreElements()) {
|
||||
|
||||
ChatChannel *CurrentChannel = iterator.GetData();
|
||||
|
||||
if(CurrentChannel && CurrentChannel->ReadyToDelete()) {
|
||||
|
||||
_log(UCS__TRACE, "Empty temporary password protected channel %s being destroyed.",
|
||||
CurrentChannel->GetName().c_str());
|
||||
|
||||
RemoveChannel(CurrentChannel);
|
||||
}
|
||||
|
||||
iterator.Advance();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ChatChannel::AddInvitee(string Invitee) {
|
||||
|
||||
if(!IsInvitee(Invitee)) {
|
||||
|
||||
Invitees.push_back(Invitee);
|
||||
|
||||
_log(UCS__TRACE, "Added %s as invitee to channel %s", Invitee.c_str(), Name.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ChatChannel::RemoveInvitee(string Invitee) {
|
||||
|
||||
list<string>::iterator Iterator;
|
||||
|
||||
for(Iterator = Invitees.begin(); Iterator != Invitees.end(); Iterator++) {
|
||||
|
||||
if((*Iterator) == Invitee) {
|
||||
|
||||
Invitees.erase(Iterator);
|
||||
|
||||
_log(UCS__TRACE, "Removed %s as invitee to channel %s", Invitee.c_str(), Name.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ChatChannel::IsInvitee(string Invitee) {
|
||||
|
||||
list<string>::iterator Iterator;
|
||||
|
||||
for(Iterator = Invitees.begin(); Iterator != Invitees.end(); Iterator++) {
|
||||
|
||||
if((*Iterator) == Invitee)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ChatChannel::AddModerator(string Moderator) {
|
||||
|
||||
if(!IsModerator(Moderator)) {
|
||||
|
||||
Moderators.push_back(Moderator);
|
||||
|
||||
_log(UCS__TRACE, "Added %s as moderator to channel %s", Moderator.c_str(), Name.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ChatChannel::RemoveModerator(string Moderator) {
|
||||
|
||||
list<string>::iterator Iterator;
|
||||
|
||||
for(Iterator = Moderators.begin(); Iterator != Moderators.end(); Iterator++) {
|
||||
|
||||
if((*Iterator) == Moderator) {
|
||||
|
||||
Moderators.erase(Iterator);
|
||||
|
||||
_log(UCS__TRACE, "Removed %s as moderator to channel %s", Moderator.c_str(), Name.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ChatChannel::IsModerator(string Moderator) {
|
||||
|
||||
list<string>::iterator Iterator;
|
||||
|
||||
for(Iterator = Moderators.begin(); Iterator != Moderators.end(); Iterator++) {
|
||||
|
||||
if((*Iterator) == Moderator)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ChatChannel::AddVoice(string inVoiced) {
|
||||
|
||||
if(!HasVoice(inVoiced)) {
|
||||
|
||||
Voiced.push_back(inVoiced);
|
||||
|
||||
_log(UCS__TRACE, "Added %s as voiced to channel %s", inVoiced.c_str(), Name.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ChatChannel::RemoveVoice(string inVoiced) {
|
||||
|
||||
list<string>::iterator Iterator;
|
||||
|
||||
for(Iterator = Voiced.begin(); Iterator != Voiced.end(); Iterator++) {
|
||||
|
||||
if((*Iterator) == inVoiced) {
|
||||
|
||||
Voiced.erase(Iterator);
|
||||
|
||||
_log(UCS__TRACE, "Removed %s as voiced to channel %s", inVoiced.c_str(), Name.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ChatChannel::HasVoice(string inVoiced) {
|
||||
|
||||
list<string>::iterator Iterator;
|
||||
|
||||
for(Iterator = Voiced.begin(); Iterator != Voiced.end(); Iterator++) {
|
||||
|
||||
if((*Iterator) == inVoiced)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string CapitaliseName(string inString) {
|
||||
|
||||
string NormalisedName = inString;
|
||||
|
||||
for(unsigned int i = 0; i < NormalisedName.length(); i++) {
|
||||
|
||||
if(i == 0)
|
||||
NormalisedName[i] = toupper(NormalisedName[i]);
|
||||
else
|
||||
NormalisedName[i] = tolower(NormalisedName[i]);
|
||||
}
|
||||
|
||||
return NormalisedName;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#ifndef CHATCHANNEL_H
|
||||
#define CHATCHANNEL_H
|
||||
|
||||
//#include "clientlist.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/timer.h"
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Client;
|
||||
|
||||
class ChatChannel {
|
||||
|
||||
public:
|
||||
|
||||
ChatChannel(string inName, string inOwner, string inPassword, bool inPermanent, int inMinimumStatus = 0);
|
||||
~ChatChannel();
|
||||
|
||||
void AddClient(Client *c);
|
||||
bool RemoveClient(Client *c);
|
||||
bool IsClientInChannel(Client *c);
|
||||
|
||||
int MemberCount(int Status);
|
||||
string GetName() { return Name; }
|
||||
void SendMessageToChannel(string Message, Client* Sender);
|
||||
bool CheckPassword(string inPassword) { return ((Password.length() == 0) || (Password == inPassword)); }
|
||||
void SetPassword(string inPassword);
|
||||
bool IsOwner(string Name) { return (Owner == Name); }
|
||||
void SetOwner(string inOwner);
|
||||
void SendChannelMembers(Client *c);
|
||||
int GetMinStatus() { return MinimumStatus; }
|
||||
bool ReadyToDelete() { return DeleteTimer.Check(); }
|
||||
void SendOPList(Client *c);
|
||||
void AddInvitee(string Invitee);
|
||||
void RemoveInvitee(string Invitee);
|
||||
bool IsInvitee(string Invitee);
|
||||
void AddModerator(string Moderator);
|
||||
void RemoveModerator(string Modeerator);
|
||||
bool IsModerator(string Moderator);
|
||||
void AddVoice(string Voiced);
|
||||
void RemoveVoice(string Voiced);
|
||||
bool HasVoice(string Voiced);
|
||||
inline bool IsModerated() { return Moderated; }
|
||||
void SetModerated(bool inModerated);
|
||||
|
||||
friend class ChatChannelList;
|
||||
|
||||
private:
|
||||
|
||||
string Name;
|
||||
string Owner;
|
||||
string Password;
|
||||
|
||||
bool Permanent;
|
||||
bool Moderated;
|
||||
|
||||
int MinimumStatus;
|
||||
|
||||
Timer DeleteTimer;
|
||||
|
||||
LinkedList<Client*> ClientsInChannel;
|
||||
|
||||
list<string> Moderators;
|
||||
list<string> Invitees;
|
||||
list<string> Voiced;
|
||||
|
||||
};
|
||||
|
||||
class ChatChannelList {
|
||||
|
||||
public:
|
||||
ChatChannel* CreateChannel(string Name, string Owner, string Passwordi, bool Permanent, int MinimumStatus = 0);
|
||||
ChatChannel* FindChannel(string Name);
|
||||
ChatChannel* AddClientToChannel(string Channel, Client *c);
|
||||
ChatChannel* RemoveClientFromChannel(string Channel, Client *c);
|
||||
void RemoveClientFromAllChannels(Client *c);
|
||||
void RemoveChannel(ChatChannel *Channel);
|
||||
void RemoveAllChannels();
|
||||
void SendAllChannels(Client *c);
|
||||
void Process();
|
||||
|
||||
private:
|
||||
|
||||
LinkedList<ChatChannel*> ChatChannels;
|
||||
|
||||
};
|
||||
|
||||
string CapitaliseName(string inString);
|
||||
|
||||
#endif
|
||||
+2409
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CHATSERVER_CLIENTLIST_H
|
||||
#define CHATSERVER_CLIENTLIST_H
|
||||
|
||||
#include "../common/opcodemgr.h"
|
||||
#include "../common/EQStreamType.h"
|
||||
#include "../common/EQStreamFactory.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "chatchannel.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#define MAX_JOINED_CHANNELS 10
|
||||
|
||||
enum { CommandJoin = 0, CommandLeaveAll, CommandLeave, CommandListAll, CommandList, CommandSet, CommandAnnounce, CommandSetOwner,
|
||||
CommandOPList, CommandInvite, CommandGrant, CommandModerate, CommandVoice, CommandKick,
|
||||
CommandPassword, CommandToggleInvites, CommandAFK, CommandUptime,
|
||||
CommandGetHeaders, CommandGetBody, CommandMailTo, CommandSetMessageStatus, CommandSelectMailBox,
|
||||
CommandSetMailForwarding, CommandBuddy, CommandIgnorePlayer,
|
||||
CommandEndOfList };
|
||||
|
||||
struct CommandEntry {
|
||||
const char *CommandString;
|
||||
int CommandCode;
|
||||
};
|
||||
|
||||
typedef enum { ConnectionTypeUnknown, ConnectionTypeCombined, ConnectionTypeMail, ConnectionTypeChat } ConnectionType;
|
||||
|
||||
static const CommandEntry Commands[] = {
|
||||
{ "join", CommandJoin },
|
||||
{ "leaveall", CommandLeaveAll },
|
||||
{ "leave", CommandLeave },
|
||||
{ "listall", CommandListAll },
|
||||
{ "list", CommandList },
|
||||
{ "set", CommandSet },
|
||||
{ "announce", CommandAnnounce },
|
||||
{ "setowner", CommandSetOwner },
|
||||
{ "oplist", CommandOPList },
|
||||
{ "invite", CommandInvite },
|
||||
{ "grant", CommandGrant },
|
||||
{ "moderate", CommandModerate },
|
||||
{ "voice", CommandVoice },
|
||||
{ "kick", CommandKick },
|
||||
{ "password", CommandPassword },
|
||||
{ "toggleinvites", CommandToggleInvites },
|
||||
{ "afk", CommandAFK },
|
||||
{ "uptime", CommandUptime },
|
||||
{ "getheaders", CommandGetHeaders },
|
||||
{ "getbody", CommandGetBody },
|
||||
{ "mailto", CommandMailTo },
|
||||
{ "setmessagestatus", CommandSetMessageStatus },
|
||||
{ "selectmailbox", CommandSelectMailBox },
|
||||
{ "setmailforwarding", CommandSetMailForwarding },
|
||||
{ "buddy", CommandBuddy },
|
||||
{ "ignoreplayer", CommandIgnorePlayer },
|
||||
{ "", CommandEndOfList } };
|
||||
|
||||
struct CharacterEntry {
|
||||
int CharID;
|
||||
int Level;
|
||||
string Name;
|
||||
};
|
||||
|
||||
class Client {
|
||||
|
||||
public:
|
||||
Client(EQStream* eqs);
|
||||
~Client();
|
||||
|
||||
EQStream *ClientStream;
|
||||
void AddCharacter(int CharID, const char *CharacterName, int Level);
|
||||
void ClearCharacters() { Characters.clear(); }
|
||||
void SendMailBoxes();
|
||||
inline void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) { ClientStream->QueuePacket(p, ack_req); }
|
||||
string GetName() { if(Characters.size()) return Characters[0].Name; else return ""; }
|
||||
void JoinChannels(string ChannelList);
|
||||
void LeaveChannels(string ChannelList);
|
||||
void LeaveAllChannels(bool SendUpdatedChannelList = true);
|
||||
void AddToChannelList(ChatChannel *JoinedChannel);
|
||||
void RemoveFromChannelList(ChatChannel *JoinedChannel);
|
||||
void SendChannelMessage(string Message);
|
||||
void SendChannelMessage(string ChannelName, string Message, Client *Sender);
|
||||
void SendChannelMessageByNumber(string Message);
|
||||
void SendChannelList();
|
||||
void CloseConnection();
|
||||
void ToggleAnnounce(string State);
|
||||
bool IsAnnounceOn() { return (Announce == true); }
|
||||
void AnnounceJoin(ChatChannel *Channel, Client *c);
|
||||
void AnnounceLeave(ChatChannel *Channel, Client *c);
|
||||
void GeneralChannelMessage(string Message);
|
||||
void GeneralChannelMessage(const char *Characters);
|
||||
void SetChannelPassword(string ChannelPassword);
|
||||
void ProcessChannelList(string CommandString);
|
||||
void AccountUpdate();
|
||||
int ChannelCount();
|
||||
inline void SetAccountID(int inAccountID) { AccountID = inAccountID; }
|
||||
inline int GetAccountID() { return AccountID; }
|
||||
inline void SetAccountStatus(int inStatus) { Status = inStatus; }
|
||||
inline void SetHideMe(bool inHideMe) { HideMe = inHideMe; }
|
||||
inline void SetKarma(uint32 inKarma) { TotalKarma = inKarma; }
|
||||
inline int GetAccountStatus() { return Status; }
|
||||
inline bool GetHideMe() { return HideMe; }
|
||||
inline uint32 GetKarma() { return TotalKarma; }
|
||||
void SetChannelOwner(string CommandString);
|
||||
void OPList(string CommandString);
|
||||
void ChannelInvite(string CommandString);
|
||||
void ChannelGrantModerator(string CommandString);
|
||||
void ChannelGrantVoice(string CommandString);
|
||||
void ChannelKick(string CommandString);
|
||||
void ChannelModerate(string CommandString);
|
||||
string ChannelSlotName(int ChannelNumber);
|
||||
void ToggleInvites();
|
||||
bool InvitesAllowed() { return AllowInvites; }
|
||||
bool IsRevoked() { return Revoked; }
|
||||
void SetRevoked(bool r) { Revoked = r; }
|
||||
inline bool IsChannelAdmin() { return (Status >= RuleI(Channels, RequiredStatusAdmin)); }
|
||||
inline bool CanListAllChannels() { return (Status >= RuleI(Channels, RequiredStatusListAll)); }
|
||||
void SendHelp();
|
||||
inline bool GetForceDisconnect() { return ForceDisconnect; }
|
||||
string MailBoxName();
|
||||
int GetMailBoxNumber() { return CurrentMailBox; }
|
||||
int GetMailBoxNumber(string CharacterName);
|
||||
void SetConnectionType(char c);
|
||||
ConnectionType GetConnectionType() { return TypeOfConnection; }
|
||||
inline bool IsMailConnection() { return (TypeOfConnection == ConnectionTypeMail) || (TypeOfConnection == ConnectionTypeCombined); }
|
||||
void SendNotification(int MailBoxNumber, string From, string Subject, int MessageID);
|
||||
void ChangeMailBox(int NewMailBox);
|
||||
inline void SetMailBox(int NewMailBox) { CurrentMailBox = NewMailBox; }
|
||||
void SendFriends();
|
||||
int GetCharID();
|
||||
void SendUptime();
|
||||
|
||||
private:
|
||||
unsigned int CurrentMailBox;
|
||||
vector<CharacterEntry> Characters;
|
||||
ChatChannel *JoinedChannels[MAX_JOINED_CHANNELS];
|
||||
bool Announce;
|
||||
int AccountID;
|
||||
int Status;
|
||||
bool HideMe;
|
||||
bool AllowInvites;
|
||||
bool Revoked;
|
||||
|
||||
//Anti Spam Stuff
|
||||
Timer *AccountGrabUpdateTimer;
|
||||
uint32 TotalKarma;
|
||||
|
||||
Timer *GlobalChatLimiterTimer; //60 seconds
|
||||
int AttemptedMessages;
|
||||
bool ForceDisconnect;
|
||||
ConnectionType TypeOfConnection;
|
||||
bool UnderfootOrLater;
|
||||
};
|
||||
|
||||
class Clientlist {
|
||||
|
||||
public:
|
||||
Clientlist(int MailPort);
|
||||
void Process();
|
||||
void CloseAllConnections();
|
||||
Client *FindCharacter(string CharacterName);
|
||||
void CheckForStaleConnections(Client *c);
|
||||
Client *IsCharacterOnline(string CharacterName);
|
||||
void ProcessOPMailCommand(Client *c, string CommandString);
|
||||
|
||||
private:
|
||||
|
||||
EQStreamFactory *chatsf;
|
||||
|
||||
list<Client*> ClientChatConnections;
|
||||
|
||||
OpcodeManager *ChatOpMgr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,770 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
|
||||
// Disgrace: for windows compile
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#define snprintf _snprintf
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#else
|
||||
#include "../common/unix.h"
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "database.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "chatchannel.h"
|
||||
|
||||
extern Clientlist *CL;
|
||||
extern string GetMailPrefix();
|
||||
extern ChatChannelList *ChannelList;
|
||||
extern uint32 MailMessagesSent;
|
||||
|
||||
Database::Database ()
|
||||
{
|
||||
DBInitVars();
|
||||
}
|
||||
|
||||
/*
|
||||
Establish a connection to a mysql database with the supplied parameters
|
||||
*/
|
||||
|
||||
Database::Database(const char* host, const char* user, const char* passwd, const char* database, uint32 port)
|
||||
{
|
||||
DBInitVars();
|
||||
Connect(host, user, passwd, database, port);
|
||||
}
|
||||
|
||||
bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port)
|
||||
{
|
||||
uint32 errnum= 0;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
if (!Open(host, user, passwd, database, port, &errnum, errbuf))
|
||||
{
|
||||
LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf);
|
||||
HandleMysqlError(errnum);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile->write(EQEMuLog::Status, "Using database '%s' at %s:%d",database,host,port);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Database::DBInitVars() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Database::HandleMysqlError(uint32 errnum) {
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Close the connection to the database
|
||||
*/
|
||||
Database::~Database()
|
||||
{
|
||||
}
|
||||
|
||||
void Database::GetAccountStatus(Client *c) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `status`, `hideme`, `karma`, `revoked` from `account` where `id`='%i' limit 1",
|
||||
c->GetAccountID()),errbuf,&result)){
|
||||
|
||||
_log(UCS__ERROR, "Unable to get account status for character %s, error %s", c->GetName().c_str(), errbuf);
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return;
|
||||
}
|
||||
_log(UCS__TRACE, "GetAccountStatus Query: %s", query);
|
||||
safe_delete_array(query);
|
||||
|
||||
if(mysql_num_rows(result) != 1)
|
||||
{
|
||||
_log(UCS__ERROR, "Error in GetAccountStatus");
|
||||
mysql_free_result(result);
|
||||
return;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
c->SetAccountStatus(atoi(row[0]));
|
||||
c->SetHideMe(atoi(row[1]) != 0);
|
||||
c->SetKarma(atoi(row[2]));
|
||||
c->SetRevoked((atoi(row[3])==1?true:false));
|
||||
|
||||
_log(UCS__TRACE, "Set account status to %i, hideme to %i and karma to %i for %s", c->GetAccountStatus(), c->GetHideMe(), c->GetKarma(), c->GetName().c_str());
|
||||
mysql_free_result(result);
|
||||
}
|
||||
|
||||
int Database::FindAccount(const char *CharacterName, Client *c) {
|
||||
|
||||
_log(UCS__TRACE, "FindAccount for character %s", CharacterName);
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
c->ClearCharacters();
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `id`, `account_id`, `level` from `character_` where `name`='%s' limit 1",
|
||||
CharacterName),errbuf,&result))
|
||||
{
|
||||
_log(UCS__ERROR, "FindAccount query failed: %s", query);
|
||||
safe_delete_array(query);
|
||||
return -1;
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
if (mysql_num_rows(result) != 1)
|
||||
{
|
||||
_log(UCS__ERROR, "Bad result from query");
|
||||
mysql_free_result(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
c->AddCharacter(atoi(row[0]), CharacterName, atoi(row[2]));
|
||||
int AccountID = atoi(row[1]);
|
||||
|
||||
mysql_free_result(result);
|
||||
_log(UCS__TRACE, "Account ID for %s is %i", CharacterName, AccountID);
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `id`, `name`, `level` from `character_` where `account_id`=%i and `name` !='%s'",
|
||||
AccountID, CharacterName),errbuf,&result))
|
||||
{
|
||||
safe_delete_array(query);
|
||||
return AccountID;
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
for(unsigned int i = 0; i < mysql_num_rows(result); i++)
|
||||
{
|
||||
row = mysql_fetch_row(result);
|
||||
c->AddCharacter(atoi(row[0]), row[1], atoi(row[2]));
|
||||
}
|
||||
mysql_free_result(result);
|
||||
return AccountID;
|
||||
}
|
||||
|
||||
bool Database::VerifyMailKey(string CharacterName, int IPAddress, string MailKey) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `mailkey` from `character_` where `name`='%s' limit 1",
|
||||
CharacterName.c_str()),errbuf,&result)){
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
_log(UCS__ERROR, "Error retrieving mailkey from database: %s", errbuf);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
// The key is the client's IP address (expressed as 8 hex digits) and an 8 hex digit random string generated
|
||||
// by world.
|
||||
//
|
||||
char CombinedKey[17];
|
||||
|
||||
if(RuleB(Chat, EnableMailKeyIPVerification) == true)
|
||||
sprintf(CombinedKey, "%08X%s", IPAddress, MailKey.c_str());
|
||||
else
|
||||
sprintf(CombinedKey, "%s", MailKey.c_str());
|
||||
|
||||
_log(UCS__TRACE, "DB key is [%s], Client key is [%s]", row[0], CombinedKey);
|
||||
|
||||
bool Valid = !strcmp(row[0], CombinedKey);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return Valid;
|
||||
|
||||
}
|
||||
|
||||
int Database::FindCharacter(const char *CharacterName) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *SafeCharName = RemoveApostrophes(CharacterName);
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `id` from `character_` where `name`='%s' limit 1",
|
||||
SafeCharName),errbuf,&result)){
|
||||
|
||||
_log(UCS__ERROR, "FindCharacter failed. %s %s", query, errbuf);
|
||||
|
||||
safe_delete_array(query);
|
||||
safe_delete_array(SafeCharName);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
safe_delete_array(SafeCharName);
|
||||
|
||||
if (mysql_num_rows(result) != 1) {
|
||||
|
||||
_log(UCS__ERROR, "Bad result from FindCharacter query for character %s", CharacterName);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
int CharacterID = atoi(row[0]);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return CharacterID;
|
||||
|
||||
}
|
||||
|
||||
bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_len) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `value` from `variables` where `varname`='%s'", varname), errbuf, &result)) {
|
||||
|
||||
_log(UCS__ERROR, "Unable to get message count from database. %s %s", query, errbuf);
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
if (mysql_num_rows(result) != 1) {
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
snprintf(varvalue, varvalue_len, "%s", row[0]);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::LoadChatChannels() {
|
||||
|
||||
_log(UCS__INIT, "Loading chat channels from the database.");
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `name`,`owner`,`password`, `minstatus` from `chatchannels`"),errbuf,&result)){
|
||||
|
||||
_log(UCS__ERROR, "Failed to load channels. %s %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
while((row = mysql_fetch_row(result))) {
|
||||
|
||||
string ChannelName = row[0];
|
||||
string ChannelOwner = row[1];
|
||||
string ChannelPassword = row[2];
|
||||
|
||||
ChannelList->CreateChannel(ChannelName, ChannelOwner, ChannelPassword, true, atoi(row[3]));
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Database::SetChannelPassword(string ChannelName, string Password) {
|
||||
|
||||
_log(UCS__TRACE, "Database::SetChannelPassword(%s, %s)", ChannelName.c_str(), Password.c_str());
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "UPDATE `chatchannels` set `password`='%s' where `name`='%s'", Password.c_str(),
|
||||
ChannelName.c_str()), errbuf)) {
|
||||
|
||||
_log(UCS__ERROR, "Error updating password in database: %s, %s", query, errbuf);
|
||||
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void Database::SetChannelOwner(string ChannelName, string Owner) {
|
||||
|
||||
_log(UCS__TRACE, "Database::SetChannelOwner(%s, %s)", ChannelName.c_str(), Owner.c_str());
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "UPDATE `chatchannels` set `owner`='%s' where `name`='%s'", Owner.c_str(),
|
||||
ChannelName.c_str()), errbuf)) {
|
||||
|
||||
_log(UCS__ERROR, "Error updating Owner in database: %s, %s", query, errbuf);
|
||||
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void Database::SendHeaders(Client *c) {
|
||||
|
||||
int UnknownField2 = 25015275;
|
||||
int UnknownField3 = 1;
|
||||
|
||||
int CharacterID = FindCharacter(c->MailBoxName().c_str());
|
||||
_log(UCS__TRACE, "Sendheaders for %s, CharID is %i", c->MailBoxName().c_str(), CharacterID);
|
||||
if(CharacterID <= 0)
|
||||
return;
|
||||
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `msgid`,`timestamp`,`from`,`subject`, `status` from `mail` "
|
||||
"where `charid`=%i", CharacterID),errbuf,&result)){
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
char Buf[100];
|
||||
|
||||
my_ulonglong NumRows = mysql_num_rows(result);
|
||||
|
||||
int HeaderCountPacketLength = 0;
|
||||
|
||||
sprintf(Buf, "%i", c->GetMailBoxNumber());
|
||||
HeaderCountPacketLength += (strlen(Buf) + 1);
|
||||
|
||||
sprintf(Buf, "%i", UnknownField2);
|
||||
HeaderCountPacketLength += (strlen(Buf) + 1);
|
||||
|
||||
sprintf(Buf, "%i", UnknownField3);
|
||||
HeaderCountPacketLength += (strlen(Buf) + 1);
|
||||
|
||||
sprintf(Buf, "%i", NumRows);
|
||||
HeaderCountPacketLength += (strlen(Buf) + 1);
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MailHeaderCount, HeaderCountPacketLength);
|
||||
|
||||
char *PacketBuffer = (char *)outapp->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, c->GetMailBoxNumber());
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, UnknownField2);
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, UnknownField3);
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, NumRows);
|
||||
|
||||
_pkt(UCS__PACKETS, outapp);
|
||||
|
||||
c->QueuePacket(outapp);
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
int RowNum = 0;
|
||||
|
||||
while((row = mysql_fetch_row(result))) {
|
||||
|
||||
|
||||
int HeaderPacketLength = 0;
|
||||
|
||||
sprintf(Buf, "%i", c->GetMailBoxNumber());
|
||||
HeaderPacketLength = HeaderPacketLength + strlen(Buf) + 1;
|
||||
sprintf(Buf, "%i", UnknownField2);
|
||||
HeaderPacketLength = HeaderPacketLength + strlen(Buf) + 1;
|
||||
sprintf(Buf, "%i", RowNum);
|
||||
HeaderPacketLength = HeaderPacketLength + strlen(Buf) + 1;
|
||||
|
||||
HeaderPacketLength = HeaderPacketLength + strlen(row[0]) + 1;
|
||||
HeaderPacketLength = HeaderPacketLength + strlen(row[1]) + 1;
|
||||
HeaderPacketLength = HeaderPacketLength + strlen(row[4]) + 1;
|
||||
HeaderPacketLength = HeaderPacketLength + GetMailPrefix().length() + strlen(row[2]) + 1;
|
||||
HeaderPacketLength = HeaderPacketLength + strlen(row[3]) + 1;
|
||||
|
||||
outapp = new EQApplicationPacket(OP_MailHeader, HeaderPacketLength);
|
||||
|
||||
PacketBuffer = (char *)outapp->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, c->GetMailBoxNumber());
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, UnknownField2);
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, RowNum);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, row[0]);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, row[1]);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, row[4]);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, GetMailPrefix().c_str()); PacketBuffer--;
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, row[2]);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, row[3]);
|
||||
|
||||
_pkt(UCS__PACKETS, outapp);
|
||||
|
||||
c->QueuePacket(outapp);
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
RowNum++;
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
}
|
||||
|
||||
void Database::SendBody(Client *c, int MessageNumber) {
|
||||
|
||||
int CharacterID = FindCharacter(c->MailBoxName().c_str());
|
||||
|
||||
_log(UCS__TRACE, "SendBody: MsgID %i, to %s, CharID is %i", MessageNumber, c->MailBoxName().c_str(), CharacterID);
|
||||
|
||||
if(CharacterID <= 0)
|
||||
return;
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `msgid`, `body`, `to` from `mail` "
|
||||
"where `charid`=%i and `msgid`=%i", CharacterID, MessageNumber), errbuf, &result)){
|
||||
safe_delete_array(query);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
if (mysql_num_rows(result) != 1) {
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
_log(UCS__TRACE, "Message: %i body (%i bytes)", MessageNumber, strlen(row[1]));
|
||||
|
||||
int PacketLength = 12 + strlen(row[0]) + strlen(row[1]) + strlen(row[2]);
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MailSendBody,PacketLength);
|
||||
|
||||
char *PacketBuffer = (char *)outapp->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_INTSTRING(PacketBuffer, c->GetMailBoxNumber());
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer,row[0]);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer,row[1]);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer,"1");
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x0a);
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, "TO:"); PacketBuffer--;
|
||||
VARSTRUCT_ENCODE_STRING(PacketBuffer, row[2]); PacketBuffer--; // Overwrite the null terminator
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, PacketBuffer, 0x0a);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
_pkt(UCS__PACKETS, outapp);
|
||||
|
||||
c->QueuePacket(outapp);
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool Database::SendMail(string Recipient, string From, string Subject, string Body, string RecipientsString) {
|
||||
|
||||
int CharacterID;
|
||||
|
||||
string CharacterName;
|
||||
|
||||
//printf("Database::SendMail(%s, %s, %s)\n", Recipient.c_str(), From.c_str(), Subject.c_str());
|
||||
|
||||
string::size_type LastPeriod = Recipient.find_last_of(".");
|
||||
|
||||
if(LastPeriod == string::npos)
|
||||
CharacterName = Recipient;
|
||||
else
|
||||
CharacterName = Recipient.substr(LastPeriod+1);
|
||||
|
||||
CharacterName[0] = toupper(CharacterName[0]);
|
||||
|
||||
for(unsigned int i = 1; i < CharacterName.length(); i++)
|
||||
CharacterName[i] = tolower(CharacterName[i]);
|
||||
|
||||
CharacterID = FindCharacter(CharacterName.c_str());
|
||||
|
||||
_log(UCS__TRACE, "SendMail: CharacterID for recipient %s is %i", CharacterName.c_str(), CharacterID);
|
||||
|
||||
if(CharacterID <= 0) return false;
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
|
||||
char *EscSubject = new char[Subject.length() * 2 + 1];
|
||||
char *EscBody = new char[Body.length() * 2 + 1];
|
||||
|
||||
DoEscapeString(EscSubject, Subject.c_str(), Subject.length());
|
||||
DoEscapeString(EscBody, Body.c_str(), Body.length());
|
||||
|
||||
const char *MailQuery="INSERT INTO `mail` (`charid`, `timestamp`, `from`, `subject`, `body`, `to`, `status`) "
|
||||
"VALUES ('%i', %i, '%s', '%s', '%s', '%s', %i)";
|
||||
|
||||
uint32 LastMsgID;
|
||||
|
||||
int Now = time(NULL); // time returns a 64 bit int on Windows at least, which vsnprintf doesn't like.
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, MailQuery, CharacterID, Now, From.c_str(), EscSubject, EscBody,
|
||||
RecipientsString.c_str(), 1), errbuf, 0, 0, &LastMsgID)) {
|
||||
|
||||
_log(UCS__ERROR, "SendMail: Query %s failed with error %s", query, errbuf);
|
||||
|
||||
safe_delete_array(EscSubject);
|
||||
safe_delete_array(EscBody);
|
||||
safe_delete_array(query);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_log(UCS__TRACE, "MessageID %i generated, from %s, to %s", LastMsgID, From.c_str(), Recipient.c_str());
|
||||
|
||||
safe_delete_array(EscSubject);
|
||||
safe_delete_array(EscBody);
|
||||
safe_delete_array(query);
|
||||
|
||||
Client *c = CL->IsCharacterOnline(CharacterName);
|
||||
|
||||
if(c) {
|
||||
string FQN = GetMailPrefix() + From;
|
||||
|
||||
c->SendNotification(c->GetMailBoxNumber(CharacterName), Subject, FQN, LastMsgID);
|
||||
}
|
||||
|
||||
MailMessagesSent++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Database::SetMessageStatus(int MessageNumber, int Status) {
|
||||
|
||||
_log(UCS__TRACE, "SetMessageStatus %i %i", MessageNumber, Status);
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if(Status == 0)
|
||||
RunQuery(query, MakeAnyLenString(&query, "delete from `mail` where `msgid`=%i", MessageNumber), errbuf);
|
||||
else if (!RunQuery(query, MakeAnyLenString(&query, "update `mail` set `status`=%i where `msgid`=%i", Status, MessageNumber), errbuf)) {
|
||||
|
||||
_log(UCS__ERROR, "Error updating status %s, %s", query, errbuf);
|
||||
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void Database::ExpireMail() {
|
||||
|
||||
_log(UCS__INIT, "Expiring mail...");
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
uint32 AffectedRows;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select COUNT(*) from `mail` "),errbuf,&result)){
|
||||
_log(UCS__ERROR, "Unable to get message count from database. %s %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return ;
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
_log(UCS__INIT, "There are %s messages in the database.", row[0]);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
// Expire Trash
|
||||
if(RuleI(Mail, ExpireTrash) >= 0) {
|
||||
if(RunQuery(query, MakeAnyLenString(&query, "delete from `mail` where `status`=4 and `timestamp` < %i",
|
||||
time(NULL) - RuleI(Mail, ExpireTrash)), errbuf, 0, &AffectedRows)) {
|
||||
_log(UCS__INIT, "Expired %i trash messages.", AffectedRows);
|
||||
}
|
||||
else {
|
||||
_log(UCS__ERROR, "Error expiring trash messages, %s %s", query, errbuf);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
// Expire Read
|
||||
if(RuleI(Mail, ExpireRead) >= 0) {
|
||||
if(RunQuery(query, MakeAnyLenString(&query, "delete from `mail` where `status`=3 and `timestamp` < %i",
|
||||
time(NULL) - RuleI(Mail, ExpireRead)), errbuf, 0, &AffectedRows)) {
|
||||
_log(UCS__INIT, "Expired %i read messages.", AffectedRows);
|
||||
}
|
||||
else {
|
||||
_log(UCS__ERROR, "Error expiring read messages, %s %s", query, errbuf);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
// Expire Unread
|
||||
if(RuleI(Mail, ExpireUnread) >= 0) {
|
||||
if(RunQuery(query, MakeAnyLenString(&query, "delete from `mail` where `status`=1 and `timestamp` < %i",
|
||||
time(NULL) - RuleI(Mail, ExpireUnread)), errbuf, 0, &AffectedRows)) {
|
||||
_log(UCS__INIT, "Expired %i unread messages.", AffectedRows);
|
||||
}
|
||||
else {
|
||||
_log(UCS__ERROR, "Error expiring unread messages, %s %s", query, errbuf);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
}
|
||||
|
||||
void Database::AddFriendOrIgnore(int CharID, int Type, string Name) {
|
||||
|
||||
const char *FriendsQuery="INSERT INTO `friends` (`charid`, `type`, `name`) VALUES ('%i', %i, '%s')";
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, FriendsQuery, CharID, Type, CapitaliseName(Name).c_str()), errbuf, 0, 0))
|
||||
_log(UCS__ERROR, "Error adding friend/ignore, query was %s : %s", query, errbuf);
|
||||
else
|
||||
_log(UCS__TRACE, "Wrote Friend/Ignore entry for charid %i, type %i, name %s to database.",
|
||||
CharID, Type, Name.c_str());
|
||||
|
||||
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void Database::RemoveFriendOrIgnore(int CharID, int Type, string Name) {
|
||||
|
||||
const char *FriendsQuery="DELETE FROM `friends` WHERE `charid`=%i AND `type`=%i and `name`='%s'";
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, FriendsQuery, CharID, Type, CapitaliseName(Name).c_str()), errbuf, 0, 0))
|
||||
_log(UCS__ERROR, "Error removing friend/ignore, query was %s", query);
|
||||
else
|
||||
_log(UCS__TRACE, "Removed Friend/Ignore entry for charid %i, type %i, name %s from database.",
|
||||
CharID, Type, Name.c_str());
|
||||
|
||||
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void Database::GetFriendsAndIgnore(int CharID, vector<string> &Friends, vector<string> &Ignorees) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
const char *FriendsQuery="select `type`, `name` from `friends` WHERE `charid`=%i";
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, FriendsQuery, CharID),errbuf,&result)){
|
||||
|
||||
_log(UCS__ERROR, "GetFriendsAndIgnore query error %s, %s", query, errbuf);
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
while((row = mysql_fetch_row(result))) {
|
||||
|
||||
string Name = row[1];
|
||||
|
||||
if(atoi(row[0]) == 0)
|
||||
{
|
||||
Ignorees.push_back(Name);
|
||||
_log(UCS__TRACE, "Added Ignoree from DB %s", Name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Friends.push_back(Name);
|
||||
_log(UCS__TRACE, "Added Friend from DB %s", Name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CHATSERVER_DATABASE_H
|
||||
#define CHATSERVER_DATABASE_H
|
||||
|
||||
#define AUTHENTICATION_TIMEOUT 60
|
||||
#define INVALID_ID 0xFFFFFFFF
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "../common/types.h"
|
||||
#include "../common/dbcore.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "clientlist.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
//atoi is not uint32 or uint32 safe!!!!
|
||||
#define atoul(str) strtoul(str, NULL, 10)
|
||||
|
||||
class Database : public DBcore {
|
||||
public:
|
||||
Database();
|
||||
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
~Database();
|
||||
|
||||
int FindAccount(const char *CharacterName, Client *c);
|
||||
int FindCharacter(const char *CharacterName);
|
||||
bool VerifyMailKey(string CharacterName, int IPAddress, string MailKey);
|
||||
bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len);
|
||||
bool LoadChatChannels();
|
||||
void GetAccountStatus(Client *c);
|
||||
void SetChannelPassword(string ChannelName, string Password);
|
||||
void SetChannelOwner(string ChannelName, string Owner);
|
||||
void SendHeaders(Client *c);
|
||||
void SendBody(Client *c, int MessageNumber);
|
||||
bool SendMail(string Recipient, string From, string Subject, string Body, string RecipientsString);
|
||||
void SetMessageStatus(int MessageNumber, int Status);
|
||||
void ExpireMail();
|
||||
void AddFriendOrIgnore(int CharID, int Type, string Name);
|
||||
void RemoveFriendOrIgnore(int CharID, int Type, string Name);
|
||||
void GetFriendsAndIgnore(int CharID, vector<string> &Friends, vector<string> &Ignorees);
|
||||
|
||||
|
||||
protected:
|
||||
void HandleMysqlError(uint32 errnum);
|
||||
private:
|
||||
void DBInitVars();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "clientlist.h"
|
||||
#include "../common/opcodemgr.h"
|
||||
#include "../common/EQStreamFactory.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/platform.h"
|
||||
#include "../common/crash.h"
|
||||
#include "database.h"
|
||||
#include "ucsconfig.h"
|
||||
#include "chatchannel.h"
|
||||
#include "worldserver.h"
|
||||
#include <list>
|
||||
#include <signal.h>
|
||||
|
||||
volatile bool RunLoops = true;
|
||||
|
||||
uint32 MailMessagesSent = 0;
|
||||
uint32 ChatMessagesSent = 0;
|
||||
|
||||
TimeoutManager timeout_manager;
|
||||
|
||||
Clientlist *CL;
|
||||
|
||||
ChatChannelList *ChannelList;
|
||||
|
||||
Database database;
|
||||
|
||||
string WorldShortName;
|
||||
|
||||
RuleManager *rules = new RuleManager();
|
||||
|
||||
const ucsconfig *Config;
|
||||
|
||||
WorldServer *worldserver = 0;
|
||||
|
||||
|
||||
void CatchSignal(int sig_num) {
|
||||
|
||||
RunLoops = false;
|
||||
|
||||
if(worldserver)
|
||||
worldserver->Disconnect();
|
||||
}
|
||||
|
||||
string GetMailPrefix() {
|
||||
|
||||
return "SOE.EQ." + WorldShortName + ".";
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
RegisterExecutablePlatform(ExePlatformUCS);
|
||||
set_exception_handler();
|
||||
|
||||
// Check every minute for unused channels we can delete
|
||||
//
|
||||
Timer ChannelListProcessTimer(60000);
|
||||
|
||||
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
|
||||
|
||||
_log(UCS__INIT, "Starting EQEmu Universal Chat Server.");
|
||||
|
||||
if (!ucsconfig::LoadConfig()) {
|
||||
|
||||
_log(UCS__INIT, "Loading server configuration failed.");
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
Config = ucsconfig::get();
|
||||
|
||||
if(!load_log_settings(Config->LogSettingsFile.c_str()))
|
||||
_log(UCS__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
|
||||
else
|
||||
_log(UCS__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());
|
||||
|
||||
WorldShortName = Config->ShortName;
|
||||
|
||||
_log(UCS__INIT, "Connecting to MySQL...");
|
||||
|
||||
if (!database.Connect(
|
||||
Config->DatabaseHost.c_str(),
|
||||
Config->DatabaseUsername.c_str(),
|
||||
Config->DatabasePassword.c_str(),
|
||||
Config->DatabaseDB.c_str(),
|
||||
Config->DatabasePort)) {
|
||||
_log(WORLD__INIT_ERR, "Cannot continue without a database connection.");
|
||||
return(1);
|
||||
}
|
||||
|
||||
char tmp[64];
|
||||
|
||||
if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) {
|
||||
_log(WORLD__INIT, "Loading rule set '%s'", tmp);
|
||||
if(!rules->LoadRules(&database, tmp)) {
|
||||
_log(UCS__ERROR, "Failed to load ruleset '%s', falling back to defaults.", tmp);
|
||||
}
|
||||
} else {
|
||||
if(!rules->LoadRules(&database, "default")) {
|
||||
_log(UCS__INIT, "No rule set configured, using default rules");
|
||||
} else {
|
||||
_log(UCS__INIT, "Loaded default rule set 'default'", tmp);
|
||||
}
|
||||
}
|
||||
|
||||
database.ExpireMail();
|
||||
|
||||
if(Config->ChatPort != Config->MailPort)
|
||||
{
|
||||
_log(UCS__ERROR, "MailPort and CharPort must be the same in eqemu_config.xml for UCS.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
CL = new Clientlist(Config->ChatPort);
|
||||
|
||||
ChannelList = new ChatChannelList();
|
||||
|
||||
database.LoadChatChannels();
|
||||
|
||||
if (signal(SIGINT, CatchSignal) == SIG_ERR) {
|
||||
_log(UCS__ERROR, "Could not set signal handler");
|
||||
return 0;
|
||||
}
|
||||
if (signal(SIGTERM, CatchSignal) == SIG_ERR) {
|
||||
_log(UCS__ERROR, "Could not set signal handler");
|
||||
return 0;
|
||||
}
|
||||
|
||||
worldserver = new WorldServer;
|
||||
|
||||
worldserver->Connect();
|
||||
|
||||
while(RunLoops) {
|
||||
|
||||
Timer::SetCurrentTime();
|
||||
|
||||
CL->Process();
|
||||
|
||||
if(ChannelListProcessTimer.Check())
|
||||
ChannelList->Process();
|
||||
|
||||
if (InterserverTimer.Check()) {
|
||||
if (worldserver->TryReconnect() && (!worldserver->Connected()))
|
||||
worldserver->AsyncConnect();
|
||||
}
|
||||
worldserver->Process();
|
||||
|
||||
timeout_manager.CheckTimeouts();
|
||||
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
ChannelList->RemoveAllChannels();
|
||||
|
||||
CL->CloseAllConnections();
|
||||
|
||||
}
|
||||
|
||||
void UpdateWindowTitle(char* iNewTitle) {
|
||||
#ifdef _WINDOWS
|
||||
char tmp[500];
|
||||
if (iNewTitle) {
|
||||
snprintf(tmp, sizeof(tmp), "UCS: %s", iNewTitle);
|
||||
}
|
||||
else {
|
||||
snprintf(tmp, sizeof(tmp), "UCS");
|
||||
}
|
||||
SetConsoleTitle(tmp);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "ucsconfig.h"
|
||||
|
||||
ucsconfig *ucsconfig::_chat_config = NULL;
|
||||
|
||||
string ucsconfig::GetByName(const string &var_name) const {
|
||||
return(EQEmuConfig::GetByName(var_name));
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
EQEMu: Everquest Server Emulator
|
||||
|
||||
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ucsconfig_H
|
||||
#define __ucsconfig_H
|
||||
|
||||
#include "../common/EQEmuConfig.h"
|
||||
|
||||
class ucsconfig : public EQEmuConfig {
|
||||
public:
|
||||
virtual string GetByName(const string &var_name) const;
|
||||
|
||||
private:
|
||||
|
||||
static ucsconfig *_chat_config;
|
||||
|
||||
public:
|
||||
|
||||
// Produce a const singleton
|
||||
static const ucsconfig *get() {
|
||||
if (_chat_config == NULL)
|
||||
LoadConfig();
|
||||
return(_chat_config);
|
||||
}
|
||||
|
||||
// Load the config
|
||||
static bool LoadConfig() {
|
||||
if (_chat_config != NULL)
|
||||
delete _chat_config;
|
||||
_chat_config=new ucsconfig;
|
||||
_config=_chat_config;
|
||||
|
||||
return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,134 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "../common/servertalk.h"
|
||||
#include "worldserver.h"
|
||||
#include "clientlist.h"
|
||||
#include "ucsconfig.h"
|
||||
#include "database.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "../common/md5.h"
|
||||
|
||||
extern WorldServer worldserver;
|
||||
extern Clientlist *CL;
|
||||
extern const ucsconfig *Config;
|
||||
extern Database database;
|
||||
|
||||
void ProcessMailTo(Client *c, string from, string subject, string message);
|
||||
|
||||
WorldServer::WorldServer()
|
||||
: WorldConnection(EmuTCPConnection::packetModeUCS, Config->SharedKey.c_str())
|
||||
{
|
||||
pTryReconnect = true;
|
||||
}
|
||||
|
||||
WorldServer::~WorldServer()
|
||||
{
|
||||
}
|
||||
|
||||
void WorldServer::OnConnected()
|
||||
{
|
||||
_log(UCS__INIT, "Connected to World.");
|
||||
WorldConnection::OnConnected();
|
||||
}
|
||||
|
||||
void WorldServer::Process()
|
||||
{
|
||||
WorldConnection::Process();
|
||||
|
||||
if (!Connected())
|
||||
return;
|
||||
|
||||
ServerPacket *pack = 0;
|
||||
|
||||
while((pack = tcpc.PopPacket()))
|
||||
{
|
||||
_log(UCS__TRACE, "Received Opcode: %4X", pack->opcode);
|
||||
|
||||
switch(pack->opcode)
|
||||
{
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case ServerOP_KeepAlive:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ServerOP_UCSMessage:
|
||||
{
|
||||
char *Buffer = (char *)pack->pBuffer;
|
||||
|
||||
char *From = new char[strlen(Buffer) + 1];
|
||||
|
||||
VARSTRUCT_DECODE_STRING(From, Buffer);
|
||||
|
||||
string Message = Buffer;
|
||||
|
||||
_log(UCS__TRACE, "Player: %s, Sent Message: %s", From, Message.c_str());
|
||||
|
||||
Client *c = CL->FindCharacter(From);
|
||||
|
||||
safe_delete_array(From);
|
||||
|
||||
if(Message.length() < 2)
|
||||
break;
|
||||
|
||||
if(!c)
|
||||
{
|
||||
_log(UCS__TRACE, "Client not found.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(Message[0] == ';')
|
||||
{
|
||||
c->SendChannelMessageByNumber(Message.substr(1, string::npos));
|
||||
}
|
||||
else if(Message[0] == '[')
|
||||
{
|
||||
CL->ProcessOPMailCommand(c, Message.substr(1, string::npos));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ServerOP_UCSMailMessage:
|
||||
{
|
||||
ServerMailMessageHeader_Struct *mail = (ServerMailMessageHeader_Struct*)pack->pBuffer;
|
||||
database.SendMail(string("SOE.EQ.") + Config->ShortName + string(".") + string(mail->to),
|
||||
string(mail->from),
|
||||
mail->subject,
|
||||
mail->message,
|
||||
string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
safe_delete(pack);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef WORLDSERVER_H
|
||||
#define WORLDSERVER_H
|
||||
|
||||
#include "../common/worldconn.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
|
||||
class WorldServer : public WorldConnection
|
||||
{
|
||||
public:
|
||||
WorldServer();
|
||||
virtual ~WorldServer();
|
||||
virtual void Process();
|
||||
|
||||
private:
|
||||
virtual void OnConnected();
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user