Make contact-storage pure storage
diff --git a/src/addcontactpanel.cpp b/src/addcontactpanel.cpp
index 012ae4f..34eb2e9 100644
--- a/src/addcontactpanel.cpp
+++ b/src/addcontactpanel.cpp
@@ -11,7 +11,10 @@
 #include "addcontactpanel.h"
 #include "ui_addcontactpanel.h"
 
-AddContactPanel::AddContactPanel(ndn::Ptr<ContactManager> contactManager,
+using namespace ndn;
+using namespace std;
+
+AddContactPanel::AddContactPanel(Ptr<ContactManager> contactManager,
                                  QWidget *parent) 
   : QDialog(parent)
   , ui(new Ui::AddContactPanel)
@@ -23,6 +26,8 @@
           this, SLOT(onCancelClicked()));
   connect(ui->searchButton, SIGNAL(clicked()),
           this, SLOT(onSearchClicked()));
+  connect(&*m_contactManager, SIGNAL(contactFetched(Ptr<EndorseCertificate>)),
+          this, SLOT(selfEndorseCertificateFetched(Ptr<EndorseCertificate>)));
 }
 
 AddContactPanel::~AddContactPanel()
@@ -37,6 +42,8 @@
 void
 AddContactPanel::onSearchClicked()
 {
+  QString inputIdentity = ui->contactInput->text();
+  m_searchIdentity = Name(inputIdentity.toUtf8().constData());
 }
 
 void
@@ -44,6 +51,11 @@
 {
 }
 
+void 
+AddContactPanel::selfEndorseCertificateFetched(Ptr<EndorseCertificate> endorseCertificate)
+{
+}
+
 #if WAF
 #include "addcontactpanel.moc"
 #include "addcontactpanel.cpp.moc"
diff --git a/src/addcontactpanel.h b/src/addcontactpanel.h
index 1da3788..fb547a1 100644
--- a/src/addcontactpanel.h
+++ b/src/addcontactpanel.h
@@ -42,8 +42,12 @@
   void
   onAddClicked();
 
+  void
+  selfEndorseCertificateFetched(ndn::Ptr<EndorseCertificate> endorseCertificate);
+
 private:
   Ui::AddContactPanel *ui;
+  ndn::Name m_searchIdentity;
   ndn::Ptr<ContactManager> m_contactManager;
 };
 
diff --git a/src/addcontactpanel.ui b/src/addcontactpanel.ui
index 3632931..99fd5e9 100644
--- a/src/addcontactpanel.ui
+++ b/src/addcontactpanel.ui
@@ -13,7 +13,7 @@
   <property name="windowTitle">
    <string>Add Contact</string>
   </property>
-  <widget class="QWidget" name="">
+  <widget class="QWidget" name="layoutWidget">
    <property name="geometry">
     <rect>
      <x>10</x>
@@ -52,6 +52,9 @@
         <property name="text">
          <string>Search</string>
         </property>
+        <property name="autoDefault">
+         <bool>false</bool>
+        </property>
        </widget>
       </item>
      </layout>
@@ -66,6 +69,9 @@
         <property name="text">
          <string>Cancel</string>
         </property>
+        <property name="autoDefault">
+         <bool>false</bool>
+        </property>
        </widget>
       </item>
       <item>
@@ -73,6 +79,9 @@
         <property name="text">
          <string>Add</string>
         </property>
+        <property name="autoDefault">
+         <bool>false</bool>
+        </property>
        </widget>
       </item>
      </layout>
diff --git a/src/contact-manager.cpp b/src/contact-manager.cpp
index 0ebd2e3..b525215 100644
--- a/src/contact-manager.cpp
+++ b/src/contact-manager.cpp
@@ -10,6 +10,7 @@
 
 #include "contact-manager.h"
 
+#ifndef Q_MOC_RUN
 #include <ndn.cxx/wrapper/wrapper.h>
 #include <ndn.cxx/security/keychain.h>
 #include <ndn.cxx/security/identity/basic-identity-storage.h>
@@ -18,24 +19,27 @@
 #include <ndn.cxx/security/policy/identity-policy-rule.h>
 #include <ndn.cxx/security/cache/ttl-certificate-cache.h>
 #include <ndn.cxx/security/encryption/basic-encryption-manager.h>
-
 #include <fstream>
+#endif
 
 using namespace ndn;
 using namespace ndn::security;
 
-ContactManager::ContactManager(Ptr<ContactStorage> contactStorage)
+ContactManager::ContactManager(Ptr<ContactStorage> contactStorage,
+                               Ptr<DnsStorage> dnsStorage)
   : m_contactStorage(contactStorage)
+  , m_dnsStorage(dnsStorage)
 {
-  
-  m_wrapper = Ptr<Wrapper>(new Wrapper(setKeychain()));
+  setKeychain();
+
+  m_wrapper = Ptr<Wrapper>(new Wrapper(m_keychain));
 }
 
 ContactManager::~ContactManager()
 {
 }
 
-Ptr<Keychain>
+void
 ContactManager::setKeychain()
 {
   Ptr<OSXPrivatekeyStorage> privateStorage = Ptr<OSXPrivatekeyStorage>::Create();
@@ -45,15 +49,22 @@
   Ptr<EncryptionManager> encryptionManager = Ptr<EncryptionManager>(new BasicEncryptionManager(privateStorage, "/tmp/encryption.db"));
   Ptr<Keychain> keychain = Ptr<Keychain>(new Keychain(identityManager, policyManager, encryptionManager));
 
+  policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><PROFILE>",
+                                                                                          "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
+                                                                                          "==", "\\1", "\\1\\2", true)));
   policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
 											  "^([^<KEY>]*)<KEY>(<>*<KSK-.*>)<ID-CERT>", 
-											  "==", "\\1", "\\1\\2", false)));
+											  "==", "\\1", "\\1\\2", true)));
   policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY>(<>*)<KSK-.*><ID-CERT>",
 											  "^([^<KEY>]*)<KEY><DSK-.*><ID-CERT>",
-											  ">", "\\1\\2", "\\1", false)));
+											  ">", "\\1\\2", "\\1", true)));
   policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY><DSK-.*><ID-CERT>",
 											  "^([^<KEY>]*)<KEY>(<>*)<KSK-.*><ID-CERT>",
-											  "==", "\\1", "\\1\\2", false)));
+											  "==", "\\1", "\\1\\2", true)));
+
+  policyManager->addSigningPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><PROFILE>",
+                                                                                     "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
+                                                                                     "==", "\\1", "\\1\\2", true)));
 
   ifstream is ("trust-anchor.data", ios::binary);
   is.seekg (0, ios::end);
@@ -70,5 +81,182 @@
   
   delete memblock;
 
-  return keychain;
+  m_keychain = keychain;
 }
+
+
+void
+ContactManager::fetchSelfEndorseCertificate(const ndn::Name& identity)
+{
+  Name interestName = identity;
+  interestName.append("DNS").append("PROFILE");
+  
+  Ptr<Interest> interestPtr = Ptr<Interest>(new Interest(interestName));
+  Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&ContactManager::onDnsSelfEndorseCertificateVerified, 
+                                                               this,
+                                                               _1,
+                                                               identity),
+						   boost::bind(&ContactManager::onDnsSelfEndorseCertificateTimeout,
+                                                               this,
+                                                               _1, 
+                                                               _2,
+                                                               identity,
+                                                               0),
+						   boost::bind(&ContactManager::onDnsSelfEndorseCertificateUnverified,
+                                                               this,
+                                                               _1,
+                                                               identity)));
+  m_wrapper->sendInterest(interestPtr, closure);
+}
+
+void
+ContactManager::updateProfileData(const Name& identity)
+{
+  // Get current profile;
+  Ptr<Profile> newProfile = m_contactStorage->getSelfProfile(identity);
+  if(NULL == newProfile)
+    return;
+  Ptr<Blob> newProfileBlob = newProfile->toDerBlob();
+
+  // Check if profile exists
+  Ptr<Blob> profileDataBlob = m_contactStorage->getSelfEndorseCertificate(identity);
+  if(NULL != profileDataBlob)
+    {
+      Ptr<Data> plainData = Data::decodeFromWire(profileDataBlob);
+      EndorseCertificate oldEndorseCertificate(*plainData);    
+      // _LOG_DEBUG("Certificate converted!");
+      const Blob& oldProfileBlob = oldEndorseCertificate.getProfileData()->content();
+
+      if(oldProfileBlob == *newProfileBlob)
+        return;
+
+      Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
+      // _LOG_DEBUG("Signing DONE!");
+      if(NULL == newEndorseCertificate)
+        return;
+
+      m_contactStorage->updateSelfEndorseCertificate(newEndorseCertificate, identity);
+
+      publishSelfEndorseCertificateInDNS(newEndorseCertificate);
+    }
+  else
+    {
+      Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
+      // _LOG_DEBUG("Signing DONE!");
+      if(NULL == newEndorseCertificate)
+        return;
+      
+      m_contactStorage->addSelfEndorseCertificate(newEndorseCertificate, identity);
+
+      publishSelfEndorseCertificateInDNS(newEndorseCertificate);
+    }
+}
+
+Ptr<EndorseCertificate>
+ContactManager::getSignedSelfEndorseCertificate(const Name& identity,
+                                                const Profile& profile)
+{
+  Ptr<IdentityManager> identityManager = m_keychain->getIdentityManager();
+  Name certificateName = identityManager->getDefaultCertificateNameByIdentity(identity);
+  if(0 == certificateName.size())
+    return NULL;
+
+  Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(identity, profile));
+  identityManager->signByCertificate(*profileData, certificateName);
+
+  Ptr<security::IdentityCertificate> dskCert = identityManager->getCertificate(certificateName);
+  Ptr<const signature::Sha256WithRsa> dskCertSig = DynamicCast<const signature::Sha256WithRsa>(dskCert->getSignature());
+  // HACK! KSK certificate should be retrieved from network.
+  Ptr<security::IdentityCertificate> kskCert = identityManager->getCertificate(dskCertSig->getKeyLocator().getKeyName());
+
+  vector<string> endorseList;
+  Profile::const_iterator it = profile.begin();
+  for(; it != profile.end(); it++)
+    endorseList.push_back(it->first);
+  
+  Ptr<EndorseCertificate> selfEndorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(*kskCert,
+                                                                                                  kskCert->getNotBefore(),
+                                                                                                  kskCert->getNotAfter(),
+                                                                                                  profileData,
+                                                                                                  endorseList));
+  identityManager->signByCertificate(*selfEndorseCertificate, kskCert->getName());
+
+  return selfEndorseCertificate;
+}
+
+
+void
+ContactManager::onDnsSelfEndorseCertificateVerified(Ptr<Data> data, const Name& identity)
+{
+  const Blob& dataContentBlob = data->content();
+  
+  boost::iostreams::stream
+    <boost::iostreams::array_source> is (dataContentBlob.buf(), dataContentBlob.size());
+
+  Ptr<Data> plainData = Data::decodeFromWire(is);
+  Ptr<EndorseCertificate> selfEndorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(*plainData));
+  
+  const security::Publickey& ksk = selfEndorseCertificate->getPublicKeyInfo();
+  if(security::PolicyManager::verifySignature(*plainData, ksk))
+    emit contactFetched (selfEndorseCertificate); 
+  else
+    emit contactFetchFailed (identity);
+}
+
+void
+ContactManager::onDnsSelfEndorseCertificateUnverified(Ptr<Data> data, const Name& identity)
+{ emit contactFetchFailed (identity); }
+
+void
+ContactManager::onDnsSelfEndorseCertificateTimeout(Ptr<Closure> closure, Ptr<Interest> interest, const Name& identity, int retry)
+{
+  if(retry > 0)
+    {
+      Ptr<Closure> newClosure = Ptr<Closure>(new Closure(closure->m_dataCallback,
+                                                         boost::bind(&ContactManager::onDnsSelfEndorseCertificateTimeout, 
+                                                                     this, 
+                                                                     _1, 
+                                                                     _2, 
+                                                                     identity,
+                                                                     retry - 1),
+                                                         closure->m_unverifiedCallback,
+                                                         closure->m_stepCount)
+                                             );
+      m_wrapper->sendInterest(interest, newClosure);
+    }
+  else
+    emit contactFetchFailed(identity);
+}
+
+void
+ContactManager::publishSelfEndorseCertificateInDNS(Ptr<EndorseCertificate> selfEndorseCertificate)
+{
+  Ptr<Data> data = Ptr<Data>::Create();
+
+  Name keyName = selfEndorseCertificate->getPublicKeyName();
+  Name identity = keyName.getSubName(0, keyName.size()-1);
+
+  TimeInterval ti = time::NowUnixTimestamp();
+  ostringstream oss;
+  oss << ti.total_seconds();
+
+  Name dnsName = identity;
+  dnsName.append("DNS").append("PROFILE").append(oss.str());
+
+  data->setName(dnsName);
+  Ptr<Blob> blob = selfEndorseCertificate->encodeToWire();
+  Content content(blob->buf(), blob->size());
+  data->setContent(content);
+
+  m_keychain->signByIdentity(*data, identity);
+  
+  Ptr<Blob> dnsBlob = data->encodeToWire();
+
+  m_wrapper->putToCcnd(*dnsBlob);
+}
+
+
+#if WAF
+#include "contact-manager.moc"
+#include "contact-manager.cpp.moc"
+#endif
diff --git a/src/contact-manager.h b/src/contact-manager.h
index ddf8489..1cde4bc 100644
--- a/src/contact-manager.h
+++ b/src/contact-manager.h
@@ -11,30 +11,81 @@
 #ifndef LINKNDN_CONTACT_MANAGER_H
 #define LINKNDN_CONTACT_MANAGER_H
 
-#include "contact-storage.h"
-#include "ndn.cxx/wrapper/wrapper.h"
+#include <QObject>
 
-class ContactManager
+#ifndef Q_MOC_RUN
+#include "contact-storage.h"
+#include "dns-storage.h"
+#include "endorse-certificate.h"
+#include "ndn.cxx/wrapper/wrapper.h"
+#endif
+
+
+class ContactManager : public QObject
 {
+  Q_OBJECT
+
 public:
-  ContactManager(ndn::Ptr<ContactStorage> contactStorage);
+  ContactManager(ndn::Ptr<ContactStorage> contactStorage,
+                 ndn::Ptr<DnsStorage> dnsStorage);
 
   ~ContactManager();
 
+  void
+  fetchSelfEndorseCertificate(const ndn::Name& identity);
+
+  void
+  updateProfileData(const ndn::Name& identity);
+
   inline ndn::Ptr<ContactStorage>
   getContactStorage()
   { return m_contactStorage; }
 
+  inline ndn::Ptr<DnsStorage>
+  getDnsStorage()
+  { return m_dnsStorage; }
+
+  inline ndn::Name
+  getDefaultIdentity()
+  { return m_keychain->getDefaultIdentity(); }
+
   inline ndn::Ptr<ndn::Wrapper>
   getWrapper()
   { return m_wrapper; }
 
 private:
-  ndn::Ptr<ndn::security::Keychain>
+  void
   setKeychain();
+
+  ndn::Ptr<EndorseCertificate>
+  getSignedSelfEndorseCertificate(const ndn::Name& identity, const Profile& profile);
+
+  void
+  publishSelfEndorseCertificateInDNS(ndn::Ptr<EndorseCertificate> selfEndorseCertificate);
+
+  void 
+  onDnsSelfEndorseCertificateVerified(ndn::Ptr<ndn::Data> selfEndorseCertificate, const ndn::Name& identity);
+
+  void
+  onDnsSelfEndorseCertificateUnverified(ndn::Ptr<ndn::Data> selfEndorseCertificate, const ndn::Name& identity);
+
+  void
+  onDnsSelfEndorseCertificateTimeout(ndn::Ptr<ndn::Closure> closure, ndn::Ptr<ndn::Interest> interest, const ndn::Name& identity, int retry);
+
+signals:
+  void 
+  contactFetched(ndn::Ptr<EndorseCertificate> selfEndorseCertificate);
+  
+  void
+  contactFetchFailed(const ndn::Name& identity);
+
+private slots:
+  
   
 private:
   ndn::Ptr<ContactStorage> m_contactStorage;
+  ndn::Ptr<DnsStorage> m_dnsStorage;
+  ndn::Ptr<ndn::security::Keychain> m_keychain;
   ndn::Ptr<ndn::Wrapper> m_wrapper;
 };
 
diff --git a/src/contact-storage.cpp b/src/contact-storage.cpp
index 3197d9c..989702a 100644
--- a/src/contact-storage.cpp
+++ b/src/contact-storage.cpp
@@ -11,11 +11,8 @@
 #include "contact-storage.h"
 #include "exception.h"
 
-#include <string>
 #include <boost/filesystem.hpp>
 #include <ndn.cxx/fields/signature-sha256-with-rsa.h>
-#include <ndn.cxx/security/exception.h>
-#include <ndn.cxx/helpers/der/exception.h>
 #include "logging.h"
 
 using namespace std;
@@ -75,8 +72,7 @@
 CREATE INDEX nc_index ON NormalContact(contact_namespace);           \n \
 ";
 
-ContactStorage::ContactStorage(Ptr<security::IdentityManager> identityManager)
-  : m_identityManager(identityManager)
+ContactStorage::ContactStorage()
 {
   fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
   fs::create_directories (chronosDir);
@@ -179,29 +175,6 @@
   return result;
 }
 
-// void
-// ContactStorage::setSelfProfileIdentity(const Name& identity)
-// {
-//   string profileType("IDENTITY");
-//   Blob identityBlob(identity.toUri().c_str(), identity.toUri().size());
-  
-//   sqlite3_stmt *stmt;  
-//   if(doesSelfEntryExist(profileType))
-//     {
-//       sqlite3_prepare_v2 (m_db, "UPDATE SelfProfile SET profile_value=? WHERE profile_type=?", -1, &stmt, 0);
-//       sqlite3_bind_text(stmt, 1, identityBlob.buf(), identityBlob.size(), SQLITE_TRANSIENT);
-//       sqlite3_bind_text(stmt, 2, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
-//     }
-//   else
-//     {
-//       sqlite3_prepare_v2 (m_db, "INSERT INTO SelfProfile (profile_type, profile_value) values (?, ?)", -1, &stmt, 0);
-//       sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
-//       sqlite3_bind_text(stmt, 2, identityBlob.buf(), identityBlob.size(), SQLITE_TRANSIENT);
-//     }
-//   sqlite3_step (stmt);
-//   sqlite3_finalize (stmt);
-// }
-
 void
 ContactStorage::setSelfProfileEntry(const Name& identity, const string& profileType, const Blob& profileValue)
 {
@@ -365,64 +338,6 @@
   return normalContacts;
 }
 
-void
-ContactStorage::updateProfileData(const Name& identity) const
-{
-  // Get current profile;
-  Ptr<Profile> newProfile = getSelfProfile(identity);
-  if(NULL == newProfile)
-    return;
-  Ptr<Blob> newProfileBlob = newProfile->toDerBlob();
-
-  // Check if profile exists
-  sqlite3_stmt *stmt;
-  sqlite3_prepare_v2 (m_db, "SELECT profile_data FROM ProfileData where identity=?", -1, &stmt, 0);
-  sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
-
-  if(sqlite3_step (stmt) != SQLITE_ROW)
-    {
-      sqlite3_finalize (stmt);
-
-      Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
-      _LOG_DEBUG("Signing DONE!");
-      if(NULL == newEndorseCertificate)
-        return;
-      Ptr<Blob> newEndorseCertificateBlob = newEndorseCertificate->encodeToWire();
-
-      _LOG_DEBUG("Before Inserting!");
-
-      sqlite3_prepare_v2 (m_db, "INSERT INTO ProfileData (identity, profile_data) values (?, ?)", -1, &stmt, 0);
-      sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
-      sqlite3_bind_text(stmt, 2, newEndorseCertificateBlob->buf(), newEndorseCertificateBlob->size(), SQLITE_TRANSIENT);
-      sqlite3_step(stmt);
-    }
-  else
-    {
-      Ptr<Blob> profileDataBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
-      Ptr<Data> plainData = Data::decodeFromWire(profileDataBlob);
-      EndorseCertificate oldEndorseCertificate(*plainData);    
-      // _LOG_DEBUG("Certificate converted!");
-      const Blob& oldProfileBlob = oldEndorseCertificate.getProfileData()->content();
-      sqlite3_finalize (stmt);
-
-      if(oldProfileBlob == *newProfileBlob)
-        return;
-
-      Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
-      _LOG_DEBUG("Signing DONE!");
-      if(NULL == newEndorseCertificate)
-        return;
-      Ptr<Blob> newEndorseCertificateBlob = newEndorseCertificate->encodeToWire();
-
-      _LOG_DEBUG("Before Updating!");
-
-      sqlite3_prepare_v2 (m_db, "UPDATE ProfileData SET profile_data=? WHERE identity=?", -1, &stmt, 0);
-      sqlite3_bind_text(stmt, 1, newEndorseCertificateBlob->buf(), newEndorseCertificateBlob->size(), SQLITE_TRANSIENT);
-      sqlite3_bind_text(stmt, 2, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
-      sqlite3_step(stmt);
-    }
-}
-
 Ptr<Profile>
 ContactStorage::getSelfProfile(const Name& identity) const
 {  
@@ -441,34 +356,42 @@
   return profile;
 }
 
-Ptr<EndorseCertificate>
-ContactStorage::getSignedSelfEndorseCertificate(const Name& identity,
-                                                const Profile& profile) const
+Ptr<Blob>
+ContactStorage::getSelfEndorseCertificate(const Name& identity)
 {
-  Name certificateName = m_identityManager->getDefaultCertificateNameByIdentity(identity);
-  if(0 == certificateName.size())
-    return NULL;
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT profile_data FROM ProfileData where identity=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
 
-  Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(identity, profile));
-  m_identityManager->signByCertificate(*profileData, certificateName);
+  Ptr<Blob> result = NULL;
+  if(sqlite3_step (stmt) == SQLITE_ROW)
+    result = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
 
-  Ptr<security::IdentityCertificate> dskCert = m_identityManager->getCertificate(certificateName);
-  Ptr<const signature::Sha256WithRsa> dskCertSig = boost::dynamic_pointer_cast<const signature::Sha256WithRsa>(dskCert->getSignature());
-  // HACK! KSK certificate should be retrieved from network.
-  Ptr<security::IdentityCertificate> kskCert = m_identityManager->getCertificate(dskCertSig->getKeyLocator().getKeyName());
+  sqlite3_finalize (stmt);
 
-  vector<string> endorseList;
-  Profile::const_iterator it = profile.begin();
-  for(; it != profile.end(); it++)
-    endorseList.push_back(it->first);
-  
-  Ptr<EndorseCertificate> selfEndorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(*kskCert,
-                                                                                                  kskCert->getNotBefore(),
-                                                                                                  kskCert->getNotAfter(),
-                                                                                                  profileData,
-                                                                                                  endorseList));
-  m_identityManager->signByCertificate(*selfEndorseCertificate, kskCert->getName());
-
-  return selfEndorseCertificate;
+  return result;
 }
 
