diff options
author | dequis <dx@dxzone.com.ar> | 2016-11-21 03:40:54 -0300 |
---|---|---|
committer | dequis <dx@dxzone.com.ar> | 2016-11-21 03:58:47 -0300 |
commit | 5a8afc3f24a5308799d3960cab5726228345022d (patch) | |
tree | dc4569f0190238e20b3ae2c7ddb7feb2db27380d | |
parent | 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b (diff) |
Manual merge with wilmer's approach to handling missing protocols
Turns out he already implemented pretty much the same thing in the
parson branch... last year.
The differences between the two approaches are subtle (there aren't too
many ways to do this, some lines are the exact same thing) but I decided
I like his version better, so this mostly reverts a handful of my
changes while keeping others. The main advantage of his approach is that
no fake protocols are registered, no actual prpl functions are called,
and the missing prpl is a singleton constant.
New things compared to the implementation in the other branch:
- The explain_unknown_protocol() function.
- Fixed named chatrooms throwing a warning and losing the "account"
setting when saving. See changes in irc_im.c
- Fixed the "server" setting dropping when saving. See account.c
Differences with my previous implementation:
- Accounts with missing protocols don't autoconnect
- 'account list' marks them as "(missing!)"
-rw-r--r-- | irc_im.c | 2 | ||||
-rw-r--r-- | protocols/Makefile | 2 | ||||
-rw-r--r-- | protocols/account.c | 5 | ||||
-rw-r--r-- | protocols/nogaim.c | 12 | ||||
-rw-r--r-- | protocols/nogaim.h | 4 | ||||
-rw-r--r-- | protocols/unknown.c | 75 | ||||
-rw-r--r-- | root_commands.c | 19 | ||||
-rw-r--r-- | storage.c | 4 | ||||
-rw-r--r-- | storage.h | 2 | ||||
-rw-r--r-- | storage_xml.c | 53 |
10 files changed, 67 insertions, 111 deletions
@@ -1013,7 +1013,7 @@ static char *set_eval_room_account(set_t *set, char *value) if (!(acc = account_get(ic->irc->b, value))) { return SET_INVALID; - } else if (!acc->prpl->chat_join) { + } else if (!acc->prpl->chat_join && acc->prpl != &protocol_missing) { irc_rootmsg(ic->irc, "Named chatrooms not supported on that account."); return SET_INVALID; } diff --git a/protocols/Makefile b/protocols/Makefile index ae969bde..b4565ab6 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -12,7 +12,7 @@ _SRCDIR_ := $(_SRCDIR_)protocols/ endif # [SH] Program variables -objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o unknown.o +objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o # [SH] The next two lines should contain the directory name (in $(subdirs)) diff --git a/protocols/account.c b/protocols/account.c index e25e40c7..1f12f56f 100644 --- a/protocols/account.c +++ b/protocols/account.c @@ -75,6 +75,11 @@ account_t *account_add(bee_t *bee, struct prpl *prpl, char *user, char *pass) s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | ACC_SET_LOCKABLE; set_setstr(&a->set, "username", user); + if (prpl == &protocol_missing) { + s = set_add(&a->set, "server", NULL, set_eval_account, a); + s->flags |= SET_NOSAVE | SET_HIDDEN | ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; + } + /* Hardcode some more clever tag guesses. */ strcpy(tag, prpl->name); if (strcmp(prpl->name, "oscar") == 0) { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 8a22654e..2f6b3783 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -159,7 +159,6 @@ GList *get_plugins() GList *protocols = NULL; GList *disabled_protocols = NULL; -static struct prpl *unknown_prpl; void register_protocol(struct prpl *p) { @@ -191,14 +190,6 @@ struct prpl *find_protocol(const char *name) return gl ? gl->data: NULL; } -struct prpl *make_unknown_protocol(const char *name) -{ - struct prpl *ret = g_memdup(unknown_prpl, sizeof(struct prpl)); - ret->name = g_strdup(name); - register_protocol(ret); - return ret; -} - gboolean is_protocol_disabled(const char *name) { return g_list_find_custom(disabled_protocols, name, proto_name_cmp) != NULL; @@ -249,9 +240,6 @@ void nogaim_init() extern void jabber_initmodule(); extern void twitter_initmodule(); extern void purple_initmodule(); - extern void unknown_prpl_initmodule(); - - unknown_prpl_initmodule(&unknown_prpl); #ifdef WITH_MSN msn_initmodule(); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 3aa89c3b..8e6c9d5a 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -158,9 +158,6 @@ typedef enum { /* The protocol is not suitable for OTR, see OPT_NOOTR */ PRPL_OPT_NOOTR = 1 << 12, - - /* This prpl is a placeholder for a missing protocol */ - PRPL_OPT_UNKNOWN_PROTOCOL = 1 << 13, } prpl_options_t; struct prpl { @@ -323,7 +320,6 @@ 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); -G_MODULE_EXPORT struct prpl *make_unknown_protocol(const char *name); G_MODULE_EXPORT char *explain_unknown_protocol(const char *name); /* When registering a new protocol, you should allocate space for a new prpl * struct, initialize it (set the function pointers to point to your diff --git a/protocols/unknown.c b/protocols/unknown.c deleted file mode 100644 index 105b2f62..00000000 --- a/protocols/unknown.c +++ /dev/null @@ -1,75 +0,0 @@ -/********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2016 Wilmer van der Gaast and others * - \********************************************************************/ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 51 Franklin St., - Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#define BITLBEE_CORE -#include "nogaim.h" - -/* Displays an error when trying to connect this account */ -static void unknown_prpl_login(account_t *acc) -{ - struct im_connection *ic = imcb_new(acc); - char *msg; - - imcb_error(ic, "Unknown protocol"); - - msg = explain_unknown_protocol(acc->prpl->name); - imcb_error(ic, "%s", msg); - g_free(msg); - - imc_logout(ic, FALSE); -} - -/* Required, no-op */ -static void unknown_prpl_logout(struct im_connection *ic) -{ -} - -/* Needed to ensure the server setting is preserved */ -static void unknown_prpl_init(account_t *acc) -{ - set_t *s; - - s = set_add(&acc->set, "server", NULL, set_eval_account, acc); - s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK; -} - -/* Needed to silence warnings about named groupchats not supported */ -struct groupchat *unknown_prpl_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password, - set_t **sets) -{ - return NULL; -} - -void unknown_prpl_initmodule(struct prpl **prpl) -{ - struct prpl *ret = g_new0(struct prpl, 1); - - ret->name = "unknown"; - ret->options = PRPL_OPT_UNKNOWN_PROTOCOL | PRPL_OPT_NOOTR; - ret->login = unknown_prpl_login; - ret->logout = unknown_prpl_logout; - ret->init = unknown_prpl_init; - ret->chat_join = unknown_prpl_chat_join; - *prpl = ret; -} - diff --git a/root_commands.c b/root_commands.c index 1bbd1722..e0c0b7f8 100644 --- a/root_commands.c +++ b/root_commands.c @@ -497,7 +497,7 @@ static void cmd_account(irc_t *irc, char **cmd) } for (a = irc->b->accounts; a; a = a->next) { - char *con; + char *con = NULL, *protocol = NULL; if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) { con = " (connected)"; @@ -509,7 +509,14 @@ static void cmd_account(irc_t *irc, char **cmd) con = ""; } - irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con); + if (a->prpl == &protocol_missing) { + protocol = g_strdup_printf("%s (missing!)", set_getstr(&a->set, "_protocol_name")); + } else { + protocol = g_strdup(a->prpl->name); + } + + irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, protocol, a->user, con); + g_free(protocol); i++; } @@ -523,7 +530,7 @@ static void cmd_account(irc_t *irc, char **cmd) irc_rootmsg(irc, "Trying to get all accounts connected..."); for (a = irc->b->accounts; a; a = a->next) { - if (!a->ic && a->auto_connect) { + if (!a->ic && a->auto_connect && a->prpl != &protocol_missing) { if (strcmp(a->pass, PASSWORD_PENDING) == 0) { irc_rootmsg(irc, "Enter password for account %s " "first (use /OPER)", a->tag); @@ -583,6 +590,12 @@ static void cmd_account(irc_t *irc, char **cmd) } else if (strcmp(a->pass, PASSWORD_PENDING) == 0) { irc_rootmsg(irc, "Enter password for account %s " "first (use /OPER)", a->tag); + } else if (a->prpl == &protocol_missing) { + char *proto = set_getstr(&a->set, "_protocol_name"); + char *msg = explain_unknown_protocol(proto); + irc_rootmsg(irc, "Unknown protocol `%s'", proto); + irc_rootmsg(irc, msg); + g_free(msg); } else { account_on(irc->b, a); } @@ -32,6 +32,10 @@ extern storage_t storage_xml; static GList *storage_backends = NULL; +const struct prpl protocol_missing = { + .name = "_unknown", +}; + void register_storage_backend(storage_t *backend) { storage_backends = g_list_append(storage_backends, backend); @@ -62,4 +62,6 @@ storage_status_t storage_remove(const char *nick); void register_storage_backend(storage_t *); G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate); +extern const struct prpl protocol_missing; + #endif /* __STORAGE_H__ */ diff --git a/storage_xml.c b/storage_xml.c index 07cdaf0f..a921524f 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -59,7 +59,7 @@ static void xml_init(void) } } -static void handle_settings(struct xt_node *node, set_t **head, gboolean add_unknowns) +static void handle_settings(struct xt_node *node, set_t **head) { struct xt_node *c; struct set *s; @@ -72,13 +72,6 @@ static void handle_settings(struct xt_node *node, set_t **head, gboolean add_unk continue; } - if (add_unknowns && !set_find(head, name)) { - s = set_add(head, name, NULL, NULL, NULL); - s->flags |= ACC_SET_ONLINE_ONLY; - s->value = g_strdup(c->text); - continue; - } - if (strcmp(node->name, "account") == 0) { set_t *s = set_find(head, name); if (s && (s->flags & ACC_SET_ONLINE_ONLY)) { @@ -95,6 +88,25 @@ static void handle_settings(struct xt_node *node, set_t **head, gboolean add_unk } } +/* Use for unsupported/not-found protocols. Save settings as-is but don't allow changes. */ +static void handle_settings_raw(struct xt_node *node, set_t **head) +{ + struct xt_node *c; + + for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) { + char *name = xt_find_attr(c, "name"); + + if (!name) { + continue; + } + + set_t *s = set_add(head, name, NULL, NULL, NULL); + set_setstr(head, name, c->text); + s->flags |= SET_HIDDEN | + ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; + } +} + static xt_status handle_account(struct xt_node *node, gpointer data) { struct xml_parsedata *xd = data; @@ -105,7 +117,6 @@ static xt_status handle_account(struct xt_node *node, gpointer data) struct prpl *prpl = NULL; account_t *acc; struct xt_node *c; - gboolean is_unknown = FALSE; handle = xt_find_attr(node, "handle"); pass_b64 = xt_find_attr(node, "password"); @@ -119,9 +130,8 @@ static xt_status handle_account(struct xt_node *node, gpointer data) prpl = find_protocol(protocol); if (!prpl) { irc_rootmsg(xd->irc, "Warning: Protocol not found: `%s'", protocol); - prpl = make_unknown_protocol(protocol); + prpl = (struct prpl*) &protocol_missing; } - is_unknown = (prpl->options & PRPL_OPT_UNKNOWN_PROTOCOL) != 0; local = protocol_account_islocal(protocol); } @@ -157,11 +167,20 @@ static xt_status handle_account(struct xt_node *node, gpointer data) if (locked && !g_strcasecmp(locked, "true")) { acc->flags |= ACC_FLAG_LOCKED; } + if (prpl == &protocol_missing) { + set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL); + s->flags |= SET_HIDDEN | SET_NOSAVE | + ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; + } g_free(pass_cr); g_free(password); - handle_settings(node, &acc->set, is_unknown); + if (prpl == &protocol_missing) { + handle_settings_raw(node, &acc->set); + } else { + handle_settings(node, &acc->set); + } for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) { char *handle, *nick; @@ -200,7 +219,7 @@ static xt_status handle_channel(struct xt_node *node, gpointer data) set_setstr(&ic->set, "type", type); } - handle_settings(node, &ic->set, FALSE); + handle_settings(node, &ic->set); return XT_HANDLED; } @@ -278,7 +297,7 @@ static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const cha ret = STORAGE_OK; } - handle_settings(node, &xd->irc->b->set, FALSE); + handle_settings(node, &xd->irc->b->set); error: xt_free(xp); @@ -350,7 +369,11 @@ struct xt_node *xml_generate(irc_t *irc) } cur = xt_new_node("account", NULL, NULL); - xt_add_attr(cur, "protocol", acc->prpl->name); + if (acc->prpl == &protocol_missing) { + xt_add_attr(cur, "protocol", set_getstr(&acc->set, "_protocol_name")); + } else { + xt_add_attr(cur, "protocol", acc->prpl->name); + } xt_add_attr(cur, "handle", acc->user); xt_add_attr(cur, "password", pass_b64); xt_add_attr(cur, "autoconnect", acc->auto_connect ? "true" : "false"); |