From 0fc67d6c090bffac3bceefc5f9bfdec65cc86bac Mon Sep 17 00:00:00 2001
From: Leopold Chappuis <leopold.chappuis@savoirfairelinux.com>
Date: Wed, 20 Nov 2024 16:28:58 -0500
Subject: [PATCH] updateProfile: Resolved the issue of duplicate keys.

If another key includes "PHOTO" during the API update process, it must be removed.

Change-Id: Ic338263ec3966556c61e12752ccea91fb730b794
---
 src/jamidht/jamiaccount.cpp                     |  4 ++--
 src/sip/sipaccount.cpp                          |  2 ++
 src/string_utils.h                              |  6 ++++++
 src/vcard.cpp                                   | 12 +++++++++++-
 src/vcard.h                                     |  1 +
 test/unitTest/string_utils/testString_utils.cpp | 11 +++++++++++
 6 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 6795c1b29..64be3b823 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -3438,6 +3438,7 @@ JamiAccount::updateProfile(const std::string& displayName,
     emitSignal<libjami::ConfigurationSignal::AccountDetailsChanged>(getAccountID(),
                                                                     getAccountDetails());
     if (flag == 0) {
+        vCard::utils::removeByKey(profile, "PHOTO");
         const auto& avatarPath = std::filesystem::path(avatar);
         if (std::filesystem::exists(avatarPath)) {
             try {
@@ -3446,10 +3447,9 @@ JamiAccount::updateProfile(const std::string& displayName,
             } catch (const std::exception& e) {
                 JAMI_ERROR("Failed to load avatar: {}", e.what());
             }
-        } else if (avatarPath.empty()) {
-            profile["PHOTO;ENCODING=BASE64;TYPE=PNG"] = "";
         }
     } else if (flag == 1) {
+        vCard::utils::removeByKey(profile, "PHOTO");
         profile["PHOTO;ENCODING=BASE64;TYPE=PNG"] = avatar;
     }
 
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index d5778cd98..735138bc5 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -159,6 +159,7 @@ SIPAccount::updateProfile(const std::string& displayName,
     profile["FN"] = displayName;
 
     if (flag == 0) {
+        vCard::utils::removeByKey(profile, "PHOTO");
         const auto& avatarPath = std::filesystem::path(avatar);
         if (std::filesystem::exists(avatarPath)) {
             try {
@@ -167,6 +168,7 @@ SIPAccount::updateProfile(const std::string& displayName,
                 JAMI_ERROR("Failed to load avatar: {}", e.what());
             }
         } else if (avatarPath.empty()) {
+            vCard::utils::removeByKey(profile, "PHOTO");
             profile["PHOTO;ENCODING=BASE64;TYPE=PNG"] = "";
         }
     } else if (flag == 1) {
diff --git a/src/string_utils.h b/src/string_utils.h
index fb589f175..eb396a111 100644
--- a/src/string_utils.h
+++ b/src/string_utils.h
@@ -133,6 +133,12 @@ stod(const std::string& str)
     return std::stod(str);
 }
 
+static inline bool
+starts_with(std::string_view str, std::string_view prefix)
+{
+    return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
+}
+
 template<typename... Args>
 std::string concat(Args &&... args){
     static_assert((std::is_constructible_v<std::string_view, Args&&> && ...));
diff --git a/src/vcard.cpp b/src/vcard.cpp
index a99319684..8e0936013 100644
--- a/src/vcard.cpp
+++ b/src/vcard.cpp
@@ -76,6 +76,16 @@ toString(const std::map<std::string, std::string>& vCard)
     return result;
 }
 
-} // namespace utils
+void
+removeByKey(std::map<std::string, std::string>& vCard, std::string_view key) {
+    for (auto it = vCard.begin(); it != vCard.end(); ) {
+        if (jami::starts_with(it->first, key)) {
+            it = vCard.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
 
+} // namespace utils
 } // namespace vCard
diff --git a/src/vcard.h b/src/vcard.h
index 322e77926..37596092e 100644
--- a/src/vcard.h
+++ b/src/vcard.h
@@ -90,6 +90,7 @@ namespace utils {
 std::map<std::string, std::string> toMap(std::string_view content);
 std::map<std::string, std::string> initVcard();
 std::string toString(const std::map<std::string, std::string>& vCard);
+void removeByKey(std::map<std::string, std::string>& vCard, std::string_view key);
 
 } // namespace utils
 
diff --git a/test/unitTest/string_utils/testString_utils.cpp b/test/unitTest/string_utils/testString_utils.cpp
index 4291a77fd..be21f47be 100644
--- a/test/unitTest/string_utils/testString_utils.cpp
+++ b/test/unitTest/string_utils/testString_utils.cpp
@@ -42,6 +42,7 @@ private:
     void to_string_test();
     void to_number_test();
     void split_string_test();
+    void starts_with_test();
     void version_test();
 
     CPPUNIT_TEST_SUITE(StringUtilsTest);
@@ -49,6 +50,7 @@ private:
     CPPUNIT_TEST(to_string_test);
     CPPUNIT_TEST(to_number_test);
     CPPUNIT_TEST(split_string_test);
+    CPPUNIT_TEST(starts_with_test);
     CPPUNIT_TEST(version_test);
     CPPUNIT_TEST_SUITE_END();
 
@@ -142,6 +144,15 @@ StringUtilsTest::version_test()
         split_string_to_unsigned("1.2.3.5", '.')));
 }
 
+void
+StringUtilsTest::starts_with_test()
+{
+    CPPUNIT_ASSERT(starts_with("test", "te"));
+    CPPUNIT_ASSERT(starts_with("test", "test"));
+    CPPUNIT_ASSERT(!starts_with("test", "testt"));
+    CPPUNIT_ASSERT(!starts_with("test", "es"));
+}
+
 } // namespace test
 } // namespace jami
 
-- 
GitLab