diff --git a/StikJIT.xcodeproj/project.pbxproj b/StikJIT.xcodeproj/project.pbxproj index 779688d..23480b9 100644 --- a/StikJIT.xcodeproj/project.pbxproj +++ b/StikJIT.xcodeproj/project.pbxproj @@ -442,6 +442,10 @@ IPHONEOS_DEPLOYMENT_TARGET = 18.2; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/StikJIT/idevice", + ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; @@ -484,6 +488,10 @@ IPHONEOS_DEPLOYMENT_TARGET = 18.2; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/StikJIT/idevice", + ); MACOSX_DEPLOYMENT_TARGET = 15.1; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.stik.StikJIT; diff --git a/StikJIT/Extensions & Stuff/DebugViewModel.swift b/StikJIT/Extensions & Stuff/DebugViewModel.swift index b5def74..f278a20 100644 --- a/StikJIT/Extensions & Stuff/DebugViewModel.swift +++ b/StikJIT/Extensions & Stuff/DebugViewModel.swift @@ -5,40 +5,3 @@ // Created by Stephen on 3/27/25. // -import SwiftUI -import em_proxy - -// Debug View Model that calls the Swift bindings on startup. -class DebugViewModel: ObservableObject { - @Published var status: String = "Initializing..." - @Published var logs: [String] = [] - - init() { - startProxy() - } - - func startProxy() { - let port = 62078 - let bindAddr = "127.0.0.1:\(port)" - - DispatchQueue.global(qos: .background).async { - DispatchQueue.main.async { - self.status = "Starting em_proxy..." - self.logs.append("Starting em_proxy on port \(port)...") - } - - // Call the Swift binding that wraps the heartbeat functionality. - let result = start_emotional_damage(bindAddr) - - DispatchQueue.main.async { - if result == 0 { - self.status = "em_proxy started successfully on port \(port)" - self.logs.append("em_proxy started successfully on port \(port).") - } else { - self.status = "Failed to start em_proxy" - self.logs.append("Failed to start em_proxy.") - } - } - } - } -} diff --git a/StikJIT/StikJIT-Bridging-Header.h b/StikJIT/StikJIT-Bridging-Header.h index e11d920..6c6230f 100644 --- a/StikJIT/StikJIT-Bridging-Header.h +++ b/StikJIT/StikJIT-Bridging-Header.h @@ -1,3 +1,6 @@ // // Use this file to import your target's public headers that you would like to expose to Swift. // + +#include "idevice.h" +#include "heartbeat.h" diff --git a/StikJIT/StikJITApp.swift b/StikJIT/StikJITApp.swift index f29ae93..ac8f15b 100644 --- a/StikJIT/StikJITApp.swift +++ b/StikJIT/StikJITApp.swift @@ -6,12 +6,41 @@ // import SwiftUI +import em_proxy @main -struct StikJITApp: App { +struct HeartbeatApp: App { var body: some Scene { WindowGroup { - MainTabView() + HomeView() + .onAppear { + startProxy() + startHeartbeatInBackground() + } + } + } + + func startHeartbeatInBackground() { + DispatchQueue.global(qos: .background).async { + startHeartbeat() + } + } + func startProxy() { + let port = 51820 + let bindAddr = "127.0.0.1:\(port)" + + DispatchQueue.global(qos: .background).async { + let result = start_emotional_damage(bindAddr) + + DispatchQueue.main.async { + if result == 0 { + print("DEBUG: em_proxy started successfully on port \(port)") + print("DEBUG: em_proxy started successfully on port \(port).") + } else { + print("DEBUG: Failed to start em_proxy") + print("DEBUG: Failed to start em_proxy.") + } + } } } } diff --git a/StikJIT/Views/DebugView.swift b/StikJIT/Views/DebugView.swift index 918f571..53497a6 100644 --- a/StikJIT/Views/DebugView.swift +++ b/StikJIT/Views/DebugView.swift @@ -7,70 +7,26 @@ import SwiftUI -// Debug View displaying status and logs. struct DebugView: View { - @StateObject private var viewModel = DebugViewModel() - var body: some View { - VStack(spacing: 15) { - Text("StikJIT Debug Panel") - .font(.title) + VStack { + Spacer() + Text("Welcome to StikJIT") + .font(.largeTitle) .bold() - .foregroundColor(.primary) - .padding(.top) - - HStack { - Circle() - .fill(viewModel.status.contains("successfully") ? Color.green : viewModel.status.contains("Failed") ? Color.red : Color.yellow) - .frame(width: 14, height: 14) - - Text(viewModel.status) - .font(.headline) - .foregroundColor(.primary) - } - .padding(.bottom, 5) - - Divider() - .background(Color.secondary.opacity(0.3)) - - ScrollView { - VStack(alignment: .leading, spacing: 5) { - ForEach(viewModel.logs, id: \.self) { log in - Text(log) - .font(.system(.body, design: .monospaced)) - .foregroundColor(.secondary) - .padding(.horizontal) - } - } - .frame(maxWidth: .infinity, alignment: .leading) - } - .frame(maxHeight: 300) - .background(RoundedRectangle(cornerRadius: 10).fill(Color(.systemGray6).opacity(0.5))) - .padding() - - Button(action: { - viewModel.startProxy() - }) { - Label("Restart Proxy", systemImage: "arrow.clockwise") - .font(.headline) - .foregroundColor(.white) - .padding() - .frame(maxWidth: .infinity) - .background(Color.blue) - .cornerRadius(10) - } - .buttonStyle(PlainButtonStyle()) - .padding(.horizontal) + .padding() + Text("Use the Debug tab to monitor the logs.") + .font(.body) + .foregroundColor(.secondary) + .padding() Spacer() } - .padding() - .frame(width: 420, height: 500) - .background( - FancyBlurView() - .cornerRadius(15) - .shadow(radius: 10) - ) - .padding() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color(.systemBackground)) } } + +#Preview { + DebugView() +} diff --git a/StikJIT/idevice/heartbeat.c b/StikJIT/idevice/heartbeat.c new file mode 100644 index 0000000..d79bb91 --- /dev/null +++ b/StikJIT/idevice/heartbeat.c @@ -0,0 +1,99 @@ +// Jackson Coxson +// heartbeat.c + +#include "idevice.h" +#include +#include +#include +#include +#include +#include +#include + +void startHeartbeat() { + printf("DEBUG: Initializing logger...\n"); + idevice_init_logger(Debug, Disabled, NULL); + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(LOCKDOWN_PORT); + if (inet_pton(AF_INET, "10.7.0.2", &addr.sin_addr) <= 0) { + fprintf(stderr, "DEBUG: Error converting IP address.\n"); + return; + } + printf("DEBUG: Socket address created for IP 10.7.0.2 on port %d.\n", LOCKDOWN_PORT); + + printf("DEBUG: Searching the app bundle for pairing_file.plist...\n"); + CFURLRef pairingFileURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), + CFSTR("pairing_file"), + CFSTR("plist"), + NULL); + if (pairingFileURL == NULL) { + fprintf(stderr, "DEBUG: Pairing file not found in the app bundle.\n"); + return; + } + + char pairingFilePath[PATH_MAX]; + if (!CFURLGetFileSystemRepresentation(pairingFileURL, TRUE, (UInt8 *)pairingFilePath, PATH_MAX)) { + fprintf(stderr, "DEBUG: Error converting pairing file URL to file system representation.\n"); + CFRelease(pairingFileURL); + return; + } + CFRelease(pairingFileURL); + printf("DEBUG: Pairing file found at path: %s\n", pairingFilePath); + + printf("DEBUG: Reading pairing file...\n"); + IdevicePairingFile *pairing_file = NULL; + IdeviceErrorCode err = idevice_pairing_file_read(pairingFilePath, &pairing_file); + if (err != IdeviceSuccess) { + fprintf(stderr, "DEBUG: Failed to read pairing file: %d\n", err); + return; + } + printf("DEBUG: Pairing file read successfully.\n"); + + printf("DEBUG: Creating TCP provider...\n"); + TcpProviderHandle *provider = NULL; + err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, + "ExampleProvider", &provider); + if (err != IdeviceSuccess) { + fprintf(stderr, "DEBUG: Failed to create TCP provider: %d\n", err); + idevice_pairing_file_free(pairing_file); + return; + } + printf("DEBUG: TCP provider created successfully.\n"); + + printf("DEBUG: Connecting to installation proxy...\n"); + HeartbeatClientHandle *client = NULL; + err = heartbeat_connect_tcp(provider, &client); + if (err != IdeviceSuccess) { + fprintf(stderr, "DEBUG: Failed to connect to installation proxy: %d\n", err); + tcp_provider_free(provider); + return; + } + tcp_provider_free(provider); + printf("DEBUG: Connected to installation proxy successfully.\n"); + + u_int64_t current_interval = 15; + while (1) { + u_int64_t new_interval = 0; + printf("DEBUG: Sending heartbeat with current interval: %llu seconds...\n", current_interval); + err = heartbeat_get_marco(client, current_interval, &new_interval); + if (err != IdeviceSuccess) { + fprintf(stderr, "DEBUG: Failed to get marco: %d\n", err); + heartbeat_client_free(client); + return; + } + printf("DEBUG: Received new interval: %llu seconds.\n", new_interval); + current_interval = new_interval + 5; + + printf("DEBUG: Sending polo reply...\n"); + err = heartbeat_send_polo(client); + if (err != IdeviceSuccess) { + fprintf(stderr, "DEBUG: Failed to send polo: %d\n", err); + heartbeat_client_free(client); + return; + } + printf("DEBUG: Polo reply sent successfully.\n"); + } +} diff --git a/StikJIT/idevice/heartbeat.h b/StikJIT/idevice/heartbeat.h new file mode 100644 index 0000000..7818859 --- /dev/null +++ b/StikJIT/idevice/heartbeat.h @@ -0,0 +1,14 @@ +// +// heartbeat.h +// StikJIT +// +// Created by Stephen on 3/27/25. +// + +// heartbeat.h +#ifndef HEARTBEAT_H +#define HEARTBEAT_H + +void startHeartbeat(); + +#endif /* HEARTBEAT_H */ diff --git a/StikJIT/idevice/idevice.h b/StikJIT/idevice/idevice.h new file mode 100644 index 0000000..855dde8 --- /dev/null +++ b/StikJIT/idevice/idevice.h @@ -0,0 +1,1631 @@ +// Jackson Coxson +// Bindings to idevice - https://github.com/jkcoxson/idevice + +#include +#include +#include +#include +#include +#include "plist.h" + +#define LOCKDOWN_PORT 62078 + +typedef enum IdeviceErrorCode { + IdeviceSuccess = 0, + Socket = -1, + Ssl = -2, + SslSetup = -3, + Plist = -4, + Utf8 = -5, + UnexpectedResponse = -6, + GetProhibited = -7, + SessionInactive = -8, + InvalidHostID = -9, + NoEstablishedConnection = -10, + HeartbeatSleepyTime = -11, + HeartbeatTimeout = -12, + NotFound = -13, + CdtunnelPacketTooShort = -14, + CdtunnelPacketInvalidMagic = -15, + PacketSizeMismatch = -16, + Json = -17, + DeviceNotFound = -18, + DeviceLocked = -19, + UsbConnectionRefused = -20, + UsbBadCommand = -21, + UsbBadDevice = -22, + UsbBadVersion = -23, + BadBuildManifest = -24, + ImageNotMounted = -25, + Reqwest = -26, + InternalError = -27, + Xpc = -28, + NsKeyedArchiveError = -29, + UnknownAuxValueType = -30, + UnknownChannel = -31, + AddrParseError = -32, + DisableMemoryLimitFailed = -33, + NotEnoughBytes = -34, + Utf8Error = -35, + InvalidArgument = -36, + UnknownErrorType = -37, + AdapterIOFailed = -996, + ServiceNotFound = -997, + BufferTooSmall = -998, + InvalidString = -999, + InvalidArg = -1000, +} IdeviceErrorCode; + +typedef enum IdeviceLogLevel { + Disabled = 0, + ErrorLevel = 1, + Warn = 2, + Info = 3, + Debug = 4, + Trace = 5, +} IdeviceLogLevel; + +typedef enum IdeviceLoggerError { + Success = 0, + FileError = -1, + AlreadyInitialized = -2, + InvalidPathString = -3, +} IdeviceLoggerError; + +typedef struct AdapterHandle AdapterHandle; + +typedef struct CoreDeviceProxyHandle CoreDeviceProxyHandle; + +/** + * Opaque handle to a DebugProxyClient + */ +typedef struct DebugProxyAdapterHandle DebugProxyAdapterHandle; + +typedef struct HeartbeatClientHandle HeartbeatClientHandle; + +/** + * Opaque C-compatible handle to an Idevice connection + */ +typedef struct IdeviceHandle IdeviceHandle; + +/** + * Opaque C-compatible handle to a PairingFile + */ +typedef struct IdevicePairingFile IdevicePairingFile; + +typedef struct IdeviceSocketHandle IdeviceSocketHandle; + +typedef struct ImageMounterHandle ImageMounterHandle; + +typedef struct InstallationProxyClientHandle InstallationProxyClientHandle; + +/** + * Opaque handle to a ProcessControlClient + */ +typedef struct ProcessControlAdapterHandle ProcessControlAdapterHandle; + +/** + * Opaque handle to a RemoteServerClient + */ +typedef struct RemoteServerAdapterHandle RemoteServerAdapterHandle; + +typedef struct TcpProviderHandle TcpProviderHandle; + +typedef struct UsbmuxdAddrHandle UsbmuxdAddrHandle; + +typedef struct UsbmuxdConnectionHandle UsbmuxdConnectionHandle; + +typedef struct UsbmuxdProviderHandle UsbmuxdProviderHandle; + +/** + * Opaque handle to an XPCDevice + */ +typedef struct XPCDeviceAdapterHandle XPCDeviceAdapterHandle; + +typedef struct sockaddr sockaddr; + +/** + * Represents a debugserver command + */ +typedef struct DebugserverCommandHandle { + char *name; + char **argv; + uintptr_t argv_count; +} DebugserverCommandHandle; + +/** + * Opaque handle to an XPCService + */ +typedef struct XPCServiceHandle { + char *entitlement; + uint16_t port; + bool uses_remote_xpc; + char **features; + uintptr_t features_count; + int64_t service_version; +} XPCServiceHandle; + +/** + * Creates a new Idevice connection + * + * # Arguments + * * [`socket`] - Socket for communication with the device + * * [`label`] - Label for the connection + * * [`idevice`] - On success, will be set to point to a newly allocated Idevice handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `label` must be a valid null-terminated C string + * `idevice` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_new(struct IdeviceSocketHandle *socket, + const char *label, + struct IdeviceHandle **idevice); + +/** + * Creates a new Idevice connection + * + * # Arguments + * * [`addr`] - The socket address to connect to + * * [`addr_len`] - Length of the socket + * * [`label`] - Label for the connection + * * [`idevice`] - On success, will be set to point to a newly allocated Idevice handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `addr` must be a valid sockaddr + * `label` must be a valid null-terminated C string + * `idevice` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_new_tcp_socket(const struct sockaddr *addr, + socklen_t addr_len, + const char *label, + struct IdeviceHandle **idevice); + +/** + * Gets the device type + * + * # Arguments + * * [`idevice`] - The Idevice handle + * * [`device_type`] - On success, will be set to point to a newly allocated string containing the device type + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `idevice` must be a valid, non-null pointer to an Idevice handle + * `device_type` must be a valid, non-null pointer to a location where the string pointer will be stored + */ +enum IdeviceErrorCode idevice_get_type(struct IdeviceHandle *idevice, + char **device_type); + +/** + * Performs RSD checkin + * + * # Arguments + * * [`idevice`] - The Idevice handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `idevice` must be a valid, non-null pointer to an Idevice handle + */ +enum IdeviceErrorCode idevice_rsd_checkin(struct IdeviceHandle *idevice); + +/** + * Starts a TLS session + * + * # Arguments + * * [`idevice`] - The Idevice handle + * * [`pairing_file`] - The pairing file to use for TLS + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `idevice` must be a valid, non-null pointer to an Idevice handle + * `pairing_file` must be a valid, non-null pointer to a pairing file handle + */ +enum IdeviceErrorCode idevice_start_session(struct IdeviceHandle *idevice, + const struct IdevicePairingFile *pairing_file); + +/** + * Frees an Idevice handle + * + * # Arguments + * * [`idevice`] - The Idevice handle to free + * + * # Safety + * `idevice` must be a valid pointer to an Idevice handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void idevice_free(struct IdeviceHandle *idevice); + +/** + * Frees a string allocated by this library + * + * # Arguments + * * [`string`] - The string to free + * + * # Safety + * `string` must be a valid pointer to a string that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void idevice_string_free(char *string); + +/** + * Connects the adapter to a specific port + * + * # Arguments + * * [`handle`] - The adapter handle + * * [`port`] - The port to connect to + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + */ +enum IdeviceErrorCode adapter_connect(struct AdapterHandle *handle, uint16_t port); + +/** + * Enables PCAP logging for the adapter + * + * # Arguments + * * [`handle`] - The adapter handle + * * [`path`] - The path to save the PCAP file (null-terminated string) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `path` must be a valid null-terminated string + */ +enum IdeviceErrorCode adapter_pcap(struct AdapterHandle *handle, const char *path); + +/** + * Closes the adapter connection + * + * # Arguments + * * [`handle`] - The adapter handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + */ +enum IdeviceErrorCode adapter_close(struct AdapterHandle *handle); + +/** + * Sends data through the adapter + * + * # Arguments + * * [`handle`] - The adapter handle + * * [`data`] - The data to send + * * [`length`] - The length of the data + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `data` must be a valid pointer to at least `length` bytes + */ +enum IdeviceErrorCode adapter_send(struct AdapterHandle *handle, + const uint8_t *data, + uintptr_t length); + +/** + * Receives data from the adapter + * + * # Arguments + * * [`handle`] - The adapter handle + * * [`data`] - Pointer to a buffer where the received data will be stored + * * [`length`] - Pointer to store the actual length of received data + * * [`max_length`] - Maximum number of bytes that can be stored in `data` + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `data` must be a valid pointer to at least `max_length` bytes + * `length` must be a valid pointer to a usize + */ +enum IdeviceErrorCode adapter_recv(struct AdapterHandle *handle, + uint8_t *data, + uintptr_t *length, + uintptr_t max_length); + +/** + * Automatically creates and connects to Core Device Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - A TcpProvider + * * [`client`] - On success, will be set to point to a newly allocated CoreDeviceProxy handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode core_device_proxy_connect_tcp(struct TcpProviderHandle *provider, + struct CoreDeviceProxyHandle **client); + +/** + * Automatically creates and connects to Core Device Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - A UsbmuxdProvider + * * [`client`] - On success, will be set to point to a newly allocated CoreDeviceProxy handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode core_device_proxy_connect_usbmuxd(struct UsbmuxdProviderHandle *provider, + struct CoreDeviceProxyHandle **client); + +/** + * Automatically creates and connects to Core Device Proxy, returning a client handle + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated CoreDeviceProxy handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode core_device_proxy_new(struct IdeviceHandle *socket, + struct CoreDeviceProxyHandle **client); + +/** + * Sends data through the CoreDeviceProxy tunnel + * + * # Arguments + * * [`handle`] - The CoreDeviceProxy handle + * * [`data`] - The data to send + * * [`length`] - The length of the data + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `data` must be a valid pointer to at least `length` bytes + */ +enum IdeviceErrorCode core_device_proxy_send(struct CoreDeviceProxyHandle *handle, + const uint8_t *data, + uintptr_t length); + +/** + * Receives data from the CoreDeviceProxy tunnel + * + * # Arguments + * * [`handle`] - The CoreDeviceProxy handle + * * [`data`] - Pointer to a buffer where the received data will be stored + * * [`length`] - Pointer to store the actual length of received data + * * [`max_length`] - Maximum number of bytes that can be stored in `data` + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `data` must be a valid pointer to at least `max_length` bytes + * `length` must be a valid pointer to a usize + */ +enum IdeviceErrorCode core_device_proxy_recv(struct CoreDeviceProxyHandle *handle, + uint8_t *data, + uintptr_t *length, + uintptr_t max_length); + +/** + * Gets the client parameters from the handshake + * + * # Arguments + * * [`handle`] - The CoreDeviceProxy handle + * * [`mtu`] - Pointer to store the MTU value + * * [`address`] - Pointer to store the IP address string (must be at least 16 bytes) + * * [`netmask`] - Pointer to store the netmask string (must be at least 16 bytes) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `mtu` must be a valid pointer to a u16 + * `address` and `netmask` must be valid pointers to buffers of at least 16 bytes + */ +enum IdeviceErrorCode core_device_proxy_get_client_parameters(struct CoreDeviceProxyHandle *handle, + uint16_t *mtu, + char **address, + char **netmask); + +/** + * Gets the server address from the handshake + * + * # Arguments + * * [`handle`] - The CoreDeviceProxy handle + * * [`address`] - Pointer to store the server address string (must be at least 16 bytes) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `address` must be a valid pointer to a buffer of at least 16 bytes + */ +enum IdeviceErrorCode core_device_proxy_get_server_address(struct CoreDeviceProxyHandle *handle, + char **address); + +/** + * Gets the server RSD port from the handshake + * + * # Arguments + * * [`handle`] - The CoreDeviceProxy handle + * * [`port`] - Pointer to store the port number + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `port` must be a valid pointer to a u16 + */ +enum IdeviceErrorCode core_device_proxy_get_server_rsd_port(struct CoreDeviceProxyHandle *handle, + uint16_t *port); + +/** + * Creates a software TCP tunnel adapter + * + * # Arguments + * * [`handle`] - The CoreDeviceProxy handle + * * [`adapter`] - Pointer to store the newly created adapter handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library, and never used again + * `adapter` must be a valid pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode core_device_proxy_create_tcp_adapter(struct CoreDeviceProxyHandle *handle, + struct AdapterHandle **adapter); + +/** + * Frees a handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void core_device_proxy_free(struct CoreDeviceProxyHandle *handle); + +/** + * Frees a handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void adapter_free(struct AdapterHandle *handle); + +/** + * Creates a new DebugserverCommand + * + * # Safety + * Caller must free with debugserver_command_free + */ +struct DebugserverCommandHandle *debugserver_command_new(const char *name, + const char *const *argv, + uintptr_t argv_count); + +/** + * Frees a DebugserverCommand + * + * # Safety + * `command` must be a valid pointer or NULL + */ +void debugserver_command_free(struct DebugserverCommandHandle *command); + +/** + * Creates a new DebugProxyClient + * + * # Arguments + * * [`socket`] - The socket to use for communication + * * [`handle`] - Pointer to store the newly created DebugProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library + * `handle` must be a valid pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode debug_proxy_adapter_new(struct AdapterHandle *socket, + struct DebugProxyAdapterHandle **handle); + +/** + * Frees a DebugProxyClient handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL + */ +void debug_proxy_free(struct DebugProxyAdapterHandle *handle); + +/** + * Sends a command to the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * * [`command`] - The command to send + * * [`response`] - Pointer to store the response (caller must free) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` and `command` must be valid pointers + * `response` must be a valid pointer to a location where the string will be stored + */ +enum IdeviceErrorCode debug_proxy_send_command(struct DebugProxyAdapterHandle *handle, + struct DebugserverCommandHandle *command, + char **response); + +/** + * Reads a response from the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * * [`response`] - Pointer to store the response (caller must free) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer + * `response` must be a valid pointer to a location where the string will be stored + */ +enum IdeviceErrorCode debug_proxy_read_response(struct DebugProxyAdapterHandle *handle, + char **response); + +/** + * Sends raw data to the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * * [`data`] - The data to send + * * [`len`] - Length of the data + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer + * `data` must be a valid pointer to `len` bytes + */ +enum IdeviceErrorCode debug_proxy_send_raw(struct DebugProxyAdapterHandle *handle, + const uint8_t *data, + uintptr_t len); + +/** + * Reads data from the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * * [`len`] - Maximum number of bytes to read + * * [`response`] - Pointer to store the response (caller must free) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer + * `response` must be a valid pointer to a location where the string will be stored + */ +enum IdeviceErrorCode debug_proxy_read(struct DebugProxyAdapterHandle *handle, + uintptr_t len, + char **response); + +/** + * Sets the argv for the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * * [`argv`] - NULL-terminated array of arguments + * * [`argv_count`] - Number of arguments + * * [`response`] - Pointer to store the response (caller must free) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer + * `argv` must be a valid pointer to `argv_count` C strings or NULL + * `response` must be a valid pointer to a location where the string will be stored + */ +enum IdeviceErrorCode debug_proxy_set_argv(struct DebugProxyAdapterHandle *handle, + const char *const *argv, + uintptr_t argv_count, + char **response); + +/** + * Sends an ACK to the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer + */ +enum IdeviceErrorCode debug_proxy_send_ack(struct DebugProxyAdapterHandle *handle); + +/** + * Sends a NACK to the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer + */ +enum IdeviceErrorCode debug_proxy_send_nack(struct DebugProxyAdapterHandle *handle); + +/** + * Sets the ACK mode for the debug proxy + * + * # Arguments + * * [`handle`] - The DebugProxyClient handle + * * [`enabled`] - Whether ACK mode should be enabled + * + * # Safety + * `handle` must be a valid pointer + */ +void debug_proxy_set_ack_mode(struct DebugProxyAdapterHandle *handle, int enabled); + +/** + * Returns the underlying socket from a DebugProxyClient + * + * # Arguments + * * [`handle`] - The handle to get the socket from + * * [`adapter`] - The newly allocated ConnectionHandle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL, and never used again + */ +enum IdeviceErrorCode debug_proxy_adapter_into_inner(struct DebugProxyAdapterHandle *handle, + struct AdapterHandle **adapter); + +/** + * Automatically creates and connects to Installation Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - A TcpProvider + * * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode heartbeat_connect_tcp(struct TcpProviderHandle *provider, + struct HeartbeatClientHandle **client); + +/** + * Automatically creates and connects to Installation Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - A UsbmuxdProvider + * * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode heartbeat_connect_usbmuxd(struct UsbmuxdProviderHandle *provider, + struct HeartbeatClientHandle **client); + +/** + * Automatically creates and connects to Installation Proxy, returning a client handle + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode heartbeat_new(struct IdeviceHandle *socket, + struct HeartbeatClientHandle **client); + +/** + * Sends a polo to the device + * + * # Arguments + * * `client` - A valid HeartbeatClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +enum IdeviceErrorCode heartbeat_send_polo(struct HeartbeatClientHandle *client); + +/** + * Sends a polo to the device + * + * # Arguments + * * `client` - A valid HeartbeatClient handle + * * `interval` - The time to wait for a marco + * * `new_interval` - A pointer to set the requested marco + * + * # Returns + * An error code indicating success or failure. + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +enum IdeviceErrorCode heartbeat_get_marco(struct HeartbeatClientHandle *client, + uint64_t interval, + uint64_t *new_interval); + +/** + * Frees a handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void heartbeat_client_free(struct HeartbeatClientHandle *handle); + +/** + * Automatically creates and connects to Installation Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - A TcpProvider + * * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode installation_proxy_connect_tcp(struct TcpProviderHandle *provider, + struct InstallationProxyClientHandle **client); + +/** + * Automatically creates and connects to Installation Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - A UsbmuxdProvider + * * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode installation_proxy_connect_usbmuxd(struct UsbmuxdProviderHandle *provider, + struct InstallationProxyClientHandle **client); + +/** + * Automatically creates and connects to Installation Proxy, returning a client handle + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode installation_proxy_new(struct IdeviceHandle *socket, + struct InstallationProxyClientHandle **client); + +/** + * Gets installed apps on the device + * + * # Arguments + * * `client` - A valid InstallationProxyClient handle + * * `application_type` - The application type to filter by (optional, NULL for "Any") + * * `bundle_identifiers` - The identifiers to filter by (optional, NULL for all apps) + * * `out_result` - On success, will be set to point to a newly allocated array of PlistRef + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `out_result` must be a valid, non-null pointer to a location where the result will be stored + */ +enum IdeviceErrorCode installation_proxy_get_apps(struct InstallationProxyClientHandle *client, + const char *application_type, + const char *const *bundle_identifiers, + size_t bundle_identifiers_len, + void **out_result, + size_t *out_result_len); + +/** + * Frees a handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void installation_proxy_client_free(struct InstallationProxyClientHandle *handle); + +/** + * Initializes the logger + * + * # Arguments + * * [`console_level`] - The level to log to the file + * * [`file_level`] - The level to log to the file + * * [`file_path`] - If not null, the file to write logs to + * + * ## Log Level + * 0. Disabled + * 1. Error + * 2. Warn + * 3. Info + * 4. Debug + * 5. Trace + * + * # Returns + * 0 for success, -1 if the file couldn't be created, -2 if a logger has been initialized, -3 for invalid path string + * + * # Safety + * Pass a valid CString for file_path. Pass valid log levels according to the enum + */ +enum IdeviceLoggerError idevice_init_logger(enum IdeviceLogLevel console_level, + enum IdeviceLogLevel file_level, + char *file_path); + +/** + * Connects to the Image Mounter service using a TCP provider + * + * # Arguments + * * [`provider`] - A TcpProvider + * * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode image_mounter_connect_tcp(struct TcpProviderHandle *provider, + struct ImageMounterHandle **client); + +/** + * Connects to the Image Mounter service using a Usbmuxd provider + * + * # Arguments + * * [`provider`] - A UsbmuxdProvider + * * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode image_mounter_connect_usbmuxd(struct UsbmuxdProviderHandle *provider, + struct ImageMounterHandle **client); + +/** + * Creates a new ImageMounter client from an existing Idevice connection + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode image_mounter_new(struct IdeviceHandle *socket, + struct ImageMounterHandle **client); + +/** + * Frees an ImageMounter handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void image_mounter_free(struct ImageMounterHandle *handle); + +/** + * Gets a list of mounted devices + * + * # Arguments + * * [`client`] - A valid ImageMounter handle + * * [`devices`] - Will be set to point to a slice of device plists on success + * * [`devices_len`] - Will be set to the number of devices copied + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `devices` must be a valid, non-null pointer to a location where the plist will be stored + */ +enum IdeviceErrorCode image_mounter_copy_devices(struct ImageMounterHandle *client, + void **devices, + size_t *devices_len); + +/** + * Looks up an image and returns its signature + * + * # Arguments + * * [`client`] - A valid ImageMounter handle + * * [`image_type`] - The type of image to look up + * * [`signature`] - Will be set to point to the signature data on success + * * [`signature_len`] - Will be set to the length of the signature data + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `image_type` must be a valid null-terminated C string + * `signature` and `signature_len` must be valid pointers + */ +enum IdeviceErrorCode image_mounter_lookup_image(struct ImageMounterHandle *client, + const char *image_type, + uint8_t **signature, + size_t *signature_len); + +/** + * Uploads an image to the device + * + * # Arguments + * * [`client`] - A valid ImageMounter handle + * * [`image_type`] - The type of image being uploaded + * * [`image`] - Pointer to the image data + * * [`image_len`] - Length of the image data + * * [`signature`] - Pointer to the signature data + * * [`signature_len`] - Length of the signature data + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * All pointers must be valid and non-null + * `image_type` must be a valid null-terminated C string + */ +enum IdeviceErrorCode image_mounter_upload_image(struct ImageMounterHandle *client, + const char *image_type, + const uint8_t *image, + size_t image_len, + const uint8_t *signature, + size_t signature_len); + +/** + * Mounts an image on the device + * + * # Arguments + * * [`client`] - A valid ImageMounter handle + * * [`image_type`] - The type of image being mounted + * * [`signature`] - Pointer to the signature data + * * [`signature_len`] - Length of the signature data + * * [`trust_cache`] - Pointer to trust cache data (optional) + * * [`trust_cache_len`] - Length of trust cache data (0 if none) + * * [`info_plist`] - Pointer to info plist (optional) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * All pointers must be valid (except optional ones which can be null) + * `image_type` must be a valid null-terminated C string + */ +enum IdeviceErrorCode image_mounter_mount_image(struct ImageMounterHandle *client, + const char *image_type, + const uint8_t *signature, + size_t signature_len, + const uint8_t *trust_cache, + size_t trust_cache_len, + const void *info_plist); + +/** + * Unmounts an image from the device + * + * # Arguments + * * [`client`] - A valid ImageMounter handle + * * [`mount_path`] - The path where the image is mounted + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `mount_path` must be a valid null-terminated C string + */ +enum IdeviceErrorCode image_mounter_unmount_image(struct ImageMounterHandle *client, + const char *mount_path); + +/** + * Queries the developer mode status + * + * # Arguments + * * [`client`] - A valid ImageMounter handle + * * [`status`] - Will be set to the developer mode status (1 = enabled, 0 = disabled) + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `status` must be a valid pointer + */ +enum IdeviceErrorCode image_mounter_query_developer_mode_status(struct ImageMounterHandle *client, + int *status); + +/** + * Mounts a developer image + * + * # Arguments + * * [`client`] - A valid ImageMounter handle + * * [`image`] - Pointer to the image data + * * [`image_len`] - Length of the image data + * * [`signature`] - Pointer to the signature data + * * [`signature_len`] - Length of the signature data + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * All pointers must be valid and non-null + */ +enum IdeviceErrorCode image_mounter_mount_developer(struct ImageMounterHandle *client, + const uint8_t *image, + size_t image_len, + const uint8_t *signature, + size_t signature_len); + +/** + * Reads a pairing file from the specified path + * + * # Arguments + * * [`path`] - Path to the pairing file + * * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `path` must be a valid null-terminated C string + * `pairing_file` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_pairing_file_read(const char *path, + struct IdevicePairingFile **pairing_file); + +/** + * Parses a pairing file from a byte buffer + * + * # Arguments + * * [`data`] - Pointer to the buffer containing pairing file data + * * [`size`] - Size of the buffer in bytes + * * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `data` must be a valid pointer to a buffer of at least `size` bytes + * `pairing_file` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_pairing_file_from_bytes(const uint8_t *data, + uintptr_t size, + struct IdevicePairingFile **pairing_file); + +/** + * Serializes a pairing file to XML format + * + * # Arguments + * * [`pairing_file`] - The pairing file to serialize + * * [`data`] - On success, will be set to point to a newly allocated buffer containing the serialized data + * * [`size`] - On success, will be set to the size of the allocated buffer + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `pairing_file` must be a valid, non-null pointer to a pairing file instance + * `data` must be a valid, non-null pointer to a location where the buffer pointer will be stored + * `size` must be a valid, non-null pointer to a location where the buffer size will be stored + */ +enum IdeviceErrorCode idevice_pairing_file_serialize(const struct IdevicePairingFile *pairing_file, + uint8_t **data, + uintptr_t *size); + +/** + * Frees a pairing file instance + * + * # Arguments + * * [`pairing_file`] - The pairing file to free + * + * # Safety + * `pairing_file` must be a valid pointer to a pairing file instance that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void idevice_pairing_file_free(struct IdevicePairingFile *pairing_file); + +/** + * Creates a new ProcessControlClient from a RemoteServerClient + * + * # Arguments + * * [`server`] - The RemoteServerClient to use + * * [`handle`] - Pointer to store the newly created ProcessControlClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `server` must be a valid pointer to a handle allocated by this library + * `handle` must be a valid pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode process_control_new(struct RemoteServerAdapterHandle *server, + struct ProcessControlAdapterHandle **handle); + +/** + * Frees a ProcessControlClient handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL + */ +void process_control_free(struct ProcessControlAdapterHandle *handle); + +/** + * Launches an application on the device + * + * # Arguments + * * [`handle`] - The ProcessControlClient handle + * * [`bundle_id`] - The bundle identifier of the app to launch + * * [`env_vars`] - NULL-terminated array of environment variables (format "KEY=VALUE") + * * [`arguments`] - NULL-terminated array of arguments + * * [`start_suspended`] - Whether to start the app suspended + * * [`kill_existing`] - Whether to kill existing instances of the app + * * [`pid`] - Pointer to store the process ID of the launched app + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * All pointers must be valid or NULL where appropriate + */ +enum IdeviceErrorCode process_control_launch_app(struct ProcessControlAdapterHandle *handle, + const char *bundle_id, + const char *const *env_vars, + uintptr_t env_vars_count, + const char *const *arguments, + uintptr_t arguments_count, + bool start_suspended, + bool kill_existing, + uint64_t *pid); + +/** + * Kills a running process + * + * # Arguments + * * [`handle`] - The ProcessControlClient handle + * * [`pid`] - The process ID to kill + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + */ +enum IdeviceErrorCode process_control_kill_app(struct ProcessControlAdapterHandle *handle, + uint64_t pid); + +/** + * Disables memory limits for a process + * + * # Arguments + * * [`handle`] - The ProcessControlClient handle + * * [`pid`] - The process ID to modify + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + */ +enum IdeviceErrorCode process_control_disable_memory_limit(struct ProcessControlAdapterHandle *handle, + uint64_t pid); + +/** + * Creates a TCP provider for idevice + * + * # Arguments + * * [`ip`] - The sockaddr IP to connect to + * * [`pairing_file`] - The pairing file handle to use + * * [`label`] - The label to use with the connection + * * [`provider`] - A pointer to a newly allocated provider + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `ip` must be a valid sockaddr + * `pairing_file` must never be used again + * `label` must be a valid Cstr + * `provider` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_tcp_provider_new(const struct sockaddr *ip, + struct IdevicePairingFile *pairing_file, + const char *label, + struct TcpProviderHandle **provider); + +/** + * Frees a TcpProvider handle + * + * # Arguments + * * [`provider`] - The provider handle to free + * + * # Safety + * `provider` must be a valid pointer to a TcpProvider handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void tcp_provider_free(struct TcpProviderHandle *provider); + +/** + * Creates a usbmuxd provider for idevice + * + * # Arguments + * * [`addr`] - The UsbmuxdAddr handle to connect to + * * [`tag`] - The tag returned in usbmuxd responses + * * [`udid`] - The UDID of the device to connect to + * * [`device_id`] - The muxer ID of the device to connect to + * * [`pairing_file`] - The pairing file handle to use + * * [`label`] - The label to use with the connection + * * [`provider`] - A pointer to a newly allocated provider + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `addr` must be a valid pointer to UsbmuxdAddrHandle created by this library, and never used again + * `udid` must be a valid CStr + * `pairing_file` must never be used again + * `label` must be a valid Cstr + * `provider` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode usbmuxd_provider_new(struct UsbmuxdAddrHandle *addr, + uint32_t tag, + const char *udid, + uint32_t device_id, + const char *label, + struct UsbmuxdProviderHandle **provider); + +/** + * Frees a UsbmuxdProvider handle + * + * # Arguments + * * [`provider`] - The provider handle to free + * + * # Safety + * `provider` must be a valid pointer to a UsbmuxdProvider handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void usbmuxd_provider_free(struct UsbmuxdProviderHandle *provider); + +/** + * Creates a new RemoteServerClient from a ReadWrite connection + * + * # Arguments + * * [`connection`] - The connection to use for communication + * * [`handle`] - Pointer to store the newly created RemoteServerClient handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `connection` must be a valid pointer to a handle allocated by this library + * `handle` must be a valid pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode remote_server_adapter_new(struct AdapterHandle *adapter, + struct RemoteServerAdapterHandle **handle); + +/** + * Frees a RemoteServerClient handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL + */ +void remote_server_free(struct RemoteServerAdapterHandle *handle); + +/** + * Returns the underlying connection from a RemoteServerClient + * + * # Arguments + * * [`handle`] - The handle to get the connection from + * * [`connection`] - The newly allocated ConnectionHandle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL, and never used again + */ +enum IdeviceErrorCode remote_server_adapter_into_inner(struct RemoteServerAdapterHandle *handle, + struct AdapterHandle **connection); + +/** + * Creates a new XPCDevice from an adapter + * + * # Arguments + * * [`adapter`] - The adapter to use for communication + * * [`device`] - Pointer to store the newly created XPCDevice handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `adapter` must be a valid pointer to a handle allocated by this library + * `device` must be a valid pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode xpc_device_new(struct AdapterHandle *adapter, + struct XPCDeviceAdapterHandle **device); + +/** + * Frees an XPCDevice handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL + */ +void xpc_device_free(struct XPCDeviceAdapterHandle *handle); + +/** + * Gets a service by name from the XPCDevice + * + * # Arguments + * * [`handle`] - The XPCDevice handle + * * [`service_name`] - The name of the service to get + * * [`service`] - Pointer to store the newly created XPCService handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `service_name` must be a valid null-terminated C string + * `service` must be a valid pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode xpc_device_get_service(struct XPCDeviceAdapterHandle *handle, + const char *service_name, + struct XPCServiceHandle **service); + +/** + * Returns the adapter in the RemoteXPC Device + * + * # Arguments + * * [`handle`] - The handle to get the adapter from + * * [`adapter`] - The newly allocated AdapterHandle + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL, and never used again + */ +enum IdeviceErrorCode xpc_device_adapter_into_inner(struct XPCDeviceAdapterHandle *handle, + struct AdapterHandle **adapter); + +/** + * Frees an XPCService handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library or NULL + */ +void xpc_service_free(struct XPCServiceHandle *handle); + +/** + * Gets the list of available service names + * + * # Arguments + * * [`handle`] - The XPCDevice handle + * * [`names`] - Pointer to store the array of service names + * * [`count`] - Pointer to store the number of services + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `handle` must be a valid pointer to a handle allocated by this library + * `names` must be a valid pointer to a location where the array will be stored + * `count` must be a valid pointer to a location where the count will be stored + */ +enum IdeviceErrorCode xpc_device_get_service_names(struct XPCDeviceAdapterHandle *handle, + char ***names, + uintptr_t *count); + +/** + * Frees a list of service names + * + * # Arguments + * * [`names`] - The array of service names to free + * * [`count`] - The number of services in the array + * + * # Safety + * `names` must be a valid pointer to an array of `count` C strings + */ +void xpc_device_free_service_names(char **names, uintptr_t count); + +/** + * Connects to a usbmuxd instance over TCP + * + * # Arguments + * * [`addr`] - The socket address to connect to + * * [`addr_len`] - Length of the socket + * * [`tag`] - A tag that will be returned by usbmuxd responses + * * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `addr` must be a valid sockaddr + * `usbmuxd_connection` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_usbmuxd_new_tcp_connection(const struct sockaddr *addr, + socklen_t addr_len, + uint32_t tag, + struct UsbmuxdConnectionHandle **usbmuxd_connection); + +/** + * Connects to a usbmuxd instance over unix socket + * + * # Arguments + * * [`addr`] - The socket path to connect to + * * [`tag`] - A tag that will be returned by usbmuxd responses + * * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `addr` must be a valid CStr + * `usbmuxd_connection` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_usbmuxd_new_unix_socket_connection(const char *addr, + uint32_t tag, + struct UsbmuxdConnectionHandle **usbmuxd_connection); + +/** + * Frees a UsbmuxdConnection handle + * + * # Arguments + * * [`usbmuxd_connection`] - The UsbmuxdConnection handle to free + * + * # Safety + * `usbmuxd_connection` must be a valid pointer to a UsbmuxdConnection handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void idevice_usbmuxd_connection_free(struct UsbmuxdConnectionHandle *usbmuxd_connection); + +/** + * Creates a usbmuxd TCP address struct + * + * # Arguments + * * [`addr`] - The socket address to connect to + * * [`addr_len`] - Length of the socket + * * [`usbmuxd_addr`] - On success, will be set to point to a newly allocated UsbmuxdAddr handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `addr` must be a valid sockaddr + * `usbmuxd_Addr` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_usbmuxd_tcp_addr_new(const struct sockaddr *addr, + socklen_t addr_len, + struct UsbmuxdAddrHandle **usbmuxd_addr); + +/** + * Creates a new UsbmuxdAddr struct with a unix socket + * + * # Arguments + * * [`addr`] - The socket path to connect to + * * [`usbmuxd_addr`] - On success, will be set to point to a newly allocated UsbmuxdAddr handle + * + * # Returns + * An error code indicating success or failure + * + * # Safety + * `addr` must be a valid CStr + * `usbmuxd_addr` must be a valid, non-null pointer to a location where the handle will be stored + */ +enum IdeviceErrorCode idevice_usbmuxd_unix_addr_new(const char *addr, + struct UsbmuxdAddrHandle **usbmuxd_addr); + +/** + * Frees a UsbmuxdAddr handle + * + * # Arguments + * * [`usbmuxd_addr`] - The UsbmuxdAddr handle to free + * + * # Safety + * `usbmuxd_addr` must be a valid pointer to a UsbmuxdAddr handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void idevice_usbmuxd_addr_free(struct UsbmuxdAddrHandle *usbmuxd_addr); diff --git a/StikJIT/idevice/libidevice_ffi.a b/StikJIT/idevice/libidevice_ffi.a new file mode 100644 index 0000000..c8d1df2 Binary files /dev/null and b/StikJIT/idevice/libidevice_ffi.a differ diff --git a/StikJIT/idevice/libplist-2.0.a b/StikJIT/idevice/libplist-2.0.a new file mode 100644 index 0000000..41adc1d Binary files /dev/null and b/StikJIT/idevice/libplist-2.0.a differ diff --git a/StikJIT/idevice/pairing_file.plist b/StikJIT/idevice/pairing_file.plist new file mode 100644 index 0000000..9939fa7 --- /dev/null +++ b/StikJIT/idevice/pairing_file.plist @@ -0,0 +1,159 @@ + + + + + DeviceCertificate + + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1akNDQWFLZ0F3SUJBZ0lCQURB + TkJna3Foa2lHOXcwQkFRVUZBREFBTUI0WERUSTFNRE15TnpBM01UQXoKTWxvWERUTTFN + RE15TlRBM01UQXpNbG93QURDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBREND + QVFvQwpnZ0VCQUxpZjNCS2VWUHlZSC85LzNKL2ZJeUdNSUdWbHNvWGJtWmJLYml1OGJo + TFpnRkRjbEhtME1LODRNRk9iCkJFUW9NRkNlRFUwQWV1VHZzNlkrMERqQWlEbzJTTXZw + TnpkbVlGZWtRL1JzWUtSN3VJSGJRc1h0bWJSU0FLRlgKdUpsZUNyMjdKeFpUSXNGT3FE + bzRZNmdXWWptSVVXSm1qbXRtVXFoMTVYSFVTWFVOYnUwMVhRS0lqRFBScXRVaQpIakMr + N0J4ZXVvNzBySlgwTldTcXdnSjQxNWEyRnNITUQyRW9FM2NIalNXU0dSWFFUazVKZkFH + NHlJV1VLeVJOClZGNTVybDU5bjR3Q083SlR5U0sveHVCR09RWFNzVnFkUUY4NVE2ZFpi + aDZNNHpTaDB4T3BYanNKVURFZUlLaUMKNC9IUmIxOEE1ZXBrVnlibURPcmhJa09TWGJr + Q0F3RUFBYU0vTUQwd0RBWURWUjBUQVFIL0JBSXdBREFkQmdOVgpIUTRFRmdRVWFJNU9t + aHBaL2JpeVA1N3d0KzBhVE1rODhUWXdEZ1lEVlIwUEFRSC9CQVFEQWdXZ01BMEdDU3FH + ClNJYjNEUUVCQlFVQUE0SUJBUUEzV3NyTU93QWhDUDZkSVRGMG5YR09adUJnSnVrRkFs + TWR1Zm8wL2ZIT2tVdE0KY2xJYU1WK05naFVUMGZVQWY2YlpnQUFyNW1xU0dkVDlxUFlw + dFh3eU9FVFI5d2NMWTlZQWFCamtnbkJUWllTSwo2eGRZa3hZRHJOQ3lnZCtvR05CUXBT + ME1BQ0lpWm9sNUNZZmgzK2d6UFJjUUZKeXVkaTNTVlJUaWRUSDNGV2lxCmpYT25kekpM + RVBnZTZaUDJjZWZjMXI0anFaM3JHd1FabjlWWWxxTnFwUGk5aTNWSjNacTMrcnlsYWNT + LzRMdHIKUGxtZnljQ0xWakF2djZxU3NPc1l3dGp3YllVRG52UDM0V0xnK2tMbFBOemlU + cEV3NmxGdXdXRndXUVNSSUNHOApPV0QzeEliczB2RmtramdjaDhVTUVuUlZMRmNpWUV5 + bzJoN1F4MXpzCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + + HostPrivateKey + + LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcw + QkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQys5dENJa3pDLzZ6VXgKZ29YUGxCb3NH + a1kzUThxbkVwSU1LczRIRU9aanM5RXAra1BoT3BxbWEzWGtmc2lvM1VFY2RVOUoybDM1 + YXB4RApseC83MGRSN2lNMFFmSU5aSXFiSHBHT3JaeGxuVjBxcysvNkNGbTM5ME9keUpW + K2ptSnBZbFU3aXh0N3A0bWRyCjZLdGVLTGpDMW56VzFOVFdDL0dWNitZTk5PUDV5MThp + dE9sOGt0YnBacTFtSjNCQURyaWdqOW1hQVpmbXFreWUKcmR6RDl1REFqUVdad2ZoZVIx + U2piS0QwdGs5ZWpxZCtxdkdsMEd6OE56YUJDYXI0Qk9FTXcvSFl2eVhhS1Nwagp4L3Zo + T2pkM0Y4S2xIcXZodWFOcVhCc3UrSlkzdVRzVzdIV3RwRGo4QlFCT2dpTks3UytlMnJ5 + ZytmR0FpZXV6ClVSbHJZSzhEQWdNQkFBRUNnZ0VBUSttczBkVmUwZklKRWRsMFV4VTls + WSttaHdMeDhDYlhqOEl0VVMvK2IxakUKdXlRSXZmSEVqQWpOZlh4bFNrQ2Raa3lGN1NM + ZXB0UDJUTWRURlpCUys3ZjBEYmZxVW1uVFhFNm5MNDdUNXYrUgpUQ0cyS25kbG1JMlJz + Zk4rcHNTZnAzODU5Y1o2QWoyRlFFZ1hvYjNqcjA3dVNNeWFBS0Z3d2p1SnJncXdST1lr + Ckw5ZTkxdnl2Rm9VWVlPWHpnRTE0dWxnK2NTSEdRTFh6bStDeEVEWWxUaEJ1Mi9HQUJ5 + RWZwUEtXN0pWS1ZUQ1YKdm0xSnI1Z0s5eVhYL1hEKzN5ZlBnd0RvZ3VNV3NNRFRURSti + Q3BERVB2b3BxRVUxMEgrNldtRW1hbkZlVElLSwpIeElpaEoyOFhmWDBUNVd4QldTWFlK + NGRETTVpdWMwYkZ6dzVvQVFsS1FLQmdRRG9zamxBSUNmWmZOVU43OGg1CjJheFFyZlhw + MmpzL0xEc1pGUzlib0V0VjVjOW1yb0FWR1BpaXJIZ2VNUUMxWkNMaDRLek9ObC9wYXlq + TVhkUnAKS0p6OGhtNTNtc1JkbVZ3OFo4WUozckFUanh6blRKMWN5c01QRGN3UC9zK3NG + cFkybXk0b2hENFFvQ2FsMzc1QwpGelp5VHR5aUU3NjhwbG9wWHJQZmJpNE8xd0tCZ1FE + U0ZxNGFUNGMwNFJKL1NuUTVDVGhMTWF1MTcrZE9DU0dZCjJvLzl5T3RmN1dlMHhjeHdK + SEV2MXFqOHlDcWM4eFd1Yzcram84cVkzTGNKYVN6WEM3WGtlTXdXRDVhZFNVQ2MKVnhO + WEFScFR0ZWxBOXB1VTBYWnNBWDJCV0hrTFhpb3BPb0h6SnVuMnR4NWYvdHluRFg2UFRJ + YjgzOUJabDFSeQpQbVB5aVdBM3RRS0JnRHpNQy85QUo0bEFmMTREejBwZTRCRzRVZThH + c01JaHFWTTFZTWs4eVZJcEdCWkk4M2dQCnJTNjdoeXJFUE40bnlxRmZsV2JQZUNIQmVN + aGtuNUhXSmFZbzdZWGNidi9SaVBMVFhqL0g2aE5DS2hnWXdXaTAKSldDeWh5V0t1dkhJ + ZVBqTmRMTHJVbGYvci9sWXl4bnpmS3REQll4blFrZUI0ejY1MnA4KzUxUERBb0dCQUtH + UwpNNytrWGhWNjYyRGQvOWhGa1BlemNaMXdyWEZFY0lRL3d2R283ZXhPaHExdVdiWDlN + TmRidlliNjRscm1VRXhrClZJUWpXWktLWEhKdVlyL1lEOEZ3YlhTaDlIRnVmclE5KzIr + ME4yMGR3QS9vR09zdzFHUm9HUCs2N1F5akZNVzAKYTNCM0F3UnMvSDFUWXB0UE00QTlt + S3N0N2V5WkI2YjgrSnowcmZ6cEFvR0FkaGYyOFNuZVFzOEkzM0ZHRXdFcwpJellJWStI + Q2ZjU2UrU2k0UWZuSmtqWW96NS95ZlJpK3MrUE9tdWxXMXVxM0pMdGlSNGsydlpUWXl5 + OUt5L1lXCjJwUHhJOURuY0VhUlBTYW5tb0FBck1uYlVER1hsT2JOakJEWldOSTVhenUr + ZzZ6bE91UkYzRE5wUC9CTm54WWgKdUpXenI1Y1VqMlI3bURMTFRCMFFCcjg9Ci0tLS0t + RU5EIFBSSVZBVEUgS0VZLS0tLS0K + + HostCertificate + + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNtekNDQVlPZ0F3SUJBZ0lCQURB + TkJna3Foa2lHOXcwQkFRVUZBREFBTUI0WERUSTFNRE15TnpBM01UQXoKTWxvWERUTTFN + RE15TlRBM01UQXpNbG93QURDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBREND + QVFvQwpnZ0VCQUw3MjBJaVRNTC9yTlRHQ2hjK1VHaXdhUmpkRHlxY1NrZ3dxemdjUTVt + T3owU242UStFNm1xWnJkZVIrCnlLamRRUngxVDBuYVhmbHFuRU9YSC92UjFIdUl6UkI4 + ZzFraXBzZWtZNnRuR1dkWFNxejcvb0lXYmYzUTUzSWwKWDZPWW1saVZUdUxHM3VuaVoy + dm9xMTRvdU1MV2ZOYlUxTllMOFpYcjVnMDA0L25MWHlLMDZYeVMxdWxtcldZbgpjRUFP + dUtDUDJab0JsK2FxVEo2dDNNUDI0TUNOQlpuQitGNUhWS05zb1BTMlQxNk9wMzZxOGFY + UWJQdzNOb0VKCnF2Z0U0UXpEOGRpL0pkb3BLbVBIKytFNk4zY1h3cVVlcStHNW8ycGNH + eTc0bGplNU94YnNkYTJrT1B3RkFFNkMKSTBydEw1N2F2S0Q1OFlDSjY3TlJHV3RncndN + Q0F3RUFBYU1nTUI0d0RBWURWUjBUQVFIL0JBSXdBREFPQmdOVgpIUThCQWY4RUJBTUNC + YUF3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQUZBbkEyUjFObGF2bVZGQm51ZnAyb0lM + CitOYXcrYXZpcmJBYVBnRHR4MXNTNzRsNFQ2eTdOWDFsdlFxY1Nqa01Salp6TmEvQUdX + VkNiaVovNUZCZjF4eWIKbmcrSjliL3VKWVpBRVBXaUEyanlVZlZ2UnI1aVVDdHdGZFBY + VmZuU2hOcXpxSjZuUEw5V1FoWm40dy9LdXJFRQovNU1kTnkxWnh1YytmczZHUzd1K3Ey + ZHpnQUJiYjN1NFIwRU1rL1pWV2pwKzRsaVZYd29UbVhyY2Z5OThqZWNsClY5RHF4V0ZJ + Q1BvTkdZbHcrT0R2TDdieFNERzhKaHBZOHJOVFNYYU1rUmJPNS91M0RnY0hWY2haNjVD + czlIRVEKem1IQXV5TGttdUE1Mzd1dVFvTHlYVUkrZmtHZGNmRjNwZ1VveUhzaFQ3ZlJx + QzhuTW9aWlNjdDVtc244a0RBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + + RootPrivateKey + + LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcw + QkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRE1kQmJTTkZtbURKUXMKb1U1ZVFQRFEy + NVhBN3RkUVdnaG9obUN0NU54UUUvR21rUjhNODNWUHg0WmMvSlZyUFJ0QUE5Rms0TzBE + VnFnYgpkNTJHZmVaa0xjWFlVVi9aWU9MQW5JbTM1bGJCNjVlRGIvb21sT2txOE95c21I + SS9SbmczWDZBQVVYWENsK3NQCkxjT3BYaFdHRzhBRzNONDk2cHN6c2hIN2R4dG1wTU9B + bHBVZHdaeVhXaVVDMFdsd3p0RXB5YXFvWWxOdS9GUVIKRkNEZ0l3Rlc4Ny8xSVZWYlEx + dVlOL1l1MXVENytrT2ZPRHNlUnkrc1JwQ2NGVWI2U1R5aFdmQnhic1ZUQ3puVwpwZ21Q + M284SFFaM2RGMzlHa1BIZTJJQnBXc1l2bEdoUFNqaVVibm03a1FXeGhrZ3ZNSE1yUmt5 + a2U1TTY1U3EwCjJNWW5IdUFiQWdNQkFBRUNnZ0VCQUtTeGZ4Q2xDdkl2Zjh6VHc0VTVX + c05qbnlaalB4NkM1L01MRENZSURWQ1UKUUR5aytoWThwMnMwbG8raEI5dnl4Vml6dXFG + QWJxd1p5aUVXSWRhTTVHSWVYUmo3cy9JdmtYa0dvQWw3aXJkNwpSL21nNGlqaUcxRno4 + YksydXBFdCt2amdGc3NxMDJtRlp0dzdTVG5OaUJrWGtYLzF1ekMxSTRCcEdRTXYxdXEr + CnErZnRRTktsQVd1TUJxclJCajNDd01nME5udzJtdnU4aUhhQXVCRU1mL1pKd1JyVVdV + UEhxMzFBQml1U0c3NXUKOWZ0SkIwaVZ3RVY0S21vQ0h3MVhGbTFUZjlPZ3h3Nnl5SUFN + YXNsdkdtN0NPM1lpYWdZUzFmYnJqWDVwUWJ4aQpjTWNnNHhKdUhicTQ5MWxTZCtNOVFt + dVRDdEtETkZyWVRGMHhMVVMwV0VFQ2dZRUEvcld5SkhXVWMwNDZGUFNJCktQSU1LRTFR + ZlV6SFlQeWRSV1BQUmxFeVg1MW9SbURGZnpsaDBUVSs5QlRJOFNKNmVGbFBMMktZTS9C + cjI0VTQKZUIwbHNHbS9EeWt6anBIZG1TVHZYbmN3Q1ZCTEQ4N1JUampiK015ZVV2TEln + QlVzYUJhODZJS2VpdXgxQUhWTgpFM0E0VEZmRzJ2dXFsYk85Mno3ajFnK3NyejhDZ1lF + QXpYMDR2RHBJdzBGZy9pT0NBSWUzaUdwUllaSjVSeWsxCmFVakprdm10b1VqWE5BbjBl + RlFUV3ZUdndqclZkTjdxemZwT1hOZlN5U3VBS2M4bVVTeTJ3SE4wVlRPK3lnNmEKQlhk + MTFJbmZiQ2owa003dkxTdjdOWGJ0c1pYT2NUYm1QOSsweTAwZlErc2Y5NlYyVE9NRng1 + VmN6eFl2ZjFkZwpPWVFERmV6L2RDVUNnWUJzSVZxRkc5MXZyZS8rWVdsRWFLMDhsc1hx + eTZPQXl2MUJMZ1FhaC9Ib29YeFpGRkFECm1LcXNFL3lyeGY4Z1QxREtzcTlwSUdRWStL + SHhTWGNWbHRvZk1HVkozR1hreW92V3JkVm90eFNQZjZTK0MwRFUKQWxOd0pmMjRuUlQ5 + T3YvbEdISU9DeFdmU0k3TEtRRVZsWGh4QUhxTkVIWDBvNStmNmV6elBTaEVKUUtCZ1FD + MgovR09oZW1XQk9wOGNzSkg3MXQ5ZzR3eEZUeUlnZEZuVHY3V0E1RVh4OGVOeHU4dXZ1 + MjdnK0d6cEVXc3ovNjRvCmJsV0o1OGNVelYvNzJ6UEw1WDE0TTFmTTU1OW1YMHBZdytC + eHU3VHhwQ2JsTE9GZjRHSjdZY1NZOTBZM0d5USsKalA5NmF0c0VxRVIzU3lqbG51UnVy + bHRQTGZwdDgya0V6c0hRckpOdTRRS0JnSDIwNXMwaEpaMkk0YS9JWE5aawo3N1d5YXlu + R2Y0YTFMUkw1bmJHOWl1TkJlT3FGVGJRQ3hIbVFmQ0daZ01vajZta2RMeTRNZHhXN05C + U0JrRzdZCmQ3SVNPbUx4QzRsSU85Rnp6eEpheDZKR3FIcWFkSDBTVzcydjlQTUJOTXFi + UXdYeWc3RUNMVTlPaThWNVZQR20KcHh4cG8vMytWMVgrY003dDdHRVBSNDM3Ci0tLS0t + RU5EIFBSSVZBVEUgS0VZLS0tLS0K + + RootCertificate + + LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNqakNDQVhhZ0F3SUJBZ0lCQURB + TkJna3Foa2lHOXcwQkFRVUZBREFBTUI0WERUSTFNRE15TnpBM01UQXoKTWxvWERUTTFN + RE15TlRBM01UQXpNbG93QURDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBREND + QVFvQwpnZ0VCQU14MEZ0STBXYVlNbEN5aFRsNUE4TkRibGNEdTExQmFDR2lHWUszazNG + QVQ4YWFSSHd6emRVL0hobHo4CmxXczlHMEFEMFdUZzdRTldxQnQzbllaOTVtUXR4ZGhS + WDlsZzRzQ2NpYmZtVnNIcmw0TnYraWFVNlNydzdLeVkKY2o5R2VEZGZvQUJSZGNLWDZ3 + OHR3NmxlRllZYndBYmMzajNxbXpPeUVmdDNHMmFrdzRDV2xSM0JuSmRhSlFMUgphWERP + MFNuSnFxaGlVMjc4VkJFVUlPQWpBVmJ6di9VaFZWdERXNWczOWk3VzRQdjZRNTg0T3g1 + SEw2eEdrSndWClJ2cEpQS0ZaOEhGdXhWTUxPZGFtQ1kvZWp3ZEJuZDBYZjBhUThkN1ln + R2xheGkrVWFFOUtPSlJ1ZWJ1UkJiR0cKU0M4d2N5dEdUS1I3a3pybEtyVFl4aWNlNEJz + Q0F3RUFBYU1UTUJFd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTgpCZ2txaGtpRzl3MEJB + UVVGQUFPQ0FRRUFDdTRUQi9vWnJHQStUS0M4a0YvWU9QcjVyTEpnQkRaaVVVNnNqQ0d6 + Ckk5QzV5dXZnSHc0bXlISnNoVjFaNDQxeDl6RDN2OGZvVTRuRldtbkhGa3h4TG9zaDNi + Zk5mM09ObVB5dkV0amgKMEhWQU5ydUozVXg4YzZtNmdRQjlpMGk4UkVJcUs2RWFwOXJz + bDkwN3ZSTityTFZmWGFuSU9BQzU5RUV4WnpiMwplYWF4S0YwM1czcUJFZUlyUEUxT3hQ + eUFpSi9Ic29nRU1JYVo4SlJjaCtmSGJWeGFXcmxwSnlGNExGdWROYituCnEzdGx3QUVO + NkV3Wk02VFkwSUlXdzg4aElYdEtZdXlCWldLcHloWjkxcUJoUDZWKzhaMHFMallGbWtV + U29PQ2UKajBVeTBGNVMwMWQzbVJGR1YvZzBpakR2dmoyMm9acXM0dzQvei9vREN0YWtx + Zz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + + SystemBUID + A805572C-254B-4E89-8834-69AC330F8C0F + HostID + B8908445-96B8-A598-2E42-37EE5108C1FC + EscrowBag + + dBHuB7agDgAU1p2P7o2d/XQw2stjvTNo4Q2oXTHRVp8= + + WiFiMACAddress + c4:c1:7d:ab:e1:9b + UDID + 00008130-0011356808A1401C + + diff --git a/StikJIT/idevice/plist.h b/StikJIT/idevice/plist.h new file mode 100644 index 0000000..2bb947f --- /dev/null +++ b/StikJIT/idevice/plist.h @@ -0,0 +1,1094 @@ +/** + * @file plist/plist.h + * @brief Main include of libplist + * \internal + * + * Copyright (c) 2012-2023 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2008-2009 Jonathan Beck, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBPLIST_H +#define LIBPLIST_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if _MSC_VER && _MSC_VER < 1700 + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + +#else +#include +#endif + +#ifdef __llvm__ + #if defined(__has_extension) + #if (__has_extension(attribute_deprecated_with_message)) + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated(x))) + #endif + #else + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated)) + #endif + #endif + #else + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated)) + #endif + #endif +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 5))) + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __attribute__((deprecated(x))) + #endif +#elif defined(_MSC_VER) + #ifndef PLIST_WARN_DEPRECATED + #define PLIST_WARN_DEPRECATED(x) __declspec(deprecated(x)) + #endif +#else + #define PLIST_WARN_DEPRECATED(x) + #pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#endif + +#include +#include + + /** + * \mainpage libplist : A library to handle Apple Property Lists + * \defgroup PublicAPI Public libplist API + */ + /*@{*/ + + + /** + * The basic plist abstract data type. + */ + typedef void *plist_t; + + /** + * The plist dictionary iterator. + */ + typedef void* plist_dict_iter; + + /** + * The plist array iterator. + */ + typedef void* plist_array_iter; + + /** + * The enumeration of plist node types. + */ + typedef enum + { + PLIST_BOOLEAN, /**< Boolean, scalar type */ + PLIST_INT, /**< Integer, scalar type */ + PLIST_REAL, /**< Real, scalar type */ + PLIST_STRING, /**< ASCII string, scalar type */ + PLIST_ARRAY, /**< Ordered array, structured type */ + PLIST_DICT, /**< Unordered dictionary (key/value pair), structured type */ + PLIST_DATE, /**< Date, scalar type */ + PLIST_DATA, /**< Binary data, scalar type */ + PLIST_KEY, /**< Key in dictionaries (ASCII String), scalar type */ + PLIST_UID, /**< Special type used for 'keyed encoding' */ + PLIST_NULL, /**< NULL type */ + PLIST_NONE /**< No type */ + } plist_type; + + /* for backwards compatibility */ + #define PLIST_UINT PLIST_INT + + /** + * libplist error values + */ + typedef enum + { + PLIST_ERR_SUCCESS = 0, /**< operation successful */ + PLIST_ERR_INVALID_ARG = -1, /**< one or more of the parameters are invalid */ + PLIST_ERR_FORMAT = -2, /**< the plist contains nodes not compatible with the output format */ + PLIST_ERR_PARSE = -3, /**< parsing of the input format failed */ + PLIST_ERR_NO_MEM = -4, /**< not enough memory to handle the operation */ + PLIST_ERR_UNKNOWN = -255 /**< an unspecified error occurred */ + } plist_err_t; + + /******************************************** + * * + * Creation & Destruction * + * * + ********************************************/ + + /** + * Create a new root plist_t type #PLIST_DICT + * + * @return the created plist + * @sa #plist_type + */ + plist_t plist_new_dict(void); + + /** + * Create a new root plist_t type #PLIST_ARRAY + * + * @return the created plist + * @sa #plist_type + */ + plist_t plist_new_array(void); + + /** + * Create a new plist_t type #PLIST_STRING + * + * @param val the sting value, encoded in UTF8. + * @return the created item + * @sa #plist_type + */ + plist_t plist_new_string(const char *val); + + /** + * Create a new plist_t type #PLIST_BOOLEAN + * + * @param val the boolean value, 0 is false, other values are true. + * @return the created item + * @sa #plist_type + */ + plist_t plist_new_bool(uint8_t val); + + /** + * Create a new plist_t type #PLIST_INT with an unsigned integer value + * + * @param val the unsigned integer value + * @return the created item + * @sa #plist_type + * @note The value is always stored as uint64_t internally. + * Use #plist_get_uint_val or #plist_get_int_val to get the unsigned or signed value. + */ + plist_t plist_new_uint(uint64_t val); + + /** + * Create a new plist_t type #PLIST_INT with a signed integer value + * + * @param val the signed integer value + * @return the created item + * @sa #plist_type + * @note The value is always stored as uint64_t internally. + * Use #plist_get_uint_val or #plist_get_int_val to get the unsigned or signed value. + */ + plist_t plist_new_int(int64_t val); + + /** + * Create a new plist_t type #PLIST_REAL + * + * @param val the real value + * @return the created item + * @sa #plist_type + */ + plist_t plist_new_real(double val); + + /** + * Create a new plist_t type #PLIST_DATA + * + * @param val the binary buffer + * @param length the length of the buffer + * @return the created item + * @sa #plist_type + */ + plist_t plist_new_data(const char *val, uint64_t length); + + /** + * Create a new plist_t type #PLIST_DATE + * + * @param sec the number of seconds since 01/01/2001 + * @param usec the number of microseconds + * @return the created item + * @sa #plist_type + */ + plist_t plist_new_date(int32_t sec, int32_t usec); + + /** + * Create a new plist_t type #PLIST_UID + * + * @param val the unsigned integer value + * @return the created item + * @sa #plist_type + */ + plist_t plist_new_uid(uint64_t val); + + /** + * Create a new plist_t type #PLIST_NULL + * @return the created item + * @sa #plist_type + * @note This type is not valid for all formats, e.g. the XML format + * does not support it. + */ + plist_t plist_new_null(void); + + /** + * Destruct a plist_t node and all its children recursively + * + * @param plist the plist to free + */ + void plist_free(plist_t plist); + + /** + * Return a copy of passed node and it's children + * + * @param node the plist to copy + * @return copied plist + */ + plist_t plist_copy(plist_t node); + + + /******************************************** + * * + * Array functions * + * * + ********************************************/ + + /** + * Get size of a #PLIST_ARRAY node. + * + * @param node the node of type #PLIST_ARRAY + * @return size of the #PLIST_ARRAY node + */ + uint32_t plist_array_get_size(plist_t node); + + /** + * Get the nth item in a #PLIST_ARRAY node. + * + * @param node the node of type #PLIST_ARRAY + * @param n the index of the item to get. Range is [0, array_size[ + * @return the nth item or NULL if node is not of type #PLIST_ARRAY + */ + plist_t plist_array_get_item(plist_t node, uint32_t n); + + /** + * Get the index of an item. item must be a member of a #PLIST_ARRAY node. + * + * @param node the node + * @return the node index or UINT_MAX if node index can't be determined + */ + uint32_t plist_array_get_item_index(plist_t node); + + /** + * Set the nth item in a #PLIST_ARRAY node. + * The previous item at index n will be freed using #plist_free + * + * @param node the node of type #PLIST_ARRAY + * @param item the new item at index n. The array is responsible for freeing item when it is no longer needed. + * @param n the index of the item to get. Range is [0, array_size[. Assert if n is not in range. + */ + void plist_array_set_item(plist_t node, plist_t item, uint32_t n); + + /** + * Append a new item at the end of a #PLIST_ARRAY node. + * + * @param node the node of type #PLIST_ARRAY + * @param item the new item. The array is responsible for freeing item when it is no longer needed. + */ + void plist_array_append_item(plist_t node, plist_t item); + + /** + * Insert a new item at position n in a #PLIST_ARRAY node. + * + * @param node the node of type #PLIST_ARRAY + * @param item the new item to insert. The array is responsible for freeing item when it is no longer needed. + * @param n The position at which the node will be stored. Range is [0, array_size[. Assert if n is not in range. + */ + void plist_array_insert_item(plist_t node, plist_t item, uint32_t n); + + /** + * Remove an existing position in a #PLIST_ARRAY node. + * Removed position will be freed using #plist_free. + * + * @param node the node of type #PLIST_ARRAY + * @param n The position to remove. Range is [0, array_size[. Assert if n is not in range. + */ + void plist_array_remove_item(plist_t node, uint32_t n); + + /** + * Remove a node that is a child node of a #PLIST_ARRAY node. + * node will be freed using #plist_free. + * + * @param node The node to be removed from its #PLIST_ARRAY parent. + */ + void plist_array_item_remove(plist_t node); + + /** + * Create an iterator of a #PLIST_ARRAY node. + * The allocated iterator should be freed with the standard free function. + * + * @param node The node of type #PLIST_ARRAY + * @param iter Location to store the iterator for the array. + */ + void plist_array_new_iter(plist_t node, plist_array_iter *iter); + + /** + * Increment iterator of a #PLIST_ARRAY node. + * + * @param node The node of type #PLIST_ARRAY. + * @param iter Iterator of the array + * @param item Location to store the item. The caller must *not* free the + * returned item. Will be set to NULL when no more items are left + * to iterate. + */ + void plist_array_next_item(plist_t node, plist_array_iter iter, plist_t *item); + + + /******************************************** + * * + * Dictionary functions * + * * + ********************************************/ + + /** + * Get size of a #PLIST_DICT node. + * + * @param node the node of type #PLIST_DICT + * @return size of the #PLIST_DICT node + */ + uint32_t plist_dict_get_size(plist_t node); + + /** + * Create an iterator of a #PLIST_DICT node. + * The allocated iterator should be freed with the standard free function. + * + * @param node The node of type #PLIST_DICT. + * @param iter Location to store the iterator for the dictionary. + */ + void plist_dict_new_iter(plist_t node, plist_dict_iter *iter); + + /** + * Increment iterator of a #PLIST_DICT node. + * + * @param node The node of type #PLIST_DICT + * @param iter Iterator of the dictionary + * @param key Location to store the key, or NULL. The caller is responsible + * for freeing the the returned string. + * @param val Location to store the value, or NULL. The caller must *not* + * free the returned value. Will be set to NULL when no more + * key/value pairs are left to iterate. + */ + void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_t *val); + + /** + * Get key associated key to an item. Item must be member of a dictionary. + * + * @param node the item + * @param key a location to store the key. The caller is responsible for freeing the returned string. + */ + void plist_dict_get_item_key(plist_t node, char **key); + + /** + * Get the nth item in a #PLIST_DICT node. + * + * @param node the node of type #PLIST_DICT + * @param key the identifier of the item to get. + * @return the item or NULL if node is not of type #PLIST_DICT. The caller should not free + * the returned node. + */ + plist_t plist_dict_get_item(plist_t node, const char* key); + + /** + * Get key node associated to an item. Item must be member of a dictionary. + * + * @param node the item + * @return the key node of the given item, or NULL. + */ + plist_t plist_dict_item_get_key(plist_t node); + + /** + * Set item identified by key in a #PLIST_DICT node. + * The previous item identified by key will be freed using #plist_free. + * If there is no item for the given key a new item will be inserted. + * + * @param node the node of type #PLIST_DICT + * @param item the new item associated to key + * @param key the identifier of the item to set. + */ + void plist_dict_set_item(plist_t node, const char* key, plist_t item); + + /** + * Insert a new item into a #PLIST_DICT node. + * + * @deprecated Deprecated. Use plist_dict_set_item instead. + * + * @param node the node of type #PLIST_DICT + * @param item the new item to insert + * @param key The identifier of the item to insert. + */ + PLIST_WARN_DEPRECATED("use plist_dict_set_item instead") + void plist_dict_insert_item(plist_t node, const char* key, plist_t item); + + /** + * Remove an existing position in a #PLIST_DICT node. + * Removed position will be freed using #plist_free + * + * @param node the node of type #PLIST_DICT + * @param key The identifier of the item to remove. Assert if identifier is not present. + */ + void plist_dict_remove_item(plist_t node, const char* key); + + /** + * Merge a dictionary into another. This will add all key/value pairs + * from the source dictionary to the target dictionary, overwriting + * any existing key/value pairs that are already present in target. + * + * @param target pointer to an existing node of type #PLIST_DICT + * @param source node of type #PLIST_DICT that should be merged into target + */ + void plist_dict_merge(plist_t *target, plist_t source); + + + /******************************************** + * * + * Getters * + * * + ********************************************/ + + /** + * Get the parent of a node + * + * @param node the parent (NULL if node is root) + */ + plist_t plist_get_parent(plist_t node); + + /** + * Get the #plist_type of a node. + * + * @param node the node + * @return the type of the node + */ + plist_type plist_get_node_type(plist_t node); + + /** + * Get the value of a #PLIST_KEY node. + * This function does nothing if node is not of type #PLIST_KEY + * + * @param node the node + * @param val a pointer to a C-string. This function allocates the memory, + * caller is responsible for freeing it. + * @note Use plist_mem_free() to free the allocated memory. + */ + void plist_get_key_val(plist_t node, char **val); + + /** + * Get the value of a #PLIST_STRING node. + * This function does nothing if node is not of type #PLIST_STRING + * + * @param node the node + * @param val a pointer to a C-string. This function allocates the memory, + * caller is responsible for freeing it. Data is UTF-8 encoded. + * @note Use plist_mem_free() to free the allocated memory. + */ + void plist_get_string_val(plist_t node, char **val); + + /** + * Get a pointer to the buffer of a #PLIST_STRING node. + * + * @note DO NOT MODIFY the buffer. Mind that the buffer is only available + * until the plist node gets freed. Make a copy if needed. + * + * @param node The node + * @param length If non-NULL, will be set to the length of the string + * + * @return Pointer to the NULL-terminated buffer. + */ + const char* plist_get_string_ptr(plist_t node, uint64_t* length); + + /** + * Get the value of a #PLIST_BOOLEAN node. + * This function does nothing if node is not of type #PLIST_BOOLEAN + * + * @param node the node + * @param val a pointer to a uint8_t variable. + */ + void plist_get_bool_val(plist_t node, uint8_t * val); + + /** + * Get the unsigned integer value of a #PLIST_INT node. + * This function does nothing if node is not of type #PLIST_INT + * + * @param node the node + * @param val a pointer to a uint64_t variable. + */ + void plist_get_uint_val(plist_t node, uint64_t * val); + + /** + * Get the signed integer value of a #PLIST_INT node. + * This function does nothing if node is not of type #PLIST_INT + * + * @param node the node + * @param val a pointer to a int64_t variable. + */ + void plist_get_int_val(plist_t node, int64_t * val); + + /** + * Get the value of a #PLIST_REAL node. + * This function does nothing if node is not of type #PLIST_REAL + * + * @param node the node + * @param val a pointer to a double variable. + */ + void plist_get_real_val(plist_t node, double *val); + + /** + * Get the value of a #PLIST_DATA node. + * This function does nothing if node is not of type #PLIST_DATA + * + * @param node the node + * @param val a pointer to an unallocated char buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length the length of the buffer + * @note Use plist_mem_free() to free the allocated memory. + */ + void plist_get_data_val(plist_t node, char **val, uint64_t * length); + + /** + * Get a pointer to the data buffer of a #PLIST_DATA node. + * + * @note DO NOT MODIFY the buffer. Mind that the buffer is only available + * until the plist node gets freed. Make a copy if needed. + * + * @param node The node + * @param length Pointer to a uint64_t that will be set to the length of the buffer + * + * @return Pointer to the buffer + */ + const char* plist_get_data_ptr(plist_t node, uint64_t* length); + + /** + * Get the value of a #PLIST_DATE node. + * This function does nothing if node is not of type #PLIST_DATE + * + * @param node the node + * @param sec a pointer to an int32_t variable. Represents the number of seconds since 01/01/2001. + * @param usec a pointer to an int32_t variable. Represents the number of microseconds + */ + void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec); + + /** + * Get the value of a #PLIST_UID node. + * This function does nothing if node is not of type #PLIST_UID + * + * @param node the node + * @param val a pointer to a uint64_t variable. + */ + void plist_get_uid_val(plist_t node, uint64_t * val); + + + /******************************************** + * * + * Setters * + * * + ********************************************/ + + /** + * Set the value of a node. + * Forces type of node to #PLIST_KEY + * + * @param node the node + * @param val the key value + */ + void plist_set_key_val(plist_t node, const char *val); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_STRING + * + * @param node the node + * @param val the string value. The string is copied when set and will be + * freed by the node. + */ + void plist_set_string_val(plist_t node, const char *val); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_BOOLEAN + * + * @param node the node + * @param val the boolean value + */ + void plist_set_bool_val(plist_t node, uint8_t val); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_INT + * + * @param node the node + * @param val the unsigned integer value + */ + void plist_set_uint_val(plist_t node, uint64_t val); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_INT + * + * @param node the node + * @param val the signed integer value + */ + void plist_set_int_val(plist_t node, int64_t val); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_REAL + * + * @param node the node + * @param val the real value + */ + void plist_set_real_val(plist_t node, double val); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_DATA + * + * @param node the node + * @param val the binary buffer. The buffer is copied when set and will + * be freed by the node. + * @param length the length of the buffer + */ + void plist_set_data_val(plist_t node, const char *val, uint64_t length); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_DATE + * + * @param node the node + * @param sec the number of seconds since 01/01/2001 + * @param usec the number of microseconds + */ + void plist_set_date_val(plist_t node, int32_t sec, int32_t usec); + + /** + * Set the value of a node. + * Forces type of node to #PLIST_UID + * + * @param node the node + * @param val the unsigned integer value + */ + void plist_set_uid_val(plist_t node, uint64_t val); + + + /******************************************** + * * + * Import & Export * + * * + ********************************************/ + + /** + * Export the #plist_t structure to XML format. + * + * @param plist the root node to export + * @param plist_xml a pointer to a C-string. This function allocates the memory, + * caller is responsible for freeing it. Data is UTF-8 encoded. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length); + + /** + * Export the #plist_t structure to binary format. + * + * @param plist the root node to export + * @param plist_bin a pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length); + + /** + * Export the #plist_t structure to JSON format. + * + * @param plist the root node to export + * @param plist_json a pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @param prettify pretty print the output if != 0 + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify); + + /** + * Export the #plist_t structure to OpenStep format. + * + * @param plist the root node to export + * @param plist_openstep a pointer to a char* buffer. This function allocates the memory, + * caller is responsible for freeing it. + * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. + * @param prettify pretty print the output if != 0 + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + * @note Use plist_mem_free() to free the allocated memory. + */ + plist_err_t plist_to_openstep(plist_t plist, char **plist_openstep, uint32_t* length, int prettify); + + + /** + * Import the #plist_t structure from XML format. + * + * @param plist_xml a pointer to the xml buffer. + * @param length length of the buffer to read. + * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + plist_err_t plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist); + + /** + * Import the #plist_t structure from binary format. + * + * @param plist_bin a pointer to the xml buffer. + * @param length length of the buffer to read. + * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist); + + /** + * Import the #plist_t structure from JSON format. + * + * @param json a pointer to the JSON buffer. + * @param length length of the buffer to read. + * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + plist_err_t plist_from_json(const char *json, uint32_t length, plist_t * plist); + + /** + * Import the #plist_t structure from OpenStep plist format. + * + * @param openstep a pointer to the OpenStep plist buffer. + * @param length length of the buffer to read. + * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + plist_err_t plist_from_openstep(const char *openstep, uint32_t length, plist_t * plist); + + /** + * Import the #plist_t structure from memory data. + * This method will look at the first bytes of plist_data + * to determine if plist_data contains a binary, JSON, or XML plist + * and tries to parse the data in the appropriate format. + * @note This is just a convenience function and the format detection is + * very basic. It checks with plist_is_binary() if the data supposedly + * contains binary plist data, if not it checks if the first byte is + * either '{' or '[' and assumes JSON format, otherwise it will try + * to parse the data as XML. + * + * @param plist_data a pointer to the memory buffer containing plist data. + * @param length length of the buffer to read. + * @param plist a pointer to the imported plist. + * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure + */ + plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist); + + /** + * Test if in-memory plist data is in binary format. + * This function will look at the first bytes of plist_data to determine + * if it supposedly contains a binary plist. + * @note The function is not validating the whole memory buffer to check + * if the content is truly a plist, it is only using some heuristic on + * the first few bytes of plist_data. + * + * @param plist_data a pointer to the memory buffer containing plist data. + * @param length length of the buffer to read. + * @return 1 if the buffer is a binary plist, 0 otherwise. + */ + int plist_is_binary(const char *plist_data, uint32_t length); + + /******************************************** + * * + * Utils * + * * + ********************************************/ + + /** + * Get a node from its path. Each path element depends on the associated father node type. + * For Dictionaries, var args are casted to const char*, for arrays, var args are caster to uint32_t + * Search is breath first order. + * + * @param plist the node to access result from. + * @param length length of the path to access + * @return the value to access. + */ + plist_t plist_access_path(plist_t plist, uint32_t length, ...); + + /** + * Variadic version of #plist_access_path. + * + * @param plist the node to access result from. + * @param length length of the path to access + * @param v list of array's index and dic'st key + * @return the value to access. + */ + plist_t plist_access_pathv(plist_t plist, uint32_t length, va_list v); + + /** + * Compare two node values + * + * @param node_l left node to compare + * @param node_r rigth node to compare + * @return TRUE is type and value match, FALSE otherwise. + */ + char plist_compare_node_value(plist_t node_l, plist_t node_r); + + #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type)) + + /* Helper macros for the different plist types */ + #define PLIST_IS_BOOLEAN(__plist) _PLIST_IS_TYPE(__plist, BOOLEAN) + #define PLIST_IS_INT(__plist) _PLIST_IS_TYPE(__plist, INT) + #define PLIST_IS_REAL(__plist) _PLIST_IS_TYPE(__plist, REAL) + #define PLIST_IS_STRING(__plist) _PLIST_IS_TYPE(__plist, STRING) + #define PLIST_IS_ARRAY(__plist) _PLIST_IS_TYPE(__plist, ARRAY) + #define PLIST_IS_DICT(__plist) _PLIST_IS_TYPE(__plist, DICT) + #define PLIST_IS_DATE(__plist) _PLIST_IS_TYPE(__plist, DATE) + #define PLIST_IS_DATA(__plist) _PLIST_IS_TYPE(__plist, DATA) + #define PLIST_IS_KEY(__plist) _PLIST_IS_TYPE(__plist, KEY) + #define PLIST_IS_UID(__plist) _PLIST_IS_TYPE(__plist, UID) + /* for backwards compatibility */ + #define PLIST_IS_UINT PLIST_IS_INT + + /** + * Helper function to check the value of a PLIST_BOOL node. + * + * @param boolnode node of type PLIST_BOOL + * @return 1 if the boolean node has a value of TRUE or 0 if FALSE. + */ + int plist_bool_val_is_true(plist_t boolnode); + + /** + * Helper function to test if a given #PLIST_INT node's value is negative + * + * @param intnode node of type PLIST_INT + * @return 1 if the node's value is negative, or 0 if positive. + */ + int plist_int_val_is_negative(plist_t intnode); + + /** + * Helper function to compare the value of a PLIST_INT node against + * a given signed integer value. + * + * @param uintnode node of type PLIST_INT + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + int plist_int_val_compare(plist_t uintnode, int64_t cmpval); + + /** + * Helper function to compare the value of a PLIST_INT node against + * a given unsigned integer value. + * + * @param uintnode node of type PLIST_INT + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + int plist_uint_val_compare(plist_t uintnode, uint64_t cmpval); + + /** + * Helper function to compare the value of a PLIST_UID node against + * a given value. + * + * @param uidnode node of type PLIST_UID + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + int plist_uid_val_compare(plist_t uidnode, uint64_t cmpval); + + /** + * Helper function to compare the value of a PLIST_REAL node against + * a given value. + * + * @note WARNING: Comparing floating point values can give inaccurate + * results because of the nature of floating point values on computer + * systems. While this function is designed to be as accurate as + * possible, please don't rely on it too much. + * + * @param realnode node of type PLIST_REAL + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are (almost) equal, + * 1 if the node's value is greater than cmpval, + * or -1 if the node's value is less than cmpval. + */ + int plist_real_val_compare(plist_t realnode, double cmpval); + + /** + * Helper function to compare the value of a PLIST_DATE node against + * a given set of seconds and fraction of a second since epoch. + * + * @param datenode node of type PLIST_DATE + * @param cmpsec number of seconds since epoch to compare against + * @param cmpusec fraction of a second in microseconds to compare against + * @return 0 if the node's date is equal to the supplied values, + * 1 if the node's date is greater than the supplied values, + * or -1 if the node's date is less than the supplied values. + */ + int plist_date_val_compare(plist_t datenode, int32_t cmpsec, int32_t cmpusec); + + /** + * Helper function to compare the value of a PLIST_STRING node against + * a given value. + * This function basically behaves like strcmp. + * + * @param strnode node of type PLIST_STRING + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + int plist_string_val_compare(plist_t strnode, const char* cmpval); + + /** + * Helper function to compare the value of a PLIST_STRING node against + * a given value, while not comparing more than n characters. + * This function basically behaves like strncmp. + * + * @param strnode node of type PLIST_STRING + * @param cmpval value to compare against + * @param n maximum number of characters to compare + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + int plist_string_val_compare_with_size(plist_t strnode, const char* cmpval, size_t n); + + /** + * Helper function to match a given substring in the value of a + * PLIST_STRING node. + * + * @param strnode node of type PLIST_STRING + * @param substr value to match + * @return 1 if the node's value contains the given substring, + * or 0 if not. + */ + int plist_string_val_contains(plist_t strnode, const char* substr); + + /** + * Helper function to compare the value of a PLIST_KEY node against + * a given value. + * This function basically behaves like strcmp. + * + * @param keynode node of type PLIST_KEY + * @param cmpval value to compare against + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + int plist_key_val_compare(plist_t keynode, const char* cmpval); + + /** + * Helper function to compare the value of a PLIST_KEY node against + * a given value, while not comparing more than n characters. + * This function basically behaves like strncmp. + * + * @param keynode node of type PLIST_KEY + * @param cmpval value to compare against + * @param n maximum number of characters to compare + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + int plist_key_val_compare_with_size(plist_t keynode, const char* cmpval, size_t n); + + /** + * Helper function to match a given substring in the value of a + * PLIST_KEY node. + * + * @param keynode node of type PLIST_KEY + * @param substr value to match + * @return 1 if the node's value contains the given substring, + * or 0 if not. + */ + int plist_key_val_contains(plist_t keynode, const char* substr); + + /** + * Helper function to compare the data of a PLIST_DATA node against + * a given blob and size. + * This function basically behaves like memcmp after making sure the + * size of the node's data value is equal to the size of cmpval (n), + * making this a "full match" comparison. + * + * @param datanode node of type PLIST_DATA + * @param cmpval data blob to compare against + * @param n size of data blob passed in cmpval + * @return 0 if the node's data blob and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + int plist_data_val_compare(plist_t datanode, const uint8_t* cmpval, size_t n); + + /** + * Helper function to compare the data of a PLIST_DATA node against + * a given blob and size, while no more than n bytes are compared. + * This function basically behaves like memcmp after making sure the + * size of the node's data value is at least n, making this a + * "starts with" comparison. + * + * @param datanode node of type PLIST_DATA + * @param cmpval data blob to compare against + * @param n size of data blob passed in cmpval + * @return 0 if the node's value and cmpval are equal, + * > 0 if the node's value is lexicographically greater than cmpval, + * or < 0 if the node's value is lexicographically less than cmpval. + */ + int plist_data_val_compare_with_size(plist_t datanode, const uint8_t* cmpval, size_t n); + + /** + * Helper function to match a given data blob within the value of a + * PLIST_DATA node. + * + * @param datanode node of type PLIST_KEY + * @param cmpval data blob to match + * @param n size of data blob passed in cmpval + * @return 1 if the node's value contains the given data blob + * or 0 if not. + */ + int plist_data_val_contains(plist_t datanode, const uint8_t* cmpval, size_t n); + + /** + * Free memory allocated by relevant libplist API calls: + * - plist_to_xml() + * - plist_to_bin() + * - plist_get_key_val() + * - plist_get_string_val() + * - plist_get_data_val() + * + * @param ptr pointer to the memory to free + * + * @note Do not use this function to free plist_t nodes, use plist_free() + * instead. + */ + void plist_mem_free(void* ptr); + + /*@}*/ + +#ifdef __cplusplus +} +#endif +#endif