From 9b516ac35de70350b518b2074fc5515d2baffea1 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Wed, 29 Aug 2018 11:48:33 +0200 Subject: [PATCH] Add a small wrapper around pugixml do handle xmprpc. --- src/xmlrpc.h | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 src/xmlrpc.h diff --git a/src/xmlrpc.h b/src/xmlrpc.h new file mode 100644 index 000000000..a7ea2f34b --- /dev/null +++ b/src/xmlrpc.h @@ -0,0 +1,249 @@ + + +#ifndef KIWIX_XMLRPC_H_ +#define KIWIX_XMLRPC_H_ + +#include + +namespace kiwix { + +class InvalidRPCNode : public std::runtime_error { + public: + InvalidRPCNode(const std::string& msg) : std::runtime_error(msg) {}; +}; + +class Struct; +class Array; + +class Value { + pugi::xml_node m_value; + + public: + Value(pugi::xml_node value) : m_value(value) { } + + void set(int value) { + if (!m_value.child("int")) + m_value.append_child("int"); + m_value.child("int").text().set(value); + }; + + int getAsI() const { + if (!m_value.child("int")) + throw InvalidRPCNode("Type Error"); + return m_value.child("int").text().as_int(); + } + + void set(bool value) { + if (!m_value.child("boolean")) + m_value.append_child("boolean"); + m_value.child("boolean").text().set(value); + }; + + int getAsB() const { + if (!m_value.child("boolean")) + throw InvalidRPCNode("Type Error"); + return m_value.child("boolean").text().as_bool(); + } + + void set(const std::string& value) { + if (!m_value.child("string")) + m_value.append_child("string"); + m_value.child("string").text().set(value.c_str()); + }; + + std::string getAsS() const { + if (!m_value.child("string")) + throw InvalidRPCNode("Type Error"); + return m_value.child("string").text().as_string(); + } + + void set(double value) { + if (!m_value.child("double")) + m_value.append_child("double"); + m_value.child("double").text().set(value); + }; + + double getAsD() const { + if (!m_value.child("double")) + throw InvalidRPCNode("Type Error"); + return m_value.child("double").text().as_double(); + } + + inline Struct getStruct(); + inline Array getArray(); +}; + +class Array { + pugi::xml_node m_array; + public: + Array(pugi::xml_node array) : m_array(array) { + if (!m_array.child("data")) + m_array.append_child("data"); + } + + Value addValue() { + auto value = m_array.child("data").append_child("value"); + return Value(value); + } + + Value getValue(int index) const { + auto value = m_array.child("data").child("value"); + while(index && value) { + value = value.next_sibling(); + index--; + } + if (0==index) { + return Value(value); + } else { + throw InvalidRPCNode("Index error"); + } + } + +}; + +class Member { + pugi::xml_node m_member; + + public: + Member(pugi::xml_node member) : m_member(member) { } + + Value getValue() const { + return Value(m_member.child("value")); + }; +}; + +class Struct { + pugi::xml_node m_struct; + + public: + Struct(pugi::xml_node _struct) : m_struct(_struct) { } + + Member getMember(const std::string& name) const { + for(auto member=m_struct.first_child(); member; member=member.next_sibling()) { + std::string member_name = member.child("name").text().get(); + if (member_name == name) { + return Member(member); + } + } + throw InvalidRPCNode("Key Error"); + } + + Member addMember(const std::string& name) { + auto member = m_struct.append_child("member"); + member.append_child("name").text().set(name.c_str()); + member.append_child("value"); + return Member(member); + } +}; + +class Fault : public Struct { + public: + Fault(pugi::xml_node fault) : Struct(fault) {}; + + int getFaultCode() const { + return getMember("faultCode").getValue().getAsI(); + } + + std::string getFaultString() const { + return getMember("faultString").getValue().getAsS(); + } +}; + +Struct Value::getStruct() { + if (!m_value.child("struct")) + m_value.append_child("struct"); + return Struct(m_value.child("struct")); +} + +Array Value::getArray() { + if (!m_value.child("array")) + m_value.append_child("array"); + return Array(m_value.child("array")); +} + +class Param { + pugi::xml_node m_param; + public: + Param(pugi::xml_node param) : m_param(param) { + if (!m_param.child("value")) + m_param.append_child("value"); + }; + + Value getValue() const { + return Value(m_param.child("value")); + }; +}; + +class Params { + pugi::xml_node m_params; + + public: + Params(pugi::xml_node params) : m_params(params) {}; + + Param addParam() { + auto param = m_params.append_child("param"); + return Param(param); + } + Param getParam(int index) const { + auto param = m_params.child("param"); + while(index && param) { + param = param.next_sibling(); + index--; + } + if (0==index) { + return Param(param); + } else { + throw InvalidRPCNode("Index Error"); + } + } +}; + +class MethodCall { + pugi::xml_document m_doc; + + public: + MethodCall(const std::string& methodName) { + auto mCall = m_doc.append_child("methodCall"); + mCall.append_child("methodName").text().set(methodName.c_str()); + mCall.append_child("params"); + } + + Params getParams() const { + return Params(m_doc.child("methodCall").child("params")); + } + + std::string toString() const { + return nodeToString(m_doc); + } +}; + + +class MethodResponse { + pugi::xml_document m_doc; + + public: + MethodResponse(const std::string& content) { + m_doc.load_buffer(content.c_str(), content.size()); + } + + Params getParams() const { + auto params = m_doc.child("methodResponse").child("params"); + if (!params) + throw InvalidRPCNode("No params"); + return Params(params); + } + + Fault getFault() const { + auto fault = m_doc.child("methodResponse").child("fault"); + if (!fault) + throw InvalidRPCNode("No fault"); + return Fault(fault); + } +}; + + + +}; + + +#endif // KIWIX_XMLRPC_H_