]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_xml.cc
update sources to v12.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"
12
13#include "rgw_common.h"
14#include "rgw_xml.h"
15
16#define dout_subsys ceph_subsys_rgw
17
18using namespace std;
19
20XMLObjIter::
21XMLObjIter()
22{
23}
24
25XMLObjIter::
26~XMLObjIter()
27{
28}
29
30void XMLObjIter::
31set(const XMLObjIter::map_iter_t &_cur, const XMLObjIter::map_iter_t &_end)
32{
33 cur = _cur;
34 end = _end;
35}
36
37XMLObj *XMLObjIter::
38get_next()
39{
40 XMLObj *obj = NULL;
41 if (cur != end) {
42 obj = cur->second;
43 ++cur;
44 }
45 return obj;
46}
47
48ostream& operator<<(ostream &out, const XMLObj &obj) {
49 out << obj.obj_type << ": " << obj.data;
50 return out;
51}
52
53XMLObj::
54~XMLObj()
55{
56}
57
58bool XMLObj::
59xml_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
69bool XMLObj::
70xml_end(const char *el)
71{
72 return true;
73}
74
75void XMLObj::
76xml_handle_data(const char *s, int len)
77{
78 data.append(s, len);
79}
80
81string& XMLObj::
82XMLObj::get_data()
83{
84 return data;
85}
86
87XMLObj *XMLObj::
88XMLObj::get_parent()
89{
90 return parent;
91}
92
93void XMLObj::
94add_child(string el, XMLObj *obj)
95{
96 children.insert(pair<string, XMLObj *>(el, obj));
97}
98
99bool XMLObj::
100get_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
109XMLObjIter XMLObj::
110find(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
124XMLObj *XMLObj::
125find_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}
134static 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
141RGWXMLParser::
142RGWXMLParser() : buf(NULL), buf_len(0), cur_obj(NULL), success(true)
143{
144 p = XML_ParserCreate(NULL);
145}
146
147RGWXMLParser::
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
161bool 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
182static 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
189bool 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
197static 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
204void RGWXMLParser::handle_data(const char *s, int len)
205{
206 cur_obj->xml_handle_data(s, len);
207}
208
209
210bool 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
221bool 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
248void 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
277void 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
305void 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
333void 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
361void 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
374void 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
387void 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
403void 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
416void 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
429void encode_xml(const char *name, const string& val, Formatter *f)
430{
431 f->dump_string(name, val);
432}
433
434void encode_xml(const char *name, const char *val, Formatter *f)
435{
436 f->dump_string(name, val);
437}
438
439void 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
450void encode_xml(const char *name, int val, Formatter *f)
451{
452 f->dump_int(name, val);
453}
454
455void encode_xml(const char *name, long val, Formatter *f)
456{
457 f->dump_int(name, val);
458}
459
460void encode_xml(const char *name, unsigned val, Formatter *f)
461{
462 f->dump_unsigned(name, val);
463}
464
465void encode_xml(const char *name, unsigned long val, Formatter *f)
466{
467 f->dump_unsigned(name, val);
468}
469
470void encode_xml(const char *name, unsigned long long val, Formatter *f)
471{
472 f->dump_unsigned(name, val);
473}
474
475void encode_xml(const char *name, long long val, Formatter *f)
476{
477 f->dump_int(name, val);
478}
479
480void encode_xml(const char *name, const utime_t& val, Formatter *f)
481{
482 val.gmtime(f->dump_stream(name));
483}
484
485void 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