Adding browsing existing certificates feature
diff --git a/src/browsecontactdialog.cpp b/src/browsecontactdialog.cpp
new file mode 100644
index 0000000..1e3cecb
--- /dev/null
+++ b/src/browsecontactdialog.cpp
@@ -0,0 +1,315 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+
+#include "browsecontactdialog.h"
+#include "ui_browsecontactdialog.h"
+
+#ifndef Q_MOC_RUN
+#include <boost/asio.hpp>
+#include <boost/tokenizer.hpp>
+#include "logging.h"
+#include "exception.h"
+#endif
+
+using namespace std;
+using namespace ndn;
+
+INIT_LOGGER("BrowseContactDialog");
+
+// Q_DECLARE_METATYPE(ndn::security::IdentityCertificate)
+
+BrowseContactDialog::BrowseContactDialog(Ptr<ContactManager> contactManager,
+					 QWidget *parent) 
+  : QDialog(parent)
+  , ui(new Ui::BrowseContactDialog)
+  , m_contactManager(contactManager)
+  , m_warningDialog(new WarningDialog)
+  , m_contactListModel(new QStringListModel)
+{
+  // qRegisterMetaType<ndn::security::IdentityCertificate>("NDNIdentityCertificate");
+
+  ui->setupUi(this);
+
+  ui->ContactList->setModel(m_contactListModel);
+
+  connect(ui->ContactList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+          this, SLOT(updateSelection(const QItemSelection &, const QItemSelection &)));
+  connect(&*m_contactManager, SIGNAL(contactCertificateFetched(const ndn::security::IdentityCertificate &)),
+	  this, SLOT(onCertificateFetched(const ndn::security::IdentityCertificate &)));
+  connect(&*m_contactManager, SIGNAL(contactCertificateFetchFailed(const ndn::Name&)),
+          this, SLOT(onCertificateFetchFailed(const ndn::Name&)));
+  connect(&*m_contactManager, SIGNAL(warning(QString)),
+	  this, SLOT(onWarning(QString)));
+
+  connect(ui->AddButton, SIGNAL(clicked()),
+	  this, SLOT(onAddClicked()));
+	  
+  connect(ui->CancelButton, SIGNAL(clicked()),
+	  this, SLOT(onCancelClicked()));
+}
+
+BrowseContactDialog::~BrowseContactDialog()
+{
+  delete ui;
+}
+
+
+vector<string> 
+BrowseContactDialog::getCertName()
+{
+  vector<string> result;
+  try{
+    using namespace boost::asio::ip;
+    tcp::iostream request_stream;
+    request_stream.expires_from_now(boost::posix_time::milliseconds(3000));
+    request_stream.connect("ndncert.named-data.net","80");
+    if(!request_stream)
+      {
+	m_warningDialog->setMsg("Fail to fetch certificate directory! #1");
+	m_warningDialog->show();
+	return result;
+      }
+    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)
+      {
+	m_warningDialog->setMsg("Fail to fetch certificate directory! #2");
+	m_warningDialog->show();
+	return result;
+      }
+    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/")
+      {
+    	m_warningDialog->setMsg("Fail to fetch certificate directory! #3");
+	m_warningDialog->show();
+	return result;
+      }
+    if (status_code!=200)
+      {
+    	m_warningDialog->setMsg("Fail to fetch certificate directory! #4");
+	m_warningDialog->show();
+	return result;
+      }
+    vector<string> headers;
+    std::string header;
+    while (std::getline(request_stream, header) && header != "\r")
+      headers.push_back(header);
+
+    std::stringbuf buffer;
+    std::ostream os (&buffer);
+
+    os << request_stream.rdbuf();
+    
+    using boost::tokenizer;
+    using boost::escaped_list_separator;
+
+    tokenizer<escaped_list_separator<char> > certItems(buffer.str(), escaped_list_separator<char> ('\\', '\n', '"'));
+    tokenizer<escaped_list_separator<char> >::iterator it = certItems.begin();
+    try{
+      while (it != certItems.end())
+        {
+	  result.push_back(*it);
+          it++;
+        }
+    }catch (exception &e){
+      m_warningDialog->setMsg("Fail to fetch certificate directory! #5");
+      m_warningDialog->show();
+      return vector<string>();
+    }
+    result.pop_back();
+    
+    return result;
+  }catch(std::exception &e){
+    m_warningDialog->setMsg("Fail to fetch certificate directory! #N");
+    m_warningDialog->show();
+    return result;
+  }
+}
+
+void
+BrowseContactDialog::updateCertificateMap(bool filter)
+{
+  vector<string> certNameList = getCertName();
+  if(filter)
+    {
+      map<Name, Name> certificateMap;
+
+      vector<string>::iterator it = certNameList.begin();
+  
+      for(; it != certNameList.end(); it++)
+	{
+	  Name newCertName(*it);
+	  Name keyName = security::IdentityCertificate::certificateNameToPublicKeyName(newCertName, true);
+	  Name identity = keyName.getPrefix(keyName.size()-1);
+	  
+	  map<Name, Name>::iterator map_it = certificateMap.find(identity);
+	  if(map_it != certificateMap.end())
+	    {
+	      Name oldCertName = map_it->second;
+	      Name oldKeyName = security::IdentityCertificate::certificateNameToPublicKeyName(oldCertName, true);
+	      if(keyName > oldKeyName)
+		map_it->second = newCertName;
+	      else if(keyName == oldKeyName && newCertName > oldCertName)
+		map_it->second = newCertName;
+	    }
+	  else
+	    {
+	      certificateMap.insert(pair<Name, Name>(identity, newCertName));
+	    }
+	}
+      map<Name, Name>::iterator map_it = certificateMap.begin();
+      for(; map_it != certificateMap.end(); map_it++)
+	m_certificateNameList.push_back(map_it->second);
+    }
+  else
+    {
+      vector<string>::iterator it = certNameList.begin();
+  
+      for(; it != certNameList.end(); it++)
+	{
+	  m_certificateNameList.push_back(*it);
+	}
+    }
+}
+
+void
+BrowseContactDialog::fetchCertificate()
+{
+  vector<Name>::iterator it = m_certificateNameList.begin();
+  int count = 0;
+  for(; it != m_certificateNameList.end(); it++)
+    {
+      m_contactManager->fetchIdCertificate(*it);
+    }
+}
+
+void
+BrowseContactDialog::onCertificateFetched(const security::IdentityCertificate& identityCertificate)
+{
+  Name certName = identityCertificate.getName();
+  Name certNameNoVersion = certName.getPrefix(certName.size()-1);
+  m_certificateMap.insert(pair<Name, security::IdentityCertificate>(certNameNoVersion, identityCertificate));
+  m_profileMap.insert(pair<Name, Profile>(certNameNoVersion, Profile(identityCertificate)));
+  string name(m_profileMap[certNameNoVersion].getProfileEntry("name")->buf(), m_profileMap[certNameNoVersion].getProfileEntry("name")->size());
+  // Name contactName = m_profileMap[certNameNoVersion].getIdentityName();
+  {
+      UniqueRecLock lock(m_mutex);
+      m_contactList << QString::fromStdString(name);
+      m_contactListModel->setStringList(m_contactList);
+      m_contactNameList.push_back(certNameNoVersion);
+  }    
+}
+
+void
+BrowseContactDialog::onCertificateFetchFailed(const Name& identity)
+{}
+
+void
+BrowseContactDialog::refreshList()
+{
+  {
+      UniqueRecLock lock(m_mutex);
+      m_contactList.clear();
+      m_contactNameList.clear();
+  }
+  m_certificateNameList.clear();
+  m_certificateMap.clear();
+  m_profileMap.clear();
+
+  updateCertificateMap();
+
+  fetchCertificate();
+}
+
+void
+BrowseContactDialog::updateSelection(const QItemSelection &selected,
+				     const QItemSelection &deselected)
+{
+  QModelIndexList items = selected.indexes();
+  Name certName = m_contactNameList[items.first().row()];
+
+  ui->InfoTable->clear();
+  for(int i = ui->InfoTable->rowCount() - 1; i >= 0 ; i--)
+    ui->InfoTable->removeRow(i);
+
+  map<Name, Profile>::iterator it = m_profileMap.find(certName);
+  if(it != m_profileMap.end())
+    {
+      ui->InfoTable->setColumnCount(2);
+
+      QTableWidgetItem *typeHeader = new QTableWidgetItem(QString::fromUtf8("Type"));
+      ui->InfoTable->setHorizontalHeaderItem(0, typeHeader);
+      QTableWidgetItem *valueHeader = new QTableWidgetItem(QString::fromUtf8("Value"));
+      ui->InfoTable->setHorizontalHeaderItem(1, valueHeader);
+
+      Profile::const_iterator pro_it = it->second.begin();
+      int rowCount = 0;        
+  
+      for(; pro_it != it->second.end(); pro_it++, rowCount++)
+	{
+	  ui->InfoTable->insertRow(rowCount);  
+	  QTableWidgetItem *type = new QTableWidgetItem(QString::fromStdString(pro_it->first));
+	  ui->InfoTable->setItem(rowCount, 0, type);
+	  
+	  string valueString(pro_it->second.buf(), pro_it->second.size());
+	  QTableWidgetItem *value = new QTableWidgetItem(QString::fromStdString(valueString));
+	  ui->InfoTable->setItem(rowCount, 1, value);	  
+	}
+    }
+}
+
+void
+BrowseContactDialog::onWarning(QString msg)
+{
+  m_warningDialog->setMsg(msg.toStdString());
+  m_warningDialog->show();
+}
+
+void
+BrowseContactDialog::onAddClicked()
+{
+  QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
+  QModelIndexList selectedList = selectionModel->selectedIndexes();
+  QModelIndexList::iterator it = selectedList.begin();
+  for(; it != selectedList.end(); it++)
+    {
+      Name certName = m_contactNameList[it->row()];
+      if(m_certificateMap.find(certName) != m_certificateMap.end() && m_profileMap.find(certName) != m_profileMap.end())
+	m_contactManager->addContact(m_certificateMap[certName], m_profileMap[certName]);
+      else
+	{
+	  m_warningDialog->setMsg("Not enough information to add contact!");
+	  m_warningDialog->show();
+	}
+    }
+  emit newContactAdded();
+  this->close();
+}
+
+void
+BrowseContactDialog::onCancelClicked()
+{ this->close(); }
+
+#if WAF
+#include "browsecontactdialog.moc"
+#include "browsecontactdialog.cpp.moc"
+#endif
diff --git a/src/browsecontactdialog.h b/src/browsecontactdialog.h
new file mode 100644
index 0000000..f74a14f
--- /dev/null
+++ b/src/browsecontactdialog.h
@@ -0,0 +1,106 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Yingdi Yu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+
+#ifndef BROWSECONTACTDIALOG_H
+#define BROWSECONTACTDIALOG_H
+
+#include <QDialog>
+#include <QStringListModel>
+#include "warningdialog.h"
+
+
+#ifndef Q_MOC_RUN
+#include <ndn.cxx/security/certificate/identity-certificate.h>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include "profile.h"
+#include "contact-manager.h"
+#endif
+
+namespace Ui {
+class BrowseContactDialog;
+}
+
+class BrowseContactDialog : public QDialog
+{
+  Q_OBJECT
+  
+public:
+  explicit BrowseContactDialog(ndn::Ptr<ContactManager> contactManager,
+                               QWidget *parent = 0);
+
+  ~BrowseContactDialog();
+
+protected:
+  typedef boost::recursive_mutex RecLock;
+  typedef boost::unique_lock<RecLock> UniqueRecLock;
+
+private:
+  std::vector<std::string>
+  getCertName();
+
+  void
+  updateCertificateMap(bool filter = false);
+
+  void
+  updateCertificateFetchingStatus(int count);
+
+  void
+  fetchCertificate();
+
+private slots:
+  void
+  updateSelection(const QItemSelection &selected,
+                  const QItemSelection &deselected);
+
+  void
+  onCertificateFetched(const ndn::security::IdentityCertificate& identityCertificate);
+
+  void
+  onCertificateFetchFailed(const ndn::Name& identity);
+
+  void
+  onWarning(QString msg);
+
+  void
+  onAddClicked();
+
+  void
+  onCancelClicked();
+
+public slots:
+  void
+  refreshList();
+
+signals:
+  void
+  newContactAdded();
+
+private:
+  Ui::BrowseContactDialog *ui;
+  
+  ndn::Ptr<ContactManager> m_contactManager;
+
+  WarningDialog* m_warningDialog;
+  QStringListModel* m_contactListModel;
+
+  QStringList m_contactList;  
+  std::vector<ndn::Name> m_contactNameList;
+  std::vector<ndn::Name> m_certificateNameList;
+  std::map<ndn::Name, ndn::security::IdentityCertificate> m_certificateMap;
+  std::map<ndn::Name, Profile> m_profileMap;
+
+  RecLock m_mutex;
+
+
+};
+
+#endif // BROWSECONTACTDIALOG_H
diff --git a/src/browsecontactdialog.ui b/src/browsecontactdialog.ui
new file mode 100644
index 0000000..28958b9
--- /dev/null
+++ b/src/browsecontactdialog.ui
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BrowseContactDialog</class>
+ <widget class="QDialog" name="BrowseContactDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>BrowseContacts</string>
+  </property>
+  <widget class="QWidget" name="">
+   <property name="geometry">
+    <rect>
+     <x>12</x>
+     <y>10</y>
+     <width>581</width>
+     <height>471</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout" stretch="20,1">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout" stretch="2,3">
+      <item>
+       <widget class="QListView" name="ContactList">
+        <property name="contextMenuPolicy">
+         <enum>Qt::CustomContextMenu</enum>
+        </property>
+        <property name="acceptDrops">
+         <bool>false</bool>
+        </property>
+        <property name="editTriggers">
+         <set>QAbstractItemView::NoEditTriggers</set>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QTableWidget" name="InfoTable">
+        <attribute name="horizontalHeaderStretchLastSection">
+         <bool>true</bool>
+        </attribute>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1">
+      <item>
+       <widget class="QPushButton" name="CancelButton">
+        <property name="text">
+         <string>Cancel</string>
+        </property>
+        <property name="autoDefault">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="AddButton">
+        <property name="text">
+         <string>Add </string>
+        </property>
+        <property name="autoDefault">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/contact-manager.cpp b/src/contact-manager.cpp
index 651ab82..371a317 100644
--- a/src/contact-manager.cpp
+++ b/src/contact-manager.cpp
@@ -192,6 +192,7 @@
   
   Ptr<Interest> interestPtr = Ptr<Interest>(new Interest(interestName));
   interestPtr->setChildSelector(Interest::CHILD_RIGHT);
+  interestPtr->setInterestLifetime(1);
   Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&ContactManager::onKeyVerified, 
                                                                this,
                                                                _1,
@@ -210,6 +211,31 @@
 }
 
 void
+ContactManager::fetchIdCertificate(const ndn::Name& certName)
+{
+  Name interestName = certName;
+  
+  Ptr<Interest> interestPtr = Ptr<Interest>(new Interest(interestName));
+  interestPtr->setChildSelector(Interest::CHILD_RIGHT);
+  interestPtr->setInterestLifetime(1);
+  Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&ContactManager::onIdCertificateVerified, 
+                                                               this,
+                                                               _1,
+                                                               certName),
+						   boost::bind(&ContactManager::onIdCertificateTimeout,
+                                                               this,
+                                                               _1, 
+                                                               _2,
+                                                               certName,
+                                                               0),
+						   boost::bind(&ContactManager::onIdCertificateUnverified,
+                                                               this,
+                                                               _1,
+                                                               certName)));
+  m_wrapper->sendInterest(interestPtr, closure);
+}
+
+void
 ContactManager::onDnsCollectEndorseVerified(Ptr<Data> data, const Name& identity)
 { emit collectEndorseFetched (*data); }
 
@@ -254,6 +280,21 @@
 { emit contactKeyFetchFailed(identity); }
 
 void
