diff --git a/src/account.cpp b/src/account.cpp
index a1411a64c7958e711b2aedb79902dd199112a48b..02e94c6f8d83dc905a96fef271338c8f16d941b4 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -220,7 +220,7 @@ const QString Account::accountDetail(const QString& param) const
    }
    else if (m_hAccountDetails.count() > 0) {
       if (param == Account::MapField::ENABLED) //If an account is invalid, at least does not try to register it
-         return REGISTRATION_ENABLED_FALSE;
+         return Account::RegistrationEnabled::NO;
       if (param == Account::MapField::Registration::STATUS) //If an account is new, then it is unregistered
          return Account::State::UNREGISTERED;
       if (protocol() != Account::Protocol::IAX) //IAX accounts lack some fields, be quiet
diff --git a/src/account.h b/src/account.h
index 914e4eb3de11a0263fcd3528a67176b6ea3c27ab..81f83d12c4154e4e61cf87704b7dae437ab585d4 100644
--- a/src/account.h
+++ b/src/account.h
@@ -153,6 +153,12 @@ class LIB_EXPORT Account : public QObject {
          constexpr static const char* REQUEST_TIMEOUT           = "Request Timeout"        ;
       };
 
+      class RegistrationEnabled {
+      public:
+         constexpr static const char* YES  = "true";
+         constexpr static const char* NO   = "false";
+      };
+
       ~Account();
       //Constructors
       static Account* buildExistingAccountFromId(const QString& _accountId);
diff --git a/src/call.cpp b/src/call.cpp
index de43fc5efc13bff38dfdc930f3afc65ec33ad0f4..7ae83a3129880f7211b4b0c0ff6dcf57f51d5895 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -379,14 +379,23 @@ Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
       accId = QString(Account::ProtocolName::IP2IP);
    }
 
+   //Try to assiciate a contact now, the real contact object is probably not
+   //loaded yet, but we can get a placeholder for now
+//    const QString& contactUsed    = hc[ Call::HistoryMapFields::CONTACT_USED ]; //TODO
+   const QString& contactUid     = hc[ Call::HistoryMapFields::CONTACT_UID  ];
+
+   Contact* ct = nullptr;
+   if (!hc[ Call::HistoryMapFields::CONTACT_UID].isEmpty())
+      ct = ContactModel::instance()->getPlaceHolder(contactUid.toAscii());
+
    Account*      acc       = AccountListModel::instance()->getAccountById(accId);
-   PhoneNumber*  nb        = PhoneDirectoryModel::instance()->getNumber(number,acc);
+   PhoneNumber*  nb        = PhoneDirectoryModel::instance()->getNumber(number,ct,acc);
+
    Call*         call      = new Call(Call::State::OVER, callId, (name == "empty")?QString():name, nb, acc );
 
    call->m_pStopTimeStamp  = stopTimeStamp ;
    call->m_History         = true;
    call->setStartTimeStamp(startTimeStamp);
-
    call->m_HistoryState    = historyStateFromType(type);
    call->m_Account         = AccountListModel::instance()->getAccountById(accId);
 
@@ -409,7 +418,7 @@ Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
       call->m_Direction    = Call::Direction::INCOMING            ;
    else if (call->m_HistoryState == Call::LegacyHistoryState::OUTGOING)
       call->m_Direction    = Call::Direction::OUTGOING            ;
-   else //BUG Pick one, even if it is the wrong one
+   else //Getting there is a bug. Pick one, even if it is the wrong one
       call->m_Direction    = Call::Direction::OUTGOING            ;
    if (missed)
       call->m_HistoryState = Call::LegacyHistoryState::MISSED;
@@ -419,7 +428,12 @@ Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
 
    if (call->peerPhoneNumber()) {
       call->peerPhoneNumber()->addCall(call);
+
+      //Reload the glow and number colors
       connect(call->peerPhoneNumber(),SIGNAL(presentChanged(bool)),call,SLOT(updated()));
+
+      //Change the display name and picture
+      connect(call->peerPhoneNumber(),SIGNAL(rebased(PhoneNumber*)),call,SLOT(updated()));
    }
 
    return call;
diff --git a/src/call.h b/src/call.h
index 8903127095d32b07c26df85771a136a539f344fb..3a981fba8ac80be73d411014c9f48c92494cf1c8 100644
--- a/src/call.h
+++ b/src/call.h
@@ -212,6 +212,9 @@ public:
       constexpr static const char* TIMESTAMP_STOP    = "timestamp_stop" ;
       constexpr static const char* MISSED            = "missed"         ;
       constexpr static const char* DIRECTION         = "direction"      ;
+      constexpr static const char* CONTACT_USED      = "contact_used"   ;
+      constexpr static const char* CONTACT_UID       = "contact_uid"    ;
+      constexpr static const char* NUMBER_TYPE       = "number_type"    ;
    };
 
    ///"getCallDetails()" fields
diff --git a/src/callmodel.cpp b/src/callmodel.cpp
index 244770e8248df4939b03426cb527676b5073cd0c..f190c1120925cae775d90fc43c646b5480fc22e3 100644
--- a/src/callmodel.cpp
+++ b/src/callmodel.cpp
@@ -285,6 +285,7 @@ Call* CallModel::addCall(Call* call, Call* parentCall)
       Q_ASSERT(false);
    }
 
+   //Even history call currently need to be tracked in CallModel, this may change
    InternalStruct* aNewStruct = new InternalStruct;
    aNewStruct->call_real  = call;
    aNewStruct->conference = false;
@@ -297,13 +298,15 @@ Call* CallModel::addCall(Call* call, Call* parentCall)
    }
    m_sPrivateCallList_callId[ call->id() ] = aNewStruct;
 
-   if (call->lifeCycleState() != Call::LifeCycleState::FINISHED)
+   //If the call is already finished, there is no point to track it here
+   if (call->lifeCycleState() != Call::LifeCycleState::FINISHED) {
       emit callAdded(call,parentCall);
-   const QModelIndex idx = index(m_lInternalModel.size()-1,0,QModelIndex());
-   emit dataChanged(idx, idx);
-   connect(call,SIGNAL(changed(Call*)),this,SLOT(slotCallChanged(Call*)));
-   connect(call,SIGNAL(dtmfPlayed(QString)),this,SLOT(slotDTMFPlayed(QString)));
-   emit layoutChanged();
+      const QModelIndex idx = index(m_lInternalModel.size()-1,0,QModelIndex());
+      emit dataChanged(idx, idx);
+      connect(call,SIGNAL(changed(Call*)),this,SLOT(slotCallChanged(Call*)));
+      connect(call,SIGNAL(dtmfPlayed(QString)),this,SLOT(slotDTMFPlayed(QString)));
+      emit layoutChanged();
+   }
    return call;
 } //addCall
 
diff --git a/src/contact.cpp b/src/contact.cpp
index dc0d922c910e9b58cb9e40c3714b96e87401238d..c651ed04f746f045c3e8fee569d0f306dc130847 100644
--- a/src/contact.cpp
+++ b/src/contact.cpp
@@ -46,8 +46,55 @@ public:
    Contact::PhoneNumbers   m_Numbers        ;
    bool                    m_Active         ;
    AbstractContactBackend* m_pBackend       ;
+   bool                    m_isPlaceHolder  ;
+
+   //Helper code to help handle multiple parents
+   QList<Contact*> m_lParents;
+
+   //As a single D-Pointer can have multiple parent (when merged), all emit need
+   //to use a proxy to make sure everybody is notified
+   void presenceChanged( PhoneNumber* );
+   void statusChanged  ( bool         );
+   void changed        (              );
+   void phoneNumberCountChanged(int,int);
+   void phoneNumberCountAboutToChange(int,int);
 };
 
+void ContactPrivate::changed()
+{
+   foreach (Contact* c,m_lParents) {
+      emit c->changed();
+   }
+}
+
+void ContactPrivate::presenceChanged( PhoneNumber* n )
+{
+   foreach (Contact* c,m_lParents) {
+      emit c->presenceChanged(n);
+   }
+}
+
+void ContactPrivate::statusChanged  ( bool s )
+{
+   foreach (Contact* c,m_lParents) {
+      emit c->statusChanged(s);
+   }
+}
+
+void ContactPrivate::phoneNumberCountChanged(int n,int o)
+{
+   foreach (Contact* c,m_lParents) {
+      emit c->phoneNumberCountChanged(n,o);
+   }
+}
+
+void ContactPrivate::phoneNumberCountAboutToChange(int n,int o)
+{
+   foreach (Contact* c,m_lParents) {
+      emit c->phoneNumberCountAboutToChange(n,o);
+   }
+}
+
 ContactPrivate::ContactPrivate(Contact* contact, AbstractContactBackend* parent):m_pPhoto(nullptr),
    m_Numbers(contact),m_DisplayPhoto(nullptr),m_Active(true),
    m_pBackend(parent?parent:TransitionalContactBackend::instance())
@@ -72,6 +119,8 @@ Contact* Contact::PhoneNumbers::contact() const
 Contact::Contact(AbstractContactBackend* parent):QObject(parent?parent:TransitionalContactBackend::instance()),
    d(new ContactPrivate(this,parent))
 {
+   d->m_isPlaceHolder = false;
+   d->m_lParents << this;
 }
 
 ///Destructor
@@ -153,19 +202,19 @@ void Contact::setPhoneNumbers(PhoneNumbers numbers)
       disconnect(n,SIGNAL(presentChanged(bool)),this,SLOT(slotPresenceChanged()));
    d->m_Numbers = numbers;
    if (newCount < oldCount) //Rows need to be removed from models first
-      emit phoneNumberCountAboutToChange(newCount,oldCount);
+      d->phoneNumberCountAboutToChange(newCount,oldCount);
    foreach(PhoneNumber* n, d->m_Numbers)
       connect(n,SIGNAL(presentChanged(bool)),this,SLOT(slotPresenceChanged()));
    if (newCount > oldCount) //Need to be updated after the data to prevent invalid memory access
-      emit phoneNumberCountChanged(newCount,oldCount);
-   emit changed();
+      d->phoneNumberCountChanged(newCount,oldCount);
+   d->changed();
 }
 
 ///Set the nickname
 void Contact::setNickName(const QString& name)
 {
    d->m_NickName = name;
-   emit changed();
+   d->changed();
 }
 
 ///Set the first name
@@ -173,7 +222,7 @@ void Contact::setFirstName(const QString& name)
 {
    d->m_FirstName = name;
    setObjectName(formattedName());
-   emit changed();
+   d->changed();
 }
 
 ///Set the family name
@@ -181,64 +230,64 @@ void Contact::setFamilyName(const QString& name)
 {
    d->m_SecondName = name;
    setObjectName(formattedName());
-   emit changed();
+   d->changed();
 }
 
 ///Set the Photo/Avatar
 void Contact::setPhoto(QPixmap* photo)
 {
    d->m_pPhoto = photo;
-   emit changed();
+   d->changed();
 }
 
 ///Set the formatted name (display name)
 void Contact::setFormattedName(const QString& name)
 {
    d->m_FormattedName = name;
-   emit changed();
+   d->changed();
 }
 
 ///Set the organisation / business
 void Contact::setOrganization(const QString& name)
 {
    d->m_Organization = name;
-   emit changed();
+   d->changed();
 }
 
 ///Set the default email
 void Contact::setPreferredEmail(const QString& name)
 {
    d->m_PreferredEmail = name;
-   emit changed();
+   d->changed();
 }
 
 ///Set UID
 void Contact::setUid(const QByteArray& id)
 {
    d->m_Uid = id;
-   emit changed();
+   d->changed();
 }
 
 ///Set Group
 void Contact::setGroup(const QString& name)
 {
    d->m_Group = name;
-   emit changed();
+   d->changed();
 }
 
 ///Set department
 void Contact::setDepartment(const QString& name)
 {
    d->m_Department = name;
-   emit changed();
+   d->changed();
 }
 
 ///If the contact have been deleted or not yet fully created
 void Contact::setActive( bool active)
 {
    d->m_Active = active;
-   emit statusChanged(d->m_Active);
-   emit changed();
+   d->statusChanged(d->m_Active);
+   d->changed();
 }
 
 ///Return if one of the PhoneNumber is present
@@ -295,7 +344,7 @@ time_t Contact::PhoneNumbers::lastUsedTimeStamp() const
 ///Callback when one of the phone number presence change
 void Contact::slotPresenceChanged()
 {
-   emit changed();
+   d->changed();
 }
 
 ///Save the contact
@@ -322,3 +371,49 @@ bool Contact::addPhoneNumber(PhoneNumber* n)
 {
    return d->m_pBackend->addPhoneNumber(this,n);
 }
+
+///Create a placeholder contact, it will eventually be replaced when the real one is loaded
+ContactPlaceHolder::ContactPlaceHolder(const QByteArray& uid)
+{
+   setUid(uid);
+   d->m_isPlaceHolder = true;
+}
+
+
+bool ContactPlaceHolder::merge(Contact* contact)
+{
+   ContactPrivate* currentD = d;
+   replaceDPointer(contact);
+   currentD->m_lParents.removeAll(this);
+   if (!currentD->m_lParents.size())
+      delete currentD;
+   return true;
+}
+
+void Contact::replaceDPointer(Contact* c)
+{
+   this->d = c->d;
+   d->m_lParents << this;
+   emit changed();
+   emit rebased(c);
+}
+
+bool Contact::operator==(Contact* other)
+{
+   return this->d == other->d;
+}
+
+bool Contact::operator==(const Contact* other) const
+{
+   return this->d == other->d;
+}
+
+bool Contact::operator==(Contact& other)
+{
+   return this->d == other.d;
+}
+
+bool Contact::operator==(const Contact& other) const
+{
+   return this->d == other.d;
+}
diff --git a/src/contact.h b/src/contact.h
index 3e0fc08243ba6b915ba27b906069db2081750fc6..a42a982e45bef4295554be0348ed959677d4189f 100644
--- a/src/contact.h
+++ b/src/contact.h
@@ -22,7 +22,6 @@
 
 #include <QtCore/QObject>
 #include <QtCore/QVariant>
-#include <QtCore/QSharedPointer>
 #include <time.h>
 
 //Qt
@@ -84,9 +83,10 @@ public:
    Q_INVOKABLE bool remove()    ;
    Q_INVOKABLE bool addPhoneNumber(PhoneNumber* n);
 
-private:
+protected:
    //The D-Pointer can be shared if a PlaceHolderContact is merged with a real one
-   QSharedPointer<ContactPrivate> d;
+   ContactPrivate* d;
+   void replaceDPointer(Contact* other);
 
 public:
    //Constructors & Destructors
@@ -126,6 +126,12 @@ public:
    void setPhoto          ( QPixmap*          photo  );
    void setActive         ( bool              active );
 
+   //Operator
+   bool operator==(Contact* other);
+   bool operator==(const Contact* other) const;
+   bool operator==(Contact& other);
+   bool operator==(const Contact& other) const;
+
 private Q_SLOTS:
    void slotPresenceChanged();
 
@@ -135,12 +141,21 @@ Q_SIGNALS:
    void changed        (              );
    void phoneNumberCountChanged(int,int);
    void phoneNumberCountAboutToChange(int,int);
+   void rebased        ( Contact*     );
 
 protected:
    //Presence secret methods
    void updatePresenceInformations(const QString& uri, bool status, const QString& message);
 };
 
+class LIB_EXPORT ContactPlaceHolder : public Contact {
+   Q_OBJECT
+public:
+   ContactPlaceHolder(const QByteArray& uid);
+   bool merge(Contact* contact);
+};
+
+
 Q_DECLARE_METATYPE(Contact*)
 
 #endif
diff --git a/src/contactmodel.cpp b/src/contactmodel.cpp
index e4c0da7becc9b4290a3d5b7f4315839d5a7ef019..6d7923b898a0bd16f26589f42e5fb42424cc48c8 100644
--- a/src/contactmodel.cpp
+++ b/src/contactmodel.cpp
@@ -163,6 +163,25 @@ Contact* ContactModel::getContactByUid(const QByteArray& uid)
    return m_hContactsByUid[uid];
 }
 
+/**
+ * Create a temporary contact or return the existing one for an UID
+ * This temporary contact should eventually be merged into the real one
+ */
+Contact* ContactModel::getPlaceHolder(const QByteArray& uid )
+{
+   Contact* ct = m_hContactsByUid[uid];
+
+   //Do not create a placeholder if the real deal exist
+   if (ct) {
+      return ct;
+   }
+
+   ContactPlaceHolder* ct2 = new ContactPlaceHolder(uid);
+
+   m_hPlaceholders[ct2->uid()] = ct2;
+   return ct2;
+}
+
 ///Return if there is backends
 bool ContactModel::hasBackends() const
 {
@@ -208,6 +227,12 @@ bool ContactModel::addContact(Contact* c)
    beginInsertRows(QModelIndex(),m_lContacts.size()-1,m_lContacts.size());
    m_lContacts << c;
    m_hContactsByUid[c->uid()] = c;
+
+   //Deprecate the placeholder
+   if (m_hPlaceholders.contains(c->uid())) {
+      m_hPlaceholders[c->uid()]->merge(c);
+      m_hPlaceholders[c->uid()] = nullptr;
+   }
    endInsertRows();
    emit layoutChanged();
    emit newContactAdded(c);
diff --git a/src/contactmodel.h b/src/contactmodel.h
index e708f41990c482ac5afca26b50709d3d5482e2d5..01c8c6f8765a9090bcb131a03e6be3c54de297ba 100644
--- a/src/contactmodel.h
+++ b/src/contactmodel.h
@@ -70,6 +70,7 @@ public:
 
    //Getters
    Contact* getContactByUid   ( const QByteArray& uid );
+   Contact* getPlaceHolder(const QByteArray& uid );
    bool     hasBackends       () const;
    const ContactList contacts() const;
    virtual const QVector<AbstractContactBackend*> enabledBackends() const;
@@ -96,6 +97,7 @@ private:
    static ContactModel* m_spInstance;
    QVector<AbstractContactBackend*> m_lBackends;
    CommonItemBackendModel* m_pBackendModel;
+   QHash<QByteArray,ContactPlaceHolder*> m_hPlaceholders;
 
    //Indexes
    QHash<QByteArray,Contact*> m_hContactsByUid;
@@ -114,4 +116,5 @@ Q_SIGNALS:
    void newBackendAdded(AbstractContactBackend* backend);
 };
 
+
 #endif
diff --git a/src/phonedirectorymodel.cpp b/src/phonedirectorymodel.cpp
index db352611d1bb279ccfbfbb8bda5d7f405da4a616..b78118afb930e2cbe42d4090b173e59a0b067de7 100644
--- a/src/phonedirectorymodel.cpp
+++ b/src/phonedirectorymodel.cpp
@@ -409,6 +409,9 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Account* account
 
 PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact, Account* account, const QString& type)
 {
+   if (!contact)
+      return getNumber(uri,account,type);
+
    const QString strippedUri =  PhoneNumber::stripUri(uri);
 
    //See if the number is already loaded
@@ -426,7 +429,9 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact
          if ((!number->hasType()) && (!type.isEmpty())) {
             number->setCategory(NumberCategoryModel::instance()->getCategory(type));
          }
-         if (((!contact) || number->contact() == contact) && ((!account) || number->account() == account))
+         //Use the operator== check to avoid issues with placeholders
+         if (((!contact) || (number->contact() && (*number->contact()) == (*contact)))
+            && ((!account) || number->account() == account))
             return number;
       }
    }
diff --git a/src/phonenumber.cpp b/src/phonenumber.cpp
index 1bd1701cf8317236d91e04cd8bd8572787543155..1e6f703f499ff41d6bd15f441d041dfb604baf14 100644
--- a/src/phonenumber.cpp
+++ b/src/phonenumber.cpp
@@ -162,6 +162,7 @@ void PhoneNumber::setContact(Contact* contact)
       PhoneDirectoryModel::instance()->indexNumber(this,d->m_hNames.keys()+QStringList(contact->formattedName()));
       d->m_PrimaryName_cache = contact->formattedName();
       emit primaryNameChanged(d->m_PrimaryName_cache);
+      connect(contact,SIGNAL(rebased(Contact*)),this,SLOT(contactRebased(Contact*)));
    }
    emit changed();
 }
@@ -443,6 +444,20 @@ void PhoneNumber::accountDestroyed(QObject* o)
       d->m_pAccount = nullptr;
 }
 
