diff --git a/coreapi/friend.c b/coreapi/friend.c index 368f2242b..7d43f1f9f 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -195,6 +195,10 @@ void linphone_core_interpret_friend_uri(LinphoneCore *lc, const char *uri, char } } +const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf){ + return lf->uri; +} + int linphone_friend_set_address(LinphoneFriend *lf, const LinphoneAddress *addr){ LinphoneAddress *fr = linphone_address_clone(addr); LinphoneVcard *vcard = NULL; @@ -211,6 +215,106 @@ int linphone_friend_set_address(LinphoneFriend *lf, const LinphoneAddress *addr) return 0; } +void linphone_friend_add_address(LinphoneFriend *lf, const LinphoneAddress *addr) { + LinphoneVcard *vcard = NULL; + if (!lf || !addr) { + return; + } + + vcard = linphone_friend_get_vcard(lf); + if (!vcard) { + return; + } + + linphone_vcard_add_sip_address(vcard, linphone_address_as_string_uri_only(addr)); +} + +MSList* linphone_friend_get_addresses(LinphoneFriend *lf) { + LinphoneVcard *vcard = NULL; + MSList *sipAddresses = NULL; + MSList *addresses = NULL; + MSList *iterator = NULL; + + if (!lf) { + return NULL; + } + + vcard = linphone_friend_get_vcard(lf); + if (!vcard) { + return NULL; + } + + sipAddresses = linphone_vcard_get_sip_addresses(vcard); + iterator = sipAddresses; + while (iterator) { + const char *sipAddress = (const char *)iterator->data; + LinphoneAddress *addr = linphone_address_new(sipAddress); + if (addr) { + addresses = ms_list_append(addresses, addr); + } + iterator = ms_list_next(iterator); + } + if (sipAddresses) ms_list_free(sipAddresses); + return addresses; +} + +void linphone_friend_remove_address(LinphoneFriend *lf, const LinphoneAddress *addr) { + LinphoneVcard *vcard = NULL; + if (!lf || !addr) { + return; + } + + vcard = linphone_friend_get_vcard(lf); + if (!vcard) { + return; + } + + linphone_vcard_remove_sip_address(vcard, linphone_address_as_string_uri_only(addr)); +} + +void linphone_friend_add_phone_number(LinphoneFriend *lf, const char *phone) { + LinphoneVcard *vcard = NULL; + if (!lf || !phone) { + return; + } + + vcard = linphone_friend_get_vcard(lf); + if (!vcard) { + return; + } + + linphone_vcard_add_phone_number(vcard, phone); +} + +MSList* linphone_friend_get_phone_numbers(LinphoneFriend *lf) { + LinphoneVcard *vcard = NULL; + + if (!lf) { + return NULL; + } + + vcard = linphone_friend_get_vcard(lf); + if (!vcard) { + return NULL; + } + + return linphone_vcard_get_phone_numbers(vcard); +} + +void linphone_friend_remove_phone_number(LinphoneFriend *lf, const char *phone) { + LinphoneVcard *vcard = NULL; + if (!lf || !phone) { + return; + } + + vcard = linphone_friend_get_vcard(lf); + if (!vcard) { + return; + } + + linphone_vcard_remove_phone_number(vcard, phone); +} + int linphone_friend_set_name(LinphoneFriend *lf, const char *name){ LinphoneAddress *fr = lf->uri; LinphoneVcard *vcard = NULL; @@ -334,10 +438,6 @@ static belle_sip_error_code _linphone_friend_marshall(belle_sip_object_t *obj, c return err; } -const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf){ - return lf->uri; -} - const char * linphone_friend_get_name(const LinphoneFriend *lf) { if (lf && lf->vcard) { return linphone_vcard_get_full_name(lf->vcard); @@ -915,6 +1015,7 @@ LinphoneFriend *linphone_friend_new_from_vcard(LinphoneVcard *vcard) { linphone_friend_set_address(fr, linphone_address); linphone_address_unref(linphone_address); } + ms_free(sipAddresses); } if (name) { linphone_friend_set_name(fr, name); diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 7a0f504bb..0331ba033 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -3442,8 +3442,72 @@ extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_updateSubscription linphone_friend_list_update_subscriptions((LinphoneFriendList*)friendListptr, (LinphoneProxyConfig*)proxyConfigPtr, jonlyWhenRegistered); } +extern "C" jlongArray Java_org_linphone_core_LinphoneFriendImpl_getAddresses(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + MSList *addresses = linphone_friend_get_addresses((LinphoneFriend*)ptr); + int size = ms_list_size(addresses); + jlongArray jaddresses = env->NewLongArray(size); + jlong *jInternalArray = env->GetLongArrayElements(jaddresses, NULL); + for (int i = 0; i < size; i++) { + jInternalArray[i] = (unsigned long) (addresses->data); + addresses = ms_list_next(addresses); + } + ms_list_free(addresses); + env->ReleaseLongArrayElements(jaddresses, jInternalArray, 0); + return jaddresses; +} +extern "C" void Java_org_linphone_core_LinphoneFriendImpl_addAddress(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jlong jaddress) { + linphone_friend_add_address((LinphoneFriend*)ptr, (LinphoneAddress*)jaddress); +} +extern "C" void Java_org_linphone_core_LinphoneFriendImpl_removeAddress(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jlong jaddress) { + linphone_friend_remove_address((LinphoneFriend*)ptr, (LinphoneAddress*)jaddress); +} + +extern "C" jobjectArray Java_org_linphone_core_LinphoneFriendImpl_getPhoneNumbers(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + MSList *phone_numbers = linphone_friend_get_phone_numbers((LinphoneFriend*)ptr); + int size = ms_list_size(phone_numbers); + jobjectArray jphonenumbers = env->NewObjectArray(size, env->FindClass("java/lang/String"), env->NewStringUTF("")); + for (int i = 0; i < size; i++) { + const char *phone = (const char *)phone_numbers->data; + env->SetObjectArrayElement(jphonenumbers, i, env->NewStringUTF(phone)); + phone_numbers = ms_list_next(phone_numbers); + } + ms_list_free(phone_numbers); + return jphonenumbers; +} + +extern "C" void Java_org_linphone_core_LinphoneFriendImpl_addPhoneNumber(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jstring jphone) { + if (jphone) { + const char* phone = env->GetStringUTFChars(jphone, NULL); + linphone_friend_add_phone_number((LinphoneFriend*)ptr, phone); + env->ReleaseStringUTFChars(jphone, phone); + } +} + +extern "C" void Java_org_linphone_core_LinphoneFriendImpl_removePhoneNumber(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jstring jphone) { + if (jphone) { + const char* phone = env->GetStringUTFChars(jphone, NULL); + linphone_friend_remove_phone_number((LinphoneFriend*)ptr, phone); + env->ReleaseStringUTFChars(jphone, phone); + } +} extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_getAddress(JNIEnv* env ,jobject thiz diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index 5488a1358..dac4afa24 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -162,7 +162,49 @@ LINPHONE_PUBLIC int linphone_friend_set_address(LinphoneFriend *fr, const Linpho * @param lf #LinphoneFriend object * @return #LinphoneAddress */ -LINPHONE_PUBLIC const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf); +LINPHONE_PUBLIC const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf); + +/** + * Adds an address in this friend + * @param lf #LinphoneFriend object + * @param addr #LinphoneAddress object + */ +LINPHONE_PUBLIC void linphone_friend_add_address(LinphoneFriend *lf, const LinphoneAddress *addr); + +/** + * Returns a list of #LinphoneAddress for this friend + * @param lf #LinphoneFriend object + * @return \mslist{LinphoneAddress} + */ +LINPHONE_PUBLIC MSList* linphone_friend_get_addresses(LinphoneFriend *lf); + +/** + * Removes an address in this friend + * @param lf #LinphoneFriend object + * @param addr #LinphoneAddress object + */ +LINPHONE_PUBLIC void linphone_friend_remove_address(LinphoneFriend *lf, const LinphoneAddress *addr); + +/** + * Adds a phone number in this friend + * @param lf #LinphoneFriend object + * @param phone number to add + */ +LINPHONE_PUBLIC void linphone_friend_add_phone_number(LinphoneFriend *lf, const char *phone); + +/** + * Returns a list of phone numbers for this friend + * @param lf #LinphoneFriend object + * @return a MSList of phone numbers + */ +LINPHONE_PUBLIC MSList* linphone_friend_get_phone_numbers(LinphoneFriend *lf); + +/** + * Removes a phone number in this friend + * @param lf #LinphoneFriend object + * @param phone number to remove + */ +LINPHONE_PUBLIC void linphone_friend_remove_phone_number(LinphoneFriend *lf, const char *phone); /** * Set the display name for this friend diff --git a/coreapi/vcard.cc b/coreapi/vcard.cc index 635312069..2623c241f 100644 --- a/coreapi/vcard.cc +++ b/coreapi/vcard.cc @@ -163,6 +163,37 @@ MSList* linphone_vcard_get_sip_addresses(const LinphoneVcard *vCard) { return result; } +void linphone_vcard_add_phone_number(LinphoneVcard *vCard, const char *phone) { + if (!vCard || !phone) return; + + shared_ptr phone_number = belcard::BelCardGeneric::create(); + phone_number->setValue(phone); + vCard->belCard->addPhoneNumber(phone_number); +} + +void linphone_vcard_remove_phone_number(LinphoneVcard *vCard, const char *phone) { + if (!vCard) return; + + for (auto it = vCard->belCard->getPhoneNumbers().begin(); it != vCard->belCard->getPhoneNumbers().end(); ++it) { + const char *value = (*it)->getValue().c_str(); + if (strcmp(value, phone) == 0) { + vCard->belCard->removePhoneNumber(*it); + break; + } + } +} + +MSList* linphone_vcard_get_phone_numbers(const LinphoneVcard *vCard) { + MSList *result = NULL; + if (!vCard) return NULL; + + for (auto it = vCard->belCard->getPhoneNumbers().begin(); it != vCard->belCard->getPhoneNumbers().end(); ++it) { + const char *value = (*it)->getValue().c_str(); + result = ms_list_append(result, (char *)value); + } + return result; +} + void linphone_vcard_set_organization(LinphoneVcard *vCard, const char *organization) { if (!vCard) return; diff --git a/coreapi/vcard.h b/coreapi/vcard.h index 71e5440e7..7948fbd11 100644 --- a/coreapi/vcard.h +++ b/coreapi/vcard.h @@ -122,6 +122,34 @@ void linphone_vcard_edit_main_sip_address(LinphoneVcard *vCard, const char *sip_ */ LINPHONE_PUBLIC MSList* linphone_vcard_get_sip_addresses(const LinphoneVcard *vCard); +/** + * Adds a phone number in the vCard, using the TEL property + * @param[in] vCard the LinphoneVcard + * @param[in] sip_address the phone number to add + */ +void linphone_vcard_add_phone_number(LinphoneVcard *vCard, const char *phone); + +/** + * Removes a phone number in the vCard (if it exists), using the TEL property + * @param[in] vCard the LinphoneVcard + * @param[in] sip_address the phone number to remove + */ +void linphone_vcard_remove_phone_number(LinphoneVcard *vCard, const char *phone); + +/** + * Returns the list of phone numbers (as string) in the vCard (all the TEL attributes) or NULL + * @param[in] vCard the LinphoneVcard + * @return \mslist{const char *} + */ +LINPHONE_PUBLIC MSList* linphone_vcard_get_phone_numbers(const LinphoneVcard *vCard); + +/** + * Returns the list of SIP addresses (as string) in the vCard (all the IMPP attributes that has an URI value starting by "sip:") or NULL + * @param[in] vCard the LinphoneVcard + * @return \mslist{const char *} + */ +LINPHONE_PUBLIC MSList* linphone_vcard_get_sip_addresses(const LinphoneVcard *vCard); + /** * Fills the Organization field of the vCard * @param[in] vCard the LinphoneVcard diff --git a/coreapi/vcard_stubs.c b/coreapi/vcard_stubs.c index 6e9a33a3b..0a0fa20ae 100644 --- a/coreapi/vcard_stubs.c +++ b/coreapi/vcard_stubs.c @@ -71,6 +71,18 @@ MSList* linphone_vcard_get_sip_addresses(const LinphoneVcard *vCard) { return NULL; } +void linphone_vcard_add_phone_number(LinphoneVcard *vCard, const char *phone) { + +} + +void linphone_vcard_remove_phone_number(LinphoneVcard *vCard, const char *phone) { + +} + +MSList* linphone_vcard_get_phone_numbers(const LinphoneVcard *vCard) { + return NULL; +} + void linphone_vcard_set_organization(LinphoneVcard *vCard, const char *organization) { } diff --git a/java/common/org/linphone/core/LinphoneFriend.java b/java/common/org/linphone/core/LinphoneFriend.java index af55605a6..a44b2546e 100644 --- a/java/common/org/linphone/core/LinphoneFriend.java +++ b/java/common/org/linphone/core/LinphoneFriend.java @@ -165,4 +165,12 @@ public interface LinphoneFriend { * @return */ String getOrganization(); + + LinphoneAddress[] getAddresses(); + void addAddress(LinphoneAddress addr); + void removeAddress(LinphoneAddress addr); + + String[] getPhoneNumbers(); + void addPhoneNumber(String phone); + void removePhoneNumber(String phone); } diff --git a/java/impl/org/linphone/core/LinphoneFriendImpl.java b/java/impl/org/linphone/core/LinphoneFriendImpl.java index 3cc45ec21..86240d8c9 100644 --- a/java/impl/org/linphone/core/LinphoneFriendImpl.java +++ b/java/impl/org/linphone/core/LinphoneFriendImpl.java @@ -146,4 +146,54 @@ class LinphoneFriendImpl implements LinphoneFriend, Serializable { public String getOrganization() { return getOrganization(nativePtr); } + + private native long[] getAddresses(long nativePtr); + @Override + public LinphoneAddress[] getAddresses() { + long[] ptrs = getAddresses(nativePtr); + if (ptrs == null) return null; + + LinphoneAddress[] addresses = new LinphoneAddress[ptrs.length]; + for (int i = 0; i < addresses.length; i++) { + addresses[i] = new LinphoneAddressImpl(ptrs[i], LinphoneAddressImpl.WrapMode.FromConst); + } + return addresses; + } + + private native void addAddress(long nativePtr, long addr); + @Override + public void addAddress(LinphoneAddress addr) { + addAddress(nativePtr, ((LinphoneAddressImpl)addr).nativePtr); + } + + private native void removeAddress(long nativePtr, long addr); + @Override + public void removeAddress(LinphoneAddress addr) { + removeAddress(nativePtr, ((LinphoneAddressImpl)addr).nativePtr); + } + + private native Object[] getPhoneNumbers(long nativePtr); + @Override + public String[] getPhoneNumbers() { + Object[] phones = getPhoneNumbers(nativePtr); + if (phones == null) return null; + + String[] phoneNumbers = new String[phones.length]; + for (int i = 0; i < phones.length; i++) { + phoneNumbers[i] = phones[i].toString(); + } + return phoneNumbers; + } + + private native void addPhoneNumber(long nativePtr, String phone); + @Override + public void addPhoneNumber(String phone) { + addPhoneNumber(nativePtr, phone); + } + + private native void removePhoneNumber(long nativePtr, String phone); + @Override + public void removePhoneNumber(String phone) { + removePhoneNumber(nativePtr, phone); + } } diff --git a/tester/vcard_tester.c b/tester/vcard_tester.c index 496fb3604..5bb38fb22 100644 --- a/tester/vcard_tester.c +++ b/tester/vcard_tester.c @@ -129,6 +129,63 @@ static void linphone_vcard_update_existing_friends_test(void) { lf = NULL; } +static void linphone_vcard_phone_numbers_and_sip_addresses(void) { + LinphoneVcard *lvc = linphone_vcard_new_from_vcard4_buffer("BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nIMPP;TYPE=home:sip:sylvain@sip.linphone.org\r\nTEL;TYPE=work:0952636505\r\nEND:VCARD\r\n"); + LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); + MSList *sip_addresses = linphone_friend_get_addresses(lf); + MSList *phone_numbers = linphone_friend_get_phone_numbers(lf); + LinphoneAddress *addr = NULL; + + BC_ASSERT_EQUAL(ms_list_size(sip_addresses), 2, int, "%i"); + BC_ASSERT_EQUAL(ms_list_size(phone_numbers), 1, int, "%i"); + if (sip_addresses) ms_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); + if (phone_numbers) ms_list_free(phone_numbers); + linphone_friend_unref(lf); + + lvc = linphone_vcard_new_from_vcard4_buffer("BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nTEL;TYPE=work:0952636505\r\nTEL:0476010203\r\nEND:VCARD\r\n"); + lf = linphone_friend_new_from_vcard(lvc); + sip_addresses = linphone_friend_get_addresses(lf); + phone_numbers = linphone_friend_get_phone_numbers(lf); + + BC_ASSERT_EQUAL(ms_list_size(sip_addresses), 0, int, "%i"); + BC_ASSERT_EQUAL(ms_list_size(phone_numbers), 2, int, "%i"); + if (sip_addresses) ms_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); + if (phone_numbers) ms_list_free(phone_numbers); + + addr = linphone_address_new("sip:sylvain@sip.linphone.org"); + linphone_friend_add_address(lf, addr); + linphone_address_unref(addr); + sip_addresses = linphone_friend_get_addresses(lf); + BC_ASSERT_EQUAL(ms_list_size(sip_addresses), 1, int, "%i"); + if (sip_addresses) ms_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); + + linphone_friend_remove_phone_number(lf, "0952636505"); + phone_numbers = linphone_friend_get_phone_numbers(lf); + BC_ASSERT_EQUAL(ms_list_size(phone_numbers), 1, int, "%i"); + if (phone_numbers) ms_list_free(phone_numbers); + + linphone_friend_remove_phone_number(lf, "0476010203"); + phone_numbers = linphone_friend_get_phone_numbers(lf); + BC_ASSERT_EQUAL(ms_list_size(phone_numbers), 0, int, "%i"); + if (phone_numbers) ms_list_free(phone_numbers); + + addr = linphone_address_new("sip:sylvain@sip.linphone.org"); + linphone_friend_remove_address(lf, addr); + linphone_address_unref(addr); + sip_addresses = linphone_friend_get_addresses(lf); + BC_ASSERT_EQUAL(ms_list_size(sip_addresses), 0, int, "%i"); + if (sip_addresses) ms_list_free_with_data(sip_addresses, (void (*)(void *))linphone_address_unref); + + linphone_friend_add_phone_number(lf, "+33952636505"); + phone_numbers = linphone_friend_get_phone_numbers(lf); + BC_ASSERT_EQUAL(ms_list_size(phone_numbers), 1, int, "%i"); + if (phone_numbers) ms_list_free(phone_numbers); + + linphone_friend_unref(lf); + lf = NULL; + lvc = NULL; +} + static void friends_if_no_db_set(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); LinphoneFriend *lf = linphone_core_create_friend(manager->lc); @@ -663,6 +720,7 @@ test_t vcard_tests[] = { { "Import / Export friends from vCards", linphone_vcard_import_export_friends_test }, { "Import a lot of friends from vCards", linphone_vcard_import_a_lot_of_friends_test }, { "vCard creation for existing friends", linphone_vcard_update_existing_friends_test }, + { "vCard phone numbers and SIP addresses", linphone_vcard_phone_numbers_and_sip_addresses }, #ifdef FRIENDS_SQL_STORAGE_ENABLED { "Friends working if no db set", friends_if_no_db_set }, { "Friends storage migration from rc to db", friends_migration },