blob: bc91ac683d3cdbc877c103c719308d626c7f8a9f [file] [log] [blame]
Yingdi Yud04ed1a2013-10-14 14:07:03 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * Yingdi Yu
5 *
6 * BSD license, See the LICENSE file for more information
7 *
8 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
9 */
10
Yingdi Yu0b0a7362014-08-05 16:31:30 -070011#include "contact-storage.hpp"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070012
Yingdi Yud04ed1a2013-10-14 14:07:03 -070013#include <boost/filesystem.hpp>
Yingdi Yu0b0a7362014-08-05 16:31:30 -070014#include "cryptopp.hpp"
Yingdi Yu3b318c12013-10-15 17:54:00 -070015#include "logging.h"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070016
Yingdi Yu0b0a7362014-08-05 16:31:30 -070017
18// INIT_LOGGER ("chronos.ContactStorage");
19
Yingdi Yueb692ac2015-02-10 18:46:18 -080020namespace chronochat {
Yingdi Yu0b0a7362014-08-05 16:31:30 -070021
Yingdi Yud04ed1a2013-10-14 14:07:03 -070022namespace fs = boost::filesystem;
23
Yingdi Yu0b0a7362014-08-05 16:31:30 -070024using std::string;
25using std::vector;
Yingdi Yu3b318c12013-10-15 17:54:00 -070026
Yingdi Yu0b0a7362014-08-05 16:31:30 -070027using ndn::PublicKey;
Yingdi Yufa4ce792014-02-06 18:09:22 -080028
Yingdi Yu0b0a7362014-08-05 16:31:30 -070029// user's own profile;
30const string INIT_SP_TABLE =
31 "CREATE TABLE IF NOT EXISTS "
32 " SelfProfile( "
33 " profile_type BLOB NOT NULL, "
34 " profile_value BLOB NOT NULL, "
35 " PRIMARY KEY (profile_type) "
36 " ); "
37 "CREATE INDEX sp_index ON SelfProfile(profile_type); ";
Yingdi Yu17032f82014-03-25 15:48:23 -070038
Yingdi Yu0b0a7362014-08-05 16:31:30 -070039// user's self endorse cert;
40const string INIT_SE_TABLE =
41 "CREATE TABLE IF NOT EXISTS "
42 " SelfEndorse( "
43 " identity BLOB NOT NULL UNIQUE, "
44 " endorse_data BLOB NOT NULL, "
45 " PRIMARY KEY (identity) "
46 " ); "
47 "CREATE INDEX se_index ON SelfEndorse(identity); ";
Yingdi Yu3b318c12013-10-15 17:54:00 -070048
Yingdi Yu0b0a7362014-08-05 16:31:30 -070049// contact's basic info
50const string INIT_CONTACT_TABLE =
51 "CREATE TABLE IF NOT EXISTS "
52 " Contact( "
53 " contact_namespace BLOB NOT NULL, "
54 " contact_alias BLOB NOT NULL, "
55 " contact_keyName BLOB NOT NULL, "
56 " contact_key BLOB NOT NULL, "
57 " notBefore INTEGER DEFAULT 0, "
58 " notAfter INTEGER DEFAULT 0, "
59 " is_introducer INTEGER DEFAULT 0, "
60 " PRIMARY KEY (contact_namespace) "
61 " ); "
62 "CREATE INDEX contact_index ON Contact(contact_namespace); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -070063
Yingdi Yu0b0a7362014-08-05 16:31:30 -070064// contact's trust scope;
65const string INIT_TS_TABLE =
66 "CREATE TABLE IF NOT EXISTS "
67 " TrustScope( "
68 " id INTEGER PRIMARY KEY AUTOINCREMENT, "
69 " contact_namespace BLOB NOT NULL, "
70 " trust_scope BLOB NOT NULL "
71 " ); "
72 "CREATE INDEX ts_index ON TrustScope(contact_namespace); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -070073
Yingdi Yu0b0a7362014-08-05 16:31:30 -070074// contact's profile
75const string INIT_CP_TABLE =
76 "CREATE TABLE IF NOT EXISTS "
77 " ContactProfile( "
78 " profile_identity BLOB NOT NULL, "
79 " profile_type BLOB NOT NULL, "
80 " profile_value BLOB NOT NULL, "
81 " endorse INTEGER NOT NULL, "
82 " PRIMARY KEY (profile_identity, profile_type) "
83 " ); "
84 "CREATE INDEX cp_index ON ContactProfile(profile_identity); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -080085
Yingdi Yu0b0a7362014-08-05 16:31:30 -070086// user's endorsement on contacts
87const string INIT_PE_TABLE =
88 "CREATE TABLE IF NOT EXISTS "
89 " ProfileEndorse( "
90 " identity BLOB NOT NULL UNIQUE, "
91 " endorse_data BLOB NOT NULL, "
92 " PRIMARY KEY (identity) "
93 " ); "
94 "CREATE INDEX pe_index ON ProfileEndorse(identity); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -080095
Yingdi Yu0b0a7362014-08-05 16:31:30 -070096// contact's endorsements on the user
97const string INIT_CE_TABLE =
98 "CREATE TABLE IF NOT EXISTS "
99 " CollectEndorse( "
100 " endorser BLOB NOT NULL, "
101 " endorse_name BLOB NOT NULL, "
102 " endorse_data BLOB NOT NULL, "
103 " PRIMARY KEY (endorser) "
104 " ); ";
Yingdi Yub2e747d2013-11-05 23:06:43 -0800105
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700106// dns data;
107const string INIT_DD_TABLE =
108 "CREATE TABLE IF NOT EXISTS "
109 " DnsData( "
110 " dns_name BLOB NOT NULL, "
111 " dns_type BLOB NOT NULL, "
112 " data_name BLOB NOT NULL, "
113 " dns_value BLOB NOT NULL, "
114 " PRIMARY KEY (dns_name, dns_type) "
115 " ); "
116 "CREATE INDEX dd_index ON DnsData(dns_name, dns_type); "
117 "CREATE INDEX dd_index2 ON DnsData(data_name); ";
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700118
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700119/**
120 * A utility function to call the normal sqlite3_bind_text where the value and length are
121 * value.c_str() and value.size().
122 */
123static int
124sqlite3_bind_string(sqlite3_stmt* statement,
125 int index,
126 const string& value,
127 void(*destructor)(void*))
128{
129 return sqlite3_bind_text(statement, index, value.c_str(), value.size(), destructor);
130}
131
132/**
133 * A utility function to call the normal sqlite3_bind_blob where the value and length are
134 * block.wire() and block.size().
135 */
136static int
137sqlite3_bind_block(sqlite3_stmt* statement,
138 int index,
139 const Block& block,
140 void(*destructor)(void*))
141{
142 return sqlite3_bind_blob(statement, index, block.wire(), block.size(), destructor);
143}
144
145/**
146 * A utility function to generate string by calling the normal sqlite3_column_text.
147 */
148static string
149sqlite3_column_string(sqlite3_stmt* statement, int column)
150{
151 return string(reinterpret_cast<const char*>(sqlite3_column_text(statement, column)),
152 sqlite3_column_bytes(statement, column));
153}
154
155/**
156 * A utility function to generate block by calling the normal sqlite3_column_text.
157 */
158static Block
159sqlite3_column_block(sqlite3_stmt* statement, int column)
160{
161 return Block(reinterpret_cast<const char*>(sqlite3_column_blob(statement, column)),
162 sqlite3_column_bytes(statement, column));
163}
164
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800165
166ContactStorage::ContactStorage(const Name& identity)
167 : m_identity(identity)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700168{
169 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700170 fs::create_directories(chronosDir);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700171
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700172 int res = sqlite3_open((chronosDir / getDBName()).c_str(), &m_db);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700173 if (res != SQLITE_OK)
Yingdi Yueb692ac2015-02-10 18:46:18 -0800174 throw Error("chronochat DB cannot be open/created");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700175
Yingdi Yufa4ce792014-02-06 18:09:22 -0800176 initializeTable("SelfProfile", INIT_SP_TABLE);
177 initializeTable("SelfEndorse", INIT_SE_TABLE);
178 initializeTable("Contact", INIT_CONTACT_TABLE);
179 initializeTable("TrustScope", INIT_TS_TABLE);
180 initializeTable("ContactProfile", INIT_CP_TABLE);
181 initializeTable("ProfileEndorse", INIT_PE_TABLE);
182 initializeTable("CollectEndorse", INIT_CE_TABLE);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800183 initializeTable("DnsData", INIT_DD_TABLE);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700184
Yingdi Yu3b318c12013-10-15 17:54:00 -0700185}
186
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700187string
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800188ContactStorage::getDBName()
189{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700190 string dbName("chronos-");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800191
Yingdi Yu17032f82014-03-25 15:48:23 -0700192 std::stringstream ss;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800193 {
194 using namespace CryptoPP;
195
196 SHA256 hash;
197 StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
198 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
199 }
200 dbName.append(ss.str()).append(".db");
201
202 return dbName;
203}
204
Yingdi Yu3b318c12013-10-15 17:54:00 -0700205void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700206ContactStorage::initializeTable(const string& tableName, const string& sqlCreateStmt)
Yingdi Yu3b318c12013-10-15 17:54:00 -0700207{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800208 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700209 sqlite3_prepare_v2(m_db,
210 "SELECT name FROM sqlite_master WHERE type='table' And name=?",
211 -1, &stmt, 0);
212 sqlite3_bind_string(stmt, 1, tableName, SQLITE_TRANSIENT);
213 int res = sqlite3_step(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800214
215 bool tableExist = false;
216 if (res == SQLITE_ROW)
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700217 tableExist = true;
218 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800219
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700220 if (!tableExist) {
221 char *errmsg = 0;
222 res = sqlite3_exec(m_db, sqlCreateStmt.c_str (), NULL, NULL, &errmsg);
223 if (res != SQLITE_OK && errmsg != 0)
224 throw Error("Init \"error\" in " + tableName);
225 }
Yingdi Yu3b318c12013-10-15 17:54:00 -0700226}
227
Yingdi Yu76dd8002013-12-24 11:16:32 +0800228shared_ptr<Profile>
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800229ContactStorage::getSelfProfile()
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700230{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800231 shared_ptr<Profile> profile = make_shared<Profile>(m_identity);
Yingdi Yu3b318c12013-10-15 17:54:00 -0700232 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700233 sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile", -1, &stmt, 0);
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700234
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700235 while (sqlite3_step(stmt) == SQLITE_ROW) {
236 string profileType = sqlite3_column_string(stmt, 0);
237 string profileValue = sqlite3_column_string (stmt, 1);
238 (*profile)[profileType] = profileValue;
239 }
Yingdi Yu72781e52013-11-06 23:00:21 -0800240 sqlite3_finalize(stmt);
241
Yingdi Yu3b318c12013-10-15 17:54:00 -0700242 return profile;
243}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800244
Yingdi Yufa4ce792014-02-06 18:09:22 -0800245void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800246ContactStorage::addSelfEndorseCertificate(const EndorseCertificate& newEndorseCertificate)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800247{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800248 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700249 sqlite3_prepare_v2(m_db,
250 "INSERT OR REPLACE INTO SelfEndorse (identity, endorse_data) values (?, ?)",
251 -1, &stmt, 0);
252 sqlite3_bind_string(stmt, 1, m_identity.toUri(), SQLITE_TRANSIENT);
253 sqlite3_bind_block(stmt, 2, newEndorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700254 sqlite3_step(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800255
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700256 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800257}
258
Yingdi Yufa4ce792014-02-06 18:09:22 -0800259void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700260ContactStorage::addEndorseCertificate(const EndorseCertificate& endorseCertificate,
261 const Name& identity)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800262{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800263 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700264 sqlite3_prepare_v2(m_db,
265 "INSERT OR REPLACE INTO ProfileEndorse \
266 (identity, endorse_data) values (?, ?)",
267 -1, &stmt, 0);
268 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
269 sqlite3_bind_block(stmt, 2, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800270 sqlite3_step(stmt);
271
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700272 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800273}
274
275void
276ContactStorage::updateCollectEndorse(const EndorseCertificate& endorseCertificate)
277{
278 Name endorserName = endorseCertificate.getSigner();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800279 Name certName = endorseCertificate.getName();
Yingdi Yufa4ce792014-02-06 18:09:22 -0800280
281 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700282 sqlite3_prepare_v2(m_db,
283 "INSERT OR REPLACE INTO CollectEndorse \
284 (endorser, endorse_name, endorse_data) \
285 VALUES (?, ?, ?, ?)",
286 -1, &stmt, 0);
287 sqlite3_bind_string(stmt, 1, endorserName.toUri(), SQLITE_TRANSIENT);
288 sqlite3_bind_string(stmt, 2, certName.toUri(), SQLITE_TRANSIENT);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700289 sqlite3_bind_block(stmt, 3, endorseCertificate.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700290 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700291 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800292 return;
293}
294
295void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800296ContactStorage::getCollectEndorse(EndorseCollection& endorseCollection)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800297{
298 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700299 sqlite3_prepare_v2(m_db, "SELECT endorse_name, endorse_data FROM CollectEndorse", -1, &stmt, 0);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800300
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700301 while (sqlite3_step(stmt) == SQLITE_ROW) {
302 string certName = sqlite3_column_string(stmt, 0);
303 std::stringstream ss;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800304 {
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700305 using namespace CryptoPP;
306 SHA256 hash;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800307
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700308 StringSource(sqlite3_column_text(stmt, 1), sqlite3_column_bytes (stmt, 1), true,
309 new HashFilter(hash, new FileSink(ss)));
Yingdi Yufa4ce792014-02-06 18:09:22 -0800310 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700311 EndorseCollection::Endorsement* endorsement = endorseCollection.add_endorsement();
312 endorsement->set_certname(certName);
313 endorsement->set_hash(ss.str());
314 }
Yingdi Yufa4ce792014-02-06 18:09:22 -0800315
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700316 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800317}
318
319void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700320ContactStorage::getEndorseList(const Name& identity, vector<string>& endorseList)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800321{
322 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700323 sqlite3_prepare_v2(m_db,
324 "SELECT profile_type FROM ContactProfile \
325 WHERE profile_identity=? AND endorse=1 ORDER BY profile_type",
326 -1, &stmt, 0);
327 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800328
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700329 while (sqlite3_step(stmt) == SQLITE_ROW) {
330 string profileType = sqlite3_column_string(stmt, 0);
331 endorseList.push_back(profileType);
332 }
333 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800334}
335
336
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700337void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800338ContactStorage::removeContact(const Name& identityName)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800339{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700340 string identity = identityName.toUri();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700341
342 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700343 sqlite3_prepare_v2(m_db, "DELETE FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
344 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700345 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700346 sqlite3_finalize(stmt);
Yingdi Yuae8217c2013-11-09 00:03:26 -0800347
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700348 sqlite3_prepare_v2(m_db, "DELETE FROM ContactProfile WHERE profile_identity=?", -1, &stmt, 0);
349 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700350 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700351 sqlite3_finalize(stmt);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700352
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700353 sqlite3_prepare_v2(m_db, "DELETE FROM TrustScope WHERE contact_namespace=?", -1, &stmt, 0);
354 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700355 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700356 sqlite3_finalize(stmt);
Yingdi Yuae8217c2013-11-09 00:03:26 -0800357}
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700358
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700359void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800360ContactStorage::addContact(const Contact& contact)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700361{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700362 if (doesContactExist(contact.getNameSpace()))
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800363 throw Error("Normal Contact has already existed");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700364
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700365 string identity = contact.getNameSpace().toUri();
Yingdi Yu71c01872013-11-03 16:22:05 -0800366 bool isIntroducer = contact.isIntroducer();
367
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700368 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700369 sqlite3_prepare_v2(m_db,
370 "INSERT INTO Contact (contact_namespace, contact_alias, contact_keyName, \
371 contact_key, notBefore, notAfter, is_introducer) \
372 values (?, ?, ?, ?, ?, ?, ?)",
373 -1, &stmt, 0);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700374
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700375 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
376 sqlite3_bind_string(stmt, 2, contact.getAlias(), SQLITE_TRANSIENT);
377 sqlite3_bind_string(stmt, 3, contact.getPublicKeyName().toUri(), SQLITE_TRANSIENT);
378 sqlite3_bind_text(stmt, 4,
379 reinterpret_cast<const char*>(contact.getPublicKey().get().buf()),
380 contact.getPublicKey().get().size(), SQLITE_TRANSIENT);
Yingdi Yua7876722014-03-25 14:46:55 -0700381 sqlite3_bind_int64(stmt, 5, time::toUnixTimestamp(contact.getNotBefore()).count());
382 sqlite3_bind_int64(stmt, 6, time::toUnixTimestamp(contact.getNotAfter()).count());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800383 sqlite3_bind_int(stmt, 7, (isIntroducer ? 1 : 0));
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700384
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800385 sqlite3_step(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800386
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700387 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800388
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800389 const Profile& profile = contact.getProfile();
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700390 for (Profile::const_iterator it = profile.begin(); it != profile.end(); it++) {
391 sqlite3_prepare_v2(m_db,
392 "INSERT INTO ContactProfile \
393 (profile_identity, profile_type, profile_value, endorse) \
394 values (?, ?, ?, 0)",
395 -1, &stmt, 0);
396 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
397 sqlite3_bind_string(stmt, 2, it->first, SQLITE_TRANSIENT);
398 sqlite3_bind_string(stmt, 3, it->second, SQLITE_TRANSIENT);
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800399 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700400 sqlite3_finalize(stmt);
401 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800402
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700403 if (isIntroducer) {
404 Contact::const_iterator it = contact.trustScopeBegin();
405 Contact::const_iterator end = contact.trustScopeEnd();
406
407 while (it != end) {
408 sqlite3_prepare_v2(m_db,
409 "INSERT INTO TrustScope (contact_namespace, trust_scope) values (?, ?)",
410 -1, &stmt, 0);
411 sqlite3_bind_string(stmt, 1, identity, SQLITE_TRANSIENT);
412 sqlite3_bind_string(stmt, 2, it->first.toUri(), SQLITE_TRANSIENT);
Yingdi Yu1cc45d92015-02-09 14:19:54 -0800413 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700414 sqlite3_finalize(stmt);
415 it++;
Yingdi Yub2e747d2013-11-05 23:06:43 -0800416 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700417 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700418}
419
Yingdi Yufa4ce792014-02-06 18:09:22 -0800420
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800421shared_ptr<Contact>
422ContactStorage::getContact(const Name& identity) const
Yingdi Yufa4ce792014-02-06 18:09:22 -0800423{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800424 shared_ptr<Contact> contact;
425 Profile profile;
426
Yingdi Yufa4ce792014-02-06 18:09:22 -0800427 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700428 sqlite3_prepare_v2(m_db,
429 "SELECT contact_alias, contact_keyName, contact_key, notBefore, notAfter, \
430 is_introducer FROM Contact where contact_namespace=?",
431 -1, &stmt, 0);
432 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800433
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700434 if (sqlite3_step(stmt) == SQLITE_ROW) {
435 string alias = sqlite3_column_string(stmt, 0);
436 string keyName = sqlite3_column_string(stmt, 1);
437 PublicKey key(sqlite3_column_text(stmt, 2), sqlite3_column_bytes (stmt, 2));
438 time::system_clock::TimePoint notBefore =
439 time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 3)));
440 time::system_clock::TimePoint notAfter =
441 time::fromUnixTimestamp(time::milliseconds(sqlite3_column_int64 (stmt, 4)));
442 int isIntroducer = sqlite3_column_int (stmt, 5);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800443
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700444 contact = make_shared<Contact>(identity, alias, Name(keyName),
445 notBefore, notAfter, key, isIntroducer);
446 }
447 sqlite3_finalize(stmt);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800448
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700449 sqlite3_prepare_v2(m_db,
450 "SELECT profile_type, profile_value FROM ContactProfile \
451 where profile_identity=?",
452 -1, &stmt, 0);
453 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700454
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700455 while (sqlite3_step(stmt) == SQLITE_ROW) {
456 string type = sqlite3_column_string(stmt, 0);
457 string value = sqlite3_column_string(stmt, 1);
458 profile[type] = value;
459 }
460 sqlite3_finalize(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800461 contact->setProfile(profile);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800462
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700463 if (contact->isIntroducer()) {
464 sqlite3_prepare_v2(m_db,
465 "SELECT trust_scope FROM TrustScope WHERE contact_namespace=?",
466 -1, &stmt, 0);
467 sqlite3_bind_string(stmt, 1, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800468
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700469 while (sqlite3_step(stmt) == SQLITE_ROW) {
470 Name scope(sqlite3_column_string(stmt, 0));
471 contact->addTrustScope(scope);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800472 }
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700473 sqlite3_finalize(stmt);
474 }
Yingdi Yufa4ce792014-02-06 18:09:22 -0800475
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800476 return contact;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800477}
478
479
Yingdi Yub2e747d2013-11-05 23:06:43 -0800480void
Yingdi Yufa4ce792014-02-06 18:09:22 -0800481ContactStorage::updateIsIntroducer(const Name& identity, bool isIntroducer)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800482{
483 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700484 sqlite3_prepare_v2(m_db, "UPDATE Contact SET is_introducer=? WHERE contact_namespace=?",
485 -1, &stmt, 0);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800486 sqlite3_bind_int(stmt, 1, (isIntroducer ? 1 : 0));
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700487 sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700488 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700489 sqlite3_finalize(stmt);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800490 return;
491}
492
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700493void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700494ContactStorage::updateAlias(const Name& identity, const string& alias)
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700495{
Yingdi Yu71c01872013-11-03 16:22:05 -0800496 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700497 sqlite3_prepare_v2(m_db, "UPDATE Contact SET contact_alias=? WHERE contact_namespace=?",
498 -1, &stmt, 0);
499 sqlite3_bind_string(stmt, 1, alias, SQLITE_TRANSIENT);
500 sqlite3_bind_string(stmt, 2, identity.toUri(), SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700501 sqlite3_step(stmt);
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700502 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800503 return;
Yingdi Yu2ac40fb2013-10-21 13:38:38 -0700504}
505
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700506bool
Yingdi Yu71c01872013-11-03 16:22:05 -0800507ContactStorage::doesContactExist(const Name& name)
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700508{
509 bool result = false;
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700510
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700511 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700512 sqlite3_prepare_v2(m_db, "SELECT count(*) FROM Contact WHERE contact_namespace=?", -1, &stmt, 0);
513 sqlite3_bind_string(stmt, 1, name.toUri(), SQLITE_TRANSIENT);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700514
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700515 int res = sqlite3_step(stmt);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700516
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700517 if (res == SQLITE_ROW) {
518 int countAll = sqlite3_column_int (stmt, 0);
519 if (countAll > 0)
520 result = true;
521 }
522
523 sqlite3_finalize(stmt);
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700524 return result;
525}
526
Yingdi Yu76dd8002013-12-24 11:16:32 +0800527void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700528ContactStorage::getAllContacts(vector<shared_ptr<Contact> >& contacts) const
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700529{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700530 vector<Name> contactNames;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800531
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700532 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700533 sqlite3_prepare_v2(m_db, "SELECT contact_namespace FROM Contact", -1, &stmt, 0);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700534
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700535 while (sqlite3_step(stmt) == SQLITE_ROW) {
536 string identity = sqlite3_column_string(stmt, 0);
537 contactNames.push_back(Name(identity));
538 }
539 sqlite3_finalize(stmt);
Yingdi Yu71c01872013-11-03 16:22:05 -0800540
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700541 for (vector<Name>::iterator it = contactNames.begin(); it != contactNames.end(); it++) {
542 shared_ptr<Contact> contact = getContact(*it);
543 if (static_cast<bool>(contact))
544 contacts.push_back(contact);
545 }
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700546}
Yingdi Yu3b318c12013-10-15 17:54:00 -0700547
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800548void
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700549ContactStorage::updateDnsData(const Block& data, const string& name,
550 const string& type, const string& dataName)
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700551{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800552 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700553 sqlite3_prepare_v2(m_db,
554 "INSERT OR REPLACE INTO DnsData (dns_name, dns_type, dns_value, data_name) \
555 VALUES (?, ?, ?, ?)",
556 -1, &stmt, 0);
557 sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
558 sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
559 sqlite3_bind_block(stmt, 3, data, SQLITE_TRANSIENT);
560 sqlite3_bind_string(stmt, 4, dataName, SQLITE_TRANSIENT);
Yingdi Yu42125862014-08-07 17:04:28 -0700561 sqlite3_step(stmt);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800562
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800563 sqlite3_finalize(stmt);
564}
565
566shared_ptr<Data>
567ContactStorage::getDnsData(const Name& dataName)
568{
569 shared_ptr<Data> data;
570
571 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700572 sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where data_name=?", -1, &stmt, 0);
573 sqlite3_bind_string(stmt, 1, dataName.toUri(), SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700574
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700575 if (sqlite3_step(stmt) == SQLITE_ROW) {
576 data = make_shared<Data>();
577 data->wireDecode(sqlite3_column_block(stmt, 0));
578 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800579 sqlite3_finalize(stmt);
580
581 return data;
582}
583
584shared_ptr<Data>
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700585ContactStorage::getDnsData(const string& name, const string& type)
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800586{
587 shared_ptr<Data> data;
588
589 sqlite3_stmt *stmt;
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700590 sqlite3_prepare_v2(m_db, "SELECT dns_value FROM DnsData where dns_name=? and dns_type=?",
591 -1, &stmt, 0);
592 sqlite3_bind_string(stmt, 1, name, SQLITE_TRANSIENT);
593 sqlite3_bind_string(stmt, 2, type, SQLITE_TRANSIENT);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700594
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700595 if (sqlite3_step(stmt) == SQLITE_ROW) {
596 data = make_shared<Data>();
597 data->wireDecode(sqlite3_column_block(stmt, 0));
598 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800599 sqlite3_finalize(stmt);
600
601 return data;
602}
603
Yingdi Yueb692ac2015-02-10 18:46:18 -0800604} // namespace chronochat