+void
+ContactStorage::updateSelfEndorseCertificate(Ptr<EndorseCertificate> newEndorseCertificate, const Name& identity)
+{
+  Ptr<Blob> newEndorseCertificateBlob = newEndorseCertificate->encodeToWire();
+
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "UPDATE ProfileData SET profile_data=? WHERE identity=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, newEndorseCertificateBlob->buf(), newEndorseCertificateBlob->size(), SQLITE_TRANSIENT);
+  sqlite3_bind_text(stmt, 2, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
+  sqlite3_step(stmt);
+}
+
+void
+ContactStorage::addSelfEndorseCertificate(Ptr<EndorseCertificate> newEndorseCertificate, const Name& identity)
+{
+  Ptr<Blob> newEndorseCertificateBlob = newEndorseCertificate->encodeToWire();
+
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "INSERT INTO ProfileData (identity, profile_data) values (?, ?)", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
+  sqlite3_bind_text(stmt, 2, newEndorseCertificateBlob->buf(), newEndorseCertificateBlob->size(), SQLITE_TRANSIENT);
+  sqlite3_step(stmt);
+}
diff --git a/src/contact-storage.h b/src/contact-storage.h
index 7fc3171..3275c40 100644
--- a/src/contact-storage.h
+++ b/src/contact-storage.h
@@ -18,12 +18,15 @@
 #include <ndn.cxx/security/identity/identity-manager.h>
 #include <ndn.cxx/fields/signature-sha256-with-rsa.h>
 
+
 class ContactStorage
 {
+
 public:
-  ContactStorage(ndn::Ptr<ndn::security::IdentityManager> identityManager);
+  ContactStorage();
   
-  ~ContactStorage() {}
+  ~ContactStorage() 
+  {sqlite3_close(m_db);}
 
   void
   setSelfProfileEntry(const ndn::Name& identity, const std::string& profileType, const ndn::Blob& profileValue);
@@ -42,13 +45,18 @@
 
   std::vector<ndn::Ptr<ContactItem> >
   getAllNormalContacts() const;
+    
+  ndn::Ptr<Profile>
+  getSelfProfile(const ndn::Name& identity) const;
+
+  ndn::Ptr<ndn::Blob>
+  getSelfEndorseCertificate(const ndn::Name& identity);
 
   void
-  updateProfileData(const ndn::Name& identity) const;
-  
-  inline ndn::Ptr<ndn::security::IdentityManager> 
-  getIdentityManager()
-  { return m_identityManager; }
+  updateSelfEndorseCertificate(ndn::Ptr<EndorseCertificate> endorseCertificate, const ndn::Name& identity);
+
+  void
+  addSelfEndorseCertificate(ndn::Ptr<EndorseCertificate> endorseCertificate, const ndn::Name& identity);
   
 private:
   bool
@@ -65,15 +73,7 @@
   bool
   doesContactExist(const ndn::Name& name, bool normal);
 
-  ndn::Ptr<Profile>
-  getSelfProfile(const ndn::Name& identity) const;
-
-  ndn::Ptr<EndorseCertificate>
-  getSignedSelfEndorseCertificate(const ndn::Name& identity,
-                                  const Profile& profile) const;
-  
 private:
-  ndn::Ptr<ndn::security::IdentityManager> m_identityManager;
   sqlite3 *m_db;
 };
 
diff --git a/src/contactpanel.cpp b/src/contactpanel.cpp
index 37cd13e..abfbb08 100644
--- a/src/contactpanel.cpp
+++ b/src/contactpanel.cpp
@@ -44,7 +44,7 @@
     db.setDatabaseName(path);
     bool ok = db.open();
 
-    m_profileEditor = new ProfileEditor(m_contactManager->getContactStorage());
+    m_profileEditor = new ProfileEditor(m_contactManager);
 
     QStringList contactNameList;
     contactNameList << "Alex" << "Wentao" << "Yingdi";
diff --git a/src/main.cpp b/src/main.cpp
index dbf3747..9464195 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -14,6 +14,7 @@
 #include "chronochat.h"
 #include "contactpanel.h"
 #include "contact-storage.h"
+#include "dns-storage.h"
 #include "contact-manager.h"
 #include <ndn.cxx/security/identity/identity-manager.h>
 #include <ndn.cxx/security/identity/osx-privatekey-storage.h>
@@ -31,13 +32,11 @@
 // // 	app.setWindowIcon(QIcon("/Users/yuyingdi/Develop/QT/images/icon_large.png"));
 // // #endif
 
-  Ptr<security::BasicIdentityStorage> publicStorage = Ptr<security::BasicIdentityStorage>::Create();
-  Ptr<security::OSXPrivatekeyStorage> privateStorage = Ptr<security::OSXPrivatekeyStorage>::Create();
-  Ptr<security::IdentityManager> identityManager = Ptr<security::IdentityManager>(new security::IdentityManager(publicStorage, privateStorage));
-  Ptr<ContactStorage> contactStorage = Ptr<ContactStorage>(new ContactStorage(identityManager));
-  Ptr<ContactManager> contactManager = Ptr<ContactManager>(new ContactManager(contactStorage));
-  ContactPanel contactPanel(contactManager);
+  Ptr<ContactStorage> contactStorage = Ptr<ContactStorage>(new ContactStorage());
+  Ptr<DnsStorage> dnsStorage = Ptr<DnsStorage>(new DnsStorage());
+  Ptr<ContactManager> contactManager = Ptr<ContactManager>(new ContactManager(contactStorage, dnsStorage));
 
+  ContactPanel contactPanel(contactManager);
 
   contactPanel.show ();
   contactPanel.activateWindow ();
diff --git a/src/profileeditor.cpp b/src/profileeditor.cpp
index 14eeff4..dd037ca 100644
--- a/src/profileeditor.cpp
+++ b/src/profileeditor.cpp
@@ -23,16 +23,16 @@
 
 INIT_LOGGER("ProfileEditor");
 
-ProfileEditor::ProfileEditor(Ptr<ContactStorage> contactStorage, 
+ProfileEditor::ProfileEditor(Ptr<ContactManager> contactManager, 
                              QWidget *parent) 
     : QDialog(parent)
     , ui(new Ui::ProfileEditor)
     , m_tableModel(new QSqlTableModel())
-    , m_contactStorage(contactStorage)
+    , m_contactManager(contactManager)
 {
   ui->setupUi(this);
   
-  Name defaultIdentity = contactStorage->getIdentityManager()->getDefaultIdentity();
+  Name defaultIdentity = contactManager->getDefaultIdentity();
   ui->identityInput->setText(defaultIdentity.toUri().c_str());
 
   connect(ui->addRowButton, SIGNAL(clicked()),
@@ -83,7 +83,7 @@
 ProfileEditor::onOkClicked()
 {
   m_tableModel->submitAll();
-  m_contactStorage->updateProfileData(m_currentIdentity);
+  m_contactManager->updateProfileData(m_currentIdentity);
   this->hide();
 }
 
diff --git a/src/profileeditor.h b/src/profileeditor.h
index 78d949d..196a263 100644
--- a/src/profileeditor.h
+++ b/src/profileeditor.h
@@ -15,7 +15,7 @@
 #include <QtSql/QSqlTableModel>
 
 #ifndef Q_MOC_RUN
-#include "contact-storage.h"
+#include "contact-manager.h"
 #endif
 
 namespace Ui {
@@ -27,7 +27,7 @@
     Q_OBJECT
 
 public:
-  explicit ProfileEditor(ndn::Ptr<ContactStorage> contactStorage, 
+  explicit ProfileEditor(ndn::Ptr<ContactManager> contactManager, 
                          QWidget *parent = 0);
   
   ~ProfileEditor();
@@ -49,7 +49,7 @@
 private:
   Ui::ProfileEditor *ui;
   QSqlTableModel* m_tableModel;
-  ndn::Ptr<ContactStorage> m_contactStorage;
+  ndn::Ptr<ContactManager> m_contactManager;
   ndn::Name m_defaultIdentity;
   ndn::Name m_currentIdentity;
 };