1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13 /* interface header */
14 #include "BZAdminClient.h"
15
16 /* system implementation headers */
17 #ifdef HAVE_CMATH
18 # include <cmath>
19 #else
20 # include <math.h>
21 #endif
22 #include <stdio.h>
23 #include <string.h>
24 #include <iostream>
25 #include <sstream>
26
27 /* common implementation headers */
28 #include "BZAdminUI.h"
29 #include "StateDatabase.h"
30 #include "TextUtils.h"
31 #include "version.h"
32 #include "Team.h"
33 #include "ServerList.h"
34 #include "ErrorHandler.h"
35 #include "cURLManager.h"
36 #include "TimeKeeper.h"
37
38 StartupInfo startupInfo;
39
BZAdminClient(BZAdminUI * bzInterface)40 BZAdminClient::BZAdminClient(BZAdminUI* bzInterface)
41 : myTeam(ObserverTeam), sLink(Address(startupInfo.serverName), startupInfo.serverPort), valid(false), ui(bzInterface)
42 {
43
44 if (sLink.getState() != ServerLink::Okay)
45 {
46 switch (sLink.getState())
47 {
48 case ServerLink::BadVersion:
49 {
50 std::cout << "Incompatible server version " << sLink.getVersion();
51 break;
52 }
53 case ServerLink::Refused:
54 {
55 std::string banMessage = "Server Refused connection due to ban: ";
56 banMessage += sLink.getRejectionMessage();
57 std::cout << banMessage;
58 break;
59 }
60 case ServerLink::Rejected:
61 std::cout << "Game is full or over. Try again later.";
62 break;
63 case ServerLink::SocketError:
64 std::cout << "Error connecting to server.";
65 break;
66 case ServerLink::CrippledVersion:
67 std::cout << "Cannot connect to full version server.";
68 break;
69 default:
70 std::cout << "Internal error connecting to server.";
71 break;
72 }
73 std::cout << std::endl;
74 return;
75 }
76 if ((startupInfo.token[0] == '\0') && (startupInfo.password[0] != '\0'))
77 {
78 // won't really output anything, just gets token
79 outputServerList();
80 }
81 sLink.sendEnter(TankPlayer, myTeam, startupInfo.callsign, "bzadmin", startupInfo.token);
82 if (sLink.getState() != ServerLink::Okay)
83 {
84 std::cerr << "Rejected." << std::endl;
85 return;
86 }
87
88 std::string reason;
89 uint16_t code, rejcode;
90 if (sLink.readEnter (reason, code, rejcode))
91 valid = true;
92 else
93 std::cerr << reason << std::endl;
94
95
96 // tell BZDB to shut up, we can't have debug data printed to stdout
97 BZDB.setDebug(false);
98
99 // set a default message mask
100 showMessageType(MsgAddPlayer);
101 showMessageType(MsgAdminInfo);
102 showMessageType(MsgKilled);
103 showMessageType(MsgMessage);
104 showMessageType(MsgNewRabbit);
105 showMessageType(MsgPause);
106 showMessageType(MsgRemovePlayer);
107 showMessageType(MsgSuperKill);
108
109 // initialise the colormap
110 colorMap[NoTeam] = Yellow;
111 colorMap[RogueTeam] = Yellow;
112 colorMap[RedTeam] = Red;
113 colorMap[GreenTeam] = Green;
114 colorMap[BlueTeam] = Blue;
115 colorMap[PurpleTeam] = Purple;
116 colorMap[ObserverTeam] = Cyan;
117
118 // initialise the msg type map
119 // FIXME MsgPlayerInfo
120 msgTypeMap["bzdb"] = MsgSetVar;
121 msgTypeMap["chat"] = MsgMessage;
122 msgTypeMap["admin"] = MsgAdminInfo;
123 msgTypeMap["join"] = MsgAddPlayer;
124 msgTypeMap["kill"] = MsgKilled;
125 msgTypeMap["leave"] = MsgRemovePlayer;
126 msgTypeMap["pause"] = MsgPause;
127 msgTypeMap["ping"] = MsgLagPing;
128 msgTypeMap["rabbit"] = MsgNewRabbit;
129 msgTypeMap["score"] = MsgScore;
130 msgTypeMap["spawn"] = MsgAlive;
131 msgTypeMap["time"] = MsgTimeUpdate;
132 msgTypeMap["over"] = MsgScoreOver;
133 }
134
135
getMyId()136 PlayerId BZAdminClient::getMyId()
137 {
138 return sLink.getId();
139 }
140
141
checkMessage()142 BZAdminClient::ServerCode BZAdminClient::checkMessage()
143 {
144 uint16_t code, len;
145 char inbuf[MaxPacketLen];
146 PlayerIdMap::iterator iter;
147
148 // read until we have a package, or until we have waited 100 ms
149 if (sLink.read(code, len, inbuf, 100) == 1)
150 {
151 lastMessage.first = "";
152 lastMessage.second = Default;
153 const void* vbuf = inbuf;
154 PlayerId p;
155 PlayerIdMap::const_iterator it;
156 std::string victimName, killerName;
157 Address a;
158
159 switch (code)
160 {
161
162 case MsgNewRabbit:
163 if (messageMask[MsgNewRabbit])
164 {
165 vbuf = nboUnpackUByte(vbuf, p);
166 if (p != NoPlayer)
167 lastMessage.first = std::string("*** '") + players[p].name +
168 "' is now the rabbit.";
169 }
170 break;
171
172 case MsgPause:
173 if (messageMask[MsgPause])
174 {
175 uint8_t paused;
176 vbuf = nboUnpackUByte(vbuf, p);
177 vbuf = nboUnpackUByte(vbuf, paused);
178 lastMessage.first = std::string("*** '") + players[p].name + "': " +
179 (paused ? "paused" : "resumed") + ".";
180 }
181 break;
182
183 case MsgAlive:
184 if (messageMask[MsgAlive])
185 {
186 vbuf = nboUnpackUByte(vbuf, p);
187 lastMessage.first = std::string("*** '") + players[p].name +
188 "' has respawned.";
189 }
190 break;
191
192 case MsgLagPing:
193 if (messageMask[MsgLagPing])
194 lastMessage.first = "*** Received lag ping from server.";
195 break;
196
197 case MsgSetVar:
198 // code stolen from playing.cxx
199 uint16_t numVars;
200 uint8_t nameLen, valueLen;
201
202 // Flawfinder: ignore
203 char name[MaxPacketLen];
204 // Flawfinder: ignore
205 char value[MaxPacketLen];
206 int i;
207
208 vbuf = nboUnpackUShort(vbuf, numVars);
209 for (i = 0; i < numVars; i++)
210 {
211 vbuf = nboUnpackUByte(vbuf, nameLen);
212 vbuf = nboUnpackString(vbuf, name, nameLen);
213 name[nameLen] = '\0';
214
215 vbuf = nboUnpackUByte(vbuf, valueLen);
216 vbuf = nboUnpackString(vbuf, value, valueLen);
217 value[valueLen] = '\0';
218
219 BZDB.set(name, value);
220 BZDB.setPersistent(name, false);
221 BZDB.setPermission(name, StateDatabase::Locked);
222 }
223 if (messageMask[MsgSetVar])
224 {
225 lastMessage.first = std::string("*** Received BZDB update, ") +
226 TextUtils::format("%d", numVars) + " variable" +
227 (numVars == 1 ? "" : "s") + " updated.";
228 }
229 break;
230
231 case MsgAddPlayer:
232 uint16_t team, type, wins, losses, tks;
233 // Flawfinder: ignore
234 char callsign[CallSignLen];
235 // Flawfinder: ignore
236 char motto[MottoLen];
237 vbuf = nboUnpackUByte(vbuf, p);
238 vbuf = nboUnpackUShort(vbuf, type);
239 vbuf = nboUnpackUShort(vbuf, team);
240 vbuf = nboUnpackUShort(vbuf, wins);
241 vbuf = nboUnpackUShort(vbuf, losses);
242 vbuf = nboUnpackUShort(vbuf, tks);
243 vbuf = nboUnpackString(vbuf, callsign, CallSignLen);
244 vbuf = nboUnpackString(vbuf, motto, MottoLen);
245 players[p].name = callsign;
246 players[p].team = TeamColor(team);
247 players[p].wins = wins;
248 players[p].losses = losses;
249 players[p].tks = tks;
250 players[p].isRegistered = false;
251 players[p].isVerified = false;
252 players[p].isAdmin = false;
253 if (ui != NULL)
254 ui->addedPlayer(p);
255 // If you are an admin, then MsgAdminInfo will output the message
256 if (messageMask[MsgAddPlayer] && !players[getMyId()].isAdmin)
257 {
258 Team temp;
259 std::string joinMsg = std::string("*** \'") + callsign + "\' joined the game as " +
260 temp.getName(players[p].team) + ".";
261 lastMessage.first = joinMsg;
262 }
263 break;
264
265 case MsgRemovePlayer:
266 vbuf = nboUnpackUByte(vbuf, p);
267 if (ui != NULL)
268 ui->removingPlayer(p);
269 if (messageMask[MsgRemovePlayer])
270 {
271 lastMessage.first = std::string("*** '") + players[p].name +
272 "' left the game.";
273 }
274 players.erase(p);
275 break;
276
277 case MsgPlayerInfo:
278 uint8_t numPlayers;
279 vbuf = nboUnpackUByte(vbuf, numPlayers);
280 for (i = 0; i < numPlayers; ++i)
281 {
282 vbuf = nboUnpackUByte(vbuf, p);
283 uint8_t info;
284 // parse player info bitfield
285 vbuf = nboUnpackUByte(vbuf, info);
286 players[p].isAdmin = ((info & IsAdmin) != 0);
287 players[p].isRegistered = ((info & IsRegistered) != 0);
288 players[p].isVerified = ((info & IsVerified) != 0);
289 }
290 break;
291
292 case MsgAdminInfo:
293 uint8_t numIPs;
294 uint8_t tmp;
295 vbuf = nboUnpackUByte(vbuf, numIPs);
296 if (numIPs > 1)
297 {
298 for (i = 0; i < numIPs; ++i)
299 {
300 vbuf = nboUnpackUByte(vbuf, tmp);
301 vbuf = nboUnpackUByte(vbuf, p);
302 vbuf = a.unpack(vbuf);
303 players[p].ip = a.getDotNotation();
304 if ((ui != NULL) && messageMask[MsgAdminInfo])
305 {
306 ui->outputMessage("*** IPINFO: " + players[p].name + " from " +
307 players[p].ip, Default);
308 }
309 }
310 }
311 //Alternative to the MsgAddPlayer message
312 else if (numIPs == 1)
313 {
314 vbuf = nboUnpackUByte(vbuf, tmp);
315 vbuf = nboUnpackUByte(vbuf, p);
316 vbuf = a.unpack(vbuf);
317 players[p].ip = a.getDotNotation();
318 Team temp;
319 if (messageMask[MsgAdminInfo])
320 {
321 std::string joinMsg = std::string("*** \'") + players[p].name + "\' joined the game as " +
322 temp.getName(players[p].team) + " from " + players[p].ip + ".";
323 lastMessage.first = joinMsg;
324 }
325 }
326 break;
327
328 case MsgScoreOver:
329 if (messageMask[MsgScoreOver])
330 {
331 PlayerId id;
332 uint16_t _team;
333 vbuf = nboUnpackUByte(vbuf, id);
334 vbuf = nboUnpackUShort(vbuf, _team);
335 it = players.find(id);
336 victimName = (it != players.end() ? it->second.name : "<unknown>");
337 if (_team != (uint16_t)NoTeam)
338 {
339 Team temp;
340 victimName = temp.getName((TeamColor)_team);
341 }
342 lastMessage.first = std::string("*** \'") + victimName + "\' won the game.";
343 }
344 break;
345
346 case MsgTimeUpdate:
347 if (messageMask[MsgTimeUpdate])
348 {
349 uint32_t timeLeft;
350 vbuf = nboUnpackUInt(vbuf, timeLeft);
351 if (timeLeft == 0)
352 lastMessage.first = "*** Time Expired.";
353 else if (timeLeft == ~0u)
354 lastMessage.first = "*** Paused.";
355 else
356 lastMessage.first = std::string("*** ") +
357 TextUtils::format("%u", timeLeft) + " seconds remaining.";
358 }
359 break;
360
361 case MsgKilled:
362 if (messageMask[MsgKilled])
363 {
364 PlayerId victim, killer;
365 FlagType* flagType;
366 int16_t shotId, reason;
367 vbuf = nboUnpackUByte(vbuf, victim);
368 vbuf = nboUnpackUByte(vbuf, killer);
369 vbuf = nboUnpackShort(vbuf, reason);
370 vbuf = nboUnpackShort(vbuf, shotId);
371 vbuf = FlagType::unpack(vbuf, flagType);
372 if (reason == PhysicsDriverDeath)
373 {
374 int32_t inPhyDrv;
375 vbuf = nboUnpackInt(vbuf, inPhyDrv);
376 }
377
378 // find the player names and build a kill message string
379 it = players.find(victim);
380 victimName = (it != players.end() ? it->second.name : "<unknown>");
381 it = players.find(killer);
382 killerName = (it != players.end() ? it->second.name : "<unknown>");
383 lastMessage.first = std::string("*** ") + "'" + victimName + "' ";
384 if (killer == victim)
385 lastMessage.first = lastMessage.first + "blew myself up.";
386 else
387 {
388 lastMessage.first = lastMessage.first + "destroyed by '" +
389 killerName + "'.";
390 }
391 }
392 break;
393
394 case MsgSuperKill:
395 return Superkilled;
396
397 case MsgScore:
398 uint8_t numScores;
399 vbuf = nboUnpackUByte(vbuf, numScores);
400 for (i = 0; i < numScores; i++)
401 {
402 uint16_t winners, loosers, teamkillers;
403 vbuf = nboUnpackUByte(vbuf, p);
404 vbuf = nboUnpackUShort(vbuf, winners);
405 vbuf = nboUnpackUShort(vbuf, loosers);
406 vbuf = nboUnpackUShort(vbuf, teamkillers);
407 if ((iter = players.find(p)) != players.end())
408 {
409 iter->second.wins = winners;
410 iter->second.losses = loosers;
411 iter->second.tks = teamkillers;
412 }
413 }
414 if (messageMask[MsgScore])
415 {
416 lastMessage.first =
417 std::string("*** Received score update, score for ")+
418 TextUtils::format("%d", numScores) + " player" +
419 (numScores == 1 ? "s" : "") + " updated.";
420 }
421 break;
422
423 case MsgMessage:
424
425 // unpack the message header
426 PlayerId src;
427 PlayerId dst;
428 uint8_t mtype;
429 PlayerId me = sLink.getId();
430 vbuf = nboUnpackUByte(vbuf, src);
431 vbuf = nboUnpackUByte(vbuf, dst);
432 vbuf = nboUnpackUByte(vbuf, mtype);
433
434 // Only bother processing the message if we know how to handle it
435 if (MessageType(mtype) != ChatMessage && MessageType(mtype) != ActionMessage)
436 break;
437
438 // format the message depending on src and dst
439 TeamColor dstTeam = (LastRealPlayer < dst && dst <= FirstTeam ?
440 TeamColor(FirstTeam - dst) : NoTeam);
441 if (messageMask[MsgMessage])
442 {
443 lastMessage.first = formatMessage((const char*)vbuf, MessageType(mtype),
444 src, dst, dstTeam, me);
445 PlayerIdMap::const_iterator iterator = players.find(src);
446 lastMessage.second = (iterator == players.end() ?
447 colorMap[NoTeam] :
448 colorMap[iterator->second.team]);
449 }
450 break;
451 }
452 if (ui != NULL)
453 ui->handleNewPacket(code);
454 return GotMessage;
455 }
456
457 if (sLink.getState() != ServerLink::Okay)
458 {
459 if (ui != NULL)
460 ui->outputMessage("--- ERROR: Communication error", Red);
461 return CommError;
462 }
463
464 return NoMessage;
465 }
466
467
getLastMessage() const468 std::pair<std::string, ColorCode> BZAdminClient::getLastMessage() const
469 {
470 return lastMessage;
471 }
472
473
getPlayers()474 PlayerIdMap& BZAdminClient::getPlayers()
475 {
476 return players;
477 }
478
479
isValid() const480 bool BZAdminClient::isValid() const
481 {
482 return valid;
483 }
484
outputServerList() const485 void BZAdminClient::outputServerList() const
486 {
487 if (ui)
488 ui->outputMessage(std::string("Server List:"), Yellow);
489 ServerList serverList;
490
491 serverList.startServerPings(&startupInfo);
492
493 // wait no more than 20 seconds for the list server
494 for (int i = 0; i < 20; i++)
495 {
496 if (!serverList.searchActive() && serverList.serverFound())
497 break;
498 if (ui)
499 {
500 if (!serverList.serverFound())
501 ui->outputMessage(std::string("...waiting on the list server..."), Yellow);
502 else
503 ui->outputMessage(TextUtils::format("...retrieving list of servers... (found %zu)", serverList.size()), Yellow);
504 }
505 serverList.checkEchos(&startupInfo);
506 cURLManager::perform();
507 TimeKeeper::sleep(1.0);
508 }
509 // what is your final answer?
510 serverList.checkEchos(&startupInfo);
511
512 if (ui)
513 {
514 std::vector<ServerItem> servers = serverList.getServers();
515 for (std::vector<ServerItem>::const_iterator server = servers.begin();
516 server != servers.end();
517 ++server)
518 ui->outputMessage(std::string(" ") + server->description, Yellow);
519 ui->outputMessage(std::string("End Server List."), Yellow);
520 }
521
522 return;
523 }
524
runLoop()525 void BZAdminClient::runLoop()
526 {
527 std::string cmd;
528 ServerCode what(NoMessage);
529 while (true)
530 {
531 what = checkMessage();
532 if (what == Superkilled || what == CommError)
533 break;
534 if (ui != NULL && ui->checkCommand(cmd))
535 {
536 if (cmd == "/quit")
537 break;
538 else if (cmd.substr(0, 6) == "/show ")
539 {
540 if (msgTypeMap.find(cmd.substr(6)) == msgTypeMap.end())
541 {
542 ui->outputMessage(std::string("--- ERROR: ") + cmd.substr(6) +
543 " is an unknown message type", Red);
544 }
545 else
546 {
547 showMessageType(cmd.substr(6));
548 ui->outputMessage(std::string("--- Will now show messages of the ")
549 + "type " + cmd.substr(6), Yellow);
550 }
551 }
552 else if (cmd.substr(0, 6) == "/hide ")
553 {
554 if (msgTypeMap.find(cmd.substr(6)) == msgTypeMap.end())
555 {
556 ui->outputMessage(std::string("--- ERROR: ") + cmd.substr(6) +
557 " is an unknown message type", Red);
558 }
559 else
560 {
561 ignoreMessageType(cmd.substr(6));
562 ui->outputMessage(std::string("--- Will now hide messages of the ")
563 + "type " + cmd.substr(6), Yellow);
564 }
565 }
566 else if (cmd == "/list")
567 outputServerList();
568 else if (cmd != "")
569 sendMessage(cmd, ui->getTarget());
570 }
571 }
572
573 // why did we leave the loop?
574 switch (what)
575 {
576 case Superkilled:
577 lastMessage.first = "--- ERROR: Server forced disconnect";
578 lastMessage.second = Red;
579 break;
580 case CommError:
581 lastMessage.first = "--- ERROR: Connection to server lost";
582 lastMessage.second = Red;
583 break;
584 default:
585 waitForServer();
586 }
587 }
588
589
sendMessage(const std::string & msg,PlayerId target)590 void BZAdminClient::sendMessage(const std::string& msg,
591 PlayerId target)
592 {
593 // local commands:
594 // /set lists all BZDB variables
595 if (msg == "/set")
596 {
597 if (ui != NULL)
598 BZDB.iterate(listSetVars, this);
599 return;
600 }
601
602 // Flawfinder: ignore
603 char buffer[MessageLen];
604 // Flawfinder: ignore
605 char buffer2[1 + MessageLen];
606 void* buf = buffer2;
607
608 buf = nboPackUByte(buf, target);
609 // Flawfinder: ignore
610 strncpy(buffer, msg.c_str(), MessageLen - 1);
611 buffer[MessageLen - 1] = '\0';
612 nboPackString(buffer2 + 1, buffer, MessageLen);
613 sLink.send(MsgMessage, sizeof(buffer2), buffer2);
614 }
615
616
formatMessage(const std::string & msg,const MessageType type,PlayerId src,PlayerId dst,TeamColor dstTeam,PlayerId me)617 std::string BZAdminClient::formatMessage(const std::string& msg,
618 const MessageType type, PlayerId src,
619 PlayerId dst, TeamColor dstTeam,
620 PlayerId me)
621 {
622 std::string formatted = " ";
623
624 // get sender and receiver
625 const std::string srcName = (src == ServerPlayer ? "SERVER" :
626 (players.count(src) ? players[src].name :
627 "(UNKNOWN)"));
628 const std::string dstName = (players.count(dst) ? players[dst].name :
629 "(UNKNOWN)");
630
631 // direct message to or from me
632 if (dst == me || players.count(dst))
633 {
634 if (!(src == me && dst == me))
635 {
636 if (src == me)
637 {
638 if (type == ActionMessage)
639 formatted += "[->" + dstName + "][" + srcName + " " + msg + "]";
640 else
641 formatted += "[->" + dstName + "] " + msg;
642 }
643 else
644 {
645 if (type == ActionMessage)
646 formatted += "[" + srcName + " " + msg + "]";
647 else
648 formatted += "[" + srcName + "->] " + msg;
649 }
650 }
651 else
652 formatted += msg;
653 }
654
655 // public or admin or team message
656 else
657 {
658 if (dst == AdminPlayers)
659 formatted += "[Admin] ";
660 else if (dstTeam != NoTeam)
661 formatted += "[Team] ";
662
663 formatted += srcName;
664 if (type != ActionMessage)
665 formatted += ":";
666 formatted += " ";
667 formatted += msg;
668 }
669
670 return formatted;
671 }
672
673
setUI(BZAdminUI * bzInterface)674 void BZAdminClient::setUI(BZAdminUI* bzInterface)
675 {
676 ui = bzInterface;
677 }
678
679
waitForServer()680 void BZAdminClient::waitForServer()
681 {
682 // we need to know that the server has processed all our messages
683 // send a private message to ourself and wait for it to come back
684 // this assumes that the order of messages isn't changed along the way
685 bool tmp = messageMask[MsgMessage];
686 messageMask[MsgMessage] = true;
687 PlayerId me = sLink.getId();
688 if (sLink.getState() == ServerLink::Okay)
689 {
690 sendMessage("bzadminping", me);
691 std::string expected = formatMessage("bzadminping", ChatMessage, me, me, NoTeam, me);
692 std::string noTalk = formatMessage("We're sorry, you are not allowed to talk!", ChatMessage, ServerPlayer, me, NoTeam,
693 me);
694 BZAdminUI* tmpUI = ui;
695 ui = NULL;
696 do
697 {
698 checkMessage();
699 }
700 while (lastMessage.first != expected && lastMessage.first != noTalk);
701 ui = tmpUI;
702 }
703 messageMask[MsgMessage] = tmp;
704 }
705
706
ignoreMessageType(uint16_t type)707 void BZAdminClient::ignoreMessageType(uint16_t type)
708 {
709 messageMask[type] = false;
710 }
711
712
showMessageType(uint16_t type)713 void BZAdminClient::showMessageType(uint16_t type)
714 {
715 messageMask[type] = true;
716 }
717
718
ignoreMessageType(std::string type)719 void BZAdminClient::ignoreMessageType(std::string type)
720 {
721 ignoreMessageType(msgTypeMap[type]);
722 }
723
724
showMessageType(std::string type)725 void BZAdminClient::showMessageType(std::string type)
726 {
727 showMessageType(msgTypeMap[type]);
728 }
729
730
listSetVars(const std::string & name,void * thisObject)731 void BZAdminClient::listSetVars(const std::string& name, void* thisObject)
732 {
733 //Flawfinder: ignore
734 char message[MessageLen];
735 if (BZDB.getPermission(name) == StateDatabase::Locked)
736 {
737 // Flawfinder: ignore
738 snprintf(message, sizeof(message), "/set %s %f", name.c_str(), BZDB.eval(name));
739 ((BZAdminClient*)thisObject)->ui->outputMessage(message, Default);
740 }
741 }
742
743
getMessageTypeMap() const744 const std::map<std::string, uint16_t>& BZAdminClient::getMessageTypeMap() const
745 {
746 return msgTypeMap;
747 }
748
getFilterStatus(uint16_t msgType) const749 bool BZAdminClient::getFilterStatus(uint16_t msgType) const
750 {
751 std::map<uint16_t, bool>::const_iterator iter = messageMask.find(msgType);
752 if (iter == messageMask.end())
753 return false;
754 else
755 return iter->second;
756 }
757
758
759 // Local Variables: ***
760 // mode: C++ ***
761 // tab-width: 4 ***
762 // c-basic-offset: 4 ***
763 // indent-tabs-mode: nil ***
764 // End: ***
765 // ex: shiftwidth=4 tabstop=4
766