SelfProfile related things is done, not tested yet.
diff --git a/log4cxx.properties b/log4cxx.properties
new file mode 100644
index 0000000..bdbc1a2
--- /dev/null
+++ b/log4cxx.properties
@@ -0,0 +1,24 @@
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=TRACE, A1
+#, rollingFile
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.target=System.err
+#log4j.appender.A1.layout.ConversionPattern=%d{dd-MMM HH:MM:SS,SSS} %p %c %m%n
+#log4j.appender.A1.layout.ConversionPattern=%d{hh:mm:ss,SSS} %-14t %-14c  %m%n
+log4j.appender.A1.layout.ConversionPattern=%d{ss,SSS} %-5p %-12c  %m%n
+
+log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
+log4j.appender.rollingFile.File=logfile.txt
+log4j.appender.rollingFile.MaxFileSize=10MB
+log4j.appender.rollingFile.MaxBackupIndex=9
+log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
+log4j.appender.rollingFile.layout.ConversionPattern=%d{ss,SSS} %-5p %-12c  %m%n
+
+log4j.logger.Executor = ERROR
+#log4j.logger.Scheduler = ERROR
+
diff --git a/logging.cc b/logging.cc
new file mode 100644
index 0000000..04fb6c3
--- /dev/null
+++ b/logging.cc
@@ -0,0 +1,51 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "logging.h"
+
+#ifdef HAVE_LOG4CXX
+
+#include <log4cxx/logger.h>
+#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/consoleappender.h>
+#include <log4cxx/patternlayout.h>
+#include <log4cxx/level.h>
+#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/defaultconfigurator.h>
+#include <log4cxx/helpers/exception.h>
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+#include <unistd.h>
+
+void
+INIT_LOGGERS ()
+{
+  static bool configured = false;
+
+  if (configured) return;
+
+  if (access ("log4cxx.properties", R_OK)==0)
+    PropertyConfigurator::configureAndWatch ("log4cxx.properties");
+  else
+    {
+      PatternLayoutPtr   layout   (new PatternLayout ("%d{HH:mm:ss} %p %c{1} - %m%n"));
+      ConsoleAppenderPtr appender (new ConsoleAppender (layout));
+
+      BasicConfigurator::configure( appender );
+      Logger::getRootLogger()->setLevel (log4cxx::Level::getInfo ());
+    }
+
+  configured = true;
+}
+
+#endif
diff --git a/logging.h b/logging.h
new file mode 100644
index 0000000..2aa3344
--- /dev/null
+++ b/logging.h
@@ -0,0 +1,84 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#include "config.h"
+
+#ifdef HAVE_LOG4CXX
+
+#include <log4cxx/logger.h>
+
+#define MEMBER_LOGGER                           \
+  static log4cxx::LoggerPtr staticModuleLogger;
+
+#define INIT_MEMBER_LOGGER(className,name)          \
+  log4cxx::LoggerPtr className::staticModuleLogger =  log4cxx::Logger::getLogger (name);
+
+#define INIT_LOGGER(name) \
+  static log4cxx::LoggerPtr staticModuleLogger = log4cxx::Logger::getLogger (name);
+
+#define _LOG_DEBUG(x) \
+  LOG4CXX_DEBUG(staticModuleLogger, x);
+
+#define _LOG_TRACE(x) \
+  LOG4CXX_TRACE(staticModuleLogger, x);
+
+#define _LOG_FUNCTION(x) \
+  LOG4CXX_TRACE(staticModuleLogger, __FUNCTION__ << "(" << x << ")");
+
+#define _LOG_FUNCTION_NOARGS \
+  LOG4CXX_TRACE(staticModuleLogger, __FUNCTION__ << "()");
+
+#define _LOG_ERROR(x) \
+  LOG4CXX_ERROR(staticModuleLogger, x);
+
+#define _LOG_ERROR_COND(cond,x) \
+  if (cond) { _LOG_ERROR(x) }
+
+#define _LOG_DEBUG_COND(cond,x) \
+  if (cond) { _LOG_DEBUG(x) }
+
+void
+INIT_LOGGERS ();
+
+#else // else HAVE_LOG4CXX
+
+#define INIT_LOGGER(name)
+#define _LOG_FUNCTION(x)
+#define _LOG_FUNCTION_NOARGS
+#define _LOG_TRACE(x)
+#define INIT_LOGGERS(x)
+#define _LOG_ERROR(x)
+#define _LOG_ERROR_COND(cond,x)
+#define _LOG_DEBUG_COND(cond,x)
+
+#define MEMBER_LOGGER
+#define INIT_MEMBER_LOGGER(className,name)
+
+#ifdef _DEBUG
+
+#include <boost/thread/thread.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <iostream>
+
+#define _LOG_DEBUG(x) \
+  std::clog << boost::get_system_time () << " " << boost::this_thread::get_id () << " " << x << std::endl;
+
+#else
+#define _LOG_DEBUG(x)
+#endif
+
+#endif // HAVE_LOG4CXX
+
+#endif // LOGGING_H
diff --git a/src/contact-storage.cpp b/src/contact-storage.cpp
index f42ec21..3eb8ac1 100644
--- a/src/contact-storage.cpp
+++ b/src/contact-storage.cpp
@@ -13,11 +13,35 @@
 
 #include <string>
 #include <boost/filesystem.hpp>
