Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / rgw / rgw_xml.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include <string.h>
5
6 #include <iostream>
7 #include <map>
8
9 #include <expat.h>
10
11 #include "include/types.h"
12
13 #include "rgw_common.h"
14 #include "rgw_xml.h"
15
16 #define dout_subsys ceph_subsys_rgw
17
18 using namespace std;
19
20 XMLObjIter::
21 XMLObjIter()
22 {
23 }
24
25 XMLObjIter::
26 ~XMLObjIter()
27 {
28 }
29
30 void XMLObjIter::
31 set(const XMLObjIter::map_iter_t &_cur, const XMLObjIter::map_iter_t &_end)
32 {
33   cur = _cur;
34   end = _end;
35 }
36
37 XMLObj *XMLObjIter::
38 get_next()
39 {
40   XMLObj *obj = NULL;
41   if (cur != end) {
42     obj = cur->second;
43     ++cur;
44   }
45   return obj;
46 }
47
48 ostream& operator<<(ostream &out, const XMLObj &obj) {
49    out << obj.obj_type << ": " << obj.data;
50    return out;
51 }
52
53 XMLObj::
54 ~XMLObj()
55 {
56 }
57
58 bool XMLObj::
59 xml_start(XMLObj *parent, const char *el, const char **attr)
60 {
61   this->parent = parent;
62   obj_type = el;
63   for (int i = 0; attr[i]; i += 2) {
64     attr_map[attr[i]] = string(attr[i + 1]);
65   }
66   return true;
67 }
68
69 bool XMLObj::
70 xml_end(const char *el)
71 {
72   return true;
73 }
74
75 void XMLObj::
76 xml_handle_data(const char *s, int len)
77 {
78   data.append(s, len);
79 }
80
81 string& XMLObj::
82 XMLObj::get_data()
83 {
84   return data;
85 }
86
87 XMLObj *XMLObj::
88 XMLObj::get_parent()
89 {
90   return parent;
91 }
92
93 void XMLObj::
94 add_child(string el, XMLObj *obj)
95 {
96   children.insert(pair<string, XMLObj *>(el, obj));
97 }
98
99 bool XMLObj::
100 get_attr(string name, string& attr)
101 {
102   map<string, string>::iterator iter = attr_map.find(name);
103   if (iter == attr_map.end())
104     return false;
105   attr = iter->second;
106   return true;
107 }
108
109 XMLObjIter XMLObj::
110 find(string name)
111 {
112   XMLObjIter iter;
113   map<string, XMLObj *>::iterator first;
114   map<string, XMLObj *>::iterator last;
115   first = children.find(name);
116   if (first != children.end()) {
117     last = children.upper_bound(name);
118   }else
119     last = children.end();
120   iter.set(first, last);
121   return iter;
122 }
123
124 XMLObj *XMLObj::
125 find_first(string name)
126 {
127   XMLObjIter iter;
128   map<string, XMLObj *>::iterator first;
129   first = children.find(name);
130   if (first != children.end())
131     return first->second;
132   return NULL;
133 }
134 static void xml_start(void *data, const char *el, const char **attr) {
135   RGWXMLParser *handler = static_cast<RGWXMLParser *>(data);
136
137   if (!handler->xml_start(el, attr))
138     handler->set_failure();
139 }
140
141 RGWXMLParser::
142 RGWXMLParser() : buf(NULL), buf_len(0), cur_obj(NULL), success(true)
143 {
144   p = XML_ParserCreate(NULL);
145 }
146
147 RGWXMLParser::
148 ~RGWXMLParser()
149 {
150   XML_ParserFree(p);
151
152   free(buf);
153   list<XMLObj *>::iterator iter;
154   for (iter = allocated_objs.begin(); iter != allocated_objs.end(); ++iter) {
155     XMLObj *obj = *iter;
156     delete obj;
157   }
158 }
159
160
161 bool RGWXMLParser::xml_start(const char *el, const char **attr) {
162   XMLObj * obj = alloc_obj(el);
163   if (!obj) {
164     unallocated_objs.push_back(XMLObj());
165     obj = &unallocated_objs.back();
166   } else {
167     allocated_objs.push_back(obj);
168   }
169   if (!obj->xml_start(cur_obj, el, attr))
170     return false;
171   if (cur_obj) {
172     cur_obj->add_child(el, obj);
173   } else {
174     children.insert(pair<string, XMLObj *>(el, obj));
175   }
176   cur_obj = obj;
177
178   objs.push_back(obj);
179   return true;
180 }
181
182 static void xml_end(void *data, const char *el) {
183   RGWXMLParser *handler = static_cast<RGWXMLParser *>(data);
184
185   if (!handler->xml_end(el))
186     handler->set_failure();
187 }
188
189 bool RGWXMLParser::xml_end(const char *el) {
190   XMLObj *parent_obj = cur_obj->get_parent();
191   if (!cur_obj->xml_end(el))
192     return false;
193   cur_obj = parent_obj;
194   return true;
195 }
196
197 static void handle_data(void *data, const char *s, int len)
198 {
199   RGWXMLParser *handler = static_cast<RGWXMLParser *>(data);
200
201   handler->handle_data(s, len);
202 }
203
204 void RGWXMLParser::handle_data(const char *s, int len)
205 {
206   cur_obj->xml_handle_data(s, len);
207 }
208
209
210 bool RGWXMLParser::init()
211 {
212   if (!p) {
213     return false;
214   }
215   XML_SetElementHandler(p, ::xml_start, ::xml_end);
216   XML_SetCharacterDataHandler(p, ::handle_data);
217   XML_SetUserData(p, (void *)this);
218   return true;
219 }
220
221 bool RGWXMLParser::parse(const char *_buf, int len, int done)
222 {
223   int pos = buf_len;
224   char *tmp_buf;
225   tmp_buf = (char *)realloc(buf, buf_len + len);
226   if (tmp_buf == NULL){
227     free(buf);
228     buf = NULL;
229     return false;
230   } else {
231     buf = tmp_buf;
232   }
233
234   memcpy(&buf[buf_len], _buf, len);
235   buf_len += len;
236
237   success = true;
238   if (!XML_Parse(p, &buf[pos], len, done)) {
239     fprintf(stderr, "Parse error at line %d:\n%s\n",
240               (int)XML_GetCurrentLineNumber(p),
241               XML_ErrorString(XML_GetErrorCode(p)));
242     success = false;
243   }
244
245   return success;
246 }
247
248 void decode_xml_obj(unsigned long& val, XMLObj *obj)
249 {
250   string& s = obj->get_data();
251   const char *start = s.c_str();
252   char *p;
253
254   errno = 0;
255   val = strtoul(start, &p, 10);
256
257   /* Check for various possible errors */
258
259  if ((errno == ERANGE && val == ULONG_MAX) ||
260      (errno != 0 && val == 0)) {
261    throw RGWXMLDecoder::err("failed to number");
262  }
263
264  if (p == start) {
265    throw RGWXMLDecoder::err("failed to parse number");
266  }
267
268  while (*p != '\0') {
269    if (!isspace(*p)) {
270      throw RGWXMLDecoder::err("failed to parse number");
271    }
272    p++;
273  }
274 }
275
276
277 void decode_xml_obj(long& val, XMLObj *obj)
278 {
279   string s = obj->get_data();
280   const char *start = s.c_str();
281   char *p;
282
283   errno = 0;
284   val = strtol(start, &p, 10);
285
286   /* Check for various possible errors */
287
288  if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
289      (errno != 0 && val == 0)) {
290    throw RGWXMLDecoder::err("failed to parse number");
291  }
292
293  if (p == start) {
294    throw RGWXMLDecoder::err("failed to parse number");
295  }
296
297  while (*p != '\0') {
298    if (!isspace(*p)) {
299      throw RGWXMLDecoder::err("failed to parse number");
300    }
301    p++;
302  }
303 }
304
305 void decode_xml_obj(long long& val, XMLObj *obj)
306 {
307   string s = obj->get_data();
308   const char *start = s.c_str();
309   char *p;
310
311   errno = 0;
312   val = strtoll(start, &p, 10);
313
314   /* Check for various possible errors */
315
316  if ((errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) ||
317      (errno != 0 && val == 0)) {
318    throw RGWXMLDecoder::err("failed to parse number");
319  }
320
321  if (p == start) {
322    throw RGWXMLDecoder::err("failed to parse number");
323  }
324
325  while (*p != '\0') {
326    if (!isspace(*p)) {
327      throw RGWXMLDecoder::err("failed to parse number");
328    }
329    p++;
330  }
331 }
332
333 void decode_xml_obj(unsigned long long& val, XMLObj *obj)
334 {
335   string s = obj->get_data();
336   const char *start = s.c_str();
337   char *p;
338
339   errno = 0;
340   val = strtoull(start, &p, 10);
341
342   /* Check for various possible errors */
343
344  if ((errno == ERANGE && val == ULLONG_MAX) ||
345      (errno != 0 && val == 0)) {
346    throw RGWXMLDecoder::err("failed to number");
347  }
348
349  if (p == start) {
350    throw RGWXMLDecoder::err("failed to parse number");
351  }
352
353  while (*p != '\0') {
354    if (!isspace(*p)) {
355      throw RGWXMLDecoder::err("failed to parse number");
356    }
357    p++;
358  }
359 }
360
361 void decode_xml_obj(int& val, XMLObj *obj)
362 {
363   long l;
364   decode_xml_obj(l, obj);
365 #if LONG_MAX > INT_MAX
366   if (l > INT_MAX || l < INT_MIN) {
367     throw RGWXMLDecoder::err("integer out of range");
368   }
369 #endif
370
371   val = (int)l;
372 }
373
374 void decode_xml_obj(unsigned& val, XMLObj *obj)
375 {
376   unsigned long l;
377   decode_xml_obj(l, obj);
378 #if ULONG_MAX > UINT_MAX
379   if (l > UINT_MAX) {
380     throw RGWXMLDecoder::err("unsigned integer out of range");
381   }
382 #endif
383
384   val = (unsigned)l;
385 }
386
387 void decode_xml_obj(bool& val, XMLObj *obj)
388 {
389   string s = obj->get_data();
390   if (strcasecmp(s.c_str(), "true") == 0) {
391     val = true;
392     return;
393   }
394   if (strcasecmp(s.c_str(), "false") == 0) {
395     val = false;
396     return;
397   }
398   int i;
399   decode_xml_obj(i, obj);
400   val = (bool)i;
401 }
402
403 void decode_xml_obj(bufferlist& val, XMLObj *obj)
404 {
405   string s = obj->get_data();
406
407   bufferlist bl;
408   bl.append(s.c_str(), s.size());
409   try {
410     val.decode_base64(bl);
411   } catch (buffer::error& err) {
412    throw RGWXMLDecoder::err("failed to decode base64");
413   }
414 }
415
416 void decode_xml_obj(utime_t& val, XMLObj *obj)
417 {
418   string s = obj->get_data();
419   uint64_t epoch;
420   uint64_t nsec;
421   int r = utime_t::parse_date(s, &epoch, &nsec);
422   if (r == 0) {
423     val = utime_t(epoch, nsec);
424   } else {
425     throw RGWXMLDecoder::err("failed to decode utime_t");
426   }
427 }
428
429 void encode_xml(const char *name, const string& val, Formatter *f)
430 {
431   f->dump_string(name, val);
432 }
433
434 void encode_xml(const char *name, const char *val, Formatter *f)
435 {
436   f->dump_string(name, val);
437 }
438
439 void encode_xml(const char *name, bool val, Formatter *f)
440 {
441   string s;
442   if (val)
443     s = "True";
444   else
445     s = "False";
446
447   f->dump_string(name, s);
448 }
449
450 void encode_xml(const char *name, int val, Formatter *f)
451 {
452   f->dump_int(name, val);
453 }
454
455 void encode_xml(const char *name, long val, Formatter *f)
456 {
457   f->dump_int(name, val);
458 }
459
460 void encode_xml(const char *name, unsigned val, Formatter *f)
461 {
462   f->dump_unsigned(name, val);
463 }
464
465 void encode_xml(const char *name, unsigned long val, Formatter *f)
466 {
467   f->dump_unsigned(name, val);
468 }
469
470 void encode_xml(const char *name, unsigned long long val, Formatter *f)
471 {
472   f->dump_unsigned(name, val);
473 }
474
475 void encode_xml(const char *name, long long val, Formatter *f)
476 {
477   f->dump_int(name, val);
478 }
479
480 void encode_xml(const char *name, const utime_t& val, Formatter *f)
481 {
482   val.gmtime(f->dump_stream(name));
483 }
484
485 void encode_xml(const char *name, const bufferlist& bl, Formatter *f)
486 {
487   /* need to copy data from bl, as it is const bufferlist */
488   bufferlist src = bl;
489
490   bufferlist b64;
491   src.encode_base64(b64);
492
493   string s(b64.c_str(), b64.length());
494
495   encode_xml(name, s, f);
496 }
497