1 //===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===---------------------------------------------------------------------===//
10 // This file implements the .manifest merger class.
12 //===---------------------------------------------------------------------===//
14 #include "llvm/WindowsManifest/WindowsManifestMerger.h"
15 #include "llvm/Config/config.h"
16 #include "llvm/Support/MemoryBuffer.h"
20 #if LLVM_LIBXML2_ENABLED
21 #include <libxml/xmlreader.h>
24 #define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X)
25 #define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X)
28 using namespace windows_manifest
;
30 char WindowsManifestError::ID
= 0;
32 WindowsManifestError::WindowsManifestError(const Twine
&Msg
) : Msg(Msg
.str()) {}
34 void WindowsManifestError::log(raw_ostream
&OS
) const { OS
<< Msg
; }
36 class WindowsManifestMerger::WindowsManifestMergerImpl
{
38 ~WindowsManifestMergerImpl();
39 Error
merge(const MemoryBuffer
&Manifest
);
40 std::unique_ptr
<MemoryBuffer
> getMergedManifest();
43 static void errorCallback(void *Ctx
, const char *Format
, ...);
44 Error
getParseError();
45 #if LLVM_LIBXML2_ENABLED
46 xmlDocPtr CombinedDoc
= nullptr;
47 std::vector
<xmlDocPtr
> MergedDocs
;
51 void operator()(xmlChar
*Ptr
) { xmlFree(Ptr
); }
52 void operator()(xmlDoc
*Ptr
) { xmlFreeDoc(Ptr
); }
55 std::unique_ptr
<xmlChar
, XmlDeleter
> Buffer
;
57 bool ParseErrorOccurred
= false;
60 #if LLVM_LIBXML2_ENABLED
62 static const std::pair
<StringRef
, StringRef
> MtNsHrefsPrefixes
[] = {
63 {"urn:schemas-microsoft-com:asm.v1", "ms_asmv1"},
64 {"urn:schemas-microsoft-com:asm.v2", "ms_asmv2"},
65 {"urn:schemas-microsoft-com:asm.v3", "ms_asmv3"},
66 {"http://schemas.microsoft.com/SMI/2005/WindowsSettings",
67 "ms_windowsSettings"},
68 {"urn:schemas-microsoft-com:compatibility.v1", "ms_compatibilityv1"}};
70 static bool xmlStringsEqual(const unsigned char *A
, const unsigned char *B
) {
71 // Handle null pointers. Comparison of 2 null pointers returns true because
72 // this indicates the prefix of a default namespace.
75 return strcmp(FROM_XML_CHAR(A
), FROM_XML_CHAR(B
)) == 0;
78 static bool isMergeableElement(const unsigned char *ElementName
) {
79 for (StringRef S
: {"application", "assembly", "assemblyIdentity",
80 "compatibility", "noInherit", "requestedExecutionLevel",
81 "requestedPrivileges", "security", "trustInfo"}) {
82 if (S
== FROM_XML_CHAR(ElementName
)) {
89 static xmlNodePtr
getChildWithName(xmlNodePtr Parent
,
90 const unsigned char *ElementName
) {
91 for (xmlNodePtr Child
= Parent
->children
; Child
; Child
= Child
->next
) {
92 if (xmlStringsEqual(Child
->name
, ElementName
)) {
99 static xmlAttrPtr
getAttribute(xmlNodePtr Node
,
100 const unsigned char *AttributeName
) {
101 for (xmlAttrPtr Attribute
= Node
->properties
; Attribute
!= nullptr;
102 Attribute
= Attribute
->next
) {
103 if (xmlStringsEqual(Attribute
->name
, AttributeName
)) {
110 // Check if namespace specified by HRef1 overrides that of HRef2.
111 static bool namespaceOverrides(const unsigned char *HRef1
,
112 const unsigned char *HRef2
) {
113 auto HRef1Position
= llvm::find_if(
114 MtNsHrefsPrefixes
, [=](const std::pair
<StringRef
, StringRef
> &Element
) {
115 return xmlStringsEqual(HRef1
, TO_XML_CHAR(Element
.first
.data()));
117 auto HRef2Position
= llvm::find_if(
118 MtNsHrefsPrefixes
, [=](const std::pair
<StringRef
, StringRef
> &Element
) {
119 return xmlStringsEqual(HRef2
, TO_XML_CHAR(Element
.first
.data()));
121 return HRef1Position
< HRef2Position
;
124 // Search for prefix-defined namespace specified by HRef, starting on Node and
125 // continuing recursively upwards. Returns the namespace or nullptr if not
127 static xmlNsPtr
search(const unsigned char *HRef
, xmlNodePtr Node
) {
128 for (xmlNsPtr Def
= Node
->nsDef
; Def
; Def
= Def
->next
) {
129 if (Def
->prefix
&& xmlStringsEqual(Def
->href
, HRef
)) {
134 return search(HRef
, Node
->parent
);
139 // Return the prefix that corresponds to the HRef. If HRef is not a recognized
140 // URI, then just return the HRef itself to use as the prefix.
141 static const unsigned char *getPrefixForHref(const unsigned char *HRef
) {
142 for (auto &Ns
: MtNsHrefsPrefixes
) {
143 if (xmlStringsEqual(HRef
, TO_XML_CHAR(Ns
.first
.data()))) {
144 return TO_XML_CHAR(Ns
.second
.data());
150 // Search for prefix-defined namespace specified by HRef, starting on Node and
151 // continuing recursively upwards. If it is found, then return it. If it is
152 // not found, then prefix-define that namespace on the node and return a
154 static Expected
<xmlNsPtr
> searchOrDefine(const unsigned char *HRef
,
156 if (xmlNsPtr Def
= search(HRef
, Node
))
158 if (xmlNsPtr Def
= xmlNewNs(Node
, HRef
, getPrefixForHref(HRef
)))
160 return make_error
<WindowsManifestError
>("failed to create new namespace");
163 // Set the namespace of OrigionalAttribute on OriginalNode to be that of
164 // AdditionalAttribute's.
165 static Error
copyAttributeNamespace(xmlAttrPtr OriginalAttribute
,
166 xmlNodePtr OriginalNode
,
167 xmlAttrPtr AdditionalAttribute
) {
169 Expected
<xmlNsPtr
> ExplicitOrError
=
170 searchOrDefine(AdditionalAttribute
->ns
->href
, OriginalNode
);
171 if (!ExplicitOrError
)
172 return ExplicitOrError
.takeError();
173 OriginalAttribute
->ns
= std::move(ExplicitOrError
.get());
174 return Error::success();
177 // Return the corresponding namespace definition for the prefix, defined on the
178 // given Node. Returns nullptr if there is no such definition.
179 static xmlNsPtr
getNamespaceWithPrefix(const unsigned char *Prefix
,
183 for (xmlNsPtr Def
= Node
->nsDef
; Def
; Def
= Def
->next
) {
184 if (xmlStringsEqual(Def
->prefix
, Prefix
)) {
191 // Search for the closest inheritable default namespace, starting on (and
192 // including) the Node and traveling upwards through parent nodes. Returns
193 // nullptr if there are no inheritable default namespaces.
194 static xmlNsPtr
getClosestDefault(xmlNodePtr Node
) {
195 if (xmlNsPtr Ret
= getNamespaceWithPrefix(nullptr, Node
))
197 if (Node
->parent
== nullptr)
199 return getClosestDefault(Node
->parent
);
202 // Merge the attributes of AdditionalNode into OriginalNode. If attributes
203 // with identical types are present, they are not duplicated but rather if
204 // their values are not consistent and error is thrown. In addition, the
205 // higher priority namespace is used for each attribute, EXCEPT in the case
206 // of merging two default namespaces and the lower priority namespace
207 // definition occurs closer than the higher priority one.
208 static Error
mergeAttributes(xmlNodePtr OriginalNode
,
209 xmlNodePtr AdditionalNode
) {
210 xmlNsPtr ClosestDefault
= getClosestDefault(OriginalNode
);
211 for (xmlAttrPtr Attribute
= AdditionalNode
->properties
; Attribute
;
212 Attribute
= Attribute
->next
) {
213 if (xmlAttrPtr OriginalAttribute
=
214 getAttribute(OriginalNode
, Attribute
->name
)) {
215 if (!xmlStringsEqual(OriginalAttribute
->children
->content
,
216 Attribute
->children
->content
)) {
217 return make_error
<WindowsManifestError
>(
218 Twine("conflicting attributes for ") +
219 FROM_XML_CHAR(OriginalNode
->name
));
221 if (!Attribute
->ns
) {
224 if (!OriginalAttribute
->ns
) {
225 if (auto E
= copyAttributeNamespace(OriginalAttribute
, OriginalNode
,
231 if (namespaceOverrides(OriginalAttribute
->ns
->href
,
232 Attribute
->ns
->href
)) {
233 // In this case, the original attribute has a higher priority namespace
234 // than the incomiing attribute, however the namespace definition of
235 // the lower priority namespace occurs first traveling upwards in the
236 // tree. Therefore the lower priority namespace is applied.
237 if (!OriginalAttribute
->ns
->prefix
&& !Attribute
->ns
->prefix
&&
239 xmlStringsEqual(Attribute
->ns
->href
, ClosestDefault
->href
)) {
240 if (auto E
= copyAttributeNamespace(OriginalAttribute
, OriginalNode
,
247 // This covers the case where the incoming attribute has the higher
248 // priority. The higher priority namespace is applied in all cases
249 // EXCEPT when both of the namespaces are default inherited, and the
250 // closest inherited default is the lower priority one.
252 if (Attribute
->ns
->prefix
|| OriginalAttribute
->ns
->prefix
||
253 (ClosestDefault
&& !xmlStringsEqual(OriginalAttribute
->ns
->href
,
254 ClosestDefault
->href
))) {
255 if (auto E
= copyAttributeNamespace(OriginalAttribute
, OriginalNode
,
263 // If the incoming attribute is not already found on the node, append it
264 // to the end of the properties list. Also explicitly apply its
265 // namespace as a prefix because it might be contained in a separate
266 // namespace that doesn't use the attribute.
268 xmlNewProp(OriginalNode
, Attribute
->name
, Attribute
->children
->content
);
269 Expected
<xmlNsPtr
> ExplicitOrError
=
270 searchOrDefine(Attribute
->ns
->href
, OriginalNode
);
271 if (!ExplicitOrError
)
272 return ExplicitOrError
.takeError();
273 NewProp
->ns
= std::move(ExplicitOrError
.get());
275 return Error::success();
278 // Given two nodes, return the one with the higher priority namespace.
279 static xmlNodePtr
getDominantNode(xmlNodePtr Node1
, xmlNodePtr Node2
) {
281 if (!Node1
|| !Node1
->ns
)
283 if (!Node2
|| !Node2
->ns
)
285 if (namespaceOverrides(Node1
->ns
->href
, Node2
->ns
->href
))
290 // Checks if this Node's namespace is inherited or one it defined itself.
291 static bool hasInheritedNs(xmlNodePtr Node
) {
292 return Node
->ns
&& Node
->ns
!= getNamespaceWithPrefix(Node
->ns
->prefix
, Node
);
295 // Check if this Node's namespace is a default namespace that it inherited, as
296 // opposed to defining itself.
297 static bool hasInheritedDefaultNs(xmlNodePtr Node
) {
298 return hasInheritedNs(Node
) && Node
->ns
->prefix
== nullptr;
301 // Check if this Node's namespace is a default namespace it defined itself.
302 static bool hasDefinedDefaultNamespace(xmlNodePtr Node
) {
303 return Node
->ns
&& (Node
->ns
== getNamespaceWithPrefix(nullptr, Node
));
306 // For the given explicit prefix-definition of a namespace, travel downwards
307 // from a node recursively, and for every implicit, inherited default usage of
308 // that namespace replace it with that explicit prefix use. This is important
309 // when namespace overriding occurs when merging, so that elements unique to a
310 // namespace will still stay in that namespace.
311 static void explicateNamespace(xmlNsPtr PrefixDef
, xmlNodePtr Node
) {
312 // If a node as its own default namespace definition it clearly cannot have
313 // inherited the given default namespace, and neither will any of its
315 if (hasDefinedDefaultNamespace(Node
))
317 if (Node
->ns
&& xmlStringsEqual(Node
->ns
->href
, PrefixDef
->href
) &&
318 hasInheritedDefaultNs(Node
))
319 Node
->ns
= PrefixDef
;
320 for (xmlAttrPtr Attribute
= Node
->properties
; Attribute
;
321 Attribute
= Attribute
->next
) {
323 xmlStringsEqual(Attribute
->ns
->href
, PrefixDef
->href
)) {
324 Attribute
->ns
= PrefixDef
;
327 for (xmlNodePtr Child
= Node
->children
; Child
; Child
= Child
->next
) {
328 explicateNamespace(PrefixDef
, Child
);
332 // Perform the namespace merge between two nodes.
333 static Error
mergeNamespaces(xmlNodePtr OriginalNode
,
334 xmlNodePtr AdditionalNode
) {
335 // Save the original default namespace definition in case the incoming node
337 const unsigned char *OriginalDefinedDefaultHref
= nullptr;
338 if (xmlNsPtr OriginalDefinedDefaultNs
=
339 getNamespaceWithPrefix(nullptr, OriginalNode
)) {
340 OriginalDefinedDefaultHref
= xmlStrdup(OriginalDefinedDefaultNs
->href
);
342 const unsigned char *NewDefinedDefaultHref
= nullptr;
343 // Copy all namespace definitions. There can only be one default namespace
344 // definition per node, so the higher priority one takes precedence in the
345 // case of collision.
346 for (xmlNsPtr Def
= AdditionalNode
->nsDef
; Def
; Def
= Def
->next
) {
347 if (xmlNsPtr OriginalNsDef
=
348 getNamespaceWithPrefix(Def
->prefix
, OriginalNode
)) {
350 if (namespaceOverrides(Def
->href
, OriginalNsDef
->href
)) {
351 NewDefinedDefaultHref
= TO_XML_CHAR(strdup(FROM_XML_CHAR(Def
->href
)));
353 } else if (!xmlStringsEqual(OriginalNsDef
->href
, Def
->href
)) {
354 return make_error
<WindowsManifestError
>(
355 Twine("conflicting namespace definitions for ") +
356 FROM_XML_CHAR(Def
->prefix
));
359 xmlNsPtr NewDef
= xmlCopyNamespace(Def
);
360 NewDef
->next
= OriginalNode
->nsDef
;
361 OriginalNode
->nsDef
= NewDef
;
365 // Check whether the original node or the incoming node has the higher
366 // priority namespace. Depending on which one is dominant, we will have
367 // to recursively apply namespace changes down to children of the original
369 xmlNodePtr DominantNode
= getDominantNode(OriginalNode
, AdditionalNode
);
370 xmlNodePtr NonDominantNode
=
371 DominantNode
== OriginalNode
? AdditionalNode
: OriginalNode
;
372 if (DominantNode
== OriginalNode
) {
373 if (OriginalDefinedDefaultHref
) {
374 xmlNsPtr NonDominantDefinedDefault
=
375 getNamespaceWithPrefix(nullptr, NonDominantNode
);
376 // In this case, both the nodes defined a default namespace. However
377 // the lower priority node ended up having a higher priority default
378 // definition. This can occur if the higher priority node is prefix
379 // namespace defined. In this case we have to define an explicit
380 // prefix for the overridden definition and apply it to all children
381 // who relied on that definition.
382 if (NonDominantDefinedDefault
&&
383 namespaceOverrides(NonDominantDefinedDefault
->href
,
384 OriginalDefinedDefaultHref
)) {
385 Expected
<xmlNsPtr
> EC
=
386 searchOrDefine(OriginalDefinedDefaultHref
, DominantNode
);
388 return EC
.takeError();
390 xmlNsPtr PrefixDominantDefinedDefault
= std::move(EC
.get());
391 explicateNamespace(PrefixDominantDefinedDefault
, DominantNode
);
393 // In this case the node with a higher priority namespace did not have a
394 // default namespace definition, but the lower priority node did. In this
395 // case the new default namespace definition is copied. A side effect of
396 // this is that all children will suddenly find themselves in a different
397 // default namespace. To maintain correctness we need to ensure that all
398 // children now explicitly refer to the namespace that they had previously
399 // implicitly inherited.
400 } else if (getNamespaceWithPrefix(nullptr, NonDominantNode
)) {
401 if (DominantNode
->parent
) {
402 xmlNsPtr ClosestDefault
= getClosestDefault(DominantNode
->parent
);
403 Expected
<xmlNsPtr
> EC
=
404 searchOrDefine(ClosestDefault
->href
, DominantNode
);
406 return EC
.takeError();
408 xmlNsPtr ExplicitDefault
= std::move(EC
.get());
409 explicateNamespace(ExplicitDefault
, DominantNode
);
413 // Covers case where the incoming node has a default namespace definition
414 // that overrides the original node's namespace. This always leads to
415 // the original node receiving that new default namespace.
416 if (hasDefinedDefaultNamespace(DominantNode
)) {
417 NonDominantNode
->ns
= getNamespaceWithPrefix(nullptr, NonDominantNode
);
419 // This covers the case where the incoming node either has a prefix
420 // namespace, or an inherited default namespace. Since the namespace
421 // may not yet be defined in the original tree we do a searchOrDefine
422 // for it, and then set the namespace equal to it.
423 Expected
<xmlNsPtr
> EC
=
424 searchOrDefine(DominantNode
->ns
->href
, NonDominantNode
);
426 return EC
.takeError();
428 xmlNsPtr Explicit
= std::move(EC
.get());
429 NonDominantNode
->ns
= Explicit
;
431 // This covers cases where the incoming dominant node HAS a default
432 // namespace definition, but MIGHT NOT NECESSARILY be in that namespace.
433 if (xmlNsPtr DominantDefaultDefined
=
434 getNamespaceWithPrefix(nullptr, DominantNode
)) {
435 if (OriginalDefinedDefaultHref
) {
436 if (namespaceOverrides(DominantDefaultDefined
->href
,
437 OriginalDefinedDefaultHref
)) {
438 // In this case, the incoming node's default definition overrides
439 // the original default definition, all children who relied on that
440 // definition must be updated accordingly.
441 Expected
<xmlNsPtr
> EC
=
442 searchOrDefine(OriginalDefinedDefaultHref
, NonDominantNode
);
444 return EC
.takeError();
446 xmlNsPtr ExplicitDefault
= std::move(EC
.get());
447 explicateNamespace(ExplicitDefault
, NonDominantNode
);
450 // The original did not define a default definition, however the new
451 // default definition still applies to all children, so they must be
452 // updated to explicitly refer to the namespace they had previously
453 // been inheriting implicitly.
454 xmlNsPtr ClosestDefault
= getClosestDefault(NonDominantNode
);
455 Expected
<xmlNsPtr
> EC
=
456 searchOrDefine(ClosestDefault
->href
, NonDominantNode
);
458 return EC
.takeError();
460 xmlNsPtr ExplicitDefault
= std::move(EC
.get());
461 explicateNamespace(ExplicitDefault
, NonDominantNode
);
465 if (NewDefinedDefaultHref
) {
466 xmlNsPtr OriginalNsDef
= getNamespaceWithPrefix(nullptr, OriginalNode
);
467 xmlFree(const_cast<unsigned char *>(OriginalNsDef
->href
));
468 OriginalNsDef
->href
= NewDefinedDefaultHref
;
470 xmlFree(const_cast<unsigned char *>(OriginalDefinedDefaultHref
));
471 return Error::success();
474 static bool isRecognizedNamespace(const unsigned char *NsHref
) {
475 for (auto &Ns
: MtNsHrefsPrefixes
) {
476 if (xmlStringsEqual(NsHref
, TO_XML_CHAR(Ns
.first
.data()))) {
483 static bool hasRecognizedNamespace(xmlNodePtr Node
) {
484 return isRecognizedNamespace(Node
->ns
->href
);
487 // Ensure a node's inherited namespace is actually defined in the tree it
489 static Error
reconcileNamespaces(xmlNodePtr Node
) {
491 return Error::success();
493 if (hasInheritedNs(Node
)) {
494 Expected
<xmlNsPtr
> ExplicitOrError
= searchOrDefine(Node
->ns
->href
, Node
);
495 if (!ExplicitOrError
) {
496 return ExplicitOrError
.takeError();
498 xmlNsPtr Explicit
= std::move(ExplicitOrError
.get());
501 for (xmlNodePtr Child
= Node
->children
; Child
; Child
= Child
->next
) {
502 if (auto E
= reconcileNamespaces(Child
)) {
506 return Error::success();
509 // Recursively merge the two given manifest trees, depending on which elements
510 // are of a mergeable type, and choose namespaces according to which have
512 static Error
treeMerge(xmlNodePtr OriginalRoot
, xmlNodePtr AdditionalRoot
) {
513 if (auto E
= mergeAttributes(OriginalRoot
, AdditionalRoot
))
515 if (auto E
= mergeNamespaces(OriginalRoot
, AdditionalRoot
))
517 xmlNodePtr AdditionalFirstChild
= AdditionalRoot
->children
;
519 for (xmlNodePtr Child
= AdditionalFirstChild
; Child
; Child
= Child
->next
) {
520 xmlNodePtr OriginalChildWithName
;
521 if (!isMergeableElement(Child
->name
) ||
522 !(OriginalChildWithName
=
523 getChildWithName(OriginalRoot
, Child
->name
)) ||
524 !hasRecognizedNamespace(Child
)) {
525 StoreNext
.next
= Child
->next
;
526 xmlUnlinkNode(Child
);
527 if (!xmlAddChild(OriginalRoot
, Child
)) {
528 return make_error
<WindowsManifestError
>(Twine("could not merge ") +
529 FROM_XML_CHAR(Child
->name
));
531 if (auto E
= reconcileNamespaces(Child
)) {
535 } else if (auto E
= treeMerge(OriginalChildWithName
, Child
)) {
539 return Error::success();
542 static void stripComments(xmlNodePtr Root
) {
544 for (xmlNodePtr Child
= Root
->children
; Child
; Child
= Child
->next
) {
545 if (!xmlStringsEqual(Child
->name
, TO_XML_CHAR("comment"))) {
546 stripComments(Child
);
549 StoreNext
.next
= Child
->next
;
550 xmlNodePtr Remove
= Child
;
552 xmlUnlinkNode(Remove
);
557 // libxml2 assumes that attributes do not inherit default namespaces, whereas
558 // the original mt.exe does make this assumption. This function reconciles
559 // this by setting all attributes to have the inherited default namespace.
560 static void setAttributeNamespaces(xmlNodePtr Node
) {
561 for (xmlAttrPtr Attribute
= Node
->properties
; Attribute
;
562 Attribute
= Attribute
->next
) {
563 if (!Attribute
->ns
) {
564 Attribute
->ns
= getClosestDefault(Node
);
567 for (xmlNodePtr Child
= Node
->children
; Child
; Child
= Child
->next
) {
568 setAttributeNamespaces(Child
);
572 // The merging process may create too many prefix defined namespaces. This
573 // function removes all unnecessary ones from the tree.
574 static void checkAndStripPrefixes(xmlNodePtr Node
,
575 std::vector
<xmlNsPtr
> &RequiredPrefixes
) {
576 for (xmlNodePtr Child
= Node
->children
; Child
; Child
= Child
->next
) {
577 checkAndStripPrefixes(Child
, RequiredPrefixes
);
579 if (Node
->ns
&& Node
->ns
->prefix
!= nullptr) {
580 xmlNsPtr ClosestDefault
= getClosestDefault(Node
);
581 if (ClosestDefault
&&
582 xmlStringsEqual(ClosestDefault
->href
, Node
->ns
->href
)) {
583 Node
->ns
= ClosestDefault
;
584 } else if (!llvm::is_contained(RequiredPrefixes
, Node
->ns
)) {
585 RequiredPrefixes
.push_back(Node
->ns
);
588 for (xmlAttrPtr Attribute
= Node
->properties
; Attribute
;
589 Attribute
= Attribute
->next
) {
590 if (Attribute
->ns
&& Attribute
->ns
->prefix
!= nullptr) {
591 xmlNsPtr ClosestDefault
= getClosestDefault(Node
);
592 if (ClosestDefault
&&
593 xmlStringsEqual(ClosestDefault
->href
, Attribute
->ns
->href
)) {
594 Attribute
->ns
= ClosestDefault
;
595 } else if (!llvm::is_contained(RequiredPrefixes
, Node
->ns
)) {
596 RequiredPrefixes
.push_back(Attribute
->ns
);
602 for (xmlNsPtr Def
= Node
->nsDef
; Def
; Def
= Def
->next
) {
603 if (!Def
->prefix
|| llvm::is_contained(RequiredPrefixes
, Def
)) {
607 if (Def
== Node
->nsDef
) {
608 Node
->nsDef
= Def
->next
;
610 Prev
->next
= Def
->next
;
612 Temp
.next
= Def
->next
;
618 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
619 for (auto &Doc
: MergedDocs
)
623 Error
WindowsManifestMerger::WindowsManifestMergerImpl::merge(
624 const MemoryBuffer
&Manifest
) {
626 return make_error
<WindowsManifestError
>(
627 "merge after getMergedManifest is not supported");
628 if (Manifest
.getBufferSize() == 0)
629 return make_error
<WindowsManifestError
>(
630 "attempted to merge empty manifest");
631 xmlSetGenericErrorFunc((void *)this,
632 WindowsManifestMergerImpl::errorCallback
);
633 xmlDocPtr ManifestXML
= xmlReadMemory(
634 Manifest
.getBufferStart(), Manifest
.getBufferSize(), "manifest.xml",
635 nullptr, XML_PARSE_NOBLANKS
| XML_PARSE_NODICT
);
636 xmlSetGenericErrorFunc(nullptr, nullptr);
637 if (auto E
= getParseError())
639 xmlNodePtr AdditionalRoot
= xmlDocGetRootElement(ManifestXML
);
640 stripComments(AdditionalRoot
);
641 setAttributeNamespaces(AdditionalRoot
);
642 if (CombinedDoc
== nullptr) {
643 CombinedDoc
= ManifestXML
;
645 xmlNodePtr CombinedRoot
= xmlDocGetRootElement(CombinedDoc
);
646 if (!xmlStringsEqual(CombinedRoot
->name
, AdditionalRoot
->name
) ||
647 !isMergeableElement(AdditionalRoot
->name
) ||
648 !hasRecognizedNamespace(AdditionalRoot
)) {
649 return make_error
<WindowsManifestError
>("multiple root nodes");
651 if (auto E
= treeMerge(CombinedRoot
, AdditionalRoot
)) {
655 MergedDocs
.push_back(ManifestXML
);
656 return Error::success();
659 std::unique_ptr
<MemoryBuffer
>
660 WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
667 xmlNodePtr CombinedRoot
= xmlDocGetRootElement(CombinedDoc
);
668 std::vector
<xmlNsPtr
> RequiredPrefixes
;
669 checkAndStripPrefixes(CombinedRoot
, RequiredPrefixes
);
670 std::unique_ptr
<xmlDoc
, XmlDeleter
> OutputDoc(
671 xmlNewDoc((const unsigned char *)"1.0"));
672 xmlDocSetRootElement(OutputDoc
.get(), CombinedRoot
);
673 assert(0 == xmlDocGetRootElement(CombinedDoc
));
675 xmlKeepBlanksDefault(0);
676 xmlChar
*Buff
= nullptr;
677 xmlDocDumpFormatMemoryEnc(OutputDoc
.get(), &Buff
, &BufferSize
, "UTF-8", 1);
681 return BufferSize
? MemoryBuffer::getMemBufferCopy(StringRef(
682 FROM_XML_CHAR(Buffer
.get()), (size_t)BufferSize
))
686 bool windows_manifest::isAvailable() { return true; }
690 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
693 Error
WindowsManifestMerger::WindowsManifestMergerImpl::merge(
694 const MemoryBuffer
&Manifest
) {
695 return make_error
<WindowsManifestError
>("no libxml2");
698 std::unique_ptr
<MemoryBuffer
>
699 WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
703 bool windows_manifest::isAvailable() { return false; }
707 WindowsManifestMerger::WindowsManifestMerger()
708 : Impl(make_unique
<WindowsManifestMergerImpl
>()) {}
710 WindowsManifestMerger::~WindowsManifestMerger() {}
712 Error
WindowsManifestMerger::merge(const MemoryBuffer
&Manifest
) {
713 return Impl
->merge(Manifest
);
716 std::unique_ptr
<MemoryBuffer
> WindowsManifestMerger::getMergedManifest() {
717 return Impl
->getMergedManifest();
720 void WindowsManifestMerger::WindowsManifestMergerImpl::errorCallback(
721 void *Ctx
, const char *Format
, ...) {
722 auto *Merger
= (WindowsManifestMergerImpl
*)Ctx
;
723 Merger
->ParseErrorOccurred
= true;
726 Error
WindowsManifestMerger::WindowsManifestMergerImpl::getParseError() {
727 if (!ParseErrorOccurred
)
728 return Error::success();
729 return make_error
<WindowsManifestError
>("invalid xml document");