cmWIXAccessControlList.cxx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 "cmWIXAccessControlList.h"
  4. #include <cm/string_view>
  5. #include "cmCPackGenerator.h"
  6. #include "cmStringAlgorithms.h"
  7. #include "cmSystemTools.h"
  8. cmWIXAccessControlList::cmWIXAccessControlList(
  9. cmCPackLog* logger, cmInstalledFile const& installedFile,
  10. cmWIXSourceWriter& sourceWriter)
  11. : Logger(logger)
  12. , InstalledFile(installedFile)
  13. , SourceWriter(sourceWriter)
  14. {
  15. }
  16. bool cmWIXAccessControlList::Apply()
  17. {
  18. auto entries = this->InstalledFile.GetPropertyAsList("CPACK_WIX_ACL");
  19. for (auto const& entry : entries) {
  20. this->CreatePermissionElement(entry);
  21. }
  22. return true;
  23. }
  24. void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry)
  25. {
  26. std::string::size_type pos = entry.find('=');
  27. if (pos == std::string::npos) {
  28. this->ReportError(entry, "Did not find mandatory '='");
  29. return;
  30. }
  31. cm::string_view enview(entry);
  32. cm::string_view user_and_domain = enview.substr(0, pos);
  33. cm::string_view permission_string = enview.substr(pos + 1);
  34. pos = user_and_domain.find('@');
  35. cm::string_view user;
  36. cm::string_view domain;
  37. if (pos != std::string::npos) {
  38. user = user_and_domain.substr(0, pos);
  39. domain = user_and_domain.substr(pos + 1);
  40. } else {
  41. user = user_and_domain;
  42. }
  43. this->SourceWriter.BeginElement("Permission");
  44. this->SourceWriter.AddAttribute("User", std::string(user));
  45. if (!domain.empty()) {
  46. this->SourceWriter.AddAttribute("Domain", std::string(domain));
  47. }
  48. for (auto permission :
  49. cmTokenizedView(permission_string, ',', cmTokenizerMode::New)) {
  50. this->EmitBooleanAttribute(entry, cmTrimWhitespace(permission));
  51. }
  52. this->SourceWriter.EndElement("Permission");
  53. }
  54. void cmWIXAccessControlList::ReportError(std::string const& entry,
  55. std::string const& message)
  56. {
  57. cmCPackLogger(cmCPackLog::LOG_ERROR,
  58. "Failed processing ACL entry '" << entry << "': " << message
  59. << std::endl);
  60. }
  61. bool cmWIXAccessControlList::IsBooleanAttribute(std::string const& name)
  62. {
  63. static const char* validAttributes[] = {
  64. /* clang-format needs this comment to break after the opening brace */
  65. "Append",
  66. "ChangePermission",
  67. "CreateChild",
  68. "CreateFile",
  69. "CreateLink",
  70. "CreateSubkeys",
  71. "Delete",
  72. "DeleteChild",
  73. "EnumerateSubkeys",
  74. "Execute",
  75. "FileAllRights",
  76. "GenericAll",
  77. "GenericExecute",
  78. "GenericRead",
  79. "GenericWrite",
  80. "Notify",
  81. "Read",
  82. "ReadAttributes",
  83. "ReadExtendedAttributes",
  84. "ReadPermission",
  85. "SpecificRightsAll",
  86. "Synchronize",
  87. "TakeOwnership",
  88. "Traverse",
  89. "Write",
  90. "WriteAttributes",
  91. "WriteExtendedAttributes",
  92. nullptr
  93. };
  94. size_t i = 0;
  95. while (validAttributes[i]) {
  96. if (name == validAttributes[i++]) {
  97. return true;
  98. }
  99. }
  100. return false;
  101. }
  102. void cmWIXAccessControlList::EmitBooleanAttribute(std::string const& entry,
  103. std::string const& name)
  104. {
  105. if (!this->IsBooleanAttribute(name)) {
  106. this->ReportError(entry,
  107. cmStrCat("Unknown boolean attribute '", name, '\''));
  108. }
  109. this->SourceWriter.AddAttribute(name, "yes");
  110. }