Skip to content
Snippets Groups Projects
Commit a1f07277 authored by Emmanuel Lepage Vallée's avatar Emmanuel Lepage Vallée Committed by Nicolas Jager
Browse files

contactMethod: Prevent duplication of registered name CMs


**WARNING** This makes the setRegisteredName method private and
thus break the API. That method could not stay public as this
would potentially corrupt the indexes.

This patch adds the registered names to the global name
directory. If `::getNumber()` is used with a known registered
name, no new CM are created.

This patch fixes the "most common" case, but doesn't implement the
following corner cases:

 * If the registered name is already part of the directory, but
   not fully linked to an account and/or RingId.
 * If there is multiple name service

For the multiple name service, the
`NameDirectory::registeredNameFound` signal will need to use full
URIs for the names (ring:foo@ns.ring.cx). This is out of this
patch scope and will have side effects that needs to be addressed
in each clients.

Change-Id: If06561dc4cb56453cc77092f4c30c633e852b7fd
Reviewed-by: default avatarNicolas Jäger <nicolas.jager@savoirfairelinux.com>
parent 44dcaf01
No related branches found
No related tags found
No related merge requests found
...@@ -91,6 +91,11 @@ void ContactMethodPrivate::rebased(ContactMethod* other) ...@@ -91,6 +91,11 @@ void ContactMethodPrivate::rebased(ContactMethod* other)
emit n->rebased(other); emit n->rebased(other);
} }
void ContactMethodPrivate::registeredNameSet(const QString& name)
{
foreach (ContactMethod* n, m_lParents)
emit n->registeredNameSet(name);
}
const ContactMethod* ContactMethod::BLANK() const ContactMethod* ContactMethod::BLANK()
{ {
...@@ -320,9 +325,24 @@ void ContactMethod::setTracked(bool track) ...@@ -320,9 +325,24 @@ void ContactMethod::setTracked(bool track)
} }
/// Set the registered name /// Set the registered name
void ContactMethod::setRegisteredName(const QString& registeredName) void ContactMethodPrivate::setRegisteredName(const QString& registeredName)
{ {
d_ptr->m_RegisteredName = registeredName; if (registeredName.isEmpty() || registeredName == m_RegisteredName)
return;
// If this happens, better create another ContactMethod manually to avoid
// all the corner cases. Doing this, for example, allows to keep track of
// the name in the private index of unique names kept by the
// PhoneDirectoryModel
if (!m_RegisteredName.isEmpty()) {
qWarning() << "A registered name is already set for this ContactMethod"
<< m_RegisteredName << registeredName;
return;
}
m_RegisteredName = registeredName;
registeredNameSet(registeredName);
changed();
} }
///Allow phonedirectorymodel to change presence status ///Allow phonedirectorymodel to change presence status
......
...@@ -88,7 +88,7 @@ public: ...@@ -88,7 +88,7 @@ public:
Q_PROPERTY(URI::ProtocolHint protocolHint READ protocolHint ) Q_PROPERTY(URI::ProtocolHint protocolHint READ protocolHint )
Q_PROPERTY(bool isReachable READ isReachable ) Q_PROPERTY(bool isReachable READ isReachable )
Q_PROPERTY(Certificate* certificate READ certificate ) Q_PROPERTY(Certificate* certificate READ certificate )
Q_PROPERTY(QString registeredName READ registeredName WRITE setRegisteredName ) Q_PROPERTY(QString registeredName READ registeredName NOTIFY registeredNameSet )
Q_PROPERTY(QString getBestId READ getBestId ) Q_PROPERTY(QString getBestId READ getBestId )
// Q_PROPERTY(QHash<QString,int> alternativeNames READ alternativeNames ) // Q_PROPERTY(QHash<QString,int> alternativeNames READ alternativeNames )
...@@ -145,7 +145,6 @@ public: ...@@ -145,7 +145,6 @@ public:
Q_INVOKABLE void setAccount (Account* account ); Q_INVOKABLE void setAccount (Account* account );
Q_INVOKABLE void setPerson (Person* contact ); Q_INVOKABLE void setPerson (Person* contact );
Q_INVOKABLE void setTracked (bool track ); Q_INVOKABLE void setTracked (bool track );
Q_INVOKABLE void setRegisteredName(const QString& registeredName);
void setCategory (NumberCategory* cat ); void setCategory (NumberCategory* cat );
void setBookmarked (bool bookmarked ); void setBookmarked (bool bookmarked );
void setUid (const QString& uri ); void setUid (const QString& uri );
...@@ -232,6 +231,8 @@ Q_SIGNALS: ...@@ -232,6 +231,8 @@ Q_SIGNALS:
void contactChanged(Person* newContact, Person* oldContact); void contactChanged(Person* newContact, Person* oldContact);
/// The number of unread text messages has changed /// The number of unread text messages has changed
void unreadTextMessageCountChanged(); void unreadTextMessageCountChanged();
/// When the registered name is set
void registeredNameSet(const QString& name);
}; };
Q_DECLARE_METATYPE(ContactMethod*) Q_DECLARE_METATYPE(ContactMethod*)
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "collectioninterface.h" #include "collectioninterface.h"
#include "dbus/presencemanager.h" #include "dbus/presencemanager.h"
#include "globalinstances.h" #include "globalinstances.h"
#include "private/contactmethod_p.h"
#include "interfaces/pixmapmanipulatori.h" #include "interfaces/pixmapmanipulatori.h"
#include "personmodel.h" #include "personmodel.h"
#include "dbus/configurationmanager.h" #include "dbus/configurationmanager.h"
...@@ -322,6 +323,7 @@ void PhoneDirectoryModelPrivate::setAccount(ContactMethod* number, Account* acco ...@@ -322,6 +323,7 @@ void PhoneDirectoryModelPrivate::setAccount(ContactMethod* number, Account* acco
wrap = new NumberWrapper(); wrap = new NumberWrapper();
m_hDirectory [extendedUri] = wrap; m_hDirectory [extendedUri] = wrap;
m_hSortedNumbers[extendedUri] = wrap; m_hSortedNumbers[extendedUri] = wrap;
wrap->numbers << number;
} }
else { else {
...@@ -817,13 +819,55 @@ PhoneDirectoryModelPrivate::slotRegisteredNameFound(const Account* account, Name ...@@ -817,13 +819,55 @@ PhoneDirectoryModelPrivate::slotRegisteredNameFound(const Account* account, Name
foreach (ContactMethod* cm, wrap->numbers) { foreach (ContactMethod* cm, wrap->numbers) {
if (cm->account() == account) { if (cm->account() == account) {
cm->incrementAlternativeName(name, QDateTime::currentDateTime().toTime_t()); cm->incrementAlternativeName(name, QDateTime::currentDateTime().toTime_t());
cm->setRegisteredName(name); cm->d_ptr->setRegisteredName(name);
// Add the CM to the directory using the registered name too.
// Note that in theory the wrapper can exist already if the
// user was either offline in a call attempt or if there is a
// collision with a SIP account.
if (!m_hDirectory.contains(name)) {
//TODO support multiple name service, use proper URIs for names
auto wrap2 = new NumberWrapper();
m_hDirectory [name] = wrap2;
m_hSortedNumbers[name] = wrap2;
wrap2->numbers << cm;
}
else {
auto wrapper = m_hDirectory.value(name);
// Merge the existing CMs now that it is known that the RingId match the username
foreach(ContactMethod* n, wrapper->numbers) {
// If the account is the same and (as we know) it is a registered name
// there is 100% porbability of match
const bool compAccount = n->account() &&
n->account() == cm->account();
// Less certain, but close enough. We have a contact with a phone
// number corresponding with a registeredName and `ring:` in front.
// it *could* use a different name service. Anyway, for now this
// isn't widespread enough to care.
const bool compContact = (!n->account()) && n->contact() &&
n->uri().schemeType() == URI::SchemeType::RING;
if (n != cm && (compAccount || compContact)) {
n->merge(cm);
}
}
}
// Only add it once
if (!m_hDirectory[name]->numbers.indexOf(cm)) {
//TODO check if some deduplication can be performed
m_hDirectory[name]->numbers << cm;
}
} else { } else {
qDebug() << "registered name: uri matches but not account" << name << address << account << cm->account(); qDebug() << "registered name: uri matches but not account" << name << address << account << cm->account();
} }
} }
} else { } else {
// got a registered name for a CM which hasn't been created yet // got a registered name for a CM which hasn't been created yet
// This can be left as-is to save memory. Those CMs are never freed.
// It is generally preferred to create as little as possible.
} }
} }
......
...@@ -59,10 +59,12 @@ public: ...@@ -59,10 +59,12 @@ public:
void trackedChanged(bool); void trackedChanged(bool);
void primaryNameChanged(const QString& name); void primaryNameChanged(const QString& name);
void rebased(ContactMethod* other); void rebased(ContactMethod* other);
void registeredNameSet(const QString& registeredName);
//Helpers //Helpers
void setTextRecording(Media::TextRecording* r); void setTextRecording(Media::TextRecording* r);
void setCertificate (Certificate*); void setCertificate (Certificate*);
void setRegisteredName(const QString& registeredName);
private: private:
ContactMethod* q_ptr; ContactMethod* q_ptr;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment