REBOL [ title: "Codec: PLIST" name: plist type: module options: [delay] version: 1.0.0 file: https://raw.githubusercontent.com/Oldes/Rebol3/master/src/mezz/codec-plist.reb author: "Oldes" history: [ 07-Apr-2022 "Oldes" {Initial version of the PLIST and Provisioning Profile decoder} ] references: [ https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/PropertyLists/Introduction/Introduction.html https://medium.com/@karaiskc/understanding-apples-binary-property-list-format-281e6da00dbd ] todo: { * Support binary PLIST version * PLIST encoder * Provision profile data validation? } ] system/options/log/plist: 1 stack: copy [] key: value: none ~spnl: system/catalog/bitsets/whitespace ~dict: [ any ~spnl ( append append stack :key make map! 8 ) any [ ~key ~value ( put last stack :key :value ) | any ~spnl ] any ~comment ( value: take/last stack key: take/last stack ) ] ~key: [ any ~spnl copy key: to thru #">" (try [key: to word! key])] ~string: [ any ~spnl copy value: to thru #">" ] ~data: [ any ~spnl copy value: to thru #">" (value: debase value 64)] ~date: [ any ~spnl copy value: to thru #">" (value: to-date value)] ~integer: [ any ~spnl copy value: to thru #">" (value: to integer! value)] ~real: [ any ~spnl copy value: to thru #">" (value: to decimal! value)] ~true: [ (value: true )] ~false: [ (value: false)] ~array: [ (append/only stack copy []) any [~value (append/only last stack :value) any ~spnl] (value: take/last stack) ] ~comment: [any ~spnl opt [""]] ~value: [ any ~comment [ ~string | ~true | ~false | ~array | ~dict | ~date | ~data | ~integer | ~real ] ] register-codec [ name: 'plist type: 'text title: "Property List File Format" suffixes: [%.plist] decode: function [ {Extract content of the PLIST file} data [binary! file! url!] ;return: [map!] ] [ verbose: system/options/log/plist unless binary? data [ data: read data ] if verbose > 0 [ log-info 'PLIST ["^[[1;32mDecode PLIST data^[[m (^[[1m" length? data "^[[mbytes )"] ] unless parse to string! data [ thru "" ~dict any ~comment to end ][ return none ] if verbose: system/options/log/plist > 0 [ foreach [k v] value [ switch to word! k [ DeveloperCertificates [ v: copy v forall v [ try [ crt: codecs/crt/decode v/1 change/only v compose [ commonName: (crt/subject/commonName) valid-to: (crt/valid-to) fingerprint: (select crt 'fingerprint) ] ] ] ] DER-Encoded-Profile [ log-debug 'PLIST ajoin [as-green k ": " mold v] continue ] ] log-warn 'PLIST ajoin [as-green k ": " mold v] ] ] value ] ;encode: function [data [binary!]][ ] identify: function [data [binary!]][ ; just a simple test if there are key parts... parse data [ thru "