def test_complains_about_unmapped_classes(self): del archiver.UNARCHIVE_CLASS_MAP['crap.Foo'] with self.assertRaises(archiver.MissingClassMapping): self.unarchive('simple') archiver.update_class_map({'crap.Foo': FooArchive})
def test_dataclass_not_fully_mapped(self): archiver.update_class_map({ 'FooDataclass': DataclassMussingFields, }) try: with self.assertRaises(archive_types.Error): self.unarchive('dataclass') finally: # Restore mapping. archiver.update_class_map({ 'FooDataclass': FooDataclass, })
def register(): for dataclass in [ ADCCuePoint, ADCMediaItem, ADCMediaItemAnalyzedData, ADCMediaItemLocation, ADCMediaItemTitleID, ADCMediaItemUserData, NSMutableData, NSURL, ADCProduct, ]: archiver.update_class_map({dataclass.__name__: dataclass}) archiver.update_class_map({ 'NSOrderedSet': NSOrderedSetArchiver, })
_subLocality = archive.decode("_subLocality") return CNPostalAddress( _ISOCountryCode, _city, _country, _postalCode, _state, _street, _subAdministrativeArea, _subLocality, ) # register the classes with bpylist.archiver archiver.update_class_map({"CNPostalAddress": CNPostalAddress}) archiver.update_class_map( {"PLRevGeoMapItemAdditionalPlaceInfo": PLRevGeoMapItemAdditionalPlaceInfo} ) archiver.update_class_map({"PLRevGeoMapItem": PLRevGeoMapItem}) archiver.update_class_map({"PLRevGeoLocationInfo": PLRevGeoLocationInfo}) class PlaceInfo(ABC): @property @abstractmethod def address_str(self): pass @property @abstractmethod
'secret': base64.b32encode(self.secret).decode("utf-8").rstrip("="), 'algorithm': self.algorithm.uri_value, 'period': self.period, 'digits': self.digits, 'issuer': self.issuer, 'counter': self.counter, } otp_parameters = '&'.join([ f'{str(k)}={quote(str(v))}' for (k, v) in otp_parameters.items() if v ]) return f'otpauth://{otp_type}/{otp_label}?{otp_parameters}' archiver.update_class_map({'NSMutableData': MutableData}) archiver.update_class_map({'NSMutableString': MutableString}) archiver.update_class_map({'ACOTPFolder': OTPFolder}) archiver.update_class_map({'ACOTPAccount': OTPAccount}) class RawRNCryptor(RNCryptor): def post_decrypt_data(self, data): """Remove useless symbols which appear over padding for AES (PKCS#7).""" data = data[:-bord(data[-1])] return data class DangerousUnarchive(archiver.Unarchive): def decode_object(self, index):
archive.encode('empty', obj.empty) archive.encode('recurse', obj.recursive) @staticmethod def decode_archive(archive): title = archive.decode('title') stamp = archive.decode('stamp') count = archive.decode('count') cats = archive.decode('categories') meta = archive.decode('metadata') empty = archive.decode('empty') recurse = archive.decode('recursive') return FooArchive(title, stamp, count, cats, meta, empty, recurse) archiver.update_class_map({'crap.Foo': FooArchive}) @dataclasses.dataclass class FooDataclass(archive_types.DataclassArchiver): int_field: int = 0 str_field: str = "" float_field: float = -1.1 list_field: list = dataclasses.field(default_factory=list) @dataclasses.dataclass class DataclassMussingFields(archive_types.DataclassArchiver): int_field: int = 0
def encode_archive(obj, archive): archive.encode('title', obj.title) archive.encode('recurse', obj.recursive) def decode_archive(archive): title = archive.decode('title') stamp = archive.decode('stamp') count = archive.decode('count') cats = archive.decode('categories') meta = archive.decode('metadata') empty = archive.decode('empty') recurse = archive.decode('recursive') return FooArchive(title, stamp, count, cats, meta, empty, recurse) archiver.update_class_map({'crap.Foo': FooArchive}) class UnarchiveTest(TestCase): def fixture(self, name): return get_fixture(f'{name}_archive.plist') def unarchive(self, plist): return archiver.unarchive(self.fixture(plist)) def test_complains_about_incorrect_archive_type(self): with self.assertRaises(archiver.UnsupportedArchiver): self.unarchive('invalid_type') def test_complains_about_incorrect_version(self): with self.assertRaises(archiver.UnsupportedArchiveVersion):
def decode_archive(archive): secret = archive.decode('secret') issuer = archive.decode('issuer') account_name = archive.decode('accountName') num_digits = archive.decode('numDigits') algorithm = archive.decode('algorithm') unique_id = archive.decode('uniqueID') generation_type = archive.decode('type') period = archive.decode('period') counter = archive.decode('counter') return OTPToken(secret, issuer, account_name, num_digits, algorithm, unique_id, generation_type, period, counter) archiver.update_class_map({'twostepCommon.OTPToken': OTPToken}) class RawRNCryptor(RNCryptor): def post_decrypt_data(self, data): """Remove useless symbols which appear over padding for AES (PKCS#7).""" data = data[:-bord(data[-1])] return data class DangerousUnarchive(archiver.Unarchive): def decode_object(self, index): if index == 0: return None
path: str name: str id: str @dataclass_json @dataclasses.dataclass class BookmarkOrderItemEntity(DataclassArchiver): """Models BookmarkOrderItemEntity PLIST class""" id: str children: list # update archiver so it can process custom types in PLISTs archiver.update_class_map({ 'MSUserIdHistoryInfo': UserIdHistoryInfo, 'MSDeviceHistoryInfo': DeviceHistoryInfo, 'MSDevice': Device, 'MSSessionHistoryInfo' : SessionHistoryInfo, 'Client.FolderRedirectionEntity' : ClientFolderRedirectionEntity , 'BookmarkOrderItemEntity': BookmarkOrderItemEntity }) def _read_plist(path: str, format: plistlib.PlistFormat) -> dict: """Helper function. Read a plist from given path using provided format.""" if not os.path.isfile(path): raise ValueError(f'File {path} does not exist') with open(path, 'rb') as file: return plistlib.load(file, fmt=format, dict_type=dict) def decode_plist(data: bytes, format: plistlib.PlistFormat = plistlib.FMT_BINARY) -> dict: """Decode byte string into dictionary using provided format.
class Person: def __init__(self, name, age, house): self.name = name self.age = age self.house = house def __eq__(self, other): for field in ['name', 'age', 'house']: if getattr(self, field) != getattr(other, field): return False return True @staticmethod def encode_archive(obj, archive): archive.encode('name', obj.name) archive.encode('age', obj.age) archive.encode('house', obj.house) @staticmethod def decode_archive(archive): name = archive.decode('name') age = archive.decode('age') house = archive.decode('house') return Person(name, age, house) archiver.update_class_map({'crap.Foo': Person}) obj = Person('herp', '42', 'strawberries') archiver.archive(obj)