ManaPlus
groupdb.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2016-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "resources/db/groupdb.h"
23 
24 #include "configuration.h"
25 
26 #include "being/localplayer.h"
27 
28 #include "utils/checkutils.h"
29 
30 #ifdef TMWA_SUPPORT
31 #include "net/net.h"
32 #endif // TMWA_SUPPORT
33 
34 #include "resources/beingcommon.h"
35 #include "resources/groupinfo.h"
36 
37 #include "debug.h"
38 
39 namespace
40 {
43  bool mLoaded = false;
44 } // namespace
45 
47 {
48  if (mLoaded)
49  unload();
50 
51  logger->log1("Initializing group database...");
52 
54  loadXmlFile(paths.getStringValue("groupsPatchFile"), SkipError_true);
55  loadXmlDir("groupsPatchDir", loadXmlFile)
56  mLoaded = true;
57 }
58 
59 #define servercommandFirst(name) \
60  if (str == #name) \
61  return ServerCommandType::name; \
62  else
63 #define servercommand(name) \
64  if (str == #name) \
65  return ServerCommandType::name; \
66  else
67 #define servercommand2(name1, name2) \
68  if (str == #name2) \
69  return ServerCommandType::name1; \
70  else
71 
72 static ServerCommandTypeT parseCommand(const std::string &str,
73  const int id)
74 {
75 #include "resources/servercommands.inc"
76  {
77  reportAlways("GroupsDb: unknown command name: '%s' in group id '%d'.",
78  str.c_str(),
79  id)
80  }
81 
83 }
84 
85 SERVERCOMMANDS_VOID
86 #undef servercommandFirst
87 #undef servercommand
88 #undef servercommand2
89 
90 #define serverpermissionFirst(name) \
91  if (str == #name) \
92  return ServerPermissionType::name; \
93  else
94 #define serverpermission(name) \
95  if (str == #name) \
96  return ServerPermissionType::name; \
97  else
98 
99 static ServerPermissionTypeT parsePermission(const std::string &str,
100  const int id)
101 {
102 #include "resources/serverpermissions.inc"
103  {
104  reportAlways("GroupsDb: unknown permission name: "
105  "'%s' in group id '%d'.",
106  str.c_str(),
107  id)
108  }
109 
111 }
112 
113 SERVERPERMISSION_VOID
114 #undef serverpermissionFirst
115 #undef serverpermission
116 
117 static ServerCommandEnable::Type parseUseFlag(const std::string &str,
118  const int id)
119 {
120  if (str == "self")
121  {
123  }
124  else if (str == "other")
125  {
127  }
128  else if (str == "both")
129  {
131  }
132  else if (str == "false")
133  {
135  }
136  else
137  {
138  reportAlways("GroupsDb: unknown use flag: '%s' in group id '%d'."
139  "Possible values 'self', 'other', 'both'.",
140  str.c_str(),
141  id)
143  }
144 }
145 
146 static void loadCommands(XmlNodePtr rootNode,
147  const int id,
148  GroupInfo *groupInfo) A_NONNULL(3);
149 static void loadCommands(XmlNodePtr rootNode,
150  const int id,
151  GroupInfo *groupInfo)
152 {
153  for_each_xml_child_node(node, rootNode)
154  {
155  if (xmlNameEqual(node, "command"))
156  {
157  const std::string nameStr = XML::getProperty(node,
158  "name",
159  "");
160  const std::string useStr = XML::getProperty(node,
161  "use",
162  "");
163  ServerCommandTypeT name = parseCommand(nameStr, id);
164  if (name == ServerCommandType::Max)
165  continue;
166  ServerCommandEnable::Type useFlag = parseUseFlag(useStr, id);
167  if (useFlag == ServerCommandEnable::No)
168  continue;
169  groupInfo->mCommands[CAST_SIZE(name)] = useFlag;
170  }
171  }
172 }
173 
174 static void loadPermissions(XmlNodePtr rootNode,
175  const int id,
176  GroupInfo *groupInfo) A_NONNULL(3);
177 static void loadPermissions(XmlNodePtr rootNode,
178  const int id,
179  GroupInfo *groupInfo)
180 {
181  for_each_xml_child_node(node, rootNode)
182  {
183  if (xmlNameEqual(node, "permission"))
184  {
185  const std::string nameStr = XML::getProperty(node,
186  "name",
187  "");
188  ServerPermissionTypeT perm = parsePermission(nameStr, id);
189  if (perm == ServerPermissionType::Max)
190  continue;
191  if (!XML::getBoolProperty(node,
192  "enable",
193  true))
194  {
195  continue;
196  }
197  groupInfo->mPermissions[CAST_SIZE(perm)] = Enable_true;
198  }
199  }
200 }
201 
202 static void loadSubNodes(XmlNodePtr groupNode,
203  const int id,
204  GroupInfo *groupInfo) A_NONNULL(3);
205 static void loadSubNodes(XmlNodePtr groupNode,
206  const int id,
207  GroupInfo *groupInfo)
208 {
209  for_each_xml_child_node(node, groupNode)
210  {
211  if (xmlNameEqual(node, "commands"))
212  loadCommands(node, id, groupInfo);
213  if (xmlNameEqual(node, "permissions"))
214  loadPermissions(node, id, groupInfo);
215  }
216 }
217 
218 static void parseInherit(XmlNodePtr groupNode,
219  const int id,
220  GroupInfo *groupInfo) A_NONNULL(3);
221 static void parseInherit(XmlNodePtr groupNode,
222  const int id,
223  GroupInfo *groupInfo)
224 {
225  const std::string inherit = XML::langProperty(groupNode,
226  "inherit",
227  "");
228  STD_VECTOR<int> parts;
229  splitToIntVector(parts, inherit, ',');
230  FOR_EACH (STD_VECTOR<int>::const_iterator, it, parts)
231  {
232  const int id2 = *it;
233  GroupDb::GroupInfos::const_iterator it2 = mGroups.find(id2);
234  if (it2 == mGroups.end())
235  {
236  reportAlways("Unknown inherit group id '%d' in group '%d'",
237  id2,
238  id)
239  continue;
240  }
241  GroupInfo *const groupInfo2 = (*it2).second;
242  for (size_t f = 0; f < CAST_SIZE(ServerCommandType::Max); f ++)
243  {
244  ServerCommandEnable::Type enable = groupInfo2->mCommands[f];
245  if (enable != ServerCommandEnable::No)
246  groupInfo->mCommands[f] = enable;
247  }
248  for (size_t f = 0; f < CAST_SIZE(ServerPermissionType::Max); f ++)
249  {
250  if (groupInfo2->mPermissions[f] == Enable_true)
251  groupInfo->mPermissions[f] = Enable_true;
252  }
253  }
254 }
255 
256 void GroupDb::loadXmlFile(const std::string &fileName,
257  const SkipError skipError)
258 {
261  skipError);
262  XmlNodeConstPtrConst rootNode = doc.rootNode();
263 
264  if (rootNode == nullptr ||
265  !xmlNameEqual(rootNode, "groups"))
266  {
267  if (skipError == SkipError_true)
268  {
269  logger->log("GroupsDb: Error while loading %s!",
270  fileName.c_str());
271  }
272  else
273  {
274  reportAlways("GroupsDb: Error while loading %s!",
275  fileName.c_str())
276  }
277  return;
278  }
279 
280  for_each_xml_child_node(node, rootNode)
281  {
282  if (xmlNameEqual(node, "include"))
283  {
284  const std::string name = XML::getProperty(node, "name", "");
285  if (!name.empty())
286  loadXmlFile(name, skipError);
287  continue;
288  }
289  if (xmlNameEqual(node, "group"))
290  {
291  const int id = XML::getProperty(node,
292  "id",
293  -1);
294  if (id < 0)
295  {
296  reportAlways("Empty id field in GroupDb")
297  continue;
298  }
299  GroupInfosIter it = mGroups.find(id);
300  GroupInfo *group = nullptr;
301  if (it != mGroups.end())
302  {
303  reportAlways("GroupDb: group with id %d already added",
304  id)
305  group = (*it).second;
306  }
307  else
308  {
309  group = new GroupInfo;
310  mGroups[id] = group;
311  }
312  group->name = XML::langProperty(node,
313  "name",
314  "");
315  group->longName = XML::langProperty(node,
316  "longName",
317  "");
318  group->badge = XML::langProperty(node,
319  "badge",
320  paths.getStringValue("gmbadge"));
321  group->showBadge = XML::getBoolProperty(node,
322  "showBadge",
323  false);
324  group->highlightName = XML::getBoolProperty(node,
325  "highlightName",
326  false);
327  loadSubNodes(node, id, group);
328  parseInherit(node, id, group);
329  }
330  }
331 }
332 
334 {
335  logger->log1("Unloading group database...");
337  {
338  delete (*it).second;
339  }
340  mGroups.clear();
341  mLoaded = false;
342 }
343 
344 const std::string &GroupDb::getName(const int id)
345 {
346  GroupInfos::const_iterator it = mGroups.find(id);
347  if (it == mGroups.end())
348  {
349  reportAlways("Unknown group id requested: %d", id)
350  return mEmptyGroup.name;
351  }
352  return (*it).second->name;
353 }
354 
355 const std::string &GroupDb::getLongName(const int id)
356 {
357  GroupInfos::const_iterator it = mGroups.find(id);
358  if (it == mGroups.end())
359  {
360  reportAlways("Unknown group id requested: %d", id)
361  return mEmptyGroup.longName;
362  }
363  return (*it).second->longName;
364 }
365 
366 bool GroupDb::getShowBadge(const int id)
367 {
368  GroupInfos::const_iterator it = mGroups.find(id);
369  if (it == mGroups.end())
370  {
371  reportAlways("Unknown group id requested: %d", id)
372  return mEmptyGroup.showBadge;
373  }
374  return (*it).second->showBadge;
375 }
376 
377 bool GroupDb::getHighlightName(const int id)
378 {
379  GroupInfos::const_iterator it = mGroups.find(id);
380  if (it == mGroups.end())
381  {
382  reportAlways("Unknown group id requested: %d", id)
383  return mEmptyGroup.highlightName;
384  }
385  return (*it).second->highlightName;
386 }
387 
388 const std::string &GroupDb::getBadge(const int id)
389 {
390  GroupInfos::const_iterator it = mGroups.find(id);
391  if (it == mGroups.end())
392  {
393  reportAlways("Unknown group id requested: %d", id)
394  return mEmptyGroup.badge;
395  }
396  return (*it).second->badge;
397 }
398 
399 const GroupInfo *GroupDb::getGroup(const int id)
400 {
401  GroupInfos::const_iterator it = mGroups.find(id);
402  if (it == mGroups.end())
403  {
404  reportAlways("Unknown group id requested: %d", id)
405  return &mEmptyGroup;
406  }
407  return (*it).second;
408 }
409 
411 {
412  if (localPlayer == nullptr)
413  return false;
414  const int groupId = localPlayer->getGroupId();
415  const GroupInfo *const group = GroupDb::getGroup(groupId);
416 
417 #ifdef TMWA_SUPPORT
418  // allow any commands for legacy if group > 0
420  localPlayer->isGM())
421  {
422  return true;
423  }
424 #endif
425  if (group->mPermissions[CAST_SIZE(ServerPermissionType::all_commands)] ==
426  Enable_true)
427  {
428  return true;
429  }
430  const ServerCommandEnable::Type enabled =
431  group->mCommands[CAST_SIZE(command)];
432  return (enabled & ServerCommandEnable::Self) != 0;
433 }
434 
435 #ifdef UNITTESTS
436 GroupDb::GroupInfos &GroupDb::getGroups()
437 {
438  return mGroups;
439 }
440 #endif // UNITTESTS
static void loadXmlFile(const std::string &file, const std::string &name, BadgesInfos &arr, const SkipError skipError)
Definition: badgesdb.cpp:43
#define loadXmlDir(name, function)
Definition: beingcommon.h:39
#define CAST_SIZE
Definition: cast.h:34
#define reportAlways(...)
Definition: checkutils.h:253
int getGroupId() const
Definition: being.h:1087
bool isGM() const
Definition: being.h:659
std::string getStringValue(const std::string &key) const
void log(const char *const log_text,...)
Definition: logger.cpp:269
void log1(const char *const log_text)
Definition: logger.cpp:238
xmlNodePtr rootNode()
Definition: libxml.cpp:169
Configuration paths
const bool Enable_true
Definition: enable.h:30
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
static ServerCommandTypeT parseCommand(const std::string &str, const int id)
Definition: groupdb.cpp:72
static ServerCommandEnable::Type parseUseFlag(const std::string &str, const int id)
Definition: groupdb.cpp:117
static void loadCommands(xmlNodePtr rootNode, const int id, GroupInfo *groupInfo)
Definition: groupdb.cpp:149
static ServerPermissionTypeT parsePermission(const std::string &str, const int id)
Definition: groupdb.cpp:99
static void loadSubNodes(xmlNodePtr groupNode, const int id, GroupInfo *groupInfo)
Definition: groupdb.cpp:205
static void parseInherit(xmlNodePtr groupNode, const int id, GroupInfo *groupInfo)
Definition: groupdb.cpp:221
static void loadPermissions(xmlNodePtr rootNode, const int id, GroupInfo *groupInfo)
Definition: groupdb.cpp:177
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:161
#define A_NONNULL(...)
Definition: localconsts.h:168
LocalPlayer * localPlayer
Logger * logger
Definition: logger.cpp:89
const std::string & getBadge(const int id)
Definition: groupdb.cpp:388
void loadXmlFile(const std::string &fileName, const SkipError skipError)
Definition: groupdb.cpp:256
void load()
Definition: groupdb.cpp:46
bool getShowBadge(const int id)
Definition: groupdb.cpp:366
void unload()
Definition: groupdb.cpp:333
bool getHighlightName(const int id)
Definition: groupdb.cpp:377
const std::string & getName(const int id)
Definition: groupdb.cpp:344
bool isAllowCommand(const ServerCommandTypeT command)
Definition: groupdb.cpp:410
GroupInfos::iterator GroupInfosIter
Definition: groupdb.h:53
std::map< int, GroupInfo * > GroupInfos
Definition: groupdb.h:52
const GroupInfo * getGroup(const int id)
Definition: groupdb.cpp:399
const std::string & getLongName(const int id)
Definition: groupdb.cpp:355
void unload()
Definition: net.cpp:180
ServerTypeT getNetworkType()
Definition: net.cpp:189
std::string langProperty(const xmlNodePtr node, const char *const name, const std::string &def)
Definition: libxml.cpp:258
bool getBoolProperty(const xmlNodePtr node, const char *const name, const bool def)
Definition: libxml.cpp:269
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:174
GroupDb::GroupInfos mGroups
Definition: groupdb.cpp:41
ServerCommandType ::T ServerCommandTypeT
ServerPermissionType ::T ServerPermissionTypeT
const bool SkipError_false
Definition: skiperror.h:30
const bool SkipError_true
Definition: skiperror.h:30
bool SkipError
Definition: skiperror.h:30
void splitToIntVector(std::vector< int > &tokens, const std::string &text, const char separator)
bool highlightName
Definition: groupinfo.h:49
Enable mPermissions[static_cast< size_t >(ServerPermissionType::Max)]
Definition: groupinfo.h:44
std::string name
Definition: groupinfo.h:45
std::string badge
Definition: groupinfo.h:47
std::string longName
Definition: groupinfo.h:46
bool showBadge
Definition: groupinfo.h:48
ServerCommandEnable::Type mCommands[static_cast< size_t >(ServerCommandType::Max)]
Definition: groupinfo.h:43
std::string fileName
Definition: testmain.cpp:39
const bool UseVirtFs_true
Definition: usevirtfs.h:30