//===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===---------------------------------------------------------------------===//
//
// This file implements the .manifest merger class.
//
//===---------------------------------------------------------------------===//

#include "llvm/WindowsManifest/WindowsManifestMerger.h"
#include "llvm/Config/config.h"
#include "llvm/Support/MemoryBuffer.h"

#if LLVM_ENABLE_LIBXML2
#include <libxml/xmlreader.h>
#endif

#define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X)
#define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X)

using namespace llvm;
using namespace windows_manifest;

char WindowsManifestError::ID = 0;

WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}

void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }

class WindowsManifestMerger::WindowsManifestMergerImpl {
public:
  ~WindowsManifestMergerImpl();
  Error merge(MemoryBufferRef Manifest);
  std::unique_ptr<MemoryBuffer> getMergedManifest();

private:
  static void errorCallback(void *Ctx, const char *Format, ...);
  Error getParseError();
#if LLVM_ENABLE_LIBXML2
  xmlDocPtr CombinedDoc = nullptr;
  std::vector<xmlDocPtr> MergedDocs;

  bool Merged = false;
  struct XmlDeleter {
    void operator()(xmlChar *Ptr) { xmlFree(Ptr); }
    void operator()(xmlDoc *Ptr) { xmlFreeDoc(Ptr); }
  };
  int BufferSize = 0;
  std::unique_ptr<xmlChar, XmlDeleter> Buffer;
#endif
  bool ParseErrorOccurred = false;
};

#if LLVM_ENABLE_LIBXML2

static constexpr std::pair<StringLiteral, StringLiteral> MtNsHrefsPrefixes[] = {
    {"urn:schemas-microsoft-com:asm.v1", "ms_asmv1"},
    {"urn:schemas-microsoft-com:asm.v2", "ms_asmv2"},
    {"urn:schemas-microsoft-com:asm.v3", "ms_asmv3"},
    {"http://schemas.microsoft.com/SMI/2005/WindowsSettings",
     "ms_windowsSettings"},
    {"urn:schemas-microsoft-com:compatibility.v1", "ms_compatibilityv1"}};

static bool xmlStringsEqual(const unsigned char *A, const unsigned char *B) {
  // Handle null pointers.  Comparison of 2 null pointers returns true because
  // this indicates the prefix of a default namespace.
  if (!A || !B)
    return A == B;
  return strcmp(FROM_XML_CHAR(A), FROM_XML_CHAR(B)) == 0;
}

static bool isMergeableElement(const unsigned char *ElementName) {
  for (StringRef S : {"application", "assembly", "assemblyIdentity",
                      "compatibility", "noInherit", "requestedExecutionLevel",
                      "requestedPrivileges", "security", "trustInfo"}) {
    if (S == FROM_XML_CHAR(ElementName)) {
      return true;
    }
  }
  return false;
}

static xmlNodePtr getChildWithName(xmlNodePtr Parent,
                                   const unsigned char *ElementName) {
  for (xmlNodePtr Child = Parent->children; Child; Child = Child->next) {
    if (xmlStringsEqual(Child->name, ElementName)) {
      return Child;
    }
  }
  return nullptr;
}

static xmlAttrPtr getAttribute(xmlNodePtr Node,
                               const unsigned char *AttributeName) {
  for (xmlAttrPtr Attribute = Node->properties; Attribute != nullptr;
       Attribute = Attribute->next) {
    if (xmlStringsEqual(Attribute->name, AttributeName)) {
      return Attribute;
    }
  }
  return nullptr;
}

// Check if namespace specified by HRef1 overrides that of HRef2.
static bool namespaceOverrides(const unsigned char *HRef1,
                               const unsigned char *HRef2) {
  auto HRef1Position = llvm::find_if(
      MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) {
        return xmlStringsEqual(HRef1, TO_XML_CHAR(Element.first.data()));
      });
  auto HRef2Position = llvm::find_if(
      MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) {
        return xmlStringsEqual(HRef2, TO_XML_CHAR(Element.first.data()));
      });
  return HRef1Position < HRef2Position;
}

// Search for prefix-defined namespace specified by HRef, starting on Node and
// continuing recursively upwards.  Returns the namespace or nullptr if not
// found.
static xmlNsPtr search(const unsigned char *HRef, xmlNodePtr Node) {
  for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
    if (Def->prefix && xmlStringsEqual(Def->href, HRef)) {
      return Def;
    }
  }
  if (Node->parent) {
    return search(HRef, Node->parent);
  }
  return nullptr;
}

// Return the prefix that corresponds to the HRef.  If HRef is not a recognized
// URI, then just return the HRef itself to use as the prefix.
static const unsigned char *getPrefixForHref(const unsigned char *HRef) {
  for (auto &Ns : MtNsHrefsPrefixes) {
    if (xmlStringsEqual(HRef, TO_XML_CHAR(Ns.first.data()))) {
      return TO_XML_CHAR(Ns.second.data());
    }
  }
  return HRef;
}

// Search for prefix-defined namespace specified by HRef, starting on Node and
// continuing recursively upwards.  If it is found, then return it.  If it is
// not found, then prefix-define that namespace on the node and return a
// reference to it.
static Expected<xmlNsPtr> searchOrDefine(const unsigned char *HRef,
                                         xmlNodePtr Node) {
  if (xmlNsPtr Def = search(HRef, Node))
    return Def;
  if (xmlNsPtr Def = xmlNewNs(Node, HRef, getPrefixForHref(HRef)))
    return Def;
  return make_error<WindowsManifestError>("failed to create new namespace");
}

// Set the namespace of OrigionalAttribute on OriginalNode to be that of
// AdditionalAttribute's.
static Error copyAttributeNamespace(xmlAttrPtr OriginalAttribute,
                                    xmlNodePtr OriginalNode,
                                    xmlAttrPtr AdditionalAttribute) {

  Expected<xmlNsPtr> ExplicitOrError =
      searchOrDefine(AdditionalAttribute->ns->href, OriginalNode);
  if (!ExplicitOrError)
    return ExplicitOrError.takeError();
  OriginalAttribute->ns = std::move(ExplicitOrError.get());
  return Error::success();
}

// Return the corresponding namespace definition for the prefix, defined on the
// given Node.  Returns nullptr if there is no such definition.
static xmlNsPtr getNamespaceWithPrefix(const unsigned char *Prefix,
                                       xmlNodePtr Node) {
  if (Node == nullptr)
    return nullptr;
  for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
    if (xmlStringsEqual(Def->prefix, Prefix)) {
      return Def;
    }
  }
  return nullptr;
}

// Search for the closest inheritable default namespace, starting on (and
// including) the Node and traveling upwards through parent nodes.  Returns
// nullptr if there are no inheritable default namespaces.
static xmlNsPtr getClosestDefault(xmlNodePtr Node) {
  if (xmlNsPtr Ret = getNamespaceWithPrefix(nullptr, Node))
    return Ret;
  if (Node->parent == nullptr)
    return nullptr;
  return getClosestDefault(Node->parent);
}

