cmWIXAccessControlList.cxx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2014 Kitware, Inc.
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmWIXAccessControlList.h"
  11. #include <CPack/cmCPackGenerator.h>
  12. #include <cmSystemTools.h>
  13. cmWIXAccessControlList::cmWIXAccessControlList(
  14. cmCPackLog* logger, cmInstalledFile const& installedFile,
  15. cmWIXSourceWriter& sourceWriter)
  16. : Logger(logger)
  17. , InstalledFile(installedFile)
  18. , SourceWriter(sourceWriter)
  19. {
  20. }
  21. bool cmWIXAccessControlList::Apply()
  22. {
  23. std::vector<std::string> entries;
  24. this->InstalledFile.GetPropertyAsList("CPACK_WIX_ACL", entries);
  25. for (size_t i = 0; i < entries.size(); ++i) {
  26. this->CreatePermissionElement(entries[i]);
  27. }
  28. return true;
  29. }
  30. void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry)
  31. {
  32. std::string::size_type pos = entry.find('=');
  33. if (pos == std::string::npos) {
  34. this->ReportError(entry, "Did not find mandatory '='");
  35. return;
  36. }
  37. std::string user_and_domain = entry.substr(0, pos);
  38. std::string permission_string = entry.substr(pos + 1);
  39. pos = user_and_domain.find('@');
  40. std::string user;
  41. std::string domain;
  42. if (pos != std::string::npos) {
  43. user = user_and_domain.substr(0, pos);
  44. domain = user_and_domain.substr(pos + 1);
  45. } else {
  46. user = user_and_domain;
  47. }
  48. std::vector<std::string> permissions =
  49. cmSystemTools::tokenize(permission_string, ",");
  50. this->SourceWriter.BeginElement("Permission");
  51. this->SourceWriter.AddAttribute("User", user);
  52. if (!domain.empty()) {
  53. this->SourceWriter.AddAttribute("Domain", domain);
  54. }
  55. for (size_t i = 0; i < permissions.size(); ++i) {
  56. this->EmitBooleanAttribute(entry,
  57. cmSystemTools::TrimWhitespace(permissions[i]));
  58. }
  59. this->SourceWriter.EndElement("Permission");
  60. }
  61. void cmWIXAccessControlList::ReportError(std::string const& entry,
  62. std::string const& message)
  63. {
  64. cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed processing ACL entry '"
  65. << entry << "': " << message << std::endl);
  66. }
  67. bool cmWIXAccessControlList::IsBooleanAttribute(std::string const& name)
  68. {
  69. static const char* validAttributes[] = {
  70. /* clang-format needs this comment to break after the opening brace */
  71. "Append",
  72. "ChangePermission",
  73. "CreateChild",
  74. "CreateFile",
  75. "CreateLink",
  76. "CreateSubkeys",
  77. "Delete",
  78. "DeleteChild",
  79. "EnumerateSubkeys",
  80. "Execute",
  81. "FileAllRights",
  82. "GenericAll",
  83. "GenericExecute",
  84. "GenericRead",
  85. "GenericWrite",
  86. "Notify",
  87. "Read",
  88. "ReadAttributes",
  89. "ReadExtendedAttributes",
  90. "ReadPermission",
  91. "SpecificRightsAll",
  92. "Synchronize",
  93. "TakeOwnership",
  94. "Traverse",
  95. "Write",
  96. "WriteAttributes",
  97. "WriteExtendedAttributes",
  98. 0
  99. };
  100. size_t i = 0;
  101. while (validAttributes[i]) {
  102. if (name == validAttributes[i++])
  103. return true;
  104. }
  105. return false;
  106. }
  107. void cmWIXAccessControlList::EmitBooleanAttribute(std::string const& entry,
  108. std::string const& name)
  109. {
  110. if (!this->IsBooleanAttribute(name)) {
  111. std::stringstream message;
  112. message << "Unknown boolean attribute '" << name << "'";
  113. this->ReportError(entry, message.str());
  114. }
  115. this->SourceWriter.AddAttribute(name, "yes");
  116. }