diff --git a/src/contact-manager.cpp b/src/contact-manager.cpp
index f755965..7be5017 100644
--- a/src/contact-manager.cpp
+++ b/src/contact-manager.cpp
@@ -12,38 +12,38 @@
 #pragma clang diagnostic ignored "-Wtautological-compare"
 #endif
 
-
 #include "contact-manager.h"
+#include <QStringList>
 
 #ifndef Q_MOC_RUN
-#include <ndn-cpp-dev/face.hpp>
-#include <ndn-cpp-dev/security/signature-sha256-with-rsa.hpp>
-
-#ifndef WITH_SECURITY
-#include <ndn-cpp-dev/security/validator-null.hpp>
-#else
+#include <ndn-cpp-dev/util/crypto.hpp>
+#include <ndn-cpp-dev/util/io.hpp>
+#include <ndn-cpp-dev/security/sec-rule-relative.hpp>
 #include <ndn-cpp-dev/security/validator-regex.hpp>
 #include <cryptopp/base64.h>
-#include <ndn-cpp-dev/security/sec-rule-relative.hpp>
-#endif
-
-#include "endorse-collection.pb.h"
+#include <cryptopp/files.h>
+#include <cryptopp/sha.h>
+#include <boost/asio.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/filesystem.hpp>
 #include "logging.h"
 #endif
 
 using namespace ndn;
 using namespace std;
+namespace fs = boost::filesystem;
 
-INIT_LOGGER("ContactManager");
+INIT_LOGGER("chronos.ContactManager");
 
 namespace chronos{
 
+static const uint8_t DNS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.
+
 ContactManager::ContactManager(shared_ptr<Face> face,
                                QObject* parent)
   : QObject(parent)
-  , m_contactStorage(new ContactStorage())
-  , m_dnsStorage(new DnsStorage())
   , m_face(face)
+  , m_dnsListenerId(0)
 {
   initializeSecurity();
 }
@@ -51,108 +51,37 @@
 ContactManager::~ContactManager()
 {}
 
+// private methods
 void
 ContactManager::initializeSecurity()
 {
-  
-#ifndef WITH_SECURITY
-  
-  m_keyChain = make_shared<KeyChain>();
-  m_validator = make_shared<ValidatorNull>();
+  fs::path anchorPath = fs::path(getenv("HOME")) / ".chronos" / "anchor.cert";
+  shared_ptr<IdentityCertificate> anchor = io::load<IdentityCertificate>(anchorPath.c_str());
 
-#else
-
-  shared_ptr<SecPolicySimple> policy = make_shared<SecPolicySimple>();
-  m_verifier = make_shared<Verifier>(policy);
-  m_verifier->setFace(m_face);
-
-  policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><ENDORSED>",
-                                                                 "^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
-                                                                 "==", "\\1", "\\1\\2", true));
-  policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
-                                                                 "^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
-                                                                 "==", "\\1", "\\1\\2", true));
-  policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
-                                                                 "^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$", 
-                                                                 "==", "\\1", "\\1\\2", true));
-  policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
-                                                                 "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
-                                                                 ">", "\\1\\2", "\\1", true));
-  policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
-                                                                 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
-                                                                 "==", "\\1", "\\1\\2", true));
-  policy->addVerificationPolicyRule(make_shared<SecRuleRelative>("^(<>*)$", 
-                                                                 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$", 
-                                                                 ">", "\\1", "\\1\\2", true));
-  
-
-  policy->addSigningPolicyRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
-                                                            "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
-                                                            "==", "\\1", "\\1\\2", true));
-
-
-  const string TrustAnchor("BIICqgOyEIWlKzDI2xX2hdq5Azheu9IVyewcV4uM7ylfh67Y8MIxF3tDCTx5JgEn\
-HYMuCaYQm6XuaXTlVfDdWff/K7Xebq8IgGxjNBeU9eMf7Gy9iIMrRAOdBG0dBHmo\
-67biGs8F+P1oh1FwKu/FN1AE9vh8HSOJ94PWmjO+6PvITFIXuI3QbcCz8rhvbsfb\
-5X/DmfbJ8n8c4X3nVxrBm6fd4z8kOFOvvhgJImvqsow69Uy+38m8gJrmrcWMoPBJ\
-WsNLcEriZCt/Dlg7EqqVrIn6ukylKCvVrxA9vm/cEB74J/N+T0JyMRDnTLm17gpq\
-Gd75rhj+bLmpOMOBT7Nb27wUKq8gcXzeAADy+p1uZG4A+p1LRVkA+vVrc2stMTM4\
-MzMyNTcyMAD6vUlELUNFUlQA+q39PgurHgAAAaID4gKF5vjua9EIr3/Fn8k1AdSc\
-nEryjVDW3ikvYoSwjK7egTkAArq1BSc+C6sdAAHiAery+p1uZG4A+p1LRVkA+vVr\
-c2stMTM4MzMyNTcyMAD6vUlELUNFUlQAAAAAAAGaFr0wggFjMCIYDzIwMTMxMTAx\
-MTcxMTIyWhgPMjAxNDExMDExNzExMjJaMBkwFwYDVQQpExBORE4gVGVzdGJlZCBS\
-b290MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA06x+elwzWCHa4I3b\
-yrYCMAIVxQpRVLuOXp0h+BS+5GNgMVPi7+40o4zSJG+kiU8CIH1mtj8RQAzBX9hF\
-I5VAyOC8nS8D8YOfBwt2yRDZPgt1E5PpyYUBiDYuq/zmJDL8xjxAlxrMzVOqD/uj\
-/vkkcBM/T1t9Q6p1CpRyq+GMRbV4EAHvH7MFb6bDrH9t8DHEg7NPUCaSQBrd7PvL\
-72P+QdiNH9zs/EiVzAkeMG4iniSXLuYM3z0gMqqcyUUUr6r1F9IBmDO+Kp97nZh8\
-VCL+cnIEwyzAFAupQH5GoXUWGiee8oKWwH2vGHX7u6sWZsCp15NMSG3OC4jUIZOE\
-iVUF1QIBEQAA");
-
-  string decoded;
-  CryptoPP::StringSource ss(reinterpret_cast<const unsigned char *>(TrustAnchor.c_str()), 
-                            TrustAnchor.size(), 
-                            true,
-                            new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
-  Data data;
-  data.wireDecode(Block(reinterpret_cast<const uint8_t*>(decoded.c_str()), decoded.size()));
-  shared_ptr<IdentityCertificate> anchor = make_shared<IdentityCertificate>(data);
-  policy->addTrustAnchor(anchor);  
-#endif
-}
-
-
-void
-ContactManager::fetchSelfEndorseCertificate(const ndn::Name& identity)
-{
-  Name interestName = identity;
-  interestName.append("DNS").append("PROFILE");
-  
-  Interest interest(interestName);
-  interest.setMustBeFresh(true);
-
-  OnDataValidated onValidated = bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identity);
-  OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, identity);
-  TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, identity);
-
-  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
-}
-
-void
-ContactManager::onDnsSelfEndorseCertValidated(const shared_ptr<const Data>& data, 
-                                              const Name& identity)
-{
-  try{
-    Data plainData;
-    plainData.wireDecode(data->getContent().blockFromValue());
-    EndorseCertificate selfEndorseCertificate(plainData);
-    if(Validator::verifySignature(plainData, plainData.getSignature(), selfEndorseCertificate.getPublicKeyInfo()))
-      emit contactFetched(selfEndorseCertificate); 
-    else
-      emit contactFetchFailed(identity);
-  }catch(...){
-    emit contactFetchFailed (identity);
-  }
+  shared_ptr<ValidatorRegex> validator = make_shared<ValidatorRegex>(m_face);
+  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><ENDORSED>",
+                                                                  "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
+                                                                  "==", "\\1", "\\1\\2", true));
+  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><><ENDORSEE>",
+                                                                  "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
+                                                                  "==", "\\1", "\\1\\2", true));
+  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
+                                                                  "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
+                                                                  "==", "\\1", "\\1\\2", true));
+  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
+                                                                  "^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$", 
+                                                                  "==", "\\1", "\\1\\2", true));
+  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
+                                                                  "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
+                                                                  ">", "\\1\\2", "\\1", true));
+  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
+                                                                  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
+                                                                  "==", "\\1", "\\1\\2", true));
+  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^(<>*)$", 
+                                                                  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$", 
+                                                                  ">", "\\1", "\\1\\2", true));
+  validator->addTrustAnchor(anchor);
+  m_validator = validator;
 }
 
 void
@@ -167,254 +96,799 @@
 
   OnDataValidated onValidated = bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
   OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsCollectEndorseValidationFailed, this, _1, identity);
-  TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, identity);
+  TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, _1, identity);
 
-  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
+  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
 }
 
 void
-ContactManager::fetchKey(const Name& certName)
+ContactManager::fetchEndorseCertificateInternal(const Name& identity, int certIndex)
 {
-  Name interestName = certName;
-  
+  shared_ptr<EndorseCollection> endorseCollection = m_bufferedContacts[identity].m_endorseCollection;
+
+  if(certIndex >= endorseCollection->endorsement_size())
+    prepareEndorseInfo(identity);
+
+  Name interestName(endorseCollection->endorsement(certIndex).certname());
+
   Interest interest(interestName);
   interest.setInterestLifetime(1000);
   interest.setMustBeFresh(true);
 
-  OnDataValidated onValidated = bind(&ContactManager::onKeyValidated, this, _1, certName);
-  OnDataValidationFailed onValidationFailed = bind(&ContactManager::onKeyValidationFailed, this, _1, certName);
-  TimeoutNotify timeoutNotify = bind(&ContactManager::onKeyTimeoutNotify, this, certName);
-
-  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
+  m_face->expressInterest(interest,
+                          bind(&ContactManager::onEndorseCertificateInternal, 
+                               this, _1, _2, identity, certIndex,
+                               endorseCollection->endorsement(certIndex).hash()),
+                          bind(&ContactManager::onEndorseCertificateInternalTimeout,
+                               this, _1, identity, certIndex));
 }
 
 void