// Merge the attributes of AdditionalNode into OriginalNode.  If attributes
// with identical types are present, they are not duplicated but rather if
// their values are not consistent and error is thrown.  In addition, the
// higher priority namespace is used for each attribute, EXCEPT in the case
// of merging two default namespaces and the lower priority namespace
// definition occurs closer than the higher priority one.
static Error mergeAttributes(xmlNodePtr OriginalNode,
                             xmlNodePtr AdditionalNode) {
  xmlNsPtr ClosestDefault = getClosestDefault(OriginalNode);
  for (xmlAttrPtr Attribute = AdditionalNode->properties; Attribute;
       Attribute = Attribute->next) {
    if (xmlAttrPtr OriginalAttribute =
            getAttribute(OriginalNode, Attribute->name)) {
      if (!xmlStringsEqual(OriginalAttribute->children->content,
                           Attribute->children->content)) {
        return make_error<WindowsManifestError>(
            Twine("conflicting attributes for ") +
            FROM_XML_CHAR(OriginalNode->name));
      }
      if (!Attribute->ns) {
        continue;
      }
      if (!OriginalAttribute->ns) {
        if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
                                            Attribute)) {
          return E;
        }
        continue;
      }
      if (namespaceOverrides(OriginalAttribute->ns->href,
                             Attribute->ns->href)) {
        // In this case, the original attribute has a higher priority namespace
        // than the incomiing attribute, however the namespace definition of
        // the lower priority namespace occurs first traveling upwards in the
        // tree.  Therefore the lower priority namespace is applied.
        if (!OriginalAttribute->ns->prefix && !Attribute->ns->prefix &&
            ClosestDefault &&
            xmlStringsEqual(Attribute->ns->href, ClosestDefault->href)) {
          if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
                                              Attribute)) {
            return E;
          }
          continue;
        }
        continue;
        // This covers the case where the incoming attribute has the higher
        // priority.  The higher priority namespace is applied in all cases
        // EXCEPT when both of the namespaces are default inherited, and the
        // closest inherited default is the lower priority one.
      }
      if (Attribute->ns->prefix || OriginalAttribute->ns->prefix ||
          (ClosestDefault && !xmlStringsEqual(OriginalAttribute->ns->href,
                                              ClosestDefault->href))) {
        if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
                                            Attribute)) {
          return E;
        }
        continue;
      }
      continue;
    }
    // If the incoming attribute is not already found on the node, append it
    // to the end of the properties list.  Also explicitly apply its
    // namespace as a prefix because it might be contained in a separate
    // namespace that doesn't use the attribute.
    xmlAttrPtr NewProp =
        xmlNewProp(OriginalNode, Attribute->name, Attribute->children->content);
    Expected<xmlNsPtr> ExplicitOrError =
        searchOrDefine(Attribute->ns->href, OriginalNode);
    if (!ExplicitOrError)
      return ExplicitOrError.takeError();
    NewProp->ns = std::move(ExplicitOrError.get());
  }
  return Error::success();
}

// Given two nodes, return the one with the higher priority namespace.
static xmlNodePtr getDominantNode(xmlNodePtr Node1, xmlNodePtr Node2) {

  if (!Node1 || !Node1->ns)
    return Node2;
  if (!Node2 || !Node2->ns)
    return Node1;
  if (namespaceOverrides(Node1->ns->href, Node2->ns->href))
    return Node1;
  return Node2;
}

// Checks if this Node's namespace is inherited or one it defined itself.
static bool hasInheritedNs(xmlNodePtr Node) {
  return Node->ns && Node->ns != getNamespaceWithPrefix(Node->ns->prefix, Node);
}

// Check if this Node's namespace is a default namespace that it inherited, as
// opposed to defining itself.
static bool hasInheritedDefaultNs(xmlNodePtr Node) {
  return hasInheritedNs(Node) && Node->ns->prefix == nullptr;
}

// Check if this Node's namespace is a default namespace it defined itself.
static bool hasDefinedDefaultNamespace(xmlNodePtr Node) {
  return Node->ns && (Node->ns == getNamespaceWithPrefix(nullptr, Node));
}

// For the given explicit prefix-definition of a namespace, travel downwards
// from a node recursively, and for every implicit, inherited default usage of
// that namespace replace it with that explicit prefix use.  This is important
// when namespace overriding occurs when merging, so that elements unique to a
// namespace will still stay in that namespace.
static void explicateNamespace(xmlNsPtr PrefixDef, xmlNodePtr Node) {
  // If a node as its own default namespace definition it clearly cannot have
  // inherited the given default namespace, and neither will any of its
  // children.
  if (hasDefinedDefaultNamespace(Node))
    return;
  if (Node->ns && xmlStringsEqual(Node->ns->href, PrefixDef->href) &&
      hasInheritedDefaultNs(Node))
    Node->ns = PrefixDef;
  for (xmlAttrPtr Attribute = Node->properties; Attribute;
       Attribute = Attribute->next) {
    if (Attribute->ns &&
        xmlStringsEqual(Attribute->ns->href, PrefixDef->href)) {
      Attribute->ns = PrefixDef;
    }
  }
  for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    explicateNamespace(PrefixDef, Child);
  }
}

