macOS plists are the worst

Short questions, long gross answers expected…

Given the following sample “defaults” output, how would you use BigFix relevance to extract the stored values at varying depths?

user@mac ~ % defaults read /Library/Preferences/Example/exampleplist
{
    "Thing One" =     {
        Thing2 =         {
            "Thing Three" =             (
                "name one",
                value1
            );
            "name two" = 1;
            "name three" = 0;
            };
            "name four" = 4;
            "name five" = five;
        };
    };
    "name six" = "ess eye ex";
    Thing4 =     {
        "name seven" = 7;
    };
    name8 = "eighth name";
    thing9 =     (
        "name nine"
    );
}

And then, more generally, how would one go about “exploring” a construct like this to determine the answer for themselves? I’ve started by testing for a Dictionary of the plist:

Q: exists dictionary of file "/Library/Preferences/la.dee.da.plist"
A: True

I then tried testing for “entries of dictionary…”, “arrays of dictionary…”, etc., but I’m not getting very far. I can haz hint? Plz?

(I eventually got what I was looking for (in the above example, “eighth name”) by doing the following:
strings of values of (entries of dictionary of file "/Library/Preferences/exampleplist.plist") whose (key of it = "name8")
Seems like there should be a better way, though…)

1 Like

(Asked about this in the BigFix “Open Mic” webinar and was asked to re-ask it here for a longer treatment.)

/cc @jgstew, @brolly33

This looks accurate, for formatting i’d probably do:

strings of values of entries whose (key of it = "name8") of dictionary of file "/Library/Preferences/exampleplist.plist"

I dont have access to a Mac but this may also work:
strings "name8" of dictionary of file "/Library/Preferences/exampleplist.plist"

These inspectors are very similar to the JSON and XML inspectors and it’s helpful to understand the original data format before trying to use the inspectors.

{
    "Thing One" =     {
        Thing2 =         {
            "Thing Three" =             (
                "name one",
                value1
            );
            "name two" = 1;
            "name three" = 0;
            };
            "name four" = 4;
            "name five" = five;
        };
    };
    "name six" = "ess eye ex";
    Thing4 =     {
        "name seven" = 7;
    };
    name8 = "eighth name";
    thing9 =     (
        "name nine"
    );
}

The root of the document is a dictionary which is made up of dictionary entries which each have a key and a value.

So:

{
    name8 = "eighth name";
}

The outer { } is how we know it’s a dictionary. name8 = "eighth name" is our dictionary entry. name8 is our key and “eighth name” is our value.

So entries of dictionary of file "/Library/Preferences/exampleplist.plist" would return a single dictionary entry with a key of “name8” and a value of “eighth name”.

You might assume that value is a string but it’s actually a value object and to get the actual value out of it you need to tell us what type to get out of it which is what strings of <values> does. If it was an integer we’d do integers of <values>, etc.

So back to our original relevance:
strings of values of entries whose (key of it = "name8") of dictionary of file "/Library/Preferences/exampleplist.plist"

Broken down:

  • Get the File: file "/Library/Preferences/exampleplist.plist"
  • Get the Dictionary: dictionary of file "/Library/Preferences/exampleplist.plist"
  • Get the Dictionary Entries: entries of dictionary of file "/Library/Preferences/exampleplist.plist"
  • Get the Dictionary Entries that match our criteria by adding whose (key of it = "name8")
  • Get the Value Object from the Dictionary Entry: values of entries whose (key of it = "name8") of dictionary of file "/Library/Preferences/exampleplist.plist"
  • Get a String from the Value Object: strings of values of entries whose (key of it = "name8") of dictionary of file "/Library/Preferences/exampleplist.plist"

With this knowledge at hand you can re-use this logic to navigate into nested dictionaries:

  • Get the dictionary entries nested inside of the top level “Thing One”: entries of entries whose (key of it = "Thing One") of dictionary of file "/Library/Preferences/exampleplist.plist"
  • Get the nested Dictionary “Thing2”: entries whose (key of it = "Thing2") of entries whose (key of it = "Thing One") of dictionary of file "/Library/Preferences/exampleplist.plist"
  • Get the value of “name two” from the nested “Thing2” dictionary: strings of values of entries whose (key of it = "name two") of entries whose (key of it = "Thing2") of entries whose (key of it = "Thing One") of dictionary of file "/Library/Preferences/exampleplist.plist"

If all of this traversal of entries is giving you a headache there are some helper properties available. The last example should be able to be simplified to:
strings "name two" of dictionary "Thing2" of dictionary "Thing One" of dictionary of file "/Library/Preferences/exampleplist.plist"

I haven’t actually tested these in QnA so there may be minor typos, etc. If you notice an error send me a PM so we can keep the thread here relatively clean!

4 Likes

Replying only to the title:

macOS plists are the worst

Yes. Yes, they are.

4 Likes

Bookmarked! Thanks, @strawgate!

Also, this did work, so thank you TWICE!

2 Likes