+ContactManager::onIdCertificateVerified(Ptr<Data> data, const Name& identity)
+{
+  IdentityCertificate identityCertificate(*data);
+  emit contactCertificateFetched(identityCertificate);
+}
+
+void
+ContactManager::onIdCertificateUnverified(Ptr<Data> data, const Name& identity)
+{ emit contactCertificateFetchFailed (identity); }
+
+void
+ContactManager::onIdCertificateTimeout(Ptr<Closure> closure, Ptr<Interest> interest, const Name& identity, int retry)
+{ emit contactCertificateFetchFailed (identity); }
+
+void
 ContactManager::updateProfileData(const Name& identity)
 {
   // Get current profile;
@@ -547,6 +588,37 @@
   m_wrapper->putToNdnd(*dnsBlob);
 }
 
+void
+ContactManager::addContact(const IdentityCertificate& identityCertificate, const Profile& profile)
+{
+  Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(profile));
+  
+  Ptr<IdentityManager> identityManager = m_keychain->getIdentityManager();
+  Name certificateName = identityManager->getDefaultCertificateNameByIdentity (m_defaultIdentity);
+  identityManager->signByCertificate(*profileData, certificateName);
+
+  Ptr<EndorseCertificate> endorseCertificate = NULL;
+  try{
+    endorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(identityCertificate, profileData));
+  }catch(exception& e){
+    _LOG_ERROR("Exception: " << e.what());
+    return;
+  }
+
+  identityManager->signByCertificate(*endorseCertificate, certificateName);
+
+  ContactItem contactItem(*endorseCertificate);
+
+  try{
+    m_contactStorage->addContact(contactItem);
+  }catch(exception& e){
+    emit warning(e.what());
+    _LOG_ERROR("Exception: " << e.what());
+    return;
+  }
+}
+
+
 
 #if WAF
 #include "contact-manager.moc"