// Perform the namespace merge between two nodes.
static Error mergeNamespaces(xmlNodePtr OriginalNode,
                             xmlNodePtr AdditionalNode) {
  // Save the original default namespace definition in case the incoming node
  // overrides it.
  const unsigned char *OriginalDefinedDefaultHref = nullptr;
  if (xmlNsPtr OriginalDefinedDefaultNs =
          getNamespaceWithPrefix(nullptr, OriginalNode)) {
    OriginalDefinedDefaultHref = xmlStrdup(OriginalDefinedDefaultNs->href);
  }
  const unsigned char *NewDefinedDefaultHref = nullptr;
  // Copy all namespace definitions.  There can only be one default namespace
  // definition per node, so the higher priority one takes precedence in the
  // case of collision.
  for (xmlNsPtr Def = AdditionalNode->nsDef; Def; Def = Def->next) {
    if (xmlNsPtr OriginalNsDef =
            getNamespaceWithPrefix(Def->prefix, OriginalNode)) {
      if (!Def->prefix) {
        if (namespaceOverrides(Def->href, OriginalNsDef->href)) {
          NewDefinedDefaultHref = TO_XML_CHAR(strdup(FROM_XML_CHAR(Def->href)));
        }
      } else if (!xmlStringsEqual(OriginalNsDef->href, Def->href)) {
        return make_error<WindowsManifestError>(
            Twine("conflicting namespace definitions for ") +
            FROM_XML_CHAR(Def->prefix));
      }
    } else {
      xmlNsPtr NewDef = xmlCopyNamespace(Def);
      NewDef->next = OriginalNode->nsDef;
      OriginalNode->nsDef = NewDef;
    }
  }

  // Check whether the original node or the incoming node has the higher
  // priority namespace.  Depending on which one is dominant, we will have
  // to recursively apply namespace changes down to children of the original
  // node.
  xmlNodePtr DominantNode = getDominantNode(OriginalNode, AdditionalNode);
  xmlNodePtr NonDominantNode =
      DominantNode == OriginalNode ? AdditionalNode : OriginalNode;
  if (DominantNode == OriginalNode) {
    if (OriginalDefinedDefaultHref) {
      xmlNsPtr NonDominantDefinedDefault =
          getNamespaceWithPrefix(nullptr, NonDominantNode);
      // In this case, both the nodes defined a default namespace.  However
      // the lower priority node ended up having a higher priority default
      // definition.  This can occur if the higher priority node is prefix
      // namespace defined.  In this case we have to define an explicit
      // prefix for the overridden definition and apply it to all children
      // who relied on that definition.
      if (NonDominantDefinedDefault &&
          namespaceOverrides(NonDominantDefinedDefault->href,
                             OriginalDefinedDefaultHref)) {
        Expected<xmlNsPtr> EC =
            searchOrDefine(OriginalDefinedDefaultHref, DominantNode);
        if (!EC) {
          return EC.takeError();
        }
        xmlNsPtr PrefixDominantDefinedDefault = std::move(EC.get());
        explicateNamespace(PrefixDominantDefinedDefault, DominantNode);
      }
      // In this case the node with a higher priority namespace did not have a
      // default namespace definition, but the lower priority node did.  In this
      // case the new default namespace definition is copied.  A side effect of
      // this is that all children will suddenly find themselves in a different
      // default namespace.  To maintain correctness we need to ensure that all
      // children now explicitly refer to the namespace that they had previously
      // implicitly inherited.
    } else if (getNamespaceWithPrefix(nullptr, NonDominantNode)) {
      if (DominantNode->parent) {
        xmlNsPtr ClosestDefault = getClosestDefault(DominantNode->parent);
        Expected<xmlNsPtr> EC =
            searchOrDefine(ClosestDefault->href, DominantNode);
        if (!EC) {
          return EC.takeError();
        }
        xmlNsPtr ExplicitDefault = std::move(EC.get());
        explicateNamespace(ExplicitDefault, DominantNode);
      }
    }
  } else {
    // Covers case where the incoming node has a default namespace definition
    // that overrides the original node's namespace.  This always leads to
    // the original node receiving that new default namespace.
    if (hasDefinedDefaultNamespace(DominantNode)) {
      NonDominantNode->ns = getNamespaceWithPrefix(nullptr, NonDominantNode);
    } else {
      // This covers the case where the incoming node either has a prefix
      // namespace, or an inherited default namespace.  Since the namespace
      // may not yet be defined in the original tree we do a searchOrDefine
      // for it, and then set the namespace equal to it.
      Expected<xmlNsPtr> EC =
          searchOrDefine(DominantNode->ns->href, NonDominantNode);
      if (!EC) {
        return EC.takeError();
      }
      xmlNsPtr Explicit = std::move(EC.get());
      NonDominantNode->ns = Explicit;
    }
    // This covers cases where the incoming dominant node HAS a default
    // namespace definition, but MIGHT NOT NECESSARILY be in that namespace.
    if (xmlNsPtr DominantDefaultDefined =
            getNamespaceWithPrefix(nullptr, DominantNode)) {
      if (OriginalDefinedDefaultHref) {
        if (namespaceOverrides(DominantDefaultDefined->href,
                               OriginalDefinedDefaultHref)) {
          // In this case, the incoming node's default definition overrides
          // the original default definition, all children who relied on that
          // definition must be updated accordingly.
          Expected<xmlNsPtr> EC =
              searchOrDefine(OriginalDefinedDefaultHref, NonDominantNode);
          if (!EC) {
            return EC.takeError();
          }
          xmlNsPtr ExplicitDefault = std::move(EC.get());
          explicateNamespace(ExplicitDefault, NonDominantNode);
        }
      } else {
        // The original did not define a default definition, however the new
        // default definition still applies to all children, so they must be
        // updated to explicitly refer to the namespace they had previously
        // been inheriting implicitly.
        xmlNsPtr ClosestDefault = getClosestDefault(NonDominantNode);
        Expected<xmlNsPtr> EC =
            searchOrDefine(ClosestDefault->href, NonDominantNode);
        if (!EC) {
          return EC.takeError();
        }
        xmlNsPtr ExplicitDefault = std::move(EC.get());
        explicateNamespace(ExplicitDefault, NonDominantNode);
      }
    }
  }
  if (NewDefinedDefaultHref) {
    xmlNsPtr OriginalNsDef = getNamespaceWithPrefix(nullptr, OriginalNode);
    xmlFree(const_cast<unsigned char *>(OriginalNsDef->href));
    OriginalNsDef->href = NewDefinedDefaultHref;
  }
  xmlFree(const_cast<unsigned char *>(OriginalDefinedDefaultHref));
  return Error::success();
}

static bool isRecognizedNamespace(const unsigned char *NsHref) {
  for (auto &Ns : MtNsHrefsPrefixes) {
    if (xmlStringsEqual(NsHref, TO_XML_CHAR(Ns.first.data()))) {
      return true;
    }
  }
  return false;
}

static bool hasRecognizedNamespace(xmlNodePtr Node) {
  return isRecognizedNamespace(Node->ns->href);
}

// Ensure a node's inherited namespace is actually defined in the tree it
// resides in.
static Error reconcileNamespaces(xmlNodePtr Node) {
  if (!Node) {
    return Error::success();
  }
  if (hasInheritedNs(Node)) {
    Expected<xmlNsPtr> ExplicitOrError = searchOrDefine(Node->ns->href, Node);
    if (!ExplicitOrError) {
      return ExplicitOrError.takeError();
    }
    xmlNsPtr Explicit = std::move(ExplicitOrError.get());
    Node->ns = Explicit;
  }
  for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    if (auto E = reconcileNamespaces(Child)) {
      return E;
    }
  }
  return Error::success();
}

// Recursively merge the two given manifest trees, depending on which elements
// are of a mergeable type, and choose namespaces according to which have
// higher priority.
static Error treeMerge(xmlNodePtr OriginalRoot, xmlNodePtr AdditionalRoot) {
  if (auto E = mergeAttributes(OriginalRoot, AdditionalRoot))
    return E;
  if (auto E = mergeNamespaces(OriginalRoot, AdditionalRoot))
    return E;
  xmlNodePtr AdditionalFirstChild = AdditionalRoot->children;
  xmlNode StoreNext;
  for (xmlNodePtr Child = AdditionalFirstChild; Child; Child = Child->next) {
    xmlNodePtr OriginalChildWithName;
    if (!isMergeableElement(Child->name) ||
        !(OriginalChildWithName =
              getChildWithName(OriginalRoot, Child->name)) ||
        !hasRecognizedNamespace(Child)) {
      StoreNext.next = Child->next;
      xmlUnlinkNode(Child);
      if (!xmlAddChild(OriginalRoot, Child)) {
        return make_error<WindowsManifestError>(Twine("could not merge ") +
                                                FROM_XML_CHAR(Child->name));
      }
      if (auto E = reconcileNamespaces(Child)) {
        return E;
      }
      Child = &StoreNext;
    } else if (auto E = treeMerge(OriginalChildWithName, Child)) {
      return E;
    }
  }
  return Error::success();
}

