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",
)