diff options
Diffstat (limited to 'Swiften/History/SQLiteHistoryManager.cpp')
-rw-r--r-- | Swiften/History/SQLiteHistoryManager.cpp | 374 |
1 files changed, 0 insertions, 374 deletions
diff --git a/Swiften/History/SQLiteHistoryManager.cpp b/Swiften/History/SQLiteHistoryManager.cpp deleted file mode 100644 index e385b1e..0000000 --- a/Swiften/History/SQLiteHistoryManager.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <iostream> -#include <boost/lexical_cast.hpp> - -#include <sqlite3.h> -#include <Swiften/History/SQLiteHistoryManager.h> -#include <boost/date_time/gregorian/gregorian.hpp> - -inline std::string getEscapedString(const std::string& s) { - std::string result(s); - - size_t pos = result.find('\''); - while (pos != std::string::npos) { - result.insert(pos, "'"); - pos = result.find('\'', pos + 2); - } - return result; -} - -namespace Swift { - -SQLiteHistoryManager::SQLiteHistoryManager(const std::string& file) : db_(0) { - sqlite3_open(file.c_str(), &db_); - if (!db_) { - std::cerr << "Error opening database " << file << std::endl; // FIXME - } - - char* errorMessage; - int result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS messages('message' STRING, 'fromBare' INTEGER, 'fromResource' STRING, 'toBare' INTEGER, 'toResource' STRING, 'type' INTEGER, 'time' INTEGER, 'offset' INTEGER)", 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } - - result = sqlite3_exec(db_, "CREATE TABLE IF NOT EXISTS jids('id' INTEGER PRIMARY KEY ASC AUTOINCREMENT, 'jid' STRING UNIQUE NOT NULL)", 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } -} - -SQLiteHistoryManager::~SQLiteHistoryManager() { - sqlite3_close(db_); -} - -void SQLiteHistoryManager::addMessage(const HistoryMessage& message) { - int secondsSinceEpoch = (message.getTime() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); - - std::string statement = std::string("INSERT INTO messages('message', 'fromBare', 'fromResource', 'toBare', 'toResource', 'type', 'time', 'offset') VALUES(") + - "'" + getEscapedString(message.getMessage()) + "', " + - boost::lexical_cast<std::string>(getIDForJID(message.getFromJID().toBare())) + ", '" + - getEscapedString(message.getFromJID().getResource()) + "', " + - boost::lexical_cast<std::string>(getIDForJID(message.getToJID().toBare())) + ", '" + - getEscapedString(message.getToJID().getResource()) + "', " + - boost::lexical_cast<std::string>(message.getType()) + ", " + - boost::lexical_cast<std::string>(secondsSinceEpoch) + ", " + - boost::lexical_cast<std::string>(message.getOffset()) + ")"; - char* errorMessage; - int result = sqlite3_exec(db_, statement.c_str(), 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } -} - -std::vector<HistoryMessage> SQLiteHistoryManager::getMessagesFromDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const { - sqlite3_stmt* selectStatement; - - boost::optional<int> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<int> contactID = getIDFromJID(contactJID.toBare()); - - if (!selfID || !contactID) { - // JIDs missing from the database - return std::vector<HistoryMessage>(); - } - - std::string selectQuery = "SELECT * FROM messages WHERE (type=" + boost::lexical_cast<std::string>(type); - if (contactJID.isBare()) { - // match only bare jid - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" + - boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND toBare=" + boost::lexical_cast<std::string>(*selfID) + ")))"; - } - else { - // match resource too - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND (toBare=" + - boost::lexical_cast<std::string>(*contactID) +" AND toResource='" + - getEscapedString(contactJID.getResource()) + "')) OR ((fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND fromResource='" + - getEscapedString(contactJID.getResource()) + "') AND toBare=" + - boost::lexical_cast<std::string>(*selfID) + ")))"; - } - - if (!date.is_not_a_date()) { - int lowerBound = (boost::posix_time::ptime(date) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds(); - int upperBound = lowerBound + 86400; - - selectQuery += " AND (time>=" + boost::lexical_cast<std::string>(lowerBound) + - " AND time<" + boost::lexical_cast<std::string>(upperBound) + ")"; - } - - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - r = sqlite3_step(selectStatement); - - // Retrieve result - std::vector<HistoryMessage> result; - while (r == SQLITE_ROW) { - std::string message(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 0))); - - // fromJID - boost::optional<JID> fromJID(getJIDFromID(sqlite3_column_int(selectStatement, 1))); - std::string fromResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 2))); - if (fromJID) { - fromJID = boost::optional<JID>(JID(fromJID->getNode(), fromJID->getDomain(), fromResource)); - } - - // toJID - boost::optional<JID> toJID(getJIDFromID(sqlite3_column_int(selectStatement, 3))); - std::string toResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 4))); - if (toJID) { - toJID = boost::optional<JID>(JID(toJID->getNode(), toJID->getDomain(), toResource)); - } - - // message type - HistoryMessage::Type type = static_cast<HistoryMessage::Type>(sqlite3_column_int(selectStatement, 5)); - - // timestamp - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 6)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - - // offset from utc - int offset = sqlite3_column_int(selectStatement, 7); - - result.push_back(HistoryMessage(message, (fromJID ? *fromJID : JID()), (toJID ? *toJID : JID()), type, time, offset)); - r = sqlite3_step(selectStatement); - } - if (r != SQLITE_DONE) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - sqlite3_finalize(selectStatement); - - return result; -} - -int SQLiteHistoryManager::getIDForJID(const JID& jid) { - boost::optional<int> id = getIDFromJID(jid); - if (id) { - return *id; - } - else { - return addJID(jid); - } -} - -int SQLiteHistoryManager::addJID(const JID& jid) { - std::string statement = std::string("INSERT INTO jids('jid') VALUES('") + getEscapedString(jid.toString()) + "')"; - char* errorMessage; - int result = sqlite3_exec(db_, statement.c_str(), 0, 0, &errorMessage); - if (result != SQLITE_OK) { - std::cerr << "SQL Error: " << errorMessage << std::endl; - sqlite3_free(errorMessage); - } - return sqlite3_last_insert_rowid(db_); -} - -boost::optional<JID> SQLiteHistoryManager::getJIDFromID(int id) const { - boost::optional<JID> result; - sqlite3_stmt* selectStatement; - std::string selectQuery("SELECT jid FROM jids WHERE id=" + boost::lexical_cast<std::string>(id)); - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - result = boost::optional<JID>(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 0))); - } - sqlite3_finalize(selectStatement); - return result; -} - -boost::optional<int> SQLiteHistoryManager::getIDFromJID(const JID& jid) const { - boost::optional<int> result; - sqlite3_stmt* selectStatement; - std::string selectQuery("SELECT id FROM jids WHERE jid='" + jid.toString() + "'"); - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - result = boost::optional<int>(sqlite3_column_int(selectStatement, 0)); - } - sqlite3_finalize(selectStatement); - return result; -} - -ContactsMap SQLiteHistoryManager::getContacts(const JID& selfJID, HistoryMessage::Type type, const std::string& keyword) const { - ContactsMap result; - sqlite3_stmt* selectStatement; - - // get id - boost::optional<int> id = getIDFromJID(selfJID); - if (!id) { - return result; - } - - // get contacts - std::string query = "SELECT DISTINCT messages.'fromBare', messages.'fromResource', messages.'toBare', messages.'toResource', messages.'time' " - "FROM messages WHERE (type=" - + boost::lexical_cast<std::string>(type) + " AND (toBare=" - + boost::lexical_cast<std::string>(*id) + " OR fromBare=" + boost::lexical_cast<std::string>(*id) + "))"; - - // match keyword - if (getEscapedString(keyword).length()) { - query += " AND message LIKE '%" + getEscapedString(keyword) + "%'"; - } - - int r = sqlite3_prepare(db_, query.c_str(), query.size(), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - - r = sqlite3_step(selectStatement); - while (r == SQLITE_ROW) { - int fromBareID = sqlite3_column_int(selectStatement, 0); - std::string fromResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 1))); - int toBareID = sqlite3_column_int(selectStatement, 2); - std::string toResource(reinterpret_cast<const char*>(sqlite3_column_text(selectStatement, 3))); - std::string resource; - - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 4)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - - boost::optional<JID> contactJID; - - if (fromBareID == *id) { - contactJID = getJIDFromID(toBareID); - resource = toResource; - } - else { - contactJID = getJIDFromID(fromBareID); - resource = fromResource; - } - - // check if it is a MUC contact (from a private conversation) - if (type == HistoryMessage::PrivateMessage) { - contactJID = boost::optional<JID>(JID(contactJID->getNode(), contactJID->getDomain(), resource)); - } - - if (contactJID) { - result[*contactJID].insert(time.date()); - } - - r = sqlite3_step(selectStatement); - } - - if (r != SQLITE_DONE) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - sqlite3_finalize(selectStatement); - - return result; -} - -boost::gregorian::date SQLiteHistoryManager::getNextDateWithLogs(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date, bool reverseOrder) const { - sqlite3_stmt* selectStatement; - boost::optional<int> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<int> contactID = getIDFromJID(contactJID.toBare()); - - if (!selfID || !contactID) { - // JIDs missing from the database - return boost::gregorian::date(boost::gregorian::not_a_date_time); - } - - std::string selectQuery = "SELECT time FROM messages WHERE (type=" + boost::lexical_cast<std::string>(type); - if (contactJID.isBare()) { - // match only bare jid - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND toBare=" + - boost::lexical_cast<std::string>(*contactID) + ") OR (fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND toBare=" + boost::lexical_cast<std::string>(*selfID) + ")))"; - } - else { - // match resource too - selectQuery += " AND ((fromBare=" + boost::lexical_cast<std::string>(*selfID) + " AND (toBare=" + - boost::lexical_cast<std::string>(*contactID) +" AND toResource='" + - getEscapedString(contactJID.getResource()) + "')) OR ((fromBare=" + - boost::lexical_cast<std::string>(*contactID) + " AND fromResource='" + - getEscapedString(contactJID.getResource()) + "') AND toBare=" + - boost::lexical_cast<std::string>(*selfID) + ")))"; - } - - int timeStamp = (boost::posix_time::ptime(date) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_seconds() + (reverseOrder ? 0 : 86400); - - selectQuery += " AND time" + (reverseOrder ? std::string("<") : std::string(">")) + boost::lexical_cast<std::string>(timeStamp); - selectQuery += " ORDER BY time " + (reverseOrder ? std::string("DESC") : std::string("ASC")) + " LIMIT 1"; - - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 0)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - std::cout << "next day is: " << time.date() << "\n"; - return time.date(); - } - - return boost::gregorian::date(boost::gregorian::not_a_date_time); -} - -std::vector<HistoryMessage> SQLiteHistoryManager::getMessagesFromNextDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const { - boost::gregorian::date nextDate = getNextDateWithLogs(selfJID, contactJID, type, date, false); - - if (nextDate.is_not_a_date()) { - return std::vector<HistoryMessage>(); - } - - return getMessagesFromDate(selfJID, contactJID, type, nextDate); -} - -std::vector<HistoryMessage> SQLiteHistoryManager::getMessagesFromPreviousDate(const JID& selfJID, const JID& contactJID, HistoryMessage::Type type, const boost::gregorian::date& date) const { - boost::gregorian::date previousDate = getNextDateWithLogs(selfJID, contactJID, type, date, true); - - if (previousDate.is_not_a_date()) { - return std::vector<HistoryMessage>(); - } - - return getMessagesFromDate(selfJID, contactJID, type, previousDate); -} - -boost::posix_time::ptime SQLiteHistoryManager::getLastTimeStampFromMUC(const JID& selfJID, const JID& mucJID) const { - boost::optional<int> selfID = getIDFromJID(selfJID.toBare()); - boost::optional<int> mucID = getIDFromJID(mucJID.toBare()); - - if (!selfID || !mucID) { - // JIDs missing from the database - return boost::posix_time::ptime(boost::posix_time::not_a_date_time); - } - - - sqlite3_stmt* selectStatement; - std::string selectQuery = "SELECT messages.'time', messages.'offset' from messages WHERE type=1 AND (toBare=" + - boost::lexical_cast<std::string>(*selfID) + " AND fromBare=" + - boost::lexical_cast<std::string>(*mucID) + ") ORDER BY time DESC LIMIT 1"; - - int r = sqlite3_prepare(db_, selectQuery.c_str(), selectQuery.size(), &selectStatement, NULL); - if (r != SQLITE_OK) { - std::cout << "Error: " << sqlite3_errmsg(db_) << std::endl; - } - - r = sqlite3_step(selectStatement); - if (r == SQLITE_ROW) { - int secondsSinceEpoch(sqlite3_column_int(selectStatement, 0)); - boost::posix_time::ptime time(boost::gregorian::date(1970, 1, 1), boost::posix_time::seconds(secondsSinceEpoch)); - int offset = sqlite3_column_int(selectStatement, 1); - - return time - boost::posix_time::hours(offset); - } - - return boost::posix_time::ptime(boost::posix_time::not_a_date_time); -} - -} |