10b57cec5SDimitry Andric //===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===---------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the .manifest merger class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===---------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/WindowsManifest/WindowsManifestMerger.h" 140b57cec5SDimitry Andric #include "llvm/Config/config.h" 150b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 160b57cec5SDimitry Andric 17e8d8bef9SDimitry Andric #if LLVM_ENABLE_LIBXML2 180b57cec5SDimitry Andric #include <libxml/xmlreader.h> 190b57cec5SDimitry Andric #endif 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X) 220b57cec5SDimitry Andric #define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X) 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace llvm; 250b57cec5SDimitry Andric using namespace windows_manifest; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric char WindowsManifestError::ID = 0; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {} 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; } 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric class WindowsManifestMerger::WindowsManifestMergerImpl { 340b57cec5SDimitry Andric public: 350b57cec5SDimitry Andric ~WindowsManifestMergerImpl(); 36349cc55cSDimitry Andric Error merge(MemoryBufferRef Manifest); 370b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> getMergedManifest(); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric private: 400b57cec5SDimitry Andric static void errorCallback(void *Ctx, const char *Format, ...); 410b57cec5SDimitry Andric Error getParseError(); 42e8d8bef9SDimitry Andric #if LLVM_ENABLE_LIBXML2 430b57cec5SDimitry Andric xmlDocPtr CombinedDoc = nullptr; 440b57cec5SDimitry Andric std::vector<xmlDocPtr> MergedDocs; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric bool Merged = false; 470b57cec5SDimitry Andric struct XmlDeleter { 480b57cec5SDimitry Andric void operator()(xmlChar *Ptr) { xmlFree(Ptr); } 490b57cec5SDimitry Andric void operator()(xmlDoc *Ptr) { xmlFreeDoc(Ptr); } 500b57cec5SDimitry Andric }; 510b57cec5SDimitry Andric int BufferSize = 0; 520b57cec5SDimitry Andric std::unique_ptr<xmlChar, XmlDeleter> Buffer; 530b57cec5SDimitry Andric #endif 540b57cec5SDimitry Andric bool ParseErrorOccurred = false; 550b57cec5SDimitry Andric }; 560b57cec5SDimitry Andric 57e8d8bef9SDimitry Andric #if LLVM_ENABLE_LIBXML2 580b57cec5SDimitry Andric 598bcb0991SDimitry Andric static constexpr std::pair<StringLiteral, StringLiteral> MtNsHrefsPrefixes[] = { 600b57cec5SDimitry Andric {"urn:schemas-microsoft-com:asm.v1", "ms_asmv1"}, 610b57cec5SDimitry Andric {"urn:schemas-microsoft-com:asm.v2", "ms_asmv2"}, 620b57cec5SDimitry Andric {"urn:schemas-microsoft-com:asm.v3", "ms_asmv3"}, 630b57cec5SDimitry Andric {"http://schemas.microsoft.com/SMI/2005/WindowsSettings", 640b57cec5SDimitry Andric "ms_windowsSettings"}, 650b57cec5SDimitry Andric {"urn:schemas-microsoft-com:compatibility.v1", "ms_compatibilityv1"}}; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric static bool xmlStringsEqual(const unsigned char *A, const unsigned char *B) { 680b57cec5SDimitry Andric // Handle null pointers. Comparison of 2 null pointers returns true because 690b57cec5SDimitry Andric // this indicates the prefix of a default namespace. 700b57cec5SDimitry Andric if (!A || !B) 710b57cec5SDimitry Andric return A == B; 720b57cec5SDimitry Andric return strcmp(FROM_XML_CHAR(A), FROM_XML_CHAR(B)) == 0; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric static bool isMergeableElement(const unsigned char *ElementName) { 760b57cec5SDimitry Andric for (StringRef S : {"application", "assembly", "assemblyIdentity", 770b57cec5SDimitry Andric "compatibility", "noInherit", "requestedExecutionLevel", 780b57cec5SDimitry Andric "requestedPrivileges", "security", "trustInfo"}) { 790b57cec5SDimitry Andric if (S == FROM_XML_CHAR(ElementName)) { 800b57cec5SDimitry Andric return true; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric return false; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric static xmlNodePtr getChildWithName(xmlNodePtr Parent, 870b57cec5SDimitry Andric const unsigned char *ElementName) { 880b57cec5SDimitry Andric for (xmlNodePtr Child = Parent->children; Child; Child = Child->next) { 890b57cec5SDimitry Andric if (xmlStringsEqual(Child->name, ElementName)) { 900b57cec5SDimitry Andric return Child; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric return nullptr; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric static xmlAttrPtr getAttribute(xmlNodePtr Node, 970b57cec5SDimitry Andric const unsigned char *AttributeName) { 980b57cec5SDimitry Andric for (xmlAttrPtr Attribute = Node->properties; Attribute != nullptr; 990b57cec5SDimitry Andric Attribute = Attribute->next) { 1000b57cec5SDimitry Andric if (xmlStringsEqual(Attribute->name, AttributeName)) { 1010b57cec5SDimitry Andric return Attribute; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric return nullptr; 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // Check if namespace specified by HRef1 overrides that of HRef2. 1080b57cec5SDimitry Andric static bool namespaceOverrides(const unsigned char *HRef1, 1090b57cec5SDimitry Andric const unsigned char *HRef2) { 1100b57cec5SDimitry Andric auto HRef1Position = llvm::find_if( 1110b57cec5SDimitry Andric MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) { 1120b57cec5SDimitry Andric return xmlStringsEqual(HRef1, TO_XML_CHAR(Element.first.data())); 1130b57cec5SDimitry Andric }); 1140b57cec5SDimitry Andric auto HRef2Position = llvm::find_if( 1150b57cec5SDimitry Andric MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) { 1160b57cec5SDimitry Andric return xmlStringsEqual(HRef2, TO_XML_CHAR(Element.first.data())); 1170b57cec5SDimitry Andric }); 1180b57cec5SDimitry Andric return HRef1Position < HRef2Position; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // Search for prefix-defined namespace specified by HRef, starting on Node and 1220b57cec5SDimitry Andric // continuing recursively upwards. Returns the namespace or nullptr if not 1230b57cec5SDimitry Andric // found. 1240b57cec5SDimitry Andric static xmlNsPtr search(const unsigned char *HRef, xmlNodePtr Node) { 1250b57cec5SDimitry Andric for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) { 1260b57cec5SDimitry Andric if (Def->prefix && xmlStringsEqual(Def->href, HRef)) { 1270b57cec5SDimitry Andric return Def; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric if (Node->parent) { 1310b57cec5SDimitry Andric return search(HRef, Node->parent); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric return nullptr; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric // Return the prefix that corresponds to the HRef. If HRef is not a recognized 1370b57cec5SDimitry Andric // URI, then just return the HRef itself to use as the prefix. 1380b57cec5SDimitry Andric static const unsigned char *getPrefixForHref(const unsigned char *HRef) { 1390b57cec5SDimitry Andric for (auto &Ns : MtNsHrefsPrefixes) { 1400b57cec5SDimitry Andric if (xmlStringsEqual(HRef, TO_XML_CHAR(Ns.first.data()))) { 1410b57cec5SDimitry Andric return TO_XML_CHAR(Ns.second.data()); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric return HRef; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // Search for prefix-defined namespace specified by HRef, starting on Node and 1480b57cec5SDimitry Andric // continuing recursively upwards. If it is found, then return it. If it is 1490b57cec5SDimitry Andric // not found, then prefix-define that namespace on the node and return a 1500b57cec5SDimitry Andric // reference to it. 1510b57cec5SDimitry Andric static Expected<xmlNsPtr> searchOrDefine(const unsigned char *HRef, 1520b57cec5SDimitry Andric xmlNodePtr Node) { 1530b57cec5SDimitry Andric if (xmlNsPtr Def = search(HRef, Node)) 1540b57cec5SDimitry Andric return Def; 1550b57cec5SDimitry Andric if (xmlNsPtr Def = xmlNewNs(Node, HRef, getPrefixForHref(HRef))) 1560b57cec5SDimitry Andric return Def; 1570b57cec5SDimitry Andric return make_error<WindowsManifestError>("failed to create new namespace"); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // Set the namespace of OrigionalAttribute on OriginalNode to be that of 1610b57cec5SDimitry Andric // AdditionalAttribute's. 1620b57cec5SDimitry Andric static Error copyAttributeNamespace(xmlAttrPtr OriginalAttribute, 1630b57cec5SDimitry Andric xmlNodePtr OriginalNode, 1640b57cec5SDimitry Andric xmlAttrPtr AdditionalAttribute) { 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric Expected<xmlNsPtr> ExplicitOrError = 1670b57cec5SDimitry Andric searchOrDefine(AdditionalAttribute->ns->href, OriginalNode); 1680b57cec5SDimitry Andric if (!ExplicitOrError) 1690b57cec5SDimitry Andric return ExplicitOrError.takeError(); 1700b57cec5SDimitry Andric OriginalAttribute->ns = std::move(ExplicitOrError.get()); 1710b57cec5SDimitry Andric return Error::success(); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric // Return the corresponding namespace definition for the prefix, defined on the 1750b57cec5SDimitry Andric // given Node. Returns nullptr if there is no such definition. 1760b57cec5SDimitry Andric static xmlNsPtr getNamespaceWithPrefix(const unsigned char *Prefix, 1770b57cec5SDimitry Andric xmlNodePtr Node) { 1780b57cec5SDimitry Andric if (Node == nullptr) 1790b57cec5SDimitry Andric return nullptr; 1800b57cec5SDimitry Andric for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) { 1810b57cec5SDimitry Andric if (xmlStringsEqual(Def->prefix, Prefix)) { 1820b57cec5SDimitry Andric return Def; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric return nullptr; 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric // Search for the closest inheritable default namespace, starting on (and 1890b57cec5SDimitry Andric // including) the Node and traveling upwards through parent nodes. Returns 1900b57cec5SDimitry Andric // nullptr if there are no inheritable default namespaces. 1910b57cec5SDimitry Andric static xmlNsPtr getClosestDefault(xmlNodePtr Node) { 1920b57cec5SDimitry Andric if (xmlNsPtr Ret = getNamespaceWithPrefix(nullptr, Node)) 1930b57cec5SDimitry Andric return Ret; 1940b57cec5SDimitry Andric if (Node->parent == nullptr) 1950b57cec5SDimitry Andric return nullptr; 1960b57cec5SDimitry Andric return getClosestDefault(Node->parent); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // Merge the attributes of AdditionalNode into OriginalNode. If attributes 2000b57cec5SDimitry Andric // with identical types are present, they are not duplicated but rather if 2010b57cec5SDimitry Andric // their values are not consistent and error is thrown. In addition, the 2020b57cec5SDimitry Andric // higher priority namespace is used for each attribute, EXCEPT in the case 2030b57cec5SDimitry Andric // of merging two default namespaces and the lower priority namespace 2040b57cec5SDimitry Andric // definition occurs closer than the higher priority one. 2050b57cec5SDimitry Andric static Error mergeAttributes(xmlNodePtr OriginalNode, 2060b57cec5SDimitry Andric xmlNodePtr AdditionalNode) { 2070b57cec5SDimitry Andric xmlNsPtr ClosestDefault = getClosestDefault(OriginalNode); 2080b57cec5SDimitry Andric for (xmlAttrPtr Attribute = AdditionalNode->properties; Attribute; 2090b57cec5SDimitry Andric Attribute = Attribute->next) { 2100b57cec5SDimitry Andric if (xmlAttrPtr OriginalAttribute = 2110b57cec5SDimitry Andric getAttribute(OriginalNode, Attribute->name)) { 2120b57cec5SDimitry Andric if (!xmlStringsEqual(OriginalAttribute->children->content, 2130b57cec5SDimitry Andric Attribute->children->content)) { 2140b57cec5SDimitry Andric return make_error<WindowsManifestError>( 2150b57cec5SDimitry Andric Twine("conflicting attributes for ") + 2160b57cec5SDimitry Andric FROM_XML_CHAR(OriginalNode->name)); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric if (!Attribute->ns) { 2190b57cec5SDimitry Andric continue; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric if (!OriginalAttribute->ns) { 2220b57cec5SDimitry Andric if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode, 2230b57cec5SDimitry Andric Attribute)) { 2240b57cec5SDimitry Andric return E; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric continue; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric if (namespaceOverrides(OriginalAttribute->ns->href, 2290b57cec5SDimitry Andric Attribute->ns->href)) { 2300b57cec5SDimitry Andric // In this case, the original attribute has a higher priority namespace 2310b57cec5SDimitry Andric // than the incomiing attribute, however the namespace definition of 2320b57cec5SDimitry Andric // the lower priority namespace occurs first traveling upwards in the 2330b57cec5SDimitry Andric // tree. Therefore the lower priority namespace is applied. 2340b57cec5SDimitry Andric if (!OriginalAttribute->ns->prefix && !Attribute->ns->prefix && 2350b57cec5SDimitry Andric ClosestDefault && 2360b57cec5SDimitry Andric xmlStringsEqual(Attribute->ns->href, ClosestDefault->href)) { 2370b57cec5SDimitry Andric if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode, 2380b57cec5SDimitry Andric Attribute)) { 2390b57cec5SDimitry Andric return E; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric continue; 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric continue; 2440b57cec5SDimitry Andric // This covers the case where the incoming attribute has the higher 2450b57cec5SDimitry Andric // priority. The higher priority namespace is applied in all cases 2460b57cec5SDimitry Andric // EXCEPT when both of the namespaces are default inherited, and the 2470b57cec5SDimitry Andric // closest inherited default is the lower priority one. 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric if (Attribute->ns->prefix || OriginalAttribute->ns->prefix || 2500b57cec5SDimitry Andric (ClosestDefault && !xmlStringsEqual(OriginalAttribute->ns->href, 2510b57cec5SDimitry Andric ClosestDefault->href))) { 2520b57cec5SDimitry Andric if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode, 2530b57cec5SDimitry Andric Attribute)) { 2540b57cec5SDimitry Andric return E; 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric continue; 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric continue; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric // If the incoming attribute is not already found on the node, append it 2610b57cec5SDimitry Andric // to the end of the properties list. Also explicitly apply its 2620b57cec5SDimitry Andric // namespace as a prefix because it might be contained in a separate 2630b57cec5SDimitry Andric // namespace that doesn't use the attribute. 2640b57cec5SDimitry Andric xmlAttrPtr NewProp = 2650b57cec5SDimitry Andric xmlNewProp(OriginalNode, Attribute->name, Attribute->children->content); 2660b57cec5SDimitry Andric Expected<xmlNsPtr> ExplicitOrError = 2670b57cec5SDimitry Andric searchOrDefine(Attribute->ns->href, OriginalNode); 2680b57cec5SDimitry Andric if (!ExplicitOrError) 2690b57cec5SDimitry Andric return ExplicitOrError.takeError(); 2700b57cec5SDimitry Andric NewProp->ns = std::move(ExplicitOrError.get()); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric return Error::success(); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric // Given two nodes, return the one with the higher priority namespace. 2760b57cec5SDimitry Andric static xmlNodePtr getDominantNode(xmlNodePtr Node1, xmlNodePtr Node2) { 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric if (!Node1 || !Node1->ns) 2790b57cec5SDimitry Andric return Node2; 2800b57cec5SDimitry Andric if (!Node2 || !Node2->ns) 2810b57cec5SDimitry Andric return Node1; 2820b57cec5SDimitry Andric if (namespaceOverrides(Node1->ns->href, Node2->ns->href)) 2830b57cec5SDimitry Andric return Node1; 2840b57cec5SDimitry Andric return Node2; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric // Checks if this Node's namespace is inherited or one it defined itself. 2880b57cec5SDimitry Andric static bool hasInheritedNs(xmlNodePtr Node) { 2890b57cec5SDimitry Andric return Node->ns && Node->ns != getNamespaceWithPrefix(Node->ns->prefix, Node); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric // Check if this Node's namespace is a default namespace that it inherited, as 2930b57cec5SDimitry Andric // opposed to defining itself. 2940b57cec5SDimitry Andric static bool hasInheritedDefaultNs(xmlNodePtr Node) { 2950b57cec5SDimitry Andric return hasInheritedNs(Node) && Node->ns->prefix == nullptr; 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // Check if this Node's namespace is a default namespace it defined itself. 2990b57cec5SDimitry Andric static bool hasDefinedDefaultNamespace(xmlNodePtr Node) { 3000b57cec5SDimitry Andric return Node->ns && (Node->ns == getNamespaceWithPrefix(nullptr, Node)); 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // For the given explicit prefix-definition of a namespace, travel downwards 3040b57cec5SDimitry Andric // from a node recursively, and for every implicit, inherited default usage of 3050b57cec5SDimitry Andric // that namespace replace it with that explicit prefix use. This is important 3060b57cec5SDimitry Andric // when namespace overriding occurs when merging, so that elements unique to a 3070b57cec5SDimitry Andric // namespace will still stay in that namespace. 3080b57cec5SDimitry Andric static void explicateNamespace(xmlNsPtr PrefixDef, xmlNodePtr Node) { 3090b57cec5SDimitry Andric // If a node as its own default namespace definition it clearly cannot have 3100b57cec5SDimitry Andric // inherited the given default namespace, and neither will any of its 3110b57cec5SDimitry Andric // children. 3120b57cec5SDimitry Andric if (hasDefinedDefaultNamespace(Node)) 3130b57cec5SDimitry Andric return; 3140b57cec5SDimitry Andric if (Node->ns && xmlStringsEqual(Node->ns->href, PrefixDef->href) && 3150b57cec5SDimitry Andric hasInheritedDefaultNs(Node)) 3160b57cec5SDimitry Andric Node->ns = PrefixDef; 3170b57cec5SDimitry Andric for (xmlAttrPtr Attribute = Node->properties; Attribute; 3180b57cec5SDimitry Andric Attribute = Attribute->next) { 3190b57cec5SDimitry Andric if (Attribute->ns && 3200b57cec5SDimitry Andric xmlStringsEqual(Attribute->ns->href, PrefixDef->href)) { 3210b57cec5SDimitry Andric Attribute->ns = PrefixDef; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric for (xmlNodePtr Child = Node->children; Child; Child = Child->next) { 3250b57cec5SDimitry Andric explicateNamespace(PrefixDef, Child); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric // Perform the namespace merge between two nodes. 3300b57cec5SDimitry Andric static Error mergeNamespaces(xmlNodePtr OriginalNode, 3310b57cec5SDimitry Andric xmlNodePtr AdditionalNode) { 3320b57cec5SDimitry Andric // Save the original default namespace definition in case the incoming node 3330b57cec5SDimitry Andric // overrides it. 3340b57cec5SDimitry Andric const unsigned char *OriginalDefinedDefaultHref = nullptr; 3350b57cec5SDimitry Andric if (xmlNsPtr OriginalDefinedDefaultNs = 3360b57cec5SDimitry Andric getNamespaceWithPrefix(nullptr, OriginalNode)) { 3370b57cec5SDimitry Andric OriginalDefinedDefaultHref = xmlStrdup(OriginalDefinedDefaultNs->href); 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric const unsigned char *NewDefinedDefaultHref = nullptr; 3400b57cec5SDimitry Andric // Copy all namespace definitions. There can only be one default namespace 3410b57cec5SDimitry Andric // definition per node, so the higher priority one takes precedence in the 3420b57cec5SDimitry Andric // case of collision. 3430b57cec5SDimitry Andric for (xmlNsPtr Def = AdditionalNode->nsDef; Def; Def = Def->next) { 3440b57cec5SDimitry Andric if (xmlNsPtr OriginalNsDef = 3450b57cec5SDimitry Andric getNamespaceWithPrefix(Def->prefix, OriginalNode)) { 3460b57cec5SDimitry Andric if (!Def->prefix) { 3470b57cec5SDimitry Andric if (namespaceOverrides(Def->href, OriginalNsDef->href)) { 3480b57cec5SDimitry Andric NewDefinedDefaultHref = TO_XML_CHAR(strdup(FROM_XML_CHAR(Def->href))); 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric } else if (!xmlStringsEqual(OriginalNsDef->href, Def->href)) { 3510b57cec5SDimitry Andric return make_error<WindowsManifestError>( 3520b57cec5SDimitry Andric Twine("conflicting namespace definitions for ") + 3530b57cec5SDimitry Andric FROM_XML_CHAR(Def->prefix)); 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric } else { 3560b57cec5SDimitry Andric xmlNsPtr NewDef = xmlCopyNamespace(Def); 3570b57cec5SDimitry Andric NewDef->next = OriginalNode->nsDef; 3580b57cec5SDimitry Andric OriginalNode->nsDef = NewDef; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric // Check whether the original node or the incoming node has the higher 3630b57cec5SDimitry Andric // priority namespace. Depending on which one is dominant, we will have 3640b57cec5SDimitry Andric // to recursively apply namespace changes down to children of the original 3650b57cec5SDimitry Andric // node. 3660b57cec5SDimitry Andric xmlNodePtr DominantNode = getDominantNode(OriginalNode, AdditionalNode); 3670b57cec5SDimitry Andric xmlNodePtr NonDominantNode = 3680b57cec5SDimitry Andric DominantNode == OriginalNode ? AdditionalNode : OriginalNode; 3690b57cec5SDimitry Andric if (DominantNode == OriginalNode) { 3700b57cec5SDimitry Andric if (OriginalDefinedDefaultHref) { 3710b57cec5SDimitry Andric xmlNsPtr NonDominantDefinedDefault = 3720b57cec5SDimitry Andric getNamespaceWithPrefix(nullptr, NonDominantNode); 3730b57cec5SDimitry Andric // In this case, both the nodes defined a default namespace. However 3740b57cec5SDimitry Andric // the lower priority node ended up having a higher priority default 3750b57cec5SDimitry Andric // definition. This can occur if the higher priority node is prefix 3760b57cec5SDimitry Andric // namespace defined. In this case we have to define an explicit 3770b57cec5SDimitry Andric // prefix for the overridden definition and apply it to all children 3780b57cec5SDimitry Andric // who relied on that definition. 3790b57cec5SDimitry Andric if (NonDominantDefinedDefault && 3800b57cec5SDimitry Andric namespaceOverrides(NonDominantDefinedDefault->href, 3810b57cec5SDimitry Andric OriginalDefinedDefaultHref)) { 3820b57cec5SDimitry Andric Expected<xmlNsPtr> EC = 3830b57cec5SDimitry Andric searchOrDefine(OriginalDefinedDefaultHref, DominantNode); 3840b57cec5SDimitry Andric if (!EC) { 3850b57cec5SDimitry Andric return EC.takeError(); 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric xmlNsPtr PrefixDominantDefinedDefault = std::move(EC.get()); 3880b57cec5SDimitry Andric explicateNamespace(PrefixDominantDefinedDefault, DominantNode); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric // In this case the node with a higher priority namespace did not have a 3910b57cec5SDimitry Andric // default namespace definition, but the lower priority node did. In this 3920b57cec5SDimitry Andric // case the new default namespace definition is copied. A side effect of 3930b57cec5SDimitry Andric // this is that all children will suddenly find themselves in a different 3940b57cec5SDimitry Andric // default namespace. To maintain correctness we need to ensure that all 3950b57cec5SDimitry Andric // children now explicitly refer to the namespace that they had previously 3960b57cec5SDimitry Andric // implicitly inherited. 3970b57cec5SDimitry Andric } else if (getNamespaceWithPrefix(nullptr, NonDominantNode)) { 3980b57cec5SDimitry Andric if (DominantNode->parent) { 3990b57cec5SDimitry Andric xmlNsPtr ClosestDefault = getClosestDefault(DominantNode->parent); 4000b57cec5SDimitry Andric Expected<xmlNsPtr> EC = 4010b57cec5SDimitry Andric searchOrDefine(ClosestDefault->href, DominantNode); 4020b57cec5SDimitry Andric if (!EC) { 4030b57cec5SDimitry Andric return EC.takeError(); 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric xmlNsPtr ExplicitDefault = std::move(EC.get()); 4060b57cec5SDimitry Andric explicateNamespace(ExplicitDefault, DominantNode); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric } else { 4100b57cec5SDimitry Andric // Covers case where the incoming node has a default namespace definition 4110b57cec5SDimitry Andric // that overrides the original node's namespace. This always leads to 4120b57cec5SDimitry Andric // the original node receiving that new default namespace. 4130b57cec5SDimitry Andric if (hasDefinedDefaultNamespace(DominantNode)) { 4140b57cec5SDimitry Andric NonDominantNode->ns = getNamespaceWithPrefix(nullptr, NonDominantNode); 4150b57cec5SDimitry Andric } else { 4160b57cec5SDimitry Andric // This covers the case where the incoming node either has a prefix 4170b57cec5SDimitry Andric // namespace, or an inherited default namespace. Since the namespace 4180b57cec5SDimitry Andric // may not yet be defined in the original tree we do a searchOrDefine 4190b57cec5SDimitry Andric // for it, and then set the namespace equal to it. 4200b57cec5SDimitry Andric Expected<xmlNsPtr> EC = 4210b57cec5SDimitry Andric searchOrDefine(DominantNode->ns->href, NonDominantNode); 4220b57cec5SDimitry Andric if (!EC) { 4230b57cec5SDimitry Andric return EC.takeError(); 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric xmlNsPtr Explicit = std::move(EC.get()); 4260b57cec5SDimitry Andric NonDominantNode->ns = Explicit; 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric // This covers cases where the incoming dominant node HAS a default 4290b57cec5SDimitry Andric // namespace definition, but MIGHT NOT NECESSARILY be in that namespace. 4300b57cec5SDimitry Andric if (xmlNsPtr DominantDefaultDefined = 4310b57cec5SDimitry Andric getNamespaceWithPrefix(nullptr, DominantNode)) { 4320b57cec5SDimitry Andric if (OriginalDefinedDefaultHref) { 4330b57cec5SDimitry Andric if (namespaceOverrides(DominantDefaultDefined->href, 4340b57cec5SDimitry Andric OriginalDefinedDefaultHref)) { 4350b57cec5SDimitry Andric // In this case, the incoming node's default definition overrides 4360b57cec5SDimitry Andric // the original default definition, all children who relied on that 4370b57cec5SDimitry Andric // definition must be updated accordingly. 4380b57cec5SDimitry Andric Expected<xmlNsPtr> EC = 4390b57cec5SDimitry Andric searchOrDefine(OriginalDefinedDefaultHref, NonDominantNode); 4400b57cec5SDimitry Andric if (!EC) { 4410b57cec5SDimitry Andric return EC.takeError(); 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric xmlNsPtr ExplicitDefault = std::move(EC.get()); 4440b57cec5SDimitry Andric explicateNamespace(ExplicitDefault, NonDominantNode); 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric } else { 4470b57cec5SDimitry Andric // The original did not define a default definition, however the new 4480b57cec5SDimitry Andric // default definition still applies to all children, so they must be 4490b57cec5SDimitry Andric // updated to explicitly refer to the namespace they had previously 4500b57cec5SDimitry Andric // been inheriting implicitly. 4510b57cec5SDimitry Andric xmlNsPtr ClosestDefault = getClosestDefault(NonDominantNode); 4520b57cec5SDimitry Andric Expected<xmlNsPtr> EC = 4530b57cec5SDimitry Andric searchOrDefine(ClosestDefault->href, NonDominantNode); 4540b57cec5SDimitry Andric if (!EC) { 4550b57cec5SDimitry Andric return EC.takeError(); 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric xmlNsPtr ExplicitDefault = std::move(EC.get()); 4580b57cec5SDimitry Andric explicateNamespace(ExplicitDefault, NonDominantNode); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric if (NewDefinedDefaultHref) { 4630b57cec5SDimitry Andric xmlNsPtr OriginalNsDef = getNamespaceWithPrefix(nullptr, OriginalNode); 4640b57cec5SDimitry Andric xmlFree(const_cast<unsigned char *>(OriginalNsDef->href)); 4650b57cec5SDimitry Andric OriginalNsDef->href = NewDefinedDefaultHref; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric xmlFree(const_cast<unsigned char *>(OriginalDefinedDefaultHref)); 4680b57cec5SDimitry Andric return Error::success(); 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric static bool isRecognizedNamespace(const unsigned char *NsHref) { 4720b57cec5SDimitry Andric for (auto &Ns : MtNsHrefsPrefixes) { 4730b57cec5SDimitry Andric if (xmlStringsEqual(NsHref, TO_XML_CHAR(Ns.first.data()))) { 4740b57cec5SDimitry Andric return true; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric return false; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric static bool hasRecognizedNamespace(xmlNodePtr Node) { 4810b57cec5SDimitry Andric return isRecognizedNamespace(Node->ns->href); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric // Ensure a node's inherited namespace is actually defined in the tree it 4850b57cec5SDimitry Andric // resides in. 4860b57cec5SDimitry Andric static Error reconcileNamespaces(xmlNodePtr Node) { 4870b57cec5SDimitry Andric if (!Node) { 4880b57cec5SDimitry Andric return Error::success(); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric if (hasInheritedNs(Node)) { 4910b57cec5SDimitry Andric Expected<xmlNsPtr> ExplicitOrError = searchOrDefine(Node->ns->href, Node); 4920b57cec5SDimitry Andric if (!ExplicitOrError) { 4930b57cec5SDimitry Andric return ExplicitOrError.takeError(); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric xmlNsPtr Explicit = std::move(ExplicitOrError.get()); 4960b57cec5SDimitry Andric Node->ns = Explicit; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric for (xmlNodePtr Child = Node->children; Child; Child = Child->next) { 4990b57cec5SDimitry Andric if (auto E = reconcileNamespaces(Child)) { 5000b57cec5SDimitry Andric return E; 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric return Error::success(); 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric // Recursively merge the two given manifest trees, depending on which elements 5070b57cec5SDimitry Andric // are of a mergeable type, and choose namespaces according to which have 5080b57cec5SDimitry Andric // higher priority. 5090b57cec5SDimitry Andric static Error treeMerge(xmlNodePtr OriginalRoot, xmlNodePtr AdditionalRoot) { 5100b57cec5SDimitry Andric if (auto E = mergeAttributes(OriginalRoot, AdditionalRoot)) 5110b57cec5SDimitry Andric return E; 5120b57cec5SDimitry Andric if (auto E = mergeNamespaces(OriginalRoot, AdditionalRoot)) 5130b57cec5SDimitry Andric return E; 5140b57cec5SDimitry Andric xmlNodePtr AdditionalFirstChild = AdditionalRoot->children; 5150b57cec5SDimitry Andric xmlNode StoreNext; 5160b57cec5SDimitry Andric for (xmlNodePtr Child = AdditionalFirstChild; Child; Child = Child->next) { 5170b57cec5SDimitry Andric xmlNodePtr OriginalChildWithName; 5180b57cec5SDimitry Andric if (!isMergeableElement(Child->name) || 5190b57cec5SDimitry Andric !(OriginalChildWithName = 5200b57cec5SDimitry Andric getChildWithName(OriginalRoot, Child->name)) || 5210b57cec5SDimitry Andric !hasRecognizedNamespace(Child)) { 5220b57cec5SDimitry Andric StoreNext.next = Child->next; 5230b57cec5SDimitry Andric xmlUnlinkNode(Child); 5240b57cec5SDimitry Andric if (!xmlAddChild(OriginalRoot, Child)) { 5250b57cec5SDimitry Andric return make_error<WindowsManifestError>(Twine("could not merge ") + 5260b57cec5SDimitry Andric FROM_XML_CHAR(Child->name)); 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric if (auto E = reconcileNamespaces(Child)) { 5290b57cec5SDimitry Andric return E; 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric Child = &StoreNext; 5320b57cec5SDimitry Andric } else if (auto E = treeMerge(OriginalChildWithName, Child)) { 5330b57cec5SDimitry Andric return E; 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric return Error::success(); 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric static void stripComments(xmlNodePtr Root) { 5400b57cec5SDimitry Andric xmlNode StoreNext; 5410b57cec5SDimitry Andric for (xmlNodePtr Child = Root->children; Child; Child = Child->next) { 5420b57cec5SDimitry Andric if (!xmlStringsEqual(Child->name, TO_XML_CHAR("comment"))) { 5430b57cec5SDimitry Andric stripComments(Child); 5440b57cec5SDimitry Andric continue; 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric StoreNext.next = Child->next; 5470b57cec5SDimitry Andric xmlNodePtr Remove = Child; 5480b57cec5SDimitry Andric Child = &StoreNext; 5490b57cec5SDimitry Andric xmlUnlinkNode(Remove); 5500b57cec5SDimitry Andric xmlFreeNode(Remove); 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric // libxml2 assumes that attributes do not inherit default namespaces, whereas 5550b57cec5SDimitry Andric // the original mt.exe does make this assumption. This function reconciles 5560b57cec5SDimitry Andric // this by setting all attributes to have the inherited default namespace. 5570b57cec5SDimitry Andric static void setAttributeNamespaces(xmlNodePtr Node) { 5580b57cec5SDimitry Andric for (xmlAttrPtr Attribute = Node->properties; Attribute; 5590b57cec5SDimitry Andric Attribute = Attribute->next) { 5600b57cec5SDimitry Andric if (!Attribute->ns) { 5610b57cec5SDimitry Andric Attribute->ns = getClosestDefault(Node); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric for (xmlNodePtr Child = Node->children; Child; Child = Child->next) { 5650b57cec5SDimitry Andric setAttributeNamespaces(Child); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric // The merging process may create too many prefix defined namespaces. This 5700b57cec5SDimitry Andric // function removes all unnecessary ones from the tree. 5710b57cec5SDimitry Andric static void checkAndStripPrefixes(xmlNodePtr Node, 5720b57cec5SDimitry Andric std::vector<xmlNsPtr> &RequiredPrefixes) { 5730b57cec5SDimitry Andric for (xmlNodePtr Child = Node->children; Child; Child = Child->next) { 5740b57cec5SDimitry Andric checkAndStripPrefixes(Child, RequiredPrefixes); 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric if (Node->ns && Node->ns->prefix != nullptr) { 5770b57cec5SDimitry Andric xmlNsPtr ClosestDefault = getClosestDefault(Node); 5780b57cec5SDimitry Andric if (ClosestDefault && 5790b57cec5SDimitry Andric xmlStringsEqual(ClosestDefault->href, Node->ns->href)) { 5800b57cec5SDimitry Andric Node->ns = ClosestDefault; 5810b57cec5SDimitry Andric } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) { 5820b57cec5SDimitry Andric RequiredPrefixes.push_back(Node->ns); 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric for (xmlAttrPtr Attribute = Node->properties; Attribute; 5860b57cec5SDimitry Andric Attribute = Attribute->next) { 5870b57cec5SDimitry Andric if (Attribute->ns && Attribute->ns->prefix != nullptr) { 5880b57cec5SDimitry Andric xmlNsPtr ClosestDefault = getClosestDefault(Node); 5890b57cec5SDimitry Andric if (ClosestDefault && 5900b57cec5SDimitry Andric xmlStringsEqual(ClosestDefault->href, Attribute->ns->href)) { 5910b57cec5SDimitry Andric Attribute->ns = ClosestDefault; 5920b57cec5SDimitry Andric } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) { 5930b57cec5SDimitry Andric RequiredPrefixes.push_back(Attribute->ns); 5940b57cec5SDimitry Andric } 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric xmlNsPtr Prev; 5980b57cec5SDimitry Andric xmlNs Temp; 5990b57cec5SDimitry Andric for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) { 6000b57cec5SDimitry Andric if (!Def->prefix || llvm::is_contained(RequiredPrefixes, Def)) { 6010b57cec5SDimitry Andric Prev = Def; 6020b57cec5SDimitry Andric continue; 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric if (Def == Node->nsDef) { 6050b57cec5SDimitry Andric Node->nsDef = Def->next; 6060b57cec5SDimitry Andric } else { 6070b57cec5SDimitry Andric Prev->next = Def->next; 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric Temp.next = Def->next; 6100b57cec5SDimitry Andric xmlFreeNs(Def); 6110b57cec5SDimitry Andric Def = &Temp; 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() { 6160b57cec5SDimitry Andric for (auto &Doc : MergedDocs) 6170b57cec5SDimitry Andric xmlFreeDoc(Doc); 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric Error WindowsManifestMerger::WindowsManifestMergerImpl::merge( 621349cc55cSDimitry Andric MemoryBufferRef Manifest) { 6220b57cec5SDimitry Andric if (Merged) 6230b57cec5SDimitry Andric return make_error<WindowsManifestError>( 6240b57cec5SDimitry Andric "merge after getMergedManifest is not supported"); 6250b57cec5SDimitry Andric if (Manifest.getBufferSize() == 0) 6260b57cec5SDimitry Andric return make_error<WindowsManifestError>( 6270b57cec5SDimitry Andric "attempted to merge empty manifest"); 6280b57cec5SDimitry Andric xmlSetGenericErrorFunc((void *)this, 6290b57cec5SDimitry Andric WindowsManifestMergerImpl::errorCallback); 6300b57cec5SDimitry Andric xmlDocPtr ManifestXML = xmlReadMemory( 6310b57cec5SDimitry Andric Manifest.getBufferStart(), Manifest.getBufferSize(), "manifest.xml", 6320b57cec5SDimitry Andric nullptr, XML_PARSE_NOBLANKS | XML_PARSE_NODICT); 6330b57cec5SDimitry Andric xmlSetGenericErrorFunc(nullptr, nullptr); 6340b57cec5SDimitry Andric if (auto E = getParseError()) 6350b57cec5SDimitry Andric return E; 6360b57cec5SDimitry Andric xmlNodePtr AdditionalRoot = xmlDocGetRootElement(ManifestXML); 6370b57cec5SDimitry Andric stripComments(AdditionalRoot); 6380b57cec5SDimitry Andric setAttributeNamespaces(AdditionalRoot); 6390b57cec5SDimitry Andric if (CombinedDoc == nullptr) { 6400b57cec5SDimitry Andric CombinedDoc = ManifestXML; 6410b57cec5SDimitry Andric } else { 6420b57cec5SDimitry Andric xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc); 6430b57cec5SDimitry Andric if (!xmlStringsEqual(CombinedRoot->name, AdditionalRoot->name) || 6440b57cec5SDimitry Andric !isMergeableElement(AdditionalRoot->name) || 6450b57cec5SDimitry Andric !hasRecognizedNamespace(AdditionalRoot)) { 6460b57cec5SDimitry Andric return make_error<WindowsManifestError>("multiple root nodes"); 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric if (auto E = treeMerge(CombinedRoot, AdditionalRoot)) { 6490b57cec5SDimitry Andric return E; 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric MergedDocs.push_back(ManifestXML); 6530b57cec5SDimitry Andric return Error::success(); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> 6570b57cec5SDimitry Andric WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() { 6580b57cec5SDimitry Andric if (!Merged) { 6590b57cec5SDimitry Andric Merged = true; 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric if (!CombinedDoc) 6620b57cec5SDimitry Andric return nullptr; 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc); 6650b57cec5SDimitry Andric std::vector<xmlNsPtr> RequiredPrefixes; 6660b57cec5SDimitry Andric checkAndStripPrefixes(CombinedRoot, RequiredPrefixes); 6670b57cec5SDimitry Andric std::unique_ptr<xmlDoc, XmlDeleter> OutputDoc( 6680b57cec5SDimitry Andric xmlNewDoc((const unsigned char *)"1.0")); 6690b57cec5SDimitry Andric xmlDocSetRootElement(OutputDoc.get(), CombinedRoot); 67004eeddc0SDimitry Andric assert(nullptr == xmlDocGetRootElement(CombinedDoc)); 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric xmlKeepBlanksDefault(0); 6730b57cec5SDimitry Andric xmlChar *Buff = nullptr; 6740b57cec5SDimitry Andric xmlDocDumpFormatMemoryEnc(OutputDoc.get(), &Buff, &BufferSize, "UTF-8", 1); 6750b57cec5SDimitry Andric Buffer.reset(Buff); 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric return BufferSize ? MemoryBuffer::getMemBufferCopy(StringRef( 6790b57cec5SDimitry Andric FROM_XML_CHAR(Buffer.get()), (size_t)BufferSize)) 6800b57cec5SDimitry Andric : nullptr; 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric bool windows_manifest::isAvailable() { return true; } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric #else 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() { 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric Error WindowsManifestMerger::WindowsManifestMergerImpl::merge( 691349cc55cSDimitry Andric MemoryBufferRef Manifest) { 6920b57cec5SDimitry Andric return make_error<WindowsManifestError>("no libxml2"); 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> 6960b57cec5SDimitry Andric WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() { 6970b57cec5SDimitry Andric return nullptr; 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric bool windows_manifest::isAvailable() { return false; } 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric #endif 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric WindowsManifestMerger::WindowsManifestMerger() 7058bcb0991SDimitry Andric : Impl(std::make_unique<WindowsManifestMergerImpl>()) {} 7060b57cec5SDimitry Andric 707*81ad6265SDimitry Andric WindowsManifestMerger::~WindowsManifestMerger() = default; 7080b57cec5SDimitry Andric 709349cc55cSDimitry Andric Error WindowsManifestMerger::merge(MemoryBufferRef Manifest) { 7100b57cec5SDimitry Andric return Impl->merge(Manifest); 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> WindowsManifestMerger::getMergedManifest() { 7140b57cec5SDimitry Andric return Impl->getMergedManifest(); 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric void WindowsManifestMerger::WindowsManifestMergerImpl::errorCallback( 7180b57cec5SDimitry Andric void *Ctx, const char *Format, ...) { 7190b57cec5SDimitry Andric auto *Merger = (WindowsManifestMergerImpl *)Ctx; 7200b57cec5SDimitry Andric Merger->ParseErrorOccurred = true; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric Error WindowsManifestMerger::WindowsManifestMergerImpl::getParseError() { 7240b57cec5SDimitry Andric if (!ParseErrorOccurred) 7250b57cec5SDimitry Andric return Error::success(); 7260b57cec5SDimitry Andric return make_error<WindowsManifestError>("invalid xml document"); 7270b57cec5SDimitry Andric } 728