mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-08-08 22:36:48 +02:00
fixup for byte and datetime values
This commit is contained in:
@ -2,6 +2,10 @@
|
||||
|
||||
Converts binary and XML PLIST files.
|
||||
|
||||
Binary values are converted into an ASCII hex representation.
|
||||
|
||||
Datetime objects are converted into Unix epoch timestamps and ISO strings.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat file.plist | jc --plist
|
||||
@ -31,6 +35,8 @@ Examples:
|
||||
"""
|
||||
from typing import List, Dict, Union
|
||||
import plistlib
|
||||
import binascii
|
||||
from datetime import datetime
|
||||
import jc.utils
|
||||
|
||||
|
||||
@ -61,6 +67,57 @@ def _process(proc_data: Dict) -> Dict:
|
||||
return proc_data
|
||||
|
||||
|
||||
def _b2a(byte_string: bytes) -> str:
|
||||
"""Convert a byte string to a colon-delimited hex ascii string"""
|
||||
# need try/except since seperator was only introduced in python 3.8.
|
||||
# provides compatibility for python 3.6 and 3.7.
|
||||
try:
|
||||
return binascii.hexlify(byte_string, ':').decode('utf-8')
|
||||
except TypeError:
|
||||
hex_string = binascii.hexlify(byte_string).decode('utf-8')
|
||||
colon_seperated = ':'.join(hex_string[i:i+2] for i in range(0, len(hex_string), 2))
|
||||
return colon_seperated
|
||||
|
||||
|
||||
def _fix_objects(obj):
|
||||
"""
|
||||
Recursively traverse the nested dictionary or list and convert objects
|
||||
into JSON serializable types.
|
||||
"""
|
||||
if isinstance(obj, dict):
|
||||
for k, v in obj.copy().items():
|
||||
|
||||
if isinstance(v, datetime):
|
||||
iso = v.isoformat()
|
||||
v = int(round(v.timestamp()))
|
||||
obj.update({k: v, f'{k}_iso': iso})
|
||||
continue
|
||||
|
||||
if isinstance(v, bytes):
|
||||
v = _b2a(v)
|
||||
obj.update({k: v})
|
||||
continue
|
||||
|
||||
if isinstance(v, dict):
|
||||
obj.update({k: _fix_objects(v)})
|
||||
continue
|
||||
|
||||
if isinstance(v, list):
|
||||
newlist =[]
|
||||
for i in v:
|
||||
newlist.append(_fix_objects(i))
|
||||
obj.update({k: newlist})
|
||||
continue
|
||||
|
||||
if isinstance(obj, list):
|
||||
new_list = []
|
||||
for i in obj:
|
||||
new_list.append(_fix_objects(i))
|
||||
obj = new_list
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
def parse(
|
||||
data: Union[str, bytes],
|
||||
raw: bool = False,
|
||||
@ -89,5 +146,6 @@ def parse(
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
raw_output = plistlib.loads(data)
|
||||
raw_output = _fix_objects(raw_output)
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
|
49
tests/fixtures/generic/plist-alltypes.plist
vendored
Normal file
49
tests/fixtures/generic/plist-alltypes.plist
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>aDate</key>
|
||||
<date>2022-07-31T16:34:30Z</date>
|
||||
<key>aDict</key>
|
||||
<dict>
|
||||
<key>aFalseValue</key>
|
||||
<false/>
|
||||
<key>aThirdString</key>
|
||||
<string>Mässig, Maß</string>
|
||||
<key>aTrueValue</key>
|
||||
<true/>
|
||||
<key>anotherString</key>
|
||||
<string><hello & hi there!></string>
|
||||
</dict>
|
||||
<key>aFloat</key>
|
||||
<real>0.1</real>
|
||||
<key>aList</key>
|
||||
<array>
|
||||
<string>A</string>
|
||||
<string>B</string>
|
||||
<integer>12</integer>
|
||||
<real>32.1</real>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
<integer>3</integer>
|
||||
</array>
|
||||
</array>
|
||||
<key>aString</key>
|
||||
<string>Doodah</string>
|
||||
<key>anInt</key>
|
||||
<integer>728</integer>
|
||||
<key>someData</key>
|
||||
<data>
|
||||
PGJpbmFyeSBndW5rPg==
|
||||
</data>
|
||||
<key>someMoreData</key>
|
||||
<data>
|
||||
PGxvdHMgb2YgYmluYXJ5IGd1bms+PGxvdHMgb2YgYmluYXJ5IGd1bms+PGxvdHMgb2Yg
|
||||
YmluYXJ5IGd1bms+PGxvdHMgb2YgYmluYXJ5IGd1bms+PGxvdHMgb2YgYmluYXJ5IGd1
|
||||
bms+PGxvdHMgb2YgYmluYXJ5IGd1bms+PGxvdHMgb2YgYmluYXJ5IGd1bms+PGxvdHMg
|
||||
b2YgYmluYXJ5IGd1bms+PGxvdHMgb2YgYmluYXJ5IGd1bms+PGxvdHMgb2YgYmluYXJ5
|
||||
IGd1bms+
|
||||
</data>
|
||||
</dict>
|
||||
</plist>
|
Reference in New Issue
Block a user