ManaPlus
tinyxml2.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifdef ENABLE_TINYXML2
25 
26 #include "utils/xml/tinyxml2.h"
27 
28 #include "fs/virtfs/fs.h"
29 
30 #include "utils/cast.h"
31 #include "utils/checkutils.h"
32 #include "utils/fuzzer.h"
33 #include "utils/stringutils.h"
34 
36 
37 #include <fstream>
38 
39 #include "debug.h"
40 
41 namespace
42 {
43  bool valid = false;
44 } // namespace
45 
46 namespace XML
47 {
48  static void showErrorStatus(tinyxml2::XMLDocument &doc)
49  {
50 #ifdef USE_TINYXML_OLD
51  logger->log("xml error: %s, in lines: %s\n%s",
52  doc.ErrorName(),
53  doc.GetErrorStr1(),
54  doc.GetErrorStr2());
55 #else // USE_TINYXML_OLD
56 
57  logger->log("xml error: %s, in lines: %s",
58  doc.ErrorName(),
59  doc.ErrorStr());
60 #endif // USE_TINYXML_OLD
61  }
62 
63  Document::Document(const std::string &filename,
64  const UseVirtFs useResman,
65  const SkipError skipError) :
66  Resource(),
67  mDoc(),
68  mData(nullptr),
69  mIsValid(false)
70  {
71 #ifdef USE_FUZZER
72  if (Fuzzer::conditionTerminate(filename.c_str()))
73  return;
74 #endif // USE_FUZZER
75 
76  BLOCK_START("XML::Document::Document")
77  int size = 0;
78  char *data = nullptr;
79  valid = true;
80  if (useResman == UseVirtFs_true)
81  {
82  data = const_cast<char*>(VirtFs::loadFile(
83  filename.c_str(),
84  size));
85  }
86  else
87  {
88  std::ifstream file;
89  file.open(filename.c_str(), std::ios::in);
90 
91  if (file.is_open())
92  {
93  // Get length of file
94  file.seekg(0, std::ios::end);
95  size = CAST_S32(file.tellg());
96  if (size < 0)
97  {
98  reportAlways("Error loading XML file %s",
99  filename.c_str())
100  }
101  else
102  {
103  file.seekg(0, std::ios::beg);
104  data = new char[size];
105  file.read(data, size);
106  }
107  file.close();
108  }
109  else if (skipError == SkipError_false)
110  {
111  reportAlways("Error loading XML file %s",
112  filename.c_str())
113  }
114  }
115 
116  if (data)
117  {
118  tinyxml2::XMLError result = mDoc.Parse(data,
119  size);
120  if (result != tinyxml2::XML_SUCCESS)
121  {
122  showErrorStatus(mDoc);
123  delete [] data;
124  }
125  else
126  {
127  mData = data;
128  }
129  }
130  else if (skipError == SkipError_false)
131  {
132  reportAlways("Error loading %s", filename.c_str())
133  }
134  mIsValid = valid;
135  BLOCK_END("XML::Document::Document")
136  }
137 
138  Document::Document(const char *const data, const int size) :
139  Resource(),
140  mDoc(),
141  mData(nullptr),
142  mIsValid(true)
143  {
144  if (!data)
145  return;
146 
147  char *buf = new char[size + 1];
148  strncpy(buf, data, size);
149  buf[size] = 0;
150 
151  tinyxml2::XMLError result = mDoc.Parse(buf,
152  size);
153  if (result != tinyxml2::XML_SUCCESS)
154  {
155  showErrorStatus(mDoc);
156  delete [] buf;
157  }
158  else
159  {
160  mData = buf;
161  }
162  }
163 
164  Document::~Document()
165  {
166  delete [] mData;
167  mData = nullptr;
168  }
169 
170  XmlNodeConstPtr Document::rootNode()
171  {
172  return mDoc.FirstChildElement();
173  }
174 
175  int getProperty(XmlNodeConstPtr node,
176  const char *const name,
177  int def)
178  {
179  int &ret = def;
180 
181  if (!node)
182  return ret;
183  const char *attr = node->Attribute(name);
184  if (attr != nullptr)
185  ret = atoi(attr);
186 
187  return ret;
188  }
189 
190  int getIntProperty(XmlNodeConstPtr node,
191  const char *const name,
192  int def,
193  const int min,
194  const int max)
195  {
196  int &ret = def;
197 
198  if (!node)
199  return ret;
200  const char *attr = node->Attribute(name);
201  if (attr != nullptr)
202  ret = atoi(attr);
203 
204  if (ret < min)
205  ret = min;
206  else if (ret > max)
207  ret = max;
208  return ret;
209  }
210 
211  float getFloatProperty(XmlNodeConstPtr node,
212  const char *const name,
213  float def)
214  {
215  float &ret = def;
216 
217  if (!node)
218  return ret;
219  const char *attr = node->Attribute(name);
220  if (attr != nullptr)
221  ret = atof(attr);
222 
223  return ret;
224  }
225 
226  double getDoubleProperty(XmlNodeConstPtr node,
227  const char *const name,
228  double def)
229  {
230  double &ret = def;
231 
232  if (!node)
233  return ret;
234  const char *attr = node->Attribute(name);
235  if (attr != nullptr)
236  ret = atof(attr);
237 
238  return ret;
239  }
240 
241  std::string getProperty(XmlNodeConstPtr node,
242  const char *const name,
243  const std::string &def)
244  {
245  if (!node)
246  return def;
247  const char *attr = node->Attribute(name);
248  if (attr != nullptr)
249  return attr;
250 
251  return def;
252  }
253 
254  std::string langProperty(XmlNodeConstPtr node,
255  const char *const name,
256  const std::string &def)
257  {
258  std::string str = getProperty(node, name, def);
259  if (!translator)
260  return str;
261 
262  return translator->getStr(str);
263  }
264 
265  bool getBoolProperty(XmlNodeConstPtr node,
266  const char *const name,
267  const bool def)
268  {
269  if (!node)
270  return def;
271  const char *attr = node->Attribute(name);
272  if (attr != nullptr)
273  {
274  std::string val = attr;
275  if (val == "true")
276  return true;
277  if (val == "false")
278  return false;
279  }
280 
281  return def;
282  }
283 
284  XmlNodeConstPtr findFirstChildByName(XmlNodeConstPtrConst parent,
285  const char *const name)
286  {
287  if (!parent || !name)
288  return nullptr;
289  return parent->FirstChildElement(name);
290  }
291 
292  // Initialize xml
293  void initXML()
294  {
295  }
296 
297  // Shutdown xml
298  void cleanupXML()
299  {
300  }
301 
302  bool Document::validateXml(const std::string &fileName)
303  {
304  tinyxml2::XMLDocument doc;
305  tinyxml2::XMLError result = doc.LoadFile(fileName.c_str());
306 
307  if (result != tinyxml2::XML_SUCCESS)
308  {
309  showErrorStatus(doc);
310  return false;
311  }
312 
313  std::ifstream file;
314  file.open(fileName.c_str(), std::ios::in);
315  if (!file.is_open())
316  {
317  file.close();
318  return false;
319  }
320  char line[101];
321  if (!file.getline(line, 100))
322  return false;
323  file.close();
324 
325  const std::string str = line;
326  if (!strStartWith(str, "<?xml "))
327  return false;
328 
329  return true;
330  }
331 } // namespace XML
332 
333 #endif // ENABLE_TINYXML2
#define CAST_S32
Definition: cast.h:30
#define reportAlways(...)
Definition: checkutils.h:253
void log(const char *const log_text,...)
Definition: logger.cpp:269
const std::string getStr(const std::string &str)
Definition: podict.cpp:45
Document(const std::string &filename, const UseVirtFs useResman, const SkipError skipError)
Definition: libxml.cpp:87
if(!vert) return
#define nullptr
Definition: localconsts.h:45
Logger * logger
Definition: logger.cpp:89
uint32_t data
int size()
Definition: emotedb.cpp:306
PlayerInfoBackend mData
Definition: playerinfo.cpp:56
const char * loadFile(std::string filename, int &fileSize)
Definition: fs.cpp:859
Definition: libxml.cpp:86
void initXML()
Definition: libxml.cpp:305
std::string langProperty(const xmlNodePtr node, const char *const name, const std::string &def)
Definition: libxml.cpp:258
float getFloatProperty(const xmlNodePtr node, const char *const name, float def)
Definition: libxml.cpp:211
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
int getIntProperty(const xmlNodePtr node, const char *const name, int def, const int min, const int max)
Definition: libxml.cpp:190
void cleanupXML()
Definition: libxml.cpp:315
xmlNodePtr findFirstChildByName(const xmlNode *const parent, const char *const name)
Definition: libxml.cpp:289
double getDoubleProperty(const xmlNodePtr node, const char *const name, double def)
Definition: libxml.cpp:227
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
PoDict * translator
Definition: podict.cpp:28
const bool SkipError_false
Definition: skiperror.h:30
bool SkipError
Definition: skiperror.h:30
bool strStartWith(const std::string &str1, const std::string &str2)
std::string fileName
Definition: testmain.cpp:39
bool UseVirtFs
Definition: usevirtfs.h:30
const bool UseVirtFs_true
Definition: usevirtfs.h:30