static void stripComments(xmlNodePtr Root) {
  xmlNode StoreNext;
  for (xmlNodePtr Child = Root->children; Child; Child = Child->next) {
    if (!xmlStringsEqual(Child->name, TO_XML_CHAR("comment"))) {
      stripComments(Child);
      continue;
    }
    StoreNext.next = Child->next;
    xmlNodePtr Remove = Child;
    Child = &StoreNext;
    xmlUnlinkNode(Remove);
    xmlFreeNode(Remove);
  }
}

// libxml2 assumes that attributes do not inherit default namespaces, whereas
// the original  mt.exe does make this assumption.  This function reconciles
// this by setting all attributes to have the inherited default namespace.
static void setAttributeNamespaces(xmlNodePtr Node) {
  for (xmlAttrPtr Attribute = Node->properties; Attribute;
       Attribute = Attribute->next) {
    if (!Attribute->ns) {
      Attribute->ns = getClosestDefault(Node);
    }
  }
  for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    setAttributeNamespaces(Child);
  }
}

// The merging process may create too many prefix defined namespaces.  This
// function removes all unnecessary ones from the tree.
static void checkAndStripPrefixes(xmlNodePtr Node,
                                  std::vector<xmlNsPtr> &RequiredPrefixes) {
  for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    checkAndStripPrefixes(Child, RequiredPrefixes);
  }
  if (Node->ns && Node->ns->prefix != nullptr) {
    xmlNsPtr ClosestDefault = getClosestDefault(Node);
    if (ClosestDefault &&
        xmlStringsEqual(ClosestDefault->href, Node->ns->href)) {
      Node->ns = ClosestDefault;
    } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) {
      RequiredPrefixes.push_back(Node->ns);
    }
  }
  for (xmlAttrPtr Attribute = Node->properties; Attribute;
       Attribute = Attribute->next) {
    if (Attribute->ns && Attribute->ns->prefix != nullptr) {
      xmlNsPtr ClosestDefault = getClosestDefault(Node);
      if (ClosestDefault &&
          xmlStringsEqual(ClosestDefault->href, Attribute->ns->href)) {
        Attribute->ns = ClosestDefault;
      } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) {
        RequiredPrefixes.push_back(Attribute->ns);
      }
    }
  }
  xmlNsPtr Prev;
  xmlNs Temp;
  for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
    if (!Def->prefix || llvm::is_contained(RequiredPrefixes, Def)) {
      Prev = Def;
      continue;
    }
    if (Def == Node->nsDef) {
      Node->nsDef = Def->next;
    } else {
      Prev->next = Def->next;
    }
    Temp.next = Def->next;
    xmlFreeNs(Def);
    Def = &Temp;
  }
}

WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
  for (auto &Doc : MergedDocs)
    xmlFreeDoc(Doc);
}