-ContactManager::onKeyValidated(const shared_ptr<const Data>& data, const Name& identity)
+ContactManager::prepareEndorseInfo(const Name& identity)
 {
-  IdentityCertificate identityCertificate(*data);
-  Profile profile(identityCertificate);
+  // _LOG_DEBUG("prepareEndorseInfo");
+  const Profile& profile = m_bufferedContacts[identity].m_selfEndorseCert->getProfile();
 
-  try{
-    EndorseCertificate endorseCertificate(identityCertificate, profile);
-    m_keyChain->sign(endorseCertificate);
-    emit contactKeyFetched (endorseCertificate); 
-  }catch(...){
-    return;
+  shared_ptr<EndorseInfo> endorseInfo = make_shared<EndorseInfo>();
+  m_bufferedContacts[identity].m_endorseInfo = endorseInfo;
+
+  Profile::const_iterator pIt  = profile.begin();
+  Profile::const_iterator pEnd = profile.end();
+
+  map<string, int> endorseCount;
+  for(; pIt != pEnd; pIt++)
+    {
+      // _LOG_DEBUG("prepareEndorseInfo: profile[" << pIt->first << "]: " << pIt->second);
+      endorseCount[pIt->first] = 0;
+    }
+
+  int endorseCertCount = 0;
+
+  vector<shared_ptr<EndorseCertificate> >::const_iterator cIt  = m_bufferedContacts[identity].m_endorseCertList.begin();
+  vector<shared_ptr<EndorseCertificate> >::const_iterator cEnd = m_bufferedContacts[identity].m_endorseCertList.end();
+
+  for(; cIt != cEnd; cIt++, endorseCertCount++)
+    {
+      shared_ptr<Contact> contact = getContact((*cIt)->getSigner().getPrefix(-1));
+      if(!static_cast<bool>(contact))
+        continue;
+      
+      if(!contact->isIntroducer() 
+         || !contact->canBeTrustedFor(profile.getIdentityName()))
+        continue;
+
+      if(!Validator::verifySignature(**cIt, contact->getPublicKey()))
+        continue;
+
+      const Profile& tmpProfile = (*cIt)->getProfile();
+      if(tmpProfile != profile)
+        continue;
+
+      const vector<string>& endorseList = (*cIt)->getEndorseList();
+      vector<string>::const_iterator eIt = endorseList.begin();
+      for(; eIt != endorseList.end(); eIt++)
+        endorseCount[*eIt] += 1;
+    }
+
+  pIt  = profile.begin();
+  pEnd = profile.end();
+  for(; pIt != pEnd; pIt++)
+    {
+      EndorseInfo::Endorsement* endorsement = endorseInfo->add_endorsement();
+      endorsement->set_type(pIt->first);
+      endorsement->set_value(pIt->second);
+      stringstream ss;
+      ss << endorseCount[pIt->first] << "/" << endorseCertCount;
+      endorsement->set_endorse(ss.str());
+    }
+
+  emit contactEndorseInfoReady (*endorseInfo);
+}
+
+void
+ContactManager::onDnsSelfEndorseCertValidated(const shared_ptr<const Data>& data, 
+                                              const Name& identity)
+{
+  try
+    {
+      Data plainData;
+      plainData.wireDecode(data->getContent().blockFromValue());
+      shared_ptr<EndorseCertificate> selfEndorseCertificate = make_shared<EndorseCertificate>(boost::cref(plainData));
+      if(Validator::verifySignature(plainData, selfEndorseCertificate->getPublicKeyInfo()))
+        {
+          m_bufferedContacts[identity].m_selfEndorseCert = selfEndorseCertificate;
+          fetchCollectEndorse(identity);
+        }
+      else
+        emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+    }
+  catch(Block::Error& e)
+    {
+      emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+    }
+  catch(Data::Error& e)
+    {
+      emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+    }
+  catch(EndorseCertificate::Error& e)
+    {
+      emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+    }
+}
+
+void
+ContactManager::onDnsSelfEndorseCertValidationFailed(const shared_ptr<const Data>& data, 
+                                                     const Name& identity)
+{
+  // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
+  // but let's stay with failure for now.
+  emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+}
+
+void
+ContactManager::onDnsSelfEndorseCertTimeoutNotify(const Interest& interest,
+                                                  const Name& identity)
+{
+  // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
+  // but let's stay with failure for now.
+  emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
+}
+
+void
+ContactManager::onDnsCollectEndorseValidated(const shared_ptr<const Data>& data, 
+                                             const Name& identity)
+{
+  shared_ptr<EndorseCollection> endorseCollection = make_shared<EndorseCollection>();
+  if(!endorseCollection->ParseFromArray(data->getContent().value(), data->getContent().value_size()))
+    {
+      m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
+      fetchEndorseCertificateInternal(identity, 0);
+    }
+  else
+    prepareEndorseInfo(identity);
+}
+
+void
+ContactManager::onDnsCollectEndorseValidationFailed(const shared_ptr<const Data>& data, 
+                                                    const Name& identity)
+{
+  prepareEndorseInfo(identity);
+}
+
+void
+ContactManager::onDnsCollectEndorseTimeoutNotify(const Interest& interest,
+                                                 const Name& identity)
+{
+  // _LOG_DEBUG("onDnsCollectEndorseTimeoutNotify: " << interest.getName());
+  prepareEndorseInfo(identity);
+}
+
+void
+ContactManager::onEndorseCertificateInternal(const Interest& interest,
+                                             Data& data, 
+                                             const Name& identity, 
+                                             int certIndex,
+                                             string hash)
+{
+  stringstream ss;
+  {  
+    using namespace CryptoPP;
+
+    SHA256 hash;
+    StringSource(data.wireEncode().wire(), data.wireEncode().size(), true,
+                 new HashFilter(hash, new FileSink(ss)));
+  }
+  
+  if(ss.str() == hash)
+    {
+      shared_ptr<EndorseCertificate> endorseCertificate = make_shared<EndorseCertificate>(boost::cref(data));
+      m_bufferedContacts[identity].m_endorseCertList.push_back(endorseCertificate);
+    }
+
+  fetchEndorseCertificateInternal(identity, certIndex+1);
+}
+
+void
+ContactManager::onEndorseCertificateInternalTimeout(const Interest& interest,
+                                                    const Name& identity, 
+                                                    int certIndex)
+{
+  fetchEndorseCertificateInternal(identity, certIndex+1);
+}
+
+void
+ContactManager::collectEndorsement()
+{
+  {
+    boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
+    m_collectCount = m_contactList.size();
+    
+    ContactList::iterator it  = m_contactList.begin();
+    ContactList::iterator end = m_contactList.end();
+
+    for(; it != end ; it++)
+      {
+        Name interestName = (*it)->getNameSpace();
+        interestName.append("DNS").append(m_identity.wireEncode()).append("ENDORSEE");
+        
+        Interest interest(interestName);
+        interest.setInterestLifetime(1000);
+        
+        OnDataValidated onValidated = bind(&ContactManager::onDnsEndorseeValidated, this, _1);
+        OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1);
+        TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);
+        
+        sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
+      }
   }
 }
 
 void
-ContactManager::fetchIdCertificate(const Name& certName)
+ContactManager::onDnsEndorseeValidated(const shared_ptr<const Data>& data)
 {
-  Name interestName = certName;
-  
-  Interest interest(interestName);
-  interest.setInterestLifetime(1000);
-  interest.setMustBeFresh(true);
+  Data endorseData;
+  endorseData.wireDecode(data->getContent().blockFromValue());
 
-  OnDataValidated onValidated = bind(&ContactManager::onIdCertValidated, this, _1, certName);
-  OnDataValidationFailed onValidationFailed = bind(&ContactManager::onIdCertValidationFailed, this, _1, certName);
-  TimeoutNotify timeoutNotify = bind(&ContactManager::onIdCertTimeoutNotify, this, certName);
+  EndorseCertificate endorseCertificate(endorseData);
+  m_contactStorage->updateCollectEndorse(endorseCertificate);
 
-  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify);
+  decreaseCollectStatus();
 }
 
 void
-ContactManager::updateProfileData(const Name& identity)
+ContactManager::onDnsEndorseeValidationFailed(const shared_ptr<const Data>& data)
 {
-  // Get current profile;
-  shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile(identity);
-  if(!static_cast<bool>(newProfile))
-    return;
-
-  shared_ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
-
-  if(!static_cast<bool>(newEndorseCertificate))
-    return;
-
-  m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate, identity);
-
-  publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
+  decreaseCollectStatus();
 }
 
 void
-ContactManager::updateEndorseCertificate(const ndn::Name& identity, const ndn::Name& signerIdentity)
+ContactManager::onDnsEndorseeTimeoutNotify(const Interest& interest)
 {
-  shared_ptr<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identity, signerIdentity);
-
-  if(!static_cast<bool>(newEndorseCertificate))
-    return;
-
-  m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identity);
-
-  publishEndorseCertificateInDNS(*newEndorseCertificate, signerIdentity);
+  decreaseCollectStatus();
 }
 
-shared_ptr<EndorseCertificate> 
-ContactManager::generateEndorseCertificate(const Name& identity, const Name& signerIdentity)
+void 
+ContactManager::decreaseCollectStatus()
 {
-  shared_ptr<ContactItem> contact = getContact(identity);
-  if(!static_cast<bool>(contact))
-    return shared_ptr<EndorseCertificate>();
+  int count; 
+  {
+    boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
+    m_collectCount--;
+    count = m_collectCount;
+  }
 
-  Name signerKeyName = m_keyChain->getDefaultKeyNameForIdentity(signerIdentity);
+  if(count == 0)
+    publishCollectEndorsedDataInDNS();
+}
 
-  vector<string> endorseList;
-  m_contactStorage->getEndorseList(identity, endorseList);
+void
+ContactManager::publishCollectEndorsedDataInDNS()
+{
+  Name dnsName = m_identity;
+  dnsName.append("DNS").append("ENDORSED").appendVersion();
 
-  try{
-    shared_ptr<EndorseCertificate> cert = make_shared<EndorseCertificate>(contact->getSelfEndorseCertificate(), signerKeyName, endorseList); 
-    m_keyChain->signByIdentity(*cert, signerIdentity);
-    return cert;
-  }catch(...){
-    return shared_ptr<EndorseCertificate>();
-  } 
+  Data data;
+  data.setName(dnsName);
+
+  EndorseCollection endorseCollection;
+  m_contactStorage->getCollectEndorse(endorseCollection);
+
+  OBufferStream os;
+  endorseCollection.SerializeToOstream(&os);
+
+  data.setContent(os.buf());  
+  m_keyChain.signByIdentity(data, m_identity);
+
+  m_contactStorage->updateDnsOthersEndorse(data);
+  m_face->put(data);
+}
+
+void
+ContactManager::onIdentityCertValidated(const shared_ptr<const Data>& data)
+{
+  shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(boost::cref(*data));
+  m_bufferedIdCerts[cert->getName()] = cert;
+  decreaseIdCertCount();
+}
+
+void
+ContactManager::onIdentityCertValidationFailed(const shared_ptr<const Data>& data)
+{
+  _LOG_DEBUG("ContactManager::onIdentityCertValidationFailed " << data->getName());
+  decreaseIdCertCount();
+}
+
+void
+ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
+{
+  _LOG_DEBUG("ContactManager::onIdentityCertTimeoutNotify: " << interest.getName());
+  decreaseIdCertCount();
+}
+
+void
+ContactManager::decreaseIdCertCount()
+{
+  int count;
+  {
+    boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
+    m_idCertCount--;
+    count = m_idCertCount;
+  }
+
+  if(count == 0)
+    {
+      QStringList certNameList;
+      QStringList nameList;
+
+      BufferedIdCerts::const_iterator it  = m_bufferedIdCerts.begin();
+      BufferedIdCerts::const_iterator end = m_bufferedIdCerts.end();
+      for(; it != end; it++)
+        {
+          certNameList << QString::fromStdString(it->second->getName().toUri());
+          Profile profile(*(it->second));
+          nameList << QString::fromStdString(profile.get("name"));
+        }
+
+      emit idCertNameListReady(certNameList);
+      emit nameListReady(nameList);
+    }
 }
 
 shared_ptr<EndorseCertificate>
-ContactManager::getSignedSelfEndorseCertificate(const Name& identity,
-                                                const Profile& profile)
+ContactManager::getSignedSelfEndorseCertificate(const Profile& profile)
 {
-  Name certificateName = m_keyChain->getDefaultCertificateNameForIdentity(identity);
-  if(0 == certificateName.size())
-    return shared_ptr<EndorseCertificate>();
+  Name certificateName = m_keyChain.getDefaultCertificateNameForIdentity(m_identity);
 
-  Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
-  shared_ptr<IdentityCertificate> kskCert;
-
-  if(signingKeyName.get(-1).toEscapedString().substr(0,4) == "dsk-")
-    {
-      shared_ptr<IdentityCertificate> signingCert = m_keyChain->getCertificate(certificateName);
-      if(!static_cast<bool>(signingCert))
-        return shared_ptr<EndorseCertificate>();
-
-      try{
-        SignatureSha256WithRsa dskCertSig(signingCert->getSignature());
-        Name keyName = IdentityCertificate::certificateNameToPublicKeyName(dskCertSig.getKeyLocator().getName());
-        Name kskCertName = m_keyChain->getDefaultCertificateNameForKey(keyName);
-        kskCert = m_keyChain->getCertificate(kskCertName);
-      }catch(...){
-        return shared_ptr<EndorseCertificate>();
-      }
-    }      
-  else
-    kskCert = m_keyChain->getCertificate(certificateName);
-
-  if(!static_cast<bool>(kskCert))
-    return shared_ptr<EndorseCertificate>();
+  shared_ptr<IdentityCertificate> signingCert = m_keyChain.getCertificate(certificateName);
 
   vector<string> endorseList;
   Profile::const_iterator it = profile.begin();
   for(; it != profile.end(); it++)
     endorseList.push_back(it->first);
   
-  try{
-    shared_ptr<EndorseCertificate> selfEndorseCertificate = make_shared<EndorseCertificate>(*kskCert, profile, endorseList);
-    m_keyChain->sign(*selfEndorseCertificate, kskCert->getName());
-    return selfEndorseCertificate;
-  }catch(...){
-    return shared_ptr<EndorseCertificate>();
-  } 
+  shared_ptr<EndorseCertificate> selfEndorseCertificate = 
+    shared_ptr<EndorseCertificate>(new EndorseCertificate(*signingCert, profile, endorseList));
+  
+  m_keyChain.sign(*selfEndorseCertificate, certificateName);
+  
+  return selfEndorseCertificate;
 }
 
 void
 ContactManager::publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate)
 {
-  Data data;
-
-  Name identity = selfEndorseCertificate.getPublicKeyName().getPrefix(-1);
-
-  Name dnsName = identity;
+  Name dnsName = m_identity;
   dnsName.append("DNS").append("PROFILE").appendVersion();
+
+  Data data;
   data.setName(dnsName);
   data.setContent(selfEndorseCertificate.wireEncode());
+  data.setFreshnessPeriod(1000);
 
-  m_keyChain->signByIdentity(data, identity);
-  m_dnsStorage->updateDnsSelfProfileData(data, identity);
+  m_keyChain.signByIdentity(data, m_identity);
+
+  m_contactStorage->updateDnsSelfProfileData(data);
   m_face->put(data);
 }
 
-void
-ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate, const Name& signerIdentity)
+shared_ptr<EndorseCertificate> 
+ContactManager::generateEndorseCertificate(const Name& identity)
 {
-  Data data;
+  shared_ptr<Contact> contact = getContact(identity);
+  if(!static_cast<bool>(contact))
+    return shared_ptr<EndorseCertificate>();
 
+  Name signerKeyName = m_keyChain.getDefaultKeyNameForIdentity(m_identity);
+
+  vector<string> endorseList;
+  m_contactStorage->getEndorseList(identity, endorseList);
+
+  shared_ptr<EndorseCertificate> cert = 
+    shared_ptr<EndorseCertificate>(new EndorseCertificate(contact->getPublicKeyName(), 
+                                                          contact->getPublicKey(),
+                                                          contact->getNotBefore(),
+                                                          contact->getNotAfter(),
+                                                          signerKeyName, 
+                                                          contact->getProfile(), 
+                                                          endorseList)); 
+  m_keyChain.signByIdentity(*cert, m_identity);
+  return cert;
+
+}
+
+void
+ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate)
+{
   Name endorsee = endorseCertificate.getPublicKeyName().getPrefix(-1);
+  Name dnsName = m_identity;
+  dnsName.append("DNS")
+    .append(endorsee.wireEncode())
+    .append("ENDORSEE")
+    .appendVersion();
 
-  Name dnsName = signerIdentity;
-  dnsName.append("DNS").append(endorsee.wireEncode()).append("ENDORSEE").appendVersion();
+  Data data;
   data.setName(dnsName);
-
   data.setContent(endorseCertificate.wireEncode());
 
-  m_keyChain->signByIdentity(data, signerIdentity);
-  m_dnsStorage->updateDnsEndorseOthers(data, signerIdentity, endorsee);
+  m_keyChain.signByIdentity(data, m_identity);
+
+  m_contactStorage->updateDnsEndorseOthers(data, dnsName.get(-3).toEscapedString());
   m_face->put(data);
 }
 
 void
-ContactManager::publishCollectEndorsedDataInDNS(const Name& identity)
+ContactManager::sendInterest(const Interest& interest,
+                             const OnDataValidated& onValidated,
+                             const OnDataValidationFailed& onValidationFailed,
+                             const TimeoutNotify& timeoutNotify,
+                             int retry /* = 1 */)
 {
-  Data data;
+  m_face->expressInterest(interest, 
+                          bind(&ContactManager::onTargetData, 
+                               this, _1, _2, onValidated, onValidationFailed),
+                          bind(&ContactManager::onTargetTimeout,
+                               this, _1, retry, onValidated, onValidationFailed, timeoutNotify));
+}
 
-  Name dnsName = identity;
-  dnsName.append("DNS").append("ENDORSED").appendVersion();
-  data.setName(dnsName);
-  
-  vector<Buffer> collectEndorseList;
-  m_contactStorage->getCollectEndorseList(identity, collectEndorseList);
-  
-  Chronos::EndorseCollection endorseCollection;
+void
+ContactManager::onTargetData(const Interest& interest, 
+                             const Data& data,
+                             const OnDataValidated& onValidated,
+                             const OnDataValidationFailed& onValidationFailed)
+{
+  // _LOG_DEBUG("On receiving data: " << data.getName());
+  m_validator->validate(data, onValidated, onValidationFailed); 
+}
 
-  vector<Buffer>::const_iterator it = collectEndorseList.begin();
-  for(; it != collectEndorseList.end(); it++)
+void
+ContactManager::onTargetTimeout(const Interest& interest, 
+                                int retry,
+                                const OnDataValidated& onValidated,
+                                const OnDataValidationFailed& onValidationFailed,
+                                const TimeoutNotify& timeoutNotify)
+{
+  // _LOG_DEBUG("On interest timeout: " << interest.getName());
+  if(retry > 0)
+    sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
+  else
+    timeoutNotify(interest);
+}
+
+void
+ContactManager::onDnsInterest(const Name& prefix, const Interest& interest)
+{
+  const Name& interestName = interest.getName();
+  shared_ptr<Data> data;
+  
+  if(interestName.size() <= prefix.size())
+    return;
+
+  if(interestName.size() == (prefix.size()+1))
     {
-      string entryStr(reinterpret_cast<const char*>(it->buf()), it->size());
-      endorseCollection.add_endorsement()->set_blob(entryStr);
+      data = m_contactStorage->getDnsData("N/A", interestName.get(prefix.size()).toEscapedString());
+      if(static_cast<bool>(data))
+        m_face->put(*data);
+      return;
     }
 
-  string encoded;
-  endorseCollection.SerializeToString(&encoded);
-
-  data.setContent(reinterpret_cast<const uint8_t*>(encoded.c_str()), encoded.size());
+  if(interestName.size() == (prefix.size()+2))
+    {
+      data = m_contactStorage->getDnsData(interestName.get(prefix.size()).toEscapedString(),
+                                          interestName.get(prefix.size()+1).toEscapedString());
+      if(static_cast<bool>(data))
+        m_face->put(*data);
+      return;
+    }
+}
   
