1

If you download a file from the internet using Safari, some extended attributes are added to the downloaded file, among which com.apple.metadata:kMDItemWhereFroms which contains the original URL of the download. In Finder > Get Info the value of this key will be displayed under Where from:.

/bin/ls -alh shows the presence of extended attributes with a @ in the mode column and xattr -l filename.zip will list all the attributes.

According to the xattr's man page to print the value of an attribute one can use:

xattr -p com.apple.metadata:kMDItemWhereFroms filename.zip

# OUTPUT
# com.apple.metadata:kMDItemWhereFroms: bplist00�_=https://example.com/filename.zip

So even if the content is visible, the value is in a binary format with a header of bplist00�_.

I tried to parse it in the following way:

xattr -p com.apple.metadata:kMDItemWhereFroms filename.zip > url.plist

# checking the file format:
file url.plist

# OUTPUT:
# url.plist: Apple binary property list

# assuming this should work:
plutil -convert xml1 url.plist

# OUTPUT:
# url.plist: Property List error: Unexpected character b at line 1 / JSON error: 
# JSON text did not start with array or object and option to allow 
# fragments not set. around line 1, column 0.

Trying to parse the file with python's ootb plistlib throws an error too:

import plistlib

with open('url.plist', 'rb') as fi:
    plist = plistlib.load(fi)

# OUTPUT:
# plistlib.InvalidFileException: Invalid file

From the output it looks like it is not a regular binary plist format even though file url.plist claims it is an 'Apple binary property list'. Any hints as to what the format is and how to parse it to a plain text value?

3 Answers 3

4

You can print it in hex and then run it through xxd like so:

xattr -x -p com.apple.metadata:kMDItemWhereFroms filename.zip | xxd -r -p | plutil -p - 

If you want to have other output format you can change plutil to something like:

plutil -convert json -o - -

Example output:

["https:\/\/another.example.com","https:\/\/example.com\/path\/"]
3
  • interesting approach; any hints on why plutil covert ... won't work? I tried all of the formats listed in the manpage, ie xml1, binary1, json, objc,raw and all of them fail; could it be because the value is an array of two URLs and not a single plain text value?
    – ccpizza
    Feb 7, 2023 at 8:20
  • 1
    Hard to tell, probably the output of xattr -p strips some non-displayable characters. By passing -x you'll get raw hex output which has to be transformed into "pure" binary before passing that to plutil. BTW I've added a possibility to convert the output to JSON etc. Feb 7, 2023 at 9:55
  • 1
    awesome! thank you! combined with jq a plain text string can be pulled with /usr/bin/xattr -x -p com.apple.metadata:kMDItemWhereFroms "$1" | xxd -r -p | plutil -convert json -o - - | jq -r '.[0]' — this takes the first element from the array; also, I'm prefixing xattr because on my system there is another xattr in /usr/local/bin which doesn't understand the -x flag.
    – ccpizza
    Feb 7, 2023 at 16:20
2

Ended up using python as described at https://stackoverflow.com/a/33182025/191246

# dependencies:
# pip install xattr biplist

import biplist
import xattr

attrs = xattr.xattr('filename.zip')

print(biplist.readPlistFromString(attrs.get('com.apple.metadata:kMDItemWhereFroms')))

# OUTPUT:
# ['https://example.com/..', 'https://another.example/..']

With python the result is a list that can be manipulated and iterated programmatically.

1

Howard Oakley has created an editor for extended attributes, that may be useful for parsing the contents.

https://eclecticlight.co/xattred-sandstrip-xattr-tools/

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .