aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Halden <marius.h@lden.org>2016-11-14 08:19:00 +0100
committerMarius Halden <marius.h@lden.org>2016-11-14 08:19:00 +0100
commitaf800c35a3927638914bd9c2aed60ad04694b34e (patch)
tree8e25fba5a40871eb11bbda2d70cb48839ace0d9b
parent6967042e3559d1dc40532660a690deab159146c9 (diff)
parent9f03c472fef309878ff2f3bc720d51e6d03077f1 (diff)
Merge branch 'master' into patched-master
-rw-r--r--otr.c4
-rw-r--r--protocols/bee_ft.c2
-rw-r--r--protocols/nogaim.h21
-rw-r--r--protocols/purple/bpurple.h1
-rw-r--r--protocols/purple/ft.c79
-rw-r--r--protocols/purple/purple.c16
-rw-r--r--protocols/twitter/twitter.c3
-rw-r--r--root_commands.c9
8 files changed, 120 insertions, 15 deletions
diff --git a/otr.c b/otr.c
index d07617f7..d2c1a2f2 100644
--- a/otr.c
+++ b/otr.c
@@ -428,7 +428,7 @@ int otr_check_for_key(account_t *a)
OtrlPrivKey *k;
/* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
- if (a->prpl->options & OPT_NOOTR) {
+ if (a->prpl->options & PRPL_OPT_NOOTR) {
return 0;
}
@@ -456,7 +456,7 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags)
struct im_connection *ic = iu->bu->ic;
/* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
- if (ic->acc->prpl->options & OPT_NOOTR ||
+ if (ic->acc->prpl->options & PRPL_OPT_NOOTR ||
iu->bu->flags & BEE_USER_NOOTR) {
return msg;
}
diff --git a/protocols/bee_ft.c b/protocols/bee_ft.c
index 27fd4eac..916b2e88 100644
--- a/protocols/bee_ft.c
+++ b/protocols/bee_ft.c
@@ -30,7 +30,7 @@ file_transfer_t *imcb_file_send_start(struct im_connection *ic, char *handle, ch
bee_t *bee = ic->bee;
bee_user_t *bu = bee_user_by_handle(bee, ic, handle);
- if (bee->ui->ft_in_start) {
+ if (bee->ui->ft_in_start && bu) {
return bee->ui->ft_in_start(bee, bu, file_name, file_size);
} else {
return NULL;
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index 4cba2174..b5a46524 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -139,6 +139,27 @@ struct buddy_action {
char *description;
};
+/* This enum takes a few things from libpurple and a few things from old OPT_ flags.
+ * The only flag that was used before this struct was PRPL_OPT_NOOTR.
+ *
+ * The libpurple ones only use the same values as the PurpleProtocolOptions
+ * enum for convenience, but there's no promise of direct compatibility with
+ * those values. As of libpurple 2.8.0 they use up to 0x800 (1 << 11), which is
+ * a nice coincidence.
+ */
+typedef enum {
+ /* The protocol doesn't use passwords
+ * Mirrors libpurple's OPT_PROTO_NO_PASSWORD */
+ PRPL_OPT_NO_PASSWORD = 1 << 4,
+
+ /* The protocol doesn't require passwords, but may use them
+ * Mirrors libpurple's OPT_PROTO_PASSWORD_OPTIONAL */
+ PRPL_OPT_PASSWORD_OPTIONAL = 1 << 7,
+
+ /* The protocol is not suitable for OTR, see OPT_NOOTR */
+ PRPL_OPT_NOOTR = 1 << 12,
+} prpl_options_t;
+
struct prpl {
int options;
/* You should set this to the name of your protocol.
diff --git a/protocols/purple/bpurple.h b/protocols/purple/bpurple.h
index 8225f0b8..81be2575 100644
--- a/protocols/purple/bpurple.h
+++ b/protocols/purple/bpurple.h
@@ -13,6 +13,7 @@ struct purple_data
GHashTable *input_requests;
guint next_request_id;
char *chat_list_server;
+ GSList *filetransfers;
};
#endif /* !BPURPLE_H */
diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c
index 320fc887..81fee8d0 100644
--- a/protocols/purple/ft.c
+++ b/protocols/purple/ft.c
@@ -41,6 +41,7 @@ struct prpl_xfer_data {
int fd;
char *fn, *handle;
gboolean ui_wants_data;
+ int timeout;
};
static file_transfer_t *next_ft;
@@ -63,13 +64,47 @@ static void prpl_xfer_canceled(struct file_transfer *ft, char *reason)
{
struct prpl_xfer_data *px = ft->data;
- purple_xfer_request_denied(px->xfer);
+ if (px->xfer) {
+ if (!purple_xfer_is_completed(px->xfer) && !purple_xfer_is_canceled(px->xfer)) {
+ purple_xfer_cancel_local(px->xfer);
+ }
+ px->xfer->ui_data = NULL;
+ purple_xfer_unref(px->xfer);
+ px->xfer = NULL;
+ }
+}
+
+static void prpl_xfer_free(struct file_transfer *ft)
+{
+ struct prpl_xfer_data *px = ft->data;
+ struct purple_data *pd = px->ic->proto_data;
+
+ pd->filetransfers = g_slist_remove(pd->filetransfers, px);
+
+ if (px->xfer) {
+ px->xfer->ui_data = NULL;
+ purple_xfer_unref(px->xfer);
+ }
+
+ if (px->timeout) {
+ b_event_remove(px->timeout);
+ }
+
+ g_free(px->fn);
+ g_free(px->handle);
+ if (px->fd >= 0) {
+ close(px->fd);
+ }
+ g_free(px);
}
static void prplcb_xfer_new(PurpleXfer *xfer)
{
+ purple_xfer_ref(xfer);
+
if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
+ struct purple_data *pd;
xfer->ui_data = px;
px->xfer = xfer;
@@ -77,6 +112,9 @@ static void prplcb_xfer_new(PurpleXfer *xfer)
px->fd = -1;
px->ic = purple_ic_by_pa(xfer->account);
+ pd = px->ic->proto_data;
+ pd->filetransfers = g_slist_prepend(pd->filetransfers, px);
+
purple_xfer_set_local_filename(xfer, px->fn);
/* Sadly the xfer struct is still empty ATM so come back after
@@ -111,6 +149,7 @@ static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_conditio
px->ft->accept = prpl_xfer_accept;
px->ft->canceled = prpl_xfer_canceled;
+ px->ft->free = prpl_xfer_free;
px->ft->write_request = prpl_xfer_write_request;
return FALSE;
@@ -163,17 +202,13 @@ static gboolean prpl_xfer_write_request(struct file_transfer *ft)
}
-/* Generic (IM<>UI): */
static void prplcb_xfer_destroy(PurpleXfer *xfer)
{
struct prpl_xfer_data *px = xfer->ui_data;
- g_free(px->fn);
- g_free(px->handle);
- if (px->fd >= 0) {
- close(px->fd);
+ if (px) {
+ px->xfer = NULL;
}
- g_free(px);
}
static void prplcb_xfer_progress(PurpleXfer *xfer, double percent)
@@ -223,9 +258,9 @@ static void prplcb_xfer_cancel_remote(PurpleXfer *xfer)
{
struct prpl_xfer_data *px = xfer->ui_data;
- if (px->ft) {
+ if (px && px->ft) {
imcb_file_canceled(px->ic, px->ft, "Canceled by remote end");
- } else {
+ } else if (px) {
/* px->ft == NULL for sends, because of the two stages. :-/ */
imcb_error(px->ic, "File transfer cancelled by remote end");
}
@@ -239,10 +274,12 @@ static gboolean purple_transfer_request_cb(gpointer data, gint fd, b_input_condi
void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle)
{
struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
+ struct purple_data *pd;
char *dir, *basename;
ft->data = px;
px->ft = ft;
+ px->ft->free = prpl_xfer_free;
dir = g_strdup("/tmp/bitlbee-purple-ft.XXXXXX");
if (!mkdtemp(dir)) {
@@ -271,10 +308,13 @@ void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char
px->ic = ic;
px->handle = g_strdup(handle);
+ pd = px->ic->proto_data;
+ pd->filetransfers = g_slist_prepend(pd->filetransfers, px);
+
imcb_log(ic,
"Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait...");
- b_timeout_add(0, purple_transfer_request_cb, ft);
+ px->timeout = b_timeout_add(0, purple_transfer_request_cb, ft);
}
static void purple_transfer_forward(struct file_transfer *ft)
@@ -294,6 +334,8 @@ static gboolean purple_transfer_request_cb(gpointer data, gint fd, b_input_condi
file_transfer_t *ft = data;
struct prpl_xfer_data *px = ft->data;
+ px->timeout = 0;
+
if (ft->write == NULL) {
ft->write = prpl_xfer_write;
imcb_file_recv_start(px->ic, ft);
@@ -321,12 +363,27 @@ static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned
imcb_file_finished(px->ic, ft);
px->ft = NULL;
} else {
- b_timeout_add(0, purple_transfer_request_cb, ft);
+ px->timeout = b_timeout_add(0, purple_transfer_request_cb, ft);
}
return TRUE;
}
+void purple_transfer_cancel_all(struct im_connection *ic)
+{
+ struct purple_data *pd = ic->proto_data;
+
+ while (pd->filetransfers) {
+ struct prpl_xfer_data *px = pd->filetransfers->data;
+
+ if (px->ft) {
+ imcb_file_canceled(ic, px->ft, "Logging out");
+ }
+
+ pd->filetransfers = g_slist_remove(pd->filetransfers, px);
+ }
+}
+
PurpleXferUiOps bee_xfer_uiops =
diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c
index 1a48b31c..edd1e9c3 100644
--- a/protocols/purple/purple.c
+++ b/protocols/purple/purple.c
@@ -42,6 +42,8 @@ static char *set_eval_display_name(set_t *set, char *value);
void purple_request_input_callback(guint id, struct im_connection *ic,
const char *message, const char *who);
+void purple_transfer_cancel_all(struct im_connection *ic);
+
/* purple_request_input specific stuff */
typedef void (*ri_callback_t)(gpointer, const gchar *);
@@ -398,6 +400,10 @@ static void purple_logout(struct im_connection *ic)
purple_save_password(ic->acc, pd->account);
+ if (pd->filetransfers) {
+ purple_transfer_cancel_all(ic);
+ }
+
purple_account_set_enabled(pd->account, "BitlBee", FALSE);
purple_connections = g_slist_remove(purple_connections, ic);
purple_accounts_remove(pd->account);
@@ -1732,6 +1738,7 @@ void purple_initmodule()
supported by this libpurple instance. */
for (prots = purple_plugins_get_protocols(); prots; prots = prots->next) {
PurplePlugin *prot = prots->data;
+ PurplePluginProtocolInfo *pi = prot->info->extra_info;
struct prpl *ret;
/* If we already have this one (as a native module), don't
@@ -1745,6 +1752,15 @@ void purple_initmodule()
if (strncmp(ret->name, "prpl-", 5) != 0) {
ret->name = g_strdup_printf("prpl-%s", ret->name);
}
+
+ if (pi->options & OPT_PROTO_NO_PASSWORD) {
+ ret->options |= PRPL_OPT_NO_PASSWORD;
+ }
+
+ if (pi->options & OPT_PROTO_PASSWORD_OPTIONAL) {
+ ret->options |= PRPL_OPT_PASSWORD_OPTIONAL;
+ }
+
register_protocol(ret);
g_string_append_printf(help, "\n* %s (%s)", ret->name, prot->info->name);
diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c
index 468f9eaa..9d3b743c 100644
--- a/protocols/twitter/twitter.c
+++ b/protocols/twitter/twitter.c
@@ -1176,7 +1176,7 @@ void twitter_initmodule()
{
struct prpl *ret = g_new0(struct prpl, 1);
- ret->options = OPT_NOOTR;
+ ret->options = PRPL_OPT_NOOTR | PRPL_OPT_NO_PASSWORD;
ret->name = "twitter";
ret->login = twitter_login;
ret->init = twitter_init;
@@ -1203,5 +1203,6 @@ void twitter_initmodule()
/* And an identi.ca variant: */
ret = g_memdup(ret, sizeof(struct prpl));
ret->name = "identica";
+ ret->options = PRPL_OPT_NOOTR;
register_protocol(ret);
}
diff --git a/root_commands.c b/root_commands.c
index fde84527..414ab640 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -478,6 +478,13 @@ static void cmd_account(irc_t *irc, char **cmd)
*a->pass = '\0';
irc_rootmsg(irc, "No need to enter a password for this "
"account since it's using OAuth");
+ } else if (prpl->options & PRPL_OPT_NO_PASSWORD) {
+ *a->pass = '\0';
+ } else if (prpl->options & PRPL_OPT_PASSWORD_OPTIONAL) {
+ *a->pass = '\0';
+ irc_rootmsg(irc, "Passwords are optional for this account. "
+ "If you wish to enter the password with /OPER, do "
+ "account %s set -del password", a->tag);
} else {
irc_rootmsg(irc, "You can now use the /OPER command to "
"enter the password");
@@ -487,6 +494,8 @@ static void cmd_account(irc_t *irc, char **cmd)
"set oauth on", a->tag);
}
}
+ } else if (prpl->options & PRPL_OPT_NO_PASSWORD) {
+ irc_rootmsg(irc, "Note: this account doesn't use password for login");
}
return;