diff options
Diffstat (limited to 'cython')
| -rw-r--r-- | cython/Makefile.am | 97 | ||||
| -rw-r--r-- | cython/afc.pxi | 85 | ||||
| -rw-r--r-- | cython/debugserver.pxi | 246 | ||||
| -rw-r--r-- | cython/diagnostics_relay.pxi | 128 | ||||
| -rw-r--r-- | cython/file_relay.pxi | 8 | ||||
| -rw-r--r-- | cython/heartbeat.pxi | 60 | ||||
| -rw-r--r-- | cython/house_arrest.pxi | 84 | ||||
| -rw-r--r-- | cython/imobiledevice.pxd | 28 | ||||
| -rw-r--r-- | cython/imobiledevice.pyx | 79 | ||||
| -rw-r--r-- | cython/installation_proxy.pxi | 31 | ||||
| -rw-r--r-- | cython/lockdown.pxi | 169 | ||||
| -rw-r--r-- | cython/misagent.pxi | 74 | ||||
| -rw-r--r-- | cython/mobile_image_mounter.pxi | 49 | ||||
| -rw-r--r-- | cython/mobilebackup.pxi | 71 | ||||
| -rw-r--r-- | cython/mobilebackup2.pxi | 123 | ||||
| -rw-r--r-- | cython/mobilesync.pxi | 27 | ||||
| -rw-r--r-- | cython/notification_proxy.pxi | 8 | ||||
| -rw-r--r-- | cython/restore.pxi | 131 | ||||
| -rw-r--r-- | cython/sbservices.pxi | 16 | ||||
| -rw-r--r-- | cython/screenshotr.pxi | 12 | ||||
| -rw-r--r-- | cython/stdint.pxi | 18 | ||||
| -rw-r--r-- | cython/webinspector.pxi | 60 |
22 files changed, 1437 insertions, 167 deletions
diff --git a/cython/Makefile.am b/cython/Makefile.am index ae10b06..93ea6ed 100644 --- a/cython/Makefile.am +++ b/cython/Makefile.am @@ -1,45 +1,84 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CPPFLAGS = \ + -I$(top_srcdir)/include -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) -AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) $(libplist_LIBS) +AM_CFLAGS = \ + $(GLOBAL_CFLAGS) \ + $(ssl_lib_CFLAGS) \ + $(LFS_CFLAGS) \ + $(PTHREAD_CFLAGS) \ + $(libplist_CFLAGS) + +AM_LIBS = \ + $(ssl_lib_LIBS) \ + $(PTHREAD_LIBS) \ + $(libplist_LIBS) if HAVE_CYTHON BUILT_SOURCES = imobiledevice.c -PXDINCLUDES = imobiledevice.pxd stdint.pxi $(CYTHON_PLIST_INCLUDE_DIR)/plist.pxd -PXIINCLUDES = \ - stdint.pxi \ - lockdown.pxi \ - mobilesync.pxi \ - notification_proxy.pxi \ - sbservices.pxi \ - mobilebackup.pxi \ - afc.pxi \ - file_relay.pxi \ - screenshotr.pxi \ - installation_proxy.pxi \ - mobile_image_mounter.pxi - -CLEANFILES = \ - *.pyc \ - *.pyo \ - imobiledevice.c - -EXTRA_DIST = imobiledevice.pyx imobiledevice.pxd $(PXIINCLUDES) +PXDINCLUDES = \ + imobiledevice.pxd \ + $(CYTHON_PLIST_INCLUDE_DIR)/plist.pxd + +PXIINCLUDES = \ + lockdown.pxi \ + mobilesync.pxi \ + notification_proxy.pxi \ + sbservices.pxi \ + mobilebackup.pxi \ + mobilebackup2.pxi \ + afc.pxi \ + file_relay.pxi \ + screenshotr.pxi \ + installation_proxy.pxi \ + webinspector.pxi \ + heartbeat.pxi \ + diagnostics_relay.pxi \ + misagent.pxi \ + house_arrest.pxi \ + restore.pxi \ + mobile_image_mounter.pxi \ + debugserver.pxi + +CLEANFILES = \ + *.pyc \ + *.pyo \ + imobiledevice.c + +EXTRA_DIST = \ + imobiledevice.pyx \ + imobiledevice.pxd \ + $(PXIINCLUDES) imobiledevicedir = $(pyexecdir) imobiledevice_LTLIBRARIES = imobiledevice.la imobiledevice_la_SOURCES = imobiledevice.pyx -imobiledevice_la_CFLAGS = -I../include -I../src $(PYTHON_CPPFLAGS) $(AM_CFLAGS) -Wno-shadow -Wno-redundant-decls -Wno-switch-default -Wno-strict-aliasing -Wno-implicit-function-declaration -imobiledevice_la_LDFLAGS = -module -avoid-version -L$(libdir) $(PYTHON_LDFLAGS) $(AM_LDFLAGS) -imobiledevice_la_LIBADD = ../src/libimobiledevice.la +imobiledevice_la_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ + $(PYTHON_CPPFLAGS) \ + $(AM_CFLAGS) \ + -Wno-shadow \ + -Wno-redundant-decls \ + -Wno-switch-default \ + -Wno-strict-aliasing \ + -Wno-implicit-function-declaration \ + -fvisibility=default \ + $(CYTHON_CFLAGS) + +imobiledevice_la_LDFLAGS = \ + -module \ + -avoid-version \ + -L$(libdir) \ + $(PYTHON_LIBS) \ + $(AM_LIBS) \ + -no-undefined + +imobiledevice_la_LIBADD = $(top_builddir)/src/libimobiledevice-1.0.la imobiledevice.c: imobiledevice.pyx $(PXDINCLUDES) $(PXIINCLUDES) .pyx.c: $(CYTHON) -I$(CYTHON_PLIST_INCLUDE_DIR) -I$(top_srcdir)/src -o $@ $< -# imobiledevice_private.c: $(IMOBILEDEVICE_PRIVATE_SOURCES) $(IMOBILEDEVICE_INCLUDES) $(PLIST_INCLUDES) -# $(CYTHON) $(IMOBILEDEVICE_CPPFLAGS) -I$(top_srcdir)/src -o $@ $< - endif diff --git a/cython/afc.pxi b/cython/afc.pxi index 0383471..6bd8182 100644 --- a/cython/afc.pxi +++ b/cython/afc.pxi @@ -46,12 +46,13 @@ cdef extern from "libimobiledevice/afc.h": AFC_LOCK_EX = 2 | 4 AFC_LOCK_UN = 8 | 4 - afc_error_t afc_client_new(idevice_t device, uint16_t port, afc_client_t *client) + afc_error_t afc_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, afc_client_t *client) afc_error_t afc_client_free(afc_client_t client) afc_error_t afc_get_device_info(afc_client_t client, char ***infos) afc_error_t afc_read_directory(afc_client_t client, char *dir, char ***list) afc_error_t afc_get_file_info(afc_client_t client, char *filename, char ***infolist) afc_error_t afc_remove_path(afc_client_t client, char *path) + afc_error_t afc_remove_path_and_contents(afc_client_t client, char *path) afc_error_t afc_rename_path(afc_client_t client, char *f, char *to) afc_error_t afc_make_directory(afc_client_t client, char *dir) afc_error_t afc_truncate(afc_client_t client, char *path, uint64_t newsize) @@ -116,6 +117,12 @@ cdef class AfcFile(Base): def __init__(self, *args, **kwargs): raise TypeError("AfcFile cannot be instantiated") + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + cpdef close(self): self.handle_error(afc_file_close(self._client._c_client, self._c_handle)) @@ -133,6 +140,20 @@ cdef class AfcFile(Base): cpdef truncate(self, uint64_t newsize): self.handle_error(afc_file_truncate(self._client._c_client, self._c_handle, newsize)) + cpdef bytes read(self, uint32_t size): + cdef: + uint32_t bytes_read + char* c_data = <char *>malloc(size) + bytes result + try: + self.handle_error(afc_file_read(self._client._c_client, self._c_handle, c_data, size, &bytes_read)) + result = c_data[:bytes_read] + return result + except BaseError, e: + raise + finally: + free(c_data) + cpdef uint32_t write(self, bytes data): cdef: uint32_t bytes_written @@ -141,8 +162,6 @@ cdef class AfcFile(Base): self.handle_error(afc_file_write(self._client._c_client, self._c_handle, c_data, len(data), &bytes_written)) except BaseError, e: raise - finally: - free(c_data) return bytes_written @@ -153,8 +172,9 @@ cdef class AfcClient(BaseService): __service_name__ = "com.apple.afc" cdef afc_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(afc_client_new(device._c_dev, port, &(self._c_client))) + def __cinit__(self, iDevice device = None, LockdownServiceDescriptor descriptor = None, *args, **kwargs): + if (device is not None and descriptor is not None): + self.handle_error(afc_client_new(device._c_dev, descriptor._c_service_descriptor, &(self._c_client))) def __dealloc__(self): cdef afc_error_t err @@ -168,7 +188,7 @@ cdef class AfcClient(BaseService): cpdef list get_device_info(self): cdef: afc_error_t err - char** infos + char** infos = NULL bytes info int i = 0 list result = [] @@ -191,7 +211,7 @@ cdef class AfcClient(BaseService): cpdef list read_directory(self, bytes directory): cdef: afc_error_t err - char** dir_list + char** dir_list = NULL bytes f int i = 0 list result = [] @@ -216,17 +236,17 @@ cdef class AfcClient(BaseService): afc_file_mode_t c_mode uint64_t handle AfcFile f - if mode == <bytes>'r': + if mode == b'r': c_mode = AFC_FOPEN_RDONLY - elif mode == <bytes>'r+': + elif mode == b'r+': c_mode = AFC_FOPEN_RW - elif mode == <bytes>'w': + elif mode == b'w': c_mode = AFC_FOPEN_WRONLY - elif mode == <bytes>'w+': + elif mode == b'w+': c_mode = AFC_FOPEN_WR - elif mode == <bytes>'a': + elif mode == b'a': c_mode = AFC_FOPEN_APPEND - elif mode == <bytes>'a+': + elif mode == b'a+': c_mode = AFC_FOPEN_RDAPPEND else: raise ValueError("mode string must be 'r', 'r+', 'w', 'w+', 'a', or 'a+'") @@ -239,10 +259,10 @@ cdef class AfcClient(BaseService): return f - cpdef get_file_info(self, bytes path): + cpdef list get_file_info(self, bytes path): cdef: list result = [] - char** c_result + char** c_result = NULL int i = 0 bytes info try: @@ -263,6 +283,9 @@ cdef class AfcClient(BaseService): cpdef remove_path(self, bytes path): self.handle_error(afc_remove_path(self._c_client, path)) + cpdef remove_path_and_contents(self, bytes path): + self.handle_error(afc_remove_path_and_contents(self._c_client, path)) + cpdef rename_path(self, bytes f, bytes t): self.handle_error(afc_rename_path(self._c_client, f, t)) @@ -280,3 +303,35 @@ cdef class AfcClient(BaseService): cpdef set_file_time(self, bytes path, uint64_t mtime): self.handle_error(afc_set_file_time(self._c_client, path, mtime)) + +cdef class Afc2Client(AfcClient): + __service_name__ = "com.apple.afc2" + + cpdef AfcFile open(self, bytes filename, bytes mode=b'r'): + cdef: + afc_file_mode_t c_mode + uint64_t handle + AfcFile f + if mode == b'r': + c_mode = AFC_FOPEN_RDONLY + elif mode == b'r+': + c_mode = AFC_FOPEN_RW + elif mode == b'w': + c_mode = AFC_FOPEN_WRONLY + elif mode == b'w+': + c_mode = AFC_FOPEN_WR + elif mode == b'a': + c_mode = AFC_FOPEN_APPEND + elif mode == b'a+': + c_mode = AFC_FOPEN_RDAPPEND + else: + raise ValueError("mode string must be 'r', 'r+', 'w', 'w+', 'a', or 'a+'") + + self.handle_error(afc_file_open(self._c_client, filename, c_mode, &handle)) + f = AfcFile.__new__(AfcFile) + f._c_handle = handle + f._client = <AfcClient>self + f._filename = filename + + return f + diff --git a/cython/debugserver.pxi b/cython/debugserver.pxi new file mode 100644 index 0000000..fb96320 --- /dev/null +++ b/cython/debugserver.pxi @@ -0,0 +1,246 @@ +cdef extern from "libimobiledevice/debugserver.h": + cdef struct debugserver_client_private: + pass + ctypedef debugserver_client_private *debugserver_client_t + cdef struct debugserver_command_private: + pass + ctypedef debugserver_command_private *debugserver_command_t + ctypedef enum debugserver_error_t: + DEBUGSERVER_E_SUCCESS = 0 + DEBUGSERVER_E_INVALID_ARG = -1 + DEBUGSERVER_E_MUX_ERROR = -2 + DEBUGSERVER_E_SSL_ERROR = -3 + DEBUGSERVER_E_RESPONSE_ERROR = -4 + DEBUGSERVER_E_UNKNOWN_ERROR = -256 + + debugserver_error_t debugserver_client_new(idevice_t device, lockdownd_service_descriptor_t service, debugserver_client_t * client) + debugserver_error_t debugserver_client_free(debugserver_client_t client) + + debugserver_error_t debugserver_client_send(debugserver_client_t client, const char* data, uint32_t size, uint32_t *sent) + debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response, size_t* response_size) + debugserver_error_t debugserver_client_receive(debugserver_client_t client, char *data, uint32_t size, uint32_t *received) + debugserver_error_t debugserver_client_receive_with_timeout(debugserver_client_t client, char *data, uint32_t size, uint32_t *received, unsigned int timeout) + debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response, size_t* response_size) + debugserver_error_t debugserver_client_set_argv(debugserver_client_t client, int argc, char* argv[], char** response) + debugserver_error_t debugserver_client_set_environment_hex_encoded(debugserver_client_t client, const char* env, char** response) + + debugserver_error_t debugserver_command_new(const char* name, int argc, const char* argv[], debugserver_command_t* command) + debugserver_error_t debugserver_command_free(debugserver_command_t command) + void debugserver_encode_string(const char* buffer, char** encoded_buffer, uint32_t* encoded_length) + void debugserver_decode_string(const char *encoded_buffer, size_t encoded_length, char** buffer) + + +cdef class DebugServerError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + DEBUGSERVER_E_SUCCESS: "Success", + DEBUGSERVER_E_INVALID_ARG: "Invalid argument", + DEBUGSERVER_E_MUX_ERROR: "MUX error", + DEBUGSERVER_E_SSL_ERROR: "SSL error", + DEBUGSERVER_E_RESPONSE_ERROR: "Response error", + DEBUGSERVER_E_UNKNOWN_ERROR: "Unknown error", + } + BaseError.__init__(self, *args, **kwargs) + + +from cpython.bytes cimport PyBytes_AsString as PyString_AsString +cdef char ** to_cstring_array(list_str): + if not list_str: + return NULL + cdef char **ret = <char **>malloc(len(list_str) * sizeof(char *)) + for i in xrange(len(list_str)): + ret[i] = PyString_AsString(list_str[i]) + return ret + + +cdef class DebugServerCommand(Base): + cdef debugserver_command_t _c_command + + def __init__(self, bytes name, int argc = 0, argv = None, *args, **kwargs): + cdef: + char* c_name = name + char** c_argv = to_cstring_array(argv) + + try: + self.handle_error(debugserver_command_new(c_name, argc, c_argv, &self._c_command)) + except BaseError, e: + raise + finally: + free(c_argv) + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.free() + + cdef free(self): + cdef debugserver_error_t err + if self._c_command is not NULL: + err = debugserver_command_free(self._c_command) + self.handle_error(err) + + cdef inline BaseError _error(self, int16_t ret): + return DebugServerError(ret) + + +cdef class DebugServerClient(BaseService): + __service_name__ = "com.apple.debugserver" + cdef debugserver_client_t _c_client + + def __cinit__(self, iDevice device = None, LockdownServiceDescriptor descriptor = None, *args, **kwargs): + if (device is not None and descriptor is not None): + self.handle_error(debugserver_client_new(device._c_dev, descriptor._c_service_descriptor, &(self._c_client))) + + def __dealloc__(self): + cdef debugserver_error_t err + if self._c_client is not NULL: + err = debugserver_client_free(self._c_client) + self.handle_error(err) + + cdef BaseError _error(self, int16_t ret): + return DebugServerError(ret) + + cpdef uint32_t send(self, bytes data): + cdef: + uint32_t bytes_send + char* c_data = data + try: + self.handle_error(debugserver_client_send(self._c_client, c_data, len(data), &bytes_send)) + except BaseError, e: + raise + + return bytes_send + + cpdef bytes send_command(self, DebugServerCommand command): + cdef: + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_send_command(self._c_client, command._c_command, &c_response, NULL)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_response) + + cpdef bytes receive(self, uint32_t size): + cdef: + uint32_t bytes_received + char* c_data = <char *>malloc(size) + bytes result + + try: + self.handle_error(debugserver_client_receive(self._c_client, c_data, size, &bytes_received)) + result = c_data[:bytes_received] + return result + except BaseError, e: + raise + finally: + free(c_data) + + cpdef bytes receive_with_timeout(self, uint32_t size, unsigned int timeout): + cdef: + uint32_t bytes_received + char* c_data = <char *>malloc(size) + bytes result + + try: + self.handle_error(debugserver_client_receive_with_timeout(self._c_client, c_data, size, &bytes_received, timeout)) + result = c_data[:bytes_received] + return result + except BaseError, e: + raise + finally: + free(c_data) + + cpdef bytes receive_response(self): + cdef: + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_receive_response(self._c_client, &c_response, NULL)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_response) + + cpdef bytes set_argv(self, int argc, argv): + cdef: + char** c_argv = to_cstring_array(argv) + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_set_argv(self._c_client, argc, c_argv, &c_response)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_argv) + free(c_response) + + cpdef bytes set_environment_hex_encoded(self, bytes env): + cdef: + char* c_env = env + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_set_environment_hex_encoded(self._c_client, c_env, &c_response)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_response) + + cpdef bytes encode_string(self, bytes buffer): + cdef: + char *c_buffer = buffer + uint32_t encoded_length = len(c_buffer) * 2 + 0x3 + 1 + char* c_encoded_buffer = <char *>malloc(encoded_length) + bytes result + + try: + debugserver_encode_string(c_buffer, &c_encoded_buffer, &encoded_length) + result = c_encoded_buffer[:encoded_length] + return result + except BaseError, e: + raise + finally: + free(c_encoded_buffer) + + cpdef bytes decode_string(self, bytes encoded_buffer): + cdef: + char* c_encoded_buffer = encoded_buffer + uint32_t encoded_length = len(c_encoded_buffer) + char *c_buffer = <char *>malloc(encoded_length) + bytes result + + try: + debugserver_decode_string(c_encoded_buffer, encoded_length, &c_buffer) + result = c_buffer + return result + except BaseError, e: + raise + finally: + free(c_buffer) diff --git a/cython/diagnostics_relay.pxi b/cython/diagnostics_relay.pxi new file mode 100644 index 0000000..0e6bd20 --- /dev/null +++ b/cython/diagnostics_relay.pxi @@ -0,0 +1,128 @@ +REQUEST_TYPE_ALL = "All" +REQUEST_TYPE_WIFI = "WiFi" +REQUEST_TYPE_GAS_GAUGE = "GasGauge" +REQUEST_TYPE_NAND = "NAND" + +cdef extern from "libimobiledevice/diagnostics_relay.h": + cdef struct diagnostics_relay_client_private: + pass + ctypedef diagnostics_relay_client_private *diagnostics_relay_client_t + + ctypedef enum diagnostics_relay_error_t: + DIAGNOSTICS_RELAY_E_SUCCESS = 0 + DIAGNOSTICS_RELAY_E_INVALID_ARG = -1 + DIAGNOSTICS_RELAY_E_PLIST_ERROR = -2 + DIAGNOSTICS_RELAY_E_MUX_ERROR = -3 + DIAGNOSTICS_RELAY_E_UNKNOWN_REQUEST = -4 + DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR = -256 + ctypedef enum diagnostics_relay_action_t: + DIAGNOSTICS_RELAY_ACTION_FLAG_WAIT_FOR_DISCONNECT = (1 << 1) + DIAGNOSTICS_RELAY_ACTION_FLAG_DISPLAY_PASS = (1 << 2) + DIAGNOSTICS_RELAY_ACTION_FLAG_DISPLAY_FAIL = (1 << 3) + + diagnostics_relay_error_t diagnostics_relay_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, diagnostics_relay_client_t * client) + diagnostics_relay_error_t diagnostics_relay_client_free(diagnostics_relay_client_t client) + + diagnostics_relay_error_t diagnostics_relay_goodbye(diagnostics_relay_client_t client) + diagnostics_relay_error_t diagnostics_relay_sleep(diagnostics_relay_client_t client) + diagnostics_relay_error_t diagnostics_relay_restart(diagnostics_relay_client_t client, diagnostics_relay_action_t flags) + diagnostics_relay_error_t diagnostics_relay_shutdown(diagnostics_relay_client_t client, diagnostics_relay_action_t flags) + diagnostics_relay_error_t diagnostics_relay_request_diagnostics(diagnostics_relay_client_t client, char* type, plist.plist_t* diagnostics) + diagnostics_relay_error_t diagnostics_relay_query_mobilegestalt(diagnostics_relay_client_t client, plist.plist_t keys, plist.plist_t* result) + diagnostics_relay_error_t diagnostics_relay_query_ioregistry_entry(diagnostics_relay_client_t client, char* name, char* class_name, plist.plist_t* result) + diagnostics_relay_error_t diagnostics_relay_query_ioregistry_plane(diagnostics_relay_client_t client, char* plane, plist.plist_t* result) + +cdef class DiagnosticsRelayError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + DIAGNOSTICS_RELAY_E_SUCCESS: "Success", + DIAGNOSTICS_RELAY_E_INVALID_ARG: "Invalid argument", + DIAGNOSTICS_RELAY_E_PLIST_ERROR: "Property list error", + DIAGNOSTICS_RELAY_E_MUX_ERROR: "MUX error", + DIAGNOSTICS_RELAY_E_UNKNOWN_REQUEST: "Unknown request", + DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) + +cdef class DiagnosticsRelayClient(PropertyListService): + __service_name__ = "com.apple.mobile.diagnostics_relay" + cdef diagnostics_relay_client_t _c_client + + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(diagnostics_relay_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) + + def __dealloc__(self): + cdef diagnostics_relay_error_t err + if self._c_client is not NULL: + err = diagnostics_relay_client_free(self._c_client) + self.handle_error(err) + + cdef inline BaseError _error(self, int16_t ret): + return DiagnosticsRelayError(ret) + + cpdef goodbye(self): + self.handle_error(diagnostics_relay_goodbye(self._c_client)) + + cpdef sleep(self): + self.handle_error(diagnostics_relay_sleep(self._c_client)) + + cpdef restart(self, diagnostics_relay_action_t flags): + self.handle_error(diagnostics_relay_restart(self._c_client, flags)) + + cpdef shutdown(self, diagnostics_relay_action_t flags): + self.handle_error(diagnostics_relay_shutdown(self._c_client, flags)) + + cpdef plist.Node request_diagnostics(self, bytes type): + cdef: + plist.plist_t c_node = NULL + diagnostics_relay_error_t err + err = diagnostics_relay_request_diagnostics(self._c_client, type, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef plist.Node query_mobilegestalt(self, plist.Node keys = None): + cdef: + plist.plist_t c_node = NULL + diagnostics_relay_error_t err + plist.plist_t keys_c_node = NULL + if keys is not None: + keys_c_node = keys._c_node + err = diagnostics_relay_query_mobilegestalt(self._c_client, keys_c_node, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef plist.Node query_ioregistry_entry(self, bytes name, bytes class_name): + cdef: + plist.plist_t c_node = NULL + diagnostics_relay_error_t err + err = diagnostics_relay_query_ioregistry_entry(self._c_client, name, class_name, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef plist.Node query_ioregistry_plane(self, bytes plane = None): + cdef: + plist.plist_t c_node = NULL + diagnostics_relay_error_t err + err = diagnostics_relay_query_ioregistry_plane(self._c_client, plane, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise diff --git a/cython/file_relay.pxi b/cython/file_relay.pxi index 450b030..5e9cbbe 100644 --- a/cython/file_relay.pxi +++ b/cython/file_relay.pxi @@ -11,9 +11,10 @@ cdef extern from "libimobiledevice/file_relay.h": FILE_RELAY_E_MUX_ERROR = -3 FILE_RELAY_E_INVALID_SOURCE = -4 FILE_RELAY_E_STAGING_EMPTY = -5 + FILE_RELAY_E_PERMISSION_DENIED = -6 FILE_RELAY_E_UNKNOWN_ERROR = -256 - file_relay_error_t file_relay_client_new(idevice_t device, uint16_t port, file_relay_client_t *client) + file_relay_error_t file_relay_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, file_relay_client_t *client) file_relay_error_t file_relay_client_free(file_relay_client_t client) file_relay_error_t file_relay_request_sources(file_relay_client_t client, const_sources_t sources, idevice_connection_t *connection) @@ -27,6 +28,7 @@ cdef class FileRelayError(BaseError): FILE_RELAY_E_MUX_ERROR: "MUX error", FILE_RELAY_E_INVALID_SOURCE: "Invalid source", FILE_RELAY_E_STAGING_EMPTY: "Staging empty", + FILE_RELAY_E_PERMISSION_DENIED: "Permission denied", FILE_RELAY_E_UNKNOWN_ERROR: "Unknown error" } BaseError.__init__(self, *args, **kwargs) @@ -37,8 +39,8 @@ cdef class FileRelayClient(PropertyListService): __service_name__ = "com.apple.mobile.file_relay" cdef file_relay_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(file_relay_client_new(device._c_dev, port, &self._c_client)) + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(file_relay_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) def __dealloc__(self): cdef file_relay_error_t err diff --git a/cython/heartbeat.pxi b/cython/heartbeat.pxi new file mode 100644 index 0000000..2f58909 --- /dev/null +++ b/cython/heartbeat.pxi @@ -0,0 +1,60 @@ +cdef extern from "libimobiledevice/heartbeat.h": + cdef struct heartbeat_client_private: + pass + ctypedef heartbeat_client_private *heartbeat_client_t + + ctypedef enum heartbeat_error_t: + HEARTBEAT_E_SUCCESS = 0 + HEARTBEAT_E_INVALID_ARG = -1 + HEARTBEAT_E_PLIST_ERROR = -2 + HEARTBEAT_E_MUX_ERROR = -3 + HEARTBEAT_E_SSL_ERROR = -4 + HEARTBEAT_E_NOT_ENOUGH_DATA = -5 + HEARTBEAT_E_TIMEOUT = -6 + HEARTBEAT_E_UNKNOWN_ERROR = -256 + + heartbeat_error_t heartbeat_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, heartbeat_client_t * client) + heartbeat_error_t heartbeat_client_free(heartbeat_client_t client) + + heartbeat_error_t heartbeat_send(heartbeat_client_t client, plist.plist_t plist) + heartbeat_error_t heartbeat_receive(heartbeat_client_t client, plist.plist_t * plist) + heartbeat_error_t heartbeat_receive_with_timeout(heartbeat_client_t client, plist.plist_t * plist, uint32_t timeout_ms) + +cdef class HeartbeatError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + HEARTBEAT_E_SUCCESS: "Success", + HEARTBEAT_E_INVALID_ARG: "Invalid argument", + HEARTBEAT_E_PLIST_ERROR: "Property list error", + HEARTBEAT_E_MUX_ERROR: "MUX error", + HEARTBEAT_E_SSL_ERROR: "SSL Error", + HEARTBEAT_E_NOT_ENOUGH_DATA: 'Not enough data', + HEARTBEAT_E_TIMEOUT: 'Connection timeout', + HEARTBEAT_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) + +cdef class HeartbeatClient(PropertyListService): + __service_name__ = "com.apple.heartbeat" + cdef heartbeat_client_t _c_client + + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(heartbeat_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) + + def __dealloc__(self): + cdef heartbeat_error_t err + if self._c_client is not NULL: + err = heartbeat_client_free(self._c_client) + self.handle_error(err) + + cdef inline int16_t _send(self, plist.plist_t node): + return heartbeat_send(self._c_client, node) + + cdef inline int16_t _receive(self, plist.plist_t* node): + return heartbeat_receive(self._c_client, node) + + cdef inline int16_t _receive_with_timeout(self, plist.plist_t* node, int timeout_ms): + return heartbeat_receive_with_timeout(self._c_client, node, timeout_ms) + + cdef inline BaseError _error(self, int16_t ret): + return HeartbeatError(ret) diff --git a/cython/house_arrest.pxi b/cython/house_arrest.pxi new file mode 100644 index 0000000..54eebc1 --- /dev/null +++ b/cython/house_arrest.pxi @@ -0,0 +1,84 @@ +cdef extern from "libimobiledevice/house_arrest.h": + cdef struct house_arrest_client_private: + pass + ctypedef house_arrest_client_private *house_arrest_client_t + + ctypedef enum house_arrest_error_t: + HOUSE_ARREST_E_SUCCESS = 0 + HOUSE_ARREST_E_INVALID_ARG = -1 + HOUSE_ARREST_E_PLIST_ERROR = -2 + HOUSE_ARREST_E_CONN_FAILED = -3 + HOUSE_ARREST_E_INVALID_MODE = -4 + HOUSE_ARREST_E_UNKNOWN_ERROR = -256 + + house_arrest_error_t house_arrest_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, house_arrest_client_t * client) + house_arrest_error_t house_arrest_client_free(house_arrest_client_t client) + + house_arrest_error_t house_arrest_send_request(house_arrest_client_t client, plist.plist_t dict) + house_arrest_error_t house_arrest_send_command(house_arrest_client_t client, char *command, char *appid) + house_arrest_error_t house_arrest_get_result(house_arrest_client_t client, plist.plist_t *dict) + + afc_error_t afc_client_new_from_house_arrest_client(house_arrest_client_t client, afc_client_t *afc_client) + +cdef class HouseArrestError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + HOUSE_ARREST_E_SUCCESS: "Success", + HOUSE_ARREST_E_INVALID_ARG: "Invalid argument", + HOUSE_ARREST_E_PLIST_ERROR: "Property list error", + HOUSE_ARREST_E_CONN_FAILED: "Connection failed", + HOUSE_ARREST_E_INVALID_MODE: "Invalid mode", + HOUSE_ARREST_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) + +cdef class HouseArrestClient(PropertyListService): + __service_name__ = "com.apple.mobile.house_arrest" + cdef house_arrest_client_t _c_client + + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(house_arrest_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) + + def __dealloc__(self): + cdef house_arrest_error_t err + if self._c_client is not NULL: + err = house_arrest_client_free(self._c_client) + self.handle_error(err) + + cdef inline BaseError _error(self, int16_t ret): + return HouseArrestError(ret) + + cpdef send_request(self, plist.Node message): + self.handle_error(house_arrest_send_request(self._c_client, message._c_node)) + + cpdef send_command(self, bytes command, bytes appid): + self.handle_error(house_arrest_send_command(self._c_client, command, appid)) + + cpdef plist.Node get_result(self): + cdef: + plist.plist_t c_node = NULL + house_arrest_error_t err + err = house_arrest_get_result(self._c_client, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef AfcClient to_afc_client(self): + cdef: + afc_client_t c_afc_client = NULL + AfcClient result + afc_error_t err + err = afc_client_new_from_house_arrest_client(self._c_client, &c_afc_client) + try: + result = AfcClient.__new__(AfcClient) + result._c_client = c_afc_client + result.handle_error(err) + return result + except BaseError, e: + if c_afc_client != NULL: + afc_client_free(c_afc_client); + raise diff --git a/cython/imobiledevice.pxd b/cython/imobiledevice.pxd index 3ec8dfb..238df68 100644 --- a/cython/imobiledevice.pxd +++ b/cython/imobiledevice.pxd @@ -1,6 +1,9 @@ +#!python +#cython: language_level=3str + cimport plist -include "stdint.pxi" +from libc.stdint cimport * cdef extern from "pyerrors.h": ctypedef class __builtin__.Exception [object PyBaseExceptionObject]: @@ -12,7 +15,7 @@ cdef class BaseError(Exception): cdef class Base: cdef inline int handle_error(self, int16_t ret) except -1 - cdef inline BaseError _error(self, int16_t ret) + cdef BaseError _error(self, int16_t ret) cdef class iDeviceError(BaseError): pass @@ -23,13 +26,17 @@ cdef extern from "libimobiledevice/libimobiledevice.h": cdef struct idevice_connection_private: pass ctypedef idevice_connection_private* idevice_connection_t + cdef enum idevice_connection_type: + CONNECTION_USBMUXD = 1 + CONNECTION_NETWORK cdef enum idevice_event_type: - IDEVICE_DEVICE_ADD = 1, + IDEVICE_DEVICE_ADD = 1 IDEVICE_DEVICE_REMOVE + IDEVICE_DEVICE_PAIRED ctypedef struct idevice_event_t: idevice_event_type event char *udid - int conn_type + idevice_connection_type conn_type ctypedef idevice_event_t* const_idevice_event_t "const idevice_event_t*" cdef class iDeviceEvent: @@ -38,6 +45,8 @@ cdef class iDeviceEvent: cdef class iDeviceConnection(Base): cdef idevice_connection_t _c_connection + cpdef bytes receive_timeout(self, uint32_t max_len, unsigned int timeout) + cpdef bytes receive(self, max_len) cpdef disconnect(self) cdef class iDevice(Base): @@ -51,8 +60,10 @@ cdef class BaseService(Base): cdef class PropertyListService(BaseService): cpdef send(self, plist.Node node) cpdef object receive(self) + cpdef object receive_with_timeout(self, int timeout_ms) cdef int16_t _send(self, plist.plist_t node) cdef int16_t _receive(self, plist.plist_t* c_node) + cdef int16_t _receive_with_timeout(self, plist.plist_t* c_node, int timeout_ms) cdef extern from "libimobiledevice/lockdown.h": cdef struct lockdownd_client_private: @@ -64,12 +75,19 @@ cdef extern from "libimobiledevice/lockdown.h": char *host_id char *root_certificate ctypedef lockdownd_pair_record *lockdownd_pair_record_t + cdef struct lockdownd_service_descriptor: + uint16_t port + uint8_t ssl_enabled + ctypedef lockdownd_service_descriptor *lockdownd_service_descriptor_t cdef class LockdownError(BaseError): pass cdef class LockdownPairRecord: cdef lockdownd_pair_record_t _c_record +cdef class LockdownServiceDescriptor(Base): + cdef lockdownd_service_descriptor_t _c_service_descriptor + cdef class LockdownClient(PropertyListService): cdef lockdownd_client_t _c_client cdef readonly iDevice device @@ -78,7 +96,7 @@ cdef class LockdownClient(PropertyListService): cpdef plist.Node get_value(self, bytes domain=*, bytes key=*) cpdef set_value(self, bytes domain, bytes key, object value) cpdef remove_value(self, bytes domain, bytes key) - cpdef uint16_t start_service(self, object service) + cpdef object start_service(self, object service) cpdef object get_service_client(self, object service_class) cpdef tuple start_session(self, bytes host_id) cpdef stop_session(self, bytes session_id) diff --git a/cython/imobiledevice.pyx b/cython/imobiledevice.pyx index 9d2e13d..8da2296 100644 --- a/cython/imobiledevice.pyx +++ b/cython/imobiledevice.pyx @@ -7,7 +7,10 @@ cdef class BaseError(Exception): property message: def __get__(self): - return self._lookup_table[self._c_errcode] + if self._c_errcode in self._lookup_table: + return self._lookup_table[self._c_errcode] + else: + return "Unknown error ({0})".format(self._c_errcode) property code: def __get__(self): @@ -35,8 +38,12 @@ cdef extern from "libimobiledevice/libimobiledevice.h": IDEVICE_E_UNKNOWN_ERROR = -2 IDEVICE_E_NO_DEVICE = -3 IDEVICE_E_NOT_ENOUGH_DATA = -4 - IDEVICE_E_BAD_HEADER = -5 IDEVICE_E_SSL_ERROR = -6 + IDEVICE_E_TIMEOUT = -7 + cdef enum idevice_options: + IDEVICE_LOOKUP_USBMUX = 1 << 1 + IDEVICE_LOOKUP_NETWORK = 1 << 2 + IDEVICE_LOOKUP_PREFER_NETWORK = 1 << 3 ctypedef void (*idevice_event_cb_t) (const_idevice_event_t event, void *user_data) cdef extern idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data) cdef extern idevice_error_t idevice_event_unsubscribe() @@ -44,6 +51,7 @@ cdef extern from "libimobiledevice/libimobiledevice.h": idevice_error_t idevice_device_list_free(char **devices) void idevice_set_debug_level(int level) idevice_error_t idevice_new(idevice_t *device, char *udid) + idevice_error_t idevice_new_with_options(idevice_t *device, const char *udid, idevice_options options); idevice_error_t idevice_free(idevice_t device) idevice_error_t idevice_get_udid(idevice_t device, char** udid) idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle) @@ -61,8 +69,8 @@ cdef class iDeviceError(BaseError): IDEVICE_E_UNKNOWN_ERROR: 'Unknown error', IDEVICE_E_NO_DEVICE: 'No device', IDEVICE_E_NOT_ENOUGH_DATA: 'Not enough data', - IDEVICE_E_BAD_HEADER: 'Bad header', - IDEVICE_E_SSL_ERROR: 'SSL Error' + IDEVICE_E_SSL_ERROR: 'SSL Error', + IDEVICE_E_TIMEOUT: 'Connection timeout' } BaseError.__init__(self, *args, **kwargs) @@ -86,7 +94,7 @@ cdef class iDeviceEvent: def __get__(self): return self._c_event.conn_type -cdef void idevice_event_cb(const_idevice_event_t c_event, void *user_data) with gil: +cdef void idevice_event_cb(const_idevice_event_t c_event, void *user_data) noexcept: cdef iDeviceEvent event = iDeviceEvent.__new__(iDeviceEvent) event._c_event = c_event (<object>user_data)(event) @@ -125,12 +133,42 @@ cdef class iDeviceConnection(Base): def __init__(self, *args, **kwargs): raise TypeError("iDeviceConnection cannot be instantiated. Please use iDevice.connect()") + cpdef bytes receive_timeout(self, uint32_t max_len, unsigned int timeout): + cdef: + uint32_t bytes_received + char* c_data = <char *>malloc(max_len) + bytes result + + try: + self.handle_error(idevice_connection_receive_timeout(self._c_connection, c_data, max_len, &bytes_received, timeout)) + result = c_data[:bytes_received] + return result + except BaseError, e: + raise + finally: + free(c_data) + + cpdef bytes receive(self, max_len): + cdef: + uint32_t bytes_received + char* c_data = <char *>malloc(max_len) + bytes result + + try: + self.handle_error(idevice_connection_receive(self._c_connection, c_data, max_len, &bytes_received)) + result = c_data[:bytes_received] + return result + except BaseError, e: + raise + finally: + free(c_data) + cpdef disconnect(self): cdef idevice_error_t err err = idevice_disconnect(self._c_connection) self.handle_error(err) - cdef inline BaseError _error(self, int16_t ret): + cdef BaseError _error(self, int16_t ret): return iDeviceError(ret) from libc.stdlib cimport * @@ -138,7 +176,7 @@ from libc.stdlib cimport * cdef class iDevice(Base): def __cinit__(self, object udid=None, *args, **kwargs): cdef char* c_udid = NULL - if isinstance(udid, basestring): + if isinstance(udid, (str, bytes)): c_udid = <bytes>udid elif udid is not None: raise TypeError("iDevice's constructor takes a string or None as the udid argument") @@ -148,7 +186,7 @@ cdef class iDevice(Base): if self._c_dev is not NULL: self.handle_error(idevice_free(self._c_dev)) - cdef inline BaseError _error(self, int16_t ret): + cdef BaseError _error(self, int16_t ret): return iDeviceError(ret) cpdef iDeviceConnection connect(self, uint16_t port): @@ -210,12 +248,29 @@ cdef class PropertyListService(BaseService): plist.plist_free(c_node) raise + cpdef object receive_with_timeout(self, int timeout_ms): + cdef: + plist.plist_t c_node = NULL + int16_t err + err = self._receive_with_timeout(&c_node, timeout_ms) + try: + self.handle_error(err) + + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + cdef int16_t _send(self, plist.plist_t node): raise NotImplementedError("send is not implemented") cdef int16_t _receive(self, plist.plist_t* c_node): raise NotImplementedError("receive is not implemented") + cdef int16_t _receive_with_timeout(self, plist.plist_t* c_node, int timeout_ms): + raise NotImplementedError("receive_with_timeout is not implemented") + cdef class DeviceLinkService(PropertyListService): pass @@ -224,8 +279,16 @@ include "mobilesync.pxi" include "notification_proxy.pxi" include "sbservices.pxi" include "mobilebackup.pxi" +include "mobilebackup2.pxi" include "afc.pxi" include "file_relay.pxi" include "screenshotr.pxi" include "installation_proxy.pxi" include "mobile_image_mounter.pxi" +include "webinspector.pxi" +include "heartbeat.pxi" +include "diagnostics_relay.pxi" +include "misagent.pxi" +include "house_arrest.pxi" +include "restore.pxi" +include "debugserver.pxi" diff --git a/cython/installation_proxy.pxi b/cython/installation_proxy.pxi index 3dfb0b1..1d3e323 100644 --- a/cython/installation_proxy.pxi +++ b/cython/installation_proxy.pxi @@ -2,7 +2,7 @@ cdef extern from "libimobiledevice/installation_proxy.h": cdef struct instproxy_client_private: pass ctypedef instproxy_client_private *instproxy_client_t - ctypedef void (*instproxy_status_cb_t) (const_char_ptr operation, plist.plist_t status, void *user_data) + ctypedef void (*instproxy_status_cb_t) (plist.plist_t command, plist.plist_t status, void *user_data) ctypedef enum instproxy_error_t: INSTPROXY_E_SUCCESS = 0 @@ -13,8 +13,9 @@ cdef extern from "libimobiledevice/installation_proxy.h": INSTPROXY_E_OP_FAILED = -5 INSTPROXY_E_UNKNOWN_ERROR = -256 - instproxy_error_t instproxy_client_new(idevice_t device, uint16_t port, instproxy_client_t *client) + instproxy_error_t instproxy_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, instproxy_client_t *client) instproxy_error_t instproxy_client_free(instproxy_client_t client) + instproxy_error_t instproxy_client_get_path_for_bundle_identifier(instproxy_client_t client, const char* bundle_id, char** path) instproxy_error_t instproxy_browse(instproxy_client_t client, plist.plist_t client_options, plist.plist_t *result) instproxy_error_t instproxy_install(instproxy_client_t client, char *pkg_path, plist.plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) @@ -26,8 +27,8 @@ cdef extern from "libimobiledevice/installation_proxy.h": instproxy_error_t instproxy_restore(instproxy_client_t client, char *appid, plist.plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) instproxy_error_t instproxy_remove_archive(instproxy_client_t client, char *appid, plist.plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) -cdef void instproxy_notify_cb(const_char_ptr operation, plist.plist_t status, void *py_callback) with gil: - (<object>py_callback)(operation, plist.plist_t_to_node(status, False)) +cdef void instproxy_notify_cb(plist.plist_t command, plist.plist_t status, void *py_callback) noexcept: + (<object>py_callback)(plist.plist_t_to_node(command, False), plist.plist_t_to_node(status, False)) cdef class InstallationProxyError(BaseError): def __init__(self, *args, **kwargs): @@ -46,11 +47,11 @@ cdef class InstallationProxyClient(PropertyListService): __service_name__ = "com.apple.mobile.installation_proxy" cdef instproxy_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): cdef: iDevice dev = device instproxy_error_t err - err = instproxy_client_new(dev._c_dev, port, &self._c_client) + err = instproxy_client_new(dev._c_dev, descriptor._c_service_descriptor, &self._c_client) self.handle_error(err) def __dealloc__(self): @@ -59,6 +60,24 @@ cdef class InstallationProxyClient(PropertyListService): err = instproxy_client_free(self._c_client) self.handle_error(err) + cpdef get_path_for_bundle_identifier(self, bytes bundle_id): + cdef: + char* c_bundle_id = bundle_id + char* c_path = NULL + bytes result + + try: + self.handle_error(instproxy_client_get_path_for_bundle_identifier(self._c_client, c_bundle_id, &c_path)) + if c_path != NULL: + result = c_path + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_path) + cpdef plist.Node browse(self, object client_options): cdef: plist.Node options diff --git a/cython/lockdown.pxi b/cython/lockdown.pxi index b5207e8..25edb4c 100644 --- a/cython/lockdown.pxi +++ b/cython/lockdown.pxi @@ -1,25 +1,48 @@ cdef extern from "libimobiledevice/lockdown.h": ctypedef enum lockdownd_error_t: - LOCKDOWN_E_SUCCESS = 0 - LOCKDOWN_E_INVALID_ARG = -1 - LOCKDOWN_E_INVALID_CONF = -2 - LOCKDOWN_E_PLIST_ERROR = -3 - LOCKDOWN_E_PAIRING_FAILED = -4 - LOCKDOWN_E_SSL_ERROR = -5 - LOCKDOWN_E_DICT_ERROR = -6 - LOCKDOWN_E_START_SERVICE_FAILED = -7 - LOCKDOWN_E_NOT_ENOUGH_DATA = -8 - LOCKDOWN_E_SET_VALUE_PROHIBITED = -9 - LOCKDOWN_E_GET_VALUE_PROHIBITED = -10 - LOCKDOWN_E_REMOVE_VALUE_PROHIBITED = -11 - LOCKDOWN_E_MUX_ERROR = -12 - LOCKDOWN_E_ACTIVATION_FAILED = -13 - LOCKDOWN_E_PASSWORD_PROTECTED = -14 - LOCKDOWN_E_NO_RUNNING_SESSION = -15 - LOCKDOWN_E_INVALID_HOST_ID = -16 - LOCKDOWN_E_INVALID_SERVICE = -17 - LOCKDOWN_E_INVALID_ACTIVATION_RECORD = -18 - LOCKDOWN_E_UNKNOWN_ERROR = -256 + LOCKDOWN_E_SUCCESS + LOCKDOWN_E_INVALID_ARG + LOCKDOWN_E_INVALID_CONF + LOCKDOWN_E_PLIST_ERROR + LOCKDOWN_E_PAIRING_FAILED + LOCKDOWN_E_SSL_ERROR + LOCKDOWN_E_DICT_ERROR + LOCKDOWN_E_RECEIVE_TIMEOUT + LOCKDOWN_E_SET_VALUE_PROHIBITED + LOCKDOWN_E_GET_VALUE_PROHIBITED + LOCKDOWN_E_MUX_ERROR + LOCKDOWN_E_NO_RUNNING_SESSION + LOCKDOWN_E_INVALID_RESPONSE + LOCKDOWN_E_MISSING_KEY + LOCKDOWN_E_MISSING_VALUE + LOCKDOWN_E_GET_PROHIBITED + LOCKDOWN_E_SET_PROHIBITED + LOCKDOWN_E_REMOVE_PROHIBITED + LOCKDOWN_E_IMMUTABLE_VALUE + LOCKDOWN_E_PASSWORD_PROTECTED + LOCKDOWN_E_USER_DENIED_PAIRING + LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING + LOCKDOWN_E_MISSING_HOST_ID + LOCKDOWN_E_INVALID_HOST_ID + LOCKDOWN_E_SESSION_ACTIVE + LOCKDOWN_E_SESSION_INACTIVE + LOCKDOWN_E_MISSING_SESSION_ID + LOCKDOWN_E_INVALID_SESSION_ID + LOCKDOWN_E_MISSING_SERVICE + LOCKDOWN_E_INVALID_SERVICE + LOCKDOWN_E_SERVICE_LIMIT + LOCKDOWN_E_MISSING_PAIR_RECORD + LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED + LOCKDOWN_E_INVALID_PAIR_RECORD + LOCKDOWN_E_INVALID_ACTIVATION_RECORD + LOCKDOWN_E_MISSING_ACTIVATION_RECORD + LOCKDOWN_E_SERVICE_PROHIBITED + LOCKDOWN_E_ESCROW_LOCKED + LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION + LOCKDOWN_E_FMIP_PROTECTED + LOCKDOWN_E_MC_PROTECTED + LOCKDOWN_E_MC_CHALLENGE_REQUIRED + LOCKDOWN_E_UNKNOWN_ERROR lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, char *label) lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdownd_client_t *client, char *label) @@ -29,7 +52,7 @@ cdef extern from "libimobiledevice/lockdown.h": lockdownd_error_t lockdownd_get_value(lockdownd_client_t client, char *domain, char *key, plist.plist_t *value) lockdownd_error_t lockdownd_set_value(lockdownd_client_t client, char *domain, char *key, plist.plist_t value) lockdownd_error_t lockdownd_remove_value(lockdownd_client_t client, char *domain, char *key) - lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, char *service, uint16_t *port) + lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, char *identifier, lockdownd_service_descriptor_t *service) lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, char *host_id, char **session_id, int *ssl_enabled) lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, char *session_id) lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist.plist_t plist) @@ -43,6 +66,7 @@ cdef extern from "libimobiledevice/lockdown.h": lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client) lockdownd_error_t lockdownd_get_sync_data_classes(lockdownd_client_t client, char ***classes, int *count) lockdownd_error_t lockdownd_data_classes_free(char **classes) + lockdownd_error_t lockdownd_service_descriptor_free(lockdownd_service_descriptor_t service) cdef class LockdownError(BaseError): def __init__(self, *args, **kwargs): @@ -53,19 +77,40 @@ cdef class LockdownError(BaseError): LOCKDOWN_E_PLIST_ERROR: "Property list error", LOCKDOWN_E_PAIRING_FAILED: "Pairing failed", LOCKDOWN_E_SSL_ERROR: "SSL error", - LOCKDOWN_E_DICT_ERROR: "Dict error", - LOCKDOWN_E_START_SERVICE_FAILED: "Start service failed", - LOCKDOWN_E_NOT_ENOUGH_DATA: "Not enough data", - LOCKDOWN_E_SET_VALUE_PROHIBITED: "Set value prohibited", - LOCKDOWN_E_GET_VALUE_PROHIBITED: "Get value prohibited", - LOCKDOWN_E_REMOVE_VALUE_PROHIBITED: "Remove value prohibited", - LOCKDOWN_E_MUX_ERROR: "MUX Error", - LOCKDOWN_E_ACTIVATION_FAILED: "Activation failed", - LOCKDOWN_E_PASSWORD_PROTECTED: "Password protected", + LOCKDOWN_E_DICT_ERROR: "Dictionary error", + LOCKDOWN_E_RECEIVE_TIMEOUT: "Receive timeout", + LOCKDOWN_E_MUX_ERROR: "Mux Protocol Error", LOCKDOWN_E_NO_RUNNING_SESSION: "No running session", + LOCKDOWN_E_INVALID_RESPONSE: "Invalid response", + LOCKDOWN_E_MISSING_KEY: "Missing key", + LOCKDOWN_E_MISSING_VALUE: "Missing value", + LOCKDOWN_E_GET_PROHIBITED: "Get value prohibited", + LOCKDOWN_E_SET_PROHIBITED: "Set value prohibited", + LOCKDOWN_E_REMOVE_PROHIBITED: "Remove value prohibited", + LOCKDOWN_E_IMMUTABLE_VALUE: "Immutable value", + LOCKDOWN_E_PASSWORD_PROTECTED: "Password protected", + LOCKDOWN_E_USER_DENIED_PAIRING: "User denied pairing", + LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING: "Pairing dialog response pending", + LOCKDOWN_E_MISSING_HOST_ID: "Missing host ID", LOCKDOWN_E_INVALID_HOST_ID: "Invalid host ID", + LOCKDOWN_E_SESSION_ACTIVE: "Session active", + LOCKDOWN_E_SESSION_INACTIVE: "Session inactive", + LOCKDOWN_E_MISSING_SESSION_ID: "Missing session ID", + LOCKDOWN_E_INVALID_SESSION_ID: "Invalid session ID", + LOCKDOWN_E_MISSING_SERVICE: "Missing service", LOCKDOWN_E_INVALID_SERVICE: "Invalid service", + LOCKDOWN_E_SERVICE_LIMIT: "Service limit reached", + LOCKDOWN_E_MISSING_PAIR_RECORD: "Missing pair record", + LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED: "Saving pair record failed", + LOCKDOWN_E_INVALID_PAIR_RECORD: "Invalid pair record", LOCKDOWN_E_INVALID_ACTIVATION_RECORD: "Invalid activation record", + LOCKDOWN_E_MISSING_ACTIVATION_RECORD: "Missing activation record", + LOCKDOWN_E_SERVICE_PROHIBITED: "Service prohibited", + LOCKDOWN_E_ESCROW_LOCKED: "Escrow locked", + LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION: "Pairing prohibited over this connection", + LOCKDOWN_E_FMIP_PROTECTED: "Find My iPhone/iPod/iPad protected", + LOCKDOWN_E_MC_PROTECTED: "MC protected", + LOCKDOWN_E_MC_CHALLENGE_REQUIRED: "MC challenge required", LOCKDOWN_E_UNKNOWN_ERROR: "Unknown error" } BaseError.__init__(self, *args, **kwargs) @@ -89,6 +134,21 @@ cdef class LockdownPairRecord: cdef bytes result = self._c_record.root_certificate return result +cdef class LockdownServiceDescriptor(Base): + #def __cinit__(self, uint16_t port, uint8_t ssl_enabled, *args, **kwargs): + def __dealloc__(self): + cdef lockdownd_error_t err + if self._c_service_descriptor is not NULL: + err = lockdownd_service_descriptor_free(self._c_service_descriptor) + self._c_service_descriptor = NULL + self.handle_error(err) + property port: + def __get__(self): + return self._c_service_descriptor.port + property ssl_enabled: + def __get__(self): + return self._c_service_descriptor.ssl_enabled + cdef class LockdownClient(PropertyListService): def __cinit__(self, iDevice device not None, bytes label=b'', bint handshake=True, *args, **kwargs): cdef: @@ -150,51 +210,64 @@ cdef class LockdownClient(PropertyListService): raise cpdef set_value(self, bytes domain, bytes key, object value): - cdef plist.plist_t c_node = plist.native_to_plist_t(value) + cdef: + plist.plist_t c_node = NULL + char* c_domain = NULL + char* c_key = NULL + + c_node = plist.native_to_plist_t(value) + if domain is not None: + c_domain = domain + if key is not None: + c_key = key try: - self.handle_error(lockdownd_set_value(self._c_client, domain, key, c_node)) + self.handle_error(lockdownd_set_value(self._c_client, c_domain, c_key, c_node)) except BaseError, e: raise finally: if c_node != NULL: - plist.plist_free(c_node) + c_node = NULL cpdef remove_value(self, bytes domain, bytes key): self.handle_error(lockdownd_remove_value(self._c_client, domain, key)) - cpdef uint16_t start_service(self, object service): + cpdef object start_service(self, object service): cdef: char* c_service_name = NULL - uint16_t port = 0 + lockdownd_service_descriptor_t c_descriptor = NULL + LockdownServiceDescriptor result if issubclass(service, BaseService) and \ service.__service_name__ is not None \ - and isinstance(service.__service_name__, basestring): - c_service_name = <bytes>service.__service_name__ - elif isinstance(service, basestring): - c_service_name = <bytes>service + and isinstance(service.__service_name__, (str, bytes)): + c_service_name_str = service.__service_name__.encode('utf-8') + elif isinstance(service, (str, bytes)): + c_service_name_str = service.encode('utf-8') else: raise TypeError("LockdownClient.start_service() takes a BaseService or string as its first argument") + c_service_name = c_service_name_str try: - self.handle_error(lockdownd_start_service(self._c_client, c_service_name, &port)) - - return port + self.handle_error(lockdownd_start_service(self._c_client, c_service_name, &c_descriptor)) + + result = LockdownServiceDescriptor.__new__(LockdownServiceDescriptor) + result._c_service_descriptor = c_descriptor + + return result except BaseError, e: raise cpdef object get_service_client(self, object service_class): cdef: - uint16_t port = 0 - object result + LockdownServiceDescriptor descriptor if not hasattr(service_class, '__service_name__') and \ not service_class.__service_name__ is not None \ - and not isinstance(service_class.__service_name__, basestring): + and not isinstance(service_class.__service_name__, (str, bytes)): raise TypeError("LockdownClient.get_service_client() takes a BaseService as its first argument") - port = self.start_service(service_class) - return service_class(self.device, port) + descriptor = self.start_service(service_class) + return service_class(self.device, descriptor) cpdef tuple start_session(self, bytes host_id): cdef: @@ -202,7 +275,7 @@ cdef class LockdownClient(PropertyListService): char* c_session_id = NULL bint ssl_enabled bytes session_id - err = lockdownd_start_session(self._c_client, host_id, &c_session_id, &ssl_enabled) + err = lockdownd_start_session(self._c_client, host_id, &c_session_id, <int *>&ssl_enabled) try: self.handle_error(err) diff --git a/cython/misagent.pxi b/cython/misagent.pxi new file mode 100644 index 0000000..1fee4b9 --- /dev/null +++ b/cython/misagent.pxi @@ -0,0 +1,74 @@ +cdef extern from "libimobiledevice/misagent.h": + cdef struct misagent_client_private: + pass + ctypedef misagent_client_private *misagent_client_t + + ctypedef enum misagent_error_t: + MISAGENT_E_SUCCESS = 0 + MISAGENT_E_INVALID_ARG = -1 + MISAGENT_E_PLIST_ERROR = -2 + MISAGENT_E_CONN_FAILED = -3 + MISAGENT_E_REQUEST_FAILED = -4 + MISAGENT_E_UNKNOWN_ERROR = -256 + + misagent_error_t misagent_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, misagent_client_t * client) + misagent_error_t misagent_client_free(misagent_client_t client) + + misagent_error_t misagent_install(misagent_client_t client, plist.plist_t profile) + misagent_error_t misagent_copy(misagent_client_t client, plist.plist_t* profiles) + misagent_error_t misagent_remove(misagent_client_t client, char* profileID) + int misagent_get_status_code(misagent_client_t client) + +cdef class MisagentError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + MISAGENT_E_SUCCESS: "Success", + MISAGENT_E_INVALID_ARG: "Invalid argument", + MISAGENT_E_PLIST_ERROR: "Property list error", + MISAGENT_E_CONN_FAILED: "Connection failed", + MISAGENT_E_REQUEST_FAILED: "Request failed", + MISAGENT_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) + +cdef class MisagentClient(PropertyListService): + __service_name__ = "com.apple.misagent" + cdef misagent_client_t _c_client + + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(misagent_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) + + def __dealloc__(self): + cdef misagent_error_t err + if self._c_client is not NULL: + err = misagent_client_free(self._c_client) + self.handle_error(err) + + cdef inline BaseError _error(self, int16_t ret): + return MisagentError(ret) + + cpdef install(self, plist.Node profile): + cdef misagent_error_t err + err = misagent_install(self._c_client, profile._c_node) + self.handle_error(err) + + cpdef plist.Node copy(self): + cdef: + plist.plist_t c_node = NULL + misagent_error_t err + err = misagent_copy(self._c_client, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef remove(self, bytes profile_id): + cdef misagent_error_t err + err = misagent_remove(self._c_client, profile_id) + self.handle_error(err) + + cpdef int get_status_code(self): + return misagent_get_status_code(self._c_client) diff --git a/cython/mobile_image_mounter.pxi b/cython/mobile_image_mounter.pxi index bf304d4..d9d40d5 100644 --- a/cython/mobile_image_mounter.pxi +++ b/cython/mobile_image_mounter.pxi @@ -10,10 +10,12 @@ cdef extern from "libimobiledevice/mobile_image_mounter.h": MOBILE_IMAGE_MOUNTER_E_CONN_FAILED = -3 MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR = -256 - mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, uint16_t port, mobile_image_mounter_client_t *client) + mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, lockdownd_service_descriptor_t descriptor, mobile_image_mounter_client_t *client) mobile_image_mounter_error_t mobile_image_mounter_free(mobile_image_mounter_client_t client) mobile_image_mounter_error_t mobile_image_mounter_lookup_image(mobile_image_mounter_client_t client, char *image_type, plist.plist_t *result) - mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, char *image_path, char *image_signature, uint16_t signature_length, char *image_type, plist.plist_t *result) + mobile_image_mounter_error_t mobile_image_mounter_mount_image_with_options(mobile_image_mounter_client_t client, char *image_path, const unsigned char *signature, unsigned int signature_length, char *image_type, plist.plist_t options, plist.plist_t *result) + mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, char *image_path, const unsigned char *signature, unsigned int signature_length, char *image_type, plist.plist_t *result) + mobile_image_mounter_error_t mobile_image_mounter_unmount_image(mobile_image_mounter_client_t client, const char *mount_path); mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client) cdef class MobileImageMounterError(BaseError): @@ -31,8 +33,8 @@ cdef class MobileImageMounterClient(PropertyListService): __service_name__ = "com.apple.mobile.mobile_image_mounter" cdef mobile_image_mounter_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(mobile_image_mounter_new(device._c_dev, port, &self._c_client)) + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(mobile_image_mounter_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) def __dealloc__(self): cdef mobile_image_mounter_error_t err @@ -57,11 +59,39 @@ cdef class MobileImageMounterClient(PropertyListService): if c_node != NULL: plist.plist_free(c_node) - cpdef plist.Node mount_image(self, bytes image_path, bytes image_signature, bytes image_type): + cpdef plist.Node mount_image_with_options(self, bytes image_path, bytes signature, bytes image_type, object options): cdef: + plist.Node n_options + plist.plist_t c_options + plist.plist_t c_result = NULL + bint free_options = False plist.plist_t c_node = NULL mobile_image_mounter_error_t err - err = mobile_image_mounter_mount_image(self._c_client, image_path, image_signature, len(image_signature), + if isinstance(options, plist.Dict): + n_options = options + c_options = n_options._c_node + elif isinstance(options, dict): + c_options = plist.native_to_plist_t(options) + free_options = True + else: + raise InstallationProxyError(INSTPROXY_E_INVALID_ARG) + err = mobile_image_mounter_mount_image_with_options(self._c_client, image_path, signature, len(signature), + image_type, c_options, &c_node) + if free_options: + plist.plist_free(c_options) + try: + self.handle_error(err) + + return plist.plist_t_to_node(c_node) + except Exception, e: + if c_node != NULL: + plist.plist_free(c_node) + + cpdef plist.Node mount_image(self, bytes image_path, bytes signature, bytes image_type): + cdef: + plist.plist_t c_node = NULL + mobile_image_mounter_error_t err + err = mobile_image_mounter_mount_image(self._c_client, image_path, signature, len(signature), image_type, &c_node) try: @@ -72,6 +102,13 @@ cdef class MobileImageMounterClient(PropertyListService): if c_node != NULL: plist.plist_free(c_node) + cpdef unmount_image(self, bytes mount_path): + cdef: + mobile_image_mounter_error_t err + err = mobile_image_mounter_unmount_image(self._c_client, mount_path) + + self.handle_error(err) + cpdef hangup(self): cdef mobile_image_mounter_error_t err err = mobile_image_mounter_hangup(self._c_client) diff --git a/cython/mobilebackup.pxi b/cython/mobilebackup.pxi index 4f07683..f2d58d4 100644 --- a/cython/mobilebackup.pxi +++ b/cython/mobilebackup.pxi @@ -8,13 +8,28 @@ cdef extern from "libimobiledevice/mobilebackup.h": MOBILEBACKUP_E_INVALID_ARG = -1 MOBILEBACKUP_E_PLIST_ERROR = -2 MOBILEBACKUP_E_MUX_ERROR = -3 - MOBILEBACKUP_E_BAD_VERSION = -4 + MOBILEBACKUP_E_SSL_ERROR = -4 + MOBILEBACKUP_E_RECEIVE_TIMEOUT = -5 + MOBILEBACKUP_E_BAD_VERSION = -6 + MOBILEBACKUP_E_REPLY_NOT_OK = -7 MOBILEBACKUP_E_UNKNOWN_ERROR = -256 - mobilebackup_error_t mobilebackup_client_new(idevice_t device, uint16_t port, mobilebackup_client_t * client) + ctypedef enum mobilebackup_flags_t: + MB_RESTORE_NOTIFY_SPRINGBOARD = (1 << 0) + MB_RESTORE_PRESERVE_SETTINGS = (1 << 1) + MB_RESTORE_PRESERVE_CAMERA_ROLL = (1 << 2) + + mobilebackup_error_t mobilebackup_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, mobilebackup_client_t * client) mobilebackup_error_t mobilebackup_client_free(mobilebackup_client_t client) mobilebackup_error_t mobilebackup_receive(mobilebackup_client_t client, plist.plist_t *plist) mobilebackup_error_t mobilebackup_send(mobilebackup_client_t client, plist.plist_t plist) + mobilebackup_error_t mobilebackup_request_backup(mobilebackup_client_t client, plist.plist_t backup_manifest, char *base_path, char *proto_version) + mobilebackup_error_t mobilebackup_send_backup_file_received(mobilebackup_client_t client) + mobilebackup_error_t mobilebackup_request_restore(mobilebackup_client_t client, plist.plist_t backup_manifest, mobilebackup_flags_t flags, char *proto_version) + mobilebackup_error_t mobilebackup_receive_restore_file_received(mobilebackup_client_t client, plist.plist_t *result) + mobilebackup_error_t mobilebackup_receive_restore_application_received(mobilebackup_client_t client, plist.plist_t *result) + mobilebackup_error_t mobilebackup_send_restore_complete(mobilebackup_client_t client) + mobilebackup_error_t mobilebackup_send_error(mobilebackup_client_t client, char *reason) cdef class MobileBackupError(BaseError): def __init__(self, *args, **kwargs): @@ -23,7 +38,10 @@ cdef class MobileBackupError(BaseError): MOBILEBACKUP_E_INVALID_ARG: "Invalid argument", MOBILEBACKUP_E_PLIST_ERROR: "Property list error", MOBILEBACKUP_E_MUX_ERROR: "MUX error", + MOBILEBACKUP_E_SSL_ERROR: "SSL error", + MOBILEBACKUP_E_RECEIVE_TIMEOUT: "Receive timeout", MOBILEBACKUP_E_BAD_VERSION: "Bad version", + MOBILEBACKUP_E_REPLY_NOT_OK: "Reply not OK", MOBILEBACKUP_E_UNKNOWN_ERROR: "Unknown error" } BaseError.__init__(self, *args, **kwargs) @@ -32,8 +50,8 @@ cdef class MobileBackupClient(PropertyListService): __service_name__ = "com.apple.mobilebackup" cdef mobilebackup_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(mobilebackup_client_new(device._c_dev, port, &self._c_client)) + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(mobilebackup_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) def __dealloc__(self): cdef mobilebackup_error_t err @@ -41,11 +59,52 @@ cdef class MobileBackupClient(PropertyListService): err = mobilebackup_client_free(self._c_client) self.handle_error(err) + cdef inline BaseError _error(self, int16_t ret): + return MobileBackupError(ret) + cdef inline int16_t _send(self, plist.plist_t node): return mobilebackup_send(self._c_client, node) cdef inline int16_t _receive(self, plist.plist_t* node): return mobilebackup_receive(self._c_client, node) - cdef inline BaseError _error(self, int16_t ret): - return MobileBackupError(ret) + cdef request_backup(self, plist.Node backup_manifest, bytes base_path, bytes proto_version): + self.handle_error(mobilebackup_request_backup(self._c_client, backup_manifest._c_node, base_path, proto_version)) + + cdef send_backup_file_received(self): + self.handle_error(mobilebackup_send_backup_file_received(self._c_client)) + + cdef request_restore(self, plist.Node backup_manifest, int flags, proto_version): + self.handle_error(mobilebackup_request_restore(self._c_client, backup_manifest._c_node, <mobilebackup_flags_t>flags, proto_version)) + + cpdef plist.Node receive_restore_file_received(self): + cdef: + plist.plist_t c_node = NULL + mobilebackup_error_t err + err = mobilebackup_receive_restore_file_received(self._c_client, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef plist.Node receive_restore_application_received(self): + cdef: + plist.plist_t c_node = NULL + mobilebackup_error_t err + err = mobilebackup_receive_restore_application_received(self._c_client, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cdef send_restore_complete(self): + self.handle_error(mobilebackup_send_restore_complete(self._c_client)) + + cdef send_error(self, bytes reason): + self.handle_error(mobilebackup_send_error(self._c_client, reason)) diff --git a/cython/mobilebackup2.pxi b/cython/mobilebackup2.pxi new file mode 100644 index 0000000..4b47e5b --- /dev/null +++ b/cython/mobilebackup2.pxi @@ -0,0 +1,123 @@ +cdef extern from "libimobiledevice/mobilebackup2.h": + cdef struct mobilebackup2_client_private: + pass + ctypedef mobilebackup2_client_private *mobilebackup2_client_t + + ctypedef enum mobilebackup2_error_t: + MOBILEBACKUP2_E_SUCCESS = 0 + MOBILEBACKUP2_E_INVALID_ARG = -1 + MOBILEBACKUP2_E_PLIST_ERROR = -2 + MOBILEBACKUP2_E_MUX_ERROR = -3 + MOBILEBACKUP2_E_SSL_ERROR = -4 + MOBILEBACKUP2_E_RECEIVE_TIMEOUT = -5 + MOBILEBACKUP2_E_BAD_VERSION = -6 + MOBILEBACKUP2_E_REPLY_NOT_OK = -7 + MOBILEBACKUP2_E_NO_COMMON_VERSION = -8 + MOBILEBACKUP2_E_UNKNOWN_ERROR = -256 + + mobilebackup2_error_t mobilebackup2_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, mobilebackup2_client_t * client) + mobilebackup2_error_t mobilebackup2_client_free(mobilebackup2_client_t client) + + mobilebackup2_error_t mobilebackup2_send_message(mobilebackup2_client_t client, char *message, plist.plist_t options) + mobilebackup2_error_t mobilebackup2_receive_message(mobilebackup2_client_t client, plist.plist_t *msg_plist, char **dlmessage) + mobilebackup2_error_t mobilebackup2_send_raw(mobilebackup2_client_t client, char *data, uint32_t length, uint32_t *bytes) + mobilebackup2_error_t mobilebackup2_receive_raw(mobilebackup2_client_t client, char *data, uint32_t length, uint32_t *bytes) + mobilebackup2_error_t mobilebackup2_version_exchange(mobilebackup2_client_t client, double local_versions[], char count, double *remote_version) + mobilebackup2_error_t mobilebackup2_send_request(mobilebackup2_client_t client, char *request, char *target_identifier, char *source_identifier, plist.plist_t options) + mobilebackup2_error_t mobilebackup2_send_status_response(mobilebackup2_client_t client, int status_code, char *status1, plist.plist_t status2) + +cdef class MobileBackup2Error(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + MOBILEBACKUP2_E_SUCCESS: "Success", + MOBILEBACKUP2_E_INVALID_ARG: "Invalid argument", + MOBILEBACKUP2_E_PLIST_ERROR: "Property list error", + MOBILEBACKUP2_E_MUX_ERROR: "MUX error", + MOBILEBACKUP2_E_SSL_ERROR: "SSL error", + MOBILEBACKUP2_E_RECEIVE_TIMEOUT: "Receive timeout", + MOBILEBACKUP2_E_BAD_VERSION: "Bad version", + MOBILEBACKUP2_E_REPLY_NOT_OK: "Reply not OK", + MOBILEBACKUP2_E_NO_COMMON_VERSION: "No common version", + MOBILEBACKUP2_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) + +cdef class MobileBackup2Client(PropertyListService): + __service_name__ = "com.apple.mobilebackup2" + cdef mobilebackup2_client_t _c_client + + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(mobilebackup2_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) + + def __dealloc__(self): + cdef mobilebackup2_error_t err + if self._c_client is not NULL: + err = mobilebackup2_client_free(self._c_client) + self.handle_error(err) + + cdef inline BaseError _error(self, int16_t ret): + return MobileBackup2Error(ret) + + cpdef send_message(self, bytes message, plist.Node options): + self.handle_error(mobilebackup2_send_message(self._c_client, message, options._c_node)) + + cpdef tuple receive_message(self): + cdef: + char* dlmessage = NULL + plist.plist_t c_node = NULL + mobilebackup2_error_t err + err = mobilebackup2_receive_message(self._c_client, &c_node, &dlmessage) + try: + self.handle_error(err) + return (plist.plist_t_to_node(c_node), <bytes>dlmessage) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + if dlmessage != NULL: + free(dlmessage) + raise + + cpdef int send_raw(self, bytes data, int length): + cdef: + uint32_t bytes_recvd = 0 + mobilebackup2_error_t err + err = mobilebackup2_send_raw(self._c_client, data, length, &bytes_recvd) + try: + self.handle_error(err) + return <bint>bytes_recvd + except BaseError, e: + raise + + cpdef int receive_raw(self, bytearray data, int length): + cdef: + uint32_t bytes_recvd = 0 + mobilebackup2_error_t err + err = mobilebackup2_receive_raw(self._c_client, data, length, &bytes_recvd) + + # Throwing an exception when we test if theres more data to read is excessive + if err == -1 and bytes_recvd == 0: + return 0 + + try: + self.handle_error(err) + return <bint>bytes_recvd + except BaseError, e: + raise + + cpdef float version_exchange(self, double[::1] local_versions): + cdef: + double[::1] temp = None + double remote_version = 0.0 + mobilebackup2_error_t err + err = mobilebackup2_version_exchange(self._c_client, &local_versions[0], len(local_versions), &remote_version) + try: + self.handle_error(err) + return <float>remote_version + except BaseError, e: + raise + + cpdef send_request(self, bytes request, bytes target_identifier, bytes source_identifier, plist.Node options): + self.handle_error(mobilebackup2_send_request(self._c_client, request, target_identifier, source_identifier, options._c_node)) + + cpdef send_status_response(self, int status_code, bytes status1, plist.Node status2): + self.handle_error(mobilebackup2_send_status_response(self._c_client, status_code, status1, status2._c_node)) diff --git a/cython/mobilesync.pxi b/cython/mobilesync.pxi index e610191..23f0005 100644 --- a/cython/mobilesync.pxi +++ b/cython/mobilesync.pxi @@ -7,11 +7,13 @@ cdef extern from "libimobiledevice/mobilesync.h": MOBILESYNC_E_INVALID_ARG = -1 MOBILESYNC_E_PLIST_ERROR = -2 MOBILESYNC_E_MUX_ERROR = -3 - MOBILESYNC_E_BAD_VERSION = -4 - MOBILESYNC_E_SYNC_REFUSED = -5 - MOBILESYNC_E_CANCELLED = -6 - MOBILESYNC_E_WRONG_DIRECTION = -7 - MOBILESYNC_E_NOT_READY = -8 + MOBILESYNC_E_SSL_ERROR = -4 + MOBILESYNC_E_RECEIVE_TIMEOUT = -5 + MOBILESYNC_E_BAD_VERSION = -6 + MOBILESYNC_E_SYNC_REFUSED = -7 + MOBILESYNC_E_CANCELLED = -8 + MOBILESYNC_E_WRONG_DIRECTION = -9 + MOBILESYNC_E_NOT_READY = -10 MOBILESYNC_E_UNKNOWN_ERROR = -256 ctypedef enum mobilesync_sync_type_t: @@ -24,12 +26,12 @@ cdef extern from "libimobiledevice/mobilesync.h": char *host_anchor ctypedef mobilesync_anchors *mobilesync_anchors_t - mobilesync_error_t mobilesync_client_new(idevice_t device, uint16_t port, mobilesync_client_t * client) + mobilesync_error_t mobilesync_client_new(idevice_t device, lockdownd_service_descriptor_t service, mobilesync_client_t * client) mobilesync_error_t mobilesync_client_free(mobilesync_client_t client) mobilesync_error_t mobilesync_receive(mobilesync_client_t client, plist.plist_t *plist) mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist.plist_t plist) - mobilesync_error_t mobilesync_start(mobilesync_client_t client, char *data_class, mobilesync_anchors_t anchors, uint64_t computer_data_class_version, mobilesync_sync_type_t *sync_type, uint64_t *device_data_class_version) + mobilesync_error_t mobilesync_start(mobilesync_client_t client, char *data_class, mobilesync_anchors_t anchors, uint64_t computer_data_class_version, mobilesync_sync_type_t *sync_type, uint64_t *device_data_class_version, char** error_description) mobilesync_error_t mobilesync_cancel(mobilesync_client_t client, char* reason) mobilesync_error_t mobilesync_finish(mobilesync_client_t client) @@ -60,6 +62,8 @@ cdef class MobileSyncError(BaseError): MOBILESYNC_E_INVALID_ARG: "Invalid argument", MOBILESYNC_E_PLIST_ERROR: "Property list error", MOBILESYNC_E_MUX_ERROR: "MUX error", + MOBILESYNC_E_SSL_ERROR: "SSL error", + MOBILESYNC_E_RECEIVE_TIMEOUT: "Receive timeout", MOBILESYNC_E_BAD_VERSION: "Bad version", MOBILESYNC_E_SYNC_REFUSED: "Sync refused", MOBILESYNC_E_CANCELLED: "Sync cancelled", @@ -73,8 +77,8 @@ cdef class MobileSyncClient(DeviceLinkService): __service_name__ = "com.apple.mobilesync" cdef mobilesync_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(mobilesync_client_new(device._c_dev, port, &(self._c_client))) + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(mobilesync_client_new(device._c_dev, descriptor._c_service_descriptor, &(self._c_client))) def __dealloc__(self): cdef mobilesync_error_t err @@ -88,6 +92,7 @@ cdef class MobileSyncClient(DeviceLinkService): mobilesync_sync_type_t sync_type uint64_t computer_data_class_version = 1 uint64_t device_data_class_version + char* error_description = NULL if device_anchor is None: anchors = mobilesync_anchors_new(NULL, host_anchor) @@ -95,8 +100,8 @@ cdef class MobileSyncClient(DeviceLinkService): anchors = mobilesync_anchors_new(device_anchor, host_anchor) try: - self.handle_error(mobilesync_start(self._c_client, data_class, anchors, computer_data_class_version, &sync_type, &device_data_class_version)) - return (sync_type, <bint>computer_data_class_version, <bint>device_data_class_version) + self.handle_error(mobilesync_start(self._c_client, data_class, anchors, computer_data_class_version, &sync_type, &device_data_class_version, &error_description)) + return (sync_type, <bint>computer_data_class_version, <bint>device_data_class_version, <bytes>error_description) except Exception, e: raise finally: diff --git a/cython/notification_proxy.pxi b/cython/notification_proxy.pxi index 07a72d9..261200e 100644 --- a/cython/notification_proxy.pxi +++ b/cython/notification_proxy.pxi @@ -9,7 +9,7 @@ cdef extern from "libimobiledevice/notification_proxy.h": NP_E_CONN_FAILED = -3 NP_E_UNKNOWN_ERROR = -256 ctypedef void (*np_notify_cb_t) (const_char_ptr notification, void *userdata) - np_error_t np_client_new(idevice_t device, uint16_t port, np_client_t *client) + np_error_t np_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, np_client_t *client) np_error_t np_client_free(np_client_t client) np_error_t np_post_notification(np_client_t client, char *notification) np_error_t np_observe_notification(np_client_t client, char *notification) @@ -70,7 +70,7 @@ NP_ITDBPREP_DID_END = C_NP_ITDBPREP_DID_END NP_LANGUAGE_CHANGED = C_NP_LANGUAGE_CHANGED NP_ADDRESS_BOOK_PREF_CHANGED = C_NP_ADDRESS_BOOK_PREF_CHANGED -cdef void np_notify_cb(const_char_ptr notification, void *py_callback): +cdef void np_notify_cb(const_char_ptr notification, void *py_callback) noexcept: (<object>py_callback)(notification) cdef class NotificationProxyError(BaseError): @@ -88,8 +88,8 @@ cdef class NotificationProxyClient(PropertyListService): __service_name__ = "com.apple.mobile.notification_proxy" cdef np_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(np_client_new(device._c_dev, port, &self._c_client)) + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(np_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) def __dealloc__(self): cdef np_error_t err diff --git a/cython/restore.pxi b/cython/restore.pxi new file mode 100644 index 0000000..9d03935 --- /dev/null +++ b/cython/restore.pxi @@ -0,0 +1,131 @@ +cdef extern from "libimobiledevice/restore.h": + cdef struct restored_client_private: + pass + ctypedef restored_client_private *restored_client_t + + ctypedef enum restored_error_t: + RESTORE_E_SUCCESS = 0 + RESTORE_E_INVALID_ARG = -1 + RESTORE_E_PLIST_ERROR = -2 + RESTORE_E_MUX_ERROR = -3 + RESTORE_E_NOT_ENOUGH_DATA = -4 + RESTORE_E_RECEIVE_TIMEOUT = -5 + RESTORE_E_UNKNOWN_ERROR = -256 + + restored_error_t restored_client_new(idevice_t device, restored_client_t *client, char *label) + restored_error_t restored_client_free(restored_client_t client) + + restored_error_t restored_query_type(restored_client_t client, char **tp, uint64_t *version) + restored_error_t restored_query_value(restored_client_t client, char *key, plist.plist_t *value) + restored_error_t restored_get_value(restored_client_t client, char *key, plist.plist_t *value) + restored_error_t restored_send(restored_client_t client, plist.plist_t plist) + restored_error_t restored_receive(restored_client_t client, plist.plist_t *plist) + restored_error_t restored_goodbye(restored_client_t client) + + restored_error_t restored_start_restore(restored_client_t client, plist.plist_t options, uint64_t version) + restored_error_t restored_reboot(restored_client_t client) + + void restored_client_set_label(restored_client_t client, char *label) + +cdef class RestoreError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + RESTORE_E_SUCCESS: "Success", + RESTORE_E_INVALID_ARG: "Invalid argument", + RESTORE_E_PLIST_ERROR: "Property list error", + RESTORE_E_MUX_ERROR: "MUX Error", + RESTORE_E_NOT_ENOUGH_DATA: "Not enough data", + RESTORE_E_RECEIVE_TIMEOUT: "Receive timeout", + RESTORE_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) + +cdef class RestoreClient(PropertyListService): + cdef restored_client_t _c_client + + def __cinit__(self, iDevice device not None, bytes label=b'', *args, **kwargs): + cdef: + restored_error_t err + char* c_label = NULL + if label: + c_label = label + err = restored_client_new(device._c_dev, &self._c_client, c_label) + self.handle_error(err) + + self.device = device + + def __dealloc__(self): + cdef restored_error_t err + if self._c_client is not NULL: + err = restored_client_free(self._c_client) + self.handle_error(err) + + cdef inline BaseError _error(self, int16_t ret): + return RestoreError(ret) + + cdef inline int16_t _send(self, plist.plist_t node): + return restored_send(self._c_client, node) + + cdef inline int16_t _receive(self, plist.plist_t* node): + return restored_receive(self._c_client, node) + + cpdef tuple query_type(self): + cdef: + restored_error_t err + char* c_type = NULL + uint64_t c_version = 0 + tuple result + err = restored_query_type(self._c_client, &c_type, &c_version) + try: + self.handle_error(err) + result = (c_type, c_version) + return result + except BaseError, e: + raise + finally: + if c_type != NULL: + free(c_type) + + cpdef plist.Node query_value(self, bytes key=None): + cdef: + restored_error_t err + plist.plist_t c_node = NULL + char* c_key = NULL + if key is not None: + c_key = key + err = restored_query_value(self._c_client, c_key, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef plist.Node get_value(self, bytes key=None): + cdef: + restored_error_t err + plist.plist_t c_node = NULL + char* c_key = NULL + if key is not None: + c_key = key + err = restored_get_value(self._c_client, c_key, &c_node) + try: + self.handle_error(err) + return plist.plist_t_to_node(c_node) + except BaseError, e: + if c_node != NULL: + plist.plist_free(c_node) + raise + + cpdef goodbye(self): + self.handle_error(restored_goodbye(self._c_client)) + + cpdef start_restore(self, plist.Node options, uint64_t version): + self.handle_error(restored_start_restore(self._c_client, options._c_node, version)) + + cpdef reboot(self): + self.handle_error(restored_reboot(self._c_client)) + + cpdef set_label(self, bytes label): + restored_client_set_label(self._c_client, label) diff --git a/cython/sbservices.pxi b/cython/sbservices.pxi index e826b2a..8ff2595 100644 --- a/cython/sbservices.pxi +++ b/cython/sbservices.pxi @@ -8,7 +8,7 @@ cdef extern from "libimobiledevice/sbservices.h": SBSERVICES_E_PLIST_ERROR = -2 SBSERVICES_E_CONN_FAILED = -3 SBSERVICES_E_UNKNOWN_ERROR = -256 - sbservices_error_t sbservices_client_new(idevice_t device, uint16_t port, sbservices_client_t *client) + sbservices_error_t sbservices_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, sbservices_client_t *client) sbservices_error_t sbservices_client_free(sbservices_client_t client) sbservices_error_t sbservices_get_icon_state(sbservices_client_t client, plist.plist_t *state, char *format_version) sbservices_error_t sbservices_set_icon_state(sbservices_client_t client, plist.plist_t newstate) @@ -28,9 +28,11 @@ cdef class SpringboardServicesError(BaseError): cdef class SpringboardServicesClient(PropertyListService): __service_name__ = "com.apple.springboardservices" cdef sbservices_client_t _c_client + cdef char* format_version - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(sbservices_client_new(device._c_dev, port, &self._c_client)) + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(sbservices_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) + self.format_version = "2" def __dealloc__(self): if self._c_client is not NULL: @@ -40,12 +42,18 @@ cdef class SpringboardServicesClient(PropertyListService): cdef inline BaseError _error(self, int16_t ret): return SpringboardServicesError(ret) + property format_version: + def __get__(self): + return <bytes>self.format_version + def __set__(self, char* newversion): + self.format_version = newversion + property icon_state: def __get__(self): cdef: plist.plist_t c_node = NULL sbservices_error_t err - err = sbservices_get_icon_state(self._c_client, &c_node, NULL) + err = sbservices_get_icon_state(self._c_client, &c_node, self.format_version) try: self.handle_error(err) diff --git a/cython/screenshotr.pxi b/cython/screenshotr.pxi index a53fab2..a1e82e2 100644 --- a/cython/screenshotr.pxi +++ b/cython/screenshotr.pxi @@ -8,10 +8,12 @@ cdef extern from "libimobiledevice/screenshotr.h": SCREENSHOTR_E_INVALID_ARG = -1 SCREENSHOTR_E_PLIST_ERROR = -2 SCREENSHOTR_E_MUX_ERROR = -3 - SCREENSHOTR_E_BAD_VERSION = -4 + SCREENSHOTR_E_SSL_ERROR = -4 + SCREENSHOTR_E_RECEIVE_TIMEOUT = 5 + SCREENSHOTR_E_BAD_VERSION = -6 SCREENSHOTR_E_UNKNOWN_ERROR = -256 - screenshotr_error_t screenshotr_client_new(idevice_t device, uint16_t port, screenshotr_client_t * client) + screenshotr_error_t screenshotr_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, screenshotr_client_t * client) screenshotr_error_t screenshotr_client_free(screenshotr_client_t client) screenshotr_error_t screenshotr_take_screenshot(screenshotr_client_t client, char **imgdata, uint64_t *imgsize) @@ -22,6 +24,8 @@ cdef class ScreenshotrError(BaseError): SCREENSHOTR_E_INVALID_ARG: "Invalid argument", SCREENSHOTR_E_PLIST_ERROR: "Property list error", SCREENSHOTR_E_MUX_ERROR: "MUX error", + SCREENSHOTR_E_SSL_ERROR: "SSL error", + SCREENSHOTR_E_RECEIVE_TIMEOUT: "Receive timeout", SCREENSHOTR_E_BAD_VERSION: "Bad version", SCREENSHOTR_E_UNKNOWN_ERROR: "Unknown error" } @@ -31,8 +35,8 @@ cdef class ScreenshotrClient(DeviceLinkService): __service_name__ = "com.apple.mobile.screenshotr" cdef screenshotr_client_t _c_client - def __cinit__(self, iDevice device not None, int port, *args, **kwargs): - self.handle_error(screenshotr_client_new(device._c_dev, port, &self._c_client)) + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(screenshotr_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) def __dealloc__(self): cdef screenshotr_error_t err diff --git a/cython/stdint.pxi b/cython/stdint.pxi deleted file mode 100644 index f9e5e95..0000000 --- a/cython/stdint.pxi +++ /dev/null @@ -1,18 +0,0 @@ -cdef extern from *: - ctypedef unsigned char uint8_t - ctypedef short int int16_t - ctypedef unsigned short int uint16_t - ctypedef unsigned int uint32_t - ctypedef int int32_t - ctypedef long int time_t -IF UNAME_MACHINE == 'x86_64': - ctypedef long int int64_t - ctypedef unsigned long int uint64_t -ELSE: - ctypedef long long int int64_t - ctypedef unsigned long long int uint64_t - -cdef extern from "time.h": - cdef struct timeval: - time_t tv_sec - time_t tv_usec diff --git a/cython/webinspector.pxi b/cython/webinspector.pxi new file mode 100644 index 0000000..f77547d --- /dev/null +++ b/cython/webinspector.pxi @@ -0,0 +1,60 @@ +cdef extern from "libimobiledevice/webinspector.h": + cdef struct webinspector_client_private: + pass + ctypedef webinspector_client_private *webinspector_client_t + + ctypedef enum webinspector_error_t: + WEBINSPECTOR_E_SUCCESS = 0 + WEBINSPECTOR_E_INVALID_ARG = -1 + WEBINSPECTOR_E_PLIST_ERROR = -2 + WEBINSPECTOR_E_MUX_ERROR = -3 + WEBINSPECTOR_E_SSL_ERROR = -4 + WEBINSPECTOR_E_RECEIVE_TIMEOUT = -5, + WEBINSPECTOR_E_NOT_ENOUGH_DATA = -6, + WEBINSPECTOR_E_UNKNOWN_ERROR = -256 + + webinspector_error_t webinspector_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, webinspector_client_t * client) + webinspector_error_t webinspector_client_free(webinspector_client_t client) + + webinspector_error_t webinspector_send(webinspector_client_t client, plist.plist_t plist) + webinspector_error_t webinspector_receive(webinspector_client_t client, plist.plist_t * plist) + webinspector_error_t webinspector_receive_with_timeout(webinspector_client_t client, plist.plist_t * plist, uint32_t timeout_ms) + +cdef class WebinspectorError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + WEBINSPECTOR_E_SUCCESS: "Success", + WEBINSPECTOR_E_INVALID_ARG: "Invalid argument", + WEBINSPECTOR_E_PLIST_ERROR: "Property list error", + WEBINSPECTOR_E_MUX_ERROR: "MUX error", + WEBINSPECTOR_E_SSL_ERROR: "SSL Error", + WEBINSPECTOR_E_NOT_ENOUGH_DATA: 'Not enough data', + WEBINSPECTOR_E_RECEIVE_TIMEOUT: 'Connection timeout', + WEBINSPECTOR_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) + +cdef class WebinspectorClient(PropertyListService): + __service_name__ = "com.apple.webinspector" + cdef webinspector_client_t _c_client + + def __cinit__(self, iDevice device not None, LockdownServiceDescriptor descriptor, *args, **kwargs): + self.handle_error(webinspector_client_new(device._c_dev, descriptor._c_service_descriptor, &self._c_client)) + + def __dealloc__(self): + cdef webinspector_error_t err + if self._c_client is not NULL: + err = webinspector_client_free(self._c_client) + self.handle_error(err) + + cdef inline int16_t _send(self, plist.plist_t node): + return webinspector_send(self._c_client, node) + + cdef inline int16_t _receive(self, plist.plist_t* node): + return webinspector_receive(self._c_client, node) + + cdef inline int16_t _receive_with_timeout(self, plist.plist_t* node, int timeout_ms): + return webinspector_receive_with_timeout(self._c_client, node, timeout_ms) + + cdef inline BaseError _error(self, int16_t ret): + return WebinspectorError(ret) |
