mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-07 05:53:06 +00:00
feat(MainDb): legacy friends import
This commit is contained in:
parent
588bea60b9
commit
335f19b20b
6 changed files with 332 additions and 222 deletions
|
|
@ -41,6 +41,8 @@
|
|||
#endif
|
||||
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
#include "core/core-p.h"
|
||||
#include "db/main-db.h"
|
||||
|
||||
// TODO: From coreapi. Remove me later.
|
||||
#include "private.h"
|
||||
|
|
@ -529,11 +531,11 @@ void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
|
|||
}
|
||||
|
||||
static void close_presence_notification(SalPresenceOp *op) {
|
||||
op->notify_presence_close();
|
||||
op->notify_presence_close();
|
||||
}
|
||||
|
||||
static void release_sal_op(SalOp *op) {
|
||||
op->release();
|
||||
op->release();
|
||||
}
|
||||
|
||||
static void linphone_friend_close_incoming_subscriptions(LinphoneFriend *lf) {
|
||||
|
|
@ -1722,6 +1724,10 @@ bctbx_list_t* linphone_core_fetch_friends_lists_from_db(LinphoneCore *lc) {
|
|||
#endif
|
||||
|
||||
void linphone_core_set_friends_database_path(LinphoneCore *lc, const char *path) {
|
||||
if (!linphone_core_conference_server_enabled(lc))
|
||||
L_GET_PRIVATE(lc->cppPtr)->mainDb->import(LinphonePrivate::MainDb::Sqlite3, path);
|
||||
|
||||
// TODO: Remove me later.
|
||||
if (lc->friends_db_file){
|
||||
ms_free(lc->friends_db_file);
|
||||
lc->friends_db_file = NULL;
|
||||
|
|
@ -1729,8 +1735,6 @@ void linphone_core_set_friends_database_path(LinphoneCore *lc, const char *path)
|
|||
if (path) {
|
||||
lc->friends_db_file = ms_strdup(path);
|
||||
linphone_core_friends_storage_init(lc);
|
||||
|
||||
linphone_core_migrate_friends_from_rc_to_db(lc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1738,69 +1742,6 @@ const char* linphone_core_get_friends_database_path(LinphoneCore *lc) {
|
|||
return lc->friends_db_file;
|
||||
}
|
||||
|
||||
void linphone_core_migrate_friends_from_rc_to_db(LinphoneCore *lc) {
|
||||
LpConfig *lpc = NULL;
|
||||
LinphoneFriend *lf = NULL;
|
||||
LinphoneFriendList *lfl = linphone_core_get_default_friend_list(lc);
|
||||
int i;
|
||||
#ifndef SQLITE_STORAGE_ENABLED
|
||||
ms_warning("linphone has been compiled without sqlite, can't migrate friends");
|
||||
return;
|
||||
#endif
|
||||
if (!lc) {
|
||||
return;
|
||||
}
|
||||
|
||||
lpc = linphone_core_get_config(lc);
|
||||
if (!lpc) {
|
||||
ms_warning("this core has been started without a rc file, nothing to migrate");
|
||||
return;
|
||||
}
|
||||
if (lp_config_get_int(lpc, "misc", "friends_migration_done", 0) == 1) {
|
||||
ms_warning("the friends migration has already been done, skipping...");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bctbx_list_size(linphone_friend_list_get_friends(lfl)) > 0 && lfl->storage_id == 0) {
|
||||
linphone_core_remove_friend_list(lc, lfl);
|
||||
lfl = linphone_core_create_friend_list(lc);
|
||||
linphone_core_add_friend_list(lc, lfl);
|
||||
linphone_friend_list_unref(lfl);
|
||||
}
|
||||
|
||||
for (i = 0; (lf = linphone_friend_new_from_config_file(lc, i)) != NULL; i++) {
|
||||
char friend_section[32];
|
||||
|
||||
const LinphoneAddress *addr = linphone_friend_get_address(lf);
|
||||
if (addr) {
|
||||
char *address = NULL;
|
||||
const char *displayName = linphone_address_get_display_name(addr);
|
||||
if (!displayName) displayName = linphone_address_get_username(addr);
|
||||
|
||||
address = linphone_address_as_string(addr);
|
||||
if (linphone_core_vcard_supported()) {
|
||||
if (!linphone_friend_create_vcard(lf, displayName)) {
|
||||
ms_warning("Couldn't create vCard for friend %s", address);
|
||||
} else {
|
||||
linphone_vcard_add_sip_address(linphone_friend_get_vcard(lf), address);
|
||||
linphone_address_unref(lf->uri);
|
||||
lf->uri = NULL;
|
||||
}
|
||||
}
|
||||
ms_free(address);
|
||||
|
||||
linphone_friend_list_add_friend(lfl, lf);
|
||||
linphone_friend_unref(lf);
|
||||
|
||||
snprintf(friend_section, sizeof(friend_section), "friend_%i", i);
|
||||
lp_config_clean_section(lpc, friend_section);
|
||||
}
|
||||
}
|
||||
|
||||
ms_debug("friends migration successful: %i friends migrated", i);
|
||||
lp_config_set_int(lpc, "misc", "friends_migration_done", 1);
|
||||
}
|
||||
|
||||
LinphoneSubscriptionState linphone_friend_get_subscription_state(const LinphoneFriend *lf) {
|
||||
return lf->out_sub_state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6692,11 +6692,8 @@ int linphone_core_get_video_dscp(const LinphoneCore *lc){
|
|||
}
|
||||
|
||||
void linphone_core_set_chat_database_path (LinphoneCore *lc, const char *path) {
|
||||
if (
|
||||
linphone_core_conference_server_enabled(lc) ||
|
||||
!L_GET_PRIVATE(lc->cppPtr)->mainDb->import(LinphonePrivate::MainDb::Sqlite3, path)
|
||||
)
|
||||
lError() << "Do not use `linphone_core_set_chat_database_path`. Not necessary.";
|
||||
if (!linphone_core_conference_server_enabled(lc))
|
||||
L_GET_PRIVATE(lc->cppPtr)->mainDb->import(LinphonePrivate::MainDb::Sqlite3, path);
|
||||
}
|
||||
|
||||
const char *linphone_core_get_chat_database_path (const LinphoneCore *) {
|
||||
|
|
|
|||
|
|
@ -5287,13 +5287,6 @@ LINPHONE_PUBLIC void linphone_core_set_friends_database_path(LinphoneCore *lc, c
|
|||
**/
|
||||
LINPHONE_PUBLIC const char* linphone_core_get_friends_database_path(LinphoneCore *lc);
|
||||
|
||||
/**
|
||||
* Migrates the friends from the linphonerc to the database if not done yet
|
||||
* @ingroup initializing
|
||||
* @param lc the linphone core
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_core_migrate_friends_from_rc_to_db(LinphoneCore *lc);
|
||||
|
||||
/**
|
||||
* Create a new empty LinphoneFriendList object.
|
||||
* @param[in] lc LinphoneCore object.
|
||||
|
|
|
|||
|
|
@ -154,6 +154,13 @@ private:
|
|||
unsigned int getModuleVersion (const std::string &name);
|
||||
void updateModuleVersion (const std::string &name, unsigned int version);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Import.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void importLegacyFriends (DbSession &inDbSession);
|
||||
void importLegacyHistory (DbSession &inDbSession);
|
||||
|
||||
L_DECLARE_PUBLIC(MainDb);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@
|
|||
#include "main-db-p.h"
|
||||
|
||||
#define DB_MODULE_VERSION_EVENTS L_VERSION(1, 0, 0)
|
||||
#define DB_MODULE_VERSION_FRIENDS L_VERSION(1, 0, 0)
|
||||
#define DB_MODULE_VERSION_LEGACY_FRIENDS_IMPORT L_VERSION(1, 0, 0)
|
||||
#define DB_MODULE_VERSION_LEGACY_HISTORY_IMPORT L_VERSION(1, 0, 0)
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -1051,6 +1053,265 @@ void MainDbPrivate::updateModuleVersion (const string &name, unsigned int versio
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define CHECK_LEGACY_TABLE_EXISTS(SESSION, NAME) \
|
||||
do { \
|
||||
SESSION << "SELECT name FROM sqlite_master WHERE type='table' AND name='" NAME "'"; \
|
||||
return SESSION.got_data() > 0; \
|
||||
} while (false);
|
||||
|
||||
static inline bool checkLegacyFriendsTableExists (soci::session &session) {
|
||||
CHECK_LEGACY_TABLE_EXISTS(session, "friends");
|
||||
}
|
||||
|
||||
static inline bool checkLegacyHistoryTableExists (soci::session &session) {
|
||||
CHECK_LEGACY_TABLE_EXISTS(session, "history");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T getValueFromRow (const soci::row &row, int index, bool &isNull) {
|
||||
isNull = false;
|
||||
|
||||
try {
|
||||
return row.get<T>(static_cast<size_t>(index));
|
||||
} catch (const exception &) {
|
||||
isNull = true;
|
||||
}
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define LEGACY_FRIEND_LIST_COL_ID 0
|
||||
#define LEGACY_FRIEND_LIST_COL_NAME 1
|
||||
#define LEGACY_FRIEND_LIST_COL_RLS_URI 2
|
||||
#define LEGACY_FRIEND_LIST_COL_SYNC_URI 3
|
||||
#define LEGACY_FRIEND_LIST_COL_REVISION 4
|
||||
|
||||
#define LEGACY_FRIEND_COL_FRIEND_LIST_ID 1
|
||||
#define LEGACY_FRIEND_COL_SIP_ADDRESS 2
|
||||
#define LEGACY_FRIEND_COL_SUBSCRIBE_POLICY 3
|
||||
#define LEGACY_FRIEND_COL_SEND_SUBSCRIBE 4
|
||||
#define LEGACY_FRIEND_COL_REF_KEY 5
|
||||
#define LEGACY_FRIEND_COL_V_CARD 6
|
||||
#define LEGACY_FRIEND_COL_V_CARD_ETAG 7
|
||||
#define LEGACY_FRIEND_COL_V_CARD_SYNC_URI 8
|
||||
#define LEGACY_FRIEND_COL_PRESENCE_RECEIVED 9
|
||||
|
||||
void MainDbPrivate::importLegacyFriends (DbSession &inDbSession) {
|
||||
L_Q();
|
||||
|
||||
soci::session *inSession = inDbSession.getBackendSession<soci::session>();
|
||||
soci::transaction tr(*dbSession.getBackendSession<soci::session>());
|
||||
|
||||
if (getModuleVersion("legacy-friends-import") >= L_VERSION(1, 0, 0))
|
||||
return;
|
||||
updateModuleVersion("legacy-friends-import", DB_MODULE_VERSION_LEGACY_FRIENDS_IMPORT);
|
||||
|
||||
if (!checkLegacyFriendsTableExists(*inSession))
|
||||
return;
|
||||
|
||||
unordered_map<int, long long> resolvedListsIds;
|
||||
soci::session *session = dbSession.getBackendSession<soci::session>();
|
||||
|
||||
soci::rowset<soci::row> friendsLists = (inSession->prepare << "SELECT * FROM friends_lists");
|
||||
try {
|
||||
set<string> names;
|
||||
for (const auto &friendList : friendsLists) {
|
||||
const string &name = friendList.get<string>(LEGACY_FRIEND_LIST_COL_NAME, "");
|
||||
const string &rlsUri = friendList.get<string>(LEGACY_FRIEND_LIST_COL_RLS_URI, "");
|
||||
const string &syncUri = friendList.get<string>(LEGACY_FRIEND_LIST_COL_SYNC_URI, "");
|
||||
const int &revision = friendList.get<int>(LEGACY_FRIEND_LIST_COL_REVISION, 0);
|
||||
|
||||
string uniqueName = name;
|
||||
for (int id = 0; names.find(uniqueName) != names.end(); uniqueName = name + "-" + Utils::toString(id++));
|
||||
names.insert(uniqueName);
|
||||
|
||||
*session << "INSERT INTO friends_list (name, rls_uri, sync_uri, revision) VALUES ("
|
||||
" :name, :rlsUri, :syncUri, :revision"
|
||||
")", soci::use(uniqueName), soci::use(rlsUri), soci::use(syncUri), soci::use(revision);
|
||||
resolvedListsIds[friendList.get<int>(LEGACY_FRIEND_LIST_COL_ID)] = q->getLastInsertId();
|
||||
}
|
||||
} catch (const exception &e) {
|
||||
lWarning() << "Failed to import legacy friends list: " << e.what() << ".";
|
||||
return;
|
||||
}
|
||||
|
||||
soci::rowset<soci::row> friends = (inSession->prepare << "SELECT * FROM friends");
|
||||
try {
|
||||
for (const auto &friendInfo : friends) {
|
||||
long long friendsListId;
|
||||
{
|
||||
auto it = resolvedListsIds.find(friendInfo.get<int>(LEGACY_FRIEND_COL_FRIEND_LIST_ID, -1));
|
||||
if (it == resolvedListsIds.end())
|
||||
continue;
|
||||
friendsListId = it->second;
|
||||
}
|
||||
|
||||
const long long &sipAddressId = insertSipAddress(friendInfo.get<string>(LEGACY_FRIEND_COL_SIP_ADDRESS, ""));
|
||||
const int &subscribePolicy = friendInfo.get<int>(LEGACY_FRIEND_COL_SUBSCRIBE_POLICY, LinphoneSPAccept);
|
||||
const int &sendSubscribe = friendInfo.get<int>(LEGACY_FRIEND_COL_SEND_SUBSCRIBE, 1);
|
||||
const string &vCard = friendInfo.get<string>(LEGACY_FRIEND_COL_V_CARD, "");
|
||||
const string &vCardEtag = friendInfo.get<string>(LEGACY_FRIEND_COL_V_CARD_ETAG, "");
|
||||
const string &vCardSyncUri = friendInfo.get<string>(LEGACY_FRIEND_COL_V_CARD_SYNC_URI, "");
|
||||
const int &presenceReveived = friendInfo.get<int>(LEGACY_FRIEND_COL_PRESENCE_RECEIVED, 0);
|
||||
|
||||
*session << "INSERT INTO friend ("
|
||||
" sip_address_id, friends_list_id, subscribe_policy, send_subscribe,"
|
||||
" presence_received, v_card, v_card_etag, v_card_sync_uri"
|
||||
") VALUES ("
|
||||
" :sipAddressId, :friendsListId, :subscribePolicy, :sendSubscribe,"
|
||||
" :presenceReceived, :vCard, :vCardEtag, :vCardSyncUri"
|
||||
")", soci::use(sipAddressId), soci::use(friendsListId), soci::use(subscribePolicy), soci::use(sendSubscribe),
|
||||
soci::use(presenceReveived), soci::use(vCard), soci::use(vCardEtag), soci::use(vCardSyncUri);
|
||||
|
||||
bool isNull;
|
||||
const string &data = getValueFromRow<string>(friendInfo, LEGACY_FRIEND_COL_REF_KEY, isNull);
|
||||
if (!isNull)
|
||||
*session << "INSERT INTO friend_app_data (friend_id, name, data) VALUES"
|
||||
" (:friendId, 'legacy', :data)",
|
||||
soci::use(q->getLastInsertId()), soci::use(data);
|
||||
}
|
||||
tr.commit();
|
||||
} catch (const exception &e) {
|
||||
lWarning() << "Failed to import legacy friends: " << e.what() << ".";
|
||||
return;
|
||||
}
|
||||
|
||||
lInfo() << "Successful import of legacy friends.";
|
||||
}
|
||||
|
||||
#define LEGACY_MESSAGE_COL_LOCAL_ADDRESS 1
|
||||
#define LEGACY_MESSAGE_COL_REMOTE_ADDRESS 2
|
||||
#define LEGACY_MESSAGE_COL_DIRECTION 3
|
||||
#define LEGACY_MESSAGE_COL_TEXT 4
|
||||
#define LEGACY_MESSAGE_COL_STATE 7
|
||||
#define LEGACY_MESSAGE_COL_URL 8
|
||||
#define LEGACY_MESSAGE_COL_DATE 9
|
||||
#define LEGACY_MESSAGE_COL_APP_DATA 10
|
||||
#define LEGACY_MESSAGE_COL_CONTENT_ID 11
|
||||
#define LEGACY_MESSAGE_COL_IMDN_MESSAGE_ID 12
|
||||
#define LEGACY_MESSAGE_COL_CONTENT_TYPE 13
|
||||
#define LEGACY_MESSAGE_COL_IS_SECURED 14
|
||||
|
||||
void MainDbPrivate::importLegacyHistory (DbSession &inDbSession) {
|
||||
L_Q();
|
||||
|
||||
soci::session *inSession = inDbSession.getBackendSession<soci::session>();
|
||||
soci::transaction tr(*dbSession.getBackendSession<soci::session>());
|
||||
|
||||
unsigned int version = getModuleVersion("legacy-history-import");
|
||||
if (version >= L_VERSION(1, 0, 0))
|
||||
return;
|
||||
updateModuleVersion("legacy-history-import", DB_MODULE_VERSION_LEGACY_HISTORY_IMPORT);
|
||||
|
||||
if (!checkLegacyHistoryTableExists(*inSession))
|
||||
return;
|
||||
|
||||
soci::rowset<soci::row> messages = (inSession->prepare << "SELECT * FROM history");
|
||||
try {
|
||||
for (const auto &message : messages) {
|
||||
const int direction = message.get<int>(LEGACY_MESSAGE_COL_DIRECTION);
|
||||
if (direction != 0 && direction != 1) {
|
||||
lWarning() << "Unable to import legacy message with invalid direction.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const int &state = message.get<int>(
|
||||
LEGACY_MESSAGE_COL_STATE, static_cast<int>(ChatMessage::State::Displayed)
|
||||
);
|
||||
if (state < 0 || state > static_cast<int>(ChatMessage::State::Displayed)) {
|
||||
lWarning() << "Unable to import legacy message with invalid state.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const tm &creationTime = Utils::getTimeTAsTm(message.get<int>(LEGACY_MESSAGE_COL_DATE, 0));
|
||||
|
||||
bool isNull;
|
||||
getValueFromRow<string>(message, LEGACY_MESSAGE_COL_URL, isNull);
|
||||
|
||||
const int &contentId = message.get<int>(LEGACY_MESSAGE_COL_CONTENT_ID, -1);
|
||||
ContentType contentType(message.get<string>(LEGACY_MESSAGE_COL_CONTENT_TYPE, ""));
|
||||
if (!contentType.isValid())
|
||||
contentType = contentId != -1
|
||||
? ContentType::FileTransfer
|
||||
: (isNull ? ContentType::PlainText : ContentType::ExternalBody);
|
||||
if (contentType == ContentType::ExternalBody) {
|
||||
lInfo() << "Import of external body content is skipped.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const string &text = getValueFromRow<string>(message, LEGACY_MESSAGE_COL_TEXT, isNull);
|
||||
|
||||
Content content;
|
||||
content.setContentType(contentType);
|
||||
if (contentType == ContentType::PlainText) {
|
||||
if (isNull) {
|
||||
lWarning() << "Unable to import legacy message with no text.";
|
||||
continue;
|
||||
}
|
||||
content.setBody(text);
|
||||
} else {
|
||||
if (contentType != ContentType::FileTransfer) {
|
||||
lWarning() << "Unable to import unsupported legacy content.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const string appData = getValueFromRow<string>(message, LEGACY_MESSAGE_COL_APP_DATA, isNull);
|
||||
if (isNull) {
|
||||
lWarning() << "Unable to import legacy file message without app data.";
|
||||
continue;
|
||||
}
|
||||
|
||||
content.setAppData("legacy", appData);
|
||||
}
|
||||
|
||||
soci::session *session = dbSession.getBackendSession<soci::session>();
|
||||
const int &eventType = static_cast<int>(EventLog::Type::ConferenceChatMessage);
|
||||
*session << "INSERT INTO event (type, creation_time) VALUES (:type, :creationTime)",
|
||||
soci::use(eventType), soci::use(creationTime);
|
||||
|
||||
const long long &eventId = q->getLastInsertId();
|
||||
const long long &localSipAddressId = insertSipAddress(message.get<string>(LEGACY_MESSAGE_COL_LOCAL_ADDRESS));
|
||||
const long long &remoteSipAddressId = insertSipAddress(message.get<string>(LEGACY_MESSAGE_COL_REMOTE_ADDRESS));
|
||||
const long long &chatRoomId = insertOrUpdateImportedBasicChatRoom(
|
||||
remoteSipAddressId,
|
||||
localSipAddressId,
|
||||
creationTime
|
||||
);
|
||||
const int &isSecured = message.get<int>(LEGACY_MESSAGE_COL_IS_SECURED, 0);
|
||||
|
||||
*session << "INSERT INTO conference_event (event_id, chat_room_id)"
|
||||
" VALUES (:eventId, :chatRoomId)", soci::use(eventId), soci::use(chatRoomId);
|
||||
|
||||
*session << "INSERT INTO conference_chat_message_event ("
|
||||
" event_id, from_sip_address_id, to_sip_address_id,"
|
||||
" time, state, direction, imdn_message_id, is_secured"
|
||||
") VALUES ("
|
||||
" :eventId, :localSipAddressId, :remoteSipAddressId,"
|
||||
" :creationTime, :state, :direction, '', :isSecured"
|
||||
")", soci::use(eventId), soci::use(localSipAddressId), soci::use(remoteSipAddressId),
|
||||
soci::use(creationTime), soci::use(state), soci::use(direction),
|
||||
soci::use(isSecured);
|
||||
|
||||
insertContent(eventId, content);
|
||||
insertChatRoomParticipant(chatRoomId, remoteSipAddressId, false);
|
||||
|
||||
if (state != static_cast<int>(ChatMessage::State::Displayed))
|
||||
insertChatMessageParticipant(eventId, remoteSipAddressId, state);
|
||||
}
|
||||
|
||||
tr.commit();
|
||||
} catch (const exception &e) {
|
||||
lInfo() << "Failed to import legacy messages: " << e.what() << ".";
|
||||
return;
|
||||
}
|
||||
|
||||
lInfo() << "Successful import of legacy messages.";
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void MainDb::init () {
|
||||
L_D();
|
||||
|
||||
|
|
@ -1335,6 +1596,52 @@ void MainDb::init () {
|
|||
*session << participantMessageDeleter;
|
||||
#endif
|
||||
|
||||
*session <<
|
||||
"CREATE TABLE IF NOT EXISTS friends_list ("
|
||||
" id" + primaryKeyStr("INT UNSIGNED") + ","
|
||||
|
||||
" name VARCHAR(255) UNIQUE,"
|
||||
" rls_uri VARCHAR(2047),"
|
||||
" sync_uri VARCHAR(2047),"
|
||||
" revision INT UNSIGNED NOT NULL"
|
||||
") " + charset;
|
||||
|
||||
*session <<
|
||||
"CREATE TABLE IF NOT EXISTS friend ("
|
||||
" id" + primaryKeyStr("INT UNSIGNED") + ","
|
||||
|
||||
" sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL,"
|
||||
" friends_list_id" + primaryKeyRefStr("INT UNSIGNED") + " NOT NULL,"
|
||||
|
||||
" subscribe_policy TINYINT UNSIGNED NOT NULL,"
|
||||
" send_subscribe BOOLEAN NOT NULL,"
|
||||
" presence_received BOOLEAN NOT NULL,"
|
||||
|
||||
" v_card MEDIUMTEXT,"
|
||||
" v_card_etag VARCHAR(255),"
|
||||
" v_card_sync_uri VARCHAR(2047),"
|
||||
|
||||
" FOREIGN KEY (sip_address_id)"
|
||||
" REFERENCES sip_address(id)"
|
||||
" ON DELETE CASCADE,"
|
||||
" FOREIGN KEY (friends_list_id)"
|
||||
" REFERENCES friends_list(id)"
|
||||
" ON DELETE CASCADE"
|
||||
") " + charset;
|
||||
|
||||
*session <<
|
||||
"CREATE TABLE IF NOT EXISTS friend_app_data ("
|
||||
" friend_id" + primaryKeyRefStr("INT UNSIGNED") + ","
|
||||
|
||||
" name VARCHAR(255),"
|
||||
" data BLOB NOT NULL,"
|
||||
|
||||
" PRIMARY KEY (friend_id, name),"
|
||||
" FOREIGN KEY (friend_id)"
|
||||
" REFERENCES friend(id)"
|
||||
" ON DELETE CASCADE"
|
||||
") " + charset;
|
||||
|
||||
*session <<
|
||||
"CREATE TABLE IF NOT EXISTS db_module_version ("
|
||||
" name" + varcharPrimaryKeyStr(255) + ","
|
||||
|
|
@ -1342,6 +1649,7 @@ void MainDb::init () {
|
|||
") " + charset;
|
||||
|
||||
d->updateModuleVersion("events", DB_MODULE_VERSION_EVENTS);
|
||||
d->updateModuleVersion("friends", DB_MODULE_VERSION_FRIENDS);
|
||||
}
|
||||
|
||||
bool MainDb::addEvent (const shared_ptr<EventLog> &eventLog) {
|
||||
|
|
@ -2320,37 +2628,6 @@ void MainDb::enableChatRoomMigration (const ChatRoomId &chatRoomId, bool enable)
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define LEGACY_MESSAGE_COL_LOCAL_ADDRESS 1
|
||||
#define LEGACY_MESSAGE_COL_REMOTE_ADDRESS 2
|
||||
#define LEGACY_MESSAGE_COL_DIRECTION 3
|
||||
#define LEGACY_MESSAGE_COL_TEXT 4
|
||||
#define LEGACY_MESSAGE_COL_STATE 7
|
||||
#define LEGACY_MESSAGE_COL_URL 8
|
||||
#define LEGACY_MESSAGE_COL_DATE 9
|
||||
#define LEGACY_MESSAGE_COL_APP_DATA 10
|
||||
#define LEGACY_MESSAGE_COL_CONTENT_ID 11
|
||||
#define LEGACY_MESSAGE_COL_IMDN_MESSAGE_ID 12
|
||||
#define LEGACY_MESSAGE_COL_CONTENT_TYPE 13
|
||||
#define LEGACY_MESSAGE_COL_IS_SECURED 14
|
||||
|
||||
template<typename T>
|
||||
static T getValueFromLegacyMessage (const soci::row &message, int index, bool &isNull) {
|
||||
isNull = false;
|
||||
|
||||
try {
|
||||
return message.get<T>(static_cast<size_t>(index));
|
||||
} catch (const exception &) {
|
||||
isNull = true;
|
||||
}
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
static bool checkLegacyHistoryTableExists (soci::session &session) {
|
||||
session << "SELECT name FROM sqlite_master WHERE type='table' AND name='history'";
|
||||
return session.got_data() > 0;
|
||||
}
|
||||
|
||||
bool MainDb::import (Backend, const string ¶meters) {
|
||||
L_D();
|
||||
|
||||
|
|
@ -2368,118 +2645,13 @@ bool MainDb::import (Backend, const string ¶meters) {
|
|||
return false;
|
||||
}
|
||||
|
||||
soci::session *inSession = inDbSession.getBackendSession<soci::session>();
|
||||
L_BEGIN_LOG_EXCEPTION
|
||||
d->importLegacyFriends(inDbSession);
|
||||
L_END_LOG_EXCEPTION
|
||||
|
||||
// Import messages.
|
||||
try {
|
||||
soci::transaction tr(*d->dbSession.getBackendSession<soci::session>());
|
||||
|
||||
if (!checkLegacyHistoryTableExists(*inSession))
|
||||
return false;
|
||||
|
||||
unsigned int version = d->getModuleVersion("legacy-history-import");
|
||||
if (version >= L_VERSION(1, 0, 0))
|
||||
return false;
|
||||
d->updateModuleVersion("legacy-history-import", DB_MODULE_VERSION_LEGACY_HISTORY_IMPORT);
|
||||
|
||||
soci::rowset<soci::row> messages = (inSession->prepare << "SELECT * FROM history");
|
||||
for (const auto &message : messages) {
|
||||
const int direction = message.get<int>(LEGACY_MESSAGE_COL_DIRECTION);
|
||||
if (direction != 0 && direction != 1) {
|
||||
lWarning() << "Unable to import legacy message with invalid direction.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const int &state = message.get<int>(
|
||||
LEGACY_MESSAGE_COL_STATE, static_cast<int>(ChatMessage::State::Displayed)
|
||||
);
|
||||
if (state < 0 || state > static_cast<int>(ChatMessage::State::Displayed)) {
|
||||
lWarning() << "Unable to import legacy message with invalid state.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const tm &creationTime = Utils::getTimeTAsTm(message.get<int>(LEGACY_MESSAGE_COL_DATE, 0));
|
||||
|
||||
bool isNull;
|
||||
getValueFromLegacyMessage<string>(message, LEGACY_MESSAGE_COL_URL, isNull);
|
||||
|
||||
const int &contentId = message.get<int>(LEGACY_MESSAGE_COL_CONTENT_ID, -1);
|
||||
ContentType contentType(message.get<string>(LEGACY_MESSAGE_COL_CONTENT_TYPE, ""));
|
||||
if (!contentType.isValid())
|
||||
contentType = contentId != -1
|
||||
? ContentType::FileTransfer
|
||||
: (isNull ? ContentType::PlainText : ContentType::ExternalBody);
|
||||
if (contentType == ContentType::ExternalBody) {
|
||||
lInfo() << "Import of external body content is skipped.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const string &text = getValueFromLegacyMessage<string>(message, LEGACY_MESSAGE_COL_TEXT, isNull);
|
||||
|
||||
Content content;
|
||||
content.setContentType(contentType);
|
||||
if (contentType == ContentType::PlainText) {
|
||||
if (isNull) {
|
||||
lWarning() << "Unable to import legacy message with no text.";
|
||||
continue;
|
||||
}
|
||||
content.setBody(text);
|
||||
} else {
|
||||
if (contentType != ContentType::FileTransfer) {
|
||||
lWarning() << "Unable to import unsupported legacy content.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const string appData = getValueFromLegacyMessage<string>(message, LEGACY_MESSAGE_COL_APP_DATA, isNull);
|
||||
if (isNull) {
|
||||
lWarning() << "Unable to import legacy file message without app data.";
|
||||
continue;
|
||||
}
|
||||
|
||||
content.setAppData("legacy", appData);
|
||||
}
|
||||
|
||||
soci::session *session = d->dbSession.getBackendSession<soci::session>();
|
||||
const int &eventType = static_cast<int>(EventLog::Type::ConferenceChatMessage);
|
||||
*session << "INSERT INTO event (type, creation_time) VALUES (:type, :creationTime)",
|
||||
soci::use(eventType), soci::use(creationTime);
|
||||
|
||||
const long long &eventId = getLastInsertId();
|
||||
const long long &localSipAddressId = d->insertSipAddress(message.get<string>(LEGACY_MESSAGE_COL_LOCAL_ADDRESS));
|
||||
const long long &remoteSipAddressId = d->insertSipAddress(message.get<string>(LEGACY_MESSAGE_COL_REMOTE_ADDRESS));
|
||||
const long long &chatRoomId = d->insertOrUpdateImportedBasicChatRoom(
|
||||
remoteSipAddressId,
|
||||
localSipAddressId,
|
||||
creationTime
|
||||
);
|
||||
const int &isSecured = message.get<int>(LEGACY_MESSAGE_COL_IS_SECURED, 0);
|
||||
|
||||
*session << "INSERT INTO conference_event (event_id, chat_room_id)"
|
||||
" VALUES (:eventId, :chatRoomId)", soci::use(eventId), soci::use(chatRoomId);
|
||||
|
||||
*session << "INSERT INTO conference_chat_message_event ("
|
||||
" event_id, from_sip_address_id, to_sip_address_id,"
|
||||
" time, state, direction, imdn_message_id, is_secured"
|
||||
") VALUES ("
|
||||
" :eventId, :localSipAddressId, :remoteSipAddressId,"
|
||||
" :creationTime, :state, :direction, '', :isSecured"
|
||||
")", soci::use(eventId), soci::use(localSipAddressId), soci::use(remoteSipAddressId),
|
||||
soci::use(creationTime), soci::use(state), soci::use(direction),
|
||||
soci::use(isSecured);
|
||||
|
||||
d->insertContent(eventId, content);
|
||||
d->insertChatRoomParticipant(chatRoomId, remoteSipAddressId, false);
|
||||
|
||||
if (state != static_cast<int>(ChatMessage::State::Displayed))
|
||||
d->insertChatMessageParticipant(eventId, remoteSipAddressId, state);
|
||||
}
|
||||
|
||||
tr.commit();
|
||||
} catch (const exception &e) {
|
||||
lInfo() << "Failed to import legacy messages from: `" << uri << "`. (" << e.what() << ")";
|
||||
return false;
|
||||
}
|
||||
lInfo() << "Successful import of legacy messages from: `" << uri << "`.";
|
||||
L_BEGIN_LOG_EXCEPTION
|
||||
d->importLegacyHistory(inDbSession);
|
||||
L_END_LOG_EXCEPTION
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ public:
|
|||
// Other.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Import legacy messages from old db.
|
||||
// Import legacy calls/messages from old db.
|
||||
bool import (Backend backend, const std::string ¶meters) override;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue