summaryrefslogtreecommitdiffstats
path: root/src/mobilesync.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mobilesync.c')
-rw-r--r--src/mobilesync.c286
1 files changed, 41 insertions, 245 deletions
diff --git a/src/mobilesync.c b/src/mobilesync.c
index ee9af5f..9b81a49 100644
--- a/src/mobilesync.c
+++ b/src/mobilesync.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * mobilesync.c 2 * mobilesync.c
3 * Contains functions for the built-in MobileSync client. 3 * Contains functions for the built-in MobileSync client.
4 * 4 *
5 * Copyright (c) 2010 Bryan Forbes All Rights Reserved. 5 * Copyright (c) 2010 Bryan Forbes All Rights Reserved.
6 * Copyright (c) 2009 Jonathan Beck All Rights Reserved. 6 * Copyright (c) 2009 Jonathan Beck All Rights Reserved.
7 * 7 *
@@ -9,31 +9,32 @@
9 * modify it under the terms of the GNU Lesser General Public 9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version. 11 * version 2.1 of the License, or (at your option) any later version.
12 * 12 *
13 * This library is distributed in the hope that it will be useful, 13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details. 16 * Lesser General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU Lesser General Public 18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software 19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */ 21 */
22 22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
23#define _GNU_SOURCE 1 26#define _GNU_SOURCE 1
24#define __USE_GNU 1 27#define __USE_GNU 1
25
26#include <plist/plist.h> 28#include <plist/plist.h>
27#include <string.h> 29#include <string.h>
28#include <stdlib.h> 30#include <stdlib.h>
29#include <stdio.h> 31#include <stdio.h>
30#include <glib.h>
31 32
32#include "mobilesync.h" 33#include "mobilesync.h"
33#include "device_link_service.h" 34#include "device_link_service.h"
34#include "debug.h" 35#include "common/debug.h"
35 36
36#define MSYNC_VERSION_INT1 100 37#define MSYNC_VERSION_INT1 400
37#define MSYNC_VERSION_INT2 100 38#define MSYNC_VERSION_INT2 100
38 39
39#define EMPTY_PARAMETER_STRING "___EmptyParameterString___" 40#define EMPTY_PARAMETER_STRING "___EmptyParameterString___"
@@ -58,6 +59,10 @@ static mobilesync_error_t mobilesync_error(device_link_service_error_t err)
58 return MOBILESYNC_E_PLIST_ERROR; 59 return MOBILESYNC_E_PLIST_ERROR;
59 case DEVICE_LINK_SERVICE_E_MUX_ERROR: 60 case DEVICE_LINK_SERVICE_E_MUX_ERROR:
60 return MOBILESYNC_E_MUX_ERROR; 61 return MOBILESYNC_E_MUX_ERROR;
62 case DEVICE_LINK_SERVICE_E_SSL_ERROR:
63 return MOBILESYNC_E_SSL_ERROR;
64 case DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT:
65 return MOBILESYNC_E_RECEIVE_TIMEOUT;
61 case DEVICE_LINK_SERVICE_E_BAD_VERSION: 66 case DEVICE_LINK_SERVICE_E_BAD_VERSION:
62 return MOBILESYNC_E_BAD_VERSION; 67 return MOBILESYNC_E_BAD_VERSION;
63 default: 68 default:
@@ -66,27 +71,14 @@ static mobilesync_error_t mobilesync_error(device_link_service_error_t err)
66 return MOBILESYNC_E_UNKNOWN_ERROR; 71 return MOBILESYNC_E_UNKNOWN_ERROR;
67} 72}
68 73
69/** 74mobilesync_error_t mobilesync_client_new(idevice_t device, lockdownd_service_descriptor_t service,
70 * Connects to the mobilesync service on the specified device.
71 *
72 * @param device The device to connect to.
73 * @param port Destination port (usually given by lockdownd_start_service()).
74 * @param client Pointer that will be set to a newly allocated
75 * #mobilesync_client_t upon successful return.
76 *
77 * @retval MOBILESYNC_E_SUCCESS on success
78 * @retval MOBILESYNC_E_INVALID_ARG if one or more parameters are invalid
79 * @retval DEVICE_LINK_SERVICE_E_BAD_VERSION if the mobilesync version on
80 * the device is newer.
81 */
82mobilesync_error_t mobilesync_client_new(idevice_t device, uint16_t port,
83 mobilesync_client_t * client) 75 mobilesync_client_t * client)
84{ 76{
85 if (!device || port == 0 || !client || *client) 77 if (!device || !service || service->port == 0 || !client || *client)
86 return MOBILESYNC_E_INVALID_ARG; 78 return MOBILESYNC_E_INVALID_ARG;
87 79
88 device_link_service_client_t dlclient = NULL; 80 device_link_service_client_t dlclient = NULL;
89 mobilesync_error_t ret = mobilesync_error(device_link_service_client_new(device, port, &dlclient)); 81 mobilesync_error_t ret = mobilesync_error(device_link_service_client_new(device, service, &dlclient));
90 if (ret != MOBILESYNC_E_SUCCESS) { 82 if (ret != MOBILESYNC_E_SUCCESS) {
91 return ret; 83 return ret;
92 } 84 }
@@ -109,33 +101,23 @@ mobilesync_error_t mobilesync_client_new(idevice_t device, uint16_t port,
109 return ret; 101 return ret;
110} 102}
111 103
112/** 104mobilesync_error_t mobilesync_client_start_service(idevice_t device, mobilesync_client_t * client, const char* label)
113 * Disconnects a mobilesync client from the device and frees up the 105{
114 * mobilesync client data. 106 mobilesync_error_t err = MOBILESYNC_E_UNKNOWN_ERROR;
115 * 107 service_client_factory_start_service(device, MOBILESYNC_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(mobilesync_client_new), &err);
116 * @param client The mobilesync client to disconnect and free. 108 return err;
117 * 109}
118 * @retval MOBILESYNC_E_SUCCESS on success 110
119 * @retval MOBILESYNC_E_INVALID_ARG if \a client is NULL.
120 */
121mobilesync_error_t mobilesync_client_free(mobilesync_client_t client) 111mobilesync_error_t mobilesync_client_free(mobilesync_client_t client)
122{ 112{
123 if (!client) 113 if (!client)
124 return MOBILESYNC_E_INVALID_ARG; 114 return MOBILESYNC_E_INVALID_ARG;
125 device_link_service_disconnect(client->parent); 115 device_link_service_disconnect(client->parent, "All done, thanks for the memories");
126 mobilesync_error_t err = mobilesync_error(device_link_service_client_free(client->parent)); 116 mobilesync_error_t err = mobilesync_error(device_link_service_client_free(client->parent));
127 free(client); 117 free(client);
128 return err; 118 return err;
129} 119}
130 120
131/**
132 * Polls the device for mobilesync data.
133 *
134 * @param client The mobilesync client
135 * @param plist A pointer to the location where the plist should be stored
136 *
137 * @return an error code
138 */
139mobilesync_error_t mobilesync_receive(mobilesync_client_t client, plist_t * plist) 121mobilesync_error_t mobilesync_receive(mobilesync_client_t client, plist_t * plist)
140{ 122{
141 if (!client) 123 if (!client)
@@ -144,17 +126,6 @@ mobilesync_error_t mobilesync_receive(mobilesync_client_t client, plist_t * plis
144 return ret; 126 return ret;
145} 127}
146 128
147/**
148 * Sends mobilesync data to the device
149 *
150 * @note This function is low-level and should only be used if you need to send
151 * a new type of message.
152 *
153 * @param client The mobilesync client
154 * @param plist The location of the plist to send
155 *
156 * @return an error code
157 */
158mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist) 129mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist)
159{ 130{
160 if (!client || !plist) 131 if (!client || !plist)
@@ -162,26 +133,7 @@ mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist)
162 return mobilesync_error(device_link_service_send(client->parent, plist)); 133 return mobilesync_error(device_link_service_send(client->parent, plist));
163} 134}
164 135
165/** 136mobilesync_error_t mobilesync_start(mobilesync_client_t client, const char *data_class, mobilesync_anchors_t anchors, uint64_t computer_data_class_version, mobilesync_sync_type_t *sync_type, uint64_t *device_data_class_version, char** error_description)
166 * Requests starting synchronization of a data class with the device
167 *
168 * @param client The mobilesync client
169 * @param data_class The data class identifier to sync
170 * @param anchors The anchors required to exchange with the device. The anchors
171 * allow the device to tell if the synchronization information on the computer
172 * and device are consistent to determine what sync type is required.
173 * @param computer_data_class_version The version of the data class storage on the computer
174 * @param sync_type A pointer to store the sync type reported by the device_anchor
175 * @param device_data_class_version The version of the data class storage on the device
176 *
177 * @retval MOBILESYNC_E_SUCCESS on success
178 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
179 * @retval MOBILESYNC_E_PLIST_ERROR if the received plist is not of valid form
180 * @retval MOBILESYNC_E_SYNC_REFUSED if the device refused to sync
181 * @retval MOBILESYNC_E_CANCELLED if the device explicitly cancelled the
182 * sync request
183 */
184mobilesync_error_t mobilesync_start(mobilesync_client_t client, const char *data_class, mobilesync_anchors_t anchors, uint64_t computer_data_class_version, mobilesync_sync_type_t *sync_type, uint64_t *device_data_class_version)
185{ 137{
186 if (!client || client->data_class || !data_class || 138 if (!client || client->data_class || !data_class ||
187 !anchors || !anchors->computer_anchor) { 139 !anchors || !anchors->computer_anchor) {
@@ -194,6 +146,8 @@ mobilesync_error_t mobilesync_start(mobilesync_client_t client, const char *data
194 plist_t msg = NULL; 146 plist_t msg = NULL;
195 plist_t response_type_node = NULL; 147 plist_t response_type_node = NULL;
196 148
149 *error_description = NULL;
150
197 msg = plist_new_array(); 151 msg = plist_new_array();
198 plist_array_append_item(msg, plist_new_string("SDMessageSyncDataClassWithDevice")); 152 plist_array_append_item(msg, plist_new_string("SDMessageSyncDataClassWithDevice"));
199 plist_array_append_item(msg, plist_new_string(data_class)); 153 plist_array_append_item(msg, plist_new_string(data_class));
@@ -233,23 +187,19 @@ mobilesync_error_t mobilesync_start(mobilesync_client_t client, const char *data
233 goto out; 187 goto out;
234 } 188 }
235 189
190 // did the device refuse to sync with the computer?
236 if (!strcmp(response_type, "SDMessageRefuseToSyncDataClassWithComputer")) { 191 if (!strcmp(response_type, "SDMessageRefuseToSyncDataClassWithComputer")) {
237 char *reason = NULL;
238 err = MOBILESYNC_E_SYNC_REFUSED; 192 err = MOBILESYNC_E_SYNC_REFUSED;
239 plist_get_string_val(plist_array_get_item(msg, 2), &reason); 193 plist_get_string_val(plist_array_get_item(msg, 2), error_description);
240 debug_info("Device refused sync: %s", reason); 194 debug_info("Device refused sync: %s", error_description);
241 free(reason);
242 reason = NULL;
243 goto out; 195 goto out;
244 } 196 }
245 197
198 // did the device cancel the session?
246 if (!strcmp(response_type, "SDMessageCancelSession")) { 199 if (!strcmp(response_type, "SDMessageCancelSession")) {
247 char *reason = NULL;
248 err = MOBILESYNC_E_CANCELLED; 200 err = MOBILESYNC_E_CANCELLED;
249 plist_get_string_val(plist_array_get_item(msg, 2), &reason); 201 plist_get_string_val(plist_array_get_item(msg, 2), error_description);
250 debug_info("Device cancelled: %s", reason); 202 debug_info("Device cancelled: %s", error_description);
251 free(reason);
252 reason = NULL;
253 goto out; 203 goto out;
254 } 204 }
255 205
@@ -309,17 +259,6 @@ mobilesync_error_t mobilesync_start(mobilesync_client_t client, const char *data
309 return err; 259 return err;
310} 260}
311 261
312/**
313 * Finish a synchronization session of a data class on the device.
314 * A session must have previously been started using mobilesync_start().
315 *
316 * @param client The mobilesync client
317 *
318 * @retval MOBILESYNC_E_SUCCESS on success
319 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
320 * @retval MOBILESYNC_E_PLIST_ERROR if the received plist is not of valid
321 * form
322 */
323mobilesync_error_t mobilesync_finish(mobilesync_client_t client) 262mobilesync_error_t mobilesync_finish(mobilesync_client_t client)
324{ 263{
325 if (!client || !client->data_class) { 264 if (!client || !client->data_class) {
@@ -395,7 +334,7 @@ static mobilesync_error_t mobilesync_get_records(mobilesync_client_t client, con
395 msg = plist_new_array(); 334 msg = plist_new_array();
396 plist_array_append_item(msg, plist_new_string(operation)); 335 plist_array_append_item(msg, plist_new_string(operation));
397 plist_array_append_item(msg, plist_new_string(client->data_class)); 336 plist_array_append_item(msg, plist_new_string(client->data_class));
398 337
399 err = mobilesync_send(client, msg); 338 err = mobilesync_send(client, msg);
400 339
401 if (msg) { 340 if (msg) {
@@ -405,49 +344,16 @@ static mobilesync_error_t mobilesync_get_records(mobilesync_client_t client, con
405 return err; 344 return err;
406} 345}
407 346
408/**
409 * Requests to receive all records of the currently set data class from the device.
410 * The actually changes are retrieved using mobilesync_receive_changes() after this
411 * request has been successful.
412 *
413 * @param client The mobilesync client
414 *
415 * @retval MOBILESYNC_E_SUCCESS on success
416 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
417 */
418mobilesync_error_t mobilesync_get_all_records_from_device(mobilesync_client_t client) 347mobilesync_error_t mobilesync_get_all_records_from_device(mobilesync_client_t client)
419{ 348{
420 return mobilesync_get_records(client, "SDMessageGetAllRecordsFromDevice"); 349 return mobilesync_get_records(client, "SDMessageGetAllRecordsFromDevice");
421} 350}
422 351
423/**
424 * Requests to receive only changed records of the currently set data class from the device.
425 * The actually changes are retrieved using mobilesync_receive_changes() after this
426 * request has been successful.
427 *
428 * @param client The mobilesync client
429 *
430 * @retval MOBILESYNC_E_SUCCESS on success
431 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
432 */
433mobilesync_error_t mobilesync_get_changes_from_device(mobilesync_client_t client) 352mobilesync_error_t mobilesync_get_changes_from_device(mobilesync_client_t client)
434{ 353{
435 return mobilesync_get_records(client, "SDMessageGetChangesFromDevice"); 354 return mobilesync_get_records(client, "SDMessageGetChangesFromDevice");
436} 355}
437 356
438/**
439 * Receives changed entitites of the currently set data class from the device
440 *
441 * @param client The mobilesync client
442 * @param entities A pointer to store the changed entity records as a PLIST_DICT
443 * @param is_last_record A pointer to store a flag indicating if this submission is the last one
444 * @param actions A pointer to additional flags the device is sending or NULL to ignore
445 *
446 * @retval MOBILESYNC_E_SUCCESS on success
447 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
448 * @retval MOBILESYNC_E_CANCELLED if the device explicitly cancelled the
449 * session
450 */
451mobilesync_error_t mobilesync_receive_changes(mobilesync_client_t client, plist_t *entities, uint8_t *is_last_record, plist_t *actions) 357mobilesync_error_t mobilesync_receive_changes(mobilesync_client_t client, plist_t *entities, uint8_t *is_last_record, plist_t *actions)
452{ 358{
453 if (!client || !client->data_class) { 359 if (!client || !client->data_class) {
@@ -497,7 +403,7 @@ mobilesync_error_t mobilesync_receive_changes(mobilesync_client_t client, plist_
497 403
498 if (actions != NULL) { 404 if (actions != NULL) {
499 actions_node = plist_array_get_item(msg, 4); 405 actions_node = plist_array_get_item(msg, 4);
500 if (plist_get_node_type(actions) == PLIST_DICT) 406 if (plist_get_node_type(actions_node) == PLIST_DICT)
501 *actions = plist_copy(actions_node); 407 *actions = plist_copy(actions_node);
502 else 408 else
503 *actions = NULL; 409 *actions = NULL;
@@ -515,17 +421,6 @@ mobilesync_error_t mobilesync_receive_changes(mobilesync_client_t client, plist_
515 return err; 421 return err;
516} 422}
517 423
518/**
519 * Requests the device to delete all records of the current data class
520 *
521 * @note The operation must be called after starting synchronization.
522 *
523 * @param client The mobilesync client
524 *
525 * @retval MOBILESYNC_E_SUCCESS on success
526 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
527 * @retval MOBILESYNC_E_PLIST_ERROR if the received plist is not of valid form
528 */
529mobilesync_error_t mobilesync_clear_all_records_on_device(mobilesync_client_t client) 424mobilesync_error_t mobilesync_clear_all_records_on_device(mobilesync_client_t client)
530{ 425{
531 if (!client || !client->data_class) { 426 if (!client || !client->data_class) {
@@ -578,7 +473,7 @@ mobilesync_error_t mobilesync_clear_all_records_on_device(mobilesync_client_t cl
578 goto out; 473 goto out;
579 } 474 }
580 475
581 if (strcmp(response_type, "SDMessageDeviceWillClearAllRecords")) { 476 if (strcmp(response_type, "SDMessageDeviceWillClearAllRecords") != 0) {
582 err = MOBILESYNC_E_PLIST_ERROR; 477 err = MOBILESYNC_E_PLIST_ERROR;
583 } 478 }
584 479
@@ -595,14 +490,6 @@ mobilesync_error_t mobilesync_clear_all_records_on_device(mobilesync_client_t cl
595 return err; 490 return err;
596} 491}
597 492
598/**
599 * Acknowledges to the device that the changes have been merged on the computer
600 *
601 * @param client The mobilesync client
602 *
603 * @retval MOBILESYNC_E_SUCCESS on success
604 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
605 */
606mobilesync_error_t mobilesync_acknowledge_changes_from_device(mobilesync_client_t client) 493mobilesync_error_t mobilesync_acknowledge_changes_from_device(mobilesync_client_t client)
607{ 494{
608 if (!client || !client->data_class) { 495 if (!client || !client->data_class) {
@@ -637,23 +524,6 @@ static plist_t create_process_changes_message(const char *data_class, plist_t en
637 return msg; 524 return msg;
638} 525}
639 526
640/**
641 * Verifies if the device is ready to receive changes from the computer.
642 * This call changes the synchronization direction so that mobilesync_send_changes()
643 * can be used to send changes to the device.
644 *
645 * @param client The mobilesync client
646 *
647 * @retval MOBILESYNC_E_SUCCESS on success
648 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
649 * @retval MOBILESYNC_E_PLIST_ERROR if the received plist is not of valid form
650 * @retval MOBILESYNC_E_WRONG_DIRECTION if the current sync direction does
651 * not permit this call
652 * @retval MOBILESYNC_E_CANCELLED if the device explicitly cancelled the
653 * session
654 * @retval MOBILESYNC_E_NOT_READY if the device is not ready to start
655 * receiving any changes
656 */
657mobilesync_error_t mobilesync_ready_to_send_changes_from_computer(mobilesync_client_t client) 527mobilesync_error_t mobilesync_ready_to_send_changes_from_computer(mobilesync_client_t client)
658{ 528{
659 if (!client || !client->data_class) { 529 if (!client || !client->data_class) {
@@ -721,20 +591,6 @@ mobilesync_error_t mobilesync_ready_to_send_changes_from_computer(mobilesync_cli
721 return err; 591 return err;
722} 592}
723 593
724/**
725 * Sends changed entities of the currently set data class to the device
726 *
727 * @param client The mobilesync client
728 * @param entities The changed entity records as a PLIST_DICT
729 * @param is_last_record A flag indicating if this submission is the last one
730 * @param actions Additional actions for the device created with mobilesync_actions_new()
731 * or NULL if no actions should be passed
732 *
733 * @retval MOBILESYNC_E_SUCCESS on success
734 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid,
735 * @retval MOBILESYNC_E_WRONG_DIRECTION if the current sync direction does
736 * not permit this call
737 */
738mobilesync_error_t mobilesync_send_changes(mobilesync_client_t client, plist_t entities, uint8_t is_last_record, plist_t actions) 594mobilesync_error_t mobilesync_send_changes(mobilesync_client_t client, plist_t entities, uint8_t is_last_record, plist_t actions)
739{ 595{
740 if (!client || !client->data_class || !entities) { 596 if (!client || !client->data_class || !entities) {
@@ -763,21 +619,6 @@ mobilesync_error_t mobilesync_send_changes(mobilesync_client_t client, plist_t e
763 return err; 619 return err;
764} 620}
765 621
766/**
767 * Receives any remapped identifiers reported after the device merged submitted changes.
768 *
769 * @param client The mobilesync client
770 * @param mapping A pointer to an array plist containing a dict of identifier remappings
771 *
772 * @retval MOBILESYNC_E_SUCCESS on success
773 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
774 * @retval MOBILESYNC_E_PLIST_ERROR if the received plist is not of valid
775 * form
776 * @retval MOBILESYNC_E_WRONG_DIRECTION if the current sync direction does
777 * not permit this call
778 * @retval MOBILESYNC_E_CANCELLED if the device explicitly cancelled the
779 * session
780 */
781mobilesync_error_t mobilesync_remap_identifiers(mobilesync_client_t client, plist_t *mapping) 622mobilesync_error_t mobilesync_remap_identifiers(mobilesync_client_t client, plist_t *mapping)
782{ 623{
783 if (!client || !client->data_class) { 624 if (!client || !client->data_class) {
@@ -847,15 +688,6 @@ mobilesync_error_t mobilesync_remap_identifiers(mobilesync_client_t client, plis
847 return err; 688 return err;
848} 689}
849 690
850/**
851 * Cancels a running synchronization session with a device at any time.
852 *
853 * @param client The mobilesync client
854 * @param reason The reason to supply to the device for cancelling
855 *
856 * @retval MOBILESYNC_E_SUCCESS on success
857 * @retval MOBILESYNC_E_INVALID_ARG if one of the parameters is invalid
858 */
859mobilesync_error_t mobilesync_cancel(mobilesync_client_t client, const char* reason) 691mobilesync_error_t mobilesync_cancel(mobilesync_client_t client, const char* reason)
860{ 692{
861 if (!client || !client->data_class || !reason) { 693 if (!client || !client->data_class || !reason) {
@@ -882,18 +714,9 @@ mobilesync_error_t mobilesync_cancel(mobilesync_client_t client, const char* rea
882 return err; 714 return err;
883} 715}
884 716
885/**
886 * Allocates memory for a new anchors struct initialized with the passed anchors.
887 *
888 * @param device_anchor An anchor the device reported the last time or NULL
889 * if none is known yet which for instance is true on first synchronization.
890 * @param computer_anchor An arbitrary string to use as anchor for the computer.
891 *
892 * @return A new #mobilesync_anchors_t struct. Must be freed using mobilesync_anchors_free().
893 */
894mobilesync_anchors_t mobilesync_anchors_new(const char *device_anchor, const char *computer_anchor) 717mobilesync_anchors_t mobilesync_anchors_new(const char *device_anchor, const char *computer_anchor)
895{ 718{
896 mobilesync_anchors_t anchors = (mobilesync_anchors_t) malloc(sizeof(mobilesync_anchors)); 719 mobilesync_anchors_t anchors = (mobilesync_anchors_t) malloc(sizeof(mobilesync_anchors));
897 if (device_anchor != NULL) { 720 if (device_anchor != NULL) {
898 anchors->device_anchor = strdup(device_anchor); 721 anchors->device_anchor = strdup(device_anchor);
899 } else { 722 } else {
@@ -908,11 +731,6 @@ mobilesync_anchors_t mobilesync_anchors_new(const char *device_anchor, const cha
908 return anchors; 731 return anchors;
909} 732}
910 733
911/**
912 * Free memory used by anchors.
913 *
914 * @param anchors The anchors to free.
915 */
916void mobilesync_anchors_free(mobilesync_anchors_t anchors) 734void mobilesync_anchors_free(mobilesync_anchors_t anchors)
917{ 735{
918 if (anchors->device_anchor != NULL) { 736 if (anchors->device_anchor != NULL) {
@@ -927,28 +745,11 @@ void mobilesync_anchors_free(mobilesync_anchors_t anchors)
927 anchors = NULL; 745 anchors = NULL;
928} 746}
929 747
930/** 748plist_t mobilesync_actions_new(void)
931 * Create a new actions plist to use in mobilesync_send_changes().
932 *
933 * @return A new plist_t of type PLIST_DICT.
934 */
935plist_t mobilesync_actions_new()
936{ 749{
937 return plist_new_dict(); 750 return plist_new_dict();
938} 751}
939 752
940/**
941 * Add one or more new key:value pairs to the given actions plist.
942 *
943 * @param actions The actions to modify.
944 * @param ... KEY, VALUE, [KEY, VALUE], NULL
945 *
946 * @note The known keys so far are "SyncDeviceLinkEntityNamesKey" which expects
947 * an array of entity names, followed by a count paramter as well as
948 * "SyncDeviceLinkAllRecordsOfPulledEntityTypeSentKey" which expects an
949 * integer to use as a boolean value indicating that the device should
950 * link submitted changes and report remapped identifiers.
951 */
952void mobilesync_actions_add(plist_t actions, ...) 753void mobilesync_actions_add(plist_t actions, ...)
953{ 754{
954 if (!actions) 755 if (!actions)
@@ -969,10 +770,10 @@ void mobilesync_actions_add(plist_t actions, ...)
969 plist_array_append_item(array, plist_new_string(entity_names[i])); 770 plist_array_append_item(array, plist_new_string(entity_names[i]));
970 } 771 }
971 772
972 plist_dict_insert_item(actions, key, array); 773 plist_dict_set_item(actions, key, array);
973 } else if (!strcmp(key, "SyncDeviceLinkAllRecordsOfPulledEntityTypeSentKey")) { 774 } else if (!strcmp(key, "SyncDeviceLinkAllRecordsOfPulledEntityTypeSentKey")) {
974 int link_records = va_arg(args, int); 775 int link_records = va_arg(args, int);
975 plist_dict_insert_item(actions, key, plist_new_bool(link_records)); 776 plist_dict_set_item(actions, key, plist_new_bool(link_records));
976 } 777 }
977 free(key); 778 free(key);
978 key = NULL; 779 key = NULL;
@@ -981,11 +782,6 @@ void mobilesync_actions_add(plist_t actions, ...)
981 va_end(args); 782 va_end(args);
982} 783}
983 784
984/**
985 * Free actions plist.
986 *
987 * @param actions The actions plist to free. Does nothing if NULL is passed.
988 */
989void mobilesync_actions_free(plist_t actions) 785void mobilesync_actions_free(plist_t actions)
990{ 786{
991 if (actions) { 787 if (actions) {