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