summaryrefslogtreecommitdiffstats
path: root/tsquerythread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tsquerythread.cpp')
-rw-r--r--tsquerythread.cpp1105
1 files changed, 1105 insertions, 0 deletions
diff --git a/tsquerythread.cpp b/tsquerythread.cpp
new file mode 100644
index 0000000..94a1fef
--- /dev/null
+++ b/tsquerythread.cpp
@@ -0,0 +1,1105 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; version 2 of the License.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 * Authors: Manuel Mausz (manuel@mausz.at)
16 * Christian Raschko (c.raschko@netcore.at)
17 */
18
19// Header
20#include "tsquerythread.h"
21#include "wxbufferex.h"
22#include "base64.h"
23
24//Libraries
25#include <wx/wfstream.h>
26#include <wx/stream.h>
27#include <wx/sstream.h>
28#include <wx/socket.h>
29#include <wx/mstream.h>
30#include <wx/buffer.h>
31#include <wx/sckstrm.h>
32#include <wx/utils.h>
33#include <wx/memory.h>
34#include <wx/txtstrm.h>
35#include <wx/wfstream.h>
36#include <wx/txtstrm.h>
37#include <wx/tokenzr.h>
38#include <wx/strconv.h>
39
40IMPLEMENT_CLASS(TSQueryThread, wxObject)
41
42//------------------------------------------------------------------------------
43static bool strToChannelId(wxString &str, wxUint32 *pid,
44 bool pid_allowed = true)
45{
46 unsigned long l;
47 if (!str.ToULong(&l))
48 return false;
49 if (l == ULONG_MAX)
50 l = TS_NO_PARENT;
51 if (l > TS_NO_PARENT || (!pid_allowed && l == TS_NO_PARENT))
52 return false;
53 *pid = wxUint32(l);
54 return true;
55}
56
57static bool strToNum(wxString &str, wxUint32 *val)
58{
59 unsigned long l;
60 if (!str.ToULong(&l))
61 return false;
62 if (l > TS_NUM_MAX)
63 return false;
64 *val = wxUint32(l);
65 return true;
66}
67
68//------------------------------------------------------------------------------
69// thread execution starts here
70wxThread::ExitCode TSQueryThread::Entry()
71{
72 wxLogMessage(_T("TSQuery: thread started."));
73
74 // init libxml2 library
75 wxXml2::Init();
76
77 //check for bind
78 if(m_ServerAddress.Length() < 7 || m_ServerAddress == _T("0.0.0.0"))
79 m_ServerAddr.AnyAddress();
80 else
81 m_ServerAddr.Hostname(m_ServerAddress);
82
83 m_ServerAddr.Service(m_Port);
84 m_pSocket = new wxSocketServer(m_ServerAddr, wxSOCKET_REUSEADDR);
85
86 //Check socket
87 if(!m_pSocket->Ok())
88 {
89 if(m_pSocket->LastError() == wxSOCKET_INVPORT)
90 SetLastError(_T("Socket port in use"));
91 else
92 SetLastError(_T("Socket error"));
93 m_pSocket->Destroy();
94 m_pSocket = NULL;
95 return wxThread::ExitCode(EXIT_FAILURE);
96 }
97
98 while(1)
99 {
100 if (!Accept())
101 wxLogError(_T("TSQuery: %s"), m_LastError.c_str());
102 if (m_pSocket == NULL)
103 break;
104 }
105
106 return wxThread::ExitCode(EXIT_SUCCESS);
107}
108
109//------------------------------------------------------------------------------
110// and stops here
111void TSQueryThread::OnExit()
112{
113 wxLogDebug(_T("TSQuery: thread terminated."));
114
115 // cleanup libxml2 statics
116 wxXml2::Cleanup();
117
118 if(m_pSocket != NULL)
119 {
120 m_pSocket->Destroy();
121 m_pSocket = NULL;
122 }
123}
124
125//------------------------------------------------------------------------------
126// Default CTor, Initializes the object.
127TSQueryThread::TSQueryThread(TSClient *client) : wxThread(wxTHREAD_JOINABLE)
128{
129 Create();
130 //create all objects
131 //m_pSocket = new wxSocketServer(m_ServerAddr, wxSOCKET_REUSEADDR);
132 m_pClient = client;
133 m_Password = _T("");
134}
135
136//------------------------------------------------------------------------------
137// Default DTor.
138TSQueryThread::~TSQueryThread()
139{
140 //use OnExit()
141}
142
143//------------------------------------------------------------------------------
144// Listen
145bool TSQueryThread::Accept()
146{
147 //Wait until someone connect (NOTE: wxWidgets has an internal select timeout (~10 mins))
148 wxSocketBase *sock = m_pSocket->Accept();
149
150 // wxSocketBase doesn't set Error() to true after socket timeout, so we check against null
151 if(m_pSocket->LastError() == wxSOCKET_TIMEDOUT && sock == NULL)
152 return true;
153
154 // real check against null
155 if(sock == NULL)
156 {
157 SetLastError(_T("Socket, something really bad happend"));
158 m_pSocket->Destroy();
159 m_pSocket = NULL;
160 return false;
161 }
162
163 //Check if IP is allowed
164 wxIPV4address peeraddr;
165 sock->GetPeer(peeraddr);
166
167 wxLogMessage(_T("TSQuery: incoming request from %s"), peeraddr.IPAddress().c_str());
168
169 if(!IsIPAllowed(peeraddr.IPAddress()))
170 {
171 wxLogError(_T("TSQuery: %s"),GetLastError().c_str());
172 sock->Destroy();
173 return false;
174 }
175
176 //now receive
177 wxMemoryBufferEx buf(1024);
178 sock->Read(buf.GetData(), 1024);
179 buf.SetDataLen(sock->LastCount());
180 wxMemoryInputStream in(buf.GetData(), buf.GetDataLen());
181
182 wxStringOutputStream strm;
183 buf.HexDump(strm);
184 wxLogDebug(_T("TSQuery: command received:\n%s"), strm.GetString().c_str());
185
186 //Check socket
187 if(sock->LastCount() == 0)
188 {
189 SetLastError(_T("Socket, no data available"));
190 sock->Destroy();
191 return false;
192 }
193
194 //Check XML format
195 wxString err;
196 if (!m_pXml.Load(in, &err))
197 {
198 wxLogError(_T("XML format error: %s"), err.c_str());
199 return false;
200 }
201
202 //check node format
203 if(!IsValidFormat())
204 {
205 SendError(_T("General"), GetLastError(), sock);
206 sock->Destroy();
207 return false;
208 }
209
210 //check password
211 wxXml2Node pNode = m_pXml.GetRoot().Get(_T("Password")).GetFirstChild();
212 if(pNode.GetContent() != m_Password)
213 {
214 pNode = m_pXml.GetRoot().Get(_T("Command")).GetFirstChild();
215 SetLastError(_T("Invalid password"));
216 SendError(pNode.GetContent(), GetLastError(), sock);
217 sock->Destroy();
218 return false;
219 }
220
221 //check if TSClient is connected
222 if(!m_pClient->IsConnected())
223 {
224 pNode = m_pXml.GetRoot().Get(_T("Command")).GetFirstChild();
225 SetLastError(_T("No connection to TSServer"));
226 SendError(pNode.GetContent(), GetLastError(), sock);
227 sock->Destroy();
228 return false;
229 }
230
231 //ok now process the command
232 if(!ProcessCommand(sock))
233 {
234 sock->Destroy();
235 return false;
236 }
237
238 sock->Destroy();
239 wxLogMessage(_T("TSQuery: request successfully processed."));
240 return true;
241}
242
243//------------------------------------------------------------------------------
244// IsIPAllowed
245bool TSQueryThread::IsIPAllowed(wxString const &str)
246{
247 wxStringTokenizer tkz(m_AllowedAddresses, _T(","));
248 bool found = false;
249 while(tkz.HasMoreTokens())
250 {
251 wxString token = tkz.GetNextToken();
252 wxIPV4address tmpaddr;
253 if(!tmpaddr.Hostname(token))
254 {
255 SetLastError(wxString::Format(_T("'%s' this is no valid IP"),token.c_str()));
256 return false;
257 }
258 unsigned ip1[4], ip2[4];
259 if(tmpaddr.IPAddress() == str)
260 {
261 found = true;
262 break;
263 }
264 //dirty C
265 else if(wxSscanf(tmpaddr.IPAddress().c_str(), _T("%u.%u.%u.%u"), &ip1[0], &ip1[1], &ip1[2], &ip1[3]) == 4 &&
266 wxSscanf(str.c_str(), _T("%u.%u.%u.%u"), &ip2[0], &ip2[1], &ip2[2], &ip2[3]) == 4)
267 {
268 if((ip1[0] == 0 && ip1[1] == 0 && ip1[2] == 0 && ip1[3] == 0) || //0.0.0.0
269 (ip1[0] == ip2[0] && ip1[1] == 0 && ip1[2] == 0 && ip1[3] == 0) || //x.0.0.0
270 (ip1[0] == ip2[0] && ip1[1] == ip2[1] && ip1[2] == 0 && ip1[3] == 0) || //x.x.0.0
271 (ip1[0] == ip2[0] && ip1[1] == ip2[1] && ip1[2] == ip2[2] && ip1[3] == 0)) //x.x.x.0
272 {
273 found = true;
274 break;
275 }
276 }
277 }
278 if (!found)
279 {
280 SetLastError(_T("IP is not allowed"));
281 return false;
282 }
283 return true;
284}
285
286//------------------------------------------------------------------------------
287// IsValidFormat
288bool TSQueryThread::IsValidFormat()
289{
290 //check node
291 wxXml2Node pNodeRoot = m_pXml.GetRoot();
292 if(pNodeRoot.GetName() != _T("TSClient"))
293 {
294 SetLastError(_T("No 'TSClient' node found"));
295 return false;
296 }
297
298 //check node
299 wxXml2Node pNode = pNodeRoot.Get(_T("Password"));
300 if(pNode == wxXml2EmptyNode)
301 {
302 SetLastError(_T("No 'Password' node found"));
303 return false;
304 }
305
306 pNode = pNodeRoot.Get(_T("Command"));
307 if(pNode == wxXml2EmptyNode)
308 {
309 SetLastError(_T("No 'Command' node found"));
310 return false;
311 }
312
313 return true;
314}
315
316
317//------------------------------------------------------------------------------
318// ProcessCommand.
319bool TSQueryThread::ProcessCommand(wxSocketBase *sock)
320{
321 wxXml2Node pNodeRoot = m_pXml.GetRoot();
322 //check node
323 wxXml2Node pNode = pNodeRoot.Get(_T("Command"));
324 if(pNode == wxXml2EmptyNode)
325 {
326 SetLastError(_T("No 'Command' node found"));
327 SendError(_T("General"), GetLastError(), sock);
328 return false;
329 }
330
331 wxString cmd = pNode.GetFirstChild().GetContent();
332 wxLogMessage(_T("TSQuery: command '%s' received"), cmd.c_str());
333
334 pNode = pNodeRoot.Get(_T("Text"));
335 if(pNode != wxXml2EmptyNode)
336 wxLogMessage(_T("TSQuery: Text: '%s'"), pNode.GetFirstChild().GetContent().c_str());
337
338 if(cmd == _T("GetStatus"))
339 return CmdGetStatus(sock);
340 else if(cmd == _T("GetChannels"))
341 return CmdGetChannels(sock);
342 else if(cmd == _T("GetUsers"))
343 return CmdGetUsers(sock);
344 else if(cmd == _T("CreateChannel"))
345 return CmdCreateChannel(sock);
346 else if(cmd == _T("DeleteChannel"))
347 return CmdDeleteChannel(sock);
348 else if(cmd == _T("ModifyChannel"))
349 return CmdModifyChannel(sock);
350 else if(cmd == _T("MoveUser"))
351 return CmdMoveUser(sock);
352 else if(cmd == _T("KickUser"))
353 return CmdKickUser(sock);
354 else if(cmd == _T("Kill"))
355 return CmdKill(sock);
356
357 SetLastError(_T("Unknown command"));
358 SendError(cmd, GetLastError(), sock);
359 return false;
360}
361
362//------------------------------------------------------------------------------
363// SendError.
364bool TSQueryThread::SendError(wxString const &cmd, wxString const &str, wxSocketBase *sock)
365{
366 wxSocketOutputStream so(*sock);
367 wxBufferedOutputStream out(so);
368
369 m_pXml.Create(_T("1.0"));
370 wxXml2Node pNodeRoot;
371 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
372
373 wxXml2Node pNode;
374 pNode = pNodeRoot.AddTextChild(_T("Command"), cmd);
375 pNode.AddProperty(_T("State"), _T("Error"));
376
377 pNode = pNodeRoot.AddTextChild(_T("ErrorText"), str);
378
379 if(!SendDOM(sock))
380 return false;
381 return true;
382}
383
384//------------------------------------------------------------------------------
385// Dumps object.
386void TSQueryThread::Dump(wxOutputStream &ostrm) const
387{
388 wxTextOutputStream out(ostrm);
389 out << wxString(_T("-"), 60) << endl;
390 out << _T("Object: TSQueryThread (") << wxString::Format(_T("0x%X"), this) << _T(")") << endl;
391}
392
393//------------------------------------------------------------------------------
394bool TSQueryThread::SendDOM(wxSocketBase *sock)
395{
396 wxSocketOutputStream so(*sock);
397 wxBufferedOutputStream out(so);
398 if(!m_pXml.Save(out, _T("utf-8"), wxXML2DOC_USE_NATIVE_NEWLINES | wxXML2DOC_USE_INDENTATION, 2))
399 {
400 SetLastError(_T("DOM serialization"));
401 return false;
402 }
403 out.Sync();
404 return true;
405}
406
407//------------------------------------------------------------------------------
408wxString TSQueryThread::GetNodeValue(wxXml2Node &pElemRoot, wxString const &str)
409{
410 wxXml2Node pElem = pElemRoot.Get(str);
411 if(pElem == wxXml2EmptyNode)
412 return _T("");
413 else
414 return pElem.GetFirstChild().GetContent();
415}
416
417//------------------------------------------------------------------------------
418bool TSQueryThread::CmdGetStatus(wxSocketBase *sock)
419{
420 wxString str;
421 str = wxString::Format(_T("%s:%d"), m_pClient->GetServer()->GetServerAddress().c_str(),
422 m_pClient->GetServer()->GetPort());
423
424 if(!m_pClient->IsConnected())
425 {
426 wxLogMessage(_T("TSQuery: TSServer %s is not connected"), str.c_str());
427 SetLastError(_T("No connection to TSServer"));
428 SendError(_T("GetStatus"), GetLastError(), sock);
429 return false;
430 }
431
432 m_pXml.Create(_T("1.0"));
433 wxXml2Node pNodeRoot;
434 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
435
436 wxXml2Node pNode;
437 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("GetStatus"));
438 pNode.AddProperty(_T("State"), _T("Ok"));
439
440 pNode = pNodeRoot.AddTextChild(_T("TSServer"), str);
441
442 if(!SendDOM(sock))
443 return false;
444 return true;
445}
446
447//------------------------------------------------------------------------------
448bool TSQueryThread::CmdGetChannels(wxSocketBase *sock)
449{
450 wxXml2Node pNodeRoot = m_pXml.GetRoot();
451 TSpChannelArray chs;
452
453 wxXml2Node pNode = pNodeRoot.Get(_T("ChannelName"));
454 if(pNode != wxXml2EmptyNode)
455 {
456 wxString str = pNode.GetFirstChild().GetContent();
457 m_pClient->FindChannelsByName(str, &chs);
458
459 /* remove channels not matching ParentId */
460 str = pNode.GetPropVal(_T("ParentId"), wxEmptyString);
461 wxUint32 pid;
462 if (!str.empty() && strToChannelId(str, &pid))
463 {
464 for(size_t i = 0; i < chs.Count(); i++)
465 {
466 if (chs[i]->GetParent() != pid)
467 chs.RemoveAt(i);
468 }
469 }
470
471 /* add subchannels */
472 if(pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes"))
473 {
474 for(size_t i = 0; i < chs.Count(); i++)
475 m_pClient->FindChannelsByParent(chs[i]->GetId(), &chs);
476 }
477 }
478
479 pNode = pNodeRoot.Get(_T("ChannelId"));
480 if(pNode != wxXml2EmptyNode)
481 {
482 wxString str = pNode.GetFirstChild().GetContent();
483 wxUint32 chlid;
484 if (strToChannelId(str, &chlid, false))
485 {
486 TSChannel *c = m_pClient->FindChannel(chlid);
487 if(c != NULL)
488 chs.Add(c);
489
490 /* remove channels not matching ParentId */
491 wxUint32 pid;
492 str = pNode.GetPropVal(_T("ParentId"), wxEmptyString);
493 if (!str.empty() && strToChannelId(str, &pid))
494 {
495 for(size_t i = 0; i < chs.Count(); i++)
496 {
497 if (chs[i]->GetParent() != pid)
498 chs.RemoveAt(i);
499 }
500 }
501
502 /* add subchannels */
503 if(pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes"))
504 {
505 for(size_t i = 0; i < chs.Count(); i++)
506 m_pClient->FindChannelsByParent(chs[i]->GetId(), &chs);
507 }
508 }
509 }
510
511 pNode = pNode.Get(_T("ChannelParentId"));
512 if(pNode != wxXml2EmptyNode)
513 {
514 wxString str = pNode.GetFirstChild().GetContent();
515 wxUint32 pid;
516 if (strToChannelId(str, &pid))
517 m_pClient->FindChannelsByParent(pid, &chs);
518 }
519
520 m_pXml.Create(_T("1.0"));
521 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
522 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("GetChannels"));
523 pNode.AddProperty(_T("State"), _T("Ok"));
524
525 wxLogMessage(_T("TSQuery: sending requested channels."));
526
527 for(size_t i = 0; i < chs.Count(); i++)
528 {
529 wxXml2Node pChannelNode;
530 pChannelNode = pNodeRoot.AddContainerChild(_T("Channel"));
531 pChannelNode.AddProperty(_T("Id"), wxString::Format(_T("%d"), chs[i]->GetId()));
532 pChannelNode.AddProperty(_T("ParentId"), wxString::Format(_T("%d"), chs[i]->GetParent()));
533
534 pChannelNode.AddTextChild(_T("ChannelName"), chs[i]->GetName());
535 pChannelNode.AddTextChild(_T("ChannelTopic"), chs[i]->GetTopic());
536 pChannelNode.AddTextChild(_T("ChannelSlots"), wxString::Format(_T("%d"), chs[i]->GetMaxUsers()));
537 pChannelNode.AddTextChild(_T("ChannelPassword"), chs[i]->GetPassword());
538 pChannelNode.AddTextChild(_T("ChannelCodec"), wxString::Format(_T("%d"), chs[i]->GetCodec()));
539 const wxCharBuffer buf = chs[i]->GetDescription().mb_str(wxConvUTF8);
540 pChannelNode.AddTextChild(_T("ChannelDescription"), Base64Encode(buf, strlen(buf)));
541 pChannelNode.AddTextChild(_T("ChannelFlags"), chs[i]->GetFlagsString());
542
543 wxLogVerbose(_T("TSQuery: Channel '%s' transmitted."), chs[i]->GetName().c_str());
544 }
545
546 if(!SendDOM(sock))
547 return false;
548 return true;
549}
550
551//------------------------------------------------------------------------------
552bool TSQueryThread::CmdGetUsers(wxSocketBase *sock)
553{
554 wxXml2Node pNodeRoot = m_pXml.GetRoot();
555 TSpPlayerArray pls;
556 wxString str;
557
558 wxXml2Node pNode;
559 pNode = pNodeRoot.Get(_T("UserName"));
560 if(pNode != wxXml2EmptyNode)
561 {
562 str = pNode.GetFirstChild().GetContent();
563 m_pClient->FindPlayersByName(str, &pls);
564 }
565
566 pNode = pNodeRoot.Get(_T("UserId"));
567 if(pNode != wxXml2EmptyNode)
568 {
569 str = pNode.GetFirstChild().GetContent();
570 wxUint32 plyid;
571 if (strToNum(str, &plyid))
572 pls.Add(m_pClient->FindPlayer(plyid));
573 }
574
575 pNode = pNodeRoot.Get(_T("ChannelName"));
576 if(pNode != wxXml2EmptyNode)
577 {
578 str = pNode.GetFirstChild().GetContent();
579 TSpChannelArray chs;
580 m_pClient->FindChannelsByName(str, &chs);
581
582 /* remove channels not matching ParentId */
583 wxUint32 pid;
584 str = pNode.GetPropVal(_T("ParentId"), wxEmptyString);
585 if (!str.empty() && strToChannelId(str, &pid))
586 {
587 for(size_t i = 0; i < chs.Count(); i++)
588 {
589 if (chs[i]->GetParent() != pid)
590 chs.RemoveAt(i);
591 }
592 }
593
594 /* find users */
595 for(size_t i = 0; i < chs.Count(); i++)
596 {
597 m_pClient->FindPlayersByChannel(chs[i], &pls);
598
599 /* add subchannels and their users */
600 if (pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes"))
601 {
602 TSpChannelArray chs2;
603 m_pClient->FindChannelsByParent(chs[i]->GetId(), &chs2);
604 for(size_t j = 0; j < chs2.Count(); j++)
605 m_pClient->FindPlayersByChannel(chs2[j], &pls);
606 }
607 }
608 }
609
610 pNode = pNodeRoot.Get(_T("ChannelId"));
611 if(pNode != wxXml2EmptyNode)
612 {
613 str = pNode.GetFirstChild().GetContent();
614 TSChannel *cl = NULL;
615 wxUint32 chlid;
616 if (strToChannelId(str, &chlid, false))
617 cl = m_pClient->FindChannel(chlid);
618 if (cl == NULL)
619 {
620 SetLastError(_T("Error while searching for channel."));
621 SendError(_T("GetUsers"), GetLastError(), sock);
622 return false;
623 }
624
625 m_pClient->FindPlayersByChannel(cl, &pls);
626
627 if (pNode.GetPropVal(_T("Subchannels"), _T("No")) == _T("Yes"))
628 {
629 TSpChannelArray chs;
630 m_pClient->FindChannelsByParent(cl->GetId(), &chs);
631 for(size_t i = 0; i < chs.Count(); i++)
632 m_pClient->FindPlayersByChannel(chs[i], &pls);
633 }
634 }
635
636 m_pXml.Create(_T("1.0"));
637 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
638 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("GetUsers"));
639 pNode.AddProperty(_T("State"), _T("Ok"));
640
641 wxLogMessage(_T("TSQuery: sending requested users."));
642
643 for(size_t i = 0; i < pls.Count(); i++)
644 {
645 wxXml2Node pUserNode;
646 pUserNode = pNodeRoot.AddContainerChild(_T("User"));
647 pUserNode.AddProperty(_T("Id"), wxString::Format(_T("%d"), pls[i]->GetId()));
648
649 pUserNode.AddTextChild(_T("UserName"), pls[i]->GetNickname().c_str());
650 pUserNode.AddTextChild(_T("UserChannelId"), wxString::Format(_T("%d"), pls[i]->GetChannelId()).c_str());
651 pUserNode.AddTextChild(_T("UserFlags"), wxString::Format(_T("%d"), pls[i]->GetFlags()).c_str());
652 pUserNode.AddTextChild(_T("UserPrivileges"), wxString::Format(_T("%d"), pls[i]->GetPrivileges()).c_str());
653 pUserNode.AddTextChild(_T("UserChannelPrivileges"), wxString::Format(_T("%d"), pls[i]->GetChannelPrivileges()).c_str());
654
655 wxLogVerbose(_T("TSQuery: User '%s' transmitted."), pls[i]->GetNickname().c_str());
656 }
657
658 if(!SendDOM(sock))
659 return false;
660
661 return true;
662}
663
664//------------------------------------------------------------------------------
665bool TSQueryThread::CmdCreateChannel(wxSocketBase *sock)
666{
667 wxXml2Node pNodeRoot = m_pXml.GetRoot();
668 TSChannel cl;
669 wxString str;
670
671 wxXml2Node pNode;
672 pNode = pNodeRoot.Get(_T("Channel"));
673 if(pNode == wxXml2EmptyNode)
674 {
675 SetLastError(_T("No channel node"));
676 SendError(_T("CreateChannel"), GetLastError(), sock);
677 return false;
678 }
679
680 wxUint32 chlid;
681 str = pNode.GetPropVal(_T("ParentId"), _T("-1"));
682 if (!strToChannelId(str, &chlid))
683 {
684 SetLastError(_T("Invalid parent id"));
685 SendError(_T("CreateChannel"), GetLastError(), sock);
686 return false;
687 }
688
689 cl.SetParent(chlid);
690 cl.SetName(GetNodeValue(pNode, _T("ChannelName")));
691 cl.SetTopic(GetNodeValue(pNode, _T("ChannelTopic")));
692 cl.SetPassword(GetNodeValue(pNode, _T("ChannelPassword")));
693
694 wxUint32 num;
695 str = GetNodeValue(pNode, _T("ChannelSlots"));
696 if (!strToNum(str, &num))
697 {
698 SetLastError(_T("Invalid channel slots value"));
699 SendError(_T("CreateChannel"), GetLastError(), sock);
700 return false;
701 }
702 cl.SetMaxUsers(num);
703
704 str = GetNodeValue(pNode, _T("ChannelCodec"));
705 if (!strToNum(str, &num))
706 {
707 SetLastError(_T("Invalid channel codec value"));
708 SendError(_T("CreateChannel"), GetLastError(), sock);
709 return false;
710 }
711 cl.SetCodec(num);
712
713 wxCSConv conv_iso(_T("iso-8859-1"));
714 wxString base64_encoded = GetNodeValue(pNode, _T("ChannelDescription"));
715 cl.SetDescription(wxString(Base64Decode(base64_encoded).mb_str(conv_iso), wxConvUTF8));
716 cl.SetFlags(GetNodeValue(pNode, _T("ChannelFlags")));
717
718 m_pClient->CreateChannel(&cl);
719
720 // dirty wait for channel id
721 wxUint32 channelid = 0;
722 for (wxUint32 i = 0; i <= 2; i++)
723 {
724 TSpChannelArray chs;
725 if (cl.GetParent() == TS_NO_PARENT)
726 {
727 // we wait for a main channel
728 m_pClient->FindChannelsByName(_T("^") + cl.GetName() + _T("$"), &chs);
729 for(size_t i = 0; i < chs.Count(); i++)
730 {
731 if (chs[i]->GetParent() == TS_NO_PARENT)
732 {
733 channelid = chs[i]->GetId();
734 break;
735 }
736 }
737 }
738 else
739 {
740 // we wait for a subchannel
741 m_pClient->FindChannelsByParent(cl.GetParent(), &chs);
742 for(size_t i = 0; i < chs.Count(); i++)
743 {
744 if (chs[i]->GetName() == cl.GetName())
745 {
746 channelid = chs[i]->GetId();
747 break;
748 }
749 }
750 }
751
752 if (channelid > 0)
753 break;
754 Sleep(500);
755 }
756
757 if (channelid <= 0)
758 {
759 SetLastError(_T("Error while creating channel."));
760 SendError(_T("CreateChannel"), GetLastError(), sock);
761 return false;
762 }
763
764 m_pXml.Create(_T("1.0"));
765 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
766 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("CreateChannel"));
767 pNode.AddProperty(_T("State"), _T("Ok"));
768
769 pNodeRoot.AddTextChild(_T("ChannelId"), wxString::Format(_T("%d"), channelid));
770
771 wxLogMessage(_T("TSQuery: Channel '%s' created."), cl.GetName().c_str());
772
773 if(!SendDOM(sock))
774 return false;
775
776 return true;
777}
778
779//------------------------------------------------------------------------------
780bool TSQueryThread::CmdDeleteChannel(wxSocketBase *sock)
781{
782 wxXml2Node pNodeRoot = m_pXml.GetRoot();
783 TSChannel *cl = NULL;
784 wxString str;
785
786 wxXml2Node pNode;
787 pNode = pNodeRoot.Get(_T("ChannelId"));
788 if(pNode != wxXml2EmptyNode)
789 {
790 str = pNode.GetFirstChild().GetContent();
791 wxUint32 chlid;
792 if (strToChannelId(str, &chlid, false))
793 cl = m_pClient->FindChannel(chlid);
794 }
795
796 if(cl == NULL)
797 {
798 SetLastError(_T("Channel not found."));
799 SendError(_T("DeleteChannel"), GetLastError(), sock);
800 return false;
801 }
802
803 TSChannel *defchl = m_pClient->FindDefaultChannel();
804
805 // process subchannels
806 TSpChannelArray chs;
807 m_pClient->FindChannelsByParent(cl->GetId(), &chs);
808 for(size_t i = 0; i < chs.Count(); i++)
809 {
810 TSpPlayerArray ply;
811 m_pClient->FindPlayersByChannel(chs[i], &ply);
812
813 for(size_t i=0;i<ply.GetCount();i++)
814 {
815 TSPlayer pl;
816 pl.SetId(ply.Item(i)->GetId());
817 pl.SetChannelId(defchl->GetId());
818 m_pClient->MovePlayer(&pl);
819 }
820 }
821
822 // process main channel
823 TSpPlayerArray ply;
824 m_pClient->FindPlayersByChannel(cl,&ply);
825
826 for(size_t i=0;i<ply.GetCount();i++)
827 {
828 TSPlayer pl;
829 pl.SetId(ply.Item(i)->GetId());
830 pl.SetChannelId(defchl->GetId());
831 m_pClient->MovePlayer(&pl);
832 }
833
834 wxLogMessage(_T("TSQuery: Channel '%s' deleted."),cl->GetName().c_str());
835
836 m_pClient->DeleteChannel(cl);
837
838 m_pXml.Create(_T("1.0"));
839 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
840 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("DeleteChannel"));
841 pNode.AddProperty(_T("State"), _T("Ok"));
842
843 if(!SendDOM(sock))
844 return false;
845
846 return true;
847}
848
849//------------------------------------------------------------------------------
850bool TSQueryThread::CmdModifyChannel(wxSocketBase *sock)
851{
852 wxXml2Node pNodeRoot = m_pXml.GetRoot();
853 TSChannel cl;
854 wxString str;
855
856 wxXml2Node pNode;
857 pNode = pNodeRoot.Get(_T("Channel"));
858 if(pNode == wxXml2EmptyNode)
859 {
860 SetLastError(_T("No channel node"));
861 SendError(_T("CreateChannel"), GetLastError(), sock);
862 return false;
863 }
864
865 wxUint32 chlid;
866 str = pNode.GetPropVal(_T("Id"), _T(""));
867 if (!strToChannelId(str, &chlid, false))
868 {
869 SetLastError(_T("No id attribute found"));
870 SendError(_T("CreateChannel"), GetLastError(), sock);
871 return false;
872 }
873
874 cl.SetId(chlid);
875 cl.SetName(GetNodeValue(pNode, _T("ChannelName")));
876 cl.SetTopic(GetNodeValue(pNode, _T("ChannelTopic")));
877 cl.SetPassword(GetNodeValue(pNode, _T("ChannelPassword")));
878
879 wxUint32 num;
880 str = GetNodeValue(pNode, _T("ChannelSlots"));
881 if (!strToNum(str, &num))
882 {
883 SetLastError(_T("Invalid channel slots value"));
884 SendError(_T("CreateChannel"), GetLastError(), sock);
885 return false;
886 }
887 cl.SetMaxUsers(num);
888
889 str = GetNodeValue(pNode, _T("ChannelCodec"));
890 if (!strToNum(str, &num))
891 {
892 SetLastError(_T("Invalid channel codec value"));
893 SendError(_T("CreateChannel"), GetLastError(), sock);
894 return false;
895 }
896 cl.SetCodec(num);
897
898 wxCSConv conv_iso(_T("iso-8859-1"));
899 wxString base64_encoded = GetNodeValue(pNode, _T("ChannelDescription"));
900 cl.SetDescription(wxString(Base64Decode(base64_encoded).mb_str(conv_iso), wxConvUTF8));
901 cl.SetFlags(GetNodeValue(pNode, _T("ChannelFlags")));
902
903 m_pClient->ModifyChannel(&cl);
904
905 m_pXml.Create(_T("1.0"));
906 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
907 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("ModifyChannel"));
908 pNode.AddProperty(_T("State"), _T("Ok"));
909
910 wxLogMessage(_T("TSQuery: Channel '%s' modified."), cl.GetName().c_str());
911
912 if(!SendDOM(sock))
913 return false;
914
915 return true;
916}
917
918//------------------------------------------------------------------------------
919bool TSQueryThread::CmdMoveUser(wxSocketBase *sock)
920{
921 wxXml2Node pNodeRoot = m_pXml.GetRoot();
922 TSPlayer *pl = NULL;
923 TSChannel *cl = NULL;
924 wxString str;
925
926 wxXml2Node pNode;
927 pNode = pNodeRoot.Get(_T("UserId"));
928 if(pNode != wxXml2EmptyNode)
929 {
930 str = pNode.GetFirstChild().GetContent();
931 wxUint32 plyid;
932 if (strToNum(str, &plyid))
933 pl = m_pClient->FindPlayer(plyid);
934 }
935
936 if(pl == NULL)
937 {
938 SetLastError(_T("User not found."));
939 SendError(_T("MoveUser"), GetLastError(), sock);
940 return false;
941 }
942
943 pNode = pNodeRoot.Get(_T("ChannelId"));
944 if(pNode != wxXml2EmptyNode)
945 {
946 str = pNode.GetFirstChild().GetContent();
947 wxUint32 chlid;
948 if (strToChannelId(str, &chlid, false))
949 cl = m_pClient->FindChannel(chlid);
950 }
951
952 if(cl == NULL)
953 {
954 SetLastError(_T("Channel not found."));
955 SendError(_T("MoveUser"), GetLastError(), sock);
956 return false;
957 }
958
959 pl->SetChannelId(cl->GetId());
960 m_pClient->MovePlayer(pl);
961
962 m_pXml.Create(_T("1.0"));
963 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
964 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("MoveUser"));
965 pNode.AddProperty(_T("State"), _T("Ok"));
966
967 wxLogMessage(_T("TSQuery: User '%s' moved to '%s'."), pl->GetNickname().c_str(),
968 m_pClient->FindChannel(pl->GetChannelId())->GetName().c_str());
969
970 if(!SendDOM(sock))
971 return false;
972
973 return true;
974}
975
976//------------------------------------------------------------------------------
977bool TSQueryThread::CmdKickUser(wxSocketBase *sock)
978{
979 wxXml2Node pNodeRoot = m_pXml.GetRoot();
980 TSPlayer *pl = NULL;
981 wxString str;
982
983 wxXml2Node pNode;
984 pNode = pNodeRoot.Get(_T("UserId"));
985 if(pNode != wxXml2EmptyNode)
986 {
987 str = pNode.GetFirstChild().GetContent();
988 wxUint32 plyid;
989 if (strToNum(str, &plyid))
990 pl = m_pClient->FindPlayer(plyid);
991 }
992
993 if(pl == NULL)
994 {
995 SetLastError(_T("User not found."));
996 SendError(_T("KickUser"), GetLastError(), sock);
997 return false;
998 }
999
1000 str = _T("");
1001 pNode = pNodeRoot.Get(_T("Reason"));
1002 if(pNode != wxXml2EmptyNode)
1003 str = pNode.GetFirstChild().GetContent();
1004
1005 wxLogMessage(_T("TSQuery: User '%s' kicked."), pl->GetNickname().c_str());
1006
1007 m_pClient->KickPlayer(pl, str);
1008
1009 m_pXml.Create(_T("1.0"));
1010 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
1011 pNode = pNodeRoot.AddTextChild(_T("Command"), _T("KickUser"));
1012 pNode.AddProperty(_T("State"), _T("Ok"));
1013
1014 if(!SendDOM(sock))
1015 return false;
1016
1017 return true;
1018}
1019
1020//------------------------------------------------------------------------------
1021bool TSQueryThread::CmdKill(wxSocketBase *sock)
1022{
1023 if(m_pClient->IsConnected())
1024 m_pClient->Disconnect(false);
1025
1026 wxXml2Node pNodeRoot;
1027 m_pXml.Create(_T("1.0"));
1028 pNodeRoot.CreateRoot(m_pXml, _T("TSClient"));
1029 wxXml2Node pNode = pNodeRoot.AddTextChild(_T("Command"), _T("Kill"));
1030 pNode.AddProperty(_T("State"), _T("Ok"));
1031
1032 if(!SendDOM(sock))
1033 return false;
1034
1035 return true;
1036}
1037
1038//------------------------------------------------------------------------------
1039// Sets the password for incomming connections.
1040
1041bool TSQueryThread::SetPassword(wxString const &str)
1042{
1043 if(str.Length() == 0)
1044 {
1045 SetLastError(_T("Empty string"));
1046 return false;
1047 }
1048 m_Password = str;
1049 return true;
1050}
1051
1052//------------------------------------------------------------------------------
1053// Sets the server address.
1054bool TSQueryThread::SetServerAddress(wxString const &str)
1055{
1056 if(str.Length() == 0)
1057 {
1058 SetLastError(_T("Empty string"));
1059 return false;
1060 }
1061 m_ServerAddress = str;
1062 return true;
1063}
1064
1065//------------------------------------------------------------------------------
1066// Sets the allowed address.
1067bool TSQueryThread::SetAllowedAddresses(wxString const &str)
1068{
1069 if(str.Length() == 0)
1070 {
1071 SetLastError(_T("Empty string"));
1072 return false;
1073 }
1074 m_AllowedAddresses = str;
1075 return true;
1076}
1077
1078//------------------------------------------------------------------------------
1079// Sets the connection port.
1080bool TSQueryThread::SetPort(wxUint16 const &port)
1081{
1082 if(port == 0)
1083 {
1084 SetLastError(_T("Empty port"));
1085 return false;
1086 }
1087 m_Port = port;
1088 return true;
1089}
1090
1091//------------------------------------------------------------------------------
1092// Start thread.
1093bool TSQueryThread::Start()
1094{
1095 Run();
1096 return true;
1097}
1098
1099//------------------------------------------------------------------------------
1100// Stop thread.
1101bool TSQueryThread::Stop()
1102{
1103 Kill();
1104 return true;
1105}