Skip to content

Instantly share code, notes, and snippets.

@Brandon7CC
Last active August 30, 2024 12:17
Show Gist options
  • Save Brandon7CC/0449733602c9a0d613ca582860abbe8e to your computer and use it in GitHub Desktop.
Save Brandon7CC/0449733602c9a0d613ca582860abbe8e to your computer and use it in GitHub Desktop.
(Reference POSIX AtomicTestHarnesses) Returns the list of file types supported by `Archive Utility.app`.
#
# Brandon Dalton
# Date: 20240828 / Original Red Canary ATH 20240116
#
# Description: Returns the list of supported file types (CFBundleDocumentTypes) in Archive Utility.app
# Reference: https://github.com/redcanaryco/AtomicTestHarnesses/blob/6b00e8f41062da2c424ab4e7ec71bd3ec3a6f112/posix/src/posixath/utils/common.py#L530
#
import os
import json
import logging
import subprocess
from pathlib import Path
logger = logging.getLogger(__name__)
def get_app_plist(app_path: Path) -> dict | None:
"""
Attempts to return the specified app's Info.plist in dictionary form.
"""
plist_path: Path = app_path.joinpath("Contents", "Info.plist")
if os.path.isfile(plist_path):
plutil: str = "/usr/bin/plutil"
command_line: list = [plutil, "-convert", "json", plist_path, "-o", "-"]
plist_json: str = subprocess.run(command_line, capture_output=True).stdout
# Attempt to decode the plist json into a Python dictionary
try:
plist_data: dict = json.loads(plist_json)
return plist_data
except json.JSONDecodeError as jde:
logging.error(f"JSON decode error: {jde}")
return None
else:
return None
def get_supported_file_type(archive_utility_plist: dict) -> str:
if "CFBundleTypeName" in archive_utility_plist:
return archive_utility_plist["CFBundleTypeName"]
def archives_supported_by_archive_utility() -> [str]:
"""
Returns the list of file types supported by `Archive Utility.app`.
"""
archive_utility_path: Path = Path(
"/System/Library/CoreServices/Applications/Archive Utility.app"
)
# Get the plist and attempt to read the `CFBundleDocumentTypes` key:
archive_utility_plist = get_app_plist(
app_path=archive_utility_path
)
if "CFBundleDocumentTypes" in archive_utility_plist:
return list(
filter(
lambda item: item is not None,
map(
lambda plist_dict: get_supported_file_type(
plist_dict
),
archive_utility_plist["CFBundleDocumentTypes"],
),
)
)
print(archives_supported_by_archive_utility())
@Brandon7CC
Copy link
Author

Brandon7CC commented Aug 29, 2024

@ChiChou
Copy link

ChiChou commented Aug 30, 2024

python has a built-in property list parser plistlib

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment