diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b07500..cde50bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,6 @@ add_library(tox MODULE src/twc-list.c src/twc-message-queue.c src/twc-profile.c - src/twc-sqlite.c src/twc-tox-callbacks.c src/twc-utils.c ) @@ -47,7 +46,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Wno-unused-paramet target_link_libraries(tox toxcore) target_link_libraries(tox toxav) -target_link_libraries(tox sqlite3) # remove lib prefix (libtox.so -> tox.so) set_target_properties(tox PROPERTIES PREFIX "") diff --git a/README.md b/README.md index 18fd0bf..1edf28d 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ Installation > Tox-WeeChat is available in the [AUR][4] and the [[haavard]][5] pacman repository. -Tox-WeeChat requires [WeeChat][2] >= 1.0.1, [SQLite][6] >= 3.6.19 and the -latest-ish [libtoxcore][7]. It also requires CMake to be built. Installation -is fairly simple; after getting the source, compile and install using CMake: +Tox-WeeChat requires [WeeChat][2] >= 1.0.1 and the latest-ish [libtoxcore][6]. +It also requires CMake to be built. Installation is fairly simple; after +getting the source, compile and install using CMake: $ mkdir build && cd build $ cmake -DPLUGIN_PATH=~/.weechat/plugins .. @@ -85,6 +85,5 @@ along with Tox-WeeChat. If not, see . [3]: https://travis-ci.org/haavardp/tox-weechat [4]: https://aur.archlinux.org/packages/tox-weechat-git [5]: https://haavard.me/archlinux -[6]: http://www.sqlite.org -[7]: https://github.com/irungentoo/toxcore +[6]: https://github.com/irungentoo/toxcore diff --git a/src/twc-commands.c b/src/twc-commands.c index 22b4d44..f5ac341 100644 --- a/src/twc-commands.c +++ b/src/twc-commands.c @@ -30,7 +30,6 @@ #include "twc-friend-request.h" #include "twc-group-invite.h" #include "twc-bootstrap.h" -#include "twc-sqlite.h" #include "twc-config.h" #include "twc-utils.h" @@ -404,10 +403,9 @@ twc_cmd_friend(void *data, struct t_gui_buffer *buffer, struct t_twc_friend_request *request; if (weechat_strcasecmp(argv[2], "all") == 0) { - struct t_twc_list *requests = twc_sqlite_friend_requests(profile); size_t index; struct t_twc_list_item *item; - twc_list_foreach(requests, index, item) + twc_list_foreach(profile->friend_requests, index, item) { if (accept) twc_friend_request_accept(item->friend_request); @@ -464,11 +462,9 @@ twc_cmd_friend(void *data, struct t_gui_buffer *buffer, "%sPending friend requests:", weechat_prefix("network")); - struct t_twc_list *friend_requests = twc_sqlite_friend_requests(profile); - size_t index; struct t_twc_list_item *item; - twc_list_foreach(friend_requests, index, item) + twc_list_foreach(profile->friend_requests, index, item) { size_t short_id_length = weechat_config_integer(twc_config_short_id_size); char hex_address[short_id_length + 1]; @@ -480,14 +476,10 @@ twc_cmd_friend(void *data, struct t_gui_buffer *buffer, "%s[%d] Address: %s\n" "[%d] Message: %s", weechat_prefix("network"), - item->friend_request->request_id, - hex_address, - item->friend_request->request_id, - item->friend_request->message); + index, hex_address, + index, item->friend_request->message); } - twc_friend_request_free_list(friend_requests); - return WEECHAT_RC_OK; } diff --git a/src/twc-friend-request.c b/src/twc-friend-request.c index fa63313..77b3476 100644 --- a/src/twc-friend-request.c +++ b/src/twc-friend-request.c @@ -25,25 +25,24 @@ #include "twc.h" #include "twc-list.h" #include "twc-profile.h" -#include "twc-sqlite.h" #include "twc-utils.h" #include "twc-friend-request.h" /** - * Add a new friend request to a profile. Return it's index for accepting. + * Add a new friend request to a profile. * - * Returns ID on success, -1 on a full friend request list, -2 on other error. + * Returns index on success, -1 on a full friend request list and -2 for any + * other error. */ int twc_friend_request_add(struct t_twc_profile *profile, const uint8_t *client_id, const char *message) { - int max_request_count = + size_t max_request_count = TWC_PROFILE_OPTION_INTEGER(profile, TWC_PROFILE_OPTION_MAX_FRIEND_REQUESTS); - int current_request_count = twc_sqlite_friend_request_count(profile); - if (current_request_count >= max_request_count) + if (profile->friend_requests->count >= max_request_count) return -1; // create a new request @@ -56,12 +55,10 @@ twc_friend_request_add(struct t_twc_profile *profile, request->message = strdup(message); memcpy(request->tox_id, client_id, TOX_CLIENT_ID_SIZE); - int rc = twc_sqlite_add_friend_request(profile, request); - - if (rc == -1) + if (!twc_list_item_new_data_add(profile->friend_requests, request)) return -2; - return rc; + return profile->friend_requests->count - 1; } /** @@ -80,8 +77,7 @@ twc_friend_request_accept(struct t_twc_friend_request *request) void twc_friend_request_remove(struct t_twc_friend_request *request) { - twc_sqlite_delete_friend_request_with_id(request->profile, - request->request_id); + twc_list_remove_with_data(request->profile->friend_requests, request); } /** @@ -90,7 +86,7 @@ twc_friend_request_remove(struct t_twc_friend_request *request) struct t_twc_friend_request * twc_friend_request_with_index(struct t_twc_profile *profile, int64_t index) { - return twc_sqlite_friend_request_with_id(profile, index); + return twc_list_get(profile->friend_requests, index)->friend_request; } /** diff --git a/src/twc-friend-request.h b/src/twc-friend-request.h index 3ac1783..3986080 100644 --- a/src/twc-friend-request.h +++ b/src/twc-friend-request.h @@ -31,7 +31,6 @@ struct t_twc_friend_request { struct t_twc_profile *profile; - int request_id; uint8_t tox_id[TOX_CLIENT_ID_SIZE]; char *message; }; diff --git a/src/twc-profile.c b/src/twc-profile.c index 517e103..2ff11d8 100644 --- a/src/twc-profile.c +++ b/src/twc-profile.c @@ -34,7 +34,6 @@ #include "twc-message-queue.h" #include "twc-chat.h" #include "twc-tox-callbacks.h" -#include "twc-sqlite.h" #include "twc-utils.h" #include "twc-profile.h" @@ -179,6 +178,7 @@ twc_profile_new(const char *name) profile->tox_online = false; profile->chats = twc_list_new(); + profile->friend_requests = twc_list_new(); profile->group_chat_invites = twc_list_new(); profile->message_queues = weechat_hashtable_new(32, WEECHAT_HASHTABLE_INTEGER, @@ -293,18 +293,6 @@ twc_profile_load(struct t_twc_profile *profile) (uint8_t *)name, strlen(name)); } - // register with sqlite - twc_sqlite_add_profile(profile); - - int friend_request_count = twc_sqlite_friend_request_count(profile); - if (friend_request_count > 0) - { - weechat_printf(profile->buffer, - "%sYou have %d pending friend requests.", - weechat_prefix("network"), - friend_request_count); - } - // bootstrap DHT // TODO: add count to config int bootstrap_node_count = 5; @@ -467,7 +455,6 @@ twc_profile_delete(struct t_twc_profile *profile, { char *data_path = twc_profile_expanded_data_path(profile); - twc_sqlite_delete_profile(profile); twc_profile_free(profile); if (delete_data) @@ -492,6 +479,7 @@ twc_profile_free(struct t_twc_profile *profile) // free things twc_chat_free_list(profile->chats); + twc_friend_request_free_list(profile->friend_requests); twc_group_chat_invite_free_list(profile->group_chat_invites); twc_message_queue_free_profile(profile); free(profile->name); diff --git a/src/twc-profile.h b/src/twc-profile.h index 258cab9..026e75b 100644 --- a/src/twc-profile.h +++ b/src/twc-profile.h @@ -52,6 +52,7 @@ struct t_twc_profile struct t_hook *tox_do_timer; struct t_twc_list *chats; + struct t_twc_list *friend_requests; struct t_twc_list *group_chat_invites; struct t_hashtable *message_queues; }; diff --git a/src/twc-sqlite.c b/src/twc-sqlite.c deleted file mode 100644 index c6299fc..0000000 --- a/src/twc-sqlite.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2015 Håvard Pettersson - * - * This file is part of Tox-WeeChat. - * - * Tox-WeeChat is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox-WeeChat is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox-WeeChat. If not, see . - */ - -#include -#include - -#include -#include -#include - -#include "twc.h" -#include "twc-list.h" -#include "twc-profile.h" -#include "twc-friend-request.h" - -#include "twc-sqlite.h" - -sqlite3 *twc_sqlite_db = NULL; -struct t_twc_list *twc_sqlite_statements = NULL; - -#ifdef TWC_DEBUG -#define TWC_SQLITE_DEBUG_RC(rc, expected_rc) \ - if (rc != expected_rc) \ - weechat_printf(NULL, \ - "%s%s: SQLite error in %s: error code %d", \ - weechat_prefix("error"), weechat_plugin->name, \ - __func__, rc); -#else -#define TWC_SQLITE_DEBUG_RC(rc, expected_rc) (void)rc; -#endif // TWC_DEBUG - -/** - * Create or reset an SQLite statement. - */ -#define TWC_SQLITE_STMT(statement, statement_str) \ - static sqlite3_stmt *statement = NULL; \ - if (!statement) \ - { \ - int rc = sqlite3_prepare_v2(twc_sqlite_db, \ - statement_str, \ - strlen(statement_str) + 1, \ - &statement, \ - NULL); \ - TWC_SQLITE_DEBUG_RC(rc, SQLITE_OK); \ - if (rc != SQLITE_OK) \ - statement = NULL; \ - else \ - twc_list_item_new_data_add(twc_sqlite_statements, statement); \ - } \ - else \ - { \ - sqlite3_reset(statement); \ - } - -/** - * Return the full path to our SQLite database file. Must be freed. - */ -char * -twc_sqlite_db_path() -{ - const char *weechat_dir = weechat_info_get("weechat_dir", NULL); - return weechat_string_replace("%h/tox/data.db", "%h", weechat_dir); -} - -/** - * Initialize profile table. Return 0 on success, -1 on error. - */ -int -twc_sqlite_init_profiles() -{ - TWC_SQLITE_STMT(statement, - "CREATE TABLE IF NOT EXISTS profiles (" - "id INTEGER PRIMARY KEY," - "tox_id BLOB UNIQUE NOT NULL" - ")"); - - int rc = sqlite3_step(statement); - if (rc != SQLITE_DONE) - return -1; - else - return 0; -} - -/** - * Initialize friend request table. Return 0 on success, -1 on error. - */ -int -twc_sqlite_init_friend_requests() -{ - TWC_SQLITE_STMT(statement, - "CREATE TABLE IF NOT EXISTS friend_requests (" - "id INTEGER PRIMARY KEY," - "tox_id BLOB NOT NULL," - "message TEXT," - "profile_id INTEGER NOT NULL," - "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE," - "UNIQUE(tox_id, profile_id)" - ")"); - int rc = sqlite3_step(statement); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_DONE) - if (rc != SQLITE_DONE) - return -1; - else - return 0; -} - -/** - * Add a profile, if it does not exist. - */ -int -twc_sqlite_add_profile(struct t_twc_profile *profile) -{ - TWC_SQLITE_STMT(statement, - "INSERT OR IGNORE INTO profiles (tox_id)" - "VALUES (?)"); - - uint8_t tox_id[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(profile->tox, tox_id); - sqlite3_bind_blob(statement, 1, - tox_id, TOX_CLIENT_ID_SIZE, - NULL); - - int rc = sqlite3_step(statement); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_DONE) - if (rc != SQLITE_DONE) - return -1; - else - return 0; -} - -/** - * Get the rowid of a profile. Returns true on success, false on error (e.g. - * not found). - */ -bool -twc_sqlite_profile_id(struct t_twc_profile *profile, int64_t *out) -{ - if (!(profile->tox)) - return false; - - TWC_SQLITE_STMT(statement, - "SELECT id FROM profiles WHERE tox_id == ?"); - - uint8_t tox_id[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(profile->tox, tox_id); - sqlite3_bind_blob(statement, 1, - tox_id, TOX_CLIENT_ID_SIZE, - NULL); - - int rc = sqlite3_step(statement); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_ROW) - if (rc != SQLITE_ROW) - { - return false; - } - else - { - *out = sqlite3_column_int(statement, 0); - return true; - } -} - -/** - * Delete a profile from persistent storage. - */ -int -twc_sqlite_delete_profile(struct t_twc_profile *profile) -{ - int64_t profile_id; - if (!twc_sqlite_profile_id(profile, &profile_id)) - { - weechat_printf(NULL, "missing profile!"); - return -1; - } - - TWC_SQLITE_STMT(statement, - "DELETE FROM profiles " - "WHERE id == ?"); - sqlite3_bind_int(statement, 1, - profile_id); - - int rc = sqlite3_step(statement); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_DONE) - if (rc == SQLITE_DONE) - return 0; - else - return -1; -} - -/** - * Add a friend request. Return ID on success, -1 on error. - */ -int -twc_sqlite_add_friend_request(struct t_twc_profile *profile, - struct t_twc_friend_request *friend_request) -{ - int64_t profile_id; - if (!twc_sqlite_profile_id(profile, &profile_id)) - { - weechat_printf(NULL, "missing profile!"); - return -1; - } - - TWC_SQLITE_STMT(statement, - "INSERT OR REPLACE INTO friend_requests (tox_id, message, profile_id)" - "VALUES (?, ?, ?)"); - sqlite3_bind_blob(statement, 1, - friend_request->tox_id, TOX_CLIENT_ID_SIZE, - NULL); - sqlite3_bind_text(statement, 2, - friend_request->message, strlen(friend_request->message) + 1, - NULL); - sqlite3_bind_int(statement, 3, - profile_id); - - int rc = sqlite3_step(statement); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_DONE) - if (rc != SQLITE_DONE) - return -1; - else - return sqlite3_last_insert_rowid(twc_sqlite_db); -} - -/** - * Return the number of friend requests for a profile. - */ -int -twc_sqlite_friend_request_count(struct t_twc_profile *profile) -{ - int64_t profile_id; - if (!twc_sqlite_profile_id(profile, &profile_id)) - { - weechat_printf(NULL, "missing profile!"); - return -1; - } - - TWC_SQLITE_STMT(statement, - "SELECT COUNT(*) FROM friend_requests WHERE profile_id == ?"); - sqlite3_bind_int(statement, 1, - profile_id); - - int rc = sqlite3_step(statement); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_ROW) - if (rc != SQLITE_ROW) - return 0; - else - return sqlite3_column_int(statement, 0); -} - -/** - * Convert a row from an SQLite statement to a friend request object. - */ -struct t_twc_friend_request * -twc_sqlite_friend_request_row(sqlite3_stmt *statement, - struct t_twc_profile *profile) -{ - struct t_twc_friend_request *request = malloc(sizeof(struct t_twc_friend_request)); - request->request_id = sqlite3_column_int(statement, 0); - memcpy(request->tox_id, - sqlite3_column_blob(statement, 1), - TOX_CLIENT_ID_SIZE); - request->message = strdup((const char *)sqlite3_column_text(statement, 2)); - request->profile = profile; - - return request; -} - -/** - * Return a list of all friend requests for the given profile. - */ -struct t_twc_list * -twc_sqlite_friend_requests(struct t_twc_profile *profile) -{ - int64_t profile_id; - if (!twc_sqlite_profile_id(profile, &profile_id)) - { - weechat_printf(NULL, "missing profile!"); - return NULL; - } - - TWC_SQLITE_STMT(statement, - "SELECT id, tox_id, message " - "FROM friend_requests " - "WHERE profile_id == ?"); - sqlite3_bind_int(statement, 1, - profile_id); - - struct t_twc_list *friend_requests = twc_list_new(); - - int rc; - while ((rc = sqlite3_step(statement)) == SQLITE_ROW) - { - struct t_twc_friend_request *request = - twc_sqlite_friend_request_row(statement, profile); - twc_list_item_new_data_add(friend_requests, request); - } - TWC_SQLITE_DEBUG_RC(rc, SQLITE_DONE) - - return friend_requests; -} - -struct t_twc_friend_request * -twc_sqlite_friend_request_with_id(struct t_twc_profile *profile, int64_t id) -{ - int64_t profile_id; - if (!twc_sqlite_profile_id(profile, &profile_id)) - { - weechat_printf(NULL, "missing profile!"); - return NULL; - } - - TWC_SQLITE_STMT(statement, - "SELECT id, tox_id, message " - "FROM friend_requests " - "WHERE id == ? AND profile_id == ?"); - sqlite3_bind_int(statement, 1, id); - sqlite3_bind_int(statement, 2, profile_id); - - struct t_twc_friend_request *request; - int rc = sqlite3_step(statement); - if (rc == SQLITE_ROW) - { - request = twc_sqlite_friend_request_row(statement, profile); - return request; - } - else - TWC_SQLITE_DEBUG_RC(rc, SQLITE_DONE) - - return NULL; -} - -int -twc_sqlite_delete_friend_request_with_id(struct t_twc_profile *profile, - int64_t id) -{ - int64_t profile_id; - if (!twc_sqlite_profile_id(profile, &profile_id)) - { - weechat_printf(NULL, "missing profile!"); - return -1; - } - - TWC_SQLITE_STMT(statement, - "DELETE FROM friend_requests " - "WHERE id == ? AND profile_id == ?"); - sqlite3_bind_int(statement, 1, - id); - sqlite3_bind_int(statement, 2, - profile_id); - - int rc = sqlite3_step(statement); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_DONE) - if (rc == SQLITE_DONE) - return 0; - else - return -1; -} - -/** - * Initialize connection to SQLite database and create tables if necessary. - * Returns 0 on success, -1 on failure. - */ -int -twc_sqlite_init() -{ - char *path = twc_sqlite_db_path(); - - int rc = sqlite3_open(path, &twc_sqlite_db); - free(path); - - TWC_SQLITE_DEBUG_RC(rc, SQLITE_OK) - if (rc != SQLITE_OK) - { - weechat_printf(NULL, - "%s: could not open database: %s\n", - weechat_plugin->name, - sqlite3_errmsg(twc_sqlite_db)); - sqlite3_close(twc_sqlite_db); - twc_sqlite_db = NULL; - - return -1; - } - - // statement list (so we can finalize later) - twc_sqlite_statements = twc_list_new(); - - // initialize tables - if (twc_sqlite_init_profiles() != 0 || - twc_sqlite_init_friend_requests() != 0) - return -1; - - return 0; -} - -/** - * Close connection to SQLite database. - */ -void -twc_sqlite_end() -{ - size_t index; - struct t_twc_list_item *item; - twc_list_foreach(twc_sqlite_statements, index, item) - sqlite3_finalize(item->data); - - int rc = sqlite3_close(twc_sqlite_db); - TWC_SQLITE_DEBUG_RC(rc, SQLITE_OK) -} - diff --git a/src/twc-sqlite.h b/src/twc-sqlite.h deleted file mode 100644 index 025af92..0000000 --- a/src/twc-sqlite.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2015 Håvard Pettersson - * - * This file is part of Tox-WeeChat. - * - * Tox-WeeChat is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox-WeeChat is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox-WeeChat. If not, see . - */ - -#ifndef TWC_SQLITE_H -#define TWC_SQLITE_H - -#include - -struct t_twc_profile; -struct t_twc_friend_request; - -int -twc_sqlite_init(); - -int -twc_sqlite_add_profile(struct t_twc_profile *profile); - -int -twc_sqlite_delete_profile(struct t_twc_profile *profile); - -int -twc_sqlite_add_friend_request(struct t_twc_profile *profile, - struct t_twc_friend_request *friend_request); - -int -twc_sqlite_friend_request_count(struct t_twc_profile *profile); - -struct t_twc_list * -twc_sqlite_friend_requests(struct t_twc_profile *profile); - -struct t_twc_friend_request * -twc_sqlite_friend_request_with_id(struct t_twc_profile *profile, - int64_t id); - -int -twc_sqlite_delete_friend_request_with_id(struct t_twc_profile *profile, - int64_t id); - -void -twc_sqlite_end(); - -#endif // TWC_SQLITE_H diff --git a/src/twc.c b/src/twc.c index 5d8e1f9..34aab9f 100644 --- a/src/twc.c +++ b/src/twc.c @@ -26,7 +26,6 @@ #include "twc-gui.h" #include "twc-config.h" #include "twc-completion.h" -#include "twc-sqlite.h" #include "twc.h" @@ -43,14 +42,6 @@ weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { weechat_plugin = plugin; - if (twc_sqlite_init() != 0) - { - weechat_printf(NULL, - "%s%s: failed to initialize persistent storage, some " - "data will not be saved", - weechat_prefix("error"), weechat_plugin->name); - } - twc_profile_init(); twc_commands_init(); twc_gui_init(); @@ -81,8 +72,6 @@ weechat_plugin_end(struct t_weechat_plugin *plugin) twc_profile_free_all(); - twc_sqlite_end(); - return WEECHAT_RC_OK; }