diff options
Diffstat (limited to 'Source/CPack/WiX/cmWIXSourceWriter.cxx')
-rw-r--r-- | Source/CPack/WiX/cmWIXSourceWriter.cxx | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx new file mode 100644 index 0000000..6adf80b --- /dev/null +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -0,0 +1,184 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmWIXSourceWriter.h" + +#include "cmCPackGenerator.h" + +#include "cmUuid.h" + +#include <windows.h> + +cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger, + std::string const& filename, + GuidType componentGuidType, + RootElementType rootElementType) + : Logger(logger) + , File(filename.c_str()) + , State(DEFAULT) + , SourceFilename(filename) + , ComponentGuidType(componentGuidType) +{ + WriteXMLDeclaration(); + + if (rootElementType == INCLUDE_ELEMENT_ROOT) { + BeginElement("Include"); + } else { + BeginElement("Wix"); + } + + AddAttribute("xmlns", "http://schemas.microsoft.com/wix/2006/wi"); +} + +cmWIXSourceWriter::~cmWIXSourceWriter() +{ + if (Elements.size() > 1) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + Elements.size() - 1 + << " WiX elements were still open when closing '" + << SourceFilename << "'" << std::endl); + return; + } + + EndElement(Elements.back()); +} + +void cmWIXSourceWriter::BeginElement(std::string const& name) +{ + if (State == BEGIN) { + File << ">"; + } + + File << "\n"; + Indent(Elements.size()); + File << "<" << name; + + Elements.push_back(name); + State = BEGIN; +} + +void cmWIXSourceWriter::EndElement(std::string const& name) +{ + if (Elements.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "can not end WiX element with no open elements in '" + << SourceFilename << "'" << std::endl); + return; + } + + if (Elements.back() != name) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "WiX element <" + << Elements.back() << "> can not be closed by </" << name + << "> in '" << SourceFilename << "'" << std::endl); + return; + } + + if (State == DEFAULT) { + File << "\n"; + Indent(Elements.size() - 1); + File << "</" << Elements.back() << ">"; + } else { + File << "/>"; + } + + Elements.pop_back(); + State = DEFAULT; +} + +void cmWIXSourceWriter::AddTextNode(std::string const& text) +{ + if (State == BEGIN) { + File << ">"; + } + + if (Elements.empty()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "can not add text without open WiX element in '" + << SourceFilename << "'" << std::endl); + return; + } + + File << this->EscapeAttributeValue(text); + State = DEFAULT; +} + +void cmWIXSourceWriter::AddProcessingInstruction(std::string const& target, + std::string const& content) +{ + if (State == BEGIN) { + File << ">"; + } + + File << "\n"; + Indent(Elements.size()); + File << "<?" << target << " " << content << "?>"; + + State = DEFAULT; +} + +void cmWIXSourceWriter::AddAttribute(std::string const& key, + std::string const& value) +{ + File << " " << key << "=\"" << EscapeAttributeValue(value) << '"'; +} + +void cmWIXSourceWriter::AddAttributeUnlessEmpty(std::string const& key, + std::string const& value) +{ + if (!value.empty()) { + AddAttribute(key, value); + } +} + +std::string cmWIXSourceWriter::CreateGuidFromComponentId( + std::string const& componentId) +{ + std::string guid = "*"; + if (this->ComponentGuidType == CMAKE_GENERATED_GUID) { + std::string md5 = cmSystemTools::ComputeStringMD5(componentId); + cmUuid uuid; + std::vector<unsigned char> ns; + guid = uuid.FromMd5(ns, md5); + } + return guid; +} + +void cmWIXSourceWriter::WriteXMLDeclaration() +{ + File << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl; +} + +void cmWIXSourceWriter::Indent(size_t count) +{ + for (size_t i = 0; i < count; ++i) { + File << " "; + } +} + +std::string cmWIXSourceWriter::EscapeAttributeValue(std::string const& value) +{ + std::string result; + result.reserve(value.size()); + + for (char c : value) { + switch (c) { + case '<': + result += "<"; + break; + case '>': + result += ">"; + break; + case '&': + result += "&"; + break; + case '"': + result += """; + break; + default: + result += c; + break; + } + } + + return result; +} |