forked from mirrors/linphone-iphone
Parse results for PROPFIND and REPORT requests
This commit is contained in:
parent
a8e6cc908f
commit
b5300c180c
4 changed files with 171 additions and 25 deletions
|
|
@ -55,30 +55,157 @@ void* linphone_carddav_get_user_data(LinphoneCardDavContext *cdc) {
|
|||
return cdc->user_data;
|
||||
}
|
||||
|
||||
static void linphone_carddav_vcards_fetched(LinphoneCardDavContext *cdc, MSList *vCards) {
|
||||
if (vCards != NULL && ms_list_size(vCards) > 0) {
|
||||
//MSList *localFriends = linphone_core_fetch_friends_from_db(cdc->lc);
|
||||
//TODO: find out if there are new/delete URLs and compare eTags with the current vCards
|
||||
void linphone_carddav_synchronize(LinphoneCardDavContext *cdc) {
|
||||
linphone_carddav_get_current_ctag(cdc);
|
||||
}
|
||||
|
||||
static void linphone_carddav_sync_done(LinphoneCardDavContext *cdc, bool_t success, const char *msg) {
|
||||
if (success) {
|
||||
linphone_core_set_carddav_current_ctag(cdc->lc, cdc->ctag);
|
||||
}
|
||||
|
||||
if (cdc->sync_done_cb) {
|
||||
cdc->sync_done_cb(cdc, TRUE, "TODO: remove lated");
|
||||
cdc->sync_done_cb(cdc, success, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_carddav_vcards_pulled(LinphoneCardDavContext *cdc, MSList *vCards) {
|
||||
if (vCards != NULL && ms_list_size(vCards) > 0) {
|
||||
//TODO: find out which one is new and which one is an update and call the according callback
|
||||
}
|
||||
ms_list_free(vCards);
|
||||
linphone_carddav_sync_done(cdc, TRUE, "");
|
||||
}
|
||||
|
||||
static MSList* parse_vcards_from_xml_response(const char *body) {
|
||||
MSList *result = NULL;
|
||||
xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new();
|
||||
xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error);
|
||||
xml_ctx->doc = xmlReadDoc((const unsigned char*)body, 0, NULL, 0);
|
||||
if (xml_ctx->doc != NULL) {
|
||||
if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end;
|
||||
linphone_xml_xpath_context_init_carddav_ns(xml_ctx);
|
||||
{
|
||||
xmlXPathObjectPtr etags = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/d:multistatus/d:response/d:propstat/d:prop/d:getetag");
|
||||
xmlXPathObjectPtr hrefs = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/d:multistatus/d:response/d:href");
|
||||
xmlXPathObjectPtr vcards = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/d:multistatus/d:response/d:propstat/d:prop/card:address-data");
|
||||
if (etags != NULL && hrefs != NULL && vcards != NULL) {
|
||||
if (etags->nodesetval != NULL && hrefs->nodesetval != NULL && vcards->nodesetval != NULL) {
|
||||
xmlNodeSetPtr etags_nodes = etags->nodesetval;
|
||||
xmlNodeSetPtr hrefs_nodes = hrefs->nodesetval;
|
||||
xmlNodeSetPtr vcards_nodes = vcards->nodesetval;
|
||||
if (etags_nodes->nodeNr >= 1 && hrefs_nodes->nodeNr == etags_nodes->nodeNr && vcards_nodes->nodeNr == etags_nodes->nodeNr) {
|
||||
int i;
|
||||
for (i = 0; i < vcards_nodes->nodeNr; i++) {
|
||||
xmlNodePtr etag_node = etags_nodes->nodeTab[i];
|
||||
xmlNodePtr href_node = hrefs_nodes->nodeTab[i];
|
||||
xmlNodePtr vcard_node = vcards_nodes->nodeTab[i];
|
||||
if (vcard_node->children != NULL) {
|
||||
char *etag = (char *)xmlNodeListGetString(xml_ctx->doc, etag_node->children, 1);
|
||||
char *url = (char *)xmlNodeListGetString(xml_ctx->doc, href_node->children, 1);
|
||||
char *vcard = (char *)xmlNodeListGetString(xml_ctx->doc, vcard_node->children, 1);
|
||||
LinphoneCardDavResponse *response = ms_new0(LinphoneCardDavResponse, 1);
|
||||
response->etag = ms_strdup(etag);
|
||||
response->url = ms_strdup(url);
|
||||
response->vcard = ms_strdup(vcard);
|
||||
result = ms_list_append(result, response);
|
||||
ms_debug("Added vCard object with eTag %s, URL %s and vCard %s", etag, url, vcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(vcards);
|
||||
xmlXPathFreeObject(etags);
|
||||
xmlXPathFreeObject(hrefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
linphone_xmlparsing_context_destroy(xml_ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void linphone_carddav_vcards_fetched(LinphoneCardDavContext *cdc, MSList *vCards) {
|
||||
if (vCards != NULL && ms_list_size(vCards) > 0) {
|
||||
//MSList *localFriends = linphone_core_fetch_friends_from_db(cdc->lc);
|
||||
//TODO: call onDelete from the ones that are in localFriends but not in vCards
|
||||
//TODO: remove from vCards the one that are in localFriends and for which the eTag hasn't changed
|
||||
linphone_carddav_pull_vcards(cdc, vCards);
|
||||
}
|
||||
ms_list_free(vCards);
|
||||
}
|
||||
|
||||
static MSList* parse_vcards_etags_from_xml_response(const char *body) {
|
||||
MSList *result = NULL;
|
||||
xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new();
|
||||
xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error);
|
||||
xml_ctx->doc = xmlReadDoc((const unsigned char*)body, 0, NULL, 0);
|
||||
if (xml_ctx->doc != NULL) {
|
||||
if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end;
|
||||
linphone_xml_xpath_context_init_carddav_ns(xml_ctx);
|
||||
{
|
||||
xmlXPathObjectPtr etags = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/d:multistatus/d:response/d:propstat/d:prop/d:getetag");
|
||||
xmlXPathObjectPtr hrefs = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/d:multistatus/d:response/d:href");
|
||||
if (etags != NULL && hrefs != NULL) {
|
||||
if (etags->nodesetval != NULL && hrefs->nodesetval != NULL) {
|
||||
xmlNodeSetPtr etags_nodes = etags->nodesetval;
|
||||
xmlNodeSetPtr hrefs_nodes = hrefs->nodesetval;
|
||||
if (etags_nodes->nodeNr >= 1 && hrefs_nodes->nodeNr == etags_nodes->nodeNr) {
|
||||
int i;
|
||||
for (i = 0; i < etags_nodes->nodeNr; i++) {
|
||||
xmlNodePtr etag_node = etags_nodes->nodeTab[i];
|
||||
xmlNodePtr href_node = hrefs_nodes->nodeTab[i];
|
||||
if (etag_node->children != NULL && href_node->children != NULL) {
|
||||
char *etag = (char *)xmlNodeListGetString(xml_ctx->doc, etag_node->children, 1);
|
||||
char *url = (char *)xmlNodeListGetString(xml_ctx->doc, href_node->children, 1);
|
||||
LinphoneCardDavResponse *response = ms_new0(LinphoneCardDavResponse, 1);
|
||||
response->etag = ms_strdup(etag);
|
||||
response->url = ms_strdup(url);
|
||||
result = ms_list_append(result, response);
|
||||
ms_debug("Added vCard object with eTag %s and URL %s", etag, url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(etags);
|
||||
xmlXPathFreeObject(hrefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
linphone_xmlparsing_context_destroy(xml_ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void linphone_carddav_ctag_fetched(LinphoneCardDavContext *cdc, int ctag) {
|
||||
ms_debug("Remote cTag for CardDAV addressbook is %i, local one is %i", ctag, cdc->ctag);
|
||||
if (ctag == -1 || ctag > cdc->ctag) {
|
||||
cdc->ctag = ctag;
|
||||
linphone_carddav_fetch_vcards(cdc);
|
||||
} else {
|
||||
ms_message("No changes found on server, skipping sync");
|
||||
if (cdc->sync_done_cb) {
|
||||
cdc->sync_done_cb(cdc, TRUE, "Synchronization skipped because cTag already up to date");
|
||||
}
|
||||
linphone_carddav_sync_done(cdc, TRUE, "Synchronization skipped because cTag already up to date");
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_carddav_synchronize(LinphoneCardDavContext *cdc) {
|
||||
linphone_carddav_get_current_ctag(cdc);
|
||||
static int parse_ctag_value_from_xml_response(const char *body) {
|
||||
int result = -1;
|
||||
xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new();
|
||||
xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error);
|
||||
xml_ctx->doc = xmlReadDoc((const unsigned char*)body, 0, NULL, 0);
|
||||
if (xml_ctx->doc != NULL) {
|
||||
char *response = NULL;
|
||||
if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end;
|
||||
linphone_xml_xpath_context_init_carddav_ns(xml_ctx);
|
||||
response = linphone_get_xml_text_content(xml_ctx, "/d:multistatus/d:response/d:propstat/d:prop/x1:getctag");
|
||||
if (response) {
|
||||
result = atoi(response);
|
||||
linphone_free_xml_text_content(response);
|
||||
}
|
||||
}
|
||||
end:
|
||||
linphone_xmlparsing_context_destroy(xml_ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void process_response_from_carddav_request(void *data, const belle_http_response_event_t *event) {
|
||||
|
|
@ -88,16 +215,16 @@ static void process_response_from_carddav_request(void *data, const belle_http_r
|
|||
int code = belle_http_response_get_status_code(event->response);
|
||||
if (code == 207 || code == 200) {
|
||||
const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
|
||||
ms_message("CardDAV query response body: %s", body);
|
||||
query->status = LinphoneCardDavQueryStatusOk;
|
||||
switch(query->type) {
|
||||
case LinphoneCardDavQueryTypePropfind:
|
||||
linphone_carddav_ctag_fetched(query->context, 0);//TODO parse value from body
|
||||
linphone_carddav_ctag_fetched(query->context, parse_ctag_value_from_xml_response(body));
|
||||
break;
|
||||
case LinphoneCardDavQueryTypeAddressbookQuery:
|
||||
linphone_carddav_vcards_fetched(query->context, NULL);//TODO parse value from body
|
||||
linphone_carddav_vcards_fetched(query->context, parse_vcards_etags_from_xml_response(body));
|
||||
break;
|
||||
case LinphoneCardDavQueryTypeAddressbookMultiget:
|
||||
linphone_carddav_vcards_pulled(query->context, parse_vcards_from_xml_response(body));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -109,12 +236,10 @@ 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");
|
||||
ms_error("I/O error during CardDAV request sending");
|
||||
query->status = LinphoneCardDavQueryStatusFailed;
|
||||
ms_free(query);
|
||||
if (query->context->sync_done_cb) {
|
||||
query->context->sync_done_cb(query->context, FALSE, "I/O Error during CardDAV request sending");
|
||||
}
|
||||
linphone_carddav_sync_done(query->context, FALSE, "I/O error during CardDAV request sending");
|
||||
}
|
||||
|
||||
static void process_auth_requested_from_carddav_request(void *data, belle_sip_auth_event_t *event) {
|
||||
|
|
@ -131,10 +256,8 @@ static void process_auth_requested_from_carddav_request(void *data, belle_sip_au
|
|||
}
|
||||
} else {
|
||||
query->status = LinphoneCardDavQueryStatusFailed;
|
||||
ms_error("Authentication error during CardDAV request sending");
|
||||
if (query->context->sync_done_cb) {
|
||||
query->context->sync_done_cb(query->context, FALSE, "Authentication error during CardDAV request sending");
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +326,7 @@ static LinphoneCardDavQuery* linphone_carddav_create_addressbook_query(LinphoneC
|
|||
LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)ms_new0(LinphoneCardDavQuery, 1);
|
||||
query->context = cdc;
|
||||
query->depth = "1";
|
||||
query->body = "<card:addressbook-query xmlns:d=\"DAV:\" xmlns:card=\"urn:ietf:params:xml:ns:carddav\"><d:prop><d:getetag /><card:address-data content-type='text-vcard' version='4.0'/></d:prop></card:addressbook-query>";
|
||||
query->body = "<card:addressbook-query xmlns:d=\"DAV:\" xmlns:card=\"urn:ietf:params:xml:ns:carddav\"><d:prop><d:getetag /></d:prop></card:addressbook-query>";
|
||||
query->method = "REPORT";
|
||||
query->url = cdc->server_url;
|
||||
query->type = LinphoneCardDavQueryTypeAddressbookQuery;
|
||||
|
|
@ -218,13 +341,27 @@ 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];
|
||||
MSList *iterator = vcards;
|
||||
|
||||
query->context = cdc;
|
||||
query->depth = "1";
|
||||
query->method = "REPORT";
|
||||
query->url = cdc->server_url;
|
||||
query->type = LinphoneCardDavQueryTypeAddressbookMultiget;
|
||||
query->status = LinphoneCardDavQueryStatusIdle;
|
||||
//TODO: body
|
||||
|
||||
sprintf(body, "%s", "<card:addressbook-multiget xmlns:d=\"DAV:\" xmlns:card=\"urn:ietf:params:xml:ns:carddav\"><d:prop><d:getetag /><card:address-data content-type='text-vcard' version='4.0'/></d:prop>");
|
||||
while (iterator) {
|
||||
LinphoneCardDavResponse *response = (LinphoneCardDavResponse *)iterator->data;
|
||||
char temp_body[100];
|
||||
sprintf(temp_body, "<d:href>%s</d:href>", response->url);
|
||||
sprintf(body, "%s%s", body, temp_body);
|
||||
iterator = ms_list_next(iterator);
|
||||
}
|
||||
sprintf(body, "%s%s", body, "</card:addressbook-multiget>");
|
||||
query->body = ms_strdup(body);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7511,7 +7511,7 @@ void linphone_core_set_carddav_current_ctag(LinphoneCore *lc, int ctag) {
|
|||
int linphone_core_get_carddav_last_ctag(LinphoneCore *lc) {
|
||||
if (lc) {
|
||||
LpConfig *lpc = linphone_core_get_config(lc);
|
||||
return lp_config_get_int(lpc, "carddav", "ctag", -1);
|
||||
return lp_config_get_int(lpc, "carddav", "ctag", 0);
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1328,6 +1328,7 @@ char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *
|
|||
const char * linphone_get_xml_attribute_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression, const char *attribute_name);
|
||||
void linphone_free_xml_text_content(const char *text);
|
||||
xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression);
|
||||
void linphone_xml_xpath_context_init_carddav_ns(xmlparsing_context_t *xml_ctx);
|
||||
|
||||
/*****************************************************************************
|
||||
* OTHER UTILITY FUNCTIONS *
|
||||
|
|
|
|||
|
|
@ -123,3 +123,11 @@ void linphone_free_xml_text_content(const char *text) {
|
|||
xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression) {
|
||||
return xmlXPathEvalExpression((const xmlChar *)xpath_expression, xml_ctx->xpath_ctx);
|
||||
}
|
||||
|
||||
void linphone_xml_xpath_context_init_carddav_ns(xmlparsing_context_t *xml_ctx) {
|
||||
if (xml_ctx && xml_ctx->xpath_ctx) {
|
||||
xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar*)"d", (const xmlChar*)"DAV:");
|
||||
xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar*)"card", (const xmlChar*)"urn:ietf:params:xml:ns:carddav");
|
||||
xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar*)"x1", (const xmlChar*)"http://calendarserver.org/ns/");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue