/** * Cancels a running synchronization session with a device at any time. * * @param client The mobilesync client * @param reason The reason to supply to the device for cancelling * * @retval MOBILESYNC_E_SUCCESS on success * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid */ mobilesync_error_t mobilesync_cancel(mobilesync_client_t client, const char* reason) { if (!client || !client->data_class || !reason) { return MOBILESYNC_E_INVALID_ARG; } mobilesync_error_t err = MOBILESYNC_E_UNKNOWN_ERROR; plist_t msg = NULL; msg = plist_new_array(); plist_array_append_item(msg, plist_new_string("SDMessageCancelSession")); plist_array_append_item(msg, plist_new_string(client->data_class)); plist_array_append_item(msg, plist_new_string(reason)); err = mobilesync_send(client, msg); plist_free(msg); msg = NULL; free(client->data_class); client->data_class = NULL; client->direction = MOBILESYNC_SYNC_DIR_DEVICE_TO_COMPUTER; return err; }
/** * Sends a notification to the device's notification_proxy. * * @param client The client to send to * @param notification The notification message to send * * @return NP_E_SUCCESS on success, or an error returned by np_plist_send */ np_error_t np_post_notification(np_client_t client, const char *notification) { if (!client || !notification) { return NP_E_INVALID_ARG; } np_lock(client); plist_t dict = plist_new_dict(); plist_dict_insert_item(dict,"Command", plist_new_string("PostNotification")); plist_dict_insert_item(dict,"Name", plist_new_string(notification)); np_error_t res = np_error(property_list_service_send_xml_plist(client->parent, dict)); plist_free(dict); dict = plist_new_dict(); plist_dict_insert_item(dict,"Command", plist_new_string("Shutdown")); res = np_error(property_list_service_send_xml_plist(client->parent, dict)); plist_free(dict); if (res != NP_E_SUCCESS) { debug_info("Error sending XML plist to device!"); } np_unlock(client); return res; }
plist_t tss_request_new(plist_t overrides) { plist_t request = plist_new_dict(); plist_dict_set_item(request, "@Locality", plist_new_string("en_US")); plist_dict_set_item(request, "@HostPlatformInfo", #ifdef WIN32 plist_new_string("windows") #else plist_new_string("mac") #endif ); plist_dict_set_item(request, "@VersionInfo", plist_new_string(TSS_CLIENT_VERSION_STRING)); char* guid = generate_guid(); if (guid) { plist_dict_set_item(request, "@UUID", plist_new_string(guid)); free(guid); } /* apply overrides */ if (overrides) { plist_dict_merge(&request, overrides); } return request; }
dl_status dl_start(dl_t self) { // Assume usbmuxd supports proto_version 1. If not then we'd need to // send a binary listen request, check for failure, then retry this: plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "ClientVersionString", plist_new_string( "device_listener")); plist_dict_insert_item(dict, "MessageType", plist_new_string("Listen")); plist_dict_insert_item(dict, "ProgName", plist_new_string("libusbmuxd")); char *xml = NULL; uint32_t xml_length = 0; plist_to_xml(dict, &xml, &xml_length); plist_free(dict); size_t length = 16 + xml_length; char *packet = (char *)calloc(length, sizeof(char)); if (!packet) { return DL_ERROR; } char *tail = packet; tail = dl_sprintf_uint32(tail, length); tail = dl_sprintf_uint32(tail, 1); // version: 1 tail = dl_sprintf_uint32(tail, TYPE_PLIST); // type: plist tail = dl_sprintf_uint32(tail, 1); // tag: 1 tail = stpncpy(tail, xml, xml_length); free(xml); dl_status ret = self->send_packet(self, packet, length); free(packet); return ret; }
/** * Uninstall an application from the device. * * @param client The connected installation proxy client * @param appid ApplicationIdentifier of the app to uninstall * @param client_options The client options to use, as PLIST_DICT, or NULL. * Currently there are no known client options, so pass NULL here. * @param status_cb Callback function for progress and status information. If * NULL is passed, this function will run synchronously. * @param user_data Callback data passed to status_cb. * * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if * an error occured. * * @note If a callback function is given (async mode), this function returns * INSTPROXY_E_SUCCESS immediately if the status updater thread has been * created successfully; any error occuring during the operation has to be * handled inside the specified callback function. */ instproxy_error_t instproxy_uninstall(instproxy_client_t client, const char *appid, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) { if (!client || !client->parent || !appid) { return INSTPROXY_E_INVALID_ARG; } if (client->status_updater) { return INSTPROXY_E_OP_IN_PROGRESS; } instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "ApplicationIdentifier", plist_new_string(appid)); plist_dict_insert_item(dict, "Command", plist_new_string("Uninstall")); instproxy_lock(client); res = instproxy_send_command(client, "Uninstall", client_options, appid, NULL); instproxy_unlock(client); plist_free(dict); if (res != INSTPROXY_E_SUCCESS) { debug_info("could not send plist, error %d", res); return res; } return instproxy_create_status_updater(client, status_cb, "Uninstall", user_data); }
/** * Mounts an image on the device. * * @param client The connected mobile_image_mounter client. * @param image_path The absolute path of the image to mount. The image must * be present before calling this function. * @param image_signature Pointer to a buffer holding the images' signature * @param signature_length Length of the signature image_signature points to * @param image_type Type of image to mount * @param result Pointer to a plist that will receive the result of the * operation. * * @note This function may return MOBILE_IMAGE_MOUNTER_E_SUCCESS even if the * operation has failed. Check the resulting plist for further information. * Note that there is no unmounting function. The mount persists until the * device is rebooted. * * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if on ore more parameters are * invalid, or another error code otherwise. */ mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, const char *image_path, const char *image_signature, uint16_t signature_length, const char *image_type, plist_t *result) { if (!client || !image_path || !image_signature || (signature_length == 0) || !image_type || !result) { return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; } mobile_image_mounter_lock(client); plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "Command", plist_new_string("MountImage")); plist_dict_insert_item(dict, "ImagePath", plist_new_string(image_path)); plist_dict_insert_item(dict, "ImageSignature", plist_new_data(image_signature, signature_length)); plist_dict_insert_item(dict, "ImageType", plist_new_string(image_type)); mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict)); plist_free(dict); if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { debug_info("%s: Error sending XML plist to device!", __func__); goto leave_unlock; } res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, result)); if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { debug_info("%s: Error receiving response from device!", __func__); } leave_unlock: mobile_image_mounter_unlock(client); return res; }
/** Sends a notification to the device's Notification Proxy. * * notification messages seen so far: * com.apple.itunes-mobdev.syncWillStart * com.apple.itunes-mobdev.syncDidStart * * @param client The client to send to * @param notification The notification message to send */ np_error_t np_post_notification(np_client_t client, const char *notification) { if (!client || !notification) { return NP_E_INVALID_ARG; } np_lock(client); plist_t dict = plist_new_dict(); plist_dict_insert_item(dict,"Command", plist_new_string("PostNotification")); plist_dict_insert_item(dict,"Name", plist_new_string(notification)); np_error_t res = np_plist_send(client, dict); plist_free(dict); dict = plist_new_dict(); plist_dict_insert_item(dict,"Command", plist_new_string("Shutdown")); res = np_plist_send(client, dict); plist_free(dict); if (res != NP_E_SUCCESS) { log_debug_msg("%s: Error sending XML plist to device!\n", __func__); } np_unlock(client); return res; }
LIBIMOBILEDEVICE_API mobilebackup2_error_t mobilebackup2_send_request(mobilebackup2_client_t client, const char *request, const char *target_identifier, const char *source_identifier, plist_t options) { if (!client || !client->parent || !request || !target_identifier) return MOBILEBACKUP2_E_INVALID_ARG; plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "TargetIdentifier", plist_new_string(target_identifier)); if (source_identifier) { plist_dict_set_item(dict, "SourceIdentifier", plist_new_string(source_identifier)); } if (options) { plist_dict_set_item(dict, "Options", plist_copy(options)); } if (!strcmp(request, "Unback") && options) { plist_t node = plist_dict_get_item(options, "Password"); if (node) { plist_dict_set_item(dict, "Password", plist_copy(node)); } } if (!strcmp(request, "EnableCloudBackup") && options) { plist_t node = plist_dict_get_item(options, "CloudBackupState"); if (node) { plist_dict_set_item(dict, "CloudBackupState", plist_copy(node)); } } mobilebackup2_error_t err = mobilebackup2_send_message(client, request, dict); plist_free(dict); return err; }
/** * Request a backup from the connected device. * * @param client The connected MobileBackup client to use. * @param backup_manifest The backup manifest, a plist_t of type PLIST_DICT * containing the backup state of the last backup. For a first-time backup * set this parameter to NULL. * @param base_path The base path on the device to use for the backup * operation, usually "/". * @param proto_version A string denoting the version of the backup protocol * to use. Latest known version is "1.6" * * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if * one of the parameters is invalid, MOBILEBACKUP_E_PLIST_ERROR if * backup_manifest is not of type PLIST_DICT, MOBILEBACKUP_E_MUX_ERROR * if a communication error occurs, MOBILEBACKUP_E_REPLY_NOT_OK */ mobilebackup_error_t mobilebackup_request_backup(mobilebackup_client_t client, plist_t backup_manifest, const char *base_path, const char *proto_version) { if (!client || !client->parent || !base_path || !proto_version) return MOBILEBACKUP_E_INVALID_ARG; if (backup_manifest && (plist_get_node_type(backup_manifest) != PLIST_DICT)) return MOBILEBACKUP_E_PLIST_ERROR; mobilebackup_error_t err; /* construct request plist */ plist_t dict = plist_new_dict(); if (backup_manifest) plist_dict_insert_item(dict, "BackupManifestKey", plist_copy(backup_manifest)); plist_dict_insert_item(dict, "BackupComputerBasePathKey", plist_new_string(base_path)); plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("BackupMessageBackupRequest")); plist_dict_insert_item(dict, "BackupProtocolVersion", plist_new_string(proto_version)); /* send request */ err = mobilebackup_send_message(client, NULL, dict); plist_free(dict); dict = NULL; if (err != MOBILEBACKUP_E_SUCCESS) { debug_info("ERROR: Could not send backup request message (%d)!", err); goto leave; } /* now receive and hopefully get a BackupMessageBackupReplyOK */ err = mobilebackup_receive_message(client, "BackupMessageBackupReplyOK", &dict); if (err != MOBILEBACKUP_E_SUCCESS) { debug_info("ERROR: Could not receive BackupReplyOK message (%d)!", err); goto leave; } plist_t node = plist_dict_get_item(dict, "BackupProtocolVersion"); if (node) { char *str = NULL; plist_get_string_val(node, &str); if (str) { if (strcmp(str, proto_version) != 0) { err = MOBILEBACKUP_E_BAD_VERSION; } free(str); } } if (err != MOBILEBACKUP_E_SUCCESS) goto leave; /* BackupMessageBackupReplyOK received, send it back */ err = mobilebackup_send_message(client, NULL, dict); if (err != MOBILEBACKUP_E_SUCCESS) { debug_info("ERROR: Could not send BackupReplyOK ACK (%d)", err); } leave: if (dict) plist_free(dict); return err; }
LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_value(lockdownd_client_t client, const char *domain, const char *key, plist_t *value) { if (!client) return LOCKDOWN_E_INVALID_ARG; plist_t dict = NULL; lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; /* setup request plist */ dict = plist_new_dict(); plist_dict_add_label(dict, client->label); if (domain) { plist_dict_set_item(dict,"Domain", plist_new_string(domain)); } if (key) { plist_dict_set_item(dict,"Key", plist_new_string(key)); } plist_dict_set_item(dict,"Request", plist_new_string("GetValue")); /* send to device */ ret = lockdownd_send(client, dict); plist_free(dict); dict = NULL; if (ret != LOCKDOWN_E_SUCCESS) return ret; /* Now get device's answer */ ret = lockdownd_receive(client, &dict); if (ret != LOCKDOWN_E_SUCCESS) return ret; if (lockdown_check_result(dict, "GetValue") == RESULT_SUCCESS) { debug_info("success"); ret = LOCKDOWN_E_SUCCESS; } else { ret = LOCKDOWN_E_UNKNOWN_ERROR; } if (ret != LOCKDOWN_E_SUCCESS) { plist_free(dict); return ret; } plist_t value_node = plist_dict_get_item(dict, "Value"); if (value_node) { debug_info("has a value"); *value = plist_copy(value_node); } plist_free(dict); return ret; }
/** * Request that a backup should be restored to the connected device. * * @param client The connected MobileBackup client to use. * @param backup_manifest The backup manifest, a plist_t of type PLIST_DICT * containing the backup state to be restored. * @param flags Flags to send with the request. Currently this is a combination * of the following mobilebackup_flags_t: * MB_RESTORE_NOTIFY_SPRINGBOARD - let SpringBoard show a 'Restore' screen * MB_RESTORE_PRESERVE_SETTINGS - do not overwrite any settings * MB_RESTORE_PRESERVE_CAMERA_ROLL - preserve the photos of the camera roll * @param proto_version A string denoting the version of the backup protocol * to use. Latest known version is "1.6". Ideally this value should be * extracted from the given manifest plist. * * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if * one of the parameters is invalid, MOBILEBACKUP_E_PLIST_ERROR if * backup_manifest is not of type PLIST_DICT, MOBILEBACKUP_E_MUX_ERROR * if a communication error occurs, or MOBILEBACKUP_E_REPLY_NOT_OK * if the device did not accept the request. */ mobilebackup_error_t mobilebackup_request_restore(mobilebackup_client_t client, plist_t backup_manifest, mobilebackup_flags_t flags, const char *proto_version) { if (!client || !client->parent || !backup_manifest || !proto_version) return MOBILEBACKUP_E_INVALID_ARG; if (backup_manifest && (plist_get_node_type(backup_manifest) != PLIST_DICT)) return MOBILEBACKUP_E_PLIST_ERROR; mobilebackup_error_t err; /* construct request plist */ plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "BackupManifestKey", plist_copy(backup_manifest)); plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("kBackupMessageRestoreRequest")); plist_dict_insert_item(dict, "BackupProtocolVersion", plist_new_string(proto_version)); /* add flags */ plist_dict_insert_item(dict, "BackupNotifySpringBoard", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_NOTIFY_SPRINGBOARD))); plist_dict_insert_item(dict, "BackupPreserveSettings", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_PRESERVE_SETTINGS))); plist_dict_insert_item(dict, "BackupPreserveCameraRoll", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_PRESERVE_CAMERA_ROLL))); /* send request */ err = mobilebackup_send_message(client, NULL, dict); plist_free(dict); dict = NULL; if (err != MOBILEBACKUP_E_SUCCESS) { debug_info("ERROR: Could not send restore request message (%d)!", err); goto leave; } /* now receive and hopefully get a BackupMessageRestoreReplyOK */ err = mobilebackup_receive_message(client, "BackupMessageRestoreReplyOK", &dict); if (err != MOBILEBACKUP_E_SUCCESS) { debug_info("ERROR: Could not receive RestoreReplyOK message (%d)!", err); goto leave; } plist_t node = plist_dict_get_item(dict, "BackupProtocolVersion"); if (node) { char *str = NULL; plist_get_string_val(node, &str); if (str) { if (strcmp(str, proto_version) != 0) { err = MOBILEBACKUP_E_BAD_VERSION; } free(str); } } leave: if (dict) plist_free(dict); return err; }
LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *session_id) { if (!client) return LOCKDOWN_E_INVALID_ARG; if (!session_id) { debug_info("no session_id given, cannot stop session"); return LOCKDOWN_E_INVALID_ARG; } lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("StopSession")); plist_dict_set_item(dict,"SessionID", plist_new_string(session_id)); debug_info("stopping session %s", session_id); ret = lockdownd_send(client, dict); plist_free(dict); dict = NULL; ret = lockdownd_receive(client, &dict); if (!dict) { debug_info("LOCKDOWN_E_PLIST_ERROR"); return LOCKDOWN_E_PLIST_ERROR; } ret = LOCKDOWN_E_UNKNOWN_ERROR; if (lockdown_check_result(dict, "StopSession") == RESULT_SUCCESS) { debug_info("success"); ret = LOCKDOWN_E_SUCCESS; } plist_free(dict); dict = NULL; if (client->session_id) { free(client->session_id); client->session_id = NULL; } if (client->ssl_enabled) { property_list_service_disable_ssl(client->parent); client->ssl_enabled = 0; } return ret; }
static void mobilesync_disconnect(mobilesync_client_t client) { if (!client) return; plist_t array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessageDisconnect")); plist_array_append_item(array, plist_new_string("All done, thanks for the memories")); mobilesync_send(client, array); plist_free(array); array = NULL; }
/** * Sends a notification to the device's notification_proxy. * * @param client The client to send to * @param notification The notification message to send * * @return NP_E_SUCCESS on success, or an error returned by np_plist_send */ np_error_t np_post_notification(np_client_t client, const char *notification) { if (!client || !notification) { return NP_E_INVALID_ARG; } np_lock(client); plist_t dict = plist_new_dict(); plist_dict_set_item(dict,"Command", plist_new_string("PostNotification")); plist_dict_set_item(dict,"Name", plist_new_string(notification)); np_error_t res = np_error(property_list_service_send_xml_plist(client->parent, dict)); plist_free(dict); dict = plist_new_dict(); plist_dict_set_item(dict,"Command", plist_new_string("Shutdown")); res = np_error(property_list_service_send_xml_plist(client->parent, dict)); plist_free(dict); if (res != NP_E_SUCCESS) { debug_info("Error sending XML plist to device!"); } // try to read an answer, we just ignore errors here dict = NULL; property_list_service_receive_plist(client->parent, &dict); if (dict) { #ifndef STRIP_DEBUG_CODE char *cmd_value = NULL; plist_t cmd_value_node = plist_dict_get_item(dict, "Command"); if (plist_get_node_type(cmd_value_node) == PLIST_STRING) { plist_get_string_val(cmd_value_node, &cmd_value); } if (cmd_value && !strcmp(cmd_value, "ProxyDeath")) { // this is the expected answer } else { debug_plist(dict); } if (cmd_value) { free(cmd_value); } #endif plist_free(dict); } np_unlock(client); return res; }
static plist_t create_device_attached_plist(struct device_info *dev) { plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "MessageType", plist_new_string("Attached")); plist_dict_set_item(dict, "DeviceID", plist_new_uint(dev->id)); plist_t props = plist_new_dict(); plist_dict_set_item(props, "ConnectionSpeed", plist_new_uint(dev->speed)); plist_dict_set_item(props, "ConnectionType", plist_new_string("USB")); plist_dict_set_item(props, "DeviceID", plist_new_uint(dev->id)); plist_dict_set_item(props, "LocationID", plist_new_uint(dev->location)); plist_dict_set_item(props, "ProductID", plist_new_uint(dev->pid)); plist_dict_set_item(props, "SerialNumber", plist_new_string(dev->serial)); plist_dict_set_item(dict, "Properties", props); return dict; }
/** * Returns a new plist from the supplied lockdownd pair record. The caller is * responsible for freeing the plist. * * @param pair_record The pair record to create a plist from. * * @return A pair record plist from the device, NULL if pair_record is not set */ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_record) { if (!pair_record) return NULL; /* setup request plist */ plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "DeviceCertificate", plist_new_data(pair_record->device_certificate, strlen(pair_record->device_certificate))); plist_dict_set_item(dict, "HostCertificate", plist_new_data(pair_record->host_certificate, strlen(pair_record->host_certificate))); plist_dict_set_item(dict, "HostID", plist_new_string(pair_record->host_id)); plist_dict_set_item(dict, "RootCertificate", plist_new_data(pair_record->root_certificate, strlen(pair_record->root_certificate))); plist_dict_set_item(dict, "SystemBUID", plist_new_string(pair_record->system_buid)); return dict; }
static plist_t create_process_changes_message(const char *data_class, plist_t entities, uint8_t more_changes, plist_t actions) { plist_t msg = plist_new_array(); plist_array_append_item(msg, plist_new_string("SDMessageProcessChanges")); plist_array_append_item(msg, plist_new_string(data_class)); plist_array_append_item(msg, plist_copy(entities)); plist_array_append_item(msg, plist_new_bool(more_changes)); if (actions) plist_array_append_item(msg, plist_copy(actions)); else plist_array_append_item(msg, plist_new_string(EMPTY_PARAMETER_STRING)); return msg; }
/** * Puts the device into deep sleep mode and disconnects from host. * * @param client The diagnostics_relay client * * @return DIAGNOSTICS_RELAY_E_SUCCESS on success, * DIAGNOSTICS_RELAY_E_INVALID_ARG when client is NULL, * DIAGNOSTICS_RELAY_E_PLIST_ERROR if the device did not acknowledge the * request */ diagnostics_relay_error_t diagnostics_relay_sleep(diagnostics_relay_client_t client) { if (!client) return DIAGNOSTICS_RELAY_E_INVALID_ARG; diagnostics_relay_error_t ret = DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict,"Request", plist_new_string("Sleep")); ret = diagnostics_relay_send(client, dict); plist_free(dict); dict = NULL; ret = diagnostics_relay_receive(client, &dict); if (!dict) { return DIAGNOSTICS_RELAY_E_PLIST_ERROR; } int check = diagnostics_relay_check_result(dict); if (check == RESULT_SUCCESS) { ret = DIAGNOSTICS_RELAY_E_SUCCESS; } else if (check == RESULT_UNKNOWN_REQUEST) { ret = DIAGNOSTICS_RELAY_E_UNKNOWN_REQUEST; } else { ret = DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR; } plist_free(dict); return ret; }
/** * Hangs up the connection to the mobile_image_mounter service. * This functions has to be called before freeing up a mobile_image_mounter * instance. If not, errors appear in the device's syslog. * * @param client The client to hang up * * @return MOBILE_IMAGE_MOUNTER_E_SUCCESS on success, * MOBILE_IMAGE_MOUNTER_E_INVALID_ARG if client is invalid, * or another error code otherwise. */ mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client) { if (!client) { return MOBILE_IMAGE_MOUNTER_E_INVALID_ARG; } mobile_image_mounter_lock(client); plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "Command", plist_new_string("Hangup")); mobile_image_mounter_error_t res = mobile_image_mounter_error(property_list_service_send_xml_plist(client->parent, dict)); plist_free(dict); if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { debug_info("%s: Error sending XML plist to device!", __func__); goto leave_unlock; } dict = NULL; res = mobile_image_mounter_error(property_list_service_receive_plist(client->parent, &dict)); if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { debug_info("%s: Error receiving response from device!", __func__); } if (dict) { debug_plist(dict); plist_free(dict); } leave_unlock: mobile_image_mounter_unlock(client); return res; }
/** * Get the home screen wallpaper as PNG data. * * @param client The connected sbservices client to use. * @param pngdata Pointer that will point to a newly allocated buffer * containing the PNG data upon successful return. It is up to the caller * to free the memory. * @param pngsize Pointer to a uint64_t that will be set to the size of the * buffer pngdata points to upon successful return. * * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when * client or pngdata are invalid, or an SBSERVICES_E_* error * code otherwise. */ sbservices_error_t sbservices_get_home_screen_wallpaper_pngdata(sbservices_client_t client, char **pngdata, uint64_t *pngsize) { if (!client || !client->parent || !pngdata) return SBSERVICES_E_INVALID_ARG; sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "command", plist_new_string("getHomeScreenWallpaperPNGData")); sbs_lock(client); res = sbservices_error(property_list_service_send_binary_plist(client->parent, dict)); if (res != SBSERVICES_E_SUCCESS) { debug_info("could not send plist, error %d", res); goto leave_unlock; } plist_free(dict); dict = NULL; res = sbservices_error(property_list_service_receive_plist(client->parent, &dict)); if (res == SBSERVICES_E_SUCCESS) { plist_t node = plist_dict_get_item(dict, "pngData"); if (node) { plist_get_data_val(node, pngdata, pngsize); } } leave_unlock: if (dict) { plist_free(dict); } sbs_unlock(client); return res; }
/** * Adds a label key with the passed value to a plist dict node. * * @param plist The plist to add the key to * @param label The value for the label key * */ static void plist_dict_add_label(plist_t plist, const char *label) { if (plist && label) { if (plist_get_node_type(plist) == PLIST_DICT) plist_dict_insert_item(plist, "Label", plist_new_string(label)); } }
/** * Performs a disconnect with the connected device link service client. * * @param client The device link service client to disconnect. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG if client is NULL, * or DEVICE_LINK_SERVICE_E_MUX_ERROR when there's an error when sending * the the disconnect message. */ device_link_service_error_t device_link_service_disconnect(device_link_service_client_t client) { if (!client) return DEVICE_LINK_SERVICE_E_INVALID_ARG; plist_t array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessageDisconnect")); plist_array_append_item(array, plist_new_string("All done, thanks for the memories")); device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { err = DEVICE_LINK_SERVICE_E_MUX_ERROR; } plist_free(array); return err; }
LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client) { if (!client) return LOCKDOWN_E_INVALID_ARG; lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("Goodbye")); debug_info("called"); ret = lockdownd_send(client, dict); plist_free(dict); dict = NULL; ret = lockdownd_receive(client, &dict); if (!dict) { debug_info("did not get goodbye response back"); return LOCKDOWN_E_PLIST_ERROR; } if (lockdown_check_result(dict, "Goodbye") == RESULT_SUCCESS) { debug_info("success"); ret = LOCKDOWN_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; }
LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_enter_recovery(lockdownd_client_t client) { if (!client) return LOCKDOWN_E_INVALID_ARG; lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("EnterRecovery")); debug_info("telling device to enter recovery mode"); ret = lockdownd_send(client, dict); plist_free(dict); dict = NULL; ret = lockdownd_receive(client, &dict); if (lockdown_check_result(dict, "EnterRecovery") == RESULT_SUCCESS) { debug_info("success"); ret = LOCKDOWN_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; }
LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_deactivate(lockdownd_client_t client) { if (!client) return LOCKDOWN_E_INVALID_ARG; if (!client->session_id) return LOCKDOWN_E_NO_RUNNING_SESSION; lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("Deactivate")); ret = lockdownd_send(client, dict); plist_free(dict); dict = NULL; ret = lockdownd_receive(client, &dict); if (!dict) { debug_info("LOCKDOWN_E_PLIST_ERROR"); return LOCKDOWN_E_PLIST_ERROR; } ret = LOCKDOWN_E_UNKNOWN_ERROR; if (lockdown_check_result(dict, "Deactivate") == RESULT_SUCCESS) { debug_info("success"); ret = LOCKDOWN_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; }
/** * Sends the Goodbye request to restored signaling the end of communication. * * @param client The restore client * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL, * RESTORE_E_PLIST_ERROR if the device did not acknowledge the request */ restored_error_t restored_goodbye(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("Goodbye")); debug_info("called"); ret = restored_send(client, dict); plist_free(dict); dict = NULL; ret = restored_receive(client, &dict); if (!dict) { debug_info("did not get goodbye response back"); return RESTORE_E_PLIST_ERROR; } if (restored_check_result(dict) == RESULT_SUCCESS) { debug_info("success"); ret = RESTORE_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; }
/** * Requests device to reboot. * * @param client The restored client * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG if a parameter * is NULL */ restored_error_t restored_reboot(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("Reboot")); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; if (RESTORE_E_SUCCESS != ret) return ret; ret = restored_receive(client, &dict); if (RESTORE_E_SUCCESS != ret) return ret; if (!dict) return RESTORE_E_PLIST_ERROR; plist_free(dict); dict = NULL; return ret; }
/** * Sends a DLMessagePing plist. * * @param client The device link service client to use. * @param message String to send as ping message. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG if client or message is invalid, * or DEVICE_LINK_SERVICE_E_MUX_ERROR if the DLMessagePing plist could * not be sent. */ device_link_service_error_t device_link_service_send_ping(device_link_service_client_t client, const char *message) { if (!client || !client->parent || !message) return DEVICE_LINK_SERVICE_E_INVALID_ARG; plist_t array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessagePing")); plist_array_append_item(array, plist_new_string(message)); device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { err = DEVICE_LINK_SERVICE_E_MUX_ERROR; } plist_free(array); return err; }
/** * Sends a backup message plist. * * @param client The connected MobileBackup client to use. * @param message The message to send. This will be inserted into the request * plist as value for MessageName. If this parameter is NULL, * the plist passed in the options parameter will be sent directly. * @param options Additional options as PLIST_DICT to add to the request. * The MessageName key with the value passed in the message parameter * will be inserted into this plist before sending it. This parameter * can be NULL if message is not NULL. */ mobilebackup2_error_t mobilebackup2_send_message(mobilebackup2_client_t client, const char *message, plist_t options) { if (!client || !client->parent || (!message && !options)) return MOBILEBACKUP2_E_INVALID_ARG; if (options && (plist_get_node_type(options) != PLIST_DICT)) { return MOBILEBACKUP2_E_INVALID_ARG; } mobilebackup2_error_t err; if (message) { plist_t dict = NULL; if (options) { dict = plist_copy(options); } else { dict = plist_new_dict(); } plist_dict_insert_item(dict, "MessageName", plist_new_string(message)); /* send it as DLMessageProcessMessage */ err = mobilebackup2_error(device_link_service_send_process_message(client->parent, dict)); plist_free(dict); } else { err = mobilebackup2_error(device_link_service_send_process_message(client->parent, options)); } if (err != MOBILEBACKUP2_E_SUCCESS) { debug_info("ERROR: Could not send message '%s' (%d)!", message, err); } return err; }
/** * Sets the icon state of the connected device. * * @param client The connected sbservices client to use. * @param newstate A plist containing the new iconstate. * * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when * client or newstate is NULL, or an SBSERVICES_E_* error code otherwise. */ sbservices_error_t sbservices_set_icon_state(sbservices_client_t client, plist_t newstate) { if (!client || !client->parent || !newstate) return SBSERVICES_E_INVALID_ARG; sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "command", plist_new_string("setIconState")); plist_dict_insert_item(dict, "iconState", plist_copy(newstate)); sbs_lock(client); res = sbservices_error(property_list_service_send_binary_plist(client->parent, dict)); if (res != SBSERVICES_E_SUCCESS) { debug_info("could not send plist, error %d", res); } /* NO RESPONSE */ if (dict) { plist_free(dict); } sbs_unlock(client); return res; }