From 0e48e549e7693f665b43bcad5e14ef26447bfe5b Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 25 May 2016 21:29:14 -0300 Subject: purple: strdup the message instead of casting to char * Fixes trac ticket 1255, which points out that a strip_html() call down there may modify the passed string, and some purple plugins may pass read-only string data to it. --- protocols/purple/purple.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index d0e8ec40..6ea2d7d8 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -964,10 +964,11 @@ void prplcb_conv_del_users(PurpleConversation *conv, GList *cbuddies) } /* Generic handler for IM or chat messages, covers write_chat, write_im and write_conv */ -static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message, guint32 bee_flags, time_t mtime) +static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message_, guint32 bee_flags, time_t mtime) { struct im_connection *ic = purple_ic_by_pa(conv->account); struct groupchat *gc = conv->ui_data; + char *message = g_strdup(message_); PurpleBuddy *buddy; buddy = purple_find_buddy(conv->account, who); @@ -976,10 +977,12 @@ static void handle_conv_msg(PurpleConversation *conv, const char *who, const cha } if (conv->type == PURPLE_CONV_TYPE_IM) { - imcb_buddy_msg(ic, (char *) who, (char *) message, bee_flags, mtime); + imcb_buddy_msg(ic, who, message, bee_flags, mtime); } else if (gc) { - imcb_chat_msg(gc, who, (char *) message, bee_flags, mtime); + imcb_chat_msg(gc, who, message, bee_flags, mtime); } + + g_free(message); } /* Handles write_im and write_chat. Removes echoes of locally sent messages */ -- cgit v1.2.3 From d28fe1c4f463314a79f0a71f6f8a01db53e37253 Mon Sep 17 00:00:00 2001 From: jgeboski Date: Sun, 15 May 2016 14:17:34 -0400 Subject: Implemented plugin information for external plugins As of now, bitlbee will load any plugin regardless of the ABI it was built against. This is really problematic when structures or symbols are changed within bitlbee. This often leads to the plugin not loading or the plugin acting in an undefined way. Typically a simple rebuild of the plugin will resolve such issues, but many users have no idea that this is required after they have updated bitlbee. Furthermore, it is often times impossible to determine the version of a plugin, without relying on the package manager of the system. This is quite a problem when users are reporting bugs for external plugins, and they have no idea what version of the plugin they are running. This is also an opportunity to provide additional metadata for each plugin that can then be displayed to the user. Solving these issues is done by adding a new required function to each plugin. The init_plugin_info() function must now be implemented along with the init_plugin() function. This function then returns a static structure, which retains all of the metadata for the plugin. Then this is used by bitlbee to check the ABI version and provide information to the user. The introduction of the new function is required as bitlbee needs to obtain the ABI version before calling init_plugin(). The boiler-plate implementation of init_plugin_info(): #ifdef BITLBEE_ABI_VERSION_CODE struct plugin_info *init_plugin_info(void) { static struct plugin_info info = { BITLBEE_ABI_VERSION_CODE, /* Required */ "plugin-name", /* Required */ "1.3.3.7", /* Required */ "A short description of the plugin", /* Optional */ "First Last ", /* Optional */ "http://www.domain.tld" /* Optional */ }; return &info; } #endif The example wraps the function declaration in an if block for backwards compatibility with older bitlbee versions. Displaying the plugin metadata is done via the newly added "plugins" command, which simply dumps formatted data to the root channel. --- protocols/nogaim.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++- protocols/nogaim.h | 14 +++++++++++ protocols/skype/skype.c | 14 +++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/nogaim.c b/protocols/nogaim.c index c9cbb033..9ed3b64b 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -39,24 +39,84 @@ GSList *connections; #ifdef WITH_PLUGINS +GList *plugins = NULL; + +static gint pluginscmp(gconstpointer a, gconstpointer b, gpointer data) +{ + const struct plugin_info *ia = a; + const struct plugin_info *ib = b; + + return g_strcasecmp(ia->name, ib->name); +} + gboolean load_plugin(char *path) { + GList *l; + struct plugin_info *i; + struct plugin_info *info; + struct plugin_info * (*info_function) (void) = NULL; void (*init_function) (void); GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY); + gboolean loaded = FALSE; if (!mod) { log_message(LOGLVL_ERROR, "Error loading plugin `%s': %s\n", path, g_module_error()); return FALSE; } + if (g_module_symbol(mod, "init_plugin_info", (gpointer *) &info_function)) { + info = info_function(); + + if (info->abiver != BITLBEE_ABI_VERSION_CODE) { + log_message(LOGLVL_ERROR, + "`%s' uses ABI %u but %u is required\n", + path, info->abiver, + BITLBEE_ABI_VERSION_CODE); + g_module_close(mod); + return FALSE; + } + + if (!info->name || !info->version) { + log_message(LOGLVL_ERROR, + "Name or version missing from the " + "plugin info in `%s'\n", path); + g_module_close(mod); + return FALSE; + } + + for (l = plugins; l; l = l->next) { + i = l->data; + + if (g_strcasecmp(i->name, info->name) == 0) { + loaded = TRUE; + break; + } + } + + if (loaded) { + log_message(LOGLVL_WARNING, + "%s plugin already loaded\n", + info->name); + g_module_close(mod); + return FALSE; + } + } else { + log_message(LOGLVL_WARNING, "Can't find function `init_plugin_info' in `%s'\n", path); + } + if (!g_module_symbol(mod, "init_plugin", (gpointer *) &init_function)) { log_message(LOGLVL_WARNING, "Can't find function `init_plugin' in `%s'\n", path); + g_module_close(mod); return FALSE; } - init_function(); + if (info_function) { + plugins = g_list_insert_sorted_with_data(plugins, info, + pluginscmp, NULL); + } + init_function(); return TRUE; } @@ -86,6 +146,11 @@ void load_plugins(void) g_dir_close(dir); } } + +GList *get_plugins() +{ + return plugins; +} #endif GList *protocols = NULL; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 40b1ed7b..f5b1f212 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -270,6 +270,20 @@ struct prpl { void *resv5; }; +struct plugin_info +{ + guint abiver; + const char *name; + const char *version; + const char *description; + const char *author; + const char *url; +}; + +#ifdef WITH_PLUGINS +G_MODULE_EXPORT GList *get_plugins(); +#endif + /* im_api core stuff. */ void nogaim_init(); G_MODULE_EXPORT GSList *get_connections(); diff --git a/protocols/skype/skype.c b/protocols/skype/skype.c index a21af8ef..bd8a1850 100644 --- a/protocols/skype/skype.c +++ b/protocols/skype/skype.c @@ -1762,3 +1762,17 @@ void init_plugin(void) #endif register_protocol(ret); } + +struct plugin_info *init_plugin_info(void) +{ + static struct plugin_info info = { + BITLBEE_ABI_VERSION_CODE, + "skype", + BITLBEE_VERSION, + "Skype protocol plugin", + NULL, + NULL + }; + + return &info; +} -- cgit v1.2.3 From 808825eda6d90aeabd754f70eee52e2b0165749e Mon Sep 17 00:00:00 2001 From: jgeboski Date: Sun, 15 May 2016 16:40:15 -0400 Subject: Show the enabled/disabled protocols in the 'plugins' command output --- protocols/nogaim.c | 10 ++++++++++ protocols/nogaim.h | 2 ++ 2 files changed, 12 insertions(+) (limited to 'protocols') diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 9ed3b64b..c902258a 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -229,6 +229,16 @@ void nogaim_init() #endif } +GList *get_protocols() +{ + return protocols; +} + +GList *get_protocols_disabled() +{ + return disabled_protocols; +} + GSList *get_connections() { return connections; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index f5b1f212..e5569313 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -286,6 +286,8 @@ G_MODULE_EXPORT GList *get_plugins(); /* im_api core stuff. */ void nogaim_init(); +G_MODULE_EXPORT GList *get_protocols(); +G_MODULE_EXPORT GList *get_protocols_disabled(); G_MODULE_EXPORT GSList *get_connections(); G_MODULE_EXPORT struct prpl *find_protocol(const char *name); G_MODULE_EXPORT gboolean is_protocol_disabled(const char *name); -- cgit v1.2.3 From 35712b75b589d0f40386891fa6e2cf1c4d97cf6e Mon Sep 17 00:00:00 2001 From: jgeboski Date: Sun, 15 May 2016 18:22:13 -0400 Subject: Only load plugins with the right file extension Plugins which use autotools will install a .la file along with the .so file. Both of these files are loadable as plugins, so the plugin ends up being loaded twice. To prevent this, only load the .so module. --- protocols/nogaim.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'protocols') diff --git a/protocols/nogaim.c b/protocols/nogaim.c index c902258a..ab11508b 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -132,6 +132,10 @@ void load_plugins(void) char *path; while ((entry = g_dir_read_name(dir))) { + if (!g_str_has_suffix(entry, "." G_MODULE_SUFFIX)) { + continue; + } + path = g_build_filename(global.conf->plugindir, entry, NULL); if (!path) { log_message(LOGLVL_WARNING, "Can't build path for %s\n", entry); -- cgit v1.2.3 From 59a7dc58dcf39b7eaed2015423f8a4fc2da3c7fd Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Thu, 26 May 2016 06:08:05 +0200 Subject: Twitter: add "like" as an alias for favourite. This will allow a user to type "like" in Twitter channels, reflecting recent changes to Twitter itself. Note that the API hasn't changed. --- protocols/twitter/twitter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index 4fe509bb..b2039171 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -950,7 +950,8 @@ static void twitter_handle_command(struct im_connection *ic, char *message) goto eof; } else if ((g_strcasecmp(cmd[0], "favourite") == 0 || g_strcasecmp(cmd[0], "favorite") == 0 || - g_strcasecmp(cmd[0], "fav") == 0) && cmd[1]) { + g_strcasecmp(cmd[0], "fav") == 0 || + g_strcasecmp(cmd[0], "like") == 0) && cmd[1]) { if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) { twitter_favourite_tweet(ic, id); } else { -- cgit v1.2.3