/**
 * Performs the mobilebackup2 protocol version exchange.
 * 
 * @param client The MobileBackup client to use.
 * @param local_versions An array of supported versions to send to the remote.
 * @param count The number of items in local_versions.
 * @param remote_version Holds the protocol version of the remote on success.
 * 
 * @return MOBILEBACKUP2_E_SUCCESS on success, or a MOBILEBACKUP2_E_* error
 *     code otherwise.
 */
mobilebackup2_error_t mobilebackup2_version_exchange(mobilebackup2_client_t client, double local_versions[], char count, double *remote_version)
{
	int i;

	if (!client || !client->parent)
		return MOBILEBACKUP2_E_INVALID_ARG;

	plist_t dict = plist_new_dict();
	plist_t array = plist_new_array();
	for (i = 0; i < count; i++) {
		plist_array_append_item(array, plist_new_real(local_versions[i]));
	}
	plist_dict_insert_item(dict, "SupportedProtocolVersions", array);

	mobilebackup2_error_t err = mobilebackup2_send_message(client, "Hello", dict);
	plist_free(dict);

	if (err != MOBILEBACKUP2_E_SUCCESS)
		goto leave;

	dict = NULL;
	err = internal_mobilebackup2_receive_message(client, "Response", &dict);
	if (err != MOBILEBACKUP2_E_SUCCESS)
		goto leave;

	/* check if we received an error */
	plist_t node = plist_dict_get_item(dict, "ErrorCode");
	if (!node || (plist_get_node_type(node) != PLIST_UINT)) {
		err = MOBILEBACKUP2_E_PLIST_ERROR;
		goto leave;
	}

	uint64_t val = 0;
	plist_get_uint_val(node, &val);
	if (val != 0) {
		if (val == 1) {
			err = MOBILEBACKUP2_E_NO_COMMON_VERSION;
		} else {
			err = MOBILEBACKUP2_E_REPLY_NOT_OK;
		}
		goto leave;
	}

	/* retrieve the protocol version of the device */
	node = plist_dict_get_item(dict, "ProtocolVersion");
	if (!node || (plist_get_node_type(node) != PLIST_REAL)) {
		err = MOBILEBACKUP2_E_PLIST_ERROR;
		goto leave;
	}

	*remote_version = 0.0;
	plist_get_real_val(node, remote_version);
leave:
	if (dict)
		plist_free(dict);
	return err;
}
Exemplo n.º 2
0
Node::Node(plist_type type, Node* parent) : _parent(parent)
{
    _node = NULL;

    switch (type)
    {
    case PLIST_BOOLEAN:
        _node = plist_new_bool(0);
        break;
    case PLIST_UINT:
        _node = plist_new_uint(0);
        break;
    case PLIST_REAL:
        _node = plist_new_real(0.);
        break;
    case PLIST_STRING:
        _node = plist_new_string("");
        break;
    case PLIST_KEY:
        _node = plist_new_string("");
        plist_set_key_val(_node, "");
        break;
    case PLIST_UID:
	_node = plist_new_uid(0);
	break;
    case PLIST_DATA:
        _node = plist_new_data(NULL,0);
        break;
    case PLIST_DATE:
        _node = plist_new_date(0,0);
        break;
    case PLIST_ARRAY:
        _node = plist_new_array();
        break;
    case PLIST_DICT:
        _node = plist_new_dict();
        break;
    case PLIST_NONE:
    default:
        break;
    }
}
Exemplo n.º 3
0
int main(int argc, char *argv[])
{
	lockdownd_client_t client = NULL;
	lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
	idevice_t device = NULL;
	idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
	int i;
	const char* udid = NULL;
	time_t setdate = 0;
	plist_t node = NULL;
	int node_type = -1;
	uint64_t datetime = 0;
	time_t rawtime;
	struct tm * tmp;
	char const *format = NULL;
	char buffer[80];
	int result = 0;

	/* parse cmdline args */
	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
			idevice_set_debug_level(1);
			continue;
		}
		else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) != 40)) {
				print_usage(argc, argv);
				return 0;
			}
			udid = argv[i];
			continue;
		}
		else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--set")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) <= 1)) {
				print_usage(argc, argv);
				return 0;
			}
			setdate = atoi(argv[i]);
			if (setdate == 0) {
				printf("ERROR: Invalid timestamp value.\n");
				print_usage(argc, argv);
				return 0;
			}
			continue;
		}
		else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--sync")) {
			i++;
			/* get current time */
			setdate = time(NULL);
			/* convert it to local time which sets timezone/daylight variables */
			tmp = localtime(&setdate);
			/* recalculate to make it UTC */
			setdate = mktime(tmp);
			continue;
		}
		else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
			print_usage(argc, argv);
			return 0;
		}
		else {
			print_usage(argc, argv);
			return 0;
		}
	}

	/* determine a date format */
	if (!format) {
		format = DATE_FMT_LANGINFO ();
		if (!*format) {
			format = "%a %b %e %H:%M:%S %Z %Y";
		}
	}

	ret = idevice_new(&device, udid);
	if (ret != IDEVICE_E_SUCCESS) {
		if (udid) {
			printf("No device found with udid %s, is it plugged in?\n", udid);
		} else {
			printf("No device found, is it plugged in?\n");
		}
		return -1;
	}

	if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, "idevicedate"))) {
		fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ldret);
		result = -1;
		goto cleanup;
	}

	if(lockdownd_get_value(client, NULL, "TimeIntervalSince1970", &node) != LOCKDOWN_E_SUCCESS) {
		fprintf(stderr, "ERROR: Unable to retrieve 'TimeIntervalSince1970' node from device.\n");
		result = -1;
		goto cleanup;
	}

	if (node == NULL) {
		fprintf(stderr, "ERROR: Empty node for 'TimeIntervalSince1970' received.\n");
		result = -1;
		goto cleanup;
	}

	node_type = plist_get_node_type(node);

	/* get or set? */
	if (setdate == 0) {
		/* get time value from device */
		switch (node_type) {
			case PLIST_UINT:
				plist_get_uint_val(node, &datetime);
				break;
			case PLIST_REAL:
				{
					double rv = 0;
					plist_get_real_val(node, &rv);
					datetime = rv;
				}
				break;
			default:
				fprintf(stderr, "ERROR: Unexpected node type for 'TimeIntervalSince1970'\n");
				break;
		}
		plist_free(node);
		node = NULL;

		/* date/time calculations */
		rawtime = (time_t)datetime;
		tmp = localtime(&rawtime);

		/* finally we format and print the current date */
		strftime(buffer, 80, format, tmp);
		puts(buffer);
	} else {
		datetime = setdate;

		plist_free(node);
		node = NULL;

		switch (node_type) {
			case PLIST_UINT:
				node = plist_new_uint(datetime);
				break;
			case PLIST_REAL:
				node = plist_new_real((double)datetime);
				break;
			default:
				fprintf(stderr, "ERROR: Unexpected node type for 'TimeIntervalSince1970'\n");
				break;
		}

		if(lockdownd_set_value(client, NULL, "TimeIntervalSince1970", node) == LOCKDOWN_E_SUCCESS) {
			tmp = localtime(&setdate);
			strftime(buffer, 80, format, tmp);
			puts(buffer);
		} else {
			printf("ERROR: Failed to set date on device.\n");
		}
		node = NULL;
	}

cleanup:
	if (client)
		lockdownd_client_free(client);

	if (device)
		idevice_free(device);

	return result;
}