-  m_keyChain->signByIdentity(data, identity);
-  m_dnsStorage->updateDnsOthersEndorse(data, identity);
-  m_face->put(data);
+void
+ContactManager::onDnsRegisterFailed(const Name& prefix, const string& failInfo)
+{
+  emit warning(QString(failInfo.c_str()));
+}
+
+
+// public slots
+void
+ContactManager::onIdentityUpdated(const QString& identity)
+{
+  m_identity = Name(identity.toStdString());
+
+  m_contactStorage = make_shared<ContactStorage>(m_identity);
+
+  if(m_dnsListenerId)
+    m_face->unsetInterestFilter(m_dnsListenerId);
+
+  Name dnsPrefix;
+  dnsPrefix.append(m_identity).append("DNS");
+  m_dnsListenerId = m_face->setInterestFilter(dnsPrefix, 
+                                              bind(&ContactManager::onDnsInterest, this, _1, _2),
+                                              bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));
+
+  m_contactList.clear();
+  m_contactStorage->getAllContacts(m_contactList);
+
+  m_bufferedContacts.clear();
+
+  collectEndorsement();
 }
 
 void
-ContactManager::addContact(const IdentityCertificate& identityCertificate, const Profile& profile)
+ContactManager::onFetchContactInfo(const QString& identity)
 {
-  try{
-    EndorseCertificate endorseCertificate(identityCertificate, profile);
-    
-    m_keyChain->signByIdentity(endorseCertificate, m_defaultIdentity);
+  // try to fetch self-endorse-certificate via DNS PROFILE first.
+  Name identityName(identity.toStdString());
+  Name interestName;
+  interestName.append(identityName).append("DNS").append("PROFILE");
 
-    ContactItem contactItem(endorseCertificate);
+  // _LOG_DEBUG("onFetchContactInfo " << identity.toStdString() << " profile: " << interestName);
+  
+  Interest interest(interestName);
+  interest.setInterestLifetime(1000);
+  interest.setMustBeFresh(true);
 
-    m_contactStorage->addContact(contactItem);
+  OnDataValidated onValidated = bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
+  OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, identityName);
+  TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, _1, identityName);
 
-    emit contactAdded(contactItem.getNameSpace());
+  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
+}
 
-  }catch(std::runtime_error& e){
-    emit warning(e.what());
-    _LOG_ERROR("Exception: " << e.what());
+void
+ContactManager::onAddFetchedContact(const QString& identity)
+{
+  // _LOG_DEBUG("onAddFetchedContact");
+
+  Name identityName(identity.toStdString());
+
+  BufferedContacts::const_iterator it = m_bufferedContacts.find(identityName);
+  if(it != m_bufferedContacts.end())
+    {
+      Contact contact(*(it->second.m_selfEndorseCert));
+      // _LOG_DEBUG("onAddFetchedContact: contact ready");
+      try
+        {
+          m_contactStorage->addContact(contact);
+          m_bufferedContacts.erase(identityName);
+
+          m_contactList.clear();
+          m_contactStorage->getAllContacts(m_contactList);
+
+          onWaitForContactList();
+        }
+      catch(ContactStorage::Error& e)
+        {
+          emit warning(QString::fromStdString(e.what()));
+        }
+    }
+  else
+    {
+      emit warning(QString("Failure: no information of %1").arg(identity));
+    }
+}
+
+void
+ContactManager::onUpdateProfile()
+{
+  // Get current profile;
+  shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile();
+  if(!static_cast<bool>(newProfile))
     return;
+
+  _LOG_DEBUG("ContactManager::onUpdateProfile: getProfile");
+
+  shared_ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(*newProfile);
+
+  m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate);
+
+  publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
+}
+
+void
+ContactManager::onRefreshBrowseContact()
+{
+  return; // the website info is not available.
+
+  std::vector<std::string> bufferedIdCertNames;
+  try
+    {
+      using namespace boost::asio::ip;
+      tcp::iostream request_stream;
+      request_stream.expires_from_now(boost::posix_time::milliseconds(5000));
+      request_stream.connect("ndncert.named-data.net","80");
+      if(!request_stream)
+        {
+          emit warning(QString::fromStdString("Fail to fetch certificate directory! #1"));
+          return;
+        }
+
+      request_stream << "GET /cert/list/ HTTP/1.0\r\n";
+      request_stream << "Host: ndncert.named-data.net\r\n\r\n";
+      request_stream.flush();
+
+      string line1;
+      std::getline(request_stream,line1);
+      if (!request_stream)
+        {
+          emit warning(QString::fromStdString("Fail to fetch certificate directory! #2"));
+          return;
+        }
+
+      std::stringstream response_stream(line1);
+      std::string http_version;
+      response_stream >> http_version;
+      unsigned int status_code;
+      response_stream >> status_code;
+      std::string status_message;
+      std::getline(response_stream,status_message);
+
+      if (!response_stream||http_version.substr(0,5)!="HTTP/")
+        {
+          emit warning(QString::fromStdString("Fail to fetch certificate directory! #3"));
+          return;
+        }
+      if (status_code!=200)
+        {
+          emit warning(QString::fromStdString("Fail to fetch certificate directory! #4"));
+          return;
+        }
+      vector<string> headers;
+      std::string header;
+      while (std::getline(request_stream, header) && header != "\r")
+        headers.push_back(header);
+
+      std::istreambuf_iterator<char> stream_iter (request_stream);
+      std::istreambuf_iterator<char> end_of_stream;
+      
+      typedef boost::tokenizer< boost::escaped_list_separator<char>, std::istreambuf_iterator<char> > tokenizer_t;
+      tokenizer_t certItems (stream_iter, end_of_stream,boost::escaped_list_separator<char>('\\', '\n', '"'));
+
+      for (tokenizer_t::iterator it = certItems.begin(); it != certItems.end (); it++)
+        if (!it->empty())
+          bufferedIdCertNames.push_back(*it);
+    }
+  catch(std::exception &e)
+    {
+      emit warning(QString::fromStdString("Fail to fetch certificate directory! #N"));
+    }
+
+  {
+    boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
+    m_idCertCount = bufferedIdCertNames.size();
   }
+  m_bufferedIdCerts.clear();
+
+  std::vector<std::string>::const_iterator it  = bufferedIdCertNames.begin();
+  std::vector<std::string>::const_iterator end = bufferedIdCertNames.end();
+  for(; it != end; it++)
+    {
+      Name certName(*it);
+
+      Interest interest(certName);
+      interest.setInterestLifetime(1000);
+      interest.setMustBeFresh(true);
+      
+      OnDataValidated onValidated = bind(&ContactManager::onIdentityCertValidated, this, _1);
+      OnDataValidationFailed onValidationFailed = bind(&ContactManager::onIdentityCertValidationFailed, this, _1);
+      TimeoutNotify timeoutNotify = bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);
+
+      sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
+    }
+  
 }
 
 void
-ContactManager::removeContact(const Name& contactNameSpace)
+ContactManager::onFetchIdCert(const QString& qCertName)
 {
-  shared_ptr<ContactItem> contact = getContact(contactNameSpace);
-  if(!static_cast<bool>(contact))
-    return;
-  m_contactStorage->removeContact(contactNameSpace);
-  emit contactRemoved(contact->getPublicKeyName());
+  Name certName(qCertName.toStdString());
+  if(m_bufferedIdCerts.find(certName) != m_bufferedIdCerts.end())
+    {
+      emit idCertReady(*m_bufferedIdCerts[certName]);
+    }
 }
 
-}//chronos
+void
+ContactManager::onAddFetchedContactIdCert(const QString& qCertName)
+{
+  Name certName(qCertName.toStdString());
+  Name identity = IdentityCertificate::certificateNameToPublicKeyName(certName).getPrefix(-1);
+
+  BufferedIdCerts::const_iterator it = m_bufferedIdCerts.find(certName);
+  if(it != m_bufferedIdCerts.end())
+    {
+      Contact contact(*it->second);
+      try
+        {
+          m_contactStorage->addContact(contact);
+          m_bufferedIdCerts.erase(certName);
+
+          m_contactList.clear();
+          m_contactStorage->getAllContacts(m_contactList);
+
+          onWaitForContactList();
+        }
+      catch(ContactStorage::Error& e)
+        {
+          emit warning(QString::fromStdString(e.what()));
+        }
+    }
+  else
+    emit warning(QString("Failure: no information of %1").arg(QString::fromStdString(identity.toUri())));
+}
+
+void
+ContactManager::onWaitForContactList()
+{
+  ContactList::const_iterator it  = m_contactList.begin();
+  ContactList::const_iterator end = m_contactList.end();
+  
+  QStringList aliasList;
+  QStringList idList;
+  for(; it != end; it++)
+    {
+      aliasList << QString((*it)->getAlias().c_str());
+      idList << QString((*it)->getNameSpace().toUri().c_str());
+    }
+  
+  emit contactAliasListReady(aliasList);
+  emit contactIdListReady(idList);
+}
+
+void
+ContactManager::onWaitForContactInfo(const QString& identity)
+{
+  ContactList::const_iterator it  = m_contactList.begin();
+  ContactList::const_iterator end = m_contactList.end();
+
+  for(; it != end; it++)
+    if((*it)->getNameSpace().toUri() == identity.toStdString())
+      emit contactInfoReady(QString((*it)->getNameSpace().toUri().c_str()),
+                            QString((*it)->getName().c_str()),
+                            QString((*it)->getInstitution().c_str()),
+                            (*it)->isIntroducer());
+}
+
+void
+ContactManager::onRemoveContact(const QString& identity)
+{
+  m_contactStorage->removeContact(Name(identity.toStdString()));
+  m_contactList.clear();
+  m_contactStorage->getAllContacts(m_contactList);
+
+  onWaitForContactList();
+}
+
+void
+ContactManager::onUpdateAlias(const QString& identity, const QString& alias)
+{
+  m_contactStorage->updateAlias(Name(identity.toStdString()), alias.toStdString());
+  m_contactList.clear();
+  m_contactStorage->getAllContacts(m_contactList);
+
+  onWaitForContactList();
+}
+
+void
+ContactManager::onUpdateIsIntroducer(const QString& identity, bool isIntroducer)
+{
+  m_contactStorage->updateIsIntroducer(Name(identity.toStdString()), isIntroducer);
+}
+
+void
+ContactManager::onUpdateEndorseCertificate(const QString& identity)
+{
+  Name identityName(identity.toStdString());
+  shared_ptr<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identityName);
+
+  if(!static_cast<bool>(newEndorseCertificate))
+    return;
+
+  m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identityName);
+
+  publishEndorseCertificateInDNS(*newEndorseCertificate);
+}
+
+} // namespace chronos
 
 
 #if WAF