Error WindowsManifestMerger::WindowsManifestMergerImpl::merge(
    MemoryBufferRef Manifest) {
  if (Merged)
    return make_error<WindowsManifestError>(
        "merge after getMergedManifest is not supported");
  if (Manifest.getBufferSize() == 0)
    return make_error<WindowsManifestError>(
        "attempted to merge empty manifest");
  xmlSetGenericErrorFunc((void *)this,
                         WindowsManifestMergerImpl::errorCallback);
  xmlDocPtr ManifestXML = xmlReadMemory(
      Manifest.getBufferStart(), Manifest.getBufferSize(), "manifest.xml",
      nullptr, XML_PARSE_NOBLANKS | XML_PARSE_NODICT);
  xmlSetGenericErrorFunc(nullptr, nullptr);
  if (auto E = getParseError())
    return E;
  xmlNodePtr AdditionalRoot = xmlDocGetRootElement(ManifestXML);
  stripComments(AdditionalRoot);
  setAttributeNamespaces(AdditionalRoot);
  if (CombinedDoc == nullptr) {
    CombinedDoc = ManifestXML;
  } else {
    xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc);
    if (!xmlStringsEqual(CombinedRoot->name, AdditionalRoot->name) ||
        !isMergeableElement(AdditionalRoot->name) ||
        !hasRecognizedNamespace(AdditionalRoot)) {
      return make_error<WindowsManifestError>("multiple root nodes");
    }
    if (auto E = treeMerge(CombinedRoot, AdditionalRoot)) {
      return E;
    }
  }
  MergedDocs.push_back(ManifestXML);
  return Error::success();
}

std::unique_ptr<MemoryBuffer>
WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
  if (!Merged) {
    Merged = true;

    if (!CombinedDoc)
      return nullptr;

    xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc);
    std::vector<xmlNsPtr> RequiredPrefixes;
    checkAndStripPrefixes(CombinedRoot, RequiredPrefixes);
    std::unique_ptr<xmlDoc, XmlDeleter> OutputDoc(
        xmlNewDoc((const unsigned char *)"1.0"));
    xmlDocSetRootElement(OutputDoc.get(), CombinedRoot);
    assert(nullptr == xmlDocGetRootElement(CombinedDoc));

    xmlKeepBlanksDefault(0);
    xmlChar *Buff = nullptr;
    xmlDocDumpFormatMemoryEnc(OutputDoc.get(), &Buff, &BufferSize, "UTF-8", 1);
    Buffer.reset(Buff);
  }

  return BufferSize ? MemoryBuffer::getMemBufferCopy(StringRef(
                          FROM_XML_CHAR(Buffer.get()), (size_t)BufferSize))
                    : nullptr;
}

bool windows_manifest::isAvailable() { return true; }

#else

WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
}

Error WindowsManifestMerger::WindowsManifestMergerImpl::merge(
    MemoryBufferRef Manifest) {
  return make_error<WindowsManifestError>("no libxml2");
}

std::unique_ptr<MemoryBuffer>
WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
  return nullptr;
}

bool windows_manifest::isAvailable() { return false; }

#endif

WindowsManifestMerger::WindowsManifestMerger()
    : Impl(std::make_unique<WindowsManifestMergerImpl>()) {}

WindowsManifestMerger::~WindowsManifestMerger() = default;

Error WindowsManifestMerger::merge(MemoryBufferRef Manifest) {
  return Impl->merge(Manifest);
}

std::unique_ptr<MemoryBuffer> WindowsManifestMerger::getMergedManifest() {
  return Impl->getMergedManifest();
}

void WindowsManifestMerger::WindowsManifestMergerImpl::errorCallback(
    void *Ctx, const char *Format, ...) {
  auto *Merger = (WindowsManifestMergerImpl *)Ctx;
  Merger->ParseErrorOccurred = true;
}

Error WindowsManifestMerger::WindowsManifestMergerImpl::getParseError() {
  if (!ParseErrorOccurred)
    return Error::success();
  return make_error<WindowsManifestError>("invalid xml document");
}
