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