diff --git a/src/contact-manager.h b/src/contact-manager.h
index b8498cc..26a2a63 100644
--- a/src/contact-manager.h
+++ b/src/contact-manager.h
@@ -43,6 +43,9 @@
   fetchCollectEndorse(const ndn::Name& identity);
 
   void
+  fetchIdCertificate(const ndn::Name& certName);
+
+  void
   updateProfileData(const ndn::Name& identity);
 
   void
@@ -73,6 +76,13 @@
   void
   publishEndorsedDataInDns(const ndn::Name& identity);
 
+  inline void
+  setDefaultIdentity(const ndn::Name& identity)
+  { m_defaultIdentity = identity; }
+
+  void
+  addContact(const ndn::security::IdentityCertificate& idCert, const Profile& profile);
+
 private:
   void
   setKeychain();
@@ -116,6 +126,14 @@
   void
   onDnsCollectEndorseUnverified(ndn::Ptr<ndn::Data> data, const ndn::Name& identity);
 
+  void
+  onIdCertificateVerified(ndn::Ptr<ndn::Data> data, const ndn::Name& identity);
+
+  void
+  onIdCertificateUnverified(ndn::Ptr<ndn::Data> data, const ndn::Name& identity);
+
+  void
+  onIdCertificateTimeout(ndn::Ptr<ndn::Closure> closure, ndn::Ptr<ndn::Interest> interest, const ndn::Name& identity, int retry);
   
 
 signals:
@@ -132,11 +150,20 @@
   contactKeyFetchFailed(const ndn::Name& identity);
 
   void 
+  contactCertificateFetched(const ndn::security::IdentityCertificate& identityCertificate);
+  
+  void
+  contactCertificateFetchFailed(const ndn::Name& identity);
+
+  void 
   collectEndorseFetched(const ndn::Data& data);
 
   void
   collectEndorseFetchFailed(const ndn::Name& identity);
 
+  void
+  warning(QString msg);
+
 private slots:
   
   
@@ -145,6 +172,7 @@
   ndn::Ptr<DnsStorage> m_dnsStorage;
   ndn::Ptr<ndn::security::Keychain> m_keychain;
   ndn::Ptr<ndn::Wrapper> m_wrapper;
+  ndn::Name m_defaultIdentity;
 };
 
 #endif
diff --git a/src/contact-storage.cpp b/src/contact-storage.cpp
index b3ee977..595dd68 100644
--- a/src/contact-storage.cpp
+++ b/src/contact-storage.cpp
@@ -306,6 +306,35 @@
 
   return profile;
 }
+
+void 
+ContactStorage::removeContact(const Name& contactNameSpace)
+{
+  Ptr<ContactItem> contact = getContact(contactNameSpace);
+  string identity = contactNameSpace.toUri();
+  
+  if(contact == NULL)
+    return;
+
+  sqlite3_stmt *stmt;  
+  sqlite3_prepare_v2 (m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, identity.c_str(), identity.size (), SQLITE_TRANSIENT);
+  int res = sqlite3_step (stmt);
+  sqlite3_finalize (stmt);
+
+  sqlite3_prepare_v2 (m_db, "DELETE FROM ContactProfile WHERE profile_identity=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, identity.c_str(),  identity.size (), SQLITE_TRANSIENT);
+  res = sqlite3_step (stmt);
+  sqlite3_finalize (stmt);
+  
+  if(contact->isIntroducer())
+    {
+      sqlite3_prepare_v2 (m_db, "DELETE FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 1, identity.c_str(),  identity.size (), SQLITE_TRANSIENT);
+      res = sqlite3_step (stmt);
+      sqlite3_finalize (stmt);         
+    }
+}
   
 void
 ContactStorage::addContact(const ContactItem& contact)
diff --git a/src/contact-storage.h b/src/contact-storage.h
index ee5f032..4887dbf 100644
--- a/src/contact-storage.h
+++ b/src/contact-storage.h
@@ -34,6 +34,9 @@
   getSelfProfile(const ndn::Name& identity);
 
   void
+  removeContact(const ndn::Name& identity);
+
+  void
   addContact(const ContactItem& contactItem);
 
   void
diff --git a/src/contactpanel.cpp b/src/contactpanel.cpp
index 4d281d6..56db0a7 100644
--- a/src/contactpanel.cpp
+++ b/src/contactpanel.cpp
@@ -64,6 +64,7 @@
   setKeychain();
 
   m_defaultIdentity = m_keychain->getDefaultIdentity();
+  m_contactManager->setDefaultIdentity(m_defaultIdentity);
   m_nickName = m_defaultIdentity.get(-1).toUri();
   m_settingDialog->setIdentity(m_defaultIdentity.toUri(), m_nickName);
 
@@ -71,6 +72,7 @@
   m_profileEditor->setCurrentIdentity(m_defaultIdentity);
 
   m_addContactPanel = new AddContactPanel(contactManager);
+  m_browseContactDialog = new BrowseContactDialog(contactManager);
   m_setAliasDialog = new SetAliasDialog(contactManager);
  
   ui->setupUi(this);
@@ -95,13 +97,21 @@
   connect(ui->EditProfileButton, SIGNAL(clicked()), 
           this, SLOT(openProfileEditor()));
 
+  // connect(ui->AddContactButton, SIGNAL(clicked()),
+  //         this, SLOT(openAddContactPanel()));
   connect(ui->AddContactButton, SIGNAL(clicked()),
-          this, SLOT(openAddContactPanel()));
+          this, SLOT(openBrowseContactDialog()));
+
+  connect(this, SIGNAL(refreshCertDirectory()),
+          m_browseContactDialog, SLOT(refreshList()));
+
+  connect(ui->DeleteContactButton, SIGNAL(clicked()),
+          this, SLOT(removeContactButton()));
    
   connect(ui->settingButton, SIGNAL(clicked()),
           this, SLOT(openSettingDialog()));
    
-  connect(m_addContactPanel, SIGNAL(newContactAdded()),
+  connect(m_browseContactDialog, SIGNAL(newContactAdded()),
           this, SLOT(refreshContactList()));
   connect(m_setAliasDialog, SIGNAL(aliasChanged()),
           this, SLOT(refreshContactList()));
@@ -144,6 +154,7 @@
 
   delete m_profileEditor;
   delete m_addContactPanel;
+  delete m_browseContactDialog;
   delete m_setAliasDialog;
 
   delete m_trustScopeModel;
@@ -499,6 +510,7 @@
   m_profileEditor->setCurrentIdentity(m_defaultIdentity);
   m_nickName = nickName.toStdString();
   m_handler->clearInterestFilter(m_inviteListenPrefix);
+  m_contactManager->setDefaultIdentity(m_defaultIdentity);
   setInvitationListener();
   collectEndorsement();
 }
@@ -512,6 +524,36 @@
 { m_addContactPanel->show(); }
 
 void
+ContactPanel::openBrowseContactDialog()
+{ 
+  m_browseContactDialog->show(); 
+  emit refreshCertDirectory();
+}
+
+void
+ContactPanel::removeContactButton()
+{
+  QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
+  QModelIndexList selectedList = selectionModel->selectedIndexes();
+  QModelIndexList::iterator it = selectedList.begin();
+  for(; it != selectedList.end(); it++)
+    {
+      string alias =  m_contactListModel->data(*it, Qt::DisplayRole).toString().toStdString();
+      vector<Ptr<ContactItem> >::iterator contactIt = m_contactList.begin();
+      for(; contactIt != m_contactList.end(); contactIt++)
+        {
+          if((*contactIt)->getAlias() == alias)
+            {
+              m_contactManager->getContactStorage()->removeContact((*contactIt)->getNameSpace());
+              m_contactList.erase(contactIt);
+              break;
+            }
+        }
+    }
+  refreshContactList();
+}
+
+void
 ContactPanel::openInvitationDialog()
 { m_invitationDialog->show(); }
 
diff --git a/src/contactpanel.h b/src/contactpanel.h
index f6e794c..55f9daf 100644
--- a/src/contactpanel.h
+++ b/src/contactpanel.h
@@ -24,6 +24,7 @@
 #include "settingdialog.h"
 #include "chatdialog.h"
 #include "endorse-combobox-delegate.h"
+#include "browsecontactdialog.h"
 
 #ifndef Q_MOC_RUN
 #include "contact-manager.h"
@@ -112,6 +113,9 @@
   void
   newInvitationReady();
 
+  void
+  refreshCertDirectory();
+
 private slots:
   void
   updateSelection(const QItemSelection &selected,
@@ -126,9 +130,15 @@
 
   void
   openAddContactPanel();
+  
+  void
+  openBrowseContactDialog();
 
   void
   openSetAliasDialog();
+
+  void
+  removeContactButton();
   
   void
   openStartChatDialog();
@@ -187,6 +197,7 @@
   QStringListModel* m_contactListModel;
   ProfileEditor* m_profileEditor;
   AddContactPanel* m_addContactPanel;
+  BrowseContactDialog* m_browseContactDialog;
   SetAliasDialog* m_setAliasDialog;
   StartChatDialog* m_startChatDialog;
   InvitationDialog* m_invitationDialog;
diff --git a/src/contactpanel.ui b/src/contactpanel.ui
index b79ef5d..2f31a1a 100644
--- a/src/contactpanel.ui
+++ b/src/contactpanel.ui
@@ -22,16 +22,16 @@
   <property name="windowTitle">
    <string>ChronoChat Contacts</string>
   </property>
-  <widget class="QWidget" name="layoutWidget">
+  <widget class="QWidget" name="">
    <property name="geometry">
     <rect>
-     <x>11</x>
-     <y>11</y>
+     <x>12</x>
+     <y>12</y>
      <width>581</width>
-     <height>461</height>
+     <height>471</height>
     </rect>
    </property>
-   <layout class="QVBoxLayout" name="verticalLayout_2">
+   <layout class="QVBoxLayout" name="verticalLayout_2" stretch="30,1">
     <item>
      <layout class="QHBoxLayout" name="ContactPanelLayout" stretch="3,7">
       <property name="spacing">
@@ -279,19 +279,33 @@
      </layout>
     </item>
     <item>
-     <layout class="QHBoxLayout" name="ButtonsLayout" stretch="1,1,1">
-      <property name="spacing">
-       <number>50</number>
-      </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1,1,1">
       <item>
-       <widget class="QPushButton" name="AddContactButton">
-        <property name="text">
-         <string>Add Contact</string>
+       <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,1">
+        <property name="spacing">
+         <number>-1</number>
         </property>
-        <property name="autoDefault">
-         <bool>false</bool>
-        </property>
-       </widget>
+        <item>
+         <widget class="QPushButton" name="AddContactButton">
+          <property name="text">
+           <string>Add </string>
+          </property>
+          <property name="autoDefault">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="DeleteContactButton">
+          <property name="text">
+           <string>Delete</string>
+          </property>
+          <property name="autoDefault">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
       </item>
       <item>
        <widget class="QPushButton" name="settingButton">
diff --git a/src/profile.cpp b/src/profile.cpp
index 5261207..24372a4 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -26,9 +26,10 @@
 static string advisor("2.5.4.80");
 static string emailOid("1.2.840.113549.1.9.1");
 
-Profile::Profile(security::IdentityCertificate& identityCertificate)
+Profile::Profile(const security::IdentityCertificate& oldIdentityCertificate)
 {
   using namespace ndn::security;
+  security::IdentityCertificate identityCertificate(oldIdentityCertificate);
 
   Name keyName = identityCertificate.getPublicKeyName();
   m_identityName = keyName.getPrefix(keyName.size()-1);
diff --git a/src/profile.h b/src/profile.h
index b020408..7a65553 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -26,7 +26,7 @@
 public:
   Profile() {}
 
-  Profile(ndn::security::IdentityCertificate& identityCertificate);
+  Profile(const ndn::security::IdentityCertificate& identityCertificate);
 
   Profile(const ndn::Name& identityName);