From 11f144f8b8581891a3f3ef82b02a7dd71bfe2c9a Mon Sep 17 00:00:00 2001 From: DoronZ Date: Thu, 17 Feb 2022 12:41:56 +0200 Subject: [PATCH] symbol: refactor py property --- src/rpcclient/rpcclient/darwin/symbol.py | 101 ++++++++++++++--------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/src/rpcclient/rpcclient/darwin/symbol.py b/src/rpcclient/rpcclient/darwin/symbol.py index 5e4c17e7..d42e3959 100644 --- a/src/rpcclient/rpcclient/darwin/symbol.py +++ b/src/rpcclient/rpcclient/darwin/symbol.py @@ -1,5 +1,6 @@ import struct import time +from typing import List, Mapping from rpcclient.darwin.consts import kCFNumberSInt64Type, kCFNumberDoubleType from rpcclient.exceptions import CfSerializationError, UnrecognizedSelector @@ -25,52 +26,72 @@ def cfdesc(self): return None return self._client.symbols.CFCopyDescription(self).py + def _decode_cfstr(self) -> str: + ptr = self._client.symbols.CFStringGetCStringPtr(self, 0) + if ptr: + return ptr.peek_str() + + with self._client.safe_malloc(4096) as buf: + if not self._client.symbols.CFStringGetCString(self, buf, 4096, 0): + raise CfSerializationError('CFStringGetCString failed') + return buf.peek_str() + + def _decode_cfbool(self) -> bool: + return bool(self._client.symbols.CFBooleanGetValue(self, 0)) + + def _decode_cfnumber(self) -> int: + with self._client.safe_malloc(200) as buf: + if self._client.symbols.CFNumberIsFloatType(self): + if not self._client.symbols.CFNumberGetValue(self, kCFNumberDoubleType, buf): + raise CfSerializationError(f'failed to deserialize float: {self}') + return struct.unpack(' time.struct_time: + return time.strptime(self.cfdesc, '%Y-%m-%d %H:%M:%S %z') + + def _decode_cfdata(self) -> bytes: + count = self._client.symbols.CFDataGetLength(self) + return self._client.symbols.CFDataGetBytePtr(self).peek(count) + + def _decode_cfarray(self) -> List: + result = [] + count = self._client.symbols.CFArrayGetCount(self) + for i in range(count): + result.append(self._client.symbols.CFArrayGetValueAtIndex(self, i).py) + return result + + def _decode_cfdict(self) -> Mapping: + result = {} + count = self._client.symbols.CFArrayGetCount(self) + with self._client.safe_malloc(8 * count) as keys: + with self._client.safe_malloc(8 * count) as values: + self._client.symbols.CFDictionaryGetKeysAndValues(self, keys, values) + for i in range(count): + result[keys[i].py] = values[i].py + return result + @property def py(self): if self == 0: return None t = self._client._cf_types[self._client.symbols.CFGetTypeID(self)] - if t == 'str': - ptr = self._client.symbols.CFStringGetCStringPtr(self, 0) - if not ptr: - with self._client.safe_malloc(4096) as buf: - if not self._client.symbols.CFStringGetCString(self, buf, 4096, 0): - raise CfSerializationError('CFStringGetCString failed') - return buf.peek_str() - return ptr.peek_str() - if t == 'bool': - return bool(self._client.symbols.CFBooleanGetValue(self, 0)) - if t == 'number': - with self._client.safe_malloc(200) as buf: - if self._client.symbols.CFNumberIsFloatType(self): - if not self._client.symbols.CFNumberGetValue(self, kCFNumberDoubleType, buf): - raise CfSerializationError(f'failed to deserialize float: {self}') - return struct.unpack('