From 2837c4054f0c46f9cbbd0f09571e7d91501f2253 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 30 Jun 2013 18:59:38 +0300 Subject: [PATCH 01/24] initial support of autojoin for MUC --- Makefile.am | 2 + src/xmpp/bookmark.c | 116 ++++++++++++++++++++++++++++++++++++++++++ src/xmpp/bookmark.h | 7 +++ src/xmpp/connection.c | 15 ++++++ src/xmpp/connection.h | 1 + src/xmpp/stanza.c | 57 +++++++++++++++++++++ src/xmpp/stanza.h | 6 +++ 7 files changed, 204 insertions(+) create mode 100644 src/xmpp/bookmark.c create mode 100644 src/xmpp/bookmark.h diff --git a/Makefile.am b/Makefile.am index f161b92a..72503004 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,6 +10,7 @@ profanity_SOURCES = \ src/xmpp/stanza.h src/xmpp/message.h src/xmpp/iq.h src/xmpp/presence.h \ src/xmpp/capabilities.h src/xmpp/connection.h \ src/xmpp/roster.c src/xmpp/roster.h \ + src/xmpp/bookmark.c src/xmpp/bookmark.h \ src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \ src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \ src/ui/console.c src/ui/notifier.c src/ui/notifier.h \ @@ -36,6 +37,7 @@ tests_testsuite_SOURCES = \ src/xmpp/stanza.h src/xmpp/message.h src/xmpp/iq.h src/xmpp/presence.h \ src/xmpp/capabilities.h src/xmpp/connection.h \ src/xmpp/roster.c src/xmpp/roster.h \ + src/xmpp/bookmark.c src/xmpp/bookmark.h \ src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \ src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \ src/ui/console.c src/ui/notifier.c src/ui/notifier.h \ diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c new file mode 100644 index 00000000..e6d5efe3 --- /dev/null +++ b/src/xmpp/bookmark.c @@ -0,0 +1,116 @@ + +#include +#include +#include +#include +#include + +#include "log.h" +#include "muc.h" +#include "ui/ui.h" +#include "xmpp/connection.h" +#include "xmpp/stanza.h" +#include "xmpp/xmpp.h" + +static int _bookmark_handle_result(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata); + +void +bookmark_request(void) +{ + int id; + char id_str[10]; + xmpp_conn_t * const conn = connection_get_conn(); + xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_stanza_t *iq = stanza_create_storage_bookmarks(ctx); + + id = jabber_get_id(); + snprintf(id_str, sizeof(id_str), "%u", id); + + /* TODO: timed handler to remove this id_handler */ + xmpp_id_handler_add(conn, _bookmark_handle_result, id_str, ctx); + + xmpp_stanza_set_id(iq, id_str); + xmpp_send(conn, iq); + xmpp_stanza_release(iq); +} + +static int +_bookmark_handle_result(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata) +{ + xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + xmpp_stanza_t *ptr; + xmpp_stanza_t *nick; + char *name; + char *jid; + char *autojoin; + Jid *my_jid; + + name = xmpp_stanza_get_name(stanza); + if (!name || strcmp(name, STANZA_NAME_IQ) != 0) { + return 0; + } + + ptr = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY); + if (!ptr) { + return 0; + } + ptr = xmpp_stanza_get_child_by_name(ptr, STANZA_NAME_STORAGE); + if (!ptr) { + return 0; + } + + my_jid = jid_create(jabber_get_fulljid()); + + ptr = xmpp_stanza_get_children(ptr); + while (ptr) { + name = xmpp_stanza_get_name(ptr); + if (strcmp(name, STANZA_NAME_CONFERENCE) != 0) { + continue; + } + jid = xmpp_stanza_get_attribute(ptr, STANZA_ATTR_JID); + if (!jid) { + continue; + } + + log_debug("Handle bookmark for %s", jid); + + autojoin = xmpp_stanza_get_attribute(ptr, "autojoin"); + if (autojoin && strcmp(autojoin, "1") == 0) { + name = NULL; + nick = xmpp_stanza_get_child_by_name(ptr, "nick"); + if (nick) { + char *tmp; + tmp = xmpp_stanza_get_text(nick); + if (tmp) { + name = strdup(tmp); + xmpp_free(ctx, tmp); + } + } else { + name = strdup(my_jid->localpart); + } + + if (name) { + /* TODO: autojoin maximum (e.g. 5) rooms */ + log_debug("Autojoin %s with nick=%s", jid, name); + Jid *room_jid = jid_create_from_bare_and_resource(jid, name); + if (!muc_room_is_active(room_jid)) { + presence_join_room(room_jid); + /* XXX: this should be removed after fixing #195 */ + ui_room_join(room_jid); + } + jid_destroy(room_jid); + free(name); + } + } + + /* TODO: add to autocompleter */ + + ptr = xmpp_stanza_get_next(ptr); + } + + jid_destroy(my_jid); + + return 0; +} diff --git a/src/xmpp/bookmark.h b/src/xmpp/bookmark.h new file mode 100644 index 00000000..d4ab8b5b --- /dev/null +++ b/src/xmpp/bookmark.h @@ -0,0 +1,7 @@ + +#ifndef BOOKMARK_H +#define BOOKMARK_H + +void bookmark_request(void); + +#endif diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 85ddfa45..600e813a 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -33,6 +33,7 @@ #include "log.h" #include "muc.h" #include "profanity.h" +#include "xmpp/bookmark.h" #include "xmpp/capabilities.h" #include "xmpp/connection.h" #include "xmpp/iq.h" @@ -231,6 +232,19 @@ jabber_set_autoping(const int seconds) } } +int +jabber_get_id(void) +{ + static int xmpp_id; + + ++xmpp_id; + if (xmpp_id < 0) { + xmpp_id = 1; + } + + return xmpp_id; +} + GList * jabber_get_available_resources(void) { @@ -494,6 +508,7 @@ _connection_handler(xmpp_conn_t * const conn, } roster_request(); + bookmark_request(); jabber_conn.conn_status = JABBER_CONNECTED; if (prefs_get_reconnect() != 0) { diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h index b5701252..81a6e3b3 100644 --- a/src/xmpp/connection.h +++ b/src/xmpp/connection.h @@ -31,6 +31,7 @@ xmpp_conn_t *connection_get_conn(void); xmpp_ctx_t *connection_get_ctx(void); int connection_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); +int jabber_get_id(void); void connection_set_priority(int priority); void connection_set_presence_message(const char * const message); void connection_add_available_resource(Resource *resource); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index d2de44f0..e1178ccf 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -33,6 +33,63 @@ static int _field_compare(FormField *f1, FormField *f2); +#if 0 +xmpp_stanza_t * +stanza_create_storage_bookmarks(xmpp_ctx_t *ctx) +{ + xmpp_stanza_t *iq, *pubsub, *items; + + /* TODO: check pointers for NULL */ + iq = xmpp_stanza_new(ctx); + pubsub = xmpp_stanza_new(ctx); + items = xmpp_stanza_new(ctx); + + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_GET); + + xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB); + xmpp_stanza_set_ns(pubsub, STANZA_NS_PUBSUB); + + xmpp_stanza_set_name(items, STANZA_NAME_ITEMS); + xmpp_stanza_set_attribute(items, "node", "storage:bookmarks"); + + xmpp_stanza_add_child(pubsub, items); + xmpp_stanza_add_child(iq, pubsub); + xmpp_stanza_release(items); + xmpp_stanza_release(pubsub); + + return iq; +} +#endif + +xmpp_stanza_t * +stanza_create_storage_bookmarks(xmpp_ctx_t *ctx) +{ + xmpp_stanza_t *iq, *query, *storage; + + /* TODO: check pointers for NULL */ + iq = xmpp_stanza_new(ctx); + query = xmpp_stanza_new(ctx); + storage = xmpp_stanza_new(ctx); + + xmpp_stanza_set_name(iq, STANZA_NAME_IQ); + xmpp_stanza_set_type(iq, STANZA_TYPE_GET); + xmpp_stanza_set_ns(iq, "jabber:client"); + + xmpp_stanza_set_name(query, STANZA_NAME_QUERY); + xmpp_stanza_set_ns(query, "jabber:iq:private"); + + xmpp_stanza_set_name(storage, STANZA_NAME_STORAGE); + xmpp_stanza_set_ns(storage, "storage:bookmarks"); + + xmpp_stanza_add_child(query, storage); + xmpp_stanza_add_child(iq, query); + xmpp_stanza_release(storage); + xmpp_stanza_release(query); + + return iq; +} + xmpp_stanza_t * stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient, const char * const state) diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index ad777f24..108b0806 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -52,6 +52,9 @@ #define STANZA_NAME_INVITE "invite" #define STANZA_NAME_REASON "reason" #define STANZA_NAME_GROUP "group" +#define STANZA_NAME_PUBSUB "pubsub" +#define STANZA_NAME_STORAGE "storage" +#define STANZA_NAME_CONFERENCE "conference" #define STANZA_TYPE_CHAT "chat" #define STANZA_TYPE_GROUPCHAT "groupchat" @@ -100,6 +103,7 @@ #define STANZA_NS_VERSION "jabber:iq:version" #define STANZA_NS_CONFERENCE "jabber:x:conference" #define STANZA_NS_CAPTCHA "urn:xmpp:captcha" +#define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" @@ -113,6 +117,8 @@ typedef struct data_form_t { GSList *fields; } DataForm; +xmpp_stanza_t* stanza_create_storage_bookmarks(xmpp_ctx_t *ctx); + xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient, const char * const state); From 034cf730cc89210e9d423b015968938b9f291d60 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 14 Jul 2013 13:49:50 +0300 Subject: [PATCH 02/24] use get_unique_id for bookmarks --- src/common.c | 9 ++++----- src/xmpp/bookmark.c | 18 +++++++++++------- src/xmpp/connection.c | 13 ------------- src/xmpp/connection.h | 1 - 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/common.c b/src/common.c index 2d1ac3d7..e2ff0171 100644 --- a/src/common.c +++ b/src/common.c @@ -37,9 +37,6 @@ // and page size is at least 4KB #define READ_BUF_SIZE 4088 -// for generating ids -static int unique_id = 0; - struct curl_data_t { char *buffer; @@ -400,10 +397,12 @@ xdg_get_data_home(void) char * get_unique_id(void) { + static unsigned long unique_id; char *result = NULL; - unique_id++; GString *result_str = g_string_new(""); - g_string_printf(result_str, "prof%d", unique_id); + + unique_id++; + g_string_printf(result_str, "prof%lu", unique_id); result = result_str->str; g_string_free(result_str, FALSE); diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c index e6d5efe3..dd4cebe1 100644 --- a/src/xmpp/bookmark.c +++ b/src/xmpp/bookmark.c @@ -18,21 +18,25 @@ static int _bookmark_handle_result(xmpp_conn_t * const conn, void bookmark_request(void) { - int id; - char id_str[10]; + char *id; xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *iq = stanza_create_storage_bookmarks(ctx); + xmpp_stanza_t *iq; - id = jabber_get_id(); - snprintf(id_str, sizeof(id_str), "%u", id); + id = get_unique_id(); + if (!id) { + return; + } /* TODO: timed handler to remove this id_handler */ - xmpp_id_handler_add(conn, _bookmark_handle_result, id_str, ctx); + xmpp_id_handler_add(conn, _bookmark_handle_result, id, ctx); - xmpp_stanza_set_id(iq, id_str); + iq = stanza_create_storage_bookmarks(ctx); + xmpp_stanza_set_id(iq, id); xmpp_send(conn, iq); xmpp_stanza_release(iq); + + g_free(id); } static int diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 600e813a..5040aa91 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -232,19 +232,6 @@ jabber_set_autoping(const int seconds) } } -int -jabber_get_id(void) -{ - static int xmpp_id; - - ++xmpp_id; - if (xmpp_id < 0) { - xmpp_id = 1; - } - - return xmpp_id; -} - GList * jabber_get_available_resources(void) { diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h index 81a6e3b3..b5701252 100644 --- a/src/xmpp/connection.h +++ b/src/xmpp/connection.h @@ -31,7 +31,6 @@ xmpp_conn_t *connection_get_conn(void); xmpp_ctx_t *connection_get_ctx(void); int connection_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); -int jabber_get_id(void); void connection_set_priority(int priority); void connection_set_presence_message(const char * const message); void connection_add_available_resource(Resource *resource); From 6e23584575cb2749009255dbd13dde4718d3fb04 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 14 Jul 2013 17:05:46 +0300 Subject: [PATCH 03/24] improved autojoin logic Delete id handler after timeout (5sec) if response isn't received Auto join maximum 5 conferences --- src/xmpp/bookmark.c | 64 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c index dd4cebe1..52ac9244 100644 --- a/src/xmpp/bookmark.c +++ b/src/xmpp/bookmark.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -12,15 +13,23 @@ #include "xmpp/stanza.h" #include "xmpp/xmpp.h" +#define BOOKMARK_TIMEOUT 5000 +/* TODO: replace with a preference */ +#define BOOKMARK_AUTOJOIN_MAX 5 + +static int autojoin_count; + static int _bookmark_handle_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); +static int _bookmark_handle_delete(xmpp_conn_t * const conn, + void * const userdata); void bookmark_request(void) { char *id; - xmpp_conn_t * const conn = connection_get_conn(); - xmpp_ctx_t * const ctx = connection_get_ctx(); + xmpp_conn_t *conn = connection_get_conn(); + xmpp_ctx_t *ctx = connection_get_ctx(); xmpp_stanza_t *iq; id = get_unique_id(); @@ -28,22 +37,22 @@ bookmark_request(void) return; } - /* TODO: timed handler to remove this id_handler */ - xmpp_id_handler_add(conn, _bookmark_handle_result, id, ctx); + autojoin_count = 0; + xmpp_timed_handler_add(conn, _bookmark_handle_delete, BOOKMARK_TIMEOUT, id); + xmpp_id_handler_add(conn, _bookmark_handle_result, id, id); iq = stanza_create_storage_bookmarks(ctx); xmpp_stanza_set_id(iq, id); xmpp_send(conn, iq); xmpp_stanza_release(iq); - - g_free(id); } static int _bookmark_handle_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { - xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; + xmpp_ctx_t *ctx = connection_get_ctx(); + char *id = (char *)userdata; xmpp_stanza_t *ptr; xmpp_stanza_t *nick; char *name; @@ -51,6 +60,9 @@ _bookmark_handle_result(xmpp_conn_t * const conn, char *autojoin; Jid *my_jid; + xmpp_timed_handler_delete(conn, _bookmark_handle_delete); + g_free(id); + name = xmpp_stanza_get_name(stanza); if (!name || strcmp(name, STANZA_NAME_IQ) != 0) { return 0; @@ -96,15 +108,21 @@ _bookmark_handle_result(xmpp_conn_t * const conn, } if (name) { - /* TODO: autojoin maximum (e.g. 5) rooms */ - log_debug("Autojoin %s with nick=%s", jid, name); - Jid *room_jid = jid_create_from_bare_and_resource(jid, name); - if (!muc_room_is_active(room_jid)) { - presence_join_room(room_jid); - /* XXX: this should be removed after fixing #195 */ - ui_room_join(room_jid); + if (autojoin_count < BOOKMARK_AUTOJOIN_MAX) { + Jid *room_jid; + + log_debug("Autojoin %s with nick=%s", jid, name); + ++autojoin_count; + room_jid = jid_create_from_bare_and_resource(jid, name); + if (!muc_room_is_active(room_jid)) { + presence_join_room(room_jid); + /* TODO: this should be removed after fixing #195 */ + ui_room_join(room_jid); + } + jid_destroy(room_jid); + } else { + log_debug("Rejected autojoin %s (maximum has been reached)", jid); } - jid_destroy(room_jid); free(name); } } @@ -118,3 +136,19 @@ _bookmark_handle_result(xmpp_conn_t * const conn, return 0; } + +static int +_bookmark_handle_delete(xmpp_conn_t * const conn, + void * const userdata) +{ + char *id = (char *)userdata; + + assert(id != NULL); + + log_debug("Timeout for handler with id=%s", id); + + xmpp_id_handler_delete(conn, _bookmark_handle_result, id); + g_free(id); + + return 0; +} From b9d29e9aa59a16bcfc06f7e91fd562688565e12a Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 14 Jul 2013 23:58:02 +0300 Subject: [PATCH 04/24] draft of bookmarks implementation '/bookmark add' and '/bookmark remove' ain't finished --- src/command/command.c | 126 +++++++++++++++++++++++++++++++++- src/ui/console.c | 29 ++++++++ src/ui/ui.h | 1 + src/xmpp/bookmark.c | 155 +++++++++++++++++++++++++++++++++--------- src/xmpp/bookmark.h | 15 ++++ 5 files changed, 292 insertions(+), 34 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 63d003f4..6da2e758 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -44,6 +44,7 @@ #include "tools/tinyurl.h" #include "ui/ui.h" #include "xmpp/xmpp.h" +#include "xmpp/bookmark.h" /* * Command structure @@ -83,6 +84,7 @@ static char * _account_autocomplete(char *input, int *size); static char * _who_autocomplete(char *input, int *size); static char * _roster_autocomplete(char *input, int *size); static char * _group_autocomplete(char *input, int *size); +static char * _bookmark_autocomplete(char *input, int *size); static int _strtoi(char *str, int *saveptr, int min, int max); @@ -128,6 +130,7 @@ static gboolean _cmd_priority(gchar **args, struct cmd_help_t help); static gboolean _cmd_quit(gchar **args, struct cmd_help_t help); static gboolean _cmd_reconnect(gchar **args, struct cmd_help_t help); static gboolean _cmd_rooms(gchar **args, struct cmd_help_t help); +static gboolean _cmd_bookmark(gchar **args, struct cmd_help_t help); static gboolean _cmd_roster(gchar **args, struct cmd_help_t help); static gboolean _cmd_software(gchar **args, struct cmd_help_t help); static gboolean _cmd_splash(gchar **args, struct cmd_help_t help); @@ -367,6 +370,15 @@ static struct cmd_t command_defs[] = "Example : /rooms (if logged in as me@server.org, is equivalent to /rooms conference.server.org)", NULL } } }, + { "/bookmark", + _cmd_bookmark, parse_args, 0, 4, NULL, + { "/bookmark [add|list|remove] [room@server] [autojoin on|off] [nick nickname]", + "Manage bookmarks.", + { "/bookmark [add|list|remove] [room@server] [autojoin on|off] [nick nickname]", + "---------------------------------------------------------------------------", + "Manage bookmarks.", + NULL } } }, + { "/disco", _cmd_disco, parse_args, 1, 2, NULL, { "/disco command entity", "Service discovery.", @@ -853,6 +865,7 @@ static Autocomplete close_ac; static Autocomplete wins_ac; static Autocomplete roster_ac; static Autocomplete group_ac; +static Autocomplete bookmark_ac; /* * Initialise command autocompleter and history @@ -978,6 +991,11 @@ cmd_init(void) autocomplete_add(who_ac, strdup("unavailable")); autocomplete_add(who_ac, strdup("any")); + bookmark_ac = autocomplete_new(); + autocomplete_add(bookmark_ac, strdup("add")); + autocomplete_add(bookmark_ac, strdup("list")); + autocomplete_add(bookmark_ac, strdup("remove")); + cmd_history_init(); } @@ -1003,6 +1021,7 @@ cmd_close(void) autocomplete_free(wins_ac); autocomplete_free(roster_ac); autocomplete_free(group_ac); + autocomplete_free(bookmark_ac); } // Command autocompletion functions @@ -1072,6 +1091,8 @@ cmd_reset_autocomplete() autocomplete_reset(wins_ac); autocomplete_reset(roster_ac); autocomplete_reset(group_ac); + autocomplete_reset(bookmark_ac); + bookmark_autocomplete_reset(); } // Command execution @@ -1255,6 +1276,13 @@ _cmd_complete_parameters(char *input, int *size) } } + result = autocomplete_param_with_func(input, size, "/join", bookmark_find); + if (result != NULL) { + inp_replace_input(input, result, size); + g_free(result); + return; + } + result = autocomplete_param_with_func(input, size, "/connect", accounts_find_enabled); if (result != NULL) { inp_replace_input(input, result, size); @@ -1276,7 +1304,8 @@ _cmd_complete_parameters(char *input, int *size) autocompleter acs[] = { _who_autocomplete, _sub_autocomplete, _notify_autocomplete, _autoaway_autocomplete, _titlebar_autocomplete, _theme_autocomplete, - _account_autocomplete, _roster_autocomplete, _group_autocomplete }; + _account_autocomplete, _roster_autocomplete, _group_autocomplete, + _bookmark_autocomplete }; for (i = 0; i < ARRAY_SIZE(acs); i++) { result = acs[i](input, size); @@ -2798,6 +2827,73 @@ _cmd_rooms(gchar **args, struct cmd_help_t help) return TRUE; } +static gboolean +_cmd_bookmark(gchar **args, struct cmd_help_t help) +{ + jabber_conn_status_t conn_status = jabber_get_connection_status(); + gchar *cmd = args[0]; + + if (conn_status != JABBER_CONNECTED) { + cons_show("You are not currenlty connect."); + return TRUE; + } + + /* TODO: /bookmark list room@server */ + + if (cmd == NULL || strcmp(cmd, "list") == 0) { + cons_show_bookmarks(bookmark_get_list()); + } else { + gboolean autojoin = FALSE; + gboolean jid_release = FALSE; + gchar *jid = NULL; + gchar *nick = NULL; + int idx = 1; + + while (args[idx] != NULL) { + gchar *opt = args[idx]; + + if (strcmp(opt, "autojoin") == 0) { + autojoin = TRUE; + } else if (jid == NULL) { + jid = opt; + } else if (nick == NULL) { + nick = opt; + } else { + cons_show("Usage: %s", help.usage); + } + + ++idx; + } + + if (jid == NULL) { + win_type_t win_type = ui_current_win_type(); + + if (win_type == WIN_MUC) { + jid = ui_current_recipient(); + jid_release = TRUE; + nick = muc_get_room_nick(jid); + } else { + cons_show("Usage: %s", help.usage); + return TRUE; + } + } + + if (strcmp(cmd, "add") == 0) { + bookmark_add(jid, nick, autojoin); + } else if (strcmp(cmd, "remove") == 0) { + bookmark_remove(jid, autojoin); + } else { + cons_show("Usage: %s", help.usage); + } + + if (jid_release) { + free(jid); + } + } + + return TRUE; +} + static gboolean _cmd_disco(gchar **args, struct cmd_help_t help) { @@ -3588,6 +3684,34 @@ _group_autocomplete(char *input, int *size) return NULL; } +static char * +_bookmark_autocomplete(char *input, int *size) +{ + char *result = NULL; + + if (strcmp(input, "/bookmark add ") == 0) { + GString *str = g_string_new(input); + + str = g_string_append(str, "autojoin"); + result = str->str; + g_string_free(str, FALSE); + return result; + } + + result = autocomplete_param_with_func(input, size, "/bookmark list", bookmark_find); + if (result != NULL) { + return result; + } + result = autocomplete_param_with_func(input, size, "/bookmark remove", bookmark_find); + if (result != NULL) { + return result; + } + + result = autocomplete_param_with_ac(input, size, "/bookmark", bookmark_ac); + + return result; +} + static char * _notify_autocomplete(char *input, int *size) { diff --git a/src/ui/console.c b/src/ui/console.c index ee5ad221..50d2b649 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -37,6 +37,7 @@ #include "ui/window.h" #include "ui/ui.h" #include "xmpp/xmpp.h" +#include "xmpp/bookmark.h" #define CONS_WIN_TITLE "_cons" @@ -643,6 +644,34 @@ cons_show_room_list(GSList *rooms, const char * const conference_node) cons_alert(); } +void +cons_show_bookmarks(const GList *list) +{ + Bookmark *item; + + cons_show(""); + cons_show("Bookmarks:"); + + /* TODO: show status (connected or not) and window number */ + while (list != NULL) { + item = list->data; + + win_print_time(console, '-'); + wprintw(console->win, " %s", item->jid); + if (item->nick != NULL) { + wprintw(console->win, "/%s", item->nick); + } + if (item->autojoin) { + wprintw(console->win, " (autojoin)"); + } + wprintw(console->win, "\n"); + list = g_list_next(list); + } + + ui_console_dirty(); + cons_alert(); +} + void cons_show_disco_info(const char *jid, GSList *identities, GSList *features) { diff --git a/src/ui/ui.h b/src/ui/ui.h index d8ac22fa..f0601753 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -184,6 +184,7 @@ void cons_show_software_version(const char * const jid, const char * const version, const char * const os); void cons_show_account_list(gchar **accounts); void cons_show_room_list(GSList *room, const char * const conference_node); +void cons_show_bookmarks(const GList *list); void cons_show_disco_items(GSList *items, const char * const jid); void cons_show_disco_info(const char *from, GSList *identities, GSList *features); void cons_show_room_invite(const char * const invitor, const char * const room, diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c index 52ac9244..4c636abf 100644 --- a/src/xmpp/bookmark.c +++ b/src/xmpp/bookmark.c @@ -12,6 +12,7 @@ #include "xmpp/connection.h" #include "xmpp/stanza.h" #include "xmpp/xmpp.h" +#include "xmpp/bookmark.h" #define BOOKMARK_TIMEOUT 5000 /* TODO: replace with a preference */ @@ -19,10 +20,14 @@ static int autojoin_count; +static Autocomplete bookmark_ac; +static GList *bookmark_list; + static int _bookmark_handle_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata); static int _bookmark_handle_delete(xmpp_conn_t * const conn, void * const userdata); +static void _bookmark_item_destroy(gpointer item); void bookmark_request(void) @@ -38,6 +43,15 @@ bookmark_request(void) } autojoin_count = 0; + if (bookmark_ac != NULL) { + autocomplete_free(bookmark_ac); + } + bookmark_ac = autocomplete_new(); + if (bookmark_list != NULL) { + g_list_free_full(bookmark_list, _bookmark_item_destroy); + bookmark_list = NULL; + } + xmpp_timed_handler_add(conn, _bookmark_handle_delete, BOOKMARK_TIMEOUT, id); xmpp_id_handler_add(conn, _bookmark_handle_result, id, id); @@ -47,6 +61,49 @@ bookmark_request(void) xmpp_stanza_release(iq); } +void +bookmark_add(const char *jid, const char *nick, gboolean autojoin) +{ + /* TODO: send request */ + /* TODO: manage bookmark_list */ + + /* this may be command for modifying */ + autocomplete_remove(bookmark_ac, jid); + autocomplete_add(bookmark_ac, strdup(jid)); +} + +void +bookmark_remove(const char *jid, gboolean autojoin) +{ + /* TODO: manage bookmark_list */ + if (autojoin) { + /* TODO: just set autojoin=0 */ + } else { + /* TODO: send request */ + autocomplete_remove(bookmark_ac, jid); + } +} + +const GList * +bookmark_get_list(void) +{ + return bookmark_list; +} + +char * +bookmark_find(char *search_str) +{ + return autocomplete_complete(bookmark_ac, search_str); +} + +void +bookmark_autocomplete_reset(void) +{ + if (bookmark_ac != NULL) { + autocomplete_reset(bookmark_ac); + } +} + static int _bookmark_handle_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) @@ -58,7 +115,9 @@ _bookmark_handle_result(xmpp_conn_t * const conn, char *name; char *jid; char *autojoin; + gboolean autojoin_val; Jid *my_jid; + Bookmark *item; xmpp_timed_handler_delete(conn, _bookmark_handle_delete); g_free(id); @@ -77,6 +136,9 @@ _bookmark_handle_result(xmpp_conn_t * const conn, return 0; } + if (bookmark_ac == NULL) { + bookmark_ac = autocomplete_new(); + } my_jid = jid_create(jabber_get_fulljid()); ptr = xmpp_stanza_get_children(ptr); @@ -92,42 +154,55 @@ _bookmark_handle_result(xmpp_conn_t * const conn, log_debug("Handle bookmark for %s", jid); - autojoin = xmpp_stanza_get_attribute(ptr, "autojoin"); - if (autojoin && strcmp(autojoin, "1") == 0) { - name = NULL; - nick = xmpp_stanza_get_child_by_name(ptr, "nick"); - if (nick) { - char *tmp; - tmp = xmpp_stanza_get_text(nick); - if (tmp) { - name = strdup(tmp); - xmpp_free(ctx, tmp); - } - } else { - name = strdup(my_jid->localpart); - } - - if (name) { - if (autojoin_count < BOOKMARK_AUTOJOIN_MAX) { - Jid *room_jid; - - log_debug("Autojoin %s with nick=%s", jid, name); - ++autojoin_count; - room_jid = jid_create_from_bare_and_resource(jid, name); - if (!muc_room_is_active(room_jid)) { - presence_join_room(room_jid); - /* TODO: this should be removed after fixing #195 */ - ui_room_join(room_jid); - } - jid_destroy(room_jid); - } else { - log_debug("Rejected autojoin %s (maximum has been reached)", jid); - } - free(name); + name = NULL; + nick = xmpp_stanza_get_child_by_name(ptr, "nick"); + if (nick) { + char *tmp; + tmp = xmpp_stanza_get_text(nick); + if (tmp) { + name = strdup(tmp); + xmpp_free(ctx, tmp); } } - /* TODO: add to autocompleter */ + autojoin = xmpp_stanza_get_attribute(ptr, "autojoin"); + if (autojoin && strcmp(autojoin, "1") == 0) { + autojoin_val = TRUE; + } else { + autojoin_val = FALSE; + } + + autocomplete_add(bookmark_ac, strdup(jid)); + item = malloc(sizeof(*item)); + item->jid = strdup(jid); + item->nick = name; + item->autojoin = autojoin_val; + bookmark_list = g_list_append(bookmark_list, item); + + + /* TODO: preference whether autojoin */ + if (autojoin_val) { + if (autojoin_count < BOOKMARK_AUTOJOIN_MAX) { + Jid *room_jid; + + ++autojoin_count; + + if (name == NULL) { + name = my_jid->localpart; + } + + log_debug("Autojoin %s with nick=%s", jid, name); + room_jid = jid_create_from_bare_and_resource(jid, name); + if (!muc_room_is_active(room_jid)) { + presence_join_room(room_jid); + /* TODO: this should be removed after fixing #195 */ + ui_room_join(room_jid); + } + jid_destroy(room_jid); + } else { + log_debug("Rejected autojoin %s (maximum has been reached)", jid); + } + } ptr = xmpp_stanza_get_next(ptr); } @@ -152,3 +227,17 @@ _bookmark_handle_delete(xmpp_conn_t * const conn, return 0; } + +static void +_bookmark_item_destroy(gpointer item) +{ + Bookmark *p = (Bookmark *)item; + + if (p == NULL) { + return; + } + + free(p->jid); + free(p->nick); + free(p); +} diff --git a/src/xmpp/bookmark.h b/src/xmpp/bookmark.h index d4ab8b5b..e15b6eab 100644 --- a/src/xmpp/bookmark.h +++ b/src/xmpp/bookmark.h @@ -2,6 +2,21 @@ #ifndef BOOKMARK_H #define BOOKMARK_H +#include + +struct bookmark_t { + char *jid; + char *nick; + gboolean autojoin; +}; + +typedef struct bookmark_t Bookmark; + void bookmark_request(void); +void bookmark_add(const char *jid, const char *nick, gboolean autojoin); +void bookmark_remove(const char *jid, gboolean autojoin); +const GList *bookmark_get_list(void); +char *bookmark_find(char *search_str); +void bookmark_autocomplete_reset(void); #endif From 7906bd6a9dc76a98d9bd63c4ea30801f0f91a485 Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 15 Jul 2013 00:52:47 +0100 Subject: [PATCH 05/24] Bookmarks: Move stanza pointer on in loop, check for autojoin "true" --- src/xmpp/bookmark.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c index 4c636abf..92e6d7e8 100644 --- a/src/xmpp/bookmark.c +++ b/src/xmpp/bookmark.c @@ -144,11 +144,13 @@ _bookmark_handle_result(xmpp_conn_t * const conn, ptr = xmpp_stanza_get_children(ptr); while (ptr) { name = xmpp_stanza_get_name(ptr); - if (strcmp(name, STANZA_NAME_CONFERENCE) != 0) { + if (!name || strcmp(name, STANZA_NAME_CONFERENCE) != 0) { + ptr = xmpp_stanza_get_next(ptr); continue; } jid = xmpp_stanza_get_attribute(ptr, STANZA_ATTR_JID); if (!jid) { + ptr = xmpp_stanza_get_next(ptr); continue; } @@ -166,7 +168,7 @@ _bookmark_handle_result(xmpp_conn_t * const conn, } autojoin = xmpp_stanza_get_attribute(ptr, "autojoin"); - if (autojoin && strcmp(autojoin, "1") == 0) { + if (autojoin && (strcmp(autojoin, "1") == 0 || strcmp(autojoin, "true") == 0)) { autojoin_val = TRUE; } else { autojoin_val = FALSE; From 5505387c37f594db0368317a2349c429c8ddedfe Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Wed, 31 Jul 2013 01:51:07 +0300 Subject: [PATCH 06/24] fixed several memory leaks in command.c and jid.c --- src/command/command.c | 59 ++++++++++++++++++++++++++++++------------- src/jid.c | 44 ++++++++++++++++---------------- 2 files changed, 63 insertions(+), 40 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 2e31605d..d4851116 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -1121,7 +1121,6 @@ cmd_execute_default(const char * const inp) ui_current_print_line("You are not currently connected."); } else { message_send_groupchat(inp, recipient); - free(recipient); } break; @@ -1139,7 +1138,6 @@ cmd_execute_default(const char * const inp) } ui_outgoing_msg("me", recipient, inp); - free(recipient); } break; @@ -1149,7 +1147,6 @@ cmd_execute_default(const char * const inp) } else { message_send(inp, recipient); ui_outgoing_msg("me", recipient, inp); - free(recipient); } break; @@ -1163,7 +1160,6 @@ cmd_execute_default(const char * const inp) } else { message_send_duck(inp); ui_duck(inp); - free(recipient); } break; @@ -1171,6 +1167,8 @@ cmd_execute_default(const char * const inp) break; } + free(recipient); + return TRUE; } @@ -1197,7 +1195,9 @@ _cmd_complete_parameters(char *input, int *size) // autocomplete nickname in chat rooms if (ui_current_win_type() == WIN_MUC) { - Autocomplete nick_ac = muc_get_roster_ac(ui_current_recipient()); + char *recipient = ui_current_recipient(); + Autocomplete nick_ac = muc_get_roster_ac(recipient); + free(recipient); if (nick_ac != NULL) { gchar *nick_choices[] = { "/msg", "/info", "/caps", "/status", "/software" } ; @@ -1979,6 +1979,8 @@ _cmd_who(gchar **args, struct cmd_help_t help) ui_room_roster(room, filtered, presence); } + free(room); + // not in groupchat window } else { cons_show(""); @@ -2143,6 +2145,8 @@ _cmd_msg(gchar **args, struct cmd_help_t help) ui_current_print_line("No such participant \"%s\" in room.", usr); } + free(room_name); + return TRUE; } else { @@ -2464,17 +2468,20 @@ _cmd_info(gchar **args, struct cmd_help_t help) jabber_conn_status_t conn_status = jabber_get_connection_status(); win_type_t win_type = ui_current_win_type(); PContact pcontact = NULL; + char *recipient; if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); return TRUE; } + recipient = ui_current_recipient(); + switch (win_type) { case WIN_MUC: if (usr != NULL) { - pcontact = muc_get_participant(ui_current_recipient(), usr); + pcontact = muc_get_participant(recipient, usr); if (pcontact != NULL) { cons_show_info(pcontact); } else { @@ -2488,11 +2495,11 @@ _cmd_info(gchar **args, struct cmd_help_t help) if (usr != NULL) { cons_show("No parameter required for /info in chat."); } else { - pcontact = roster_get_contact(ui_current_recipient()); + pcontact = roster_get_contact(recipient); if (pcontact != NULL) { cons_show_info(pcontact); } else { - cons_show("No such contact \"%s\" in roster.", ui_current_recipient()); + cons_show("No such contact \"%s\" in roster.", recipient); } } break; @@ -2500,7 +2507,7 @@ _cmd_info(gchar **args, struct cmd_help_t help) if (usr != NULL) { ui_current_print_line("No parameter required when in chat."); } else { - Jid *jid = jid_create(ui_current_recipient()); + Jid *jid = jid_create(recipient); pcontact = muc_get_participant(jid->barejid, jid->resourcepart); if (pcontact != NULL) { cons_show_info(pcontact); @@ -2530,6 +2537,8 @@ _cmd_info(gchar **args, struct cmd_help_t help) break; } + free(recipient); + return TRUE; } @@ -2539,6 +2548,7 @@ _cmd_caps(gchar **args, struct cmd_help_t help) jabber_conn_status_t conn_status = jabber_get_connection_status(); win_type_t win_type = ui_current_win_type(); PContact pcontact = NULL; + char *recipient; if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); @@ -2549,13 +2559,15 @@ _cmd_caps(gchar **args, struct cmd_help_t help) { case WIN_MUC: if (args[0] != NULL) { - pcontact = muc_get_participant(ui_current_recipient(), args[0]); + recipient = ui_current_recipient(); + pcontact = muc_get_participant(recipient, args[0]); if (pcontact != NULL) { Resource *resource = p_contact_get_resource(pcontact, args[0]); cons_show_caps(args[0], resource); } else { cons_show("No such participant \"%s\" in room.", args[0]); } + free(recipient); } else { cons_show("No nickname supplied to /caps in chat room."); } @@ -2588,10 +2600,15 @@ _cmd_caps(gchar **args, struct cmd_help_t help) if (args[0] != NULL) { cons_show("No parameter needed to /caps when in private chat."); } else { - Jid *jid = jid_create(ui_current_recipient()); - pcontact = muc_get_participant(jid->barejid, jid->resourcepart); - Resource *resource = p_contact_get_resource(pcontact, jid->resourcepart); - cons_show_caps(jid->resourcepart, resource); + recipient = ui_current_recipient(); + Jid *jid = jid_create(recipient); + if (jid) { + pcontact = muc_get_participant(jid->barejid, jid->resourcepart); + Resource *resource = p_contact_get_resource(pcontact, jid->resourcepart); + cons_show_caps(jid->resourcepart, resource); + jid_destroy(jid); + } + free(recipient); } break; default: @@ -2608,6 +2625,7 @@ _cmd_software(gchar **args, struct cmd_help_t help) jabber_conn_status_t conn_status = jabber_get_connection_status(); win_type_t win_type = ui_current_win_type(); PContact pcontact = NULL; + char *recipient; if (conn_status != JABBER_CONNECTED) { cons_show("You are not currently connected."); @@ -2618,14 +2636,16 @@ _cmd_software(gchar **args, struct cmd_help_t help) { case WIN_MUC: if (args[0] != NULL) { - pcontact = muc_get_participant(ui_current_recipient(), args[0]); + recipient = ui_current_recipient(); + pcontact = muc_get_participant(recipient, args[0]); if (pcontact != NULL) { - Jid *jid = jid_create_from_bare_and_resource(ui_current_recipient(), args[0]); + Jid *jid = jid_create_from_bare_and_resource(recipient, args[0]); iq_send_software_version(jid->fulljid); jid_destroy(jid); } else { cons_show("No such participant \"%s\" in room.", args[0]); } + free(recipient); } else { cons_show("No nickname supplied to /software in chat room."); } @@ -2635,11 +2655,12 @@ _cmd_software(gchar **args, struct cmd_help_t help) if (args[0] != NULL) { Jid *jid = jid_create(args[0]); - if (jid->fulljid == NULL) { + if (jid == NULL || jid->fulljid == NULL) { cons_show("You must provide a full jid to the /software command."); } else { iq_send_software_version(jid->fulljid); } + jid_destroy(jid); } else { cons_show("You must provide a jid to the /software command."); } @@ -2648,7 +2669,9 @@ _cmd_software(gchar **args, struct cmd_help_t help) if (args[0] != NULL) { cons_show("No parameter needed to /software when in private chat."); } else { - iq_send_software_version(ui_current_recipient()); + recipient = ui_current_recipient(); + iq_send_software_version(recipient); + free(recipient); } break; default: diff --git a/src/jid.c b/src/jid.c index 6347f083..81f51745 100644 --- a/src/jid.c +++ b/src/jid.c @@ -34,13 +34,14 @@ jid_create(const gchar * const str) { Jid *result = NULL; - if (str == NULL) { + /* if str is NULL g_strdup returns NULL */ + gchar *trimmed = g_strdup(str); + if (trimmed == NULL) { return NULL; } - gchar *trimmed = g_strdup(str); - if (strlen(trimmed) == 0) { + g_free(trimmed); return NULL; } @@ -50,10 +51,12 @@ jid_create(const gchar * const str) } if (!g_utf8_validate(trimmed, -1, NULL)) { + g_free(trimmed); return NULL; } result = malloc(sizeof(struct jid_t)); + result->str = NULL; result->localpart = NULL; result->domainpart = NULL; result->resourcepart = NULL; @@ -81,13 +84,11 @@ jid_create(const gchar * const str) } if (result->domainpart == NULL) { - free(trimmed); + jid_destroy(result); return NULL; } - result->str = g_strdup(trimmed); - - free(trimmed); + result->str = trimmed; return result; } @@ -181,17 +182,17 @@ char * get_room_from_full_jid(const char * const full_room_jid) { char **tokens = g_strsplit(full_room_jid, "/", 0); - char *room_part; + char *room_part = NULL; - if (tokens == NULL || tokens[0] == NULL) { - return NULL; - } else { - room_part = strdup(tokens[0]); + if (tokens != NULL) { + if (tokens[0] != NULL) { + room_part = strdup(tokens[0]); + } g_strfreev(tokens); - - return room_part; } + + return room_part; } /* @@ -203,16 +204,15 @@ char * get_nick_from_full_jid(const char * const full_room_jid) { char **tokens = g_strsplit(full_room_jid, "/", 0); - char *nick_part; + char *nick_part = NULL; - if (tokens == NULL || tokens[1] == NULL) { - return NULL; - } else { - nick_part = strdup(tokens[1]); + if (tokens != NULL) { + if (tokens[0] != NULL && tokens[1] != NULL) { + nick_part = strdup(tokens[1]); + } g_strfreev(tokens); - - return nick_part; } -} + return nick_part; +} From f2638e001aef47c04168784e6f45af7264bcd309 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Wed, 31 Jul 2013 01:53:10 +0300 Subject: [PATCH 07/24] rewritten FREE_SET_NULL and GFREE_SET_NULL NULL is valid argument for free(). Construction do {} while (0) allows using FREE_SET_NULL as one token and force to put semicolon at the end. --- src/common.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/common.h b/src/common.h index b87f2a97..f8ed82a5 100644 --- a/src/common.h +++ b/src/common.h @@ -42,18 +42,16 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define FREE_SET_NULL(resource) \ -{ \ - if (resource != NULL) { \ - free(resource); \ - resource = NULL; \ - } \ -} +do { \ + free(resource); \ + resource = NULL; \ +} while (0) #define GFREE_SET_NULL(resource) \ -{ \ +do { \ g_free(resource); \ resource = NULL; \ -} +} while (0) typedef enum { CONTACT_OFFLINE, From 7b37f2ace7536ae12f1726819cb0b6224232361c Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Wed, 31 Jul 2013 02:03:22 +0300 Subject: [PATCH 08/24] separate glib allocator and stdlib malloc/free Memory allocated by glib should be freed by g_free. Probably g_free calls stdlib free, but in order to avoid portability issues better use g_free as described in glib documentation. --- src/jid.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/jid.c b/src/jid.c index 81f51745..b236c164 100644 --- a/src/jid.c +++ b/src/jid.c @@ -108,12 +108,12 @@ void jid_destroy(Jid *jid) { if (jid != NULL) { - FREE_SET_NULL(jid->str); - FREE_SET_NULL(jid->localpart); - FREE_SET_NULL(jid->domainpart); - FREE_SET_NULL(jid->resourcepart); - FREE_SET_NULL(jid->barejid); - FREE_SET_NULL(jid->fulljid); + GFREE_SET_NULL(jid->str); + GFREE_SET_NULL(jid->localpart); + GFREE_SET_NULL(jid->domainpart); + GFREE_SET_NULL(jid->resourcepart); + GFREE_SET_NULL(jid->barejid); + GFREE_SET_NULL(jid->fulljid); FREE_SET_NULL(jid); } } From c559d96d7739d499f9b747839e1115d28976306f Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 3 Aug 2013 13:17:50 +0300 Subject: [PATCH 09/24] removed sizeof(char) sizeof(char) == 1 according to standard --- src/command/command.c | 2 +- src/tools/autocomplete.c | 4 ++-- src/ui/statusbar.c | 2 +- src/ui/titlebar.c | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 45086e18..1017b899 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -1041,7 +1041,7 @@ cmd_autocomplete(char *input, int *size) inp_cpy[i] = '\0'; found = autocomplete_complete(commands_ac, inp_cpy); if (found != NULL) { - auto_msg = (char *) malloc((strlen(found) + 1) * sizeof(char)); + auto_msg = (char *) malloc(strlen(found) + 1); strcpy(auto_msg, found); inp_replace_input(input, auto_msg, size); free(auto_msg); diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c index 0c56cac7..8426de85 100644 --- a/src/tools/autocomplete.c +++ b/src/tools/autocomplete.c @@ -220,7 +220,7 @@ autocomplete_param_with_func(char *input, int *size, char *command, inp_cpy[(*size) - len] = '\0'; found = func(inp_cpy); if (found != NULL) { - auto_msg = (char *) malloc((len + (strlen(found) + 1)) * sizeof(char)); + auto_msg = (char *) malloc(len + strlen(found) + 1); strcpy(auto_msg, command_cpy); strcat(auto_msg, found); free(found); @@ -249,7 +249,7 @@ autocomplete_param_with_ac(char *input, int *size, char *command, inp_cpy[(*size) - len] = '\0'; found = autocomplete_complete(ac, inp_cpy); if (found != NULL) { - auto_msg = (char *) malloc((len + (strlen(found) + 1)) * sizeof(char)); + auto_msg = (char *) malloc(len + strlen(found) + 1); strcpy(auto_msg, command_cpy); strcat(auto_msg, found); free(found); diff --git a/src/ui/statusbar.c b/src/ui/statusbar.c index 3f0798d3..cd218e73 100644 --- a/src/ui/statusbar.c +++ b/src/ui/statusbar.c @@ -191,7 +191,7 @@ status_bar_print_message(const char * const msg) werase(status_bar); - message = (char *) malloc((strlen(msg) + 1) * sizeof(char)); + message = (char *) malloc(strlen(msg) + 1); strcpy(message, msg); mvwprintw(status_bar, 0, 10, message); diff --git a/src/ui/titlebar.c b/src/ui/titlebar.c index 4b3ca997..791a5fbe 100644 --- a/src/ui/titlebar.c +++ b/src/ui/titlebar.c @@ -87,7 +87,7 @@ title_bar_refresh(void) free(current_title); } - current_title = (char *) malloc((strlen(recipient) + 1) * sizeof(char)); + current_title = (char *) malloc(strlen(recipient) + 1); strcpy(current_title, recipient); title_bar_draw(); @@ -113,7 +113,7 @@ title_bar_show(const char * const title) if (current_title != NULL) free(current_title); - current_title = (char *) malloc((strlen(title) + 1) * sizeof(char)); + current_title = (char *) malloc(strlen(title) + 1); strcpy(current_title, title); _title_bar_draw_title(); } @@ -138,7 +138,7 @@ title_bar_set_recipient(const char * const from) free(current_title); } - current_title = (char *) malloc((strlen(from) + 1) * sizeof(char)); + current_title = (char *) malloc(strlen(from) + 1); strcpy(current_title, from); dirty = TRUE; @@ -160,10 +160,10 @@ title_bar_set_typing(gboolean is_typing) } if (is_typing) { - current_title = (char *) malloc((strlen(recipient) + 13) * sizeof(char)); + current_title = (char *) malloc(strlen(recipient) + 13); sprintf(current_title, "%s (typing...)", recipient); } else { - current_title = (char *) malloc((strlen(recipient) + 1) * sizeof(char)); + current_title = (char *) malloc(strlen(recipient) + 1); strcpy(current_title, recipient); } From 6f498d1f69098742acc33d429c5e8dcee4edd86d Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 3 Aug 2013 14:14:30 +0300 Subject: [PATCH 10/24] refactored mkdir_recursive Now this function returns result of operation. TRUE is success. --- src/common.c | 32 ++++++++++++++++++++++++-------- src/common.h | 4 ++-- src/profanity.c | 12 +++++++++--- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/common.c b/src/common.c index e2ff0171..da33cc3d 100644 --- a/src/common.c +++ b/src/common.c @@ -25,12 +25,14 @@ #include #include #include +#include #include #include #include #include +#include "log.h" #include "common.h" // assume malloc stores at most 8 bytes for size of allocated memory @@ -69,29 +71,43 @@ p_slist_free_full(GSList *items, GDestroyNotify free_func) g_slist_free (items); } -void +gboolean create_dir(char *name) { - int e; struct stat sb; - e = stat(name, &sb); - if (e != 0) - if (errno == ENOENT) - e = mkdir(name, S_IRWXU); + if (stat(name, &sb) != 0) { + if (errno != ENOENT || mkdir(name, S_IRWXU) != 0) { + return FALSE; + } + } else { + if ((sb.st_mode & S_IFDIR) != S_IFDIR) { + log_debug("create_dir: %s exists and is not a directory!", name); + return FALSE; + } + } + + return TRUE; } -void +gboolean mkdir_recursive(const char *dir) { int i; + gboolean result = TRUE; + for (i = 1; i <= strlen(dir); i++) { if (dir[i] == '/' || dir[i] == '\0') { gchar *next_dir = g_strndup(dir, i); - create_dir(next_dir); + result = create_dir(next_dir); g_free(next_dir); + if (!result) { + break; + } } } + + return result; } char * diff --git a/src/common.h b/src/common.h index f8ed82a5..469a63ec 100644 --- a/src/common.h +++ b/src/common.h @@ -72,8 +72,8 @@ typedef enum { gchar* p_utf8_substring(const gchar *str, glong start_pos, glong end_pos); void p_slist_free_full(GSList *items, GDestroyNotify free_func); -void create_dir(char *name); -void mkdir_recursive(const char *dir); +gboolean create_dir(char *name); +gboolean mkdir_recursive(const char *dir); char * str_replace(const char *string, const char *substr, const char *replacement); int str_contains(char str[], int size, char ch); diff --git a/src/profanity.c b/src/profanity.c index 9c729ca1..4e9e887c 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -664,9 +664,15 @@ _create_directories(void) GString *logs_dir = g_string_new(xdg_data); g_string_append(logs_dir, "/profanity/logs"); - mkdir_recursive(themes_dir->str); - mkdir_recursive(chatlogs_dir->str); - mkdir_recursive(logs_dir->str); + if (!mkdir_recursive(themes_dir->str)) { + log_error("Error while creating directory %s", themes_dir->str); + } + if (!mkdir_recursive(chatlogs_dir->str)) { + log_error("Error while creating directory %s", chatlogs_dir->str); + } + if (!mkdir_recursive(logs_dir->str)) { + log_error("Error while creating directory %s", logs_dir->str); + } g_string_free(themes_dir, TRUE); g_string_free(chatlogs_dir, TRUE); From 0346fda0b3ddc484c3a28d88a5c42b890feb3079 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 3 Aug 2013 14:27:07 +0300 Subject: [PATCH 11/24] most FREE_SET_NULL replaced with free FREE_SET_NULL makes extra assignment of NULL for pointers in stack or dynamic memory that is going to be freed. FREE_SET_NULL is useful for pointers that can be used in future. --- src/config/accounts.c | 14 +++++++------- src/contact.c | 36 ++++++++++++++++-------------------- src/jid.c | 14 +++++++------- src/muc.c | 20 ++++---------------- src/resource.c | 11 ++++++----- src/tools/autocomplete.c | 6 ++---- src/ui/console.c | 2 +- src/ui/core.c | 5 +++-- src/xmpp/capabilities.c | 17 ++++++++--------- src/xmpp/presence.c | 26 +++++++++++++++----------- src/xmpp/stanza.c | 8 ++++---- 11 files changed, 73 insertions(+), 86 deletions(-) diff --git a/src/config/accounts.c b/src/config/accounts.c index 876ff870..c82f6b2d 100644 --- a/src/config/accounts.c +++ b/src/config/accounts.c @@ -236,13 +236,13 @@ void accounts_free_account(ProfAccount *account) { if (account != NULL) { - FREE_SET_NULL(account->name); - FREE_SET_NULL(account->jid); - FREE_SET_NULL(account->resource); - FREE_SET_NULL(account->server); - FREE_SET_NULL(account->last_presence); - FREE_SET_NULL(account->login_presence); - FREE_SET_NULL(account); + free(account->name); + free(account->jid); + free(account->resource); + free(account->server); + free(account->last_presence); + free(account->login_presence); + free(account); } } diff --git a/src/contact.c b/src/contact.c index 44cbd4b4..1b566d40 100644 --- a/src/contact.c +++ b/src/contact.c @@ -79,14 +79,9 @@ p_contact_new(const char * const barejid, const char * const name, void p_contact_set_name(const PContact contact, const char * const name) { - if (contact->name != NULL) { - FREE_SET_NULL(contact->name); - } - + FREE_SET_NULL(contact->name); if (name != NULL) { contact->name = strdup(name); - } else { - FREE_SET_NULL(contact->name); } } @@ -130,22 +125,23 @@ p_contact_remove_resource(PContact contact, const char * const resource) void p_contact_free(PContact contact) { - FREE_SET_NULL(contact->barejid); - FREE_SET_NULL(contact->name); - FREE_SET_NULL(contact->subscription); - FREE_SET_NULL(contact->offline_message); + if (contact != NULL) { + free(contact->barejid); + free(contact->name); + free(contact->subscription); + free(contact->offline_message); - if (contact->groups != NULL) { - g_slist_free_full(contact->groups, g_free); + if (contact->groups != NULL) { + g_slist_free_full(contact->groups, g_free); + } + + if (contact->last_activity != NULL) { + g_date_time_unref(contact->last_activity); + } + + g_hash_table_destroy(contact->available_resources); + free(contact); } - - if (contact->last_activity != NULL) { - g_date_time_unref(contact->last_activity); - } - - g_hash_table_destroy(contact->available_resources); - - FREE_SET_NULL(contact); } const char * diff --git a/src/jid.c b/src/jid.c index b236c164..6840b64b 100644 --- a/src/jid.c +++ b/src/jid.c @@ -108,13 +108,13 @@ void jid_destroy(Jid *jid) { if (jid != NULL) { - GFREE_SET_NULL(jid->str); - GFREE_SET_NULL(jid->localpart); - GFREE_SET_NULL(jid->domainpart); - GFREE_SET_NULL(jid->resourcepart); - GFREE_SET_NULL(jid->barejid); - GFREE_SET_NULL(jid->fulljid); - FREE_SET_NULL(jid); + g_free(jid->str); + g_free(jid->localpart); + g_free(jid->domainpart); + g_free(jid->resourcepart); + g_free(jid->barejid); + g_free(jid->fulljid); + free(jid); } } diff --git a/src/muc.c b/src/muc.c index 464d3e1b..1e706f6a 100644 --- a/src/muc.c +++ b/src/muc.c @@ -442,32 +442,20 @@ static void _free_room(ChatRoom *room) { if (room != NULL) { - if (room->room != NULL) { - g_free(room->room); - room->room = NULL; - } - if (room->nick != NULL) { - g_free(room->nick); - room->nick = NULL; - } - if (room->subject != NULL) { - g_free(room->subject); - room->subject = NULL; - } + free(room->room); + free(room->nick); + free(room->subject); if (room->roster != NULL) { g_hash_table_remove_all(room->roster); - room->roster = NULL; } if (room->nick_ac != NULL) { autocomplete_free(room->nick_ac); } if (room->nick_changes != NULL) { g_hash_table_remove_all(room->nick_changes); - room->nick_changes = NULL; } - g_free(room); + free(room); } - room = NULL; } static diff --git a/src/resource.c b/src/resource.c index 0a7838f3..86ba7e18 100644 --- a/src/resource.c +++ b/src/resource.c @@ -81,9 +81,10 @@ resource_compare_availability(Resource *first, Resource *second) void resource_destroy(Resource *resource) { - assert(resource != NULL); - FREE_SET_NULL(resource->name); - FREE_SET_NULL(resource->status); - FREE_SET_NULL(resource->caps_str); - FREE_SET_NULL(resource); + if (resource != NULL) { + free(resource->name); + free(resource->status); + free(resource->caps_str); + free(resource); + } } diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c index 8426de85..5c70f874 100644 --- a/src/tools/autocomplete.c +++ b/src/tools/autocomplete.c @@ -24,6 +24,7 @@ #include #include +#include "common.h" #include "tools/autocomplete.h" #include "tools/parser.h" @@ -59,10 +60,7 @@ void autocomplete_reset(Autocomplete ac) { ac->last_found = NULL; - if (ac->search_str != NULL) { - free(ac->search_str); - ac->search_str = NULL; - } + FREE_SET_NULL(ac->search_str); } void diff --git a/src/ui/console.c b/src/ui/console.c index 50d2b649..6efc1cf1 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -784,7 +784,7 @@ cons_show_room_invite(const char * const invitor, const char * const room, notify_invite(display_from, room, reason); } - FREE_SET_NULL(display_from); + free(display_from); ui_console_dirty(); cons_alert(); diff --git a/src/ui/core.c b/src/ui/core.c index 126fe127..6b0b2d8d 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -293,8 +293,9 @@ ui_incoming_msg(const char * const from, const char * const message, GTimeVal *tv_stamp, gboolean priv) { gboolean win_created = FALSE; - char *display_from; + char *display_from = NULL; win_type_t win_type; + if (priv) { win_type = WIN_PRIVATE; display_from = get_nick_from_full_jid(from); @@ -436,7 +437,7 @@ ui_incoming_msg(const char * const from, const char * const message, if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) notify_message(display_from, ui_index); - FREE_SET_NULL(display_from); + free(display_from); } void diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c index 10aa8a38..f9624f90 100644 --- a/src/xmpp/capabilities.c +++ b/src/xmpp/capabilities.c @@ -301,17 +301,16 @@ static void _caps_destroy(Capabilities *caps) { if (caps != NULL) { - FREE_SET_NULL(caps->category); - FREE_SET_NULL(caps->type); - FREE_SET_NULL(caps->name); - FREE_SET_NULL(caps->software); - FREE_SET_NULL(caps->software_version); - FREE_SET_NULL(caps->os); - FREE_SET_NULL(caps->os_version); + free(caps->category); + free(caps->type); + free(caps->name); + free(caps->software); + free(caps->software_version); + free(caps->os); + free(caps->os_version); if (caps->features != NULL) { g_slist_free_full(caps->features, free); - caps->features = NULL; } - FREE_SET_NULL(caps); + free(caps); } } diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index f072196d..6c87a8ac 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -385,7 +385,7 @@ _unavailable_handler(xmpp_conn_t * const conn, } } - FREE_SET_NULL(status_str); + free(status_str); jid_destroy(my_jid); jid_destroy(from_jid); @@ -471,8 +471,8 @@ _available_handler(xmpp_conn_t * const conn, last_activity); } - FREE_SET_NULL(status_str); - FREE_SET_NULL(show_str); + free(status_str); + free(show_str); jid_destroy(my_jid); jid_destroy(from_jid); @@ -556,10 +556,11 @@ _room_presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, return 1; } - const char *jid = xmpp_conn_get_jid(conn); char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); - Jid *my_jid = jid_create(jid); Jid *from_jid = jid_create(from); + if (from_jid == NULL || from_jid->resourcepart == NULL) { + return 1; + } char *room = from_jid->barejid; char *nick = from_jid->resourcepart; @@ -592,7 +593,7 @@ _room_presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, // handle presence from room members } else { char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); - char *show_str, *status_str; + char *status_str; char *caps_key = NULL; if (stanza_contains_caps(stanza)) { @@ -608,12 +609,15 @@ _room_presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, // handle nickname change if (stanza_is_room_nick_change(stanza)) { char *new_nick = stanza_get_new_nick(stanza); - muc_set_roster_pending_nick_change(room, new_nick, nick); + if (new_nick != NULL) { + muc_set_roster_pending_nick_change(room, new_nick, nick); + free(new_nick); + } } else { prof_handle_room_member_offline(room, nick, "offline", status_str); } } else { - show_str = stanza_get_show(stanza, "online"); + char *show_str = stanza_get_show(stanza, "online"); if (!muc_get_roster_received(room)) { muc_add_to_roster(room, nick, show_str, status_str, caps_key); } else { @@ -631,13 +635,13 @@ _room_presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, } } - FREE_SET_NULL(show_str); + free(show_str); } - FREE_SET_NULL(status_str); + free(status_str); + free(caps_key); } - jid_destroy(my_jid); jid_destroy(from_jid); return 1; diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 4d7d1f9d..61db0537 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -140,7 +140,7 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient, xmpp_stanza_set_name(chat_state, state); xmpp_stanza_set_ns(chat_state, STANZA_NS_CHATSTATES); xmpp_stanza_add_child(msg, chat_state); - xmpp_stanza_release(chat_state); + xmpp_stanza_release(chat_state); } return msg; @@ -840,12 +840,11 @@ void stanza_destroy_form(DataForm *form) { if (form != NULL) { - FREE_SET_NULL(form->form_type); if (form->fields != NULL) { GSList *curr_field = form->fields; while (curr_field != NULL) { FormField *field = curr_field->data; - FREE_SET_NULL(field->var); + free(field->var); if ((field->values) != NULL) { g_slist_free_full(field->values, free); } @@ -854,6 +853,7 @@ stanza_destroy_form(DataForm *form) g_slist_free_full(form->fields, free); } + free(form->form_type); free(form); } } @@ -941,7 +941,7 @@ stanza_attach_caps(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence) xmpp_stanza_add_child(presence, caps); xmpp_stanza_release(caps); xmpp_stanza_release(query); - FREE_SET_NULL(sha1); + g_free(sha1); } const char * From 28ec3334cf616c275440546269083fab44a07a60 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 3 Aug 2013 14:31:36 +0300 Subject: [PATCH 12/24] refactored logging Use ftell instead of stat syscall to increase portability. --- src/log.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/log.c b/src/log.c index 1f877d21..7a57fa98 100644 --- a/src/log.c +++ b/src/log.c @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include "glib.h" @@ -37,11 +35,6 @@ #define PROF "prof" -#ifdef _WIN32 -// replace 'struct stat' and 'stat()' for windows -#define stat _stat -#endif - static FILE *logp; static GTimeZone *tz; @@ -125,7 +118,7 @@ log_init(log_level_t filter) tz = g_time_zone_new_local(); gchar *log_file = _get_log_file(); logp = fopen(log_file, "a"); - g_free(log_file); + free(log_file); } log_level_t @@ -145,9 +138,7 @@ void log_msg(log_level_t level, const char * const area, const char * const msg) { if (level >= level_filter) { - struct stat st; - int result; - gchar *log_file = _get_log_file(); + long result; dt = g_date_time_new_now(tz); gchar *date_fmt = g_date_time_format(dt, "%d/%m/%Y %H:%M:%S"); @@ -157,12 +148,10 @@ log_msg(log_level_t level, const char * const area, const char * const msg) fflush(logp); g_free(date_fmt); - result = stat(log_file, &st); - if (result == 0 && st.st_size >= prefs_get_max_log_size()) { + result = ftell(logp); + if (result != -1 && result >= prefs_get_max_log_size()) { _rotate_log_file(); } - - g_free(log_file); } } @@ -200,7 +189,7 @@ _rotate_log_file(void) log_init(log_get_filter()); free(log_file_new); - g_free(log_file); + free(log_file); log_info("Log has been rotated"); } @@ -448,7 +437,7 @@ _get_log_filename(const char * const other, const char * const login, { gchar *chatlogs_dir = _get_chatlog_dir(); GString *log_file = g_string_new(chatlogs_dir); - g_free(chatlogs_dir); + free(chatlogs_dir); gchar *login_dir = str_replace(login, "@", "_at_"); g_string_append_printf(log_file, "/%s", login_dir); @@ -516,7 +505,7 @@ _get_chatlog_dir(void) GString *chatlogs_dir = g_string_new(xdg_data); g_string_append(chatlogs_dir, "/profanity/chatlogs"); gchar *result = strdup(chatlogs_dir->str); - g_free(xdg_data); + free(xdg_data); g_string_free(chatlogs_dir, TRUE); return result; @@ -529,7 +518,7 @@ _get_log_file(void) GString *logfile = g_string_new(xdg_data); g_string_append(logfile, "/profanity/logs/profanity.log"); gchar *result = strdup(logfile->str); - g_free(xdg_data); + free(xdg_data); g_string_free(logfile, TRUE); return result; From a6e66cc57106402944445fc709625dcf88785a5b Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 3 Aug 2013 14:38:38 +0300 Subject: [PATCH 13/24] fixed memory leaks Also avoided several NULL pointer dereferences. --- src/ui/notifier.c | 6 ++--- src/xmpp/capabilities.c | 32 +++++++++++----------- src/xmpp/iq.c | 20 +++++++------- src/xmpp/message.c | 6 +++++ src/xmpp/presence.c | 60 +++++++++++++++++++++++++++++++++-------- 5 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/ui/notifier.c b/src/ui/notifier.c index f43c8c25..403c215e 100644 --- a/src/ui/notifier.c +++ b/src/ui/notifier.c @@ -80,7 +80,7 @@ notify_invite(const char * const from, const char * const room, _notify(message->str, 10000, "Incoming message"); - g_string_free(message, FALSE); + g_string_free(message, TRUE); } void @@ -102,7 +102,7 @@ notify_room_message(const char * const handle, const char * const room, int win) _notify(text->str, 10000, "incoming message"); - g_string_free(text, FALSE); + g_string_free(text, TRUE); } void @@ -111,7 +111,7 @@ notify_subscription(const char * const from) GString *message = g_string_new("Subscription request: \n"); g_string_append(message, from); _notify(message->str, 10000, "Incomming message"); - g_string_free(message, FALSE); + g_string_free(message, TRUE); } void diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c index f9624f90..ed3cf169 100644 --- a/src/xmpp/capabilities.c +++ b/src/xmpp/capabilities.c @@ -122,7 +122,7 @@ caps_create_sha1_str(xmpp_stanza_t * const query) GSList *form_names = NULL; DataForm *form = NULL; FormField *field = NULL; - GHashTable *forms = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)stanza_destroy_form); + GHashTable *forms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)stanza_destroy_form); GString *s = g_string_new(""); @@ -134,18 +134,18 @@ caps_create_sha1_str(xmpp_stanza_t * const query) lang = xmpp_stanza_get_attribute(child, "xml:lang"); name = xmpp_stanza_get_attribute(child, "name"); - GString *identity_str = g_string_new(g_strdup(category)); + GString *identity_str = g_string_new(category); g_string_append(identity_str, "/"); if (type != NULL) { - g_string_append(identity_str, g_strdup(type)); + g_string_append(identity_str, type); } g_string_append(identity_str, "/"); if (lang != NULL) { - g_string_append(identity_str, g_strdup(lang)); + g_string_append(identity_str, lang); } g_string_append(identity_str, "/"); if (name != NULL) { - g_string_append(identity_str, g_strdup(name)); + g_string_append(identity_str, name); } g_string_append(identity_str, "<"); identities = g_slist_insert_sorted(identities, g_strdup(identity_str->str), (GCompareFunc)octet_compare); @@ -156,8 +156,8 @@ caps_create_sha1_str(xmpp_stanza_t * const query) } else if (g_strcmp0(xmpp_stanza_get_name(child), STANZA_NAME_X) == 0) { if (strcmp(xmpp_stanza_get_ns(child), STANZA_NS_DATA) == 0) { form = stanza_create_form(child); - form_names = g_slist_insert_sorted(form_names, strdup(form->form_type), (GCompareFunc)octet_compare); - g_hash_table_insert(forms, strdup(form->form_type), form); + form_names = g_slist_insert_sorted(form_names, g_strdup(form->form_type), (GCompareFunc)octet_compare); + g_hash_table_insert(forms, g_strdup(form->form_type), form); } } child = xmpp_stanza_get_next(child); @@ -165,13 +165,13 @@ caps_create_sha1_str(xmpp_stanza_t * const query) GSList *curr = identities; while (curr != NULL) { - g_string_append(s, strdup(curr->data)); + g_string_append(s, curr->data); curr = g_slist_next(curr); } curr = features; while (curr != NULL) { - g_string_append(s, strdup(curr->data)); + g_string_append(s, curr->data); g_string_append(s, "<"); curr = g_slist_next(curr); } @@ -179,17 +179,17 @@ caps_create_sha1_str(xmpp_stanza_t * const query) curr = form_names; while (curr != NULL) { form = g_hash_table_lookup(forms, curr->data); - g_string_append(s, strdup(form->form_type)); + g_string_append(s, form->form_type); g_string_append(s, "<"); GSList *curr_field = form->fields; while (curr_field != NULL) { field = curr_field->data; - g_string_append(s, strdup(field->var)); + g_string_append(s, field->var); g_string_append(s, "<"); GSList *curr_value = field->values; while (curr_value != NULL) { - g_string_append(s, strdup(curr_value->data)); + g_string_append(s, curr_value->data); g_string_append(s, "<"); curr_value = g_slist_next(curr_value); } @@ -215,10 +215,10 @@ caps_create_sha1_str(xmpp_stanza_t * const query) char *result = g_base64_encode(md_value, md_len); g_string_free(s, TRUE); - g_slist_free_full(identities, free); - g_slist_free_full(features, free); - g_slist_free_full(form_names, free); - //g_hash_table_destroy(forms); + g_slist_free_full(identities, g_free); + g_slist_free_full(features, g_free); + g_slist_free_full(form_names, g_free); + g_hash_table_destroy(forms); return result; } diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 48b561f0..742a2258 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -312,10 +312,10 @@ static void _identity_destroy(DiscoIdentity *identity) { if (identity != NULL) { - FREE_SET_NULL(identity->name); - FREE_SET_NULL(identity->type); - FREE_SET_NULL(identity->category); - FREE_SET_NULL(identity); + free(identity->name); + free(identity->type); + free(identity->category); + free(identity); } } @@ -323,9 +323,9 @@ static void _item_destroy(DiscoItem *item) { if (item != NULL) { - FREE_SET_NULL(item->jid); - FREE_SET_NULL(item->name); - FREE_SET_NULL(item); + free(item->jid); + free(item->name); + free(item); } } @@ -411,12 +411,13 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan log_info("Generated sha-1 does not match given:"); log_info("Generated : %s", generated_sha1); log_info("Given : %s", given_sha1); - FREE_SET_NULL(generated_sha1); + g_free(generated_sha1); g_strfreev(split); + free(caps_key); return 1; } - FREE_SET_NULL(generated_sha1); + g_free(generated_sha1); g_strfreev(split); // non supported hash, or legacy caps @@ -429,6 +430,7 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan // already cached if (caps_contains(caps_key)) { log_info("Client info already cached."); + free(caps_key); return 1; } diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 29d11958..95b3152a 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -212,6 +212,9 @@ _conference_message_handler(xmpp_conn_t * const conn, } Jid *jidp = jid_create(invitor_jid); + if (jidp == NULL) { + return 1; + } invitor = jidp->barejid; xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON); @@ -233,6 +236,9 @@ _conference_message_handler(xmpp_conn_t * const conn, } Jid *jidp = jid_create(from); + if (jidp == NULL) { + return 1; + } invitor = jidp->barejid; reason = xmpp_stanza_get_attribute(x_groupchat, STANZA_ATTR_REASON); diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index 6c87a8ac..93870088 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -156,14 +156,23 @@ presence_sub_request_find(char * search_str) gboolean presence_sub_request_exists(const char * const bare_jid) { - GSList *requests = autocomplete_get_list(sub_requests_ac); + gboolean result = FALSE; + GSList *requests_p = autocomplete_get_list(sub_requests_ac); + GSList *requests = requests_p; + while (requests != NULL) { if (strcmp(requests->data, bare_jid) == 0) { - return TRUE; + result = TRUE; + break; } requests = g_slist_next(requests); } - return FALSE; + + if (requests_p != NULL) { + g_slist_free_full(requests_p, free); + } + + return result; } void @@ -220,20 +229,28 @@ presence_update(const resource_presence_t presence_type, const char * const msg, static void _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence) { - GList *rooms = muc_get_active_room_list(); + GList *rooms_p = muc_get_active_room_list(); + GList *rooms = rooms_p; + while (rooms != NULL) { const char *room = rooms->data; const char *nick = muc_get_room_nick(room); - char *full_room_jid = create_fulljid(room, nick); - xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid); - log_debug("Sending presence to room: %s", full_room_jid); - xmpp_send(conn, presence); - free(full_room_jid); + if (nick != NULL) { + char *full_room_jid = create_fulljid(room, nick); + + xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid); + log_debug("Sending presence to room: %s", full_room_jid); + xmpp_send(conn, presence); + free(full_room_jid); + } rooms = g_list_next(rooms); } - g_list_free(rooms); + + if (rooms_p != NULL) { + g_list_free(rooms_p); + } } void @@ -347,9 +364,13 @@ _subscribe_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); - Jid *from_jid = jid_create(from); log_debug("Subscribe presence handler fired for %s", from); + Jid *from_jid = jid_create(from); + if (from_jid == NULL) { + return 1; + } + prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE); autocomplete_add(sub_requests_ac, strdup(from_jid->barejid)); @@ -368,6 +389,11 @@ _unavailable_handler(xmpp_conn_t * const conn, Jid *my_jid = jid_create(jid); Jid *from_jid = jid_create(from); + if (my_jid == NULL || from_jid == NULL) { + jid_destroy(my_jid); + jid_destroy(from_jid); + return 1; + } char *status_str = stanza_get_status(stanza, NULL); @@ -420,6 +446,11 @@ _available_handler(xmpp_conn_t * const conn, Jid *my_jid = jid_create(jid); Jid *from_jid = jid_create(from); + if (my_jid == NULL || from_jid == NULL) { + jid_destroy(my_jid); + jid_destroy(from_jid); + return 1; + } char *show_str = stanza_get_show(stanza, "online"); char *status_str = stanza_get_status(stanza, NULL); @@ -515,6 +546,10 @@ _get_caps_key(xmpp_stanza_t * const stanza) log_debug("Presence contains capabilities."); + if (node == NULL) { + return NULL; + } + // xep-0115 if ((hash_type != NULL) && (strcmp(hash_type, "sha-1") == 0)) { log_debug("Hash type %s supported.", hash_type); @@ -544,6 +579,8 @@ _get_caps_key(xmpp_stanza_t * const stanza) g_string_free(id_str, TRUE); } + g_free(node); + return caps_key; } @@ -626,6 +663,7 @@ _room_presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, if (old_nick != NULL) { muc_add_to_roster(room, nick, show_str, status_str, caps_key); prof_handle_room_member_nick_change(room, old_nick, nick); + free(old_nick); } else { if (!muc_nick_in_roster(room, nick)) { prof_handle_room_member_online(room, nick, show_str, status_str, caps_key); From 3c385e0aaa9cfaabc69581b7095a79c4452bcf2c Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 3 Aug 2013 14:42:02 +0300 Subject: [PATCH 14/24] replace struct stat and stat() for windows --- src/common.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common.c b/src/common.c index da33cc3d..42c1415f 100644 --- a/src/common.c +++ b/src/common.c @@ -39,6 +39,12 @@ // and page size is at least 4KB #define READ_BUF_SIZE 4088 +#ifdef _WIN32 +// replace 'struct stat' and 'stat()' for windows +#define stat _stat +#define S_IFDIR _S_IFDIR +#endif /* _WIN32 */ + struct curl_data_t { char *buffer; From 9e092843021534058558878d9bca4ce35be1c81c Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 3 Aug 2013 15:31:54 +0300 Subject: [PATCH 15/24] removed assignment to NULL in _chat_session_free --- src/chat_session.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/chat_session.c b/src/chat_session.c index 281f4b96..2cb3091b 100644 --- a/src/chat_session.c +++ b/src/chat_session.c @@ -266,15 +266,11 @@ static void _chat_session_free(ChatSession session) { if (session != NULL) { - if (session->recipient != NULL) { - g_free(session->recipient); - session->recipient = NULL; - } + free(session->recipient); if (session->active_timer != NULL) { g_timer_destroy(session->active_timer); session->active_timer = NULL; } - g_free(session); + free(session); } - session = NULL; } From 20dff5fe2f0251d39a1667b547a49cef3b115899 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 4 Aug 2013 19:14:07 +0300 Subject: [PATCH 16/24] use posix stat syscall for windows --- src/common.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/common.c b/src/common.c index 42c1415f..da33cc3d 100644 --- a/src/common.c +++ b/src/common.c @@ -39,12 +39,6 @@ // and page size is at least 4KB #define READ_BUF_SIZE 4088 -#ifdef _WIN32 -// replace 'struct stat' and 'stat()' for windows -#define stat _stat -#define S_IFDIR _S_IFDIR -#endif /* _WIN32 */ - struct curl_data_t { char *buffer; From 139ffcbbb988ed35cf37f699ee445251d322b2b2 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 24 Aug 2013 00:30:54 +0300 Subject: [PATCH 17/24] free titlebar_ac autocompleter --- src/command/command.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/command/command.c b/src/command/command.c index 1032be29..41c8a2ae 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -1007,6 +1007,7 @@ cmd_close(void) autocomplete_free(help_ac); autocomplete_free(notify_ac); autocomplete_free(sub_ac); + autocomplete_free(titlebar_ac); autocomplete_free(log_ac); autocomplete_free(prefs_ac); autocomplete_free(autoaway_ac); From c94495bc312e7bafecc12540c2968dc1c9b6f161 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 24 Aug 2013 00:34:47 +0300 Subject: [PATCH 18/24] avoid double allocaion of session_started --- src/log.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/log.c b/src/log.c index 7a57fa98..f6ce7b5b 100644 --- a/src/log.c +++ b/src/log.c @@ -205,7 +205,6 @@ chat_log_init(void) void groupchat_log_init(void) { - session_started = g_date_time_new_now_local(); log_info("Initialising groupchat logs"); groupchat_logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, g_free, (GDestroyNotify)_free_chat_log); From 1ef361684f8c6b892df9a364265c7ffa7d57adbd Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 24 Aug 2013 00:37:00 +0300 Subject: [PATCH 19/24] tz should be cached in static variable --- src/log.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/log.c b/src/log.c index f6ce7b5b..14d801a9 100644 --- a/src/log.c +++ b/src/log.c @@ -308,8 +308,6 @@ GSList * chat_log_get_previous(const gchar * const login, const gchar * const recipient, GSList *history) { - GTimeZone *tz = g_time_zone_new_local(); - GDateTime *now = g_date_time_new_now_local(); GDateTime *log_date = g_date_time_new(tz, g_date_time_get_year(session_started), @@ -348,8 +346,6 @@ chat_log_get_previous(const gchar * const login, const gchar * const recipient, log_date = g_date_time_ref(next); } - g_time_zone_unref(tz); - return history; } From 021d0955368272456434db4061e6c6b15bbd77db Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 24 Aug 2013 00:39:03 +0300 Subject: [PATCH 20/24] small refactoring in statusbar.c --- src/ui/statusbar.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/ui/statusbar.c b/src/ui/statusbar.c index cd218e73..6e7eae30 100644 --- a/src/ui/statusbar.c +++ b/src/ui/statusbar.c @@ -22,6 +22,7 @@ #include "config.h" +#include #include #include @@ -63,6 +64,8 @@ create_status_bar(void) mvwprintw(status_bar, 0, cols - 31, _active); wattroff(status_bar, COLOUR_STATUS_BRACKET); + if (last_time != NULL) + g_date_time_unref(last_time); last_time = g_date_time_new_now_local(); dirty = TRUE; @@ -76,6 +79,8 @@ status_bar_refresh(void) if (elapsed >= 60000000) { dirty = TRUE; + if (last_time != NULL) + g_date_time_unref(last_time); last_time = g_date_time_new_now_local(); } @@ -113,6 +118,8 @@ status_bar_resize(void) if (message != NULL) mvwprintw(status_bar, 0, 10, message); + if (last_time != NULL) + g_date_time_unref(last_time); last_time = g_date_time_new_now_local(); dirty = TRUE; } @@ -184,13 +191,11 @@ status_bar_get_password(void) void status_bar_print_message(const char * const msg) { - if (message != NULL) { - free(message); - message = NULL; - } - werase(status_bar); + if (message != NULL) { + free(message); + } message = (char *) malloc(strlen(msg) + 1); strcpy(message, msg); mvwprintw(status_bar, 0, 10, message); @@ -270,6 +275,7 @@ static void _status_bar_update_time(void) { gchar *date_fmt = g_date_time_format(last_time, "%H:%M"); + assert(date_fmt != NULL); wattron(status_bar, COLOUR_STATUS_BRACKET); mvwaddch(status_bar, 0, 1, '['); @@ -279,7 +285,7 @@ _status_bar_update_time(void) mvwaddch(status_bar, 0, 7, ']'); wattroff(status_bar, COLOUR_STATUS_BRACKET); - free(date_fmt); + g_free(date_fmt); dirty = TRUE; } From 012366cf13df4094e43b7567fe47d03b0d025fad Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 24 Aug 2013 00:40:23 +0300 Subject: [PATCH 21/24] fixed memleak in _iq_handle_discoinfo_get --- src/xmpp/iq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 742a2258..3430b4d1 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -302,6 +302,7 @@ _iq_handle_discoinfo_get(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, xmpp_stanza_add_child(response, query); xmpp_send(conn, response); + xmpp_stanza_release(query); xmpp_stanza_release(response); } From d6c90ac7ca8bd3e32e353b36e1eab54ccabd5eb9 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sat, 24 Aug 2013 00:41:57 +0300 Subject: [PATCH 22/24] fixed indenting --- src/xmpp/presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index a18bf6fe..a1d851e4 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -493,7 +493,7 @@ _available_handler(xmpp_conn_t * const conn, } // self presence - if (strcmp(my_jid->barejid, from_jid->barejid) ==0) { + if (strcmp(my_jid->barejid, from_jid->barejid) == 0) { connection_add_available_resource(resource); // contact presence From c7ec06ff65f6b49f264d3a3a21c64615c9c1f090 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 25 Aug 2013 14:52:25 +0300 Subject: [PATCH 23/24] removed strdup from g_string_append --- src/ui/console.c | 10 +++++----- src/ui/core.c | 12 ++++++------ src/xmpp/roster.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ui/console.c b/src/ui/console.c index 6efc1cf1..42c4e080 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -687,15 +687,15 @@ cons_show_disco_info(const char *jid, GSList *identities, GSList *features) DiscoIdentity *identity = identities->data; // anme trpe, cat GString *identity_str = g_string_new(" "); if (identity->name != NULL) { - identity_str = g_string_append(identity_str, strdup(identity->name)); + identity_str = g_string_append(identity_str, identity->name); identity_str = g_string_append(identity_str, " "); } if (identity->type != NULL) { - identity_str = g_string_append(identity_str, strdup(identity->type)); + identity_str = g_string_append(identity_str, identity->type); identity_str = g_string_append(identity_str, " "); } if (identity->category != NULL) { - identity_str = g_string_append(identity_str, strdup(identity->category)); + identity_str = g_string_append(identity_str, identity->category); } cons_show(identity_str->str); g_string_free(identity_str, FALSE); @@ -1347,7 +1347,7 @@ _show_roster_contacts(GSList *list, gboolean show_groups) title = g_string_append(title, p_contact_barejid(contact)); if (p_contact_name(contact) != NULL) { title = g_string_append(title, " ("); - title = g_string_append(title, strdup(p_contact_name(contact))); + title = g_string_append(title, p_contact_name(contact)); title = g_string_append(title, ")"); } @@ -1394,7 +1394,7 @@ _show_roster_contacts(GSList *list, gboolean show_groups) if (groups != NULL) { GString *groups_str = g_string_new(" Groups : "); while (groups != NULL) { - g_string_append(groups_str, strdup(groups->data)); + g_string_append(groups_str, groups->data); if (g_slist_next(groups) != NULL) { g_string_append(groups_str, ", "); } diff --git a/src/ui/core.c b/src/ui/core.c index b33186ec..e73c0a67 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -492,15 +492,15 @@ ui_contact_online(const char * const barejid, const char * const resource, // use nickname if exists if (p_contact_name(contact) != NULL) { - g_string_append(display_str, strdup(p_contact_name(contact))); + g_string_append(display_str, p_contact_name(contact)); } else { - g_string_append(display_str, strdup(barejid)); + g_string_append(display_str, barejid); } // add resource if not default provided by profanity if (strcmp(jid->resourcepart, "__prof_default") != 0) { g_string_append(display_str, " ("); - g_string_append(display_str, strdup(jid->resourcepart)); + g_string_append(display_str, jid->resourcepart); g_string_append(display_str, ")"); } @@ -531,15 +531,15 @@ ui_contact_offline(const char * const from, const char * const show, // use nickname if exists if (p_contact_name(contact) != NULL) { - g_string_append(display_str, strdup(p_contact_name(contact))); + g_string_append(display_str, p_contact_name(contact)); } else { - g_string_append(display_str, strdup(jidp->barejid)); + g_string_append(display_str, jidp->barejid); } // add resource if not default provided by profanity if (strcmp(jidp->resourcepart, "__prof_default") != 0) { g_string_append(display_str, " ("); - g_string_append(display_str, strdup(jidp->resourcepart)); + g_string_append(display_str, jidp->resourcepart); g_string_append(display_str, ")"); } diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c index ed72d502..b31a2725 100644 --- a/src/xmpp/roster.c +++ b/src/xmpp/roster.c @@ -567,7 +567,7 @@ _roster_handle_push(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, while (resources != NULL) { GString *fulljid = g_string_new(strdup(barejid)); g_string_append(fulljid, "/"); - g_string_append(fulljid, strdup(resources->data)); + g_string_append(fulljid, resources->data); autocomplete_remove(fulljid_ac, fulljid->str); g_string_free(fulljid, TRUE); resources = g_list_next(resources); From b1bfdf650a93c84b92fef02fdd8441c1b2002e66 Mon Sep 17 00:00:00 2001 From: Dmitry Podgorny Date: Sun, 25 Aug 2013 14:54:34 +0300 Subject: [PATCH 24/24] fixed memory leaks in various files --- src/config/accounts.c | 61 ++++++++++++++++++++++++++++------------- src/xmpp/capabilities.c | 11 ++++---- src/xmpp/iq.c | 15 ++++++---- src/xmpp/message.c | 1 + src/xmpp/presence.c | 1 + 5 files changed, 60 insertions(+), 29 deletions(-) diff --git a/src/config/accounts.c b/src/config/accounts.c index c82f6b2d..3d198874 100644 --- a/src/config/accounts.c +++ b/src/config/accounts.c @@ -72,10 +72,7 @@ accounts_load(void) _fix_legacy_accounts(account_names[i]); } - for (i = 0; i < naccounts; i++) { - free(account_names[i]); - } - free(account_names); + g_strfreev(account_names); } void @@ -166,6 +163,7 @@ accounts_get_account(const char * const name) gchar *jid = g_key_file_get_string(accounts, name, "jid", NULL); if (jid != NULL) { account->jid = strdup(jid); + g_free(jid); } else { account->jid = strdup(name); g_key_file_set_string(accounts, name, "jid", name); @@ -177,6 +175,7 @@ accounts_get_account(const char * const name) gchar *server = g_key_file_get_string(accounts, name, "server", NULL); if (server != NULL) { account->server = strdup(server); + g_free(server); } else { account->server = NULL; } @@ -184,6 +183,7 @@ accounts_get_account(const char * const name) gchar *resource = g_key_file_get_string(accounts, name, "resource", NULL); if (resource != NULL) { account->resource = strdup(resource); + g_free(resource); } else { account->resource = NULL; } @@ -195,6 +195,10 @@ accounts_get_account(const char * const name) account->last_presence = strdup(presence); } + if (presence != NULL) { + g_free(presence); + } + presence = g_key_file_get_string(accounts, name, "presence.login", NULL); if (presence == NULL) { account->login_presence = strdup("online"); @@ -206,6 +210,10 @@ accounts_get_account(const char * const name) account->login_presence = strdup(presence); } + if (presence != NULL) { + g_free(presence); + } + account->priority_online = g_key_file_get_integer(accounts, name, "priority.online", NULL); account->priority_chat = g_key_file_get_integer(accounts, name, "priority.chat", NULL); account->priority_away = g_key_file_get_integer(accounts, name, "priority.away", NULL); @@ -302,7 +310,7 @@ accounts_rename(const char * const account_name, const char * const new_name) char *value = g_key_file_get_string(accounts, account_name, string_keys[i], NULL); if (value != NULL) { g_key_file_set_string(accounts, new_name, string_keys[i], value); - free(value); + g_free(value); } } @@ -469,45 +477,59 @@ accounts_set_login_presence(const char * const account_name, const char * const resource_presence_t accounts_get_last_presence(const char * const account_name) { + resource_presence_t result; gchar *setting = g_key_file_get_string(accounts, account_name, "presence.last", NULL); + if (setting == NULL || (strcmp(setting, "online") == 0)) { - return RESOURCE_ONLINE; + result = RESOURCE_ONLINE; } else if (strcmp(setting, "chat") == 0) { - return RESOURCE_CHAT; + result = RESOURCE_CHAT; } else if (strcmp(setting, "away") == 0) { - return RESOURCE_AWAY; + result = RESOURCE_AWAY; } else if (strcmp(setting, "xa") == 0) { - return RESOURCE_XA; + result = RESOURCE_XA; } else if (strcmp(setting, "dnd") == 0) { - return RESOURCE_DND; + result = RESOURCE_DND; } else { log_warning("Error reading presence.last for account: '%s', value: '%s', defaulting to 'online'", account_name, setting); - return RESOURCE_ONLINE; + result = RESOURCE_ONLINE; } + + if (setting != NULL) { + g_free(setting); + } + return result; } resource_presence_t accounts_get_login_presence(const char * const account_name) { + resource_presence_t result; gchar *setting = g_key_file_get_string(accounts, account_name, "presence.login", NULL); + if (setting == NULL || (strcmp(setting, "online") == 0)) { - return RESOURCE_ONLINE; + result = RESOURCE_ONLINE; } else if (strcmp(setting, "chat") == 0) { - return RESOURCE_CHAT; + result = RESOURCE_CHAT; } else if (strcmp(setting, "away") == 0) { - return RESOURCE_AWAY; + result = RESOURCE_AWAY; } else if (strcmp(setting, "xa") == 0) { - return RESOURCE_XA; + result = RESOURCE_XA; } else if (strcmp(setting, "dnd") == 0) { - return RESOURCE_DND; + result = RESOURCE_DND; } else if (strcmp(setting, "last") == 0) { - return accounts_get_last_presence(account_name); + result = accounts_get_last_presence(account_name); } else { log_warning("Error reading presence.login for account: '%s', value: '%s', defaulting to 'online'", account_name, setting); - return RESOURCE_ONLINE; + result = RESOURCE_ONLINE; } + + if (setting != NULL) { + g_free(setting); + } + return result; } static void @@ -543,8 +565,9 @@ static void _save_accounts(void) { gsize g_data_size; - char *g_accounts_data = g_key_file_to_data(accounts, &g_data_size, NULL); + gchar *g_accounts_data = g_key_file_to_data(accounts, &g_data_size, NULL); g_file_set_contents(accounts_loc, g_accounts_data, g_data_size, NULL); + g_free(g_accounts_data); } static gchar * diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c index ed3cf169..2b0a12e5 100644 --- a/src/xmpp/capabilities.c +++ b/src/xmpp/capabilities.c @@ -280,13 +280,14 @@ caps_create_query_response_stanza(xmpp_ctx_t * const ctx) xmpp_stanza_add_child(query, feature_version); xmpp_stanza_add_child(query, feature_ping); - xmpp_stanza_release(identity); - xmpp_stanza_release(feature_muc); - xmpp_stanza_release(feature_discoinfo); - xmpp_stanza_release(feature_discoitems); - xmpp_stanza_release(feature_caps); + xmpp_stanza_release(feature_ping); xmpp_stanza_release(feature_version); + xmpp_stanza_release(feature_muc); + xmpp_stanza_release(feature_discoitems); + xmpp_stanza_release(feature_discoinfo); xmpp_stanza_release(feature_chatstates); + xmpp_stanza_release(feature_caps); + xmpp_stanza_release(identity); return query; } diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 3430b4d1..5de84056 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -247,6 +247,12 @@ _iq_handle_version_get(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, xmpp_send(conn, response); + g_free(version_str); + xmpp_stanza_release(name_txt); + xmpp_stanza_release(version_txt); + xmpp_stanza_release(name); + xmpp_stanza_release(version); + xmpp_stanza_release(query); xmpp_stanza_release(response); } @@ -437,9 +443,6 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan log_debug("Client info not cached"); - DataForm *form = NULL; - FormField *formField = NULL; - const char *category = NULL; const char *type = NULL; const char *name = NULL; @@ -458,7 +461,8 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan xmpp_stanza_t *softwareinfo = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA); if (softwareinfo != NULL) { - form = stanza_create_form(softwareinfo); + DataForm *form = stanza_create_form(softwareinfo); + FormField *formField = NULL; if (g_strcmp0(form->form_type, STANZA_DATAFORM_SOFTWARE) == 0) { GSList *field = form->fields; @@ -478,6 +482,8 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan field = g_slist_next(field); } } + + stanza_destroy_form(form); } xmpp_stanza_t *child = xmpp_stanza_get_children(query); @@ -492,7 +498,6 @@ _iq_handle_discoinfo_result(xmpp_conn_t * const conn, xmpp_stanza_t * const stan caps_add(caps_key, category, type, name, software, software_version, os, os_version, features); - //stanza_destroy_form(form); free(caps_key); } diff --git a/src/xmpp/message.c b/src/xmpp/message.c index 95b3152a..19b4df49 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -280,6 +280,7 @@ _groupchat_message_handler(xmpp_conn_t * const conn, message = xmpp_stanza_get_text(subject); if (message != NULL) { prof_handle_room_subject(jid->barejid, message); + xmpp_free(ctx, message); } jid_destroy(jid); diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index a1d851e4..ec439871 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -502,6 +502,7 @@ _available_handler(xmpp_conn_t * const conn, last_activity); } + free(caps_key); free(status_str); free(show_str); jid_destroy(my_jid);