diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c
index c98dbec7f..19fb28cea 100644
--- a/coreapi/bellesip_sal/sal_impl.c
+++ b/coreapi/bellesip_sal/sal_impl.c
@@ -976,12 +976,11 @@ typedef struct {
unsigned char node[6];
} sal_uuid_t;
-
-int sal_create_uuid(Sal*ctx, char *uuid, size_t len){
+int sal_generate_uuid(char *uuid, size_t len) {
sal_uuid_t uuid_struct;
int i;
int written;
-
+
if (len==0) return -1;
/*create an UUID as described in RFC4122, 4.4 */
belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t));
@@ -1000,10 +999,17 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){
for (i = 0; i < 6; i++)
written+=snprintf(uuid+written,len-written,"%2.2x", uuid_struct.node[i]);
uuid[len-1]='\0';
- sal_set_uuid(ctx,uuid);
return 0;
}
+int sal_create_uuid(Sal*ctx, char *uuid, size_t len) {
+ if (sal_generate_uuid(uuid, len) == 0) {
+ sal_set_uuid(ctx, uuid);
+ return 0;
+ }
+ return -1;
+}
+
static void make_supported_header(Sal *sal){
MSList *it;
char *alltags=NULL;
diff --git a/coreapi/carddav.c b/coreapi/carddav.c
index ea7b0b63b..f9ea99f73 100644
--- a/coreapi/carddav.c
+++ b/coreapi/carddav.c
@@ -274,9 +274,8 @@ static void process_response_from_carddav_request(void *data, const belle_http_r
if (event->response) {
int code = belle_http_response_get_status_code(event->response);
- if (code == 207 || code == 200) {
+ if (code == 207 || code == 200 || code == 201 || code == 204) {
const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
- query->status = LinphoneCardDavQueryStatusOk;
switch(query->type) {
case LinphoneCardDavQueryTypePropfind:
linphone_carddav_ctag_fetched(query->context, parse_ctag_value_from_xml_response(body));
@@ -287,10 +286,38 @@ static void process_response_from_carddav_request(void *data, const belle_http_r
case LinphoneCardDavQueryTypeAddressbookMultiget:
linphone_carddav_vcards_pulled(query->context, parse_vcards_from_xml_response(body));
break;
+ case LinphoneCardDavQueryTypePut:
+ {
+ belle_sip_header_t *header = belle_sip_message_get_header((belle_sip_message_t *)event->response, "ETag");
+ LinphoneFriend *lf = (LinphoneFriend *)query->user_data;
+ if (lf) {
+ LinphoneVCard *lvc = linphone_friend_get_vcard(lf);
+ if (header && lvc && !linphone_vcard_get_etag(lvc)) {
+ const char *etag = belle_sip_header_get_unparsed_value(header);
+ ms_debug("eTag for newly created vCard is: %s", etag);
+ linphone_vcard_set_etag(lvc, etag);
+ }
+ linphone_carddav_sync_done(query->context, TRUE, "");
+ linphone_friend_unref(lf);
+ } else {
+ linphone_carddav_sync_done(query->context, FALSE, "No LinphoneFriend found in user_date field of query");
+ }
+ }
+ break;
+ case LinphoneCardDavQueryTypeDelete:
+ linphone_carddav_sync_done(query->context, TRUE, "");
+ break;
+ default:
+ ms_error("Unknown request: %i", query->type);
+ break;
}
} else {
- query->status = LinphoneCardDavQueryStatusFailed;
+ char msg[100];
+ snprintf(msg, sizeof(msg), "Unexpected HTTP response code: %i", code);
+ linphone_carddav_sync_done(query->context, FALSE, msg);
}
+ } else {
+ linphone_carddav_sync_done(query->context, FALSE, "No response found");
}
ms_free(query);
}
@@ -298,7 +325,6 @@ static void process_response_from_carddav_request(void *data, const belle_http_r
static void process_io_error_from_carddav_request(void *data, const belle_sip_io_error_event_t *event) {
LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)data;
ms_error("I/O error during CardDAV request sending");
- query->status = LinphoneCardDavQueryStatusFailed;
ms_free(query);
linphone_carddav_sync_done(query->context, FALSE, "I/O error during CardDAV request sending");
}
@@ -316,7 +342,6 @@ static void process_auth_requested_from_carddav_request(void *data, belle_sip_au
belle_sip_auth_event_set_ha1(event, context->ha1);
}
} else {
- query->status = LinphoneCardDavQueryStatusFailed;
ms_error("Authentication requested during CardDAV request sending, and username/password weren't provided");
linphone_carddav_sync_done(query->context, FALSE, "Authentication requested during CardDAV request sending, and username/password weren't provided");
}
@@ -331,18 +356,33 @@ static void linphone_carddav_send_query(LinphoneCardDavQuery *query) {
uri = belle_generic_uri_parse(query->url);
if (!uri) {
+ LinphoneCardDavContext *cdc = query->context;
+ if (cdc && cdc->sync_done_cb) {
+ cdc->sync_done_cb(cdc, FALSE, "Could not send request, URL is invalid");
+ }
belle_sip_error("Could not send request, URL %s is invalid", query->url);
- query->status = LinphoneCardDavQueryStatusFailed;
return;
}
- req = belle_http_request_create(query->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), belle_sip_header_create("Depth", query->depth), NULL);
+ if (query->depth) {
+ req = belle_http_request_create(query->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), belle_sip_header_create("Depth", query->depth), NULL);
+ } else if (query->ifmatch) {
+ req = belle_http_request_create(query->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), belle_sip_header_create("If-Match", query->ifmatch), NULL);
+ } else {
+ if (strcmp(query->method, "PUT")) {
+ req = belle_http_request_create(query->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), belle_sip_header_create("If-None-Match", "*"), NULL);
+ } else {
+ req = belle_http_request_create(query->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), NULL);
+ }
+ }
if (!req) {
+ LinphoneCardDavContext *cdc = query->context;
+ if (cdc && cdc->sync_done_cb) {
+ cdc->sync_done_cb(cdc, FALSE, "Could not create belle_http_request_t");
+ }
belle_sip_object_unref(uri);
belle_sip_error("Could not create belle_http_request_t");
- query->status = LinphoneCardDavQueryStatusFailed;
return;
}
- query->status = LinphoneCardDavQueryStatusPending;
bh = belle_sip_memory_body_handler_new_copy_from_buffer(query->body, strlen(query->body), NULL, NULL);
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(bh));
@@ -354,12 +394,106 @@ static void linphone_carddav_send_query(LinphoneCardDavQuery *query) {
belle_http_provider_send_request(query->context->lc->http_provider, req, l);
}
+static LinphoneCardDavQuery* linphone_carddav_create_put_query(LinphoneCardDavContext *cdc, LinphoneVCard *lvc) {
+ LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)ms_new0(LinphoneCardDavQuery, 1);
+ query->context = cdc;
+ query->depth = NULL;
+ query->ifmatch = linphone_vcard_get_etag(lvc);
+ query->body = linphone_vcard_as_vcard4_string(lvc);
+ query->method = "PUT";
+ query->url = linphone_vcard_get_url(lvc);
+ query->type = LinphoneCardDavQueryTypePut;
+ return query;
+}
+
+static char* generate_url_from_server_address_and_uid(const char *server_url) {
+ if (server_url) {
+ char uuid[32];
+ if (sal_generate_uuid(uuid, sizeof(uuid)) == 0) {
+ char url[300];
+ snprintf(url, sizeof(url), "%s/linphone-%s.vcf", server_url, uuid);
+ ms_debug("Generated url is %s", url);
+ return ms_strdup(url);
+ }
+ }
+ return NULL;
+}
+
void linphone_carddav_put_vcard(LinphoneCardDavContext *cdc, LinphoneFriend *lf) {
- //TODO
+ LinphoneVCard *lvc = linphone_friend_get_vcard(lf);
+ if (lvc && linphone_vcard_get_uid(lvc)) {
+ LinphoneCardDavQuery *query = NULL;
+
+ if (!linphone_vcard_get_url(lvc)) {
+ char *url = generate_url_from_server_address_and_uid(cdc->server_url);
+ linphone_vcard_set_url(lvc, url);
+ ms_free(url);
+ }
+
+ query = linphone_carddav_create_put_query(cdc, lvc);
+ query->user_data = linphone_friend_ref(lf);
+ linphone_carddav_send_query(query);
+ } else {
+ const char *msg = NULL;
+ if (!lvc) {
+ msg = "LinphoneVCard is NULL";
+ } else if (!linphone_vcard_get_url(lvc)) {
+ msg = "LinphoneVCard doesn't have an UID";
+ }
+
+ if (msg) {
+ ms_error("%s", msg);
+ }
+
+ if (cdc && cdc->sync_done_cb) {
+ cdc->sync_done_cb(cdc, FALSE, msg);
+ }
+ }
+}
+
+static LinphoneCardDavQuery* linphone_carddav_create_delete_query(LinphoneCardDavContext *cdc, LinphoneVCard *lvc) {
+ LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)ms_new0(LinphoneCardDavQuery, 1);
+ query->context = cdc;
+ query->depth = NULL;
+ query->ifmatch = linphone_vcard_get_etag(lvc);
+ query->body = linphone_vcard_as_vcard4_string(lvc);
+ query->method = "DELETE";
+ query->url = linphone_vcard_get_url(lvc);
+ query->type = LinphoneCardDavQueryTypeDelete;
+ return query;
}
void linphone_carddav_delete_vcard(LinphoneCardDavContext *cdc, LinphoneFriend *lf) {
- //TODO
+ LinphoneVCard *lvc = linphone_friend_get_vcard(lf);
+ if (lvc && linphone_vcard_get_uid(lvc) && linphone_vcard_get_etag(lvc)) {
+ LinphoneCardDavQuery *query = NULL;
+
+ if (!linphone_vcard_get_url(lvc)) {
+ char *url = generate_url_from_server_address_and_uid(cdc->server_url);
+ linphone_vcard_set_url(lvc, url);
+ ms_free(url);
+ }
+
+ query = linphone_carddav_create_delete_query(cdc, lvc);
+ linphone_carddav_send_query(query);
+ } else {
+ const char *msg = NULL;
+ if (!lvc) {
+ msg = "LinphoneVCard is NULL";
+ } else if (!linphone_vcard_get_uid(lvc)) {
+ msg = "LinphoneVCard doesn't have an UID";
+ } else if (!linphone_vcard_get_etag(lvc)) {
+ msg = "LinphoneVCard doesn't have an eTag";
+ }
+
+ if (msg) {
+ ms_error("%s", msg);
+ }
+
+ if (cdc && cdc->sync_done_cb) {
+ cdc->sync_done_cb(cdc, FALSE, msg);
+ }
+ }
}
void linphone_carddav_set_synchronization_done_callback(LinphoneCardDavContext *cdc, LinphoneCardDavSynchronizationDoneCb cb) {
@@ -382,11 +516,11 @@ static LinphoneCardDavQuery* linphone_carddav_create_propfind_query(LinphoneCard
LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)ms_new0(LinphoneCardDavQuery, 1);
query->context = cdc;
query->depth = "0";
+ query->ifmatch = NULL;
query->body = "";
query->method = "PROPFIND";
query->url = cdc->server_url;
query->type = LinphoneCardDavQueryTypePropfind;
- query->status = LinphoneCardDavQueryStatusIdle;
return query;
}
@@ -399,11 +533,11 @@ static LinphoneCardDavQuery* linphone_carddav_create_addressbook_query(LinphoneC
LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)ms_new0(LinphoneCardDavQuery, 1);
query->context = cdc;
query->depth = "1";
+ query->ifmatch = NULL;
query->body = "";
query->method = "REPORT";
query->url = cdc->server_url;
query->type = LinphoneCardDavQueryTypeAddressbookQuery;
- query->status = LinphoneCardDavQueryStatusIdle;
return query;
}
@@ -414,22 +548,22 @@ void linphone_carddav_fetch_vcards(LinphoneCardDavContext *cdc) {
static LinphoneCardDavQuery* linphone_carddav_create_addressbook_multiget_query(LinphoneCardDavContext *cdc, MSList *vcards) {
LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)ms_new0(LinphoneCardDavQuery, 1);
- char body[(ms_list_size(vcards)+1)*100];
+ char body[(ms_list_size(vcards)+1)*300];
MSList *iterator = vcards;
query->context = cdc;
query->depth = "1";
+ query->ifmatch = NULL;
query->method = "REPORT";
query->url = cdc->server_url;
query->type = LinphoneCardDavQueryTypeAddressbookMultiget;
- query->status = LinphoneCardDavQueryStatusIdle;
sprintf(body, "%s", "");
while (iterator) {
LinphoneCardDavResponse *response = (LinphoneCardDavResponse *)iterator->data;
if (response) {
- char temp_body[100];
- sprintf(temp_body, "%s", response->url);
+ char temp_body[300];
+ snprintf(temp_body, sizeof(temp_body), "%s", response->url);
sprintf(body, "%s%s", body, temp_body);
iterator = ms_list_next(iterator);
}
diff --git a/coreapi/carddav.h b/coreapi/carddav.h
index 1a8a22b26..dac895066 100644
--- a/coreapi/carddav.h
+++ b/coreapi/carddav.h
@@ -23,22 +23,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef __cplusplus
extern "C" {
#endif
+
+/**
+ * @addtogroup carddav_vcard
+ * @{
+ */
typedef struct _LinphoneCardDavContext LinphoneCardDavContext;
typedef enum _LinphoneCardDavQueryType {
LinphoneCardDavQueryTypePropfind,
LinphoneCardDavQueryTypeAddressbookQuery,
- LinphoneCardDavQueryTypeAddressbookMultiget
+ LinphoneCardDavQueryTypeAddressbookMultiget,
+ LinphoneCardDavQueryTypePut,
+ LinphoneCardDavQueryTypeDelete
} LinphoneCardDavQueryType;
-typedef enum _LinphoneCardDavQueryStatus {
- LinphoneCardDavQueryStatusIdle,
- LinphoneCardDavQueryStatusPending,
- LinphoneCardDavQueryStatusOk,
- LinphoneCardDavQueryStatusFailed
-} LinphoneCardDavQueryStatus;
-
typedef struct _LinphoneCardDavQuery LinphoneCardDavQuery;
typedef struct _LinphoneCardDavResponse LinphoneCardDavResponse;
@@ -157,6 +157,10 @@ void linphone_carddav_fetch_vcards(LinphoneCardDavContext *cdc);
*/
void linphone_carddav_pull_vcards(LinphoneCardDavContext *cdc, MSList *vcards_to_pull);
+/**
+ * @}
+ */
+
#ifdef __cplusplus
}
#endif
diff --git a/coreapi/private.h b/coreapi/private.h
index afeb75781..03ae84a36 100644
--- a/coreapi/private.h
+++ b/coreapi/private.h
@@ -1244,8 +1244,9 @@ struct _LinphoneCardDavQuery {
const char *method;
const char *body;
const char *depth;
+ const char *ifmatch;
+ void *user_data;
LinphoneCardDavQueryType type;
- LinphoneCardDavQueryStatus status;
};
struct _LinphoneCardDavResponse {
diff --git a/coreapi/vcard.cc b/coreapi/vcard.cc
index c8d94c5b2..c9b9153bf 100644
--- a/coreapi/vcard.cc
+++ b/coreapi/vcard.cc
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "vcard.h"
#include "belcard/belcard.hpp"
#include "belcard/belcard_parser.hpp"
+#include "sal/sal.h"
struct _LinphoneVCard {
shared_ptr belCard;
@@ -27,20 +28,24 @@ struct _LinphoneVCard {
const char *url;
};
-extern "C" LinphoneVCard* linphone_vcard_new(void) {
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LinphoneVCard* linphone_vcard_new(void) {
LinphoneVCard* vCard = (LinphoneVCard*) ms_new0(LinphoneVCard, 1);
vCard->belCard = belcard::BelCardGeneric::create();
return vCard;
}
-extern "C" void linphone_vcard_free(LinphoneVCard *vCard) {
+void linphone_vcard_free(LinphoneVCard *vCard) {
if (!vCard) return;
vCard->belCard.reset();
ms_free(vCard);
}
-extern "C" MSList* linphone_vcard_list_from_vcard4_file(const char *filename) {
+MSList* linphone_vcard_list_from_vcard4_file(const char *filename) {
MSList *result = NULL;
if (filename && ortp_file_exist(filename) == 0) {
belcard::BelCardParser parser = belcard::BelCardParser::getInstance();
@@ -57,7 +62,7 @@ extern "C" MSList* linphone_vcard_list_from_vcard4_file(const char *filename) {
return result;
}
-extern "C" MSList* linphone_vcard_list_from_vcard4_buffer(const char *buffer) {
+MSList* linphone_vcard_list_from_vcard4_buffer(const char *buffer) {
MSList *result = NULL;
if (buffer) {
belcard::BelCardParser parser = belcard::BelCardParser::getInstance();
@@ -74,7 +79,7 @@ extern "C" MSList* linphone_vcard_list_from_vcard4_buffer(const char *buffer) {
return result;
}
-extern "C" LinphoneVCard* linphone_vcard_new_from_vcard4_buffer(const char *buffer) {
+LinphoneVCard* linphone_vcard_new_from_vcard4_buffer(const char *buffer) {
LinphoneVCard *vCard = NULL;
if (buffer) {
belcard::BelCardParser parser = belcard::BelCardParser::getInstance();
@@ -89,13 +94,13 @@ extern "C" LinphoneVCard* linphone_vcard_new_from_vcard4_buffer(const char *buff
return vCard;
}
-extern "C" const char * linphone_vcard_as_vcard4_string(LinphoneVCard *vCard) {
+const char * linphone_vcard_as_vcard4_string(LinphoneVCard *vCard) {
if (!vCard) return NULL;
return vCard->belCard->toFoldedString().c_str();
}
-extern "C" void linphone_vcard_set_full_name(LinphoneVCard *vCard, const char *name) {
+void linphone_vcard_set_full_name(LinphoneVCard *vCard, const char *name) {
if (!vCard || !name) return;
shared_ptr fn = belcard::BelCardGeneric::create();
@@ -103,14 +108,14 @@ extern "C" void linphone_vcard_set_full_name(LinphoneVCard *vCard, const char *n
vCard->belCard->setFullName(fn);
}
-extern "C" const char* linphone_vcard_get_full_name(const LinphoneVCard *vCard) {
+const char* linphone_vcard_get_full_name(const LinphoneVCard *vCard) {
if (!vCard) return NULL;
const char *result = vCard->belCard->getFullName() ? vCard->belCard->getFullName()->getValue().c_str() : NULL;
return result;
}
-extern "C" void linphone_vcard_add_sip_address(LinphoneVCard *vCard, const char *sip_address) {
+void linphone_vcard_add_sip_address(LinphoneVCard *vCard, const char *sip_address) {
if (!vCard || !sip_address) return;
shared_ptr impp = belcard::BelCardGeneric::create();
@@ -118,7 +123,7 @@ extern "C" void linphone_vcard_add_sip_address(LinphoneVCard *vCard, const char
vCard->belCard->addImpp(impp);
}
-extern "C" void linphone_vcard_remove_sip_address(LinphoneVCard *vCard, const char *sip_address) {
+void linphone_vcard_remove_sip_address(LinphoneVCard *vCard, const char *sip_address) {
if (!vCard) return;
for (auto it = vCard->belCard->getImpp().begin(); it != vCard->belCard->getImpp().end(); ++it) {
@@ -130,7 +135,7 @@ extern "C" void linphone_vcard_remove_sip_address(LinphoneVCard *vCard, const ch
}
}
-extern "C" void linphone_vcard_edit_main_sip_address(LinphoneVCard *vCard, const char *sip_address) {
+void linphone_vcard_edit_main_sip_address(LinphoneVCard *vCard, const char *sip_address) {
if (!vCard || !sip_address) return;
if (vCard->belCard->getImpp().size() > 0) {
@@ -143,7 +148,7 @@ extern "C" void linphone_vcard_edit_main_sip_address(LinphoneVCard *vCard, const
}
}
-extern "C" MSList* linphone_vcard_get_sip_addresses(const LinphoneVCard *vCard) {
+MSList* linphone_vcard_get_sip_addresses(const LinphoneVCard *vCard) {
MSList *result = NULL;
if (!vCard) return NULL;
@@ -156,27 +161,56 @@ extern "C" MSList* linphone_vcard_get_sip_addresses(const LinphoneVCard *vCard)
return result;
}
-extern "C" const char* linphone_vcard_get_uid(const LinphoneVCard *vCard) {
+bool_t linphone_vcard_generate_unique_id(LinphoneVCard *vCard) {
+ char uuid[64];
+
+ if (vCard) {
+ if (linphone_vcard_get_uid(vCard)) {
+ return FALSE;
+ }
+ if (sal_generate_uuid(uuid, sizeof(uuid)) == 0) {
+ char vcard_uuid[sizeof(uuid)+4];
+ snprintf(vcard_uuid, sizeof(vcard_uuid), "urn:%s", uuid);
+ linphone_vcard_set_uid(vCard, ms_strdup(vcard_uuid));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void linphone_vcard_set_uid(LinphoneVCard *vCard, const char *uid) {
+ if (!vCard || !uid) return;
+
+ shared_ptr uniqueId = belcard::BelCardGeneric::create();
+ uniqueId->setValue(uid);
+ vCard->belCard->setUniqueId(uniqueId);
+}
+
+const char* linphone_vcard_get_uid(const LinphoneVCard *vCard) {
if (vCard && vCard->belCard->getUniqueId()) {
return vCard->belCard->getUniqueId()->getValue().c_str();
}
return NULL;
}
-extern "C" void linphone_vcard_set_etag(LinphoneVCard *vCard, const char * etag) {
+void linphone_vcard_set_etag(LinphoneVCard *vCard, const char * etag) {
vCard->etag = ms_strdup(etag);
}
-extern "C" const char* linphone_vcard_get_etag(const LinphoneVCard *vCard) {
+const char* linphone_vcard_get_etag(const LinphoneVCard *vCard) {
if (!vCard) return NULL;
return vCard->etag;
}
-extern "C" void linphone_vcard_set_url(LinphoneVCard *vCard, const char * url) {
+void linphone_vcard_set_url(LinphoneVCard *vCard, const char * url) {
vCard->url = ms_strdup(url);
}
-extern "C" const char* linphone_vcard_get_url(const LinphoneVCard *vCard) {
+const char* linphone_vcard_get_url(const LinphoneVCard *vCard) {
if (!vCard) return NULL;
return vCard->url;
-}
\ No newline at end of file
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/coreapi/vcard.h b/coreapi/vcard.h
index c8eeec45d..f9a0782d3 100644
--- a/coreapi/vcard.h
+++ b/coreapi/vcard.h
@@ -32,7 +32,7 @@ extern "C"
#endif
/**
- * @addtogroup buddy_list
+ * @addtogroup carddav_vcard
* @{
*/
@@ -119,12 +119,54 @@ LINPHONE_PUBLIC void linphone_vcard_edit_main_sip_address(LinphoneVCard *vCard,
*/
LINPHONE_PUBLIC MSList* linphone_vcard_get_sip_addresses(const LinphoneVCard *vCard);
+/**
+ * Generates a random unique id for the vCard.
+ * If is required to be able to synchronize the vCard with a CardDAV server
+ * @param[in] vCard the LinphoneVCard
+ * @return TRUE if operation is successful, otherwise FALSE (for example if it already has an unique ID)
+ */
+LINPHONE_PUBLIC bool_t linphone_vcard_generate_unique_id(LinphoneVCard *vCard);
+
+/**
+ * Sets the unique ID of the vCard
+ * @param[in] vCard the LinphoneVCard
+ * @param[in] uid the unique id
+ */
+void linphone_vcard_set_uid(LinphoneVCard *vCard, const char *uid);
+
+/**
+ * Gets the UID of the vCard
+ * @param[in] vCard the LinphoneVCard
+ * @return the UID of the vCard, otherwise NULL
+ */
const char* linphone_vcard_get_uid(const LinphoneVCard *vCard);
+/**
+ * Sets the eTAG of the vCard
+ * @param[in] vCard the LinphoneVCard
+ * @param[in] etag the eTAG
+ */
void linphone_vcard_set_etag(LinphoneVCard *vCard, const char * etag);
+
+/**
+ * Gets the eTag of the vCard
+ * @param[in] vCard the LinphoneVCard
+ * @return the eTag of the vCard in the CardDAV server, otherwise NULL
+ */
const char* linphone_vcard_get_etag(const LinphoneVCard *vCard);
+/**
+ * Sets the URL of the vCard
+ * @param[in] vCard the LinphoneVCard
+ * @param[in] url the URL
+ */
void linphone_vcard_set_url(LinphoneVCard *vCard, const char * url);
+
+/**
+ * Gets the URL of the vCard
+ * @param[in] vCard the LinphoneVCard
+ * @return the URL of the vCard in the CardDAV server, otherwise NULL
+ */
const char* linphone_vcard_get_url(const LinphoneVCard *vCard);
/**
diff --git a/coreapi/vcard_stubs.c b/coreapi/vcard_stubs.c
index 148858e09..4309e7b7b 100644
--- a/coreapi/vcard_stubs.c
+++ b/coreapi/vcard_stubs.c
@@ -71,6 +71,14 @@ MSList* linphone_vcard_get_sip_addresses(const LinphoneVCard *vCard) {
return NULL;
}
+bool_t linphone_vcard_generate_unique_id(LinphoneVCard *vCard) {
+ return FALSE;
+}
+
+void linphone_vcard_set_uid(LinphoneVCard *vCard, const char *uid) {
+
+}
+
const char* linphone_vcard_get_uid(const LinphoneVCard *vCard) {
return NULL;
}
diff --git a/include/sal/sal.h b/include/sal/sal.h
index d8106f6b7..c1ed0dc21 100644
--- a/include/sal/sal.h
+++ b/include/sal/sal.h
@@ -618,6 +618,7 @@ void sal_verify_server_certificates(Sal *ctx, bool_t verify);
void sal_verify_server_cn(Sal *ctx, bool_t verify);
void sal_set_uuid(Sal*ctx, const char *uuid);
int sal_create_uuid(Sal*ctx, char *uuid, size_t len);
+int sal_generate_uuid(char *uuid, size_t len);
LINPHONE_PUBLIC void sal_enable_test_features(Sal*ctx, bool_t enabled);
void sal_use_no_initial_route(Sal *ctx, bool_t enabled);
diff --git a/tester/vcard_tester.c b/tester/vcard_tester.c
index c146ac7f7..774aec654 100644
--- a/tester/vcard_tester.c
+++ b/tester/vcard_tester.c
@@ -200,7 +200,6 @@ typedef struct _LinphoneCardDAVStats {
static void carddav_sync_done(LinphoneCardDavContext *c, bool_t success, const char *message) {
LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_carddav_get_user_data(c);
BC_ASSERT_TRUE(success);
- linphone_carddav_destroy(c);
stats->sync_done_count++;
}
@@ -250,6 +249,7 @@ static void carddav_sync(void) {
BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i");
ms_free(stats);
+ linphone_carddav_destroy(c);
linphone_core_manager_destroy(manager);
}
@@ -288,6 +288,7 @@ static void carddav_sync_2(void) {
ms_free(stats);
unlink(friends_db);
ms_free(friends_db);
+ linphone_carddav_destroy(c);
linphone_core_manager_destroy(manager);
}
@@ -325,6 +326,40 @@ static void carddav_sync_3(void) {
ms_free(stats);
unlink(friends_db);
ms_free(friends_db);
+ linphone_carddav_destroy(c);
+ linphone_core_manager_destroy(manager);
+}
+
+static void carddav_sync_4(void) {
+ LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE);
+ LinphoneCardDavContext *c = linphone_core_create_carddav_context(manager->lc);
+ LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1);
+ LinphoneVCard *lvc = linphone_vcard_new_from_vcard4_buffer("BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n");
+ LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc);
+
+ BC_ASSERT_PTR_NOT_NULL_FATAL(c);
+ BC_ASSERT_PTR_NOT_NULL(c->server_url);
+ BC_ASSERT_PTR_NOT_NULL(c->username);
+ BC_ASSERT_PTR_NOT_NULL(c->ha1);
+
+ linphone_carddav_set_user_data(c, stats);
+ linphone_carddav_set_synchronization_done_callback(c, carddav_sync_done);
+
+ BC_ASSERT_PTR_NULL(linphone_vcard_get_uid(lvc));
+ BC_ASSERT_TRUE(linphone_vcard_generate_unique_id(lvc));
+ BC_ASSERT_PTR_NOT_NULL(linphone_vcard_get_uid(lvc));
+
+ linphone_carddav_put_vcard(c, lf);
+ wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, 2000);
+ BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i");
+
+ linphone_carddav_delete_vcard(c, lf);
+ wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, 2000);
+ BC_ASSERT_EQUAL(stats->sync_done_count, 2, int, "%i");
+
+ linphone_friend_unref(lf);
+ ms_free(stats);
+ linphone_carddav_destroy(c);
linphone_core_manager_destroy(manager);
}
@@ -346,6 +381,7 @@ test_t vcard_tests[] = {
{ "CardDAV synchronization", carddav_sync },
{ "CardDAV synchronization 2", carddav_sync_2 },
{ "CardDAV synchronization 3", carddav_sync_3 },
+ { "CardDAV synchronization 4", carddav_sync_4 },
#else
{ "Dummy test", dummy_test }
#endif