+#include "logging.h"
 
 using namespace std;
 using namespace ndn;
 namespace fs = boost::filesystem;
 
+INIT_LOGGER ("ContactStorage");
+
+const string INIT_SP_TABLE = "\
+CREATE TABLE IF NOT EXISTS                                           \n \
+  SelfProfile(                                                       \n \
+      profile_id        INTEGER PRIMARY KEY AUTOINCREMENT,           \n \
+      profile_type      BLOB NOT NULL,                               \n \
+      profile_value     BLOB NOT NULL                                \n \
+  );                                                                 \n \
+                                                                     \
+CREATE INDEX sp_index ON SelfProfile(profile_type);                  \n \
+";
+
+const string INIT_PD_TABLE = "\
+CREATE TABLE IF NOT EXISTS                                           \n \
+  ProfileData(                                                       \n \
+      identity          BLOB NOT NULL UNIQUE,                        \n \
+      profile_data      BLOB NOT NULL,                               \n \
+                                                                     \
+      PRIMARY KEY (identity)                                         \n \
+  );                                                                 \n \
+CREATE INDEX pd_index ON ProfileData(identity);                      \n \
+";
 
 const string INIT_TC_TABLE = "\
 CREATE TABLE IF NOT EXISTS                                           \n \
@@ -46,7 +70,8 @@
 CREATE INDEX nc_index ON NormalContact(contact_namespace);           \n \
 ";
 
-ContactStorage::ContactStorage()
+ContactStorage::ContactStorage(Ptr<security::IdentityManager> identityManager)
+  : m_identityManager(identityManager)
 {
   fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
   fs::create_directories (chronosDir);
@@ -55,8 +80,43 @@
   if (res != SQLITE_OK)
     throw LnException("Chronos DB cannot be open/created");
 
-  // Check if TrustedContact table exists
+  // Check if SelfProfile table exists
   sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='SelfProfile'", -1, &stmt, 0);
+  res = sqlite3_step (stmt);
+
+  bool spTableExist = false;
+  if (res == SQLITE_ROW)
+      spTableExist = true;
+  sqlite3_finalize (stmt);
+
+  if(!spTableExist)
+    {
+      char *errmsg = 0;
+      res = sqlite3_exec (m_db, INIT_SP_TABLE.c_str (), NULL, NULL, &errmsg);
+      if (res != SQLITE_OK && errmsg != 0)
+        throw LnException("Init \"error\" in SelfProfile");
+    }
+
+  // Check if ProfileData table exists
+  sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='ProfileData'", -1, &stmt, 0);
+  res = sqlite3_step (stmt);
+
+  bool pdTableExist = false;
+  if (res == SQLITE_ROW)
+      pdTableExist = true;
+  sqlite3_finalize (stmt);
+
+  if(!pdTableExist)
+    {
+      char *errmsg = 0;
+      res = sqlite3_exec (m_db, INIT_PD_TABLE.c_str (), NULL, NULL, &errmsg);
+      if (res != SQLITE_OK && errmsg != 0)
+        throw LnException("Init \"error\" in ProfileData");
+    }
+
+
+  // Check if TrustedContact table exists
   sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='TrustedContact'", -1, &stmt, 0);
   res = sqlite3_step (stmt);
 
@@ -71,7 +131,6 @@
       res = sqlite3_exec (m_db, INIT_TC_TABLE.c_str (), NULL, NULL, &errmsg);
       if (res != SQLITE_OK && errmsg != 0)
         throw LnException("Init \"error\" in TrustedContact");
-      sqlite3_finalize (stmt);
     }
     
   // Check if NormalContact table exists
@@ -93,6 +152,102 @@
     }
 }
 
+bool
+ContactStorage::doesSelfEntryExist(const string& profileType)
+{
+  bool result = false;
+  
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
+
+  int res = sqlite3_step (stmt);
+    
+  if (res == SQLITE_ROW)
+    {
+      int countAll = sqlite3_column_int (stmt, 0);
+      if (countAll > 0)
+        result = true;
+    } 
+  sqlite3_finalize (stmt); 
+  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 string& profileType, const Blob& profileValue)
+{
+  if(profileType == string("IDENTITY"))
+    return;
+
+  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, profileValue.buf(), profileValue.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, profileValue.buf(), profileValue.size(), SQLITE_TRANSIENT);
+    }
+  sqlite3_step (stmt);
+  sqlite3_finalize (stmt);
+}
+
+Ptr<Profile>
+ContactStorage::getSelfProfile()
+{
+  string idString("IDENTITY");
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2(m_db, "SELECT profile_value FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+
+  Name nameSpace;
+  int res = sqlite3_step (stmt);
+  if (res == SQLITE_ROW)
+    nameSpace.append(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+
+  Ptr<Profile> profile = Ptr<Profile>(new Profile(nameSpace));
+  
+  sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_type!=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+  
+  while( sqlite3_step (stmt) == SQLITE_ROW)
+    {
+      string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
+      Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
+
+      profile->setProfileEntry(profileType, profileValue );
+    }
+
+  return profile;
+}
+
 void
 ContactStorage::addTrustedContact(const TrustedContact& trustedContact)
 {
@@ -213,3 +368,96 @@
   
   return normalContacts;
 }
+
+void
+ContactStorage::updateProfileData() const
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT identity, profile_data FROM ProfileData", -1, &stmt, 0);
+
+  if(sqlite3_step (stmt) != SQLITE_ROW)
+    {
+      sqlite3_finalize (stmt);
+      return;
+    }
+
+  Name identity(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+
+  Ptr<Blob> profileDataBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
+  Ptr<Data> plainData = Data::decodeFromWire(profileDataBlob);
+  const Blob& oldProfileBlob = plainData->content();
+  sqlite3_finalize (stmt);
+  
+  Ptr<Profile> newProfile = getSelfProfile();
+  if(NULL == newProfile)
+    return;
+  Ptr<Blob> newProfileBlob = newProfile->toDerBlob();
+  
+  if(oldProfileBlob == *newProfileBlob)
+    return;
+  
+  string idString("IDENTITY");
+  Ptr<const Blob> identityBlob = newProfile->getProfileEntry(idString);
+  Name newIdentity(string(identityBlob->buf(), identityBlob->size()));
+
+  Ptr<ProfileData> newProfileData = getSignedSelfProfileData(newIdentity, *newProfile);
+  Ptr<Blob> newProfileDataBlob = newProfileData->encodeToWire();
+
+  if(identity == newIdentity)
+    {
+      sqlite3_prepare_v2 (m_db, "UPDATE ProfileData SET profile_data=? WHERE identity=?", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 1, newProfileDataBlob->buf(), newProfileDataBlob->size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 2, newIdentity.toUri().c_str(), newIdentity.toUri().size(), SQLITE_TRANSIENT);
+    }
+  else
+    {
+      sqlite3_prepare_v2 (m_db, "INSERT INTO ProfileData (identity, profile_data) values (?, ?)", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 2, newIdentity.toUri().c_str(), newIdentity.toUri().size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 1, newProfileDataBlob->buf(), newProfileDataBlob->size(), SQLITE_TRANSIENT);
+    }
+}
+
+Ptr<Profile>
+ContactStorage::getSelfProfile() const
+{
+  string idString("IDENTITY");
+
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT profile_value FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+
+  if(sqlite3_step (stmt) != SQLITE_ROW)
+    {
+      sqlite3_finalize (stmt);
+      return NULL;
+    }
+
+  Name identity(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+  
+  Ptr<Profile> profile = Ptr<Profile>(new Profile(identity));
+  sqlite3_finalize (stmt);
+  
+  sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_type!=? and profile_type!=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+
+  while( sqlite3_step (stmt) == SQLITE_ROW)
+    {
+      string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
+      Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
+      profile->setProfileEntry(profileType, profileValue);
+    }
+
+  return profile;
+}
+
+Ptr<ProfileData>
+ContactStorage::getSignedSelfProfileData(const Name& identity,
+                         const Profile& profile) const
+{
+  Name certificateName = m_identityManager->getDefaultCertificateNameByIdentity(identity);
+  Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(identity, profile));
+  m_identityManager->signByCertificate(*profileData, certificateName);
+
+  return profileData;
+}
+
diff --git a/src/contact-storage.h b/src/contact-storage.h
index eca65da..deb330a 100644
--- a/src/contact-storage.h
+++ b/src/contact-storage.h
@@ -14,15 +14,27 @@
 #include <sqlite3.h>
 #include "trusted-contact.h"
 #include "contact-item.h"
+#include "profile-data.h"
+#include <ndn.cxx/security/identity/identity-manager.h>
+#include <ndn.cxx/fields/signature-sha256-with-rsa.h>
 
 class ContactStorage
 {
 public:
-  ContactStorage();
+  ContactStorage(ndn::Ptr<ndn::security::IdentityManager> identityManager);
   
   ~ContactStorage() {}
 
   void
+  setSelfProfileIdentity(const ndn::Name& identity);
+
+  void
+  setSelfProfileEntry(const std::string& profileType, const ndn::Blob& profileValue);
+
+  ndn::Ptr<Profile>
+  getSelfProfile();
+
+  void
   addTrustedContact(const TrustedContact& trustedContact);
   
   void
@@ -34,7 +46,13 @@
   std::vector<ndn::Ptr<ContactItem> >
   getAllNormalContacts() const;
 
+  void
+  updateProfileData() const;
+
 private:
+  bool
+  doesSelfEntryExist(const std::string& profileType);
+
   inline bool
   doesTrustedContactExist(const ndn::Name& name)
   { return doesContactExist(name, false); }
@@ -45,8 +63,16 @@
 
   bool
   doesContactExist(const ndn::Name& name, bool normal);
+
+  ndn::Ptr<Profile>
+  getSelfProfile() const;
+
+  ndn::Ptr<ProfileData>
+  getSignedSelfProfileData(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 14a89df..5dea76c 100644
--- a/src/contactpanel.cpp
+++ b/src/contactpanel.cpp
@@ -15,14 +15,35 @@
 #include <QStringList>
 #include <QItemSelectionModel>
 #include <QModelIndex>
+#include <QDir>
 
-ContactPanel::ContactPanel(QWidget *parent) :
-    QDialog(parent),
-    ui(new Ui::ContactPanel),
-    m_contactListModel(new QStringListModel)
+#ifndef Q_MOC_RUN
+#include <boost/filesystem.hpp>
+#include "logging.h"
+#include "exception.h"
+#endif
+
+namespace fs = boost::filesystem;
+using namespace ndn;
+
+INIT_LOGGER("ContactPanel");
+
+ContactPanel::ContactPanel(Ptr<ContactStorage> contactStorage, QWidget *parent) 
+    : QDialog(parent)
+    , ui(new Ui::ContactPanel)
+    , m_contactStorage(contactStorage)
+    , m_contactListModel(new QStringListModel)
+    , m_profileEditor(NULL)
 {
+  
     ui->setupUi(this);
 
+    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
+    QString path = (QDir::home().path());
+    path.append(QDir::separator()).append(".chronos").append(QDir::separator()).append("chronos.db");
+    db.setDatabaseName(path);
+    bool ok = db.open();
+
     QStringList contactNameList;
     contactNameList << "Alex" << "Wentao" << "Yingdi";
 
@@ -32,6 +53,8 @@
     QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
     connect(selectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
 	    this, SLOT(updateSelection(const QItemSelection &, const QItemSelection &)));
+    connect(ui->EditProfileButton, SIGNAL(clicked()), 
+            this, SLOT(openProfileEditor()));
 }
 
 ContactPanel::~ContactPanel()
@@ -49,6 +72,15 @@
   ui->NameData->setText(text);
 }
 
+void
+ContactPanel::openProfileEditor()
+{
+  if(m_profileEditor == NULL)
+    m_profileEditor = new ProfileEditor(m_contactStorage);
+
+  m_profileEditor->show();
+}
+
 #if WAF
 #include "contactpanel.moc"
 #include "contactpanel.cpp.moc"
diff --git a/src/contactpanel.h b/src/contactpanel.h
index 5b05b56..5ee8ce7 100644
--- a/src/contactpanel.h
+++ b/src/contactpanel.h
@@ -13,6 +13,13 @@
 
 #include <QDialog>
 #include <QStringListModel>
+#include <QtSql/QSqlDatabase>
+
+#include "profileeditor.h"
+
+#ifndef Q_MOC_RUN
+#include "contact-storage.h"
+#endif
 
 namespace Ui {
 class ContactPanel;
@@ -23,17 +30,22 @@
     Q_OBJECT
 
 public:
-    explicit ContactPanel(QWidget *parent = 0);
-    ~ContactPanel();
+  explicit ContactPanel(ndn::Ptr<ContactStorage> contactStorage, QWidget *parent = 0);
+  ~ContactPanel();
 
 private slots:
   void
   updateSelection(const QItemSelection &selected,
                   const QItemSelection &deselected);
 
+  void
+  openProfileEditor();
+
 private:
-    Ui::ContactPanel *ui;
-    QStringListModel* m_contactListModel;
+  Ui::ContactPanel *ui;
+  ndn::Ptr<ContactStorage> m_contactStorage;
+  QStringListModel* m_contactListModel;
+  ProfileEditor* m_profileEditor;
 };
 
 #endif // CONTACTPANEL_H
diff --git a/src/contactpanel.ui b/src/contactpanel.ui
index ae6392c..0b26479 100644
--- a/src/contactpanel.ui
+++ b/src/contactpanel.ui
@@ -10,7 +10,7 @@
     <x>0</x>
     <y>0</y>
     <width>600</width>
-    <height>450</height>
+    <height>480</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -25,165 +25,190 @@
   <widget class="QWidget" name="">
    <property name="geometry">
     <rect>
-     <x>10</x>
-     <y>10</y>
+     <x>11</x>
+     <y>11</y>
      <width>581</width>
-     <height>431</height>
+     <height>461</height>
     </rect>
    </property>
-   <layout class="QHBoxLayout" name="ContactPanelLayout" stretch="3,7">
-    <property name="spacing">
-     <number>10</number>
-    </property>
-    <property name="sizeConstraint">
-     <enum>QLayout::SetDefaultConstraint</enum>
-    </property>
+   <layout class="QVBoxLayout" name="verticalLayout_2">
     <item>
-     <widget class="QListView" name="ContactList">
-      <property name="contextMenuPolicy">
-       <enum>Qt::DefaultContextMenu</enum>
+     <layout class="QHBoxLayout" name="ContactPanelLayout" stretch="3,7">
+      <property name="spacing">
+       <number>10</number>
       </property>
-      <property name="acceptDrops">
-       <bool>false</bool>
+      <property name="sizeConstraint">
+       <enum>QLayout::SetDefaultConstraint</enum>
       </property>
-      <property name="editTriggers">
-       <set>QAbstractItemView::NoEditTriggers</set>
-      </property>
-     </widget>
+      <item>
+       <widget class="QListView" name="ContactList">
+        <property name="contextMenuPolicy">
+         <enum>Qt::DefaultContextMenu</enum>
+        </property>
+        <property name="acceptDrops">
+         <bool>false</bool>
+        </property>
+        <property name="editTriggers">
+         <set>QAbstractItemView::NoEditTriggers</set>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QTabWidget" name="ContactInfo">
+        <property name="currentIndex">
+         <number>0</number>
+        </property>
+        <widget class="QWidget" name="General">
+         <attribute name="title">
+          <string>General</string>
+         </attribute>
+         <widget class="QGraphicsView" name="Avatar">
+          <property name="geometry">
+           <rect>
+            <x>130</x>
+            <y>10</y>
+            <width>128</width>
+            <height>128</height>
+           </rect>
+          </property>
+         </widget>
+         <widget class="QWidget" name="layoutWidget">
+          <property name="geometry">
+           <rect>
+            <x>30</x>
+            <y>160</y>
+            <width>331</width>
+            <height>124</height>
+           </rect>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout">
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout" stretch="35,100">
+             <property name="spacing">
+              <number>-1</number>
+             </property>
+             <item>
+              <widget class="QLabel" name="NameSpaceLabel">
+               <property name="font">
+                <font>
+                 <weight>75</weight>
+                 <bold>true</bold>
+                </font>
+               </property>
+               <property name="text">
+                <string>Name space</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QLineEdit" name="NameSpaceData">
+               <property name="font">
+                <font>
+                 <family>Lucida Grande</family>
+                </font>
+               </property>
+               <property name="readOnly">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="35,100">
+             <item>
+              <widget class="QLabel" name="NameLabel">
+               <property name="font">
+                <font>
+                 <weight>75</weight>
+                 <bold>true</bold>
+                </font>
+               </property>
+               <property name="text">
+                <string>Name</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QLineEdit" name="NameData">
+               <property name="font">
+                <font>
+                 <family>Lucida Grande</family>
+                </font>
+               </property>
+               <property name="readOnly">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="35,100">
+             <item>
+              <widget class="QLabel" name="InstitutionLabel">
+               <property name="font">
+                <font>
+                 <weight>75</weight>
+                 <bold>true</bold>
+                </font>
+               </property>
+               <property name="text">
+                <string>Institution   </string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QLineEdit" name="InstitutionData">
+               <property name="font">
+                <font>
+                 <family>Lucida Grande</family>
+                </font>
+               </property>
+               <property name="readOnly">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+        <widget class="QWidget" name="TrustLevel">
+         <attribute name="title">
+          <string>Trust Level</string>
+         </attribute>
+        </widget>
+        <widget class="QWidget" name="Endorse">
+         <attribute name="title">
+          <string>Endorse</string>
+         </attribute>
+        </widget>
+       </widget>
+      </item>
+     </layout>
     </item>
     <item>
-     <widget class="QTabWidget" name="ContactInfo">
-      <property name="currentIndex">
-       <number>0</number>
+     <layout class="QHBoxLayout" name="ButtonsLayout" stretch="1,1">
+      <property name="spacing">
+       <number>100</number>
       </property>
-      <widget class="QWidget" name="General">
-       <attribute name="title">
-        <string>General</string>
-       </attribute>
-       <widget class="QGraphicsView" name="Avatar">
-        <property name="geometry">
-         <rect>
-          <x>130</x>
-          <y>10</y>
-          <width>128</width>
-          <height>128</height>
-         </rect>
+      <item>
+       <widget class="QPushButton" name="AddContactButton">
+        <property name="text">
+         <string>Add Contact</string>
         </property>
        </widget>
-       <widget class="QWidget" name="">
-        <property name="geometry">
-         <rect>
-          <x>30</x>
-          <y>160</y>
-          <width>331</width>
-          <height>124</height>
-         </rect>
+      </item>
+      <item>
+       <widget class="QPushButton" name="EditProfileButton">
+        <property name="text">
+         <string>Edit Profile</string>
         </property>
-        <layout class="QVBoxLayout" name="verticalLayout">
-         <item>
-          <layout class="QHBoxLayout" name="horizontalLayout" stretch="35,100">
-           <property name="spacing">
-            <number>-1</number>
-           </property>
-           <item>
-            <widget class="QLabel" name="NameSpaceLabel">
-             <property name="font">
-              <font>
-               <weight>75</weight>
-               <bold>true</bold>
-              </font>
-             </property>
-             <property name="text">
-              <string>Name space</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QLineEdit" name="NameSpaceData">
-             <property name="font">
-              <font>
-               <family>Lucida Grande</family>
-              </font>
-             </property>
-             <property name="readOnly">
-              <bool>true</bool>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </item>
-         <item>
-          <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="35,100">
-           <item>
-            <widget class="QLabel" name="NameLabel">
-             <property name="font">
-              <font>
-               <weight>75</weight>
-               <bold>true</bold>
-              </font>
-             </property>
-             <property name="text">
-              <string>Name</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QLineEdit" name="NameData">
-             <property name="font">
-              <font>
-               <family>Lucida Grande</family>
-              </font>
-             </property>
-             <property name="readOnly">
-              <bool>true</bool>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </item>
-         <item>
-          <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="35,100">
-           <item>
-            <widget class="QLabel" name="InstitutionLabel">
-             <property name="font">
-              <font>
-               <weight>75</weight>
-               <bold>true</bold>
-              </font>
-             </property>
-             <property name="text">
-              <string>Institution   </string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QLineEdit" name="InstitutionData">
-             <property name="font">
-              <font>
-               <family>Lucida Grande</family>
-              </font>
-             </property>
-             <property name="readOnly">
-              <bool>true</bool>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </item>
-        </layout>
        </widget>
-      </widget>
-      <widget class="QWidget" name="TrustLevel">
-       <attribute name="title">
-        <string>Trust Level</string>
-       </attribute>
-      </widget>
-      <widget class="QWidget" name="Endorse">
-       <attribute name="title">
-        <string>Endorse</string>
-       </attribute>
-      </widget>
-     </widget>
+      </item>
+     </layout>
     </item>
    </layout>
   </widget>
diff --git a/src/main.cpp b/src/main.cpp
index 83212d2..7e60c8a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,6 +13,12 @@
 
 #include "chronochat.h"
 #include "contactpanel.h"
+#include "contact-storage.h"
+#include <ndn.cxx/security/identity/identity-manager.h>
+#include <ndn.cxx/security/identity/osx-privatekey-storage.h>
+#include <ndn.cxx/security/identity/basic-identity-storage.h>
+
+using namespace ndn;
 
 int main(int argc, char *argv[])
 {
@@ -24,7 +30,11 @@
 // // 	app.setWindowIcon(QIcon("/Users/yuyingdi/Develop/QT/images/icon_large.png"));
 // // #endif
 
-  ContactPanel contactPanel;
+  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));
+  ContactPanel contactPanel(contactStorage);
 
   contactPanel.show ();
   contactPanel.activateWindow ();
diff --git a/src/profile.cpp b/src/profile.cpp
index 06282af..7f2ba6e 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -17,13 +17,21 @@
 
 Profile::Profile(const Name& identityName)
   : m_identityName(identityName)
-{}
+{
+  const string& nameString = identityName.toUri();
+  Blob identityBlob (nameString.c_str(), nameString.size());
+  m_entries[string("IDENTITY")] = identityBlob;
+}
 
 Profile::Profile(const Name& identityName,
 		 const string& name,
 		 const string& institution)
   : m_identityName(identityName)
 {
+  const string& nameString = identityName.toUri();
+  Blob identityBlob (nameString.c_str(), nameString.size());
+  m_entries[string("IDENTITY")] = identityBlob;
+
   Blob nameBlob (name.c_str(), name.size());
   Blob institutionBlob (institution.c_str(), institution.size());
 
diff --git a/src/profileeditor.cpp b/src/profileeditor.cpp
new file mode 100644
index 0000000..9b75f50
--- /dev/null
+++ b/src/profileeditor.cpp
@@ -0,0 +1,104 @@
+/* -*- 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 "profileeditor.h"
+#include "ui_profileeditor.h"
+#include <QtSql/QSqlRecord>
+#include <QtSql/QSqlField>
+#include <QtSql/QSqlError>
+
+#ifndef Q_MOC_RUN
+#include "logging.h"
+#include "exception.h"
+#endif
+
+using namespace ndn;
+
+INIT_LOGGER("ProfileEditor");
+
+ProfileEditor::ProfileEditor(Ptr<ContactStorage> contactStorage, QWidget *parent) 
+    : QDialog(parent)
+    , ui(new Ui::ProfileEditor)
+    , m_tableModel(new QSqlTableModel())
+    , m_contactStorage(contactStorage)
+{
+    ui->setupUi(this);
+
+    connect(ui->addRowButton, SIGNAL(clicked()),
+            this, SLOT(onAddClicked()));
+    connect(ui->deleteRowButton, SIGNAL(clicked()),
+            this, SLOT(onDeleteClicked()));
+    connect(ui->okButton, SIGNAL(clicked()),
+            this, SLOT(onOkClicked()));
+    
+    m_tableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
+    m_tableModel->setTable("SelfProfile");
+    m_tableModel->select();
+    m_tableModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Index"));
+    m_tableModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Type"));
+    m_tableModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Value"));
+
+    ui->profileTable->setModel(m_tableModel);
+    ui->profileTable->setColumnHidden(0, true);
+    ui->profileTable->show();
+
+}
+
+ProfileEditor::~ProfileEditor()
+{
+    delete ui;
+    delete m_tableModel;
+}
+
+void
+ProfileEditor::onAddClicked()
+{
+  int rowCount = m_tableModel->rowCount();
+
+  // QSqlRecord record;
+  // QSqlField typeField("profile_type", QVariant::String);
+  // QSqlField valueField("profile_value", QVariant::String);
+  // record.append(typeField);
+  // record.append(valueField);
+  // record.setValue("profile_type", QString("N/A"));
+  // record.setValue("profile_value", QString("N/A"));
+
+  // bool res = m_tableModel->insertRecord(-1, record);
+
+  // res = m_tableModel->submitAll();
+  m_tableModel->insertRow(rowCount);
+}
+
+void
+ProfileEditor::onDeleteClicked()
+{
+  QItemSelectionModel* selectionModel = ui->profileTable->selectionModel();
+  QModelIndexList indexList = selectionModel->selectedRows();
+
+  int i = indexList.size() - 1;  
+  for(; i >= 0; i--)
+    {
+      if(0 != indexList[i].row())
+        m_tableModel->removeRow(indexList[i].row());
+    }
+  m_tableModel->submitAll();
+}
+
+void
+ProfileEditor::onOkClicked()
+{
+  m_tableModel->submitAll();
+  this->hide();
+}
+
+#if WAF
+#include "profileeditor.moc"
+#include "profileeditor.cpp.moc"
+#endif
diff --git a/src/profileeditor.h b/src/profileeditor.h
new file mode 100644
index 0000000..4bb073b
--- /dev/null
+++ b/src/profileeditor.h
@@ -0,0 +1,51 @@
+/* -*- 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 PROFILEEDITOR_H
+#define PROFILEEDITOR_H
+
+#include <QDialog>
+#include <QtSql/QSqlTableModel>
+
+#ifndef Q_MOC_RUN
+#include "contact-storage.h"
+#endif
+
+namespace Ui {
+class ProfileEditor;
+}
+
+class ProfileEditor : public QDialog
+{
+    Q_OBJECT
+
+public:
+  explicit ProfileEditor(ndn::Ptr<ContactStorage> contactStorage, QWidget *parent = 0);
+  
+  ~ProfileEditor();
+  
+private slots:
+  void
+  onAddClicked();
+
+  void
+  onDeleteClicked();
+
+  void
+  onOkClicked();
+
+
+private:
+  Ui::ProfileEditor *ui;
+  QSqlTableModel* m_tableModel;
+  ndn::Ptr<ContactStorage> m_contactStorage;
+};
+
+#endif // PROFILEEDITOR_H
diff --git a/src/profileeditor.ui b/src/profileeditor.ui
new file mode 100644
index 0000000..89a0612
--- /dev/null
+++ b/src/profileeditor.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProfileEditor</class>
+ <widget class="QDialog" name="ProfileEditor">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Profile Editor</string>
+  </property>
+  <widget class="QWidget" name="">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>11</y>
+     <width>381</width>
+     <height>491</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <widget class="QTableView" name="profileTable">
+      <attribute name="horizontalHeaderCascadingSectionResizes">
+       <bool>false</bool>
+      </attribute>
+      <attribute name="horizontalHeaderDefaultSectionSize">
+       <number>100</number>
+      </attribute>
+      <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+       <bool>true</bool>
+      </attribute>
+      <attribute name="horizontalHeaderStretchLastSection">
+       <bool>true</bool>
+      </attribute>
+      <attribute name="verticalHeaderVisible">
+       <bool>true</bool>
+      </attribute>
+     </widget>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" name="buttonLayout" stretch="1,1,1">
+      <item>
+       <widget class="QPushButton" name="addRowButton">
+        <property name="text">
+         <string>Add</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="deleteRowButton">
+        <property name="text">
+         <string>Delete</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="okButton">
+        <property name="text">
+         <string>OK</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/wscript b/wscript
index c949474..34a2c49 100644
--- a/wscript
+++ b/wscript
@@ -17,6 +17,8 @@
     conf.check_tinyxml(path=conf.options.tinyxml_dir)
     conf.check_cfg(package='libndn.cxx', args=['--cflags', '--libs'], uselib_store='NDNCXX', mandatory=True)
     conf.check_cfg(package='sqlite3', args=['--cflags', '--libs'], uselib_store='SQLITE3', mandatory=True)
+    conf.check_cfg(package='liblog4cxx', args=['--cflags', '--libs'], uselib_store='LOG4CXX', mandatory=True)
+    conf.define ("HAVE_LOG4CXX", 1)
 
     conf.check_boost(lib='system random thread filesystem')
 
@@ -28,9 +30,9 @@
         target = "Contacts",
         features = "qt4 cxx cxxprogram",
         defines = "WAF",
-        source = bld.path.ant_glob(['src/*.cpp', 'src/*.ui']),
+        source = bld.path.ant_glob(['src/*.cpp', 'src/*.ui', 'logging.cc']),
         includes = ".",
-        use = "QTCORE QTGUI SQLITE3 NDNCXX TINYXML BOOST BOOST_FILESYSTEM",
+        use = "QTCORE QTGUI QTSQL SQLITE3 NDNCXX TINYXML BOOST BOOST_FILESYSTEM LOG4CXX",
         )