security: Fix security bugs, now ChronoChat should work with security

Change-Id: I81e7687bb4b02798ad9de3da34b36b0f011ffd66
diff --git a/TODO b/TODO
index 61f4d58..0c8dd35 100644
--- a/TODO
+++ b/TODO
@@ -1,2 +1,3 @@
 1. When clicking message balloon, the corresponding ChatDialog is raised.
-2. Check how does QT handle pointers created by new.
\ No newline at end of file
+2. Fix mulitple occurance problem.
+3. Add the trust spanning tree.
\ No newline at end of file
diff --git a/debug-tools/dump-local-prefix.cc b/debug-tools/dump-local-prefix.cc
new file mode 100644
index 0000000..ba67ac4
--- /dev/null
+++ b/debug-tools/dump-local-prefix.cc
@@ -0,0 +1,37 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <ndn-cpp-dev/security/key-chain.hpp>
+#include <ndn-cpp-dev/face.hpp>
+
+using namespace ndn;
+
+int 
+main()
+{
+  Name root("/ndn");
+
+  KeyChainImpl<SecPublicInfoSqlite3, SecTpmFile> keyChain;
+
+  if(!keyChain.doesIdentityExist(root))
+    return 1;
+
+  shared_ptr<boost::asio::io_service> ioService = make_shared<boost::asio::io_service>();
+  shared_ptr<Face> face = shared_ptr<Face>(new Face(ioService));
+
+  Name name("/local/ndn/prefix");
+  name.appendVersion().appendSegment(0);
+
+  Data data(name);
+  std::string prefix("/ndn/test");
+  data.setContent(reinterpret_cast<const uint8_t*>(prefix.c_str()), prefix.size());
+  keyChain.signByIdentity(data, root);
+  
+  face->put(data);
+
+  ioService->run();
+}
diff --git a/src/chat-dialog.cpp b/src/chat-dialog.cpp
index 954a4c6..baa9f78 100644
--- a/src/chat-dialog.cpp
+++ b/src/chat-dialog.cpp
@@ -37,7 +37,7 @@
 static const uint8_t CHRONOS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.
 
 Q_DECLARE_METATYPE(std::vector<Sync::MissingDataInfo> )
-Q_DECLARE_METATYPE(ndn::Data)
+Q_DECLARE_METATYPE(ndn::shared_ptr<const ndn::Data>)
 Q_DECLARE_METATYPE(ndn::Interest)
 Q_DECLARE_METATYPE(size_t)
 
