aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/account.c
diff options
context:
space:
mode:
authorMarius Halden <marius.h@lden.org>2016-04-12 13:00:00 +0200
committerMarius Halden <marius.h@lden.org>2016-04-12 17:03:28 +0200
commit2b6f481a4e1bac54de7dc6a9a5444af9180babb0 (patch)
treeb4a6fe3c413f44e8feb5ee80df3b8c4bf4e7c22e /protocols/account.c
parentc9603a38774fb118d4aaa96e170674412ed7328a (diff)
Add support for multiple accounts in set accountset-account
The set account for control channels is now a comma separeted list of accounts instead of just one. If the user changes the tag of an accounts trough `account <id> set tag <new_tag>`, the account set will be updated to reflect this change for all relevant channels. If an account is removed trough `account <id> delete` it will be removed from the account set for all relevant channels.
Diffstat (limited to 'protocols/account.c')
-rw-r--r--protocols/account.c90
1 files changed, 89 insertions, 1 deletions
diff --git a/protocols/account.c b/protocols/account.c
index e25e40c7..685d15ec 100644
--- a/protocols/account.c
+++ b/protocols/account.c
@@ -122,6 +122,36 @@ account_t *account_add(bee_t *bee, struct prpl *prpl, char *user, char *pass)
return a;
}
+void account_update_channel_set(irc_channel_t *ic, char *old_tag, char *new_tag)
+{
+ gboolean found = FALSE;
+ char **account, **accounts;
+ char *saccount = set_getstr(&ic->set, "account");
+
+ if (saccount == NULL || *saccount == '\0') {
+ return;
+ }
+
+ accounts = g_strsplit(saccount, ",", 0);
+ for (account = accounts; *account; account++) {
+ if (g_strcasecmp(*account, old_tag) == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) {
+ g_free(*account);
+ *account = g_strdup(new_tag);
+
+ saccount = g_strjoinv(",", accounts);
+ set_setstr(&ic->set, "account", saccount);
+ g_free(saccount);
+ }
+
+ g_strfreev(accounts);
+}
+
char *set_eval_account(set_t *set, char *value)
{
account_t *acc = set->data;
@@ -163,14 +193,28 @@ char *set_eval_account(set_t *set, char *value)
return NULL; /* password shouldn't be visible in plaintext! */
} else if (strcmp(set->key, "tag") == 0) {
account_t *oa;
+ irc_t *irc;
+ GSList *l;
+ char *old;
/* Enforce uniqueness. */
if ((oa = account_by_tag(acc->bee, value)) && oa != acc) {
return SET_INVALID;
}
- g_free(acc->tag);
+ old = acc->tag;
acc->tag = g_strdup(value);
+
+ irc = acc->bee->ui_data;
+ for (l = irc->channels; l; l = l->next) {
+ irc_channel_t *ic = l->data;
+
+ if (g_strcasecmp(set_getstr(&ic->set, "type"), "control") == 0) {
+ account_update_channel_set(ic, old, value);
+ }
+ }
+
+ g_free(old);
return value;
} else if (strcmp(set->key, "auto_connect") == 0) {
if (!is_bool(value)) {
@@ -291,9 +335,43 @@ account_t *account_by_tag(bee_t *bee, const char *tag)
return NULL;
}
+void account_remove_from_channel_set(irc_channel_t *ic, char *tag)
+{
+ gboolean found = FALSE;
+ char **account, **accounts;
+ char *saccount = set_getstr(&ic->set, "account");
+
+ if (saccount == NULL || *saccount == '\0') {
+ return;
+ }
+
+ accounts = g_strsplit(saccount, ",", 0);
+ for (account = accounts; *account; account++) {
+ if (g_strcasecmp(*account, tag) == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) {
+ g_free(*account);
+
+ do {
+ *account = *(account + 1);
+ } while (*(++account) != NULL);
+
+ saccount = g_strjoinv(",", accounts);
+ set_setstr(&ic->set, "account", saccount);
+ }
+
+ g_strfreev(accounts);
+}
+
void account_del(bee_t *bee, account_t *acc)
{
account_t *a, *l = NULL;
+ GSList *accl;
+ irc_t *irc;
if (acc->ic) {
/* Caller should have checked, accounts still in use can't be deleted. */
@@ -317,6 +395,16 @@ void account_del(bee_t *bee, account_t *acc)
}
*/
+ /* Remove from channel set account */
+ irc = acc->bee->ui_data;
+ for (accl = irc->channels; accl; accl = accl->next) {
+ irc_channel_t *ic = accl->data;
+
+ if (g_strcasecmp(set_getstr(&ic->set, "type"), "control") == 0) {
+ account_remove_from_channel_set(ic, acc->tag);
+ }
+ }
+
while (a->set) {
set_del(&a->set, a->set->key);
}