From a561607fac3378538f3913cbce0c669e51904160 Mon Sep 17 00:00:00 2001 From: Dmitry Degtyarev Date: Mon, 7 Sep 2020 17:15:22 +0400 Subject: [PATCH] load gpo xml schema attributes --- src/gpgui/CMakeLists.txt | 10 +- src/gpgui/gui/MainWindow.cpp | 3 + src/gpgui/gui/xml_editor.cpp | 173 +++++++++++++++++++++++++++++------ src/gpgui/gui/xml_editor.h | 20 ++++ 4 files changed, 177 insertions(+), 29 deletions(-) diff --git a/src/gpgui/CMakeLists.txt b/src/gpgui/CMakeLists.txt index b3b907ec..ef77097b 100644 --- a/src/gpgui/CMakeLists.txt +++ b/src/gpgui/CMakeLists.txt @@ -11,7 +11,12 @@ if(SYSTEM_NAME STREQUAL "FreeBSD") set(Iconv_IS_BUILT_IN FALSE) endif() -find_package(Qt5 REQUIRED COMPONENTS Core Widgets) +find_package(Qt5 REQUIRED + COMPONENTS + Core + Widgets + Xml +) find_package(Smbclient REQUIRED) if(NOT Iconv_IS_BUILT_IN) find_package(Iconv) # For libgptbackend @@ -40,7 +45,8 @@ endif() target_link_libraries(gpgui PRIVATE Qt5::Core - Qt5::Widgets + Qt5::Widgets + Qt5::Xml gptbackend Smbclient::Smbclient ) diff --git a/src/gpgui/gui/MainWindow.cpp b/src/gpgui/gui/MainWindow.cpp index 23e4a7fd..b952e1be 100644 --- a/src/gpgui/gui/MainWindow.cpp +++ b/src/gpgui/gui/MainWindow.cpp @@ -18,6 +18,7 @@ */ #include "config.h" #include "browse_widget.h" +#include "xml_editor.h" #include #include @@ -107,6 +108,8 @@ MainWindow::MainWindow(const QString &path) // NOTE: default dir for testing browse_widget->change_target("/home/kevl/pol-files/{2BE174FB-22F4-4CD1-BA93-5311F87E80A2}"); + + XmlEditor::load_schema(); } void MainWindow::about() { diff --git a/src/gpgui/gui/xml_editor.cpp b/src/gpgui/gui/xml_editor.cpp index a6a027be..449f4a12 100644 --- a/src/gpgui/gui/xml_editor.cpp +++ b/src/gpgui/gui/xml_editor.cpp @@ -24,10 +24,130 @@ #include #include #include +#include + +const QHash attribute_type_to_string = { + {AttributeType_String, "string"}, + {AttributeType_Boolean, "boolean"}, + {AttributeType_UnsignedByte, "unsignedByte"} +}; + +QList XmlEditor::schema_attributes; + +AttributeType string_to_attribute_type(const QString string_raw) { + auto generate_string_to_attribute_type_map = + []() -> QHash { + QHash result; + + for (auto type : attribute_type_to_string.keys()) { + const QString string = attribute_type_to_string[type]; + result.insert(string, type); + } + + return result; + }; + static QHash string_to_attribute_type_map = generate_string_to_attribute_type_map(); + + QString string = string_raw; + if (string.contains("xs:")) { + string.remove("xs:"); + } + + const AttributeType type = string_to_attribute_type_map.value(string, AttributeType_None); + + return type; +} + +void XmlEditor::load_schema() { + static bool loaded = false; + if (loaded) { + return; + } else { + loaded = true; + } + + QFile file("../shortcuts_xml_schema.xml"); + const bool open_success = file.open(QIODevice::ReadOnly | QIODevice::Text); + if (!open_success) { + printf("Failed to open xml file\n"); + return; + } + + QDomDocument doc("schema"); + doc.setContent(&file); + + file.close(); + + QDomNode root = doc.namedItem("Properties"); + QDomNodeList node_list = root.childNodes(); + for (int i = 0; i < node_list.size(); i++) { + printf("=%s\n", qPrintable(node_list.at(i).nodeValue())); + } + + // NOTE: there are two things that are called "attributes" in this context, the nodes which are named "xs:attribute" and the attributes of those nodes + QDomNodeList attributes = doc.elementsByTagName("xs:attribute"); + for (int i = 0; i < attributes.size(); i++) { + const QDomNode node = attributes.at(i); + + GpoXmlAttribute gpo_attribute; + + // Recurse through all ancestors of node and check if any of them have an attribute "name" set to "Properties" + auto is_child_of_properties = + [node]() -> bool { + QDomNode current = node.parentNode(); + + while (!current.isNull()) { + const QDomNamedNodeMap node_attributes = current.attributes(); + const QDomNode name_node = node_attributes.namedItem("name"); + if (!name_node.isNull()) { + const QString this_name = name_node.nodeValue(); + + if (this_name == "Properties") { + return true; + } + } + + const QDomNode new_current = current.parentNode(); + + if (new_current == current) { + // Reached top node + return false; + } else { + current = new_current; + } + } + + return false; + }; + + gpo_attribute.properties = is_child_of_properties(); + + const QDomNamedNodeMap xml_attribs = node.attributes(); + + const QDomNode xml_name = xml_attribs.namedItem("name"); + gpo_attribute.name = xml_name.nodeValue(); + + const QDomNode xml_use = xml_attribs.namedItem("use"); + gpo_attribute.required = (xml_use.nodeValue() == "required"); + + QDomNode xml_type = xml_attribs.namedItem("type"); + gpo_attribute.type = string_to_attribute_type(xml_type.nodeValue()); + + printf("attribute\n"); + printf(" name=%s\n", qPrintable(gpo_attribute.name)); + printf(" type=%s\n", qPrintable(attribute_type_to_string[gpo_attribute.type])); + printf(" required=%d\n", gpo_attribute.required); + printf(" properties=%d\n", gpo_attribute.properties); + + schema_attributes.append(gpo_attribute); + } +} XmlEditor::XmlEditor(const QString &path) : QDialog() { + load_schema(); + setAttribute(Qt::WA_DeleteOnClose); resize(300, 600); @@ -48,39 +168,38 @@ XmlEditor::XmlEditor(const QString &path) button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); - QFile file(path); - const bool open_success = file.open(QIODevice::ReadOnly | QIODevice::Text); - if (!open_success) { - printf("Failed to open xml file\n"); - return; - } + { + QFile file(path); + const bool open_success = file.open(QIODevice::ReadOnly | QIODevice::Text); + if (!open_success) { + printf("Failed to open xml file\n"); + return; + } - const QByteArray file_byte_array = file.readAll(); - const QString file_string(file_byte_array); + const QByteArray file_byte_array = file.readAll(); + const QString file_string(file_byte_array); - QXmlStreamReader xml(file_string); + QXmlStreamReader xml(file_string); - while (!xml.atEnd()) { - const QXmlStreamReader::TokenType token_type = xml.readNext(); + while (!xml.atEnd()) { + const QXmlStreamReader::TokenType token_type = xml.readNext(); - switch (token_type) { - case QXmlStreamReader::StartElement: { - if (xml.name() == "Properties") { - const QXmlStreamAttributes attributes = xml.attributes(); + switch (token_type) { + case QXmlStreamReader::StartElement: { + if (xml.name() == "Properties") { + const QXmlStreamAttributes attributes = xml.attributes(); - for (const QXmlStreamAttribute attribute : attributes) { - printf("%s=%s\n", qPrintable(attribute.name().toString()), qPrintable(attribute.value().toString())); + for (const QXmlStreamAttribute attribute : attributes) { + printf("%s=%s\n", qPrintable(attribute.name().toString()), qPrintable(attribute.value().toString())); + } } + + break; } - - break; - } - default: { - break; - } - } - } - if (xml.hasError()) { - + default: { + break; + } + } + } } } diff --git a/src/gpgui/gui/xml_editor.h b/src/gpgui/gui/xml_editor.h index c106bf1e..3f9146ba 100644 --- a/src/gpgui/gui/xml_editor.h +++ b/src/gpgui/gui/xml_editor.h @@ -22,12 +22,32 @@ #include #include +#include + +enum AttributeType { + AttributeType_String, + AttributeType_Boolean, + AttributeType_UnsignedByte, + AttributeType_None +}; + +class GpoXmlAttribute { +public: + QString name; + AttributeType type; + bool required; + bool properties; +}; class XmlEditor final : public QDialog { Q_OBJECT public: + static QList schema_attributes; + XmlEditor(const QString &path); + + static void load_schema(); }; #endif /* XML_EDITOR_H */