@@ -66,7 +66,7 @@
   , m_inviteListDialog(new InviteListDialog)
 {
   qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
-  qRegisterMetaType<ndn::Data>("ndn.Data");
+  qRegisterMetaType<ndn::shared_ptr<const ndn::Data> >("ndn.DataPtr");
   qRegisterMetaType<ndn::Interest>("ndn.Interest");
   qRegisterMetaType<size_t>("size_t");
 
@@ -98,16 +98,16 @@
   connect(m_timer, SIGNAL(timeout()), 
           this, SLOT(onReplot()));
 
-  connect(this, SIGNAL(processData(const ndn::Data&, bool, bool)), 
-          this, SLOT(onProcessData(const ndn::Data&, bool, bool)));
+  connect(this, SIGNAL(processData(const ndn::shared_ptr<const ndn::Data>&, bool, bool)), 
+          this, SLOT(onProcessData(const ndn::shared_ptr<const ndn::Data>&, bool, bool)));
   connect(this, SIGNAL(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)), 
           this, SLOT(onProcessTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
-  connect(this, SIGNAL(reply(const ndn::Interest&, const ndn::Data&, size_t, bool)),
-          this, SLOT(onReply(const ndn::Interest&, const ndn::Data&, size_t, bool)));
+  connect(this, SIGNAL(reply(const ndn::Interest&, const ndn::shared_ptr<const ndn::Data>&, size_t, bool)),
+          this, SLOT(onReply(const ndn::Interest&, const ndn::shared_ptr<const ndn::Data>&, size_t, bool)));
   connect(this, SIGNAL(replyTimeout(const ndn::Interest&, size_t)),
           this, SLOT(onReplyTimeout(const ndn::Interest&, size_t)));
-  connect(this, SIGNAL(introCert(const ndn::Interest&, const ndn::Data&)),
-          this, SLOT(onIntroCert(const ndn::Interest&, const ndn::Data&)));
+  connect(this, SIGNAL(introCert(const ndn::Interest&, const ndn::shared_ptr<const ndn::Data>&)),
+          this, SLOT(onIntroCert(const ndn::Interest&, const ndn::shared_ptr<const ndn::Data>&)));
   connect(this, SIGNAL(introCertTimeout(const ndn::Interest&, int, const QString&)),
           this, SLOT(onIntroCertTimeout(const ndn::Interest&, int, const QString&)));
 
@@ -124,6 +124,8 @@
               this, SLOT(onInviteListDialogRequested()));
       connect(m_inviteListDialog, SIGNAL(sendInvitation(const QString&)),
               this, SLOT(onSendInvitation(const QString&)));
+      connect(this, SIGNAL(waitForContactList()),
+              m_contactManager, SLOT(onWaitForContactList()));
       connect(m_contactManager, SIGNAL(contactAliasListReady(const QStringList&)),
               m_inviteListDialog, SLOT(onContactAliasListReady(const QStringList&)));
       connect(m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
@@ -154,6 +156,7 @@
 void
 ChatDialog::addSyncAnchor(const Invitation& invitation)
 {
+  _LOG_DEBUG("Add sync anchor from invation");
   // Add inviter certificate as trust anchor.
   m_sock->addParticipant(invitation.getInviterCertificate());
 
@@ -172,14 +175,14 @@
 void
 ChatDialog::processDataWrapper(const shared_ptr<const Data>& data)
 {
-  emit processData(*data, true, false);
+  emit processData(data, true, false);
   _LOG_DEBUG("<<< " << data->getName() << " fetched");
 }
 
 void
 ChatDialog::processDataNoShowWrapper(const shared_ptr<const Data>& data)
 {
-  emit processData(*data, false, false);
+  emit processData(data, false, false);
 }
 
 void
@@ -202,6 +205,22 @@
 }
 
 void
+ChatDialog::changeEvent(QEvent *e)
+{
+  switch(e->type())
+  {
+  case QEvent::ActivationChange:
+    if (isActiveWindow())
+    {
+      emit resetIcon();
+    }
+    break;
+  default:
+    break;
+  }
+}
+
+void
 ChatDialog::resizeEvent(QResizeEvent *e)
 {
   fitView();
@@ -326,6 +345,7 @@
   // Send the invitation out
   Interest interest(interestName);
   interest.setMustBeFresh(true);
+  _LOG_DEBUG("sendInvitation: " << interest.getName());
   m_face->expressInterest(interest,
                           bind(&ChatDialog::replyWrapper, this, _1, _2, routablePrefixOffset, isIntroducer),
                           bind(&ChatDialog::replyTimeoutWrapper, this, _1, routablePrefixOffset));
@@ -337,13 +357,16 @@
                          size_t routablePrefixOffset,
                          bool isIntroducer)
 {
-  emit reply(interest, data, routablePrefixOffset, isIntroducer);
+  _LOG_DEBUG("ChatDialog::replyWrapper");
+  emit reply(interest, data.shared_from_this(), routablePrefixOffset, isIntroducer);
+  _LOG_DEBUG("OK?");
 }
 
 void
 ChatDialog::replyTimeoutWrapper(const Interest& interest, 
                                 size_t routablePrefixOffset)
 {
+  _LOG_DEBUG("ChatDialog::replyTimeoutWrapper");
   emit replyTimeout(interest, routablePrefixOffset);
 }
 
@@ -429,6 +452,8 @@
       Interest interest(certName);
       interest.setMustBeFresh(true);
 
+      _LOG_DEBUG("onIntroCertList: to fetch " << certName);
+
       m_face->expressInterest(interest,
                               bind(&ChatDialog::introCertWrapper, this, _1, _2),
                               bind(&ChatDialog::introCertTimeoutWrapper, this, _1, 0, 
@@ -450,7 +475,7 @@
 void
 ChatDialog::introCertWrapper(const Interest& interest, Data& data)
 {
-  emit introCert(interest, data);
+  emit introCert(interest, data.shared_from_this());
 }
 
 void
@@ -500,6 +525,7 @@
       const Sync::IntroCertificate& introCert = m_sock->getIntroCertificate(certName);
       Data data(interest.getName());
       data.setContent(introCert.wireEncode());
+      m_keyChain.sign(data,  m_myCertificate.getName());
       m_face->put(data);
     }
   catch(Sync::SyncSocket::Error& e)
@@ -526,12 +552,12 @@
     _LOG_DEBUG("Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?");
     abort();
   }
+  uint64_t nextSequence = m_sock->getNextSeq();
   m_sock->publishData(os.buf()->buf(), os.buf()->size(), FRESHNESS);
 
   m_lastMsgTime = time::now();
 
-  uint64_t nextSequence = m_sock->getNextSeq();
-  Sync::MissingDataInfo mdi = {m_localChatPrefix.toUri(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
+  Sync::MissingDataInfo mdi = {m_localChatPrefix.toUri(), Sync::SeqNo(0), Sync::SeqNo(nextSequence)};
   std::vector<Sync::MissingDataInfo> v;
   v.push_back(mdi);
   {
@@ -913,13 +939,13 @@
 }
 
 void
-ChatDialog::onProcessData(const Data& data, bool show, bool isHistory)
+ChatDialog::onProcessData(const shared_ptr<const Data>& data, bool show, bool isHistory)
 {
   SyncDemo::ChatMessage msg;
   bool corrupted = false;
-  if (!msg.ParseFromArray(data.getContent().value(), data.getContent().value_size()))
+  if (!msg.ParseFromArray(data->getContent().value(), data->getContent().value_size()))
   {
-    _LOG_DEBUG("Errrrr.. Can not parse msg with name: " << data.getName() << ". what is happening?");
+    _LOG_DEBUG("Errrrr.. Can not parse msg with name: " << data->getName() << ". what is happening?");
     // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
     msg.set_from("inconnu");
     msg.set_type(SyncDemo::ChatMessage::OTHER);
@@ -939,7 +965,7 @@
   if (!isHistory)
   {
     // update the tree view
-    std::string stdStrName = data.getName().toUri();
+    std::string stdStrName = data->getName().toUri();
     std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
     std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
     _LOG_DEBUG("<<< updating scene for" << prefix << ": " << msg.from());
@@ -1030,6 +1056,7 @@
 void
 ChatDialog::onInviteListDialogRequested()
 {
+  emit waitForContactList();
   m_inviteListDialog->setInviteLabel(m_chatroomPrefix.toUri());
   m_inviteListDialog->show();
 }
@@ -1112,7 +1139,7 @@
 
 void 
 ChatDialog::onReply(const Interest& interest, 
-                    const Data& data,
+                    const shared_ptr<const Data>& data,
                     size_t routablePrefixOffset,
                     bool isIntroducer)
 {
@@ -1127,12 +1154,12 @@
   if(routablePrefixOffset > 0)
     {
       // It is an encapsulated packet, we only validate the inner packet.
-      Data innerData;
-      innerData.wireDecode(data.getContent().blockFromValue());
-      m_invitationValidator->validate(innerData, onValidated, onFailed);
+      shared_ptr<Data> innerData = make_shared<Data>();
+      innerData->wireDecode(data->getContent().blockFromValue());
+      m_invitationValidator->validate(*innerData, onValidated, onFailed);
     }
   else
-    m_invitationValidator->validate(data, onValidated, onFailed);
+    m_invitationValidator->validate(*data, onValidated, onFailed);
 }
 
 void
@@ -1152,16 +1179,16 @@
 }
 
 void
-ChatDialog::onIntroCert(const ndn::Interest& interest, const Data& data)
+ChatDialog::onIntroCert(const Interest& interest, const shared_ptr<const Data>& data)
 {
   Data innerData;
-  innerData.wireDecode(data.getContent().blockFromValue());
+  innerData.wireDecode(data->getContent().blockFromValue());
   Sync::IntroCertificate introCert(innerData);
   m_sock->addParticipant(introCert);
 }
 
 void
-ChatDialog::onIntroCertTimeout(const ndn::Interest& interest, int retry, const QString& msg)
+ChatDialog::onIntroCertTimeout(const Interest& interest, int retry, const QString& msg)
 {
   _LOG_DEBUG("onIntroCertTimeout: " << msg.toStdString());
 }
diff --git a/src/chat-dialog.h b/src/chat-dialog.h
index f136b82..0ddbc85 100644
--- a/src/chat-dialog.h
+++ b/src/chat-dialog.h
@@ -81,6 +81,9 @@
   void 
   closeEvent(QCloseEvent *e);
 
+  void
+  changeEvent(QEvent *e);
+
   void 
   resizeEvent(QResizeEvent *);
   
@@ -196,7 +199,7 @@
 
 signals:  
   void
-  processData(const ndn::Data& data, bool show, bool isHistory);
+  processData(const ndn::shared_ptr<const ndn::Data>& data, bool show, bool isHistory);
 
   void 
   processTreeUpdate(const std::vector<Sync::MissingDataInfo>);
@@ -211,17 +214,27 @@
   showChatMessage(const QString& chatroomName, const QString& from, const QString& data);
 
   void
-  reply(const ndn::Interest& interest, const ndn::Data& data, size_t routablePrefixOffset, bool isIntroducer);
+  resetIcon();
 
   void
-  replyTimeout(const ndn::Interest& interest, size_t routablePrefixOffset);
+  reply(const ndn::Interest& interest,
+        const ndn::shared_ptr<const ndn::Data>& data,
+        size_t routablePrefixOffset, bool isIntroducer);
 
   void
-  introCert(const ndn::Interest& interest, const ndn::Data& data);
+  replyTimeout(const ndn::Interest& interest, 
+               size_t routablePrefixOffset);
+
+  void
+  introCert(const ndn::Interest& interest,
+            const ndn::shared_ptr<const ndn::Data>& data);
   
   void
-  introCertTimeout(const ndn::Interest& interest, int retry, const QString& msg);
+  introCertTimeout(const ndn::Interest& interest,
+                   int retry, const QString& msg);
 
+  void
+  waitForContactList();
 
 public slots:
   void
@@ -238,7 +251,8 @@
   onTreeButtonPressed();
 
   void 
-  onProcessData(const ndn::Data& data, bool show, bool isHistory);
+  onProcessData(const ndn::shared_ptr<const ndn::Data>& data,
+                bool show, bool isHistory);
 
   void 
   onProcessTreeUpdate(const std::vector<Sync::MissingDataInfo>&);
@@ -271,16 +285,21 @@
   onSendInvitation(QString);
 
   void
-  onReply(const ndn::Interest& interest, const ndn::Data& data, size_t routablePrefixOffset, bool isIntroducer);
+  onReply(const ndn::Interest& interest,
+          const ndn::shared_ptr<const ndn::Data>& data,
+          size_t routablePrefixOffset, bool isIntroducer);
 
   void
-  onReplyTimeout(const ndn::Interest& interest, size_t routablePrefixOffset);
+  onReplyTimeout(const ndn::Interest& interest,
+                 size_t routablePrefixOffset);
 
   void
-  onIntroCert(const ndn::Interest& interest, const ndn::Data& data);
+  onIntroCert(const ndn::Interest& interest,
+              const ndn::shared_ptr<const ndn::Data>& data);
 
   void
-  onIntroCertTimeout(const ndn::Interest& interest, int retry, const QString& msg);
+  onIntroCertTimeout(const ndn::Interest& interest,
+                     int retry, const QString& msg);
 
 private:
   Ui::ChatDialog *ui;
diff --git a/src/controller.cpp b/src/controller.cpp
index 723617a..43e79a4 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -34,6 +34,8 @@
 Q_DECLARE_METATYPE(ndn::Name)
 Q_DECLARE_METATYPE(ndn::IdentityCertificate)
 Q_DECLARE_METATYPE(chronos::EndorseInfo)
+Q_DECLARE_METATYPE(ndn::Interest)
+Q_DECLARE_METATYPE(size_t)
 
 namespace chronos {
 
@@ -57,9 +59,13 @@
   qRegisterMetaType<ndn::Name>("ndn.Name");
   qRegisterMetaType<ndn::IdentityCertificate>("ndn.IdentityCertificate");
   qRegisterMetaType<chronos::EndorseInfo>("chronos.EndorseInfo");
+  qRegisterMetaType<ndn::Interest>("ndn.Interest");
+  qRegisterMetaType<size_t>("size_t");
 
   connect(this, SIGNAL(localPrefixUpdated(const QString&)),
           this, SLOT(onLocalPrefixUpdated(const QString&)));
+  connect(this, SIGNAL(invitationInterest(const ndn::Name&, const ndn::Interest&, size_t)),
+          this, SLOT(onInvitationInterest(const ndn::Name&, const ndn::Interest&, size_t)));
 
   // Connection to ContactManager
   connect(this, SIGNAL(identityUpdated(const QString&)),
@@ -148,7 +154,9 @@
 
   initialize();
 
-  createTrayIcon();          
+  createTrayIcon();
+
+  onUpdateLocalPrefixAction();
 }
   
 Controller::~Controller()
@@ -221,7 +229,7 @@
   invitationPrefix.append(m_identity).append("CHRONOCHAT-INVITATION");
 
   m_invitationListenerId = m_face->setInterestFilter(invitationPrefix, 
-                                                     bind(&Controller::onInvitationInterest, this, _1, _2, offset),
+                                                     bind(&Controller::onInvitationInterestWrapper, this, _1, _2, offset),
                                                      bind(&Controller::onInvitationRegisterFailed, this, _1, _2));
 }
 
@@ -342,6 +350,7 @@
   menu->addAction(m_settingsAction);
   menu->addAction(m_editProfileAction);
   menu->addSeparator();
+  menu->addAction(m_contactListAction);
   menu->addAction(m_addContactAction);
   menu->addSeparator();
   {
@@ -403,32 +412,15 @@
 }
 
 void
-Controller::onInvitationInterest(const Name& prefix, const Interest& interest, size_t routingPrefixOffset)
+Controller::onInvitationInterestWrapper(const Name& prefix, const Interest& interest, size_t routingPrefixOffset)
 {
-  shared_ptr<Interest> invitationInterest = make_shared<Interest>(boost::cref(interest.getName().getSubName(routingPrefixOffset)));
-
-  // check if the chatroom already exists;
-  try
-    {
-      Invitation invitation(invitationInterest->getName());
-      if(m_chatDialogList.find(invitation.getChatroom()) != m_chatDialogList.end())
-        return;
-    }
-  catch(Invitation::Error& e)
-    {
-      // Cannot parse the invitation;
-      return;
-    }
-
-  OnInterestValidated onValidated = bind(&Controller::onInvitationValidated, this, _1);
-  OnInterestValidationFailed onValidationFailed = bind(&Controller::onInvitationValidationFailed, this, _1, _2);
-  m_validator.validate(*invitationInterest, onValidated, onValidationFailed);
+  emit invitationInterest(prefix, interest, routingPrefixOffset);
 }
 
 void
 Controller::onInvitationRegisterFailed(const Name& prefix, const std::string& failInfo)
 {
-  std::cerr << "Controller::onInvitationRegisterFailed: " << failInfo << std::endl;
+  _LOG_DEBUG("Controller::onInvitationRegisterFailed: " << failInfo);
 }
 
 void
@@ -444,7 +436,7 @@
 void
 Controller::onInvitationValidationFailed(const shared_ptr<const Interest>& interest, std::string failureInfo)
 {
-  std::cerr << "Invitation: " << interest->getName() << " cannot not be validated due to: " << failureInfo << std::endl;
+  _LOG_DEBUG("Invitation: " << interest->getName() << " cannot not be validated due to: " << failureInfo);
 }
 
 std::string
@@ -485,6 +477,8 @@
           this, SLOT(onRemoveChatDialog(const QString&)));
   connect(chatDialog, SIGNAL(showChatMessage(const QString&, const QString&, const QString&)),
           this, SLOT(onShowChatMessage(const QString&, const QString&, const QString&)));
+  connect(chatDialog, SIGNAL(resetIcon()),
+          this, SLOT(onResetIcon()));
   connect(this, SIGNAL(localPrefixUpdated(const QString&)),
           chatDialog, SLOT(onLocalPrefixUpdated(const QString&)));
 
@@ -513,6 +507,7 @@
 
   m_identity = identityName;
   m_keyChain.createIdentity(m_identity);
+  setInvitationListener();
 
   emit closeDBModule();
   
@@ -645,6 +640,9 @@
       onRemoveChatDialog(QString::fromStdString(it->first));
     }
 
+  if(m_invitationListenerId != 0)
+    m_face->unsetInterestFilter(m_invitationListenerId);
+
   delete m_settingDialog;
   delete m_startChatDialog;
   delete m_profileEditor;
@@ -706,25 +704,29 @@
       response.setName(invitationName);
       response.setFreshnessPeriod(1000);
     }
+  m_keyChain.signByIdentity(response, m_identity);
   
   // Check if we need a wrapper
   Name invitationRoutingPrefix = getInvitationRoutingPrefix();
   if(invitationRoutingPrefix.isPrefixOf(m_identity))
     {
-      m_keyChain.signByIdentity(response, m_identity);
       m_face->put(response);
     }
   else
     {
       Name wrappedName;
-      wrappedName.append(invitationRoutingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2);
+      wrappedName.append(invitationRoutingPrefix)
+        .append(ROUTING_PREFIX_SEPARATOR, 2)
+        .append(response.getName());
+
+      _LOG_DEBUG("onInvitationResponded: prepare reply " << wrappedName);
       
       Data wrappedData(wrappedName);
       wrappedData.setContent(response.wireEncode());
       wrappedData.setFreshnessPeriod(1000);
 
-      m_keyChain.signByIdentity(response, m_identity);
-      m_face->put(response);
+      m_keyChain.signByIdentity(wrappedData, m_identity);
+      m_face->put(wrappedData);
     }
 
   // create chatroom
@@ -740,9 +742,9 @@
       //We should create a chatroom specific key/cert (which should be created in the first half of this method, but let's use the default one for now.
       shared_ptr<IdentityCertificate> idCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
       ChatDialog* chatDialog = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix, m_localPrefix, m_nick, true);
+      chatDialog->addSyncAnchor(invitation);
 
       addChatDialog(QString::fromStdString(invitation.getChatroom()), chatDialog);
-      chatDialog->addSyncAnchor(invitation);
       chatDialog->show();
     }
 }
