Documentation
¶
Overview ¶
Package plisthelpers provides generic, resource-agnostic plist (Apple Property List) primitives: parse, marshal, canonicalise, and structural equality. It carries no mobileconfig- or resource-specific knowledge — the configuration-profile masking / lenient-compare logic that layers on top of these primitives lives in the payloadhelpers package, which imports this one.
Index ¶
- func CanonicalisePlistXML(raw []byte) []byte
- func CompactStructuralWhitespace(raw []byte) ([]byte, error)
- func Equal(a, b any) bool
- func MarshalPlist(m map[string]any) ([]byte, error)
- func NumericEqual(a int64, b any) bool
- func ParsePlist(raw []byte) (map[string]any, int, error)
- func SemanticallyEqual(a, b []byte) (equal bool, ok bool)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CanonicalisePlistXML ¶
CanonicalisePlistXML parses a plist and re-emits it as tab-indented XML so two documents that differ only in formatting (whitespace, indentation, line endings, trailing newline) render identically. Falls back to returning the input unchanged when it fails to parse — the caller still has a usable string.
func CompactStructuralWhitespace ¶
CompactStructuralWhitespace deletes whitespace-only text that sits between tags inside plist structural elements (<plist>, <dict>, <array>) and in the document prolog/epilog, collapsing a pretty-printed plist onto a single line. Everything else passes through byte-for-byte: leaf element content (<string>, <key>, <data>, …), comments, CDATA sections, entity and character references, attribute formatting, and dict key order are untouched — the document is never re-serialised, only whitespace-only byte ranges of the original input are removed.
Exists because the Jamf Classic API's server-side plist parser materialises whitespace text nodes between sibling <array> tags as phantom empty <array/> entries in the stored plist on write (wire-probed against JSSResource/mobiledeviceconfigurationprofiles, 2026-06-10). Plist semantics ignore inter-element whitespace inside containers, so stripping all of it sidesteps the whole bug class; the wire payload needs no readability.
Returns the input unchanged alongside the error when the payload is not well-formed XML — callers should fall back to sending the original bytes and let the server report the malformation.
func Equal ¶
Equal is a structural-equality compare for parsed plist trees: dicts require matching keysets, arrays compare positionally, and the int64/uint64/int trio howett.net/plist emits compares numerically. Use this when every key is author-controlled and there are no server-injected keys to tolerate (the common case for opaque user-authored plist content). For mobileconfig payloads — where Jamf Pro injects/defaults keys — use the intersection-aware comparator in payloadhelpers instead.
func MarshalPlist ¶
MarshalPlist serialises a plist dict back to tab-indented XML form.
func NumericEqual ¶
NumericEqual reports whether int64 a equals b across the int64/uint64/int representations howett.net/plist may emit for the same plist <integer>.
func ParsePlist ¶
ParsePlist decodes a plist (XML or binary) into a Go map. The returned int is howett.net/plist's format identifier (plist.XMLFormat, plist.BinaryFormat, etc.) — typed as int because the library exposes formats as untyped int constants. A bare `<dict>…</dict>` fragment (no <plist> wrapper) parses fine.
func SemanticallyEqual ¶
SemanticallyEqual reports whether two plist documents are structurally equal once parsed — erasing all formatting differences (whitespace, indentation, line endings, trailing newline, dict key order). The bool ok is false when either input fails to parse as a plist, signalling the caller to fall back to a byte/string comparison for non-plist content.
Types ¶
This section is empty.