+/**
+ * When the PhoneNumber contact is merged with another one, the phone number
+ * data might be replaced, like the preferred name.
+ */
+void PhoneNumber::contactRebased(Contact* other)
+{
+   d->m_PrimaryName_cache = other->formattedName();
+   emit primaryNameChanged(d->m_PrimaryName_cache);
+   emit changed();
+
+   //It is a "partial" rebase, so the PhoneNumber data stay the same
+   emit rebased(this);
+}
+
 /**
  * Merge two phone number to share the same data. This avoid having to change
  * pointers all over the place. The PhoneNumber objects remain intact, the
diff --git a/src/phonenumber.h b/src/phonenumber.h
index 0367861296db8cc98538063a95e6451110575157..d8824b7bc0d15aed37916d3b6b7d05e77baff223 100644
--- a/src/phonenumber.h
+++ b/src/phonenumber.h
@@ -183,6 +183,7 @@ private:
 
 private Q_SLOTS:
    void accountDestroyed(QObject* o);
+   void contactRebased(Contact* other);
 
 Q_SIGNALS:
    void callAdded(Call* call);
@@ -191,6 +192,7 @@ Q_SIGNALS:
    void presenceMessageChanged(const QString&);
    void trackedChanged(bool);
    void primaryNameChanged(const QString& name);
+   void rebased(PhoneNumber* other);
 };
 
 Q_DECLARE_METATYPE(PhoneNumber*)
diff --git a/src/sflphone_const.h b/src/sflphone_const.h
index ed13598eb89b72f7f18ae0536c3e655b4607d853..3312859d02ecfefeffba6d6f35dfc3a588e9fec8 100644
--- a/src/sflphone_const.h
+++ b/src/sflphone_const.h
@@ -22,19 +22,6 @@
 #ifndef SFLPHONE_CONST_H
 #define SFLPHONE_CONST_H
 
-#include <QtCore/QString>
-
-#define ACTION_LABEL_CALL                 i18n("New call")
-#define ACTION_LABEL_PLACE_CALL           i18n("Place call")
-#define ACTION_LABEL_HANG_UP              i18n("Hang up")
-#define ACTION_LABEL_HOLD                 i18n("Hold on")
-#define ACTION_LABEL_TRANSFER             i18n("Transfer")
-#define ACTION_LABEL_RECORD               i18n("Record")
-#define ACTION_LABEL_ACCEPT               i18n("Pick up")
-#define ACTION_LABEL_REFUSE               i18n("Hang up")
-#define ACTION_LABEL_UNHOLD               i18n("Hold off")
-#define ACTION_LABEL_GIVE_UP_TRANSF       i18n("Give up transfer")
-#define ACTION_LABEL_MAILBOX              i18n("Voicemail")
 
 #define ICON_INCOMING                     ":/images/icons/ring.svg"
 #define ICON_RINGING                      ":/images/icons/ring.svg"
@@ -63,20 +50,9 @@
 #define ICON_HISTORY_MISSED               ":/images/icons/missed.svg"
 #define ICON_SFLPHONE                     ":/images/icons/sflphone.svg"
 
-/** Maybe to remove **/
-static const QString REGISTRATION_ENABLED_TRUE("true");
-static const QString REGISTRATION_ENABLED_FALSE("false");
 // #define ACCOUNT_TYPES_TAB                 {QString(Account::ProtocolName::SIP), QString(Account::ProtocolName::IAX)}
 /*********************/
 
-/** Hooks settings */
-#define HOOKS_ADD_PREFIX                  "PHONE_NUMBER_HOOK_ADD_PREFIX"
-#define HOOKS_ENABLED                     "PHONE_NUMBER_HOOK_ENABLED"
-#define HOOKS_COMMAND                     "URLHOOK_COMMAND"
-#define HOOKS_IAX2_ENABLED                "URLHOOK_IAX2_ENABLED"
-#define HOOKS_SIP_ENABLED                 "URLHOOK_SIP_ENABLED"
-#define HOOKS_SIP_FIELD                   "URLHOOK_SIP_FIELD"
-
 /** MIME API */
 #define MIME_CALLID           "text/sflphone.call.id"
 #define MIME_CONTACT          "text/sflphone.contact"