summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_xml.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rgw/rgw_xml.cc')
-rw-r--r--src/rgw/rgw_xml.cc500
1 files changed, 500 insertions, 0 deletions
diff --git a/src/rgw/rgw_xml.cc b/src/rgw/rgw_xml.cc
new file mode 100644
index 000000000..19f0ac4f9
--- /dev/null
+++ b/src/rgw/rgw_xml.cc
@@ -0,0 +1,500 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+#include <string.h>
+
+#include <iostream>
+#include <map>
+
+#include <expat.h>
+
+#include "include/types.h"
+#include "include/utime.h"
+
+#include "rgw_xml.h"
+
+XMLObjIter::
+XMLObjIter()
+{
+}
+
+XMLObjIter::
+~XMLObjIter()
+{
+}
+
+void XMLObjIter::
+set(const XMLObjIter::map_iter_t &_cur, const XMLObjIter::map_iter_t &_end)
+{
+ cur = _cur;
+ end = _end;
+}
+
+XMLObj *XMLObjIter::
+get_next()
+{
+ XMLObj *obj = NULL;
+ if (cur != end) {
+ obj = cur->second;
+ ++cur;
+ }
+ return obj;
+}
+
+bool XMLObjIter::get_name(std::string& name) const
+{
+ if (cur == end) {
+ return false;
+ }
+
+ name = cur->first;
+ return true;
+}
+
+ostream& operator<<(ostream &out, const XMLObj &obj) {
+ out << obj.obj_type << ": " << obj.data;
+ return out;
+}
+
+XMLObj::
+~XMLObj()
+{
+}
+
+bool XMLObj::
+xml_start(XMLObj *parent, const char *el, const char **attr)
+{
+ this->parent = parent;
+ obj_type = el;
+ for (int i = 0; attr[i]; i += 2) {
+ attr_map[attr[i]] = std::string(attr[i + 1]);
+ }
+ return true;
+}
+
+bool XMLObj::
+xml_end(const char *el)
+{
+ return true;
+}
+
+void XMLObj::
+xml_handle_data(const char *s, int len)
+{
+ data.append(s, len);
+}
+
+const std::string& XMLObj::
+XMLObj::get_data() const
+{
+ return data;
+}
+
+const std::string& XMLObj::
+XMLObj::get_obj_type() const
+{
+ return obj_type;
+}
+
+XMLObj *XMLObj::
+XMLObj::get_parent()
+{
+ return parent;
+}
+
+void XMLObj::
+add_child(const std::string& el, XMLObj *obj)
+{
+ children.insert(std::pair<std::string, XMLObj *>(el, obj));
+}
+
+bool XMLObj::
+get_attr(const std::string& name, std::string& attr) const
+{
+ const std::map<std::string, std::string>::const_iterator iter = attr_map.find(name);
+ if (iter == attr_map.end())
+ return false;
+ attr = iter->second;
+ return true;
+}
+
+XMLObjIter XMLObj::
+find(const std::string& name)
+{
+ XMLObjIter iter;
+ const XMLObjIter::const_map_iter_t first = children.find(name);
+ XMLObjIter::const_map_iter_t last;
+ if (first != children.end()) {
+ last = children.upper_bound(name);
+ }else
+ last = children.end();
+ iter.set(first, last);
+ return iter;
+}
+
+XMLObjIter XMLObj::find_first()
+{
+ XMLObjIter iter;
+ const XMLObjIter::const_map_iter_t first = children.begin();
+ const XMLObjIter::const_map_iter_t last = children.end();
+ iter.set(first, last);
+ return iter;
+}
+
+XMLObj *XMLObj::
+find_first(const std::string& name)
+{
+ const XMLObjIter::const_map_iter_t first = children.find(name);
+ if (first != children.end())
+ return first->second;
+ return nullptr;
+}
+
+RGWXMLParser::
+RGWXMLParser() : buf(nullptr), buf_len(0), cur_obj(nullptr), success(true), init_called(false)
+{
+ p = XML_ParserCreate(nullptr);
+}
+
+RGWXMLParser::
+~RGWXMLParser()
+{
+ XML_ParserFree(p);
+
+ free(buf);
+ std::list<XMLObj *>::const_iterator iter;
+ for (iter = allocated_objs.begin(); iter != allocated_objs.end(); ++iter) {
+ XMLObj *obj = *iter;
+ delete obj;
+ }
+}
+
+void RGWXMLParser::call_xml_start(void* user_data, const char *el, const char **attr) {
+ RGWXMLParser *handler = static_cast<RGWXMLParser *>(user_data);
+ XMLObj * obj = handler->alloc_obj(el);
+ if (!obj) {
+ handler->unallocated_objs.push_back(XMLObj());
+ obj = &handler->unallocated_objs.back();
+ } else {
+ handler->allocated_objs.push_back(obj);
+ }
+ if (!obj->xml_start(handler->cur_obj, el, attr)) {
+ handler->success = false;
+ return;
+ }
+ if (handler->cur_obj) {
+ handler->cur_obj->add_child(el, obj);
+ } else {
+ handler->children.insert(std::pair<std::string, XMLObj *>(el, obj));
+ }
+ handler->cur_obj = obj;
+
+ handler->objs.push_back(obj);
+}
+
+void RGWXMLParser::call_xml_end(void* user_data, const char *el) {
+ RGWXMLParser *handler = static_cast<RGWXMLParser *>(user_data);
+ XMLObj *parent_obj = handler->cur_obj->get_parent();
+ if (!handler->cur_obj->xml_end(el)) {
+ handler->success = false;
+ return;
+ }
+ handler->cur_obj = parent_obj;
+}
+
+void RGWXMLParser::call_xml_handle_data(void* user_data, const char *s, int len)
+{
+ RGWXMLParser *handler = static_cast<RGWXMLParser *>(user_data);
+ handler->cur_obj->xml_handle_data(s, len);
+}
+
+bool RGWXMLParser::init()
+{
+ if (!p) {
+ return false;
+ }
+ init_called = true;
+ XML_SetElementHandler(p, RGWXMLParser::call_xml_start, RGWXMLParser::call_xml_end);
+ XML_SetCharacterDataHandler(p, RGWXMLParser::call_xml_handle_data);
+ XML_SetUserData(p, (void *)this);
+ return true;
+}
+
+bool RGWXMLParser::parse(const char *_buf, int len, int done)
+{
+ ceph_assert(init_called);
+ int pos = buf_len;
+ char *tmp_buf;
+ tmp_buf = (char *)realloc(buf, buf_len + len);
+ if (tmp_buf == NULL){
+ free(buf);
+ buf = NULL;
+ return false;
+ } else {
+ buf = tmp_buf;
+ }
+
+ memcpy(&buf[buf_len], _buf, len);
+ buf_len += len;
+
+ success = true;
+ if (!XML_Parse(p, &buf[pos], len, done)) {
+ fprintf(stderr, "Parse error at line %d:\n%s\n",
+ (int)XML_GetCurrentLineNumber(p),
+ XML_ErrorString(XML_GetErrorCode(p)));
+ success = false;
+ }
+
+ return success;
+}
+
+void decode_xml_obj(unsigned long& val, XMLObj *obj)
+{
+ auto& s = obj->get_data();
+ const char *start = s.c_str();
+ char *p;
+
+ errno = 0;
+ val = strtoul(start, &p, 10);
+
+ /* Check for various possible errors */
+
+ if ((errno == ERANGE && val == ULONG_MAX) ||
+ (errno != 0 && val == 0)) {
+ throw RGWXMLDecoder::err("failed to number");
+ }
+
+ if (p == start) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+
+ while (*p != '\0') {
+ if (!isspace(*p)) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+ p++;
+ }
+}
+
+
+void decode_xml_obj(long& val, XMLObj *obj)
+{
+ const std::string s = obj->get_data();
+ const char *start = s.c_str();
+ char *p;
+
+ errno = 0;
+ val = strtol(start, &p, 10);
+
+ /* Check for various possible errors */
+
+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
+ (errno != 0 && val == 0)) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+
+ if (p == start) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+
+ while (*p != '\0') {
+ if (!isspace(*p)) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+ p++;
+ }
+}
+
+void decode_xml_obj(long long& val, XMLObj *obj)
+{
+ const std::string s = obj->get_data();
+ const char *start = s.c_str();
+ char *p;
+
+ errno = 0;
+ val = strtoll(start, &p, 10);
+
+ /* Check for various possible errors */
+
+ if ((errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) ||
+ (errno != 0 && val == 0)) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+
+ if (p == start) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+
+ while (*p != '\0') {
+ if (!isspace(*p)) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+ p++;
+ }
+}
+
+void decode_xml_obj(unsigned long long& val, XMLObj *obj)
+{
+ const std::string s = obj->get_data();
+ const char *start = s.c_str();
+ char *p;
+
+ errno = 0;
+ val = strtoull(start, &p, 10);
+
+ /* Check for various possible errors */
+
+ if ((errno == ERANGE && val == ULLONG_MAX) ||
+ (errno != 0 && val == 0)) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+
+ if (p == start) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+
+ while (*p != '\0') {
+ if (!isspace(*p)) {
+ throw RGWXMLDecoder::err("failed to parse number");
+ }
+ p++;
+ }
+}
+
+void decode_xml_obj(int& val, XMLObj *obj)
+{
+ long l;
+ decode_xml_obj(l, obj);
+#if LONG_MAX > INT_MAX
+ if (l > INT_MAX || l < INT_MIN) {
+ throw RGWXMLDecoder::err("integer out of range");
+ }
+#endif
+
+ val = (int)l;
+}
+
+void decode_xml_obj(unsigned& val, XMLObj *obj)
+{
+ unsigned long l;
+ decode_xml_obj(l, obj);
+#if ULONG_MAX > UINT_MAX
+ if (l > UINT_MAX) {
+ throw RGWXMLDecoder::err("unsigned integer out of range");
+ }
+#endif
+
+ val = (unsigned)l;
+}
+
+void decode_xml_obj(bool& val, XMLObj *obj)
+{
+ const std::string s = obj->get_data();
+ if (strncasecmp(s.c_str(), "true", 8) == 0) {
+ val = true;
+ return;
+ }
+ if (strncasecmp(s.c_str(), "false", 8) == 0) {
+ val = false;
+ return;
+ }
+ int i;
+ decode_xml_obj(i, obj);
+ val = (bool)i;
+}
+
+void decode_xml_obj(bufferlist& val, XMLObj *obj)
+{
+ const std::string s = obj->get_data();
+
+ bufferlist bl;
+ bl.append(s.c_str(), s.size());
+ try {
+ val.decode_base64(bl);
+ } catch (buffer::error& err) {
+ throw RGWXMLDecoder::err("failed to decode base64");
+ }
+}
+
+void decode_xml_obj(utime_t& val, XMLObj *obj)
+{
+ const std::string s = obj->get_data();
+ uint64_t epoch;
+ uint64_t nsec;
+ int r = utime_t::parse_date(s, &epoch, &nsec);
+ if (r == 0) {
+ val = utime_t(epoch, nsec);
+ } else {
+ throw RGWXMLDecoder::err("failed to decode utime_t");
+ }
+}
+
+void encode_xml(const char *name, const string& val, Formatter *f)
+{
+ f->dump_string(name, val);
+}
+
+void encode_xml(const char *name, const char *val, Formatter *f)
+{
+ f->dump_string(name, val);
+}
+
+void encode_xml(const char *name, bool val, Formatter *f)
+{
+ std::string s;
+ if (val)
+ s = "True";
+ else
+ s = "False";
+
+ f->dump_string(name, s);
+}
+
+void encode_xml(const char *name, int val, Formatter *f)
+{
+ f->dump_int(name, val);
+}
+
+void encode_xml(const char *name, long val, Formatter *f)
+{
+ f->dump_int(name, val);
+}
+
+void encode_xml(const char *name, unsigned val, Formatter *f)
+{
+ f->dump_unsigned(name, val);
+}
+
+void encode_xml(const char *name, unsigned long val, Formatter *f)
+{
+ f->dump_unsigned(name, val);
+}
+
+void encode_xml(const char *name, unsigned long long val, Formatter *f)
+{
+ f->dump_unsigned(name, val);
+}
+
+void encode_xml(const char *name, long long val, Formatter *f)
+{
+ f->dump_int(name, val);
+}
+
+void encode_xml(const char *name, const utime_t& val, Formatter *f)
+{
+ val.gmtime(f->dump_stream(name));
+}
+
+void encode_xml(const char *name, const bufferlist& bl, Formatter *f)
+{
+ /* need to copy data from bl, as it is const bufferlist */
+ bufferlist src = bl;
+
+ bufferlist b64;
+ src.encode_base64(b64);
+
+ const std::string s(b64.c_str(), b64.length());
+
+ encode_xml(name, s, f);
+}
+