cmWIXSourceWriter.cxx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmWIXSourceWriter.h"
  4. #include <windows.h>
  5. #include "cmCPackGenerator.h"
  6. #include "cmUuid.h"
  7. cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger,
  8. std::string const& filename,
  9. GuidType componentGuidType,
  10. RootElementType rootElementType)
  11. : Logger(logger)
  12. , File(filename.c_str())
  13. , State(DEFAULT)
  14. , SourceFilename(filename)
  15. , ComponentGuidType(componentGuidType)
  16. {
  17. WriteXMLDeclaration();
  18. if (rootElementType == INCLUDE_ELEMENT_ROOT) {
  19. BeginElement("Include");
  20. } else {
  21. BeginElement("Wix");
  22. }
  23. AddAttribute("xmlns", "http://schemas.microsoft.com/wix/2006/wi");
  24. }
  25. cmWIXSourceWriter::~cmWIXSourceWriter()
  26. {
  27. if (Elements.size() > 1) {
  28. cmCPackLogger(cmCPackLog::LOG_ERROR,
  29. Elements.size() - 1
  30. << " WiX elements were still open when closing '"
  31. << SourceFilename << "'" << std::endl);
  32. return;
  33. }
  34. EndElement(Elements.back());
  35. }
  36. void cmWIXSourceWriter::BeginElement(std::string const& name)
  37. {
  38. if (State == BEGIN) {
  39. File << ">";
  40. }
  41. File << "\n";
  42. Indent(Elements.size());
  43. File << "<" << name;
  44. Elements.push_back(name);
  45. State = BEGIN;
  46. }
  47. void cmWIXSourceWriter::EndElement(std::string const& name)
  48. {
  49. if (Elements.empty()) {
  50. cmCPackLogger(cmCPackLog::LOG_ERROR,
  51. "can not end WiX element with no open elements in '"
  52. << SourceFilename << "'" << std::endl);
  53. return;
  54. }
  55. if (Elements.back() != name) {
  56. cmCPackLogger(cmCPackLog::LOG_ERROR,
  57. "WiX element <"
  58. << Elements.back() << "> can not be closed by </" << name
  59. << "> in '" << SourceFilename << "'" << std::endl);
  60. return;
  61. }
  62. if (State == DEFAULT) {
  63. File << "\n";
  64. Indent(Elements.size() - 1);
  65. File << "</" << Elements.back() << ">";
  66. } else {
  67. File << "/>";
  68. }
  69. Elements.pop_back();
  70. State = DEFAULT;
  71. }
  72. void cmWIXSourceWriter::AddTextNode(std::string const& text)
  73. {
  74. if (State == BEGIN) {
  75. File << ">";
  76. }
  77. if (Elements.empty()) {
  78. cmCPackLogger(cmCPackLog::LOG_ERROR,
  79. "can not add text without open WiX element in '"
  80. << SourceFilename << "'" << std::endl);
  81. return;
  82. }
  83. File << this->EscapeAttributeValue(text);
  84. State = DEFAULT;
  85. }
  86. void cmWIXSourceWriter::AddProcessingInstruction(std::string const& target,
  87. std::string const& content)
  88. {
  89. if (State == BEGIN) {
  90. File << ">";
  91. }
  92. File << "\n";
  93. Indent(Elements.size());
  94. File << "<?" << target << " " << content << "?>";
  95. State = DEFAULT;
  96. }
  97. void cmWIXSourceWriter::AddAttribute(std::string const& key,
  98. std::string const& value)
  99. {
  100. File << " " << key << "=\"" << EscapeAttributeValue(value) << '"';
  101. }
  102. void cmWIXSourceWriter::AddAttributeUnlessEmpty(std::string const& key,
  103. std::string const& value)
  104. {
  105. if (!value.empty()) {
  106. AddAttribute(key, value);
  107. }
  108. }
  109. std::string cmWIXSourceWriter::CreateGuidFromComponentId(
  110. std::string const& componentId)
  111. {
  112. std::string guid = "*";
  113. if (this->ComponentGuidType == CMAKE_GENERATED_GUID) {
  114. std::string md5 = cmSystemTools::ComputeStringMD5(componentId);
  115. cmUuid uuid;
  116. std::vector<unsigned char> ns;
  117. guid = uuid.FromMd5(ns, md5);
  118. }
  119. return guid;
  120. }
  121. void cmWIXSourceWriter::WriteXMLDeclaration()
  122. {
  123. File << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
  124. }
  125. void cmWIXSourceWriter::Indent(size_t count)
  126. {
  127. for (size_t i = 0; i < count; ++i) {
  128. File << " ";
  129. }
  130. }
  131. std::string cmWIXSourceWriter::EscapeAttributeValue(std::string const& value)
  132. {
  133. std::string result;
  134. result.reserve(value.size());
  135. for (char c : value) {
  136. switch (c) {
  137. case '<':
  138. result += "&lt;";
  139. break;
  140. case '>':
  141. result += "&gt;";
  142. break;
  143. case '&':
  144. result += "&amp;";
  145. break;
  146. case '"':
  147. result += "&quot;";
  148. break;
  149. default:
  150. result += c;
  151. break;
  152. }
  153. }
  154. return result;
  155. }