/* * 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; 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Manuel Mausz (manuel@mausz.at) * Christian Raschko (c.raschko@netcore.at) */ // Header #include "tsquerythread.h" #include "wxbufferex.h" #include "base64.h" //Libraries #include #include #include #include #include #include #include #include #include #include #include #include #include #include IMPLEMENT_CLASS(TSQueryThread, wxObject) //------------------------------------------------------------------------------ static bool strToChannelId(wxString &str, wxUint32 *pid, bool pid_allowed = true) { unsigned long l; if (!str.ToULong(&l)) return false; if (l == ULONG_MAX) l = TS_NO_PARENT; if (l > TS_NO_PARENT || (!pid_allowed && l == TS_NO_PARENT)) return false; *pid = wxUint32(l); return true; } static bool strToNum(wxString &str, wxUint32 *val) { unsigned long l; if (!str.ToULong(&l)) return false; if (l > TS_NUM_MAX) return false; *val = wxUint32(l); return true; } //------------------------------------------------------------------------------ // thread execution starts here wxThread::ExitCode TSQueryThread::Entry() { wxLogMessage(_T("TSQuery: thread started.")); // init libxml2 library wxXml2::Init(); //check for bind if(m_ServerAddress.Length() < 7 || m_ServerAddress == _T("0.0.0.0")) m_ServerAddr.AnyAddress(); else m_ServerAddr.Hostname(m_ServerAddress); m_ServerAddr.Service(m_Port); m_pSocket = new wxSocketServer(m_ServerAddr, wxSOCKET_REUSEADDR); //Check socket if(!m_pSocket->Ok()) { if(m_pSocket->LastError() == wxSOCKET_INVPORT) SetLastError(_T("Socket port in use")); else SetLastError(_T("Socket error")); m_pSocket->Destroy(); m_pSocket = NULL; return wxThread::ExitCode(EXIT_FAILURE); } while(1) { if (!Accept()) wxLogError(_T("TSQuery: %s"), m_LastError.c_str()); if (m_pSocket == NULL) break; } return wxThread::ExitCode(EXIT_SUCCESS); } //------------------------------------------------------------------------------ // and stops here void TSQueryThread::OnExit() { wxLogDebug(_T("TSQuery: thread terminated.")); // cleanup libxml2 statics wxXml2::Cleanup(); if(m_pSocket != NULL) { m_pSocket->Destroy(); m_pSocket = NULL; } } //------------------------------------------------------------------------------ // Default CTor, Initializes the object. TSQueryThread::TSQueryThread(TSClient *client) : wxThread(wxTHREAD_JOINABLE) { Create(); //create all objects //m_pSocket = new wxSocketServer(m_ServerAddr, wxSOCKET_REUSEADDR); m_pClient = client; m_Password = _T(""); } //------------------------------------------------------------------------------ // Default DTor. TSQueryThread::~TSQueryThread() { //use OnExit() } //------------------------------------------------------------------------------ // Listen bool TSQueryThread::Accept() { //Wait until someone connect (NOTE: wxWidgets has an internal select timeout (~10 mins)) wxSocketBase *sock = m_pSocket->Accept(); // wxSocketBase doesn't set Error() to true after socket timeout, so we check against null if(m_pSocket->LastError() == wxSOCKET_TIMEDOUT && sock == NULL) return true; // real check against null if(sock == NULL) { SetLastError(_T("Socket, something really bad happend")); m_pSocket->Destroy(); m_pSocket = NULL; return false; } //Check if IP is allowed wxIPV4address peeraddr; sock->GetPeer(peeraddr); wxLogMessage(_T("TSQuery: incoming request from %s"), peeraddr.IPAddress().c_str()); if(!IsIPAllowed(peeraddr.IPAddress())) { wxLogError(_T("TSQuery: %s"),GetLastError().c_str()); sock->Destroy(); return false; } //now receive wxMemoryBufferEx buf(1024); sock->Read(buf.GetData(), 1024); buf.SetDataLen(sock->LastCount()); wxMemoryInputStream in(buf.GetData(), buf.GetDataLen()); wxStringOutputStream strm; buf.HexDump(strm); wxLogDebug(_T("TSQuery: command received:\n%s"), strm.GetString().c_str()); //Check socket if(sock->LastCount() == 0) { SetLastError(_T("Socket, no data available")); sock->Destroy(); return false; } //Check XML format wxString err; if (!m_pXml.Load(in, &err)) { wxLogError(_T("XML format error: %s"), err.c_str()); return false; } //check node format if(!IsValidFormat()) { SendError(_T("General"), GetLastError(), sock); sock->Destroy(); return false; } //check password wxXml2Node pNode = m_pXml.GetRoot().Get(_T("Password")).GetFirstChild(); if(pNode.GetContent() != m_Password) { pNode = m_pXml.GetRoot().Get(_T("Command")).GetFirstChild(); SetLastError(_T("Invalid password")); SendError(pNode.GetContent(), GetLastError(), sock); sock->Destroy(); return false; } //check if TSClient is connected if(!m_pClient->IsConnected()) { pNode = m_pXml.GetRoot().Get(_T("Command")).GetFirstChild(); SetLastError(_T("No connection to TSServer")); SendError(pNode.GetContent(), GetLastError(), sock); sock->Destroy(); return false; } //ok now process the command if(!ProcessCommand(sock)) { sock->Destroy(); return false; } sock->Destroy(); wxLogMessage(_T("TSQuery: request successfully processed.")); return true; } //------------------------------------------------------------------------------ // IsIPAllowed bool TSQueryThread::IsIPAllowed(wxString const &str) { wxStringTokenizer tkz(m_AllowedAddresses, _T(",")); bool found = false; while(tkz.HasMoreTokens()) { wxString token = tkz.GetNextToken(); wxIPV4address tmpaddr; if(!tmpaddr.Hostname(token)) { SetLastError(wxString::Format(_T("'%s' this is no valid IP"),token.c_str())); return false; } unsigned ip1[4], ip2[4]; if(tmpaddr.IPAddress() == str) { found = true; break; } //dirty C else if(wxSscanf(tmpaddr.IPAddress().c_str(), _T("%u.%u.%u.%u"), &ip1[0], &ip1[1], &ip1[2], &ip1[3]) == 4 && wxSscanf(str.c_str(), _T("%u.%u.%u.%u"), &ip2[0], &ip2[1], &ip2[2], &ip2[3]) == 4) { if((ip1[0] == 0 && ip1[1] == 0 && ip1[2] == 0 && ip1[3] == 0) || //0.0.0.0 (ip1[0] == ip2[0] && ip1[1] == 0 && ip1[2] == 0 && ip1[3] == 0) || //x.0.0.0 (ip1[0] == ip2[0] && ip1[1] == ip2[1] && ip1[2] == 0 && ip1[3] == 0) || //x.x.0.0 (ip1[0] == ip2[0] && ip1[1] == ip2[1] && ip1[2] == ip2[2] && ip1[3] == 0)) //x.x.x.0 { found = true; break; } } } if (!found) { SetLastError(_T("IP is not allowed")); return false; } return true; } //------------------------------------------------------------------------------ // IsValidFormat bool TSQueryThread::IsValidFormat() { //check node wxXml2Node pNodeRoot = m_pXml.GetRoot(); if(pNodeRoot.GetName() != _T("TSClient")) { SetLastError(_T("No 'TSClient' node found")); return false; } //check node wxXml2Node pNode = pNodeRoot.Get(_T("Password")); if(pNode == wxXml2EmptyNode) { SetLastError(_T("No 'Password' node found")); return false; } pNode = pNodeRoot.Get(_T("Command")); if(pNode == wxXml2EmptyNode) { SetLastError(_T("No 'Command' node found")); return false; } return true; } //------------------------------------------------------------------------------ // ProcessCommand. bool TSQueryThread::ProcessCommand(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); //check node wxXml2Node pNode = pNodeRoot.Get(_T("Command")); if(pNode == wxXml2EmptyNode) { SetLastError(_T("No 'Command' node found")); SendError(_T("General"), GetLastError(), sock); return false; } wxString cmd = pNode.GetFirstChild().GetContent(); wxLogMessage(_T("TSQuery: command '%s' received"), cmd.c_str()); pNode = pNodeRoot.Get(_T("Text")); if(pNode != wxXml2EmptyNode) wxLogMessage(_T("TSQuery: Text: '%s'"), pNode.GetFirstChild().GetContent().c_str()); if(cmd == _T("GetStatus")) return CmdGetStatus(sock); else if(cmd == _T("GetChannels")) return CmdGetChannels(sock); else if(cmd == _T("GetUsers")) return CmdGetUsers(sock); else if(cmd == _T("CreateChannel")) return CmdCreateChannel(sock); else if(cmd == _T("DeleteChannel")) return CmdDeleteChannel(sock); else if(cmd == _T("ModifyChannel")) return CmdModifyChannel(sock); else if(cmd == _T("MoveUser")) return CmdMoveUser(sock); else if(cmd == _T("KickUser")) return CmdKickUser(sock); else if(cmd == _T("Kill")) return CmdKill(sock); SetLastError(_T("Unknown command")); SendError(cmd, GetLastError(), sock); return false; } //------------------------------------------------------------------------------ // SendError. bool TSQueryThread::SendError(wxString const &cmd, wxString const &str, wxSocketBase *sock) { wxSocketOutputStream so(*sock); wxBufferedOutputStream out(so); m_pXml.Create(_T("1.0")); wxXml2Node pNodeRoot; pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); wxXml2Node pNode; pNode = pNodeRoot.AddTextChild(_T("Command"), cmd); pNode.AddProperty(_T("State"), _T("Error")); pNode = pNodeRoot.AddTextChild(_T("ErrorText"), str); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ // Dumps object. void TSQueryThread::Dump(wxOutputStream &ostrm) const { wxTextOutputStream out(ostrm); out << wxString(_T("-"), 60) << endl; out << _T("Object: TSQueryThread (") << wxString::Format(_T("0x%X"), this) << _T(")") << endl; } //------------------------------------------------------------------------------ bool TSQueryThread::SendDOM(wxSocketBase *sock) { wxSocketOutputStream so(*sock); wxBufferedOutputStream out(so); if(!m_pXml.Save(out, _T("utf-8"), wxXML2DOC_USE_NATIVE_NEWLINES | wxXML2DOC_USE_INDENTATION, 2)) { SetLastError(_T("DOM serialization")); return false; } out.Sync(); return true; } //------------------------------------------------------------------------------ wxString TSQueryThread::GetNodeValue(wxXml2Node &pElemRoot, wxString const &str) { wxXml2Node pElem = pElemRoot.Get(str); if(pElem == wxXml2EmptyNode) return _T(""); else return pElem.GetFirstChild().GetContent(); } //------------------------------------------------------------------------------ bool TSQueryThread::CmdGetStatus(wxSocketBase *sock) { wxString str; str = wxString::Format(_T("%s:%d"), m_pClient->GetServer()->GetServerAddress().c_str(), m_pClient->GetServer()->GetPort()); if(!m_pClient->IsConnected()) { wxLogMessage(_T("TSQuery: TSServer %s is not connected"), str.c_str()); SetLastError(_T("No connection to TSServer")); SendError(_T("GetStatus"), GetLastError(), sock); return false; } m_pXml.Create(_T("1.0")); wxXml2Node pNodeRoot; pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); wxXml2Node pNode; pNode = pNodeRoot.AddTextChild(_T("Command"), _T("GetStatus")); pNode.AddProperty(_T("State"), _T("Ok")); pNode = pNodeRoot.AddTextChild(_T("TSServer"), str); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdGetChannels(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); TSpChannelArray chs; wxXml2Node pNode = pNodeRoot.Get(_T("ChannelName")); if(pNode != wxXml2EmptyNode) { wxString str = pNode.GetFirstChild().GetContent(); m_pClient->FindChannelsByName(str, &chs); /* remove channels not matching ParentId */ str = pNode.GetPropVal(_T("ParentId"), wxEmptyString); wxUint32 pid; if (!str.empty() && strToChannelId(str, &pid)) { for(size_t i = 0; i < chs.Count(); i++) { if (chs[i]->GetParent() != pid) chs.RemoveAt(i); } } /* add subchannels */ if(pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes")) { for(size_t i = 0; i < chs.Count(); i++) m_pClient->FindChannelsByParent(chs[i]->GetId(), &chs); } } pNode = pNodeRoot.Get(_T("ChannelId")); if(pNode != wxXml2EmptyNode) { wxString str = pNode.GetFirstChild().GetContent(); wxUint32 chlid; if (strToChannelId(str, &chlid, false)) { TSChannel *c = m_pClient->FindChannel(chlid); if(c != NULL) chs.Add(c); /* remove channels not matching ParentId */ wxUint32 pid; str = pNode.GetPropVal(_T("ParentId"), wxEmptyString); if (!str.empty() && strToChannelId(str, &pid)) { for(size_t i = 0; i < chs.Count(); i++) { if (chs[i]->GetParent() != pid) chs.RemoveAt(i); } } /* add subchannels */ if(pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes")) { for(size_t i = 0; i < chs.Count(); i++) m_pClient->FindChannelsByParent(chs[i]->GetId(), &chs); } } } pNode = pNode.Get(_T("ChannelParentId")); if(pNode != wxXml2EmptyNode) { wxString str = pNode.GetFirstChild().GetContent(); wxUint32 pid; if (strToChannelId(str, &pid)) m_pClient->FindChannelsByParent(pid, &chs); } m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); pNode = pNodeRoot.AddTextChild(_T("Command"), _T("GetChannels")); pNode.AddProperty(_T("State"), _T("Ok")); wxLogMessage(_T("TSQuery: sending requested channels.")); for(size_t i = 0; i < chs.Count(); i++) { wxXml2Node pChannelNode; pChannelNode = pNodeRoot.AddContainerChild(_T("Channel")); pChannelNode.AddProperty(_T("Id"), wxString::Format(_T("%d"), chs[i]->GetId())); pChannelNode.AddProperty(_T("ParentId"), wxString::Format(_T("%d"), chs[i]->GetParent())); pChannelNode.AddTextChild(_T("ChannelName"), chs[i]->GetName()); pChannelNode.AddTextChild(_T("ChannelTopic"), chs[i]->GetTopic()); pChannelNode.AddTextChild(_T("ChannelSlots"), wxString::Format(_T("%d"), chs[i]->GetMaxUsers())); pChannelNode.AddTextChild(_T("ChannelPassword"), chs[i]->GetPassword()); pChannelNode.AddTextChild(_T("ChannelCodec"), wxString::Format(_T("%d"), chs[i]->GetCodec())); const wxCharBuffer buf = chs[i]->GetDescription().mb_str(wxConvUTF8); pChannelNode.AddTextChild(_T("ChannelDescription"), Base64Encode(buf, strlen(buf))); pChannelNode.AddTextChild(_T("ChannelFlags"), chs[i]->GetFlagsString()); wxLogVerbose(_T("TSQuery: Channel '%s' transmitted."), chs[i]->GetName().c_str()); } if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdGetUsers(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); TSpPlayerArray pls; wxString str; wxXml2Node pNode; pNode = pNodeRoot.Get(_T("UserName")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); m_pClient->FindPlayersByName(str, &pls); } pNode = pNodeRoot.Get(_T("UserId")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); wxUint32 plyid; if (strToNum(str, &plyid)) pls.Add(m_pClient->FindPlayer(plyid)); } pNode = pNodeRoot.Get(_T("ChannelName")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); TSpChannelArray chs; m_pClient->FindChannelsByName(str, &chs); /* remove channels not matching ParentId */ wxUint32 pid; str = pNode.GetPropVal(_T("ParentId"), wxEmptyString); if (!str.empty() && strToChannelId(str, &pid)) { for(size_t i = 0; i < chs.Count(); i++) { if (chs[i]->GetParent() != pid) chs.RemoveAt(i); } } /* find users */ for(size_t i = 0; i < chs.Count(); i++) { m_pClient->FindPlayersByChannel(chs[i], &pls); /* add subchannels and their users */ if (pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes")) { TSpChannelArray chs2; m_pClient->FindChannelsByParent(chs[i]->GetId(), &chs2); for(size_t j = 0; j < chs2.Count(); j++) m_pClient->FindPlayersByChannel(chs2[j], &pls); } } } pNode = pNodeRoot.Get(_T("ChannelId")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); TSChannel *cl = NULL; wxUint32 chlid; if (strToChannelId(str, &chlid, false)) cl = m_pClient->FindChannel(chlid); if (cl == NULL) { SetLastError(_T("Error while searching for channel.")); SendError(_T("GetUsers"), GetLastError(), sock); return false; } m_pClient->FindPlayersByChannel(cl, &pls); if (pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes")) { TSpChannelArray chs; m_pClient->FindChannelsByParent(cl->GetId(), &chs); for(size_t i = 0; i < chs.Count(); i++) m_pClient->FindPlayersByChannel(chs[i], &pls); } } m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); pNode = pNodeRoot.AddTextChild(_T("Command"), _T("GetUsers")); pNode.AddProperty(_T("State"), _T("Ok")); wxLogMessage(_T("TSQuery: sending requested users.")); for(size_t i = 0; i < pls.Count(); i++) { wxXml2Node pUserNode; pUserNode = pNodeRoot.AddContainerChild(_T("User")); pUserNode.AddProperty(_T("Id"), wxString::Format(_T("%d"), pls[i]->GetId())); pUserNode.AddTextChild(_T("UserName"), pls[i]->GetNickname().c_str()); pUserNode.AddTextChild(_T("UserChannelId"), wxString::Format(_T("%d"), pls[i]->GetChannelId()).c_str()); pUserNode.AddTextChild(_T("UserFlags"), wxString::Format(_T("%d"), pls[i]->GetFlags()).c_str()); pUserNode.AddTextChild(_T("UserPrivileges"), wxString::Format(_T("%d"), pls[i]->GetPrivileges()).c_str()); pUserNode.AddTextChild(_T("UserChannelPrivileges"), wxString::Format(_T("%d"), pls[i]->GetChannelPrivileges()).c_str()); wxLogVerbose(_T("TSQuery: User '%s' transmitted."), pls[i]->GetNickname().c_str()); } if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdCreateChannel(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); TSChannel cl; wxString str; wxXml2Node pNode; pNode = pNodeRoot.Get(_T("Channel")); if(pNode == wxXml2EmptyNode) { SetLastError(_T("No channel node")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } wxUint32 chlid; str = pNode.GetPropVal(_T("ParentId"), _T("-1")); if (!strToChannelId(str, &chlid)) { SetLastError(_T("Invalid parent id")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } cl.SetParent(chlid); cl.SetName(GetNodeValue(pNode, _T("ChannelName"))); cl.SetTopic(GetNodeValue(pNode, _T("ChannelTopic"))); cl.SetPassword(GetNodeValue(pNode, _T("ChannelPassword"))); wxUint32 num; str = GetNodeValue(pNode, _T("ChannelSlots")); if (!strToNum(str, &num)) { SetLastError(_T("Invalid channel slots value")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } cl.SetMaxUsers(num); str = GetNodeValue(pNode, _T("ChannelCodec")); if (!strToNum(str, &num)) { SetLastError(_T("Invalid channel codec value")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } cl.SetCodec(num); wxCSConv conv_iso(_T("iso-8859-1")); wxString base64_encoded = GetNodeValue(pNode, _T("ChannelDescription")); cl.SetDescription(wxString(Base64Decode(base64_encoded).mb_str(conv_iso), wxConvUTF8)); cl.SetFlags(GetNodeValue(pNode, _T("ChannelFlags"))); m_pClient->CreateChannel(&cl); // dirty wait for channel id wxUint32 channelid = 0; for (wxUint32 i = 0; i <= 2; i++) { TSpChannelArray chs; if (cl.GetParent() == TS_NO_PARENT) { // we wait for a main channel m_pClient->FindChannelsByName(_T("^") + cl.GetName() + _T("$"), &chs); for(size_t i = 0; i < chs.Count(); i++) { if (chs[i]->GetParent() == TS_NO_PARENT) { channelid = chs[i]->GetId(); break; } } } else { // we wait for a subchannel m_pClient->FindChannelsByParent(cl.GetParent(), &chs); for(size_t i = 0; i < chs.Count(); i++) { if (chs[i]->GetName() == cl.GetName()) { channelid = chs[i]->GetId(); break; } } } if (channelid > 0) break; Sleep(500); } if (channelid <= 0) { SetLastError(_T("Error while creating channel.")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); pNode = pNodeRoot.AddTextChild(_T("Command"), _T("CreateChannel")); pNode.AddProperty(_T("State"), _T("Ok")); pNodeRoot.AddTextChild(_T("ChannelId"), wxString::Format(_T("%d"), channelid)); wxLogMessage(_T("TSQuery: Channel '%s' created."), cl.GetName().c_str()); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdDeleteChannel(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); TSChannel *cl = NULL; wxString str; wxXml2Node pNode; pNode = pNodeRoot.Get(_T("ChannelId")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); wxUint32 chlid; if (strToChannelId(str, &chlid, false)) cl = m_pClient->FindChannel(chlid); } if(cl == NULL) { SetLastError(_T("Channel not found.")); SendError(_T("DeleteChannel"), GetLastError(), sock); return false; } TSChannel *defchl = m_pClient->FindDefaultChannel(); // process subchannels TSpChannelArray chs; m_pClient->FindChannelsByParent(cl->GetId(), &chs); for(size_t i = 0; i < chs.Count(); i++) { TSpPlayerArray ply; m_pClient->FindPlayersByChannel(chs[i], &ply); for(size_t i=0;iGetId()); pl.SetChannelId(defchl->GetId()); m_pClient->MovePlayer(&pl); } } // process main channel TSpPlayerArray ply; m_pClient->FindPlayersByChannel(cl,&ply); for(size_t i=0;iGetId()); pl.SetChannelId(defchl->GetId()); m_pClient->MovePlayer(&pl); } wxLogMessage(_T("TSQuery: Channel '%s' deleted."),cl->GetName().c_str()); m_pClient->DeleteChannel(cl); m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); pNode = pNodeRoot.AddTextChild(_T("Command"), _T("DeleteChannel")); pNode.AddProperty(_T("State"), _T("Ok")); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdModifyChannel(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); TSChannel cl; wxString str; wxXml2Node pNode; pNode = pNodeRoot.Get(_T("Channel")); if(pNode == wxXml2EmptyNode) { SetLastError(_T("No channel node")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } wxUint32 chlid; str = pNode.GetPropVal(_T("Id"), _T("")); if (!strToChannelId(str, &chlid, false)) { SetLastError(_T("No id attribute found")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } cl.SetId(chlid); cl.SetName(GetNodeValue(pNode, _T("ChannelName"))); cl.SetTopic(GetNodeValue(pNode, _T("ChannelTopic"))); cl.SetPassword(GetNodeValue(pNode, _T("ChannelPassword"))); wxUint32 num; str = GetNodeValue(pNode, _T("ChannelSlots")); if (!strToNum(str, &num)) { SetLastError(_T("Invalid channel slots value")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } cl.SetMaxUsers(num); str = GetNodeValue(pNode, _T("ChannelCodec")); if (!strToNum(str, &num)) { SetLastError(_T("Invalid channel codec value")); SendError(_T("CreateChannel"), GetLastError(), sock); return false; } cl.SetCodec(num); wxCSConv conv_iso(_T("iso-8859-1")); wxString base64_encoded = GetNodeValue(pNode, _T("ChannelDescription")); cl.SetDescription(wxString(Base64Decode(base64_encoded).mb_str(conv_iso), wxConvUTF8)); cl.SetFlags(GetNodeValue(pNode, _T("ChannelFlags"))); m_pClient->ModifyChannel(&cl); m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); pNode = pNodeRoot.AddTextChild(_T("Command"), _T("ModifyChannel")); pNode.AddProperty(_T("State"), _T("Ok")); wxLogMessage(_T("TSQuery: Channel '%s' modified."), cl.GetName().c_str()); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdMoveUser(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); TSPlayer *pl = NULL; TSChannel *cl = NULL; wxString str; wxXml2Node pNode; pNode = pNodeRoot.Get(_T("UserId")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); wxUint32 plyid; if (strToNum(str, &plyid)) pl = m_pClient->FindPlayer(plyid); } if(pl == NULL) { SetLastError(_T("User not found.")); SendError(_T("MoveUser"), GetLastError(), sock); return false; } pNode = pNodeRoot.Get(_T("ChannelId")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); wxUint32 chlid; if (strToChannelId(str, &chlid, false)) cl = m_pClient->FindChannel(chlid); } if(cl == NULL) { SetLastError(_T("Channel not found.")); SendError(_T("MoveUser"), GetLastError(), sock); return false; } pl->SetChannelId(cl->GetId()); m_pClient->MovePlayer(pl); m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); pNode = pNodeRoot.AddTextChild(_T("Command"), _T("MoveUser")); pNode.AddProperty(_T("State"), _T("Ok")); wxLogMessage(_T("TSQuery: User '%s' moved to '%s'."), pl->GetNickname().c_str(), m_pClient->FindChannel(pl->GetChannelId())->GetName().c_str()); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdKickUser(wxSocketBase *sock) { wxXml2Node pNodeRoot = m_pXml.GetRoot(); TSPlayer *pl = NULL; wxString str; wxXml2Node pNode; pNode = pNodeRoot.Get(_T("UserId")); if(pNode != wxXml2EmptyNode) { str = pNode.GetFirstChild().GetContent(); wxUint32 plyid; if (strToNum(str, &plyid)) pl = m_pClient->FindPlayer(plyid); } if(pl == NULL) { SetLastError(_T("User not found.")); SendError(_T("KickUser"), GetLastError(), sock); return false; } str = _T(""); pNode = pNodeRoot.Get(_T("Reason")); if(pNode != wxXml2EmptyNode) str = pNode.GetFirstChild().GetContent(); wxLogMessage(_T("TSQuery: User '%s' kicked."), pl->GetNickname().c_str()); m_pClient->KickPlayer(pl, str); m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); pNode = pNodeRoot.AddTextChild(_T("Command"), _T("KickUser")); pNode.AddProperty(_T("State"), _T("Ok")); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ bool TSQueryThread::CmdKill(wxSocketBase *sock) { if(m_pClient->IsConnected()) m_pClient->Disconnect(false); wxXml2Node pNodeRoot; m_pXml.Create(_T("1.0")); pNodeRoot.CreateRoot(m_pXml, _T("TSClient")); wxXml2Node pNode = pNodeRoot.AddTextChild(_T("Command"), _T("Kill")); pNode.AddProperty(_T("State"), _T("Ok")); if(!SendDOM(sock)) return false; return true; } //------------------------------------------------------------------------------ // Sets the password for incomming connections. bool TSQueryThread::SetPassword(wxString const &str) { if(str.Length() == 0) { SetLastError(_T("Empty string")); return false; } m_Password = str; return true; } //------------------------------------------------------------------------------ // Sets the server address. bool TSQueryThread::SetServerAddress(wxString const &str) { if(str.Length() == 0) { SetLastError(_T("Empty string")); return false; } m_ServerAddress = str; return true; } //------------------------------------------------------------------------------ // Sets the allowed address. bool TSQueryThread::SetAllowedAddresses(wxString const &str) { if(str.Length() == 0) { SetLastError(_T("Empty string")); return false; } m_AllowedAddresses = str; return true; } //------------------------------------------------------------------------------ // Sets the connection port. bool TSQueryThread::SetPort(wxUint16 const &port) { if(port == 0) { SetLastError(_T("Empty port")); return false; } m_Port = port; return true; } //------------------------------------------------------------------------------ // Start thread. bool TSQueryThread::Start() { Run(); return true; } //------------------------------------------------------------------------------ // Stop thread. bool TSQueryThread::Stop() { Kill(); return true; }