@@ -757,6 +759,12 @@
 }
 
 void
+Controller::onResetIcon()
+{
+  m_trayIcon->setIcon(QIcon(":/images/icon_small.png"));
+}
+
+void
 Controller::onRemoveChatDialog(const QString& chatroomName)
 {
   ChatDialogList::iterator it = m_chatDialogList.find(chatroomName.toStdString());
@@ -795,6 +803,30 @@
   exit(1);
 }
 
+void
+Controller::onInvitationInterest(const Name& prefix, const Interest& interest, size_t routingPrefixOffset)
+{
+  _LOG_DEBUG("onInvitationInterest: " << interest.getName());
+  shared_ptr<Interest> invitationInterest = make_shared<Interest>(boost::cref(interest.getName().getSubName(routingPrefixOffset)));
+
+  // check if the chatroom already exists;
+  try
+    {
+      Invitation invitation(invitationInterest->getName());
+      if(m_chatDialogList.find(invitation.getChatroom()) != m_chatDialogList.end())
+        return;
+    }
+  catch(Invitation::Error& e)
+    {
+      // Cannot parse the invitation;
+      return;
+    }
+
+  OnInterestValidated onValidated = bind(&Controller::onInvitationValidated, this, _1);
+  OnInterestValidationFailed onValidationFailed = bind(&Controller::onInvitationValidationFailed, this, _1, _2);
+  m_validator.validate(*invitationInterest, onValidated, onValidationFailed);
+}
+
 } // namespace chronos
 
 #if WAF
diff --git a/src/controller.h b/src/controller.h
index 85986c7..40a481a 100644
--- a/src/controller.h
+++ b/src/controller.h
@@ -80,7 +80,7 @@
   onLocalPrefixTimeout(const ndn::Interest& interest);
 
   void
-  onInvitationInterest(const ndn::Name& prefix, const ndn::Interest& interest, size_t routingPrefixOffset);
+  onInvitationInterestWrapper(const ndn::Name& prefix, const ndn::Interest& interest, size_t routingPrefixOffset);
   
   void
   onInvitationRegisterFailed(const ndn::Name& prefix, const std::string& failInfo);
@@ -113,6 +113,9 @@
   void
   refreshBrowseContact();
 
+  void
+  invitationInterest(const ndn::Name& prefix, const ndn::Interest& interest, size_t routingPrefixOffset);
+
 private slots:
   void
   onIdentityUpdated(const QString& identity);
@@ -164,6 +167,9 @@
 
   void
   onShowChatMessage(const QString& chatroomName, const QString& from, const QString& data);
+  
+  void
+  onResetIcon();
 
   void
   onRemoveChatDialog(const QString& chatroom);
@@ -174,6 +180,9 @@
   void
   onError(const QString& msg);
 
+  void
+  onInvitationInterest(const ndn::Name& prefix, const ndn::Interest& interest, size_t routingPrefixOffset);
+
 private: // private member
   typedef std::map<std::string, QAction*> ChatActionList;
   typedef std::map<std::string, ChatDialog*> ChatDialogList;
diff --git a/src/invitation-dialog.cpp b/src/invitation-dialog.cpp
index 8be49fc..d14715b 100644
--- a/src/invitation-dialog.cpp
+++ b/src/invitation-dialog.cpp
@@ -38,6 +38,7 @@
                                 const Name& interestName)
 {
   string msg = alias;
+  m_invitationInterest = interestName;
   msg.append(" invites you to: ").append(chatroom);
   ui->msgLabel->setText(QString::fromStdString(msg));
 }
diff --git a/src/validator-invitation.cpp b/src/validator-invitation.cpp
index ec54a38..1c38860 100644
--- a/src/validator-invitation.cpp
+++ b/src/validator-invitation.cpp
@@ -53,8 +53,8 @@
       Data innerData;
       innerData.wireDecode(data.getContent().blockFromValue());
       
-      return internalCheck(data.wireEncode().wire(), 
-                           data.wireEncode().size(),
+      return internalCheck(data.wireEncode().value(), 
+                           data.wireEncode().value_size() - data.getSignature().getValue().size(),
                            sig,
                            innerData,
                            bind(onValidated, data.shared_from_this()), 
@@ -123,10 +123,11 @@
         return onValidationFailed("Cannot reach any trust anchor");
 
       if(!Validator::verifySignature(buf, size, sig, m_trustAnchors[signingKeyName]))
-        return onValidationFailed("Cannot verify interest signature");
+        return onValidationFailed("Cannot verify outer signature");
 
-      if(!Validator::verifySignature(innerData, m_trustAnchors[signingKeyName]))
-        return onValidationFailed("Cannot verify interest signature");
+      // Temporarily disabled, we should get it back when we create a specific key for the chatroom.
+      // if(!Validator::verifySignature(innerData, m_trustAnchors[signingKeyName]))
+      //   return onValidationFailed("Cannot verify inner signature");
 
       if(!m_innerKeyRegex.match(innerData.getName())
           || m_innerKeyRegex.expand() != signingKeyName.getPrefix(-1))