summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/xmlfile.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-09-06 01:41:44 +1000
committer Vas Crabb <vas@vastheman.com>2020-09-06 01:41:44 +1000
commit94601c77cc5b645a7738d634fb6e668dfd98d6db (patch)
treefeaddeac4cbb07e66f29cd3fd08c508a2a10339a /src/lib/util/xmlfile.cpp
parent080826aac441562e168fbd82eaa6bc27d2bd19a2 (diff)
-util/xmlfile: Escape attribute and element content.
The previous behaviour was unintuitive - parsing an XML file and writing it out immediately would produce invalid XML if the file contained any characters that needed escaping. It makes far more sense to escape on writing rather than expecting the user to escape input. -Add preliminary support for visibility toggles to artwork system. This allows the user to show/hide related elements in a view, with nesting. The view can specify whether elements are shown or hidden by default. Settings are saved per host window/screen per view. There is no way to set the initial visibility state on the command line. Legacy "Space Invaders cabinet model" layers are mapped onto visibility toggles. This is not stable yet. In particular, the XML element/attribute names have not been finalised. The new features have not been added to complay.py to prevent them from being used before they're finalised.
Diffstat (limited to 'src/lib/util/xmlfile.cpp')
-rw-r--r--src/lib/util/xmlfile.cpp46
1 files changed, 42 insertions, 4 deletions
diff --git a/src/lib/util/xmlfile.cpp b/src/lib/util/xmlfile.cpp
index ad4d4e1e8f8..af5f36fae0d 100644
--- a/src/lib/util/xmlfile.cpp
+++ b/src/lib/util/xmlfile.cpp
@@ -33,6 +33,37 @@ namespace {
constexpr unsigned TEMP_BUFFER_SIZE(4096U);
std::locale const f_portable_locale("C");
+
+/***************************************************************************
+ UTILITY FUNCTIONS
+***************************************************************************/
+
+void write_escaped(core_file &file, std::string const &str)
+{
+ std::string::size_type pos = 0;
+ while ((str.size() > pos) && (std::string::npos != pos))
+ {
+ std::string::size_type const found = str.find_first_of("\"&<>", pos);
+ if (found != std::string::npos)
+ {
+ file.write(&str[pos], found - pos);
+ switch (str[found])
+ {
+ case '"': file.puts("&quot;"); pos = found + 1; break;
+ case '&': file.puts("&amp;"); pos = found + 1; break;
+ case '<': file.puts("&lt;"); pos = found + 1; break;
+ case '>': file.puts("&gt;"); pos = found + 1; break;
+ default: pos = found;
+ }
+ }
+ else
+ {
+ file.write(&str[pos], str.size() - pos);
+ pos = found;
+ }
+ }
+}
+
} // anonymous namespace
@@ -950,9 +981,13 @@ void data_node::write_recursive(int indent, util::core_file &file) const
/* output this tag */
file.printf("%*s<%s", indent, "", get_name());
- /* output any attributes */
+ /* output any attributes, escaping as necessary */
for (attribute_node const &anode : m_attributes)
- file.printf(" %s=\"%s\"", anode.name, anode.value);
+ {
+ file.printf(" %s=\"", anode.name);
+ write_escaped(file, anode.value);
+ file.puts("\"");
+ }
if (!get_first_child() && !get_value())
{
@@ -965,8 +1000,11 @@ void data_node::write_recursive(int indent, util::core_file &file) const
file.printf(">\n");
/* if there is a value, output that here */
- if (get_value())
- file.printf("%*s%s\n", indent + 4, "", get_value());
+ if (!m_value.empty())
+ {
+ file.printf("%*s\n", indent + 4, "");
+ write_escaped(file, m_value);
+ }
/* loop over children and output them as well */
if (get_first_child())