diff options
-rw-r--r-- | otr.c | 4 | ||||
-rw-r--r-- | protocols/bee_ft.c | 2 | ||||
-rw-r--r-- | protocols/nogaim.h | 21 | ||||
-rw-r--r-- | protocols/purple/bpurple.h | 1 | ||||
-rw-r--r-- | protocols/purple/ft.c | 79 | ||||
-rw-r--r-- | protocols/purple/purple.c | 16 | ||||
-rw-r--r-- | protocols/twitter/twitter.c | 3 | ||||
-rw-r--r-- | root_commands.c | 9 |
8 files changed, 120 insertions, 15 deletions
@@ -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; |