diff --git a/src/search/magic-search.cpp b/src/search/magic-search.cpp index df23ef61c..951bbcc6b 100644 --- a/src/search/magic-search.cpp +++ b/src/search/magic-search.cpp @@ -154,19 +154,36 @@ void MagicSearch::setSearchCache(list *cache) { list *MagicSearch::beginNewSearch(const string &filter, const string &withDomain) { list *resultList = new list(); - LinphoneFriendList* list = linphone_core_get_default_friend_list(this->getCore()->getCCore()); + LinphoneFriendList *list = linphone_core_get_default_friend_list(this->getCore()->getCCore()); + const bctbx_list_t *callLog = linphone_core_get_call_logs(this->getCore()->getCCore()); // For all friends or when we reach the search limit for (bctbx_list_t *f = list->friends; f != nullptr && (!getLimitedSearch() || resultList->size() < getSearchLimit()); - f = bctbx_list_next(f) + f = bctbx_list_next(f) ) { - SearchResult result = search(reinterpret_cast(f->data), filter, withDomain); + SearchResult result = searchInFriend(reinterpret_cast(f->data), filter, withDomain); if (result.getWeight() > getMinWeight()) { resultList->push_back(result); } } + // For all call log or when we reach the search limit + for (const bctbx_list_t *f = callLog; + f != nullptr && (!getLimitedSearch() || resultList->size() < getSearchLimit()); + f = bctbx_list_next(f) + ) { + LinphoneCallLog *log = reinterpret_cast(f->data); + const LinphoneAddress *addr = (linphone_call_log_get_dir(log) == LinphoneCallDir::LinphoneCallIncoming) ? + linphone_call_log_get_from_address(log) : linphone_call_log_get_to_address(log); + if (addr) { + unsigned int weight = searchInAddress(addr, filter, withDomain); + if (weight > getMinWeight()) { + resultList->push_back(SearchResult(weight, addr, nullptr)); + } + } + } + return resultList; } @@ -176,7 +193,7 @@ list *MagicSearch::continueSearch(const string &filter, const stri for (const auto sr : *cacheList) { if (sr.getFriend()) { - SearchResult result = search(sr.getFriend(), filter, withDomain); + SearchResult result = searchInFriend(sr.getFriend(), filter, withDomain); if (result.getWeight() > getMinWeight()) { resultList->push_back(result); } @@ -186,39 +203,20 @@ list *MagicSearch::continueSearch(const string &filter, const stri return resultList; } -SearchResult MagicSearch::search(const LinphoneFriend* lFriend, const string &filter, const string &withDomain) { +SearchResult MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const string &filter, const string &withDomain) { unsigned int weight = getMinWeight(); const LinphoneAddress* lAddress = linphone_friend_get_address(lFriend); - bool allDomain = !withDomain.empty() && withDomain.compare("*") == 0; - if (allDomain && - lAddress == nullptr && - linphone_friend_get_presence_model(lFriend) == nullptr - ) return SearchResult(weight, nullptr); - - // Check domain - if (!allDomain && - !withDomain.empty() && - lAddress != nullptr && - withDomain.compare(linphone_address_get_domain(lAddress)) != 0 - ) return SearchResult(weight, nullptr); - - if (lAddress != nullptr) { - // SIPURI - if (linphone_address_get_username(lAddress) != nullptr) { - weight += getWeight(linphone_address_get_username(lAddress), filter); - } - // DISPLAYNAME - if (linphone_address_get_display_name(lAddress) != nullptr) { - weight += getWeight(linphone_address_get_display_name(lAddress), filter); - } - } + if (!checkDomain(lFriend, lAddress, withDomain)) return SearchResult(weight, nullptr); // NAME if (linphone_friend_get_name(lFriend) != nullptr) { weight += getWeight(linphone_friend_get_name(lFriend), filter); } + //SIP URI + weight += searchInAddress(lAddress, filter, withDomain); + // PHONE NUMBER bctbx_list_t *begin, *phoneNumbers = linphone_friend_get_phone_numbers(lFriend); begin = phoneNumbers; @@ -236,6 +234,21 @@ SearchResult MagicSearch::search(const LinphoneFriend* lFriend, const string &fi return SearchResult(weight, lAddress, lFriend); } +unsigned int MagicSearch::searchInAddress(const LinphoneAddress *lAddress, const string &filter, const string &withDomain) { + unsigned int weight = getMinWeight(); + if (lAddress != nullptr && checkDomain(nullptr, lAddress, withDomain)) { + // SIPURI + if (linphone_address_get_username(lAddress) != nullptr) { + weight += getWeight(linphone_address_get_username(lAddress), filter); + } + // DISPLAYNAME + if (linphone_address_get_display_name(lAddress) != nullptr) { + weight += getWeight(linphone_address_get_display_name(lAddress), filter); + } + } + return weight; +} + unsigned int MagicSearch::getWeight(const string &stringWords, const string &filter) const { size_t weight = string::npos; @@ -271,4 +284,22 @@ unsigned int MagicSearch::getWeight(const string &stringWords, const string &fil return (weight != string::npos) ? (unsigned int)(weight) : getMinWeight(); } +bool MagicSearch::checkDomain(const LinphoneFriend *lFriend, const LinphoneAddress *lAddress, const string &withDomain) const { + bool onlySipUri = !withDomain.empty() && withDomain.compare("*") != 0; + const LinphonePresenceModel *presenceModel = (lFriend) ? linphone_friend_get_presence_model(lFriend) : nullptr; + const char *contactPresence = (presenceModel) ? linphone_presence_model_get_contact(presenceModel) : nullptr; + const LinphoneAddress *addrPresence = (contactPresence) ? + linphone_core_create_address(this->getCore()->getCCore(), contactPresence) : nullptr; + + return ( + // If we don't want Sip URI only or Address or Presence model + (!onlySipUri || lAddress != nullptr || presenceModel != nullptr) && + // And If we don't want Sip URI only or Address match or Address presence match + (!onlySipUri || + (lAddress != nullptr && withDomain.compare(linphone_address_get_domain(lAddress)) == 0) || + (addrPresence != nullptr && withDomain.compare(linphone_address_get_domain(addrPresence)) == 0) + ) + ); +} + LINPHONE_END_NAMESPACE diff --git a/src/search/magic-search.h b/src/search/magic-search.h index e360ea249..3776af288 100644 --- a/src/search/magic-search.h +++ b/src/search/magic-search.h @@ -156,13 +156,22 @@ private: std::list *continueSearch(const std::string &filter, const std::string &withDomain); /** - * Continue the search from the cache of precedent search + * Search informations in friend given * @param[in] lFriend friend whose informations will be check * @param[in] filter word we search * @param[in] withDomain domain which we want to search only * @private **/ - SearchResult search(const LinphoneFriend* lFriend, const std::string &filter, const std::string &withDomain); + SearchResult searchInFriend(const LinphoneFriend* lFriend, const std::string &filter, const std::string &withDomain); + + /** + * Search informations in address given + * @param[in] lAddress address whose informations will be check + * @param[in] filter word we search + * @param[in] withDomain domain which we want to search only + * @private + **/ + unsigned int searchInAddress(const LinphoneAddress *lAddress, const std::string &filter, const std::string &withDomain); /** * Return a weight for a searched in with a filter @@ -173,6 +182,15 @@ private: **/ unsigned int getWeight(const std::string &stringWords, const std::string &filter) const; + /** + * Return if the given address match domain policy + * @param[in] lFriend friend whose domain will be check + * @param[in] lAddress address whose domain will be check + * @param[in] withDomain domain policy + * @private + **/ + bool checkDomain(const LinphoneFriend* lFriend, const LinphoneAddress *lAddress, const std::string &withDomain) const; + L_DECLARE_PRIVATE(MagicSearch); }; diff --git a/tester/setup_tester.c b/tester/setup_tester.c index 692e1b5a8..7e1e90adc 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -28,8 +28,8 @@ #define S_SIZE_FRIEND 12 static const unsigned int sSizeFriend = S_SIZE_FRIEND; static const char *sFriends[S_SIZE_FRIEND] = { - "sip:test@sip.example.org",//0 - "sip:test2@sip.example.org",//1 + "sip:charu@sip.test.org",//0 + "sip:charette@sip.example.org",//1 "sip:allo@sip.example.org",//2 "sip:hello@sip.example.org",//3 "sip:hello@sip.test.org",//4 @@ -56,10 +56,13 @@ static void _remove_friends_from_list(LinphoneFriendList *list, const char *frie } } -static void _check_friend_result_list(const bctbx_list_t *resultList, const unsigned int index, const char* uri, const char* phone) { +static void _check_friend_result_list(LinphoneCore *lc, const bctbx_list_t *resultList, const unsigned int index, const char* uri, const char* phone) { + if (index >= bctbx_list_size(resultList)) { + ms_error("Attempt to access result to an outbound index"); + return; + } const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, index); const LinphoneFriend *lf = linphone_search_result_get_friend(sr); - BC_ASSERT_PTR_NOT_NULL(lf); if (lf != NULL) { const LinphoneAddress *la = linphone_friend_get_address(lf); if (la != NULL) { @@ -77,10 +80,29 @@ static void _check_friend_result_list(const bctbx_list_t *resultList, const unsi return; } } + } else { + const bctbx_list_t *callLog = linphone_core_get_call_logs(lc); + for (const bctbx_list_t *f = callLog ; f != NULL ; f = bctbx_list_next(f)) { + LinphoneCallLog *log = (LinphoneCallLog*)(f->data); + const LinphoneAddress *addr = (linphone_call_log_get_dir(log) == LinphoneCallIncoming) ? + linphone_call_log_get_from_address(log) : linphone_call_log_get_to_address(log); + if (addr) { + char *addrUri = linphone_address_as_string_uri_only(addr); + if (addrUri && strcmp(addrUri, uri) == 0) { + return; + } + if (addrUri) free(addrUri); + } + } } + BC_ASSERT(FALSE); ms_error("Address NULL and Presence NULL"); } +static void _create_call_log(LinphoneCore *lc, LinphoneAddress *addrFrom, LinphoneAddress *addrTo) { + linphone_core_create_call_log(lc, addrFrom, addrTo, LinphoneCallOutgoing, 100, time(NULL), time(NULL), LinphoneCallSuccess, FALSE, 1.0); +} + static void linphone_version_test(void){ const char *version=linphone_core_get_version(); /*make sure the git version is always included in the version number*/ @@ -467,9 +489,9 @@ static void search_friend_all_domains(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 3, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[2], NULL);//"sip:allo@sip.example.org" - _check_friend_result_list(resultList, 1, sFriends[3], NULL);//"sip:hello@sip.example.org" - _check_friend_result_list(resultList, 2, sFriends[4], NULL);//"sip:hello@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[3], NULL);//"sip:hello@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[4], NULL);//"sip:hello@sip.test.org" } free(resultList); @@ -495,8 +517,8 @@ static void search_friend_one_domain(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[2], NULL);//"sip:allo@sip.example.org" - _check_friend_result_list(resultList, 1, sFriends[3], NULL);//"sip:hello@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[3], NULL);//"sip:hello@sip.example.org" } free(resultList); @@ -522,13 +544,13 @@ static void search_friend_research_estate(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 7, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" - _check_friend_result_list(resultList, 1, sFriends[7], NULL);//"sip:loic@sip.example.org" - _check_friend_result_list(resultList, 2, sFriends[8], NULL);//"sip:laure@sip.test.org" - _check_friend_result_list(resultList, 3, sFriends[9], NULL);//"sip:loic@sip.test.org" - _check_friend_result_list(resultList, 4, sFriends[2], NULL);//"sip:allo@sip.example.org" - _check_friend_result_list(resultList, 5, sFriends[3], NULL);//"sip:hello@sip.example.org" - _check_friend_result_list(resultList, 6, sFriends[4], NULL);//"sip:hello@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[7], NULL);//"sip:loic@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 3, sFriends[9], NULL);//"sip:loic@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 4, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 5, sFriends[3], NULL);//"sip:hello@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 6, sFriends[4], NULL);//"sip:hello@sip.test.org" } free(resultList); @@ -539,8 +561,8 @@ static void search_friend_research_estate(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[8], NULL);//"sip:laure@sip.test.org" - _check_friend_result_list(resultList, 1, sFriends[6], NULL);//"sip:laura@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[6], NULL);//"sip:laura@sip.example.org" } free(resultList); @@ -566,8 +588,8 @@ static void search_friend_research_estate_reset(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" - _check_friend_result_list(resultList, 1, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[8], NULL);//"sip:laure@sip.test.org" } free(resultList); @@ -580,13 +602,13 @@ static void search_friend_research_estate_reset(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 7, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" - _check_friend_result_list(resultList, 1, sFriends[7], NULL);//"sip:loic@sip.example.org" - _check_friend_result_list(resultList, 2, sFriends[8], NULL);//"sip:laure@sip.test.org" - _check_friend_result_list(resultList, 3, sFriends[9], NULL);//"sip:loic@sip.test.org" - _check_friend_result_list(resultList, 4, sFriends[2], NULL);//"sip:allo@sip.example.org" - _check_friend_result_list(resultList, 5, sFriends[3], NULL);//"sip:hello@sip.example.org" - _check_friend_result_list(resultList, 6, sFriends[4], NULL);//"sip:hello@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[7], NULL);//"sip:loic@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 3, sFriends[9], NULL);//"sip:loic@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 4, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 5, sFriends[3], NULL);//"sip:hello@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 6, sFriends[4], NULL);//"sip:hello@sip.test.org" } free(resultList); @@ -616,9 +638,9 @@ static void search_friend_with_phone_number(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 3, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[11], NULL);//"sip:+111223344@sip.example.org" - _check_friend_result_list(resultList, 1, sFriends[10], NULL);//"sip:+33655667788@sip.example.org" - _check_friend_result_list(resultList, 2, sFriends[5], NULL);//"sip:marie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+111223344@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[10], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[5], NULL);//"sip:marie@sip.example.org" } free(resultList); @@ -658,9 +680,9 @@ static void search_friend_with_presence(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 3, int, "%d"); - _check_friend_result_list(resultList, 0, sFriends[11], NULL);//"sip:+111223344@sip.example.org" - _check_friend_result_list(resultList, 1, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org" - _check_friend_result_list(resultList, 2, sFriends[10], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+111223344@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[10], NULL);//"sip:+33655667788@sip.example.org" } free(resultList); @@ -673,7 +695,7 @@ static void search_friend_with_presence(void) { if (resultList != NULL) { BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d"); - _check_friend_result_list(resultList, 0, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, chloePhoneNumber);//"sip:chloe@sip.example.org" } free(resultList); @@ -687,6 +709,61 @@ static void search_friend_with_presence(void) { linphone_core_manager_destroy(manager); } +static void search_friend_in_call_log(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *chloeSipUri = {"sip:chloe@sip.example.org"}; + const char *benjaminSipUri = {"sip:benjamin@sip.example.org"}; + const char *charlesSipUri = {"sip:charles@sip.test.org"}; + const char *ronanSipUri = {"sip:ronan@sip.example.org"}; + LinphoneAddress *chloeAddress = linphone_address_new(chloeSipUri); + LinphoneAddress *benjaminAddress = linphone_address_new(benjaminSipUri); + LinphoneAddress *charlesAddress = linphone_address_new(charlesSipUri); + LinphoneAddress *ronanAddress = linphone_address_new(ronanSipUri); + + _create_call_log(manager->lc, ronanAddress, chloeAddress); + _create_call_log(manager->lc, ronanAddress, charlesAddress); + _create_call_log(manager->lc, ronanAddress, benjaminAddress); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "ch", ""); + + BC_ASSERT_PTR_NOT_NULL(resultList); + + if (resultList != NULL) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[1], NULL);//"sip:charette@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, chloeSipUri, NULL);//"sip:chloe@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, charlesSipUri, NULL);//"sip:charles@sip.test.org" + } + + free(resultList); + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "ch", "sip.test.org"); + + BC_ASSERT_PTR_NOT_NULL(resultList); + + if (resultList != NULL) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, charlesSipUri, NULL);//"sip:charles@sip.test.org" + } + + free(resultList); + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_core_manager_destroy(manager); +} + static void search_friend_large_database(void) { MSTimeSpec start, current; LinphoneMagicSearch *magicSearch = NULL; @@ -739,7 +816,8 @@ test_t setup_tests[] = { TEST_TWO_TAGS("Multiple looking for friends with cache resetting", search_friend_research_estate_reset, "MagicSearch", "LeaksMemory"), TEST_TWO_TAGS("Search friend with phone number", search_friend_with_phone_number, "MagicSearch", "LeaksMemory"), TEST_TWO_TAGS("Search friend and find it with its presence", search_friend_with_presence, "MagicSearch", "LeaksMemory"), - TEST_TWO_TAGS("search friend in large friends database", search_friend_large_database, "MagicSearch", "LeaksMemory") + TEST_TWO_TAGS("Search friend in call log", search_friend_in_call_log, "MagicSearch", "LeaksMemory"), + TEST_TWO_TAGS("Search friend in large friends database", search_friend_large_database, "MagicSearch", "LeaksMemory") }; test_suite_t setup_test_suite = {"Setup", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,