static void parse_valid_xml_rpc_response(LinphoneXmlRpcRequest *request, const char *response_body) { xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); request->status = LinphoneXmlRpcStatusFailed; xml_ctx->doc = xmlReadDoc((const unsigned char*)response_body, 0, NULL, 0); if (xml_ctx->doc != NULL) { const char *response_str = NULL; if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end; switch (request->response.type) { case LinphoneXmlRpcArgInt: response_str = linphone_get_xml_text_content(xml_ctx, "/methodResponse/params/param/value/int"); if (response_str != NULL) { request->response.data.i = atoi(response_str); request->status = LinphoneXmlRpcStatusOk; } break; case LinphoneXmlRpcArgString: response_str = linphone_get_xml_text_content(xml_ctx, "/methodResponse/params/param/value/string"); if (response_str != NULL) { request->response.data.s = belle_sip_strdup(response_str); request->status = LinphoneXmlRpcStatusOk; } break; default: break; } if (response_str) linphone_free_xml_text_content(response_str); } else { ms_warning("Wrongly formatted XML-RPC response: %s", xml_ctx->errorBuffer); } end: linphone_xmlparsing_context_destroy(xml_ctx); if (request->callbacks->response != NULL) { request->callbacks->response(request); } }
static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList *list, const LinphoneContent *body, const char *first_part_body) { xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); xml_ctx->doc = xmlReadDoc((const unsigned char*)first_part_body, 0, NULL, 0); if (xml_ctx->doc != NULL) { char xpath_str[MAX_XPATH_LENGTH]; LinphoneFriend *lf; LinphoneContent *presence_part; xmlXPathObjectPtr resource_object; const char *version_str = NULL; const char *full_state_str = NULL; const char *uri = NULL; bool_t full_state = FALSE; int version; int i; if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end; xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"rlmi", (const xmlChar *)"urn:ietf:params:xml:ns:rlmi"); version_str = linphone_get_xml_attribute_text_content(xml_ctx, "/rlmi:list", "version"); if (version_str == NULL) { ms_warning("rlmi+xml: No version attribute in list"); goto end; } version = atoi(version_str); linphone_free_xml_text_content(version_str); if (version < list->expected_notification_version) { ms_warning("rlmi+xml: Discarding received notification with version %d because %d was expected", version, list->expected_notification_version); linphone_friend_list_update_subscriptions(list, NULL, FALSE); /* Refresh subscription to get new full state notify. */ goto end; } full_state_str = linphone_get_xml_attribute_text_content(xml_ctx, "/rlmi:list", "fullState"); if (full_state_str == NULL) { ms_warning("rlmi+xml: No fullState attribute in list"); goto end; } if ((strcmp(full_state_str, "true") == 0) || (strcmp(full_state_str, "1") == 0)) { bctbx_list_t *l = list->friends; for (; l != NULL; l = l->next) { lf = (LinphoneFriend *)l->data; linphone_friend_set_presence_model(lf, NULL); } full_state = TRUE; } linphone_free_xml_text_content(full_state_str); if ((list->expected_notification_version == 0) && (full_state == FALSE)) { ms_warning("rlmi+xml: Notification with version 0 is not full state, this is not valid"); goto end; } list->expected_notification_version = version + 1; resource_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/rlmi:list/rlmi:resource"); if ((resource_object != NULL) && (resource_object->nodesetval != NULL)) { for (i = 1; i <= resource_object->nodesetval->nodeNr; i++) { snprintf(xpath_str, sizeof(xpath_str), "/rlmi:list/rlmi:resource[%i]/@uri", i); uri = linphone_get_xml_text_content(xml_ctx, xpath_str); if (uri == NULL) continue; lf = linphone_friend_list_find_friend_by_uri(list, uri); if (lf != NULL) { const char *state = NULL; snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@state", i); state = linphone_get_xml_text_content(xml_ctx, xpath_str); if ((state != NULL) && (strcmp(state, "active") == 0)) { const char *cid = NULL; snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@cid", i); cid = linphone_get_xml_text_content(xml_ctx, xpath_str); if (cid != NULL) { presence_part = linphone_content_find_part_by_header(body, "Content-Id", cid); if (presence_part == NULL) { ms_warning("rlmi+xml: Cannot find part with Content-Id: %s", cid); } else { SalPresenceModel *presence = NULL; linphone_notify_parse_presence(linphone_content_get_type(presence_part), linphone_content_get_subtype(presence_part), linphone_content_get_string_buffer(presence_part), &presence); if (presence != NULL) { lf->presence_received = TRUE; linphone_friend_set_presence_model(lf, (LinphonePresenceModel *)presence); if (full_state == FALSE) { linphone_core_notify_notify_presence_received(list->lc, lf); } } linphone_content_unref(presence_part); } } if (cid != NULL) linphone_free_xml_text_content(cid); } if (state != NULL) linphone_free_xml_text_content(state); lf->subscribe_active = TRUE; } linphone_free_xml_text_content(uri); } } if (resource_object != NULL) xmlXPathFreeObject(resource_object); if (full_state == TRUE) { bctbx_list_t *l = list->friends; for (; l != NULL; l = l->next) { lf = (LinphoneFriend *)l->data; if (linphone_friend_is_presence_received(lf) == TRUE) { linphone_core_notify_notify_presence_received(list->lc, lf); } } } } else { ms_warning("Wrongly formatted rlmi+xml body: %s", xml_ctx->errorBuffer); } end: linphone_xmlparsing_context_destroy(xml_ctx); }